diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index f76e41e0..0d8f3a16 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -47,6 +47,8 @@ jobs: - name: Install dependencies for macOS run: brew bundle + - run: npm install && npx playwright install chromium + - name: Build the project run: swift build --build-tests @@ -89,6 +91,8 @@ jobs: sudo apt-get update && sudo apt-get install -y wabt binaryen + - run: npm install && npx playwright install chromium + - name: Install WebAssembly runtime uses: bytecodealliance/actions/wasmtime/setup@v1 diff --git a/Package.swift b/Package.swift index 91bfb149..e8c8886c 100644 --- a/Package.swift +++ b/Package.swift @@ -4,7 +4,7 @@ import PackageDescription #if swift(<5.9.2) -#warning("Swift 5.9.1 or earlier is not supported by carton") + #warning("Swift 5.9.1 or earlier is not supported by carton") #endif let package = Package( @@ -33,7 +33,7 @@ let package = Package( .target( name: "CartonDriver", dependencies: [ - "SwiftToolchain", + "SwiftToolchain" ] ), .executableTarget( @@ -57,52 +57,52 @@ let package = Package( ] ), .plugin( - name: "CartonBundlePlugin", - capability: .command( - intent: .custom( - verb: "carton-bundle", - description: "Produces an optimized app bundle for distribution." - ) - ), - dependencies: ["carton-frontend-slim"], - exclude: [ - "CartonCore/README.md", - "CartonPluginShared/README.md" - ] + name: "CartonBundlePlugin", + capability: .command( + intent: .custom( + verb: "carton-bundle", + description: "Produces an optimized app bundle for distribution." + ) + ), + dependencies: ["carton-frontend-slim"], + exclude: [ + "CartonCore/README.md", + "CartonPluginShared/README.md", + ] ), .plugin( - name: "CartonTestPlugin", - capability: .command( - intent: .custom( - verb: "carton-test", - description: "Run the tests in a WASI environment." - ) - ), - dependencies: ["carton-frontend"], - exclude: [ - "CartonCore/README.md", - "CartonPluginShared/README.md" - ] + name: "CartonTestPlugin", + capability: .command( + intent: .custom( + verb: "carton-test", + description: "Run the tests in a WASI environment." + ) + ), + dependencies: ["carton-frontend-slim"], + exclude: [ + "CartonCore/README.md", + "CartonPluginShared/README.md", + ] ), .plugin( - name: "CartonDevPlugin", - capability: .command( - intent: .custom( - verb: "carton-dev", - description: "Watch the current directory, host the app, rebuild on change." - ) - ), - dependencies: ["carton-frontend"], - exclude: [ - "CartonCore/README.md", - "CartonPluginShared/README.md" - ] + name: "CartonDevPlugin", + capability: .command( + intent: .custom( + verb: "carton-dev", + description: "Watch the current directory, host the app, rebuild on change." + ) + ), + dependencies: ["carton-frontend"], + exclude: [ + "CartonCore/README.md", + "CartonPluginShared/README.md", + ] ), .executableTarget(name: "carton-plugin-helper"), .target( name: "CartonFrontend", dependencies: [ - "CartonKit", + "CartonKit" ] ), .target( @@ -113,7 +113,6 @@ let package = Package( .product(name: "NIO", package: "swift-nio"), .product(name: "ArgumentParser", package: "swift-argument-parser"), "CartonHelpers", - "WebDriver", "WasmTransformer", ], exclude: ["Utilities/README.md"], @@ -124,7 +123,7 @@ let package = Package( .target( name: "SwiftToolchain", dependencies: [ - "CartonCore", + "CartonCore" ], exclude: ["Utilities/README.md"] ), @@ -132,19 +131,19 @@ let package = Package( /** Shim target to import missing C headers in Darwin and Glibc modulemap. */ name: "TSCclibc", cSettings: [ - .define("_GNU_SOURCE", .when(platforms: [.linux])), + .define("_GNU_SOURCE", .when(platforms: [.linux])) ] ), .target( - /** Cross-platform access to bare `libc` functionality. */ - name: "TSCLibc" + /** Cross-platform access to bare `libc` functionality. */ + name: "TSCLibc" ), .target( name: "CartonHelpers", dependencies: [ "TSCclibc", "TSCLibc", - "CartonCore" + "CartonCore", ], exclude: ["Basics/README.md"] ), @@ -156,7 +155,7 @@ let package = Package( name: "WebDriver", dependencies: [ .product(name: "NIO", package: "swift-nio"), - "CartonHelpers" + "CartonHelpers", ] ), // This target is used only for release automation tasks and @@ -165,6 +164,7 @@ let package = Package( name: "carton-release", dependencies: [ .product(name: "ArgumentParser", package: "swift-argument-parser"), + "CartonHelpers", "CartonCore", ] ), diff --git a/Plugins/CartonTestPlugin/CartonTestPluginCommand.swift b/Plugins/CartonTestPlugin/CartonTestPluginCommand.swift index bb15bf10..1d35c75f 100644 --- a/Plugins/CartonTestPlugin/CartonTestPluginCommand.swift +++ b/Plugins/CartonTestPlugin/CartonTestPluginCommand.swift @@ -37,7 +37,8 @@ struct CartonTestPluginCommand: CommandPlugin { func performCommand(context: PluginContext, arguments: [String]) async throws { try checkSwiftVersion() - try checkHelpFlag(arguments, subcommand: "test", context: context) + try checkHelpFlag( + arguments, frontend: "carton-frontend-slim", subcommand: "test", context: context) let productName = "\(context.package.displayName)PackageTests" @@ -71,25 +72,25 @@ struct CartonTestPluginCommand: CommandPlugin { let wasmFileName = "\(productName).wasm" testProductArtifactPath = buildDirectory.appending(subpath: wasmFileName).string #if compiler(>=5.10) - var buildParameters = PackageManager.BuildParameters() - options.environment.applyBuildParameters(&buildParameters) - applyExtraBuildFlags(from: &extractor, parameters: &buildParameters) + var buildParameters = PackageManager.BuildParameters() + options.environment.applyBuildParameters(&buildParameters) + applyExtraBuildFlags(from: &extractor, parameters: &buildParameters) - let build = try packageManager.build(.product(productName), parameters: buildParameters) - guard build.succeeded else { - throw Error("Failed to build test product: \(build.logText)") - } - guard FileManager.default.fileExists(atPath: testProductArtifactPath) else { - throw Error("Product \(productName) did not produce \(buildDirectory)!?") - } + let build = try packageManager.build(.product(productName), parameters: buildParameters) + guard build.succeeded else { + throw Error("Failed to build test product: \(build.logText)") + } + guard FileManager.default.fileExists(atPath: testProductArtifactPath) else { + throw Error("Product \(productName) did not produce \(buildDirectory)!?") + } #else - // NOTE: Old SwiftPM does not allow to build *only tests* from plugin, so we expect - // the test product to be built already by external wrapper command. - guard FileManager.default.fileExists(atPath: testProductArtifactPath) else { - throw Error( - "Failed to find \"\(wasmFileName)\" in \(buildDirectory). Please build \"\(productName)\" product first" - ) - } + // NOTE: Old SwiftPM does not allow to build *only tests* from plugin, so we expect + // the test product to be built already by external wrapper command. + guard FileManager.default.fileExists(atPath: testProductArtifactPath) else { + throw Error( + "Failed to find \"\(wasmFileName)\" in \(buildDirectory). Please build \"\(productName)\" product first" + ) + } #endif } @@ -107,14 +108,15 @@ struct CartonTestPluginCommand: CommandPlugin { "test", "--prebuilt-test-bundle-path", testProductArtifactPath, "--environment", options.environment.rawValue, - "--plugin-work-directory", context.pluginWorkDirectory.string + "--plugin-work-directory", context.pluginWorkDirectory.string, ] args += (options.pid.map { ["--pid", $0] } ?? []) args += resourcesPaths.flatMap { ["--resources", $0.string] } args += extractor.remainingArguments - let frontend = try makeCartonFrontendProcess(context: context, arguments: args) + let frontend = try makeCartonFrontendProcess( + context: context, frontend: "carton-frontend-slim", arguments: args) try frontend.checkRun(printsLoadingMessage: false, forwardExit: true) } diff --git a/Sources/CartonFrontend/CartonFrontendCommand.swift b/Sources/CartonFrontend/CartonFrontendCommand.swift index 316b9341..43a81b9d 100644 --- a/Sources/CartonFrontend/CartonFrontendCommand.swift +++ b/Sources/CartonFrontend/CartonFrontendCommand.swift @@ -21,8 +21,7 @@ public struct CartonFrontendCommand: AsyncParsableCommand { abstract: "📦 Watcher, bundler, and test runner for your SwiftWasm apps.", version: cartonVersion, subcommands: [ - CartonFrontendDevCommand.self, - CartonFrontendTestCommand.self + CartonFrontendDevCommand.self ] ) diff --git a/Sources/CartonFrontend/Commands/CartonFrontendDevCommand.swift b/Sources/CartonFrontend/Commands/CartonFrontendDevCommand.swift index 3a85ef24..b1a19810 100644 --- a/Sources/CartonFrontend/Commands/CartonFrontendDevCommand.swift +++ b/Sources/CartonFrontend/Commands/CartonFrontendDevCommand.swift @@ -13,8 +13,8 @@ // limitations under the License. import ArgumentParser -import CartonHelpers import CartonCore +import CartonHelpers import CartonKit import Foundation @@ -28,8 +28,10 @@ enum DevCommandError: Error & CustomStringConvertible { var description: String { switch self { - case .noBuildRequestOption: "--build-request option is necessary if you want to watch, but has not been specified." - case .noBuildResponseOption: "--build-response option is necessary if you want to watch, but has not been specified." + case .noBuildRequestOption: + "--build-request option is necessary if you want to watch, but has not been specified." + case .noBuildResponseOption: + "--build-response option is necessary if you want to watch, but has not been specified." case .failedToOpenBuildRequestPipe: "failed to open build request pipe." case .failedToOpenBuildResponsePipe: "failed to open build response pipe." case .pluginConnectionClosed: "connection with the plugin has been closed." @@ -50,9 +52,6 @@ struct CartonFrontendDevCommand: AsyncParsableCommand { @Flag(help: "When specified, build in the release mode.") var release = false - @Option(help: "Turn on runtime checks for various behavior.") - private var sanitize: SanitizeVariant? - @Flag(name: .shortAndLong, help: "Don't clear terminal window after files change.") var verbose = false diff --git a/Sources/CartonFrontend/Commands/TestRunners/BrowserTestRunner.swift b/Sources/CartonFrontend/Commands/TestRunners/BrowserTestRunner.swift deleted file mode 100644 index e278d77d..00000000 --- a/Sources/CartonFrontend/Commands/TestRunners/BrowserTestRunner.swift +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2020 Carton 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. - -import CartonHelpers -import CartonCore -import CartonKit -import Foundation -import NIOCore -import NIOPosix -import WebDriver - -#if canImport(FoundationNetworking) - import FoundationNetworking -#endif - -private enum Constants { - static let entrypoint = Entrypoint(fileName: "test.js", content: StaticResource.test) -} - -enum BrowserTestRunnerError: Error, CustomStringConvertible { - case invalidRemoteURL(String) - case failedToFindWebDriver - - var description: String { - switch self { - case let .invalidRemoteURL(url): return "Invalid remote URL: \(url)" - case .failedToFindWebDriver: - return """ - Failed to find WebDriver executable or remote URL to a running driver process. - Please make sure that you are satisfied with one of the followings (in order of priority) - 1. Set `WEBDRIVER_REMOTE_URL` with the address of remote WebDriver like `WEBDRIVER_REMOTE_URL=http://localhost:9515`. - 2. Set `WEBDRIVER_PATH` with the path to your WebDriver executable. - 3. `chromedriver`, `geckodriver`, `safaridriver`, or `msedgedriver` has been installed in `PATH` - """ - } - } -} - -struct BrowserTestRunner: TestRunner { - let testFilePath: AbsolutePath - let bindingAddress: String - let host: String - let port: Int - let headless: Bool - let resourcesPaths: [String] - let pid: Int32? - let terminal: InteractiveWriter - let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) - - init( - testFilePath: AbsolutePath, - bindingAddress: String, - host: String, - port: Int, - headless: Bool, - resourcesPaths: [String], - pid: Int32?, - terminal: InteractiveWriter - ) { - self.testFilePath = testFilePath - self.bindingAddress = bindingAddress - self.host = host - self.port = port - self.headless = headless - self.resourcesPaths = resourcesPaths - self.pid = pid - self.terminal = terminal - } - - func run(options: TestRunnerOptions) async throws { - let server = try await Server( - .init( - builder: nil, - mainWasmPath: testFilePath, - verbose: true, - bindingAddress: bindingAddress, - port: port, - host: host, - env: options.env, - customIndexPath: nil, - resourcesPaths: resourcesPaths, - entrypoint: Constants.entrypoint, - pid: pid, - terminal: terminal - ) - ) - let localURL = try await server.start() - var disposer: () async throws -> Void = {} - do { - if headless { - let webDriver = try await WebDriverServices.find(terminal: terminal) - let client = try await webDriver.client() - disposer = { - try await client.closeSession() - webDriver.dispose() - } - try await client.goto(url: localURL) - } else { - disposer = {} - try openInSystemBrowser(url: localURL) - } - let hadError = try await server.waitUntilTestFinished() - try await disposer() - exit(hadError ? EXIT_FAILURE : EXIT_SUCCESS) - } catch { - try await disposer() - throw error - } - } -} diff --git a/Sources/CartonFrontend/Commands/TestRunners/NodeTestRunner.swift b/Sources/CartonFrontend/Commands/TestRunners/NodeTestRunner.swift deleted file mode 100644 index 424a4606..00000000 --- a/Sources/CartonFrontend/Commands/TestRunners/NodeTestRunner.swift +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2022 Carton 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. - -import CartonHelpers -import CartonCore -import CartonKit -import Foundation - -private enum Constants { - static let entrypoint = Entrypoint(fileName: "testNode.js", content: StaticResource.testNode) -} - -/// Test runner for Node.js. -struct NodeTestRunner: TestRunner { - let pluginWorkDirectory: AbsolutePath - let testFilePath: AbsolutePath - let listTestCases: Bool - let testCases: [String] - let nodeArguments: [String] - let terminal: InteractiveWriter - - func run(options: TestRunnerOptions) async throws { - terminal.write("\nRunning the test bundle with Node.js:\n", inColor: .yellow) - - let entrypointPath = try Constants.entrypoint.write( - at: pluginWorkDirectory, fileSystem: localFileSystem - ) - - // Allow Node.js to resolve modules from resource directories by making them relative to the entrypoint path. - let buildDirectory = testFilePath.parentDirectory - let staticDirectory = pluginWorkDirectory - - // Clean up existing symlinks before creating new ones. - for existingSymlink in try FileManager.default.resourcesDirectoryNames(relativeTo: staticDirectory.asURL) - { - try localFileSystem.removeFileTree(staticDirectory.appending(component: existingSymlink)) - } - - let resourceDirectories = try FileManager.default.resourcesDirectoryNames( - relativeTo: buildDirectory.asURL) - - // Create new symlink for each resource directory. - for resourcesDirectoryName in resourceDirectories { - try localFileSystem.createSymbolicLink( - staticDirectory.appending(component: resourcesDirectoryName), - pointingAt: buildDirectory.appending(component: resourcesDirectoryName), - relative: false - ) - } - - var nodeArguments = - ["node"] + nodeArguments + [entrypointPath.pathString, testFilePath.pathString] - if listTestCases { - nodeArguments.append(contentsOf: ["--", "-l"]) - } else if !testCases.isEmpty { - nodeArguments.append(contentsOf: testCases) - } - try await Process.run(nodeArguments, environment: options.env, terminal) - } -} diff --git a/Sources/CartonHelpers/Process+run.swift b/Sources/CartonHelpers/Process+run.swift index bdc58829..2c073373 100644 --- a/Sources/CartonHelpers/Process+run.swift +++ b/Sources/CartonHelpers/Process+run.swift @@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +import CartonCore import Dispatch import Foundation -import CartonCore struct ProcessError: Error { let stderr: String? @@ -137,12 +137,6 @@ extension Foundation.Process { terminal.write(stdout) } } - } else { - terminal.write( - "\nProcess failed and produced following output: \n", - inColor: .red - ) - print(error) } throw error diff --git a/Sources/CartonHelpers/StaticArchive.swift b/Sources/CartonHelpers/StaticArchive.swift index f5c2530f..f40a4dba 100644 --- a/Sources/CartonHelpers/StaticArchive.swift +++ b/Sources/CartonHelpers/StaticArchive.swift @@ -1,10 +1,8 @@ import Foundation public enum StaticResource { - public static let dev: Data = Data(base64Encoded: "Ly8gbm9kZV9tb2R1bGVzL3JlY29ubmVjdGluZy13ZWJzb2NrZXQvZGlzdC9yZWNvbm5lY3Rpbmctd2Vic29ja2V0LW1qcy5qcwp2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHsKICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24oZDIsIGIyKSB7CiAgICBkMi5fX3Byb3RvX18gPSBiMjsKICB9IHx8IGZ1bmN0aW9uKGQyLCBiMikgewogICAgZm9yICh2YXIgcCBpbiBiMikKICAgICAgaWYgKGIyLmhhc093blByb3BlcnR5KHApKQogICAgICAgIGQyW3BdID0gYjJbcF07CiAgfTsKICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTsKfTsKZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHsKICBleHRlbmRTdGF0aWNzKGQsIGIpOwogIGZ1bmN0aW9uIF9fKCkgewogICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7CiAgfQogIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTsKfQpmdW5jdGlvbiBfX3ZhbHVlcyhvKSB7CiAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSAiZnVuY3Rpb24iICYmIG9bU3ltYm9sLml0ZXJhdG9yXSwgaSA9IDA7CiAgaWYgKG0pCiAgICByZXR1cm4gbS5jYWxsKG8pOwogIHJldHVybiB7CiAgICBuZXh0OiBmdW5jdGlvbigpIHsKICAgICAgaWYgKG8gJiYgaSA+PSBvLmxlbmd0aCkKICAgICAgICBvID0gdm9pZCAwOwogICAgICByZXR1cm4geyB2YWx1ZTogbyAmJiBvW2krK10sIGRvbmU6ICFvIH07CiAgICB9CiAgfTsKfQpmdW5jdGlvbiBfX3JlYWQobywgbikgewogIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gImZ1bmN0aW9uIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07CiAgaWYgKCFtKQogICAgcmV0dXJuIG87CiAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7CiAgdHJ5IHsKICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKQogICAgICBhci5wdXNoKHIudmFsdWUpOwogIH0gY2F0Y2ggKGVycm9yKSB7CiAgICBlID0geyBlcnJvciB9OwogIH0gZmluYWxseSB7CiAgICB0cnkgewogICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVsicmV0dXJuIl0pKQogICAgICAgIG0uY2FsbChpKTsKICAgIH0gZmluYWxseSB7CiAgICAgIGlmIChlKQogICAgICAgIHRocm93IGUuZXJyb3I7CiAgICB9CiAgfQogIHJldHVybiBhcjsKfQpmdW5jdGlvbiBfX3NwcmVhZCgpIHsKICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykKICAgIGFyID0gYXIuY29uY2F0KF9fcmVhZChhcmd1bWVudHNbaV0pKTsKICByZXR1cm4gYXI7Cn0KdmFyIEV2ZW50ID0gZnVuY3Rpb24oKSB7CiAgZnVuY3Rpb24gRXZlbnQyKHR5cGUsIHRhcmdldCkgewogICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7CiAgICB0aGlzLnR5cGUgPSB0eXBlOwogIH0KICByZXR1cm4gRXZlbnQyOwp9KCk7CnZhciBFcnJvckV2ZW50ID0gZnVuY3Rpb24oX3N1cGVyKSB7CiAgX19leHRlbmRzKEVycm9yRXZlbnQyLCBfc3VwZXIpOwogIGZ1bmN0aW9uIEVycm9yRXZlbnQyKGVycm9yLCB0YXJnZXQpIHsKICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsICJlcnJvciIsIHRhcmdldCkgfHwgdGhpczsKICAgIF90aGlzLm1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlOwogICAgX3RoaXMuZXJyb3IgPSBlcnJvcjsKICAgIHJldHVybiBfdGhpczsKICB9CiAgcmV0dXJuIEVycm9yRXZlbnQyOwp9KEV2ZW50KTsKdmFyIENsb3NlRXZlbnQgPSBmdW5jdGlvbihfc3VwZXIpIHsKICBfX2V4dGVuZHMoQ2xvc2VFdmVudDIsIF9zdXBlcik7CiAgZnVuY3Rpb24gQ2xvc2VFdmVudDIoY29kZSwgcmVhc29uLCB0YXJnZXQpIHsKICAgIGlmIChjb2RlID09PSB2b2lkIDApIHsKICAgICAgY29kZSA9IDFlMzsKICAgIH0KICAgIGlmIChyZWFzb24gPT09IHZvaWQgMCkgewogICAgICByZWFzb24gPSAiIjsKICAgIH0KICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsICJjbG9zZSIsIHRhcmdldCkgfHwgdGhpczsKICAgIF90aGlzLndhc0NsZWFuID0gdHJ1ZTsKICAgIF90aGlzLmNvZGUgPSBjb2RlOwogICAgX3RoaXMucmVhc29uID0gcmVhc29uOwogICAgcmV0dXJuIF90aGlzOwogIH0KICByZXR1cm4gQ2xvc2VFdmVudDI7Cn0oRXZlbnQpOwp2YXIgZ2V0R2xvYmFsV2ViU29ja2V0ID0gZnVuY3Rpb24oKSB7CiAgaWYgKHR5cGVvZiBXZWJTb2NrZXQgIT09ICJ1bmRlZmluZWQiKSB7CiAgICByZXR1cm4gV2ViU29ja2V0OwogIH0KfTsKdmFyIGlzV2ViU29ja2V0ID0gZnVuY3Rpb24odykgewogIHJldHVybiB0eXBlb2YgdyAhPT0gInVuZGVmaW5lZCIgJiYgISF3ICYmIHcuQ0xPU0lORyA9PT0gMjsKfTsKdmFyIERFRkFVTFQgPSB7CiAgbWF4UmVjb25uZWN0aW9uRGVsYXk6IDFlNCwKICBtaW5SZWNvbm5lY3Rpb25EZWxheTogMWUzICsgTWF0aC5yYW5kb20oKSAqIDRlMywKICBtaW5VcHRpbWU6IDVlMywKICByZWNvbm5lY3Rpb25EZWxheUdyb3dGYWN0b3I6IDEuMywKICBjb25uZWN0aW9uVGltZW91dDogNGUzLAogIG1heFJldHJpZXM6IEluZmluaXR5LAogIG1heEVucXVldWVkTWVzc2FnZXM6IEluZmluaXR5LAogIHN0YXJ0Q2xvc2VkOiBmYWxzZSwKICBkZWJ1ZzogZmFsc2UKfTsKdmFyIFJlY29ubmVjdGluZ1dlYlNvY2tldCA9IGZ1bmN0aW9uKCkgewogIGZ1bmN0aW9uIFJlY29ubmVjdGluZ1dlYlNvY2tldDIodXJsLCBwcm90b2NvbHMsIG9wdGlvbnMpIHsKICAgIHZhciBfdGhpcyA9IHRoaXM7CiAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgIG9wdGlvbnMgPSB7fTsKICAgIH0KICAgIHRoaXMuX2xpc3RlbmVycyA9IHsKICAgICAgZXJyb3I6IFtdLAogICAgICBtZXNzYWdlOiBbXSwKICAgICAgb3BlbjogW10sCiAgICAgIGNsb3NlOiBbXQogICAgfTsKICAgIHRoaXMuX3JldHJ5Q291bnQgPSAtMTsKICAgIHRoaXMuX3Nob3VsZFJlY29ubmVjdCA9IHRydWU7CiAgICB0aGlzLl9jb25uZWN0TG9jayA9IGZhbHNlOwogICAgdGhpcy5fYmluYXJ5VHlwZSA9ICJibG9iIjsKICAgIHRoaXMuX2Nsb3NlQ2FsbGVkID0gZmFsc2U7CiAgICB0aGlzLl9tZXNzYWdlUXVldWUgPSBbXTsKICAgIHRoaXMub25jbG9zZSA9IG51bGw7CiAgICB0aGlzLm9uZXJyb3IgPSBudWxsOwogICAgdGhpcy5vbm1lc3NhZ2UgPSBudWxsOwogICAgdGhpcy5vbm9wZW4gPSBudWxsOwogICAgdGhpcy5faGFuZGxlT3BlbiA9IGZ1bmN0aW9uKGV2ZW50KSB7CiAgICAgIF90aGlzLl9kZWJ1Zygib3BlbiBldmVudCIpOwogICAgICB2YXIgX2EgPSBfdGhpcy5fb3B0aW9ucy5taW5VcHRpbWUsIG1pblVwdGltZSA9IF9hID09PSB2b2lkIDAgPyBERUZBVUxULm1pblVwdGltZSA6IF9hOwogICAgICBjbGVhclRpbWVvdXQoX3RoaXMuX2Nvbm5lY3RUaW1lb3V0KTsKICAgICAgX3RoaXMuX3VwdGltZVRpbWVvdXQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiBfdGhpcy5fYWNjZXB0T3BlbigpOwogICAgICB9LCBtaW5VcHRpbWUpOwogICAgICBfdGhpcy5fd3MuYmluYXJ5VHlwZSA9IF90aGlzLl9iaW5hcnlUeXBlOwogICAgICBfdGhpcy5fbWVzc2FnZVF1ZXVlLmZvckVhY2goZnVuY3Rpb24obWVzc2FnZSkgewogICAgICAgIHJldHVybiBfdGhpcy5fd3Muc2VuZChtZXNzYWdlKTsKICAgICAgfSk7CiAgICAgIF90aGlzLl9tZXNzYWdlUXVldWUgPSBbXTsKICAgICAgaWYgKF90aGlzLm9ub3BlbikgewogICAgICAgIF90aGlzLm9ub3BlbihldmVudCk7CiAgICAgIH0KICAgICAgX3RoaXMuX2xpc3RlbmVycy5vcGVuLmZvckVhY2goZnVuY3Rpb24obGlzdGVuZXIpIHsKICAgICAgICByZXR1cm4gX3RoaXMuX2NhbGxFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcik7CiAgICAgIH0pOwogICAgfTsKICAgIHRoaXMuX2hhbmRsZU1lc3NhZ2UgPSBmdW5jdGlvbihldmVudCkgewogICAgICBfdGhpcy5fZGVidWcoIm1lc3NhZ2UgZXZlbnQiKTsKICAgICAgaWYgKF90aGlzLm9ubWVzc2FnZSkgewogICAgICAgIF90aGlzLm9ubWVzc2FnZShldmVudCk7CiAgICAgIH0KICAgICAgX3RoaXMuX2xpc3RlbmVycy5tZXNzYWdlLmZvckVhY2goZnVuY3Rpb24obGlzdGVuZXIpIHsKICAgICAgICByZXR1cm4gX3RoaXMuX2NhbGxFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcik7CiAgICAgIH0pOwogICAgfTsKICAgIHRoaXMuX2hhbmRsZUVycm9yID0gZnVuY3Rpb24oZXZlbnQpIHsKICAgICAgX3RoaXMuX2RlYnVnKCJlcnJvciBldmVudCIsIGV2ZW50Lm1lc3NhZ2UpOwogICAgICBfdGhpcy5fZGlzY29ubmVjdCh2b2lkIDAsIGV2ZW50Lm1lc3NhZ2UgPT09ICJUSU1FT1VUIiA/ICJ0aW1lb3V0IiA6IHZvaWQgMCk7CiAgICAgIGlmIChfdGhpcy5vbmVycm9yKSB7CiAgICAgICAgX3RoaXMub25lcnJvcihldmVudCk7CiAgICAgIH0KICAgICAgX3RoaXMuX2RlYnVnKCJleGVjIGVycm9yIGxpc3RlbmVycyIpOwogICAgICBfdGhpcy5fbGlzdGVuZXJzLmVycm9yLmZvckVhY2goZnVuY3Rpb24obGlzdGVuZXIpIHsKICAgICAgICByZXR1cm4gX3RoaXMuX2NhbGxFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcik7CiAgICAgIH0pOwogICAgICBfdGhpcy5fY29ubmVjdCgpOwogICAgfTsKICAgIHRoaXMuX2hhbmRsZUNsb3NlID0gZnVuY3Rpb24oZXZlbnQpIHsKICAgICAgX3RoaXMuX2RlYnVnKCJjbG9zZSBldmVudCIpOwogICAgICBfdGhpcy5fY2xlYXJUaW1lb3V0cygpOwogICAgICBpZiAoX3RoaXMuX3Nob3VsZFJlY29ubmVjdCkgewogICAgICAgIF90aGlzLl9jb25uZWN0KCk7CiAgICAgIH0KICAgICAgaWYgKF90aGlzLm9uY2xvc2UpIHsKICAgICAgICBfdGhpcy5vbmNsb3NlKGV2ZW50KTsKICAgICAgfQogICAgICBfdGhpcy5fbGlzdGVuZXJzLmNsb3NlLmZvckVhY2goZnVuY3Rpb24obGlzdGVuZXIpIHsKICAgICAgICByZXR1cm4gX3RoaXMuX2NhbGxFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcik7CiAgICAgIH0pOwogICAgfTsKICAgIHRoaXMuX3VybCA9IHVybDsKICAgIHRoaXMuX3Byb3RvY29scyA9IHByb3RvY29sczsKICAgIHRoaXMuX29wdGlvbnMgPSBvcHRpb25zOwogICAgaWYgKHRoaXMuX29wdGlvbnMuc3RhcnRDbG9zZWQpIHsKICAgICAgdGhpcy5fc2hvdWxkUmVjb25uZWN0ID0gZmFsc2U7CiAgICB9CiAgICB0aGlzLl9jb25uZWN0KCk7CiAgfQogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLCAiQ09OTkVDVElORyIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiAwOwogICAgfSwKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBjb25maWd1cmFibGU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoUmVjb25uZWN0aW5nV2ViU29ja2V0MiwgIk9QRU4iLCB7CiAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gMTsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIsICJDTE9TSU5HIiwgewogICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgcmV0dXJuIDI7CiAgICB9LAogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLCAiQ0xPU0VEIiwgewogICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgcmV0dXJuIDM7CiAgICB9LAogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZSwgIkNPTk5FQ1RJTkciLCB7CiAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5DT05ORUNUSU5HOwogICAgfSwKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBjb25maWd1cmFibGU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUsICJPUEVOIiwgewogICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgcmV0dXJuIFJlY29ubmVjdGluZ1dlYlNvY2tldDIuT1BFTjsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAiQ0xPU0lORyIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLkNMT1NJTkc7CiAgICB9LAogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZSwgIkNMT1NFRCIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLkNMT1NFRDsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAiYmluYXJ5VHlwZSIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiB0aGlzLl93cyA/IHRoaXMuX3dzLmJpbmFyeVR5cGUgOiB0aGlzLl9iaW5hcnlUeXBlOwogICAgfSwKICAgIHNldDogZnVuY3Rpb24odmFsdWUpIHsKICAgICAgdGhpcy5fYmluYXJ5VHlwZSA9IHZhbHVlOwogICAgICBpZiAodGhpcy5fd3MpIHsKICAgICAgICB0aGlzLl93cy5iaW5hcnlUeXBlID0gdmFsdWU7CiAgICAgIH0KICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAicmV0cnlDb3VudCIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiBNYXRoLm1heCh0aGlzLl9yZXRyeUNvdW50LCAwKTsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAiYnVmZmVyZWRBbW91bnQiLCB7CiAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICB2YXIgYnl0ZXMgPSB0aGlzLl9tZXNzYWdlUXVldWUucmVkdWNlKGZ1bmN0aW9uKGFjYywgbWVzc2FnZSkgewogICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSA9PT0gInN0cmluZyIpIHsKICAgICAgICAgIGFjYyArPSBtZXNzYWdlLmxlbmd0aDsKICAgICAgICB9IGVsc2UgaWYgKG1lc3NhZ2UgaW5zdGFuY2VvZiBCbG9iKSB7CiAgICAgICAgICBhY2MgKz0gbWVzc2FnZS5zaXplOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBhY2MgKz0gbWVzc2FnZS5ieXRlTGVuZ3RoOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYWNjOwogICAgICB9LCAwKTsKICAgICAgcmV0dXJuIGJ5dGVzICsgKHRoaXMuX3dzID8gdGhpcy5fd3MuYnVmZmVyZWRBbW91bnQgOiAwKTsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAiZXh0ZW5zaW9ucyIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiB0aGlzLl93cyA/IHRoaXMuX3dzLmV4dGVuc2lvbnMgOiAiIjsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAicHJvdG9jb2wiLCB7CiAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gdGhpcy5fd3MgPyB0aGlzLl93cy5wcm90b2NvbCA6ICIiOwogICAgfSwKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBjb25maWd1cmFibGU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUsICJyZWFkeVN0YXRlIiwgewogICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgaWYgKHRoaXMuX3dzKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX3dzLnJlYWR5U3RhdGU7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuc3RhcnRDbG9zZWQgPyBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLkNMT1NFRCA6IFJlY29ubmVjdGluZ1dlYlNvY2tldDIuQ09OTkVDVElORzsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAidXJsIiwgewogICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgcmV0dXJuIHRoaXMuX3dzID8gdGhpcy5fd3MudXJsIDogIiI7CiAgICB9LAogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZQogIH0pOwogIFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLmNsb3NlID0gZnVuY3Rpb24oY29kZSwgcmVhc29uKSB7CiAgICBpZiAoY29kZSA9PT0gdm9pZCAwKSB7CiAgICAgIGNvZGUgPSAxZTM7CiAgICB9CiAgICB0aGlzLl9jbG9zZUNhbGxlZCA9IHRydWU7CiAgICB0aGlzLl9zaG91bGRSZWNvbm5lY3QgPSBmYWxzZTsKICAgIHRoaXMuX2NsZWFyVGltZW91dHMoKTsKICAgIGlmICghdGhpcy5fd3MpIHsKICAgICAgdGhpcy5fZGVidWcoImNsb3NlIGVucXVldWVkOiBubyB3cyBpbnN0YW5jZSIpOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAodGhpcy5fd3MucmVhZHlTdGF0ZSA9PT0gdGhpcy5DTE9TRUQpIHsKICAgICAgdGhpcy5fZGVidWcoImNsb3NlOiBhbHJlYWR5IGNsb3NlZCIpOwogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl93cy5jbG9zZShjb2RlLCByZWFzb24pOwogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUucmVjb25uZWN0ID0gZnVuY3Rpb24oY29kZSwgcmVhc29uKSB7CiAgICB0aGlzLl9zaG91bGRSZWNvbm5lY3QgPSB0cnVlOwogICAgdGhpcy5fY2xvc2VDYWxsZWQgPSBmYWxzZTsKICAgIHRoaXMuX3JldHJ5Q291bnQgPSAtMTsKICAgIGlmICghdGhpcy5fd3MgfHwgdGhpcy5fd3MucmVhZHlTdGF0ZSA9PT0gdGhpcy5DTE9TRUQpIHsKICAgICAgdGhpcy5fY29ubmVjdCgpOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5fZGlzY29ubmVjdChjb2RlLCByZWFzb24pOwogICAgICB0aGlzLl9jb25uZWN0KCk7CiAgICB9CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5zZW5kID0gZnVuY3Rpb24oZGF0YSkgewogICAgaWYgKHRoaXMuX3dzICYmIHRoaXMuX3dzLnJlYWR5U3RhdGUgPT09IHRoaXMuT1BFTikgewogICAgICB0aGlzLl9kZWJ1Zygic2VuZCIsIGRhdGEpOwogICAgICB0aGlzLl93cy5zZW5kKGRhdGEpOwogICAgfSBlbHNlIHsKICAgICAgdmFyIF9hID0gdGhpcy5fb3B0aW9ucy5tYXhFbnF1ZXVlZE1lc3NhZ2VzLCBtYXhFbnF1ZXVlZE1lc3NhZ2VzID0gX2EgPT09IHZvaWQgMCA/IERFRkFVTFQubWF4RW5xdWV1ZWRNZXNzYWdlcyA6IF9hOwogICAgICBpZiAodGhpcy5fbWVzc2FnZVF1ZXVlLmxlbmd0aCA8IG1heEVucXVldWVkTWVzc2FnZXMpIHsKICAgICAgICB0aGlzLl9kZWJ1ZygiZW5xdWV1ZSIsIGRhdGEpOwogICAgICAgIHRoaXMuX21lc3NhZ2VRdWV1ZS5wdXNoKGRhdGEpOwogICAgICB9CiAgICB9CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5hZGRFdmVudExpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHsKICAgIGlmICh0aGlzLl9saXN0ZW5lcnNbdHlwZV0pIHsKICAgICAgdGhpcy5fbGlzdGVuZXJzW3R5cGVdLnB1c2gobGlzdGVuZXIpOwogICAgfQogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuZGlzcGF0Y2hFdmVudCA9IGZ1bmN0aW9uKGV2ZW50KSB7CiAgICB2YXIgZV8xLCBfYTsKICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLl9saXN0ZW5lcnNbZXZlbnQudHlwZV07CiAgICBpZiAobGlzdGVuZXJzKSB7CiAgICAgIHRyeSB7CiAgICAgICAgZm9yICh2YXIgbGlzdGVuZXJzXzEgPSBfX3ZhbHVlcyhsaXN0ZW5lcnMpLCBsaXN0ZW5lcnNfMV8xID0gbGlzdGVuZXJzXzEubmV4dCgpOyAhbGlzdGVuZXJzXzFfMS5kb25lOyBsaXN0ZW5lcnNfMV8xID0gbGlzdGVuZXJzXzEubmV4dCgpKSB7CiAgICAgICAgICB2YXIgbGlzdGVuZXIgPSBsaXN0ZW5lcnNfMV8xLnZhbHVlOwogICAgICAgICAgdGhpcy5fY2FsbEV2ZW50TGlzdGVuZXIoZXZlbnQsIGxpc3RlbmVyKTsKICAgICAgICB9CiAgICAgIH0gY2F0Y2ggKGVfMV8xKSB7CiAgICAgICAgZV8xID0geyBlcnJvcjogZV8xXzEgfTsKICAgICAgfSBmaW5hbGx5IHsKICAgICAgICB0cnkgewogICAgICAgICAgaWYgKGxpc3RlbmVyc18xXzEgJiYgIWxpc3RlbmVyc18xXzEuZG9uZSAmJiAoX2EgPSBsaXN0ZW5lcnNfMS5yZXR1cm4pKQogICAgICAgICAgICBfYS5jYWxsKGxpc3RlbmVyc18xKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgaWYgKGVfMSkKICAgICAgICAgICAgdGhyb3cgZV8xLmVycm9yOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIHRydWU7CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5yZW1vdmVFdmVudExpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHsKICAgIGlmICh0aGlzLl9saXN0ZW5lcnNbdHlwZV0pIHsKICAgICAgdGhpcy5fbGlzdGVuZXJzW3R5cGVdID0gdGhpcy5fbGlzdGVuZXJzW3R5cGVdLmZpbHRlcihmdW5jdGlvbihsKSB7CiAgICAgICAgcmV0dXJuIGwgIT09IGxpc3RlbmVyOwogICAgICB9KTsKICAgIH0KICB9OwogIFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLl9kZWJ1ZyA9IGZ1bmN0aW9uKCkgewogICAgdmFyIGFyZ3MgPSBbXTsKICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7CiAgICAgIGFyZ3NbX2ldID0gYXJndW1lbnRzW19pXTsKICAgIH0KICAgIGlmICh0aGlzLl9vcHRpb25zLmRlYnVnKSB7CiAgICAgIGNvbnNvbGUubG9nLmFwcGx5KGNvbnNvbGUsIF9fc3ByZWFkKFsiUldTPiJdLCBhcmdzKSk7CiAgICB9CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5fZ2V0TmV4dERlbGF5ID0gZnVuY3Rpb24oKSB7CiAgICB2YXIgX2EgPSB0aGlzLl9vcHRpb25zLCBfYiA9IF9hLnJlY29ubmVjdGlvbkRlbGF5R3Jvd0ZhY3RvciwgcmVjb25uZWN0aW9uRGVsYXlHcm93RmFjdG9yID0gX2IgPT09IHZvaWQgMCA/IERFRkFVTFQucmVjb25uZWN0aW9uRGVsYXlHcm93RmFjdG9yIDogX2IsIF9jID0gX2EubWluUmVjb25uZWN0aW9uRGVsYXksIG1pblJlY29ubmVjdGlvbkRlbGF5ID0gX2MgPT09IHZvaWQgMCA/IERFRkFVTFQubWluUmVjb25uZWN0aW9uRGVsYXkgOiBfYywgX2QgPSBfYS5tYXhSZWNvbm5lY3Rpb25EZWxheSwgbWF4UmVjb25uZWN0aW9uRGVsYXkgPSBfZCA9PT0gdm9pZCAwID8gREVGQVVMVC5tYXhSZWNvbm5lY3Rpb25EZWxheSA6IF9kOwogICAgdmFyIGRlbGF5ID0gMDsKICAgIGlmICh0aGlzLl9yZXRyeUNvdW50ID4gMCkgewogICAgICBkZWxheSA9IG1pblJlY29ubmVjdGlvbkRlbGF5ICogTWF0aC5wb3cocmVjb25uZWN0aW9uRGVsYXlHcm93RmFjdG9yLCB0aGlzLl9yZXRyeUNvdW50IC0gMSk7CiAgICAgIGlmIChkZWxheSA+IG1heFJlY29ubmVjdGlvbkRlbGF5KSB7CiAgICAgICAgZGVsYXkgPSBtYXhSZWNvbm5lY3Rpb25EZWxheTsKICAgICAgfQogICAgfQogICAgdGhpcy5fZGVidWcoIm5leHQgZGVsYXkiLCBkZWxheSk7CiAgICByZXR1cm4gZGVsYXk7CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5fd2FpdCA9IGZ1bmN0aW9uKCkgewogICAgdmFyIF90aGlzID0gdGhpczsKICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlKSB7CiAgICAgIHNldFRpbWVvdXQocmVzb2x2ZSwgX3RoaXMuX2dldE5leHREZWxheSgpKTsKICAgIH0pOwogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuX2dldE5leHRVcmwgPSBmdW5jdGlvbih1cmxQcm92aWRlcikgewogICAgaWYgKHR5cGVvZiB1cmxQcm92aWRlciA9PT0gInN0cmluZyIpIHsKICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh1cmxQcm92aWRlcik7CiAgICB9CiAgICBpZiAodHlwZW9mIHVybFByb3ZpZGVyID09PSAiZnVuY3Rpb24iKSB7CiAgICAgIHZhciB1cmwgPSB1cmxQcm92aWRlcigpOwogICAgICBpZiAodHlwZW9mIHVybCA9PT0gInN0cmluZyIpIHsKICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHVybCk7CiAgICAgIH0KICAgICAgaWYgKCEhdXJsLnRoZW4pIHsKICAgICAgICByZXR1cm4gdXJsOwogICAgICB9CiAgICB9CiAgICB0aHJvdyBFcnJvcigiSW52YWxpZCBVUkwiKTsKICB9OwogIFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLl9jb25uZWN0ID0gZnVuY3Rpb24oKSB7CiAgICB2YXIgX3RoaXMgPSB0aGlzOwogICAgaWYgKHRoaXMuX2Nvbm5lY3RMb2NrIHx8ICF0aGlzLl9zaG91bGRSZWNvbm5lY3QpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5fY29ubmVjdExvY2sgPSB0cnVlOwogICAgdmFyIF9hID0gdGhpcy5fb3B0aW9ucywgX2IgPSBfYS5tYXhSZXRyaWVzLCBtYXhSZXRyaWVzID0gX2IgPT09IHZvaWQgMCA/IERFRkFVTFQubWF4UmV0cmllcyA6IF9iLCBfYyA9IF9hLmNvbm5lY3Rpb25UaW1lb3V0LCBjb25uZWN0aW9uVGltZW91dCA9IF9jID09PSB2b2lkIDAgPyBERUZBVUxULmNvbm5lY3Rpb25UaW1lb3V0IDogX2MsIF9kID0gX2EuV2ViU29ja2V0LCBXZWJTb2NrZXQyID0gX2QgPT09IHZvaWQgMCA/IGdldEdsb2JhbFdlYlNvY2tldCgpIDogX2Q7CiAgICBpZiAodGhpcy5fcmV0cnlDb3VudCA+PSBtYXhSZXRyaWVzKSB7CiAgICAgIHRoaXMuX2RlYnVnKCJtYXggcmV0cmllcyByZWFjaGVkIiwgdGhpcy5fcmV0cnlDb3VudCwgIj49IiwgbWF4UmV0cmllcyk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuX3JldHJ5Q291bnQrKzsKICAgIHRoaXMuX2RlYnVnKCJjb25uZWN0IiwgdGhpcy5fcmV0cnlDb3VudCk7CiAgICB0aGlzLl9yZW1vdmVMaXN0ZW5lcnMoKTsKICAgIGlmICghaXNXZWJTb2NrZXQoV2ViU29ja2V0MikpIHsKICAgICAgdGhyb3cgRXJyb3IoIk5vIHZhbGlkIFdlYlNvY2tldCBjbGFzcyBwcm92aWRlZCIpOwogICAgfQogICAgdGhpcy5fd2FpdCgpLnRoZW4oZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiBfdGhpcy5fZ2V0TmV4dFVybChfdGhpcy5fdXJsKTsKICAgIH0pLnRoZW4oZnVuY3Rpb24odXJsKSB7CiAgICAgIGlmIChfdGhpcy5fY2xvc2VDYWxsZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgX3RoaXMuX2RlYnVnKCJjb25uZWN0IiwgeyB1cmwsIHByb3RvY29sczogX3RoaXMuX3Byb3RvY29scyB9KTsKICAgICAgX3RoaXMuX3dzID0gX3RoaXMuX3Byb3RvY29scyA/IG5ldyBXZWJTb2NrZXQyKHVybCwgX3RoaXMuX3Byb3RvY29scykgOiBuZXcgV2ViU29ja2V0Mih1cmwpOwogICAgICBfdGhpcy5fd3MuYmluYXJ5VHlwZSA9IF90aGlzLl9iaW5hcnlUeXBlOwogICAgICBfdGhpcy5fY29ubmVjdExvY2sgPSBmYWxzZTsKICAgICAgX3RoaXMuX2FkZExpc3RlbmVycygpOwogICAgICBfdGhpcy5fY29ubmVjdFRpbWVvdXQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiBfdGhpcy5faGFuZGxlVGltZW91dCgpOwogICAgICB9LCBjb25uZWN0aW9uVGltZW91dCk7CiAgICB9KTsKICB9OwogIFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLl9oYW5kbGVUaW1lb3V0ID0gZnVuY3Rpb24oKSB7CiAgICB0aGlzLl9kZWJ1ZygidGltZW91dCBldmVudCIpOwogICAgdGhpcy5faGFuZGxlRXJyb3IobmV3IEVycm9yRXZlbnQoRXJyb3IoIlRJTUVPVVQiKSwgdGhpcykpOwogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuX2Rpc2Nvbm5lY3QgPSBmdW5jdGlvbihjb2RlLCByZWFzb24pIHsKICAgIGlmIChjb2RlID09PSB2b2lkIDApIHsKICAgICAgY29kZSA9IDFlMzsKICAgIH0KICAgIHRoaXMuX2NsZWFyVGltZW91dHMoKTsKICAgIGlmICghdGhpcy5fd3MpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5fcmVtb3ZlTGlzdGVuZXJzKCk7CiAgICB0cnkgewogICAgICB0aGlzLl93cy5jbG9zZShjb2RlLCByZWFzb24pOwogICAgICB0aGlzLl9oYW5kbGVDbG9zZShuZXcgQ2xvc2VFdmVudChjb2RlLCByZWFzb24sIHRoaXMpKTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICB9CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5fYWNjZXB0T3BlbiA9IGZ1bmN0aW9uKCkgewogICAgdGhpcy5fZGVidWcoImFjY2VwdCBvcGVuIik7CiAgICB0aGlzLl9yZXRyeUNvdW50ID0gMDsKICB9OwogIFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLl9jYWxsRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uKGV2ZW50LCBsaXN0ZW5lcikgewogICAgaWYgKCJoYW5kbGVFdmVudCIgaW4gbGlzdGVuZXIpIHsKICAgICAgbGlzdGVuZXIuaGFuZGxlRXZlbnQoZXZlbnQpOwogICAgfSBlbHNlIHsKICAgICAgbGlzdGVuZXIoZXZlbnQpOwogICAgfQogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuX3JlbW92ZUxpc3RlbmVycyA9IGZ1bmN0aW9uKCkgewogICAgaWYgKCF0aGlzLl93cykgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9kZWJ1ZygicmVtb3ZlTGlzdGVuZXJzIik7CiAgICB0aGlzLl93cy5yZW1vdmVFdmVudExpc3RlbmVyKCJvcGVuIiwgdGhpcy5faGFuZGxlT3Blbik7CiAgICB0aGlzLl93cy5yZW1vdmVFdmVudExpc3RlbmVyKCJjbG9zZSIsIHRoaXMuX2hhbmRsZUNsb3NlKTsKICAgIHRoaXMuX3dzLnJlbW92ZUV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLCB0aGlzLl9oYW5kbGVNZXNzYWdlKTsKICAgIHRoaXMuX3dzLnJlbW92ZUV2ZW50TGlzdGVuZXIoImVycm9yIiwgdGhpcy5faGFuZGxlRXJyb3IpOwogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuX2FkZExpc3RlbmVycyA9IGZ1bmN0aW9uKCkgewogICAgaWYgKCF0aGlzLl93cykgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9kZWJ1ZygiYWRkTGlzdGVuZXJzIik7CiAgICB0aGlzLl93cy5hZGRFdmVudExpc3RlbmVyKCJvcGVuIiwgdGhpcy5faGFuZGxlT3Blbik7CiAgICB0aGlzLl93cy5hZGRFdmVudExpc3RlbmVyKCJjbG9zZSIsIHRoaXMuX2hhbmRsZUNsb3NlKTsKICAgIHRoaXMuX3dzLmFkZEV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLCB0aGlzLl9oYW5kbGVNZXNzYWdlKTsKICAgIHRoaXMuX3dzLmFkZEV2ZW50TGlzdGVuZXIoImVycm9yIiwgdGhpcy5faGFuZGxlRXJyb3IpOwogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuX2NsZWFyVGltZW91dHMgPSBmdW5jdGlvbigpIHsKICAgIGNsZWFyVGltZW91dCh0aGlzLl9jb25uZWN0VGltZW91dCk7CiAgICBjbGVhclRpbWVvdXQodGhpcy5fdXB0aW1lVGltZW91dCk7CiAgfTsKICByZXR1cm4gUmVjb25uZWN0aW5nV2ViU29ja2V0MjsKfSgpOwp2YXIgcmVjb25uZWN0aW5nX3dlYnNvY2tldF9tanNfZGVmYXVsdCA9IFJlY29ubmVjdGluZ1dlYlNvY2tldDsKCi8vIG5vZGVfbW9kdWxlcy9AYmpvcm4zL2Jyb3dzZXJfd2FzaV9zaGltL2Rpc3Qvd2FzaV9kZWZzLmpzCnZhciBDTE9DS0lEX1JFQUxUSU1FID0gMDsKdmFyIENMT0NLSURfTU9OT1RPTklDID0gMTsKdmFyIEVSUk5PX1NVQ0NFU1MgPSAwOwp2YXIgRVJSTk9fQkFERiA9IDg7CnZhciBFUlJOT19FWElTVCA9IDIwOwp2YXIgRVJSTk9fSU5WQUwgPSAyODsKdmFyIEVSUk5PX0lTRElSID0gMzE7CnZhciBFUlJOT19OQU1FVE9PTE9ORyA9IDM3Owp2YXIgRVJSTk9fTk9FTlQgPSA0NDsKdmFyIEVSUk5PX05PU1lTID0gNTI7CnZhciBFUlJOT19OT1RESVIgPSA1NDsKdmFyIEVSUk5PX05PVEVNUFRZID0gNTU7CnZhciBFUlJOT19OT1RTVVAgPSA1ODsKdmFyIEVSUk5PX1BFUk0gPSA2MzsKdmFyIEVSUk5PX05PVENBUEFCTEUgPSA3NjsKdmFyIFJJR0hUU19GRF9EQVRBU1lOQyA9IDEgPDwgMDsKdmFyIFJJR0hUU19GRF9SRUFEID0gMSA8PCAxOwp2YXIgUklHSFRTX0ZEX1NFRUsgPSAxIDw8IDI7CnZhciBSSUdIVFNfRkRfRkRTVEFUX1NFVF9GTEFHUyA9IDEgPDwgMzsKdmFyIFJJR0hUU19GRF9TWU5DID0gMSA8PCA0Owp2YXIgUklHSFRTX0ZEX1RFTEwgPSAxIDw8IDU7CnZhciBSSUdIVFNfRkRfV1JJVEUgPSAxIDw8IDY7CnZhciBSSUdIVFNfRkRfQURWSVNFID0gMSA8PCA3Owp2YXIgUklHSFRTX0ZEX0FMTE9DQVRFID0gMSA8PCA4Owp2YXIgUklHSFRTX1BBVEhfQ1JFQVRFX0RJUkVDVE9SWSA9IDEgPDwgOTsKdmFyIFJJR0hUU19QQVRIX0NSRUFURV9GSUxFID0gMSA8PCAxMDsKdmFyIFJJR0hUU19QQVRIX0xJTktfU09VUkNFID0gMSA8PCAxMTsKdmFyIFJJR0hUU19QQVRIX0xJTktfVEFSR0VUID0gMSA8PCAxMjsKdmFyIFJJR0hUU19QQVRIX09QRU4gPSAxIDw8IDEzOwp2YXIgUklHSFRTX0ZEX1JFQURESVIgPSAxIDw8IDE0Owp2YXIgUklHSFRTX1BBVEhfUkVBRExJTksgPSAxIDw8IDE1Owp2YXIgUklHSFRTX1BBVEhfUkVOQU1FX1NPVVJDRSA9IDEgPDwgMTY7CnZhciBSSUdIVFNfUEFUSF9SRU5BTUVfVEFSR0VUID0gMSA8PCAxNzsKdmFyIFJJR0hUU19QQVRIX0ZJTEVTVEFUX0dFVCA9IDEgPDwgMTg7CnZhciBSSUdIVFNfUEFUSF9GSUxFU1RBVF9TRVRfU0laRSA9IDEgPDwgMTk7CnZhciBSSUdIVFNfUEFUSF9GSUxFU1RBVF9TRVRfVElNRVMgPSAxIDw8IDIwOwp2YXIgUklHSFRTX0ZEX0ZJTEVTVEFUX0dFVCA9IDEgPDwgMjE7CnZhciBSSUdIVFNfRkRfRklMRVNUQVRfU0VUX1NJWkUgPSAxIDw8IDIyOwp2YXIgUklHSFRTX0ZEX0ZJTEVTVEFUX1NFVF9USU1FUyA9IDEgPDwgMjM7CnZhciBSSUdIVFNfUEFUSF9TWU1MSU5LID0gMSA8PCAyNDsKdmFyIFJJR0hUU19QQVRIX1JFTU9WRV9ESVJFQ1RPUlkgPSAxIDw8IDI1Owp2YXIgUklHSFRTX1BBVEhfVU5MSU5LX0ZJTEUgPSAxIDw8IDI2Owp2YXIgUklHSFRTX1BPTExfRkRfUkVBRFdSSVRFID0gMSA8PCAyNzsKdmFyIFJJR0hUU19TT0NLX1NIVVRET1dOID0gMSA8PCAyODsKdmFyIElvdmVjID0gY2xhc3MgewogIHN0YXRpYyByZWFkX2J5dGVzKHZpZXcsIHB0cikgewogICAgY29uc3QgaW92ZWMgPSBuZXcgSW92ZWMoKTsKICAgIGlvdmVjLmJ1ZiA9IHZpZXcuZ2V0VWludDMyKHB0ciwgdHJ1ZSk7CiAgICBpb3ZlYy5idWZfbGVuID0gdmlldy5nZXRVaW50MzIocHRyICsgNCwgdHJ1ZSk7CiAgICByZXR1cm4gaW92ZWM7CiAgfQogIHN0YXRpYyByZWFkX2J5dGVzX2FycmF5KHZpZXcsIHB0ciwgbGVuKSB7CiAgICBjb25zdCBpb3ZlY3MgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHsKICAgICAgaW92ZWNzLnB1c2goSW92ZWMucmVhZF9ieXRlcyh2aWV3LCBwdHIgKyA4ICogaSkpOwogICAgfQogICAgcmV0dXJuIGlvdmVjczsKICB9Cn07CnZhciBDaW92ZWMgPSBjbGFzcyB7CiAgc3RhdGljIHJlYWRfYnl0ZXModmlldywgcHRyKSB7CiAgICBjb25zdCBpb3ZlYyA9IG5ldyBDaW92ZWMoKTsKICAgIGlvdmVjLmJ1ZiA9IHZpZXcuZ2V0VWludDMyKHB0ciwgdHJ1ZSk7CiAgICBpb3ZlYy5idWZfbGVuID0gdmlldy5nZXRVaW50MzIocHRyICsgNCwgdHJ1ZSk7CiAgICByZXR1cm4gaW92ZWM7CiAgfQogIHN0YXRpYyByZWFkX2J5dGVzX2FycmF5KHZpZXcsIHB0ciwgbGVuKSB7CiAgICBjb25zdCBpb3ZlY3MgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHsKICAgICAgaW92ZWNzLnB1c2goQ2lvdmVjLnJlYWRfYnl0ZXModmlldywgcHRyICsgOCAqIGkpKTsKICAgIH0KICAgIHJldHVybiBpb3ZlY3M7CiAgfQp9Owp2YXIgV0hFTkNFX1NFVCA9IDA7CnZhciBXSEVOQ0VfQ1VSID0gMTsKdmFyIFdIRU5DRV9FTkQgPSAyOwp2YXIgRklMRVRZUEVfQ0hBUkFDVEVSX0RFVklDRSA9IDI7CnZhciBGSUxFVFlQRV9ESVJFQ1RPUlkgPSAzOwp2YXIgRklMRVRZUEVfUkVHVUxBUl9GSUxFID0gNDsKdmFyIERpcmVudCA9IGNsYXNzIHsKICBoZWFkX2xlbmd0aCgpIHsKICAgIHJldHVybiAyNDsKICB9CiAgbmFtZV9sZW5ndGgoKSB7CiAgICByZXR1cm4gdGhpcy5kaXJfbmFtZS5ieXRlTGVuZ3RoOwogIH0KICB3cml0ZV9oZWFkX2J5dGVzKHZpZXcsIHB0cikgewogICAgdmlldy5zZXRCaWdVaW50NjQocHRyLCB0aGlzLmRfbmV4dCwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA4LCB0aGlzLmRfaW5vLCB0cnVlKTsKICAgIHZpZXcuc2V0VWludDMyKHB0ciArIDE2LCB0aGlzLmRpcl9uYW1lLmxlbmd0aCwgdHJ1ZSk7CiAgICB2aWV3LnNldFVpbnQ4KHB0ciArIDIwLCB0aGlzLmRfdHlwZSk7CiAgfQogIHdyaXRlX25hbWVfYnl0ZXModmlldzgsIHB0ciwgYnVmX2xlbikgewogICAgdmlldzguc2V0KHRoaXMuZGlyX25hbWUuc2xpY2UoMCwgTWF0aC5taW4odGhpcy5kaXJfbmFtZS5ieXRlTGVuZ3RoLCBidWZfbGVuKSksIHB0cik7CiAgfQogIGNvbnN0cnVjdG9yKG5leHRfY29va2llLCBuYW1lLCB0eXBlKSB7CiAgICB0aGlzLmRfaW5vID0gMG47CiAgICBjb25zdCBlbmNvZGVkX25hbWUgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUobmFtZSk7CiAgICB0aGlzLmRfbmV4dCA9IG5leHRfY29va2llOwogICAgdGhpcy5kX25hbWxlbiA9IGVuY29kZWRfbmFtZS5ieXRlTGVuZ3RoOwogICAgdGhpcy5kX3R5cGUgPSB0eXBlOwogICAgdGhpcy5kaXJfbmFtZSA9IGVuY29kZWRfbmFtZTsKICB9Cn07CnZhciBGREZMQUdTX0FQUEVORCA9IDEgPDwgMDsKdmFyIEZERkxBR1NfRFNZTkMgPSAxIDw8IDE7CnZhciBGREZMQUdTX05PTkJMT0NLID0gMSA8PCAyOwp2YXIgRkRGTEFHU19SU1lOQyA9IDEgPDwgMzsKdmFyIEZERkxBR1NfU1lOQyA9IDEgPDwgNDsKdmFyIEZkc3RhdCA9IGNsYXNzIHsKICB3cml0ZV9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIHZpZXcuc2V0VWludDgocHRyLCB0aGlzLmZzX2ZpbGV0eXBlKTsKICAgIHZpZXcuc2V0VWludDE2KHB0ciArIDIsIHRoaXMuZnNfZmxhZ3MsIHRydWUpOwogICAgdmlldy5zZXRCaWdVaW50NjQocHRyICsgOCwgdGhpcy5mc19yaWdodHNfYmFzZSwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyAxNiwgdGhpcy5mc19yaWdodHNfaW5oZXJpdGVkLCB0cnVlKTsKICB9CiAgY29uc3RydWN0b3IoZmlsZXR5cGUsIGZsYWdzKSB7CiAgICB0aGlzLmZzX3JpZ2h0c19iYXNlID0gMG47CiAgICB0aGlzLmZzX3JpZ2h0c19pbmhlcml0ZWQgPSAwbjsKICAgIHRoaXMuZnNfZmlsZXR5cGUgPSBmaWxldHlwZTsKICAgIHRoaXMuZnNfZmxhZ3MgPSBmbGFnczsKICB9Cn07CnZhciBGU1RGTEFHU19BVElNID0gMSA8PCAwOwp2YXIgRlNURkxBR1NfQVRJTV9OT1cgPSAxIDw8IDE7CnZhciBGU1RGTEFHU19NVElNID0gMSA8PCAyOwp2YXIgRlNURkxBR1NfTVRJTV9OT1cgPSAxIDw8IDM7CnZhciBPRkxBR1NfQ1JFQVQgPSAxIDw8IDA7CnZhciBPRkxBR1NfRElSRUNUT1JZID0gMSA8PCAxOwp2YXIgT0ZMQUdTX0VYQ0wgPSAxIDw8IDI7CnZhciBPRkxBR1NfVFJVTkMgPSAxIDw8IDM7CnZhciBGaWxlc3RhdCA9IGNsYXNzIHsKICB3cml0ZV9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciwgdGhpcy5kZXYsIHRydWUpOwogICAgdmlldy5zZXRCaWdVaW50NjQocHRyICsgOCwgdGhpcy5pbm8sIHRydWUpOwogICAgdmlldy5zZXRVaW50OChwdHIgKyAxNiwgdGhpcy5maWxldHlwZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyAyNCwgdGhpcy5ubGluaywgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyAzMiwgdGhpcy5zaXplLCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDM4LCB0aGlzLmF0aW0sIHRydWUpOwogICAgdmlldy5zZXRCaWdVaW50NjQocHRyICsgNDYsIHRoaXMubXRpbSwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA1MiwgdGhpcy5jdGltLCB0cnVlKTsKICB9CiAgY29uc3RydWN0b3IoZmlsZXR5cGUsIHNpemUpIHsKICAgIHRoaXMuZGV2ID0gMG47CiAgICB0aGlzLmlubyA9IDBuOwogICAgdGhpcy5ubGluayA9IDBuOwogICAgdGhpcy5hdGltID0gMG47CiAgICB0aGlzLm10aW0gPSAwbjsKICAgIHRoaXMuY3RpbSA9IDBuOwogICAgdGhpcy5maWxldHlwZSA9IGZpbGV0eXBlOwogICAgdGhpcy5zaXplID0gc2l6ZTsKICB9Cn07CnZhciBFVkVOVFJXRkxBR1NfRkRfUkVBRFdSSVRFX0hBTkdVUCA9IDEgPDwgMDsKdmFyIFNVQkNMT0NLRkxBR1NfU1VCU0NSSVBUSU9OX0NMT0NLX0FCU1RJTUUgPSAxIDw8IDA7CnZhciBSSUZMQUdTX1JFQ1ZfUEVFSyA9IDEgPDwgMDsKdmFyIFJJRkxBR1NfUkVDVl9XQUlUQUxMID0gMSA8PCAxOwp2YXIgUk9GTEFHU19SRUNWX0RBVEFfVFJVTkNBVEVEID0gMSA8PCAwOwp2YXIgU0RGTEFHU19SRCA9IDEgPDwgMDsKdmFyIFNERkxBR1NfV1IgPSAxIDw8IDE7CnZhciBQUkVPUEVOVFlQRV9ESVIgPSAwOwp2YXIgUHJlc3RhdERpciA9IGNsYXNzIHsKICB3cml0ZV9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIHZpZXcuc2V0VWludDMyKHB0ciwgdGhpcy5wcl9uYW1lLmJ5dGVMZW5ndGgsIHRydWUpOwogIH0KICBjb25zdHJ1Y3RvcihuYW1lKSB7CiAgICB0aGlzLnByX25hbWUgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUobmFtZSk7CiAgfQp9Owp2YXIgUHJlc3RhdCA9IGNsYXNzIHsKICBzdGF0aWMgZGlyKG5hbWUpIHsKICAgIGNvbnN0IHByZXN0YXQgPSBuZXcgUHJlc3RhdCgpOwogICAgcHJlc3RhdC50YWcgPSBQUkVPUEVOVFlQRV9ESVI7CiAgICBwcmVzdGF0LmlubmVyID0gbmV3IFByZXN0YXREaXIobmFtZSk7CiAgICByZXR1cm4gcHJlc3RhdDsKICB9CiAgd3JpdGVfYnl0ZXModmlldywgcHRyKSB7CiAgICB2aWV3LnNldFVpbnQzMihwdHIsIHRoaXMudGFnLCB0cnVlKTsKICAgIHRoaXMuaW5uZXIud3JpdGVfYnl0ZXModmlldywgcHRyICsgNCk7CiAgfQp9OwoKLy8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC9kZWJ1Zy5qcwp2YXIgRGVidWcgPSBjbGFzcyBEZWJ1ZzIgewogIGVuYWJsZShlbmFibGVkKSB7CiAgICB0aGlzLmxvZyA9IGNyZWF0ZUxvZ2dlcihlbmFibGVkID09PSB2b2lkIDAgPyB0cnVlIDogZW5hYmxlZCwgdGhpcy5wcmVmaXgpOwogIH0KICBnZXQgZW5hYmxlZCgpIHsKICAgIHJldHVybiB0aGlzLmlzRW5hYmxlZDsKICB9CiAgY29uc3RydWN0b3IoaXNFbmFibGVkKSB7CiAgICB0aGlzLmlzRW5hYmxlZCA9IGlzRW5hYmxlZDsKICAgIHRoaXMucHJlZml4ID0gIndhc2k6IjsKICAgIHRoaXMuZW5hYmxlKGlzRW5hYmxlZCk7CiAgfQp9OwpmdW5jdGlvbiBjcmVhdGVMb2dnZXIoZW5hYmxlZCwgcHJlZml4KSB7CiAgaWYgKGVuYWJsZWQpIHsKICAgIGNvbnN0IGEgPSBjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUsICIlYyVzIiwgImNvbG9yOiAjMjY1QkEwIiwgcHJlZml4KTsKICAgIHJldHVybiBhOwogIH0gZWxzZSB7CiAgICByZXR1cm4gKCkgPT4gewogICAgfTsKICB9Cn0KdmFyIGRlYnVnID0gbmV3IERlYnVnKGZhbHNlKTsKCi8vIG5vZGVfbW9kdWxlcy9AYmpvcm4zL2Jyb3dzZXJfd2FzaV9zaGltL2Rpc3Qvd2FzaS5qcwp2YXIgV0FTSVByb2NFeGl0ID0gY2xhc3MgZXh0ZW5kcyBFcnJvciB7CiAgY29uc3RydWN0b3IoY29kZSkgewogICAgc3VwZXIoImV4aXQgd2l0aCBleGl0IGNvZGUgIiArIGNvZGUpOwogICAgdGhpcy5jb2RlID0gY29kZTsKICB9Cn07CnZhciBXQVNJID0gY2xhc3MgV0FTSTIgewogIHN0YXJ0KGluc3RhbmNlKSB7CiAgICB0aGlzLmluc3QgPSBpbnN0YW5jZTsKICAgIHRyeSB7CiAgICAgIGluc3RhbmNlLmV4cG9ydHMuX3N0YXJ0KCk7CiAgICAgIHJldHVybiAwOwogICAgfSBjYXRjaCAoZSkgewogICAgICBpZiAoZSBpbnN0YW5jZW9mIFdBU0lQcm9jRXhpdCkgewogICAgICAgIHJldHVybiBlLmNvZGU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgZTsKICAgICAgfQogICAgfQogIH0KICBpbml0aWFsaXplKGluc3RhbmNlKSB7CiAgICB0aGlzLmluc3QgPSBpbnN0YW5jZTsKICAgIGlmIChpbnN0YW5jZS5leHBvcnRzLl9pbml0aWFsaXplKSB7CiAgICAgIGluc3RhbmNlLmV4cG9ydHMuX2luaXRpYWxpemUoKTsKICAgIH0KICB9CiAgY29uc3RydWN0b3IoYXJncywgZW52LCBmZHMsIG9wdGlvbnMgPSB7fSkgewogICAgdGhpcy5hcmdzID0gW107CiAgICB0aGlzLmVudiA9IFtdOwogICAgdGhpcy5mZHMgPSBbXTsKICAgIGRlYnVnLmVuYWJsZShvcHRpb25zLmRlYnVnKTsKICAgIHRoaXMuYXJncyA9IGFyZ3M7CiAgICB0aGlzLmVudiA9IGVudjsKICAgIHRoaXMuZmRzID0gZmRzOwogICAgY29uc3Qgc2VsZiA9IHRoaXM7CiAgICB0aGlzLndhc2lJbXBvcnQgPSB7IGFyZ3Nfc2l6ZXNfZ2V0KGFyZ2MsIGFyZ3ZfYnVmX3NpemUpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBidWZmZXIuc2V0VWludDMyKGFyZ2MsIHNlbGYuYXJncy5sZW5ndGgsIHRydWUpOwogICAgICBsZXQgYnVmX3NpemUgPSAwOwogICAgICBmb3IgKGNvbnN0IGFyZyBvZiBzZWxmLmFyZ3MpIHsKICAgICAgICBidWZfc2l6ZSArPSBhcmcubGVuZ3RoICsgMTsKICAgICAgfQogICAgICBidWZmZXIuc2V0VWludDMyKGFyZ3ZfYnVmX3NpemUsIGJ1Zl9zaXplLCB0cnVlKTsKICAgICAgZGVidWcubG9nKGJ1ZmZlci5nZXRVaW50MzIoYXJnYywgdHJ1ZSksIGJ1ZmZlci5nZXRVaW50MzIoYXJndl9idWZfc2l6ZSwgdHJ1ZSkpOwogICAgICByZXR1cm4gMDsKICAgIH0sIGFyZ3NfZ2V0KGFyZ3YsIGFyZ3ZfYnVmKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBvcmlnX2FyZ3ZfYnVmID0gYXJndl9idWY7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZi5hcmdzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgYnVmZmVyLnNldFVpbnQzMihhcmd2LCBhcmd2X2J1ZiwgdHJ1ZSk7CiAgICAgICAgYXJndiArPSA0OwogICAgICAgIGNvbnN0IGFyZyA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzZWxmLmFyZ3NbaV0pOwogICAgICAgIGJ1ZmZlcjguc2V0KGFyZywgYXJndl9idWYpOwogICAgICAgIGJ1ZmZlci5zZXRVaW50OChhcmd2X2J1ZiArIGFyZy5sZW5ndGgsIDApOwogICAgICAgIGFyZ3ZfYnVmICs9IGFyZy5sZW5ndGggKyAxOwogICAgICB9CiAgICAgIGlmIChkZWJ1Zy5lbmFibGVkKSB7CiAgICAgICAgZGVidWcubG9nKG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShvcmlnX2FyZ3ZfYnVmLCBhcmd2X2J1ZikpKTsKICAgICAgfQogICAgICByZXR1cm4gMDsKICAgIH0sIGVudmlyb25fc2l6ZXNfZ2V0KGVudmlyb25fY291bnQsIGVudmlyb25fc2l6ZSkgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGJ1ZmZlci5zZXRVaW50MzIoZW52aXJvbl9jb3VudCwgc2VsZi5lbnYubGVuZ3RoLCB0cnVlKTsKICAgICAgbGV0IGJ1Zl9zaXplID0gMDsKICAgICAgZm9yIChjb25zdCBlbnZpcm9uIG9mIHNlbGYuZW52KSB7CiAgICAgICAgYnVmX3NpemUgKz0gZW52aXJvbi5sZW5ndGggKyAxOwogICAgICB9CiAgICAgIGJ1ZmZlci5zZXRVaW50MzIoZW52aXJvbl9zaXplLCBidWZfc2l6ZSwgdHJ1ZSk7CiAgICAgIGRlYnVnLmxvZyhidWZmZXIuZ2V0VWludDMyKGVudmlyb25fY291bnQsIHRydWUpLCBidWZmZXIuZ2V0VWludDMyKGVudmlyb25fc2l6ZSwgdHJ1ZSkpOwogICAgICByZXR1cm4gMDsKICAgIH0sIGVudmlyb25fZ2V0KGVudmlyb24sIGVudmlyb25fYnVmKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBvcmlnX2Vudmlyb25fYnVmID0gZW52aXJvbl9idWY7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZi5lbnYubGVuZ3RoOyBpKyspIHsKICAgICAgICBidWZmZXIuc2V0VWludDMyKGVudmlyb24sIGVudmlyb25fYnVmLCB0cnVlKTsKICAgICAgICBlbnZpcm9uICs9IDQ7CiAgICAgICAgY29uc3QgZSA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzZWxmLmVudltpXSk7CiAgICAgICAgYnVmZmVyOC5zZXQoZSwgZW52aXJvbl9idWYpOwogICAgICAgIGJ1ZmZlci5zZXRVaW50OChlbnZpcm9uX2J1ZiArIGUubGVuZ3RoLCAwKTsKICAgICAgICBlbnZpcm9uX2J1ZiArPSBlLmxlbmd0aCArIDE7CiAgICAgIH0KICAgICAgaWYgKGRlYnVnLmVuYWJsZWQpIHsKICAgICAgICBkZWJ1Zy5sb2cobmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG9yaWdfZW52aXJvbl9idWYsIGVudmlyb25fYnVmKSkpOwogICAgICB9CiAgICAgIHJldHVybiAwOwogICAgfSwgY2xvY2tfcmVzX2dldChpZCwgcmVzX3B0cikgewogICAgICBsZXQgcmVzb2x1dGlvblZhbHVlOwogICAgICBzd2l0Y2ggKGlkKSB7CiAgICAgICAgY2FzZSBDTE9DS0lEX01PTk9UT05JQzogewogICAgICAgICAgcmVzb2x1dGlvblZhbHVlID0gNTAwMG47CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgY2FzZSBDTE9DS0lEX1JFQUxUSU1FOiB7CiAgICAgICAgICByZXNvbHV0aW9uVmFsdWUgPSAxMDAwMDAwbjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBkZWZhdWx0OgogICAgICAgICAgcmV0dXJuIEVSUk5PX05PU1lTOwogICAgICB9CiAgICAgIGNvbnN0IHZpZXcgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIHZpZXcuc2V0QmlnVWludDY0KHJlc19wdHIsIHJlc29sdXRpb25WYWx1ZSwgdHJ1ZSk7CiAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgfSwgY2xvY2tfdGltZV9nZXQoaWQsIHByZWNpc2lvbiwgdGltZSkgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChpZCA9PT0gQ0xPQ0tJRF9SRUFMVElNRSkgewogICAgICAgIGJ1ZmZlci5zZXRCaWdVaW50NjQodGltZSwgQmlnSW50KG5ldyBEYXRlKCkuZ2V0VGltZSgpKSAqIDEwMDAwMDBuLCB0cnVlKTsKICAgICAgfSBlbHNlIGlmIChpZCA9PSBDTE9DS0lEX01PTk9UT05JQykgewogICAgICAgIGxldCBtb25vdG9uaWNfdGltZTsKICAgICAgICB0cnkgewogICAgICAgICAgbW9ub3RvbmljX3RpbWUgPSBCaWdJbnQoTWF0aC5yb3VuZChwZXJmb3JtYW5jZS5ub3coKSAqIDFlNikpOwogICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgIG1vbm90b25pY190aW1lID0gMG47CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRCaWdVaW50NjQodGltZSwgbW9ub3RvbmljX3RpbWUsIHRydWUpOwogICAgICB9IGVsc2UgewogICAgICAgIGJ1ZmZlci5zZXRCaWdVaW50NjQodGltZSwgMG4sIHRydWUpOwogICAgICB9CiAgICAgIHJldHVybiAwOwogICAgfSwgZmRfYWR2aXNlKGZkLCBvZmZzZXQsIGxlbiwgYWR2aWNlKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2FsbG9jYXRlKGZkLCBvZmZzZXQsIGxlbikgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfYWxsb2NhdGUob2Zmc2V0LCBsZW4pOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9jbG9zZShmZCkgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHJldCA9IHNlbGYuZmRzW2ZkXS5mZF9jbG9zZSgpOwogICAgICAgIHNlbGYuZmRzW2ZkXSA9IHZvaWQgMDsKICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9kYXRhc3luYyhmZCkgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfc3luYygpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9mZHN0YXRfZ2V0KGZkLCBmZHN0YXRfcHRyKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIGZkc3RhdCB9ID0gc2VsZi5mZHNbZmRdLmZkX2Zkc3RhdF9nZXQoKTsKICAgICAgICBpZiAoZmRzdGF0ICE9IG51bGwpIHsKICAgICAgICAgIGZkc3RhdC53cml0ZV9ieXRlcyhuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlciksIGZkc3RhdF9wdHIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9mZHN0YXRfc2V0X2ZsYWdzKGZkLCBmbGFncykgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfZmRzdGF0X3NldF9mbGFncyhmbGFncyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Zkc3RhdF9zZXRfcmlnaHRzKGZkLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICByZXR1cm4gc2VsZi5mZHNbZmRdLmZkX2Zkc3RhdF9zZXRfcmlnaHRzKGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2ZpbGVzdGF0X2dldChmZCwgZmlsZXN0YXRfcHRyKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIGZpbGVzdGF0IH0gPSBzZWxmLmZkc1tmZF0uZmRfZmlsZXN0YXRfZ2V0KCk7CiAgICAgICAgaWYgKGZpbGVzdGF0ICE9IG51bGwpIHsKICAgICAgICAgIGZpbGVzdGF0LndyaXRlX2J5dGVzKG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKSwgZmlsZXN0YXRfcHRyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfZmlsZXN0YXRfc2V0X3NpemUoZmQsIHNpemUpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICByZXR1cm4gc2VsZi5mZHNbZmRdLmZkX2ZpbGVzdGF0X3NldF9zaXplKHNpemUpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9maWxlc3RhdF9zZXRfdGltZXMoZmQsIGF0aW0sIG10aW0sIGZzdF9mbGFncykgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfZmlsZXN0YXRfc2V0X3RpbWVzKGF0aW0sIG10aW0sIGZzdF9mbGFncyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3ByZWFkKGZkLCBpb3ZzX3B0ciwgaW92c19sZW4sIG9mZnNldCwgbnJlYWRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IGlvdmVjcyA9IElvdmVjLnJlYWRfYnl0ZXNfYXJyYXkoYnVmZmVyLCBpb3ZzX3B0ciwgaW92c19sZW4pOwogICAgICAgIGxldCBucmVhZCA9IDA7CiAgICAgICAgZm9yIChjb25zdCBpb3ZlYyBvZiBpb3ZlY3MpIHsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBkYXRhIH0gPSBzZWxmLmZkc1tmZF0uZmRfcHJlYWQoaW92ZWMuYnVmX2xlbiwgb2Zmc2V0KTsKICAgICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgbnJlYWQsIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgYnVmZmVyOC5zZXQoZGF0YSwgaW92ZWMuYnVmKTsKICAgICAgICAgIG5yZWFkICs9IGRhdGEubGVuZ3RoOwogICAgICAgICAgb2Zmc2V0ICs9IEJpZ0ludChkYXRhLmxlbmd0aCk7CiAgICAgICAgICBpZiAoZGF0YS5sZW5ndGggIT0gaW92ZWMuYnVmX2xlbikgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgYnVmZmVyLnNldFVpbnQzMihucmVhZF9wdHIsIG5yZWFkLCB0cnVlKTsKICAgICAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcHJlc3RhdF9nZXQoZmQsIGJ1Zl9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHsgcmV0LCBwcmVzdGF0IH0gPSBzZWxmLmZkc1tmZF0uZmRfcHJlc3RhdF9nZXQoKTsKICAgICAgICBpZiAocHJlc3RhdCAhPSBudWxsKSB7CiAgICAgICAgICBwcmVzdGF0LndyaXRlX2J5dGVzKGJ1ZmZlciwgYnVmX3B0cik7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3ByZXN0YXRfZGlyX25hbWUoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbikgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHsgcmV0LCBwcmVzdGF0IH0gPSBzZWxmLmZkc1tmZF0uZmRfcHJlc3RhdF9nZXQoKTsKICAgICAgICBpZiAocHJlc3RhdCA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgIH0KICAgICAgICBjb25zdCBwcmVzdGF0X2Rpcl9uYW1lID0gcHJlc3RhdC5pbm5lci5wcl9uYW1lOwogICAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgICBidWZmZXI4LnNldChwcmVzdGF0X2Rpcl9uYW1lLnNsaWNlKDAsIHBhdGhfbGVuKSwgcGF0aF9wdHIpOwogICAgICAgIHJldHVybiBwcmVzdGF0X2Rpcl9uYW1lLmJ5dGVMZW5ndGggPiBwYXRoX2xlbiA/IEVSUk5PX05BTUVUT09MT05HIDogRVJSTk9fU1VDQ0VTUzsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcHdyaXRlKGZkLCBpb3ZzX3B0ciwgaW92c19sZW4sIG9mZnNldCwgbndyaXR0ZW5fcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IGlvdmVjcyA9IENpb3ZlYy5yZWFkX2J5dGVzX2FycmF5KGJ1ZmZlciwgaW92c19wdHIsIGlvdnNfbGVuKTsKICAgICAgICBsZXQgbndyaXR0ZW4gPSAwOwogICAgICAgIGZvciAoY29uc3QgaW92ZWMgb2YgaW92ZWNzKSB7CiAgICAgICAgICBjb25zdCBkYXRhID0gYnVmZmVyOC5zbGljZShpb3ZlYy5idWYsIGlvdmVjLmJ1ZiArIGlvdmVjLmJ1Zl9sZW4pOwogICAgICAgICAgY29uc3QgeyByZXQsIG53cml0dGVuOiBud3JpdHRlbl9wYXJ0IH0gPSBzZWxmLmZkc1tmZF0uZmRfcHdyaXRlKGRhdGEsIG9mZnNldCk7CiAgICAgICAgICBpZiAocmV0ICE9IEVSUk5PX1NVQ0NFU1MpIHsKICAgICAgICAgICAgYnVmZmVyLnNldFVpbnQzMihud3JpdHRlbl9wdHIsIG53cml0dGVuLCB0cnVlKTsKICAgICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICAgIH0KICAgICAgICAgIG53cml0dGVuICs9IG53cml0dGVuX3BhcnQ7CiAgICAgICAgICBvZmZzZXQgKz0gQmlnSW50KG53cml0dGVuX3BhcnQpOwogICAgICAgICAgaWYgKG53cml0dGVuX3BhcnQgIT0gZGF0YS5ieXRlTGVuZ3RoKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKG53cml0dGVuX3B0ciwgbndyaXR0ZW4sIHRydWUpOwogICAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9yZWFkKGZkLCBpb3ZzX3B0ciwgaW92c19sZW4sIG5yZWFkX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBpb3ZlY3MgPSBJb3ZlYy5yZWFkX2J5dGVzX2FycmF5KGJ1ZmZlciwgaW92c19wdHIsIGlvdnNfbGVuKTsKICAgICAgICBsZXQgbnJlYWQgPSAwOwogICAgICAgIGZvciAoY29uc3QgaW92ZWMgb2YgaW92ZWNzKSB7CiAgICAgICAgICBjb25zdCB7IHJldCwgZGF0YSB9ID0gc2VsZi5mZHNbZmRdLmZkX3JlYWQoaW92ZWMuYnVmX2xlbik7CiAgICAgICAgICBpZiAocmV0ICE9IEVSUk5PX1NVQ0NFU1MpIHsKICAgICAgICAgICAgYnVmZmVyLnNldFVpbnQzMihucmVhZF9wdHIsIG5yZWFkLCB0cnVlKTsKICAgICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICAgIH0KICAgICAgICAgIGJ1ZmZlcjguc2V0KGRhdGEsIGlvdmVjLmJ1Zik7CiAgICAgICAgICBucmVhZCArPSBkYXRhLmxlbmd0aDsKICAgICAgICAgIGlmIChkYXRhLmxlbmd0aCAhPSBpb3ZlYy5idWZfbGVuKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgbnJlYWQsIHRydWUpOwogICAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9yZWFkZGlyKGZkLCBidWYsIGJ1Zl9sZW4sIGNvb2tpZSwgYnVmdXNlZF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgbGV0IGJ1ZnVzZWQgPSAwOwogICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICBjb25zdCB7IHJldCwgZGlyZW50IH0gPSBzZWxmLmZkc1tmZF0uZmRfcmVhZGRpcl9zaW5nbGUoY29va2llKTsKICAgICAgICAgIGlmIChyZXQgIT0gMCkgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKGJ1ZnVzZWRfcHRyLCBidWZ1c2VkLCB0cnVlKTsKICAgICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChkaXJlbnQgPT0gbnVsbCkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChidWZfbGVuIC0gYnVmdXNlZCA8IGRpcmVudC5oZWFkX2xlbmd0aCgpKSB7CiAgICAgICAgICAgIGJ1ZnVzZWQgPSBidWZfbGVuOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGhlYWRfYnl0ZXMgPSBuZXcgQXJyYXlCdWZmZXIoZGlyZW50LmhlYWRfbGVuZ3RoKCkpOwogICAgICAgICAgZGlyZW50LndyaXRlX2hlYWRfYnl0ZXMobmV3IERhdGFWaWV3KGhlYWRfYnl0ZXMpLCAwKTsKICAgICAgICAgIGJ1ZmZlcjguc2V0KG5ldyBVaW50OEFycmF5KGhlYWRfYnl0ZXMpLnNsaWNlKDAsIE1hdGgubWluKGhlYWRfYnl0ZXMuYnl0ZUxlbmd0aCwgYnVmX2xlbiAtIGJ1ZnVzZWQpKSwgYnVmKTsKICAgICAgICAgIGJ1ZiArPSBkaXJlbnQuaGVhZF9sZW5ndGgoKTsKICAgICAgICAgIGJ1ZnVzZWQgKz0gZGlyZW50LmhlYWRfbGVuZ3RoKCk7CiAgICAgICAgICBpZiAoYnVmX2xlbiAtIGJ1ZnVzZWQgPCBkaXJlbnQubmFtZV9sZW5ndGgoKSkgewogICAgICAgICAgICBidWZ1c2VkID0gYnVmX2xlbjsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBkaXJlbnQud3JpdGVfbmFtZV9ieXRlcyhidWZmZXI4LCBidWYsIGJ1Zl9sZW4gLSBidWZ1c2VkKTsKICAgICAgICAgIGJ1ZiArPSBkaXJlbnQubmFtZV9sZW5ndGgoKTsKICAgICAgICAgIGJ1ZnVzZWQgKz0gZGlyZW50Lm5hbWVfbGVuZ3RoKCk7CiAgICAgICAgICBjb29raWUgPSBkaXJlbnQuZF9uZXh0OwogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKGJ1ZnVzZWRfcHRyLCBidWZ1c2VkLCB0cnVlKTsKICAgICAgICByZXR1cm4gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcmVudW1iZXIoZmQsIHRvKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwICYmIHNlbGYuZmRzW3RvXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCByZXQgPSBzZWxmLmZkc1t0b10uZmRfY2xvc2UoKTsKICAgICAgICBpZiAocmV0ICE9IDApIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIHNlbGYuZmRzW3RvXSA9IHNlbGYuZmRzW2ZkXTsKICAgICAgICBzZWxmLmZkc1tmZF0gPSB2b2lkIDA7CiAgICAgICAgcmV0dXJuIDA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3NlZWsoZmQsIG9mZnNldCwgd2hlbmNlLCBvZmZzZXRfb3V0X3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIG9mZnNldDogb2Zmc2V0X291dCB9ID0gc2VsZi5mZHNbZmRdLmZkX3NlZWsob2Zmc2V0LCB3aGVuY2UpOwogICAgICAgIGJ1ZmZlci5zZXRCaWdJbnQ2NChvZmZzZXRfb3V0X3B0ciwgb2Zmc2V0X291dCwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfc3luYyhmZCkgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfc3luYygpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF90ZWxsKGZkLCBvZmZzZXRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgb2Zmc2V0IH0gPSBzZWxmLmZkc1tmZF0uZmRfdGVsbCgpOwogICAgICAgIGJ1ZmZlci5zZXRCaWdVaW50NjQob2Zmc2V0X3B0ciwgb2Zmc2V0LCB0cnVlKTsKICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF93cml0ZShmZCwgaW92c19wdHIsIGlvdnNfbGVuLCBud3JpdHRlbl9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgaW92ZWNzID0gQ2lvdmVjLnJlYWRfYnl0ZXNfYXJyYXkoYnVmZmVyLCBpb3ZzX3B0ciwgaW92c19sZW4pOwogICAgICAgIGxldCBud3JpdHRlbiA9IDA7CiAgICAgICAgZm9yIChjb25zdCBpb3ZlYyBvZiBpb3ZlY3MpIHsKICAgICAgICAgIGNvbnN0IGRhdGEgPSBidWZmZXI4LnNsaWNlKGlvdmVjLmJ1ZiwgaW92ZWMuYnVmICsgaW92ZWMuYnVmX2xlbik7CiAgICAgICAgICBjb25zdCB7IHJldCwgbndyaXR0ZW46IG53cml0dGVuX3BhcnQgfSA9IHNlbGYuZmRzW2ZkXS5mZF93cml0ZShkYXRhKTsKICAgICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG53cml0dGVuX3B0ciwgbndyaXR0ZW4sIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgbndyaXR0ZW4gKz0gbndyaXR0ZW5fcGFydDsKICAgICAgICAgIGlmIChud3JpdHRlbl9wYXJ0ICE9IGRhdGEuYnl0ZUxlbmd0aCkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgYnVmZmVyLnNldFVpbnQzMihud3JpdHRlbl9wdHIsIG53cml0dGVuLCB0cnVlKTsKICAgICAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9jcmVhdGVfZGlyZWN0b3J5KGZkLCBwYXRoX3B0ciwgcGF0aF9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICByZXR1cm4gc2VsZi5mZHNbZmRdLnBhdGhfY3JlYXRlX2RpcmVjdG9yeShwYXRoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9maWxlc3RhdF9nZXQoZmQsIGZsYWdzLCBwYXRoX3B0ciwgcGF0aF9sZW4sIGZpbGVzdGF0X3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBwYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgY29uc3QgeyByZXQsIGZpbGVzdGF0IH0gPSBzZWxmLmZkc1tmZF0ucGF0aF9maWxlc3RhdF9nZXQoZmxhZ3MsIHBhdGgpOwogICAgICAgIGlmIChmaWxlc3RhdCAhPSBudWxsKSB7CiAgICAgICAgICBmaWxlc3RhdC53cml0ZV9ieXRlcyhidWZmZXIsIGZpbGVzdGF0X3B0cik7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfZmlsZXN0YXRfc2V0X3RpbWVzKGZkLCBmbGFncywgcGF0aF9wdHIsIHBhdGhfbGVuLCBhdGltLCBtdGltLCBmc3RfZmxhZ3MpIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICByZXR1cm4gc2VsZi5mZHNbZmRdLnBhdGhfZmlsZXN0YXRfc2V0X3RpbWVzKGZsYWdzLCBwYXRoLCBhdGltLCBtdGltLCBmc3RfZmxhZ3MpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX2xpbmsob2xkX2ZkLCBvbGRfZmxhZ3MsIG9sZF9wYXRoX3B0ciwgb2xkX3BhdGhfbGVuLCBuZXdfZmQsIG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW29sZF9mZF0gIT0gdm9pZCAwICYmIHNlbGYuZmRzW25ld19mZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3Qgb2xkX3BhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2Uob2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9wdHIgKyBvbGRfcGF0aF9sZW4pKTsKICAgICAgICBjb25zdCBuZXdfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShuZXdfcGF0aF9wdHIsIG5ld19wYXRoX3B0ciArIG5ld19wYXRoX2xlbikpOwogICAgICAgIGNvbnN0IHsgcmV0LCBpbm9kZV9vYmogfSA9IHNlbGYuZmRzW29sZF9mZF0ucGF0aF9sb29rdXAob2xkX3BhdGgsIG9sZF9mbGFncyk7CiAgICAgICAgaWYgKGlub2RlX29iaiA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgIH0KICAgICAgICByZXR1cm4gc2VsZi5mZHNbbmV3X2ZkXS5wYXRoX2xpbmsobmV3X3BhdGgsIGlub2RlX29iaiwgZmFsc2UpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX29wZW4oZmQsIGRpcmZsYWdzLCBwYXRoX3B0ciwgcGF0aF9sZW4sIG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nLCBmZF9mbGFncywgb3BlbmVkX2ZkX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBwYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgZGVidWcubG9nKHBhdGgpOwogICAgICAgIGNvbnN0IHsgcmV0LCBmZF9vYmogfSA9IHNlbGYuZmRzW2ZkXS5wYXRoX29wZW4oZGlyZmxhZ3MsIHBhdGgsIG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nLCBmZF9mbGFncyk7CiAgICAgICAgaWYgKHJldCAhPSAwKSB7CiAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgIH0KICAgICAgICBzZWxmLmZkcy5wdXNoKGZkX29iaik7CiAgICAgICAgY29uc3Qgb3BlbmVkX2ZkID0gc2VsZi5mZHMubGVuZ3RoIC0gMTsKICAgICAgICBidWZmZXIuc2V0VWludDMyKG9wZW5lZF9mZF9wdHIsIG9wZW5lZF9mZCwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIDA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfcmVhZGxpbmsoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbiwgYnVmX3B0ciwgYnVmX2xlbiwgbnJlYWRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICBkZWJ1Zy5sb2cocGF0aCk7CiAgICAgICAgY29uc3QgeyByZXQsIGRhdGEgfSA9IHNlbGYuZmRzW2ZkXS5wYXRoX3JlYWRsaW5rKHBhdGgpOwogICAgICAgIGlmIChkYXRhICE9IG51bGwpIHsKICAgICAgICAgIGNvbnN0IGRhdGFfYnVmID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKGRhdGEpOwogICAgICAgICAgaWYgKGRhdGFfYnVmLmxlbmd0aCA+IGJ1Zl9sZW4pIHsKICAgICAgICAgICAgYnVmZmVyLnNldFVpbnQzMihucmVhZF9wdHIsIDAsIHRydWUpOwogICAgICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgICAgIH0KICAgICAgICAgIGJ1ZmZlcjguc2V0KGRhdGFfYnVmLCBidWZfcHRyKTsKICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobnJlYWRfcHRyLCBkYXRhX2J1Zi5sZW5ndGgsIHRydWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX3JlbW92ZV9kaXJlY3RvcnkoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0ucGF0aF9yZW1vdmVfZGlyZWN0b3J5KHBhdGgpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX3JlbmFtZShmZCwgb2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9sZW4sIG5ld19mZCwgbmV3X3BhdGhfcHRyLCBuZXdfcGF0aF9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCAmJiBzZWxmLmZkc1tuZXdfZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IG9sZF9wYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG9sZF9wYXRoX3B0ciwgb2xkX3BhdGhfcHRyICsgb2xkX3BhdGhfbGVuKSk7CiAgICAgICAgY29uc3QgbmV3X3BhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UobmV3X3BhdGhfcHRyLCBuZXdfcGF0aF9wdHIgKyBuZXdfcGF0aF9sZW4pKTsKICAgICAgICBsZXQgeyByZXQsIGlub2RlX29iaiB9ID0gc2VsZi5mZHNbZmRdLnBhdGhfdW5saW5rKG9sZF9wYXRoKTsKICAgICAgICBpZiAoaW5vZGVfb2JqID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIHJldCA9IHNlbGYuZmRzW25ld19mZF0ucGF0aF9saW5rKG5ld19wYXRoLCBpbm9kZV9vYmosIHRydWUpOwogICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgaWYgKHNlbGYuZmRzW2ZkXS5wYXRoX2xpbmsob2xkX3BhdGgsIGlub2RlX29iaiwgdHJ1ZSkgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICB0aHJvdyAicGF0aF9saW5rIHNob3VsZCBhbHdheXMgcmV0dXJuIHN1Y2Nlc3Mgd2hlbiByZWxpbmtpbmcgYW4gaW5vZGUgYmFjayB0byB0aGUgb3JpZ2luYWwgcGxhY2UiOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX3N5bWxpbmsob2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9sZW4sIGZkLCBuZXdfcGF0aF9wdHIsIG5ld19wYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3Qgb2xkX3BhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2Uob2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9wdHIgKyBvbGRfcGF0aF9sZW4pKTsKICAgICAgICBjb25zdCBuZXdfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShuZXdfcGF0aF9wdHIsIG5ld19wYXRoX3B0ciArIG5ld19wYXRoX2xlbikpOwogICAgICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfdW5saW5rX2ZpbGUoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0ucGF0aF91bmxpbmtfZmlsZShwYXRoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcG9sbF9vbmVvZmYoaW5fLCBvdXQsIG5zdWJzY3JpcHRpb25zKSB7CiAgICAgIHRocm93ICJhc3luYyBpbyBub3Qgc3VwcG9ydGVkIjsKICAgIH0sIHByb2NfZXhpdChleGl0X2NvZGUpIHsKICAgICAgdGhyb3cgbmV3IFdBU0lQcm9jRXhpdChleGl0X2NvZGUpOwogICAgfSwgcHJvY19yYWlzZShzaWcpIHsKICAgICAgdGhyb3cgInJhaXNlZCBzaWduYWwgIiArIHNpZzsKICAgIH0sIHNjaGVkX3lpZWxkKCkgewogICAgfSwgcmFuZG9tX2dldChidWYsIGJ1Zl9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJ1Zl9sZW47IGkrKykgewogICAgICAgIGJ1ZmZlcjhbYnVmICsgaV0gPSBNYXRoLnJhbmRvbSgpICogMjU2IHwgMDsKICAgICAgfQogICAgfSwgc29ja19yZWN2KGZkLCByaV9kYXRhLCByaV9mbGFncykgewogICAgICB0aHJvdyAic29ja2V0cyBub3Qgc3VwcG9ydGVkIjsKICAgIH0sIHNvY2tfc2VuZChmZCwgc2lfZGF0YSwgc2lfZmxhZ3MpIHsKICAgICAgdGhyb3cgInNvY2tldHMgbm90IHN1cHBvcnRlZCI7CiAgICB9LCBzb2NrX3NodXRkb3duKGZkLCBob3cpIHsKICAgICAgdGhyb3cgInNvY2tldHMgbm90IHN1cHBvcnRlZCI7CiAgICB9LCBzb2NrX2FjY2VwdChmZCwgZmxhZ3MpIHsKICAgICAgdGhyb3cgInNvY2tldHMgbm90IHN1cHBvcnRlZCI7CiAgICB9IH07CiAgfQp9OwoKLy8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC9mZC5qcwp2YXIgRmQgPSBjbGFzcyB7CiAgZmRfYWxsb2NhdGUob2Zmc2V0LCBsZW4pIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIGZkX2Nsb3NlKCkgewogICAgcmV0dXJuIDA7CiAgfQogIGZkX2Zkc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZmRzdGF0OiBudWxsIH07CiAgfQogIGZkX2Zkc3RhdF9zZXRfZmxhZ3MoZmxhZ3MpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIGZkX2Zkc3RhdF9zZXRfcmlnaHRzKGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZykgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfZmlsZXN0YXRfZ2V0KCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGZpbGVzdGF0OiBudWxsIH07CiAgfQogIGZkX2ZpbGVzdGF0X3NldF9zaXplKHNpemUpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIGZkX2ZpbGVzdGF0X3NldF90aW1lcyhhdGltLCBtdGltLCBmc3RfZmxhZ3MpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIGZkX3ByZWFkKHNpemUsIG9mZnNldCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGRhdGE6IG5ldyBVaW50OEFycmF5KCkgfTsKICB9CiAgZmRfcHJlc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgcHJlc3RhdDogbnVsbCB9OwogIH0KICBmZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgbndyaXR0ZW46IDAgfTsKICB9CiAgZmRfcmVhZChzaXplKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZGF0YTogbmV3IFVpbnQ4QXJyYXkoKSB9OwogIH0KICBmZF9yZWFkZGlyX3NpbmdsZShjb29raWUpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBkaXJlbnQ6IG51bGwgfTsKICB9CiAgZmRfc2VlayhvZmZzZXQsIHdoZW5jZSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIG9mZnNldDogMG4gfTsKICB9CiAgZmRfc3luYygpIHsKICAgIHJldHVybiAwOwogIH0KICBmZF90ZWxsKCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIG9mZnNldDogMG4gfTsKICB9CiAgZmRfd3JpdGUoZGF0YSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIG53cml0dGVuOiAwIH07CiAgfQogIHBhdGhfY3JlYXRlX2RpcmVjdG9yeShwYXRoKSB7CiAgICByZXR1cm4gRVJSTk9fTk9UU1VQOwogIH0KICBwYXRoX2ZpbGVzdGF0X2dldChmbGFncywgcGF0aCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGZpbGVzdGF0OiBudWxsIH07CiAgfQogIHBhdGhfZmlsZXN0YXRfc2V0X3RpbWVzKGZsYWdzLCBwYXRoLCBhdGltLCBtdGltLCBmc3RfZmxhZ3MpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfbGluayhwYXRoLCBpbm9kZSwgYWxsb3dfZGlyKSB7CiAgICByZXR1cm4gRVJSTk9fTk9UU1VQOwogIH0KICBwYXRoX3VubGluayhwYXRoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgaW5vZGVfb2JqOiBudWxsIH07CiAgfQogIHBhdGhfbG9va3VwKHBhdGgsIGRpcmZsYWdzKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgaW5vZGVfb2JqOiBudWxsIH07CiAgfQogIHBhdGhfb3BlbihkaXJmbGFncywgcGF0aCwgb2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcsIGZkX2ZsYWdzKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgZmRfb2JqOiBudWxsIH07CiAgfQogIHBhdGhfcmVhZGxpbmsocGF0aCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGRhdGE6IG51bGwgfTsKICB9CiAgcGF0aF9yZW1vdmVfZGlyZWN0b3J5KHBhdGgpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfcmVuYW1lKG9sZF9wYXRoLCBuZXdfZmQsIG5ld19wYXRoKSB7CiAgICByZXR1cm4gRVJSTk9fTk9UU1VQOwogIH0KICBwYXRoX3VubGlua19maWxlKHBhdGgpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQp9Owp2YXIgSW5vZGUgPSBjbGFzcyB7Cn07CgovLyBub2RlX21vZHVsZXMvQGJqb3JuMy9icm93c2VyX3dhc2lfc2hpbS9kaXN0L2ZzX21lbS5qcwp2YXIgT3BlbkZpbGUgPSBjbGFzcyBleHRlbmRzIEZkIHsKICBmZF9hbGxvY2F0ZShvZmZzZXQsIGxlbikgewogICAgaWYgKHRoaXMuZmlsZS5zaXplID4gb2Zmc2V0ICsgbGVuKSB7CiAgICB9IGVsc2UgewogICAgICBjb25zdCBuZXdfZGF0YSA9IG5ldyBVaW50OEFycmF5KE51bWJlcihvZmZzZXQgKyBsZW4pKTsKICAgICAgbmV3X2RhdGEuc2V0KHRoaXMuZmlsZS5kYXRhLCAwKTsKICAgICAgdGhpcy5maWxlLmRhdGEgPSBuZXdfZGF0YTsKICAgIH0KICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogIH0KICBmZF9mZHN0YXRfZ2V0KCkgewogICAgcmV0dXJuIHsgcmV0OiAwLCBmZHN0YXQ6IG5ldyBGZHN0YXQoRklMRVRZUEVfUkVHVUxBUl9GSUxFLCAwKSB9OwogIH0KICBmZF9maWxlc3RhdF9zZXRfc2l6ZShzaXplKSB7CiAgICBpZiAodGhpcy5maWxlLnNpemUgPiBzaXplKSB7CiAgICAgIHRoaXMuZmlsZS5kYXRhID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5maWxlLmRhdGEuYnVmZmVyLnNsaWNlKDAsIE51bWJlcihzaXplKSkpOwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgbmV3X2RhdGEgPSBuZXcgVWludDhBcnJheShOdW1iZXIoc2l6ZSkpOwogICAgICBuZXdfZGF0YS5zZXQodGhpcy5maWxlLmRhdGEsIDApOwogICAgICB0aGlzLmZpbGUuZGF0YSA9IG5ld19kYXRhOwogICAgfQogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIGZkX3JlYWQoc2l6ZSkgewogICAgY29uc3Qgc2xpY2UgPSB0aGlzLmZpbGUuZGF0YS5zbGljZShOdW1iZXIodGhpcy5maWxlX3BvcyksIE51bWJlcih0aGlzLmZpbGVfcG9zICsgQmlnSW50KHNpemUpKSk7CiAgICB0aGlzLmZpbGVfcG9zICs9IEJpZ0ludChzbGljZS5sZW5ndGgpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBkYXRhOiBzbGljZSB9OwogIH0KICBmZF9wcmVhZChzaXplLCBvZmZzZXQpIHsKICAgIGNvbnN0IHNsaWNlID0gdGhpcy5maWxlLmRhdGEuc2xpY2UoTnVtYmVyKG9mZnNldCksIE51bWJlcihvZmZzZXQgKyBCaWdJbnQoc2l6ZSkpKTsKICAgIHJldHVybiB7IHJldDogMCwgZGF0YTogc2xpY2UgfTsKICB9CiAgZmRfc2VlayhvZmZzZXQsIHdoZW5jZSkgewogICAgbGV0IGNhbGN1bGF0ZWRfb2Zmc2V0OwogICAgc3dpdGNoICh3aGVuY2UpIHsKICAgICAgY2FzZSBXSEVOQ0VfU0VUOgogICAgICAgIGNhbGN1bGF0ZWRfb2Zmc2V0ID0gb2Zmc2V0OwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFdIRU5DRV9DVVI6CiAgICAgICAgY2FsY3VsYXRlZF9vZmZzZXQgPSB0aGlzLmZpbGVfcG9zICsgb2Zmc2V0OwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFdIRU5DRV9FTkQ6CiAgICAgICAgY2FsY3VsYXRlZF9vZmZzZXQgPSBCaWdJbnQodGhpcy5maWxlLmRhdGEuYnl0ZUxlbmd0aCkgKyBvZmZzZXQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19JTlZBTCwgb2Zmc2V0OiAwbiB9OwogICAgfQogICAgaWYgKGNhbGN1bGF0ZWRfb2Zmc2V0IDwgMCkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0lOVkFMLCBvZmZzZXQ6IDBuIH07CiAgICB9CiAgICB0aGlzLmZpbGVfcG9zID0gY2FsY3VsYXRlZF9vZmZzZXQ7CiAgICByZXR1cm4geyByZXQ6IDAsIG9mZnNldDogdGhpcy5maWxlX3BvcyB9OwogIH0KICBmZF90ZWxsKCkgewogICAgcmV0dXJuIHsgcmV0OiAwLCBvZmZzZXQ6IHRoaXMuZmlsZV9wb3MgfTsKICB9CiAgZmRfd3JpdGUoZGF0YSkgewogICAgaWYgKHRoaXMuZmlsZS5yZWFkb25seSkKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBud3JpdHRlbjogMCB9OwogICAgaWYgKHRoaXMuZmlsZV9wb3MgKyBCaWdJbnQoZGF0YS5ieXRlTGVuZ3RoKSA+IHRoaXMuZmlsZS5zaXplKSB7CiAgICAgIGNvbnN0IG9sZCA9IHRoaXMuZmlsZS5kYXRhOwogICAgICB0aGlzLmZpbGUuZGF0YSA9IG5ldyBVaW50OEFycmF5KE51bWJlcih0aGlzLmZpbGVfcG9zICsgQmlnSW50KGRhdGEuYnl0ZUxlbmd0aCkpKTsKICAgICAgdGhpcy5maWxlLmRhdGEuc2V0KG9sZCk7CiAgICB9CiAgICB0aGlzLmZpbGUuZGF0YS5zZXQoZGF0YSwgTnVtYmVyKHRoaXMuZmlsZV9wb3MpKTsKICAgIHRoaXMuZmlsZV9wb3MgKz0gQmlnSW50KGRhdGEuYnl0ZUxlbmd0aCk7CiAgICByZXR1cm4geyByZXQ6IDAsIG53cml0dGVuOiBkYXRhLmJ5dGVMZW5ndGggfTsKICB9CiAgZmRfcHdyaXRlKGRhdGEsIG9mZnNldCkgewogICAgaWYgKHRoaXMuZmlsZS5yZWFkb25seSkKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBud3JpdHRlbjogMCB9OwogICAgaWYgKG9mZnNldCArIEJpZ0ludChkYXRhLmJ5dGVMZW5ndGgpID4gdGhpcy5maWxlLnNpemUpIHsKICAgICAgY29uc3Qgb2xkID0gdGhpcy5maWxlLmRhdGE7CiAgICAgIHRoaXMuZmlsZS5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoTnVtYmVyKG9mZnNldCArIEJpZ0ludChkYXRhLmJ5dGVMZW5ndGgpKSk7CiAgICAgIHRoaXMuZmlsZS5kYXRhLnNldChvbGQpOwogICAgfQogICAgdGhpcy5maWxlLmRhdGEuc2V0KGRhdGEsIE51bWJlcihvZmZzZXQpKTsKICAgIHJldHVybiB7IHJldDogMCwgbndyaXR0ZW46IGRhdGEuYnl0ZUxlbmd0aCB9OwogIH0KICBmZF9maWxlc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIGZpbGVzdGF0OiB0aGlzLmZpbGUuc3RhdCgpIH07CiAgfQogIGNvbnN0cnVjdG9yKGZpbGUpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLmZpbGVfcG9zID0gMG47CiAgICB0aGlzLmZpbGUgPSBmaWxlOwogIH0KfTsKdmFyIE9wZW5EaXJlY3RvcnkgPSBjbGFzcyBleHRlbmRzIEZkIHsKICBmZF9zZWVrKG9mZnNldCwgd2hlbmNlKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG9mZnNldDogMG4gfTsKICB9CiAgZmRfdGVsbCgpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fQkFERiwgb2Zmc2V0OiAwbiB9OwogIH0KICBmZF9hbGxvY2F0ZShvZmZzZXQsIGxlbikgewogICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgfQogIGZkX2Zkc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIGZkc3RhdDogbmV3IEZkc3RhdChGSUxFVFlQRV9ESVJFQ1RPUlksIDApIH07CiAgfQogIGZkX3JlYWRkaXJfc2luZ2xlKGNvb2tpZSkgewogICAgaWYgKGRlYnVnLmVuYWJsZWQpIHsKICAgICAgZGVidWcubG9nKCJyZWFkZGlyX3NpbmdsZSIsIGNvb2tpZSk7CiAgICAgIGRlYnVnLmxvZyhjb29raWUsIHRoaXMuZGlyLmNvbnRlbnRzLmtleXMoKSk7CiAgICB9CiAgICBpZiAoY29va2llID09IDBuKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZGlyZW50OiBuZXcgRGlyZW50KDFuLCAiLiIsIEZJTEVUWVBFX0RJUkVDVE9SWSkgfTsKICAgIH0gZWxzZSBpZiAoY29va2llID09IDFuKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZGlyZW50OiBuZXcgRGlyZW50KDJuLCAiLi4iLCBGSUxFVFlQRV9ESVJFQ1RPUlkpIH07CiAgICB9CiAgICBpZiAoY29va2llID49IEJpZ0ludCh0aGlzLmRpci5jb250ZW50cy5zaXplKSArIDJuKSB7CiAgICAgIHJldHVybiB7IHJldDogMCwgZGlyZW50OiBudWxsIH07CiAgICB9CiAgICBjb25zdCBbbmFtZSwgZW50cnldID0gQXJyYXkuZnJvbSh0aGlzLmRpci5jb250ZW50cy5lbnRyaWVzKCkpW051bWJlcihjb29raWUgLSAybildOwogICAgcmV0dXJuIHsgcmV0OiAwLCBkaXJlbnQ6IG5ldyBEaXJlbnQoY29va2llICsgMW4sIG5hbWUsIGVudHJ5LnN0YXQoKS5maWxldHlwZSkgfTsKICB9CiAgcGF0aF9maWxlc3RhdF9nZXQoZmxhZ3MsIHBhdGhfc3RyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9lcnIsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogcGF0aF9lcnIsIGZpbGVzdGF0OiBudWxsIH07CiAgICB9CiAgICBjb25zdCB7IHJldCwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9lbnRyeV9mb3JfcGF0aChwYXRoKTsKICAgIGlmIChlbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldCwgZmlsZXN0YXQ6IG51bGwgfTsKICAgIH0KICAgIHJldHVybiB7IHJldDogMCwgZmlsZXN0YXQ6IGVudHJ5LnN0YXQoKSB9OwogIH0KICBwYXRoX2xvb2t1cChwYXRoX3N0ciwgZGlyZmxhZ3MpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX3JldCwgcGF0aCB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXRoX3JldCwgaW5vZGVfb2JqOiBudWxsIH07CiAgICB9CiAgICBjb25zdCB7IHJldCwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9lbnRyeV9mb3JfcGF0aChwYXRoKTsKICAgIGlmIChlbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldCwgaW5vZGVfb2JqOiBudWxsIH07CiAgICB9CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGlub2RlX29iajogZW50cnkgfTsKICB9CiAgcGF0aF9vcGVuKGRpcmZsYWdzLCBwYXRoX3N0ciwgb2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcsIGZkX2ZsYWdzKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogcGF0aF9yZXQsIGZkX29iajogbnVsbCB9OwogICAgfQogICAgbGV0IHsgcmV0LCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgpOwogICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgaWYgKHJldCAhPSBFUlJOT19OT0VOVCkgewogICAgICAgIHJldHVybiB7IHJldCwgZmRfb2JqOiBudWxsIH07CiAgICAgIH0KICAgICAgaWYgKChvZmxhZ3MgJiBPRkxBR1NfQ1JFQVQpID09IE9GTEFHU19DUkVBVCkgewogICAgICAgIGNvbnN0IHsgcmV0OiByZXQyLCBlbnRyeTogbmV3X2VudHJ5IH0gPSB0aGlzLmRpci5jcmVhdGVfZW50cnlfZm9yX3BhdGgocGF0aF9zdHIsIChvZmxhZ3MgJiBPRkxBR1NfRElSRUNUT1JZKSA9PSBPRkxBR1NfRElSRUNUT1JZKTsKICAgICAgICBpZiAobmV3X2VudHJ5ID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiB7IHJldDogcmV0MiwgZmRfb2JqOiBudWxsIH07CiAgICAgICAgfQogICAgICAgIGVudHJ5ID0gbmV3X2VudHJ5OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9FTlQsIGZkX29iajogbnVsbCB9OwogICAgICB9CiAgICB9IGVsc2UgaWYgKChvZmxhZ3MgJiBPRkxBR1NfRVhDTCkgPT0gT0ZMQUdTX0VYQ0wpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19FWElTVCwgZmRfb2JqOiBudWxsIH07CiAgICB9CiAgICBpZiAoKG9mbGFncyAmIE9GTEFHU19ESVJFQ1RPUlkpID09IE9GTEFHU19ESVJFQ1RPUlkgJiYgZW50cnkuc3RhdCgpLmZpbGV0eXBlICE9PSBGSUxFVFlQRV9ESVJFQ1RPUlkpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIGZkX29iajogbnVsbCB9OwogICAgfQogICAgcmV0dXJuIGVudHJ5LnBhdGhfb3BlbihvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmZF9mbGFncyk7CiAgfQogIHBhdGhfY3JlYXRlX2RpcmVjdG9yeShwYXRoKSB7CiAgICByZXR1cm4gdGhpcy5wYXRoX29wZW4oMCwgcGF0aCwgT0ZMQUdTX0NSRUFUIHwgT0ZMQUdTX0RJUkVDVE9SWSwgMG4sIDBuLCAwKS5yZXQ7CiAgfQogIHBhdGhfbGluayhwYXRoX3N0ciwgaW5vZGUsIGFsbG93X2RpcikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4gcGF0aF9yZXQ7CiAgICB9CiAgICBpZiAocGF0aC5pc19kaXIpIHsKICAgICAgcmV0dXJuIEVSUk5PX05PRU5UOwogICAgfQogICAgY29uc3QgeyByZXQ6IHBhcmVudF9yZXQsIHBhcmVudF9lbnRyeSwgZmlsZW5hbWUsIGVudHJ5IH0gPSB0aGlzLmRpci5nZXRfcGFyZW50X2Rpcl9hbmRfZW50cnlfZm9yX3BhdGgocGF0aCwgdHJ1ZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCkgewogICAgICByZXR1cm4gcGFyZW50X3JldDsKICAgIH0KICAgIGlmIChlbnRyeSAhPSBudWxsKSB7CiAgICAgIGNvbnN0IHNvdXJjZV9pc19kaXIgPSBpbm9kZS5zdGF0KCkuZmlsZXR5cGUgPT0gRklMRVRZUEVfRElSRUNUT1JZOwogICAgICBjb25zdCB0YXJnZXRfaXNfZGlyID0gZW50cnkuc3RhdCgpLmZpbGV0eXBlID09IEZJTEVUWVBFX0RJUkVDVE9SWTsKICAgICAgaWYgKHNvdXJjZV9pc19kaXIgJiYgdGFyZ2V0X2lzX2RpcikgewogICAgICAgIGlmIChhbGxvd19kaXIgJiYgZW50cnkgaW5zdGFuY2VvZiBEaXJlY3RvcnkpIHsKICAgICAgICAgIGlmIChlbnRyeS5jb250ZW50cy5zaXplID09IDApIHsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBFUlJOT19OT1RFTVBUWTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIEVSUk5PX0VYSVNUOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChzb3VyY2VfaXNfZGlyICYmICF0YXJnZXRfaXNfZGlyKSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX05PVERJUjsKICAgICAgfSBlbHNlIGlmICghc291cmNlX2lzX2RpciAmJiB0YXJnZXRfaXNfZGlyKSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0lTRElSOwogICAgICB9IGVsc2UgaWYgKGlub2RlLnN0YXQoKS5maWxldHlwZSA9PSBGSUxFVFlQRV9SRUdVTEFSX0ZJTEUgJiYgZW50cnkuc3RhdCgpLmZpbGV0eXBlID09IEZJTEVUWVBFX1JFR1VMQVJfRklMRSkgewogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19FWElTVDsKICAgICAgfQogICAgfQogICAgaWYgKCFhbGxvd19kaXIgJiYgaW5vZGUuc3RhdCgpLmZpbGV0eXBlID09IEZJTEVUWVBFX0RJUkVDVE9SWSkgewogICAgICByZXR1cm4gRVJSTk9fUEVSTTsKICAgIH0KICAgIHBhcmVudF9lbnRyeS5jb250ZW50cy5zZXQoZmlsZW5hbWUsIGlub2RlKTsKICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogIH0KICBwYXRoX3VubGluayhwYXRoX3N0cikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhdGhfcmV0LCBpbm9kZV9vYmo6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBwYXJlbnRfcmV0LCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIHRydWUpOwogICAgaWYgKHBhcmVudF9lbnRyeSA9PSBudWxsIHx8IGZpbGVuYW1lID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXJlbnRfcmV0LCBpbm9kZV9vYmo6IG51bGwgfTsKICAgIH0KICAgIGlmIChlbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9FTlQsIGlub2RlX29iajogbnVsbCB9OwogICAgfQogICAgcGFyZW50X2VudHJ5LmNvbnRlbnRzLmRlbGV0ZShmaWxlbmFtZSk7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGlub2RlX29iajogZW50cnkgfTsKICB9CiAgcGF0aF91bmxpbmtfZmlsZShwYXRoX3N0cikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4gcGF0aF9yZXQ7CiAgICB9CiAgICBjb25zdCB7IHJldDogcGFyZW50X3JldCwgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9wYXJlbnRfZGlyX2FuZF9lbnRyeV9mb3JfcGF0aChwYXRoLCBmYWxzZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCB8fCBlbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXJlbnRfcmV0OwogICAgfQogICAgaWYgKGVudHJ5LnN0YXQoKS5maWxldHlwZSA9PT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgIHJldHVybiBFUlJOT19JU0RJUjsKICAgIH0KICAgIHBhcmVudF9lbnRyeS5jb250ZW50cy5kZWxldGUoZmlsZW5hbWUpOwogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIHBhdGhfcmVtb3ZlX2RpcmVjdG9yeShwYXRoX3N0cikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4gcGF0aF9yZXQ7CiAgICB9CiAgICBjb25zdCB7IHJldDogcGFyZW50X3JldCwgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9wYXJlbnRfZGlyX2FuZF9lbnRyeV9mb3JfcGF0aChwYXRoLCBmYWxzZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCB8fCBlbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXJlbnRfcmV0OwogICAgfQogICAgaWYgKCEoZW50cnkgaW5zdGFuY2VvZiBEaXJlY3RvcnkpIHx8IGVudHJ5LnN0YXQoKS5maWxldHlwZSAhPT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgIHJldHVybiBFUlJOT19OT1RESVI7CiAgICB9CiAgICBpZiAoZW50cnkuY29udGVudHMuc2l6ZSAhPT0gMCkgewogICAgICByZXR1cm4gRVJSTk9fTk9URU1QVFk7CiAgICB9CiAgICBpZiAoIXBhcmVudF9lbnRyeS5jb250ZW50cy5kZWxldGUoZmlsZW5hbWUpKSB7CiAgICAgIHJldHVybiBFUlJOT19OT0VOVDsKICAgIH0KICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogIH0KICBmZF9maWxlc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIGZpbGVzdGF0OiB0aGlzLmRpci5zdGF0KCkgfTsKICB9CiAgZmRfZmlsZXN0YXRfc2V0X3NpemUoc2l6ZSkgewogICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgfQogIGZkX3JlYWQoc2l6ZSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBkYXRhOiBuZXcgVWludDhBcnJheSgpIH07CiAgfQogIGZkX3ByZWFkKHNpemUsIG9mZnNldCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBkYXRhOiBuZXcgVWludDhBcnJheSgpIH07CiAgfQogIGZkX3dyaXRlKGRhdGEpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fQkFERiwgbndyaXR0ZW46IDAgfTsKICB9CiAgZmRfcHdyaXRlKGRhdGEsIG9mZnNldCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBud3JpdHRlbjogMCB9OwogIH0KICBjb25zdHJ1Y3RvcihkaXIpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLmRpciA9IGRpcjsKICB9Cn07CnZhciBQcmVvcGVuRGlyZWN0b3J5ID0gY2xhc3MgZXh0ZW5kcyBPcGVuRGlyZWN0b3J5IHsKICBmZF9wcmVzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgcHJlc3RhdDogUHJlc3RhdC5kaXIodGhpcy5wcmVzdGF0X25hbWUpIH07CiAgfQogIGNvbnN0cnVjdG9yKG5hbWUsIGNvbnRlbnRzKSB7CiAgICBzdXBlcihuZXcgRGlyZWN0b3J5KGNvbnRlbnRzKSk7CiAgICB0aGlzLnByZXN0YXRfbmFtZSA9IG5hbWU7CiAgfQp9Owp2YXIgRmlsZSA9IGNsYXNzIGV4dGVuZHMgSW5vZGUgewogIHBhdGhfb3BlbihvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmZF9mbGFncykgewogICAgaWYgKHRoaXMucmVhZG9ubHkgJiYgKGZzX3JpZ2h0c19iYXNlICYgQmlnSW50KFJJR0hUU19GRF9XUklURSkpID09IEJpZ0ludChSSUdIVFNfRkRfV1JJVEUpKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fUEVSTSwgZmRfb2JqOiBudWxsIH07CiAgICB9CiAgICBpZiAoKG9mbGFncyAmIE9GTEFHU19UUlVOQykgPT0gT0ZMQUdTX1RSVU5DKSB7CiAgICAgIGlmICh0aGlzLnJlYWRvbmx5KQogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fUEVSTSwgZmRfb2JqOiBudWxsIH07CiAgICAgIHRoaXMuZGF0YSA9IG5ldyBVaW50OEFycmF5KFtdKTsKICAgIH0KICAgIGNvbnN0IGZpbGUgPSBuZXcgT3BlbkZpbGUodGhpcyk7CiAgICBpZiAoZmRfZmxhZ3MgJiBGREZMQUdTX0FQUEVORCkKICAgICAgZmlsZS5mZF9zZWVrKDBuLCBXSEVOQ0VfRU5EKTsKICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZmRfb2JqOiBmaWxlIH07CiAgfQogIGdldCBzaXplKCkgewogICAgcmV0dXJuIEJpZ0ludCh0aGlzLmRhdGEuYnl0ZUxlbmd0aCk7CiAgfQogIHN0YXQoKSB7CiAgICByZXR1cm4gbmV3IEZpbGVzdGF0KEZJTEVUWVBFX1JFR1VMQVJfRklMRSwgdGhpcy5zaXplKTsKICB9CiAgY29uc3RydWN0b3IoZGF0YSwgb3B0aW9ucykgewogICAgc3VwZXIoKTsKICAgIHRoaXMuZGF0YSA9IG5ldyBVaW50OEFycmF5KGRhdGEpOwogICAgdGhpcy5yZWFkb25seSA9ICEhb3B0aW9ucz8ucmVhZG9ubHk7CiAgfQp9Owp2YXIgUGF0aCA9IGNsYXNzIFBhdGgyIHsKICBzdGF0aWMgZnJvbShwYXRoKSB7CiAgICBjb25zdCBzZWxmID0gbmV3IFBhdGgyKCk7CiAgICBzZWxmLmlzX2RpciA9IHBhdGguZW5kc1dpdGgoIi8iKTsKICAgIGlmIChwYXRoLnN0YXJ0c1dpdGgoIi8iKSkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVENBUEFCTEUsIHBhdGg6IG51bGwgfTsKICAgIH0KICAgIGlmIChwYXRoLmluY2x1ZGVzKCJcMCIpKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fSU5WQUwsIHBhdGg6IG51bGwgfTsKICAgIH0KICAgIGZvciAoY29uc3QgY29tcG9uZW50IG9mIHBhdGguc3BsaXQoIi8iKSkgewogICAgICBpZiAoY29tcG9uZW50ID09PSAiIiB8fCBjb21wb25lbnQgPT09ICIuIikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChjb21wb25lbnQgPT09ICIuLiIpIHsKICAgICAgICBpZiAoc2VsZi5wYXJ0cy5wb3AoKSA9PSB2b2lkIDApIHsKICAgICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UQ0FQQUJMRSwgcGF0aDogbnVsbCB9OwogICAgICAgIH0KICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBzZWxmLnBhcnRzLnB1c2goY29tcG9uZW50KTsKICAgIH0KICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgcGF0aDogc2VsZiB9OwogIH0KICB0b19wYXRoX3N0cmluZygpIHsKICAgIGxldCBzID0gdGhpcy5wYXJ0cy5qb2luKCIvIik7CiAgICBpZiAodGhpcy5pc19kaXIpIHsKICAgICAgcyArPSAiLyI7CiAgICB9CiAgICByZXR1cm4gczsKICB9CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLnBhcnRzID0gW107CiAgICB0aGlzLmlzX2RpciA9IGZhbHNlOwogIH0KfTsKdmFyIERpcmVjdG9yeSA9IGNsYXNzIGV4dGVuZHMgSW5vZGUgewogIHBhdGhfb3BlbihvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmZF9mbGFncykgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBmZF9vYmo6IG5ldyBPcGVuRGlyZWN0b3J5KHRoaXMpIH07CiAgfQogIHN0YXQoKSB7CiAgICByZXR1cm4gbmV3IEZpbGVzdGF0KEZJTEVUWVBFX0RJUkVDVE9SWSwgMG4pOwogIH0KICBnZXRfZW50cnlfZm9yX3BhdGgocGF0aCkgewogICAgbGV0IGVudHJ5ID0gdGhpczsKICAgIGZvciAoY29uc3QgY29tcG9uZW50IG9mIHBhdGgucGFydHMpIHsKICAgICAgaWYgKCEoZW50cnkgaW5zdGFuY2VvZiBEaXJlY3RvcnkpKSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIGVudHJ5OiBudWxsIH07CiAgICAgIH0KICAgICAgY29uc3QgY2hpbGQgPSBlbnRyeS5jb250ZW50cy5nZXQoY29tcG9uZW50KTsKICAgICAgaWYgKGNoaWxkICE9PSB2b2lkIDApIHsKICAgICAgICBlbnRyeSA9IGNoaWxkOwogICAgICB9IGVsc2UgewogICAgICAgIGRlYnVnLmxvZyhjb21wb25lbnQpOwogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9FTlQsIGVudHJ5OiBudWxsIH07CiAgICAgIH0KICAgIH0KICAgIGlmIChwYXRoLmlzX2RpcikgewogICAgICBpZiAoZW50cnkuc3RhdCgpLmZpbGV0eXBlICE9IEZJTEVUWVBFX0RJUkVDVE9SWSkgewogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9URElSLCBlbnRyeTogbnVsbCB9OwogICAgICB9CiAgICB9CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGVudHJ5IH07CiAgfQogIGdldF9wYXJlbnRfZGlyX2FuZF9lbnRyeV9mb3JfcGF0aChwYXRoLCBhbGxvd191bmRlZmluZWQpIHsKICAgIGNvbnN0IGZpbGVuYW1lID0gcGF0aC5wYXJ0cy5wb3AoKTsKICAgIGlmIChmaWxlbmFtZSA9PT0gdm9pZCAwKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fSU5WQUwsIHBhcmVudF9lbnRyeTogbnVsbCwgZmlsZW5hbWU6IG51bGwsIGVudHJ5OiBudWxsIH07CiAgICB9CiAgICBjb25zdCB7IHJldDogZW50cnlfcmV0LCBlbnRyeTogcGFyZW50X2VudHJ5IH0gPSB0aGlzLmdldF9lbnRyeV9mb3JfcGF0aChwYXRoKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IGVudHJ5X3JldCwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGlmICghKHBhcmVudF9lbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIHBhcmVudF9lbnRyeTogbnVsbCwgZmlsZW5hbWU6IG51bGwsIGVudHJ5OiBudWxsIH07CiAgICB9CiAgICBjb25zdCBlbnRyeSA9IHBhcmVudF9lbnRyeS5jb250ZW50cy5nZXQoZmlsZW5hbWUpOwogICAgaWYgKGVudHJ5ID09PSB2b2lkIDApIHsKICAgICAgaWYgKCFhbGxvd191bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PRU5ULCBwYXJlbnRfZW50cnk6IG51bGwsIGZpbGVuYW1lOiBudWxsLCBlbnRyeTogbnVsbCB9OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgfQogICAgaWYgKHBhdGguaXNfZGlyKSB7CiAgICAgIGlmIChlbnRyeS5zdGF0KCkuZmlsZXR5cGUgIT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIHBhcmVudF9lbnRyeTogbnVsbCwgZmlsZW5hbWU6IG51bGwsIGVudHJ5OiBudWxsIH07CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfTsKICB9CiAgY3JlYXRlX2VudHJ5X2Zvcl9wYXRoKHBhdGhfc3RyLCBpc19kaXIpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX3JldCwgcGF0aCB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXRoX3JldCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGxldCB7IHJldDogcGFyZW50X3JldCwgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfSA9IHRoaXMuZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIHRydWUpOwogICAgaWYgKHBhcmVudF9lbnRyeSA9PSBudWxsIHx8IGZpbGVuYW1lID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXJlbnRfcmV0LCBlbnRyeTogbnVsbCB9OwogICAgfQogICAgaWYgKGVudHJ5ICE9IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19FWElTVCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGRlYnVnLmxvZygiY3JlYXRlIiwgcGF0aCk7CiAgICBsZXQgbmV3X2NoaWxkOwogICAgaWYgKCFpc19kaXIpIHsKICAgICAgbmV3X2NoaWxkID0gbmV3IEZpbGUobmV3IEFycmF5QnVmZmVyKDApKTsKICAgIH0gZWxzZSB7CiAgICAgIG5ld19jaGlsZCA9IG5ldyBEaXJlY3RvcnkoLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKSk7CiAgICB9CiAgICBwYXJlbnRfZW50cnkuY29udGVudHMuc2V0KGZpbGVuYW1lLCBuZXdfY2hpbGQpOwogICAgZW50cnkgPSBuZXdfY2hpbGQ7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGVudHJ5IH07CiAgfQogIGNvbnN0cnVjdG9yKGNvbnRlbnRzKSB7CiAgICBzdXBlcigpOwogICAgaWYgKGNvbnRlbnRzIGluc3RhbmNlb2YgQXJyYXkpIHsKICAgICAgdGhpcy5jb250ZW50cyA9IG5ldyBNYXAoY29udGVudHMpOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5jb250ZW50cyA9IGNvbnRlbnRzOwogICAgfQogIH0KfTsKdmFyIENvbnNvbGVTdGRvdXQgPSBjbGFzcyBleHRlbmRzIEZkIHsKICBmZF9maWxlc3RhdF9nZXQoKSB7CiAgICBjb25zdCBmaWxlc3RhdCA9IG5ldyBGaWxlc3RhdChGSUxFVFlQRV9DSEFSQUNURVJfREVWSUNFLCBCaWdJbnQoMCkpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBmaWxlc3RhdCB9OwogIH0KICBmZF9mZHN0YXRfZ2V0KCkgewogICAgY29uc3QgZmRzdGF0ID0gbmV3IEZkc3RhdChGSUxFVFlQRV9DSEFSQUNURVJfREVWSUNFLCAwKTsKICAgIGZkc3RhdC5mc19yaWdodHNfYmFzZSA9IEJpZ0ludChSSUdIVFNfRkRfV1JJVEUpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBmZHN0YXQgfTsKICB9CiAgZmRfd3JpdGUoZGF0YSkgewogICAgdGhpcy53cml0ZShkYXRhKTsKICAgIHJldHVybiB7IHJldDogMCwgbndyaXR0ZW46IGRhdGEuYnl0ZUxlbmd0aCB9OwogIH0KICBzdGF0aWMgbGluZUJ1ZmZlcmVkKHdyaXRlKSB7CiAgICBjb25zdCBkZWMgPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IiwgeyBmYXRhbDogZmFsc2UgfSk7CiAgICBsZXQgbGluZV9idWYgPSAiIjsKICAgIHJldHVybiBuZXcgQ29uc29sZVN0ZG91dCgoYnVmZmVyKSA9PiB7CiAgICAgIGxpbmVfYnVmICs9IGRlYy5kZWNvZGUoYnVmZmVyLCB7IHN0cmVhbTogdHJ1ZSB9KTsKICAgICAgY29uc3QgbGluZXMgPSBsaW5lX2J1Zi5zcGxpdCgiXG4iKTsKICAgICAgZm9yIChjb25zdCBbaSwgbGluZV0gb2YgbGluZXMuZW50cmllcygpKSB7CiAgICAgICAgaWYgKGkgPCBsaW5lcy5sZW5ndGggLSAxKSB7CiAgICAgICAgICB3cml0ZShsaW5lKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbGluZV9idWYgPSBsaW5lOwogICAgICAgIH0KICAgICAgfQogICAgfSk7CiAgfQogIGNvbnN0cnVjdG9yKHdyaXRlKSB7CiAgICBzdXBlcigpOwogICAgdGhpcy53cml0ZSA9IHdyaXRlOwogIH0KfTsKCi8vIG5vZGVfbW9kdWxlcy93YXNtLWltcG9ydHMtcGFyc2VyL2luZGV4LmpzCmZ1bmN0aW9uIHBhcnNlSW1wb3J0cyhtb2R1bGVCeXRlcykgewogIGlmIChtb2R1bGVCeXRlcyBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHsKICB9IGVsc2UgaWYgKG1vZHVsZUJ5dGVzIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHsKICAgIG1vZHVsZUJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkobW9kdWxlQnl0ZXMpOwogIH0gZWxzZSBpZiAobW9kdWxlQnl0ZXMuYnVmZmVyIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHsKICAgIG1vZHVsZUJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkobW9kdWxlQnl0ZXMuYnVmZmVyKTsKICB9IGVsc2UgewogICAgdGhyb3cgbmV3IEVycm9yKCJBcmd1bWVudCBtdXN0IGJlIGEgYnVmZmVyIHNvdXJjZSwgbGlrZSBVaW50OEFycmF5IG9yIEFycmF5QnVmZmVyIik7CiAgfQogIGNvbnN0IHBhcnNlU3RhdGUgPSBuZXcgUGFyc2VTdGF0ZShtb2R1bGVCeXRlcyk7CiAgcGFyc2VNYWdpY051bWJlcihwYXJzZVN0YXRlKTsKICBwYXJzZVZlcnNpb24ocGFyc2VTdGF0ZSk7CiAgY29uc3QgdHlwZXMgPSBbXTsKICBjb25zdCBpbXBvcnRzID0gW107CiAgd2hpbGUgKHBhcnNlU3RhdGUuaGFzTW9yZUJ5dGVzKCkpIHsKICAgIGNvbnN0IHNlY3Rpb25JZCA9IHBhcnNlU3RhdGUucmVhZEJ5dGUoKTsKICAgIGNvbnN0IHNlY3Rpb25TaXplID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICAgIHN3aXRjaCAoc2VjdGlvbklkKSB7CiAgICAgIGNhc2UgMTogewogICAgICAgIGNvbnN0IHR5cGVDb3VudCA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0eXBlQ291bnQ7IGkrKykgewogICAgICAgICAgdHlwZXMucHVzaChwYXJzZUZ1bmN0aW9uVHlwZShwYXJzZVN0YXRlKSk7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGNhc2UgMjogewogICAgICAgIGNvbnN0IGltcG9ydENvdW50ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGltcG9ydENvdW50OyBpKyspIHsKICAgICAgICAgIGNvbnN0IG1vZHVsZSA9IHBhcnNlU3RhdGUucmVhZE5hbWUoKTsKICAgICAgICAgIGNvbnN0IG5hbWUgPSBwYXJzZVN0YXRlLnJlYWROYW1lKCk7CiAgICAgICAgICBjb25zdCB0eXBlID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogICAgICAgICAgc3dpdGNoICh0eXBlKSB7CiAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICBjb25zdCBpbmRleCA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgICAgICAgICAgICAgaW1wb3J0cy5wdXNoKHsgbW9kdWxlLCBuYW1lLCBraW5kOiAiZnVuY3Rpb24iLCB0eXBlOiB0eXBlc1tpbmRleF0gfSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgICBpbXBvcnRzLnB1c2goeyBtb2R1bGUsIG5hbWUsIGtpbmQ6ICJ0YWJsZSIsIHR5cGU6IHBhcnNlVGFibGVUeXBlKHBhcnNlU3RhdGUpIH0pOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgaW1wb3J0cy5wdXNoKHsgbW9kdWxlLCBuYW1lLCBraW5kOiAibWVtb3J5IiwgdHlwZTogcGFyc2VMaW1pdHMocGFyc2VTdGF0ZSkgfSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgICBpbXBvcnRzLnB1c2goeyBtb2R1bGUsIG5hbWUsIGtpbmQ6ICJnbG9iYWwiLCB0eXBlOiBwYXJzZUdsb2JhbFR5cGUocGFyc2VTdGF0ZSkgfSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGltcG9ydCBkZXNjcmlwdG9yIHR5cGUgJHt0eXBlfWApOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gaW1wb3J0czsKICAgICAgfQogICAgICBkZWZhdWx0OiB7CiAgICAgICAgcGFyc2VTdGF0ZS5za2lwQnl0ZXMoc2VjdGlvblNpemUpOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfQogIHJldHVybiBbXTsKfQp2YXIgUGFyc2VTdGF0ZSA9IGNsYXNzIHsKICBjb25zdHJ1Y3Rvcihtb2R1bGVCeXRlcykgewogICAgdGhpcy5tb2R1bGVCeXRlcyA9IG1vZHVsZUJ5dGVzOwogICAgdGhpcy5vZmZzZXQgPSAwOwogICAgdGhpcy50ZXh0RGVjb2RlciA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKTsKICB9CiAgaGFzTW9yZUJ5dGVzKCkgewogICAgcmV0dXJuIHRoaXMub2Zmc2V0IDwgdGhpcy5tb2R1bGVCeXRlcy5sZW5ndGg7CiAgfQogIHJlYWRCeXRlKCkgewogICAgcmV0dXJuIHRoaXMubW9kdWxlQnl0ZXNbdGhpcy5vZmZzZXQrK107CiAgfQogIHNraXBCeXRlcyhjb3VudCkgewogICAgdGhpcy5vZmZzZXQgKz0gY291bnQ7CiAgfQogIHJlYWRVbnNpZ25lZExFQjEyOCgpIHsKICAgIGxldCByZXN1bHQgPSAwOwogICAgbGV0IHNoaWZ0ID0gMDsKICAgIGxldCBieXRlOwogICAgZG8gewogICAgICBieXRlID0gdGhpcy5yZWFkQnl0ZSgpOwogICAgICByZXN1bHQgfD0gKGJ5dGUgJiAxMjcpIDw8IHNoaWZ0OwogICAgICBzaGlmdCArPSA3OwogICAgfSB3aGlsZSAoYnl0ZSAmIDEyOCk7CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICByZWFkTmFtZSgpIHsKICAgIGNvbnN0IG5hbWVMZW5ndGggPSB0aGlzLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgY29uc3QgbmFtZUJ5dGVzID0gdGhpcy5tb2R1bGVCeXRlcy5zbGljZSh0aGlzLm9mZnNldCwgdGhpcy5vZmZzZXQgKyBuYW1lTGVuZ3RoKTsKICAgIGNvbnN0IG5hbWUgPSB0aGlzLnRleHREZWNvZGVyLmRlY29kZShuYW1lQnl0ZXMpOwogICAgdGhpcy5vZmZzZXQgKz0gbmFtZUxlbmd0aDsKICAgIHJldHVybiBuYW1lOwogIH0KICBhc3NlcnRCeXRlcyhleHBlY3RlZCkgewogICAgY29uc3QgYmFzZU9mZnNldCA9IHRoaXMub2Zmc2V0OwogICAgY29uc3QgZXhwZWN0ZWRMZW5ndGggPSBleHBlY3RlZC5sZW5ndGg7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGV4cGVjdGVkTGVuZ3RoOyBpKyspIHsKICAgICAgaWYgKHRoaXMubW9kdWxlQnl0ZXNbYmFzZU9mZnNldCArIGldICE9PSBleHBlY3RlZFtpXSkgewogICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgJHtleHBlY3RlZH0gYXQgb2Zmc2V0ICR7YmFzZU9mZnNldH1gKTsKICAgICAgfQogICAgfQogICAgdGhpcy5vZmZzZXQgKz0gZXhwZWN0ZWRMZW5ndGg7CiAgfQp9OwpmdW5jdGlvbiBwYXJzZU1hZ2ljTnVtYmVyKHBhcnNlU3RhdGUpIHsKICBjb25zdCBleHBlY3RlZCA9IFswLCA5NywgMTE1LCAxMDldOwogIHBhcnNlU3RhdGUuYXNzZXJ0Qnl0ZXMoZXhwZWN0ZWQpOwp9CmZ1bmN0aW9uIHBhcnNlVmVyc2lvbihwYXJzZVN0YXRlKSB7CiAgY29uc3QgZXhwZWN0ZWQgPSBbMSwgMCwgMCwgMF07CiAgcGFyc2VTdGF0ZS5hc3NlcnRCeXRlcyhleHBlY3RlZCk7Cn0KZnVuY3Rpb24gcGFyc2VUYWJsZVR5cGUocGFyc2VTdGF0ZSkgewogIGNvbnN0IGVsZW1lbnRUeXBlID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogIGxldCBlbGVtZW50OwogIHN3aXRjaCAoZWxlbWVudFR5cGUpIHsKICAgIGNhc2UgMTEyOgogICAgICBlbGVtZW50ID0gImZ1bmNyZWYiOwogICAgICBicmVhazsKICAgIGNhc2UgMTExOgogICAgICBlbGVtZW50ID0gImV4dGVybnJlZiI7CiAgICAgIGJyZWFrOwogICAgZGVmYXVsdDoKICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIHRhYmxlIGVsZW1lbnQgdHlwZSAke2VsZW1lbnRUeXBlfWApOwogIH0KICBjb25zdCB7IG1pbmltdW0sIG1heGltdW0gfSA9IHBhcnNlTGltaXRzKHBhcnNlU3RhdGUpOwogIGlmIChtYXhpbXVtKSB7CiAgICByZXR1cm4geyBlbGVtZW50LCBtaW5pbXVtLCBtYXhpbXVtIH07CiAgfSBlbHNlIHsKICAgIHJldHVybiB7IGVsZW1lbnQsIG1pbmltdW0gfTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VMaW1pdHMocGFyc2VTdGF0ZSkgewogIGNvbnN0IGZsYWdzID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogIGNvbnN0IG1pbmltdW0gPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogIGNvbnN0IGhhc01heGltdW0gPSBmbGFncyAmIDE7CiAgY29uc3Qgc2hhcmVkID0gKGZsYWdzICYgMikgIT09IDA7CiAgY29uc3QgaXNNZW1vcnk2NCA9IChmbGFncyAmIDQpICE9PSAwOwogIGNvbnN0IGluZGV4ID0gaXNNZW1vcnk2NCA/ICJpNjQiIDogImkzMiI7CiAgaWYgKGhhc01heGltdW0pIHsKICAgIGNvbnN0IG1heGltdW0gPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgcmV0dXJuIHsgbWluaW11bSwgc2hhcmVkLCBpbmRleCwgbWF4aW11bSB9OwogIH0gZWxzZSB7CiAgICByZXR1cm4geyBtaW5pbXVtLCBzaGFyZWQsIGluZGV4IH07CiAgfQp9CmZ1bmN0aW9uIHBhcnNlR2xvYmFsVHlwZShwYXJzZVN0YXRlKSB7CiAgY29uc3QgdmFsdWUgPSBwYXJzZVZhbHVlVHlwZShwYXJzZVN0YXRlKTsKICBjb25zdCBtdXRhYmxlID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpID09PSAxOwogIHJldHVybiB7IHZhbHVlLCBtdXRhYmxlIH07Cn0KZnVuY3Rpb24gcGFyc2VWYWx1ZVR5cGUocGFyc2VTdGF0ZSkgewogIGNvbnN0IHR5cGUgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgc3dpdGNoICh0eXBlKSB7CiAgICBjYXNlIDEyNzoKICAgICAgcmV0dXJuICJpMzIiOwogICAgY2FzZSAxMjY6CiAgICAgIHJldHVybiAiaTY0IjsKICAgIGNhc2UgMTI1OgogICAgICByZXR1cm4gImYzMiI7CiAgICBjYXNlIDEyNDoKICAgICAgcmV0dXJuICJmNjQiOwogICAgY2FzZSAxMTI6CiAgICAgIHJldHVybiAiZnVuY3JlZiI7CiAgICBjYXNlIDExMToKICAgICAgcmV0dXJuICJleHRlcm5yZWYiOwogICAgY2FzZSAxMjM6CiAgICAgIHJldHVybiAidjEyOCI7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gdmFsdWUgdHlwZSAke3R5cGV9YCk7CiAgfQp9CmZ1bmN0aW9uIHBhcnNlRnVuY3Rpb25UeXBlKHBhcnNlU3RhdGUpIHsKICBjb25zdCBmb3JtID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogIGlmIChmb3JtICE9PSA5NikgewogICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBmdW5jdGlvbiB0eXBlIGZvcm0gMHg2MCwgZ290ICR7Zm9ybX1gKTsKICB9CiAgY29uc3QgcGFyYW1ldGVycyA9IFtdOwogIGNvbnN0IHBhcmFtZXRlckNvdW50ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICBmb3IgKGxldCBpID0gMDsgaSA8IHBhcmFtZXRlckNvdW50OyBpKyspIHsKICAgIHBhcmFtZXRlcnMucHVzaChwYXJzZVZhbHVlVHlwZShwYXJzZVN0YXRlKSk7CiAgfQogIGNvbnN0IHJlc3VsdHMgPSBbXTsKICBjb25zdCByZXN1bHRDb3VudCA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgZm9yIChsZXQgaSA9IDA7IGkgPCByZXN1bHRDb3VudDsgaSsrKSB7CiAgICByZXN1bHRzLnB1c2gocGFyc2VWYWx1ZVR5cGUocGFyc2VTdGF0ZSkpOwogIH0KICByZXR1cm4geyBwYXJhbWV0ZXJzLCByZXN1bHRzIH07Cn0KCi8vIG5vZGVfbW9kdWxlcy93YXNtLWltcG9ydHMtcGFyc2VyL3BvbHlmaWxsLmpzCnZhciBoYXNXYXNtVHlwZVJlZmxlY3Rpb25TdXBwb3J0ID0gKCgpID0+IHsKICBjb25zdCBtb2R1bGVCeXRlcyA9IG5ldyBVaW50OEFycmF5KFsKICAgIDAsCiAgICA5NywKICAgIDExNSwKICAgIDEwOSwKICAgIDEsCiAgICAwLAogICAgMCwKICAgIDAsCiAgICAyLAogICAgNiwKICAgIDEsCiAgICAwLAogICAgMCwKICAgIDIsCiAgICAwLAogICAgMQogIF0pOwogIGNvbnN0IG1vZHVsZSA9IG5ldyBXZWJBc3NlbWJseS5Nb2R1bGUobW9kdWxlQnl0ZXMpOwogIGNvbnN0IGltcG9ydHMgPSBXZWJBc3NlbWJseS5Nb2R1bGUuaW1wb3J0cyhtb2R1bGUpOwogIGNvbnN0IG1lbW9yeUltcG9ydCA9IGltcG9ydHNbMF07CiAgcmV0dXJuIHR5cGVvZiBtZW1vcnlJbXBvcnQudHlwZSA9PT0gIm9iamVjdCI7Cn0pKCk7CmZ1bmN0aW9uIHBvbHlmaWxsKFdlYkFzc2VtYmx5MykgewogIGlmIChoYXNXYXNtVHlwZVJlZmxlY3Rpb25TdXBwb3J0KSB7CiAgICByZXR1cm4gV2ViQXNzZW1ibHkzOwogIH0KICBjb25zdCBuZXdXZWJBc3NlbWJseSA9IHt9OwogIGZvciAoY29uc3Qga2V5IGluIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzKFdlYkFzc2VtYmx5MykpIHsKICAgIG5ld1dlYkFzc2VtYmx5W2tleV0gPSBXZWJBc3NlbWJseTNba2V5XTsKICB9CiAgY29uc3QgcG9seWZpbGxlZEltcG9ydHNTeW1ib2wgPSBTeW1ib2woInBvbHlmaWxsZWRJbXBvcnRzU3ltYm9sIik7CiAgY29uc3QgYXNzaWduSW1wb3J0cyA9IChtb2R1bGUsIHNvdXJjZUJ5dGVzKSA9PiB7CiAgICBtb2R1bGVbcG9seWZpbGxlZEltcG9ydHNTeW1ib2xdID0gcGFyc2VJbXBvcnRzKHNvdXJjZUJ5dGVzKTsKICB9OwogIGNvbnN0IG5ld01vZHVsZSA9IG5ld1dlYkFzc2VtYmx5Lk1vZHVsZSA9IGZ1bmN0aW9uKGJ5dGVzKSB7CiAgICBjb25zdCBtb2R1bGUgPSBuZXcgV2ViQXNzZW1ibHkzLk1vZHVsZShieXRlcyk7CiAgICBhc3NpZ25JbXBvcnRzKG1vZHVsZSwgYnl0ZXMpOwogICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKG1vZHVsZSwgbmV3TW9kdWxlLnByb3RvdHlwZSk7CiAgICByZXR1cm4gbW9kdWxlOwogIH07CiAgT2JqZWN0LnNldFByb3RvdHlwZU9mKG5ld01vZHVsZS5wcm90b3R5cGUsIFdlYkFzc2VtYmx5My5Nb2R1bGUucHJvdG90eXBlKTsKICBuZXdXZWJBc3NlbWJseS5jb21waWxlID0gYXN5bmMgKHNvdXJjZSkgPT4gewogICAgY29uc3QgbW9kdWxlID0gYXdhaXQgV2ViQXNzZW1ibHkzLmNvbXBpbGUoc291cmNlKTsKICAgIGFzc2lnbkltcG9ydHMobW9kdWxlLCBzb3VyY2UpOwogICAgcmV0dXJuIG1vZHVsZTsKICB9OwogIGlmIChXZWJBc3NlbWJseTMuY29tcGlsZVN0cmVhbWluZykgewogICAgbmV3V2ViQXNzZW1ibHkuY29tcGlsZVN0cmVhbWluZyA9IGFzeW5jIChzb3VyY2UpID0+IHsKICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBzb3VyY2U7CiAgICAgIGNvbnN0IGNsb25lID0gcmVzcG9uc2UuY2xvbmUoKTsKICAgICAgY29uc3QgbW9kdWxlID0gYXdhaXQgV2ViQXNzZW1ibHkzLmNvbXBpbGVTdHJlYW1pbmcocmVzcG9uc2UpOwogICAgICBhc3NpZ25JbXBvcnRzKG1vZHVsZSwgbmV3IFVpbnQ4QXJyYXkoYXdhaXQgY2xvbmUuYXJyYXlCdWZmZXIoKSkpOwogICAgICByZXR1cm4gbW9kdWxlOwogICAgfTsKICB9CiAgbmV3TW9kdWxlLmltcG9ydHMgPSAobW9kdWxlKSA9PiB7CiAgICBjb25zdCBwYXJzZWRJbXBvcnRzID0gbW9kdWxlW3BvbHlmaWxsZWRJbXBvcnRzU3ltYm9sXTsKICAgIGlmICghcGFyc2VkSW1wb3J0cykgewogICAgICByZXR1cm4gV2ViQXNzZW1ibHkzLk1vZHVsZS5pbXBvcnRzKG1vZHVsZSk7CiAgICB9CiAgICByZXR1cm4gcGFyc2VkSW1wb3J0czsKICB9OwogIHJldHVybiBuZXdXZWJBc3NlbWJseTsKfQoKLy8gZW50cnlwb2ludC9pbnRyaW5zaWNzLnRzCnZhciBXZWJBc3NlbWJseTIgPSBwb2x5ZmlsbChnbG9iYWxUaGlzLldlYkFzc2VtYmx5KTsKdmFyIExpbmVEZWNvZGVyID0gY2xhc3MgewogIGNvbnN0cnVjdG9yKG9uTGluZSkgewogICAgdGhpcy5kZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIsIHsgZmF0YWw6IGZhbHNlIH0pOwogICAgdGhpcy5idWZmZXIgPSAiIjsKICAgIHRoaXMub25MaW5lID0gb25MaW5lOwogIH0KICBkZWNvZGVyOwogIGJ1ZmZlcjsKICBvbkxpbmU7CiAgc2VuZChjaHVuaykgewogICAgdGhpcy5idWZmZXIgKz0gdGhpcy5kZWNvZGVyLmRlY29kZShjaHVuaywgeyBzdHJlYW06IHRydWUgfSk7CiAgICBjb25zdCBsaW5lcyA9IHRoaXMuYnVmZmVyLnNwbGl0KCJcbiIpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGggLSAxOyBpKyspIHsKICAgICAgdGhpcy5vbkxpbmUobGluZXNbaV0pOwogICAgfQogICAgdGhpcy5idWZmZXIgPSBsaW5lc1tsaW5lcy5sZW5ndGggLSAxXTsKICB9Cn07CmFzeW5jIGZ1bmN0aW9uIGluc3RhbnRpYXRlKHJhd09wdGlvbnMsIGV4dHJhV2FzbUltcG9ydHMpIHsKICBjb25zdCBvcHRpb25zID0gZGVmYXVsdEluc3RhbnRpYXRpb25PcHRpb25zKHJhd09wdGlvbnMpOwogIGxldCBzd2lmdCA9IG9wdGlvbnMuc3dpZnQ7CiAgaWYgKCFzd2lmdCAmJiBvcHRpb25zLlN3aWZ0UnVudGltZSkgewogICAgc3dpZnQgPSBuZXcgb3B0aW9ucy5Td2lmdFJ1bnRpbWUoKTsKICB9CiAgbGV0IHN0ZG91dExpbmUgPSB2b2lkIDA7CiAgaWYgKG9wdGlvbnMub25TdGRvdXRMaW5lICE9IG51bGwpIHsKICAgIHN0ZG91dExpbmUgPSBuZXcgTGluZURlY29kZXIob3B0aW9ucy5vblN0ZG91dExpbmUpOwogIH0KICBjb25zdCBzdGRvdXQgPSBuZXcgQ29uc29sZVN0ZG91dCgoY2h1bmspID0+IHsKICAgIG9wdGlvbnMub25TdGRvdXQ/LmNhbGwodm9pZCAwLCBjaHVuayk7CiAgICBzdGRvdXRMaW5lPy5zZW5kKGNodW5rKTsKICB9KTsKICBsZXQgc3RkZXJyTGluZSA9IHZvaWQgMDsKICBpZiAob3B0aW9ucy5vblN0ZGVyckxpbmUgIT0gbnVsbCkgewogICAgc3RkZXJyTGluZSA9IG5ldyBMaW5lRGVjb2RlcihvcHRpb25zLm9uU3RkZXJyTGluZSk7CiAgfQogIGNvbnN0IHN0ZGVyciA9IG5ldyBDb25zb2xlU3Rkb3V0KChjaHVuaykgPT4gewogICAgb3B0aW9ucy5vblN0ZGVycj8uY2FsbCh2b2lkIDAsIGNodW5rKTsKICAgIHN0ZGVyckxpbmU/LnNlbmQoY2h1bmspOwogIH0pOwogIGNvbnN0IGFyZ3MgPSBvcHRpb25zLmFyZ3MgfHwgW107CiAgY29uc3QgZmRzID0gWwogICAgbmV3IE9wZW5GaWxlKG5ldyBGaWxlKFtdKSksCiAgICBzdGRvdXQsCiAgICBzdGRlcnIsCiAgICBuZXcgUHJlb3BlbkRpcmVjdG9yeSgiLyIsIC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCkpCiAgXTsKICBjb25zdCBlbnZzID0gb3B0aW9ucy5lbnYgPyBPYmplY3QuZW50cmllcyhvcHRpb25zLmVudikubWFwKChba2V5LCB2YWx1ZV0pID0+IGAke2tleX09JHt2YWx1ZX1gKSA6IFtdOwogIGNvbnN0IHdhc2kgPSBuZXcgV0FTSShhcmdzLCBlbnZzLCBmZHMsIHsKICAgIGRlYnVnOiBmYWxzZQogIH0pOwogIGNvbnN0IGNyZWF0ZVdhc21JbXBvcnRPYmplY3QgPSAoZXh0cmFXYXNtSW1wb3J0czIsIG1vZHVsZSkgPT4gewogICAgY29uc3QgaW1wb3J0T2JqZWN0MiA9IHsKICAgICAgd2FzaV9zbmFwc2hvdF9wcmV2aWV3MTogd2FzaS53YXNpSW1wb3J0CiAgICB9OwogICAgaWYgKHN3aWZ0KSB7CiAgICAgIGltcG9ydE9iamVjdDIuamF2YXNjcmlwdF9raXQgPSBzd2lmdC53YXNtSW1wb3J0czsKICAgIH0KICAgIGlmIChleHRyYVdhc21JbXBvcnRzMikgewogICAgICBmb3IgKGNvbnN0IG1vZHVsZU5hbWUgaW4gZXh0cmFXYXNtSW1wb3J0czIpIHsKICAgICAgICBpZiAoIWltcG9ydE9iamVjdDJbbW9kdWxlTmFtZV0pIHsKICAgICAgICAgIGltcG9ydE9iamVjdDJbbW9kdWxlTmFtZV0gPSB7fTsKICAgICAgICB9CiAgICAgICAgZm9yIChjb25zdCBlbnRyeSBpbiBleHRyYVdhc21JbXBvcnRzMlttb2R1bGVOYW1lXSkgewogICAgICAgICAgaW1wb3J0T2JqZWN0Mlttb2R1bGVOYW1lXVtlbnRyeV0gPSBleHRyYVdhc21JbXBvcnRzMlttb2R1bGVOYW1lXVtlbnRyeV07CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBmb3IgKGNvbnN0IF9pbXBvcnRFbnRyeSBvZiBXZWJBc3NlbWJseTIuTW9kdWxlLmltcG9ydHMobW9kdWxlKSkgewogICAgICBjb25zdCBpbXBvcnRFbnRyeSA9IF9pbXBvcnRFbnRyeTsKICAgICAgaWYgKCFpbXBvcnRPYmplY3QyW2ltcG9ydEVudHJ5Lm1vZHVsZV0pIHsKICAgICAgICBpbXBvcnRPYmplY3QyW2ltcG9ydEVudHJ5Lm1vZHVsZV0gPSB7fTsKICAgICAgfQogICAgICBpZiAoaW1wb3J0T2JqZWN0MltpbXBvcnRFbnRyeS5tb2R1bGVdW2ltcG9ydEVudHJ5Lm5hbWVdKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGltcG9ydEVudHJ5LmtpbmQgPT0gImZ1bmN0aW9uIikgewogICAgICAgIGltcG9ydE9iamVjdDJbaW1wb3J0RW50cnkubW9kdWxlXVtpbXBvcnRFbnRyeS5uYW1lXSA9ICgpID0+IHsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW1wb3J0ZWQgZnVuY3Rpb24gJHtpbXBvcnRFbnRyeS5tb2R1bGV9LiR7aW1wb3J0RW50cnkubmFtZX0gbm90IGltcGxlbWVudGVkYCk7CiAgICAgICAgfTsKICAgICAgfSBlbHNlIGlmIChpbXBvcnRFbnRyeS5raW5kID09ICJtZW1vcnkiICYmIGltcG9ydEVudHJ5Lm1vZHVsZSA9PSAiZW52IiAmJiBpbXBvcnRFbnRyeS5uYW1lID09ICJtZW1vcnkiKSB7CiAgICAgICAgY29uc3QgdHlwZSA9IGltcG9ydEVudHJ5LnR5cGU7CiAgICAgICAgY29uc3QgZGVzY3JpcHRvciA9IHsKICAgICAgICAgIGluaXRpYWw6IHR5cGUubWluaW11bSwKICAgICAgICAgIG1heGltdW06IHR5cGUubWF4aW11bSwKICAgICAgICAgIHNoYXJlZDogdHlwZS5zaGFyZWQKICAgICAgICB9OwogICAgICAgIGltcG9ydE9iamVjdDJbaW1wb3J0RW50cnkubW9kdWxlXVtpbXBvcnRFbnRyeS5uYW1lXSA9IG5ldyBXZWJBc3NlbWJseTIuTWVtb3J5KGRlc2NyaXB0b3IpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gaW1wb3J0T2JqZWN0MjsKICB9OwogIGNvbnN0IGltcG9ydE9iamVjdCA9IGNyZWF0ZVdhc21JbXBvcnRPYmplY3QoZXh0cmFXYXNtSW1wb3J0cywgb3B0aW9ucy5tb2R1bGUpOwogIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgV2ViQXNzZW1ibHkyLmluc3RhbnRpYXRlKG9wdGlvbnMubW9kdWxlLCBpbXBvcnRPYmplY3QpOwogIGlmIChzd2lmdCAmJiBpbnN0YW5jZS5leHBvcnRzLnN3anNfbGlicmFyeV92ZXJzaW9uKSB7CiAgICBzd2lmdC5zZXRJbnN0YW5jZShpbnN0YW5jZSk7CiAgfQogIGlmICh0eXBlb2YgaW5zdGFuY2UuZXhwb3J0cy5fc3RhcnQgPT09ICJmdW5jdGlvbiIpIHsKICAgIHdhc2kuc3RhcnQoaW5zdGFuY2UpOwogIH0gZWxzZSBpZiAodHlwZW9mIGluc3RhbmNlLmV4cG9ydHMuX2luaXRpYWxpemUgPT0gImZ1bmN0aW9uIikgewogICAgd2FzaS5pbml0aWFsaXplKGluc3RhbmNlKTsKICAgIGlmIChzd2lmdCAmJiBzd2lmdC5tYWluKSB7CiAgICAgIHN3aWZ0Lm1haW4oKTsKICAgIH0gZWxzZSB7CiAgICAgIGlmICh0eXBlb2YgaW5zdGFuY2UuZXhwb3J0cy5tYWluID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgaW5zdGFuY2UuZXhwb3J0cy5tYWluKCk7CiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGluc3RhbmNlLmV4cG9ydHMuX19tYWluX2FyZ2NfYXJndiA9PT0gImZ1bmN0aW9uIikgewogICAgICAgIGluc3RhbmNlLmV4cG9ydHMuX19tYWluX2FyZ2NfYXJndigwLCAwKTsKICAgICAgfQogICAgfQogIH0KICByZXR1cm4geyBpbnN0YW5jZSB9Owp9CmZ1bmN0aW9uIGRlZmF1bHRJbnN0YW50aWF0aW9uT3B0aW9ucyhvcHRpb25zKSB7CiAgaWYgKG9wdGlvbnMuYXJncyA9PSBudWxsKSB7CiAgICBvcHRpb25zLmFyZ3MgPSBbIm1haW4ud2FzbSJdOwogIH0KICBjb25zdCBpc05vZGVKcyA9IHR5cGVvZiBwcm9jZXNzICE9PSAidW5kZWZpbmVkIiAmJiBwcm9jZXNzLnJlbGVhc2UubmFtZSA9PT0gIm5vZGUiOwogIGNvbnN0IGlzV2ViQnJvd3NlciA9IHR5cGVvZiB3aW5kb3cgIT09ICJ1bmRlZmluZWQiOwogIGlmIChpc05vZGVKcykgewogICAgaWYgKCFvcHRpb25zLm9uU3Rkb3V0KSB7CiAgICAgIG9wdGlvbnMub25TdGRvdXQgPSAoY2h1bmspID0+IHByb2Nlc3Muc3Rkb3V0LndyaXRlKGNodW5rKTsKICAgIH0KICAgIGlmICghb3B0aW9ucy5vblN0ZGVycikgewogICAgICBvcHRpb25zLm9uU3RkZXJyID0gKGNodW5rKSA9PiBwcm9jZXNzLnN0ZGVyci53cml0ZShjaHVuayk7CiAgICB9CiAgfSBlbHNlIGlmIChpc1dlYkJyb3dzZXIpIHsKICAgIGlmICghb3B0aW9ucy5vblN0ZG91dExpbmUpIHsKICAgICAgb3B0aW9ucy5vblN0ZG91dExpbmUgPSAobGluZSkgPT4gY29uc29sZS5sb2cobGluZSk7CiAgICB9CiAgICBpZiAoIW9wdGlvbnMub25TdGRlcnJMaW5lKSB7CiAgICAgIG9wdGlvbnMub25TdGRlcnJMaW5lID0gKGxpbmUpID0+IGNvbnNvbGUud2FybihsaW5lKTsKICAgIH0KICB9CiAgcmV0dXJuIG9wdGlvbnM7Cn0KCi8vIGVudHJ5cG9pbnQvZGV2LnRzCnZhciBzb2NrZXQgPSBuZXcgcmVjb25uZWN0aW5nX3dlYnNvY2tldF9tanNfZGVmYXVsdChgd3M6Ly8ke2xvY2F0aW9uLmhvc3R9L3dhdGNoZXJgKTsKc29ja2V0LmFkZEV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLCAobWVzc2FnZSkgPT4gewogIGlmIChtZXNzYWdlLmRhdGEgPT09ICJyZWxvYWQiKSB7CiAgICBsb2NhdGlvbi5yZWxvYWQoKTsKICB9Cn0pOwp2YXIgc3RhcnRXYXNpVGFzayA9IGFzeW5jICgpID0+IHsKICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKCIvbWFpbi53YXNtIik7CiAgbGV0IHJ1bnRpbWVDb25zdHJ1Y3RvciA9IHZvaWQgMDsKICB0cnkgewogICAgY29uc3QgeyBTd2lmdFJ1bnRpbWUgfSA9IGF3YWl0IGltcG9ydCgKICAgICAgLy8gQHRzLWlnbm9yZQogICAgICAiLi9KYXZhU2NyaXB0S2l0X0phdmFTY3JpcHRLaXQucmVzb3VyY2VzL1J1bnRpbWUvaW5kZXgubWpzIgogICAgKTsKICAgIHJ1bnRpbWVDb25zdHJ1Y3RvciA9IFN3aWZ0UnVudGltZTsKICB9IGNhdGNoIHsKICAgIGNvbnNvbGUubG9nKCJKYXZhU2NyaXB0S2l0IG1vZHVsZSBub3QgYXZhaWxhYmxlLCBydW5uaW5nIHdpdGhvdXQgSmF2YVNjcmlwdEtpdCBydW50aW1lLiIpOwogIH0KICBhd2FpdCBpbnN0YW50aWF0ZSh7CiAgICBtb2R1bGU6IGF3YWl0IFdlYkFzc2VtYmx5LmNvbXBpbGVTdHJlYW1pbmcocmVzcG9uc2UpLAogICAgb25TdGRvdXQoY2h1bmspIHsKICAgICAgY29uc3Qga2luZEJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcigyKTsKICAgICAgbmV3IERhdGFWaWV3KGtpbmRCdWZmZXIpLnNldFVpbnQxNigwLCAxMDAxLCB0cnVlKTsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IFVpbnQ4QXJyYXkoMiArIGNodW5rLmxlbmd0aCk7CiAgICAgIGJ1ZmZlci5zZXQobmV3IFVpbnQ4QXJyYXkoa2luZEJ1ZmZlciksIDApOwogICAgICBidWZmZXIuc2V0KGNodW5rLCAyKTsKICAgICAgc29ja2V0LnNlbmQoYnVmZmVyKTsKICAgIH0sCiAgICBvblN0ZG91dExpbmUobGluZSkgewogICAgICBjb25zb2xlLmxvZyhsaW5lKTsKICAgIH0sCiAgICBvblN0ZGVycihjaHVuaykgewogICAgICBjb25zdCBraW5kQnVmZmVyID0gbmV3IEFycmF5QnVmZmVyKDIpOwogICAgICBuZXcgRGF0YVZpZXcoa2luZEJ1ZmZlcikuc2V0VWludDE2KDAsIDEwMDIsIHRydWUpOwogICAgICBjb25zdCBidWZmZXIgPSBuZXcgVWludDhBcnJheSgyICsgY2h1bmsubGVuZ3RoKTsKICAgICAgYnVmZmVyLnNldChuZXcgVWludDhBcnJheShraW5kQnVmZmVyKSwgMCk7CiAgICAgIGJ1ZmZlci5zZXQoY2h1bmssIDIpOwogICAgICBzb2NrZXQuc2VuZChidWZmZXIpOwogICAgfSwKICAgIG9uU3RkZXJyTGluZShsaW5lKSB7CiAgICAgIGNvbnNvbGUuZXJyb3IobGluZSk7CiAgICB9LAogICAgU3dpZnRSdW50aW1lOiBydW50aW1lQ29uc3RydWN0b3IKICB9KTsKfTsKZnVuY3Rpb24gaGFuZGxlRXJyb3IoZSkgewogIGlmIChlIGluc3RhbmNlb2YgRXJyb3IpIHsKICAgIGNvbnN0IHN0YWNrID0gZS5zdGFjazsKICAgIGlmIChzdGFjayAhPSBudWxsKSB7CiAgICAgIHNvY2tldC5zZW5kKEpTT04uc3RyaW5naWZ5KHsKICAgICAgICBraW5kOiAic3RhY2tUcmFjZSIsCiAgICAgICAgc3RhY2tUcmFjZTogc3RhY2sKICAgICAgfSkpOwogICAgfQogIH0KfQphc3luYyBmdW5jdGlvbiBtYWluKCkgewogIHRyeSB7CiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigiZXJyb3IiLCAoZXZlbnQpID0+IHsKICAgICAgaGFuZGxlRXJyb3IoZXZlbnQuZXJyb3IpOwogICAgfSk7CiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigidW5oYW5kbGVkcmVqZWN0aW9uIiwgKGV2ZW50KSA9PiB7CiAgICAgIGhhbmRsZUVycm9yKGV2ZW50LnJlYXNvbik7CiAgICB9KTsKICAgIGF3YWl0IHN0YXJ0V2FzaVRhc2soKTsKICB9IGNhdGNoIChlKSB7CiAgICBoYW5kbGVFcnJvcihlKTsKICAgIHRocm93IGU7CiAgfQp9Cm1haW4oKTsKLyohCiAqIFJlY29ubmVjdGluZyBXZWJTb2NrZXQKICogYnkgUGVkcm8gTGFkYXJpYSA8cGVkcm8ubGFkYXJpYUBnbWFpbC5jb20+CiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9wbGFkYXJpYS9yZWNvbm5lY3Rpbmctd2Vic29ja2V0CiAqIExpY2Vuc2UgTUlUCiAqLwovKiEgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuCkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOyB5b3UgbWF5IG5vdCB1c2UKdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUKTGljZW5zZSBhdCBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAKClRISVMgQ09ERSBJUyBQUk9WSURFRCBPTiBBTiAqQVMgSVMqIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkKS0lORCwgRUlUSEVSIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIFdJVEhPVVQgTElNSVRBVElPTiBBTlkgSU1QTElFRApXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgVElUTEUsIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLApNRVJDSEFOVEFCTElUWSBPUiBOT04tSU5GUklOR0VNRU5ULgoKU2VlIHRoZSBBcGFjaGUgVmVyc2lvbiAyLjAgTGljZW5zZSBmb3Igc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zCmFuZCBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi8K")! - public static let bundle: Data = Data(base64Encoded: "Ly8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC93YXNpX2RlZnMuanMKdmFyIENMT0NLSURfUkVBTFRJTUUgPSAwOwp2YXIgQ0xPQ0tJRF9NT05PVE9OSUMgPSAxOwp2YXIgRVJSTk9fU1VDQ0VTUyA9IDA7CnZhciBFUlJOT19CQURGID0gODsKdmFyIEVSUk5PX0VYSVNUID0gMjA7CnZhciBFUlJOT19JTlZBTCA9IDI4Owp2YXIgRVJSTk9fSVNESVIgPSAzMTsKdmFyIEVSUk5PX05BTUVUT09MT05HID0gMzc7CnZhciBFUlJOT19OT0VOVCA9IDQ0Owp2YXIgRVJSTk9fTk9TWVMgPSA1MjsKdmFyIEVSUk5PX05PVERJUiA9IDU0Owp2YXIgRVJSTk9fTk9URU1QVFkgPSA1NTsKdmFyIEVSUk5PX05PVFNVUCA9IDU4Owp2YXIgRVJSTk9fUEVSTSA9IDYzOwp2YXIgRVJSTk9fTk9UQ0FQQUJMRSA9IDc2Owp2YXIgUklHSFRTX0ZEX0RBVEFTWU5DID0gMSA8PCAwOwp2YXIgUklHSFRTX0ZEX1JFQUQgPSAxIDw8IDE7CnZhciBSSUdIVFNfRkRfU0VFSyA9IDEgPDwgMjsKdmFyIFJJR0hUU19GRF9GRFNUQVRfU0VUX0ZMQUdTID0gMSA8PCAzOwp2YXIgUklHSFRTX0ZEX1NZTkMgPSAxIDw8IDQ7CnZhciBSSUdIVFNfRkRfVEVMTCA9IDEgPDwgNTsKdmFyIFJJR0hUU19GRF9XUklURSA9IDEgPDwgNjsKdmFyIFJJR0hUU19GRF9BRFZJU0UgPSAxIDw8IDc7CnZhciBSSUdIVFNfRkRfQUxMT0NBVEUgPSAxIDw8IDg7CnZhciBSSUdIVFNfUEFUSF9DUkVBVEVfRElSRUNUT1JZID0gMSA8PCA5Owp2YXIgUklHSFRTX1BBVEhfQ1JFQVRFX0ZJTEUgPSAxIDw8IDEwOwp2YXIgUklHSFRTX1BBVEhfTElOS19TT1VSQ0UgPSAxIDw8IDExOwp2YXIgUklHSFRTX1BBVEhfTElOS19UQVJHRVQgPSAxIDw8IDEyOwp2YXIgUklHSFRTX1BBVEhfT1BFTiA9IDEgPDwgMTM7CnZhciBSSUdIVFNfRkRfUkVBRERJUiA9IDEgPDwgMTQ7CnZhciBSSUdIVFNfUEFUSF9SRUFETElOSyA9IDEgPDwgMTU7CnZhciBSSUdIVFNfUEFUSF9SRU5BTUVfU09VUkNFID0gMSA8PCAxNjsKdmFyIFJJR0hUU19QQVRIX1JFTkFNRV9UQVJHRVQgPSAxIDw8IDE3Owp2YXIgUklHSFRTX1BBVEhfRklMRVNUQVRfR0VUID0gMSA8PCAxODsKdmFyIFJJR0hUU19QQVRIX0ZJTEVTVEFUX1NFVF9TSVpFID0gMSA8PCAxOTsKdmFyIFJJR0hUU19QQVRIX0ZJTEVTVEFUX1NFVF9USU1FUyA9IDEgPDwgMjA7CnZhciBSSUdIVFNfRkRfRklMRVNUQVRfR0VUID0gMSA8PCAyMTsKdmFyIFJJR0hUU19GRF9GSUxFU1RBVF9TRVRfU0laRSA9IDEgPDwgMjI7CnZhciBSSUdIVFNfRkRfRklMRVNUQVRfU0VUX1RJTUVTID0gMSA8PCAyMzsKdmFyIFJJR0hUU19QQVRIX1NZTUxJTksgPSAxIDw8IDI0Owp2YXIgUklHSFRTX1BBVEhfUkVNT1ZFX0RJUkVDVE9SWSA9IDEgPDwgMjU7CnZhciBSSUdIVFNfUEFUSF9VTkxJTktfRklMRSA9IDEgPDwgMjY7CnZhciBSSUdIVFNfUE9MTF9GRF9SRUFEV1JJVEUgPSAxIDw8IDI3Owp2YXIgUklHSFRTX1NPQ0tfU0hVVERPV04gPSAxIDw8IDI4Owp2YXIgSW92ZWMgPSBjbGFzcyB7CiAgc3RhdGljIHJlYWRfYnl0ZXModmlldywgcHRyKSB7CiAgICBjb25zdCBpb3ZlYyA9IG5ldyBJb3ZlYygpOwogICAgaW92ZWMuYnVmID0gdmlldy5nZXRVaW50MzIocHRyLCB0cnVlKTsKICAgIGlvdmVjLmJ1Zl9sZW4gPSB2aWV3LmdldFVpbnQzMihwdHIgKyA0LCB0cnVlKTsKICAgIHJldHVybiBpb3ZlYzsKICB9CiAgc3RhdGljIHJlYWRfYnl0ZXNfYXJyYXkodmlldywgcHRyLCBsZW4pIHsKICAgIGNvbnN0IGlvdmVjcyA9IFtdOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgICBpb3ZlY3MucHVzaChJb3ZlYy5yZWFkX2J5dGVzKHZpZXcsIHB0ciArIDggKiBpKSk7CiAgICB9CiAgICByZXR1cm4gaW92ZWNzOwogIH0KfTsKdmFyIENpb3ZlYyA9IGNsYXNzIHsKICBzdGF0aWMgcmVhZF9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIGNvbnN0IGlvdmVjID0gbmV3IENpb3ZlYygpOwogICAgaW92ZWMuYnVmID0gdmlldy5nZXRVaW50MzIocHRyLCB0cnVlKTsKICAgIGlvdmVjLmJ1Zl9sZW4gPSB2aWV3LmdldFVpbnQzMihwdHIgKyA0LCB0cnVlKTsKICAgIHJldHVybiBpb3ZlYzsKICB9CiAgc3RhdGljIHJlYWRfYnl0ZXNfYXJyYXkodmlldywgcHRyLCBsZW4pIHsKICAgIGNvbnN0IGlvdmVjcyA9IFtdOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgICBpb3ZlY3MucHVzaChDaW92ZWMucmVhZF9ieXRlcyh2aWV3LCBwdHIgKyA4ICogaSkpOwogICAgfQogICAgcmV0dXJuIGlvdmVjczsKICB9Cn07CnZhciBXSEVOQ0VfU0VUID0gMDsKdmFyIFdIRU5DRV9DVVIgPSAxOwp2YXIgV0hFTkNFX0VORCA9IDI7CnZhciBGSUxFVFlQRV9DSEFSQUNURVJfREVWSUNFID0gMjsKdmFyIEZJTEVUWVBFX0RJUkVDVE9SWSA9IDM7CnZhciBGSUxFVFlQRV9SRUdVTEFSX0ZJTEUgPSA0Owp2YXIgRGlyZW50ID0gY2xhc3MgewogIGhlYWRfbGVuZ3RoKCkgewogICAgcmV0dXJuIDI0OwogIH0KICBuYW1lX2xlbmd0aCgpIHsKICAgIHJldHVybiB0aGlzLmRpcl9uYW1lLmJ5dGVMZW5ndGg7CiAgfQogIHdyaXRlX2hlYWRfYnl0ZXModmlldywgcHRyKSB7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIsIHRoaXMuZF9uZXh0LCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDgsIHRoaXMuZF9pbm8sIHRydWUpOwogICAgdmlldy5zZXRVaW50MzIocHRyICsgMTYsIHRoaXMuZGlyX25hbWUubGVuZ3RoLCB0cnVlKTsKICAgIHZpZXcuc2V0VWludDgocHRyICsgMjAsIHRoaXMuZF90eXBlKTsKICB9CiAgd3JpdGVfbmFtZV9ieXRlcyh2aWV3OCwgcHRyLCBidWZfbGVuKSB7CiAgICB2aWV3OC5zZXQodGhpcy5kaXJfbmFtZS5zbGljZSgwLCBNYXRoLm1pbih0aGlzLmRpcl9uYW1lLmJ5dGVMZW5ndGgsIGJ1Zl9sZW4pKSwgcHRyKTsKICB9CiAgY29uc3RydWN0b3IobmV4dF9jb29raWUsIG5hbWUsIHR5cGUpIHsKICAgIHRoaXMuZF9pbm8gPSAwbjsKICAgIGNvbnN0IGVuY29kZWRfbmFtZSA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShuYW1lKTsKICAgIHRoaXMuZF9uZXh0ID0gbmV4dF9jb29raWU7CiAgICB0aGlzLmRfbmFtbGVuID0gZW5jb2RlZF9uYW1lLmJ5dGVMZW5ndGg7CiAgICB0aGlzLmRfdHlwZSA9IHR5cGU7CiAgICB0aGlzLmRpcl9uYW1lID0gZW5jb2RlZF9uYW1lOwogIH0KfTsKdmFyIEZERkxBR1NfQVBQRU5EID0gMSA8PCAwOwp2YXIgRkRGTEFHU19EU1lOQyA9IDEgPDwgMTsKdmFyIEZERkxBR1NfTk9OQkxPQ0sgPSAxIDw8IDI7CnZhciBGREZMQUdTX1JTWU5DID0gMSA8PCAzOwp2YXIgRkRGTEFHU19TWU5DID0gMSA8PCA0Owp2YXIgRmRzdGF0ID0gY2xhc3MgewogIHdyaXRlX2J5dGVzKHZpZXcsIHB0cikgewogICAgdmlldy5zZXRVaW50OChwdHIsIHRoaXMuZnNfZmlsZXR5cGUpOwogICAgdmlldy5zZXRVaW50MTYocHRyICsgMiwgdGhpcy5mc19mbGFncywgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA4LCB0aGlzLmZzX3JpZ2h0c19iYXNlLCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDE2LCB0aGlzLmZzX3JpZ2h0c19pbmhlcml0ZWQsIHRydWUpOwogIH0KICBjb25zdHJ1Y3RvcihmaWxldHlwZSwgZmxhZ3MpIHsKICAgIHRoaXMuZnNfcmlnaHRzX2Jhc2UgPSAwbjsKICAgIHRoaXMuZnNfcmlnaHRzX2luaGVyaXRlZCA9IDBuOwogICAgdGhpcy5mc19maWxldHlwZSA9IGZpbGV0eXBlOwogICAgdGhpcy5mc19mbGFncyA9IGZsYWdzOwogIH0KfTsKdmFyIEZTVEZMQUdTX0FUSU0gPSAxIDw8IDA7CnZhciBGU1RGTEFHU19BVElNX05PVyA9IDEgPDwgMTsKdmFyIEZTVEZMQUdTX01USU0gPSAxIDw8IDI7CnZhciBGU1RGTEFHU19NVElNX05PVyA9IDEgPDwgMzsKdmFyIE9GTEFHU19DUkVBVCA9IDEgPDwgMDsKdmFyIE9GTEFHU19ESVJFQ1RPUlkgPSAxIDw8IDE7CnZhciBPRkxBR1NfRVhDTCA9IDEgPDwgMjsKdmFyIE9GTEFHU19UUlVOQyA9IDEgPDwgMzsKdmFyIEZpbGVzdGF0ID0gY2xhc3MgewogIHdyaXRlX2J5dGVzKHZpZXcsIHB0cikgewogICAgdmlldy5zZXRCaWdVaW50NjQocHRyLCB0aGlzLmRldiwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA4LCB0aGlzLmlubywgdHJ1ZSk7CiAgICB2aWV3LnNldFVpbnQ4KHB0ciArIDE2LCB0aGlzLmZpbGV0eXBlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDI0LCB0aGlzLm5saW5rLCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDMyLCB0aGlzLnNpemUsIHRydWUpOwogICAgdmlldy5zZXRCaWdVaW50NjQocHRyICsgMzgsIHRoaXMuYXRpbSwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA0NiwgdGhpcy5tdGltLCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDUyLCB0aGlzLmN0aW0sIHRydWUpOwogIH0KICBjb25zdHJ1Y3RvcihmaWxldHlwZSwgc2l6ZSkgewogICAgdGhpcy5kZXYgPSAwbjsKICAgIHRoaXMuaW5vID0gMG47CiAgICB0aGlzLm5saW5rID0gMG47CiAgICB0aGlzLmF0aW0gPSAwbjsKICAgIHRoaXMubXRpbSA9IDBuOwogICAgdGhpcy5jdGltID0gMG47CiAgICB0aGlzLmZpbGV0eXBlID0gZmlsZXR5cGU7CiAgICB0aGlzLnNpemUgPSBzaXplOwogIH0KfTsKdmFyIEVWRU5UUldGTEFHU19GRF9SRUFEV1JJVEVfSEFOR1VQID0gMSA8PCAwOwp2YXIgU1VCQ0xPQ0tGTEFHU19TVUJTQ1JJUFRJT05fQ0xPQ0tfQUJTVElNRSA9IDEgPDwgMDsKdmFyIFJJRkxBR1NfUkVDVl9QRUVLID0gMSA8PCAwOwp2YXIgUklGTEFHU19SRUNWX1dBSVRBTEwgPSAxIDw8IDE7CnZhciBST0ZMQUdTX1JFQ1ZfREFUQV9UUlVOQ0FURUQgPSAxIDw8IDA7CnZhciBTREZMQUdTX1JEID0gMSA8PCAwOwp2YXIgU0RGTEFHU19XUiA9IDEgPDwgMTsKdmFyIFBSRU9QRU5UWVBFX0RJUiA9IDA7CnZhciBQcmVzdGF0RGlyID0gY2xhc3MgewogIHdyaXRlX2J5dGVzKHZpZXcsIHB0cikgewogICAgdmlldy5zZXRVaW50MzIocHRyLCB0aGlzLnByX25hbWUuYnl0ZUxlbmd0aCwgdHJ1ZSk7CiAgfQogIGNvbnN0cnVjdG9yKG5hbWUpIHsKICAgIHRoaXMucHJfbmFtZSA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShuYW1lKTsKICB9Cn07CnZhciBQcmVzdGF0ID0gY2xhc3MgewogIHN0YXRpYyBkaXIobmFtZSkgewogICAgY29uc3QgcHJlc3RhdCA9IG5ldyBQcmVzdGF0KCk7CiAgICBwcmVzdGF0LnRhZyA9IFBSRU9QRU5UWVBFX0RJUjsKICAgIHByZXN0YXQuaW5uZXIgPSBuZXcgUHJlc3RhdERpcihuYW1lKTsKICAgIHJldHVybiBwcmVzdGF0OwogIH0KICB3cml0ZV9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIHZpZXcuc2V0VWludDMyKHB0ciwgdGhpcy50YWcsIHRydWUpOwogICAgdGhpcy5pbm5lci53cml0ZV9ieXRlcyh2aWV3LCBwdHIgKyA0KTsKICB9Cn07CgovLyBub2RlX21vZHVsZXMvQGJqb3JuMy9icm93c2VyX3dhc2lfc2hpbS9kaXN0L2RlYnVnLmpzCnZhciBEZWJ1ZyA9IGNsYXNzIERlYnVnMiB7CiAgZW5hYmxlKGVuYWJsZWQpIHsKICAgIHRoaXMubG9nID0gY3JlYXRlTG9nZ2VyKGVuYWJsZWQgPT09IHZvaWQgMCA/IHRydWUgOiBlbmFibGVkLCB0aGlzLnByZWZpeCk7CiAgfQogIGdldCBlbmFibGVkKCkgewogICAgcmV0dXJuIHRoaXMuaXNFbmFibGVkOwogIH0KICBjb25zdHJ1Y3Rvcihpc0VuYWJsZWQpIHsKICAgIHRoaXMuaXNFbmFibGVkID0gaXNFbmFibGVkOwogICAgdGhpcy5wcmVmaXggPSAid2FzaToiOwogICAgdGhpcy5lbmFibGUoaXNFbmFibGVkKTsKICB9Cn07CmZ1bmN0aW9uIGNyZWF0ZUxvZ2dlcihlbmFibGVkLCBwcmVmaXgpIHsKICBpZiAoZW5hYmxlZCkgewogICAgY29uc3QgYSA9IGNvbnNvbGUubG9nLmJpbmQoY29uc29sZSwgIiVjJXMiLCAiY29sb3I6ICMyNjVCQTAiLCBwcmVmaXgpOwogICAgcmV0dXJuIGE7CiAgfSBlbHNlIHsKICAgIHJldHVybiAoKSA9PiB7CiAgICB9OwogIH0KfQp2YXIgZGVidWcgPSBuZXcgRGVidWcoZmFsc2UpOwoKLy8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC93YXNpLmpzCnZhciBXQVNJUHJvY0V4aXQgPSBjbGFzcyBleHRlbmRzIEVycm9yIHsKICBjb25zdHJ1Y3Rvcihjb2RlKSB7CiAgICBzdXBlcigiZXhpdCB3aXRoIGV4aXQgY29kZSAiICsgY29kZSk7CiAgICB0aGlzLmNvZGUgPSBjb2RlOwogIH0KfTsKdmFyIFdBU0kgPSBjbGFzcyBXQVNJMiB7CiAgc3RhcnQoaW5zdGFuY2UpIHsKICAgIHRoaXMuaW5zdCA9IGluc3RhbmNlOwogICAgdHJ5IHsKICAgICAgaW5zdGFuY2UuZXhwb3J0cy5fc3RhcnQoKTsKICAgICAgcmV0dXJuIDA7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIGlmIChlIGluc3RhbmNlb2YgV0FTSVByb2NFeGl0KSB7CiAgICAgICAgcmV0dXJuIGUuY29kZTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aHJvdyBlOwogICAgICB9CiAgICB9CiAgfQogIGluaXRpYWxpemUoaW5zdGFuY2UpIHsKICAgIHRoaXMuaW5zdCA9IGluc3RhbmNlOwogICAgaWYgKGluc3RhbmNlLmV4cG9ydHMuX2luaXRpYWxpemUpIHsKICAgICAgaW5zdGFuY2UuZXhwb3J0cy5faW5pdGlhbGl6ZSgpOwogICAgfQogIH0KICBjb25zdHJ1Y3RvcihhcmdzLCBlbnYsIGZkcywgb3B0aW9ucyA9IHt9KSB7CiAgICB0aGlzLmFyZ3MgPSBbXTsKICAgIHRoaXMuZW52ID0gW107CiAgICB0aGlzLmZkcyA9IFtdOwogICAgZGVidWcuZW5hYmxlKG9wdGlvbnMuZGVidWcpOwogICAgdGhpcy5hcmdzID0gYXJnczsKICAgIHRoaXMuZW52ID0gZW52OwogICAgdGhpcy5mZHMgPSBmZHM7CiAgICBjb25zdCBzZWxmID0gdGhpczsKICAgIHRoaXMud2FzaUltcG9ydCA9IHsgYXJnc19zaXplc19nZXQoYXJnYywgYXJndl9idWZfc2l6ZSkgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYXJnYywgc2VsZi5hcmdzLmxlbmd0aCwgdHJ1ZSk7CiAgICAgIGxldCBidWZfc2l6ZSA9IDA7CiAgICAgIGZvciAoY29uc3QgYXJnIG9mIHNlbGYuYXJncykgewogICAgICAgIGJ1Zl9zaXplICs9IGFyZy5sZW5ndGggKyAxOwogICAgICB9CiAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYXJndl9idWZfc2l6ZSwgYnVmX3NpemUsIHRydWUpOwogICAgICBkZWJ1Zy5sb2coYnVmZmVyLmdldFVpbnQzMihhcmdjLCB0cnVlKSwgYnVmZmVyLmdldFVpbnQzMihhcmd2X2J1Zl9zaXplLCB0cnVlKSk7CiAgICAgIHJldHVybiAwOwogICAgfSwgYXJnc19nZXQoYXJndiwgYXJndl9idWYpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IG9yaWdfYXJndl9idWYgPSBhcmd2X2J1ZjsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxmLmFyZ3MubGVuZ3RoOyBpKyspIHsKICAgICAgICBidWZmZXIuc2V0VWludDMyKGFyZ3YsIGFyZ3ZfYnVmLCB0cnVlKTsKICAgICAgICBhcmd2ICs9IDQ7CiAgICAgICAgY29uc3QgYXJnID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHNlbGYuYXJnc1tpXSk7CiAgICAgICAgYnVmZmVyOC5zZXQoYXJnLCBhcmd2X2J1Zik7CiAgICAgICAgYnVmZmVyLnNldFVpbnQ4KGFyZ3ZfYnVmICsgYXJnLmxlbmd0aCwgMCk7CiAgICAgICAgYXJndl9idWYgKz0gYXJnLmxlbmd0aCArIDE7CiAgICAgIH0KICAgICAgaWYgKGRlYnVnLmVuYWJsZWQpIHsKICAgICAgICBkZWJ1Zy5sb2cobmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG9yaWdfYXJndl9idWYsIGFyZ3ZfYnVmKSkpOwogICAgICB9CiAgICAgIHJldHVybiAwOwogICAgfSwgZW52aXJvbl9zaXplc19nZXQoZW52aXJvbl9jb3VudCwgZW52aXJvbl9zaXplKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgYnVmZmVyLnNldFVpbnQzMihlbnZpcm9uX2NvdW50LCBzZWxmLmVudi5sZW5ndGgsIHRydWUpOwogICAgICBsZXQgYnVmX3NpemUgPSAwOwogICAgICBmb3IgKGNvbnN0IGVudmlyb24gb2Ygc2VsZi5lbnYpIHsKICAgICAgICBidWZfc2l6ZSArPSBlbnZpcm9uLmxlbmd0aCArIDE7CiAgICAgIH0KICAgICAgYnVmZmVyLnNldFVpbnQzMihlbnZpcm9uX3NpemUsIGJ1Zl9zaXplLCB0cnVlKTsKICAgICAgZGVidWcubG9nKGJ1ZmZlci5nZXRVaW50MzIoZW52aXJvbl9jb3VudCwgdHJ1ZSksIGJ1ZmZlci5nZXRVaW50MzIoZW52aXJvbl9zaXplLCB0cnVlKSk7CiAgICAgIHJldHVybiAwOwogICAgfSwgZW52aXJvbl9nZXQoZW52aXJvbiwgZW52aXJvbl9idWYpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IG9yaWdfZW52aXJvbl9idWYgPSBlbnZpcm9uX2J1ZjsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxmLmVudi5sZW5ndGg7IGkrKykgewogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIoZW52aXJvbiwgZW52aXJvbl9idWYsIHRydWUpOwogICAgICAgIGVudmlyb24gKz0gNDsKICAgICAgICBjb25zdCBlID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHNlbGYuZW52W2ldKTsKICAgICAgICBidWZmZXI4LnNldChlLCBlbnZpcm9uX2J1Zik7CiAgICAgICAgYnVmZmVyLnNldFVpbnQ4KGVudmlyb25fYnVmICsgZS5sZW5ndGgsIDApOwogICAgICAgIGVudmlyb25fYnVmICs9IGUubGVuZ3RoICsgMTsKICAgICAgfQogICAgICBpZiAoZGVidWcuZW5hYmxlZCkgewogICAgICAgIGRlYnVnLmxvZyhuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2Uob3JpZ19lbnZpcm9uX2J1ZiwgZW52aXJvbl9idWYpKSk7CiAgICAgIH0KICAgICAgcmV0dXJuIDA7CiAgICB9LCBjbG9ja19yZXNfZ2V0KGlkLCByZXNfcHRyKSB7CiAgICAgIGxldCByZXNvbHV0aW9uVmFsdWU7CiAgICAgIHN3aXRjaCAoaWQpIHsKICAgICAgICBjYXNlIENMT0NLSURfTU9OT1RPTklDOiB7CiAgICAgICAgICByZXNvbHV0aW9uVmFsdWUgPSA1MDAwbjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjYXNlIENMT0NLSURfUkVBTFRJTUU6IHsKICAgICAgICAgIHJlc29sdXRpb25WYWx1ZSA9IDEwMDAwMDBuOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICByZXR1cm4gRVJSTk9fTk9TWVM7CiAgICAgIH0KICAgICAgY29uc3QgdmlldyA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgdmlldy5zZXRCaWdVaW50NjQocmVzX3B0ciwgcmVzb2x1dGlvblZhbHVlLCB0cnVlKTsKICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICB9LCBjbG9ja190aW1lX2dldChpZCwgcHJlY2lzaW9uLCB0aW1lKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKGlkID09PSBDTE9DS0lEX1JFQUxUSU1FKSB7CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NCh0aW1lLCBCaWdJbnQobmV3IERhdGUoKS5nZXRUaW1lKCkpICogMTAwMDAwMG4sIHRydWUpOwogICAgICB9IGVsc2UgaWYgKGlkID09IENMT0NLSURfTU9OT1RPTklDKSB7CiAgICAgICAgbGV0IG1vbm90b25pY190aW1lOwogICAgICAgIHRyeSB7CiAgICAgICAgICBtb25vdG9uaWNfdGltZSA9IEJpZ0ludChNYXRoLnJvdW5kKHBlcmZvcm1hbmNlLm5vdygpICogMWU2KSk7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgbW9ub3RvbmljX3RpbWUgPSAwbjsKICAgICAgICB9CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NCh0aW1lLCBtb25vdG9uaWNfdGltZSwgdHJ1ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NCh0aW1lLCAwbiwgdHJ1ZSk7CiAgICAgIH0KICAgICAgcmV0dXJuIDA7CiAgICB9LCBmZF9hZHZpc2UoZmQsIG9mZnNldCwgbGVuLCBhZHZpY2UpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfYWxsb2NhdGUoZmQsIG9mZnNldCwgbGVuKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9hbGxvY2F0ZShvZmZzZXQsIGxlbik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Nsb3NlKGZkKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcmV0ID0gc2VsZi5mZHNbZmRdLmZkX2Nsb3NlKCk7CiAgICAgICAgc2VsZi5mZHNbZmRdID0gdm9pZCAwOwogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2RhdGFzeW5jKGZkKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9zeW5jKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Zkc3RhdF9nZXQoZmQsIGZkc3RhdF9wdHIpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgZmRzdGF0IH0gPSBzZWxmLmZkc1tmZF0uZmRfZmRzdGF0X2dldCgpOwogICAgICAgIGlmIChmZHN0YXQgIT0gbnVsbCkgewogICAgICAgICAgZmRzdGF0LndyaXRlX2J5dGVzKG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKSwgZmRzdGF0X3B0cik7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Zkc3RhdF9zZXRfZmxhZ3MoZmQsIGZsYWdzKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9mZHN0YXRfc2V0X2ZsYWdzKGZsYWdzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfZmRzdGF0X3NldF9yaWdodHMoZmQsIGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZykgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfZmRzdGF0X3NldF9yaWdodHMoZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfZmlsZXN0YXRfZ2V0KGZkLCBmaWxlc3RhdF9wdHIpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgZmlsZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9maWxlc3RhdF9nZXQoKTsKICAgICAgICBpZiAoZmlsZXN0YXQgIT0gbnVsbCkgewogICAgICAgICAgZmlsZXN0YXQud3JpdGVfYnl0ZXMobmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpLCBmaWxlc3RhdF9wdHIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9maWxlc3RhdF9zZXRfc2l6ZShmZCwgc2l6ZSkgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfZmlsZXN0YXRfc2V0X3NpemUoc2l6ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2ZpbGVzdGF0X3NldF90aW1lcyhmZCwgYXRpbSwgbXRpbSwgZnN0X2ZsYWdzKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9maWxlc3RhdF9zZXRfdGltZXMoYXRpbSwgbXRpbSwgZnN0X2ZsYWdzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcHJlYWQoZmQsIGlvdnNfcHRyLCBpb3ZzX2xlbiwgb2Zmc2V0LCBucmVhZF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgaW92ZWNzID0gSW92ZWMucmVhZF9ieXRlc19hcnJheShidWZmZXIsIGlvdnNfcHRyLCBpb3ZzX2xlbik7CiAgICAgICAgbGV0IG5yZWFkID0gMDsKICAgICAgICBmb3IgKGNvbnN0IGlvdmVjIG9mIGlvdmVjcykgewogICAgICAgICAgY29uc3QgeyByZXQsIGRhdGEgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wcmVhZChpb3ZlYy5idWZfbGVuLCBvZmZzZXQpOwogICAgICAgICAgaWYgKHJldCAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobnJlYWRfcHRyLCBucmVhZCwgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgICB9CiAgICAgICAgICBidWZmZXI4LnNldChkYXRhLCBpb3ZlYy5idWYpOwogICAgICAgICAgbnJlYWQgKz0gZGF0YS5sZW5ndGg7CiAgICAgICAgICBvZmZzZXQgKz0gQmlnSW50KGRhdGEubGVuZ3RoKTsKICAgICAgICAgIGlmIChkYXRhLmxlbmd0aCAhPSBpb3ZlYy5idWZfbGVuKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgbnJlYWQsIHRydWUpOwogICAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9wcmVzdGF0X2dldChmZCwgYnVmX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIHByZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wcmVzdGF0X2dldCgpOwogICAgICAgIGlmIChwcmVzdGF0ICE9IG51bGwpIHsKICAgICAgICAgIHByZXN0YXQud3JpdGVfYnl0ZXMoYnVmZmVyLCBidWZfcHRyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcHJlc3RhdF9kaXJfbmFtZShmZCwgcGF0aF9wdHIsIHBhdGhfbGVuKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIHByZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wcmVzdGF0X2dldCgpOwogICAgICAgIGlmIChwcmVzdGF0ID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHByZXN0YXRfZGlyX25hbWUgPSBwcmVzdGF0LmlubmVyLnByX25hbWU7CiAgICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICAgIGJ1ZmZlcjguc2V0KHByZXN0YXRfZGlyX25hbWUuc2xpY2UoMCwgcGF0aF9sZW4pLCBwYXRoX3B0cik7CiAgICAgICAgcmV0dXJuIHByZXN0YXRfZGlyX25hbWUuYnl0ZUxlbmd0aCA+IHBhdGhfbGVuID8gRVJSTk9fTkFNRVRPT0xPTkcgOiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9wd3JpdGUoZmQsIGlvdnNfcHRyLCBpb3ZzX2xlbiwgb2Zmc2V0LCBud3JpdHRlbl9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgaW92ZWNzID0gQ2lvdmVjLnJlYWRfYnl0ZXNfYXJyYXkoYnVmZmVyLCBpb3ZzX3B0ciwgaW92c19sZW4pOwogICAgICAgIGxldCBud3JpdHRlbiA9IDA7CiAgICAgICAgZm9yIChjb25zdCBpb3ZlYyBvZiBpb3ZlY3MpIHsKICAgICAgICAgIGNvbnN0IGRhdGEgPSBidWZmZXI4LnNsaWNlKGlvdmVjLmJ1ZiwgaW92ZWMuYnVmICsgaW92ZWMuYnVmX2xlbik7CiAgICAgICAgICBjb25zdCB7IHJldCwgbndyaXR0ZW46IG53cml0dGVuX3BhcnQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG53cml0dGVuX3B0ciwgbndyaXR0ZW4sIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgbndyaXR0ZW4gKz0gbndyaXR0ZW5fcGFydDsKICAgICAgICAgIG9mZnNldCArPSBCaWdJbnQobndyaXR0ZW5fcGFydCk7CiAgICAgICAgICBpZiAobndyaXR0ZW5fcGFydCAhPSBkYXRhLmJ5dGVMZW5ndGgpIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobndyaXR0ZW5fcHRyLCBud3JpdHRlbiwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3JlYWQoZmQsIGlvdnNfcHRyLCBpb3ZzX2xlbiwgbnJlYWRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IGlvdmVjcyA9IElvdmVjLnJlYWRfYnl0ZXNfYXJyYXkoYnVmZmVyLCBpb3ZzX3B0ciwgaW92c19sZW4pOwogICAgICAgIGxldCBucmVhZCA9IDA7CiAgICAgICAgZm9yIChjb25zdCBpb3ZlYyBvZiBpb3ZlY3MpIHsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBkYXRhIH0gPSBzZWxmLmZkc1tmZF0uZmRfcmVhZChpb3ZlYy5idWZfbGVuKTsKICAgICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgbnJlYWQsIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgYnVmZmVyOC5zZXQoZGF0YSwgaW92ZWMuYnVmKTsKICAgICAgICAgIG5yZWFkICs9IGRhdGEubGVuZ3RoOwogICAgICAgICAgaWYgKGRhdGEubGVuZ3RoICE9IGlvdmVjLmJ1Zl9sZW4pIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobnJlYWRfcHRyLCBucmVhZCwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3JlYWRkaXIoZmQsIGJ1ZiwgYnVmX2xlbiwgY29va2llLCBidWZ1c2VkX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBsZXQgYnVmdXNlZCA9IDA7CiAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBkaXJlbnQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9yZWFkZGlyX3NpbmdsZShjb29raWUpOwogICAgICAgICAgaWYgKHJldCAhPSAwKSB7CiAgICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYnVmdXNlZF9wdHIsIGJ1ZnVzZWQsIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgaWYgKGRpcmVudCA9PSBudWxsKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGJ1Zl9sZW4gLSBidWZ1c2VkIDwgZGlyZW50LmhlYWRfbGVuZ3RoKCkpIHsKICAgICAgICAgICAgYnVmdXNlZCA9IGJ1Zl9sZW47CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgaGVhZF9ieXRlcyA9IG5ldyBBcnJheUJ1ZmZlcihkaXJlbnQuaGVhZF9sZW5ndGgoKSk7CiAgICAgICAgICBkaXJlbnQud3JpdGVfaGVhZF9ieXRlcyhuZXcgRGF0YVZpZXcoaGVhZF9ieXRlcyksIDApOwogICAgICAgICAgYnVmZmVyOC5zZXQobmV3IFVpbnQ4QXJyYXkoaGVhZF9ieXRlcykuc2xpY2UoMCwgTWF0aC5taW4oaGVhZF9ieXRlcy5ieXRlTGVuZ3RoLCBidWZfbGVuIC0gYnVmdXNlZCkpLCBidWYpOwogICAgICAgICAgYnVmICs9IGRpcmVudC5oZWFkX2xlbmd0aCgpOwogICAgICAgICAgYnVmdXNlZCArPSBkaXJlbnQuaGVhZF9sZW5ndGgoKTsKICAgICAgICAgIGlmIChidWZfbGVuIC0gYnVmdXNlZCA8IGRpcmVudC5uYW1lX2xlbmd0aCgpKSB7CiAgICAgICAgICAgIGJ1ZnVzZWQgPSBidWZfbGVuOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGRpcmVudC53cml0ZV9uYW1lX2J5dGVzKGJ1ZmZlcjgsIGJ1ZiwgYnVmX2xlbiAtIGJ1ZnVzZWQpOwogICAgICAgICAgYnVmICs9IGRpcmVudC5uYW1lX2xlbmd0aCgpOwogICAgICAgICAgYnVmdXNlZCArPSBkaXJlbnQubmFtZV9sZW5ndGgoKTsKICAgICAgICAgIGNvb2tpZSA9IGRpcmVudC5kX25leHQ7CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYnVmdXNlZF9wdHIsIGJ1ZnVzZWQsIHRydWUpOwogICAgICAgIHJldHVybiAwOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9yZW51bWJlcihmZCwgdG8pIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDAgJiYgc2VsZi5mZHNbdG9dICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHJldCA9IHNlbGYuZmRzW3RvXS5mZF9jbG9zZSgpOwogICAgICAgIGlmIChyZXQgIT0gMCkgewogICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICB9CiAgICAgICAgc2VsZi5mZHNbdG9dID0gc2VsZi5mZHNbZmRdOwogICAgICAgIHNlbGYuZmRzW2ZkXSA9IHZvaWQgMDsKICAgICAgICByZXR1cm4gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfc2VlayhmZCwgb2Zmc2V0LCB3aGVuY2UsIG9mZnNldF9vdXRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgb2Zmc2V0OiBvZmZzZXRfb3V0IH0gPSBzZWxmLmZkc1tmZF0uZmRfc2VlayhvZmZzZXQsIHdoZW5jZSk7CiAgICAgICAgYnVmZmVyLnNldEJpZ0ludDY0KG9mZnNldF9vdXRfcHRyLCBvZmZzZXRfb3V0LCB0cnVlKTsKICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9zeW5jKGZkKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9zeW5jKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3RlbGwoZmQsIG9mZnNldF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHsgcmV0LCBvZmZzZXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF90ZWxsKCk7CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NChvZmZzZXRfcHRyLCBvZmZzZXQsIHRydWUpOwogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3dyaXRlKGZkLCBpb3ZzX3B0ciwgaW92c19sZW4sIG53cml0dGVuX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBpb3ZlY3MgPSBDaW92ZWMucmVhZF9ieXRlc19hcnJheShidWZmZXIsIGlvdnNfcHRyLCBpb3ZzX2xlbik7CiAgICAgICAgbGV0IG53cml0dGVuID0gMDsKICAgICAgICBmb3IgKGNvbnN0IGlvdmVjIG9mIGlvdmVjcykgewogICAgICAgICAgY29uc3QgZGF0YSA9IGJ1ZmZlcjguc2xpY2UoaW92ZWMuYnVmLCBpb3ZlYy5idWYgKyBpb3ZlYy5idWZfbGVuKTsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBud3JpdHRlbjogbndyaXR0ZW5fcGFydCB9ID0gc2VsZi5mZHNbZmRdLmZkX3dyaXRlKGRhdGEpOwogICAgICAgICAgaWYgKHJldCAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobndyaXR0ZW5fcHRyLCBud3JpdHRlbiwgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgICB9CiAgICAgICAgICBud3JpdHRlbiArPSBud3JpdHRlbl9wYXJ0OwogICAgICAgICAgaWYgKG53cml0dGVuX3BhcnQgIT0gZGF0YS5ieXRlTGVuZ3RoKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKG53cml0dGVuX3B0ciwgbndyaXR0ZW4sIHRydWUpOwogICAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX2NyZWF0ZV9kaXJlY3RvcnkoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0ucGF0aF9jcmVhdGVfZGlyZWN0b3J5KHBhdGgpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX2ZpbGVzdGF0X2dldChmZCwgZmxhZ3MsIHBhdGhfcHRyLCBwYXRoX2xlbiwgZmlsZXN0YXRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICBjb25zdCB7IHJldCwgZmlsZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5wYXRoX2ZpbGVzdGF0X2dldChmbGFncywgcGF0aCk7CiAgICAgICAgaWYgKGZpbGVzdGF0ICE9IG51bGwpIHsKICAgICAgICAgIGZpbGVzdGF0LndyaXRlX2J5dGVzKGJ1ZmZlciwgZmlsZXN0YXRfcHRyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9maWxlc3RhdF9zZXRfdGltZXMoZmQsIGZsYWdzLCBwYXRoX3B0ciwgcGF0aF9sZW4sIGF0aW0sIG10aW0sIGZzdF9mbGFncykgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0ucGF0aF9maWxlc3RhdF9zZXRfdGltZXMoZmxhZ3MsIHBhdGgsIGF0aW0sIG10aW0sIGZzdF9mbGFncyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfbGluayhvbGRfZmQsIG9sZF9mbGFncywgb2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9sZW4sIG5ld19mZCwgbmV3X3BhdGhfcHRyLCBuZXdfcGF0aF9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbb2xkX2ZkXSAhPSB2b2lkIDAgJiYgc2VsZi5mZHNbbmV3X2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBvbGRfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX3B0ciArIG9sZF9wYXRoX2xlbikpOwogICAgICAgIGNvbnN0IG5ld19wYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfcHRyICsgbmV3X3BhdGhfbGVuKSk7CiAgICAgICAgY29uc3QgeyByZXQsIGlub2RlX29iaiB9ID0gc2VsZi5mZHNbb2xkX2ZkXS5wYXRoX2xvb2t1cChvbGRfcGF0aCwgb2xkX2ZsYWdzKTsKICAgICAgICBpZiAoaW5vZGVfb2JqID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzZWxmLmZkc1tuZXdfZmRdLnBhdGhfbGluayhuZXdfcGF0aCwgaW5vZGVfb2JqLCBmYWxzZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfb3BlbihmZCwgZGlyZmxhZ3MsIHBhdGhfcHRyLCBwYXRoX2xlbiwgb2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcsIGZkX2ZsYWdzLCBvcGVuZWRfZmRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICBkZWJ1Zy5sb2cocGF0aCk7CiAgICAgICAgY29uc3QgeyByZXQsIGZkX29iaiB9ID0gc2VsZi5mZHNbZmRdLnBhdGhfb3BlbihkaXJmbGFncywgcGF0aCwgb2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcsIGZkX2ZsYWdzKTsKICAgICAgICBpZiAocmV0ICE9IDApIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIHNlbGYuZmRzLnB1c2goZmRfb2JqKTsKICAgICAgICBjb25zdCBvcGVuZWRfZmQgPSBzZWxmLmZkcy5sZW5ndGggLSAxOwogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIob3BlbmVkX2ZkX3B0ciwgb3BlbmVkX2ZkLCB0cnVlKTsKICAgICAgICByZXR1cm4gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9yZWFkbGluayhmZCwgcGF0aF9wdHIsIHBhdGhfbGVuLCBidWZfcHRyLCBidWZfbGVuLCBucmVhZF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIGRlYnVnLmxvZyhwYXRoKTsKICAgICAgICBjb25zdCB7IHJldCwgZGF0YSB9ID0gc2VsZi5mZHNbZmRdLnBhdGhfcmVhZGxpbmsocGF0aCk7CiAgICAgICAgaWYgKGRhdGEgIT0gbnVsbCkgewogICAgICAgICAgY29uc3QgZGF0YV9idWYgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoZGF0YSk7CiAgICAgICAgICBpZiAoZGF0YV9idWYubGVuZ3RoID4gYnVmX2xlbikgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgMCwgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICAgICAgfQogICAgICAgICAgYnVmZmVyOC5zZXQoZGF0YV9idWYsIGJ1Zl9wdHIpOwogICAgICAgICAgYnVmZmVyLnNldFVpbnQzMihucmVhZF9wdHIsIGRhdGFfYnVmLmxlbmd0aCwgdHJ1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfcmVtb3ZlX2RpcmVjdG9yeShmZCwgcGF0aF9wdHIsIHBhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBwYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5wYXRoX3JlbW92ZV9kaXJlY3RvcnkocGF0aCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfcmVuYW1lKGZkLCBvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX2xlbiwgbmV3X2ZkLCBuZXdfcGF0aF9wdHIsIG5ld19wYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwICYmIHNlbGYuZmRzW25ld19mZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3Qgb2xkX3BhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2Uob2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9wdHIgKyBvbGRfcGF0aF9sZW4pKTsKICAgICAgICBjb25zdCBuZXdfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShuZXdfcGF0aF9wdHIsIG5ld19wYXRoX3B0ciArIG5ld19wYXRoX2xlbikpOwogICAgICAgIGxldCB7IHJldCwgaW5vZGVfb2JqIH0gPSBzZWxmLmZkc1tmZF0ucGF0aF91bmxpbmsob2xkX3BhdGgpOwogICAgICAgIGlmIChpbm9kZV9vYmogPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICB9CiAgICAgICAgcmV0ID0gc2VsZi5mZHNbbmV3X2ZkXS5wYXRoX2xpbmsobmV3X3BhdGgsIGlub2RlX29iaiwgdHJ1ZSk7CiAgICAgICAgaWYgKHJldCAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICBpZiAoc2VsZi5mZHNbZmRdLnBhdGhfbGluayhvbGRfcGF0aCwgaW5vZGVfb2JqLCB0cnVlKSAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICAgIHRocm93ICJwYXRoX2xpbmsgc2hvdWxkIGFsd2F5cyByZXR1cm4gc3VjY2VzcyB3aGVuIHJlbGlua2luZyBhbiBpbm9kZSBiYWNrIHRvIHRoZSBvcmlnaW5hbCBwbGFjZSI7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfc3ltbGluayhvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX2xlbiwgZmQsIG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBvbGRfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX3B0ciArIG9sZF9wYXRoX2xlbikpOwogICAgICAgIGNvbnN0IG5ld19wYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfcHRyICsgbmV3X3BhdGhfbGVuKSk7CiAgICAgICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF91bmxpbmtfZmlsZShmZCwgcGF0aF9wdHIsIHBhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBwYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5wYXRoX3VubGlua19maWxlKHBhdGgpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwb2xsX29uZW9mZihpbl8sIG91dCwgbnN1YnNjcmlwdGlvbnMpIHsKICAgICAgdGhyb3cgImFzeW5jIGlvIG5vdCBzdXBwb3J0ZWQiOwogICAgfSwgcHJvY19leGl0KGV4aXRfY29kZSkgewogICAgICB0aHJvdyBuZXcgV0FTSVByb2NFeGl0KGV4aXRfY29kZSk7CiAgICB9LCBwcm9jX3JhaXNlKHNpZykgewogICAgICB0aHJvdyAicmFpc2VkIHNpZ25hbCAiICsgc2lnOwogICAgfSwgc2NoZWRfeWllbGQoKSB7CiAgICB9LCByYW5kb21fZ2V0KGJ1ZiwgYnVmX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnVmX2xlbjsgaSsrKSB7CiAgICAgICAgYnVmZmVyOFtidWYgKyBpXSA9IE1hdGgucmFuZG9tKCkgKiAyNTYgfCAwOwogICAgICB9CiAgICB9LCBzb2NrX3JlY3YoZmQsIHJpX2RhdGEsIHJpX2ZsYWdzKSB7CiAgICAgIHRocm93ICJzb2NrZXRzIG5vdCBzdXBwb3J0ZWQiOwogICAgfSwgc29ja19zZW5kKGZkLCBzaV9kYXRhLCBzaV9mbGFncykgewogICAgICB0aHJvdyAic29ja2V0cyBub3Qgc3VwcG9ydGVkIjsKICAgIH0sIHNvY2tfc2h1dGRvd24oZmQsIGhvdykgewogICAgICB0aHJvdyAic29ja2V0cyBub3Qgc3VwcG9ydGVkIjsKICAgIH0sIHNvY2tfYWNjZXB0KGZkLCBmbGFncykgewogICAgICB0aHJvdyAic29ja2V0cyBub3Qgc3VwcG9ydGVkIjsKICAgIH0gfTsKICB9Cn07CgovLyBub2RlX21vZHVsZXMvQGJqb3JuMy9icm93c2VyX3dhc2lfc2hpbS9kaXN0L2ZkLmpzCnZhciBGZCA9IGNsYXNzIHsKICBmZF9hbGxvY2F0ZShvZmZzZXQsIGxlbikgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfY2xvc2UoKSB7CiAgICByZXR1cm4gMDsKICB9CiAgZmRfZmRzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBmZHN0YXQ6IG51bGwgfTsKICB9CiAgZmRfZmRzdGF0X3NldF9mbGFncyhmbGFncykgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfZmRzdGF0X3NldF9yaWdodHMoZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nKSB7CiAgICByZXR1cm4gRVJSTk9fTk9UU1VQOwogIH0KICBmZF9maWxlc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZmlsZXN0YXQ6IG51bGwgfTsKICB9CiAgZmRfZmlsZXN0YXRfc2V0X3NpemUoc2l6ZSkgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfZmlsZXN0YXRfc2V0X3RpbWVzKGF0aW0sIG10aW0sIGZzdF9mbGFncykgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfcHJlYWQoc2l6ZSwgb2Zmc2V0KSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZGF0YTogbmV3IFVpbnQ4QXJyYXkoKSB9OwogIH0KICBmZF9wcmVzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBwcmVzdGF0OiBudWxsIH07CiAgfQogIGZkX3B3cml0ZShkYXRhLCBvZmZzZXQpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBud3JpdHRlbjogMCB9OwogIH0KICBmZF9yZWFkKHNpemUpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBkYXRhOiBuZXcgVWludDhBcnJheSgpIH07CiAgfQogIGZkX3JlYWRkaXJfc2luZ2xlKGNvb2tpZSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGRpcmVudDogbnVsbCB9OwogIH0KICBmZF9zZWVrKG9mZnNldCwgd2hlbmNlKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgb2Zmc2V0OiAwbiB9OwogIH0KICBmZF9zeW5jKCkgewogICAgcmV0dXJuIDA7CiAgfQogIGZkX3RlbGwoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgb2Zmc2V0OiAwbiB9OwogIH0KICBmZF93cml0ZShkYXRhKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgbndyaXR0ZW46IDAgfTsKICB9CiAgcGF0aF9jcmVhdGVfZGlyZWN0b3J5KHBhdGgpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfZmlsZXN0YXRfZ2V0KGZsYWdzLCBwYXRoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZmlsZXN0YXQ6IG51bGwgfTsKICB9CiAgcGF0aF9maWxlc3RhdF9zZXRfdGltZXMoZmxhZ3MsIHBhdGgsIGF0aW0sIG10aW0sIGZzdF9mbGFncykgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgcGF0aF9saW5rKHBhdGgsIGlub2RlLCBhbGxvd19kaXIpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfdW5saW5rKHBhdGgpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBpbm9kZV9vYmo6IG51bGwgfTsKICB9CiAgcGF0aF9sb29rdXAocGF0aCwgZGlyZmxhZ3MpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBpbm9kZV9vYmo6IG51bGwgfTsKICB9CiAgcGF0aF9vcGVuKGRpcmZsYWdzLCBwYXRoLCBvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZywgZmRfZmxhZ3MpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9URElSLCBmZF9vYmo6IG51bGwgfTsKICB9CiAgcGF0aF9yZWFkbGluayhwYXRoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZGF0YTogbnVsbCB9OwogIH0KICBwYXRoX3JlbW92ZV9kaXJlY3RvcnkocGF0aCkgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgcGF0aF9yZW5hbWUob2xkX3BhdGgsIG5ld19mZCwgbmV3X3BhdGgpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfdW5saW5rX2ZpbGUocGF0aCkgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9Cn07CnZhciBJbm9kZSA9IGNsYXNzIHsKfTsKCi8vIG5vZGVfbW9kdWxlcy9AYmpvcm4zL2Jyb3dzZXJfd2FzaV9zaGltL2Rpc3QvZnNfbWVtLmpzCnZhciBPcGVuRmlsZSA9IGNsYXNzIGV4dGVuZHMgRmQgewogIGZkX2FsbG9jYXRlKG9mZnNldCwgbGVuKSB7CiAgICBpZiAodGhpcy5maWxlLnNpemUgPiBvZmZzZXQgKyBsZW4pIHsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IG5ld19kYXRhID0gbmV3IFVpbnQ4QXJyYXkoTnVtYmVyKG9mZnNldCArIGxlbikpOwogICAgICBuZXdfZGF0YS5zZXQodGhpcy5maWxlLmRhdGEsIDApOwogICAgICB0aGlzLmZpbGUuZGF0YSA9IG5ld19kYXRhOwogICAgfQogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIGZkX2Zkc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIGZkc3RhdDogbmV3IEZkc3RhdChGSUxFVFlQRV9SRUdVTEFSX0ZJTEUsIDApIH07CiAgfQogIGZkX2ZpbGVzdGF0X3NldF9zaXplKHNpemUpIHsKICAgIGlmICh0aGlzLmZpbGUuc2l6ZSA+IHNpemUpIHsKICAgICAgdGhpcy5maWxlLmRhdGEgPSBuZXcgVWludDhBcnJheSh0aGlzLmZpbGUuZGF0YS5idWZmZXIuc2xpY2UoMCwgTnVtYmVyKHNpemUpKSk7CiAgICB9IGVsc2UgewogICAgICBjb25zdCBuZXdfZGF0YSA9IG5ldyBVaW50OEFycmF5KE51bWJlcihzaXplKSk7CiAgICAgIG5ld19kYXRhLnNldCh0aGlzLmZpbGUuZGF0YSwgMCk7CiAgICAgIHRoaXMuZmlsZS5kYXRhID0gbmV3X2RhdGE7CiAgICB9CiAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICB9CiAgZmRfcmVhZChzaXplKSB7CiAgICBjb25zdCBzbGljZSA9IHRoaXMuZmlsZS5kYXRhLnNsaWNlKE51bWJlcih0aGlzLmZpbGVfcG9zKSwgTnVtYmVyKHRoaXMuZmlsZV9wb3MgKyBCaWdJbnQoc2l6ZSkpKTsKICAgIHRoaXMuZmlsZV9wb3MgKz0gQmlnSW50KHNsaWNlLmxlbmd0aCk7CiAgICByZXR1cm4geyByZXQ6IDAsIGRhdGE6IHNsaWNlIH07CiAgfQogIGZkX3ByZWFkKHNpemUsIG9mZnNldCkgewogICAgY29uc3Qgc2xpY2UgPSB0aGlzLmZpbGUuZGF0YS5zbGljZShOdW1iZXIob2Zmc2V0KSwgTnVtYmVyKG9mZnNldCArIEJpZ0ludChzaXplKSkpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBkYXRhOiBzbGljZSB9OwogIH0KICBmZF9zZWVrKG9mZnNldCwgd2hlbmNlKSB7CiAgICBsZXQgY2FsY3VsYXRlZF9vZmZzZXQ7CiAgICBzd2l0Y2ggKHdoZW5jZSkgewogICAgICBjYXNlIFdIRU5DRV9TRVQ6CiAgICAgICAgY2FsY3VsYXRlZF9vZmZzZXQgPSBvZmZzZXQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgV0hFTkNFX0NVUjoKICAgICAgICBjYWxjdWxhdGVkX29mZnNldCA9IHRoaXMuZmlsZV9wb3MgKyBvZmZzZXQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgV0hFTkNFX0VORDoKICAgICAgICBjYWxjdWxhdGVkX29mZnNldCA9IEJpZ0ludCh0aGlzLmZpbGUuZGF0YS5ieXRlTGVuZ3RoKSArIG9mZnNldDsKICAgICAgICBicmVhazsKICAgICAgZGVmYXVsdDoKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0lOVkFMLCBvZmZzZXQ6IDBuIH07CiAgICB9CiAgICBpZiAoY2FsY3VsYXRlZF9vZmZzZXQgPCAwKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fSU5WQUwsIG9mZnNldDogMG4gfTsKICAgIH0KICAgIHRoaXMuZmlsZV9wb3MgPSBjYWxjdWxhdGVkX29mZnNldDsKICAgIHJldHVybiB7IHJldDogMCwgb2Zmc2V0OiB0aGlzLmZpbGVfcG9zIH07CiAgfQogIGZkX3RlbGwoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIG9mZnNldDogdGhpcy5maWxlX3BvcyB9OwogIH0KICBmZF93cml0ZShkYXRhKSB7CiAgICBpZiAodGhpcy5maWxlLnJlYWRvbmx5KQogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG53cml0dGVuOiAwIH07CiAgICBpZiAodGhpcy5maWxlX3BvcyArIEJpZ0ludChkYXRhLmJ5dGVMZW5ndGgpID4gdGhpcy5maWxlLnNpemUpIHsKICAgICAgY29uc3Qgb2xkID0gdGhpcy5maWxlLmRhdGE7CiAgICAgIHRoaXMuZmlsZS5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoTnVtYmVyKHRoaXMuZmlsZV9wb3MgKyBCaWdJbnQoZGF0YS5ieXRlTGVuZ3RoKSkpOwogICAgICB0aGlzLmZpbGUuZGF0YS5zZXQob2xkKTsKICAgIH0KICAgIHRoaXMuZmlsZS5kYXRhLnNldChkYXRhLCBOdW1iZXIodGhpcy5maWxlX3BvcykpOwogICAgdGhpcy5maWxlX3BvcyArPSBCaWdJbnQoZGF0YS5ieXRlTGVuZ3RoKTsKICAgIHJldHVybiB7IHJldDogMCwgbndyaXR0ZW46IGRhdGEuYnl0ZUxlbmd0aCB9OwogIH0KICBmZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KSB7CiAgICBpZiAodGhpcy5maWxlLnJlYWRvbmx5KQogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG53cml0dGVuOiAwIH07CiAgICBpZiAob2Zmc2V0ICsgQmlnSW50KGRhdGEuYnl0ZUxlbmd0aCkgPiB0aGlzLmZpbGUuc2l6ZSkgewogICAgICBjb25zdCBvbGQgPSB0aGlzLmZpbGUuZGF0YTsKICAgICAgdGhpcy5maWxlLmRhdGEgPSBuZXcgVWludDhBcnJheShOdW1iZXIob2Zmc2V0ICsgQmlnSW50KGRhdGEuYnl0ZUxlbmd0aCkpKTsKICAgICAgdGhpcy5maWxlLmRhdGEuc2V0KG9sZCk7CiAgICB9CiAgICB0aGlzLmZpbGUuZGF0YS5zZXQoZGF0YSwgTnVtYmVyKG9mZnNldCkpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBud3JpdHRlbjogZGF0YS5ieXRlTGVuZ3RoIH07CiAgfQogIGZkX2ZpbGVzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgZmlsZXN0YXQ6IHRoaXMuZmlsZS5zdGF0KCkgfTsKICB9CiAgY29uc3RydWN0b3IoZmlsZSkgewogICAgc3VwZXIoKTsKICAgIHRoaXMuZmlsZV9wb3MgPSAwbjsKICAgIHRoaXMuZmlsZSA9IGZpbGU7CiAgfQp9Owp2YXIgT3BlbkRpcmVjdG9yeSA9IGNsYXNzIGV4dGVuZHMgRmQgewogIGZkX3NlZWsob2Zmc2V0LCB3aGVuY2UpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fQkFERiwgb2Zmc2V0OiAwbiB9OwogIH0KICBmZF90ZWxsKCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBvZmZzZXQ6IDBuIH07CiAgfQogIGZkX2FsbG9jYXRlKG9mZnNldCwgbGVuKSB7CiAgICByZXR1cm4gRVJSTk9fQkFERjsKICB9CiAgZmRfZmRzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgZmRzdGF0OiBuZXcgRmRzdGF0KEZJTEVUWVBFX0RJUkVDVE9SWSwgMCkgfTsKICB9CiAgZmRfcmVhZGRpcl9zaW5nbGUoY29va2llKSB7CiAgICBpZiAoZGVidWcuZW5hYmxlZCkgewogICAgICBkZWJ1Zy5sb2coInJlYWRkaXJfc2luZ2xlIiwgY29va2llKTsKICAgICAgZGVidWcubG9nKGNvb2tpZSwgdGhpcy5kaXIuY29udGVudHMua2V5cygpKTsKICAgIH0KICAgIGlmIChjb29raWUgPT0gMG4pIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBkaXJlbnQ6IG5ldyBEaXJlbnQoMW4sICIuIiwgRklMRVRZUEVfRElSRUNUT1JZKSB9OwogICAgfSBlbHNlIGlmIChjb29raWUgPT0gMW4pIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBkaXJlbnQ6IG5ldyBEaXJlbnQoMm4sICIuLiIsIEZJTEVUWVBFX0RJUkVDVE9SWSkgfTsKICAgIH0KICAgIGlmIChjb29raWUgPj0gQmlnSW50KHRoaXMuZGlyLmNvbnRlbnRzLnNpemUpICsgMm4pIHsKICAgICAgcmV0dXJuIHsgcmV0OiAwLCBkaXJlbnQ6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IFtuYW1lLCBlbnRyeV0gPSBBcnJheS5mcm9tKHRoaXMuZGlyLmNvbnRlbnRzLmVudHJpZXMoKSlbTnVtYmVyKGNvb2tpZSAtIDJuKV07CiAgICByZXR1cm4geyByZXQ6IDAsIGRpcmVudDogbmV3IERpcmVudChjb29raWUgKyAxbiwgbmFtZSwgZW50cnkuc3RhdCgpLmZpbGV0eXBlKSB9OwogIH0KICBwYXRoX2ZpbGVzdGF0X2dldChmbGFncywgcGF0aF9zdHIpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX2VyciwgcGF0aCB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXRoX2VyciwgZmlsZXN0YXQ6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0LCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgpOwogICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0LCBmaWxlc3RhdDogbnVsbCB9OwogICAgfQogICAgcmV0dXJuIHsgcmV0OiAwLCBmaWxlc3RhdDogZW50cnkuc3RhdCgpIH07CiAgfQogIHBhdGhfbG9va3VwKHBhdGhfc3RyLCBkaXJmbGFncykgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhdGhfcmV0LCBpbm9kZV9vYmo6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0LCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgpOwogICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0LCBpbm9kZV9vYmo6IG51bGwgfTsKICAgIH0KICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgaW5vZGVfb2JqOiBlbnRyeSB9OwogIH0KICBwYXRoX29wZW4oZGlyZmxhZ3MsIHBhdGhfc3RyLCBvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZywgZmRfZmxhZ3MpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX3JldCwgcGF0aCB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXRoX3JldCwgZmRfb2JqOiBudWxsIH07CiAgICB9CiAgICBsZXQgeyByZXQsIGVudHJ5IH0gPSB0aGlzLmRpci5nZXRfZW50cnlfZm9yX3BhdGgocGF0aCk7CiAgICBpZiAoZW50cnkgPT0gbnVsbCkgewogICAgICBpZiAocmV0ICE9IEVSUk5PX05PRU5UKSB7CiAgICAgICAgcmV0dXJuIHsgcmV0LCBmZF9vYmo6IG51bGwgfTsKICAgICAgfQogICAgICBpZiAoKG9mbGFncyAmIE9GTEFHU19DUkVBVCkgPT0gT0ZMQUdTX0NSRUFUKSB7CiAgICAgICAgY29uc3QgeyByZXQ6IHJldDIsIGVudHJ5OiBuZXdfZW50cnkgfSA9IHRoaXMuZGlyLmNyZWF0ZV9lbnRyeV9mb3JfcGF0aChwYXRoX3N0ciwgKG9mbGFncyAmIE9GTEFHU19ESVJFQ1RPUlkpID09IE9GTEFHU19ESVJFQ1RPUlkpOwogICAgICAgIGlmIChuZXdfZW50cnkgPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHsgcmV0OiByZXQyLCBmZF9vYmo6IG51bGwgfTsKICAgICAgICB9CiAgICAgICAgZW50cnkgPSBuZXdfZW50cnk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT0VOVCwgZmRfb2JqOiBudWxsIH07CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoKG9mbGFncyAmIE9GTEFHU19FWENMKSA9PSBPRkxBR1NfRVhDTCkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0VYSVNULCBmZF9vYmo6IG51bGwgfTsKICAgIH0KICAgIGlmICgob2ZsYWdzICYgT0ZMQUdTX0RJUkVDVE9SWSkgPT0gT0ZMQUdTX0RJUkVDVE9SWSAmJiBlbnRyeS5zdGF0KCkuZmlsZXR5cGUgIT09IEZJTEVUWVBFX0RJUkVDVE9SWSkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgZmRfb2JqOiBudWxsIH07CiAgICB9CiAgICByZXR1cm4gZW50cnkucGF0aF9vcGVuKG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZkX2ZsYWdzKTsKICB9CiAgcGF0aF9jcmVhdGVfZGlyZWN0b3J5KHBhdGgpIHsKICAgIHJldHVybiB0aGlzLnBhdGhfb3BlbigwLCBwYXRoLCBPRkxBR1NfQ1JFQVQgfCBPRkxBR1NfRElSRUNUT1JZLCAwbiwgMG4sIDApLnJldDsKICB9CiAgcGF0aF9saW5rKHBhdGhfc3RyLCBpbm9kZSwgYWxsb3dfZGlyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXRoX3JldDsKICAgIH0KICAgIGlmIChwYXRoLmlzX2RpcikgewogICAgICByZXR1cm4gRVJSTk9fTk9FTlQ7CiAgICB9CiAgICBjb25zdCB7IHJldDogcGFyZW50X3JldCwgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9wYXJlbnRfZGlyX2FuZF9lbnRyeV9mb3JfcGF0aChwYXRoLCB0cnVlKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCB8fCBmaWxlbmFtZSA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXJlbnRfcmV0OwogICAgfQogICAgaWYgKGVudHJ5ICE9IG51bGwpIHsKICAgICAgY29uc3Qgc291cmNlX2lzX2RpciA9IGlub2RlLnN0YXQoKS5maWxldHlwZSA9PSBGSUxFVFlQRV9ESVJFQ1RPUlk7CiAgICAgIGNvbnN0IHRhcmdldF9pc19kaXIgPSBlbnRyeS5zdGF0KCkuZmlsZXR5cGUgPT0gRklMRVRZUEVfRElSRUNUT1JZOwogICAgICBpZiAoc291cmNlX2lzX2RpciAmJiB0YXJnZXRfaXNfZGlyKSB7CiAgICAgICAgaWYgKGFsbG93X2RpciAmJiBlbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkgewogICAgICAgICAgaWYgKGVudHJ5LmNvbnRlbnRzLnNpemUgPT0gMCkgewogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIEVSUk5PX05PVEVNUFRZOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gRVJSTk9fRVhJU1Q7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKHNvdXJjZV9pc19kaXIgJiYgIXRhcmdldF9pc19kaXIpIHsKICAgICAgICByZXR1cm4gRVJSTk9fTk9URElSOwogICAgICB9IGVsc2UgaWYgKCFzb3VyY2VfaXNfZGlyICYmIHRhcmdldF9pc19kaXIpIHsKICAgICAgICByZXR1cm4gRVJSTk9fSVNESVI7CiAgICAgIH0gZWxzZSBpZiAoaW5vZGUuc3RhdCgpLmZpbGV0eXBlID09IEZJTEVUWVBFX1JFR1VMQVJfRklMRSAmJiBlbnRyeS5zdGF0KCkuZmlsZXR5cGUgPT0gRklMRVRZUEVfUkVHVUxBUl9GSUxFKSB7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0VYSVNUOwogICAgICB9CiAgICB9CiAgICBpZiAoIWFsbG93X2RpciAmJiBpbm9kZS5zdGF0KCkuZmlsZXR5cGUgPT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgIHJldHVybiBFUlJOT19QRVJNOwogICAgfQogICAgcGFyZW50X2VudHJ5LmNvbnRlbnRzLnNldChmaWxlbmFtZSwgaW5vZGUpOwogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIHBhdGhfdW5saW5rKHBhdGhfc3RyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogcGF0aF9yZXQsIGlub2RlX29iajogbnVsbCB9OwogICAgfQogICAgY29uc3QgeyByZXQ6IHBhcmVudF9yZXQsIHBhcmVudF9lbnRyeSwgZmlsZW5hbWUsIGVudHJ5IH0gPSB0aGlzLmRpci5nZXRfcGFyZW50X2Rpcl9hbmRfZW50cnlfZm9yX3BhdGgocGF0aCwgdHJ1ZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhcmVudF9yZXQsIGlub2RlX29iajogbnVsbCB9OwogICAgfQogICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT0VOVCwgaW5vZGVfb2JqOiBudWxsIH07CiAgICB9CiAgICBwYXJlbnRfZW50cnkuY29udGVudHMuZGVsZXRlKGZpbGVuYW1lKTsKICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgaW5vZGVfb2JqOiBlbnRyeSB9OwogIH0KICBwYXRoX3VubGlua19maWxlKHBhdGhfc3RyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXRoX3JldDsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBwYXJlbnRfcmV0LCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIGZhbHNlKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCB8fCBmaWxlbmFtZSA9PSBudWxsIHx8IGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHBhcmVudF9yZXQ7CiAgICB9CiAgICBpZiAoZW50cnkuc3RhdCgpLmZpbGV0eXBlID09PSBGSUxFVFlQRV9ESVJFQ1RPUlkpIHsKICAgICAgcmV0dXJuIEVSUk5PX0lTRElSOwogICAgfQogICAgcGFyZW50X2VudHJ5LmNvbnRlbnRzLmRlbGV0ZShmaWxlbmFtZSk7CiAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICB9CiAgcGF0aF9yZW1vdmVfZGlyZWN0b3J5KHBhdGhfc3RyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXRoX3JldDsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBwYXJlbnRfcmV0LCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIGZhbHNlKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCB8fCBmaWxlbmFtZSA9PSBudWxsIHx8IGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHBhcmVudF9yZXQ7CiAgICB9CiAgICBpZiAoIShlbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkgfHwgZW50cnkuc3RhdCgpLmZpbGV0eXBlICE9PSBGSUxFVFlQRV9ESVJFQ1RPUlkpIHsKICAgICAgcmV0dXJuIEVSUk5PX05PVERJUjsKICAgIH0KICAgIGlmIChlbnRyeS5jb250ZW50cy5zaXplICE9PSAwKSB7CiAgICAgIHJldHVybiBFUlJOT19OT1RFTVBUWTsKICAgIH0KICAgIGlmICghcGFyZW50X2VudHJ5LmNvbnRlbnRzLmRlbGV0ZShmaWxlbmFtZSkpIHsKICAgICAgcmV0dXJuIEVSUk5PX05PRU5UOwogICAgfQogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIGZkX2ZpbGVzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgZmlsZXN0YXQ6IHRoaXMuZGlyLnN0YXQoKSB9OwogIH0KICBmZF9maWxlc3RhdF9zZXRfc2l6ZShzaXplKSB7CiAgICByZXR1cm4gRVJSTk9fQkFERjsKICB9CiAgZmRfcmVhZChzaXplKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIGRhdGE6IG5ldyBVaW50OEFycmF5KCkgfTsKICB9CiAgZmRfcHJlYWQoc2l6ZSwgb2Zmc2V0KSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIGRhdGE6IG5ldyBVaW50OEFycmF5KCkgfTsKICB9CiAgZmRfd3JpdGUoZGF0YSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBud3JpdHRlbjogMCB9OwogIH0KICBmZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG53cml0dGVuOiAwIH07CiAgfQogIGNvbnN0cnVjdG9yKGRpcikgewogICAgc3VwZXIoKTsKICAgIHRoaXMuZGlyID0gZGlyOwogIH0KfTsKdmFyIFByZW9wZW5EaXJlY3RvcnkgPSBjbGFzcyBleHRlbmRzIE9wZW5EaXJlY3RvcnkgewogIGZkX3ByZXN0YXRfZ2V0KCkgewogICAgcmV0dXJuIHsgcmV0OiAwLCBwcmVzdGF0OiBQcmVzdGF0LmRpcih0aGlzLnByZXN0YXRfbmFtZSkgfTsKICB9CiAgY29uc3RydWN0b3IobmFtZSwgY29udGVudHMpIHsKICAgIHN1cGVyKG5ldyBEaXJlY3RvcnkoY29udGVudHMpKTsKICAgIHRoaXMucHJlc3RhdF9uYW1lID0gbmFtZTsKICB9Cn07CnZhciBGaWxlID0gY2xhc3MgZXh0ZW5kcyBJbm9kZSB7CiAgcGF0aF9vcGVuKG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZkX2ZsYWdzKSB7CiAgICBpZiAodGhpcy5yZWFkb25seSAmJiAoZnNfcmlnaHRzX2Jhc2UgJiBCaWdJbnQoUklHSFRTX0ZEX1dSSVRFKSkgPT0gQmlnSW50KFJJR0hUU19GRF9XUklURSkpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19QRVJNLCBmZF9vYmo6IG51bGwgfTsKICAgIH0KICAgIGlmICgob2ZsYWdzICYgT0ZMQUdTX1RSVU5DKSA9PSBPRkxBR1NfVFJVTkMpIHsKICAgICAgaWYgKHRoaXMucmVhZG9ubHkpCiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19QRVJNLCBmZF9vYmo6IG51bGwgfTsKICAgICAgdGhpcy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoW10pOwogICAgfQogICAgY29uc3QgZmlsZSA9IG5ldyBPcGVuRmlsZSh0aGlzKTsKICAgIGlmIChmZF9mbGFncyAmIEZERkxBR1NfQVBQRU5EKQogICAgICBmaWxlLmZkX3NlZWsoMG4sIFdIRU5DRV9FTkQpOwogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBmZF9vYmo6IGZpbGUgfTsKICB9CiAgZ2V0IHNpemUoKSB7CiAgICByZXR1cm4gQmlnSW50KHRoaXMuZGF0YS5ieXRlTGVuZ3RoKTsKICB9CiAgc3RhdCgpIHsKICAgIHJldHVybiBuZXcgRmlsZXN0YXQoRklMRVRZUEVfUkVHVUxBUl9GSUxFLCB0aGlzLnNpemUpOwogIH0KICBjb25zdHJ1Y3RvcihkYXRhLCBvcHRpb25zKSB7CiAgICBzdXBlcigpOwogICAgdGhpcy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoZGF0YSk7CiAgICB0aGlzLnJlYWRvbmx5ID0gISFvcHRpb25zPy5yZWFkb25seTsKICB9Cn07CnZhciBQYXRoID0gY2xhc3MgUGF0aDIgewogIHN0YXRpYyBmcm9tKHBhdGgpIHsKICAgIGNvbnN0IHNlbGYgPSBuZXcgUGF0aDIoKTsKICAgIHNlbGYuaXNfZGlyID0gcGF0aC5lbmRzV2l0aCgiLyIpOwogICAgaWYgKHBhdGguc3RhcnRzV2l0aCgiLyIpKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UQ0FQQUJMRSwgcGF0aDogbnVsbCB9OwogICAgfQogICAgaWYgKHBhdGguaW5jbHVkZXMoIlwwIikpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19JTlZBTCwgcGF0aDogbnVsbCB9OwogICAgfQogICAgZm9yIChjb25zdCBjb21wb25lbnQgb2YgcGF0aC5zcGxpdCgiLyIpKSB7CiAgICAgIGlmIChjb21wb25lbnQgPT09ICIiIHx8IGNvbXBvbmVudCA9PT0gIi4iKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGNvbXBvbmVudCA9PT0gIi4uIikgewogICAgICAgIGlmIChzZWxmLnBhcnRzLnBvcCgpID09IHZvaWQgMCkgewogICAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RDQVBBQkxFLCBwYXRoOiBudWxsIH07CiAgICAgICAgfQogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHNlbGYucGFydHMucHVzaChjb21wb25lbnQpOwogICAgfQogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBwYXRoOiBzZWxmIH07CiAgfQogIHRvX3BhdGhfc3RyaW5nKCkgewogICAgbGV0IHMgPSB0aGlzLnBhcnRzLmpvaW4oIi8iKTsKICAgIGlmICh0aGlzLmlzX2RpcikgewogICAgICBzICs9ICIvIjsKICAgIH0KICAgIHJldHVybiBzOwogIH0KICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMucGFydHMgPSBbXTsKICAgIHRoaXMuaXNfZGlyID0gZmFsc2U7CiAgfQp9Owp2YXIgRGlyZWN0b3J5ID0gY2xhc3MgZXh0ZW5kcyBJbm9kZSB7CiAgcGF0aF9vcGVuKG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZkX2ZsYWdzKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGZkX29iajogbmV3IE9wZW5EaXJlY3RvcnkodGhpcykgfTsKICB9CiAgc3RhdCgpIHsKICAgIHJldHVybiBuZXcgRmlsZXN0YXQoRklMRVRZUEVfRElSRUNUT1JZLCAwbik7CiAgfQogIGdldF9lbnRyeV9mb3JfcGF0aChwYXRoKSB7CiAgICBsZXQgZW50cnkgPSB0aGlzOwogICAgZm9yIChjb25zdCBjb21wb25lbnQgb2YgcGF0aC5wYXJ0cykgewogICAgICBpZiAoIShlbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkpIHsKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgICBjb25zdCBjaGlsZCA9IGVudHJ5LmNvbnRlbnRzLmdldChjb21wb25lbnQpOwogICAgICBpZiAoY2hpbGQgIT09IHZvaWQgMCkgewogICAgICAgIGVudHJ5ID0gY2hpbGQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZGVidWcubG9nKGNvbXBvbmVudCk7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT0VOVCwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgfQogICAgaWYgKHBhdGguaXNfZGlyKSB7CiAgICAgIGlmIChlbnRyeS5zdGF0KCkuZmlsZXR5cGUgIT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIGVudHJ5OiBudWxsIH07CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZW50cnkgfTsKICB9CiAgZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIGFsbG93X3VuZGVmaW5lZCkgewogICAgY29uc3QgZmlsZW5hbWUgPSBwYXRoLnBhcnRzLnBvcCgpOwogICAgaWYgKGZpbGVuYW1lID09PSB2b2lkIDApIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19JTlZBTCwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBlbnRyeV9yZXQsIGVudHJ5OiBwYXJlbnRfZW50cnkgfSA9IHRoaXMuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgpOwogICAgaWYgKHBhcmVudF9lbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogZW50cnlfcmV0LCBwYXJlbnRfZW50cnk6IG51bGwsIGZpbGVuYW1lOiBudWxsLCBlbnRyeTogbnVsbCB9OwogICAgfQogICAgaWYgKCEocGFyZW50X2VudHJ5IGluc3RhbmNlb2YgRGlyZWN0b3J5KSkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IGVudHJ5ID0gcGFyZW50X2VudHJ5LmNvbnRlbnRzLmdldChmaWxlbmFtZSk7CiAgICBpZiAoZW50cnkgPT09IHZvaWQgMCkgewogICAgICBpZiAoIWFsbG93X3VuZGVmaW5lZCkgewogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9FTlQsIHBhcmVudF9lbnRyeTogbnVsbCwgZmlsZW5hbWU6IG51bGwsIGVudHJ5OiBudWxsIH07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeTogbnVsbCB9OwogICAgICB9CiAgICB9CiAgICBpZiAocGF0aC5pc19kaXIpIHsKICAgICAgaWYgKGVudHJ5LnN0YXQoKS5maWxldHlwZSAhPSBGSUxFVFlQRV9ESVJFQ1RPUlkpIHsKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9OwogIH0KICBjcmVhdGVfZW50cnlfZm9yX3BhdGgocGF0aF9zdHIsIGlzX2RpcikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhdGhfcmV0LCBlbnRyeTogbnVsbCB9OwogICAgfQogICAgbGV0IHsgcmV0OiBwYXJlbnRfcmV0LCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9ID0gdGhpcy5nZXRfcGFyZW50X2Rpcl9hbmRfZW50cnlfZm9yX3BhdGgocGF0aCwgdHJ1ZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhcmVudF9yZXQsIGVudHJ5OiBudWxsIH07CiAgICB9CiAgICBpZiAoZW50cnkgIT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0VYSVNULCBlbnRyeTogbnVsbCB9OwogICAgfQogICAgZGVidWcubG9nKCJjcmVhdGUiLCBwYXRoKTsKICAgIGxldCBuZXdfY2hpbGQ7CiAgICBpZiAoIWlzX2RpcikgewogICAgICBuZXdfY2hpbGQgPSBuZXcgRmlsZShuZXcgQXJyYXlCdWZmZXIoMCkpOwogICAgfSBlbHNlIHsKICAgICAgbmV3X2NoaWxkID0gbmV3IERpcmVjdG9yeSgvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpKTsKICAgIH0KICAgIHBhcmVudF9lbnRyeS5jb250ZW50cy5zZXQoZmlsZW5hbWUsIG5ld19jaGlsZCk7CiAgICBlbnRyeSA9IG5ld19jaGlsZDsKICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZW50cnkgfTsKICB9CiAgY29uc3RydWN0b3IoY29udGVudHMpIHsKICAgIHN1cGVyKCk7CiAgICBpZiAoY29udGVudHMgaW5zdGFuY2VvZiBBcnJheSkgewogICAgICB0aGlzLmNvbnRlbnRzID0gbmV3IE1hcChjb250ZW50cyk7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmNvbnRlbnRzID0gY29udGVudHM7CiAgICB9CiAgfQp9Owp2YXIgQ29uc29sZVN0ZG91dCA9IGNsYXNzIGV4dGVuZHMgRmQgewogIGZkX2ZpbGVzdGF0X2dldCgpIHsKICAgIGNvbnN0IGZpbGVzdGF0ID0gbmV3IEZpbGVzdGF0KEZJTEVUWVBFX0NIQVJBQ1RFUl9ERVZJQ0UsIEJpZ0ludCgwKSk7CiAgICByZXR1cm4geyByZXQ6IDAsIGZpbGVzdGF0IH07CiAgfQogIGZkX2Zkc3RhdF9nZXQoKSB7CiAgICBjb25zdCBmZHN0YXQgPSBuZXcgRmRzdGF0KEZJTEVUWVBFX0NIQVJBQ1RFUl9ERVZJQ0UsIDApOwogICAgZmRzdGF0LmZzX3JpZ2h0c19iYXNlID0gQmlnSW50KFJJR0hUU19GRF9XUklURSk7CiAgICByZXR1cm4geyByZXQ6IDAsIGZkc3RhdCB9OwogIH0KICBmZF93cml0ZShkYXRhKSB7CiAgICB0aGlzLndyaXRlKGRhdGEpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBud3JpdHRlbjogZGF0YS5ieXRlTGVuZ3RoIH07CiAgfQogIHN0YXRpYyBsaW5lQnVmZmVyZWQod3JpdGUpIHsKICAgIGNvbnN0IGRlYyA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiLCB7IGZhdGFsOiBmYWxzZSB9KTsKICAgIGxldCBsaW5lX2J1ZiA9ICIiOwogICAgcmV0dXJuIG5ldyBDb25zb2xlU3Rkb3V0KChidWZmZXIpID0+IHsKICAgICAgbGluZV9idWYgKz0gZGVjLmRlY29kZShidWZmZXIsIHsgc3RyZWFtOiB0cnVlIH0pOwogICAgICBjb25zdCBsaW5lcyA9IGxpbmVfYnVmLnNwbGl0KCJcbiIpOwogICAgICBmb3IgKGNvbnN0IFtpLCBsaW5lXSBvZiBsaW5lcy5lbnRyaWVzKCkpIHsKICAgICAgICBpZiAoaSA8IGxpbmVzLmxlbmd0aCAtIDEpIHsKICAgICAgICAgIHdyaXRlKGxpbmUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBsaW5lX2J1ZiA9IGxpbmU7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICB9CiAgY29uc3RydWN0b3Iod3JpdGUpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLndyaXRlID0gd3JpdGU7CiAgfQp9OwoKLy8gbm9kZV9tb2R1bGVzL3dhc20taW1wb3J0cy1wYXJzZXIvaW5kZXguanMKZnVuY3Rpb24gcGFyc2VJbXBvcnRzKG1vZHVsZUJ5dGVzKSB7CiAgaWYgKG1vZHVsZUJ5dGVzIGluc3RhbmNlb2YgVWludDhBcnJheSkgewogIH0gZWxzZSBpZiAobW9kdWxlQnl0ZXMgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikgewogICAgbW9kdWxlQnl0ZXMgPSBuZXcgVWludDhBcnJheShtb2R1bGVCeXRlcyk7CiAgfSBlbHNlIGlmIChtb2R1bGVCeXRlcy5idWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikgewogICAgbW9kdWxlQnl0ZXMgPSBuZXcgVWludDhBcnJheShtb2R1bGVCeXRlcy5idWZmZXIpOwogIH0gZWxzZSB7CiAgICB0aHJvdyBuZXcgRXJyb3IoIkFyZ3VtZW50IG11c3QgYmUgYSBidWZmZXIgc291cmNlLCBsaWtlIFVpbnQ4QXJyYXkgb3IgQXJyYXlCdWZmZXIiKTsKICB9CiAgY29uc3QgcGFyc2VTdGF0ZSA9IG5ldyBQYXJzZVN0YXRlKG1vZHVsZUJ5dGVzKTsKICBwYXJzZU1hZ2ljTnVtYmVyKHBhcnNlU3RhdGUpOwogIHBhcnNlVmVyc2lvbihwYXJzZVN0YXRlKTsKICBjb25zdCB0eXBlcyA9IFtdOwogIGNvbnN0IGltcG9ydHMgPSBbXTsKICB3aGlsZSAocGFyc2VTdGF0ZS5oYXNNb3JlQnl0ZXMoKSkgewogICAgY29uc3Qgc2VjdGlvbklkID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogICAgY29uc3Qgc2VjdGlvblNpemUgPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgc3dpdGNoIChzZWN0aW9uSWQpIHsKICAgICAgY2FzZSAxOiB7CiAgICAgICAgY29uc3QgdHlwZUNvdW50ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHR5cGVDb3VudDsgaSsrKSB7CiAgICAgICAgICB0eXBlcy5wdXNoKHBhcnNlRnVuY3Rpb25UeXBlKHBhcnNlU3RhdGUpKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY2FzZSAyOiB7CiAgICAgICAgY29uc3QgaW1wb3J0Q291bnQgPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW1wb3J0Q291bnQ7IGkrKykgewogICAgICAgICAgY29uc3QgbW9kdWxlID0gcGFyc2VTdGF0ZS5yZWFkTmFtZSgpOwogICAgICAgICAgY29uc3QgbmFtZSA9IHBhcnNlU3RhdGUucmVhZE5hbWUoKTsKICAgICAgICAgIGNvbnN0IHR5cGUgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICAgICAgICAgICAgICBpbXBvcnRzLnB1c2goeyBtb2R1bGUsIG5hbWUsIGtpbmQ6ICJmdW5jdGlvbiIsIHR5cGU6IHR5cGVzW2luZGV4XSB9KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgIGltcG9ydHMucHVzaCh7IG1vZHVsZSwgbmFtZSwga2luZDogInRhYmxlIiwgdHlwZTogcGFyc2VUYWJsZVR5cGUocGFyc2VTdGF0ZSkgfSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgICBpbXBvcnRzLnB1c2goeyBtb2R1bGUsIG5hbWUsIGtpbmQ6ICJtZW1vcnkiLCB0eXBlOiBwYXJzZUxpbWl0cyhwYXJzZVN0YXRlKSB9KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAzOgogICAgICAgICAgICAgIGltcG9ydHMucHVzaCh7IG1vZHVsZSwgbmFtZSwga2luZDogImdsb2JhbCIsIHR5cGU6IHBhcnNlR2xvYmFsVHlwZShwYXJzZVN0YXRlKSB9KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gaW1wb3J0IGRlc2NyaXB0b3IgdHlwZSAke3R5cGV9YCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBpbXBvcnRzOwogICAgICB9CiAgICAgIGRlZmF1bHQ6IHsKICAgICAgICBwYXJzZVN0YXRlLnNraXBCeXRlcyhzZWN0aW9uU2l6ZSk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICB9CiAgcmV0dXJuIFtdOwp9CnZhciBQYXJzZVN0YXRlID0gY2xhc3MgewogIGNvbnN0cnVjdG9yKG1vZHVsZUJ5dGVzKSB7CiAgICB0aGlzLm1vZHVsZUJ5dGVzID0gbW9kdWxlQnl0ZXM7CiAgICB0aGlzLm9mZnNldCA9IDA7CiAgICB0aGlzLnRleHREZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpOwogIH0KICBoYXNNb3JlQnl0ZXMoKSB7CiAgICByZXR1cm4gdGhpcy5vZmZzZXQgPCB0aGlzLm1vZHVsZUJ5dGVzLmxlbmd0aDsKICB9CiAgcmVhZEJ5dGUoKSB7CiAgICByZXR1cm4gdGhpcy5tb2R1bGVCeXRlc1t0aGlzLm9mZnNldCsrXTsKICB9CiAgc2tpcEJ5dGVzKGNvdW50KSB7CiAgICB0aGlzLm9mZnNldCArPSBjb3VudDsKICB9CiAgcmVhZFVuc2lnbmVkTEVCMTI4KCkgewogICAgbGV0IHJlc3VsdCA9IDA7CiAgICBsZXQgc2hpZnQgPSAwOwogICAgbGV0IGJ5dGU7CiAgICBkbyB7CiAgICAgIGJ5dGUgPSB0aGlzLnJlYWRCeXRlKCk7CiAgICAgIHJlc3VsdCB8PSAoYnl0ZSAmIDEyNykgPDwgc2hpZnQ7CiAgICAgIHNoaWZ0ICs9IDc7CiAgICB9IHdoaWxlIChieXRlICYgMTI4KTsKICAgIHJldHVybiByZXN1bHQ7CiAgfQogIHJlYWROYW1lKCkgewogICAgY29uc3QgbmFtZUxlbmd0aCA9IHRoaXMucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgICBjb25zdCBuYW1lQnl0ZXMgPSB0aGlzLm1vZHVsZUJ5dGVzLnNsaWNlKHRoaXMub2Zmc2V0LCB0aGlzLm9mZnNldCArIG5hbWVMZW5ndGgpOwogICAgY29uc3QgbmFtZSA9IHRoaXMudGV4dERlY29kZXIuZGVjb2RlKG5hbWVCeXRlcyk7CiAgICB0aGlzLm9mZnNldCArPSBuYW1lTGVuZ3RoOwogICAgcmV0dXJuIG5hbWU7CiAgfQogIGFzc2VydEJ5dGVzKGV4cGVjdGVkKSB7CiAgICBjb25zdCBiYXNlT2Zmc2V0ID0gdGhpcy5vZmZzZXQ7CiAgICBjb25zdCBleHBlY3RlZExlbmd0aCA9IGV4cGVjdGVkLmxlbmd0aDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZXhwZWN0ZWRMZW5ndGg7IGkrKykgewogICAgICBpZiAodGhpcy5tb2R1bGVCeXRlc1tiYXNlT2Zmc2V0ICsgaV0gIT09IGV4cGVjdGVkW2ldKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCAke2V4cGVjdGVkfSBhdCBvZmZzZXQgJHtiYXNlT2Zmc2V0fWApOwogICAgICB9CiAgICB9CiAgICB0aGlzLm9mZnNldCArPSBleHBlY3RlZExlbmd0aDsKICB9Cn07CmZ1bmN0aW9uIHBhcnNlTWFnaWNOdW1iZXIocGFyc2VTdGF0ZSkgewogIGNvbnN0IGV4cGVjdGVkID0gWzAsIDk3LCAxMTUsIDEwOV07CiAgcGFyc2VTdGF0ZS5hc3NlcnRCeXRlcyhleHBlY3RlZCk7Cn0KZnVuY3Rpb24gcGFyc2VWZXJzaW9uKHBhcnNlU3RhdGUpIHsKICBjb25zdCBleHBlY3RlZCA9IFsxLCAwLCAwLCAwXTsKICBwYXJzZVN0YXRlLmFzc2VydEJ5dGVzKGV4cGVjdGVkKTsKfQpmdW5jdGlvbiBwYXJzZVRhYmxlVHlwZShwYXJzZVN0YXRlKSB7CiAgY29uc3QgZWxlbWVudFR5cGUgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgbGV0IGVsZW1lbnQ7CiAgc3dpdGNoIChlbGVtZW50VHlwZSkgewogICAgY2FzZSAxMTI6CiAgICAgIGVsZW1lbnQgPSAiZnVuY3JlZiI7CiAgICAgIGJyZWFrOwogICAgY2FzZSAxMTE6CiAgICAgIGVsZW1lbnQgPSAiZXh0ZXJucmVmIjsKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gdGFibGUgZWxlbWVudCB0eXBlICR7ZWxlbWVudFR5cGV9YCk7CiAgfQogIGNvbnN0IHsgbWluaW11bSwgbWF4aW11bSB9ID0gcGFyc2VMaW1pdHMocGFyc2VTdGF0ZSk7CiAgaWYgKG1heGltdW0pIHsKICAgIHJldHVybiB7IGVsZW1lbnQsIG1pbmltdW0sIG1heGltdW0gfTsKICB9IGVsc2UgewogICAgcmV0dXJuIHsgZWxlbWVudCwgbWluaW11bSB9OwogIH0KfQpmdW5jdGlvbiBwYXJzZUxpbWl0cyhwYXJzZVN0YXRlKSB7CiAgY29uc3QgZmxhZ3MgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgY29uc3QgbWluaW11bSA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgY29uc3QgaGFzTWF4aW11bSA9IGZsYWdzICYgMTsKICBjb25zdCBzaGFyZWQgPSAoZmxhZ3MgJiAyKSAhPT0gMDsKICBjb25zdCBpc01lbW9yeTY0ID0gKGZsYWdzICYgNCkgIT09IDA7CiAgY29uc3QgaW5kZXggPSBpc01lbW9yeTY0ID8gImk2NCIgOiAiaTMyIjsKICBpZiAoaGFzTWF4aW11bSkgewogICAgY29uc3QgbWF4aW11bSA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgICByZXR1cm4geyBtaW5pbXVtLCBzaGFyZWQsIGluZGV4LCBtYXhpbXVtIH07CiAgfSBlbHNlIHsKICAgIHJldHVybiB7IG1pbmltdW0sIHNoYXJlZCwgaW5kZXggfTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VHbG9iYWxUeXBlKHBhcnNlU3RhdGUpIHsKICBjb25zdCB2YWx1ZSA9IHBhcnNlVmFsdWVUeXBlKHBhcnNlU3RhdGUpOwogIGNvbnN0IG11dGFibGUgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCkgPT09IDE7CiAgcmV0dXJuIHsgdmFsdWUsIG11dGFibGUgfTsKfQpmdW5jdGlvbiBwYXJzZVZhbHVlVHlwZShwYXJzZVN0YXRlKSB7CiAgY29uc3QgdHlwZSA9IHBhcnNlU3RhdGUucmVhZEJ5dGUoKTsKICBzd2l0Y2ggKHR5cGUpIHsKICAgIGNhc2UgMTI3OgogICAgICByZXR1cm4gImkzMiI7CiAgICBjYXNlIDEyNjoKICAgICAgcmV0dXJuICJpNjQiOwogICAgY2FzZSAxMjU6CiAgICAgIHJldHVybiAiZjMyIjsKICAgIGNhc2UgMTI0OgogICAgICByZXR1cm4gImY2NCI7CiAgICBjYXNlIDExMjoKICAgICAgcmV0dXJuICJmdW5jcmVmIjsKICAgIGNhc2UgMTExOgogICAgICByZXR1cm4gImV4dGVybnJlZiI7CiAgICBjYXNlIDEyMzoKICAgICAgcmV0dXJuICJ2MTI4IjsKICAgIGRlZmF1bHQ6CiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biB2YWx1ZSB0eXBlICR7dHlwZX1gKTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VGdW5jdGlvblR5cGUocGFyc2VTdGF0ZSkgewogIGNvbnN0IGZvcm0gPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgaWYgKGZvcm0gIT09IDk2KSB7CiAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGZ1bmN0aW9uIHR5cGUgZm9ybSAweDYwLCBnb3QgJHtmb3JtfWApOwogIH0KICBjb25zdCBwYXJhbWV0ZXJzID0gW107CiAgY29uc3QgcGFyYW1ldGVyQ291bnQgPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogIGZvciAobGV0IGkgPSAwOyBpIDwgcGFyYW1ldGVyQ291bnQ7IGkrKykgewogICAgcGFyYW1ldGVycy5wdXNoKHBhcnNlVmFsdWVUeXBlKHBhcnNlU3RhdGUpKTsKICB9CiAgY29uc3QgcmVzdWx0cyA9IFtdOwogIGNvbnN0IHJlc3VsdENvdW50ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICBmb3IgKGxldCBpID0gMDsgaSA8IHJlc3VsdENvdW50OyBpKyspIHsKICAgIHJlc3VsdHMucHVzaChwYXJzZVZhbHVlVHlwZShwYXJzZVN0YXRlKSk7CiAgfQogIHJldHVybiB7IHBhcmFtZXRlcnMsIHJlc3VsdHMgfTsKfQoKLy8gbm9kZV9tb2R1bGVzL3dhc20taW1wb3J0cy1wYXJzZXIvcG9seWZpbGwuanMKdmFyIGhhc1dhc21UeXBlUmVmbGVjdGlvblN1cHBvcnQgPSAoKCkgPT4gewogIGNvbnN0IG1vZHVsZUJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoWwogICAgMCwKICAgIDk3LAogICAgMTE1LAogICAgMTA5LAogICAgMSwKICAgIDAsCiAgICAwLAogICAgMCwKICAgIDIsCiAgICA2LAogICAgMSwKICAgIDAsCiAgICAwLAogICAgMiwKICAgIDAsCiAgICAxCiAgXSk7CiAgY29uc3QgbW9kdWxlID0gbmV3IFdlYkFzc2VtYmx5Lk1vZHVsZShtb2R1bGVCeXRlcyk7CiAgY29uc3QgaW1wb3J0cyA9IFdlYkFzc2VtYmx5Lk1vZHVsZS5pbXBvcnRzKG1vZHVsZSk7CiAgY29uc3QgbWVtb3J5SW1wb3J0ID0gaW1wb3J0c1swXTsKICByZXR1cm4gdHlwZW9mIG1lbW9yeUltcG9ydC50eXBlID09PSAib2JqZWN0IjsKfSkoKTsKZnVuY3Rpb24gcG9seWZpbGwoV2ViQXNzZW1ibHkzKSB7CiAgaWYgKGhhc1dhc21UeXBlUmVmbGVjdGlvblN1cHBvcnQpIHsKICAgIHJldHVybiBXZWJBc3NlbWJseTM7CiAgfQogIGNvbnN0IG5ld1dlYkFzc2VtYmx5ID0ge307CiAgZm9yIChjb25zdCBrZXkgaW4gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMoV2ViQXNzZW1ibHkzKSkgewogICAgbmV3V2ViQXNzZW1ibHlba2V5XSA9IFdlYkFzc2VtYmx5M1trZXldOwogIH0KICBjb25zdCBwb2x5ZmlsbGVkSW1wb3J0c1N5bWJvbCA9IFN5bWJvbCgicG9seWZpbGxlZEltcG9ydHNTeW1ib2wiKTsKICBjb25zdCBhc3NpZ25JbXBvcnRzID0gKG1vZHVsZSwgc291cmNlQnl0ZXMpID0+IHsKICAgIG1vZHVsZVtwb2x5ZmlsbGVkSW1wb3J0c1N5bWJvbF0gPSBwYXJzZUltcG9ydHMoc291cmNlQnl0ZXMpOwogIH07CiAgY29uc3QgbmV3TW9kdWxlID0gbmV3V2ViQXNzZW1ibHkuTW9kdWxlID0gZnVuY3Rpb24oYnl0ZXMpIHsKICAgIGNvbnN0IG1vZHVsZSA9IG5ldyBXZWJBc3NlbWJseTMuTW9kdWxlKGJ5dGVzKTsKICAgIGFzc2lnbkltcG9ydHMobW9kdWxlLCBieXRlcyk7CiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YobW9kdWxlLCBuZXdNb2R1bGUucHJvdG90eXBlKTsKICAgIHJldHVybiBtb2R1bGU7CiAgfTsKICBPYmplY3Quc2V0UHJvdG90eXBlT2YobmV3TW9kdWxlLnByb3RvdHlwZSwgV2ViQXNzZW1ibHkzLk1vZHVsZS5wcm90b3R5cGUpOwogIG5ld1dlYkFzc2VtYmx5LmNvbXBpbGUgPSBhc3luYyAoc291cmNlKSA9PiB7CiAgICBjb25zdCBtb2R1bGUgPSBhd2FpdCBXZWJBc3NlbWJseTMuY29tcGlsZShzb3VyY2UpOwogICAgYXNzaWduSW1wb3J0cyhtb2R1bGUsIHNvdXJjZSk7CiAgICByZXR1cm4gbW9kdWxlOwogIH07CiAgaWYgKFdlYkFzc2VtYmx5My5jb21waWxlU3RyZWFtaW5nKSB7CiAgICBuZXdXZWJBc3NlbWJseS5jb21waWxlU3RyZWFtaW5nID0gYXN5bmMgKHNvdXJjZSkgPT4gewogICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHNvdXJjZTsKICAgICAgY29uc3QgY2xvbmUgPSByZXNwb25zZS5jbG9uZSgpOwogICAgICBjb25zdCBtb2R1bGUgPSBhd2FpdCBXZWJBc3NlbWJseTMuY29tcGlsZVN0cmVhbWluZyhyZXNwb25zZSk7CiAgICAgIGFzc2lnbkltcG9ydHMobW9kdWxlLCBuZXcgVWludDhBcnJheShhd2FpdCBjbG9uZS5hcnJheUJ1ZmZlcigpKSk7CiAgICAgIHJldHVybiBtb2R1bGU7CiAgICB9OwogIH0KICBuZXdNb2R1bGUuaW1wb3J0cyA9IChtb2R1bGUpID0+IHsKICAgIGNvbnN0IHBhcnNlZEltcG9ydHMgPSBtb2R1bGVbcG9seWZpbGxlZEltcG9ydHNTeW1ib2xdOwogICAgaWYgKCFwYXJzZWRJbXBvcnRzKSB7CiAgICAgIHJldHVybiBXZWJBc3NlbWJseTMuTW9kdWxlLmltcG9ydHMobW9kdWxlKTsKICAgIH0KICAgIHJldHVybiBwYXJzZWRJbXBvcnRzOwogIH07CiAgcmV0dXJuIG5ld1dlYkFzc2VtYmx5Owp9CgovLyBlbnRyeXBvaW50L2ludHJpbnNpY3MudHMKdmFyIFdlYkFzc2VtYmx5MiA9IHBvbHlmaWxsKGdsb2JhbFRoaXMuV2ViQXNzZW1ibHkpOwp2YXIgTGluZURlY29kZXIgPSBjbGFzcyB7CiAgY29uc3RydWN0b3Iob25MaW5lKSB7CiAgICB0aGlzLmRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IiwgeyBmYXRhbDogZmFsc2UgfSk7CiAgICB0aGlzLmJ1ZmZlciA9ICIiOwogICAgdGhpcy5vbkxpbmUgPSBvbkxpbmU7CiAgfQogIGRlY29kZXI7CiAgYnVmZmVyOwogIG9uTGluZTsKICBzZW5kKGNodW5rKSB7CiAgICB0aGlzLmJ1ZmZlciArPSB0aGlzLmRlY29kZXIuZGVjb2RlKGNodW5rLCB7IHN0cmVhbTogdHJ1ZSB9KTsKICAgIGNvbnN0IGxpbmVzID0gdGhpcy5idWZmZXIuc3BsaXQoIlxuIik7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aCAtIDE7IGkrKykgewogICAgICB0aGlzLm9uTGluZShsaW5lc1tpXSk7CiAgICB9CiAgICB0aGlzLmJ1ZmZlciA9IGxpbmVzW2xpbmVzLmxlbmd0aCAtIDFdOwogIH0KfTsKYXN5bmMgZnVuY3Rpb24gaW5zdGFudGlhdGUocmF3T3B0aW9ucywgZXh0cmFXYXNtSW1wb3J0cykgewogIGNvbnN0IG9wdGlvbnMgPSBkZWZhdWx0SW5zdGFudGlhdGlvbk9wdGlvbnMocmF3T3B0aW9ucyk7CiAgbGV0IHN3aWZ0ID0gb3B0aW9ucy5zd2lmdDsKICBpZiAoIXN3aWZ0ICYmIG9wdGlvbnMuU3dpZnRSdW50aW1lKSB7CiAgICBzd2lmdCA9IG5ldyBvcHRpb25zLlN3aWZ0UnVudGltZSgpOwogIH0KICBsZXQgc3Rkb3V0TGluZSA9IHZvaWQgMDsKICBpZiAob3B0aW9ucy5vblN0ZG91dExpbmUgIT0gbnVsbCkgewogICAgc3Rkb3V0TGluZSA9IG5ldyBMaW5lRGVjb2RlcihvcHRpb25zLm9uU3Rkb3V0TGluZSk7CiAgfQogIGNvbnN0IHN0ZG91dCA9IG5ldyBDb25zb2xlU3Rkb3V0KChjaHVuaykgPT4gewogICAgb3B0aW9ucy5vblN0ZG91dD8uY2FsbCh2b2lkIDAsIGNodW5rKTsKICAgIHN0ZG91dExpbmU/LnNlbmQoY2h1bmspOwogIH0pOwogIGxldCBzdGRlcnJMaW5lID0gdm9pZCAwOwogIGlmIChvcHRpb25zLm9uU3RkZXJyTGluZSAhPSBudWxsKSB7CiAgICBzdGRlcnJMaW5lID0gbmV3IExpbmVEZWNvZGVyKG9wdGlvbnMub25TdGRlcnJMaW5lKTsKICB9CiAgY29uc3Qgc3RkZXJyID0gbmV3IENvbnNvbGVTdGRvdXQoKGNodW5rKSA9PiB7CiAgICBvcHRpb25zLm9uU3RkZXJyPy5jYWxsKHZvaWQgMCwgY2h1bmspOwogICAgc3RkZXJyTGluZT8uc2VuZChjaHVuayk7CiAgfSk7CiAgY29uc3QgYXJncyA9IG9wdGlvbnMuYXJncyB8fCBbXTsKICBjb25zdCBmZHMgPSBbCiAgICBuZXcgT3BlbkZpbGUobmV3IEZpbGUoW10pKSwKICAgIHN0ZG91dCwKICAgIHN0ZGVyciwKICAgIG5ldyBQcmVvcGVuRGlyZWN0b3J5KCIvIiwgLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKSkKICBdOwogIGNvbnN0IGVudnMgPSBvcHRpb25zLmVudiA/IE9iamVjdC5lbnRyaWVzKG9wdGlvbnMuZW52KS5tYXAoKFtrZXksIHZhbHVlXSkgPT4gYCR7a2V5fT0ke3ZhbHVlfWApIDogW107CiAgY29uc3Qgd2FzaSA9IG5ldyBXQVNJKGFyZ3MsIGVudnMsIGZkcywgewogICAgZGVidWc6IGZhbHNlCiAgfSk7CiAgY29uc3QgY3JlYXRlV2FzbUltcG9ydE9iamVjdCA9IChleHRyYVdhc21JbXBvcnRzMiwgbW9kdWxlKSA9PiB7CiAgICBjb25zdCBpbXBvcnRPYmplY3QyID0gewogICAgICB3YXNpX3NuYXBzaG90X3ByZXZpZXcxOiB3YXNpLndhc2lJbXBvcnQKICAgIH07CiAgICBpZiAoc3dpZnQpIHsKICAgICAgaW1wb3J0T2JqZWN0Mi5qYXZhc2NyaXB0X2tpdCA9IHN3aWZ0Lndhc21JbXBvcnRzOwogICAgfQogICAgaWYgKGV4dHJhV2FzbUltcG9ydHMyKSB7CiAgICAgIGZvciAoY29uc3QgbW9kdWxlTmFtZSBpbiBleHRyYVdhc21JbXBvcnRzMikgewogICAgICAgIGlmICghaW1wb3J0T2JqZWN0Mlttb2R1bGVOYW1lXSkgewogICAgICAgICAgaW1wb3J0T2JqZWN0Mlttb2R1bGVOYW1lXSA9IHt9OwogICAgICAgIH0KICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IGluIGV4dHJhV2FzbUltcG9ydHMyW21vZHVsZU5hbWVdKSB7CiAgICAgICAgICBpbXBvcnRPYmplY3QyW21vZHVsZU5hbWVdW2VudHJ5XSA9IGV4dHJhV2FzbUltcG9ydHMyW21vZHVsZU5hbWVdW2VudHJ5XTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGZvciAoY29uc3QgX2ltcG9ydEVudHJ5IG9mIFdlYkFzc2VtYmx5Mi5Nb2R1bGUuaW1wb3J0cyhtb2R1bGUpKSB7CiAgICAgIGNvbnN0IGltcG9ydEVudHJ5ID0gX2ltcG9ydEVudHJ5OwogICAgICBpZiAoIWltcG9ydE9iamVjdDJbaW1wb3J0RW50cnkubW9kdWxlXSkgewogICAgICAgIGltcG9ydE9iamVjdDJbaW1wb3J0RW50cnkubW9kdWxlXSA9IHt9OwogICAgICB9CiAgICAgIGlmIChpbXBvcnRPYmplY3QyW2ltcG9ydEVudHJ5Lm1vZHVsZV1baW1wb3J0RW50cnkubmFtZV0pIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoaW1wb3J0RW50cnkua2luZCA9PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgaW1wb3J0T2JqZWN0MltpbXBvcnRFbnRyeS5tb2R1bGVdW2ltcG9ydEVudHJ5Lm5hbWVdID0gKCkgPT4gewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbXBvcnRlZCBmdW5jdGlvbiAke2ltcG9ydEVudHJ5Lm1vZHVsZX0uJHtpbXBvcnRFbnRyeS5uYW1lfSBub3QgaW1wbGVtZW50ZWRgKTsKICAgICAgICB9OwogICAgICB9IGVsc2UgaWYgKGltcG9ydEVudHJ5LmtpbmQgPT0gIm1lbW9yeSIgJiYgaW1wb3J0RW50cnkubW9kdWxlID09ICJlbnYiICYmIGltcG9ydEVudHJ5Lm5hbWUgPT0gIm1lbW9yeSIpIHsKICAgICAgICBjb25zdCB0eXBlID0gaW1wb3J0RW50cnkudHlwZTsKICAgICAgICBjb25zdCBkZXNjcmlwdG9yID0gewogICAgICAgICAgaW5pdGlhbDogdHlwZS5taW5pbXVtLAogICAgICAgICAgbWF4aW11bTogdHlwZS5tYXhpbXVtLAogICAgICAgICAgc2hhcmVkOiB0eXBlLnNoYXJlZAogICAgICAgIH07CiAgICAgICAgaW1wb3J0T2JqZWN0MltpbXBvcnRFbnRyeS5tb2R1bGVdW2ltcG9ydEVudHJ5Lm5hbWVdID0gbmV3IFdlYkFzc2VtYmx5Mi5NZW1vcnkoZGVzY3JpcHRvcik7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBpbXBvcnRPYmplY3QyOwogIH07CiAgY29uc3QgaW1wb3J0T2JqZWN0ID0gY3JlYXRlV2FzbUltcG9ydE9iamVjdChleHRyYVdhc21JbXBvcnRzLCBvcHRpb25zLm1vZHVsZSk7CiAgY29uc3QgaW5zdGFuY2UgPSBhd2FpdCBXZWJBc3NlbWJseTIuaW5zdGFudGlhdGUob3B0aW9ucy5tb2R1bGUsIGltcG9ydE9iamVjdCk7CiAgaWYgKHN3aWZ0ICYmIGluc3RhbmNlLmV4cG9ydHMuc3dqc19saWJyYXJ5X3ZlcnNpb24pIHsKICAgIHN3aWZ0LnNldEluc3RhbmNlKGluc3RhbmNlKTsKICB9CiAgaWYgKHR5cGVvZiBpbnN0YW5jZS5leHBvcnRzLl9zdGFydCA9PT0gImZ1bmN0aW9uIikgewogICAgd2FzaS5zdGFydChpbnN0YW5jZSk7CiAgfSBlbHNlIGlmICh0eXBlb2YgaW5zdGFuY2UuZXhwb3J0cy5faW5pdGlhbGl6ZSA9PSAiZnVuY3Rpb24iKSB7CiAgICB3YXNpLmluaXRpYWxpemUoaW5zdGFuY2UpOwogICAgaWYgKHN3aWZ0ICYmIHN3aWZ0Lm1haW4pIHsKICAgICAgc3dpZnQubWFpbigpOwogICAgfSBlbHNlIHsKICAgICAgaWYgKHR5cGVvZiBpbnN0YW5jZS5leHBvcnRzLm1haW4gPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICBpbnN0YW5jZS5leHBvcnRzLm1haW4oKTsKICAgICAgfSBlbHNlIGlmICh0eXBlb2YgaW5zdGFuY2UuZXhwb3J0cy5fX21haW5fYXJnY19hcmd2ID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgaW5zdGFuY2UuZXhwb3J0cy5fX21haW5fYXJnY19hcmd2KDAsIDApOwogICAgICB9CiAgICB9CiAgfQogIHJldHVybiB7IGluc3RhbmNlIH07Cn0KZnVuY3Rpb24gZGVmYXVsdEluc3RhbnRpYXRpb25PcHRpb25zKG9wdGlvbnMpIHsKICBpZiAob3B0aW9ucy5hcmdzID09IG51bGwpIHsKICAgIG9wdGlvbnMuYXJncyA9IFsibWFpbi53YXNtIl07CiAgfQogIGNvbnN0IGlzTm9kZUpzID0gdHlwZW9mIHByb2Nlc3MgIT09ICJ1bmRlZmluZWQiICYmIHByb2Nlc3MucmVsZWFzZS5uYW1lID09PSAibm9kZSI7CiAgY29uc3QgaXNXZWJCcm93c2VyID0gdHlwZW9mIHdpbmRvdyAhPT0gInVuZGVmaW5lZCI7CiAgaWYgKGlzTm9kZUpzKSB7CiAgICBpZiAoIW9wdGlvbnMub25TdGRvdXQpIHsKICAgICAgb3B0aW9ucy5vblN0ZG91dCA9IChjaHVuaykgPT4gcHJvY2Vzcy5zdGRvdXQud3JpdGUoY2h1bmspOwogICAgfQogICAgaWYgKCFvcHRpb25zLm9uU3RkZXJyKSB7CiAgICAgIG9wdGlvbnMub25TdGRlcnIgPSAoY2h1bmspID0+IHByb2Nlc3Muc3RkZXJyLndyaXRlKGNodW5rKTsKICAgIH0KICB9IGVsc2UgaWYgKGlzV2ViQnJvd3NlcikgewogICAgaWYgKCFvcHRpb25zLm9uU3Rkb3V0TGluZSkgewogICAgICBvcHRpb25zLm9uU3Rkb3V0TGluZSA9IChsaW5lKSA9PiBjb25zb2xlLmxvZyhsaW5lKTsKICAgIH0KICAgIGlmICghb3B0aW9ucy5vblN0ZGVyckxpbmUpIHsKICAgICAgb3B0aW9ucy5vblN0ZGVyckxpbmUgPSAobGluZSkgPT4gY29uc29sZS53YXJuKGxpbmUpOwogICAgfQogIH0KICByZXR1cm4gb3B0aW9uczsKfQoKLy8gZW50cnlwb2ludC9idW5kbGUudHMKdmFyIHN0YXJ0V2FzaVRhc2sgPSBhc3luYyAoKSA9PiB7CiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCgiUkVQTEFDRV9USElTX1dJVEhfVEhFX01BSU5fV0VCQVNTRU1CTFlfTU9EVUxFIik7CiAgbGV0IHJ1bnRpbWVDb25zdHJ1Y3RvciA9IHZvaWQgMDsKICB0cnkgewogICAgY29uc3QgeyBTd2lmdFJ1bnRpbWUgfSA9IGF3YWl0IGltcG9ydCgKICAgICAgLy8gQHRzLWlnbm9yZQogICAgICAiLi9KYXZhU2NyaXB0S2l0X0phdmFTY3JpcHRLaXQucmVzb3VyY2VzL1J1bnRpbWUvaW5kZXgubWpzIgogICAgKTsKICAgIHJ1bnRpbWVDb25zdHJ1Y3RvciA9IFN3aWZ0UnVudGltZTsKICB9IGNhdGNoIHsKICB9CiAgYXdhaXQgaW5zdGFudGlhdGUoewogICAgbW9kdWxlOiBhd2FpdCBXZWJBc3NlbWJseS5jb21waWxlU3RyZWFtaW5nKHJlc3BvbnNlKSwKICAgIG9uU3Rkb3V0TGluZShsaW5lKSB7CiAgICAgIGNvbnNvbGUubG9nKGxpbmUpOwogICAgfSwKICAgIG9uU3RkZXJyTGluZShsaW5lKSB7CiAgICAgIGNvbnNvbGUuZXJyb3IobGluZSk7CiAgICB9LAogICAgU3dpZnRSdW50aW1lOiBydW50aW1lQ29uc3RydWN0b3IKICB9KTsKfTsKYXN5bmMgZnVuY3Rpb24gbWFpbigpIHsKICBhd2FpdCBzdGFydFdhc2lUYXNrKCk7Cn0KbWFpbigpOwo=")! - public static let test: Data = Data(base64Encoded: "Ly8gbm9kZV9tb2R1bGVzL3JlY29ubmVjdGluZy13ZWJzb2NrZXQvZGlzdC9yZWNvbm5lY3Rpbmctd2Vic29ja2V0LW1qcy5qcwp2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHsKICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24oZDIsIGIyKSB7CiAgICBkMi5fX3Byb3RvX18gPSBiMjsKICB9IHx8IGZ1bmN0aW9uKGQyLCBiMikgewogICAgZm9yICh2YXIgcCBpbiBiMikKICAgICAgaWYgKGIyLmhhc093blByb3BlcnR5KHApKQogICAgICAgIGQyW3BdID0gYjJbcF07CiAgfTsKICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTsKfTsKZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHsKICBleHRlbmRTdGF0aWNzKGQsIGIpOwogIGZ1bmN0aW9uIF9fKCkgewogICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7CiAgfQogIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTsKfQpmdW5jdGlvbiBfX3ZhbHVlcyhvKSB7CiAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSAiZnVuY3Rpb24iICYmIG9bU3ltYm9sLml0ZXJhdG9yXSwgaSA9IDA7CiAgaWYgKG0pCiAgICByZXR1cm4gbS5jYWxsKG8pOwogIHJldHVybiB7CiAgICBuZXh0OiBmdW5jdGlvbigpIHsKICAgICAgaWYgKG8gJiYgaSA+PSBvLmxlbmd0aCkKICAgICAgICBvID0gdm9pZCAwOwogICAgICByZXR1cm4geyB2YWx1ZTogbyAmJiBvW2krK10sIGRvbmU6ICFvIH07CiAgICB9CiAgfTsKfQpmdW5jdGlvbiBfX3JlYWQobywgbikgewogIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gImZ1bmN0aW9uIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07CiAgaWYgKCFtKQogICAgcmV0dXJuIG87CiAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7CiAgdHJ5IHsKICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKQogICAgICBhci5wdXNoKHIudmFsdWUpOwogIH0gY2F0Y2ggKGVycm9yKSB7CiAgICBlID0geyBlcnJvciB9OwogIH0gZmluYWxseSB7CiAgICB0cnkgewogICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVsicmV0dXJuIl0pKQogICAgICAgIG0uY2FsbChpKTsKICAgIH0gZmluYWxseSB7CiAgICAgIGlmIChlKQogICAgICAgIHRocm93IGUuZXJyb3I7CiAgICB9CiAgfQogIHJldHVybiBhcjsKfQpmdW5jdGlvbiBfX3NwcmVhZCgpIHsKICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykKICAgIGFyID0gYXIuY29uY2F0KF9fcmVhZChhcmd1bWVudHNbaV0pKTsKICByZXR1cm4gYXI7Cn0KdmFyIEV2ZW50ID0gZnVuY3Rpb24oKSB7CiAgZnVuY3Rpb24gRXZlbnQyKHR5cGUsIHRhcmdldCkgewogICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7CiAgICB0aGlzLnR5cGUgPSB0eXBlOwogIH0KICByZXR1cm4gRXZlbnQyOwp9KCk7CnZhciBFcnJvckV2ZW50ID0gZnVuY3Rpb24oX3N1cGVyKSB7CiAgX19leHRlbmRzKEVycm9yRXZlbnQyLCBfc3VwZXIpOwogIGZ1bmN0aW9uIEVycm9yRXZlbnQyKGVycm9yLCB0YXJnZXQpIHsKICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsICJlcnJvciIsIHRhcmdldCkgfHwgdGhpczsKICAgIF90aGlzLm1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlOwogICAgX3RoaXMuZXJyb3IgPSBlcnJvcjsKICAgIHJldHVybiBfdGhpczsKICB9CiAgcmV0dXJuIEVycm9yRXZlbnQyOwp9KEV2ZW50KTsKdmFyIENsb3NlRXZlbnQgPSBmdW5jdGlvbihfc3VwZXIpIHsKICBfX2V4dGVuZHMoQ2xvc2VFdmVudDIsIF9zdXBlcik7CiAgZnVuY3Rpb24gQ2xvc2VFdmVudDIoY29kZSwgcmVhc29uLCB0YXJnZXQpIHsKICAgIGlmIChjb2RlID09PSB2b2lkIDApIHsKICAgICAgY29kZSA9IDFlMzsKICAgIH0KICAgIGlmIChyZWFzb24gPT09IHZvaWQgMCkgewogICAgICByZWFzb24gPSAiIjsKICAgIH0KICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsICJjbG9zZSIsIHRhcmdldCkgfHwgdGhpczsKICAgIF90aGlzLndhc0NsZWFuID0gdHJ1ZTsKICAgIF90aGlzLmNvZGUgPSBjb2RlOwogICAgX3RoaXMucmVhc29uID0gcmVhc29uOwogICAgcmV0dXJuIF90aGlzOwogIH0KICByZXR1cm4gQ2xvc2VFdmVudDI7Cn0oRXZlbnQpOwp2YXIgZ2V0R2xvYmFsV2ViU29ja2V0ID0gZnVuY3Rpb24oKSB7CiAgaWYgKHR5cGVvZiBXZWJTb2NrZXQgIT09ICJ1bmRlZmluZWQiKSB7CiAgICByZXR1cm4gV2ViU29ja2V0OwogIH0KfTsKdmFyIGlzV2ViU29ja2V0ID0gZnVuY3Rpb24odykgewogIHJldHVybiB0eXBlb2YgdyAhPT0gInVuZGVmaW5lZCIgJiYgISF3ICYmIHcuQ0xPU0lORyA9PT0gMjsKfTsKdmFyIERFRkFVTFQgPSB7CiAgbWF4UmVjb25uZWN0aW9uRGVsYXk6IDFlNCwKICBtaW5SZWNvbm5lY3Rpb25EZWxheTogMWUzICsgTWF0aC5yYW5kb20oKSAqIDRlMywKICBtaW5VcHRpbWU6IDVlMywKICByZWNvbm5lY3Rpb25EZWxheUdyb3dGYWN0b3I6IDEuMywKICBjb25uZWN0aW9uVGltZW91dDogNGUzLAogIG1heFJldHJpZXM6IEluZmluaXR5LAogIG1heEVucXVldWVkTWVzc2FnZXM6IEluZmluaXR5LAogIHN0YXJ0Q2xvc2VkOiBmYWxzZSwKICBkZWJ1ZzogZmFsc2UKfTsKdmFyIFJlY29ubmVjdGluZ1dlYlNvY2tldCA9IGZ1bmN0aW9uKCkgewogIGZ1bmN0aW9uIFJlY29ubmVjdGluZ1dlYlNvY2tldDIodXJsLCBwcm90b2NvbHMsIG9wdGlvbnMpIHsKICAgIHZhciBfdGhpcyA9IHRoaXM7CiAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgIG9wdGlvbnMgPSB7fTsKICAgIH0KICAgIHRoaXMuX2xpc3RlbmVycyA9IHsKICAgICAgZXJyb3I6IFtdLAogICAgICBtZXNzYWdlOiBbXSwKICAgICAgb3BlbjogW10sCiAgICAgIGNsb3NlOiBbXQogICAgfTsKICAgIHRoaXMuX3JldHJ5Q291bnQgPSAtMTsKICAgIHRoaXMuX3Nob3VsZFJlY29ubmVjdCA9IHRydWU7CiAgICB0aGlzLl9jb25uZWN0TG9jayA9IGZhbHNlOwogICAgdGhpcy5fYmluYXJ5VHlwZSA9ICJibG9iIjsKICAgIHRoaXMuX2Nsb3NlQ2FsbGVkID0gZmFsc2U7CiAgICB0aGlzLl9tZXNzYWdlUXVldWUgPSBbXTsKICAgIHRoaXMub25jbG9zZSA9IG51bGw7CiAgICB0aGlzLm9uZXJyb3IgPSBudWxsOwogICAgdGhpcy5vbm1lc3NhZ2UgPSBudWxsOwogICAgdGhpcy5vbm9wZW4gPSBudWxsOwogICAgdGhpcy5faGFuZGxlT3BlbiA9IGZ1bmN0aW9uKGV2ZW50KSB7CiAgICAgIF90aGlzLl9kZWJ1Zygib3BlbiBldmVudCIpOwogICAgICB2YXIgX2EgPSBfdGhpcy5fb3B0aW9ucy5taW5VcHRpbWUsIG1pblVwdGltZSA9IF9hID09PSB2b2lkIDAgPyBERUZBVUxULm1pblVwdGltZSA6IF9hOwogICAgICBjbGVhclRpbWVvdXQoX3RoaXMuX2Nvbm5lY3RUaW1lb3V0KTsKICAgICAgX3RoaXMuX3VwdGltZVRpbWVvdXQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiBfdGhpcy5fYWNjZXB0T3BlbigpOwogICAgICB9LCBtaW5VcHRpbWUpOwogICAgICBfdGhpcy5fd3MuYmluYXJ5VHlwZSA9IF90aGlzLl9iaW5hcnlUeXBlOwogICAgICBfdGhpcy5fbWVzc2FnZVF1ZXVlLmZvckVhY2goZnVuY3Rpb24obWVzc2FnZSkgewogICAgICAgIHJldHVybiBfdGhpcy5fd3Muc2VuZChtZXNzYWdlKTsKICAgICAgfSk7CiAgICAgIF90aGlzLl9tZXNzYWdlUXVldWUgPSBbXTsKICAgICAgaWYgKF90aGlzLm9ub3BlbikgewogICAgICAgIF90aGlzLm9ub3BlbihldmVudCk7CiAgICAgIH0KICAgICAgX3RoaXMuX2xpc3RlbmVycy5vcGVuLmZvckVhY2goZnVuY3Rpb24obGlzdGVuZXIpIHsKICAgICAgICByZXR1cm4gX3RoaXMuX2NhbGxFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcik7CiAgICAgIH0pOwogICAgfTsKICAgIHRoaXMuX2hhbmRsZU1lc3NhZ2UgPSBmdW5jdGlvbihldmVudCkgewogICAgICBfdGhpcy5fZGVidWcoIm1lc3NhZ2UgZXZlbnQiKTsKICAgICAgaWYgKF90aGlzLm9ubWVzc2FnZSkgewogICAgICAgIF90aGlzLm9ubWVzc2FnZShldmVudCk7CiAgICAgIH0KICAgICAgX3RoaXMuX2xpc3RlbmVycy5tZXNzYWdlLmZvckVhY2goZnVuY3Rpb24obGlzdGVuZXIpIHsKICAgICAgICByZXR1cm4gX3RoaXMuX2NhbGxFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcik7CiAgICAgIH0pOwogICAgfTsKICAgIHRoaXMuX2hhbmRsZUVycm9yID0gZnVuY3Rpb24oZXZlbnQpIHsKICAgICAgX3RoaXMuX2RlYnVnKCJlcnJvciBldmVudCIsIGV2ZW50Lm1lc3NhZ2UpOwogICAgICBfdGhpcy5fZGlzY29ubmVjdCh2b2lkIDAsIGV2ZW50Lm1lc3NhZ2UgPT09ICJUSU1FT1VUIiA/ICJ0aW1lb3V0IiA6IHZvaWQgMCk7CiAgICAgIGlmIChfdGhpcy5vbmVycm9yKSB7CiAgICAgICAgX3RoaXMub25lcnJvcihldmVudCk7CiAgICAgIH0KICAgICAgX3RoaXMuX2RlYnVnKCJleGVjIGVycm9yIGxpc3RlbmVycyIpOwogICAgICBfdGhpcy5fbGlzdGVuZXJzLmVycm9yLmZvckVhY2goZnVuY3Rpb24obGlzdGVuZXIpIHsKICAgICAgICByZXR1cm4gX3RoaXMuX2NhbGxFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcik7CiAgICAgIH0pOwogICAgICBfdGhpcy5fY29ubmVjdCgpOwogICAgfTsKICAgIHRoaXMuX2hhbmRsZUNsb3NlID0gZnVuY3Rpb24oZXZlbnQpIHsKICAgICAgX3RoaXMuX2RlYnVnKCJjbG9zZSBldmVudCIpOwogICAgICBfdGhpcy5fY2xlYXJUaW1lb3V0cygpOwogICAgICBpZiAoX3RoaXMuX3Nob3VsZFJlY29ubmVjdCkgewogICAgICAgIF90aGlzLl9jb25uZWN0KCk7CiAgICAgIH0KICAgICAgaWYgKF90aGlzLm9uY2xvc2UpIHsKICAgICAgICBfdGhpcy5vbmNsb3NlKGV2ZW50KTsKICAgICAgfQogICAgICBfdGhpcy5fbGlzdGVuZXJzLmNsb3NlLmZvckVhY2goZnVuY3Rpb24obGlzdGVuZXIpIHsKICAgICAgICByZXR1cm4gX3RoaXMuX2NhbGxFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcik7CiAgICAgIH0pOwogICAgfTsKICAgIHRoaXMuX3VybCA9IHVybDsKICAgIHRoaXMuX3Byb3RvY29scyA9IHByb3RvY29sczsKICAgIHRoaXMuX29wdGlvbnMgPSBvcHRpb25zOwogICAgaWYgKHRoaXMuX29wdGlvbnMuc3RhcnRDbG9zZWQpIHsKICAgICAgdGhpcy5fc2hvdWxkUmVjb25uZWN0ID0gZmFsc2U7CiAgICB9CiAgICB0aGlzLl9jb25uZWN0KCk7CiAgfQogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLCAiQ09OTkVDVElORyIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiAwOwogICAgfSwKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBjb25maWd1cmFibGU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoUmVjb25uZWN0aW5nV2ViU29ja2V0MiwgIk9QRU4iLCB7CiAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gMTsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIsICJDTE9TSU5HIiwgewogICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgcmV0dXJuIDI7CiAgICB9LAogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLCAiQ0xPU0VEIiwgewogICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgcmV0dXJuIDM7CiAgICB9LAogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZSwgIkNPTk5FQ1RJTkciLCB7CiAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5DT05ORUNUSU5HOwogICAgfSwKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBjb25maWd1cmFibGU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUsICJPUEVOIiwgewogICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgcmV0dXJuIFJlY29ubmVjdGluZ1dlYlNvY2tldDIuT1BFTjsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAiQ0xPU0lORyIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLkNMT1NJTkc7CiAgICB9LAogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZSwgIkNMT1NFRCIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLkNMT1NFRDsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAiYmluYXJ5VHlwZSIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiB0aGlzLl93cyA/IHRoaXMuX3dzLmJpbmFyeVR5cGUgOiB0aGlzLl9iaW5hcnlUeXBlOwogICAgfSwKICAgIHNldDogZnVuY3Rpb24odmFsdWUpIHsKICAgICAgdGhpcy5fYmluYXJ5VHlwZSA9IHZhbHVlOwogICAgICBpZiAodGhpcy5fd3MpIHsKICAgICAgICB0aGlzLl93cy5iaW5hcnlUeXBlID0gdmFsdWU7CiAgICAgIH0KICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAicmV0cnlDb3VudCIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiBNYXRoLm1heCh0aGlzLl9yZXRyeUNvdW50LCAwKTsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAiYnVmZmVyZWRBbW91bnQiLCB7CiAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICB2YXIgYnl0ZXMgPSB0aGlzLl9tZXNzYWdlUXVldWUucmVkdWNlKGZ1bmN0aW9uKGFjYywgbWVzc2FnZSkgewogICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSA9PT0gInN0cmluZyIpIHsKICAgICAgICAgIGFjYyArPSBtZXNzYWdlLmxlbmd0aDsKICAgICAgICB9IGVsc2UgaWYgKG1lc3NhZ2UgaW5zdGFuY2VvZiBCbG9iKSB7CiAgICAgICAgICBhY2MgKz0gbWVzc2FnZS5zaXplOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBhY2MgKz0gbWVzc2FnZS5ieXRlTGVuZ3RoOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYWNjOwogICAgICB9LCAwKTsKICAgICAgcmV0dXJuIGJ5dGVzICsgKHRoaXMuX3dzID8gdGhpcy5fd3MuYnVmZmVyZWRBbW91bnQgOiAwKTsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAiZXh0ZW5zaW9ucyIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiB0aGlzLl93cyA/IHRoaXMuX3dzLmV4dGVuc2lvbnMgOiAiIjsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAicHJvdG9jb2wiLCB7CiAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gdGhpcy5fd3MgPyB0aGlzLl93cy5wcm90b2NvbCA6ICIiOwogICAgfSwKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBjb25maWd1cmFibGU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUsICJyZWFkeVN0YXRlIiwgewogICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgaWYgKHRoaXMuX3dzKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX3dzLnJlYWR5U3RhdGU7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuc3RhcnRDbG9zZWQgPyBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLkNMT1NFRCA6IFJlY29ubmVjdGluZ1dlYlNvY2tldDIuQ09OTkVDVElORzsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAidXJsIiwgewogICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgcmV0dXJuIHRoaXMuX3dzID8gdGhpcy5fd3MudXJsIDogIiI7CiAgICB9LAogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZQogIH0pOwogIFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLmNsb3NlID0gZnVuY3Rpb24oY29kZSwgcmVhc29uKSB7CiAgICBpZiAoY29kZSA9PT0gdm9pZCAwKSB7CiAgICAgIGNvZGUgPSAxZTM7CiAgICB9CiAgICB0aGlzLl9jbG9zZUNhbGxlZCA9IHRydWU7CiAgICB0aGlzLl9zaG91bGRSZWNvbm5lY3QgPSBmYWxzZTsKICAgIHRoaXMuX2NsZWFyVGltZW91dHMoKTsKICAgIGlmICghdGhpcy5fd3MpIHsKICAgICAgdGhpcy5fZGVidWcoImNsb3NlIGVucXVldWVkOiBubyB3cyBpbnN0YW5jZSIpOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAodGhpcy5fd3MucmVhZHlTdGF0ZSA9PT0gdGhpcy5DTE9TRUQpIHsKICAgICAgdGhpcy5fZGVidWcoImNsb3NlOiBhbHJlYWR5IGNsb3NlZCIpOwogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl93cy5jbG9zZShjb2RlLCByZWFzb24pOwogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUucmVjb25uZWN0ID0gZnVuY3Rpb24oY29kZSwgcmVhc29uKSB7CiAgICB0aGlzLl9zaG91bGRSZWNvbm5lY3QgPSB0cnVlOwogICAgdGhpcy5fY2xvc2VDYWxsZWQgPSBmYWxzZTsKICAgIHRoaXMuX3JldHJ5Q291bnQgPSAtMTsKICAgIGlmICghdGhpcy5fd3MgfHwgdGhpcy5fd3MucmVhZHlTdGF0ZSA9PT0gdGhpcy5DTE9TRUQpIHsKICAgICAgdGhpcy5fY29ubmVjdCgpOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5fZGlzY29ubmVjdChjb2RlLCByZWFzb24pOwogICAgICB0aGlzLl9jb25uZWN0KCk7CiAgICB9CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5zZW5kID0gZnVuY3Rpb24oZGF0YSkgewogICAgaWYgKHRoaXMuX3dzICYmIHRoaXMuX3dzLnJlYWR5U3RhdGUgPT09IHRoaXMuT1BFTikgewogICAgICB0aGlzLl9kZWJ1Zygic2VuZCIsIGRhdGEpOwogICAgICB0aGlzLl93cy5zZW5kKGRhdGEpOwogICAgfSBlbHNlIHsKICAgICAgdmFyIF9hID0gdGhpcy5fb3B0aW9ucy5tYXhFbnF1ZXVlZE1lc3NhZ2VzLCBtYXhFbnF1ZXVlZE1lc3NhZ2VzID0gX2EgPT09IHZvaWQgMCA/IERFRkFVTFQubWF4RW5xdWV1ZWRNZXNzYWdlcyA6IF9hOwogICAgICBpZiAodGhpcy5fbWVzc2FnZVF1ZXVlLmxlbmd0aCA8IG1heEVucXVldWVkTWVzc2FnZXMpIHsKICAgICAgICB0aGlzLl9kZWJ1ZygiZW5xdWV1ZSIsIGRhdGEpOwogICAgICAgIHRoaXMuX21lc3NhZ2VRdWV1ZS5wdXNoKGRhdGEpOwogICAgICB9CiAgICB9CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5hZGRFdmVudExpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHsKICAgIGlmICh0aGlzLl9saXN0ZW5lcnNbdHlwZV0pIHsKICAgICAgdGhpcy5fbGlzdGVuZXJzW3R5cGVdLnB1c2gobGlzdGVuZXIpOwogICAgfQogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuZGlzcGF0Y2hFdmVudCA9IGZ1bmN0aW9uKGV2ZW50KSB7CiAgICB2YXIgZV8xLCBfYTsKICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLl9saXN0ZW5lcnNbZXZlbnQudHlwZV07CiAgICBpZiAobGlzdGVuZXJzKSB7CiAgICAgIHRyeSB7CiAgICAgICAgZm9yICh2YXIgbGlzdGVuZXJzXzEgPSBfX3ZhbHVlcyhsaXN0ZW5lcnMpLCBsaXN0ZW5lcnNfMV8xID0gbGlzdGVuZXJzXzEubmV4dCgpOyAhbGlzdGVuZXJzXzFfMS5kb25lOyBsaXN0ZW5lcnNfMV8xID0gbGlzdGVuZXJzXzEubmV4dCgpKSB7CiAgICAgICAgICB2YXIgbGlzdGVuZXIgPSBsaXN0ZW5lcnNfMV8xLnZhbHVlOwogICAgICAgICAgdGhpcy5fY2FsbEV2ZW50TGlzdGVuZXIoZXZlbnQsIGxpc3RlbmVyKTsKICAgICAgICB9CiAgICAgIH0gY2F0Y2ggKGVfMV8xKSB7CiAgICAgICAgZV8xID0geyBlcnJvcjogZV8xXzEgfTsKICAgICAgfSBmaW5hbGx5IHsKICAgICAgICB0cnkgewogICAgICAgICAgaWYgKGxpc3RlbmVyc18xXzEgJiYgIWxpc3RlbmVyc18xXzEuZG9uZSAmJiAoX2EgPSBsaXN0ZW5lcnNfMS5yZXR1cm4pKQogICAgICAgICAgICBfYS5jYWxsKGxpc3RlbmVyc18xKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgaWYgKGVfMSkKICAgICAgICAgICAgdGhyb3cgZV8xLmVycm9yOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIHRydWU7CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5yZW1vdmVFdmVudExpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHsKICAgIGlmICh0aGlzLl9saXN0ZW5lcnNbdHlwZV0pIHsKICAgICAgdGhpcy5fbGlzdGVuZXJzW3R5cGVdID0gdGhpcy5fbGlzdGVuZXJzW3R5cGVdLmZpbHRlcihmdW5jdGlvbihsKSB7CiAgICAgICAgcmV0dXJuIGwgIT09IGxpc3RlbmVyOwogICAgICB9KTsKICAgIH0KICB9OwogIFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLl9kZWJ1ZyA9IGZ1bmN0aW9uKCkgewogICAgdmFyIGFyZ3MgPSBbXTsKICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7CiAgICAgIGFyZ3NbX2ldID0gYXJndW1lbnRzW19pXTsKICAgIH0KICAgIGlmICh0aGlzLl9vcHRpb25zLmRlYnVnKSB7CiAgICAgIGNvbnNvbGUubG9nLmFwcGx5KGNvbnNvbGUsIF9fc3ByZWFkKFsiUldTPiJdLCBhcmdzKSk7CiAgICB9CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5fZ2V0TmV4dERlbGF5ID0gZnVuY3Rpb24oKSB7CiAgICB2YXIgX2EgPSB0aGlzLl9vcHRpb25zLCBfYiA9IF9hLnJlY29ubmVjdGlvbkRlbGF5R3Jvd0ZhY3RvciwgcmVjb25uZWN0aW9uRGVsYXlHcm93RmFjdG9yID0gX2IgPT09IHZvaWQgMCA/IERFRkFVTFQucmVjb25uZWN0aW9uRGVsYXlHcm93RmFjdG9yIDogX2IsIF9jID0gX2EubWluUmVjb25uZWN0aW9uRGVsYXksIG1pblJlY29ubmVjdGlvbkRlbGF5ID0gX2MgPT09IHZvaWQgMCA/IERFRkFVTFQubWluUmVjb25uZWN0aW9uRGVsYXkgOiBfYywgX2QgPSBfYS5tYXhSZWNvbm5lY3Rpb25EZWxheSwgbWF4UmVjb25uZWN0aW9uRGVsYXkgPSBfZCA9PT0gdm9pZCAwID8gREVGQVVMVC5tYXhSZWNvbm5lY3Rpb25EZWxheSA6IF9kOwogICAgdmFyIGRlbGF5ID0gMDsKICAgIGlmICh0aGlzLl9yZXRyeUNvdW50ID4gMCkgewogICAgICBkZWxheSA9IG1pblJlY29ubmVjdGlvbkRlbGF5ICogTWF0aC5wb3cocmVjb25uZWN0aW9uRGVsYXlHcm93RmFjdG9yLCB0aGlzLl9yZXRyeUNvdW50IC0gMSk7CiAgICAgIGlmIChkZWxheSA+IG1heFJlY29ubmVjdGlvbkRlbGF5KSB7CiAgICAgICAgZGVsYXkgPSBtYXhSZWNvbm5lY3Rpb25EZWxheTsKICAgICAgfQogICAgfQogICAgdGhpcy5fZGVidWcoIm5leHQgZGVsYXkiLCBkZWxheSk7CiAgICByZXR1cm4gZGVsYXk7CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5fd2FpdCA9IGZ1bmN0aW9uKCkgewogICAgdmFyIF90aGlzID0gdGhpczsKICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlKSB7CiAgICAgIHNldFRpbWVvdXQocmVzb2x2ZSwgX3RoaXMuX2dldE5leHREZWxheSgpKTsKICAgIH0pOwogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuX2dldE5leHRVcmwgPSBmdW5jdGlvbih1cmxQcm92aWRlcikgewogICAgaWYgKHR5cGVvZiB1cmxQcm92aWRlciA9PT0gInN0cmluZyIpIHsKICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh1cmxQcm92aWRlcik7CiAgICB9CiAgICBpZiAodHlwZW9mIHVybFByb3ZpZGVyID09PSAiZnVuY3Rpb24iKSB7CiAgICAgIHZhciB1cmwgPSB1cmxQcm92aWRlcigpOwogICAgICBpZiAodHlwZW9mIHVybCA9PT0gInN0cmluZyIpIHsKICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHVybCk7CiAgICAgIH0KICAgICAgaWYgKCEhdXJsLnRoZW4pIHsKICAgICAgICByZXR1cm4gdXJsOwogICAgICB9CiAgICB9CiAgICB0aHJvdyBFcnJvcigiSW52YWxpZCBVUkwiKTsKICB9OwogIFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLl9jb25uZWN0ID0gZnVuY3Rpb24oKSB7CiAgICB2YXIgX3RoaXMgPSB0aGlzOwogICAgaWYgKHRoaXMuX2Nvbm5lY3RMb2NrIHx8ICF0aGlzLl9zaG91bGRSZWNvbm5lY3QpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5fY29ubmVjdExvY2sgPSB0cnVlOwogICAgdmFyIF9hID0gdGhpcy5fb3B0aW9ucywgX2IgPSBfYS5tYXhSZXRyaWVzLCBtYXhSZXRyaWVzID0gX2IgPT09IHZvaWQgMCA/IERFRkFVTFQubWF4UmV0cmllcyA6IF9iLCBfYyA9IF9hLmNvbm5lY3Rpb25UaW1lb3V0LCBjb25uZWN0aW9uVGltZW91dCA9IF9jID09PSB2b2lkIDAgPyBERUZBVUxULmNvbm5lY3Rpb25UaW1lb3V0IDogX2MsIF9kID0gX2EuV2ViU29ja2V0LCBXZWJTb2NrZXQyID0gX2QgPT09IHZvaWQgMCA/IGdldEdsb2JhbFdlYlNvY2tldCgpIDogX2Q7CiAgICBpZiAodGhpcy5fcmV0cnlDb3VudCA+PSBtYXhSZXRyaWVzKSB7CiAgICAgIHRoaXMuX2RlYnVnKCJtYXggcmV0cmllcyByZWFjaGVkIiwgdGhpcy5fcmV0cnlDb3VudCwgIj49IiwgbWF4UmV0cmllcyk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuX3JldHJ5Q291bnQrKzsKICAgIHRoaXMuX2RlYnVnKCJjb25uZWN0IiwgdGhpcy5fcmV0cnlDb3VudCk7CiAgICB0aGlzLl9yZW1vdmVMaXN0ZW5lcnMoKTsKICAgIGlmICghaXNXZWJTb2NrZXQoV2ViU29ja2V0MikpIHsKICAgICAgdGhyb3cgRXJyb3IoIk5vIHZhbGlkIFdlYlNvY2tldCBjbGFzcyBwcm92aWRlZCIpOwogICAgfQogICAgdGhpcy5fd2FpdCgpLnRoZW4oZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiBfdGhpcy5fZ2V0TmV4dFVybChfdGhpcy5fdXJsKTsKICAgIH0pLnRoZW4oZnVuY3Rpb24odXJsKSB7CiAgICAgIGlmIChfdGhpcy5fY2xvc2VDYWxsZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgX3RoaXMuX2RlYnVnKCJjb25uZWN0IiwgeyB1cmwsIHByb3RvY29sczogX3RoaXMuX3Byb3RvY29scyB9KTsKICAgICAgX3RoaXMuX3dzID0gX3RoaXMuX3Byb3RvY29scyA/IG5ldyBXZWJTb2NrZXQyKHVybCwgX3RoaXMuX3Byb3RvY29scykgOiBuZXcgV2ViU29ja2V0Mih1cmwpOwogICAgICBfdGhpcy5fd3MuYmluYXJ5VHlwZSA9IF90aGlzLl9iaW5hcnlUeXBlOwogICAgICBfdGhpcy5fY29ubmVjdExvY2sgPSBmYWxzZTsKICAgICAgX3RoaXMuX2FkZExpc3RlbmVycygpOwogICAgICBfdGhpcy5fY29ubmVjdFRpbWVvdXQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiBfdGhpcy5faGFuZGxlVGltZW91dCgpOwogICAgICB9LCBjb25uZWN0aW9uVGltZW91dCk7CiAgICB9KTsKICB9OwogIFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLl9oYW5kbGVUaW1lb3V0ID0gZnVuY3Rpb24oKSB7CiAgICB0aGlzLl9kZWJ1ZygidGltZW91dCBldmVudCIpOwogICAgdGhpcy5faGFuZGxlRXJyb3IobmV3IEVycm9yRXZlbnQoRXJyb3IoIlRJTUVPVVQiKSwgdGhpcykpOwogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuX2Rpc2Nvbm5lY3QgPSBmdW5jdGlvbihjb2RlLCByZWFzb24pIHsKICAgIGlmIChjb2RlID09PSB2b2lkIDApIHsKICAgICAgY29kZSA9IDFlMzsKICAgIH0KICAgIHRoaXMuX2NsZWFyVGltZW91dHMoKTsKICAgIGlmICghdGhpcy5fd3MpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5fcmVtb3ZlTGlzdGVuZXJzKCk7CiAgICB0cnkgewogICAgICB0aGlzLl93cy5jbG9zZShjb2RlLCByZWFzb24pOwogICAgICB0aGlzLl9oYW5kbGVDbG9zZShuZXcgQ2xvc2VFdmVudChjb2RlLCByZWFzb24sIHRoaXMpKTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICB9CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5fYWNjZXB0T3BlbiA9IGZ1bmN0aW9uKCkgewogICAgdGhpcy5fZGVidWcoImFjY2VwdCBvcGVuIik7CiAgICB0aGlzLl9yZXRyeUNvdW50ID0gMDsKICB9OwogIFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLl9jYWxsRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uKGV2ZW50LCBsaXN0ZW5lcikgewogICAgaWYgKCJoYW5kbGVFdmVudCIgaW4gbGlzdGVuZXIpIHsKICAgICAgbGlzdGVuZXIuaGFuZGxlRXZlbnQoZXZlbnQpOwogICAgfSBlbHNlIHsKICAgICAgbGlzdGVuZXIoZXZlbnQpOwogICAgfQogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuX3JlbW92ZUxpc3RlbmVycyA9IGZ1bmN0aW9uKCkgewogICAgaWYgKCF0aGlzLl93cykgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9kZWJ1ZygicmVtb3ZlTGlzdGVuZXJzIik7CiAgICB0aGlzLl93cy5yZW1vdmVFdmVudExpc3RlbmVyKCJvcGVuIiwgdGhpcy5faGFuZGxlT3Blbik7CiAgICB0aGlzLl93cy5yZW1vdmVFdmVudExpc3RlbmVyKCJjbG9zZSIsIHRoaXMuX2hhbmRsZUNsb3NlKTsKICAgIHRoaXMuX3dzLnJlbW92ZUV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLCB0aGlzLl9oYW5kbGVNZXNzYWdlKTsKICAgIHRoaXMuX3dzLnJlbW92ZUV2ZW50TGlzdGVuZXIoImVycm9yIiwgdGhpcy5faGFuZGxlRXJyb3IpOwogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuX2FkZExpc3RlbmVycyA9IGZ1bmN0aW9uKCkgewogICAgaWYgKCF0aGlzLl93cykgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9kZWJ1ZygiYWRkTGlzdGVuZXJzIik7CiAgICB0aGlzLl93cy5hZGRFdmVudExpc3RlbmVyKCJvcGVuIiwgdGhpcy5faGFuZGxlT3Blbik7CiAgICB0aGlzLl93cy5hZGRFdmVudExpc3RlbmVyKCJjbG9zZSIsIHRoaXMuX2hhbmRsZUNsb3NlKTsKICAgIHRoaXMuX3dzLmFkZEV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLCB0aGlzLl9oYW5kbGVNZXNzYWdlKTsKICAgIHRoaXMuX3dzLmFkZEV2ZW50TGlzdGVuZXIoImVycm9yIiwgdGhpcy5faGFuZGxlRXJyb3IpOwogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuX2NsZWFyVGltZW91dHMgPSBmdW5jdGlvbigpIHsKICAgIGNsZWFyVGltZW91dCh0aGlzLl9jb25uZWN0VGltZW91dCk7CiAgICBjbGVhclRpbWVvdXQodGhpcy5fdXB0aW1lVGltZW91dCk7CiAgfTsKICByZXR1cm4gUmVjb25uZWN0aW5nV2ViU29ja2V0MjsKfSgpOwp2YXIgcmVjb25uZWN0aW5nX3dlYnNvY2tldF9tanNfZGVmYXVsdCA9IFJlY29ubmVjdGluZ1dlYlNvY2tldDsKCi8vIG5vZGVfbW9kdWxlcy9AYmpvcm4zL2Jyb3dzZXJfd2FzaV9zaGltL2Rpc3Qvd2FzaV9kZWZzLmpzCnZhciBDTE9DS0lEX1JFQUxUSU1FID0gMDsKdmFyIENMT0NLSURfTU9OT1RPTklDID0gMTsKdmFyIEVSUk5PX1NVQ0NFU1MgPSAwOwp2YXIgRVJSTk9fQkFERiA9IDg7CnZhciBFUlJOT19FWElTVCA9IDIwOwp2YXIgRVJSTk9fSU5WQUwgPSAyODsKdmFyIEVSUk5PX0lTRElSID0gMzE7CnZhciBFUlJOT19OQU1FVE9PTE9ORyA9IDM3Owp2YXIgRVJSTk9fTk9FTlQgPSA0NDsKdmFyIEVSUk5PX05PU1lTID0gNTI7CnZhciBFUlJOT19OT1RESVIgPSA1NDsKdmFyIEVSUk5PX05PVEVNUFRZID0gNTU7CnZhciBFUlJOT19OT1RTVVAgPSA1ODsKdmFyIEVSUk5PX1BFUk0gPSA2MzsKdmFyIEVSUk5PX05PVENBUEFCTEUgPSA3NjsKdmFyIFJJR0hUU19GRF9EQVRBU1lOQyA9IDEgPDwgMDsKdmFyIFJJR0hUU19GRF9SRUFEID0gMSA8PCAxOwp2YXIgUklHSFRTX0ZEX1NFRUsgPSAxIDw8IDI7CnZhciBSSUdIVFNfRkRfRkRTVEFUX1NFVF9GTEFHUyA9IDEgPDwgMzsKdmFyIFJJR0hUU19GRF9TWU5DID0gMSA8PCA0Owp2YXIgUklHSFRTX0ZEX1RFTEwgPSAxIDw8IDU7CnZhciBSSUdIVFNfRkRfV1JJVEUgPSAxIDw8IDY7CnZhciBSSUdIVFNfRkRfQURWSVNFID0gMSA8PCA3Owp2YXIgUklHSFRTX0ZEX0FMTE9DQVRFID0gMSA8PCA4Owp2YXIgUklHSFRTX1BBVEhfQ1JFQVRFX0RJUkVDVE9SWSA9IDEgPDwgOTsKdmFyIFJJR0hUU19QQVRIX0NSRUFURV9GSUxFID0gMSA8PCAxMDsKdmFyIFJJR0hUU19QQVRIX0xJTktfU09VUkNFID0gMSA8PCAxMTsKdmFyIFJJR0hUU19QQVRIX0xJTktfVEFSR0VUID0gMSA8PCAxMjsKdmFyIFJJR0hUU19QQVRIX09QRU4gPSAxIDw8IDEzOwp2YXIgUklHSFRTX0ZEX1JFQURESVIgPSAxIDw8IDE0Owp2YXIgUklHSFRTX1BBVEhfUkVBRExJTksgPSAxIDw8IDE1Owp2YXIgUklHSFRTX1BBVEhfUkVOQU1FX1NPVVJDRSA9IDEgPDwgMTY7CnZhciBSSUdIVFNfUEFUSF9SRU5BTUVfVEFSR0VUID0gMSA8PCAxNzsKdmFyIFJJR0hUU19QQVRIX0ZJTEVTVEFUX0dFVCA9IDEgPDwgMTg7CnZhciBSSUdIVFNfUEFUSF9GSUxFU1RBVF9TRVRfU0laRSA9IDEgPDwgMTk7CnZhciBSSUdIVFNfUEFUSF9GSUxFU1RBVF9TRVRfVElNRVMgPSAxIDw8IDIwOwp2YXIgUklHSFRTX0ZEX0ZJTEVTVEFUX0dFVCA9IDEgPDwgMjE7CnZhciBSSUdIVFNfRkRfRklMRVNUQVRfU0VUX1NJWkUgPSAxIDw8IDIyOwp2YXIgUklHSFRTX0ZEX0ZJTEVTVEFUX1NFVF9USU1FUyA9IDEgPDwgMjM7CnZhciBSSUdIVFNfUEFUSF9TWU1MSU5LID0gMSA8PCAyNDsKdmFyIFJJR0hUU19QQVRIX1JFTU9WRV9ESVJFQ1RPUlkgPSAxIDw8IDI1Owp2YXIgUklHSFRTX1BBVEhfVU5MSU5LX0ZJTEUgPSAxIDw8IDI2Owp2YXIgUklHSFRTX1BPTExfRkRfUkVBRFdSSVRFID0gMSA8PCAyNzsKdmFyIFJJR0hUU19TT0NLX1NIVVRET1dOID0gMSA8PCAyODsKdmFyIElvdmVjID0gY2xhc3MgewogIHN0YXRpYyByZWFkX2J5dGVzKHZpZXcsIHB0cikgewogICAgY29uc3QgaW92ZWMgPSBuZXcgSW92ZWMoKTsKICAgIGlvdmVjLmJ1ZiA9IHZpZXcuZ2V0VWludDMyKHB0ciwgdHJ1ZSk7CiAgICBpb3ZlYy5idWZfbGVuID0gdmlldy5nZXRVaW50MzIocHRyICsgNCwgdHJ1ZSk7CiAgICByZXR1cm4gaW92ZWM7CiAgfQogIHN0YXRpYyByZWFkX2J5dGVzX2FycmF5KHZpZXcsIHB0ciwgbGVuKSB7CiAgICBjb25zdCBpb3ZlY3MgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHsKICAgICAgaW92ZWNzLnB1c2goSW92ZWMucmVhZF9ieXRlcyh2aWV3LCBwdHIgKyA4ICogaSkpOwogICAgfQogICAgcmV0dXJuIGlvdmVjczsKICB9Cn07CnZhciBDaW92ZWMgPSBjbGFzcyB7CiAgc3RhdGljIHJlYWRfYnl0ZXModmlldywgcHRyKSB7CiAgICBjb25zdCBpb3ZlYyA9IG5ldyBDaW92ZWMoKTsKICAgIGlvdmVjLmJ1ZiA9IHZpZXcuZ2V0VWludDMyKHB0ciwgdHJ1ZSk7CiAgICBpb3ZlYy5idWZfbGVuID0gdmlldy5nZXRVaW50MzIocHRyICsgNCwgdHJ1ZSk7CiAgICByZXR1cm4gaW92ZWM7CiAgfQogIHN0YXRpYyByZWFkX2J5dGVzX2FycmF5KHZpZXcsIHB0ciwgbGVuKSB7CiAgICBjb25zdCBpb3ZlY3MgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHsKICAgICAgaW92ZWNzLnB1c2goQ2lvdmVjLnJlYWRfYnl0ZXModmlldywgcHRyICsgOCAqIGkpKTsKICAgIH0KICAgIHJldHVybiBpb3ZlY3M7CiAgfQp9Owp2YXIgV0hFTkNFX1NFVCA9IDA7CnZhciBXSEVOQ0VfQ1VSID0gMTsKdmFyIFdIRU5DRV9FTkQgPSAyOwp2YXIgRklMRVRZUEVfQ0hBUkFDVEVSX0RFVklDRSA9IDI7CnZhciBGSUxFVFlQRV9ESVJFQ1RPUlkgPSAzOwp2YXIgRklMRVRZUEVfUkVHVUxBUl9GSUxFID0gNDsKdmFyIERpcmVudCA9IGNsYXNzIHsKICBoZWFkX2xlbmd0aCgpIHsKICAgIHJldHVybiAyNDsKICB9CiAgbmFtZV9sZW5ndGgoKSB7CiAgICByZXR1cm4gdGhpcy5kaXJfbmFtZS5ieXRlTGVuZ3RoOwogIH0KICB3cml0ZV9oZWFkX2J5dGVzKHZpZXcsIHB0cikgewogICAgdmlldy5zZXRCaWdVaW50NjQocHRyLCB0aGlzLmRfbmV4dCwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA4LCB0aGlzLmRfaW5vLCB0cnVlKTsKICAgIHZpZXcuc2V0VWludDMyKHB0ciArIDE2LCB0aGlzLmRpcl9uYW1lLmxlbmd0aCwgdHJ1ZSk7CiAgICB2aWV3LnNldFVpbnQ4KHB0ciArIDIwLCB0aGlzLmRfdHlwZSk7CiAgfQogIHdyaXRlX25hbWVfYnl0ZXModmlldzgsIHB0ciwgYnVmX2xlbikgewogICAgdmlldzguc2V0KHRoaXMuZGlyX25hbWUuc2xpY2UoMCwgTWF0aC5taW4odGhpcy5kaXJfbmFtZS5ieXRlTGVuZ3RoLCBidWZfbGVuKSksIHB0cik7CiAgfQogIGNvbnN0cnVjdG9yKG5leHRfY29va2llLCBuYW1lLCB0eXBlKSB7CiAgICB0aGlzLmRfaW5vID0gMG47CiAgICBjb25zdCBlbmNvZGVkX25hbWUgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUobmFtZSk7CiAgICB0aGlzLmRfbmV4dCA9IG5leHRfY29va2llOwogICAgdGhpcy5kX25hbWxlbiA9IGVuY29kZWRfbmFtZS5ieXRlTGVuZ3RoOwogICAgdGhpcy5kX3R5cGUgPSB0eXBlOwogICAgdGhpcy5kaXJfbmFtZSA9IGVuY29kZWRfbmFtZTsKICB9Cn07CnZhciBGREZMQUdTX0FQUEVORCA9IDEgPDwgMDsKdmFyIEZERkxBR1NfRFNZTkMgPSAxIDw8IDE7CnZhciBGREZMQUdTX05PTkJMT0NLID0gMSA8PCAyOwp2YXIgRkRGTEFHU19SU1lOQyA9IDEgPDwgMzsKdmFyIEZERkxBR1NfU1lOQyA9IDEgPDwgNDsKdmFyIEZkc3RhdCA9IGNsYXNzIHsKICB3cml0ZV9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIHZpZXcuc2V0VWludDgocHRyLCB0aGlzLmZzX2ZpbGV0eXBlKTsKICAgIHZpZXcuc2V0VWludDE2KHB0ciArIDIsIHRoaXMuZnNfZmxhZ3MsIHRydWUpOwogICAgdmlldy5zZXRCaWdVaW50NjQocHRyICsgOCwgdGhpcy5mc19yaWdodHNfYmFzZSwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyAxNiwgdGhpcy5mc19yaWdodHNfaW5oZXJpdGVkLCB0cnVlKTsKICB9CiAgY29uc3RydWN0b3IoZmlsZXR5cGUsIGZsYWdzKSB7CiAgICB0aGlzLmZzX3JpZ2h0c19iYXNlID0gMG47CiAgICB0aGlzLmZzX3JpZ2h0c19pbmhlcml0ZWQgPSAwbjsKICAgIHRoaXMuZnNfZmlsZXR5cGUgPSBmaWxldHlwZTsKICAgIHRoaXMuZnNfZmxhZ3MgPSBmbGFnczsKICB9Cn07CnZhciBGU1RGTEFHU19BVElNID0gMSA8PCAwOwp2YXIgRlNURkxBR1NfQVRJTV9OT1cgPSAxIDw8IDE7CnZhciBGU1RGTEFHU19NVElNID0gMSA8PCAyOwp2YXIgRlNURkxBR1NfTVRJTV9OT1cgPSAxIDw8IDM7CnZhciBPRkxBR1NfQ1JFQVQgPSAxIDw8IDA7CnZhciBPRkxBR1NfRElSRUNUT1JZID0gMSA8PCAxOwp2YXIgT0ZMQUdTX0VYQ0wgPSAxIDw8IDI7CnZhciBPRkxBR1NfVFJVTkMgPSAxIDw8IDM7CnZhciBGaWxlc3RhdCA9IGNsYXNzIHsKICB3cml0ZV9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciwgdGhpcy5kZXYsIHRydWUpOwogICAgdmlldy5zZXRCaWdVaW50NjQocHRyICsgOCwgdGhpcy5pbm8sIHRydWUpOwogICAgdmlldy5zZXRVaW50OChwdHIgKyAxNiwgdGhpcy5maWxldHlwZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyAyNCwgdGhpcy5ubGluaywgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyAzMiwgdGhpcy5zaXplLCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDM4LCB0aGlzLmF0aW0sIHRydWUpOwogICAgdmlldy5zZXRCaWdVaW50NjQocHRyICsgNDYsIHRoaXMubXRpbSwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA1MiwgdGhpcy5jdGltLCB0cnVlKTsKICB9CiAgY29uc3RydWN0b3IoZmlsZXR5cGUsIHNpemUpIHsKICAgIHRoaXMuZGV2ID0gMG47CiAgICB0aGlzLmlubyA9IDBuOwogICAgdGhpcy5ubGluayA9IDBuOwogICAgdGhpcy5hdGltID0gMG47CiAgICB0aGlzLm10aW0gPSAwbjsKICAgIHRoaXMuY3RpbSA9IDBuOwogICAgdGhpcy5maWxldHlwZSA9IGZpbGV0eXBlOwogICAgdGhpcy5zaXplID0gc2l6ZTsKICB9Cn07CnZhciBFVkVOVFJXRkxBR1NfRkRfUkVBRFdSSVRFX0hBTkdVUCA9IDEgPDwgMDsKdmFyIFNVQkNMT0NLRkxBR1NfU1VCU0NSSVBUSU9OX0NMT0NLX0FCU1RJTUUgPSAxIDw8IDA7CnZhciBSSUZMQUdTX1JFQ1ZfUEVFSyA9IDEgPDwgMDsKdmFyIFJJRkxBR1NfUkVDVl9XQUlUQUxMID0gMSA8PCAxOwp2YXIgUk9GTEFHU19SRUNWX0RBVEFfVFJVTkNBVEVEID0gMSA8PCAwOwp2YXIgU0RGTEFHU19SRCA9IDEgPDwgMDsKdmFyIFNERkxBR1NfV1IgPSAxIDw8IDE7CnZhciBQUkVPUEVOVFlQRV9ESVIgPSAwOwp2YXIgUHJlc3RhdERpciA9IGNsYXNzIHsKICB3cml0ZV9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIHZpZXcuc2V0VWludDMyKHB0ciwgdGhpcy5wcl9uYW1lLmJ5dGVMZW5ndGgsIHRydWUpOwogIH0KICBjb25zdHJ1Y3RvcihuYW1lKSB7CiAgICB0aGlzLnByX25hbWUgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUobmFtZSk7CiAgfQp9Owp2YXIgUHJlc3RhdCA9IGNsYXNzIHsKICBzdGF0aWMgZGlyKG5hbWUpIHsKICAgIGNvbnN0IHByZXN0YXQgPSBuZXcgUHJlc3RhdCgpOwogICAgcHJlc3RhdC50YWcgPSBQUkVPUEVOVFlQRV9ESVI7CiAgICBwcmVzdGF0LmlubmVyID0gbmV3IFByZXN0YXREaXIobmFtZSk7CiAgICByZXR1cm4gcHJlc3RhdDsKICB9CiAgd3JpdGVfYnl0ZXModmlldywgcHRyKSB7CiAgICB2aWV3LnNldFVpbnQzMihwdHIsIHRoaXMudGFnLCB0cnVlKTsKICAgIHRoaXMuaW5uZXIud3JpdGVfYnl0ZXModmlldywgcHRyICsgNCk7CiAgfQp9OwoKLy8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC9kZWJ1Zy5qcwp2YXIgRGVidWcgPSBjbGFzcyBEZWJ1ZzIgewogIGVuYWJsZShlbmFibGVkKSB7CiAgICB0aGlzLmxvZyA9IGNyZWF0ZUxvZ2dlcihlbmFibGVkID09PSB2b2lkIDAgPyB0cnVlIDogZW5hYmxlZCwgdGhpcy5wcmVmaXgpOwogIH0KICBnZXQgZW5hYmxlZCgpIHsKICAgIHJldHVybiB0aGlzLmlzRW5hYmxlZDsKICB9CiAgY29uc3RydWN0b3IoaXNFbmFibGVkKSB7CiAgICB0aGlzLmlzRW5hYmxlZCA9IGlzRW5hYmxlZDsKICAgIHRoaXMucHJlZml4ID0gIndhc2k6IjsKICAgIHRoaXMuZW5hYmxlKGlzRW5hYmxlZCk7CiAgfQp9OwpmdW5jdGlvbiBjcmVhdGVMb2dnZXIoZW5hYmxlZCwgcHJlZml4KSB7CiAgaWYgKGVuYWJsZWQpIHsKICAgIGNvbnN0IGEgPSBjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUsICIlYyVzIiwgImNvbG9yOiAjMjY1QkEwIiwgcHJlZml4KTsKICAgIHJldHVybiBhOwogIH0gZWxzZSB7CiAgICByZXR1cm4gKCkgPT4gewogICAgfTsKICB9Cn0KdmFyIGRlYnVnID0gbmV3IERlYnVnKGZhbHNlKTsKCi8vIG5vZGVfbW9kdWxlcy9AYmpvcm4zL2Jyb3dzZXJfd2FzaV9zaGltL2Rpc3Qvd2FzaS5qcwp2YXIgV0FTSVByb2NFeGl0ID0gY2xhc3MgZXh0ZW5kcyBFcnJvciB7CiAgY29uc3RydWN0b3IoY29kZSkgewogICAgc3VwZXIoImV4aXQgd2l0aCBleGl0IGNvZGUgIiArIGNvZGUpOwogICAgdGhpcy5jb2RlID0gY29kZTsKICB9Cn07CnZhciBXQVNJID0gY2xhc3MgV0FTSTIgewogIHN0YXJ0KGluc3RhbmNlKSB7CiAgICB0aGlzLmluc3QgPSBpbnN0YW5jZTsKICAgIHRyeSB7CiAgICAgIGluc3RhbmNlLmV4cG9ydHMuX3N0YXJ0KCk7CiAgICAgIHJldHVybiAwOwogICAgfSBjYXRjaCAoZSkgewogICAgICBpZiAoZSBpbnN0YW5jZW9mIFdBU0lQcm9jRXhpdCkgewogICAgICAgIHJldHVybiBlLmNvZGU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgZTsKICAgICAgfQogICAgfQogIH0KICBpbml0aWFsaXplKGluc3RhbmNlKSB7CiAgICB0aGlzLmluc3QgPSBpbnN0YW5jZTsKICAgIGlmIChpbnN0YW5jZS5leHBvcnRzLl9pbml0aWFsaXplKSB7CiAgICAgIGluc3RhbmNlLmV4cG9ydHMuX2luaXRpYWxpemUoKTsKICAgIH0KICB9CiAgY29uc3RydWN0b3IoYXJncywgZW52LCBmZHMsIG9wdGlvbnMgPSB7fSkgewogICAgdGhpcy5hcmdzID0gW107CiAgICB0aGlzLmVudiA9IFtdOwogICAgdGhpcy5mZHMgPSBbXTsKICAgIGRlYnVnLmVuYWJsZShvcHRpb25zLmRlYnVnKTsKICAgIHRoaXMuYXJncyA9IGFyZ3M7CiAgICB0aGlzLmVudiA9IGVudjsKICAgIHRoaXMuZmRzID0gZmRzOwogICAgY29uc3Qgc2VsZiA9IHRoaXM7CiAgICB0aGlzLndhc2lJbXBvcnQgPSB7IGFyZ3Nfc2l6ZXNfZ2V0KGFyZ2MsIGFyZ3ZfYnVmX3NpemUpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBidWZmZXIuc2V0VWludDMyKGFyZ2MsIHNlbGYuYXJncy5sZW5ndGgsIHRydWUpOwogICAgICBsZXQgYnVmX3NpemUgPSAwOwogICAgICBmb3IgKGNvbnN0IGFyZyBvZiBzZWxmLmFyZ3MpIHsKICAgICAgICBidWZfc2l6ZSArPSBhcmcubGVuZ3RoICsgMTsKICAgICAgfQogICAgICBidWZmZXIuc2V0VWludDMyKGFyZ3ZfYnVmX3NpemUsIGJ1Zl9zaXplLCB0cnVlKTsKICAgICAgZGVidWcubG9nKGJ1ZmZlci5nZXRVaW50MzIoYXJnYywgdHJ1ZSksIGJ1ZmZlci5nZXRVaW50MzIoYXJndl9idWZfc2l6ZSwgdHJ1ZSkpOwogICAgICByZXR1cm4gMDsKICAgIH0sIGFyZ3NfZ2V0KGFyZ3YsIGFyZ3ZfYnVmKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBvcmlnX2FyZ3ZfYnVmID0gYXJndl9idWY7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZi5hcmdzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgYnVmZmVyLnNldFVpbnQzMihhcmd2LCBhcmd2X2J1ZiwgdHJ1ZSk7CiAgICAgICAgYXJndiArPSA0OwogICAgICAgIGNvbnN0IGFyZyA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzZWxmLmFyZ3NbaV0pOwogICAgICAgIGJ1ZmZlcjguc2V0KGFyZywgYXJndl9idWYpOwogICAgICAgIGJ1ZmZlci5zZXRVaW50OChhcmd2X2J1ZiArIGFyZy5sZW5ndGgsIDApOwogICAgICAgIGFyZ3ZfYnVmICs9IGFyZy5sZW5ndGggKyAxOwogICAgICB9CiAgICAgIGlmIChkZWJ1Zy5lbmFibGVkKSB7CiAgICAgICAgZGVidWcubG9nKG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShvcmlnX2FyZ3ZfYnVmLCBhcmd2X2J1ZikpKTsKICAgICAgfQogICAgICByZXR1cm4gMDsKICAgIH0sIGVudmlyb25fc2l6ZXNfZ2V0KGVudmlyb25fY291bnQsIGVudmlyb25fc2l6ZSkgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGJ1ZmZlci5zZXRVaW50MzIoZW52aXJvbl9jb3VudCwgc2VsZi5lbnYubGVuZ3RoLCB0cnVlKTsKICAgICAgbGV0IGJ1Zl9zaXplID0gMDsKICAgICAgZm9yIChjb25zdCBlbnZpcm9uIG9mIHNlbGYuZW52KSB7CiAgICAgICAgYnVmX3NpemUgKz0gZW52aXJvbi5sZW5ndGggKyAxOwogICAgICB9CiAgICAgIGJ1ZmZlci5zZXRVaW50MzIoZW52aXJvbl9zaXplLCBidWZfc2l6ZSwgdHJ1ZSk7CiAgICAgIGRlYnVnLmxvZyhidWZmZXIuZ2V0VWludDMyKGVudmlyb25fY291bnQsIHRydWUpLCBidWZmZXIuZ2V0VWludDMyKGVudmlyb25fc2l6ZSwgdHJ1ZSkpOwogICAgICByZXR1cm4gMDsKICAgIH0sIGVudmlyb25fZ2V0KGVudmlyb24sIGVudmlyb25fYnVmKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBvcmlnX2Vudmlyb25fYnVmID0gZW52aXJvbl9idWY7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZi5lbnYubGVuZ3RoOyBpKyspIHsKICAgICAgICBidWZmZXIuc2V0VWludDMyKGVudmlyb24sIGVudmlyb25fYnVmLCB0cnVlKTsKICAgICAgICBlbnZpcm9uICs9IDQ7CiAgICAgICAgY29uc3QgZSA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzZWxmLmVudltpXSk7CiAgICAgICAgYnVmZmVyOC5zZXQoZSwgZW52aXJvbl9idWYpOwogICAgICAgIGJ1ZmZlci5zZXRVaW50OChlbnZpcm9uX2J1ZiArIGUubGVuZ3RoLCAwKTsKICAgICAgICBlbnZpcm9uX2J1ZiArPSBlLmxlbmd0aCArIDE7CiAgICAgIH0KICAgICAgaWYgKGRlYnVnLmVuYWJsZWQpIHsKICAgICAgICBkZWJ1Zy5sb2cobmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG9yaWdfZW52aXJvbl9idWYsIGVudmlyb25fYnVmKSkpOwogICAgICB9CiAgICAgIHJldHVybiAwOwogICAgfSwgY2xvY2tfcmVzX2dldChpZCwgcmVzX3B0cikgewogICAgICBsZXQgcmVzb2x1dGlvblZhbHVlOwogICAgICBzd2l0Y2ggKGlkKSB7CiAgICAgICAgY2FzZSBDTE9DS0lEX01PTk9UT05JQzogewogICAgICAgICAgcmVzb2x1dGlvblZhbHVlID0gNTAwMG47CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgY2FzZSBDTE9DS0lEX1JFQUxUSU1FOiB7CiAgICAgICAgICByZXNvbHV0aW9uVmFsdWUgPSAxMDAwMDAwbjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBkZWZhdWx0OgogICAgICAgICAgcmV0dXJuIEVSUk5PX05PU1lTOwogICAgICB9CiAgICAgIGNvbnN0IHZpZXcgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIHZpZXcuc2V0QmlnVWludDY0KHJlc19wdHIsIHJlc29sdXRpb25WYWx1ZSwgdHJ1ZSk7CiAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgfSwgY2xvY2tfdGltZV9nZXQoaWQsIHByZWNpc2lvbiwgdGltZSkgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChpZCA9PT0gQ0xPQ0tJRF9SRUFMVElNRSkgewogICAgICAgIGJ1ZmZlci5zZXRCaWdVaW50NjQodGltZSwgQmlnSW50KG5ldyBEYXRlKCkuZ2V0VGltZSgpKSAqIDEwMDAwMDBuLCB0cnVlKTsKICAgICAgfSBlbHNlIGlmIChpZCA9PSBDTE9DS0lEX01PTk9UT05JQykgewogICAgICAgIGxldCBtb25vdG9uaWNfdGltZTsKICAgICAgICB0cnkgewogICAgICAgICAgbW9ub3RvbmljX3RpbWUgPSBCaWdJbnQoTWF0aC5yb3VuZChwZXJmb3JtYW5jZS5ub3coKSAqIDFlNikpOwogICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgIG1vbm90b25pY190aW1lID0gMG47CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRCaWdVaW50NjQodGltZSwgbW9ub3RvbmljX3RpbWUsIHRydWUpOwogICAgICB9IGVsc2UgewogICAgICAgIGJ1ZmZlci5zZXRCaWdVaW50NjQodGltZSwgMG4sIHRydWUpOwogICAgICB9CiAgICAgIHJldHVybiAwOwogICAgfSwgZmRfYWR2aXNlKGZkLCBvZmZzZXQsIGxlbiwgYWR2aWNlKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2FsbG9jYXRlKGZkLCBvZmZzZXQsIGxlbikgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfYWxsb2NhdGUob2Zmc2V0LCBsZW4pOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9jbG9zZShmZCkgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHJldCA9IHNlbGYuZmRzW2ZkXS5mZF9jbG9zZSgpOwogICAgICAgIHNlbGYuZmRzW2ZkXSA9IHZvaWQgMDsKICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9kYXRhc3luYyhmZCkgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfc3luYygpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9mZHN0YXRfZ2V0KGZkLCBmZHN0YXRfcHRyKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIGZkc3RhdCB9ID0gc2VsZi5mZHNbZmRdLmZkX2Zkc3RhdF9nZXQoKTsKICAgICAgICBpZiAoZmRzdGF0ICE9IG51bGwpIHsKICAgICAgICAgIGZkc3RhdC53cml0ZV9ieXRlcyhuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlciksIGZkc3RhdF9wdHIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9mZHN0YXRfc2V0X2ZsYWdzKGZkLCBmbGFncykgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfZmRzdGF0X3NldF9mbGFncyhmbGFncyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Zkc3RhdF9zZXRfcmlnaHRzKGZkLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICByZXR1cm4gc2VsZi5mZHNbZmRdLmZkX2Zkc3RhdF9zZXRfcmlnaHRzKGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2ZpbGVzdGF0X2dldChmZCwgZmlsZXN0YXRfcHRyKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIGZpbGVzdGF0IH0gPSBzZWxmLmZkc1tmZF0uZmRfZmlsZXN0YXRfZ2V0KCk7CiAgICAgICAgaWYgKGZpbGVzdGF0ICE9IG51bGwpIHsKICAgICAgICAgIGZpbGVzdGF0LndyaXRlX2J5dGVzKG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKSwgZmlsZXN0YXRfcHRyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfZmlsZXN0YXRfc2V0X3NpemUoZmQsIHNpemUpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICByZXR1cm4gc2VsZi5mZHNbZmRdLmZkX2ZpbGVzdGF0X3NldF9zaXplKHNpemUpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9maWxlc3RhdF9zZXRfdGltZXMoZmQsIGF0aW0sIG10aW0sIGZzdF9mbGFncykgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfZmlsZXN0YXRfc2V0X3RpbWVzKGF0aW0sIG10aW0sIGZzdF9mbGFncyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3ByZWFkKGZkLCBpb3ZzX3B0ciwgaW92c19sZW4sIG9mZnNldCwgbnJlYWRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IGlvdmVjcyA9IElvdmVjLnJlYWRfYnl0ZXNfYXJyYXkoYnVmZmVyLCBpb3ZzX3B0ciwgaW92c19sZW4pOwogICAgICAgIGxldCBucmVhZCA9IDA7CiAgICAgICAgZm9yIChjb25zdCBpb3ZlYyBvZiBpb3ZlY3MpIHsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBkYXRhIH0gPSBzZWxmLmZkc1tmZF0uZmRfcHJlYWQoaW92ZWMuYnVmX2xlbiwgb2Zmc2V0KTsKICAgICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgbnJlYWQsIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgYnVmZmVyOC5zZXQoZGF0YSwgaW92ZWMuYnVmKTsKICAgICAgICAgIG5yZWFkICs9IGRhdGEubGVuZ3RoOwogICAgICAgICAgb2Zmc2V0ICs9IEJpZ0ludChkYXRhLmxlbmd0aCk7CiAgICAgICAgICBpZiAoZGF0YS5sZW5ndGggIT0gaW92ZWMuYnVmX2xlbikgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgYnVmZmVyLnNldFVpbnQzMihucmVhZF9wdHIsIG5yZWFkLCB0cnVlKTsKICAgICAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcHJlc3RhdF9nZXQoZmQsIGJ1Zl9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHsgcmV0LCBwcmVzdGF0IH0gPSBzZWxmLmZkc1tmZF0uZmRfcHJlc3RhdF9nZXQoKTsKICAgICAgICBpZiAocHJlc3RhdCAhPSBudWxsKSB7CiAgICAgICAgICBwcmVzdGF0LndyaXRlX2J5dGVzKGJ1ZmZlciwgYnVmX3B0cik7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3ByZXN0YXRfZGlyX25hbWUoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbikgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHsgcmV0LCBwcmVzdGF0IH0gPSBzZWxmLmZkc1tmZF0uZmRfcHJlc3RhdF9nZXQoKTsKICAgICAgICBpZiAocHJlc3RhdCA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgIH0KICAgICAgICBjb25zdCBwcmVzdGF0X2Rpcl9uYW1lID0gcHJlc3RhdC5pbm5lci5wcl9uYW1lOwogICAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgICBidWZmZXI4LnNldChwcmVzdGF0X2Rpcl9uYW1lLnNsaWNlKDAsIHBhdGhfbGVuKSwgcGF0aF9wdHIpOwogICAgICAgIHJldHVybiBwcmVzdGF0X2Rpcl9uYW1lLmJ5dGVMZW5ndGggPiBwYXRoX2xlbiA/IEVSUk5PX05BTUVUT09MT05HIDogRVJSTk9fU1VDQ0VTUzsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcHdyaXRlKGZkLCBpb3ZzX3B0ciwgaW92c19sZW4sIG9mZnNldCwgbndyaXR0ZW5fcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IGlvdmVjcyA9IENpb3ZlYy5yZWFkX2J5dGVzX2FycmF5KGJ1ZmZlciwgaW92c19wdHIsIGlvdnNfbGVuKTsKICAgICAgICBsZXQgbndyaXR0ZW4gPSAwOwogICAgICAgIGZvciAoY29uc3QgaW92ZWMgb2YgaW92ZWNzKSB7CiAgICAgICAgICBjb25zdCBkYXRhID0gYnVmZmVyOC5zbGljZShpb3ZlYy5idWYsIGlvdmVjLmJ1ZiArIGlvdmVjLmJ1Zl9sZW4pOwogICAgICAgICAgY29uc3QgeyByZXQsIG53cml0dGVuOiBud3JpdHRlbl9wYXJ0IH0gPSBzZWxmLmZkc1tmZF0uZmRfcHdyaXRlKGRhdGEsIG9mZnNldCk7CiAgICAgICAgICBpZiAocmV0ICE9IEVSUk5PX1NVQ0NFU1MpIHsKICAgICAgICAgICAgYnVmZmVyLnNldFVpbnQzMihud3JpdHRlbl9wdHIsIG53cml0dGVuLCB0cnVlKTsKICAgICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICAgIH0KICAgICAgICAgIG53cml0dGVuICs9IG53cml0dGVuX3BhcnQ7CiAgICAgICAgICBvZmZzZXQgKz0gQmlnSW50KG53cml0dGVuX3BhcnQpOwogICAgICAgICAgaWYgKG53cml0dGVuX3BhcnQgIT0gZGF0YS5ieXRlTGVuZ3RoKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKG53cml0dGVuX3B0ciwgbndyaXR0ZW4sIHRydWUpOwogICAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9yZWFkKGZkLCBpb3ZzX3B0ciwgaW92c19sZW4sIG5yZWFkX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBpb3ZlY3MgPSBJb3ZlYy5yZWFkX2J5dGVzX2FycmF5KGJ1ZmZlciwgaW92c19wdHIsIGlvdnNfbGVuKTsKICAgICAgICBsZXQgbnJlYWQgPSAwOwogICAgICAgIGZvciAoY29uc3QgaW92ZWMgb2YgaW92ZWNzKSB7CiAgICAgICAgICBjb25zdCB7IHJldCwgZGF0YSB9ID0gc2VsZi5mZHNbZmRdLmZkX3JlYWQoaW92ZWMuYnVmX2xlbik7CiAgICAgICAgICBpZiAocmV0ICE9IEVSUk5PX1NVQ0NFU1MpIHsKICAgICAgICAgICAgYnVmZmVyLnNldFVpbnQzMihucmVhZF9wdHIsIG5yZWFkLCB0cnVlKTsKICAgICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICAgIH0KICAgICAgICAgIGJ1ZmZlcjguc2V0KGRhdGEsIGlvdmVjLmJ1Zik7CiAgICAgICAgICBucmVhZCArPSBkYXRhLmxlbmd0aDsKICAgICAgICAgIGlmIChkYXRhLmxlbmd0aCAhPSBpb3ZlYy5idWZfbGVuKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgbnJlYWQsIHRydWUpOwogICAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9yZWFkZGlyKGZkLCBidWYsIGJ1Zl9sZW4sIGNvb2tpZSwgYnVmdXNlZF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgbGV0IGJ1ZnVzZWQgPSAwOwogICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICBjb25zdCB7IHJldCwgZGlyZW50IH0gPSBzZWxmLmZkc1tmZF0uZmRfcmVhZGRpcl9zaW5nbGUoY29va2llKTsKICAgICAgICAgIGlmIChyZXQgIT0gMCkgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKGJ1ZnVzZWRfcHRyLCBidWZ1c2VkLCB0cnVlKTsKICAgICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChkaXJlbnQgPT0gbnVsbCkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChidWZfbGVuIC0gYnVmdXNlZCA8IGRpcmVudC5oZWFkX2xlbmd0aCgpKSB7CiAgICAgICAgICAgIGJ1ZnVzZWQgPSBidWZfbGVuOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGhlYWRfYnl0ZXMgPSBuZXcgQXJyYXlCdWZmZXIoZGlyZW50LmhlYWRfbGVuZ3RoKCkpOwogICAgICAgICAgZGlyZW50LndyaXRlX2hlYWRfYnl0ZXMobmV3IERhdGFWaWV3KGhlYWRfYnl0ZXMpLCAwKTsKICAgICAgICAgIGJ1ZmZlcjguc2V0KG5ldyBVaW50OEFycmF5KGhlYWRfYnl0ZXMpLnNsaWNlKDAsIE1hdGgubWluKGhlYWRfYnl0ZXMuYnl0ZUxlbmd0aCwgYnVmX2xlbiAtIGJ1ZnVzZWQpKSwgYnVmKTsKICAgICAgICAgIGJ1ZiArPSBkaXJlbnQuaGVhZF9sZW5ndGgoKTsKICAgICAgICAgIGJ1ZnVzZWQgKz0gZGlyZW50LmhlYWRfbGVuZ3RoKCk7CiAgICAgICAgICBpZiAoYnVmX2xlbiAtIGJ1ZnVzZWQgPCBkaXJlbnQubmFtZV9sZW5ndGgoKSkgewogICAgICAgICAgICBidWZ1c2VkID0gYnVmX2xlbjsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBkaXJlbnQud3JpdGVfbmFtZV9ieXRlcyhidWZmZXI4LCBidWYsIGJ1Zl9sZW4gLSBidWZ1c2VkKTsKICAgICAgICAgIGJ1ZiArPSBkaXJlbnQubmFtZV9sZW5ndGgoKTsKICAgICAgICAgIGJ1ZnVzZWQgKz0gZGlyZW50Lm5hbWVfbGVuZ3RoKCk7CiAgICAgICAgICBjb29raWUgPSBkaXJlbnQuZF9uZXh0OwogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKGJ1ZnVzZWRfcHRyLCBidWZ1c2VkLCB0cnVlKTsKICAgICAgICByZXR1cm4gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcmVudW1iZXIoZmQsIHRvKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwICYmIHNlbGYuZmRzW3RvXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCByZXQgPSBzZWxmLmZkc1t0b10uZmRfY2xvc2UoKTsKICAgICAgICBpZiAocmV0ICE9IDApIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIHNlbGYuZmRzW3RvXSA9IHNlbGYuZmRzW2ZkXTsKICAgICAgICBzZWxmLmZkc1tmZF0gPSB2b2lkIDA7CiAgICAgICAgcmV0dXJuIDA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3NlZWsoZmQsIG9mZnNldCwgd2hlbmNlLCBvZmZzZXRfb3V0X3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIG9mZnNldDogb2Zmc2V0X291dCB9ID0gc2VsZi5mZHNbZmRdLmZkX3NlZWsob2Zmc2V0LCB3aGVuY2UpOwogICAgICAgIGJ1ZmZlci5zZXRCaWdJbnQ2NChvZmZzZXRfb3V0X3B0ciwgb2Zmc2V0X291dCwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfc3luYyhmZCkgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfc3luYygpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF90ZWxsKGZkLCBvZmZzZXRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgb2Zmc2V0IH0gPSBzZWxmLmZkc1tmZF0uZmRfdGVsbCgpOwogICAgICAgIGJ1ZmZlci5zZXRCaWdVaW50NjQob2Zmc2V0X3B0ciwgb2Zmc2V0LCB0cnVlKTsKICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF93cml0ZShmZCwgaW92c19wdHIsIGlvdnNfbGVuLCBud3JpdHRlbl9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgaW92ZWNzID0gQ2lvdmVjLnJlYWRfYnl0ZXNfYXJyYXkoYnVmZmVyLCBpb3ZzX3B0ciwgaW92c19sZW4pOwogICAgICAgIGxldCBud3JpdHRlbiA9IDA7CiAgICAgICAgZm9yIChjb25zdCBpb3ZlYyBvZiBpb3ZlY3MpIHsKICAgICAgICAgIGNvbnN0IGRhdGEgPSBidWZmZXI4LnNsaWNlKGlvdmVjLmJ1ZiwgaW92ZWMuYnVmICsgaW92ZWMuYnVmX2xlbik7CiAgICAgICAgICBjb25zdCB7IHJldCwgbndyaXR0ZW46IG53cml0dGVuX3BhcnQgfSA9IHNlbGYuZmRzW2ZkXS5mZF93cml0ZShkYXRhKTsKICAgICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG53cml0dGVuX3B0ciwgbndyaXR0ZW4sIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgbndyaXR0ZW4gKz0gbndyaXR0ZW5fcGFydDsKICAgICAgICAgIGlmIChud3JpdHRlbl9wYXJ0ICE9IGRhdGEuYnl0ZUxlbmd0aCkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgYnVmZmVyLnNldFVpbnQzMihud3JpdHRlbl9wdHIsIG53cml0dGVuLCB0cnVlKTsKICAgICAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9jcmVhdGVfZGlyZWN0b3J5KGZkLCBwYXRoX3B0ciwgcGF0aF9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICByZXR1cm4gc2VsZi5mZHNbZmRdLnBhdGhfY3JlYXRlX2RpcmVjdG9yeShwYXRoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9maWxlc3RhdF9nZXQoZmQsIGZsYWdzLCBwYXRoX3B0ciwgcGF0aF9sZW4sIGZpbGVzdGF0X3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBwYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgY29uc3QgeyByZXQsIGZpbGVzdGF0IH0gPSBzZWxmLmZkc1tmZF0ucGF0aF9maWxlc3RhdF9nZXQoZmxhZ3MsIHBhdGgpOwogICAgICAgIGlmIChmaWxlc3RhdCAhPSBudWxsKSB7CiAgICAgICAgICBmaWxlc3RhdC53cml0ZV9ieXRlcyhidWZmZXIsIGZpbGVzdGF0X3B0cik7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfZmlsZXN0YXRfc2V0X3RpbWVzKGZkLCBmbGFncywgcGF0aF9wdHIsIHBhdGhfbGVuLCBhdGltLCBtdGltLCBmc3RfZmxhZ3MpIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICByZXR1cm4gc2VsZi5mZHNbZmRdLnBhdGhfZmlsZXN0YXRfc2V0X3RpbWVzKGZsYWdzLCBwYXRoLCBhdGltLCBtdGltLCBmc3RfZmxhZ3MpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX2xpbmsob2xkX2ZkLCBvbGRfZmxhZ3MsIG9sZF9wYXRoX3B0ciwgb2xkX3BhdGhfbGVuLCBuZXdfZmQsIG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW29sZF9mZF0gIT0gdm9pZCAwICYmIHNlbGYuZmRzW25ld19mZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3Qgb2xkX3BhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2Uob2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9wdHIgKyBvbGRfcGF0aF9sZW4pKTsKICAgICAgICBjb25zdCBuZXdfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShuZXdfcGF0aF9wdHIsIG5ld19wYXRoX3B0ciArIG5ld19wYXRoX2xlbikpOwogICAgICAgIGNvbnN0IHsgcmV0LCBpbm9kZV9vYmogfSA9IHNlbGYuZmRzW29sZF9mZF0ucGF0aF9sb29rdXAob2xkX3BhdGgsIG9sZF9mbGFncyk7CiAgICAgICAgaWYgKGlub2RlX29iaiA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgIH0KICAgICAgICByZXR1cm4gc2VsZi5mZHNbbmV3X2ZkXS5wYXRoX2xpbmsobmV3X3BhdGgsIGlub2RlX29iaiwgZmFsc2UpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX29wZW4oZmQsIGRpcmZsYWdzLCBwYXRoX3B0ciwgcGF0aF9sZW4sIG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nLCBmZF9mbGFncywgb3BlbmVkX2ZkX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBwYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgZGVidWcubG9nKHBhdGgpOwogICAgICAgIGNvbnN0IHsgcmV0LCBmZF9vYmogfSA9IHNlbGYuZmRzW2ZkXS5wYXRoX29wZW4oZGlyZmxhZ3MsIHBhdGgsIG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nLCBmZF9mbGFncyk7CiAgICAgICAgaWYgKHJldCAhPSAwKSB7CiAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgIH0KICAgICAgICBzZWxmLmZkcy5wdXNoKGZkX29iaik7CiAgICAgICAgY29uc3Qgb3BlbmVkX2ZkID0gc2VsZi5mZHMubGVuZ3RoIC0gMTsKICAgICAgICBidWZmZXIuc2V0VWludDMyKG9wZW5lZF9mZF9wdHIsIG9wZW5lZF9mZCwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIDA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfcmVhZGxpbmsoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbiwgYnVmX3B0ciwgYnVmX2xlbiwgbnJlYWRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICBkZWJ1Zy5sb2cocGF0aCk7CiAgICAgICAgY29uc3QgeyByZXQsIGRhdGEgfSA9IHNlbGYuZmRzW2ZkXS5wYXRoX3JlYWRsaW5rKHBhdGgpOwogICAgICAgIGlmIChkYXRhICE9IG51bGwpIHsKICAgICAgICAgIGNvbnN0IGRhdGFfYnVmID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKGRhdGEpOwogICAgICAgICAgaWYgKGRhdGFfYnVmLmxlbmd0aCA+IGJ1Zl9sZW4pIHsKICAgICAgICAgICAgYnVmZmVyLnNldFVpbnQzMihucmVhZF9wdHIsIDAsIHRydWUpOwogICAgICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgICAgIH0KICAgICAgICAgIGJ1ZmZlcjguc2V0KGRhdGFfYnVmLCBidWZfcHRyKTsKICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobnJlYWRfcHRyLCBkYXRhX2J1Zi5sZW5ndGgsIHRydWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX3JlbW92ZV9kaXJlY3RvcnkoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0ucGF0aF9yZW1vdmVfZGlyZWN0b3J5KHBhdGgpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX3JlbmFtZShmZCwgb2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9sZW4sIG5ld19mZCwgbmV3X3BhdGhfcHRyLCBuZXdfcGF0aF9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCAmJiBzZWxmLmZkc1tuZXdfZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IG9sZF9wYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG9sZF9wYXRoX3B0ciwgb2xkX3BhdGhfcHRyICsgb2xkX3BhdGhfbGVuKSk7CiAgICAgICAgY29uc3QgbmV3X3BhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UobmV3X3BhdGhfcHRyLCBuZXdfcGF0aF9wdHIgKyBuZXdfcGF0aF9sZW4pKTsKICAgICAgICBsZXQgeyByZXQsIGlub2RlX29iaiB9ID0gc2VsZi5mZHNbZmRdLnBhdGhfdW5saW5rKG9sZF9wYXRoKTsKICAgICAgICBpZiAoaW5vZGVfb2JqID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIHJldCA9IHNlbGYuZmRzW25ld19mZF0ucGF0aF9saW5rKG5ld19wYXRoLCBpbm9kZV9vYmosIHRydWUpOwogICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgaWYgKHNlbGYuZmRzW2ZkXS5wYXRoX2xpbmsob2xkX3BhdGgsIGlub2RlX29iaiwgdHJ1ZSkgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICB0aHJvdyAicGF0aF9saW5rIHNob3VsZCBhbHdheXMgcmV0dXJuIHN1Y2Nlc3Mgd2hlbiByZWxpbmtpbmcgYW4gaW5vZGUgYmFjayB0byB0aGUgb3JpZ2luYWwgcGxhY2UiOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX3N5bWxpbmsob2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9sZW4sIGZkLCBuZXdfcGF0aF9wdHIsIG5ld19wYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3Qgb2xkX3BhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2Uob2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9wdHIgKyBvbGRfcGF0aF9sZW4pKTsKICAgICAgICBjb25zdCBuZXdfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShuZXdfcGF0aF9wdHIsIG5ld19wYXRoX3B0ciArIG5ld19wYXRoX2xlbikpOwogICAgICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfdW5saW5rX2ZpbGUoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0ucGF0aF91bmxpbmtfZmlsZShwYXRoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcG9sbF9vbmVvZmYoaW5fLCBvdXQsIG5zdWJzY3JpcHRpb25zKSB7CiAgICAgIHRocm93ICJhc3luYyBpbyBub3Qgc3VwcG9ydGVkIjsKICAgIH0sIHByb2NfZXhpdChleGl0X2NvZGUpIHsKICAgICAgdGhyb3cgbmV3IFdBU0lQcm9jRXhpdChleGl0X2NvZGUpOwogICAgfSwgcHJvY19yYWlzZShzaWcpIHsKICAgICAgdGhyb3cgInJhaXNlZCBzaWduYWwgIiArIHNpZzsKICAgIH0sIHNjaGVkX3lpZWxkKCkgewogICAgfSwgcmFuZG9tX2dldChidWYsIGJ1Zl9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJ1Zl9sZW47IGkrKykgewogICAgICAgIGJ1ZmZlcjhbYnVmICsgaV0gPSBNYXRoLnJhbmRvbSgpICogMjU2IHwgMDsKICAgICAgfQogICAgfSwgc29ja19yZWN2KGZkLCByaV9kYXRhLCByaV9mbGFncykgewogICAgICB0aHJvdyAic29ja2V0cyBub3Qgc3VwcG9ydGVkIjsKICAgIH0sIHNvY2tfc2VuZChmZCwgc2lfZGF0YSwgc2lfZmxhZ3MpIHsKICAgICAgdGhyb3cgInNvY2tldHMgbm90IHN1cHBvcnRlZCI7CiAgICB9LCBzb2NrX3NodXRkb3duKGZkLCBob3cpIHsKICAgICAgdGhyb3cgInNvY2tldHMgbm90IHN1cHBvcnRlZCI7CiAgICB9LCBzb2NrX2FjY2VwdChmZCwgZmxhZ3MpIHsKICAgICAgdGhyb3cgInNvY2tldHMgbm90IHN1cHBvcnRlZCI7CiAgICB9IH07CiAgfQp9OwoKLy8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC9mZC5qcwp2YXIgRmQgPSBjbGFzcyB7CiAgZmRfYWxsb2NhdGUob2Zmc2V0LCBsZW4pIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIGZkX2Nsb3NlKCkgewogICAgcmV0dXJuIDA7CiAgfQogIGZkX2Zkc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZmRzdGF0OiBudWxsIH07CiAgfQogIGZkX2Zkc3RhdF9zZXRfZmxhZ3MoZmxhZ3MpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIGZkX2Zkc3RhdF9zZXRfcmlnaHRzKGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZykgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfZmlsZXN0YXRfZ2V0KCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGZpbGVzdGF0OiBudWxsIH07CiAgfQogIGZkX2ZpbGVzdGF0X3NldF9zaXplKHNpemUpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIGZkX2ZpbGVzdGF0X3NldF90aW1lcyhhdGltLCBtdGltLCBmc3RfZmxhZ3MpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIGZkX3ByZWFkKHNpemUsIG9mZnNldCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGRhdGE6IG5ldyBVaW50OEFycmF5KCkgfTsKICB9CiAgZmRfcHJlc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgcHJlc3RhdDogbnVsbCB9OwogIH0KICBmZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgbndyaXR0ZW46IDAgfTsKICB9CiAgZmRfcmVhZChzaXplKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZGF0YTogbmV3IFVpbnQ4QXJyYXkoKSB9OwogIH0KICBmZF9yZWFkZGlyX3NpbmdsZShjb29raWUpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBkaXJlbnQ6IG51bGwgfTsKICB9CiAgZmRfc2VlayhvZmZzZXQsIHdoZW5jZSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIG9mZnNldDogMG4gfTsKICB9CiAgZmRfc3luYygpIHsKICAgIHJldHVybiAwOwogIH0KICBmZF90ZWxsKCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIG9mZnNldDogMG4gfTsKICB9CiAgZmRfd3JpdGUoZGF0YSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIG53cml0dGVuOiAwIH07CiAgfQogIHBhdGhfY3JlYXRlX2RpcmVjdG9yeShwYXRoKSB7CiAgICByZXR1cm4gRVJSTk9fTk9UU1VQOwogIH0KICBwYXRoX2ZpbGVzdGF0X2dldChmbGFncywgcGF0aCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGZpbGVzdGF0OiBudWxsIH07CiAgfQogIHBhdGhfZmlsZXN0YXRfc2V0X3RpbWVzKGZsYWdzLCBwYXRoLCBhdGltLCBtdGltLCBmc3RfZmxhZ3MpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfbGluayhwYXRoLCBpbm9kZSwgYWxsb3dfZGlyKSB7CiAgICByZXR1cm4gRVJSTk9fTk9UU1VQOwogIH0KICBwYXRoX3VubGluayhwYXRoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgaW5vZGVfb2JqOiBudWxsIH07CiAgfQogIHBhdGhfbG9va3VwKHBhdGgsIGRpcmZsYWdzKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgaW5vZGVfb2JqOiBudWxsIH07CiAgfQogIHBhdGhfb3BlbihkaXJmbGFncywgcGF0aCwgb2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcsIGZkX2ZsYWdzKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgZmRfb2JqOiBudWxsIH07CiAgfQogIHBhdGhfcmVhZGxpbmsocGF0aCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGRhdGE6IG51bGwgfTsKICB9CiAgcGF0aF9yZW1vdmVfZGlyZWN0b3J5KHBhdGgpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfcmVuYW1lKG9sZF9wYXRoLCBuZXdfZmQsIG5ld19wYXRoKSB7CiAgICByZXR1cm4gRVJSTk9fTk9UU1VQOwogIH0KICBwYXRoX3VubGlua19maWxlKHBhdGgpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQp9Owp2YXIgSW5vZGUgPSBjbGFzcyB7Cn07CgovLyBub2RlX21vZHVsZXMvQGJqb3JuMy9icm93c2VyX3dhc2lfc2hpbS9kaXN0L2ZzX21lbS5qcwp2YXIgT3BlbkZpbGUgPSBjbGFzcyBleHRlbmRzIEZkIHsKICBmZF9hbGxvY2F0ZShvZmZzZXQsIGxlbikgewogICAgaWYgKHRoaXMuZmlsZS5zaXplID4gb2Zmc2V0ICsgbGVuKSB7CiAgICB9IGVsc2UgewogICAgICBjb25zdCBuZXdfZGF0YSA9IG5ldyBVaW50OEFycmF5KE51bWJlcihvZmZzZXQgKyBsZW4pKTsKICAgICAgbmV3X2RhdGEuc2V0KHRoaXMuZmlsZS5kYXRhLCAwKTsKICAgICAgdGhpcy5maWxlLmRhdGEgPSBuZXdfZGF0YTsKICAgIH0KICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogIH0KICBmZF9mZHN0YXRfZ2V0KCkgewogICAgcmV0dXJuIHsgcmV0OiAwLCBmZHN0YXQ6IG5ldyBGZHN0YXQoRklMRVRZUEVfUkVHVUxBUl9GSUxFLCAwKSB9OwogIH0KICBmZF9maWxlc3RhdF9zZXRfc2l6ZShzaXplKSB7CiAgICBpZiAodGhpcy5maWxlLnNpemUgPiBzaXplKSB7CiAgICAgIHRoaXMuZmlsZS5kYXRhID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5maWxlLmRhdGEuYnVmZmVyLnNsaWNlKDAsIE51bWJlcihzaXplKSkpOwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgbmV3X2RhdGEgPSBuZXcgVWludDhBcnJheShOdW1iZXIoc2l6ZSkpOwogICAgICBuZXdfZGF0YS5zZXQodGhpcy5maWxlLmRhdGEsIDApOwogICAgICB0aGlzLmZpbGUuZGF0YSA9IG5ld19kYXRhOwogICAgfQogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIGZkX3JlYWQoc2l6ZSkgewogICAgY29uc3Qgc2xpY2UgPSB0aGlzLmZpbGUuZGF0YS5zbGljZShOdW1iZXIodGhpcy5maWxlX3BvcyksIE51bWJlcih0aGlzLmZpbGVfcG9zICsgQmlnSW50KHNpemUpKSk7CiAgICB0aGlzLmZpbGVfcG9zICs9IEJpZ0ludChzbGljZS5sZW5ndGgpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBkYXRhOiBzbGljZSB9OwogIH0KICBmZF9wcmVhZChzaXplLCBvZmZzZXQpIHsKICAgIGNvbnN0IHNsaWNlID0gdGhpcy5maWxlLmRhdGEuc2xpY2UoTnVtYmVyKG9mZnNldCksIE51bWJlcihvZmZzZXQgKyBCaWdJbnQoc2l6ZSkpKTsKICAgIHJldHVybiB7IHJldDogMCwgZGF0YTogc2xpY2UgfTsKICB9CiAgZmRfc2VlayhvZmZzZXQsIHdoZW5jZSkgewogICAgbGV0IGNhbGN1bGF0ZWRfb2Zmc2V0OwogICAgc3dpdGNoICh3aGVuY2UpIHsKICAgICAgY2FzZSBXSEVOQ0VfU0VUOgogICAgICAgIGNhbGN1bGF0ZWRfb2Zmc2V0ID0gb2Zmc2V0OwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFdIRU5DRV9DVVI6CiAgICAgICAgY2FsY3VsYXRlZF9vZmZzZXQgPSB0aGlzLmZpbGVfcG9zICsgb2Zmc2V0OwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFdIRU5DRV9FTkQ6CiAgICAgICAgY2FsY3VsYXRlZF9vZmZzZXQgPSBCaWdJbnQodGhpcy5maWxlLmRhdGEuYnl0ZUxlbmd0aCkgKyBvZmZzZXQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19JTlZBTCwgb2Zmc2V0OiAwbiB9OwogICAgfQogICAgaWYgKGNhbGN1bGF0ZWRfb2Zmc2V0IDwgMCkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0lOVkFMLCBvZmZzZXQ6IDBuIH07CiAgICB9CiAgICB0aGlzLmZpbGVfcG9zID0gY2FsY3VsYXRlZF9vZmZzZXQ7CiAgICByZXR1cm4geyByZXQ6IDAsIG9mZnNldDogdGhpcy5maWxlX3BvcyB9OwogIH0KICBmZF90ZWxsKCkgewogICAgcmV0dXJuIHsgcmV0OiAwLCBvZmZzZXQ6IHRoaXMuZmlsZV9wb3MgfTsKICB9CiAgZmRfd3JpdGUoZGF0YSkgewogICAgaWYgKHRoaXMuZmlsZS5yZWFkb25seSkKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBud3JpdHRlbjogMCB9OwogICAgaWYgKHRoaXMuZmlsZV9wb3MgKyBCaWdJbnQoZGF0YS5ieXRlTGVuZ3RoKSA+IHRoaXMuZmlsZS5zaXplKSB7CiAgICAgIGNvbnN0IG9sZCA9IHRoaXMuZmlsZS5kYXRhOwogICAgICB0aGlzLmZpbGUuZGF0YSA9IG5ldyBVaW50OEFycmF5KE51bWJlcih0aGlzLmZpbGVfcG9zICsgQmlnSW50KGRhdGEuYnl0ZUxlbmd0aCkpKTsKICAgICAgdGhpcy5maWxlLmRhdGEuc2V0KG9sZCk7CiAgICB9CiAgICB0aGlzLmZpbGUuZGF0YS5zZXQoZGF0YSwgTnVtYmVyKHRoaXMuZmlsZV9wb3MpKTsKICAgIHRoaXMuZmlsZV9wb3MgKz0gQmlnSW50KGRhdGEuYnl0ZUxlbmd0aCk7CiAgICByZXR1cm4geyByZXQ6IDAsIG53cml0dGVuOiBkYXRhLmJ5dGVMZW5ndGggfTsKICB9CiAgZmRfcHdyaXRlKGRhdGEsIG9mZnNldCkgewogICAgaWYgKHRoaXMuZmlsZS5yZWFkb25seSkKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBud3JpdHRlbjogMCB9OwogICAgaWYgKG9mZnNldCArIEJpZ0ludChkYXRhLmJ5dGVMZW5ndGgpID4gdGhpcy5maWxlLnNpemUpIHsKICAgICAgY29uc3Qgb2xkID0gdGhpcy5maWxlLmRhdGE7CiAgICAgIHRoaXMuZmlsZS5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoTnVtYmVyKG9mZnNldCArIEJpZ0ludChkYXRhLmJ5dGVMZW5ndGgpKSk7CiAgICAgIHRoaXMuZmlsZS5kYXRhLnNldChvbGQpOwogICAgfQogICAgdGhpcy5maWxlLmRhdGEuc2V0KGRhdGEsIE51bWJlcihvZmZzZXQpKTsKICAgIHJldHVybiB7IHJldDogMCwgbndyaXR0ZW46IGRhdGEuYnl0ZUxlbmd0aCB9OwogIH0KICBmZF9maWxlc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIGZpbGVzdGF0OiB0aGlzLmZpbGUuc3RhdCgpIH07CiAgfQogIGNvbnN0cnVjdG9yKGZpbGUpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLmZpbGVfcG9zID0gMG47CiAgICB0aGlzLmZpbGUgPSBmaWxlOwogIH0KfTsKdmFyIE9wZW5EaXJlY3RvcnkgPSBjbGFzcyBleHRlbmRzIEZkIHsKICBmZF9zZWVrKG9mZnNldCwgd2hlbmNlKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG9mZnNldDogMG4gfTsKICB9CiAgZmRfdGVsbCgpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fQkFERiwgb2Zmc2V0OiAwbiB9OwogIH0KICBmZF9hbGxvY2F0ZShvZmZzZXQsIGxlbikgewogICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgfQogIGZkX2Zkc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIGZkc3RhdDogbmV3IEZkc3RhdChGSUxFVFlQRV9ESVJFQ1RPUlksIDApIH07CiAgfQogIGZkX3JlYWRkaXJfc2luZ2xlKGNvb2tpZSkgewogICAgaWYgKGRlYnVnLmVuYWJsZWQpIHsKICAgICAgZGVidWcubG9nKCJyZWFkZGlyX3NpbmdsZSIsIGNvb2tpZSk7CiAgICAgIGRlYnVnLmxvZyhjb29raWUsIHRoaXMuZGlyLmNvbnRlbnRzLmtleXMoKSk7CiAgICB9CiAgICBpZiAoY29va2llID09IDBuKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZGlyZW50OiBuZXcgRGlyZW50KDFuLCAiLiIsIEZJTEVUWVBFX0RJUkVDVE9SWSkgfTsKICAgIH0gZWxzZSBpZiAoY29va2llID09IDFuKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZGlyZW50OiBuZXcgRGlyZW50KDJuLCAiLi4iLCBGSUxFVFlQRV9ESVJFQ1RPUlkpIH07CiAgICB9CiAgICBpZiAoY29va2llID49IEJpZ0ludCh0aGlzLmRpci5jb250ZW50cy5zaXplKSArIDJuKSB7CiAgICAgIHJldHVybiB7IHJldDogMCwgZGlyZW50OiBudWxsIH07CiAgICB9CiAgICBjb25zdCBbbmFtZSwgZW50cnldID0gQXJyYXkuZnJvbSh0aGlzLmRpci5jb250ZW50cy5lbnRyaWVzKCkpW051bWJlcihjb29raWUgLSAybildOwogICAgcmV0dXJuIHsgcmV0OiAwLCBkaXJlbnQ6IG5ldyBEaXJlbnQoY29va2llICsgMW4sIG5hbWUsIGVudHJ5LnN0YXQoKS5maWxldHlwZSkgfTsKICB9CiAgcGF0aF9maWxlc3RhdF9nZXQoZmxhZ3MsIHBhdGhfc3RyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9lcnIsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogcGF0aF9lcnIsIGZpbGVzdGF0OiBudWxsIH07CiAgICB9CiAgICBjb25zdCB7IHJldCwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9lbnRyeV9mb3JfcGF0aChwYXRoKTsKICAgIGlmIChlbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldCwgZmlsZXN0YXQ6IG51bGwgfTsKICAgIH0KICAgIHJldHVybiB7IHJldDogMCwgZmlsZXN0YXQ6IGVudHJ5LnN0YXQoKSB9OwogIH0KICBwYXRoX2xvb2t1cChwYXRoX3N0ciwgZGlyZmxhZ3MpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX3JldCwgcGF0aCB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXRoX3JldCwgaW5vZGVfb2JqOiBudWxsIH07CiAgICB9CiAgICBjb25zdCB7IHJldCwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9lbnRyeV9mb3JfcGF0aChwYXRoKTsKICAgIGlmIChlbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldCwgaW5vZGVfb2JqOiBudWxsIH07CiAgICB9CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGlub2RlX29iajogZW50cnkgfTsKICB9CiAgcGF0aF9vcGVuKGRpcmZsYWdzLCBwYXRoX3N0ciwgb2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcsIGZkX2ZsYWdzKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogcGF0aF9yZXQsIGZkX29iajogbnVsbCB9OwogICAgfQogICAgbGV0IHsgcmV0LCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgpOwogICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgaWYgKHJldCAhPSBFUlJOT19OT0VOVCkgewogICAgICAgIHJldHVybiB7IHJldCwgZmRfb2JqOiBudWxsIH07CiAgICAgIH0KICAgICAgaWYgKChvZmxhZ3MgJiBPRkxBR1NfQ1JFQVQpID09IE9GTEFHU19DUkVBVCkgewogICAgICAgIGNvbnN0IHsgcmV0OiByZXQyLCBlbnRyeTogbmV3X2VudHJ5IH0gPSB0aGlzLmRpci5jcmVhdGVfZW50cnlfZm9yX3BhdGgocGF0aF9zdHIsIChvZmxhZ3MgJiBPRkxBR1NfRElSRUNUT1JZKSA9PSBPRkxBR1NfRElSRUNUT1JZKTsKICAgICAgICBpZiAobmV3X2VudHJ5ID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiB7IHJldDogcmV0MiwgZmRfb2JqOiBudWxsIH07CiAgICAgICAgfQogICAgICAgIGVudHJ5ID0gbmV3X2VudHJ5OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9FTlQsIGZkX29iajogbnVsbCB9OwogICAgICB9CiAgICB9IGVsc2UgaWYgKChvZmxhZ3MgJiBPRkxBR1NfRVhDTCkgPT0gT0ZMQUdTX0VYQ0wpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19FWElTVCwgZmRfb2JqOiBudWxsIH07CiAgICB9CiAgICBpZiAoKG9mbGFncyAmIE9GTEFHU19ESVJFQ1RPUlkpID09IE9GTEFHU19ESVJFQ1RPUlkgJiYgZW50cnkuc3RhdCgpLmZpbGV0eXBlICE9PSBGSUxFVFlQRV9ESVJFQ1RPUlkpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIGZkX29iajogbnVsbCB9OwogICAgfQogICAgcmV0dXJuIGVudHJ5LnBhdGhfb3BlbihvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmZF9mbGFncyk7CiAgfQogIHBhdGhfY3JlYXRlX2RpcmVjdG9yeShwYXRoKSB7CiAgICByZXR1cm4gdGhpcy5wYXRoX29wZW4oMCwgcGF0aCwgT0ZMQUdTX0NSRUFUIHwgT0ZMQUdTX0RJUkVDVE9SWSwgMG4sIDBuLCAwKS5yZXQ7CiAgfQogIHBhdGhfbGluayhwYXRoX3N0ciwgaW5vZGUsIGFsbG93X2RpcikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4gcGF0aF9yZXQ7CiAgICB9CiAgICBpZiAocGF0aC5pc19kaXIpIHsKICAgICAgcmV0dXJuIEVSUk5PX05PRU5UOwogICAgfQogICAgY29uc3QgeyByZXQ6IHBhcmVudF9yZXQsIHBhcmVudF9lbnRyeSwgZmlsZW5hbWUsIGVudHJ5IH0gPSB0aGlzLmRpci5nZXRfcGFyZW50X2Rpcl9hbmRfZW50cnlfZm9yX3BhdGgocGF0aCwgdHJ1ZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCkgewogICAgICByZXR1cm4gcGFyZW50X3JldDsKICAgIH0KICAgIGlmIChlbnRyeSAhPSBudWxsKSB7CiAgICAgIGNvbnN0IHNvdXJjZV9pc19kaXIgPSBpbm9kZS5zdGF0KCkuZmlsZXR5cGUgPT0gRklMRVRZUEVfRElSRUNUT1JZOwogICAgICBjb25zdCB0YXJnZXRfaXNfZGlyID0gZW50cnkuc3RhdCgpLmZpbGV0eXBlID09IEZJTEVUWVBFX0RJUkVDVE9SWTsKICAgICAgaWYgKHNvdXJjZV9pc19kaXIgJiYgdGFyZ2V0X2lzX2RpcikgewogICAgICAgIGlmIChhbGxvd19kaXIgJiYgZW50cnkgaW5zdGFuY2VvZiBEaXJlY3RvcnkpIHsKICAgICAgICAgIGlmIChlbnRyeS5jb250ZW50cy5zaXplID09IDApIHsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBFUlJOT19OT1RFTVBUWTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIEVSUk5PX0VYSVNUOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChzb3VyY2VfaXNfZGlyICYmICF0YXJnZXRfaXNfZGlyKSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX05PVERJUjsKICAgICAgfSBlbHNlIGlmICghc291cmNlX2lzX2RpciAmJiB0YXJnZXRfaXNfZGlyKSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0lTRElSOwogICAgICB9IGVsc2UgaWYgKGlub2RlLnN0YXQoKS5maWxldHlwZSA9PSBGSUxFVFlQRV9SRUdVTEFSX0ZJTEUgJiYgZW50cnkuc3RhdCgpLmZpbGV0eXBlID09IEZJTEVUWVBFX1JFR1VMQVJfRklMRSkgewogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19FWElTVDsKICAgICAgfQogICAgfQogICAgaWYgKCFhbGxvd19kaXIgJiYgaW5vZGUuc3RhdCgpLmZpbGV0eXBlID09IEZJTEVUWVBFX0RJUkVDVE9SWSkgewogICAgICByZXR1cm4gRVJSTk9fUEVSTTsKICAgIH0KICAgIHBhcmVudF9lbnRyeS5jb250ZW50cy5zZXQoZmlsZW5hbWUsIGlub2RlKTsKICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogIH0KICBwYXRoX3VubGluayhwYXRoX3N0cikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhdGhfcmV0LCBpbm9kZV9vYmo6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBwYXJlbnRfcmV0LCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIHRydWUpOwogICAgaWYgKHBhcmVudF9lbnRyeSA9PSBudWxsIHx8IGZpbGVuYW1lID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXJlbnRfcmV0LCBpbm9kZV9vYmo6IG51bGwgfTsKICAgIH0KICAgIGlmIChlbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9FTlQsIGlub2RlX29iajogbnVsbCB9OwogICAgfQogICAgcGFyZW50X2VudHJ5LmNvbnRlbnRzLmRlbGV0ZShmaWxlbmFtZSk7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGlub2RlX29iajogZW50cnkgfTsKICB9CiAgcGF0aF91bmxpbmtfZmlsZShwYXRoX3N0cikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4gcGF0aF9yZXQ7CiAgICB9CiAgICBjb25zdCB7IHJldDogcGFyZW50X3JldCwgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9wYXJlbnRfZGlyX2FuZF9lbnRyeV9mb3JfcGF0aChwYXRoLCBmYWxzZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCB8fCBlbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXJlbnRfcmV0OwogICAgfQogICAgaWYgKGVudHJ5LnN0YXQoKS5maWxldHlwZSA9PT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgIHJldHVybiBFUlJOT19JU0RJUjsKICAgIH0KICAgIHBhcmVudF9lbnRyeS5jb250ZW50cy5kZWxldGUoZmlsZW5hbWUpOwogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIHBhdGhfcmVtb3ZlX2RpcmVjdG9yeShwYXRoX3N0cikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4gcGF0aF9yZXQ7CiAgICB9CiAgICBjb25zdCB7IHJldDogcGFyZW50X3JldCwgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9wYXJlbnRfZGlyX2FuZF9lbnRyeV9mb3JfcGF0aChwYXRoLCBmYWxzZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCB8fCBlbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXJlbnRfcmV0OwogICAgfQogICAgaWYgKCEoZW50cnkgaW5zdGFuY2VvZiBEaXJlY3RvcnkpIHx8IGVudHJ5LnN0YXQoKS5maWxldHlwZSAhPT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgIHJldHVybiBFUlJOT19OT1RESVI7CiAgICB9CiAgICBpZiAoZW50cnkuY29udGVudHMuc2l6ZSAhPT0gMCkgewogICAgICByZXR1cm4gRVJSTk9fTk9URU1QVFk7CiAgICB9CiAgICBpZiAoIXBhcmVudF9lbnRyeS5jb250ZW50cy5kZWxldGUoZmlsZW5hbWUpKSB7CiAgICAgIHJldHVybiBFUlJOT19OT0VOVDsKICAgIH0KICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogIH0KICBmZF9maWxlc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIGZpbGVzdGF0OiB0aGlzLmRpci5zdGF0KCkgfTsKICB9CiAgZmRfZmlsZXN0YXRfc2V0X3NpemUoc2l6ZSkgewogICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgfQogIGZkX3JlYWQoc2l6ZSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBkYXRhOiBuZXcgVWludDhBcnJheSgpIH07CiAgfQogIGZkX3ByZWFkKHNpemUsIG9mZnNldCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBkYXRhOiBuZXcgVWludDhBcnJheSgpIH07CiAgfQogIGZkX3dyaXRlKGRhdGEpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fQkFERiwgbndyaXR0ZW46IDAgfTsKICB9CiAgZmRfcHdyaXRlKGRhdGEsIG9mZnNldCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBud3JpdHRlbjogMCB9OwogIH0KICBjb25zdHJ1Y3RvcihkaXIpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLmRpciA9IGRpcjsKICB9Cn07CnZhciBQcmVvcGVuRGlyZWN0b3J5ID0gY2xhc3MgZXh0ZW5kcyBPcGVuRGlyZWN0b3J5IHsKICBmZF9wcmVzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgcHJlc3RhdDogUHJlc3RhdC5kaXIodGhpcy5wcmVzdGF0X25hbWUpIH07CiAgfQogIGNvbnN0cnVjdG9yKG5hbWUsIGNvbnRlbnRzKSB7CiAgICBzdXBlcihuZXcgRGlyZWN0b3J5KGNvbnRlbnRzKSk7CiAgICB0aGlzLnByZXN0YXRfbmFtZSA9IG5hbWU7CiAgfQp9Owp2YXIgRmlsZSA9IGNsYXNzIGV4dGVuZHMgSW5vZGUgewogIHBhdGhfb3BlbihvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmZF9mbGFncykgewogICAgaWYgKHRoaXMucmVhZG9ubHkgJiYgKGZzX3JpZ2h0c19iYXNlICYgQmlnSW50KFJJR0hUU19GRF9XUklURSkpID09IEJpZ0ludChSSUdIVFNfRkRfV1JJVEUpKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fUEVSTSwgZmRfb2JqOiBudWxsIH07CiAgICB9CiAgICBpZiAoKG9mbGFncyAmIE9GTEFHU19UUlVOQykgPT0gT0ZMQUdTX1RSVU5DKSB7CiAgICAgIGlmICh0aGlzLnJlYWRvbmx5KQogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fUEVSTSwgZmRfb2JqOiBudWxsIH07CiAgICAgIHRoaXMuZGF0YSA9IG5ldyBVaW50OEFycmF5KFtdKTsKICAgIH0KICAgIGNvbnN0IGZpbGUgPSBuZXcgT3BlbkZpbGUodGhpcyk7CiAgICBpZiAoZmRfZmxhZ3MgJiBGREZMQUdTX0FQUEVORCkKICAgICAgZmlsZS5mZF9zZWVrKDBuLCBXSEVOQ0VfRU5EKTsKICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZmRfb2JqOiBmaWxlIH07CiAgfQogIGdldCBzaXplKCkgewogICAgcmV0dXJuIEJpZ0ludCh0aGlzLmRhdGEuYnl0ZUxlbmd0aCk7CiAgfQogIHN0YXQoKSB7CiAgICByZXR1cm4gbmV3IEZpbGVzdGF0KEZJTEVUWVBFX1JFR1VMQVJfRklMRSwgdGhpcy5zaXplKTsKICB9CiAgY29uc3RydWN0b3IoZGF0YSwgb3B0aW9ucykgewogICAgc3VwZXIoKTsKICAgIHRoaXMuZGF0YSA9IG5ldyBVaW50OEFycmF5KGRhdGEpOwogICAgdGhpcy5yZWFkb25seSA9ICEhb3B0aW9ucz8ucmVhZG9ubHk7CiAgfQp9Owp2YXIgUGF0aCA9IGNsYXNzIFBhdGgyIHsKICBzdGF0aWMgZnJvbShwYXRoKSB7CiAgICBjb25zdCBzZWxmID0gbmV3IFBhdGgyKCk7CiAgICBzZWxmLmlzX2RpciA9IHBhdGguZW5kc1dpdGgoIi8iKTsKICAgIGlmIChwYXRoLnN0YXJ0c1dpdGgoIi8iKSkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVENBUEFCTEUsIHBhdGg6IG51bGwgfTsKICAgIH0KICAgIGlmIChwYXRoLmluY2x1ZGVzKCJcMCIpKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fSU5WQUwsIHBhdGg6IG51bGwgfTsKICAgIH0KICAgIGZvciAoY29uc3QgY29tcG9uZW50IG9mIHBhdGguc3BsaXQoIi8iKSkgewogICAgICBpZiAoY29tcG9uZW50ID09PSAiIiB8fCBjb21wb25lbnQgPT09ICIuIikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChjb21wb25lbnQgPT09ICIuLiIpIHsKICAgICAgICBpZiAoc2VsZi5wYXJ0cy5wb3AoKSA9PSB2b2lkIDApIHsKICAgICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UQ0FQQUJMRSwgcGF0aDogbnVsbCB9OwogICAgICAgIH0KICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBzZWxmLnBhcnRzLnB1c2goY29tcG9uZW50KTsKICAgIH0KICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgcGF0aDogc2VsZiB9OwogIH0KICB0b19wYXRoX3N0cmluZygpIHsKICAgIGxldCBzID0gdGhpcy5wYXJ0cy5qb2luKCIvIik7CiAgICBpZiAodGhpcy5pc19kaXIpIHsKICAgICAgcyArPSAiLyI7CiAgICB9CiAgICByZXR1cm4gczsKICB9CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLnBhcnRzID0gW107CiAgICB0aGlzLmlzX2RpciA9IGZhbHNlOwogIH0KfTsKdmFyIERpcmVjdG9yeSA9IGNsYXNzIGV4dGVuZHMgSW5vZGUgewogIHBhdGhfb3BlbihvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmZF9mbGFncykgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBmZF9vYmo6IG5ldyBPcGVuRGlyZWN0b3J5KHRoaXMpIH07CiAgfQogIHN0YXQoKSB7CiAgICByZXR1cm4gbmV3IEZpbGVzdGF0KEZJTEVUWVBFX0RJUkVDVE9SWSwgMG4pOwogIH0KICBnZXRfZW50cnlfZm9yX3BhdGgocGF0aCkgewogICAgbGV0IGVudHJ5ID0gdGhpczsKICAgIGZvciAoY29uc3QgY29tcG9uZW50IG9mIHBhdGgucGFydHMpIHsKICAgICAgaWYgKCEoZW50cnkgaW5zdGFuY2VvZiBEaXJlY3RvcnkpKSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIGVudHJ5OiBudWxsIH07CiAgICAgIH0KICAgICAgY29uc3QgY2hpbGQgPSBlbnRyeS5jb250ZW50cy5nZXQoY29tcG9uZW50KTsKICAgICAgaWYgKGNoaWxkICE9PSB2b2lkIDApIHsKICAgICAgICBlbnRyeSA9IGNoaWxkOwogICAgICB9IGVsc2UgewogICAgICAgIGRlYnVnLmxvZyhjb21wb25lbnQpOwogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9FTlQsIGVudHJ5OiBudWxsIH07CiAgICAgIH0KICAgIH0KICAgIGlmIChwYXRoLmlzX2RpcikgewogICAgICBpZiAoZW50cnkuc3RhdCgpLmZpbGV0eXBlICE9IEZJTEVUWVBFX0RJUkVDVE9SWSkgewogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9URElSLCBlbnRyeTogbnVsbCB9OwogICAgICB9CiAgICB9CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGVudHJ5IH07CiAgfQogIGdldF9wYXJlbnRfZGlyX2FuZF9lbnRyeV9mb3JfcGF0aChwYXRoLCBhbGxvd191bmRlZmluZWQpIHsKICAgIGNvbnN0IGZpbGVuYW1lID0gcGF0aC5wYXJ0cy5wb3AoKTsKICAgIGlmIChmaWxlbmFtZSA9PT0gdm9pZCAwKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fSU5WQUwsIHBhcmVudF9lbnRyeTogbnVsbCwgZmlsZW5hbWU6IG51bGwsIGVudHJ5OiBudWxsIH07CiAgICB9CiAgICBjb25zdCB7IHJldDogZW50cnlfcmV0LCBlbnRyeTogcGFyZW50X2VudHJ5IH0gPSB0aGlzLmdldF9lbnRyeV9mb3JfcGF0aChwYXRoKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IGVudHJ5X3JldCwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGlmICghKHBhcmVudF9lbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIHBhcmVudF9lbnRyeTogbnVsbCwgZmlsZW5hbWU6IG51bGwsIGVudHJ5OiBudWxsIH07CiAgICB9CiAgICBjb25zdCBlbnRyeSA9IHBhcmVudF9lbnRyeS5jb250ZW50cy5nZXQoZmlsZW5hbWUpOwogICAgaWYgKGVudHJ5ID09PSB2b2lkIDApIHsKICAgICAgaWYgKCFhbGxvd191bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PRU5ULCBwYXJlbnRfZW50cnk6IG51bGwsIGZpbGVuYW1lOiBudWxsLCBlbnRyeTogbnVsbCB9OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgfQogICAgaWYgKHBhdGguaXNfZGlyKSB7CiAgICAgIGlmIChlbnRyeS5zdGF0KCkuZmlsZXR5cGUgIT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIHBhcmVudF9lbnRyeTogbnVsbCwgZmlsZW5hbWU6IG51bGwsIGVudHJ5OiBudWxsIH07CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfTsKICB9CiAgY3JlYXRlX2VudHJ5X2Zvcl9wYXRoKHBhdGhfc3RyLCBpc19kaXIpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX3JldCwgcGF0aCB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXRoX3JldCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGxldCB7IHJldDogcGFyZW50X3JldCwgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfSA9IHRoaXMuZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIHRydWUpOwogICAgaWYgKHBhcmVudF9lbnRyeSA9PSBudWxsIHx8IGZpbGVuYW1lID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXJlbnRfcmV0LCBlbnRyeTogbnVsbCB9OwogICAgfQogICAgaWYgKGVudHJ5ICE9IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19FWElTVCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGRlYnVnLmxvZygiY3JlYXRlIiwgcGF0aCk7CiAgICBsZXQgbmV3X2NoaWxkOwogICAgaWYgKCFpc19kaXIpIHsKICAgICAgbmV3X2NoaWxkID0gbmV3IEZpbGUobmV3IEFycmF5QnVmZmVyKDApKTsKICAgIH0gZWxzZSB7CiAgICAgIG5ld19jaGlsZCA9IG5ldyBEaXJlY3RvcnkoLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKSk7CiAgICB9CiAgICBwYXJlbnRfZW50cnkuY29udGVudHMuc2V0KGZpbGVuYW1lLCBuZXdfY2hpbGQpOwogICAgZW50cnkgPSBuZXdfY2hpbGQ7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGVudHJ5IH07CiAgfQogIGNvbnN0cnVjdG9yKGNvbnRlbnRzKSB7CiAgICBzdXBlcigpOwogICAgaWYgKGNvbnRlbnRzIGluc3RhbmNlb2YgQXJyYXkpIHsKICAgICAgdGhpcy5jb250ZW50cyA9IG5ldyBNYXAoY29udGVudHMpOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5jb250ZW50cyA9IGNvbnRlbnRzOwogICAgfQogIH0KfTsKdmFyIENvbnNvbGVTdGRvdXQgPSBjbGFzcyBleHRlbmRzIEZkIHsKICBmZF9maWxlc3RhdF9nZXQoKSB7CiAgICBjb25zdCBmaWxlc3RhdCA9IG5ldyBGaWxlc3RhdChGSUxFVFlQRV9DSEFSQUNURVJfREVWSUNFLCBCaWdJbnQoMCkpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBmaWxlc3RhdCB9OwogIH0KICBmZF9mZHN0YXRfZ2V0KCkgewogICAgY29uc3QgZmRzdGF0ID0gbmV3IEZkc3RhdChGSUxFVFlQRV9DSEFSQUNURVJfREVWSUNFLCAwKTsKICAgIGZkc3RhdC5mc19yaWdodHNfYmFzZSA9IEJpZ0ludChSSUdIVFNfRkRfV1JJVEUpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBmZHN0YXQgfTsKICB9CiAgZmRfd3JpdGUoZGF0YSkgewogICAgdGhpcy53cml0ZShkYXRhKTsKICAgIHJldHVybiB7IHJldDogMCwgbndyaXR0ZW46IGRhdGEuYnl0ZUxlbmd0aCB9OwogIH0KICBzdGF0aWMgbGluZUJ1ZmZlcmVkKHdyaXRlKSB7CiAgICBjb25zdCBkZWMgPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IiwgeyBmYXRhbDogZmFsc2UgfSk7CiAgICBsZXQgbGluZV9idWYgPSAiIjsKICAgIHJldHVybiBuZXcgQ29uc29sZVN0ZG91dCgoYnVmZmVyKSA9PiB7CiAgICAgIGxpbmVfYnVmICs9IGRlYy5kZWNvZGUoYnVmZmVyLCB7IHN0cmVhbTogdHJ1ZSB9KTsKICAgICAgY29uc3QgbGluZXMgPSBsaW5lX2J1Zi5zcGxpdCgiXG4iKTsKICAgICAgZm9yIChjb25zdCBbaSwgbGluZV0gb2YgbGluZXMuZW50cmllcygpKSB7CiAgICAgICAgaWYgKGkgPCBsaW5lcy5sZW5ndGggLSAxKSB7CiAgICAgICAgICB3cml0ZShsaW5lKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbGluZV9idWYgPSBsaW5lOwogICAgICAgIH0KICAgICAgfQogICAgfSk7CiAgfQogIGNvbnN0cnVjdG9yKHdyaXRlKSB7CiAgICBzdXBlcigpOwogICAgdGhpcy53cml0ZSA9IHdyaXRlOwogIH0KfTsKCi8vIG5vZGVfbW9kdWxlcy93YXNtLWltcG9ydHMtcGFyc2VyL2luZGV4LmpzCmZ1bmN0aW9uIHBhcnNlSW1wb3J0cyhtb2R1bGVCeXRlcykgewogIGlmIChtb2R1bGVCeXRlcyBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHsKICB9IGVsc2UgaWYgKG1vZHVsZUJ5dGVzIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHsKICAgIG1vZHVsZUJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkobW9kdWxlQnl0ZXMpOwogIH0gZWxzZSBpZiAobW9kdWxlQnl0ZXMuYnVmZmVyIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHsKICAgIG1vZHVsZUJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkobW9kdWxlQnl0ZXMuYnVmZmVyKTsKICB9IGVsc2UgewogICAgdGhyb3cgbmV3IEVycm9yKCJBcmd1bWVudCBtdXN0IGJlIGEgYnVmZmVyIHNvdXJjZSwgbGlrZSBVaW50OEFycmF5IG9yIEFycmF5QnVmZmVyIik7CiAgfQogIGNvbnN0IHBhcnNlU3RhdGUgPSBuZXcgUGFyc2VTdGF0ZShtb2R1bGVCeXRlcyk7CiAgcGFyc2VNYWdpY051bWJlcihwYXJzZVN0YXRlKTsKICBwYXJzZVZlcnNpb24ocGFyc2VTdGF0ZSk7CiAgY29uc3QgdHlwZXMgPSBbXTsKICBjb25zdCBpbXBvcnRzID0gW107CiAgd2hpbGUgKHBhcnNlU3RhdGUuaGFzTW9yZUJ5dGVzKCkpIHsKICAgIGNvbnN0IHNlY3Rpb25JZCA9IHBhcnNlU3RhdGUucmVhZEJ5dGUoKTsKICAgIGNvbnN0IHNlY3Rpb25TaXplID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICAgIHN3aXRjaCAoc2VjdGlvbklkKSB7CiAgICAgIGNhc2UgMTogewogICAgICAgIGNvbnN0IHR5cGVDb3VudCA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0eXBlQ291bnQ7IGkrKykgewogICAgICAgICAgdHlwZXMucHVzaChwYXJzZUZ1bmN0aW9uVHlwZShwYXJzZVN0YXRlKSk7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGNhc2UgMjogewogICAgICAgIGNvbnN0IGltcG9ydENvdW50ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGltcG9ydENvdW50OyBpKyspIHsKICAgICAgICAgIGNvbnN0IG1vZHVsZSA9IHBhcnNlU3RhdGUucmVhZE5hbWUoKTsKICAgICAgICAgIGNvbnN0IG5hbWUgPSBwYXJzZVN0YXRlLnJlYWROYW1lKCk7CiAgICAgICAgICBjb25zdCB0eXBlID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogICAgICAgICAgc3dpdGNoICh0eXBlKSB7CiAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICBjb25zdCBpbmRleCA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgICAgICAgICAgICAgaW1wb3J0cy5wdXNoKHsgbW9kdWxlLCBuYW1lLCBraW5kOiAiZnVuY3Rpb24iLCB0eXBlOiB0eXBlc1tpbmRleF0gfSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgICBpbXBvcnRzLnB1c2goeyBtb2R1bGUsIG5hbWUsIGtpbmQ6ICJ0YWJsZSIsIHR5cGU6IHBhcnNlVGFibGVUeXBlKHBhcnNlU3RhdGUpIH0pOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgaW1wb3J0cy5wdXNoKHsgbW9kdWxlLCBuYW1lLCBraW5kOiAibWVtb3J5IiwgdHlwZTogcGFyc2VMaW1pdHMocGFyc2VTdGF0ZSkgfSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgICBpbXBvcnRzLnB1c2goeyBtb2R1bGUsIG5hbWUsIGtpbmQ6ICJnbG9iYWwiLCB0eXBlOiBwYXJzZUdsb2JhbFR5cGUocGFyc2VTdGF0ZSkgfSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGltcG9ydCBkZXNjcmlwdG9yIHR5cGUgJHt0eXBlfWApOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gaW1wb3J0czsKICAgICAgfQogICAgICBkZWZhdWx0OiB7CiAgICAgICAgcGFyc2VTdGF0ZS5za2lwQnl0ZXMoc2VjdGlvblNpemUpOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfQogIHJldHVybiBbXTsKfQp2YXIgUGFyc2VTdGF0ZSA9IGNsYXNzIHsKICBjb25zdHJ1Y3Rvcihtb2R1bGVCeXRlcykgewogICAgdGhpcy5tb2R1bGVCeXRlcyA9IG1vZHVsZUJ5dGVzOwogICAgdGhpcy5vZmZzZXQgPSAwOwogICAgdGhpcy50ZXh0RGVjb2RlciA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKTsKICB9CiAgaGFzTW9yZUJ5dGVzKCkgewogICAgcmV0dXJuIHRoaXMub2Zmc2V0IDwgdGhpcy5tb2R1bGVCeXRlcy5sZW5ndGg7CiAgfQogIHJlYWRCeXRlKCkgewogICAgcmV0dXJuIHRoaXMubW9kdWxlQnl0ZXNbdGhpcy5vZmZzZXQrK107CiAgfQogIHNraXBCeXRlcyhjb3VudCkgewogICAgdGhpcy5vZmZzZXQgKz0gY291bnQ7CiAgfQogIHJlYWRVbnNpZ25lZExFQjEyOCgpIHsKICAgIGxldCByZXN1bHQgPSAwOwogICAgbGV0IHNoaWZ0ID0gMDsKICAgIGxldCBieXRlOwogICAgZG8gewogICAgICBieXRlID0gdGhpcy5yZWFkQnl0ZSgpOwogICAgICByZXN1bHQgfD0gKGJ5dGUgJiAxMjcpIDw8IHNoaWZ0OwogICAgICBzaGlmdCArPSA3OwogICAgfSB3aGlsZSAoYnl0ZSAmIDEyOCk7CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICByZWFkTmFtZSgpIHsKICAgIGNvbnN0IG5hbWVMZW5ndGggPSB0aGlzLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgY29uc3QgbmFtZUJ5dGVzID0gdGhpcy5tb2R1bGVCeXRlcy5zbGljZSh0aGlzLm9mZnNldCwgdGhpcy5vZmZzZXQgKyBuYW1lTGVuZ3RoKTsKICAgIGNvbnN0IG5hbWUgPSB0aGlzLnRleHREZWNvZGVyLmRlY29kZShuYW1lQnl0ZXMpOwogICAgdGhpcy5vZmZzZXQgKz0gbmFtZUxlbmd0aDsKICAgIHJldHVybiBuYW1lOwogIH0KICBhc3NlcnRCeXRlcyhleHBlY3RlZCkgewogICAgY29uc3QgYmFzZU9mZnNldCA9IHRoaXMub2Zmc2V0OwogICAgY29uc3QgZXhwZWN0ZWRMZW5ndGggPSBleHBlY3RlZC5sZW5ndGg7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGV4cGVjdGVkTGVuZ3RoOyBpKyspIHsKICAgICAgaWYgKHRoaXMubW9kdWxlQnl0ZXNbYmFzZU9mZnNldCArIGldICE9PSBleHBlY3RlZFtpXSkgewogICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgJHtleHBlY3RlZH0gYXQgb2Zmc2V0ICR7YmFzZU9mZnNldH1gKTsKICAgICAgfQogICAgfQogICAgdGhpcy5vZmZzZXQgKz0gZXhwZWN0ZWRMZW5ndGg7CiAgfQp9OwpmdW5jdGlvbiBwYXJzZU1hZ2ljTnVtYmVyKHBhcnNlU3RhdGUpIHsKICBjb25zdCBleHBlY3RlZCA9IFswLCA5NywgMTE1LCAxMDldOwogIHBhcnNlU3RhdGUuYXNzZXJ0Qnl0ZXMoZXhwZWN0ZWQpOwp9CmZ1bmN0aW9uIHBhcnNlVmVyc2lvbihwYXJzZVN0YXRlKSB7CiAgY29uc3QgZXhwZWN0ZWQgPSBbMSwgMCwgMCwgMF07CiAgcGFyc2VTdGF0ZS5hc3NlcnRCeXRlcyhleHBlY3RlZCk7Cn0KZnVuY3Rpb24gcGFyc2VUYWJsZVR5cGUocGFyc2VTdGF0ZSkgewogIGNvbnN0IGVsZW1lbnRUeXBlID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogIGxldCBlbGVtZW50OwogIHN3aXRjaCAoZWxlbWVudFR5cGUpIHsKICAgIGNhc2UgMTEyOgogICAgICBlbGVtZW50ID0gImZ1bmNyZWYiOwogICAgICBicmVhazsKICAgIGNhc2UgMTExOgogICAgICBlbGVtZW50ID0gImV4dGVybnJlZiI7CiAgICAgIGJyZWFrOwogICAgZGVmYXVsdDoKICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIHRhYmxlIGVsZW1lbnQgdHlwZSAke2VsZW1lbnRUeXBlfWApOwogIH0KICBjb25zdCB7IG1pbmltdW0sIG1heGltdW0gfSA9IHBhcnNlTGltaXRzKHBhcnNlU3RhdGUpOwogIGlmIChtYXhpbXVtKSB7CiAgICByZXR1cm4geyBlbGVtZW50LCBtaW5pbXVtLCBtYXhpbXVtIH07CiAgfSBlbHNlIHsKICAgIHJldHVybiB7IGVsZW1lbnQsIG1pbmltdW0gfTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VMaW1pdHMocGFyc2VTdGF0ZSkgewogIGNvbnN0IGZsYWdzID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogIGNvbnN0IG1pbmltdW0gPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogIGNvbnN0IGhhc01heGltdW0gPSBmbGFncyAmIDE7CiAgY29uc3Qgc2hhcmVkID0gKGZsYWdzICYgMikgIT09IDA7CiAgY29uc3QgaXNNZW1vcnk2NCA9IChmbGFncyAmIDQpICE9PSAwOwogIGNvbnN0IGluZGV4ID0gaXNNZW1vcnk2NCA/ICJpNjQiIDogImkzMiI7CiAgaWYgKGhhc01heGltdW0pIHsKICAgIGNvbnN0IG1heGltdW0gPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgcmV0dXJuIHsgbWluaW11bSwgc2hhcmVkLCBpbmRleCwgbWF4aW11bSB9OwogIH0gZWxzZSB7CiAgICByZXR1cm4geyBtaW5pbXVtLCBzaGFyZWQsIGluZGV4IH07CiAgfQp9CmZ1bmN0aW9uIHBhcnNlR2xvYmFsVHlwZShwYXJzZVN0YXRlKSB7CiAgY29uc3QgdmFsdWUgPSBwYXJzZVZhbHVlVHlwZShwYXJzZVN0YXRlKTsKICBjb25zdCBtdXRhYmxlID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpID09PSAxOwogIHJldHVybiB7IHZhbHVlLCBtdXRhYmxlIH07Cn0KZnVuY3Rpb24gcGFyc2VWYWx1ZVR5cGUocGFyc2VTdGF0ZSkgewogIGNvbnN0IHR5cGUgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgc3dpdGNoICh0eXBlKSB7CiAgICBjYXNlIDEyNzoKICAgICAgcmV0dXJuICJpMzIiOwogICAgY2FzZSAxMjY6CiAgICAgIHJldHVybiAiaTY0IjsKICAgIGNhc2UgMTI1OgogICAgICByZXR1cm4gImYzMiI7CiAgICBjYXNlIDEyNDoKICAgICAgcmV0dXJuICJmNjQiOwogICAgY2FzZSAxMTI6CiAgICAgIHJldHVybiAiZnVuY3JlZiI7CiAgICBjYXNlIDExMToKICAgICAgcmV0dXJuICJleHRlcm5yZWYiOwogICAgY2FzZSAxMjM6CiAgICAgIHJldHVybiAidjEyOCI7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gdmFsdWUgdHlwZSAke3R5cGV9YCk7CiAgfQp9CmZ1bmN0aW9uIHBhcnNlRnVuY3Rpb25UeXBlKHBhcnNlU3RhdGUpIHsKICBjb25zdCBmb3JtID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogIGlmIChmb3JtICE9PSA5NikgewogICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBmdW5jdGlvbiB0eXBlIGZvcm0gMHg2MCwgZ290ICR7Zm9ybX1gKTsKICB9CiAgY29uc3QgcGFyYW1ldGVycyA9IFtdOwogIGNvbnN0IHBhcmFtZXRlckNvdW50ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICBmb3IgKGxldCBpID0gMDsgaSA8IHBhcmFtZXRlckNvdW50OyBpKyspIHsKICAgIHBhcmFtZXRlcnMucHVzaChwYXJzZVZhbHVlVHlwZShwYXJzZVN0YXRlKSk7CiAgfQogIGNvbnN0IHJlc3VsdHMgPSBbXTsKICBjb25zdCByZXN1bHRDb3VudCA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgZm9yIChsZXQgaSA9IDA7IGkgPCByZXN1bHRDb3VudDsgaSsrKSB7CiAgICByZXN1bHRzLnB1c2gocGFyc2VWYWx1ZVR5cGUocGFyc2VTdGF0ZSkpOwogIH0KICByZXR1cm4geyBwYXJhbWV0ZXJzLCByZXN1bHRzIH07Cn0KCi8vIG5vZGVfbW9kdWxlcy93YXNtLWltcG9ydHMtcGFyc2VyL3BvbHlmaWxsLmpzCnZhciBoYXNXYXNtVHlwZVJlZmxlY3Rpb25TdXBwb3J0ID0gKCgpID0+IHsKICBjb25zdCBtb2R1bGVCeXRlcyA9IG5ldyBVaW50OEFycmF5KFsKICAgIDAsCiAgICA5NywKICAgIDExNSwKICAgIDEwOSwKICAgIDEsCiAgICAwLAogICAgMCwKICAgIDAsCiAgICAyLAogICAgNiwKICAgIDEsCiAgICAwLAogICAgMCwKICAgIDIsCiAgICAwLAogICAgMQogIF0pOwogIGNvbnN0IG1vZHVsZSA9IG5ldyBXZWJBc3NlbWJseS5Nb2R1bGUobW9kdWxlQnl0ZXMpOwogIGNvbnN0IGltcG9ydHMgPSBXZWJBc3NlbWJseS5Nb2R1bGUuaW1wb3J0cyhtb2R1bGUpOwogIGNvbnN0IG1lbW9yeUltcG9ydCA9IGltcG9ydHNbMF07CiAgcmV0dXJuIHR5cGVvZiBtZW1vcnlJbXBvcnQudHlwZSA9PT0gIm9iamVjdCI7Cn0pKCk7CmZ1bmN0aW9uIHBvbHlmaWxsKFdlYkFzc2VtYmx5MykgewogIGlmIChoYXNXYXNtVHlwZVJlZmxlY3Rpb25TdXBwb3J0KSB7CiAgICByZXR1cm4gV2ViQXNzZW1ibHkzOwogIH0KICBjb25zdCBuZXdXZWJBc3NlbWJseSA9IHt9OwogIGZvciAoY29uc3Qga2V5IGluIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzKFdlYkFzc2VtYmx5MykpIHsKICAgIG5ld1dlYkFzc2VtYmx5W2tleV0gPSBXZWJBc3NlbWJseTNba2V5XTsKICB9CiAgY29uc3QgcG9seWZpbGxlZEltcG9ydHNTeW1ib2wgPSBTeW1ib2woInBvbHlmaWxsZWRJbXBvcnRzU3ltYm9sIik7CiAgY29uc3QgYXNzaWduSW1wb3J0cyA9IChtb2R1bGUsIHNvdXJjZUJ5dGVzKSA9PiB7CiAgICBtb2R1bGVbcG9seWZpbGxlZEltcG9ydHNTeW1ib2xdID0gcGFyc2VJbXBvcnRzKHNvdXJjZUJ5dGVzKTsKICB9OwogIGNvbnN0IG5ld01vZHVsZSA9IG5ld1dlYkFzc2VtYmx5Lk1vZHVsZSA9IGZ1bmN0aW9uKGJ5dGVzKSB7CiAgICBjb25zdCBtb2R1bGUgPSBuZXcgV2ViQXNzZW1ibHkzLk1vZHVsZShieXRlcyk7CiAgICBhc3NpZ25JbXBvcnRzKG1vZHVsZSwgYnl0ZXMpOwogICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKG1vZHVsZSwgbmV3TW9kdWxlLnByb3RvdHlwZSk7CiAgICByZXR1cm4gbW9kdWxlOwogIH07CiAgT2JqZWN0LnNldFByb3RvdHlwZU9mKG5ld01vZHVsZS5wcm90b3R5cGUsIFdlYkFzc2VtYmx5My5Nb2R1bGUucHJvdG90eXBlKTsKICBuZXdXZWJBc3NlbWJseS5jb21waWxlID0gYXN5bmMgKHNvdXJjZSkgPT4gewogICAgY29uc3QgbW9kdWxlID0gYXdhaXQgV2ViQXNzZW1ibHkzLmNvbXBpbGUoc291cmNlKTsKICAgIGFzc2lnbkltcG9ydHMobW9kdWxlLCBzb3VyY2UpOwogICAgcmV0dXJuIG1vZHVsZTsKICB9OwogIGlmIChXZWJBc3NlbWJseTMuY29tcGlsZVN0cmVhbWluZykgewogICAgbmV3V2ViQXNzZW1ibHkuY29tcGlsZVN0cmVhbWluZyA9IGFzeW5jIChzb3VyY2UpID0+IHsKICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBzb3VyY2U7CiAgICAgIGNvbnN0IGNsb25lID0gcmVzcG9uc2UuY2xvbmUoKTsKICAgICAgY29uc3QgbW9kdWxlID0gYXdhaXQgV2ViQXNzZW1ibHkzLmNvbXBpbGVTdHJlYW1pbmcocmVzcG9uc2UpOwogICAgICBhc3NpZ25JbXBvcnRzKG1vZHVsZSwgbmV3IFVpbnQ4QXJyYXkoYXdhaXQgY2xvbmUuYXJyYXlCdWZmZXIoKSkpOwogICAgICByZXR1cm4gbW9kdWxlOwogICAgfTsKICB9CiAgbmV3TW9kdWxlLmltcG9ydHMgPSAobW9kdWxlKSA9PiB7CiAgICBjb25zdCBwYXJzZWRJbXBvcnRzID0gbW9kdWxlW3BvbHlmaWxsZWRJbXBvcnRzU3ltYm9sXTsKICAgIGlmICghcGFyc2VkSW1wb3J0cykgewogICAgICByZXR1cm4gV2ViQXNzZW1ibHkzLk1vZHVsZS5pbXBvcnRzKG1vZHVsZSk7CiAgICB9CiAgICByZXR1cm4gcGFyc2VkSW1wb3J0czsKICB9OwogIHJldHVybiBuZXdXZWJBc3NlbWJseTsKfQoKLy8gZW50cnlwb2ludC9pbnRyaW5zaWNzLnRzCnZhciBXZWJBc3NlbWJseTIgPSBwb2x5ZmlsbChnbG9iYWxUaGlzLldlYkFzc2VtYmx5KTsKdmFyIExpbmVEZWNvZGVyID0gY2xhc3MgewogIGNvbnN0cnVjdG9yKG9uTGluZSkgewogICAgdGhpcy5kZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIsIHsgZmF0YWw6IGZhbHNlIH0pOwogICAgdGhpcy5idWZmZXIgPSAiIjsKICAgIHRoaXMub25MaW5lID0gb25MaW5lOwogIH0KICBkZWNvZGVyOwogIGJ1ZmZlcjsKICBvbkxpbmU7CiAgc2VuZChjaHVuaykgewogICAgdGhpcy5idWZmZXIgKz0gdGhpcy5kZWNvZGVyLmRlY29kZShjaHVuaywgeyBzdHJlYW06IHRydWUgfSk7CiAgICBjb25zdCBsaW5lcyA9IHRoaXMuYnVmZmVyLnNwbGl0KCJcbiIpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGggLSAxOyBpKyspIHsKICAgICAgdGhpcy5vbkxpbmUobGluZXNbaV0pOwogICAgfQogICAgdGhpcy5idWZmZXIgPSBsaW5lc1tsaW5lcy5sZW5ndGggLSAxXTsKICB9Cn07CmFzeW5jIGZ1bmN0aW9uIGluc3RhbnRpYXRlKHJhd09wdGlvbnMsIGV4dHJhV2FzbUltcG9ydHMpIHsKICBjb25zdCBvcHRpb25zID0gZGVmYXVsdEluc3RhbnRpYXRpb25PcHRpb25zKHJhd09wdGlvbnMpOwogIGxldCBzd2lmdCA9IG9wdGlvbnMuc3dpZnQ7CiAgaWYgKCFzd2lmdCAmJiBvcHRpb25zLlN3aWZ0UnVudGltZSkgewogICAgc3dpZnQgPSBuZXcgb3B0aW9ucy5Td2lmdFJ1bnRpbWUoKTsKICB9CiAgbGV0IHN0ZG91dExpbmUgPSB2b2lkIDA7CiAgaWYgKG9wdGlvbnMub25TdGRvdXRMaW5lICE9IG51bGwpIHsKICAgIHN0ZG91dExpbmUgPSBuZXcgTGluZURlY29kZXIob3B0aW9ucy5vblN0ZG91dExpbmUpOwogIH0KICBjb25zdCBzdGRvdXQgPSBuZXcgQ29uc29sZVN0ZG91dCgoY2h1bmspID0+IHsKICAgIG9wdGlvbnMub25TdGRvdXQ/LmNhbGwodm9pZCAwLCBjaHVuayk7CiAgICBzdGRvdXRMaW5lPy5zZW5kKGNodW5rKTsKICB9KTsKICBsZXQgc3RkZXJyTGluZSA9IHZvaWQgMDsKICBpZiAob3B0aW9ucy5vblN0ZGVyckxpbmUgIT0gbnVsbCkgewogICAgc3RkZXJyTGluZSA9IG5ldyBMaW5lRGVjb2RlcihvcHRpb25zLm9uU3RkZXJyTGluZSk7CiAgfQogIGNvbnN0IHN0ZGVyciA9IG5ldyBDb25zb2xlU3Rkb3V0KChjaHVuaykgPT4gewogICAgb3B0aW9ucy5vblN0ZGVycj8uY2FsbCh2b2lkIDAsIGNodW5rKTsKICAgIHN0ZGVyckxpbmU/LnNlbmQoY2h1bmspOwogIH0pOwogIGNvbnN0IGFyZ3MgPSBvcHRpb25zLmFyZ3MgfHwgW107CiAgY29uc3QgZmRzID0gWwogICAgbmV3IE9wZW5GaWxlKG5ldyBGaWxlKFtdKSksCiAgICBzdGRvdXQsCiAgICBzdGRlcnIsCiAgICBuZXcgUHJlb3BlbkRpcmVjdG9yeSgiLyIsIC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCkpCiAgXTsKICBjb25zdCBlbnZzID0gb3B0aW9ucy5lbnYgPyBPYmplY3QuZW50cmllcyhvcHRpb25zLmVudikubWFwKChba2V5LCB2YWx1ZV0pID0+IGAke2tleX09JHt2YWx1ZX1gKSA6IFtdOwogIGNvbnN0IHdhc2kgPSBuZXcgV0FTSShhcmdzLCBlbnZzLCBmZHMsIHsKICAgIGRlYnVnOiBmYWxzZQogIH0pOwogIGNvbnN0IGNyZWF0ZVdhc21JbXBvcnRPYmplY3QgPSAoZXh0cmFXYXNtSW1wb3J0czIsIG1vZHVsZSkgPT4gewogICAgY29uc3QgaW1wb3J0T2JqZWN0MiA9IHsKICAgICAgd2FzaV9zbmFwc2hvdF9wcmV2aWV3MTogd2FzaS53YXNpSW1wb3J0CiAgICB9OwogICAgaWYgKHN3aWZ0KSB7CiAgICAgIGltcG9ydE9iamVjdDIuamF2YXNjcmlwdF9raXQgPSBzd2lmdC53YXNtSW1wb3J0czsKICAgIH0KICAgIGlmIChleHRyYVdhc21JbXBvcnRzMikgewogICAgICBmb3IgKGNvbnN0IG1vZHVsZU5hbWUgaW4gZXh0cmFXYXNtSW1wb3J0czIpIHsKICAgICAgICBpZiAoIWltcG9ydE9iamVjdDJbbW9kdWxlTmFtZV0pIHsKICAgICAgICAgIGltcG9ydE9iamVjdDJbbW9kdWxlTmFtZV0gPSB7fTsKICAgICAgICB9CiAgICAgICAgZm9yIChjb25zdCBlbnRyeSBpbiBleHRyYVdhc21JbXBvcnRzMlttb2R1bGVOYW1lXSkgewogICAgICAgICAgaW1wb3J0T2JqZWN0Mlttb2R1bGVOYW1lXVtlbnRyeV0gPSBleHRyYVdhc21JbXBvcnRzMlttb2R1bGVOYW1lXVtlbnRyeV07CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBmb3IgKGNvbnN0IF9pbXBvcnRFbnRyeSBvZiBXZWJBc3NlbWJseTIuTW9kdWxlLmltcG9ydHMobW9kdWxlKSkgewogICAgICBjb25zdCBpbXBvcnRFbnRyeSA9IF9pbXBvcnRFbnRyeTsKICAgICAgaWYgKCFpbXBvcnRPYmplY3QyW2ltcG9ydEVudHJ5Lm1vZHVsZV0pIHsKICAgICAgICBpbXBvcnRPYmplY3QyW2ltcG9ydEVudHJ5Lm1vZHVsZV0gPSB7fTsKICAgICAgfQogICAgICBpZiAoaW1wb3J0T2JqZWN0MltpbXBvcnRFbnRyeS5tb2R1bGVdW2ltcG9ydEVudHJ5Lm5hbWVdKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGltcG9ydEVudHJ5LmtpbmQgPT0gImZ1bmN0aW9uIikgewogICAgICAgIGltcG9ydE9iamVjdDJbaW1wb3J0RW50cnkubW9kdWxlXVtpbXBvcnRFbnRyeS5uYW1lXSA9ICgpID0+IHsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW1wb3J0ZWQgZnVuY3Rpb24gJHtpbXBvcnRFbnRyeS5tb2R1bGV9LiR7aW1wb3J0RW50cnkubmFtZX0gbm90IGltcGxlbWVudGVkYCk7CiAgICAgICAgfTsKICAgICAgfSBlbHNlIGlmIChpbXBvcnRFbnRyeS5raW5kID09ICJtZW1vcnkiICYmIGltcG9ydEVudHJ5Lm1vZHVsZSA9PSAiZW52IiAmJiBpbXBvcnRFbnRyeS5uYW1lID09ICJtZW1vcnkiKSB7CiAgICAgICAgY29uc3QgdHlwZSA9IGltcG9ydEVudHJ5LnR5cGU7CiAgICAgICAgY29uc3QgZGVzY3JpcHRvciA9IHsKICAgICAgICAgIGluaXRpYWw6IHR5cGUubWluaW11bSwKICAgICAgICAgIG1heGltdW06IHR5cGUubWF4aW11bSwKICAgICAgICAgIHNoYXJlZDogdHlwZS5zaGFyZWQKICAgICAgICB9OwogICAgICAgIGltcG9ydE9iamVjdDJbaW1wb3J0RW50cnkubW9kdWxlXVtpbXBvcnRFbnRyeS5uYW1lXSA9IG5ldyBXZWJBc3NlbWJseTIuTWVtb3J5KGRlc2NyaXB0b3IpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gaW1wb3J0T2JqZWN0MjsKICB9OwogIGNvbnN0IGltcG9ydE9iamVjdCA9IGNyZWF0ZVdhc21JbXBvcnRPYmplY3QoZXh0cmFXYXNtSW1wb3J0cywgb3B0aW9ucy5tb2R1bGUpOwogIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgV2ViQXNzZW1ibHkyLmluc3RhbnRpYXRlKG9wdGlvbnMubW9kdWxlLCBpbXBvcnRPYmplY3QpOwogIGlmIChzd2lmdCAmJiBpbnN0YW5jZS5leHBvcnRzLnN3anNfbGlicmFyeV92ZXJzaW9uKSB7CiAgICBzd2lmdC5zZXRJbnN0YW5jZShpbnN0YW5jZSk7CiAgfQogIGlmICh0eXBlb2YgaW5zdGFuY2UuZXhwb3J0cy5fc3RhcnQgPT09ICJmdW5jdGlvbiIpIHsKICAgIHdhc2kuc3RhcnQoaW5zdGFuY2UpOwogIH0gZWxzZSBpZiAodHlwZW9mIGluc3RhbmNlLmV4cG9ydHMuX2luaXRpYWxpemUgPT0gImZ1bmN0aW9uIikgewogICAgd2FzaS5pbml0aWFsaXplKGluc3RhbmNlKTsKICAgIGlmIChzd2lmdCAmJiBzd2lmdC5tYWluKSB7CiAgICAgIHN3aWZ0Lm1haW4oKTsKICAgIH0gZWxzZSB7CiAgICAgIGlmICh0eXBlb2YgaW5zdGFuY2UuZXhwb3J0cy5tYWluID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgaW5zdGFuY2UuZXhwb3J0cy5tYWluKCk7CiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGluc3RhbmNlLmV4cG9ydHMuX19tYWluX2FyZ2NfYXJndiA9PT0gImZ1bmN0aW9uIikgewogICAgICAgIGluc3RhbmNlLmV4cG9ydHMuX19tYWluX2FyZ2NfYXJndigwLCAwKTsKICAgICAgfQogICAgfQogIH0KICByZXR1cm4geyBpbnN0YW5jZSB9Owp9CmZ1bmN0aW9uIGRlZmF1bHRJbnN0YW50aWF0aW9uT3B0aW9ucyhvcHRpb25zKSB7CiAgaWYgKG9wdGlvbnMuYXJncyA9PSBudWxsKSB7CiAgICBvcHRpb25zLmFyZ3MgPSBbIm1haW4ud2FzbSJdOwogIH0KICBjb25zdCBpc05vZGVKcyA9IHR5cGVvZiBwcm9jZXNzICE9PSAidW5kZWZpbmVkIiAmJiBwcm9jZXNzLnJlbGVhc2UubmFtZSA9PT0gIm5vZGUiOwogIGNvbnN0IGlzV2ViQnJvd3NlciA9IHR5cGVvZiB3aW5kb3cgIT09ICJ1bmRlZmluZWQiOwogIGlmIChpc05vZGVKcykgewogICAgaWYgKCFvcHRpb25zLm9uU3Rkb3V0KSB7CiAgICAgIG9wdGlvbnMub25TdGRvdXQgPSAoY2h1bmspID0+IHByb2Nlc3Muc3Rkb3V0LndyaXRlKGNodW5rKTsKICAgIH0KICAgIGlmICghb3B0aW9ucy5vblN0ZGVycikgewogICAgICBvcHRpb25zLm9uU3RkZXJyID0gKGNodW5rKSA9PiBwcm9jZXNzLnN0ZGVyci53cml0ZShjaHVuayk7CiAgICB9CiAgfSBlbHNlIGlmIChpc1dlYkJyb3dzZXIpIHsKICAgIGlmICghb3B0aW9ucy5vblN0ZG91dExpbmUpIHsKICAgICAgb3B0aW9ucy5vblN0ZG91dExpbmUgPSAobGluZSkgPT4gY29uc29sZS5sb2cobGluZSk7CiAgICB9CiAgICBpZiAoIW9wdGlvbnMub25TdGRlcnJMaW5lKSB7CiAgICAgIG9wdGlvbnMub25TdGRlcnJMaW5lID0gKGxpbmUpID0+IGNvbnNvbGUud2FybihsaW5lKTsKICAgIH0KICB9CiAgcmV0dXJuIG9wdGlvbnM7Cn0KCi8vIGVudHJ5cG9pbnQvdGVzdC50cwp2YXIgc29ja2V0ID0gbmV3IHJlY29ubmVjdGluZ193ZWJzb2NrZXRfbWpzX2RlZmF1bHQoYHdzOi8vJHtsb2NhdGlvbi5ob3N0fS93YXRjaGVyYCk7CnNvY2tldC5hZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIiwgKG1lc3NhZ2UpID0+IHsKICBpZiAobWVzc2FnZS5kYXRhID09PSAicmVsb2FkIikgewogICAgbG9jYXRpb24ucmVsb2FkKCk7CiAgfQp9KTsKdmFyIHN0YXJ0V2FzaVRhc2sgPSBhc3luYyAoKSA9PiB7CiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCgiL21haW4ud2FzbSIpOwogIGxldCBydW50aW1lQ29uc3RydWN0b3IgPSB2b2lkIDA7CiAgdHJ5IHsKICAgIGNvbnN0IHsgU3dpZnRSdW50aW1lIH0gPSBhd2FpdCBpbXBvcnQoCiAgICAgIC8vIEB0cy1pZ25vcmUKICAgICAgIi4vSmF2YVNjcmlwdEtpdF9KYXZhU2NyaXB0S2l0LnJlc291cmNlcy9SdW50aW1lL2luZGV4Lm1qcyIKICAgICk7CiAgICBydW50aW1lQ29uc3RydWN0b3IgPSBTd2lmdFJ1bnRpbWU7CiAgfSBjYXRjaCB7CiAgICBjb25zb2xlLmxvZygiSmF2YVNjcmlwdEtpdCBtb2R1bGUgbm90IGF2YWlsYWJsZSwgcnVubmluZyB3aXRob3V0IEphdmFTY3JpcHRLaXQgcnVudGltZS4iKTsKICB9CiAgY29uc3QgY29uZmlnID0gYXdhaXQgZmV0Y2goIi9wcm9jZXNzLWluZm8uanNvbiIpLnRoZW4oKHJlc3BvbnNlMikgPT4gcmVzcG9uc2UyLmpzb24oKSk7CiAgbGV0IHRlc3RSdW5PdXRwdXQgPSAiIjsKICBjb25zdCBoYW5kbGVFeGl0T3JFcnJvciA9IChlcnJvcikgPT4gewogICAgaWYgKGVycm9yIGluc3RhbmNlb2YgV0FTSVByb2NFeGl0KSB7CiAgICAgIHNvY2tldC5zZW5kKEpTT04uc3RyaW5naWZ5KHsga2luZDogInRlc3RSdW5PdXRwdXQiLCB0ZXN0UnVuT3V0cHV0IH0pKTsKICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDApIHsKICAgICAgICBzb2NrZXQuc2VuZChKU09OLnN0cmluZ2lmeSh7IGtpbmQ6ICJ0ZXN0UGFzc2VkIiB9KSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaGFuZGxlRXJyb3IoZXJyb3IpOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBoYW5kbGVFcnJvcihlcnJvcik7CiAgICB9CiAgICBjb25zdCBkaXZFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgicCIpOwogICAgZGl2RWxlbWVudC5pbm5lckhUTUwgPSAiVGVzdCBydW4gZmluaXNoZWQuIENoZWNrIHRoZSBvdXRwdXQgb2YgPGNvZGU+Y2FydG9uIHRlc3Q8L2NvZGU+IGZvciBkZXRhaWxzLiI7CiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGRpdkVsZW1lbnQpOwogIH07CiAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoInVuaGFuZGxlZHJlamVjdGlvbiIsIChldmVudCkgPT4gewogICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsKICAgIGNvbnN0IGVycm9yID0gZXZlbnQucmVhc29uOwogICAgaGFuZGxlRXhpdE9yRXJyb3IoZXJyb3IpOwogIH0pOwogIHRyeSB7CiAgICBhd2FpdCBpbnN0YW50aWF0ZSh7CiAgICAgIG1vZHVsZTogYXdhaXQgV2ViQXNzZW1ibHkuY29tcGlsZVN0cmVhbWluZyhyZXNwb25zZSksCiAgICAgIGVudjogY29uZmlnLmVudiwKICAgICAgb25TdGRvdXRMaW5lOiAobGluZSkgPT4gewogICAgICAgIGNvbnNvbGUubG9nKGxpbmUpOwogICAgICAgIHRlc3RSdW5PdXRwdXQgKz0gbGluZSArICJcbiI7CiAgICAgIH0sCiAgICAgIG9uU3RkZXJyTGluZTogKGxpbmUpID0+IHsKICAgICAgICBjb25zb2xlLmVycm9yKGxpbmUpOwogICAgICB9LAogICAgICBTd2lmdFJ1bnRpbWU6IHJ1bnRpbWVDb25zdHJ1Y3RvcgogICAgfSk7CiAgfSBjYXRjaCAoZXJyb3IpIHsKICAgIGhhbmRsZUV4aXRPckVycm9yKGVycm9yKTsKICAgIHJldHVybjsKICB9Cn07CmZ1bmN0aW9uIGhhbmRsZUVycm9yKGUpIHsKICBjb25zb2xlLmVycm9yKGUpOwogIGlmIChlIGluc3RhbmNlb2YgRXJyb3IpIHsKICAgIGNvbnN0IHN0YWNrID0gZS5zdGFjazsKICAgIGlmIChzdGFjayAhPSBudWxsKSB7CiAgICAgIHNvY2tldC5zZW5kKEpTT04uc3RyaW5naWZ5KHsKICAgICAgICBraW5kOiAic3RhY2tUcmFjZSIsCiAgICAgICAgc3RhY2tUcmFjZTogc3RhY2sKICAgICAgfSkpOwogICAgfQogIH0KICBzb2NrZXQuc2VuZChKU09OLnN0cmluZ2lmeSh7CiAgICBraW5kOiAiZXJyb3JSZXBvcnQiLAogICAgZXJyb3JSZXBvcnQ6IGUudG9TdHJpbmcoKQogIH0pKTsKfQphc3luYyBmdW5jdGlvbiBtYWluKCkgewogIHRyeSB7CiAgICBhd2FpdCBzdGFydFdhc2lUYXNrKCk7CiAgfSBjYXRjaCAoZSkgewogICAgaGFuZGxlRXJyb3IoZSk7CiAgfQp9Cm1haW4oKTsKLyohCiAqIFJlY29ubmVjdGluZyBXZWJTb2NrZXQKICogYnkgUGVkcm8gTGFkYXJpYSA8cGVkcm8ubGFkYXJpYUBnbWFpbC5jb20+CiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9wbGFkYXJpYS9yZWNvbm5lY3Rpbmctd2Vic29ja2V0CiAqIExpY2Vuc2UgTUlUCiAqLwovKiEgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuCkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOyB5b3UgbWF5IG5vdCB1c2UKdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUKTGljZW5zZSBhdCBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAKClRISVMgQ09ERSBJUyBQUk9WSURFRCBPTiBBTiAqQVMgSVMqIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkKS0lORCwgRUlUSEVSIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIFdJVEhPVVQgTElNSVRBVElPTiBBTlkgSU1QTElFRApXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgVElUTEUsIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLApNRVJDSEFOVEFCTElUWSBPUiBOT04tSU5GUklOR0VNRU5ULgoKU2VlIHRoZSBBcGFjaGUgVmVyc2lvbiAyLjAgTGljZW5zZSBmb3Igc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zCmFuZCBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi8K")! - public static let testNode: Data = Data(base64Encoded: "dmFyIF9fY3JlYXRlID0gT2JqZWN0LmNyZWF0ZTsKdmFyIF9fZGVmUHJvcCA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTsKdmFyIF9fZ2V0T3duUHJvcERlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yOwp2YXIgX19nZXRPd25Qcm9wTmFtZXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lczsKdmFyIF9fZ2V0UHJvdG9PZiA9IE9iamVjdC5nZXRQcm90b3R5cGVPZjsKdmFyIF9faGFzT3duUHJvcCA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7CnZhciBfX2NvcHlQcm9wcyA9ICh0bywgZnJvbSwgZXhjZXB0LCBkZXNjKSA9PiB7CiAgaWYgKGZyb20gJiYgdHlwZW9mIGZyb20gPT09ICJvYmplY3QiIHx8IHR5cGVvZiBmcm9tID09PSAiZnVuY3Rpb24iKSB7CiAgICBmb3IgKGxldCBrZXkgb2YgX19nZXRPd25Qcm9wTmFtZXMoZnJvbSkpCiAgICAgIGlmICghX19oYXNPd25Qcm9wLmNhbGwodG8sIGtleSkgJiYga2V5ICE9PSBleGNlcHQpCiAgICAgICAgX19kZWZQcm9wKHRvLCBrZXksIHsgZ2V0OiAoKSA9PiBmcm9tW2tleV0sIGVudW1lcmFibGU6ICEoZGVzYyA9IF9fZ2V0T3duUHJvcERlc2MoZnJvbSwga2V5KSkgfHwgZGVzYy5lbnVtZXJhYmxlIH0pOwogIH0KICByZXR1cm4gdG87Cn07CnZhciBfX3RvRVNNID0gKG1vZCwgaXNOb2RlTW9kZSwgdGFyZ2V0KSA9PiAodGFyZ2V0ID0gbW9kICE9IG51bGwgPyBfX2NyZWF0ZShfX2dldFByb3RvT2YobW9kKSkgOiB7fSwgX19jb3B5UHJvcHMoaXNOb2RlTW9kZSB8fCAhbW9kIHx8ICFtb2QuX19lc01vZHVsZSA/IF9fZGVmUHJvcCh0YXJnZXQsICJkZWZhdWx0IiwgeyB2YWx1ZTogbW9kLCBlbnVtZXJhYmxlOiB0cnVlIH0pIDogdGFyZ2V0LCBtb2QpKTsKCi8vIGVudHJ5cG9pbnQvdGVzdE5vZGUudHMKdmFyIGltcG9ydF9wcm9taXNlcyA9IF9fdG9FU00ocmVxdWlyZSgiZnMvcHJvbWlzZXMiKSk7CnZhciBpbXBvcnRfcGF0aCA9IF9fdG9FU00ocmVxdWlyZSgicGF0aCIpKTsKCi8vIG5vZGVfbW9kdWxlcy9AYmpvcm4zL2Jyb3dzZXJfd2FzaV9zaGltL2Rpc3Qvd2FzaV9kZWZzLmpzCnZhciBDTE9DS0lEX1JFQUxUSU1FID0gMDsKdmFyIENMT0NLSURfTU9OT1RPTklDID0gMTsKdmFyIEVSUk5PX1NVQ0NFU1MgPSAwOwp2YXIgRVJSTk9fQkFERiA9IDg7CnZhciBFUlJOT19FWElTVCA9IDIwOwp2YXIgRVJSTk9fSU5WQUwgPSAyODsKdmFyIEVSUk5PX0lTRElSID0gMzE7CnZhciBFUlJOT19OQU1FVE9PTE9ORyA9IDM3Owp2YXIgRVJSTk9fTk9FTlQgPSA0NDsKdmFyIEVSUk5PX05PU1lTID0gNTI7CnZhciBFUlJOT19OT1RESVIgPSA1NDsKdmFyIEVSUk5PX05PVEVNUFRZID0gNTU7CnZhciBFUlJOT19OT1RTVVAgPSA1ODsKdmFyIEVSUk5PX1BFUk0gPSA2MzsKdmFyIEVSUk5PX05PVENBUEFCTEUgPSA3NjsKdmFyIFJJR0hUU19GRF9EQVRBU1lOQyA9IDEgPDwgMDsKdmFyIFJJR0hUU19GRF9SRUFEID0gMSA8PCAxOwp2YXIgUklHSFRTX0ZEX1NFRUsgPSAxIDw8IDI7CnZhciBSSUdIVFNfRkRfRkRTVEFUX1NFVF9GTEFHUyA9IDEgPDwgMzsKdmFyIFJJR0hUU19GRF9TWU5DID0gMSA8PCA0Owp2YXIgUklHSFRTX0ZEX1RFTEwgPSAxIDw8IDU7CnZhciBSSUdIVFNfRkRfV1JJVEUgPSAxIDw8IDY7CnZhciBSSUdIVFNfRkRfQURWSVNFID0gMSA8PCA3Owp2YXIgUklHSFRTX0ZEX0FMTE9DQVRFID0gMSA8PCA4Owp2YXIgUklHSFRTX1BBVEhfQ1JFQVRFX0RJUkVDVE9SWSA9IDEgPDwgOTsKdmFyIFJJR0hUU19QQVRIX0NSRUFURV9GSUxFID0gMSA8PCAxMDsKdmFyIFJJR0hUU19QQVRIX0xJTktfU09VUkNFID0gMSA8PCAxMTsKdmFyIFJJR0hUU19QQVRIX0xJTktfVEFSR0VUID0gMSA8PCAxMjsKdmFyIFJJR0hUU19QQVRIX09QRU4gPSAxIDw8IDEzOwp2YXIgUklHSFRTX0ZEX1JFQURESVIgPSAxIDw8IDE0Owp2YXIgUklHSFRTX1BBVEhfUkVBRExJTksgPSAxIDw8IDE1Owp2YXIgUklHSFRTX1BBVEhfUkVOQU1FX1NPVVJDRSA9IDEgPDwgMTY7CnZhciBSSUdIVFNfUEFUSF9SRU5BTUVfVEFSR0VUID0gMSA8PCAxNzsKdmFyIFJJR0hUU19QQVRIX0ZJTEVTVEFUX0dFVCA9IDEgPDwgMTg7CnZhciBSSUdIVFNfUEFUSF9GSUxFU1RBVF9TRVRfU0laRSA9IDEgPDwgMTk7CnZhciBSSUdIVFNfUEFUSF9GSUxFU1RBVF9TRVRfVElNRVMgPSAxIDw8IDIwOwp2YXIgUklHSFRTX0ZEX0ZJTEVTVEFUX0dFVCA9IDEgPDwgMjE7CnZhciBSSUdIVFNfRkRfRklMRVNUQVRfU0VUX1NJWkUgPSAxIDw8IDIyOwp2YXIgUklHSFRTX0ZEX0ZJTEVTVEFUX1NFVF9USU1FUyA9IDEgPDwgMjM7CnZhciBSSUdIVFNfUEFUSF9TWU1MSU5LID0gMSA8PCAyNDsKdmFyIFJJR0hUU19QQVRIX1JFTU9WRV9ESVJFQ1RPUlkgPSAxIDw8IDI1Owp2YXIgUklHSFRTX1BBVEhfVU5MSU5LX0ZJTEUgPSAxIDw8IDI2Owp2YXIgUklHSFRTX1BPTExfRkRfUkVBRFdSSVRFID0gMSA8PCAyNzsKdmFyIFJJR0hUU19TT0NLX1NIVVRET1dOID0gMSA8PCAyODsKdmFyIElvdmVjID0gY2xhc3MgewogIHN0YXRpYyByZWFkX2J5dGVzKHZpZXcsIHB0cikgewogICAgY29uc3QgaW92ZWMgPSBuZXcgSW92ZWMoKTsKICAgIGlvdmVjLmJ1ZiA9IHZpZXcuZ2V0VWludDMyKHB0ciwgdHJ1ZSk7CiAgICBpb3ZlYy5idWZfbGVuID0gdmlldy5nZXRVaW50MzIocHRyICsgNCwgdHJ1ZSk7CiAgICByZXR1cm4gaW92ZWM7CiAgfQogIHN0YXRpYyByZWFkX2J5dGVzX2FycmF5KHZpZXcsIHB0ciwgbGVuKSB7CiAgICBjb25zdCBpb3ZlY3MgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHsKICAgICAgaW92ZWNzLnB1c2goSW92ZWMucmVhZF9ieXRlcyh2aWV3LCBwdHIgKyA4ICogaSkpOwogICAgfQogICAgcmV0dXJuIGlvdmVjczsKICB9Cn07CnZhciBDaW92ZWMgPSBjbGFzcyB7CiAgc3RhdGljIHJlYWRfYnl0ZXModmlldywgcHRyKSB7CiAgICBjb25zdCBpb3ZlYyA9IG5ldyBDaW92ZWMoKTsKICAgIGlvdmVjLmJ1ZiA9IHZpZXcuZ2V0VWludDMyKHB0ciwgdHJ1ZSk7CiAgICBpb3ZlYy5idWZfbGVuID0gdmlldy5nZXRVaW50MzIocHRyICsgNCwgdHJ1ZSk7CiAgICByZXR1cm4gaW92ZWM7CiAgfQogIHN0YXRpYyByZWFkX2J5dGVzX2FycmF5KHZpZXcsIHB0ciwgbGVuKSB7CiAgICBjb25zdCBpb3ZlY3MgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHsKICAgICAgaW92ZWNzLnB1c2goQ2lvdmVjLnJlYWRfYnl0ZXModmlldywgcHRyICsgOCAqIGkpKTsKICAgIH0KICAgIHJldHVybiBpb3ZlY3M7CiAgfQp9Owp2YXIgV0hFTkNFX1NFVCA9IDA7CnZhciBXSEVOQ0VfQ1VSID0gMTsKdmFyIFdIRU5DRV9FTkQgPSAyOwp2YXIgRklMRVRZUEVfQ0hBUkFDVEVSX0RFVklDRSA9IDI7CnZhciBGSUxFVFlQRV9ESVJFQ1RPUlkgPSAzOwp2YXIgRklMRVRZUEVfUkVHVUxBUl9GSUxFID0gNDsKdmFyIERpcmVudCA9IGNsYXNzIHsKICBoZWFkX2xlbmd0aCgpIHsKICAgIHJldHVybiAyNDsKICB9CiAgbmFtZV9sZW5ndGgoKSB7CiAgICByZXR1cm4gdGhpcy5kaXJfbmFtZS5ieXRlTGVuZ3RoOwogIH0KICB3cml0ZV9oZWFkX2J5dGVzKHZpZXcsIHB0cikgewogICAgdmlldy5zZXRCaWdVaW50NjQocHRyLCB0aGlzLmRfbmV4dCwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA4LCB0aGlzLmRfaW5vLCB0cnVlKTsKICAgIHZpZXcuc2V0VWludDMyKHB0ciArIDE2LCB0aGlzLmRpcl9uYW1lLmxlbmd0aCwgdHJ1ZSk7CiAgICB2aWV3LnNldFVpbnQ4KHB0ciArIDIwLCB0aGlzLmRfdHlwZSk7CiAgfQogIHdyaXRlX25hbWVfYnl0ZXModmlldzgsIHB0ciwgYnVmX2xlbikgewogICAgdmlldzguc2V0KHRoaXMuZGlyX25hbWUuc2xpY2UoMCwgTWF0aC5taW4odGhpcy5kaXJfbmFtZS5ieXRlTGVuZ3RoLCBidWZfbGVuKSksIHB0cik7CiAgfQogIGNvbnN0cnVjdG9yKG5leHRfY29va2llLCBuYW1lLCB0eXBlKSB7CiAgICB0aGlzLmRfaW5vID0gMG47CiAgICBjb25zdCBlbmNvZGVkX25hbWUgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUobmFtZSk7CiAgICB0aGlzLmRfbmV4dCA9IG5leHRfY29va2llOwogICAgdGhpcy5kX25hbWxlbiA9IGVuY29kZWRfbmFtZS5ieXRlTGVuZ3RoOwogICAgdGhpcy5kX3R5cGUgPSB0eXBlOwogICAgdGhpcy5kaXJfbmFtZSA9IGVuY29kZWRfbmFtZTsKICB9Cn07CnZhciBGREZMQUdTX0FQUEVORCA9IDEgPDwgMDsKdmFyIEZERkxBR1NfRFNZTkMgPSAxIDw8IDE7CnZhciBGREZMQUdTX05PTkJMT0NLID0gMSA8PCAyOwp2YXIgRkRGTEFHU19SU1lOQyA9IDEgPDwgMzsKdmFyIEZERkxBR1NfU1lOQyA9IDEgPDwgNDsKdmFyIEZkc3RhdCA9IGNsYXNzIHsKICB3cml0ZV9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIHZpZXcuc2V0VWludDgocHRyLCB0aGlzLmZzX2ZpbGV0eXBlKTsKICAgIHZpZXcuc2V0VWludDE2KHB0ciArIDIsIHRoaXMuZnNfZmxhZ3MsIHRydWUpOwogICAgdmlldy5zZXRCaWdVaW50NjQocHRyICsgOCwgdGhpcy5mc19yaWdodHNfYmFzZSwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyAxNiwgdGhpcy5mc19yaWdodHNfaW5oZXJpdGVkLCB0cnVlKTsKICB9CiAgY29uc3RydWN0b3IoZmlsZXR5cGUsIGZsYWdzKSB7CiAgICB0aGlzLmZzX3JpZ2h0c19iYXNlID0gMG47CiAgICB0aGlzLmZzX3JpZ2h0c19pbmhlcml0ZWQgPSAwbjsKICAgIHRoaXMuZnNfZmlsZXR5cGUgPSBmaWxldHlwZTsKICAgIHRoaXMuZnNfZmxhZ3MgPSBmbGFnczsKICB9Cn07CnZhciBGU1RGTEFHU19BVElNID0gMSA8PCAwOwp2YXIgRlNURkxBR1NfQVRJTV9OT1cgPSAxIDw8IDE7CnZhciBGU1RGTEFHU19NVElNID0gMSA8PCAyOwp2YXIgRlNURkxBR1NfTVRJTV9OT1cgPSAxIDw8IDM7CnZhciBPRkxBR1NfQ1JFQVQgPSAxIDw8IDA7CnZhciBPRkxBR1NfRElSRUNUT1JZID0gMSA8PCAxOwp2YXIgT0ZMQUdTX0VYQ0wgPSAxIDw8IDI7CnZhciBPRkxBR1NfVFJVTkMgPSAxIDw8IDM7CnZhciBGaWxlc3RhdCA9IGNsYXNzIHsKICB3cml0ZV9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciwgdGhpcy5kZXYsIHRydWUpOwogICAgdmlldy5zZXRCaWdVaW50NjQocHRyICsgOCwgdGhpcy5pbm8sIHRydWUpOwogICAgdmlldy5zZXRVaW50OChwdHIgKyAxNiwgdGhpcy5maWxldHlwZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyAyNCwgdGhpcy5ubGluaywgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyAzMiwgdGhpcy5zaXplLCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDM4LCB0aGlzLmF0aW0sIHRydWUpOwogICAgdmlldy5zZXRCaWdVaW50NjQocHRyICsgNDYsIHRoaXMubXRpbSwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA1MiwgdGhpcy5jdGltLCB0cnVlKTsKICB9CiAgY29uc3RydWN0b3IoZmlsZXR5cGUsIHNpemUpIHsKICAgIHRoaXMuZGV2ID0gMG47CiAgICB0aGlzLmlubyA9IDBuOwogICAgdGhpcy5ubGluayA9IDBuOwogICAgdGhpcy5hdGltID0gMG47CiAgICB0aGlzLm10aW0gPSAwbjsKICAgIHRoaXMuY3RpbSA9IDBuOwogICAgdGhpcy5maWxldHlwZSA9IGZpbGV0eXBlOwogICAgdGhpcy5zaXplID0gc2l6ZTsKICB9Cn07CnZhciBFVkVOVFJXRkxBR1NfRkRfUkVBRFdSSVRFX0hBTkdVUCA9IDEgPDwgMDsKdmFyIFNVQkNMT0NLRkxBR1NfU1VCU0NSSVBUSU9OX0NMT0NLX0FCU1RJTUUgPSAxIDw8IDA7CnZhciBSSUZMQUdTX1JFQ1ZfUEVFSyA9IDEgPDwgMDsKdmFyIFJJRkxBR1NfUkVDVl9XQUlUQUxMID0gMSA8PCAxOwp2YXIgUk9GTEFHU19SRUNWX0RBVEFfVFJVTkNBVEVEID0gMSA8PCAwOwp2YXIgU0RGTEFHU19SRCA9IDEgPDwgMDsKdmFyIFNERkxBR1NfV1IgPSAxIDw8IDE7CnZhciBQUkVPUEVOVFlQRV9ESVIgPSAwOwp2YXIgUHJlc3RhdERpciA9IGNsYXNzIHsKICB3cml0ZV9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIHZpZXcuc2V0VWludDMyKHB0ciwgdGhpcy5wcl9uYW1lLmJ5dGVMZW5ndGgsIHRydWUpOwogIH0KICBjb25zdHJ1Y3RvcihuYW1lKSB7CiAgICB0aGlzLnByX25hbWUgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUobmFtZSk7CiAgfQp9Owp2YXIgUHJlc3RhdCA9IGNsYXNzIHsKICBzdGF0aWMgZGlyKG5hbWUpIHsKICAgIGNvbnN0IHByZXN0YXQgPSBuZXcgUHJlc3RhdCgpOwogICAgcHJlc3RhdC50YWcgPSBQUkVPUEVOVFlQRV9ESVI7CiAgICBwcmVzdGF0LmlubmVyID0gbmV3IFByZXN0YXREaXIobmFtZSk7CiAgICByZXR1cm4gcHJlc3RhdDsKICB9CiAgd3JpdGVfYnl0ZXModmlldywgcHRyKSB7CiAgICB2aWV3LnNldFVpbnQzMihwdHIsIHRoaXMudGFnLCB0cnVlKTsKICAgIHRoaXMuaW5uZXIud3JpdGVfYnl0ZXModmlldywgcHRyICsgNCk7CiAgfQp9OwoKLy8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC9kZWJ1Zy5qcwp2YXIgRGVidWcgPSBjbGFzcyBEZWJ1ZzIgewogIGVuYWJsZShlbmFibGVkKSB7CiAgICB0aGlzLmxvZyA9IGNyZWF0ZUxvZ2dlcihlbmFibGVkID09PSB2b2lkIDAgPyB0cnVlIDogZW5hYmxlZCwgdGhpcy5wcmVmaXgpOwogIH0KICBnZXQgZW5hYmxlZCgpIHsKICAgIHJldHVybiB0aGlzLmlzRW5hYmxlZDsKICB9CiAgY29uc3RydWN0b3IoaXNFbmFibGVkKSB7CiAgICB0aGlzLmlzRW5hYmxlZCA9IGlzRW5hYmxlZDsKICAgIHRoaXMucHJlZml4ID0gIndhc2k6IjsKICAgIHRoaXMuZW5hYmxlKGlzRW5hYmxlZCk7CiAgfQp9OwpmdW5jdGlvbiBjcmVhdGVMb2dnZXIoZW5hYmxlZCwgcHJlZml4KSB7CiAgaWYgKGVuYWJsZWQpIHsKICAgIGNvbnN0IGEgPSBjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUsICIlYyVzIiwgImNvbG9yOiAjMjY1QkEwIiwgcHJlZml4KTsKICAgIHJldHVybiBhOwogIH0gZWxzZSB7CiAgICByZXR1cm4gKCkgPT4gewogICAgfTsKICB9Cn0KdmFyIGRlYnVnID0gbmV3IERlYnVnKGZhbHNlKTsKCi8vIG5vZGVfbW9kdWxlcy9AYmpvcm4zL2Jyb3dzZXJfd2FzaV9zaGltL2Rpc3Qvd2FzaS5qcwp2YXIgV0FTSVByb2NFeGl0ID0gY2xhc3MgZXh0ZW5kcyBFcnJvciB7CiAgY29uc3RydWN0b3IoY29kZSkgewogICAgc3VwZXIoImV4aXQgd2l0aCBleGl0IGNvZGUgIiArIGNvZGUpOwogICAgdGhpcy5jb2RlID0gY29kZTsKICB9Cn07CnZhciBXQVNJID0gY2xhc3MgV0FTSTIgewogIHN0YXJ0KGluc3RhbmNlKSB7CiAgICB0aGlzLmluc3QgPSBpbnN0YW5jZTsKICAgIHRyeSB7CiAgICAgIGluc3RhbmNlLmV4cG9ydHMuX3N0YXJ0KCk7CiAgICAgIHJldHVybiAwOwogICAgfSBjYXRjaCAoZSkgewogICAgICBpZiAoZSBpbnN0YW5jZW9mIFdBU0lQcm9jRXhpdCkgewogICAgICAgIHJldHVybiBlLmNvZGU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgZTsKICAgICAgfQogICAgfQogIH0KICBpbml0aWFsaXplKGluc3RhbmNlKSB7CiAgICB0aGlzLmluc3QgPSBpbnN0YW5jZTsKICAgIGlmIChpbnN0YW5jZS5leHBvcnRzLl9pbml0aWFsaXplKSB7CiAgICAgIGluc3RhbmNlLmV4cG9ydHMuX2luaXRpYWxpemUoKTsKICAgIH0KICB9CiAgY29uc3RydWN0b3IoYXJnczIsIGVudiwgZmRzLCBvcHRpb25zID0ge30pIHsKICAgIHRoaXMuYXJncyA9IFtdOwogICAgdGhpcy5lbnYgPSBbXTsKICAgIHRoaXMuZmRzID0gW107CiAgICBkZWJ1Zy5lbmFibGUob3B0aW9ucy5kZWJ1Zyk7CiAgICB0aGlzLmFyZ3MgPSBhcmdzMjsKICAgIHRoaXMuZW52ID0gZW52OwogICAgdGhpcy5mZHMgPSBmZHM7CiAgICBjb25zdCBzZWxmID0gdGhpczsKICAgIHRoaXMud2FzaUltcG9ydCA9IHsgYXJnc19zaXplc19nZXQoYXJnYywgYXJndl9idWZfc2l6ZSkgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYXJnYywgc2VsZi5hcmdzLmxlbmd0aCwgdHJ1ZSk7CiAgICAgIGxldCBidWZfc2l6ZSA9IDA7CiAgICAgIGZvciAoY29uc3QgYXJnIG9mIHNlbGYuYXJncykgewogICAgICAgIGJ1Zl9zaXplICs9IGFyZy5sZW5ndGggKyAxOwogICAgICB9CiAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYXJndl9idWZfc2l6ZSwgYnVmX3NpemUsIHRydWUpOwogICAgICBkZWJ1Zy5sb2coYnVmZmVyLmdldFVpbnQzMihhcmdjLCB0cnVlKSwgYnVmZmVyLmdldFVpbnQzMihhcmd2X2J1Zl9zaXplLCB0cnVlKSk7CiAgICAgIHJldHVybiAwOwogICAgfSwgYXJnc19nZXQoYXJndiwgYXJndl9idWYpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IG9yaWdfYXJndl9idWYgPSBhcmd2X2J1ZjsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxmLmFyZ3MubGVuZ3RoOyBpKyspIHsKICAgICAgICBidWZmZXIuc2V0VWludDMyKGFyZ3YsIGFyZ3ZfYnVmLCB0cnVlKTsKICAgICAgICBhcmd2ICs9IDQ7CiAgICAgICAgY29uc3QgYXJnID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHNlbGYuYXJnc1tpXSk7CiAgICAgICAgYnVmZmVyOC5zZXQoYXJnLCBhcmd2X2J1Zik7CiAgICAgICAgYnVmZmVyLnNldFVpbnQ4KGFyZ3ZfYnVmICsgYXJnLmxlbmd0aCwgMCk7CiAgICAgICAgYXJndl9idWYgKz0gYXJnLmxlbmd0aCArIDE7CiAgICAgIH0KICAgICAgaWYgKGRlYnVnLmVuYWJsZWQpIHsKICAgICAgICBkZWJ1Zy5sb2cobmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG9yaWdfYXJndl9idWYsIGFyZ3ZfYnVmKSkpOwogICAgICB9CiAgICAgIHJldHVybiAwOwogICAgfSwgZW52aXJvbl9zaXplc19nZXQoZW52aXJvbl9jb3VudCwgZW52aXJvbl9zaXplKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgYnVmZmVyLnNldFVpbnQzMihlbnZpcm9uX2NvdW50LCBzZWxmLmVudi5sZW5ndGgsIHRydWUpOwogICAgICBsZXQgYnVmX3NpemUgPSAwOwogICAgICBmb3IgKGNvbnN0IGVudmlyb24gb2Ygc2VsZi5lbnYpIHsKICAgICAgICBidWZfc2l6ZSArPSBlbnZpcm9uLmxlbmd0aCArIDE7CiAgICAgIH0KICAgICAgYnVmZmVyLnNldFVpbnQzMihlbnZpcm9uX3NpemUsIGJ1Zl9zaXplLCB0cnVlKTsKICAgICAgZGVidWcubG9nKGJ1ZmZlci5nZXRVaW50MzIoZW52aXJvbl9jb3VudCwgdHJ1ZSksIGJ1ZmZlci5nZXRVaW50MzIoZW52aXJvbl9zaXplLCB0cnVlKSk7CiAgICAgIHJldHVybiAwOwogICAgfSwgZW52aXJvbl9nZXQoZW52aXJvbiwgZW52aXJvbl9idWYpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IG9yaWdfZW52aXJvbl9idWYgPSBlbnZpcm9uX2J1ZjsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxmLmVudi5sZW5ndGg7IGkrKykgewogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIoZW52aXJvbiwgZW52aXJvbl9idWYsIHRydWUpOwogICAgICAgIGVudmlyb24gKz0gNDsKICAgICAgICBjb25zdCBlID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHNlbGYuZW52W2ldKTsKICAgICAgICBidWZmZXI4LnNldChlLCBlbnZpcm9uX2J1Zik7CiAgICAgICAgYnVmZmVyLnNldFVpbnQ4KGVudmlyb25fYnVmICsgZS5sZW5ndGgsIDApOwogICAgICAgIGVudmlyb25fYnVmICs9IGUubGVuZ3RoICsgMTsKICAgICAgfQogICAgICBpZiAoZGVidWcuZW5hYmxlZCkgewogICAgICAgIGRlYnVnLmxvZyhuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2Uob3JpZ19lbnZpcm9uX2J1ZiwgZW52aXJvbl9idWYpKSk7CiAgICAgIH0KICAgICAgcmV0dXJuIDA7CiAgICB9LCBjbG9ja19yZXNfZ2V0KGlkLCByZXNfcHRyKSB7CiAgICAgIGxldCByZXNvbHV0aW9uVmFsdWU7CiAgICAgIHN3aXRjaCAoaWQpIHsKICAgICAgICBjYXNlIENMT0NLSURfTU9OT1RPTklDOiB7CiAgICAgICAgICByZXNvbHV0aW9uVmFsdWUgPSA1MDAwbjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjYXNlIENMT0NLSURfUkVBTFRJTUU6IHsKICAgICAgICAgIHJlc29sdXRpb25WYWx1ZSA9IDEwMDAwMDBuOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICByZXR1cm4gRVJSTk9fTk9TWVM7CiAgICAgIH0KICAgICAgY29uc3QgdmlldyA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgdmlldy5zZXRCaWdVaW50NjQocmVzX3B0ciwgcmVzb2x1dGlvblZhbHVlLCB0cnVlKTsKICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICB9LCBjbG9ja190aW1lX2dldChpZCwgcHJlY2lzaW9uLCB0aW1lKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKGlkID09PSBDTE9DS0lEX1JFQUxUSU1FKSB7CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NCh0aW1lLCBCaWdJbnQobmV3IERhdGUoKS5nZXRUaW1lKCkpICogMTAwMDAwMG4sIHRydWUpOwogICAgICB9IGVsc2UgaWYgKGlkID09IENMT0NLSURfTU9OT1RPTklDKSB7CiAgICAgICAgbGV0IG1vbm90b25pY190aW1lOwogICAgICAgIHRyeSB7CiAgICAgICAgICBtb25vdG9uaWNfdGltZSA9IEJpZ0ludChNYXRoLnJvdW5kKHBlcmZvcm1hbmNlLm5vdygpICogMWU2KSk7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgbW9ub3RvbmljX3RpbWUgPSAwbjsKICAgICAgICB9CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NCh0aW1lLCBtb25vdG9uaWNfdGltZSwgdHJ1ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NCh0aW1lLCAwbiwgdHJ1ZSk7CiAgICAgIH0KICAgICAgcmV0dXJuIDA7CiAgICB9LCBmZF9hZHZpc2UoZmQsIG9mZnNldCwgbGVuLCBhZHZpY2UpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfYWxsb2NhdGUoZmQsIG9mZnNldCwgbGVuKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9hbGxvY2F0ZShvZmZzZXQsIGxlbik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Nsb3NlKGZkKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcmV0ID0gc2VsZi5mZHNbZmRdLmZkX2Nsb3NlKCk7CiAgICAgICAgc2VsZi5mZHNbZmRdID0gdm9pZCAwOwogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2RhdGFzeW5jKGZkKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9zeW5jKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Zkc3RhdF9nZXQoZmQsIGZkc3RhdF9wdHIpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgZmRzdGF0IH0gPSBzZWxmLmZkc1tmZF0uZmRfZmRzdGF0X2dldCgpOwogICAgICAgIGlmIChmZHN0YXQgIT0gbnVsbCkgewogICAgICAgICAgZmRzdGF0LndyaXRlX2J5dGVzKG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKSwgZmRzdGF0X3B0cik7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Zkc3RhdF9zZXRfZmxhZ3MoZmQsIGZsYWdzKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9mZHN0YXRfc2V0X2ZsYWdzKGZsYWdzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfZmRzdGF0X3NldF9yaWdodHMoZmQsIGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZykgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfZmRzdGF0X3NldF9yaWdodHMoZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfZmlsZXN0YXRfZ2V0KGZkLCBmaWxlc3RhdF9wdHIpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgZmlsZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9maWxlc3RhdF9nZXQoKTsKICAgICAgICBpZiAoZmlsZXN0YXQgIT0gbnVsbCkgewogICAgICAgICAgZmlsZXN0YXQud3JpdGVfYnl0ZXMobmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpLCBmaWxlc3RhdF9wdHIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9maWxlc3RhdF9zZXRfc2l6ZShmZCwgc2l6ZSkgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfZmlsZXN0YXRfc2V0X3NpemUoc2l6ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2ZpbGVzdGF0X3NldF90aW1lcyhmZCwgYXRpbSwgbXRpbSwgZnN0X2ZsYWdzKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9maWxlc3RhdF9zZXRfdGltZXMoYXRpbSwgbXRpbSwgZnN0X2ZsYWdzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcHJlYWQoZmQsIGlvdnNfcHRyLCBpb3ZzX2xlbiwgb2Zmc2V0LCBucmVhZF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgaW92ZWNzID0gSW92ZWMucmVhZF9ieXRlc19hcnJheShidWZmZXIsIGlvdnNfcHRyLCBpb3ZzX2xlbik7CiAgICAgICAgbGV0IG5yZWFkID0gMDsKICAgICAgICBmb3IgKGNvbnN0IGlvdmVjIG9mIGlvdmVjcykgewogICAgICAgICAgY29uc3QgeyByZXQsIGRhdGEgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wcmVhZChpb3ZlYy5idWZfbGVuLCBvZmZzZXQpOwogICAgICAgICAgaWYgKHJldCAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobnJlYWRfcHRyLCBucmVhZCwgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgICB9CiAgICAgICAgICBidWZmZXI4LnNldChkYXRhLCBpb3ZlYy5idWYpOwogICAgICAgICAgbnJlYWQgKz0gZGF0YS5sZW5ndGg7CiAgICAgICAgICBvZmZzZXQgKz0gQmlnSW50KGRhdGEubGVuZ3RoKTsKICAgICAgICAgIGlmIChkYXRhLmxlbmd0aCAhPSBpb3ZlYy5idWZfbGVuKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgbnJlYWQsIHRydWUpOwogICAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9wcmVzdGF0X2dldChmZCwgYnVmX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIHByZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wcmVzdGF0X2dldCgpOwogICAgICAgIGlmIChwcmVzdGF0ICE9IG51bGwpIHsKICAgICAgICAgIHByZXN0YXQud3JpdGVfYnl0ZXMoYnVmZmVyLCBidWZfcHRyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcHJlc3RhdF9kaXJfbmFtZShmZCwgcGF0aF9wdHIsIHBhdGhfbGVuKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIHByZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wcmVzdGF0X2dldCgpOwogICAgICAgIGlmIChwcmVzdGF0ID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHByZXN0YXRfZGlyX25hbWUgPSBwcmVzdGF0LmlubmVyLnByX25hbWU7CiAgICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICAgIGJ1ZmZlcjguc2V0KHByZXN0YXRfZGlyX25hbWUuc2xpY2UoMCwgcGF0aF9sZW4pLCBwYXRoX3B0cik7CiAgICAgICAgcmV0dXJuIHByZXN0YXRfZGlyX25hbWUuYnl0ZUxlbmd0aCA+IHBhdGhfbGVuID8gRVJSTk9fTkFNRVRPT0xPTkcgOiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9wd3JpdGUoZmQsIGlvdnNfcHRyLCBpb3ZzX2xlbiwgb2Zmc2V0LCBud3JpdHRlbl9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgaW92ZWNzID0gQ2lvdmVjLnJlYWRfYnl0ZXNfYXJyYXkoYnVmZmVyLCBpb3ZzX3B0ciwgaW92c19sZW4pOwogICAgICAgIGxldCBud3JpdHRlbiA9IDA7CiAgICAgICAgZm9yIChjb25zdCBpb3ZlYyBvZiBpb3ZlY3MpIHsKICAgICAgICAgIGNvbnN0IGRhdGEgPSBidWZmZXI4LnNsaWNlKGlvdmVjLmJ1ZiwgaW92ZWMuYnVmICsgaW92ZWMuYnVmX2xlbik7CiAgICAgICAgICBjb25zdCB7IHJldCwgbndyaXR0ZW46IG53cml0dGVuX3BhcnQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG53cml0dGVuX3B0ciwgbndyaXR0ZW4sIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgbndyaXR0ZW4gKz0gbndyaXR0ZW5fcGFydDsKICAgICAgICAgIG9mZnNldCArPSBCaWdJbnQobndyaXR0ZW5fcGFydCk7CiAgICAgICAgICBpZiAobndyaXR0ZW5fcGFydCAhPSBkYXRhLmJ5dGVMZW5ndGgpIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobndyaXR0ZW5fcHRyLCBud3JpdHRlbiwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3JlYWQoZmQsIGlvdnNfcHRyLCBpb3ZzX2xlbiwgbnJlYWRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IGlvdmVjcyA9IElvdmVjLnJlYWRfYnl0ZXNfYXJyYXkoYnVmZmVyLCBpb3ZzX3B0ciwgaW92c19sZW4pOwogICAgICAgIGxldCBucmVhZCA9IDA7CiAgICAgICAgZm9yIChjb25zdCBpb3ZlYyBvZiBpb3ZlY3MpIHsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBkYXRhIH0gPSBzZWxmLmZkc1tmZF0uZmRfcmVhZChpb3ZlYy5idWZfbGVuKTsKICAgICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgbnJlYWQsIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgYnVmZmVyOC5zZXQoZGF0YSwgaW92ZWMuYnVmKTsKICAgICAgICAgIG5yZWFkICs9IGRhdGEubGVuZ3RoOwogICAgICAgICAgaWYgKGRhdGEubGVuZ3RoICE9IGlvdmVjLmJ1Zl9sZW4pIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobnJlYWRfcHRyLCBucmVhZCwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3JlYWRkaXIoZmQsIGJ1ZiwgYnVmX2xlbiwgY29va2llLCBidWZ1c2VkX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBsZXQgYnVmdXNlZCA9IDA7CiAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBkaXJlbnQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9yZWFkZGlyX3NpbmdsZShjb29raWUpOwogICAgICAgICAgaWYgKHJldCAhPSAwKSB7CiAgICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYnVmdXNlZF9wdHIsIGJ1ZnVzZWQsIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgaWYgKGRpcmVudCA9PSBudWxsKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGJ1Zl9sZW4gLSBidWZ1c2VkIDwgZGlyZW50LmhlYWRfbGVuZ3RoKCkpIHsKICAgICAgICAgICAgYnVmdXNlZCA9IGJ1Zl9sZW47CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgaGVhZF9ieXRlcyA9IG5ldyBBcnJheUJ1ZmZlcihkaXJlbnQuaGVhZF9sZW5ndGgoKSk7CiAgICAgICAgICBkaXJlbnQud3JpdGVfaGVhZF9ieXRlcyhuZXcgRGF0YVZpZXcoaGVhZF9ieXRlcyksIDApOwogICAgICAgICAgYnVmZmVyOC5zZXQobmV3IFVpbnQ4QXJyYXkoaGVhZF9ieXRlcykuc2xpY2UoMCwgTWF0aC5taW4oaGVhZF9ieXRlcy5ieXRlTGVuZ3RoLCBidWZfbGVuIC0gYnVmdXNlZCkpLCBidWYpOwogICAgICAgICAgYnVmICs9IGRpcmVudC5oZWFkX2xlbmd0aCgpOwogICAgICAgICAgYnVmdXNlZCArPSBkaXJlbnQuaGVhZF9sZW5ndGgoKTsKICAgICAgICAgIGlmIChidWZfbGVuIC0gYnVmdXNlZCA8IGRpcmVudC5uYW1lX2xlbmd0aCgpKSB7CiAgICAgICAgICAgIGJ1ZnVzZWQgPSBidWZfbGVuOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGRpcmVudC53cml0ZV9uYW1lX2J5dGVzKGJ1ZmZlcjgsIGJ1ZiwgYnVmX2xlbiAtIGJ1ZnVzZWQpOwogICAgICAgICAgYnVmICs9IGRpcmVudC5uYW1lX2xlbmd0aCgpOwogICAgICAgICAgYnVmdXNlZCArPSBkaXJlbnQubmFtZV9sZW5ndGgoKTsKICAgICAgICAgIGNvb2tpZSA9IGRpcmVudC5kX25leHQ7CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYnVmdXNlZF9wdHIsIGJ1ZnVzZWQsIHRydWUpOwogICAgICAgIHJldHVybiAwOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9yZW51bWJlcihmZCwgdG8pIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDAgJiYgc2VsZi5mZHNbdG9dICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHJldCA9IHNlbGYuZmRzW3RvXS5mZF9jbG9zZSgpOwogICAgICAgIGlmIChyZXQgIT0gMCkgewogICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICB9CiAgICAgICAgc2VsZi5mZHNbdG9dID0gc2VsZi5mZHNbZmRdOwogICAgICAgIHNlbGYuZmRzW2ZkXSA9IHZvaWQgMDsKICAgICAgICByZXR1cm4gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfc2VlayhmZCwgb2Zmc2V0LCB3aGVuY2UsIG9mZnNldF9vdXRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgb2Zmc2V0OiBvZmZzZXRfb3V0IH0gPSBzZWxmLmZkc1tmZF0uZmRfc2VlayhvZmZzZXQsIHdoZW5jZSk7CiAgICAgICAgYnVmZmVyLnNldEJpZ0ludDY0KG9mZnNldF9vdXRfcHRyLCBvZmZzZXRfb3V0LCB0cnVlKTsKICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9zeW5jKGZkKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9zeW5jKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3RlbGwoZmQsIG9mZnNldF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHsgcmV0LCBvZmZzZXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF90ZWxsKCk7CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NChvZmZzZXRfcHRyLCBvZmZzZXQsIHRydWUpOwogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3dyaXRlKGZkLCBpb3ZzX3B0ciwgaW92c19sZW4sIG53cml0dGVuX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBpb3ZlY3MgPSBDaW92ZWMucmVhZF9ieXRlc19hcnJheShidWZmZXIsIGlvdnNfcHRyLCBpb3ZzX2xlbik7CiAgICAgICAgbGV0IG53cml0dGVuID0gMDsKICAgICAgICBmb3IgKGNvbnN0IGlvdmVjIG9mIGlvdmVjcykgewogICAgICAgICAgY29uc3QgZGF0YSA9IGJ1ZmZlcjguc2xpY2UoaW92ZWMuYnVmLCBpb3ZlYy5idWYgKyBpb3ZlYy5idWZfbGVuKTsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBud3JpdHRlbjogbndyaXR0ZW5fcGFydCB9ID0gc2VsZi5mZHNbZmRdLmZkX3dyaXRlKGRhdGEpOwogICAgICAgICAgaWYgKHJldCAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobndyaXR0ZW5fcHRyLCBud3JpdHRlbiwgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgICB9CiAgICAgICAgICBud3JpdHRlbiArPSBud3JpdHRlbl9wYXJ0OwogICAgICAgICAgaWYgKG53cml0dGVuX3BhcnQgIT0gZGF0YS5ieXRlTGVuZ3RoKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKG53cml0dGVuX3B0ciwgbndyaXR0ZW4sIHRydWUpOwogICAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX2NyZWF0ZV9kaXJlY3RvcnkoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aDIgPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICByZXR1cm4gc2VsZi5mZHNbZmRdLnBhdGhfY3JlYXRlX2RpcmVjdG9yeShwYXRoMik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfZmlsZXN0YXRfZ2V0KGZkLCBmbGFncywgcGF0aF9wdHIsIHBhdGhfbGVuLCBmaWxlc3RhdF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aDIgPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICBjb25zdCB7IHJldCwgZmlsZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5wYXRoX2ZpbGVzdGF0X2dldChmbGFncywgcGF0aDIpOwogICAgICAgIGlmIChmaWxlc3RhdCAhPSBudWxsKSB7CiAgICAgICAgICBmaWxlc3RhdC53cml0ZV9ieXRlcyhidWZmZXIsIGZpbGVzdGF0X3B0cik7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfZmlsZXN0YXRfc2V0X3RpbWVzKGZkLCBmbGFncywgcGF0aF9wdHIsIHBhdGhfbGVuLCBhdGltLCBtdGltLCBmc3RfZmxhZ3MpIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGgyID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5wYXRoX2ZpbGVzdGF0X3NldF90aW1lcyhmbGFncywgcGF0aDIsIGF0aW0sIG10aW0sIGZzdF9mbGFncyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfbGluayhvbGRfZmQsIG9sZF9mbGFncywgb2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9sZW4sIG5ld19mZCwgbmV3X3BhdGhfcHRyLCBuZXdfcGF0aF9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbb2xkX2ZkXSAhPSB2b2lkIDAgJiYgc2VsZi5mZHNbbmV3X2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBvbGRfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX3B0ciArIG9sZF9wYXRoX2xlbikpOwogICAgICAgIGNvbnN0IG5ld19wYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfcHRyICsgbmV3X3BhdGhfbGVuKSk7CiAgICAgICAgY29uc3QgeyByZXQsIGlub2RlX29iaiB9ID0gc2VsZi5mZHNbb2xkX2ZkXS5wYXRoX2xvb2t1cChvbGRfcGF0aCwgb2xkX2ZsYWdzKTsKICAgICAgICBpZiAoaW5vZGVfb2JqID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzZWxmLmZkc1tuZXdfZmRdLnBhdGhfbGluayhuZXdfcGF0aCwgaW5vZGVfb2JqLCBmYWxzZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfb3BlbihmZCwgZGlyZmxhZ3MsIHBhdGhfcHRyLCBwYXRoX2xlbiwgb2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcsIGZkX2ZsYWdzLCBvcGVuZWRfZmRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGgyID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgZGVidWcubG9nKHBhdGgyKTsKICAgICAgICBjb25zdCB7IHJldCwgZmRfb2JqIH0gPSBzZWxmLmZkc1tmZF0ucGF0aF9vcGVuKGRpcmZsYWdzLCBwYXRoMiwgb2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcsIGZkX2ZsYWdzKTsKICAgICAgICBpZiAocmV0ICE9IDApIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIHNlbGYuZmRzLnB1c2goZmRfb2JqKTsKICAgICAgICBjb25zdCBvcGVuZWRfZmQgPSBzZWxmLmZkcy5sZW5ndGggLSAxOwogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIob3BlbmVkX2ZkX3B0ciwgb3BlbmVkX2ZkLCB0cnVlKTsKICAgICAgICByZXR1cm4gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9yZWFkbGluayhmZCwgcGF0aF9wdHIsIHBhdGhfbGVuLCBidWZfcHRyLCBidWZfbGVuLCBucmVhZF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aDIgPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICBkZWJ1Zy5sb2cocGF0aDIpOwogICAgICAgIGNvbnN0IHsgcmV0LCBkYXRhIH0gPSBzZWxmLmZkc1tmZF0ucGF0aF9yZWFkbGluayhwYXRoMik7CiAgICAgICAgaWYgKGRhdGEgIT0gbnVsbCkgewogICAgICAgICAgY29uc3QgZGF0YV9idWYgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoZGF0YSk7CiAgICAgICAgICBpZiAoZGF0YV9idWYubGVuZ3RoID4gYnVmX2xlbikgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgMCwgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICAgICAgfQogICAgICAgICAgYnVmZmVyOC5zZXQoZGF0YV9idWYsIGJ1Zl9wdHIpOwogICAgICAgICAgYnVmZmVyLnNldFVpbnQzMihucmVhZF9wdHIsIGRhdGFfYnVmLmxlbmd0aCwgdHJ1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfcmVtb3ZlX2RpcmVjdG9yeShmZCwgcGF0aF9wdHIsIHBhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBwYXRoMiA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0ucGF0aF9yZW1vdmVfZGlyZWN0b3J5KHBhdGgyKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9yZW5hbWUoZmQsIG9sZF9wYXRoX3B0ciwgb2xkX3BhdGhfbGVuLCBuZXdfZmQsIG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDAgJiYgc2VsZi5mZHNbbmV3X2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBvbGRfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX3B0ciArIG9sZF9wYXRoX2xlbikpOwogICAgICAgIGNvbnN0IG5ld19wYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfcHRyICsgbmV3X3BhdGhfbGVuKSk7CiAgICAgICAgbGV0IHsgcmV0LCBpbm9kZV9vYmogfSA9IHNlbGYuZmRzW2ZkXS5wYXRoX3VubGluayhvbGRfcGF0aCk7CiAgICAgICAgaWYgKGlub2RlX29iaiA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgIH0KICAgICAgICByZXQgPSBzZWxmLmZkc1tuZXdfZmRdLnBhdGhfbGluayhuZXdfcGF0aCwgaW5vZGVfb2JqLCB0cnVlKTsKICAgICAgICBpZiAocmV0ICE9IEVSUk5PX1NVQ0NFU1MpIHsKICAgICAgICAgIGlmIChzZWxmLmZkc1tmZF0ucGF0aF9saW5rKG9sZF9wYXRoLCBpbm9kZV9vYmosIHRydWUpICE9IEVSUk5PX1NVQ0NFU1MpIHsKICAgICAgICAgICAgdGhyb3cgInBhdGhfbGluayBzaG91bGQgYWx3YXlzIHJldHVybiBzdWNjZXNzIHdoZW4gcmVsaW5raW5nIGFuIGlub2RlIGJhY2sgdG8gdGhlIG9yaWdpbmFsIHBsYWNlIjsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9zeW1saW5rKG9sZF9wYXRoX3B0ciwgb2xkX3BhdGhfbGVuLCBmZCwgbmV3X3BhdGhfcHRyLCBuZXdfcGF0aF9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IG9sZF9wYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG9sZF9wYXRoX3B0ciwgb2xkX3BhdGhfcHRyICsgb2xkX3BhdGhfbGVuKSk7CiAgICAgICAgY29uc3QgbmV3X3BhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UobmV3X3BhdGhfcHRyLCBuZXdfcGF0aF9wdHIgKyBuZXdfcGF0aF9sZW4pKTsKICAgICAgICByZXR1cm4gRVJSTk9fTk9UU1VQOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX3VubGlua19maWxlKGZkLCBwYXRoX3B0ciwgcGF0aF9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGgyID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5wYXRoX3VubGlua19maWxlKHBhdGgyKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcG9sbF9vbmVvZmYoaW5fLCBvdXQsIG5zdWJzY3JpcHRpb25zKSB7CiAgICAgIHRocm93ICJhc3luYyBpbyBub3Qgc3VwcG9ydGVkIjsKICAgIH0sIHByb2NfZXhpdChleGl0X2NvZGUpIHsKICAgICAgdGhyb3cgbmV3IFdBU0lQcm9jRXhpdChleGl0X2NvZGUpOwogICAgfSwgcHJvY19yYWlzZShzaWcpIHsKICAgICAgdGhyb3cgInJhaXNlZCBzaWduYWwgIiArIHNpZzsKICAgIH0sIHNjaGVkX3lpZWxkKCkgewogICAgfSwgcmFuZG9tX2dldChidWYsIGJ1Zl9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJ1Zl9sZW47IGkrKykgewogICAgICAgIGJ1ZmZlcjhbYnVmICsgaV0gPSBNYXRoLnJhbmRvbSgpICogMjU2IHwgMDsKICAgICAgfQogICAgfSwgc29ja19yZWN2KGZkLCByaV9kYXRhLCByaV9mbGFncykgewogICAgICB0aHJvdyAic29ja2V0cyBub3Qgc3VwcG9ydGVkIjsKICAgIH0sIHNvY2tfc2VuZChmZCwgc2lfZGF0YSwgc2lfZmxhZ3MpIHsKICAgICAgdGhyb3cgInNvY2tldHMgbm90IHN1cHBvcnRlZCI7CiAgICB9LCBzb2NrX3NodXRkb3duKGZkLCBob3cpIHsKICAgICAgdGhyb3cgInNvY2tldHMgbm90IHN1cHBvcnRlZCI7CiAgICB9LCBzb2NrX2FjY2VwdChmZCwgZmxhZ3MpIHsKICAgICAgdGhyb3cgInNvY2tldHMgbm90IHN1cHBvcnRlZCI7CiAgICB9IH07CiAgfQp9OwoKLy8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC9mZC5qcwp2YXIgRmQgPSBjbGFzcyB7CiAgZmRfYWxsb2NhdGUob2Zmc2V0LCBsZW4pIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIGZkX2Nsb3NlKCkgewogICAgcmV0dXJuIDA7CiAgfQogIGZkX2Zkc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZmRzdGF0OiBudWxsIH07CiAgfQogIGZkX2Zkc3RhdF9zZXRfZmxhZ3MoZmxhZ3MpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIGZkX2Zkc3RhdF9zZXRfcmlnaHRzKGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZykgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfZmlsZXN0YXRfZ2V0KCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGZpbGVzdGF0OiBudWxsIH07CiAgfQogIGZkX2ZpbGVzdGF0X3NldF9zaXplKHNpemUpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIGZkX2ZpbGVzdGF0X3NldF90aW1lcyhhdGltLCBtdGltLCBmc3RfZmxhZ3MpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIGZkX3ByZWFkKHNpemUsIG9mZnNldCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGRhdGE6IG5ldyBVaW50OEFycmF5KCkgfTsKICB9CiAgZmRfcHJlc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgcHJlc3RhdDogbnVsbCB9OwogIH0KICBmZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgbndyaXR0ZW46IDAgfTsKICB9CiAgZmRfcmVhZChzaXplKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZGF0YTogbmV3IFVpbnQ4QXJyYXkoKSB9OwogIH0KICBmZF9yZWFkZGlyX3NpbmdsZShjb29raWUpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBkaXJlbnQ6IG51bGwgfTsKICB9CiAgZmRfc2VlayhvZmZzZXQsIHdoZW5jZSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIG9mZnNldDogMG4gfTsKICB9CiAgZmRfc3luYygpIHsKICAgIHJldHVybiAwOwogIH0KICBmZF90ZWxsKCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIG9mZnNldDogMG4gfTsKICB9CiAgZmRfd3JpdGUoZGF0YSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIG53cml0dGVuOiAwIH07CiAgfQogIHBhdGhfY3JlYXRlX2RpcmVjdG9yeShwYXRoMikgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgcGF0aF9maWxlc3RhdF9nZXQoZmxhZ3MsIHBhdGgyKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZmlsZXN0YXQ6IG51bGwgfTsKICB9CiAgcGF0aF9maWxlc3RhdF9zZXRfdGltZXMoZmxhZ3MsIHBhdGgyLCBhdGltLCBtdGltLCBmc3RfZmxhZ3MpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfbGluayhwYXRoMiwgaW5vZGUsIGFsbG93X2RpcikgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgcGF0aF91bmxpbmsocGF0aDIpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBpbm9kZV9vYmo6IG51bGwgfTsKICB9CiAgcGF0aF9sb29rdXAocGF0aDIsIGRpcmZsYWdzKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgaW5vZGVfb2JqOiBudWxsIH07CiAgfQogIHBhdGhfb3BlbihkaXJmbGFncywgcGF0aDIsIG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nLCBmZF9mbGFncykgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIGZkX29iajogbnVsbCB9OwogIH0KICBwYXRoX3JlYWRsaW5rKHBhdGgyKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZGF0YTogbnVsbCB9OwogIH0KICBwYXRoX3JlbW92ZV9kaXJlY3RvcnkocGF0aDIpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfcmVuYW1lKG9sZF9wYXRoLCBuZXdfZmQsIG5ld19wYXRoKSB7CiAgICByZXR1cm4gRVJSTk9fTk9UU1VQOwogIH0KICBwYXRoX3VubGlua19maWxlKHBhdGgyKSB7CiAgICByZXR1cm4gRVJSTk9fTk9UU1VQOwogIH0KfTsKdmFyIElub2RlID0gY2xhc3Mgewp9OwoKLy8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC9mc19tZW0uanMKdmFyIE9wZW5GaWxlID0gY2xhc3MgZXh0ZW5kcyBGZCB7CiAgZmRfYWxsb2NhdGUob2Zmc2V0LCBsZW4pIHsKICAgIGlmICh0aGlzLmZpbGUuc2l6ZSA+IG9mZnNldCArIGxlbikgewogICAgfSBlbHNlIHsKICAgICAgY29uc3QgbmV3X2RhdGEgPSBuZXcgVWludDhBcnJheShOdW1iZXIob2Zmc2V0ICsgbGVuKSk7CiAgICAgIG5ld19kYXRhLnNldCh0aGlzLmZpbGUuZGF0YSwgMCk7CiAgICAgIHRoaXMuZmlsZS5kYXRhID0gbmV3X2RhdGE7CiAgICB9CiAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICB9CiAgZmRfZmRzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgZmRzdGF0OiBuZXcgRmRzdGF0KEZJTEVUWVBFX1JFR1VMQVJfRklMRSwgMCkgfTsKICB9CiAgZmRfZmlsZXN0YXRfc2V0X3NpemUoc2l6ZSkgewogICAgaWYgKHRoaXMuZmlsZS5zaXplID4gc2l6ZSkgewogICAgICB0aGlzLmZpbGUuZGF0YSA9IG5ldyBVaW50OEFycmF5KHRoaXMuZmlsZS5kYXRhLmJ1ZmZlci5zbGljZSgwLCBOdW1iZXIoc2l6ZSkpKTsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IG5ld19kYXRhID0gbmV3IFVpbnQ4QXJyYXkoTnVtYmVyKHNpemUpKTsKICAgICAgbmV3X2RhdGEuc2V0KHRoaXMuZmlsZS5kYXRhLCAwKTsKICAgICAgdGhpcy5maWxlLmRhdGEgPSBuZXdfZGF0YTsKICAgIH0KICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogIH0KICBmZF9yZWFkKHNpemUpIHsKICAgIGNvbnN0IHNsaWNlID0gdGhpcy5maWxlLmRhdGEuc2xpY2UoTnVtYmVyKHRoaXMuZmlsZV9wb3MpLCBOdW1iZXIodGhpcy5maWxlX3BvcyArIEJpZ0ludChzaXplKSkpOwogICAgdGhpcy5maWxlX3BvcyArPSBCaWdJbnQoc2xpY2UubGVuZ3RoKTsKICAgIHJldHVybiB7IHJldDogMCwgZGF0YTogc2xpY2UgfTsKICB9CiAgZmRfcHJlYWQoc2l6ZSwgb2Zmc2V0KSB7CiAgICBjb25zdCBzbGljZSA9IHRoaXMuZmlsZS5kYXRhLnNsaWNlKE51bWJlcihvZmZzZXQpLCBOdW1iZXIob2Zmc2V0ICsgQmlnSW50KHNpemUpKSk7CiAgICByZXR1cm4geyByZXQ6IDAsIGRhdGE6IHNsaWNlIH07CiAgfQogIGZkX3NlZWsob2Zmc2V0LCB3aGVuY2UpIHsKICAgIGxldCBjYWxjdWxhdGVkX29mZnNldDsKICAgIHN3aXRjaCAod2hlbmNlKSB7CiAgICAgIGNhc2UgV0hFTkNFX1NFVDoKICAgICAgICBjYWxjdWxhdGVkX29mZnNldCA9IG9mZnNldDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBXSEVOQ0VfQ1VSOgogICAgICAgIGNhbGN1bGF0ZWRfb2Zmc2V0ID0gdGhpcy5maWxlX3BvcyArIG9mZnNldDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBXSEVOQ0VfRU5EOgogICAgICAgIGNhbGN1bGF0ZWRfb2Zmc2V0ID0gQmlnSW50KHRoaXMuZmlsZS5kYXRhLmJ5dGVMZW5ndGgpICsgb2Zmc2V0OwogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fSU5WQUwsIG9mZnNldDogMG4gfTsKICAgIH0KICAgIGlmIChjYWxjdWxhdGVkX29mZnNldCA8IDApIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19JTlZBTCwgb2Zmc2V0OiAwbiB9OwogICAgfQogICAgdGhpcy5maWxlX3BvcyA9IGNhbGN1bGF0ZWRfb2Zmc2V0OwogICAgcmV0dXJuIHsgcmV0OiAwLCBvZmZzZXQ6IHRoaXMuZmlsZV9wb3MgfTsKICB9CiAgZmRfdGVsbCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgb2Zmc2V0OiB0aGlzLmZpbGVfcG9zIH07CiAgfQogIGZkX3dyaXRlKGRhdGEpIHsKICAgIGlmICh0aGlzLmZpbGUucmVhZG9ubHkpCiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fQkFERiwgbndyaXR0ZW46IDAgfTsKICAgIGlmICh0aGlzLmZpbGVfcG9zICsgQmlnSW50KGRhdGEuYnl0ZUxlbmd0aCkgPiB0aGlzLmZpbGUuc2l6ZSkgewogICAgICBjb25zdCBvbGQgPSB0aGlzLmZpbGUuZGF0YTsKICAgICAgdGhpcy5maWxlLmRhdGEgPSBuZXcgVWludDhBcnJheShOdW1iZXIodGhpcy5maWxlX3BvcyArIEJpZ0ludChkYXRhLmJ5dGVMZW5ndGgpKSk7CiAgICAgIHRoaXMuZmlsZS5kYXRhLnNldChvbGQpOwogICAgfQogICAgdGhpcy5maWxlLmRhdGEuc2V0KGRhdGEsIE51bWJlcih0aGlzLmZpbGVfcG9zKSk7CiAgICB0aGlzLmZpbGVfcG9zICs9IEJpZ0ludChkYXRhLmJ5dGVMZW5ndGgpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBud3JpdHRlbjogZGF0YS5ieXRlTGVuZ3RoIH07CiAgfQogIGZkX3B3cml0ZShkYXRhLCBvZmZzZXQpIHsKICAgIGlmICh0aGlzLmZpbGUucmVhZG9ubHkpCiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fQkFERiwgbndyaXR0ZW46IDAgfTsKICAgIGlmIChvZmZzZXQgKyBCaWdJbnQoZGF0YS5ieXRlTGVuZ3RoKSA+IHRoaXMuZmlsZS5zaXplKSB7CiAgICAgIGNvbnN0IG9sZCA9IHRoaXMuZmlsZS5kYXRhOwogICAgICB0aGlzLmZpbGUuZGF0YSA9IG5ldyBVaW50OEFycmF5KE51bWJlcihvZmZzZXQgKyBCaWdJbnQoZGF0YS5ieXRlTGVuZ3RoKSkpOwogICAgICB0aGlzLmZpbGUuZGF0YS5zZXQob2xkKTsKICAgIH0KICAgIHRoaXMuZmlsZS5kYXRhLnNldChkYXRhLCBOdW1iZXIob2Zmc2V0KSk7CiAgICByZXR1cm4geyByZXQ6IDAsIG53cml0dGVuOiBkYXRhLmJ5dGVMZW5ndGggfTsKICB9CiAgZmRfZmlsZXN0YXRfZ2V0KCkgewogICAgcmV0dXJuIHsgcmV0OiAwLCBmaWxlc3RhdDogdGhpcy5maWxlLnN0YXQoKSB9OwogIH0KICBjb25zdHJ1Y3RvcihmaWxlKSB7CiAgICBzdXBlcigpOwogICAgdGhpcy5maWxlX3BvcyA9IDBuOwogICAgdGhpcy5maWxlID0gZmlsZTsKICB9Cn07CnZhciBPcGVuRGlyZWN0b3J5ID0gY2xhc3MgZXh0ZW5kcyBGZCB7CiAgZmRfc2VlayhvZmZzZXQsIHdoZW5jZSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBvZmZzZXQ6IDBuIH07CiAgfQogIGZkX3RlbGwoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG9mZnNldDogMG4gfTsKICB9CiAgZmRfYWxsb2NhdGUob2Zmc2V0LCBsZW4pIHsKICAgIHJldHVybiBFUlJOT19CQURGOwogIH0KICBmZF9mZHN0YXRfZ2V0KCkgewogICAgcmV0dXJuIHsgcmV0OiAwLCBmZHN0YXQ6IG5ldyBGZHN0YXQoRklMRVRZUEVfRElSRUNUT1JZLCAwKSB9OwogIH0KICBmZF9yZWFkZGlyX3NpbmdsZShjb29raWUpIHsKICAgIGlmIChkZWJ1Zy5lbmFibGVkKSB7CiAgICAgIGRlYnVnLmxvZygicmVhZGRpcl9zaW5nbGUiLCBjb29raWUpOwogICAgICBkZWJ1Zy5sb2coY29va2llLCB0aGlzLmRpci5jb250ZW50cy5rZXlzKCkpOwogICAgfQogICAgaWYgKGNvb2tpZSA9PSAwbikgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGRpcmVudDogbmV3IERpcmVudCgxbiwgIi4iLCBGSUxFVFlQRV9ESVJFQ1RPUlkpIH07CiAgICB9IGVsc2UgaWYgKGNvb2tpZSA9PSAxbikgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGRpcmVudDogbmV3IERpcmVudCgybiwgIi4uIiwgRklMRVRZUEVfRElSRUNUT1JZKSB9OwogICAgfQogICAgaWYgKGNvb2tpZSA+PSBCaWdJbnQodGhpcy5kaXIuY29udGVudHMuc2l6ZSkgKyAybikgewogICAgICByZXR1cm4geyByZXQ6IDAsIGRpcmVudDogbnVsbCB9OwogICAgfQogICAgY29uc3QgW25hbWUsIGVudHJ5XSA9IEFycmF5LmZyb20odGhpcy5kaXIuY29udGVudHMuZW50cmllcygpKVtOdW1iZXIoY29va2llIC0gMm4pXTsKICAgIHJldHVybiB7IHJldDogMCwgZGlyZW50OiBuZXcgRGlyZW50KGNvb2tpZSArIDFuLCBuYW1lLCBlbnRyeS5zdGF0KCkuZmlsZXR5cGUpIH07CiAgfQogIHBhdGhfZmlsZXN0YXRfZ2V0KGZsYWdzLCBwYXRoX3N0cikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfZXJyLCBwYXRoOiBwYXRoMiB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoMiA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogcGF0aF9lcnIsIGZpbGVzdGF0OiBudWxsIH07CiAgICB9CiAgICBjb25zdCB7IHJldCwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9lbnRyeV9mb3JfcGF0aChwYXRoMik7CiAgICBpZiAoZW50cnkgPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQsIGZpbGVzdGF0OiBudWxsIH07CiAgICB9CiAgICByZXR1cm4geyByZXQ6IDAsIGZpbGVzdGF0OiBlbnRyeS5zdGF0KCkgfTsKICB9CiAgcGF0aF9sb29rdXAocGF0aF9zdHIsIGRpcmZsYWdzKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGg6IHBhdGgyIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGgyID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXRoX3JldCwgaW5vZGVfb2JqOiBudWxsIH07CiAgICB9CiAgICBjb25zdCB7IHJldCwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9lbnRyeV9mb3JfcGF0aChwYXRoMik7CiAgICBpZiAoZW50cnkgPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQsIGlub2RlX29iajogbnVsbCB9OwogICAgfQogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBpbm9kZV9vYmo6IGVudHJ5IH07CiAgfQogIHBhdGhfb3BlbihkaXJmbGFncywgcGF0aF9zdHIsIG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nLCBmZF9mbGFncykgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoOiBwYXRoMiB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoMiA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogcGF0aF9yZXQsIGZkX29iajogbnVsbCB9OwogICAgfQogICAgbGV0IHsgcmV0LCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgyKTsKICAgIGlmIChlbnRyeSA9PSBudWxsKSB7CiAgICAgIGlmIChyZXQgIT0gRVJSTk9fTk9FTlQpIHsKICAgICAgICByZXR1cm4geyByZXQsIGZkX29iajogbnVsbCB9OwogICAgICB9CiAgICAgIGlmICgob2ZsYWdzICYgT0ZMQUdTX0NSRUFUKSA9PSBPRkxBR1NfQ1JFQVQpIHsKICAgICAgICBjb25zdCB7IHJldDogcmV0MiwgZW50cnk6IG5ld19lbnRyeSB9ID0gdGhpcy5kaXIuY3JlYXRlX2VudHJ5X2Zvcl9wYXRoKHBhdGhfc3RyLCAob2ZsYWdzICYgT0ZMQUdTX0RJUkVDVE9SWSkgPT0gT0ZMQUdTX0RJUkVDVE9SWSk7CiAgICAgICAgaWYgKG5ld19lbnRyeSA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4geyByZXQ6IHJldDIsIGZkX29iajogbnVsbCB9OwogICAgICAgIH0KICAgICAgICBlbnRyeSA9IG5ld19lbnRyeTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PRU5ULCBmZF9vYmo6IG51bGwgfTsKICAgICAgfQogICAgfSBlbHNlIGlmICgob2ZsYWdzICYgT0ZMQUdTX0VYQ0wpID09IE9GTEFHU19FWENMKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fRVhJU1QsIGZkX29iajogbnVsbCB9OwogICAgfQogICAgaWYgKChvZmxhZ3MgJiBPRkxBR1NfRElSRUNUT1JZKSA9PSBPRkxBR1NfRElSRUNUT1JZICYmIGVudHJ5LnN0YXQoKS5maWxldHlwZSAhPT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9URElSLCBmZF9vYmo6IG51bGwgfTsKICAgIH0KICAgIHJldHVybiBlbnRyeS5wYXRoX29wZW4ob2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZmRfZmxhZ3MpOwogIH0KICBwYXRoX2NyZWF0ZV9kaXJlY3RvcnkocGF0aDIpIHsKICAgIHJldHVybiB0aGlzLnBhdGhfb3BlbigwLCBwYXRoMiwgT0ZMQUdTX0NSRUFUIHwgT0ZMQUdTX0RJUkVDVE9SWSwgMG4sIDBuLCAwKS5yZXQ7CiAgfQogIHBhdGhfbGluayhwYXRoX3N0ciwgaW5vZGUsIGFsbG93X2RpcikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoOiBwYXRoMiB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoMiA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXRoX3JldDsKICAgIH0KICAgIGlmIChwYXRoMi5pc19kaXIpIHsKICAgICAgcmV0dXJuIEVSUk5PX05PRU5UOwogICAgfQogICAgY29uc3QgeyByZXQ6IHBhcmVudF9yZXQsIHBhcmVudF9lbnRyeSwgZmlsZW5hbWUsIGVudHJ5IH0gPSB0aGlzLmRpci5nZXRfcGFyZW50X2Rpcl9hbmRfZW50cnlfZm9yX3BhdGgocGF0aDIsIHRydWUpOwogICAgaWYgKHBhcmVudF9lbnRyeSA9PSBudWxsIHx8IGZpbGVuYW1lID09IG51bGwpIHsKICAgICAgcmV0dXJuIHBhcmVudF9yZXQ7CiAgICB9CiAgICBpZiAoZW50cnkgIT0gbnVsbCkgewogICAgICBjb25zdCBzb3VyY2VfaXNfZGlyID0gaW5vZGUuc3RhdCgpLmZpbGV0eXBlID09IEZJTEVUWVBFX0RJUkVDVE9SWTsKICAgICAgY29uc3QgdGFyZ2V0X2lzX2RpciA9IGVudHJ5LnN0YXQoKS5maWxldHlwZSA9PSBGSUxFVFlQRV9ESVJFQ1RPUlk7CiAgICAgIGlmIChzb3VyY2VfaXNfZGlyICYmIHRhcmdldF9pc19kaXIpIHsKICAgICAgICBpZiAoYWxsb3dfZGlyICYmIGVudHJ5IGluc3RhbmNlb2YgRGlyZWN0b3J5KSB7CiAgICAgICAgICBpZiAoZW50cnkuY29udGVudHMuc2l6ZSA9PSAwKSB7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gRVJSTk9fTk9URU1QVFk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJldHVybiBFUlJOT19FWElTVDsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoc291cmNlX2lzX2RpciAmJiAhdGFyZ2V0X2lzX2RpcikgewogICAgICAgIHJldHVybiBFUlJOT19OT1RESVI7CiAgICAgIH0gZWxzZSBpZiAoIXNvdXJjZV9pc19kaXIgJiYgdGFyZ2V0X2lzX2RpcikgewogICAgICAgIHJldHVybiBFUlJOT19JU0RJUjsKICAgICAgfSBlbHNlIGlmIChpbm9kZS5zdGF0KCkuZmlsZXR5cGUgPT0gRklMRVRZUEVfUkVHVUxBUl9GSUxFICYmIGVudHJ5LnN0YXQoKS5maWxldHlwZSA9PSBGSUxFVFlQRV9SRUdVTEFSX0ZJTEUpIHsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fRVhJU1Q7CiAgICAgIH0KICAgIH0KICAgIGlmICghYWxsb3dfZGlyICYmIGlub2RlLnN0YXQoKS5maWxldHlwZSA9PSBGSUxFVFlQRV9ESVJFQ1RPUlkpIHsKICAgICAgcmV0dXJuIEVSUk5PX1BFUk07CiAgICB9CiAgICBwYXJlbnRfZW50cnkuY29udGVudHMuc2V0KGZpbGVuYW1lLCBpbm9kZSk7CiAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICB9CiAgcGF0aF91bmxpbmsocGF0aF9zdHIpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX3JldCwgcGF0aDogcGF0aDIgfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aDIgPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhdGhfcmV0LCBpbm9kZV9vYmo6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBwYXJlbnRfcmV0LCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgyLCB0cnVlKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCB8fCBmaWxlbmFtZSA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogcGFyZW50X3JldCwgaW5vZGVfb2JqOiBudWxsIH07CiAgICB9CiAgICBpZiAoZW50cnkgPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PRU5ULCBpbm9kZV9vYmo6IG51bGwgfTsKICAgIH0KICAgIHBhcmVudF9lbnRyeS5jb250ZW50cy5kZWxldGUoZmlsZW5hbWUpOwogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBpbm9kZV9vYmo6IGVudHJ5IH07CiAgfQogIHBhdGhfdW5saW5rX2ZpbGUocGF0aF9zdHIpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX3JldCwgcGF0aDogcGF0aDIgfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aDIgPT0gbnVsbCkgewogICAgICByZXR1cm4gcGF0aF9yZXQ7CiAgICB9CiAgICBjb25zdCB7IHJldDogcGFyZW50X3JldCwgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9wYXJlbnRfZGlyX2FuZF9lbnRyeV9mb3JfcGF0aChwYXRoMiwgZmFsc2UpOwogICAgaWYgKHBhcmVudF9lbnRyeSA9PSBudWxsIHx8IGZpbGVuYW1lID09IG51bGwgfHwgZW50cnkgPT0gbnVsbCkgewogICAgICByZXR1cm4gcGFyZW50X3JldDsKICAgIH0KICAgIGlmIChlbnRyeS5zdGF0KCkuZmlsZXR5cGUgPT09IEZJTEVUWVBFX0RJUkVDVE9SWSkgewogICAgICByZXR1cm4gRVJSTk9fSVNESVI7CiAgICB9CiAgICBwYXJlbnRfZW50cnkuY29udGVudHMuZGVsZXRlKGZpbGVuYW1lKTsKICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogIH0KICBwYXRoX3JlbW92ZV9kaXJlY3RvcnkocGF0aF9zdHIpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX3JldCwgcGF0aDogcGF0aDIgfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aDIgPT0gbnVsbCkgewogICAgICByZXR1cm4gcGF0aF9yZXQ7CiAgICB9CiAgICBjb25zdCB7IHJldDogcGFyZW50X3JldCwgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9wYXJlbnRfZGlyX2FuZF9lbnRyeV9mb3JfcGF0aChwYXRoMiwgZmFsc2UpOwogICAgaWYgKHBhcmVudF9lbnRyeSA9PSBudWxsIHx8IGZpbGVuYW1lID09IG51bGwgfHwgZW50cnkgPT0gbnVsbCkgewogICAgICByZXR1cm4gcGFyZW50X3JldDsKICAgIH0KICAgIGlmICghKGVudHJ5IGluc3RhbmNlb2YgRGlyZWN0b3J5KSB8fCBlbnRyeS5zdGF0KCkuZmlsZXR5cGUgIT09IEZJTEVUWVBFX0RJUkVDVE9SWSkgewogICAgICByZXR1cm4gRVJSTk9fTk9URElSOwogICAgfQogICAgaWYgKGVudHJ5LmNvbnRlbnRzLnNpemUgIT09IDApIHsKICAgICAgcmV0dXJuIEVSUk5PX05PVEVNUFRZOwogICAgfQogICAgaWYgKCFwYXJlbnRfZW50cnkuY29udGVudHMuZGVsZXRlKGZpbGVuYW1lKSkgewogICAgICByZXR1cm4gRVJSTk9fTk9FTlQ7CiAgICB9CiAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICB9CiAgZmRfZmlsZXN0YXRfZ2V0KCkgewogICAgcmV0dXJuIHsgcmV0OiAwLCBmaWxlc3RhdDogdGhpcy5kaXIuc3RhdCgpIH07CiAgfQogIGZkX2ZpbGVzdGF0X3NldF9zaXplKHNpemUpIHsKICAgIHJldHVybiBFUlJOT19CQURGOwogIH0KICBmZF9yZWFkKHNpemUpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fQkFERiwgZGF0YTogbmV3IFVpbnQ4QXJyYXkoKSB9OwogIH0KICBmZF9wcmVhZChzaXplLCBvZmZzZXQpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fQkFERiwgZGF0YTogbmV3IFVpbnQ4QXJyYXkoKSB9OwogIH0KICBmZF93cml0ZShkYXRhKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG53cml0dGVuOiAwIH07CiAgfQogIGZkX3B3cml0ZShkYXRhLCBvZmZzZXQpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fQkFERiwgbndyaXR0ZW46IDAgfTsKICB9CiAgY29uc3RydWN0b3IoZGlyKSB7CiAgICBzdXBlcigpOwogICAgdGhpcy5kaXIgPSBkaXI7CiAgfQp9Owp2YXIgUHJlb3BlbkRpcmVjdG9yeSA9IGNsYXNzIGV4dGVuZHMgT3BlbkRpcmVjdG9yeSB7CiAgZmRfcHJlc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIHByZXN0YXQ6IFByZXN0YXQuZGlyKHRoaXMucHJlc3RhdF9uYW1lKSB9OwogIH0KICBjb25zdHJ1Y3RvcihuYW1lLCBjb250ZW50cykgewogICAgc3VwZXIobmV3IERpcmVjdG9yeShjb250ZW50cykpOwogICAgdGhpcy5wcmVzdGF0X25hbWUgPSBuYW1lOwogIH0KfTsKdmFyIEZpbGUgPSBjbGFzcyBleHRlbmRzIElub2RlIHsKICBwYXRoX29wZW4ob2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZmRfZmxhZ3MpIHsKICAgIGlmICh0aGlzLnJlYWRvbmx5ICYmIChmc19yaWdodHNfYmFzZSAmIEJpZ0ludChSSUdIVFNfRkRfV1JJVEUpKSA9PSBCaWdJbnQoUklHSFRTX0ZEX1dSSVRFKSkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX1BFUk0sIGZkX29iajogbnVsbCB9OwogICAgfQogICAgaWYgKChvZmxhZ3MgJiBPRkxBR1NfVFJVTkMpID09IE9GTEFHU19UUlVOQykgewogICAgICBpZiAodGhpcy5yZWFkb25seSkKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX1BFUk0sIGZkX29iajogbnVsbCB9OwogICAgICB0aGlzLmRhdGEgPSBuZXcgVWludDhBcnJheShbXSk7CiAgICB9CiAgICBjb25zdCBmaWxlID0gbmV3IE9wZW5GaWxlKHRoaXMpOwogICAgaWYgKGZkX2ZsYWdzICYgRkRGTEFHU19BUFBFTkQpCiAgICAgIGZpbGUuZmRfc2VlaygwbiwgV0hFTkNFX0VORCk7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGZkX29iajogZmlsZSB9OwogIH0KICBnZXQgc2l6ZSgpIHsKICAgIHJldHVybiBCaWdJbnQodGhpcy5kYXRhLmJ5dGVMZW5ndGgpOwogIH0KICBzdGF0KCkgewogICAgcmV0dXJuIG5ldyBGaWxlc3RhdChGSUxFVFlQRV9SRUdVTEFSX0ZJTEUsIHRoaXMuc2l6ZSk7CiAgfQogIGNvbnN0cnVjdG9yKGRhdGEsIG9wdGlvbnMpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLmRhdGEgPSBuZXcgVWludDhBcnJheShkYXRhKTsKICAgIHRoaXMucmVhZG9ubHkgPSAhIW9wdGlvbnM/LnJlYWRvbmx5OwogIH0KfTsKdmFyIFBhdGggPSBjbGFzcyBQYXRoMiB7CiAgc3RhdGljIGZyb20ocGF0aDIpIHsKICAgIGNvbnN0IHNlbGYgPSBuZXcgUGF0aDIoKTsKICAgIHNlbGYuaXNfZGlyID0gcGF0aDIuZW5kc1dpdGgoIi8iKTsKICAgIGlmIChwYXRoMi5zdGFydHNXaXRoKCIvIikpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RDQVBBQkxFLCBwYXRoOiBudWxsIH07CiAgICB9CiAgICBpZiAocGF0aDIuaW5jbHVkZXMoIlwwIikpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19JTlZBTCwgcGF0aDogbnVsbCB9OwogICAgfQogICAgZm9yIChjb25zdCBjb21wb25lbnQgb2YgcGF0aDIuc3BsaXQoIi8iKSkgewogICAgICBpZiAoY29tcG9uZW50ID09PSAiIiB8fCBjb21wb25lbnQgPT09ICIuIikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChjb21wb25lbnQgPT09ICIuLiIpIHsKICAgICAgICBpZiAoc2VsZi5wYXJ0cy5wb3AoKSA9PSB2b2lkIDApIHsKICAgICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UQ0FQQUJMRSwgcGF0aDogbnVsbCB9OwogICAgICAgIH0KICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBzZWxmLnBhcnRzLnB1c2goY29tcG9uZW50KTsKICAgIH0KICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgcGF0aDogc2VsZiB9OwogIH0KICB0b19wYXRoX3N0cmluZygpIHsKICAgIGxldCBzID0gdGhpcy5wYXJ0cy5qb2luKCIvIik7CiAgICBpZiAodGhpcy5pc19kaXIpIHsKICAgICAgcyArPSAiLyI7CiAgICB9CiAgICByZXR1cm4gczsKICB9CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLnBhcnRzID0gW107CiAgICB0aGlzLmlzX2RpciA9IGZhbHNlOwogIH0KfTsKdmFyIERpcmVjdG9yeSA9IGNsYXNzIGV4dGVuZHMgSW5vZGUgewogIHBhdGhfb3BlbihvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmZF9mbGFncykgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBmZF9vYmo6IG5ldyBPcGVuRGlyZWN0b3J5KHRoaXMpIH07CiAgfQogIHN0YXQoKSB7CiAgICByZXR1cm4gbmV3IEZpbGVzdGF0KEZJTEVUWVBFX0RJUkVDVE9SWSwgMG4pOwogIH0KICBnZXRfZW50cnlfZm9yX3BhdGgocGF0aDIpIHsKICAgIGxldCBlbnRyeSA9IHRoaXM7CiAgICBmb3IgKGNvbnN0IGNvbXBvbmVudCBvZiBwYXRoMi5wYXJ0cykgewogICAgICBpZiAoIShlbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkpIHsKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgICBjb25zdCBjaGlsZCA9IGVudHJ5LmNvbnRlbnRzLmdldChjb21wb25lbnQpOwogICAgICBpZiAoY2hpbGQgIT09IHZvaWQgMCkgewogICAgICAgIGVudHJ5ID0gY2hpbGQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZGVidWcubG9nKGNvbXBvbmVudCk7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT0VOVCwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgfQogICAgaWYgKHBhdGgyLmlzX2RpcikgewogICAgICBpZiAoZW50cnkuc3RhdCgpLmZpbGV0eXBlICE9IEZJTEVUWVBFX0RJUkVDVE9SWSkgewogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9URElSLCBlbnRyeTogbnVsbCB9OwogICAgICB9CiAgICB9CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGVudHJ5IH07CiAgfQogIGdldF9wYXJlbnRfZGlyX2FuZF9lbnRyeV9mb3JfcGF0aChwYXRoMiwgYWxsb3dfdW5kZWZpbmVkKSB7CiAgICBjb25zdCBmaWxlbmFtZSA9IHBhdGgyLnBhcnRzLnBvcCgpOwogICAgaWYgKGZpbGVuYW1lID09PSB2b2lkIDApIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19JTlZBTCwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBlbnRyeV9yZXQsIGVudHJ5OiBwYXJlbnRfZW50cnkgfSA9IHRoaXMuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgyKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IGVudHJ5X3JldCwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGlmICghKHBhcmVudF9lbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIHBhcmVudF9lbnRyeTogbnVsbCwgZmlsZW5hbWU6IG51bGwsIGVudHJ5OiBudWxsIH07CiAgICB9CiAgICBjb25zdCBlbnRyeSA9IHBhcmVudF9lbnRyeS5jb250ZW50cy5nZXQoZmlsZW5hbWUpOwogICAgaWYgKGVudHJ5ID09PSB2b2lkIDApIHsKICAgICAgaWYgKCFhbGxvd191bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PRU5ULCBwYXJlbnRfZW50cnk6IG51bGwsIGZpbGVuYW1lOiBudWxsLCBlbnRyeTogbnVsbCB9OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgfQogICAgaWYgKHBhdGgyLmlzX2RpcikgewogICAgICBpZiAoZW50cnkuc3RhdCgpLmZpbGV0eXBlICE9IEZJTEVUWVBFX0RJUkVDVE9SWSkgewogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9URElSLCBwYXJlbnRfZW50cnk6IG51bGwsIGZpbGVuYW1lOiBudWxsLCBlbnRyeTogbnVsbCB9OwogICAgICB9CiAgICB9CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIHBhcmVudF9lbnRyeSwgZmlsZW5hbWUsIGVudHJ5IH07CiAgfQogIGNyZWF0ZV9lbnRyeV9mb3JfcGF0aChwYXRoX3N0ciwgaXNfZGlyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGg6IHBhdGgyIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGgyID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXRoX3JldCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGxldCB7IHJldDogcGFyZW50X3JldCwgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfSA9IHRoaXMuZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgyLCB0cnVlKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCB8fCBmaWxlbmFtZSA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogcGFyZW50X3JldCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGlmIChlbnRyeSAhPSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fRVhJU1QsIGVudHJ5OiBudWxsIH07CiAgICB9CiAgICBkZWJ1Zy5sb2coImNyZWF0ZSIsIHBhdGgyKTsKICAgIGxldCBuZXdfY2hpbGQ7CiAgICBpZiAoIWlzX2RpcikgewogICAgICBuZXdfY2hpbGQgPSBuZXcgRmlsZShuZXcgQXJyYXlCdWZmZXIoMCkpOwogICAgfSBlbHNlIHsKICAgICAgbmV3X2NoaWxkID0gbmV3IERpcmVjdG9yeSgvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpKTsKICAgIH0KICAgIHBhcmVudF9lbnRyeS5jb250ZW50cy5zZXQoZmlsZW5hbWUsIG5ld19jaGlsZCk7CiAgICBlbnRyeSA9IG5ld19jaGlsZDsKICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZW50cnkgfTsKICB9CiAgY29uc3RydWN0b3IoY29udGVudHMpIHsKICAgIHN1cGVyKCk7CiAgICBpZiAoY29udGVudHMgaW5zdGFuY2VvZiBBcnJheSkgewogICAgICB0aGlzLmNvbnRlbnRzID0gbmV3IE1hcChjb250ZW50cyk7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmNvbnRlbnRzID0gY29udGVudHM7CiAgICB9CiAgfQp9Owp2YXIgQ29uc29sZVN0ZG91dCA9IGNsYXNzIGV4dGVuZHMgRmQgewogIGZkX2ZpbGVzdGF0X2dldCgpIHsKICAgIGNvbnN0IGZpbGVzdGF0ID0gbmV3IEZpbGVzdGF0KEZJTEVUWVBFX0NIQVJBQ1RFUl9ERVZJQ0UsIEJpZ0ludCgwKSk7CiAgICByZXR1cm4geyByZXQ6IDAsIGZpbGVzdGF0IH07CiAgfQogIGZkX2Zkc3RhdF9nZXQoKSB7CiAgICBjb25zdCBmZHN0YXQgPSBuZXcgRmRzdGF0KEZJTEVUWVBFX0NIQVJBQ1RFUl9ERVZJQ0UsIDApOwogICAgZmRzdGF0LmZzX3JpZ2h0c19iYXNlID0gQmlnSW50KFJJR0hUU19GRF9XUklURSk7CiAgICByZXR1cm4geyByZXQ6IDAsIGZkc3RhdCB9OwogIH0KICBmZF93cml0ZShkYXRhKSB7CiAgICB0aGlzLndyaXRlKGRhdGEpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBud3JpdHRlbjogZGF0YS5ieXRlTGVuZ3RoIH07CiAgfQogIHN0YXRpYyBsaW5lQnVmZmVyZWQod3JpdGUpIHsKICAgIGNvbnN0IGRlYyA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiLCB7IGZhdGFsOiBmYWxzZSB9KTsKICAgIGxldCBsaW5lX2J1ZiA9ICIiOwogICAgcmV0dXJuIG5ldyBDb25zb2xlU3Rkb3V0KChidWZmZXIpID0+IHsKICAgICAgbGluZV9idWYgKz0gZGVjLmRlY29kZShidWZmZXIsIHsgc3RyZWFtOiB0cnVlIH0pOwogICAgICBjb25zdCBsaW5lcyA9IGxpbmVfYnVmLnNwbGl0KCJcbiIpOwogICAgICBmb3IgKGNvbnN0IFtpLCBsaW5lXSBvZiBsaW5lcy5lbnRyaWVzKCkpIHsKICAgICAgICBpZiAoaSA8IGxpbmVzLmxlbmd0aCAtIDEpIHsKICAgICAgICAgIHdyaXRlKGxpbmUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBsaW5lX2J1ZiA9IGxpbmU7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICB9CiAgY29uc3RydWN0b3Iod3JpdGUpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLndyaXRlID0gd3JpdGU7CiAgfQp9OwoKLy8gbm9kZV9tb2R1bGVzL3dhc20taW1wb3J0cy1wYXJzZXIvaW5kZXguanMKZnVuY3Rpb24gcGFyc2VJbXBvcnRzKG1vZHVsZUJ5dGVzKSB7CiAgaWYgKG1vZHVsZUJ5dGVzIGluc3RhbmNlb2YgVWludDhBcnJheSkgewogIH0gZWxzZSBpZiAobW9kdWxlQnl0ZXMgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikgewogICAgbW9kdWxlQnl0ZXMgPSBuZXcgVWludDhBcnJheShtb2R1bGVCeXRlcyk7CiAgfSBlbHNlIGlmIChtb2R1bGVCeXRlcy5idWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikgewogICAgbW9kdWxlQnl0ZXMgPSBuZXcgVWludDhBcnJheShtb2R1bGVCeXRlcy5idWZmZXIpOwogIH0gZWxzZSB7CiAgICB0aHJvdyBuZXcgRXJyb3IoIkFyZ3VtZW50IG11c3QgYmUgYSBidWZmZXIgc291cmNlLCBsaWtlIFVpbnQ4QXJyYXkgb3IgQXJyYXlCdWZmZXIiKTsKICB9CiAgY29uc3QgcGFyc2VTdGF0ZSA9IG5ldyBQYXJzZVN0YXRlKG1vZHVsZUJ5dGVzKTsKICBwYXJzZU1hZ2ljTnVtYmVyKHBhcnNlU3RhdGUpOwogIHBhcnNlVmVyc2lvbihwYXJzZVN0YXRlKTsKICBjb25zdCB0eXBlcyA9IFtdOwogIGNvbnN0IGltcG9ydHMgPSBbXTsKICB3aGlsZSAocGFyc2VTdGF0ZS5oYXNNb3JlQnl0ZXMoKSkgewogICAgY29uc3Qgc2VjdGlvbklkID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogICAgY29uc3Qgc2VjdGlvblNpemUgPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgc3dpdGNoIChzZWN0aW9uSWQpIHsKICAgICAgY2FzZSAxOiB7CiAgICAgICAgY29uc3QgdHlwZUNvdW50ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHR5cGVDb3VudDsgaSsrKSB7CiAgICAgICAgICB0eXBlcy5wdXNoKHBhcnNlRnVuY3Rpb25UeXBlKHBhcnNlU3RhdGUpKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY2FzZSAyOiB7CiAgICAgICAgY29uc3QgaW1wb3J0Q291bnQgPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW1wb3J0Q291bnQ7IGkrKykgewogICAgICAgICAgY29uc3QgbW9kdWxlMiA9IHBhcnNlU3RhdGUucmVhZE5hbWUoKTsKICAgICAgICAgIGNvbnN0IG5hbWUgPSBwYXJzZVN0YXRlLnJlYWROYW1lKCk7CiAgICAgICAgICBjb25zdCB0eXBlID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogICAgICAgICAgc3dpdGNoICh0eXBlKSB7CiAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICBjb25zdCBpbmRleCA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgICAgICAgICAgICAgaW1wb3J0cy5wdXNoKHsgbW9kdWxlOiBtb2R1bGUyLCBuYW1lLCBraW5kOiAiZnVuY3Rpb24iLCB0eXBlOiB0eXBlc1tpbmRleF0gfSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgICBpbXBvcnRzLnB1c2goeyBtb2R1bGU6IG1vZHVsZTIsIG5hbWUsIGtpbmQ6ICJ0YWJsZSIsIHR5cGU6IHBhcnNlVGFibGVUeXBlKHBhcnNlU3RhdGUpIH0pOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgaW1wb3J0cy5wdXNoKHsgbW9kdWxlOiBtb2R1bGUyLCBuYW1lLCBraW5kOiAibWVtb3J5IiwgdHlwZTogcGFyc2VMaW1pdHMocGFyc2VTdGF0ZSkgfSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgICBpbXBvcnRzLnB1c2goeyBtb2R1bGU6IG1vZHVsZTIsIG5hbWUsIGtpbmQ6ICJnbG9iYWwiLCB0eXBlOiBwYXJzZUdsb2JhbFR5cGUocGFyc2VTdGF0ZSkgfSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGltcG9ydCBkZXNjcmlwdG9yIHR5cGUgJHt0eXBlfWApOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gaW1wb3J0czsKICAgICAgfQogICAgICBkZWZhdWx0OiB7CiAgICAgICAgcGFyc2VTdGF0ZS5za2lwQnl0ZXMoc2VjdGlvblNpemUpOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfQogIHJldHVybiBbXTsKfQp2YXIgUGFyc2VTdGF0ZSA9IGNsYXNzIHsKICBjb25zdHJ1Y3Rvcihtb2R1bGVCeXRlcykgewogICAgdGhpcy5tb2R1bGVCeXRlcyA9IG1vZHVsZUJ5dGVzOwogICAgdGhpcy5vZmZzZXQgPSAwOwogICAgdGhpcy50ZXh0RGVjb2RlciA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKTsKICB9CiAgaGFzTW9yZUJ5dGVzKCkgewogICAgcmV0dXJuIHRoaXMub2Zmc2V0IDwgdGhpcy5tb2R1bGVCeXRlcy5sZW5ndGg7CiAgfQogIHJlYWRCeXRlKCkgewogICAgcmV0dXJuIHRoaXMubW9kdWxlQnl0ZXNbdGhpcy5vZmZzZXQrK107CiAgfQogIHNraXBCeXRlcyhjb3VudCkgewogICAgdGhpcy5vZmZzZXQgKz0gY291bnQ7CiAgfQogIHJlYWRVbnNpZ25lZExFQjEyOCgpIHsKICAgIGxldCByZXN1bHQgPSAwOwogICAgbGV0IHNoaWZ0ID0gMDsKICAgIGxldCBieXRlOwogICAgZG8gewogICAgICBieXRlID0gdGhpcy5yZWFkQnl0ZSgpOwogICAgICByZXN1bHQgfD0gKGJ5dGUgJiAxMjcpIDw8IHNoaWZ0OwogICAgICBzaGlmdCArPSA3OwogICAgfSB3aGlsZSAoYnl0ZSAmIDEyOCk7CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICByZWFkTmFtZSgpIHsKICAgIGNvbnN0IG5hbWVMZW5ndGggPSB0aGlzLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgY29uc3QgbmFtZUJ5dGVzID0gdGhpcy5tb2R1bGVCeXRlcy5zbGljZSh0aGlzLm9mZnNldCwgdGhpcy5vZmZzZXQgKyBuYW1lTGVuZ3RoKTsKICAgIGNvbnN0IG5hbWUgPSB0aGlzLnRleHREZWNvZGVyLmRlY29kZShuYW1lQnl0ZXMpOwogICAgdGhpcy5vZmZzZXQgKz0gbmFtZUxlbmd0aDsKICAgIHJldHVybiBuYW1lOwogIH0KICBhc3NlcnRCeXRlcyhleHBlY3RlZCkgewogICAgY29uc3QgYmFzZU9mZnNldCA9IHRoaXMub2Zmc2V0OwogICAgY29uc3QgZXhwZWN0ZWRMZW5ndGggPSBleHBlY3RlZC5sZW5ndGg7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGV4cGVjdGVkTGVuZ3RoOyBpKyspIHsKICAgICAgaWYgKHRoaXMubW9kdWxlQnl0ZXNbYmFzZU9mZnNldCArIGldICE9PSBleHBlY3RlZFtpXSkgewogICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgJHtleHBlY3RlZH0gYXQgb2Zmc2V0ICR7YmFzZU9mZnNldH1gKTsKICAgICAgfQogICAgfQogICAgdGhpcy5vZmZzZXQgKz0gZXhwZWN0ZWRMZW5ndGg7CiAgfQp9OwpmdW5jdGlvbiBwYXJzZU1hZ2ljTnVtYmVyKHBhcnNlU3RhdGUpIHsKICBjb25zdCBleHBlY3RlZCA9IFswLCA5NywgMTE1LCAxMDldOwogIHBhcnNlU3RhdGUuYXNzZXJ0Qnl0ZXMoZXhwZWN0ZWQpOwp9CmZ1bmN0aW9uIHBhcnNlVmVyc2lvbihwYXJzZVN0YXRlKSB7CiAgY29uc3QgZXhwZWN0ZWQgPSBbMSwgMCwgMCwgMF07CiAgcGFyc2VTdGF0ZS5hc3NlcnRCeXRlcyhleHBlY3RlZCk7Cn0KZnVuY3Rpb24gcGFyc2VUYWJsZVR5cGUocGFyc2VTdGF0ZSkgewogIGNvbnN0IGVsZW1lbnRUeXBlID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogIGxldCBlbGVtZW50OwogIHN3aXRjaCAoZWxlbWVudFR5cGUpIHsKICAgIGNhc2UgMTEyOgogICAgICBlbGVtZW50ID0gImZ1bmNyZWYiOwogICAgICBicmVhazsKICAgIGNhc2UgMTExOgogICAgICBlbGVtZW50ID0gImV4dGVybnJlZiI7CiAgICAgIGJyZWFrOwogICAgZGVmYXVsdDoKICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIHRhYmxlIGVsZW1lbnQgdHlwZSAke2VsZW1lbnRUeXBlfWApOwogIH0KICBjb25zdCB7IG1pbmltdW0sIG1heGltdW0gfSA9IHBhcnNlTGltaXRzKHBhcnNlU3RhdGUpOwogIGlmIChtYXhpbXVtKSB7CiAgICByZXR1cm4geyBlbGVtZW50LCBtaW5pbXVtLCBtYXhpbXVtIH07CiAgfSBlbHNlIHsKICAgIHJldHVybiB7IGVsZW1lbnQsIG1pbmltdW0gfTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VMaW1pdHMocGFyc2VTdGF0ZSkgewogIGNvbnN0IGZsYWdzID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogIGNvbnN0IG1pbmltdW0gPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogIGNvbnN0IGhhc01heGltdW0gPSBmbGFncyAmIDE7CiAgY29uc3Qgc2hhcmVkID0gKGZsYWdzICYgMikgIT09IDA7CiAgY29uc3QgaXNNZW1vcnk2NCA9IChmbGFncyAmIDQpICE9PSAwOwogIGNvbnN0IGluZGV4ID0gaXNNZW1vcnk2NCA/ICJpNjQiIDogImkzMiI7CiAgaWYgKGhhc01heGltdW0pIHsKICAgIGNvbnN0IG1heGltdW0gPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgcmV0dXJuIHsgbWluaW11bSwgc2hhcmVkLCBpbmRleCwgbWF4aW11bSB9OwogIH0gZWxzZSB7CiAgICByZXR1cm4geyBtaW5pbXVtLCBzaGFyZWQsIGluZGV4IH07CiAgfQp9CmZ1bmN0aW9uIHBhcnNlR2xvYmFsVHlwZShwYXJzZVN0YXRlKSB7CiAgY29uc3QgdmFsdWUgPSBwYXJzZVZhbHVlVHlwZShwYXJzZVN0YXRlKTsKICBjb25zdCBtdXRhYmxlID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpID09PSAxOwogIHJldHVybiB7IHZhbHVlLCBtdXRhYmxlIH07Cn0KZnVuY3Rpb24gcGFyc2VWYWx1ZVR5cGUocGFyc2VTdGF0ZSkgewogIGNvbnN0IHR5cGUgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgc3dpdGNoICh0eXBlKSB7CiAgICBjYXNlIDEyNzoKICAgICAgcmV0dXJuICJpMzIiOwogICAgY2FzZSAxMjY6CiAgICAgIHJldHVybiAiaTY0IjsKICAgIGNhc2UgMTI1OgogICAgICByZXR1cm4gImYzMiI7CiAgICBjYXNlIDEyNDoKICAgICAgcmV0dXJuICJmNjQiOwogICAgY2FzZSAxMTI6CiAgICAgIHJldHVybiAiZnVuY3JlZiI7CiAgICBjYXNlIDExMToKICAgICAgcmV0dXJuICJleHRlcm5yZWYiOwogICAgY2FzZSAxMjM6CiAgICAgIHJldHVybiAidjEyOCI7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gdmFsdWUgdHlwZSAke3R5cGV9YCk7CiAgfQp9CmZ1bmN0aW9uIHBhcnNlRnVuY3Rpb25UeXBlKHBhcnNlU3RhdGUpIHsKICBjb25zdCBmb3JtID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogIGlmIChmb3JtICE9PSA5NikgewogICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBmdW5jdGlvbiB0eXBlIGZvcm0gMHg2MCwgZ290ICR7Zm9ybX1gKTsKICB9CiAgY29uc3QgcGFyYW1ldGVycyA9IFtdOwogIGNvbnN0IHBhcmFtZXRlckNvdW50ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICBmb3IgKGxldCBpID0gMDsgaSA8IHBhcmFtZXRlckNvdW50OyBpKyspIHsKICAgIHBhcmFtZXRlcnMucHVzaChwYXJzZVZhbHVlVHlwZShwYXJzZVN0YXRlKSk7CiAgfQogIGNvbnN0IHJlc3VsdHMgPSBbXTsKICBjb25zdCByZXN1bHRDb3VudCA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgZm9yIChsZXQgaSA9IDA7IGkgPCByZXN1bHRDb3VudDsgaSsrKSB7CiAgICByZXN1bHRzLnB1c2gocGFyc2VWYWx1ZVR5cGUocGFyc2VTdGF0ZSkpOwogIH0KICByZXR1cm4geyBwYXJhbWV0ZXJzLCByZXN1bHRzIH07Cn0KCi8vIG5vZGVfbW9kdWxlcy93YXNtLWltcG9ydHMtcGFyc2VyL3BvbHlmaWxsLmpzCnZhciBoYXNXYXNtVHlwZVJlZmxlY3Rpb25TdXBwb3J0ID0gKCgpID0+IHsKICBjb25zdCBtb2R1bGVCeXRlcyA9IG5ldyBVaW50OEFycmF5KFsKICAgIDAsCiAgICA5NywKICAgIDExNSwKICAgIDEwOSwKICAgIDEsCiAgICAwLAogICAgMCwKICAgIDAsCiAgICAyLAogICAgNiwKICAgIDEsCiAgICAwLAogICAgMCwKICAgIDIsCiAgICAwLAogICAgMQogIF0pOwogIGNvbnN0IG1vZHVsZTIgPSBuZXcgV2ViQXNzZW1ibHkuTW9kdWxlKG1vZHVsZUJ5dGVzKTsKICBjb25zdCBpbXBvcnRzID0gV2ViQXNzZW1ibHkuTW9kdWxlLmltcG9ydHMobW9kdWxlMik7CiAgY29uc3QgbWVtb3J5SW1wb3J0ID0gaW1wb3J0c1swXTsKICByZXR1cm4gdHlwZW9mIG1lbW9yeUltcG9ydC50eXBlID09PSAib2JqZWN0IjsKfSkoKTsKZnVuY3Rpb24gcG9seWZpbGwoV2ViQXNzZW1ibHkzKSB7CiAgaWYgKGhhc1dhc21UeXBlUmVmbGVjdGlvblN1cHBvcnQpIHsKICAgIHJldHVybiBXZWJBc3NlbWJseTM7CiAgfQogIGNvbnN0IG5ld1dlYkFzc2VtYmx5ID0ge307CiAgZm9yIChjb25zdCBrZXkgaW4gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMoV2ViQXNzZW1ibHkzKSkgewogICAgbmV3V2ViQXNzZW1ibHlba2V5XSA9IFdlYkFzc2VtYmx5M1trZXldOwogIH0KICBjb25zdCBwb2x5ZmlsbGVkSW1wb3J0c1N5bWJvbCA9IFN5bWJvbCgicG9seWZpbGxlZEltcG9ydHNTeW1ib2wiKTsKICBjb25zdCBhc3NpZ25JbXBvcnRzID0gKG1vZHVsZTIsIHNvdXJjZUJ5dGVzKSA9PiB7CiAgICBtb2R1bGUyW3BvbHlmaWxsZWRJbXBvcnRzU3ltYm9sXSA9IHBhcnNlSW1wb3J0cyhzb3VyY2VCeXRlcyk7CiAgfTsKICBjb25zdCBuZXdNb2R1bGUgPSBuZXdXZWJBc3NlbWJseS5Nb2R1bGUgPSBmdW5jdGlvbihieXRlcykgewogICAgY29uc3QgbW9kdWxlMiA9IG5ldyBXZWJBc3NlbWJseTMuTW9kdWxlKGJ5dGVzKTsKICAgIGFzc2lnbkltcG9ydHMobW9kdWxlMiwgYnl0ZXMpOwogICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKG1vZHVsZTIsIG5ld01vZHVsZS5wcm90b3R5cGUpOwogICAgcmV0dXJuIG1vZHVsZTI7CiAgfTsKICBPYmplY3Quc2V0UHJvdG90eXBlT2YobmV3TW9kdWxlLnByb3RvdHlwZSwgV2ViQXNzZW1ibHkzLk1vZHVsZS5wcm90b3R5cGUpOwogIG5ld1dlYkFzc2VtYmx5LmNvbXBpbGUgPSBhc3luYyAoc291cmNlKSA9PiB7CiAgICBjb25zdCBtb2R1bGUyID0gYXdhaXQgV2ViQXNzZW1ibHkzLmNvbXBpbGUoc291cmNlKTsKICAgIGFzc2lnbkltcG9ydHMobW9kdWxlMiwgc291cmNlKTsKICAgIHJldHVybiBtb2R1bGUyOwogIH07CiAgaWYgKFdlYkFzc2VtYmx5My5jb21waWxlU3RyZWFtaW5nKSB7CiAgICBuZXdXZWJBc3NlbWJseS5jb21waWxlU3RyZWFtaW5nID0gYXN5bmMgKHNvdXJjZSkgPT4gewogICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHNvdXJjZTsKICAgICAgY29uc3QgY2xvbmUgPSByZXNwb25zZS5jbG9uZSgpOwogICAgICBjb25zdCBtb2R1bGUyID0gYXdhaXQgV2ViQXNzZW1ibHkzLmNvbXBpbGVTdHJlYW1pbmcocmVzcG9uc2UpOwogICAgICBhc3NpZ25JbXBvcnRzKG1vZHVsZTIsIG5ldyBVaW50OEFycmF5KGF3YWl0IGNsb25lLmFycmF5QnVmZmVyKCkpKTsKICAgICAgcmV0dXJuIG1vZHVsZTI7CiAgICB9OwogIH0KICBuZXdNb2R1bGUuaW1wb3J0cyA9IChtb2R1bGUyKSA9PiB7CiAgICBjb25zdCBwYXJzZWRJbXBvcnRzID0gbW9kdWxlMltwb2x5ZmlsbGVkSW1wb3J0c1N5bWJvbF07CiAgICBpZiAoIXBhcnNlZEltcG9ydHMpIHsKICAgICAgcmV0dXJuIFdlYkFzc2VtYmx5My5Nb2R1bGUuaW1wb3J0cyhtb2R1bGUyKTsKICAgIH0KICAgIHJldHVybiBwYXJzZWRJbXBvcnRzOwogIH07CiAgcmV0dXJuIG5ld1dlYkFzc2VtYmx5Owp9CgovLyBlbnRyeXBvaW50L2ludHJpbnNpY3MudHMKdmFyIFdlYkFzc2VtYmx5MiA9IHBvbHlmaWxsKGdsb2JhbFRoaXMuV2ViQXNzZW1ibHkpOwp2YXIgTGluZURlY29kZXIgPSBjbGFzcyB7CiAgY29uc3RydWN0b3Iob25MaW5lKSB7CiAgICB0aGlzLmRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IiwgeyBmYXRhbDogZmFsc2UgfSk7CiAgICB0aGlzLmJ1ZmZlciA9ICIiOwogICAgdGhpcy5vbkxpbmUgPSBvbkxpbmU7CiAgfQogIGRlY29kZXI7CiAgYnVmZmVyOwogIG9uTGluZTsKICBzZW5kKGNodW5rKSB7CiAgICB0aGlzLmJ1ZmZlciArPSB0aGlzLmRlY29kZXIuZGVjb2RlKGNodW5rLCB7IHN0cmVhbTogdHJ1ZSB9KTsKICAgIGNvbnN0IGxpbmVzID0gdGhpcy5idWZmZXIuc3BsaXQoIlxuIik7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aCAtIDE7IGkrKykgewogICAgICB0aGlzLm9uTGluZShsaW5lc1tpXSk7CiAgICB9CiAgICB0aGlzLmJ1ZmZlciA9IGxpbmVzW2xpbmVzLmxlbmd0aCAtIDFdOwogIH0KfTsKYXN5bmMgZnVuY3Rpb24gaW5zdGFudGlhdGUocmF3T3B0aW9ucywgZXh0cmFXYXNtSW1wb3J0cykgewogIGNvbnN0IG9wdGlvbnMgPSBkZWZhdWx0SW5zdGFudGlhdGlvbk9wdGlvbnMocmF3T3B0aW9ucyk7CiAgbGV0IHN3aWZ0ID0gb3B0aW9ucy5zd2lmdDsKICBpZiAoIXN3aWZ0ICYmIG9wdGlvbnMuU3dpZnRSdW50aW1lKSB7CiAgICBzd2lmdCA9IG5ldyBvcHRpb25zLlN3aWZ0UnVudGltZSgpOwogIH0KICBsZXQgc3Rkb3V0TGluZSA9IHZvaWQgMDsKICBpZiAob3B0aW9ucy5vblN0ZG91dExpbmUgIT0gbnVsbCkgewogICAgc3Rkb3V0TGluZSA9IG5ldyBMaW5lRGVjb2RlcihvcHRpb25zLm9uU3Rkb3V0TGluZSk7CiAgfQogIGNvbnN0IHN0ZG91dCA9IG5ldyBDb25zb2xlU3Rkb3V0KChjaHVuaykgPT4gewogICAgb3B0aW9ucy5vblN0ZG91dD8uY2FsbCh2b2lkIDAsIGNodW5rKTsKICAgIHN0ZG91dExpbmU/LnNlbmQoY2h1bmspOwogIH0pOwogIGxldCBzdGRlcnJMaW5lID0gdm9pZCAwOwogIGlmIChvcHRpb25zLm9uU3RkZXJyTGluZSAhPSBudWxsKSB7CiAgICBzdGRlcnJMaW5lID0gbmV3IExpbmVEZWNvZGVyKG9wdGlvbnMub25TdGRlcnJMaW5lKTsKICB9CiAgY29uc3Qgc3RkZXJyID0gbmV3IENvbnNvbGVTdGRvdXQoKGNodW5rKSA9PiB7CiAgICBvcHRpb25zLm9uU3RkZXJyPy5jYWxsKHZvaWQgMCwgY2h1bmspOwogICAgc3RkZXJyTGluZT8uc2VuZChjaHVuayk7CiAgfSk7CiAgY29uc3QgYXJnczIgPSBvcHRpb25zLmFyZ3MgfHwgW107CiAgY29uc3QgZmRzID0gWwogICAgbmV3IE9wZW5GaWxlKG5ldyBGaWxlKFtdKSksCiAgICBzdGRvdXQsCiAgICBzdGRlcnIsCiAgICBuZXcgUHJlb3BlbkRpcmVjdG9yeSgiLyIsIC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCkpCiAgXTsKICBjb25zdCBlbnZzID0gb3B0aW9ucy5lbnYgPyBPYmplY3QuZW50cmllcyhvcHRpb25zLmVudikubWFwKChba2V5LCB2YWx1ZV0pID0+IGAke2tleX09JHt2YWx1ZX1gKSA6IFtdOwogIGNvbnN0IHdhc2kgPSBuZXcgV0FTSShhcmdzMiwgZW52cywgZmRzLCB7CiAgICBkZWJ1ZzogZmFsc2UKICB9KTsKICBjb25zdCBjcmVhdGVXYXNtSW1wb3J0T2JqZWN0ID0gKGV4dHJhV2FzbUltcG9ydHMyLCBtb2R1bGUyKSA9PiB7CiAgICBjb25zdCBpbXBvcnRPYmplY3QyID0gewogICAgICB3YXNpX3NuYXBzaG90X3ByZXZpZXcxOiB3YXNpLndhc2lJbXBvcnQKICAgIH07CiAgICBpZiAoc3dpZnQpIHsKICAgICAgaW1wb3J0T2JqZWN0Mi5qYXZhc2NyaXB0X2tpdCA9IHN3aWZ0Lndhc21JbXBvcnRzOwogICAgfQogICAgaWYgKGV4dHJhV2FzbUltcG9ydHMyKSB7CiAgICAgIGZvciAoY29uc3QgbW9kdWxlTmFtZSBpbiBleHRyYVdhc21JbXBvcnRzMikgewogICAgICAgIGlmICghaW1wb3J0T2JqZWN0Mlttb2R1bGVOYW1lXSkgewogICAgICAgICAgaW1wb3J0T2JqZWN0Mlttb2R1bGVOYW1lXSA9IHt9OwogICAgICAgIH0KICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IGluIGV4dHJhV2FzbUltcG9ydHMyW21vZHVsZU5hbWVdKSB7CiAgICAgICAgICBpbXBvcnRPYmplY3QyW21vZHVsZU5hbWVdW2VudHJ5XSA9IGV4dHJhV2FzbUltcG9ydHMyW21vZHVsZU5hbWVdW2VudHJ5XTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGZvciAoY29uc3QgX2ltcG9ydEVudHJ5IG9mIFdlYkFzc2VtYmx5Mi5Nb2R1bGUuaW1wb3J0cyhtb2R1bGUyKSkgewogICAgICBjb25zdCBpbXBvcnRFbnRyeSA9IF9pbXBvcnRFbnRyeTsKICAgICAgaWYgKCFpbXBvcnRPYmplY3QyW2ltcG9ydEVudHJ5Lm1vZHVsZV0pIHsKICAgICAgICBpbXBvcnRPYmplY3QyW2ltcG9ydEVudHJ5Lm1vZHVsZV0gPSB7fTsKICAgICAgfQogICAgICBpZiAoaW1wb3J0T2JqZWN0MltpbXBvcnRFbnRyeS5tb2R1bGVdW2ltcG9ydEVudHJ5Lm5hbWVdKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGltcG9ydEVudHJ5LmtpbmQgPT0gImZ1bmN0aW9uIikgewogICAgICAgIGltcG9ydE9iamVjdDJbaW1wb3J0RW50cnkubW9kdWxlXVtpbXBvcnRFbnRyeS5uYW1lXSA9ICgpID0+IHsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW1wb3J0ZWQgZnVuY3Rpb24gJHtpbXBvcnRFbnRyeS5tb2R1bGV9LiR7aW1wb3J0RW50cnkubmFtZX0gbm90IGltcGxlbWVudGVkYCk7CiAgICAgICAgfTsKICAgICAgfSBlbHNlIGlmIChpbXBvcnRFbnRyeS5raW5kID09ICJtZW1vcnkiICYmIGltcG9ydEVudHJ5Lm1vZHVsZSA9PSAiZW52IiAmJiBpbXBvcnRFbnRyeS5uYW1lID09ICJtZW1vcnkiKSB7CiAgICAgICAgY29uc3QgdHlwZSA9IGltcG9ydEVudHJ5LnR5cGU7CiAgICAgICAgY29uc3QgZGVzY3JpcHRvciA9IHsKICAgICAgICAgIGluaXRpYWw6IHR5cGUubWluaW11bSwKICAgICAgICAgIG1heGltdW06IHR5cGUubWF4aW11bSwKICAgICAgICAgIHNoYXJlZDogdHlwZS5zaGFyZWQKICAgICAgICB9OwogICAgICAgIGltcG9ydE9iamVjdDJbaW1wb3J0RW50cnkubW9kdWxlXVtpbXBvcnRFbnRyeS5uYW1lXSA9IG5ldyBXZWJBc3NlbWJseTIuTWVtb3J5KGRlc2NyaXB0b3IpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gaW1wb3J0T2JqZWN0MjsKICB9OwogIGNvbnN0IGltcG9ydE9iamVjdCA9IGNyZWF0ZVdhc21JbXBvcnRPYmplY3QoZXh0cmFXYXNtSW1wb3J0cywgb3B0aW9ucy5tb2R1bGUpOwogIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgV2ViQXNzZW1ibHkyLmluc3RhbnRpYXRlKG9wdGlvbnMubW9kdWxlLCBpbXBvcnRPYmplY3QpOwogIGlmIChzd2lmdCAmJiBpbnN0YW5jZS5leHBvcnRzLnN3anNfbGlicmFyeV92ZXJzaW9uKSB7CiAgICBzd2lmdC5zZXRJbnN0YW5jZShpbnN0YW5jZSk7CiAgfQogIGlmICh0eXBlb2YgaW5zdGFuY2UuZXhwb3J0cy5fc3RhcnQgPT09ICJmdW5jdGlvbiIpIHsKICAgIHdhc2kuc3RhcnQoaW5zdGFuY2UpOwogIH0gZWxzZSBpZiAodHlwZW9mIGluc3RhbmNlLmV4cG9ydHMuX2luaXRpYWxpemUgPT0gImZ1bmN0aW9uIikgewogICAgd2FzaS5pbml0aWFsaXplKGluc3RhbmNlKTsKICAgIGlmIChzd2lmdCAmJiBzd2lmdC5tYWluKSB7CiAgICAgIHN3aWZ0Lm1haW4oKTsKICAgIH0gZWxzZSB7CiAgICAgIGlmICh0eXBlb2YgaW5zdGFuY2UuZXhwb3J0cy5tYWluID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgaW5zdGFuY2UuZXhwb3J0cy5tYWluKCk7CiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGluc3RhbmNlLmV4cG9ydHMuX19tYWluX2FyZ2NfYXJndiA9PT0gImZ1bmN0aW9uIikgewogICAgICAgIGluc3RhbmNlLmV4cG9ydHMuX19tYWluX2FyZ2NfYXJndigwLCAwKTsKICAgICAgfQogICAgfQogIH0KICByZXR1cm4geyBpbnN0YW5jZSB9Owp9CmZ1bmN0aW9uIGRlZmF1bHRJbnN0YW50aWF0aW9uT3B0aW9ucyhvcHRpb25zKSB7CiAgaWYgKG9wdGlvbnMuYXJncyA9PSBudWxsKSB7CiAgICBvcHRpb25zLmFyZ3MgPSBbIm1haW4ud2FzbSJdOwogIH0KICBjb25zdCBpc05vZGVKcyA9IHR5cGVvZiBwcm9jZXNzICE9PSAidW5kZWZpbmVkIiAmJiBwcm9jZXNzLnJlbGVhc2UubmFtZSA9PT0gIm5vZGUiOwogIGNvbnN0IGlzV2ViQnJvd3NlciA9IHR5cGVvZiB3aW5kb3cgIT09ICJ1bmRlZmluZWQiOwogIGlmIChpc05vZGVKcykgewogICAgaWYgKCFvcHRpb25zLm9uU3Rkb3V0KSB7CiAgICAgIG9wdGlvbnMub25TdGRvdXQgPSAoY2h1bmspID0+IHByb2Nlc3Muc3Rkb3V0LndyaXRlKGNodW5rKTsKICAgIH0KICAgIGlmICghb3B0aW9ucy5vblN0ZGVycikgewogICAgICBvcHRpb25zLm9uU3RkZXJyID0gKGNodW5rKSA9PiBwcm9jZXNzLnN0ZGVyci53cml0ZShjaHVuayk7CiAgICB9CiAgfSBlbHNlIGlmIChpc1dlYkJyb3dzZXIpIHsKICAgIGlmICghb3B0aW9ucy5vblN0ZG91dExpbmUpIHsKICAgICAgb3B0aW9ucy5vblN0ZG91dExpbmUgPSAobGluZSkgPT4gY29uc29sZS5sb2cobGluZSk7CiAgICB9CiAgICBpZiAoIW9wdGlvbnMub25TdGRlcnJMaW5lKSB7CiAgICAgIG9wdGlvbnMub25TdGRlcnJMaW5lID0gKGxpbmUpID0+IGNvbnNvbGUud2FybihsaW5lKTsKICAgIH0KICB9CiAgcmV0dXJuIG9wdGlvbnM7Cn0KCi8vIGVudHJ5cG9pbnQvdGVzdE5vZGUudHMKdmFyIGFyZ3MgPSBbLi4ucHJvY2Vzcy5hcmd2XTsKYXJncy5zaGlmdCgpOwphcmdzLnNoaWZ0KCk7CnZhciBbd2FzbUZpbGUsIC4uLnRlc3RBcmdzXSA9IGFyZ3M7CnRlc3RBcmdzLnVuc2hpZnQoaW1wb3J0X3BhdGguZGVmYXVsdC5iYXNlbmFtZSh3YXNtRmlsZSkpOwppZiAoIXdhc21GaWxlKSB7CiAgdGhyb3cgRXJyb3IoIk5vIFdBU00gdGVzdCBmaWxlIHNwZWNpZmllZCwgY2FuIG5vdCBydW4gdGVzdHMiKTsKfQp2YXIgc3RhcnRXYXNpVGFzayA9IGFzeW5jICgpID0+IHsKICBjb25zdCB3YXNtQnl0ZXMgPSBhd2FpdCBpbXBvcnRfcHJvbWlzZXMuZGVmYXVsdC5yZWFkRmlsZSh3YXNtRmlsZSk7CiAgbGV0IHJ1bnRpbWVDb25zdHJ1Y3RvciA9IHZvaWQgMDsKICB0cnkgewogICAgY29uc3QgeyBTd2lmdFJ1bnRpbWUgfSA9IGF3YWl0IGltcG9ydCgKICAgICAgLy8gQHRzLWlnbm9yZQogICAgICAiLi9KYXZhU2NyaXB0S2l0X0phdmFTY3JpcHRLaXQucmVzb3VyY2VzL1J1bnRpbWUvaW5kZXgubWpzIgogICAgKTsKICAgIHJ1bnRpbWVDb25zdHJ1Y3RvciA9IFN3aWZ0UnVudGltZTsKICAgIGdsb2JhbC5yZXF1aXJlID0gcmVxdWlyZTsKICB9IGNhdGNoIHsKICB9CiAgY29uc3QgZW52ID0ge307CiAgZm9yIChjb25zdCBrZXkgaW4gcHJvY2Vzcy5lbnYpIHsKICAgIGNvbnN0IHZhbHVlID0gcHJvY2Vzcy5lbnZba2V5XTsKICAgIGlmICh2YWx1ZSkgewogICAgICBlbnZba2V5XSA9IHZhbHVlOwogICAgfQogIH0KICBsZXQgcHJvY0V4aXRDYWxsZWQgPSBmYWxzZTsKICBwcm9jZXNzLm9uKCJiZWZvcmVFeGl0IiwgKCkgPT4gewogICAgaWYgKCFwcm9jRXhpdENhbGxlZCkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoYFRlc3QgaGFybmVzcyBwcm9jZXNzIGV4aXRlZCBiZWZvcmUgdGVzdCBwcm9jZXNzLgpUaGlzIHVzdWFsbHkgbWVhbnMgdGhlcmUgYXJlIHNvbWUgZGFuZ2xpbmcgY29udGludWF0aW9ucywgd2hpY2ggYXJlIGF3YWl0ZWQgYnV0IG5ldmVyIHJlc3VtZWQuYCk7CiAgICB9CiAgfSk7CiAgYXdhaXQgaW5zdGFudGlhdGUoewogICAgbW9kdWxlOiBhd2FpdCBXZWJBc3NlbWJseS5jb21waWxlKHdhc21CeXRlcyksCiAgICBhcmdzOiB0ZXN0QXJncywKICAgIGVudiwKICAgIG9uU3Rkb3V0TGluZTogKGxpbmUpID0+IHsKICAgICAgY29uc29sZS5sb2cobGluZSk7CiAgICB9LAogICAgb25TdGRlcnJMaW5lOiAobGluZSkgPT4gewogICAgICBjb25zb2xlLmVycm9yKGxpbmUpOwogICAgfSwKICAgIFN3aWZ0UnVudGltZTogcnVudGltZUNvbnN0cnVjdG9yCiAgfSwgewogICAgIndhc2lfc25hcHNob3RfcHJldmlldzEiOiB7CiAgICAgIHByb2NfZXhpdDogKGNvZGUpID0+IHsKICAgICAgICBwcm9jRXhpdENhbGxlZCA9IHRydWU7CiAgICAgICAgcHJvY2Vzcy5leGl0KGNvZGUpOwogICAgICB9CiAgICB9CiAgfSk7Cn07CnN0YXJ0V2FzaVRhc2soKS5jYXRjaCgoZSkgPT4gewogIHRocm93IGU7Cn0pOwo=")! - public static let intrinsics: Data = Data(base64Encoded: "Ly8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC93YXNpX2RlZnMuanMKdmFyIENMT0NLSURfUkVBTFRJTUUgPSAwOwp2YXIgQ0xPQ0tJRF9NT05PVE9OSUMgPSAxOwp2YXIgRVJSTk9fU1VDQ0VTUyA9IDA7CnZhciBFUlJOT19CQURGID0gODsKdmFyIEVSUk5PX0VYSVNUID0gMjA7CnZhciBFUlJOT19JTlZBTCA9IDI4Owp2YXIgRVJSTk9fSVNESVIgPSAzMTsKdmFyIEVSUk5PX05BTUVUT09MT05HID0gMzc7CnZhciBFUlJOT19OT0VOVCA9IDQ0Owp2YXIgRVJSTk9fTk9TWVMgPSA1MjsKdmFyIEVSUk5PX05PVERJUiA9IDU0Owp2YXIgRVJSTk9fTk9URU1QVFkgPSA1NTsKdmFyIEVSUk5PX05PVFNVUCA9IDU4Owp2YXIgRVJSTk9fUEVSTSA9IDYzOwp2YXIgRVJSTk9fTk9UQ0FQQUJMRSA9IDc2Owp2YXIgUklHSFRTX0ZEX0RBVEFTWU5DID0gMSA8PCAwOwp2YXIgUklHSFRTX0ZEX1JFQUQgPSAxIDw8IDE7CnZhciBSSUdIVFNfRkRfU0VFSyA9IDEgPDwgMjsKdmFyIFJJR0hUU19GRF9GRFNUQVRfU0VUX0ZMQUdTID0gMSA8PCAzOwp2YXIgUklHSFRTX0ZEX1NZTkMgPSAxIDw8IDQ7CnZhciBSSUdIVFNfRkRfVEVMTCA9IDEgPDwgNTsKdmFyIFJJR0hUU19GRF9XUklURSA9IDEgPDwgNjsKdmFyIFJJR0hUU19GRF9BRFZJU0UgPSAxIDw8IDc7CnZhciBSSUdIVFNfRkRfQUxMT0NBVEUgPSAxIDw8IDg7CnZhciBSSUdIVFNfUEFUSF9DUkVBVEVfRElSRUNUT1JZID0gMSA8PCA5Owp2YXIgUklHSFRTX1BBVEhfQ1JFQVRFX0ZJTEUgPSAxIDw8IDEwOwp2YXIgUklHSFRTX1BBVEhfTElOS19TT1VSQ0UgPSAxIDw8IDExOwp2YXIgUklHSFRTX1BBVEhfTElOS19UQVJHRVQgPSAxIDw8IDEyOwp2YXIgUklHSFRTX1BBVEhfT1BFTiA9IDEgPDwgMTM7CnZhciBSSUdIVFNfRkRfUkVBRERJUiA9IDEgPDwgMTQ7CnZhciBSSUdIVFNfUEFUSF9SRUFETElOSyA9IDEgPDwgMTU7CnZhciBSSUdIVFNfUEFUSF9SRU5BTUVfU09VUkNFID0gMSA8PCAxNjsKdmFyIFJJR0hUU19QQVRIX1JFTkFNRV9UQVJHRVQgPSAxIDw8IDE3Owp2YXIgUklHSFRTX1BBVEhfRklMRVNUQVRfR0VUID0gMSA8PCAxODsKdmFyIFJJR0hUU19QQVRIX0ZJTEVTVEFUX1NFVF9TSVpFID0gMSA8PCAxOTsKdmFyIFJJR0hUU19QQVRIX0ZJTEVTVEFUX1NFVF9USU1FUyA9IDEgPDwgMjA7CnZhciBSSUdIVFNfRkRfRklMRVNUQVRfR0VUID0gMSA8PCAyMTsKdmFyIFJJR0hUU19GRF9GSUxFU1RBVF9TRVRfU0laRSA9IDEgPDwgMjI7CnZhciBSSUdIVFNfRkRfRklMRVNUQVRfU0VUX1RJTUVTID0gMSA8PCAyMzsKdmFyIFJJR0hUU19QQVRIX1NZTUxJTksgPSAxIDw8IDI0Owp2YXIgUklHSFRTX1BBVEhfUkVNT1ZFX0RJUkVDVE9SWSA9IDEgPDwgMjU7CnZhciBSSUdIVFNfUEFUSF9VTkxJTktfRklMRSA9IDEgPDwgMjY7CnZhciBSSUdIVFNfUE9MTF9GRF9SRUFEV1JJVEUgPSAxIDw8IDI3Owp2YXIgUklHSFRTX1NPQ0tfU0hVVERPV04gPSAxIDw8IDI4Owp2YXIgSW92ZWMgPSBjbGFzcyB7CiAgc3RhdGljIHJlYWRfYnl0ZXModmlldywgcHRyKSB7CiAgICBjb25zdCBpb3ZlYyA9IG5ldyBJb3ZlYygpOwogICAgaW92ZWMuYnVmID0gdmlldy5nZXRVaW50MzIocHRyLCB0cnVlKTsKICAgIGlvdmVjLmJ1Zl9sZW4gPSB2aWV3LmdldFVpbnQzMihwdHIgKyA0LCB0cnVlKTsKICAgIHJldHVybiBpb3ZlYzsKICB9CiAgc3RhdGljIHJlYWRfYnl0ZXNfYXJyYXkodmlldywgcHRyLCBsZW4pIHsKICAgIGNvbnN0IGlvdmVjcyA9IFtdOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgICBpb3ZlY3MucHVzaChJb3ZlYy5yZWFkX2J5dGVzKHZpZXcsIHB0ciArIDggKiBpKSk7CiAgICB9CiAgICByZXR1cm4gaW92ZWNzOwogIH0KfTsKdmFyIENpb3ZlYyA9IGNsYXNzIHsKICBzdGF0aWMgcmVhZF9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIGNvbnN0IGlvdmVjID0gbmV3IENpb3ZlYygpOwogICAgaW92ZWMuYnVmID0gdmlldy5nZXRVaW50MzIocHRyLCB0cnVlKTsKICAgIGlvdmVjLmJ1Zl9sZW4gPSB2aWV3LmdldFVpbnQzMihwdHIgKyA0LCB0cnVlKTsKICAgIHJldHVybiBpb3ZlYzsKICB9CiAgc3RhdGljIHJlYWRfYnl0ZXNfYXJyYXkodmlldywgcHRyLCBsZW4pIHsKICAgIGNvbnN0IGlvdmVjcyA9IFtdOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgICBpb3ZlY3MucHVzaChDaW92ZWMucmVhZF9ieXRlcyh2aWV3LCBwdHIgKyA4ICogaSkpOwogICAgfQogICAgcmV0dXJuIGlvdmVjczsKICB9Cn07CnZhciBXSEVOQ0VfU0VUID0gMDsKdmFyIFdIRU5DRV9DVVIgPSAxOwp2YXIgV0hFTkNFX0VORCA9IDI7CnZhciBGSUxFVFlQRV9DSEFSQUNURVJfREVWSUNFID0gMjsKdmFyIEZJTEVUWVBFX0RJUkVDVE9SWSA9IDM7CnZhciBGSUxFVFlQRV9SRUdVTEFSX0ZJTEUgPSA0Owp2YXIgRGlyZW50ID0gY2xhc3MgewogIGhlYWRfbGVuZ3RoKCkgewogICAgcmV0dXJuIDI0OwogIH0KICBuYW1lX2xlbmd0aCgpIHsKICAgIHJldHVybiB0aGlzLmRpcl9uYW1lLmJ5dGVMZW5ndGg7CiAgfQogIHdyaXRlX2hlYWRfYnl0ZXModmlldywgcHRyKSB7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIsIHRoaXMuZF9uZXh0LCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDgsIHRoaXMuZF9pbm8sIHRydWUpOwogICAgdmlldy5zZXRVaW50MzIocHRyICsgMTYsIHRoaXMuZGlyX25hbWUubGVuZ3RoLCB0cnVlKTsKICAgIHZpZXcuc2V0VWludDgocHRyICsgMjAsIHRoaXMuZF90eXBlKTsKICB9CiAgd3JpdGVfbmFtZV9ieXRlcyh2aWV3OCwgcHRyLCBidWZfbGVuKSB7CiAgICB2aWV3OC5zZXQodGhpcy5kaXJfbmFtZS5zbGljZSgwLCBNYXRoLm1pbih0aGlzLmRpcl9uYW1lLmJ5dGVMZW5ndGgsIGJ1Zl9sZW4pKSwgcHRyKTsKICB9CiAgY29uc3RydWN0b3IobmV4dF9jb29raWUsIG5hbWUsIHR5cGUpIHsKICAgIHRoaXMuZF9pbm8gPSAwbjsKICAgIGNvbnN0IGVuY29kZWRfbmFtZSA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShuYW1lKTsKICAgIHRoaXMuZF9uZXh0ID0gbmV4dF9jb29raWU7CiAgICB0aGlzLmRfbmFtbGVuID0gZW5jb2RlZF9uYW1lLmJ5dGVMZW5ndGg7CiAgICB0aGlzLmRfdHlwZSA9IHR5cGU7CiAgICB0aGlzLmRpcl9uYW1lID0gZW5jb2RlZF9uYW1lOwogIH0KfTsKdmFyIEZERkxBR1NfQVBQRU5EID0gMSA8PCAwOwp2YXIgRkRGTEFHU19EU1lOQyA9IDEgPDwgMTsKdmFyIEZERkxBR1NfTk9OQkxPQ0sgPSAxIDw8IDI7CnZhciBGREZMQUdTX1JTWU5DID0gMSA8PCAzOwp2YXIgRkRGTEFHU19TWU5DID0gMSA8PCA0Owp2YXIgRmRzdGF0ID0gY2xhc3MgewogIHdyaXRlX2J5dGVzKHZpZXcsIHB0cikgewogICAgdmlldy5zZXRVaW50OChwdHIsIHRoaXMuZnNfZmlsZXR5cGUpOwogICAgdmlldy5zZXRVaW50MTYocHRyICsgMiwgdGhpcy5mc19mbGFncywgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA4LCB0aGlzLmZzX3JpZ2h0c19iYXNlLCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDE2LCB0aGlzLmZzX3JpZ2h0c19pbmhlcml0ZWQsIHRydWUpOwogIH0KICBjb25zdHJ1Y3RvcihmaWxldHlwZSwgZmxhZ3MpIHsKICAgIHRoaXMuZnNfcmlnaHRzX2Jhc2UgPSAwbjsKICAgIHRoaXMuZnNfcmlnaHRzX2luaGVyaXRlZCA9IDBuOwogICAgdGhpcy5mc19maWxldHlwZSA9IGZpbGV0eXBlOwogICAgdGhpcy5mc19mbGFncyA9IGZsYWdzOwogIH0KfTsKdmFyIEZTVEZMQUdTX0FUSU0gPSAxIDw8IDA7CnZhciBGU1RGTEFHU19BVElNX05PVyA9IDEgPDwgMTsKdmFyIEZTVEZMQUdTX01USU0gPSAxIDw8IDI7CnZhciBGU1RGTEFHU19NVElNX05PVyA9IDEgPDwgMzsKdmFyIE9GTEFHU19DUkVBVCA9IDEgPDwgMDsKdmFyIE9GTEFHU19ESVJFQ1RPUlkgPSAxIDw8IDE7CnZhciBPRkxBR1NfRVhDTCA9IDEgPDwgMjsKdmFyIE9GTEFHU19UUlVOQyA9IDEgPDwgMzsKdmFyIEZpbGVzdGF0ID0gY2xhc3MgewogIHdyaXRlX2J5dGVzKHZpZXcsIHB0cikgewogICAgdmlldy5zZXRCaWdVaW50NjQocHRyLCB0aGlzLmRldiwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA4LCB0aGlzLmlubywgdHJ1ZSk7CiAgICB2aWV3LnNldFVpbnQ4KHB0ciArIDE2LCB0aGlzLmZpbGV0eXBlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDI0LCB0aGlzLm5saW5rLCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDMyLCB0aGlzLnNpemUsIHRydWUpOwogICAgdmlldy5zZXRCaWdVaW50NjQocHRyICsgMzgsIHRoaXMuYXRpbSwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA0NiwgdGhpcy5tdGltLCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDUyLCB0aGlzLmN0aW0sIHRydWUpOwogIH0KICBjb25zdHJ1Y3RvcihmaWxldHlwZSwgc2l6ZSkgewogICAgdGhpcy5kZXYgPSAwbjsKICAgIHRoaXMuaW5vID0gMG47CiAgICB0aGlzLm5saW5rID0gMG47CiAgICB0aGlzLmF0aW0gPSAwbjsKICAgIHRoaXMubXRpbSA9IDBuOwogICAgdGhpcy5jdGltID0gMG47CiAgICB0aGlzLmZpbGV0eXBlID0gZmlsZXR5cGU7CiAgICB0aGlzLnNpemUgPSBzaXplOwogIH0KfTsKdmFyIEVWRU5UUldGTEFHU19GRF9SRUFEV1JJVEVfSEFOR1VQID0gMSA8PCAwOwp2YXIgU1VCQ0xPQ0tGTEFHU19TVUJTQ1JJUFRJT05fQ0xPQ0tfQUJTVElNRSA9IDEgPDwgMDsKdmFyIFJJRkxBR1NfUkVDVl9QRUVLID0gMSA8PCAwOwp2YXIgUklGTEFHU19SRUNWX1dBSVRBTEwgPSAxIDw8IDE7CnZhciBST0ZMQUdTX1JFQ1ZfREFUQV9UUlVOQ0FURUQgPSAxIDw8IDA7CnZhciBTREZMQUdTX1JEID0gMSA8PCAwOwp2YXIgU0RGTEFHU19XUiA9IDEgPDwgMTsKdmFyIFBSRU9QRU5UWVBFX0RJUiA9IDA7CnZhciBQcmVzdGF0RGlyID0gY2xhc3MgewogIHdyaXRlX2J5dGVzKHZpZXcsIHB0cikgewogICAgdmlldy5zZXRVaW50MzIocHRyLCB0aGlzLnByX25hbWUuYnl0ZUxlbmd0aCwgdHJ1ZSk7CiAgfQogIGNvbnN0cnVjdG9yKG5hbWUpIHsKICAgIHRoaXMucHJfbmFtZSA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShuYW1lKTsKICB9Cn07CnZhciBQcmVzdGF0ID0gY2xhc3MgewogIHN0YXRpYyBkaXIobmFtZSkgewogICAgY29uc3QgcHJlc3RhdCA9IG5ldyBQcmVzdGF0KCk7CiAgICBwcmVzdGF0LnRhZyA9IFBSRU9QRU5UWVBFX0RJUjsKICAgIHByZXN0YXQuaW5uZXIgPSBuZXcgUHJlc3RhdERpcihuYW1lKTsKICAgIHJldHVybiBwcmVzdGF0OwogIH0KICB3cml0ZV9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIHZpZXcuc2V0VWludDMyKHB0ciwgdGhpcy50YWcsIHRydWUpOwogICAgdGhpcy5pbm5lci53cml0ZV9ieXRlcyh2aWV3LCBwdHIgKyA0KTsKICB9Cn07CgovLyBub2RlX21vZHVsZXMvQGJqb3JuMy9icm93c2VyX3dhc2lfc2hpbS9kaXN0L2RlYnVnLmpzCnZhciBEZWJ1ZyA9IGNsYXNzIERlYnVnMiB7CiAgZW5hYmxlKGVuYWJsZWQpIHsKICAgIHRoaXMubG9nID0gY3JlYXRlTG9nZ2VyKGVuYWJsZWQgPT09IHZvaWQgMCA/IHRydWUgOiBlbmFibGVkLCB0aGlzLnByZWZpeCk7CiAgfQogIGdldCBlbmFibGVkKCkgewogICAgcmV0dXJuIHRoaXMuaXNFbmFibGVkOwogIH0KICBjb25zdHJ1Y3Rvcihpc0VuYWJsZWQpIHsKICAgIHRoaXMuaXNFbmFibGVkID0gaXNFbmFibGVkOwogICAgdGhpcy5wcmVmaXggPSAid2FzaToiOwogICAgdGhpcy5lbmFibGUoaXNFbmFibGVkKTsKICB9Cn07CmZ1bmN0aW9uIGNyZWF0ZUxvZ2dlcihlbmFibGVkLCBwcmVmaXgpIHsKICBpZiAoZW5hYmxlZCkgewogICAgY29uc3QgYSA9IGNvbnNvbGUubG9nLmJpbmQoY29uc29sZSwgIiVjJXMiLCAiY29sb3I6ICMyNjVCQTAiLCBwcmVmaXgpOwogICAgcmV0dXJuIGE7CiAgfSBlbHNlIHsKICAgIHJldHVybiAoKSA9PiB7CiAgICB9OwogIH0KfQp2YXIgZGVidWcgPSBuZXcgRGVidWcoZmFsc2UpOwoKLy8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC93YXNpLmpzCnZhciBXQVNJUHJvY0V4aXQgPSBjbGFzcyBleHRlbmRzIEVycm9yIHsKICBjb25zdHJ1Y3Rvcihjb2RlKSB7CiAgICBzdXBlcigiZXhpdCB3aXRoIGV4aXQgY29kZSAiICsgY29kZSk7CiAgICB0aGlzLmNvZGUgPSBjb2RlOwogIH0KfTsKdmFyIFdBU0kgPSBjbGFzcyBXQVNJMiB7CiAgc3RhcnQoaW5zdGFuY2UpIHsKICAgIHRoaXMuaW5zdCA9IGluc3RhbmNlOwogICAgdHJ5IHsKICAgICAgaW5zdGFuY2UuZXhwb3J0cy5fc3RhcnQoKTsKICAgICAgcmV0dXJuIDA7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIGlmIChlIGluc3RhbmNlb2YgV0FTSVByb2NFeGl0KSB7CiAgICAgICAgcmV0dXJuIGUuY29kZTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aHJvdyBlOwogICAgICB9CiAgICB9CiAgfQogIGluaXRpYWxpemUoaW5zdGFuY2UpIHsKICAgIHRoaXMuaW5zdCA9IGluc3RhbmNlOwogICAgaWYgKGluc3RhbmNlLmV4cG9ydHMuX2luaXRpYWxpemUpIHsKICAgICAgaW5zdGFuY2UuZXhwb3J0cy5faW5pdGlhbGl6ZSgpOwogICAgfQogIH0KICBjb25zdHJ1Y3RvcihhcmdzLCBlbnYsIGZkcywgb3B0aW9ucyA9IHt9KSB7CiAgICB0aGlzLmFyZ3MgPSBbXTsKICAgIHRoaXMuZW52ID0gW107CiAgICB0aGlzLmZkcyA9IFtdOwogICAgZGVidWcuZW5hYmxlKG9wdGlvbnMuZGVidWcpOwogICAgdGhpcy5hcmdzID0gYXJnczsKICAgIHRoaXMuZW52ID0gZW52OwogICAgdGhpcy5mZHMgPSBmZHM7CiAgICBjb25zdCBzZWxmID0gdGhpczsKICAgIHRoaXMud2FzaUltcG9ydCA9IHsgYXJnc19zaXplc19nZXQoYXJnYywgYXJndl9idWZfc2l6ZSkgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYXJnYywgc2VsZi5hcmdzLmxlbmd0aCwgdHJ1ZSk7CiAgICAgIGxldCBidWZfc2l6ZSA9IDA7CiAgICAgIGZvciAoY29uc3QgYXJnIG9mIHNlbGYuYXJncykgewogICAgICAgIGJ1Zl9zaXplICs9IGFyZy5sZW5ndGggKyAxOwogICAgICB9CiAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYXJndl9idWZfc2l6ZSwgYnVmX3NpemUsIHRydWUpOwogICAgICBkZWJ1Zy5sb2coYnVmZmVyLmdldFVpbnQzMihhcmdjLCB0cnVlKSwgYnVmZmVyLmdldFVpbnQzMihhcmd2X2J1Zl9zaXplLCB0cnVlKSk7CiAgICAgIHJldHVybiAwOwogICAgfSwgYXJnc19nZXQoYXJndiwgYXJndl9idWYpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IG9yaWdfYXJndl9idWYgPSBhcmd2X2J1ZjsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxmLmFyZ3MubGVuZ3RoOyBpKyspIHsKICAgICAgICBidWZmZXIuc2V0VWludDMyKGFyZ3YsIGFyZ3ZfYnVmLCB0cnVlKTsKICAgICAgICBhcmd2ICs9IDQ7CiAgICAgICAgY29uc3QgYXJnID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHNlbGYuYXJnc1tpXSk7CiAgICAgICAgYnVmZmVyOC5zZXQoYXJnLCBhcmd2X2J1Zik7CiAgICAgICAgYnVmZmVyLnNldFVpbnQ4KGFyZ3ZfYnVmICsgYXJnLmxlbmd0aCwgMCk7CiAgICAgICAgYXJndl9idWYgKz0gYXJnLmxlbmd0aCArIDE7CiAgICAgIH0KICAgICAgaWYgKGRlYnVnLmVuYWJsZWQpIHsKICAgICAgICBkZWJ1Zy5sb2cobmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG9yaWdfYXJndl9idWYsIGFyZ3ZfYnVmKSkpOwogICAgICB9CiAgICAgIHJldHVybiAwOwogICAgfSwgZW52aXJvbl9zaXplc19nZXQoZW52aXJvbl9jb3VudCwgZW52aXJvbl9zaXplKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgYnVmZmVyLnNldFVpbnQzMihlbnZpcm9uX2NvdW50LCBzZWxmLmVudi5sZW5ndGgsIHRydWUpOwogICAgICBsZXQgYnVmX3NpemUgPSAwOwogICAgICBmb3IgKGNvbnN0IGVudmlyb24gb2Ygc2VsZi5lbnYpIHsKICAgICAgICBidWZfc2l6ZSArPSBlbnZpcm9uLmxlbmd0aCArIDE7CiAgICAgIH0KICAgICAgYnVmZmVyLnNldFVpbnQzMihlbnZpcm9uX3NpemUsIGJ1Zl9zaXplLCB0cnVlKTsKICAgICAgZGVidWcubG9nKGJ1ZmZlci5nZXRVaW50MzIoZW52aXJvbl9jb3VudCwgdHJ1ZSksIGJ1ZmZlci5nZXRVaW50MzIoZW52aXJvbl9zaXplLCB0cnVlKSk7CiAgICAgIHJldHVybiAwOwogICAgfSwgZW52aXJvbl9nZXQoZW52aXJvbiwgZW52aXJvbl9idWYpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IG9yaWdfZW52aXJvbl9idWYgPSBlbnZpcm9uX2J1ZjsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxmLmVudi5sZW5ndGg7IGkrKykgewogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIoZW52aXJvbiwgZW52aXJvbl9idWYsIHRydWUpOwogICAgICAgIGVudmlyb24gKz0gNDsKICAgICAgICBjb25zdCBlID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHNlbGYuZW52W2ldKTsKICAgICAgICBidWZmZXI4LnNldChlLCBlbnZpcm9uX2J1Zik7CiAgICAgICAgYnVmZmVyLnNldFVpbnQ4KGVudmlyb25fYnVmICsgZS5sZW5ndGgsIDApOwogICAgICAgIGVudmlyb25fYnVmICs9IGUubGVuZ3RoICsgMTsKICAgICAgfQogICAgICBpZiAoZGVidWcuZW5hYmxlZCkgewogICAgICAgIGRlYnVnLmxvZyhuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2Uob3JpZ19lbnZpcm9uX2J1ZiwgZW52aXJvbl9idWYpKSk7CiAgICAgIH0KICAgICAgcmV0dXJuIDA7CiAgICB9LCBjbG9ja19yZXNfZ2V0KGlkLCByZXNfcHRyKSB7CiAgICAgIGxldCByZXNvbHV0aW9uVmFsdWU7CiAgICAgIHN3aXRjaCAoaWQpIHsKICAgICAgICBjYXNlIENMT0NLSURfTU9OT1RPTklDOiB7CiAgICAgICAgICByZXNvbHV0aW9uVmFsdWUgPSA1MDAwbjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjYXNlIENMT0NLSURfUkVBTFRJTUU6IHsKICAgICAgICAgIHJlc29sdXRpb25WYWx1ZSA9IDEwMDAwMDBuOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICByZXR1cm4gRVJSTk9fTk9TWVM7CiAgICAgIH0KICAgICAgY29uc3QgdmlldyA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgdmlldy5zZXRCaWdVaW50NjQocmVzX3B0ciwgcmVzb2x1dGlvblZhbHVlLCB0cnVlKTsKICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICB9LCBjbG9ja190aW1lX2dldChpZCwgcHJlY2lzaW9uLCB0aW1lKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKGlkID09PSBDTE9DS0lEX1JFQUxUSU1FKSB7CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NCh0aW1lLCBCaWdJbnQobmV3IERhdGUoKS5nZXRUaW1lKCkpICogMTAwMDAwMG4sIHRydWUpOwogICAgICB9IGVsc2UgaWYgKGlkID09IENMT0NLSURfTU9OT1RPTklDKSB7CiAgICAgICAgbGV0IG1vbm90b25pY190aW1lOwogICAgICAgIHRyeSB7CiAgICAgICAgICBtb25vdG9uaWNfdGltZSA9IEJpZ0ludChNYXRoLnJvdW5kKHBlcmZvcm1hbmNlLm5vdygpICogMWU2KSk7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgbW9ub3RvbmljX3RpbWUgPSAwbjsKICAgICAgICB9CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NCh0aW1lLCBtb25vdG9uaWNfdGltZSwgdHJ1ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NCh0aW1lLCAwbiwgdHJ1ZSk7CiAgICAgIH0KICAgICAgcmV0dXJuIDA7CiAgICB9LCBmZF9hZHZpc2UoZmQsIG9mZnNldCwgbGVuLCBhZHZpY2UpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfYWxsb2NhdGUoZmQsIG9mZnNldCwgbGVuKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9hbGxvY2F0ZShvZmZzZXQsIGxlbik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Nsb3NlKGZkKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcmV0ID0gc2VsZi5mZHNbZmRdLmZkX2Nsb3NlKCk7CiAgICAgICAgc2VsZi5mZHNbZmRdID0gdm9pZCAwOwogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2RhdGFzeW5jKGZkKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9zeW5jKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Zkc3RhdF9nZXQoZmQsIGZkc3RhdF9wdHIpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgZmRzdGF0IH0gPSBzZWxmLmZkc1tmZF0uZmRfZmRzdGF0X2dldCgpOwogICAgICAgIGlmIChmZHN0YXQgIT0gbnVsbCkgewogICAgICAgICAgZmRzdGF0LndyaXRlX2J5dGVzKG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKSwgZmRzdGF0X3B0cik7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Zkc3RhdF9zZXRfZmxhZ3MoZmQsIGZsYWdzKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9mZHN0YXRfc2V0X2ZsYWdzKGZsYWdzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfZmRzdGF0X3NldF9yaWdodHMoZmQsIGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZykgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfZmRzdGF0X3NldF9yaWdodHMoZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfZmlsZXN0YXRfZ2V0KGZkLCBmaWxlc3RhdF9wdHIpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgZmlsZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9maWxlc3RhdF9nZXQoKTsKICAgICAgICBpZiAoZmlsZXN0YXQgIT0gbnVsbCkgewogICAgICAgICAgZmlsZXN0YXQud3JpdGVfYnl0ZXMobmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpLCBmaWxlc3RhdF9wdHIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9maWxlc3RhdF9zZXRfc2l6ZShmZCwgc2l6ZSkgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfZmlsZXN0YXRfc2V0X3NpemUoc2l6ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2ZpbGVzdGF0X3NldF90aW1lcyhmZCwgYXRpbSwgbXRpbSwgZnN0X2ZsYWdzKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9maWxlc3RhdF9zZXRfdGltZXMoYXRpbSwgbXRpbSwgZnN0X2ZsYWdzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcHJlYWQoZmQsIGlvdnNfcHRyLCBpb3ZzX2xlbiwgb2Zmc2V0LCBucmVhZF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgaW92ZWNzID0gSW92ZWMucmVhZF9ieXRlc19hcnJheShidWZmZXIsIGlvdnNfcHRyLCBpb3ZzX2xlbik7CiAgICAgICAgbGV0IG5yZWFkID0gMDsKICAgICAgICBmb3IgKGNvbnN0IGlvdmVjIG9mIGlvdmVjcykgewogICAgICAgICAgY29uc3QgeyByZXQsIGRhdGEgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wcmVhZChpb3ZlYy5idWZfbGVuLCBvZmZzZXQpOwogICAgICAgICAgaWYgKHJldCAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobnJlYWRfcHRyLCBucmVhZCwgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgICB9CiAgICAgICAgICBidWZmZXI4LnNldChkYXRhLCBpb3ZlYy5idWYpOwogICAgICAgICAgbnJlYWQgKz0gZGF0YS5sZW5ndGg7CiAgICAgICAgICBvZmZzZXQgKz0gQmlnSW50KGRhdGEubGVuZ3RoKTsKICAgICAgICAgIGlmIChkYXRhLmxlbmd0aCAhPSBpb3ZlYy5idWZfbGVuKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgbnJlYWQsIHRydWUpOwogICAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9wcmVzdGF0X2dldChmZCwgYnVmX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIHByZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wcmVzdGF0X2dldCgpOwogICAgICAgIGlmIChwcmVzdGF0ICE9IG51bGwpIHsKICAgICAgICAgIHByZXN0YXQud3JpdGVfYnl0ZXMoYnVmZmVyLCBidWZfcHRyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcHJlc3RhdF9kaXJfbmFtZShmZCwgcGF0aF9wdHIsIHBhdGhfbGVuKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIHByZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wcmVzdGF0X2dldCgpOwogICAgICAgIGlmIChwcmVzdGF0ID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHByZXN0YXRfZGlyX25hbWUgPSBwcmVzdGF0LmlubmVyLnByX25hbWU7CiAgICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICAgIGJ1ZmZlcjguc2V0KHByZXN0YXRfZGlyX25hbWUuc2xpY2UoMCwgcGF0aF9sZW4pLCBwYXRoX3B0cik7CiAgICAgICAgcmV0dXJuIHByZXN0YXRfZGlyX25hbWUuYnl0ZUxlbmd0aCA+IHBhdGhfbGVuID8gRVJSTk9fTkFNRVRPT0xPTkcgOiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9wd3JpdGUoZmQsIGlvdnNfcHRyLCBpb3ZzX2xlbiwgb2Zmc2V0LCBud3JpdHRlbl9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgaW92ZWNzID0gQ2lvdmVjLnJlYWRfYnl0ZXNfYXJyYXkoYnVmZmVyLCBpb3ZzX3B0ciwgaW92c19sZW4pOwogICAgICAgIGxldCBud3JpdHRlbiA9IDA7CiAgICAgICAgZm9yIChjb25zdCBpb3ZlYyBvZiBpb3ZlY3MpIHsKICAgICAgICAgIGNvbnN0IGRhdGEgPSBidWZmZXI4LnNsaWNlKGlvdmVjLmJ1ZiwgaW92ZWMuYnVmICsgaW92ZWMuYnVmX2xlbik7CiAgICAgICAgICBjb25zdCB7IHJldCwgbndyaXR0ZW46IG53cml0dGVuX3BhcnQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG53cml0dGVuX3B0ciwgbndyaXR0ZW4sIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgbndyaXR0ZW4gKz0gbndyaXR0ZW5fcGFydDsKICAgICAgICAgIG9mZnNldCArPSBCaWdJbnQobndyaXR0ZW5fcGFydCk7CiAgICAgICAgICBpZiAobndyaXR0ZW5fcGFydCAhPSBkYXRhLmJ5dGVMZW5ndGgpIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobndyaXR0ZW5fcHRyLCBud3JpdHRlbiwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3JlYWQoZmQsIGlvdnNfcHRyLCBpb3ZzX2xlbiwgbnJlYWRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IGlvdmVjcyA9IElvdmVjLnJlYWRfYnl0ZXNfYXJyYXkoYnVmZmVyLCBpb3ZzX3B0ciwgaW92c19sZW4pOwogICAgICAgIGxldCBucmVhZCA9IDA7CiAgICAgICAgZm9yIChjb25zdCBpb3ZlYyBvZiBpb3ZlY3MpIHsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBkYXRhIH0gPSBzZWxmLmZkc1tmZF0uZmRfcmVhZChpb3ZlYy5idWZfbGVuKTsKICAgICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgbnJlYWQsIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgYnVmZmVyOC5zZXQoZGF0YSwgaW92ZWMuYnVmKTsKICAgICAgICAgIG5yZWFkICs9IGRhdGEubGVuZ3RoOwogICAgICAgICAgaWYgKGRhdGEubGVuZ3RoICE9IGlvdmVjLmJ1Zl9sZW4pIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobnJlYWRfcHRyLCBucmVhZCwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3JlYWRkaXIoZmQsIGJ1ZiwgYnVmX2xlbiwgY29va2llLCBidWZ1c2VkX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBsZXQgYnVmdXNlZCA9IDA7CiAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBkaXJlbnQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9yZWFkZGlyX3NpbmdsZShjb29raWUpOwogICAgICAgICAgaWYgKHJldCAhPSAwKSB7CiAgICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYnVmdXNlZF9wdHIsIGJ1ZnVzZWQsIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgaWYgKGRpcmVudCA9PSBudWxsKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGJ1Zl9sZW4gLSBidWZ1c2VkIDwgZGlyZW50LmhlYWRfbGVuZ3RoKCkpIHsKICAgICAgICAgICAgYnVmdXNlZCA9IGJ1Zl9sZW47CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgaGVhZF9ieXRlcyA9IG5ldyBBcnJheUJ1ZmZlcihkaXJlbnQuaGVhZF9sZW5ndGgoKSk7CiAgICAgICAgICBkaXJlbnQud3JpdGVfaGVhZF9ieXRlcyhuZXcgRGF0YVZpZXcoaGVhZF9ieXRlcyksIDApOwogICAgICAgICAgYnVmZmVyOC5zZXQobmV3IFVpbnQ4QXJyYXkoaGVhZF9ieXRlcykuc2xpY2UoMCwgTWF0aC5taW4oaGVhZF9ieXRlcy5ieXRlTGVuZ3RoLCBidWZfbGVuIC0gYnVmdXNlZCkpLCBidWYpOwogICAgICAgICAgYnVmICs9IGRpcmVudC5oZWFkX2xlbmd0aCgpOwogICAgICAgICAgYnVmdXNlZCArPSBkaXJlbnQuaGVhZF9sZW5ndGgoKTsKICAgICAgICAgIGlmIChidWZfbGVuIC0gYnVmdXNlZCA8IGRpcmVudC5uYW1lX2xlbmd0aCgpKSB7CiAgICAgICAgICAgIGJ1ZnVzZWQgPSBidWZfbGVuOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGRpcmVudC53cml0ZV9uYW1lX2J5dGVzKGJ1ZmZlcjgsIGJ1ZiwgYnVmX2xlbiAtIGJ1ZnVzZWQpOwogICAgICAgICAgYnVmICs9IGRpcmVudC5uYW1lX2xlbmd0aCgpOwogICAgICAgICAgYnVmdXNlZCArPSBkaXJlbnQubmFtZV9sZW5ndGgoKTsKICAgICAgICAgIGNvb2tpZSA9IGRpcmVudC5kX25leHQ7CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYnVmdXNlZF9wdHIsIGJ1ZnVzZWQsIHRydWUpOwogICAgICAgIHJldHVybiAwOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9yZW51bWJlcihmZCwgdG8pIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDAgJiYgc2VsZi5mZHNbdG9dICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHJldCA9IHNlbGYuZmRzW3RvXS5mZF9jbG9zZSgpOwogICAgICAgIGlmIChyZXQgIT0gMCkgewogICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICB9CiAgICAgICAgc2VsZi5mZHNbdG9dID0gc2VsZi5mZHNbZmRdOwogICAgICAgIHNlbGYuZmRzW2ZkXSA9IHZvaWQgMDsKICAgICAgICByZXR1cm4gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfc2VlayhmZCwgb2Zmc2V0LCB3aGVuY2UsIG9mZnNldF9vdXRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgb2Zmc2V0OiBvZmZzZXRfb3V0IH0gPSBzZWxmLmZkc1tmZF0uZmRfc2VlayhvZmZzZXQsIHdoZW5jZSk7CiAgICAgICAgYnVmZmVyLnNldEJpZ0ludDY0KG9mZnNldF9vdXRfcHRyLCBvZmZzZXRfb3V0LCB0cnVlKTsKICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9zeW5jKGZkKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9zeW5jKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3RlbGwoZmQsIG9mZnNldF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHsgcmV0LCBvZmZzZXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF90ZWxsKCk7CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NChvZmZzZXRfcHRyLCBvZmZzZXQsIHRydWUpOwogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3dyaXRlKGZkLCBpb3ZzX3B0ciwgaW92c19sZW4sIG53cml0dGVuX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBpb3ZlY3MgPSBDaW92ZWMucmVhZF9ieXRlc19hcnJheShidWZmZXIsIGlvdnNfcHRyLCBpb3ZzX2xlbik7CiAgICAgICAgbGV0IG53cml0dGVuID0gMDsKICAgICAgICBmb3IgKGNvbnN0IGlvdmVjIG9mIGlvdmVjcykgewogICAgICAgICAgY29uc3QgZGF0YSA9IGJ1ZmZlcjguc2xpY2UoaW92ZWMuYnVmLCBpb3ZlYy5idWYgKyBpb3ZlYy5idWZfbGVuKTsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBud3JpdHRlbjogbndyaXR0ZW5fcGFydCB9ID0gc2VsZi5mZHNbZmRdLmZkX3dyaXRlKGRhdGEpOwogICAgICAgICAgaWYgKHJldCAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobndyaXR0ZW5fcHRyLCBud3JpdHRlbiwgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgICB9CiAgICAgICAgICBud3JpdHRlbiArPSBud3JpdHRlbl9wYXJ0OwogICAgICAgICAgaWYgKG53cml0dGVuX3BhcnQgIT0gZGF0YS5ieXRlTGVuZ3RoKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKG53cml0dGVuX3B0ciwgbndyaXR0ZW4sIHRydWUpOwogICAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX2NyZWF0ZV9kaXJlY3RvcnkoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0ucGF0aF9jcmVhdGVfZGlyZWN0b3J5KHBhdGgpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX2ZpbGVzdGF0X2dldChmZCwgZmxhZ3MsIHBhdGhfcHRyLCBwYXRoX2xlbiwgZmlsZXN0YXRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICBjb25zdCB7IHJldCwgZmlsZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5wYXRoX2ZpbGVzdGF0X2dldChmbGFncywgcGF0aCk7CiAgICAgICAgaWYgKGZpbGVzdGF0ICE9IG51bGwpIHsKICAgICAgICAgIGZpbGVzdGF0LndyaXRlX2J5dGVzKGJ1ZmZlciwgZmlsZXN0YXRfcHRyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9maWxlc3RhdF9zZXRfdGltZXMoZmQsIGZsYWdzLCBwYXRoX3B0ciwgcGF0aF9sZW4sIGF0aW0sIG10aW0sIGZzdF9mbGFncykgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0ucGF0aF9maWxlc3RhdF9zZXRfdGltZXMoZmxhZ3MsIHBhdGgsIGF0aW0sIG10aW0sIGZzdF9mbGFncyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfbGluayhvbGRfZmQsIG9sZF9mbGFncywgb2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9sZW4sIG5ld19mZCwgbmV3X3BhdGhfcHRyLCBuZXdfcGF0aF9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbb2xkX2ZkXSAhPSB2b2lkIDAgJiYgc2VsZi5mZHNbbmV3X2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBvbGRfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX3B0ciArIG9sZF9wYXRoX2xlbikpOwogICAgICAgIGNvbnN0IG5ld19wYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfcHRyICsgbmV3X3BhdGhfbGVuKSk7CiAgICAgICAgY29uc3QgeyByZXQsIGlub2RlX29iaiB9ID0gc2VsZi5mZHNbb2xkX2ZkXS5wYXRoX2xvb2t1cChvbGRfcGF0aCwgb2xkX2ZsYWdzKTsKICAgICAgICBpZiAoaW5vZGVfb2JqID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzZWxmLmZkc1tuZXdfZmRdLnBhdGhfbGluayhuZXdfcGF0aCwgaW5vZGVfb2JqLCBmYWxzZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfb3BlbihmZCwgZGlyZmxhZ3MsIHBhdGhfcHRyLCBwYXRoX2xlbiwgb2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcsIGZkX2ZsYWdzLCBvcGVuZWRfZmRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICBkZWJ1Zy5sb2cocGF0aCk7CiAgICAgICAgY29uc3QgeyByZXQsIGZkX29iaiB9ID0gc2VsZi5mZHNbZmRdLnBhdGhfb3BlbihkaXJmbGFncywgcGF0aCwgb2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcsIGZkX2ZsYWdzKTsKICAgICAgICBpZiAocmV0ICE9IDApIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIHNlbGYuZmRzLnB1c2goZmRfb2JqKTsKICAgICAgICBjb25zdCBvcGVuZWRfZmQgPSBzZWxmLmZkcy5sZW5ndGggLSAxOwogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIob3BlbmVkX2ZkX3B0ciwgb3BlbmVkX2ZkLCB0cnVlKTsKICAgICAgICByZXR1cm4gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9yZWFkbGluayhmZCwgcGF0aF9wdHIsIHBhdGhfbGVuLCBidWZfcHRyLCBidWZfbGVuLCBucmVhZF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIGRlYnVnLmxvZyhwYXRoKTsKICAgICAgICBjb25zdCB7IHJldCwgZGF0YSB9ID0gc2VsZi5mZHNbZmRdLnBhdGhfcmVhZGxpbmsocGF0aCk7CiAgICAgICAgaWYgKGRhdGEgIT0gbnVsbCkgewogICAgICAgICAgY29uc3QgZGF0YV9idWYgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoZGF0YSk7CiAgICAgICAgICBpZiAoZGF0YV9idWYubGVuZ3RoID4gYnVmX2xlbikgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgMCwgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICAgICAgfQogICAgICAgICAgYnVmZmVyOC5zZXQoZGF0YV9idWYsIGJ1Zl9wdHIpOwogICAgICAgICAgYnVmZmVyLnNldFVpbnQzMihucmVhZF9wdHIsIGRhdGFfYnVmLmxlbmd0aCwgdHJ1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfcmVtb3ZlX2RpcmVjdG9yeShmZCwgcGF0aF9wdHIsIHBhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBwYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5wYXRoX3JlbW92ZV9kaXJlY3RvcnkocGF0aCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfcmVuYW1lKGZkLCBvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX2xlbiwgbmV3X2ZkLCBuZXdfcGF0aF9wdHIsIG5ld19wYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwICYmIHNlbGYuZmRzW25ld19mZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3Qgb2xkX3BhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2Uob2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9wdHIgKyBvbGRfcGF0aF9sZW4pKTsKICAgICAgICBjb25zdCBuZXdfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShuZXdfcGF0aF9wdHIsIG5ld19wYXRoX3B0ciArIG5ld19wYXRoX2xlbikpOwogICAgICAgIGxldCB7IHJldCwgaW5vZGVfb2JqIH0gPSBzZWxmLmZkc1tmZF0ucGF0aF91bmxpbmsob2xkX3BhdGgpOwogICAgICAgIGlmIChpbm9kZV9vYmogPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICB9CiAgICAgICAgcmV0ID0gc2VsZi5mZHNbbmV3X2ZkXS5wYXRoX2xpbmsobmV3X3BhdGgsIGlub2RlX29iaiwgdHJ1ZSk7CiAgICAgICAgaWYgKHJldCAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICBpZiAoc2VsZi5mZHNbZmRdLnBhdGhfbGluayhvbGRfcGF0aCwgaW5vZGVfb2JqLCB0cnVlKSAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICAgIHRocm93ICJwYXRoX2xpbmsgc2hvdWxkIGFsd2F5cyByZXR1cm4gc3VjY2VzcyB3aGVuIHJlbGlua2luZyBhbiBpbm9kZSBiYWNrIHRvIHRoZSBvcmlnaW5hbCBwbGFjZSI7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfc3ltbGluayhvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX2xlbiwgZmQsIG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBvbGRfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX3B0ciArIG9sZF9wYXRoX2xlbikpOwogICAgICAgIGNvbnN0IG5ld19wYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfcHRyICsgbmV3X3BhdGhfbGVuKSk7CiAgICAgICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF91bmxpbmtfZmlsZShmZCwgcGF0aF9wdHIsIHBhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBwYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5wYXRoX3VubGlua19maWxlKHBhdGgpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwb2xsX29uZW9mZihpbl8sIG91dCwgbnN1YnNjcmlwdGlvbnMpIHsKICAgICAgdGhyb3cgImFzeW5jIGlvIG5vdCBzdXBwb3J0ZWQiOwogICAgfSwgcHJvY19leGl0KGV4aXRfY29kZSkgewogICAgICB0aHJvdyBuZXcgV0FTSVByb2NFeGl0KGV4aXRfY29kZSk7CiAgICB9LCBwcm9jX3JhaXNlKHNpZykgewogICAgICB0aHJvdyAicmFpc2VkIHNpZ25hbCAiICsgc2lnOwogICAgfSwgc2NoZWRfeWllbGQoKSB7CiAgICB9LCByYW5kb21fZ2V0KGJ1ZiwgYnVmX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnVmX2xlbjsgaSsrKSB7CiAgICAgICAgYnVmZmVyOFtidWYgKyBpXSA9IE1hdGgucmFuZG9tKCkgKiAyNTYgfCAwOwogICAgICB9CiAgICB9LCBzb2NrX3JlY3YoZmQsIHJpX2RhdGEsIHJpX2ZsYWdzKSB7CiAgICAgIHRocm93ICJzb2NrZXRzIG5vdCBzdXBwb3J0ZWQiOwogICAgfSwgc29ja19zZW5kKGZkLCBzaV9kYXRhLCBzaV9mbGFncykgewogICAgICB0aHJvdyAic29ja2V0cyBub3Qgc3VwcG9ydGVkIjsKICAgIH0sIHNvY2tfc2h1dGRvd24oZmQsIGhvdykgewogICAgICB0aHJvdyAic29ja2V0cyBub3Qgc3VwcG9ydGVkIjsKICAgIH0sIHNvY2tfYWNjZXB0KGZkLCBmbGFncykgewogICAgICB0aHJvdyAic29ja2V0cyBub3Qgc3VwcG9ydGVkIjsKICAgIH0gfTsKICB9Cn07CgovLyBub2RlX21vZHVsZXMvQGJqb3JuMy9icm93c2VyX3dhc2lfc2hpbS9kaXN0L2ZkLmpzCnZhciBGZCA9IGNsYXNzIHsKICBmZF9hbGxvY2F0ZShvZmZzZXQsIGxlbikgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfY2xvc2UoKSB7CiAgICByZXR1cm4gMDsKICB9CiAgZmRfZmRzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBmZHN0YXQ6IG51bGwgfTsKICB9CiAgZmRfZmRzdGF0X3NldF9mbGFncyhmbGFncykgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfZmRzdGF0X3NldF9yaWdodHMoZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nKSB7CiAgICByZXR1cm4gRVJSTk9fTk9UU1VQOwogIH0KICBmZF9maWxlc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZmlsZXN0YXQ6IG51bGwgfTsKICB9CiAgZmRfZmlsZXN0YXRfc2V0X3NpemUoc2l6ZSkgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfZmlsZXN0YXRfc2V0X3RpbWVzKGF0aW0sIG10aW0sIGZzdF9mbGFncykgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfcHJlYWQoc2l6ZSwgb2Zmc2V0KSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZGF0YTogbmV3IFVpbnQ4QXJyYXkoKSB9OwogIH0KICBmZF9wcmVzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBwcmVzdGF0OiBudWxsIH07CiAgfQogIGZkX3B3cml0ZShkYXRhLCBvZmZzZXQpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBud3JpdHRlbjogMCB9OwogIH0KICBmZF9yZWFkKHNpemUpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBkYXRhOiBuZXcgVWludDhBcnJheSgpIH07CiAgfQogIGZkX3JlYWRkaXJfc2luZ2xlKGNvb2tpZSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGRpcmVudDogbnVsbCB9OwogIH0KICBmZF9zZWVrKG9mZnNldCwgd2hlbmNlKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgb2Zmc2V0OiAwbiB9OwogIH0KICBmZF9zeW5jKCkgewogICAgcmV0dXJuIDA7CiAgfQogIGZkX3RlbGwoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgb2Zmc2V0OiAwbiB9OwogIH0KICBmZF93cml0ZShkYXRhKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgbndyaXR0ZW46IDAgfTsKICB9CiAgcGF0aF9jcmVhdGVfZGlyZWN0b3J5KHBhdGgpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfZmlsZXN0YXRfZ2V0KGZsYWdzLCBwYXRoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZmlsZXN0YXQ6IG51bGwgfTsKICB9CiAgcGF0aF9maWxlc3RhdF9zZXRfdGltZXMoZmxhZ3MsIHBhdGgsIGF0aW0sIG10aW0sIGZzdF9mbGFncykgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgcGF0aF9saW5rKHBhdGgsIGlub2RlLCBhbGxvd19kaXIpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfdW5saW5rKHBhdGgpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBpbm9kZV9vYmo6IG51bGwgfTsKICB9CiAgcGF0aF9sb29rdXAocGF0aCwgZGlyZmxhZ3MpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBpbm9kZV9vYmo6IG51bGwgfTsKICB9CiAgcGF0aF9vcGVuKGRpcmZsYWdzLCBwYXRoLCBvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZywgZmRfZmxhZ3MpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9URElSLCBmZF9vYmo6IG51bGwgfTsKICB9CiAgcGF0aF9yZWFkbGluayhwYXRoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZGF0YTogbnVsbCB9OwogIH0KICBwYXRoX3JlbW92ZV9kaXJlY3RvcnkocGF0aCkgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgcGF0aF9yZW5hbWUob2xkX3BhdGgsIG5ld19mZCwgbmV3X3BhdGgpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfdW5saW5rX2ZpbGUocGF0aCkgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9Cn07CnZhciBJbm9kZSA9IGNsYXNzIHsKfTsKCi8vIG5vZGVfbW9kdWxlcy9AYmpvcm4zL2Jyb3dzZXJfd2FzaV9zaGltL2Rpc3QvZnNfbWVtLmpzCnZhciBPcGVuRmlsZSA9IGNsYXNzIGV4dGVuZHMgRmQgewogIGZkX2FsbG9jYXRlKG9mZnNldCwgbGVuKSB7CiAgICBpZiAodGhpcy5maWxlLnNpemUgPiBvZmZzZXQgKyBsZW4pIHsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IG5ld19kYXRhID0gbmV3IFVpbnQ4QXJyYXkoTnVtYmVyKG9mZnNldCArIGxlbikpOwogICAgICBuZXdfZGF0YS5zZXQodGhpcy5maWxlLmRhdGEsIDApOwogICAgICB0aGlzLmZpbGUuZGF0YSA9IG5ld19kYXRhOwogICAgfQogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIGZkX2Zkc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIGZkc3RhdDogbmV3IEZkc3RhdChGSUxFVFlQRV9SRUdVTEFSX0ZJTEUsIDApIH07CiAgfQogIGZkX2ZpbGVzdGF0X3NldF9zaXplKHNpemUpIHsKICAgIGlmICh0aGlzLmZpbGUuc2l6ZSA+IHNpemUpIHsKICAgICAgdGhpcy5maWxlLmRhdGEgPSBuZXcgVWludDhBcnJheSh0aGlzLmZpbGUuZGF0YS5idWZmZXIuc2xpY2UoMCwgTnVtYmVyKHNpemUpKSk7CiAgICB9IGVsc2UgewogICAgICBjb25zdCBuZXdfZGF0YSA9IG5ldyBVaW50OEFycmF5KE51bWJlcihzaXplKSk7CiAgICAgIG5ld19kYXRhLnNldCh0aGlzLmZpbGUuZGF0YSwgMCk7CiAgICAgIHRoaXMuZmlsZS5kYXRhID0gbmV3X2RhdGE7CiAgICB9CiAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICB9CiAgZmRfcmVhZChzaXplKSB7CiAgICBjb25zdCBzbGljZSA9IHRoaXMuZmlsZS5kYXRhLnNsaWNlKE51bWJlcih0aGlzLmZpbGVfcG9zKSwgTnVtYmVyKHRoaXMuZmlsZV9wb3MgKyBCaWdJbnQoc2l6ZSkpKTsKICAgIHRoaXMuZmlsZV9wb3MgKz0gQmlnSW50KHNsaWNlLmxlbmd0aCk7CiAgICByZXR1cm4geyByZXQ6IDAsIGRhdGE6IHNsaWNlIH07CiAgfQogIGZkX3ByZWFkKHNpemUsIG9mZnNldCkgewogICAgY29uc3Qgc2xpY2UgPSB0aGlzLmZpbGUuZGF0YS5zbGljZShOdW1iZXIob2Zmc2V0KSwgTnVtYmVyKG9mZnNldCArIEJpZ0ludChzaXplKSkpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBkYXRhOiBzbGljZSB9OwogIH0KICBmZF9zZWVrKG9mZnNldCwgd2hlbmNlKSB7CiAgICBsZXQgY2FsY3VsYXRlZF9vZmZzZXQ7CiAgICBzd2l0Y2ggKHdoZW5jZSkgewogICAgICBjYXNlIFdIRU5DRV9TRVQ6CiAgICAgICAgY2FsY3VsYXRlZF9vZmZzZXQgPSBvZmZzZXQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgV0hFTkNFX0NVUjoKICAgICAgICBjYWxjdWxhdGVkX29mZnNldCA9IHRoaXMuZmlsZV9wb3MgKyBvZmZzZXQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgV0hFTkNFX0VORDoKICAgICAgICBjYWxjdWxhdGVkX29mZnNldCA9IEJpZ0ludCh0aGlzLmZpbGUuZGF0YS5ieXRlTGVuZ3RoKSArIG9mZnNldDsKICAgICAgICBicmVhazsKICAgICAgZGVmYXVsdDoKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0lOVkFMLCBvZmZzZXQ6IDBuIH07CiAgICB9CiAgICBpZiAoY2FsY3VsYXRlZF9vZmZzZXQgPCAwKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fSU5WQUwsIG9mZnNldDogMG4gfTsKICAgIH0KICAgIHRoaXMuZmlsZV9wb3MgPSBjYWxjdWxhdGVkX29mZnNldDsKICAgIHJldHVybiB7IHJldDogMCwgb2Zmc2V0OiB0aGlzLmZpbGVfcG9zIH07CiAgfQogIGZkX3RlbGwoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIG9mZnNldDogdGhpcy5maWxlX3BvcyB9OwogIH0KICBmZF93cml0ZShkYXRhKSB7CiAgICBpZiAodGhpcy5maWxlLnJlYWRvbmx5KQogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG53cml0dGVuOiAwIH07CiAgICBpZiAodGhpcy5maWxlX3BvcyArIEJpZ0ludChkYXRhLmJ5dGVMZW5ndGgpID4gdGhpcy5maWxlLnNpemUpIHsKICAgICAgY29uc3Qgb2xkID0gdGhpcy5maWxlLmRhdGE7CiAgICAgIHRoaXMuZmlsZS5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoTnVtYmVyKHRoaXMuZmlsZV9wb3MgKyBCaWdJbnQoZGF0YS5ieXRlTGVuZ3RoKSkpOwogICAgICB0aGlzLmZpbGUuZGF0YS5zZXQob2xkKTsKICAgIH0KICAgIHRoaXMuZmlsZS5kYXRhLnNldChkYXRhLCBOdW1iZXIodGhpcy5maWxlX3BvcykpOwogICAgdGhpcy5maWxlX3BvcyArPSBCaWdJbnQoZGF0YS5ieXRlTGVuZ3RoKTsKICAgIHJldHVybiB7IHJldDogMCwgbndyaXR0ZW46IGRhdGEuYnl0ZUxlbmd0aCB9OwogIH0KICBmZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KSB7CiAgICBpZiAodGhpcy5maWxlLnJlYWRvbmx5KQogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG53cml0dGVuOiAwIH07CiAgICBpZiAob2Zmc2V0ICsgQmlnSW50KGRhdGEuYnl0ZUxlbmd0aCkgPiB0aGlzLmZpbGUuc2l6ZSkgewogICAgICBjb25zdCBvbGQgPSB0aGlzLmZpbGUuZGF0YTsKICAgICAgdGhpcy5maWxlLmRhdGEgPSBuZXcgVWludDhBcnJheShOdW1iZXIob2Zmc2V0ICsgQmlnSW50KGRhdGEuYnl0ZUxlbmd0aCkpKTsKICAgICAgdGhpcy5maWxlLmRhdGEuc2V0KG9sZCk7CiAgICB9CiAgICB0aGlzLmZpbGUuZGF0YS5zZXQoZGF0YSwgTnVtYmVyKG9mZnNldCkpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBud3JpdHRlbjogZGF0YS5ieXRlTGVuZ3RoIH07CiAgfQogIGZkX2ZpbGVzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgZmlsZXN0YXQ6IHRoaXMuZmlsZS5zdGF0KCkgfTsKICB9CiAgY29uc3RydWN0b3IoZmlsZSkgewogICAgc3VwZXIoKTsKICAgIHRoaXMuZmlsZV9wb3MgPSAwbjsKICAgIHRoaXMuZmlsZSA9IGZpbGU7CiAgfQp9Owp2YXIgT3BlbkRpcmVjdG9yeSA9IGNsYXNzIGV4dGVuZHMgRmQgewogIGZkX3NlZWsob2Zmc2V0LCB3aGVuY2UpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fQkFERiwgb2Zmc2V0OiAwbiB9OwogIH0KICBmZF90ZWxsKCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBvZmZzZXQ6IDBuIH07CiAgfQogIGZkX2FsbG9jYXRlKG9mZnNldCwgbGVuKSB7CiAgICByZXR1cm4gRVJSTk9fQkFERjsKICB9CiAgZmRfZmRzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgZmRzdGF0OiBuZXcgRmRzdGF0KEZJTEVUWVBFX0RJUkVDVE9SWSwgMCkgfTsKICB9CiAgZmRfcmVhZGRpcl9zaW5nbGUoY29va2llKSB7CiAgICBpZiAoZGVidWcuZW5hYmxlZCkgewogICAgICBkZWJ1Zy5sb2coInJlYWRkaXJfc2luZ2xlIiwgY29va2llKTsKICAgICAgZGVidWcubG9nKGNvb2tpZSwgdGhpcy5kaXIuY29udGVudHMua2V5cygpKTsKICAgIH0KICAgIGlmIChjb29raWUgPT0gMG4pIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBkaXJlbnQ6IG5ldyBEaXJlbnQoMW4sICIuIiwgRklMRVRZUEVfRElSRUNUT1JZKSB9OwogICAgfSBlbHNlIGlmIChjb29raWUgPT0gMW4pIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBkaXJlbnQ6IG5ldyBEaXJlbnQoMm4sICIuLiIsIEZJTEVUWVBFX0RJUkVDVE9SWSkgfTsKICAgIH0KICAgIGlmIChjb29raWUgPj0gQmlnSW50KHRoaXMuZGlyLmNvbnRlbnRzLnNpemUpICsgMm4pIHsKICAgICAgcmV0dXJuIHsgcmV0OiAwLCBkaXJlbnQ6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IFtuYW1lLCBlbnRyeV0gPSBBcnJheS5mcm9tKHRoaXMuZGlyLmNvbnRlbnRzLmVudHJpZXMoKSlbTnVtYmVyKGNvb2tpZSAtIDJuKV07CiAgICByZXR1cm4geyByZXQ6IDAsIGRpcmVudDogbmV3IERpcmVudChjb29raWUgKyAxbiwgbmFtZSwgZW50cnkuc3RhdCgpLmZpbGV0eXBlKSB9OwogIH0KICBwYXRoX2ZpbGVzdGF0X2dldChmbGFncywgcGF0aF9zdHIpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX2VyciwgcGF0aCB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXRoX2VyciwgZmlsZXN0YXQ6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0LCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgpOwogICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0LCBmaWxlc3RhdDogbnVsbCB9OwogICAgfQogICAgcmV0dXJuIHsgcmV0OiAwLCBmaWxlc3RhdDogZW50cnkuc3RhdCgpIH07CiAgfQogIHBhdGhfbG9va3VwKHBhdGhfc3RyLCBkaXJmbGFncykgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhdGhfcmV0LCBpbm9kZV9vYmo6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0LCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgpOwogICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0LCBpbm9kZV9vYmo6IG51bGwgfTsKICAgIH0KICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgaW5vZGVfb2JqOiBlbnRyeSB9OwogIH0KICBwYXRoX29wZW4oZGlyZmxhZ3MsIHBhdGhfc3RyLCBvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZywgZmRfZmxhZ3MpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX3JldCwgcGF0aCB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXRoX3JldCwgZmRfb2JqOiBudWxsIH07CiAgICB9CiAgICBsZXQgeyByZXQsIGVudHJ5IH0gPSB0aGlzLmRpci5nZXRfZW50cnlfZm9yX3BhdGgocGF0aCk7CiAgICBpZiAoZW50cnkgPT0gbnVsbCkgewogICAgICBpZiAocmV0ICE9IEVSUk5PX05PRU5UKSB7CiAgICAgICAgcmV0dXJuIHsgcmV0LCBmZF9vYmo6IG51bGwgfTsKICAgICAgfQogICAgICBpZiAoKG9mbGFncyAmIE9GTEFHU19DUkVBVCkgPT0gT0ZMQUdTX0NSRUFUKSB7CiAgICAgICAgY29uc3QgeyByZXQ6IHJldDIsIGVudHJ5OiBuZXdfZW50cnkgfSA9IHRoaXMuZGlyLmNyZWF0ZV9lbnRyeV9mb3JfcGF0aChwYXRoX3N0ciwgKG9mbGFncyAmIE9GTEFHU19ESVJFQ1RPUlkpID09IE9GTEFHU19ESVJFQ1RPUlkpOwogICAgICAgIGlmIChuZXdfZW50cnkgPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHsgcmV0OiByZXQyLCBmZF9vYmo6IG51bGwgfTsKICAgICAgICB9CiAgICAgICAgZW50cnkgPSBuZXdfZW50cnk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT0VOVCwgZmRfb2JqOiBudWxsIH07CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoKG9mbGFncyAmIE9GTEFHU19FWENMKSA9PSBPRkxBR1NfRVhDTCkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0VYSVNULCBmZF9vYmo6IG51bGwgfTsKICAgIH0KICAgIGlmICgob2ZsYWdzICYgT0ZMQUdTX0RJUkVDVE9SWSkgPT0gT0ZMQUdTX0RJUkVDVE9SWSAmJiBlbnRyeS5zdGF0KCkuZmlsZXR5cGUgIT09IEZJTEVUWVBFX0RJUkVDVE9SWSkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgZmRfb2JqOiBudWxsIH07CiAgICB9CiAgICByZXR1cm4gZW50cnkucGF0aF9vcGVuKG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZkX2ZsYWdzKTsKICB9CiAgcGF0aF9jcmVhdGVfZGlyZWN0b3J5KHBhdGgpIHsKICAgIHJldHVybiB0aGlzLnBhdGhfb3BlbigwLCBwYXRoLCBPRkxBR1NfQ1JFQVQgfCBPRkxBR1NfRElSRUNUT1JZLCAwbiwgMG4sIDApLnJldDsKICB9CiAgcGF0aF9saW5rKHBhdGhfc3RyLCBpbm9kZSwgYWxsb3dfZGlyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXRoX3JldDsKICAgIH0KICAgIGlmIChwYXRoLmlzX2RpcikgewogICAgICByZXR1cm4gRVJSTk9fTk9FTlQ7CiAgICB9CiAgICBjb25zdCB7IHJldDogcGFyZW50X3JldCwgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9wYXJlbnRfZGlyX2FuZF9lbnRyeV9mb3JfcGF0aChwYXRoLCB0cnVlKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCB8fCBmaWxlbmFtZSA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXJlbnRfcmV0OwogICAgfQogICAgaWYgKGVudHJ5ICE9IG51bGwpIHsKICAgICAgY29uc3Qgc291cmNlX2lzX2RpciA9IGlub2RlLnN0YXQoKS5maWxldHlwZSA9PSBGSUxFVFlQRV9ESVJFQ1RPUlk7CiAgICAgIGNvbnN0IHRhcmdldF9pc19kaXIgPSBlbnRyeS5zdGF0KCkuZmlsZXR5cGUgPT0gRklMRVRZUEVfRElSRUNUT1JZOwogICAgICBpZiAoc291cmNlX2lzX2RpciAmJiB0YXJnZXRfaXNfZGlyKSB7CiAgICAgICAgaWYgKGFsbG93X2RpciAmJiBlbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkgewogICAgICAgICAgaWYgKGVudHJ5LmNvbnRlbnRzLnNpemUgPT0gMCkgewogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIEVSUk5PX05PVEVNUFRZOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gRVJSTk9fRVhJU1Q7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKHNvdXJjZV9pc19kaXIgJiYgIXRhcmdldF9pc19kaXIpIHsKICAgICAgICByZXR1cm4gRVJSTk9fTk9URElSOwogICAgICB9IGVsc2UgaWYgKCFzb3VyY2VfaXNfZGlyICYmIHRhcmdldF9pc19kaXIpIHsKICAgICAgICByZXR1cm4gRVJSTk9fSVNESVI7CiAgICAgIH0gZWxzZSBpZiAoaW5vZGUuc3RhdCgpLmZpbGV0eXBlID09IEZJTEVUWVBFX1JFR1VMQVJfRklMRSAmJiBlbnRyeS5zdGF0KCkuZmlsZXR5cGUgPT0gRklMRVRZUEVfUkVHVUxBUl9GSUxFKSB7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0VYSVNUOwogICAgICB9CiAgICB9CiAgICBpZiAoIWFsbG93X2RpciAmJiBpbm9kZS5zdGF0KCkuZmlsZXR5cGUgPT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgIHJldHVybiBFUlJOT19QRVJNOwogICAgfQogICAgcGFyZW50X2VudHJ5LmNvbnRlbnRzLnNldChmaWxlbmFtZSwgaW5vZGUpOwogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIHBhdGhfdW5saW5rKHBhdGhfc3RyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogcGF0aF9yZXQsIGlub2RlX29iajogbnVsbCB9OwogICAgfQogICAgY29uc3QgeyByZXQ6IHBhcmVudF9yZXQsIHBhcmVudF9lbnRyeSwgZmlsZW5hbWUsIGVudHJ5IH0gPSB0aGlzLmRpci5nZXRfcGFyZW50X2Rpcl9hbmRfZW50cnlfZm9yX3BhdGgocGF0aCwgdHJ1ZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhcmVudF9yZXQsIGlub2RlX29iajogbnVsbCB9OwogICAgfQogICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT0VOVCwgaW5vZGVfb2JqOiBudWxsIH07CiAgICB9CiAgICBwYXJlbnRfZW50cnkuY29udGVudHMuZGVsZXRlKGZpbGVuYW1lKTsKICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgaW5vZGVfb2JqOiBlbnRyeSB9OwogIH0KICBwYXRoX3VubGlua19maWxlKHBhdGhfc3RyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXRoX3JldDsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBwYXJlbnRfcmV0LCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIGZhbHNlKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCB8fCBmaWxlbmFtZSA9PSBudWxsIHx8IGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHBhcmVudF9yZXQ7CiAgICB9CiAgICBpZiAoZW50cnkuc3RhdCgpLmZpbGV0eXBlID09PSBGSUxFVFlQRV9ESVJFQ1RPUlkpIHsKICAgICAgcmV0dXJuIEVSUk5PX0lTRElSOwogICAgfQogICAgcGFyZW50X2VudHJ5LmNvbnRlbnRzLmRlbGV0ZShmaWxlbmFtZSk7CiAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICB9CiAgcGF0aF9yZW1vdmVfZGlyZWN0b3J5KHBhdGhfc3RyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXRoX3JldDsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBwYXJlbnRfcmV0LCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIGZhbHNlKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCB8fCBmaWxlbmFtZSA9PSBudWxsIHx8IGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHBhcmVudF9yZXQ7CiAgICB9CiAgICBpZiAoIShlbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkgfHwgZW50cnkuc3RhdCgpLmZpbGV0eXBlICE9PSBGSUxFVFlQRV9ESVJFQ1RPUlkpIHsKICAgICAgcmV0dXJuIEVSUk5PX05PVERJUjsKICAgIH0KICAgIGlmIChlbnRyeS5jb250ZW50cy5zaXplICE9PSAwKSB7CiAgICAgIHJldHVybiBFUlJOT19OT1RFTVBUWTsKICAgIH0KICAgIGlmICghcGFyZW50X2VudHJ5LmNvbnRlbnRzLmRlbGV0ZShmaWxlbmFtZSkpIHsKICAgICAgcmV0dXJuIEVSUk5PX05PRU5UOwogICAgfQogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIGZkX2ZpbGVzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgZmlsZXN0YXQ6IHRoaXMuZGlyLnN0YXQoKSB9OwogIH0KICBmZF9maWxlc3RhdF9zZXRfc2l6ZShzaXplKSB7CiAgICByZXR1cm4gRVJSTk9fQkFERjsKICB9CiAgZmRfcmVhZChzaXplKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIGRhdGE6IG5ldyBVaW50OEFycmF5KCkgfTsKICB9CiAgZmRfcHJlYWQoc2l6ZSwgb2Zmc2V0KSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIGRhdGE6IG5ldyBVaW50OEFycmF5KCkgfTsKICB9CiAgZmRfd3JpdGUoZGF0YSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBud3JpdHRlbjogMCB9OwogIH0KICBmZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG53cml0dGVuOiAwIH07CiAgfQogIGNvbnN0cnVjdG9yKGRpcikgewogICAgc3VwZXIoKTsKICAgIHRoaXMuZGlyID0gZGlyOwogIH0KfTsKdmFyIFByZW9wZW5EaXJlY3RvcnkgPSBjbGFzcyBleHRlbmRzIE9wZW5EaXJlY3RvcnkgewogIGZkX3ByZXN0YXRfZ2V0KCkgewogICAgcmV0dXJuIHsgcmV0OiAwLCBwcmVzdGF0OiBQcmVzdGF0LmRpcih0aGlzLnByZXN0YXRfbmFtZSkgfTsKICB9CiAgY29uc3RydWN0b3IobmFtZSwgY29udGVudHMpIHsKICAgIHN1cGVyKG5ldyBEaXJlY3RvcnkoY29udGVudHMpKTsKICAgIHRoaXMucHJlc3RhdF9uYW1lID0gbmFtZTsKICB9Cn07CnZhciBGaWxlID0gY2xhc3MgZXh0ZW5kcyBJbm9kZSB7CiAgcGF0aF9vcGVuKG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZkX2ZsYWdzKSB7CiAgICBpZiAodGhpcy5yZWFkb25seSAmJiAoZnNfcmlnaHRzX2Jhc2UgJiBCaWdJbnQoUklHSFRTX0ZEX1dSSVRFKSkgPT0gQmlnSW50KFJJR0hUU19GRF9XUklURSkpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19QRVJNLCBmZF9vYmo6IG51bGwgfTsKICAgIH0KICAgIGlmICgob2ZsYWdzICYgT0ZMQUdTX1RSVU5DKSA9PSBPRkxBR1NfVFJVTkMpIHsKICAgICAgaWYgKHRoaXMucmVhZG9ubHkpCiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19QRVJNLCBmZF9vYmo6IG51bGwgfTsKICAgICAgdGhpcy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoW10pOwogICAgfQogICAgY29uc3QgZmlsZSA9IG5ldyBPcGVuRmlsZSh0aGlzKTsKICAgIGlmIChmZF9mbGFncyAmIEZERkxBR1NfQVBQRU5EKQogICAgICBmaWxlLmZkX3NlZWsoMG4sIFdIRU5DRV9FTkQpOwogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBmZF9vYmo6IGZpbGUgfTsKICB9CiAgZ2V0IHNpemUoKSB7CiAgICByZXR1cm4gQmlnSW50KHRoaXMuZGF0YS5ieXRlTGVuZ3RoKTsKICB9CiAgc3RhdCgpIHsKICAgIHJldHVybiBuZXcgRmlsZXN0YXQoRklMRVRZUEVfUkVHVUxBUl9GSUxFLCB0aGlzLnNpemUpOwogIH0KICBjb25zdHJ1Y3RvcihkYXRhLCBvcHRpb25zKSB7CiAgICBzdXBlcigpOwogICAgdGhpcy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoZGF0YSk7CiAgICB0aGlzLnJlYWRvbmx5ID0gISFvcHRpb25zPy5yZWFkb25seTsKICB9Cn07CnZhciBQYXRoID0gY2xhc3MgUGF0aDIgewogIHN0YXRpYyBmcm9tKHBhdGgpIHsKICAgIGNvbnN0IHNlbGYgPSBuZXcgUGF0aDIoKTsKICAgIHNlbGYuaXNfZGlyID0gcGF0aC5lbmRzV2l0aCgiLyIpOwogICAgaWYgKHBhdGguc3RhcnRzV2l0aCgiLyIpKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UQ0FQQUJMRSwgcGF0aDogbnVsbCB9OwogICAgfQogICAgaWYgKHBhdGguaW5jbHVkZXMoIlwwIikpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19JTlZBTCwgcGF0aDogbnVsbCB9OwogICAgfQogICAgZm9yIChjb25zdCBjb21wb25lbnQgb2YgcGF0aC5zcGxpdCgiLyIpKSB7CiAgICAgIGlmIChjb21wb25lbnQgPT09ICIiIHx8IGNvbXBvbmVudCA9PT0gIi4iKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGNvbXBvbmVudCA9PT0gIi4uIikgewogICAgICAgIGlmIChzZWxmLnBhcnRzLnBvcCgpID09IHZvaWQgMCkgewogICAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RDQVBBQkxFLCBwYXRoOiBudWxsIH07CiAgICAgICAgfQogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHNlbGYucGFydHMucHVzaChjb21wb25lbnQpOwogICAgfQogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBwYXRoOiBzZWxmIH07CiAgfQogIHRvX3BhdGhfc3RyaW5nKCkgewogICAgbGV0IHMgPSB0aGlzLnBhcnRzLmpvaW4oIi8iKTsKICAgIGlmICh0aGlzLmlzX2RpcikgewogICAgICBzICs9ICIvIjsKICAgIH0KICAgIHJldHVybiBzOwogIH0KICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMucGFydHMgPSBbXTsKICAgIHRoaXMuaXNfZGlyID0gZmFsc2U7CiAgfQp9Owp2YXIgRGlyZWN0b3J5ID0gY2xhc3MgZXh0ZW5kcyBJbm9kZSB7CiAgcGF0aF9vcGVuKG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZkX2ZsYWdzKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGZkX29iajogbmV3IE9wZW5EaXJlY3RvcnkodGhpcykgfTsKICB9CiAgc3RhdCgpIHsKICAgIHJldHVybiBuZXcgRmlsZXN0YXQoRklMRVRZUEVfRElSRUNUT1JZLCAwbik7CiAgfQogIGdldF9lbnRyeV9mb3JfcGF0aChwYXRoKSB7CiAgICBsZXQgZW50cnkgPSB0aGlzOwogICAgZm9yIChjb25zdCBjb21wb25lbnQgb2YgcGF0aC5wYXJ0cykgewogICAgICBpZiAoIShlbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkpIHsKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgICBjb25zdCBjaGlsZCA9IGVudHJ5LmNvbnRlbnRzLmdldChjb21wb25lbnQpOwogICAgICBpZiAoY2hpbGQgIT09IHZvaWQgMCkgewogICAgICAgIGVudHJ5ID0gY2hpbGQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZGVidWcubG9nKGNvbXBvbmVudCk7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT0VOVCwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgfQogICAgaWYgKHBhdGguaXNfZGlyKSB7CiAgICAgIGlmIChlbnRyeS5zdGF0KCkuZmlsZXR5cGUgIT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIGVudHJ5OiBudWxsIH07CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZW50cnkgfTsKICB9CiAgZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIGFsbG93X3VuZGVmaW5lZCkgewogICAgY29uc3QgZmlsZW5hbWUgPSBwYXRoLnBhcnRzLnBvcCgpOwogICAgaWYgKGZpbGVuYW1lID09PSB2b2lkIDApIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19JTlZBTCwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBlbnRyeV9yZXQsIGVudHJ5OiBwYXJlbnRfZW50cnkgfSA9IHRoaXMuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgpOwogICAgaWYgKHBhcmVudF9lbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogZW50cnlfcmV0LCBwYXJlbnRfZW50cnk6IG51bGwsIGZpbGVuYW1lOiBudWxsLCBlbnRyeTogbnVsbCB9OwogICAgfQogICAgaWYgKCEocGFyZW50X2VudHJ5IGluc3RhbmNlb2YgRGlyZWN0b3J5KSkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IGVudHJ5ID0gcGFyZW50X2VudHJ5LmNvbnRlbnRzLmdldChmaWxlbmFtZSk7CiAgICBpZiAoZW50cnkgPT09IHZvaWQgMCkgewogICAgICBpZiAoIWFsbG93X3VuZGVmaW5lZCkgewogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9FTlQsIHBhcmVudF9lbnRyeTogbnVsbCwgZmlsZW5hbWU6IG51bGwsIGVudHJ5OiBudWxsIH07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeTogbnVsbCB9OwogICAgICB9CiAgICB9CiAgICBpZiAocGF0aC5pc19kaXIpIHsKICAgICAgaWYgKGVudHJ5LnN0YXQoKS5maWxldHlwZSAhPSBGSUxFVFlQRV9ESVJFQ1RPUlkpIHsKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9OwogIH0KICBjcmVhdGVfZW50cnlfZm9yX3BhdGgocGF0aF9zdHIsIGlzX2RpcikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhdGhfcmV0LCBlbnRyeTogbnVsbCB9OwogICAgfQogICAgbGV0IHsgcmV0OiBwYXJlbnRfcmV0LCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9ID0gdGhpcy5nZXRfcGFyZW50X2Rpcl9hbmRfZW50cnlfZm9yX3BhdGgocGF0aCwgdHJ1ZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhcmVudF9yZXQsIGVudHJ5OiBudWxsIH07CiAgICB9CiAgICBpZiAoZW50cnkgIT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0VYSVNULCBlbnRyeTogbnVsbCB9OwogICAgfQogICAgZGVidWcubG9nKCJjcmVhdGUiLCBwYXRoKTsKICAgIGxldCBuZXdfY2hpbGQ7CiAgICBpZiAoIWlzX2RpcikgewogICAgICBuZXdfY2hpbGQgPSBuZXcgRmlsZShuZXcgQXJyYXlCdWZmZXIoMCkpOwogICAgfSBlbHNlIHsKICAgICAgbmV3X2NoaWxkID0gbmV3IERpcmVjdG9yeSgvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpKTsKICAgIH0KICAgIHBhcmVudF9lbnRyeS5jb250ZW50cy5zZXQoZmlsZW5hbWUsIG5ld19jaGlsZCk7CiAgICBlbnRyeSA9IG5ld19jaGlsZDsKICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZW50cnkgfTsKICB9CiAgY29uc3RydWN0b3IoY29udGVudHMpIHsKICAgIHN1cGVyKCk7CiAgICBpZiAoY29udGVudHMgaW5zdGFuY2VvZiBBcnJheSkgewogICAgICB0aGlzLmNvbnRlbnRzID0gbmV3IE1hcChjb250ZW50cyk7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmNvbnRlbnRzID0gY29udGVudHM7CiAgICB9CiAgfQp9Owp2YXIgQ29uc29sZVN0ZG91dCA9IGNsYXNzIGV4dGVuZHMgRmQgewogIGZkX2ZpbGVzdGF0X2dldCgpIHsKICAgIGNvbnN0IGZpbGVzdGF0ID0gbmV3IEZpbGVzdGF0KEZJTEVUWVBFX0NIQVJBQ1RFUl9ERVZJQ0UsIEJpZ0ludCgwKSk7CiAgICByZXR1cm4geyByZXQ6IDAsIGZpbGVzdGF0IH07CiAgfQogIGZkX2Zkc3RhdF9nZXQoKSB7CiAgICBjb25zdCBmZHN0YXQgPSBuZXcgRmRzdGF0KEZJTEVUWVBFX0NIQVJBQ1RFUl9ERVZJQ0UsIDApOwogICAgZmRzdGF0LmZzX3JpZ2h0c19iYXNlID0gQmlnSW50KFJJR0hUU19GRF9XUklURSk7CiAgICByZXR1cm4geyByZXQ6IDAsIGZkc3RhdCB9OwogIH0KICBmZF93cml0ZShkYXRhKSB7CiAgICB0aGlzLndyaXRlKGRhdGEpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBud3JpdHRlbjogZGF0YS5ieXRlTGVuZ3RoIH07CiAgfQogIHN0YXRpYyBsaW5lQnVmZmVyZWQod3JpdGUpIHsKICAgIGNvbnN0IGRlYyA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiLCB7IGZhdGFsOiBmYWxzZSB9KTsKICAgIGxldCBsaW5lX2J1ZiA9ICIiOwogICAgcmV0dXJuIG5ldyBDb25zb2xlU3Rkb3V0KChidWZmZXIpID0+IHsKICAgICAgbGluZV9idWYgKz0gZGVjLmRlY29kZShidWZmZXIsIHsgc3RyZWFtOiB0cnVlIH0pOwogICAgICBjb25zdCBsaW5lcyA9IGxpbmVfYnVmLnNwbGl0KCJcbiIpOwogICAgICBmb3IgKGNvbnN0IFtpLCBsaW5lXSBvZiBsaW5lcy5lbnRyaWVzKCkpIHsKICAgICAgICBpZiAoaSA8IGxpbmVzLmxlbmd0aCAtIDEpIHsKICAgICAgICAgIHdyaXRlKGxpbmUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBsaW5lX2J1ZiA9IGxpbmU7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICB9CiAgY29uc3RydWN0b3Iod3JpdGUpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLndyaXRlID0gd3JpdGU7CiAgfQp9OwoKLy8gbm9kZV9tb2R1bGVzL3dhc20taW1wb3J0cy1wYXJzZXIvaW5kZXguanMKZnVuY3Rpb24gcGFyc2VJbXBvcnRzKG1vZHVsZUJ5dGVzKSB7CiAgaWYgKG1vZHVsZUJ5dGVzIGluc3RhbmNlb2YgVWludDhBcnJheSkgewogIH0gZWxzZSBpZiAobW9kdWxlQnl0ZXMgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikgewogICAgbW9kdWxlQnl0ZXMgPSBuZXcgVWludDhBcnJheShtb2R1bGVCeXRlcyk7CiAgfSBlbHNlIGlmIChtb2R1bGVCeXRlcy5idWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikgewogICAgbW9kdWxlQnl0ZXMgPSBuZXcgVWludDhBcnJheShtb2R1bGVCeXRlcy5idWZmZXIpOwogIH0gZWxzZSB7CiAgICB0aHJvdyBuZXcgRXJyb3IoIkFyZ3VtZW50IG11c3QgYmUgYSBidWZmZXIgc291cmNlLCBsaWtlIFVpbnQ4QXJyYXkgb3IgQXJyYXlCdWZmZXIiKTsKICB9CiAgY29uc3QgcGFyc2VTdGF0ZSA9IG5ldyBQYXJzZVN0YXRlKG1vZHVsZUJ5dGVzKTsKICBwYXJzZU1hZ2ljTnVtYmVyKHBhcnNlU3RhdGUpOwogIHBhcnNlVmVyc2lvbihwYXJzZVN0YXRlKTsKICBjb25zdCB0eXBlcyA9IFtdOwogIGNvbnN0IGltcG9ydHMgPSBbXTsKICB3aGlsZSAocGFyc2VTdGF0ZS5oYXNNb3JlQnl0ZXMoKSkgewogICAgY29uc3Qgc2VjdGlvbklkID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogICAgY29uc3Qgc2VjdGlvblNpemUgPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgc3dpdGNoIChzZWN0aW9uSWQpIHsKICAgICAgY2FzZSAxOiB7CiAgICAgICAgY29uc3QgdHlwZUNvdW50ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHR5cGVDb3VudDsgaSsrKSB7CiAgICAgICAgICB0eXBlcy5wdXNoKHBhcnNlRnVuY3Rpb25UeXBlKHBhcnNlU3RhdGUpKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY2FzZSAyOiB7CiAgICAgICAgY29uc3QgaW1wb3J0Q291bnQgPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW1wb3J0Q291bnQ7IGkrKykgewogICAgICAgICAgY29uc3QgbW9kdWxlID0gcGFyc2VTdGF0ZS5yZWFkTmFtZSgpOwogICAgICAgICAgY29uc3QgbmFtZSA9IHBhcnNlU3RhdGUucmVhZE5hbWUoKTsKICAgICAgICAgIGNvbnN0IHR5cGUgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICAgICAgICAgICAgICBpbXBvcnRzLnB1c2goeyBtb2R1bGUsIG5hbWUsIGtpbmQ6ICJmdW5jdGlvbiIsIHR5cGU6IHR5cGVzW2luZGV4XSB9KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgIGltcG9ydHMucHVzaCh7IG1vZHVsZSwgbmFtZSwga2luZDogInRhYmxlIiwgdHlwZTogcGFyc2VUYWJsZVR5cGUocGFyc2VTdGF0ZSkgfSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgICBpbXBvcnRzLnB1c2goeyBtb2R1bGUsIG5hbWUsIGtpbmQ6ICJtZW1vcnkiLCB0eXBlOiBwYXJzZUxpbWl0cyhwYXJzZVN0YXRlKSB9KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAzOgogICAgICAgICAgICAgIGltcG9ydHMucHVzaCh7IG1vZHVsZSwgbmFtZSwga2luZDogImdsb2JhbCIsIHR5cGU6IHBhcnNlR2xvYmFsVHlwZShwYXJzZVN0YXRlKSB9KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gaW1wb3J0IGRlc2NyaXB0b3IgdHlwZSAke3R5cGV9YCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBpbXBvcnRzOwogICAgICB9CiAgICAgIGRlZmF1bHQ6IHsKICAgICAgICBwYXJzZVN0YXRlLnNraXBCeXRlcyhzZWN0aW9uU2l6ZSk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICB9CiAgcmV0dXJuIFtdOwp9CnZhciBQYXJzZVN0YXRlID0gY2xhc3MgewogIGNvbnN0cnVjdG9yKG1vZHVsZUJ5dGVzKSB7CiAgICB0aGlzLm1vZHVsZUJ5dGVzID0gbW9kdWxlQnl0ZXM7CiAgICB0aGlzLm9mZnNldCA9IDA7CiAgICB0aGlzLnRleHREZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpOwogIH0KICBoYXNNb3JlQnl0ZXMoKSB7CiAgICByZXR1cm4gdGhpcy5vZmZzZXQgPCB0aGlzLm1vZHVsZUJ5dGVzLmxlbmd0aDsKICB9CiAgcmVhZEJ5dGUoKSB7CiAgICByZXR1cm4gdGhpcy5tb2R1bGVCeXRlc1t0aGlzLm9mZnNldCsrXTsKICB9CiAgc2tpcEJ5dGVzKGNvdW50KSB7CiAgICB0aGlzLm9mZnNldCArPSBjb3VudDsKICB9CiAgcmVhZFVuc2lnbmVkTEVCMTI4KCkgewogICAgbGV0IHJlc3VsdCA9IDA7CiAgICBsZXQgc2hpZnQgPSAwOwogICAgbGV0IGJ5dGU7CiAgICBkbyB7CiAgICAgIGJ5dGUgPSB0aGlzLnJlYWRCeXRlKCk7CiAgICAgIHJlc3VsdCB8PSAoYnl0ZSAmIDEyNykgPDwgc2hpZnQ7CiAgICAgIHNoaWZ0ICs9IDc7CiAgICB9IHdoaWxlIChieXRlICYgMTI4KTsKICAgIHJldHVybiByZXN1bHQ7CiAgfQogIHJlYWROYW1lKCkgewogICAgY29uc3QgbmFtZUxlbmd0aCA9IHRoaXMucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgICBjb25zdCBuYW1lQnl0ZXMgPSB0aGlzLm1vZHVsZUJ5dGVzLnNsaWNlKHRoaXMub2Zmc2V0LCB0aGlzLm9mZnNldCArIG5hbWVMZW5ndGgpOwogICAgY29uc3QgbmFtZSA9IHRoaXMudGV4dERlY29kZXIuZGVjb2RlKG5hbWVCeXRlcyk7CiAgICB0aGlzLm9mZnNldCArPSBuYW1lTGVuZ3RoOwogICAgcmV0dXJuIG5hbWU7CiAgfQogIGFzc2VydEJ5dGVzKGV4cGVjdGVkKSB7CiAgICBjb25zdCBiYXNlT2Zmc2V0ID0gdGhpcy5vZmZzZXQ7CiAgICBjb25zdCBleHBlY3RlZExlbmd0aCA9IGV4cGVjdGVkLmxlbmd0aDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZXhwZWN0ZWRMZW5ndGg7IGkrKykgewogICAgICBpZiAodGhpcy5tb2R1bGVCeXRlc1tiYXNlT2Zmc2V0ICsgaV0gIT09IGV4cGVjdGVkW2ldKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCAke2V4cGVjdGVkfSBhdCBvZmZzZXQgJHtiYXNlT2Zmc2V0fWApOwogICAgICB9CiAgICB9CiAgICB0aGlzLm9mZnNldCArPSBleHBlY3RlZExlbmd0aDsKICB9Cn07CmZ1bmN0aW9uIHBhcnNlTWFnaWNOdW1iZXIocGFyc2VTdGF0ZSkgewogIGNvbnN0IGV4cGVjdGVkID0gWzAsIDk3LCAxMTUsIDEwOV07CiAgcGFyc2VTdGF0ZS5hc3NlcnRCeXRlcyhleHBlY3RlZCk7Cn0KZnVuY3Rpb24gcGFyc2VWZXJzaW9uKHBhcnNlU3RhdGUpIHsKICBjb25zdCBleHBlY3RlZCA9IFsxLCAwLCAwLCAwXTsKICBwYXJzZVN0YXRlLmFzc2VydEJ5dGVzKGV4cGVjdGVkKTsKfQpmdW5jdGlvbiBwYXJzZVRhYmxlVHlwZShwYXJzZVN0YXRlKSB7CiAgY29uc3QgZWxlbWVudFR5cGUgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgbGV0IGVsZW1lbnQ7CiAgc3dpdGNoIChlbGVtZW50VHlwZSkgewogICAgY2FzZSAxMTI6CiAgICAgIGVsZW1lbnQgPSAiZnVuY3JlZiI7CiAgICAgIGJyZWFrOwogICAgY2FzZSAxMTE6CiAgICAgIGVsZW1lbnQgPSAiZXh0ZXJucmVmIjsKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gdGFibGUgZWxlbWVudCB0eXBlICR7ZWxlbWVudFR5cGV9YCk7CiAgfQogIGNvbnN0IHsgbWluaW11bSwgbWF4aW11bSB9ID0gcGFyc2VMaW1pdHMocGFyc2VTdGF0ZSk7CiAgaWYgKG1heGltdW0pIHsKICAgIHJldHVybiB7IGVsZW1lbnQsIG1pbmltdW0sIG1heGltdW0gfTsKICB9IGVsc2UgewogICAgcmV0dXJuIHsgZWxlbWVudCwgbWluaW11bSB9OwogIH0KfQpmdW5jdGlvbiBwYXJzZUxpbWl0cyhwYXJzZVN0YXRlKSB7CiAgY29uc3QgZmxhZ3MgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgY29uc3QgbWluaW11bSA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgY29uc3QgaGFzTWF4aW11bSA9IGZsYWdzICYgMTsKICBjb25zdCBzaGFyZWQgPSAoZmxhZ3MgJiAyKSAhPT0gMDsKICBjb25zdCBpc01lbW9yeTY0ID0gKGZsYWdzICYgNCkgIT09IDA7CiAgY29uc3QgaW5kZXggPSBpc01lbW9yeTY0ID8gImk2NCIgOiAiaTMyIjsKICBpZiAoaGFzTWF4aW11bSkgewogICAgY29uc3QgbWF4aW11bSA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgICByZXR1cm4geyBtaW5pbXVtLCBzaGFyZWQsIGluZGV4LCBtYXhpbXVtIH07CiAgfSBlbHNlIHsKICAgIHJldHVybiB7IG1pbmltdW0sIHNoYXJlZCwgaW5kZXggfTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VHbG9iYWxUeXBlKHBhcnNlU3RhdGUpIHsKICBjb25zdCB2YWx1ZSA9IHBhcnNlVmFsdWVUeXBlKHBhcnNlU3RhdGUpOwogIGNvbnN0IG11dGFibGUgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCkgPT09IDE7CiAgcmV0dXJuIHsgdmFsdWUsIG11dGFibGUgfTsKfQpmdW5jdGlvbiBwYXJzZVZhbHVlVHlwZShwYXJzZVN0YXRlKSB7CiAgY29uc3QgdHlwZSA9IHBhcnNlU3RhdGUucmVhZEJ5dGUoKTsKICBzd2l0Y2ggKHR5cGUpIHsKICAgIGNhc2UgMTI3OgogICAgICByZXR1cm4gImkzMiI7CiAgICBjYXNlIDEyNjoKICAgICAgcmV0dXJuICJpNjQiOwogICAgY2FzZSAxMjU6CiAgICAgIHJldHVybiAiZjMyIjsKICAgIGNhc2UgMTI0OgogICAgICByZXR1cm4gImY2NCI7CiAgICBjYXNlIDExMjoKICAgICAgcmV0dXJuICJmdW5jcmVmIjsKICAgIGNhc2UgMTExOgogICAgICByZXR1cm4gImV4dGVybnJlZiI7CiAgICBjYXNlIDEyMzoKICAgICAgcmV0dXJuICJ2MTI4IjsKICAgIGRlZmF1bHQ6CiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biB2YWx1ZSB0eXBlICR7dHlwZX1gKTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VGdW5jdGlvblR5cGUocGFyc2VTdGF0ZSkgewogIGNvbnN0IGZvcm0gPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgaWYgKGZvcm0gIT09IDk2KSB7CiAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGZ1bmN0aW9uIHR5cGUgZm9ybSAweDYwLCBnb3QgJHtmb3JtfWApOwogIH0KICBjb25zdCBwYXJhbWV0ZXJzID0gW107CiAgY29uc3QgcGFyYW1ldGVyQ291bnQgPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogIGZvciAobGV0IGkgPSAwOyBpIDwgcGFyYW1ldGVyQ291bnQ7IGkrKykgewogICAgcGFyYW1ldGVycy5wdXNoKHBhcnNlVmFsdWVUeXBlKHBhcnNlU3RhdGUpKTsKICB9CiAgY29uc3QgcmVzdWx0cyA9IFtdOwogIGNvbnN0IHJlc3VsdENvdW50ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICBmb3IgKGxldCBpID0gMDsgaSA8IHJlc3VsdENvdW50OyBpKyspIHsKICAgIHJlc3VsdHMucHVzaChwYXJzZVZhbHVlVHlwZShwYXJzZVN0YXRlKSk7CiAgfQogIHJldHVybiB7IHBhcmFtZXRlcnMsIHJlc3VsdHMgfTsKfQoKLy8gbm9kZV9tb2R1bGVzL3dhc20taW1wb3J0cy1wYXJzZXIvcG9seWZpbGwuanMKdmFyIGhhc1dhc21UeXBlUmVmbGVjdGlvblN1cHBvcnQgPSAoKCkgPT4gewogIGNvbnN0IG1vZHVsZUJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoWwogICAgMCwKICAgIDk3LAogICAgMTE1LAogICAgMTA5LAogICAgMSwKICAgIDAsCiAgICAwLAogICAgMCwKICAgIDIsCiAgICA2LAogICAgMSwKICAgIDAsCiAgICAwLAogICAgMiwKICAgIDAsCiAgICAxCiAgXSk7CiAgY29uc3QgbW9kdWxlID0gbmV3IFdlYkFzc2VtYmx5Lk1vZHVsZShtb2R1bGVCeXRlcyk7CiAgY29uc3QgaW1wb3J0cyA9IFdlYkFzc2VtYmx5Lk1vZHVsZS5pbXBvcnRzKG1vZHVsZSk7CiAgY29uc3QgbWVtb3J5SW1wb3J0ID0gaW1wb3J0c1swXTsKICByZXR1cm4gdHlwZW9mIG1lbW9yeUltcG9ydC50eXBlID09PSAib2JqZWN0IjsKfSkoKTsKZnVuY3Rpb24gcG9seWZpbGwoV2ViQXNzZW1ibHkzKSB7CiAgaWYgKGhhc1dhc21UeXBlUmVmbGVjdGlvblN1cHBvcnQpIHsKICAgIHJldHVybiBXZWJBc3NlbWJseTM7CiAgfQogIGNvbnN0IG5ld1dlYkFzc2VtYmx5ID0ge307CiAgZm9yIChjb25zdCBrZXkgaW4gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMoV2ViQXNzZW1ibHkzKSkgewogICAgbmV3V2ViQXNzZW1ibHlba2V5XSA9IFdlYkFzc2VtYmx5M1trZXldOwogIH0KICBjb25zdCBwb2x5ZmlsbGVkSW1wb3J0c1N5bWJvbCA9IFN5bWJvbCgicG9seWZpbGxlZEltcG9ydHNTeW1ib2wiKTsKICBjb25zdCBhc3NpZ25JbXBvcnRzID0gKG1vZHVsZSwgc291cmNlQnl0ZXMpID0+IHsKICAgIG1vZHVsZVtwb2x5ZmlsbGVkSW1wb3J0c1N5bWJvbF0gPSBwYXJzZUltcG9ydHMoc291cmNlQnl0ZXMpOwogIH07CiAgY29uc3QgbmV3TW9kdWxlID0gbmV3V2ViQXNzZW1ibHkuTW9kdWxlID0gZnVuY3Rpb24oYnl0ZXMpIHsKICAgIGNvbnN0IG1vZHVsZSA9IG5ldyBXZWJBc3NlbWJseTMuTW9kdWxlKGJ5dGVzKTsKICAgIGFzc2lnbkltcG9ydHMobW9kdWxlLCBieXRlcyk7CiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YobW9kdWxlLCBuZXdNb2R1bGUucHJvdG90eXBlKTsKICAgIHJldHVybiBtb2R1bGU7CiAgfTsKICBPYmplY3Quc2V0UHJvdG90eXBlT2YobmV3TW9kdWxlLnByb3RvdHlwZSwgV2ViQXNzZW1ibHkzLk1vZHVsZS5wcm90b3R5cGUpOwogIG5ld1dlYkFzc2VtYmx5LmNvbXBpbGUgPSBhc3luYyAoc291cmNlKSA9PiB7CiAgICBjb25zdCBtb2R1bGUgPSBhd2FpdCBXZWJBc3NlbWJseTMuY29tcGlsZShzb3VyY2UpOwogICAgYXNzaWduSW1wb3J0cyhtb2R1bGUsIHNvdXJjZSk7CiAgICByZXR1cm4gbW9kdWxlOwogIH07CiAgaWYgKFdlYkFzc2VtYmx5My5jb21waWxlU3RyZWFtaW5nKSB7CiAgICBuZXdXZWJBc3NlbWJseS5jb21waWxlU3RyZWFtaW5nID0gYXN5bmMgKHNvdXJjZSkgPT4gewogICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHNvdXJjZTsKICAgICAgY29uc3QgY2xvbmUgPSByZXNwb25zZS5jbG9uZSgpOwogICAgICBjb25zdCBtb2R1bGUgPSBhd2FpdCBXZWJBc3NlbWJseTMuY29tcGlsZVN0cmVhbWluZyhyZXNwb25zZSk7CiAgICAgIGFzc2lnbkltcG9ydHMobW9kdWxlLCBuZXcgVWludDhBcnJheShhd2FpdCBjbG9uZS5hcnJheUJ1ZmZlcigpKSk7CiAgICAgIHJldHVybiBtb2R1bGU7CiAgICB9OwogIH0KICBuZXdNb2R1bGUuaW1wb3J0cyA9IChtb2R1bGUpID0+IHsKICAgIGNvbnN0IHBhcnNlZEltcG9ydHMgPSBtb2R1bGVbcG9seWZpbGxlZEltcG9ydHNTeW1ib2xdOwogICAgaWYgKCFwYXJzZWRJbXBvcnRzKSB7CiAgICAgIHJldHVybiBXZWJBc3NlbWJseTMuTW9kdWxlLmltcG9ydHMobW9kdWxlKTsKICAgIH0KICAgIHJldHVybiBwYXJzZWRJbXBvcnRzOwogIH07CiAgcmV0dXJuIG5ld1dlYkFzc2VtYmx5Owp9CgovLyBlbnRyeXBvaW50L2ludHJpbnNpY3MudHMKdmFyIFdlYkFzc2VtYmx5MiA9IHBvbHlmaWxsKGdsb2JhbFRoaXMuV2ViQXNzZW1ibHkpOwp2YXIgTGluZURlY29kZXIgPSBjbGFzcyB7CiAgY29uc3RydWN0b3Iob25MaW5lKSB7CiAgICB0aGlzLmRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IiwgeyBmYXRhbDogZmFsc2UgfSk7CiAgICB0aGlzLmJ1ZmZlciA9ICIiOwogICAgdGhpcy5vbkxpbmUgPSBvbkxpbmU7CiAgfQogIGRlY29kZXI7CiAgYnVmZmVyOwogIG9uTGluZTsKICBzZW5kKGNodW5rKSB7CiAgICB0aGlzLmJ1ZmZlciArPSB0aGlzLmRlY29kZXIuZGVjb2RlKGNodW5rLCB7IHN0cmVhbTogdHJ1ZSB9KTsKICAgIGNvbnN0IGxpbmVzID0gdGhpcy5idWZmZXIuc3BsaXQoIlxuIik7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aCAtIDE7IGkrKykgewogICAgICB0aGlzLm9uTGluZShsaW5lc1tpXSk7CiAgICB9CiAgICB0aGlzLmJ1ZmZlciA9IGxpbmVzW2xpbmVzLmxlbmd0aCAtIDFdOwogIH0KfTsKYXN5bmMgZnVuY3Rpb24gaW5zdGFudGlhdGUocmF3T3B0aW9ucywgZXh0cmFXYXNtSW1wb3J0cykgewogIGNvbnN0IG9wdGlvbnMgPSBkZWZhdWx0SW5zdGFudGlhdGlvbk9wdGlvbnMocmF3T3B0aW9ucyk7CiAgbGV0IHN3aWZ0ID0gb3B0aW9ucy5zd2lmdDsKICBpZiAoIXN3aWZ0ICYmIG9wdGlvbnMuU3dpZnRSdW50aW1lKSB7CiAgICBzd2lmdCA9IG5ldyBvcHRpb25zLlN3aWZ0UnVudGltZSgpOwogIH0KICBsZXQgc3Rkb3V0TGluZSA9IHZvaWQgMDsKICBpZiAob3B0aW9ucy5vblN0ZG91dExpbmUgIT0gbnVsbCkgewogICAgc3Rkb3V0TGluZSA9IG5ldyBMaW5lRGVjb2RlcihvcHRpb25zLm9uU3Rkb3V0TGluZSk7CiAgfQogIGNvbnN0IHN0ZG91dCA9IG5ldyBDb25zb2xlU3Rkb3V0KChjaHVuaykgPT4gewogICAgb3B0aW9ucy5vblN0ZG91dD8uY2FsbCh2b2lkIDAsIGNodW5rKTsKICAgIHN0ZG91dExpbmU/LnNlbmQoY2h1bmspOwogIH0pOwogIGxldCBzdGRlcnJMaW5lID0gdm9pZCAwOwogIGlmIChvcHRpb25zLm9uU3RkZXJyTGluZSAhPSBudWxsKSB7CiAgICBzdGRlcnJMaW5lID0gbmV3IExpbmVEZWNvZGVyKG9wdGlvbnMub25TdGRlcnJMaW5lKTsKICB9CiAgY29uc3Qgc3RkZXJyID0gbmV3IENvbnNvbGVTdGRvdXQoKGNodW5rKSA9PiB7CiAgICBvcHRpb25zLm9uU3RkZXJyPy5jYWxsKHZvaWQgMCwgY2h1bmspOwogICAgc3RkZXJyTGluZT8uc2VuZChjaHVuayk7CiAgfSk7CiAgY29uc3QgYXJncyA9IG9wdGlvbnMuYXJncyB8fCBbXTsKICBjb25zdCBmZHMgPSBbCiAgICBuZXcgT3BlbkZpbGUobmV3IEZpbGUoW10pKSwKICAgIHN0ZG91dCwKICAgIHN0ZGVyciwKICAgIG5ldyBQcmVvcGVuRGlyZWN0b3J5KCIvIiwgLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKSkKICBdOwogIGNvbnN0IGVudnMgPSBvcHRpb25zLmVudiA/IE9iamVjdC5lbnRyaWVzKG9wdGlvbnMuZW52KS5tYXAoKFtrZXksIHZhbHVlXSkgPT4gYCR7a2V5fT0ke3ZhbHVlfWApIDogW107CiAgY29uc3Qgd2FzaSA9IG5ldyBXQVNJKGFyZ3MsIGVudnMsIGZkcywgewogICAgZGVidWc6IGZhbHNlCiAgfSk7CiAgY29uc3QgY3JlYXRlV2FzbUltcG9ydE9iamVjdCA9IChleHRyYVdhc21JbXBvcnRzMiwgbW9kdWxlKSA9PiB7CiAgICBjb25zdCBpbXBvcnRPYmplY3QyID0gewogICAgICB3YXNpX3NuYXBzaG90X3ByZXZpZXcxOiB3YXNpLndhc2lJbXBvcnQKICAgIH07CiAgICBpZiAoc3dpZnQpIHsKICAgICAgaW1wb3J0T2JqZWN0Mi5qYXZhc2NyaXB0X2tpdCA9IHN3aWZ0Lndhc21JbXBvcnRzOwogICAgfQogICAgaWYgKGV4dHJhV2FzbUltcG9ydHMyKSB7CiAgICAgIGZvciAoY29uc3QgbW9kdWxlTmFtZSBpbiBleHRyYVdhc21JbXBvcnRzMikgewogICAgICAgIGlmICghaW1wb3J0T2JqZWN0Mlttb2R1bGVOYW1lXSkgewogICAgICAgICAgaW1wb3J0T2JqZWN0Mlttb2R1bGVOYW1lXSA9IHt9OwogICAgICAgIH0KICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IGluIGV4dHJhV2FzbUltcG9ydHMyW21vZHVsZU5hbWVdKSB7CiAgICAgICAgICBpbXBvcnRPYmplY3QyW21vZHVsZU5hbWVdW2VudHJ5XSA9IGV4dHJhV2FzbUltcG9ydHMyW21vZHVsZU5hbWVdW2VudHJ5XTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGZvciAoY29uc3QgX2ltcG9ydEVudHJ5IG9mIFdlYkFzc2VtYmx5Mi5Nb2R1bGUuaW1wb3J0cyhtb2R1bGUpKSB7CiAgICAgIGNvbnN0IGltcG9ydEVudHJ5ID0gX2ltcG9ydEVudHJ5OwogICAgICBpZiAoIWltcG9ydE9iamVjdDJbaW1wb3J0RW50cnkubW9kdWxlXSkgewogICAgICAgIGltcG9ydE9iamVjdDJbaW1wb3J0RW50cnkubW9kdWxlXSA9IHt9OwogICAgICB9CiAgICAgIGlmIChpbXBvcnRPYmplY3QyW2ltcG9ydEVudHJ5Lm1vZHVsZV1baW1wb3J0RW50cnkubmFtZV0pIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoaW1wb3J0RW50cnkua2luZCA9PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgaW1wb3J0T2JqZWN0MltpbXBvcnRFbnRyeS5tb2R1bGVdW2ltcG9ydEVudHJ5Lm5hbWVdID0gKCkgPT4gewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbXBvcnRlZCBmdW5jdGlvbiAke2ltcG9ydEVudHJ5Lm1vZHVsZX0uJHtpbXBvcnRFbnRyeS5uYW1lfSBub3QgaW1wbGVtZW50ZWRgKTsKICAgICAgICB9OwogICAgICB9IGVsc2UgaWYgKGltcG9ydEVudHJ5LmtpbmQgPT0gIm1lbW9yeSIgJiYgaW1wb3J0RW50cnkubW9kdWxlID09ICJlbnYiICYmIGltcG9ydEVudHJ5Lm5hbWUgPT0gIm1lbW9yeSIpIHsKICAgICAgICBjb25zdCB0eXBlID0gaW1wb3J0RW50cnkudHlwZTsKICAgICAgICBjb25zdCBkZXNjcmlwdG9yID0gewogICAgICAgICAgaW5pdGlhbDogdHlwZS5taW5pbXVtLAogICAgICAgICAgbWF4aW11bTogdHlwZS5tYXhpbXVtLAogICAgICAgICAgc2hhcmVkOiB0eXBlLnNoYXJlZAogICAgICAgIH07CiAgICAgICAgaW1wb3J0T2JqZWN0MltpbXBvcnRFbnRyeS5tb2R1bGVdW2ltcG9ydEVudHJ5Lm5hbWVdID0gbmV3IFdlYkFzc2VtYmx5Mi5NZW1vcnkoZGVzY3JpcHRvcik7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBpbXBvcnRPYmplY3QyOwogIH07CiAgY29uc3QgaW1wb3J0T2JqZWN0ID0gY3JlYXRlV2FzbUltcG9ydE9iamVjdChleHRyYVdhc21JbXBvcnRzLCBvcHRpb25zLm1vZHVsZSk7CiAgY29uc3QgaW5zdGFuY2UgPSBhd2FpdCBXZWJBc3NlbWJseTIuaW5zdGFudGlhdGUob3B0aW9ucy5tb2R1bGUsIGltcG9ydE9iamVjdCk7CiAgaWYgKHN3aWZ0ICYmIGluc3RhbmNlLmV4cG9ydHMuc3dqc19saWJyYXJ5X3ZlcnNpb24pIHsKICAgIHN3aWZ0LnNldEluc3RhbmNlKGluc3RhbmNlKTsKICB9CiAgaWYgKHR5cGVvZiBpbnN0YW5jZS5leHBvcnRzLl9zdGFydCA9PT0gImZ1bmN0aW9uIikgewogICAgd2FzaS5zdGFydChpbnN0YW5jZSk7CiAgfSBlbHNlIGlmICh0eXBlb2YgaW5zdGFuY2UuZXhwb3J0cy5faW5pdGlhbGl6ZSA9PSAiZnVuY3Rpb24iKSB7CiAgICB3YXNpLmluaXRpYWxpemUoaW5zdGFuY2UpOwogICAgaWYgKHN3aWZ0ICYmIHN3aWZ0Lm1haW4pIHsKICAgICAgc3dpZnQubWFpbigpOwogICAgfSBlbHNlIHsKICAgICAgaWYgKHR5cGVvZiBpbnN0YW5jZS5leHBvcnRzLm1haW4gPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICBpbnN0YW5jZS5leHBvcnRzLm1haW4oKTsKICAgICAgfSBlbHNlIGlmICh0eXBlb2YgaW5zdGFuY2UuZXhwb3J0cy5fX21haW5fYXJnY19hcmd2ID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgaW5zdGFuY2UuZXhwb3J0cy5fX21haW5fYXJnY19hcmd2KDAsIDApOwogICAgICB9CiAgICB9CiAgfQogIHJldHVybiB7IGluc3RhbmNlIH07Cn0KZnVuY3Rpb24gZGVmYXVsdEluc3RhbnRpYXRpb25PcHRpb25zKG9wdGlvbnMpIHsKICBpZiAob3B0aW9ucy5hcmdzID09IG51bGwpIHsKICAgIG9wdGlvbnMuYXJncyA9IFsibWFpbi53YXNtIl07CiAgfQogIGNvbnN0IGlzTm9kZUpzID0gdHlwZW9mIHByb2Nlc3MgIT09ICJ1bmRlZmluZWQiICYmIHByb2Nlc3MucmVsZWFzZS5uYW1lID09PSAibm9kZSI7CiAgY29uc3QgaXNXZWJCcm93c2VyID0gdHlwZW9mIHdpbmRvdyAhPT0gInVuZGVmaW5lZCI7CiAgaWYgKGlzTm9kZUpzKSB7CiAgICBpZiAoIW9wdGlvbnMub25TdGRvdXQpIHsKICAgICAgb3B0aW9ucy5vblN0ZG91dCA9IChjaHVuaykgPT4gcHJvY2Vzcy5zdGRvdXQud3JpdGUoY2h1bmspOwogICAgfQogICAgaWYgKCFvcHRpb25zLm9uU3RkZXJyKSB7CiAgICAgIG9wdGlvbnMub25TdGRlcnIgPSAoY2h1bmspID0+IHByb2Nlc3Muc3RkZXJyLndyaXRlKGNodW5rKTsKICAgIH0KICB9IGVsc2UgaWYgKGlzV2ViQnJvd3NlcikgewogICAgaWYgKCFvcHRpb25zLm9uU3Rkb3V0TGluZSkgewogICAgICBvcHRpb25zLm9uU3Rkb3V0TGluZSA9IChsaW5lKSA9PiBjb25zb2xlLmxvZyhsaW5lKTsKICAgIH0KICAgIGlmICghb3B0aW9ucy5vblN0ZGVyckxpbmUpIHsKICAgICAgb3B0aW9ucy5vblN0ZGVyckxpbmUgPSAobGluZSkgPT4gY29uc29sZS53YXJuKGxpbmUpOwogICAgfQogIH0KICByZXR1cm4gb3B0aW9uczsKfQpleHBvcnQgewogIGluc3RhbnRpYXRlCn07Cg==")! + public static let dev: Data = Data(base64Encoded: "Ly8gbm9kZV9tb2R1bGVzL3JlY29ubmVjdGluZy13ZWJzb2NrZXQvZGlzdC9yZWNvbm5lY3Rpbmctd2Vic29ja2V0LW1qcy5qcwp2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHsKICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24oZDIsIGIyKSB7CiAgICBkMi5fX3Byb3RvX18gPSBiMjsKICB9IHx8IGZ1bmN0aW9uKGQyLCBiMikgewogICAgZm9yICh2YXIgcCBpbiBiMikKICAgICAgaWYgKGIyLmhhc093blByb3BlcnR5KHApKQogICAgICAgIGQyW3BdID0gYjJbcF07CiAgfTsKICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTsKfTsKZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHsKICBleHRlbmRTdGF0aWNzKGQsIGIpOwogIGZ1bmN0aW9uIF9fKCkgewogICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7CiAgfQogIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTsKfQpmdW5jdGlvbiBfX3ZhbHVlcyhvKSB7CiAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSAiZnVuY3Rpb24iICYmIG9bU3ltYm9sLml0ZXJhdG9yXSwgaSA9IDA7CiAgaWYgKG0pCiAgICByZXR1cm4gbS5jYWxsKG8pOwogIHJldHVybiB7CiAgICBuZXh0OiBmdW5jdGlvbigpIHsKICAgICAgaWYgKG8gJiYgaSA+PSBvLmxlbmd0aCkKICAgICAgICBvID0gdm9pZCAwOwogICAgICByZXR1cm4geyB2YWx1ZTogbyAmJiBvW2krK10sIGRvbmU6ICFvIH07CiAgICB9CiAgfTsKfQpmdW5jdGlvbiBfX3JlYWQobywgbikgewogIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gImZ1bmN0aW9uIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07CiAgaWYgKCFtKQogICAgcmV0dXJuIG87CiAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7CiAgdHJ5IHsKICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKQogICAgICBhci5wdXNoKHIudmFsdWUpOwogIH0gY2F0Y2ggKGVycm9yKSB7CiAgICBlID0geyBlcnJvciB9OwogIH0gZmluYWxseSB7CiAgICB0cnkgewogICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVsicmV0dXJuIl0pKQogICAgICAgIG0uY2FsbChpKTsKICAgIH0gZmluYWxseSB7CiAgICAgIGlmIChlKQogICAgICAgIHRocm93IGUuZXJyb3I7CiAgICB9CiAgfQogIHJldHVybiBhcjsKfQpmdW5jdGlvbiBfX3NwcmVhZCgpIHsKICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykKICAgIGFyID0gYXIuY29uY2F0KF9fcmVhZChhcmd1bWVudHNbaV0pKTsKICByZXR1cm4gYXI7Cn0KdmFyIEV2ZW50ID0gZnVuY3Rpb24oKSB7CiAgZnVuY3Rpb24gRXZlbnQyKHR5cGUsIHRhcmdldCkgewogICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7CiAgICB0aGlzLnR5cGUgPSB0eXBlOwogIH0KICByZXR1cm4gRXZlbnQyOwp9KCk7CnZhciBFcnJvckV2ZW50ID0gZnVuY3Rpb24oX3N1cGVyKSB7CiAgX19leHRlbmRzKEVycm9yRXZlbnQyLCBfc3VwZXIpOwogIGZ1bmN0aW9uIEVycm9yRXZlbnQyKGVycm9yLCB0YXJnZXQpIHsKICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsICJlcnJvciIsIHRhcmdldCkgfHwgdGhpczsKICAgIF90aGlzLm1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlOwogICAgX3RoaXMuZXJyb3IgPSBlcnJvcjsKICAgIHJldHVybiBfdGhpczsKICB9CiAgcmV0dXJuIEVycm9yRXZlbnQyOwp9KEV2ZW50KTsKdmFyIENsb3NlRXZlbnQgPSBmdW5jdGlvbihfc3VwZXIpIHsKICBfX2V4dGVuZHMoQ2xvc2VFdmVudDIsIF9zdXBlcik7CiAgZnVuY3Rpb24gQ2xvc2VFdmVudDIoY29kZSwgcmVhc29uLCB0YXJnZXQpIHsKICAgIGlmIChjb2RlID09PSB2b2lkIDApIHsKICAgICAgY29kZSA9IDFlMzsKICAgIH0KICAgIGlmIChyZWFzb24gPT09IHZvaWQgMCkgewogICAgICByZWFzb24gPSAiIjsKICAgIH0KICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsICJjbG9zZSIsIHRhcmdldCkgfHwgdGhpczsKICAgIF90aGlzLndhc0NsZWFuID0gdHJ1ZTsKICAgIF90aGlzLmNvZGUgPSBjb2RlOwogICAgX3RoaXMucmVhc29uID0gcmVhc29uOwogICAgcmV0dXJuIF90aGlzOwogIH0KICByZXR1cm4gQ2xvc2VFdmVudDI7Cn0oRXZlbnQpOwp2YXIgZ2V0R2xvYmFsV2ViU29ja2V0ID0gZnVuY3Rpb24oKSB7CiAgaWYgKHR5cGVvZiBXZWJTb2NrZXQgIT09ICJ1bmRlZmluZWQiKSB7CiAgICByZXR1cm4gV2ViU29ja2V0OwogIH0KfTsKdmFyIGlzV2ViU29ja2V0ID0gZnVuY3Rpb24odykgewogIHJldHVybiB0eXBlb2YgdyAhPT0gInVuZGVmaW5lZCIgJiYgISF3ICYmIHcuQ0xPU0lORyA9PT0gMjsKfTsKdmFyIERFRkFVTFQgPSB7CiAgbWF4UmVjb25uZWN0aW9uRGVsYXk6IDFlNCwKICBtaW5SZWNvbm5lY3Rpb25EZWxheTogMWUzICsgTWF0aC5yYW5kb20oKSAqIDRlMywKICBtaW5VcHRpbWU6IDVlMywKICByZWNvbm5lY3Rpb25EZWxheUdyb3dGYWN0b3I6IDEuMywKICBjb25uZWN0aW9uVGltZW91dDogNGUzLAogIG1heFJldHJpZXM6IEluZmluaXR5LAogIG1heEVucXVldWVkTWVzc2FnZXM6IEluZmluaXR5LAogIHN0YXJ0Q2xvc2VkOiBmYWxzZSwKICBkZWJ1ZzogZmFsc2UKfTsKdmFyIFJlY29ubmVjdGluZ1dlYlNvY2tldCA9IGZ1bmN0aW9uKCkgewogIGZ1bmN0aW9uIFJlY29ubmVjdGluZ1dlYlNvY2tldDIodXJsLCBwcm90b2NvbHMsIG9wdGlvbnMpIHsKICAgIHZhciBfdGhpcyA9IHRoaXM7CiAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgIG9wdGlvbnMgPSB7fTsKICAgIH0KICAgIHRoaXMuX2xpc3RlbmVycyA9IHsKICAgICAgZXJyb3I6IFtdLAogICAgICBtZXNzYWdlOiBbXSwKICAgICAgb3BlbjogW10sCiAgICAgIGNsb3NlOiBbXQogICAgfTsKICAgIHRoaXMuX3JldHJ5Q291bnQgPSAtMTsKICAgIHRoaXMuX3Nob3VsZFJlY29ubmVjdCA9IHRydWU7CiAgICB0aGlzLl9jb25uZWN0TG9jayA9IGZhbHNlOwogICAgdGhpcy5fYmluYXJ5VHlwZSA9ICJibG9iIjsKICAgIHRoaXMuX2Nsb3NlQ2FsbGVkID0gZmFsc2U7CiAgICB0aGlzLl9tZXNzYWdlUXVldWUgPSBbXTsKICAgIHRoaXMub25jbG9zZSA9IG51bGw7CiAgICB0aGlzLm9uZXJyb3IgPSBudWxsOwogICAgdGhpcy5vbm1lc3NhZ2UgPSBudWxsOwogICAgdGhpcy5vbm9wZW4gPSBudWxsOwogICAgdGhpcy5faGFuZGxlT3BlbiA9IGZ1bmN0aW9uKGV2ZW50KSB7CiAgICAgIF90aGlzLl9kZWJ1Zygib3BlbiBldmVudCIpOwogICAgICB2YXIgX2EgPSBfdGhpcy5fb3B0aW9ucy5taW5VcHRpbWUsIG1pblVwdGltZSA9IF9hID09PSB2b2lkIDAgPyBERUZBVUxULm1pblVwdGltZSA6IF9hOwogICAgICBjbGVhclRpbWVvdXQoX3RoaXMuX2Nvbm5lY3RUaW1lb3V0KTsKICAgICAgX3RoaXMuX3VwdGltZVRpbWVvdXQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiBfdGhpcy5fYWNjZXB0T3BlbigpOwogICAgICB9LCBtaW5VcHRpbWUpOwogICAgICBfdGhpcy5fd3MuYmluYXJ5VHlwZSA9IF90aGlzLl9iaW5hcnlUeXBlOwogICAgICBfdGhpcy5fbWVzc2FnZVF1ZXVlLmZvckVhY2goZnVuY3Rpb24obWVzc2FnZSkgewogICAgICAgIHJldHVybiBfdGhpcy5fd3Muc2VuZChtZXNzYWdlKTsKICAgICAgfSk7CiAgICAgIF90aGlzLl9tZXNzYWdlUXVldWUgPSBbXTsKICAgICAgaWYgKF90aGlzLm9ub3BlbikgewogICAgICAgIF90aGlzLm9ub3BlbihldmVudCk7CiAgICAgIH0KICAgICAgX3RoaXMuX2xpc3RlbmVycy5vcGVuLmZvckVhY2goZnVuY3Rpb24obGlzdGVuZXIpIHsKICAgICAgICByZXR1cm4gX3RoaXMuX2NhbGxFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcik7CiAgICAgIH0pOwogICAgfTsKICAgIHRoaXMuX2hhbmRsZU1lc3NhZ2UgPSBmdW5jdGlvbihldmVudCkgewogICAgICBfdGhpcy5fZGVidWcoIm1lc3NhZ2UgZXZlbnQiKTsKICAgICAgaWYgKF90aGlzLm9ubWVzc2FnZSkgewogICAgICAgIF90aGlzLm9ubWVzc2FnZShldmVudCk7CiAgICAgIH0KICAgICAgX3RoaXMuX2xpc3RlbmVycy5tZXNzYWdlLmZvckVhY2goZnVuY3Rpb24obGlzdGVuZXIpIHsKICAgICAgICByZXR1cm4gX3RoaXMuX2NhbGxFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcik7CiAgICAgIH0pOwogICAgfTsKICAgIHRoaXMuX2hhbmRsZUVycm9yID0gZnVuY3Rpb24oZXZlbnQpIHsKICAgICAgX3RoaXMuX2RlYnVnKCJlcnJvciBldmVudCIsIGV2ZW50Lm1lc3NhZ2UpOwogICAgICBfdGhpcy5fZGlzY29ubmVjdCh2b2lkIDAsIGV2ZW50Lm1lc3NhZ2UgPT09ICJUSU1FT1VUIiA/ICJ0aW1lb3V0IiA6IHZvaWQgMCk7CiAgICAgIGlmIChfdGhpcy5vbmVycm9yKSB7CiAgICAgICAgX3RoaXMub25lcnJvcihldmVudCk7CiAgICAgIH0KICAgICAgX3RoaXMuX2RlYnVnKCJleGVjIGVycm9yIGxpc3RlbmVycyIpOwogICAgICBfdGhpcy5fbGlzdGVuZXJzLmVycm9yLmZvckVhY2goZnVuY3Rpb24obGlzdGVuZXIpIHsKICAgICAgICByZXR1cm4gX3RoaXMuX2NhbGxFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcik7CiAgICAgIH0pOwogICAgICBfdGhpcy5fY29ubmVjdCgpOwogICAgfTsKICAgIHRoaXMuX2hhbmRsZUNsb3NlID0gZnVuY3Rpb24oZXZlbnQpIHsKICAgICAgX3RoaXMuX2RlYnVnKCJjbG9zZSBldmVudCIpOwogICAgICBfdGhpcy5fY2xlYXJUaW1lb3V0cygpOwogICAgICBpZiAoX3RoaXMuX3Nob3VsZFJlY29ubmVjdCkgewogICAgICAgIF90aGlzLl9jb25uZWN0KCk7CiAgICAgIH0KICAgICAgaWYgKF90aGlzLm9uY2xvc2UpIHsKICAgICAgICBfdGhpcy5vbmNsb3NlKGV2ZW50KTsKICAgICAgfQogICAgICBfdGhpcy5fbGlzdGVuZXJzLmNsb3NlLmZvckVhY2goZnVuY3Rpb24obGlzdGVuZXIpIHsKICAgICAgICByZXR1cm4gX3RoaXMuX2NhbGxFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcik7CiAgICAgIH0pOwogICAgfTsKICAgIHRoaXMuX3VybCA9IHVybDsKICAgIHRoaXMuX3Byb3RvY29scyA9IHByb3RvY29sczsKICAgIHRoaXMuX29wdGlvbnMgPSBvcHRpb25zOwogICAgaWYgKHRoaXMuX29wdGlvbnMuc3RhcnRDbG9zZWQpIHsKICAgICAgdGhpcy5fc2hvdWxkUmVjb25uZWN0ID0gZmFsc2U7CiAgICB9CiAgICB0aGlzLl9jb25uZWN0KCk7CiAgfQogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLCAiQ09OTkVDVElORyIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiAwOwogICAgfSwKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBjb25maWd1cmFibGU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoUmVjb25uZWN0aW5nV2ViU29ja2V0MiwgIk9QRU4iLCB7CiAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gMTsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIsICJDTE9TSU5HIiwgewogICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgcmV0dXJuIDI7CiAgICB9LAogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLCAiQ0xPU0VEIiwgewogICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgcmV0dXJuIDM7CiAgICB9LAogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZSwgIkNPTk5FQ1RJTkciLCB7CiAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5DT05ORUNUSU5HOwogICAgfSwKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBjb25maWd1cmFibGU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUsICJPUEVOIiwgewogICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgcmV0dXJuIFJlY29ubmVjdGluZ1dlYlNvY2tldDIuT1BFTjsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAiQ0xPU0lORyIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLkNMT1NJTkc7CiAgICB9LAogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZQogIH0pOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZSwgIkNMT1NFRCIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLkNMT1NFRDsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAiYmluYXJ5VHlwZSIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiB0aGlzLl93cyA/IHRoaXMuX3dzLmJpbmFyeVR5cGUgOiB0aGlzLl9iaW5hcnlUeXBlOwogICAgfSwKICAgIHNldDogZnVuY3Rpb24odmFsdWUpIHsKICAgICAgdGhpcy5fYmluYXJ5VHlwZSA9IHZhbHVlOwogICAgICBpZiAodGhpcy5fd3MpIHsKICAgICAgICB0aGlzLl93cy5iaW5hcnlUeXBlID0gdmFsdWU7CiAgICAgIH0KICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAicmV0cnlDb3VudCIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiBNYXRoLm1heCh0aGlzLl9yZXRyeUNvdW50LCAwKTsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAiYnVmZmVyZWRBbW91bnQiLCB7CiAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICB2YXIgYnl0ZXMgPSB0aGlzLl9tZXNzYWdlUXVldWUucmVkdWNlKGZ1bmN0aW9uKGFjYywgbWVzc2FnZSkgewogICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSA9PT0gInN0cmluZyIpIHsKICAgICAgICAgIGFjYyArPSBtZXNzYWdlLmxlbmd0aDsKICAgICAgICB9IGVsc2UgaWYgKG1lc3NhZ2UgaW5zdGFuY2VvZiBCbG9iKSB7CiAgICAgICAgICBhY2MgKz0gbWVzc2FnZS5zaXplOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBhY2MgKz0gbWVzc2FnZS5ieXRlTGVuZ3RoOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYWNjOwogICAgICB9LCAwKTsKICAgICAgcmV0dXJuIGJ5dGVzICsgKHRoaXMuX3dzID8gdGhpcy5fd3MuYnVmZmVyZWRBbW91bnQgOiAwKTsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAiZXh0ZW5zaW9ucyIsIHsKICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiB0aGlzLl93cyA/IHRoaXMuX3dzLmV4dGVuc2lvbnMgOiAiIjsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAicHJvdG9jb2wiLCB7CiAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gdGhpcy5fd3MgPyB0aGlzLl93cy5wcm90b2NvbCA6ICIiOwogICAgfSwKICAgIGVudW1lcmFibGU6IHRydWUsCiAgICBjb25maWd1cmFibGU6IHRydWUKICB9KTsKICBPYmplY3QuZGVmaW5lUHJvcGVydHkoUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUsICJyZWFkeVN0YXRlIiwgewogICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgaWYgKHRoaXMuX3dzKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuX3dzLnJlYWR5U3RhdGU7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnMuc3RhcnRDbG9zZWQgPyBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLkNMT1NFRCA6IFJlY29ubmVjdGluZ1dlYlNvY2tldDIuQ09OTkVDVElORzsKICAgIH0sCiAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgY29uZmlndXJhYmxlOiB0cnVlCiAgfSk7CiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLCAidXJsIiwgewogICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgcmV0dXJuIHRoaXMuX3dzID8gdGhpcy5fd3MudXJsIDogIiI7CiAgICB9LAogICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZQogIH0pOwogIFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLmNsb3NlID0gZnVuY3Rpb24oY29kZSwgcmVhc29uKSB7CiAgICBpZiAoY29kZSA9PT0gdm9pZCAwKSB7CiAgICAgIGNvZGUgPSAxZTM7CiAgICB9CiAgICB0aGlzLl9jbG9zZUNhbGxlZCA9IHRydWU7CiAgICB0aGlzLl9zaG91bGRSZWNvbm5lY3QgPSBmYWxzZTsKICAgIHRoaXMuX2NsZWFyVGltZW91dHMoKTsKICAgIGlmICghdGhpcy5fd3MpIHsKICAgICAgdGhpcy5fZGVidWcoImNsb3NlIGVucXVldWVkOiBubyB3cyBpbnN0YW5jZSIpOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAodGhpcy5fd3MucmVhZHlTdGF0ZSA9PT0gdGhpcy5DTE9TRUQpIHsKICAgICAgdGhpcy5fZGVidWcoImNsb3NlOiBhbHJlYWR5IGNsb3NlZCIpOwogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl93cy5jbG9zZShjb2RlLCByZWFzb24pOwogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUucmVjb25uZWN0ID0gZnVuY3Rpb24oY29kZSwgcmVhc29uKSB7CiAgICB0aGlzLl9zaG91bGRSZWNvbm5lY3QgPSB0cnVlOwogICAgdGhpcy5fY2xvc2VDYWxsZWQgPSBmYWxzZTsKICAgIHRoaXMuX3JldHJ5Q291bnQgPSAtMTsKICAgIGlmICghdGhpcy5fd3MgfHwgdGhpcy5fd3MucmVhZHlTdGF0ZSA9PT0gdGhpcy5DTE9TRUQpIHsKICAgICAgdGhpcy5fY29ubmVjdCgpOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5fZGlzY29ubmVjdChjb2RlLCByZWFzb24pOwogICAgICB0aGlzLl9jb25uZWN0KCk7CiAgICB9CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5zZW5kID0gZnVuY3Rpb24oZGF0YSkgewogICAgaWYgKHRoaXMuX3dzICYmIHRoaXMuX3dzLnJlYWR5U3RhdGUgPT09IHRoaXMuT1BFTikgewogICAgICB0aGlzLl9kZWJ1Zygic2VuZCIsIGRhdGEpOwogICAgICB0aGlzLl93cy5zZW5kKGRhdGEpOwogICAgfSBlbHNlIHsKICAgICAgdmFyIF9hID0gdGhpcy5fb3B0aW9ucy5tYXhFbnF1ZXVlZE1lc3NhZ2VzLCBtYXhFbnF1ZXVlZE1lc3NhZ2VzID0gX2EgPT09IHZvaWQgMCA/IERFRkFVTFQubWF4RW5xdWV1ZWRNZXNzYWdlcyA6IF9hOwogICAgICBpZiAodGhpcy5fbWVzc2FnZVF1ZXVlLmxlbmd0aCA8IG1heEVucXVldWVkTWVzc2FnZXMpIHsKICAgICAgICB0aGlzLl9kZWJ1ZygiZW5xdWV1ZSIsIGRhdGEpOwogICAgICAgIHRoaXMuX21lc3NhZ2VRdWV1ZS5wdXNoKGRhdGEpOwogICAgICB9CiAgICB9CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5hZGRFdmVudExpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHsKICAgIGlmICh0aGlzLl9saXN0ZW5lcnNbdHlwZV0pIHsKICAgICAgdGhpcy5fbGlzdGVuZXJzW3R5cGVdLnB1c2gobGlzdGVuZXIpOwogICAgfQogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuZGlzcGF0Y2hFdmVudCA9IGZ1bmN0aW9uKGV2ZW50KSB7CiAgICB2YXIgZV8xLCBfYTsKICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLl9saXN0ZW5lcnNbZXZlbnQudHlwZV07CiAgICBpZiAobGlzdGVuZXJzKSB7CiAgICAgIHRyeSB7CiAgICAgICAgZm9yICh2YXIgbGlzdGVuZXJzXzEgPSBfX3ZhbHVlcyhsaXN0ZW5lcnMpLCBsaXN0ZW5lcnNfMV8xID0gbGlzdGVuZXJzXzEubmV4dCgpOyAhbGlzdGVuZXJzXzFfMS5kb25lOyBsaXN0ZW5lcnNfMV8xID0gbGlzdGVuZXJzXzEubmV4dCgpKSB7CiAgICAgICAgICB2YXIgbGlzdGVuZXIgPSBsaXN0ZW5lcnNfMV8xLnZhbHVlOwogICAgICAgICAgdGhpcy5fY2FsbEV2ZW50TGlzdGVuZXIoZXZlbnQsIGxpc3RlbmVyKTsKICAgICAgICB9CiAgICAgIH0gY2F0Y2ggKGVfMV8xKSB7CiAgICAgICAgZV8xID0geyBlcnJvcjogZV8xXzEgfTsKICAgICAgfSBmaW5hbGx5IHsKICAgICAgICB0cnkgewogICAgICAgICAgaWYgKGxpc3RlbmVyc18xXzEgJiYgIWxpc3RlbmVyc18xXzEuZG9uZSAmJiAoX2EgPSBsaXN0ZW5lcnNfMS5yZXR1cm4pKQogICAgICAgICAgICBfYS5jYWxsKGxpc3RlbmVyc18xKTsKICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgaWYgKGVfMSkKICAgICAgICAgICAgdGhyb3cgZV8xLmVycm9yOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIHRydWU7CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5yZW1vdmVFdmVudExpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHsKICAgIGlmICh0aGlzLl9saXN0ZW5lcnNbdHlwZV0pIHsKICAgICAgdGhpcy5fbGlzdGVuZXJzW3R5cGVdID0gdGhpcy5fbGlzdGVuZXJzW3R5cGVdLmZpbHRlcihmdW5jdGlvbihsKSB7CiAgICAgICAgcmV0dXJuIGwgIT09IGxpc3RlbmVyOwogICAgICB9KTsKICAgIH0KICB9OwogIFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLl9kZWJ1ZyA9IGZ1bmN0aW9uKCkgewogICAgdmFyIGFyZ3MgPSBbXTsKICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7CiAgICAgIGFyZ3NbX2ldID0gYXJndW1lbnRzW19pXTsKICAgIH0KICAgIGlmICh0aGlzLl9vcHRpb25zLmRlYnVnKSB7CiAgICAgIGNvbnNvbGUubG9nLmFwcGx5KGNvbnNvbGUsIF9fc3ByZWFkKFsiUldTPiJdLCBhcmdzKSk7CiAgICB9CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5fZ2V0TmV4dERlbGF5ID0gZnVuY3Rpb24oKSB7CiAgICB2YXIgX2EgPSB0aGlzLl9vcHRpb25zLCBfYiA9IF9hLnJlY29ubmVjdGlvbkRlbGF5R3Jvd0ZhY3RvciwgcmVjb25uZWN0aW9uRGVsYXlHcm93RmFjdG9yID0gX2IgPT09IHZvaWQgMCA/IERFRkFVTFQucmVjb25uZWN0aW9uRGVsYXlHcm93RmFjdG9yIDogX2IsIF9jID0gX2EubWluUmVjb25uZWN0aW9uRGVsYXksIG1pblJlY29ubmVjdGlvbkRlbGF5ID0gX2MgPT09IHZvaWQgMCA/IERFRkFVTFQubWluUmVjb25uZWN0aW9uRGVsYXkgOiBfYywgX2QgPSBfYS5tYXhSZWNvbm5lY3Rpb25EZWxheSwgbWF4UmVjb25uZWN0aW9uRGVsYXkgPSBfZCA9PT0gdm9pZCAwID8gREVGQVVMVC5tYXhSZWNvbm5lY3Rpb25EZWxheSA6IF9kOwogICAgdmFyIGRlbGF5ID0gMDsKICAgIGlmICh0aGlzLl9yZXRyeUNvdW50ID4gMCkgewogICAgICBkZWxheSA9IG1pblJlY29ubmVjdGlvbkRlbGF5ICogTWF0aC5wb3cocmVjb25uZWN0aW9uRGVsYXlHcm93RmFjdG9yLCB0aGlzLl9yZXRyeUNvdW50IC0gMSk7CiAgICAgIGlmIChkZWxheSA+IG1heFJlY29ubmVjdGlvbkRlbGF5KSB7CiAgICAgICAgZGVsYXkgPSBtYXhSZWNvbm5lY3Rpb25EZWxheTsKICAgICAgfQogICAgfQogICAgdGhpcy5fZGVidWcoIm5leHQgZGVsYXkiLCBkZWxheSk7CiAgICByZXR1cm4gZGVsYXk7CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5fd2FpdCA9IGZ1bmN0aW9uKCkgewogICAgdmFyIF90aGlzID0gdGhpczsKICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlKSB7CiAgICAgIHNldFRpbWVvdXQocmVzb2x2ZSwgX3RoaXMuX2dldE5leHREZWxheSgpKTsKICAgIH0pOwogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuX2dldE5leHRVcmwgPSBmdW5jdGlvbih1cmxQcm92aWRlcikgewogICAgaWYgKHR5cGVvZiB1cmxQcm92aWRlciA9PT0gInN0cmluZyIpIHsKICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh1cmxQcm92aWRlcik7CiAgICB9CiAgICBpZiAodHlwZW9mIHVybFByb3ZpZGVyID09PSAiZnVuY3Rpb24iKSB7CiAgICAgIHZhciB1cmwgPSB1cmxQcm92aWRlcigpOwogICAgICBpZiAodHlwZW9mIHVybCA9PT0gInN0cmluZyIpIHsKICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHVybCk7CiAgICAgIH0KICAgICAgaWYgKCEhdXJsLnRoZW4pIHsKICAgICAgICByZXR1cm4gdXJsOwogICAgICB9CiAgICB9CiAgICB0aHJvdyBFcnJvcigiSW52YWxpZCBVUkwiKTsKICB9OwogIFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLl9jb25uZWN0ID0gZnVuY3Rpb24oKSB7CiAgICB2YXIgX3RoaXMgPSB0aGlzOwogICAgaWYgKHRoaXMuX2Nvbm5lY3RMb2NrIHx8ICF0aGlzLl9zaG91bGRSZWNvbm5lY3QpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5fY29ubmVjdExvY2sgPSB0cnVlOwogICAgdmFyIF9hID0gdGhpcy5fb3B0aW9ucywgX2IgPSBfYS5tYXhSZXRyaWVzLCBtYXhSZXRyaWVzID0gX2IgPT09IHZvaWQgMCA/IERFRkFVTFQubWF4UmV0cmllcyA6IF9iLCBfYyA9IF9hLmNvbm5lY3Rpb25UaW1lb3V0LCBjb25uZWN0aW9uVGltZW91dCA9IF9jID09PSB2b2lkIDAgPyBERUZBVUxULmNvbm5lY3Rpb25UaW1lb3V0IDogX2MsIF9kID0gX2EuV2ViU29ja2V0LCBXZWJTb2NrZXQyID0gX2QgPT09IHZvaWQgMCA/IGdldEdsb2JhbFdlYlNvY2tldCgpIDogX2Q7CiAgICBpZiAodGhpcy5fcmV0cnlDb3VudCA+PSBtYXhSZXRyaWVzKSB7CiAgICAgIHRoaXMuX2RlYnVnKCJtYXggcmV0cmllcyByZWFjaGVkIiwgdGhpcy5fcmV0cnlDb3VudCwgIj49IiwgbWF4UmV0cmllcyk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuX3JldHJ5Q291bnQrKzsKICAgIHRoaXMuX2RlYnVnKCJjb25uZWN0IiwgdGhpcy5fcmV0cnlDb3VudCk7CiAgICB0aGlzLl9yZW1vdmVMaXN0ZW5lcnMoKTsKICAgIGlmICghaXNXZWJTb2NrZXQoV2ViU29ja2V0MikpIHsKICAgICAgdGhyb3cgRXJyb3IoIk5vIHZhbGlkIFdlYlNvY2tldCBjbGFzcyBwcm92aWRlZCIpOwogICAgfQogICAgdGhpcy5fd2FpdCgpLnRoZW4oZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiBfdGhpcy5fZ2V0TmV4dFVybChfdGhpcy5fdXJsKTsKICAgIH0pLnRoZW4oZnVuY3Rpb24odXJsKSB7CiAgICAgIGlmIChfdGhpcy5fY2xvc2VDYWxsZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgX3RoaXMuX2RlYnVnKCJjb25uZWN0IiwgeyB1cmwsIHByb3RvY29sczogX3RoaXMuX3Byb3RvY29scyB9KTsKICAgICAgX3RoaXMuX3dzID0gX3RoaXMuX3Byb3RvY29scyA/IG5ldyBXZWJTb2NrZXQyKHVybCwgX3RoaXMuX3Byb3RvY29scykgOiBuZXcgV2ViU29ja2V0Mih1cmwpOwogICAgICBfdGhpcy5fd3MuYmluYXJ5VHlwZSA9IF90aGlzLl9iaW5hcnlUeXBlOwogICAgICBfdGhpcy5fY29ubmVjdExvY2sgPSBmYWxzZTsKICAgICAgX3RoaXMuX2FkZExpc3RlbmVycygpOwogICAgICBfdGhpcy5fY29ubmVjdFRpbWVvdXQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiBfdGhpcy5faGFuZGxlVGltZW91dCgpOwogICAgICB9LCBjb25uZWN0aW9uVGltZW91dCk7CiAgICB9KTsKICB9OwogIFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLl9oYW5kbGVUaW1lb3V0ID0gZnVuY3Rpb24oKSB7CiAgICB0aGlzLl9kZWJ1ZygidGltZW91dCBldmVudCIpOwogICAgdGhpcy5faGFuZGxlRXJyb3IobmV3IEVycm9yRXZlbnQoRXJyb3IoIlRJTUVPVVQiKSwgdGhpcykpOwogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuX2Rpc2Nvbm5lY3QgPSBmdW5jdGlvbihjb2RlLCByZWFzb24pIHsKICAgIGlmIChjb2RlID09PSB2b2lkIDApIHsKICAgICAgY29kZSA9IDFlMzsKICAgIH0KICAgIHRoaXMuX2NsZWFyVGltZW91dHMoKTsKICAgIGlmICghdGhpcy5fd3MpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5fcmVtb3ZlTGlzdGVuZXJzKCk7CiAgICB0cnkgewogICAgICB0aGlzLl93cy5jbG9zZShjb2RlLCByZWFzb24pOwogICAgICB0aGlzLl9oYW5kbGVDbG9zZShuZXcgQ2xvc2VFdmVudChjb2RlLCByZWFzb24sIHRoaXMpKTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICB9CiAgfTsKICBSZWNvbm5lY3RpbmdXZWJTb2NrZXQyLnByb3RvdHlwZS5fYWNjZXB0T3BlbiA9IGZ1bmN0aW9uKCkgewogICAgdGhpcy5fZGVidWcoImFjY2VwdCBvcGVuIik7CiAgICB0aGlzLl9yZXRyeUNvdW50ID0gMDsKICB9OwogIFJlY29ubmVjdGluZ1dlYlNvY2tldDIucHJvdG90eXBlLl9jYWxsRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uKGV2ZW50LCBsaXN0ZW5lcikgewogICAgaWYgKCJoYW5kbGVFdmVudCIgaW4gbGlzdGVuZXIpIHsKICAgICAgbGlzdGVuZXIuaGFuZGxlRXZlbnQoZXZlbnQpOwogICAgfSBlbHNlIHsKICAgICAgbGlzdGVuZXIoZXZlbnQpOwogICAgfQogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuX3JlbW92ZUxpc3RlbmVycyA9IGZ1bmN0aW9uKCkgewogICAgaWYgKCF0aGlzLl93cykgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9kZWJ1ZygicmVtb3ZlTGlzdGVuZXJzIik7CiAgICB0aGlzLl93cy5yZW1vdmVFdmVudExpc3RlbmVyKCJvcGVuIiwgdGhpcy5faGFuZGxlT3Blbik7CiAgICB0aGlzLl93cy5yZW1vdmVFdmVudExpc3RlbmVyKCJjbG9zZSIsIHRoaXMuX2hhbmRsZUNsb3NlKTsKICAgIHRoaXMuX3dzLnJlbW92ZUV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLCB0aGlzLl9oYW5kbGVNZXNzYWdlKTsKICAgIHRoaXMuX3dzLnJlbW92ZUV2ZW50TGlzdGVuZXIoImVycm9yIiwgdGhpcy5faGFuZGxlRXJyb3IpOwogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuX2FkZExpc3RlbmVycyA9IGZ1bmN0aW9uKCkgewogICAgaWYgKCF0aGlzLl93cykgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9kZWJ1ZygiYWRkTGlzdGVuZXJzIik7CiAgICB0aGlzLl93cy5hZGRFdmVudExpc3RlbmVyKCJvcGVuIiwgdGhpcy5faGFuZGxlT3Blbik7CiAgICB0aGlzLl93cy5hZGRFdmVudExpc3RlbmVyKCJjbG9zZSIsIHRoaXMuX2hhbmRsZUNsb3NlKTsKICAgIHRoaXMuX3dzLmFkZEV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLCB0aGlzLl9oYW5kbGVNZXNzYWdlKTsKICAgIHRoaXMuX3dzLmFkZEV2ZW50TGlzdGVuZXIoImVycm9yIiwgdGhpcy5faGFuZGxlRXJyb3IpOwogIH07CiAgUmVjb25uZWN0aW5nV2ViU29ja2V0Mi5wcm90b3R5cGUuX2NsZWFyVGltZW91dHMgPSBmdW5jdGlvbigpIHsKICAgIGNsZWFyVGltZW91dCh0aGlzLl9jb25uZWN0VGltZW91dCk7CiAgICBjbGVhclRpbWVvdXQodGhpcy5fdXB0aW1lVGltZW91dCk7CiAgfTsKICByZXR1cm4gUmVjb25uZWN0aW5nV2ViU29ja2V0MjsKfSgpOwp2YXIgcmVjb25uZWN0aW5nX3dlYnNvY2tldF9tanNfZGVmYXVsdCA9IFJlY29ubmVjdGluZ1dlYlNvY2tldDsKCi8vIG5vZGVfbW9kdWxlcy9AYmpvcm4zL2Jyb3dzZXJfd2FzaV9zaGltL2Rpc3Qvd2FzaV9kZWZzLmpzCnZhciBDTE9DS0lEX1JFQUxUSU1FID0gMDsKdmFyIENMT0NLSURfTU9OT1RPTklDID0gMTsKdmFyIEVSUk5PX1NVQ0NFU1MgPSAwOwp2YXIgRVJSTk9fQkFERiA9IDg7CnZhciBFUlJOT19FWElTVCA9IDIwOwp2YXIgRVJSTk9fSU5WQUwgPSAyODsKdmFyIEVSUk5PX0lTRElSID0gMzE7CnZhciBFUlJOT19OQU1FVE9PTE9ORyA9IDM3Owp2YXIgRVJSTk9fTk9FTlQgPSA0NDsKdmFyIEVSUk5PX05PU1lTID0gNTI7CnZhciBFUlJOT19OT1RESVIgPSA1NDsKdmFyIEVSUk5PX05PVEVNUFRZID0gNTU7CnZhciBFUlJOT19OT1RTVVAgPSA1ODsKdmFyIEVSUk5PX1BFUk0gPSA2MzsKdmFyIEVSUk5PX05PVENBUEFCTEUgPSA3NjsKdmFyIFJJR0hUU19GRF9EQVRBU1lOQyA9IDEgPDwgMDsKdmFyIFJJR0hUU19GRF9SRUFEID0gMSA8PCAxOwp2YXIgUklHSFRTX0ZEX1NFRUsgPSAxIDw8IDI7CnZhciBSSUdIVFNfRkRfRkRTVEFUX1NFVF9GTEFHUyA9IDEgPDwgMzsKdmFyIFJJR0hUU19GRF9TWU5DID0gMSA8PCA0Owp2YXIgUklHSFRTX0ZEX1RFTEwgPSAxIDw8IDU7CnZhciBSSUdIVFNfRkRfV1JJVEUgPSAxIDw8IDY7CnZhciBSSUdIVFNfRkRfQURWSVNFID0gMSA8PCA3Owp2YXIgUklHSFRTX0ZEX0FMTE9DQVRFID0gMSA8PCA4Owp2YXIgUklHSFRTX1BBVEhfQ1JFQVRFX0RJUkVDVE9SWSA9IDEgPDwgOTsKdmFyIFJJR0hUU19QQVRIX0NSRUFURV9GSUxFID0gMSA8PCAxMDsKdmFyIFJJR0hUU19QQVRIX0xJTktfU09VUkNFID0gMSA8PCAxMTsKdmFyIFJJR0hUU19QQVRIX0xJTktfVEFSR0VUID0gMSA8PCAxMjsKdmFyIFJJR0hUU19QQVRIX09QRU4gPSAxIDw8IDEzOwp2YXIgUklHSFRTX0ZEX1JFQURESVIgPSAxIDw8IDE0Owp2YXIgUklHSFRTX1BBVEhfUkVBRExJTksgPSAxIDw8IDE1Owp2YXIgUklHSFRTX1BBVEhfUkVOQU1FX1NPVVJDRSA9IDEgPDwgMTY7CnZhciBSSUdIVFNfUEFUSF9SRU5BTUVfVEFSR0VUID0gMSA8PCAxNzsKdmFyIFJJR0hUU19QQVRIX0ZJTEVTVEFUX0dFVCA9IDEgPDwgMTg7CnZhciBSSUdIVFNfUEFUSF9GSUxFU1RBVF9TRVRfU0laRSA9IDEgPDwgMTk7CnZhciBSSUdIVFNfUEFUSF9GSUxFU1RBVF9TRVRfVElNRVMgPSAxIDw8IDIwOwp2YXIgUklHSFRTX0ZEX0ZJTEVTVEFUX0dFVCA9IDEgPDwgMjE7CnZhciBSSUdIVFNfRkRfRklMRVNUQVRfU0VUX1NJWkUgPSAxIDw8IDIyOwp2YXIgUklHSFRTX0ZEX0ZJTEVTVEFUX1NFVF9USU1FUyA9IDEgPDwgMjM7CnZhciBSSUdIVFNfUEFUSF9TWU1MSU5LID0gMSA8PCAyNDsKdmFyIFJJR0hUU19QQVRIX1JFTU9WRV9ESVJFQ1RPUlkgPSAxIDw8IDI1Owp2YXIgUklHSFRTX1BBVEhfVU5MSU5LX0ZJTEUgPSAxIDw8IDI2Owp2YXIgUklHSFRTX1BPTExfRkRfUkVBRFdSSVRFID0gMSA8PCAyNzsKdmFyIFJJR0hUU19TT0NLX1NIVVRET1dOID0gMSA8PCAyODsKdmFyIElvdmVjID0gY2xhc3MgewogIHN0YXRpYyByZWFkX2J5dGVzKHZpZXcsIHB0cikgewogICAgY29uc3QgaW92ZWMgPSBuZXcgSW92ZWMoKTsKICAgIGlvdmVjLmJ1ZiA9IHZpZXcuZ2V0VWludDMyKHB0ciwgdHJ1ZSk7CiAgICBpb3ZlYy5idWZfbGVuID0gdmlldy5nZXRVaW50MzIocHRyICsgNCwgdHJ1ZSk7CiAgICByZXR1cm4gaW92ZWM7CiAgfQogIHN0YXRpYyByZWFkX2J5dGVzX2FycmF5KHZpZXcsIHB0ciwgbGVuKSB7CiAgICBjb25zdCBpb3ZlY3MgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHsKICAgICAgaW92ZWNzLnB1c2goSW92ZWMucmVhZF9ieXRlcyh2aWV3LCBwdHIgKyA4ICogaSkpOwogICAgfQogICAgcmV0dXJuIGlvdmVjczsKICB9Cn07CnZhciBDaW92ZWMgPSBjbGFzcyB7CiAgc3RhdGljIHJlYWRfYnl0ZXModmlldywgcHRyKSB7CiAgICBjb25zdCBpb3ZlYyA9IG5ldyBDaW92ZWMoKTsKICAgIGlvdmVjLmJ1ZiA9IHZpZXcuZ2V0VWludDMyKHB0ciwgdHJ1ZSk7CiAgICBpb3ZlYy5idWZfbGVuID0gdmlldy5nZXRVaW50MzIocHRyICsgNCwgdHJ1ZSk7CiAgICByZXR1cm4gaW92ZWM7CiAgfQogIHN0YXRpYyByZWFkX2J5dGVzX2FycmF5KHZpZXcsIHB0ciwgbGVuKSB7CiAgICBjb25zdCBpb3ZlY3MgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHsKICAgICAgaW92ZWNzLnB1c2goQ2lvdmVjLnJlYWRfYnl0ZXModmlldywgcHRyICsgOCAqIGkpKTsKICAgIH0KICAgIHJldHVybiBpb3ZlY3M7CiAgfQp9Owp2YXIgV0hFTkNFX1NFVCA9IDA7CnZhciBXSEVOQ0VfQ1VSID0gMTsKdmFyIFdIRU5DRV9FTkQgPSAyOwp2YXIgRklMRVRZUEVfQ0hBUkFDVEVSX0RFVklDRSA9IDI7CnZhciBGSUxFVFlQRV9ESVJFQ1RPUlkgPSAzOwp2YXIgRklMRVRZUEVfUkVHVUxBUl9GSUxFID0gNDsKdmFyIERpcmVudCA9IGNsYXNzIHsKICBoZWFkX2xlbmd0aCgpIHsKICAgIHJldHVybiAyNDsKICB9CiAgbmFtZV9sZW5ndGgoKSB7CiAgICByZXR1cm4gdGhpcy5kaXJfbmFtZS5ieXRlTGVuZ3RoOwogIH0KICB3cml0ZV9oZWFkX2J5dGVzKHZpZXcsIHB0cikgewogICAgdmlldy5zZXRCaWdVaW50NjQocHRyLCB0aGlzLmRfbmV4dCwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA4LCB0aGlzLmRfaW5vLCB0cnVlKTsKICAgIHZpZXcuc2V0VWludDMyKHB0ciArIDE2LCB0aGlzLmRpcl9uYW1lLmxlbmd0aCwgdHJ1ZSk7CiAgICB2aWV3LnNldFVpbnQ4KHB0ciArIDIwLCB0aGlzLmRfdHlwZSk7CiAgfQogIHdyaXRlX25hbWVfYnl0ZXModmlldzgsIHB0ciwgYnVmX2xlbikgewogICAgdmlldzguc2V0KHRoaXMuZGlyX25hbWUuc2xpY2UoMCwgTWF0aC5taW4odGhpcy5kaXJfbmFtZS5ieXRlTGVuZ3RoLCBidWZfbGVuKSksIHB0cik7CiAgfQogIGNvbnN0cnVjdG9yKG5leHRfY29va2llLCBuYW1lLCB0eXBlKSB7CiAgICB0aGlzLmRfaW5vID0gMG47CiAgICBjb25zdCBlbmNvZGVkX25hbWUgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUobmFtZSk7CiAgICB0aGlzLmRfbmV4dCA9IG5leHRfY29va2llOwogICAgdGhpcy5kX25hbWxlbiA9IGVuY29kZWRfbmFtZS5ieXRlTGVuZ3RoOwogICAgdGhpcy5kX3R5cGUgPSB0eXBlOwogICAgdGhpcy5kaXJfbmFtZSA9IGVuY29kZWRfbmFtZTsKICB9Cn07CnZhciBGREZMQUdTX0FQUEVORCA9IDEgPDwgMDsKdmFyIEZERkxBR1NfRFNZTkMgPSAxIDw8IDE7CnZhciBGREZMQUdTX05PTkJMT0NLID0gMSA8PCAyOwp2YXIgRkRGTEFHU19SU1lOQyA9IDEgPDwgMzsKdmFyIEZERkxBR1NfU1lOQyA9IDEgPDwgNDsKdmFyIEZkc3RhdCA9IGNsYXNzIHsKICB3cml0ZV9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIHZpZXcuc2V0VWludDgocHRyLCB0aGlzLmZzX2ZpbGV0eXBlKTsKICAgIHZpZXcuc2V0VWludDE2KHB0ciArIDIsIHRoaXMuZnNfZmxhZ3MsIHRydWUpOwogICAgdmlldy5zZXRCaWdVaW50NjQocHRyICsgOCwgdGhpcy5mc19yaWdodHNfYmFzZSwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyAxNiwgdGhpcy5mc19yaWdodHNfaW5oZXJpdGVkLCB0cnVlKTsKICB9CiAgY29uc3RydWN0b3IoZmlsZXR5cGUsIGZsYWdzKSB7CiAgICB0aGlzLmZzX3JpZ2h0c19iYXNlID0gMG47CiAgICB0aGlzLmZzX3JpZ2h0c19pbmhlcml0ZWQgPSAwbjsKICAgIHRoaXMuZnNfZmlsZXR5cGUgPSBmaWxldHlwZTsKICAgIHRoaXMuZnNfZmxhZ3MgPSBmbGFnczsKICB9Cn07CnZhciBGU1RGTEFHU19BVElNID0gMSA8PCAwOwp2YXIgRlNURkxBR1NfQVRJTV9OT1cgPSAxIDw8IDE7CnZhciBGU1RGTEFHU19NVElNID0gMSA8PCAyOwp2YXIgRlNURkxBR1NfTVRJTV9OT1cgPSAxIDw8IDM7CnZhciBPRkxBR1NfQ1JFQVQgPSAxIDw8IDA7CnZhciBPRkxBR1NfRElSRUNUT1JZID0gMSA8PCAxOwp2YXIgT0ZMQUdTX0VYQ0wgPSAxIDw8IDI7CnZhciBPRkxBR1NfVFJVTkMgPSAxIDw8IDM7CnZhciBGaWxlc3RhdCA9IGNsYXNzIHsKICB3cml0ZV9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciwgdGhpcy5kZXYsIHRydWUpOwogICAgdmlldy5zZXRCaWdVaW50NjQocHRyICsgOCwgdGhpcy5pbm8sIHRydWUpOwogICAgdmlldy5zZXRVaW50OChwdHIgKyAxNiwgdGhpcy5maWxldHlwZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyAyNCwgdGhpcy5ubGluaywgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyAzMiwgdGhpcy5zaXplLCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDM4LCB0aGlzLmF0aW0sIHRydWUpOwogICAgdmlldy5zZXRCaWdVaW50NjQocHRyICsgNDYsIHRoaXMubXRpbSwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA1MiwgdGhpcy5jdGltLCB0cnVlKTsKICB9CiAgY29uc3RydWN0b3IoZmlsZXR5cGUsIHNpemUpIHsKICAgIHRoaXMuZGV2ID0gMG47CiAgICB0aGlzLmlubyA9IDBuOwogICAgdGhpcy5ubGluayA9IDBuOwogICAgdGhpcy5hdGltID0gMG47CiAgICB0aGlzLm10aW0gPSAwbjsKICAgIHRoaXMuY3RpbSA9IDBuOwogICAgdGhpcy5maWxldHlwZSA9IGZpbGV0eXBlOwogICAgdGhpcy5zaXplID0gc2l6ZTsKICB9Cn07CnZhciBFVkVOVFJXRkxBR1NfRkRfUkVBRFdSSVRFX0hBTkdVUCA9IDEgPDwgMDsKdmFyIFNVQkNMT0NLRkxBR1NfU1VCU0NSSVBUSU9OX0NMT0NLX0FCU1RJTUUgPSAxIDw8IDA7CnZhciBSSUZMQUdTX1JFQ1ZfUEVFSyA9IDEgPDwgMDsKdmFyIFJJRkxBR1NfUkVDVl9XQUlUQUxMID0gMSA8PCAxOwp2YXIgUk9GTEFHU19SRUNWX0RBVEFfVFJVTkNBVEVEID0gMSA8PCAwOwp2YXIgU0RGTEFHU19SRCA9IDEgPDwgMDsKdmFyIFNERkxBR1NfV1IgPSAxIDw8IDE7CnZhciBQUkVPUEVOVFlQRV9ESVIgPSAwOwp2YXIgUHJlc3RhdERpciA9IGNsYXNzIHsKICB3cml0ZV9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIHZpZXcuc2V0VWludDMyKHB0ciwgdGhpcy5wcl9uYW1lLmJ5dGVMZW5ndGgsIHRydWUpOwogIH0KICBjb25zdHJ1Y3RvcihuYW1lKSB7CiAgICB0aGlzLnByX25hbWUgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUobmFtZSk7CiAgfQp9Owp2YXIgUHJlc3RhdCA9IGNsYXNzIHsKICBzdGF0aWMgZGlyKG5hbWUpIHsKICAgIGNvbnN0IHByZXN0YXQgPSBuZXcgUHJlc3RhdCgpOwogICAgcHJlc3RhdC50YWcgPSBQUkVPUEVOVFlQRV9ESVI7CiAgICBwcmVzdGF0LmlubmVyID0gbmV3IFByZXN0YXREaXIobmFtZSk7CiAgICByZXR1cm4gcHJlc3RhdDsKICB9CiAgd3JpdGVfYnl0ZXModmlldywgcHRyKSB7CiAgICB2aWV3LnNldFVpbnQzMihwdHIsIHRoaXMudGFnLCB0cnVlKTsKICAgIHRoaXMuaW5uZXIud3JpdGVfYnl0ZXModmlldywgcHRyICsgNCk7CiAgfQp9OwoKLy8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC9kZWJ1Zy5qcwp2YXIgRGVidWcgPSBjbGFzcyBEZWJ1ZzIgewogIGVuYWJsZShlbmFibGVkKSB7CiAgICB0aGlzLmxvZyA9IGNyZWF0ZUxvZ2dlcihlbmFibGVkID09PSB2b2lkIDAgPyB0cnVlIDogZW5hYmxlZCwgdGhpcy5wcmVmaXgpOwogIH0KICBnZXQgZW5hYmxlZCgpIHsKICAgIHJldHVybiB0aGlzLmlzRW5hYmxlZDsKICB9CiAgY29uc3RydWN0b3IoaXNFbmFibGVkKSB7CiAgICB0aGlzLmlzRW5hYmxlZCA9IGlzRW5hYmxlZDsKICAgIHRoaXMucHJlZml4ID0gIndhc2k6IjsKICAgIHRoaXMuZW5hYmxlKGlzRW5hYmxlZCk7CiAgfQp9OwpmdW5jdGlvbiBjcmVhdGVMb2dnZXIoZW5hYmxlZCwgcHJlZml4KSB7CiAgaWYgKGVuYWJsZWQpIHsKICAgIGNvbnN0IGEgPSBjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUsICIlYyVzIiwgImNvbG9yOiAjMjY1QkEwIiwgcHJlZml4KTsKICAgIHJldHVybiBhOwogIH0gZWxzZSB7CiAgICByZXR1cm4gKCkgPT4gewogICAgfTsKICB9Cn0KdmFyIGRlYnVnID0gbmV3IERlYnVnKGZhbHNlKTsKCi8vIG5vZGVfbW9kdWxlcy9AYmpvcm4zL2Jyb3dzZXJfd2FzaV9zaGltL2Rpc3Qvd2FzaS5qcwp2YXIgV0FTSVByb2NFeGl0ID0gY2xhc3MgZXh0ZW5kcyBFcnJvciB7CiAgY29uc3RydWN0b3IoY29kZSkgewogICAgc3VwZXIoImV4aXQgd2l0aCBleGl0IGNvZGUgIiArIGNvZGUpOwogICAgdGhpcy5jb2RlID0gY29kZTsKICB9Cn07CnZhciBXQVNJID0gY2xhc3MgV0FTSTIgewogIHN0YXJ0KGluc3RhbmNlKSB7CiAgICB0aGlzLmluc3QgPSBpbnN0YW5jZTsKICAgIHRyeSB7CiAgICAgIGluc3RhbmNlLmV4cG9ydHMuX3N0YXJ0KCk7CiAgICAgIHJldHVybiAwOwogICAgfSBjYXRjaCAoZSkgewogICAgICBpZiAoZSBpbnN0YW5jZW9mIFdBU0lQcm9jRXhpdCkgewogICAgICAgIHJldHVybiBlLmNvZGU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgZTsKICAgICAgfQogICAgfQogIH0KICBpbml0aWFsaXplKGluc3RhbmNlKSB7CiAgICB0aGlzLmluc3QgPSBpbnN0YW5jZTsKICAgIGlmIChpbnN0YW5jZS5leHBvcnRzLl9pbml0aWFsaXplKSB7CiAgICAgIGluc3RhbmNlLmV4cG9ydHMuX2luaXRpYWxpemUoKTsKICAgIH0KICB9CiAgY29uc3RydWN0b3IoYXJncywgZW52LCBmZHMsIG9wdGlvbnMgPSB7fSkgewogICAgdGhpcy5hcmdzID0gW107CiAgICB0aGlzLmVudiA9IFtdOwogICAgdGhpcy5mZHMgPSBbXTsKICAgIGRlYnVnLmVuYWJsZShvcHRpb25zLmRlYnVnKTsKICAgIHRoaXMuYXJncyA9IGFyZ3M7CiAgICB0aGlzLmVudiA9IGVudjsKICAgIHRoaXMuZmRzID0gZmRzOwogICAgY29uc3Qgc2VsZiA9IHRoaXM7CiAgICB0aGlzLndhc2lJbXBvcnQgPSB7IGFyZ3Nfc2l6ZXNfZ2V0KGFyZ2MsIGFyZ3ZfYnVmX3NpemUpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBidWZmZXIuc2V0VWludDMyKGFyZ2MsIHNlbGYuYXJncy5sZW5ndGgsIHRydWUpOwogICAgICBsZXQgYnVmX3NpemUgPSAwOwogICAgICBmb3IgKGNvbnN0IGFyZyBvZiBzZWxmLmFyZ3MpIHsKICAgICAgICBidWZfc2l6ZSArPSBhcmcubGVuZ3RoICsgMTsKICAgICAgfQogICAgICBidWZmZXIuc2V0VWludDMyKGFyZ3ZfYnVmX3NpemUsIGJ1Zl9zaXplLCB0cnVlKTsKICAgICAgZGVidWcubG9nKGJ1ZmZlci5nZXRVaW50MzIoYXJnYywgdHJ1ZSksIGJ1ZmZlci5nZXRVaW50MzIoYXJndl9idWZfc2l6ZSwgdHJ1ZSkpOwogICAgICByZXR1cm4gMDsKICAgIH0sIGFyZ3NfZ2V0KGFyZ3YsIGFyZ3ZfYnVmKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBvcmlnX2FyZ3ZfYnVmID0gYXJndl9idWY7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZi5hcmdzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgYnVmZmVyLnNldFVpbnQzMihhcmd2LCBhcmd2X2J1ZiwgdHJ1ZSk7CiAgICAgICAgYXJndiArPSA0OwogICAgICAgIGNvbnN0IGFyZyA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzZWxmLmFyZ3NbaV0pOwogICAgICAgIGJ1ZmZlcjguc2V0KGFyZywgYXJndl9idWYpOwogICAgICAgIGJ1ZmZlci5zZXRVaW50OChhcmd2X2J1ZiArIGFyZy5sZW5ndGgsIDApOwogICAgICAgIGFyZ3ZfYnVmICs9IGFyZy5sZW5ndGggKyAxOwogICAgICB9CiAgICAgIGlmIChkZWJ1Zy5lbmFibGVkKSB7CiAgICAgICAgZGVidWcubG9nKG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShvcmlnX2FyZ3ZfYnVmLCBhcmd2X2J1ZikpKTsKICAgICAgfQogICAgICByZXR1cm4gMDsKICAgIH0sIGVudmlyb25fc2l6ZXNfZ2V0KGVudmlyb25fY291bnQsIGVudmlyb25fc2l6ZSkgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGJ1ZmZlci5zZXRVaW50MzIoZW52aXJvbl9jb3VudCwgc2VsZi5lbnYubGVuZ3RoLCB0cnVlKTsKICAgICAgbGV0IGJ1Zl9zaXplID0gMDsKICAgICAgZm9yIChjb25zdCBlbnZpcm9uIG9mIHNlbGYuZW52KSB7CiAgICAgICAgYnVmX3NpemUgKz0gZW52aXJvbi5sZW5ndGggKyAxOwogICAgICB9CiAgICAgIGJ1ZmZlci5zZXRVaW50MzIoZW52aXJvbl9zaXplLCBidWZfc2l6ZSwgdHJ1ZSk7CiAgICAgIGRlYnVnLmxvZyhidWZmZXIuZ2V0VWludDMyKGVudmlyb25fY291bnQsIHRydWUpLCBidWZmZXIuZ2V0VWludDMyKGVudmlyb25fc2l6ZSwgdHJ1ZSkpOwogICAgICByZXR1cm4gMDsKICAgIH0sIGVudmlyb25fZ2V0KGVudmlyb24sIGVudmlyb25fYnVmKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBvcmlnX2Vudmlyb25fYnVmID0gZW52aXJvbl9idWY7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZi5lbnYubGVuZ3RoOyBpKyspIHsKICAgICAgICBidWZmZXIuc2V0VWludDMyKGVudmlyb24sIGVudmlyb25fYnVmLCB0cnVlKTsKICAgICAgICBlbnZpcm9uICs9IDQ7CiAgICAgICAgY29uc3QgZSA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzZWxmLmVudltpXSk7CiAgICAgICAgYnVmZmVyOC5zZXQoZSwgZW52aXJvbl9idWYpOwogICAgICAgIGJ1ZmZlci5zZXRVaW50OChlbnZpcm9uX2J1ZiArIGUubGVuZ3RoLCAwKTsKICAgICAgICBlbnZpcm9uX2J1ZiArPSBlLmxlbmd0aCArIDE7CiAgICAgIH0KICAgICAgaWYgKGRlYnVnLmVuYWJsZWQpIHsKICAgICAgICBkZWJ1Zy5sb2cobmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG9yaWdfZW52aXJvbl9idWYsIGVudmlyb25fYnVmKSkpOwogICAgICB9CiAgICAgIHJldHVybiAwOwogICAgfSwgY2xvY2tfcmVzX2dldChpZCwgcmVzX3B0cikgewogICAgICBsZXQgcmVzb2x1dGlvblZhbHVlOwogICAgICBzd2l0Y2ggKGlkKSB7CiAgICAgICAgY2FzZSBDTE9DS0lEX01PTk9UT05JQzogewogICAgICAgICAgcmVzb2x1dGlvblZhbHVlID0gNTAwMG47CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgY2FzZSBDTE9DS0lEX1JFQUxUSU1FOiB7CiAgICAgICAgICByZXNvbHV0aW9uVmFsdWUgPSAxMDAwMDAwbjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBkZWZhdWx0OgogICAgICAgICAgcmV0dXJuIEVSUk5PX05PU1lTOwogICAgICB9CiAgICAgIGNvbnN0IHZpZXcgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIHZpZXcuc2V0QmlnVWludDY0KHJlc19wdHIsIHJlc29sdXRpb25WYWx1ZSwgdHJ1ZSk7CiAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgfSwgY2xvY2tfdGltZV9nZXQoaWQsIHByZWNpc2lvbiwgdGltZSkgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChpZCA9PT0gQ0xPQ0tJRF9SRUFMVElNRSkgewogICAgICAgIGJ1ZmZlci5zZXRCaWdVaW50NjQodGltZSwgQmlnSW50KG5ldyBEYXRlKCkuZ2V0VGltZSgpKSAqIDEwMDAwMDBuLCB0cnVlKTsKICAgICAgfSBlbHNlIGlmIChpZCA9PSBDTE9DS0lEX01PTk9UT05JQykgewogICAgICAgIGxldCBtb25vdG9uaWNfdGltZTsKICAgICAgICB0cnkgewogICAgICAgICAgbW9ub3RvbmljX3RpbWUgPSBCaWdJbnQoTWF0aC5yb3VuZChwZXJmb3JtYW5jZS5ub3coKSAqIDFlNikpOwogICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgIG1vbm90b25pY190aW1lID0gMG47CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRCaWdVaW50NjQodGltZSwgbW9ub3RvbmljX3RpbWUsIHRydWUpOwogICAgICB9IGVsc2UgewogICAgICAgIGJ1ZmZlci5zZXRCaWdVaW50NjQodGltZSwgMG4sIHRydWUpOwogICAgICB9CiAgICAgIHJldHVybiAwOwogICAgfSwgZmRfYWR2aXNlKGZkLCBvZmZzZXQsIGxlbiwgYWR2aWNlKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2FsbG9jYXRlKGZkLCBvZmZzZXQsIGxlbikgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfYWxsb2NhdGUob2Zmc2V0LCBsZW4pOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9jbG9zZShmZCkgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHJldCA9IHNlbGYuZmRzW2ZkXS5mZF9jbG9zZSgpOwogICAgICAgIHNlbGYuZmRzW2ZkXSA9IHZvaWQgMDsKICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9kYXRhc3luYyhmZCkgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfc3luYygpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9mZHN0YXRfZ2V0KGZkLCBmZHN0YXRfcHRyKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIGZkc3RhdCB9ID0gc2VsZi5mZHNbZmRdLmZkX2Zkc3RhdF9nZXQoKTsKICAgICAgICBpZiAoZmRzdGF0ICE9IG51bGwpIHsKICAgICAgICAgIGZkc3RhdC53cml0ZV9ieXRlcyhuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlciksIGZkc3RhdF9wdHIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9mZHN0YXRfc2V0X2ZsYWdzKGZkLCBmbGFncykgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfZmRzdGF0X3NldF9mbGFncyhmbGFncyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Zkc3RhdF9zZXRfcmlnaHRzKGZkLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICByZXR1cm4gc2VsZi5mZHNbZmRdLmZkX2Zkc3RhdF9zZXRfcmlnaHRzKGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2ZpbGVzdGF0X2dldChmZCwgZmlsZXN0YXRfcHRyKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIGZpbGVzdGF0IH0gPSBzZWxmLmZkc1tmZF0uZmRfZmlsZXN0YXRfZ2V0KCk7CiAgICAgICAgaWYgKGZpbGVzdGF0ICE9IG51bGwpIHsKICAgICAgICAgIGZpbGVzdGF0LndyaXRlX2J5dGVzKG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKSwgZmlsZXN0YXRfcHRyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfZmlsZXN0YXRfc2V0X3NpemUoZmQsIHNpemUpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICByZXR1cm4gc2VsZi5mZHNbZmRdLmZkX2ZpbGVzdGF0X3NldF9zaXplKHNpemUpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9maWxlc3RhdF9zZXRfdGltZXMoZmQsIGF0aW0sIG10aW0sIGZzdF9mbGFncykgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfZmlsZXN0YXRfc2V0X3RpbWVzKGF0aW0sIG10aW0sIGZzdF9mbGFncyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3ByZWFkKGZkLCBpb3ZzX3B0ciwgaW92c19sZW4sIG9mZnNldCwgbnJlYWRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IGlvdmVjcyA9IElvdmVjLnJlYWRfYnl0ZXNfYXJyYXkoYnVmZmVyLCBpb3ZzX3B0ciwgaW92c19sZW4pOwogICAgICAgIGxldCBucmVhZCA9IDA7CiAgICAgICAgZm9yIChjb25zdCBpb3ZlYyBvZiBpb3ZlY3MpIHsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBkYXRhIH0gPSBzZWxmLmZkc1tmZF0uZmRfcHJlYWQoaW92ZWMuYnVmX2xlbiwgb2Zmc2V0KTsKICAgICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgbnJlYWQsIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgYnVmZmVyOC5zZXQoZGF0YSwgaW92ZWMuYnVmKTsKICAgICAgICAgIG5yZWFkICs9IGRhdGEubGVuZ3RoOwogICAgICAgICAgb2Zmc2V0ICs9IEJpZ0ludChkYXRhLmxlbmd0aCk7CiAgICAgICAgICBpZiAoZGF0YS5sZW5ndGggIT0gaW92ZWMuYnVmX2xlbikgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgYnVmZmVyLnNldFVpbnQzMihucmVhZF9wdHIsIG5yZWFkLCB0cnVlKTsKICAgICAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcHJlc3RhdF9nZXQoZmQsIGJ1Zl9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHsgcmV0LCBwcmVzdGF0IH0gPSBzZWxmLmZkc1tmZF0uZmRfcHJlc3RhdF9nZXQoKTsKICAgICAgICBpZiAocHJlc3RhdCAhPSBudWxsKSB7CiAgICAgICAgICBwcmVzdGF0LndyaXRlX2J5dGVzKGJ1ZmZlciwgYnVmX3B0cik7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3ByZXN0YXRfZGlyX25hbWUoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbikgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHsgcmV0LCBwcmVzdGF0IH0gPSBzZWxmLmZkc1tmZF0uZmRfcHJlc3RhdF9nZXQoKTsKICAgICAgICBpZiAocHJlc3RhdCA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgIH0KICAgICAgICBjb25zdCBwcmVzdGF0X2Rpcl9uYW1lID0gcHJlc3RhdC5pbm5lci5wcl9uYW1lOwogICAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgICBidWZmZXI4LnNldChwcmVzdGF0X2Rpcl9uYW1lLnNsaWNlKDAsIHBhdGhfbGVuKSwgcGF0aF9wdHIpOwogICAgICAgIHJldHVybiBwcmVzdGF0X2Rpcl9uYW1lLmJ5dGVMZW5ndGggPiBwYXRoX2xlbiA/IEVSUk5PX05BTUVUT09MT05HIDogRVJSTk9fU1VDQ0VTUzsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcHdyaXRlKGZkLCBpb3ZzX3B0ciwgaW92c19sZW4sIG9mZnNldCwgbndyaXR0ZW5fcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IGlvdmVjcyA9IENpb3ZlYy5yZWFkX2J5dGVzX2FycmF5KGJ1ZmZlciwgaW92c19wdHIsIGlvdnNfbGVuKTsKICAgICAgICBsZXQgbndyaXR0ZW4gPSAwOwogICAgICAgIGZvciAoY29uc3QgaW92ZWMgb2YgaW92ZWNzKSB7CiAgICAgICAgICBjb25zdCBkYXRhID0gYnVmZmVyOC5zbGljZShpb3ZlYy5idWYsIGlvdmVjLmJ1ZiArIGlvdmVjLmJ1Zl9sZW4pOwogICAgICAgICAgY29uc3QgeyByZXQsIG53cml0dGVuOiBud3JpdHRlbl9wYXJ0IH0gPSBzZWxmLmZkc1tmZF0uZmRfcHdyaXRlKGRhdGEsIG9mZnNldCk7CiAgICAgICAgICBpZiAocmV0ICE9IEVSUk5PX1NVQ0NFU1MpIHsKICAgICAgICAgICAgYnVmZmVyLnNldFVpbnQzMihud3JpdHRlbl9wdHIsIG53cml0dGVuLCB0cnVlKTsKICAgICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICAgIH0KICAgICAgICAgIG53cml0dGVuICs9IG53cml0dGVuX3BhcnQ7CiAgICAgICAgICBvZmZzZXQgKz0gQmlnSW50KG53cml0dGVuX3BhcnQpOwogICAgICAgICAgaWYgKG53cml0dGVuX3BhcnQgIT0gZGF0YS5ieXRlTGVuZ3RoKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKG53cml0dGVuX3B0ciwgbndyaXR0ZW4sIHRydWUpOwogICAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9yZWFkKGZkLCBpb3ZzX3B0ciwgaW92c19sZW4sIG5yZWFkX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBpb3ZlY3MgPSBJb3ZlYy5yZWFkX2J5dGVzX2FycmF5KGJ1ZmZlciwgaW92c19wdHIsIGlvdnNfbGVuKTsKICAgICAgICBsZXQgbnJlYWQgPSAwOwogICAgICAgIGZvciAoY29uc3QgaW92ZWMgb2YgaW92ZWNzKSB7CiAgICAgICAgICBjb25zdCB7IHJldCwgZGF0YSB9ID0gc2VsZi5mZHNbZmRdLmZkX3JlYWQoaW92ZWMuYnVmX2xlbik7CiAgICAgICAgICBpZiAocmV0ICE9IEVSUk5PX1NVQ0NFU1MpIHsKICAgICAgICAgICAgYnVmZmVyLnNldFVpbnQzMihucmVhZF9wdHIsIG5yZWFkLCB0cnVlKTsKICAgICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICAgIH0KICAgICAgICAgIGJ1ZmZlcjguc2V0KGRhdGEsIGlvdmVjLmJ1Zik7CiAgICAgICAgICBucmVhZCArPSBkYXRhLmxlbmd0aDsKICAgICAgICAgIGlmIChkYXRhLmxlbmd0aCAhPSBpb3ZlYy5idWZfbGVuKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgbnJlYWQsIHRydWUpOwogICAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9yZWFkZGlyKGZkLCBidWYsIGJ1Zl9sZW4sIGNvb2tpZSwgYnVmdXNlZF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgbGV0IGJ1ZnVzZWQgPSAwOwogICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICBjb25zdCB7IHJldCwgZGlyZW50IH0gPSBzZWxmLmZkc1tmZF0uZmRfcmVhZGRpcl9zaW5nbGUoY29va2llKTsKICAgICAgICAgIGlmIChyZXQgIT0gMCkgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKGJ1ZnVzZWRfcHRyLCBidWZ1c2VkLCB0cnVlKTsKICAgICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChkaXJlbnQgPT0gbnVsbCkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChidWZfbGVuIC0gYnVmdXNlZCA8IGRpcmVudC5oZWFkX2xlbmd0aCgpKSB7CiAgICAgICAgICAgIGJ1ZnVzZWQgPSBidWZfbGVuOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGhlYWRfYnl0ZXMgPSBuZXcgQXJyYXlCdWZmZXIoZGlyZW50LmhlYWRfbGVuZ3RoKCkpOwogICAgICAgICAgZGlyZW50LndyaXRlX2hlYWRfYnl0ZXMobmV3IERhdGFWaWV3KGhlYWRfYnl0ZXMpLCAwKTsKICAgICAgICAgIGJ1ZmZlcjguc2V0KG5ldyBVaW50OEFycmF5KGhlYWRfYnl0ZXMpLnNsaWNlKDAsIE1hdGgubWluKGhlYWRfYnl0ZXMuYnl0ZUxlbmd0aCwgYnVmX2xlbiAtIGJ1ZnVzZWQpKSwgYnVmKTsKICAgICAgICAgIGJ1ZiArPSBkaXJlbnQuaGVhZF9sZW5ndGgoKTsKICAgICAgICAgIGJ1ZnVzZWQgKz0gZGlyZW50LmhlYWRfbGVuZ3RoKCk7CiAgICAgICAgICBpZiAoYnVmX2xlbiAtIGJ1ZnVzZWQgPCBkaXJlbnQubmFtZV9sZW5ndGgoKSkgewogICAgICAgICAgICBidWZ1c2VkID0gYnVmX2xlbjsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBkaXJlbnQud3JpdGVfbmFtZV9ieXRlcyhidWZmZXI4LCBidWYsIGJ1Zl9sZW4gLSBidWZ1c2VkKTsKICAgICAgICAgIGJ1ZiArPSBkaXJlbnQubmFtZV9sZW5ndGgoKTsKICAgICAgICAgIGJ1ZnVzZWQgKz0gZGlyZW50Lm5hbWVfbGVuZ3RoKCk7CiAgICAgICAgICBjb29raWUgPSBkaXJlbnQuZF9uZXh0OwogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKGJ1ZnVzZWRfcHRyLCBidWZ1c2VkLCB0cnVlKTsKICAgICAgICByZXR1cm4gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcmVudW1iZXIoZmQsIHRvKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwICYmIHNlbGYuZmRzW3RvXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCByZXQgPSBzZWxmLmZkc1t0b10uZmRfY2xvc2UoKTsKICAgICAgICBpZiAocmV0ICE9IDApIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIHNlbGYuZmRzW3RvXSA9IHNlbGYuZmRzW2ZkXTsKICAgICAgICBzZWxmLmZkc1tmZF0gPSB2b2lkIDA7CiAgICAgICAgcmV0dXJuIDA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3NlZWsoZmQsIG9mZnNldCwgd2hlbmNlLCBvZmZzZXRfb3V0X3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIG9mZnNldDogb2Zmc2V0X291dCB9ID0gc2VsZi5mZHNbZmRdLmZkX3NlZWsob2Zmc2V0LCB3aGVuY2UpOwogICAgICAgIGJ1ZmZlci5zZXRCaWdJbnQ2NChvZmZzZXRfb3V0X3B0ciwgb2Zmc2V0X291dCwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfc3luYyhmZCkgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfc3luYygpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF90ZWxsKGZkLCBvZmZzZXRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgb2Zmc2V0IH0gPSBzZWxmLmZkc1tmZF0uZmRfdGVsbCgpOwogICAgICAgIGJ1ZmZlci5zZXRCaWdVaW50NjQob2Zmc2V0X3B0ciwgb2Zmc2V0LCB0cnVlKTsKICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF93cml0ZShmZCwgaW92c19wdHIsIGlvdnNfbGVuLCBud3JpdHRlbl9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgaW92ZWNzID0gQ2lvdmVjLnJlYWRfYnl0ZXNfYXJyYXkoYnVmZmVyLCBpb3ZzX3B0ciwgaW92c19sZW4pOwogICAgICAgIGxldCBud3JpdHRlbiA9IDA7CiAgICAgICAgZm9yIChjb25zdCBpb3ZlYyBvZiBpb3ZlY3MpIHsKICAgICAgICAgIGNvbnN0IGRhdGEgPSBidWZmZXI4LnNsaWNlKGlvdmVjLmJ1ZiwgaW92ZWMuYnVmICsgaW92ZWMuYnVmX2xlbik7CiAgICAgICAgICBjb25zdCB7IHJldCwgbndyaXR0ZW46IG53cml0dGVuX3BhcnQgfSA9IHNlbGYuZmRzW2ZkXS5mZF93cml0ZShkYXRhKTsKICAgICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG53cml0dGVuX3B0ciwgbndyaXR0ZW4sIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgbndyaXR0ZW4gKz0gbndyaXR0ZW5fcGFydDsKICAgICAgICAgIGlmIChud3JpdHRlbl9wYXJ0ICE9IGRhdGEuYnl0ZUxlbmd0aCkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgYnVmZmVyLnNldFVpbnQzMihud3JpdHRlbl9wdHIsIG53cml0dGVuLCB0cnVlKTsKICAgICAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9jcmVhdGVfZGlyZWN0b3J5KGZkLCBwYXRoX3B0ciwgcGF0aF9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICByZXR1cm4gc2VsZi5mZHNbZmRdLnBhdGhfY3JlYXRlX2RpcmVjdG9yeShwYXRoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9maWxlc3RhdF9nZXQoZmQsIGZsYWdzLCBwYXRoX3B0ciwgcGF0aF9sZW4sIGZpbGVzdGF0X3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBwYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgY29uc3QgeyByZXQsIGZpbGVzdGF0IH0gPSBzZWxmLmZkc1tmZF0ucGF0aF9maWxlc3RhdF9nZXQoZmxhZ3MsIHBhdGgpOwogICAgICAgIGlmIChmaWxlc3RhdCAhPSBudWxsKSB7CiAgICAgICAgICBmaWxlc3RhdC53cml0ZV9ieXRlcyhidWZmZXIsIGZpbGVzdGF0X3B0cik7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfZmlsZXN0YXRfc2V0X3RpbWVzKGZkLCBmbGFncywgcGF0aF9wdHIsIHBhdGhfbGVuLCBhdGltLCBtdGltLCBmc3RfZmxhZ3MpIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICByZXR1cm4gc2VsZi5mZHNbZmRdLnBhdGhfZmlsZXN0YXRfc2V0X3RpbWVzKGZsYWdzLCBwYXRoLCBhdGltLCBtdGltLCBmc3RfZmxhZ3MpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX2xpbmsob2xkX2ZkLCBvbGRfZmxhZ3MsIG9sZF9wYXRoX3B0ciwgb2xkX3BhdGhfbGVuLCBuZXdfZmQsIG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW29sZF9mZF0gIT0gdm9pZCAwICYmIHNlbGYuZmRzW25ld19mZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3Qgb2xkX3BhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2Uob2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9wdHIgKyBvbGRfcGF0aF9sZW4pKTsKICAgICAgICBjb25zdCBuZXdfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShuZXdfcGF0aF9wdHIsIG5ld19wYXRoX3B0ciArIG5ld19wYXRoX2xlbikpOwogICAgICAgIGNvbnN0IHsgcmV0LCBpbm9kZV9vYmogfSA9IHNlbGYuZmRzW29sZF9mZF0ucGF0aF9sb29rdXAob2xkX3BhdGgsIG9sZF9mbGFncyk7CiAgICAgICAgaWYgKGlub2RlX29iaiA9PSBudWxsKSB7CiAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgIH0KICAgICAgICByZXR1cm4gc2VsZi5mZHNbbmV3X2ZkXS5wYXRoX2xpbmsobmV3X3BhdGgsIGlub2RlX29iaiwgZmFsc2UpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX29wZW4oZmQsIGRpcmZsYWdzLCBwYXRoX3B0ciwgcGF0aF9sZW4sIG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nLCBmZF9mbGFncywgb3BlbmVkX2ZkX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBwYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgZGVidWcubG9nKHBhdGgpOwogICAgICAgIGNvbnN0IHsgcmV0LCBmZF9vYmogfSA9IHNlbGYuZmRzW2ZkXS5wYXRoX29wZW4oZGlyZmxhZ3MsIHBhdGgsIG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nLCBmZF9mbGFncyk7CiAgICAgICAgaWYgKHJldCAhPSAwKSB7CiAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgIH0KICAgICAgICBzZWxmLmZkcy5wdXNoKGZkX29iaik7CiAgICAgICAgY29uc3Qgb3BlbmVkX2ZkID0gc2VsZi5mZHMubGVuZ3RoIC0gMTsKICAgICAgICBidWZmZXIuc2V0VWludDMyKG9wZW5lZF9mZF9wdHIsIG9wZW5lZF9mZCwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIDA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfcmVhZGxpbmsoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbiwgYnVmX3B0ciwgYnVmX2xlbiwgbnJlYWRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICBkZWJ1Zy5sb2cocGF0aCk7CiAgICAgICAgY29uc3QgeyByZXQsIGRhdGEgfSA9IHNlbGYuZmRzW2ZkXS5wYXRoX3JlYWRsaW5rKHBhdGgpOwogICAgICAgIGlmIChkYXRhICE9IG51bGwpIHsKICAgICAgICAgIGNvbnN0IGRhdGFfYnVmID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKGRhdGEpOwogICAgICAgICAgaWYgKGRhdGFfYnVmLmxlbmd0aCA+IGJ1Zl9sZW4pIHsKICAgICAgICAgICAgYnVmZmVyLnNldFVpbnQzMihucmVhZF9wdHIsIDAsIHRydWUpOwogICAgICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgICAgIH0KICAgICAgICAgIGJ1ZmZlcjguc2V0KGRhdGFfYnVmLCBidWZfcHRyKTsKICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobnJlYWRfcHRyLCBkYXRhX2J1Zi5sZW5ndGgsIHRydWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX3JlbW92ZV9kaXJlY3RvcnkoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0ucGF0aF9yZW1vdmVfZGlyZWN0b3J5KHBhdGgpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX3JlbmFtZShmZCwgb2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9sZW4sIG5ld19mZCwgbmV3X3BhdGhfcHRyLCBuZXdfcGF0aF9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCAmJiBzZWxmLmZkc1tuZXdfZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IG9sZF9wYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG9sZF9wYXRoX3B0ciwgb2xkX3BhdGhfcHRyICsgb2xkX3BhdGhfbGVuKSk7CiAgICAgICAgY29uc3QgbmV3X3BhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UobmV3X3BhdGhfcHRyLCBuZXdfcGF0aF9wdHIgKyBuZXdfcGF0aF9sZW4pKTsKICAgICAgICBsZXQgeyByZXQsIGlub2RlX29iaiB9ID0gc2VsZi5mZHNbZmRdLnBhdGhfdW5saW5rKG9sZF9wYXRoKTsKICAgICAgICBpZiAoaW5vZGVfb2JqID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIHJldCA9IHNlbGYuZmRzW25ld19mZF0ucGF0aF9saW5rKG5ld19wYXRoLCBpbm9kZV9vYmosIHRydWUpOwogICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgaWYgKHNlbGYuZmRzW2ZkXS5wYXRoX2xpbmsob2xkX3BhdGgsIGlub2RlX29iaiwgdHJ1ZSkgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICB0aHJvdyAicGF0aF9saW5rIHNob3VsZCBhbHdheXMgcmV0dXJuIHN1Y2Nlc3Mgd2hlbiByZWxpbmtpbmcgYW4gaW5vZGUgYmFjayB0byB0aGUgb3JpZ2luYWwgcGxhY2UiOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX3N5bWxpbmsob2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9sZW4sIGZkLCBuZXdfcGF0aF9wdHIsIG5ld19wYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3Qgb2xkX3BhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2Uob2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9wdHIgKyBvbGRfcGF0aF9sZW4pKTsKICAgICAgICBjb25zdCBuZXdfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShuZXdfcGF0aF9wdHIsIG5ld19wYXRoX3B0ciArIG5ld19wYXRoX2xlbikpOwogICAgICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfdW5saW5rX2ZpbGUoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0ucGF0aF91bmxpbmtfZmlsZShwYXRoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcG9sbF9vbmVvZmYoaW5fLCBvdXQsIG5zdWJzY3JpcHRpb25zKSB7CiAgICAgIHRocm93ICJhc3luYyBpbyBub3Qgc3VwcG9ydGVkIjsKICAgIH0sIHByb2NfZXhpdChleGl0X2NvZGUpIHsKICAgICAgdGhyb3cgbmV3IFdBU0lQcm9jRXhpdChleGl0X2NvZGUpOwogICAgfSwgcHJvY19yYWlzZShzaWcpIHsKICAgICAgdGhyb3cgInJhaXNlZCBzaWduYWwgIiArIHNpZzsKICAgIH0sIHNjaGVkX3lpZWxkKCkgewogICAgfSwgcmFuZG9tX2dldChidWYsIGJ1Zl9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJ1Zl9sZW47IGkrKykgewogICAgICAgIGJ1ZmZlcjhbYnVmICsgaV0gPSBNYXRoLnJhbmRvbSgpICogMjU2IHwgMDsKICAgICAgfQogICAgfSwgc29ja19yZWN2KGZkLCByaV9kYXRhLCByaV9mbGFncykgewogICAgICB0aHJvdyAic29ja2V0cyBub3Qgc3VwcG9ydGVkIjsKICAgIH0sIHNvY2tfc2VuZChmZCwgc2lfZGF0YSwgc2lfZmxhZ3MpIHsKICAgICAgdGhyb3cgInNvY2tldHMgbm90IHN1cHBvcnRlZCI7CiAgICB9LCBzb2NrX3NodXRkb3duKGZkLCBob3cpIHsKICAgICAgdGhyb3cgInNvY2tldHMgbm90IHN1cHBvcnRlZCI7CiAgICB9LCBzb2NrX2FjY2VwdChmZCwgZmxhZ3MpIHsKICAgICAgdGhyb3cgInNvY2tldHMgbm90IHN1cHBvcnRlZCI7CiAgICB9IH07CiAgfQp9OwoKLy8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC9mZC5qcwp2YXIgRmQgPSBjbGFzcyB7CiAgZmRfYWxsb2NhdGUob2Zmc2V0LCBsZW4pIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIGZkX2Nsb3NlKCkgewogICAgcmV0dXJuIDA7CiAgfQogIGZkX2Zkc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZmRzdGF0OiBudWxsIH07CiAgfQogIGZkX2Zkc3RhdF9zZXRfZmxhZ3MoZmxhZ3MpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIGZkX2Zkc3RhdF9zZXRfcmlnaHRzKGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZykgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfZmlsZXN0YXRfZ2V0KCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGZpbGVzdGF0OiBudWxsIH07CiAgfQogIGZkX2ZpbGVzdGF0X3NldF9zaXplKHNpemUpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIGZkX2ZpbGVzdGF0X3NldF90aW1lcyhhdGltLCBtdGltLCBmc3RfZmxhZ3MpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIGZkX3ByZWFkKHNpemUsIG9mZnNldCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGRhdGE6IG5ldyBVaW50OEFycmF5KCkgfTsKICB9CiAgZmRfcHJlc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgcHJlc3RhdDogbnVsbCB9OwogIH0KICBmZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgbndyaXR0ZW46IDAgfTsKICB9CiAgZmRfcmVhZChzaXplKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZGF0YTogbmV3IFVpbnQ4QXJyYXkoKSB9OwogIH0KICBmZF9yZWFkZGlyX3NpbmdsZShjb29raWUpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBkaXJlbnQ6IG51bGwgfTsKICB9CiAgZmRfc2VlayhvZmZzZXQsIHdoZW5jZSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIG9mZnNldDogMG4gfTsKICB9CiAgZmRfc3luYygpIHsKICAgIHJldHVybiAwOwogIH0KICBmZF90ZWxsKCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIG9mZnNldDogMG4gfTsKICB9CiAgZmRfd3JpdGUoZGF0YSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIG53cml0dGVuOiAwIH07CiAgfQogIHBhdGhfY3JlYXRlX2RpcmVjdG9yeShwYXRoKSB7CiAgICByZXR1cm4gRVJSTk9fTk9UU1VQOwogIH0KICBwYXRoX2ZpbGVzdGF0X2dldChmbGFncywgcGF0aCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGZpbGVzdGF0OiBudWxsIH07CiAgfQogIHBhdGhfZmlsZXN0YXRfc2V0X3RpbWVzKGZsYWdzLCBwYXRoLCBhdGltLCBtdGltLCBmc3RfZmxhZ3MpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfbGluayhwYXRoLCBpbm9kZSwgYWxsb3dfZGlyKSB7CiAgICByZXR1cm4gRVJSTk9fTk9UU1VQOwogIH0KICBwYXRoX3VubGluayhwYXRoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgaW5vZGVfb2JqOiBudWxsIH07CiAgfQogIHBhdGhfbG9va3VwKHBhdGgsIGRpcmZsYWdzKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgaW5vZGVfb2JqOiBudWxsIH07CiAgfQogIHBhdGhfb3BlbihkaXJmbGFncywgcGF0aCwgb2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcsIGZkX2ZsYWdzKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgZmRfb2JqOiBudWxsIH07CiAgfQogIHBhdGhfcmVhZGxpbmsocGF0aCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGRhdGE6IG51bGwgfTsKICB9CiAgcGF0aF9yZW1vdmVfZGlyZWN0b3J5KHBhdGgpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfcmVuYW1lKG9sZF9wYXRoLCBuZXdfZmQsIG5ld19wYXRoKSB7CiAgICByZXR1cm4gRVJSTk9fTk9UU1VQOwogIH0KICBwYXRoX3VubGlua19maWxlKHBhdGgpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQp9Owp2YXIgSW5vZGUgPSBjbGFzcyB7Cn07CgovLyBub2RlX21vZHVsZXMvQGJqb3JuMy9icm93c2VyX3dhc2lfc2hpbS9kaXN0L2ZzX21lbS5qcwp2YXIgT3BlbkZpbGUgPSBjbGFzcyBleHRlbmRzIEZkIHsKICBmZF9hbGxvY2F0ZShvZmZzZXQsIGxlbikgewogICAgaWYgKHRoaXMuZmlsZS5zaXplID4gb2Zmc2V0ICsgbGVuKSB7CiAgICB9IGVsc2UgewogICAgICBjb25zdCBuZXdfZGF0YSA9IG5ldyBVaW50OEFycmF5KE51bWJlcihvZmZzZXQgKyBsZW4pKTsKICAgICAgbmV3X2RhdGEuc2V0KHRoaXMuZmlsZS5kYXRhLCAwKTsKICAgICAgdGhpcy5maWxlLmRhdGEgPSBuZXdfZGF0YTsKICAgIH0KICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogIH0KICBmZF9mZHN0YXRfZ2V0KCkgewogICAgcmV0dXJuIHsgcmV0OiAwLCBmZHN0YXQ6IG5ldyBGZHN0YXQoRklMRVRZUEVfUkVHVUxBUl9GSUxFLCAwKSB9OwogIH0KICBmZF9maWxlc3RhdF9zZXRfc2l6ZShzaXplKSB7CiAgICBpZiAodGhpcy5maWxlLnNpemUgPiBzaXplKSB7CiAgICAgIHRoaXMuZmlsZS5kYXRhID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5maWxlLmRhdGEuYnVmZmVyLnNsaWNlKDAsIE51bWJlcihzaXplKSkpOwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgbmV3X2RhdGEgPSBuZXcgVWludDhBcnJheShOdW1iZXIoc2l6ZSkpOwogICAgICBuZXdfZGF0YS5zZXQodGhpcy5maWxlLmRhdGEsIDApOwogICAgICB0aGlzLmZpbGUuZGF0YSA9IG5ld19kYXRhOwogICAgfQogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIGZkX3JlYWQoc2l6ZSkgewogICAgY29uc3Qgc2xpY2UgPSB0aGlzLmZpbGUuZGF0YS5zbGljZShOdW1iZXIodGhpcy5maWxlX3BvcyksIE51bWJlcih0aGlzLmZpbGVfcG9zICsgQmlnSW50KHNpemUpKSk7CiAgICB0aGlzLmZpbGVfcG9zICs9IEJpZ0ludChzbGljZS5sZW5ndGgpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBkYXRhOiBzbGljZSB9OwogIH0KICBmZF9wcmVhZChzaXplLCBvZmZzZXQpIHsKICAgIGNvbnN0IHNsaWNlID0gdGhpcy5maWxlLmRhdGEuc2xpY2UoTnVtYmVyKG9mZnNldCksIE51bWJlcihvZmZzZXQgKyBCaWdJbnQoc2l6ZSkpKTsKICAgIHJldHVybiB7IHJldDogMCwgZGF0YTogc2xpY2UgfTsKICB9CiAgZmRfc2VlayhvZmZzZXQsIHdoZW5jZSkgewogICAgbGV0IGNhbGN1bGF0ZWRfb2Zmc2V0OwogICAgc3dpdGNoICh3aGVuY2UpIHsKICAgICAgY2FzZSBXSEVOQ0VfU0VUOgogICAgICAgIGNhbGN1bGF0ZWRfb2Zmc2V0ID0gb2Zmc2V0OwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFdIRU5DRV9DVVI6CiAgICAgICAgY2FsY3VsYXRlZF9vZmZzZXQgPSB0aGlzLmZpbGVfcG9zICsgb2Zmc2V0OwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFdIRU5DRV9FTkQ6CiAgICAgICAgY2FsY3VsYXRlZF9vZmZzZXQgPSBCaWdJbnQodGhpcy5maWxlLmRhdGEuYnl0ZUxlbmd0aCkgKyBvZmZzZXQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19JTlZBTCwgb2Zmc2V0OiAwbiB9OwogICAgfQogICAgaWYgKGNhbGN1bGF0ZWRfb2Zmc2V0IDwgMCkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0lOVkFMLCBvZmZzZXQ6IDBuIH07CiAgICB9CiAgICB0aGlzLmZpbGVfcG9zID0gY2FsY3VsYXRlZF9vZmZzZXQ7CiAgICByZXR1cm4geyByZXQ6IDAsIG9mZnNldDogdGhpcy5maWxlX3BvcyB9OwogIH0KICBmZF90ZWxsKCkgewogICAgcmV0dXJuIHsgcmV0OiAwLCBvZmZzZXQ6IHRoaXMuZmlsZV9wb3MgfTsKICB9CiAgZmRfd3JpdGUoZGF0YSkgewogICAgaWYgKHRoaXMuZmlsZS5yZWFkb25seSkKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBud3JpdHRlbjogMCB9OwogICAgaWYgKHRoaXMuZmlsZV9wb3MgKyBCaWdJbnQoZGF0YS5ieXRlTGVuZ3RoKSA+IHRoaXMuZmlsZS5zaXplKSB7CiAgICAgIGNvbnN0IG9sZCA9IHRoaXMuZmlsZS5kYXRhOwogICAgICB0aGlzLmZpbGUuZGF0YSA9IG5ldyBVaW50OEFycmF5KE51bWJlcih0aGlzLmZpbGVfcG9zICsgQmlnSW50KGRhdGEuYnl0ZUxlbmd0aCkpKTsKICAgICAgdGhpcy5maWxlLmRhdGEuc2V0KG9sZCk7CiAgICB9CiAgICB0aGlzLmZpbGUuZGF0YS5zZXQoZGF0YSwgTnVtYmVyKHRoaXMuZmlsZV9wb3MpKTsKICAgIHRoaXMuZmlsZV9wb3MgKz0gQmlnSW50KGRhdGEuYnl0ZUxlbmd0aCk7CiAgICByZXR1cm4geyByZXQ6IDAsIG53cml0dGVuOiBkYXRhLmJ5dGVMZW5ndGggfTsKICB9CiAgZmRfcHdyaXRlKGRhdGEsIG9mZnNldCkgewogICAgaWYgKHRoaXMuZmlsZS5yZWFkb25seSkKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBud3JpdHRlbjogMCB9OwogICAgaWYgKG9mZnNldCArIEJpZ0ludChkYXRhLmJ5dGVMZW5ndGgpID4gdGhpcy5maWxlLnNpemUpIHsKICAgICAgY29uc3Qgb2xkID0gdGhpcy5maWxlLmRhdGE7CiAgICAgIHRoaXMuZmlsZS5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoTnVtYmVyKG9mZnNldCArIEJpZ0ludChkYXRhLmJ5dGVMZW5ndGgpKSk7CiAgICAgIHRoaXMuZmlsZS5kYXRhLnNldChvbGQpOwogICAgfQogICAgdGhpcy5maWxlLmRhdGEuc2V0KGRhdGEsIE51bWJlcihvZmZzZXQpKTsKICAgIHJldHVybiB7IHJldDogMCwgbndyaXR0ZW46IGRhdGEuYnl0ZUxlbmd0aCB9OwogIH0KICBmZF9maWxlc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIGZpbGVzdGF0OiB0aGlzLmZpbGUuc3RhdCgpIH07CiAgfQogIGNvbnN0cnVjdG9yKGZpbGUpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLmZpbGVfcG9zID0gMG47CiAgICB0aGlzLmZpbGUgPSBmaWxlOwogIH0KfTsKdmFyIE9wZW5EaXJlY3RvcnkgPSBjbGFzcyBleHRlbmRzIEZkIHsKICBmZF9zZWVrKG9mZnNldCwgd2hlbmNlKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG9mZnNldDogMG4gfTsKICB9CiAgZmRfdGVsbCgpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fQkFERiwgb2Zmc2V0OiAwbiB9OwogIH0KICBmZF9hbGxvY2F0ZShvZmZzZXQsIGxlbikgewogICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgfQogIGZkX2Zkc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIGZkc3RhdDogbmV3IEZkc3RhdChGSUxFVFlQRV9ESVJFQ1RPUlksIDApIH07CiAgfQogIGZkX3JlYWRkaXJfc2luZ2xlKGNvb2tpZSkgewogICAgaWYgKGRlYnVnLmVuYWJsZWQpIHsKICAgICAgZGVidWcubG9nKCJyZWFkZGlyX3NpbmdsZSIsIGNvb2tpZSk7CiAgICAgIGRlYnVnLmxvZyhjb29raWUsIHRoaXMuZGlyLmNvbnRlbnRzLmtleXMoKSk7CiAgICB9CiAgICBpZiAoY29va2llID09IDBuKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZGlyZW50OiBuZXcgRGlyZW50KDFuLCAiLiIsIEZJTEVUWVBFX0RJUkVDVE9SWSkgfTsKICAgIH0gZWxzZSBpZiAoY29va2llID09IDFuKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZGlyZW50OiBuZXcgRGlyZW50KDJuLCAiLi4iLCBGSUxFVFlQRV9ESVJFQ1RPUlkpIH07CiAgICB9CiAgICBpZiAoY29va2llID49IEJpZ0ludCh0aGlzLmRpci5jb250ZW50cy5zaXplKSArIDJuKSB7CiAgICAgIHJldHVybiB7IHJldDogMCwgZGlyZW50OiBudWxsIH07CiAgICB9CiAgICBjb25zdCBbbmFtZSwgZW50cnldID0gQXJyYXkuZnJvbSh0aGlzLmRpci5jb250ZW50cy5lbnRyaWVzKCkpW051bWJlcihjb29raWUgLSAybildOwogICAgcmV0dXJuIHsgcmV0OiAwLCBkaXJlbnQ6IG5ldyBEaXJlbnQoY29va2llICsgMW4sIG5hbWUsIGVudHJ5LnN0YXQoKS5maWxldHlwZSkgfTsKICB9CiAgcGF0aF9maWxlc3RhdF9nZXQoZmxhZ3MsIHBhdGhfc3RyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9lcnIsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogcGF0aF9lcnIsIGZpbGVzdGF0OiBudWxsIH07CiAgICB9CiAgICBjb25zdCB7IHJldCwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9lbnRyeV9mb3JfcGF0aChwYXRoKTsKICAgIGlmIChlbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldCwgZmlsZXN0YXQ6IG51bGwgfTsKICAgIH0KICAgIHJldHVybiB7IHJldDogMCwgZmlsZXN0YXQ6IGVudHJ5LnN0YXQoKSB9OwogIH0KICBwYXRoX2xvb2t1cChwYXRoX3N0ciwgZGlyZmxhZ3MpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX3JldCwgcGF0aCB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXRoX3JldCwgaW5vZGVfb2JqOiBudWxsIH07CiAgICB9CiAgICBjb25zdCB7IHJldCwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9lbnRyeV9mb3JfcGF0aChwYXRoKTsKICAgIGlmIChlbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldCwgaW5vZGVfb2JqOiBudWxsIH07CiAgICB9CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGlub2RlX29iajogZW50cnkgfTsKICB9CiAgcGF0aF9vcGVuKGRpcmZsYWdzLCBwYXRoX3N0ciwgb2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcsIGZkX2ZsYWdzKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogcGF0aF9yZXQsIGZkX29iajogbnVsbCB9OwogICAgfQogICAgbGV0IHsgcmV0LCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgpOwogICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgaWYgKHJldCAhPSBFUlJOT19OT0VOVCkgewogICAgICAgIHJldHVybiB7IHJldCwgZmRfb2JqOiBudWxsIH07CiAgICAgIH0KICAgICAgaWYgKChvZmxhZ3MgJiBPRkxBR1NfQ1JFQVQpID09IE9GTEFHU19DUkVBVCkgewogICAgICAgIGNvbnN0IHsgcmV0OiByZXQyLCBlbnRyeTogbmV3X2VudHJ5IH0gPSB0aGlzLmRpci5jcmVhdGVfZW50cnlfZm9yX3BhdGgocGF0aF9zdHIsIChvZmxhZ3MgJiBPRkxBR1NfRElSRUNUT1JZKSA9PSBPRkxBR1NfRElSRUNUT1JZKTsKICAgICAgICBpZiAobmV3X2VudHJ5ID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiB7IHJldDogcmV0MiwgZmRfb2JqOiBudWxsIH07CiAgICAgICAgfQogICAgICAgIGVudHJ5ID0gbmV3X2VudHJ5OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9FTlQsIGZkX29iajogbnVsbCB9OwogICAgICB9CiAgICB9IGVsc2UgaWYgKChvZmxhZ3MgJiBPRkxBR1NfRVhDTCkgPT0gT0ZMQUdTX0VYQ0wpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19FWElTVCwgZmRfb2JqOiBudWxsIH07CiAgICB9CiAgICBpZiAoKG9mbGFncyAmIE9GTEFHU19ESVJFQ1RPUlkpID09IE9GTEFHU19ESVJFQ1RPUlkgJiYgZW50cnkuc3RhdCgpLmZpbGV0eXBlICE9PSBGSUxFVFlQRV9ESVJFQ1RPUlkpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIGZkX29iajogbnVsbCB9OwogICAgfQogICAgcmV0dXJuIGVudHJ5LnBhdGhfb3BlbihvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmZF9mbGFncyk7CiAgfQogIHBhdGhfY3JlYXRlX2RpcmVjdG9yeShwYXRoKSB7CiAgICByZXR1cm4gdGhpcy5wYXRoX29wZW4oMCwgcGF0aCwgT0ZMQUdTX0NSRUFUIHwgT0ZMQUdTX0RJUkVDVE9SWSwgMG4sIDBuLCAwKS5yZXQ7CiAgfQogIHBhdGhfbGluayhwYXRoX3N0ciwgaW5vZGUsIGFsbG93X2RpcikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4gcGF0aF9yZXQ7CiAgICB9CiAgICBpZiAocGF0aC5pc19kaXIpIHsKICAgICAgcmV0dXJuIEVSUk5PX05PRU5UOwogICAgfQogICAgY29uc3QgeyByZXQ6IHBhcmVudF9yZXQsIHBhcmVudF9lbnRyeSwgZmlsZW5hbWUsIGVudHJ5IH0gPSB0aGlzLmRpci5nZXRfcGFyZW50X2Rpcl9hbmRfZW50cnlfZm9yX3BhdGgocGF0aCwgdHJ1ZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCkgewogICAgICByZXR1cm4gcGFyZW50X3JldDsKICAgIH0KICAgIGlmIChlbnRyeSAhPSBudWxsKSB7CiAgICAgIGNvbnN0IHNvdXJjZV9pc19kaXIgPSBpbm9kZS5zdGF0KCkuZmlsZXR5cGUgPT0gRklMRVRZUEVfRElSRUNUT1JZOwogICAgICBjb25zdCB0YXJnZXRfaXNfZGlyID0gZW50cnkuc3RhdCgpLmZpbGV0eXBlID09IEZJTEVUWVBFX0RJUkVDVE9SWTsKICAgICAgaWYgKHNvdXJjZV9pc19kaXIgJiYgdGFyZ2V0X2lzX2RpcikgewogICAgICAgIGlmIChhbGxvd19kaXIgJiYgZW50cnkgaW5zdGFuY2VvZiBEaXJlY3RvcnkpIHsKICAgICAgICAgIGlmIChlbnRyeS5jb250ZW50cy5zaXplID09IDApIHsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBFUlJOT19OT1RFTVBUWTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIEVSUk5PX0VYSVNUOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChzb3VyY2VfaXNfZGlyICYmICF0YXJnZXRfaXNfZGlyKSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX05PVERJUjsKICAgICAgfSBlbHNlIGlmICghc291cmNlX2lzX2RpciAmJiB0YXJnZXRfaXNfZGlyKSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0lTRElSOwogICAgICB9IGVsc2UgaWYgKGlub2RlLnN0YXQoKS5maWxldHlwZSA9PSBGSUxFVFlQRV9SRUdVTEFSX0ZJTEUgJiYgZW50cnkuc3RhdCgpLmZpbGV0eXBlID09IEZJTEVUWVBFX1JFR1VMQVJfRklMRSkgewogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19FWElTVDsKICAgICAgfQogICAgfQogICAgaWYgKCFhbGxvd19kaXIgJiYgaW5vZGUuc3RhdCgpLmZpbGV0eXBlID09IEZJTEVUWVBFX0RJUkVDVE9SWSkgewogICAgICByZXR1cm4gRVJSTk9fUEVSTTsKICAgIH0KICAgIHBhcmVudF9lbnRyeS5jb250ZW50cy5zZXQoZmlsZW5hbWUsIGlub2RlKTsKICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogIH0KICBwYXRoX3VubGluayhwYXRoX3N0cikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhdGhfcmV0LCBpbm9kZV9vYmo6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBwYXJlbnRfcmV0LCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIHRydWUpOwogICAgaWYgKHBhcmVudF9lbnRyeSA9PSBudWxsIHx8IGZpbGVuYW1lID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXJlbnRfcmV0LCBpbm9kZV9vYmo6IG51bGwgfTsKICAgIH0KICAgIGlmIChlbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9FTlQsIGlub2RlX29iajogbnVsbCB9OwogICAgfQogICAgcGFyZW50X2VudHJ5LmNvbnRlbnRzLmRlbGV0ZShmaWxlbmFtZSk7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGlub2RlX29iajogZW50cnkgfTsKICB9CiAgcGF0aF91bmxpbmtfZmlsZShwYXRoX3N0cikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4gcGF0aF9yZXQ7CiAgICB9CiAgICBjb25zdCB7IHJldDogcGFyZW50X3JldCwgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9wYXJlbnRfZGlyX2FuZF9lbnRyeV9mb3JfcGF0aChwYXRoLCBmYWxzZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCB8fCBlbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXJlbnRfcmV0OwogICAgfQogICAgaWYgKGVudHJ5LnN0YXQoKS5maWxldHlwZSA9PT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgIHJldHVybiBFUlJOT19JU0RJUjsKICAgIH0KICAgIHBhcmVudF9lbnRyeS5jb250ZW50cy5kZWxldGUoZmlsZW5hbWUpOwogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIHBhdGhfcmVtb3ZlX2RpcmVjdG9yeShwYXRoX3N0cikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4gcGF0aF9yZXQ7CiAgICB9CiAgICBjb25zdCB7IHJldDogcGFyZW50X3JldCwgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9wYXJlbnRfZGlyX2FuZF9lbnRyeV9mb3JfcGF0aChwYXRoLCBmYWxzZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCB8fCBlbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXJlbnRfcmV0OwogICAgfQogICAgaWYgKCEoZW50cnkgaW5zdGFuY2VvZiBEaXJlY3RvcnkpIHx8IGVudHJ5LnN0YXQoKS5maWxldHlwZSAhPT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgIHJldHVybiBFUlJOT19OT1RESVI7CiAgICB9CiAgICBpZiAoZW50cnkuY29udGVudHMuc2l6ZSAhPT0gMCkgewogICAgICByZXR1cm4gRVJSTk9fTk9URU1QVFk7CiAgICB9CiAgICBpZiAoIXBhcmVudF9lbnRyeS5jb250ZW50cy5kZWxldGUoZmlsZW5hbWUpKSB7CiAgICAgIHJldHVybiBFUlJOT19OT0VOVDsKICAgIH0KICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogIH0KICBmZF9maWxlc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIGZpbGVzdGF0OiB0aGlzLmRpci5zdGF0KCkgfTsKICB9CiAgZmRfZmlsZXN0YXRfc2V0X3NpemUoc2l6ZSkgewogICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgfQogIGZkX3JlYWQoc2l6ZSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBkYXRhOiBuZXcgVWludDhBcnJheSgpIH07CiAgfQogIGZkX3ByZWFkKHNpemUsIG9mZnNldCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBkYXRhOiBuZXcgVWludDhBcnJheSgpIH07CiAgfQogIGZkX3dyaXRlKGRhdGEpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fQkFERiwgbndyaXR0ZW46IDAgfTsKICB9CiAgZmRfcHdyaXRlKGRhdGEsIG9mZnNldCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBud3JpdHRlbjogMCB9OwogIH0KICBjb25zdHJ1Y3RvcihkaXIpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLmRpciA9IGRpcjsKICB9Cn07CnZhciBQcmVvcGVuRGlyZWN0b3J5ID0gY2xhc3MgZXh0ZW5kcyBPcGVuRGlyZWN0b3J5IHsKICBmZF9wcmVzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgcHJlc3RhdDogUHJlc3RhdC5kaXIodGhpcy5wcmVzdGF0X25hbWUpIH07CiAgfQogIGNvbnN0cnVjdG9yKG5hbWUsIGNvbnRlbnRzKSB7CiAgICBzdXBlcihuZXcgRGlyZWN0b3J5KGNvbnRlbnRzKSk7CiAgICB0aGlzLnByZXN0YXRfbmFtZSA9IG5hbWU7CiAgfQp9Owp2YXIgRmlsZSA9IGNsYXNzIGV4dGVuZHMgSW5vZGUgewogIHBhdGhfb3BlbihvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmZF9mbGFncykgewogICAgaWYgKHRoaXMucmVhZG9ubHkgJiYgKGZzX3JpZ2h0c19iYXNlICYgQmlnSW50KFJJR0hUU19GRF9XUklURSkpID09IEJpZ0ludChSSUdIVFNfRkRfV1JJVEUpKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fUEVSTSwgZmRfb2JqOiBudWxsIH07CiAgICB9CiAgICBpZiAoKG9mbGFncyAmIE9GTEFHU19UUlVOQykgPT0gT0ZMQUdTX1RSVU5DKSB7CiAgICAgIGlmICh0aGlzLnJlYWRvbmx5KQogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fUEVSTSwgZmRfb2JqOiBudWxsIH07CiAgICAgIHRoaXMuZGF0YSA9IG5ldyBVaW50OEFycmF5KFtdKTsKICAgIH0KICAgIGNvbnN0IGZpbGUgPSBuZXcgT3BlbkZpbGUodGhpcyk7CiAgICBpZiAoZmRfZmxhZ3MgJiBGREZMQUdTX0FQUEVORCkKICAgICAgZmlsZS5mZF9zZWVrKDBuLCBXSEVOQ0VfRU5EKTsKICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZmRfb2JqOiBmaWxlIH07CiAgfQogIGdldCBzaXplKCkgewogICAgcmV0dXJuIEJpZ0ludCh0aGlzLmRhdGEuYnl0ZUxlbmd0aCk7CiAgfQogIHN0YXQoKSB7CiAgICByZXR1cm4gbmV3IEZpbGVzdGF0KEZJTEVUWVBFX1JFR1VMQVJfRklMRSwgdGhpcy5zaXplKTsKICB9CiAgY29uc3RydWN0b3IoZGF0YSwgb3B0aW9ucykgewogICAgc3VwZXIoKTsKICAgIHRoaXMuZGF0YSA9IG5ldyBVaW50OEFycmF5KGRhdGEpOwogICAgdGhpcy5yZWFkb25seSA9ICEhb3B0aW9ucz8ucmVhZG9ubHk7CiAgfQp9Owp2YXIgUGF0aCA9IGNsYXNzIFBhdGgyIHsKICBzdGF0aWMgZnJvbShwYXRoKSB7CiAgICBjb25zdCBzZWxmID0gbmV3IFBhdGgyKCk7CiAgICBzZWxmLmlzX2RpciA9IHBhdGguZW5kc1dpdGgoIi8iKTsKICAgIGlmIChwYXRoLnN0YXJ0c1dpdGgoIi8iKSkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVENBUEFCTEUsIHBhdGg6IG51bGwgfTsKICAgIH0KICAgIGlmIChwYXRoLmluY2x1ZGVzKCJcMCIpKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fSU5WQUwsIHBhdGg6IG51bGwgfTsKICAgIH0KICAgIGZvciAoY29uc3QgY29tcG9uZW50IG9mIHBhdGguc3BsaXQoIi8iKSkgewogICAgICBpZiAoY29tcG9uZW50ID09PSAiIiB8fCBjb21wb25lbnQgPT09ICIuIikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChjb21wb25lbnQgPT09ICIuLiIpIHsKICAgICAgICBpZiAoc2VsZi5wYXJ0cy5wb3AoKSA9PSB2b2lkIDApIHsKICAgICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UQ0FQQUJMRSwgcGF0aDogbnVsbCB9OwogICAgICAgIH0KICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBzZWxmLnBhcnRzLnB1c2goY29tcG9uZW50KTsKICAgIH0KICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgcGF0aDogc2VsZiB9OwogIH0KICB0b19wYXRoX3N0cmluZygpIHsKICAgIGxldCBzID0gdGhpcy5wYXJ0cy5qb2luKCIvIik7CiAgICBpZiAodGhpcy5pc19kaXIpIHsKICAgICAgcyArPSAiLyI7CiAgICB9CiAgICByZXR1cm4gczsKICB9CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLnBhcnRzID0gW107CiAgICB0aGlzLmlzX2RpciA9IGZhbHNlOwogIH0KfTsKdmFyIERpcmVjdG9yeSA9IGNsYXNzIGV4dGVuZHMgSW5vZGUgewogIHBhdGhfb3BlbihvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmZF9mbGFncykgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBmZF9vYmo6IG5ldyBPcGVuRGlyZWN0b3J5KHRoaXMpIH07CiAgfQogIHN0YXQoKSB7CiAgICByZXR1cm4gbmV3IEZpbGVzdGF0KEZJTEVUWVBFX0RJUkVDVE9SWSwgMG4pOwogIH0KICBnZXRfZW50cnlfZm9yX3BhdGgocGF0aCkgewogICAgbGV0IGVudHJ5ID0gdGhpczsKICAgIGZvciAoY29uc3QgY29tcG9uZW50IG9mIHBhdGgucGFydHMpIHsKICAgICAgaWYgKCEoZW50cnkgaW5zdGFuY2VvZiBEaXJlY3RvcnkpKSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIGVudHJ5OiBudWxsIH07CiAgICAgIH0KICAgICAgY29uc3QgY2hpbGQgPSBlbnRyeS5jb250ZW50cy5nZXQoY29tcG9uZW50KTsKICAgICAgaWYgKGNoaWxkICE9PSB2b2lkIDApIHsKICAgICAgICBlbnRyeSA9IGNoaWxkOwogICAgICB9IGVsc2UgewogICAgICAgIGRlYnVnLmxvZyhjb21wb25lbnQpOwogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9FTlQsIGVudHJ5OiBudWxsIH07CiAgICAgIH0KICAgIH0KICAgIGlmIChwYXRoLmlzX2RpcikgewogICAgICBpZiAoZW50cnkuc3RhdCgpLmZpbGV0eXBlICE9IEZJTEVUWVBFX0RJUkVDVE9SWSkgewogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9URElSLCBlbnRyeTogbnVsbCB9OwogICAgICB9CiAgICB9CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGVudHJ5IH07CiAgfQogIGdldF9wYXJlbnRfZGlyX2FuZF9lbnRyeV9mb3JfcGF0aChwYXRoLCBhbGxvd191bmRlZmluZWQpIHsKICAgIGNvbnN0IGZpbGVuYW1lID0gcGF0aC5wYXJ0cy5wb3AoKTsKICAgIGlmIChmaWxlbmFtZSA9PT0gdm9pZCAwKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fSU5WQUwsIHBhcmVudF9lbnRyeTogbnVsbCwgZmlsZW5hbWU6IG51bGwsIGVudHJ5OiBudWxsIH07CiAgICB9CiAgICBjb25zdCB7IHJldDogZW50cnlfcmV0LCBlbnRyeTogcGFyZW50X2VudHJ5IH0gPSB0aGlzLmdldF9lbnRyeV9mb3JfcGF0aChwYXRoKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IGVudHJ5X3JldCwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGlmICghKHBhcmVudF9lbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIHBhcmVudF9lbnRyeTogbnVsbCwgZmlsZW5hbWU6IG51bGwsIGVudHJ5OiBudWxsIH07CiAgICB9CiAgICBjb25zdCBlbnRyeSA9IHBhcmVudF9lbnRyeS5jb250ZW50cy5nZXQoZmlsZW5hbWUpOwogICAgaWYgKGVudHJ5ID09PSB2b2lkIDApIHsKICAgICAgaWYgKCFhbGxvd191bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PRU5ULCBwYXJlbnRfZW50cnk6IG51bGwsIGZpbGVuYW1lOiBudWxsLCBlbnRyeTogbnVsbCB9OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgfQogICAgaWYgKHBhdGguaXNfZGlyKSB7CiAgICAgIGlmIChlbnRyeS5zdGF0KCkuZmlsZXR5cGUgIT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIHBhcmVudF9lbnRyeTogbnVsbCwgZmlsZW5hbWU6IG51bGwsIGVudHJ5OiBudWxsIH07CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfTsKICB9CiAgY3JlYXRlX2VudHJ5X2Zvcl9wYXRoKHBhdGhfc3RyLCBpc19kaXIpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX3JldCwgcGF0aCB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXRoX3JldCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGxldCB7IHJldDogcGFyZW50X3JldCwgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfSA9IHRoaXMuZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIHRydWUpOwogICAgaWYgKHBhcmVudF9lbnRyeSA9PSBudWxsIHx8IGZpbGVuYW1lID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXJlbnRfcmV0LCBlbnRyeTogbnVsbCB9OwogICAgfQogICAgaWYgKGVudHJ5ICE9IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19FWElTVCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGRlYnVnLmxvZygiY3JlYXRlIiwgcGF0aCk7CiAgICBsZXQgbmV3X2NoaWxkOwogICAgaWYgKCFpc19kaXIpIHsKICAgICAgbmV3X2NoaWxkID0gbmV3IEZpbGUobmV3IEFycmF5QnVmZmVyKDApKTsKICAgIH0gZWxzZSB7CiAgICAgIG5ld19jaGlsZCA9IG5ldyBEaXJlY3RvcnkoLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKSk7CiAgICB9CiAgICBwYXJlbnRfZW50cnkuY29udGVudHMuc2V0KGZpbGVuYW1lLCBuZXdfY2hpbGQpOwogICAgZW50cnkgPSBuZXdfY2hpbGQ7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGVudHJ5IH07CiAgfQogIGNvbnN0cnVjdG9yKGNvbnRlbnRzKSB7CiAgICBzdXBlcigpOwogICAgaWYgKGNvbnRlbnRzIGluc3RhbmNlb2YgQXJyYXkpIHsKICAgICAgdGhpcy5jb250ZW50cyA9IG5ldyBNYXAoY29udGVudHMpOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5jb250ZW50cyA9IGNvbnRlbnRzOwogICAgfQogIH0KfTsKdmFyIENvbnNvbGVTdGRvdXQgPSBjbGFzcyBleHRlbmRzIEZkIHsKICBmZF9maWxlc3RhdF9nZXQoKSB7CiAgICBjb25zdCBmaWxlc3RhdCA9IG5ldyBGaWxlc3RhdChGSUxFVFlQRV9DSEFSQUNURVJfREVWSUNFLCBCaWdJbnQoMCkpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBmaWxlc3RhdCB9OwogIH0KICBmZF9mZHN0YXRfZ2V0KCkgewogICAgY29uc3QgZmRzdGF0ID0gbmV3IEZkc3RhdChGSUxFVFlQRV9DSEFSQUNURVJfREVWSUNFLCAwKTsKICAgIGZkc3RhdC5mc19yaWdodHNfYmFzZSA9IEJpZ0ludChSSUdIVFNfRkRfV1JJVEUpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBmZHN0YXQgfTsKICB9CiAgZmRfd3JpdGUoZGF0YSkgewogICAgdGhpcy53cml0ZShkYXRhKTsKICAgIHJldHVybiB7IHJldDogMCwgbndyaXR0ZW46IGRhdGEuYnl0ZUxlbmd0aCB9OwogIH0KICBzdGF0aWMgbGluZUJ1ZmZlcmVkKHdyaXRlKSB7CiAgICBjb25zdCBkZWMgPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IiwgeyBmYXRhbDogZmFsc2UgfSk7CiAgICBsZXQgbGluZV9idWYgPSAiIjsKICAgIHJldHVybiBuZXcgQ29uc29sZVN0ZG91dCgoYnVmZmVyKSA9PiB7CiAgICAgIGxpbmVfYnVmICs9IGRlYy5kZWNvZGUoYnVmZmVyLCB7IHN0cmVhbTogdHJ1ZSB9KTsKICAgICAgY29uc3QgbGluZXMgPSBsaW5lX2J1Zi5zcGxpdCgiXG4iKTsKICAgICAgZm9yIChjb25zdCBbaSwgbGluZV0gb2YgbGluZXMuZW50cmllcygpKSB7CiAgICAgICAgaWYgKGkgPCBsaW5lcy5sZW5ndGggLSAxKSB7CiAgICAgICAgICB3cml0ZShsaW5lKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbGluZV9idWYgPSBsaW5lOwogICAgICAgIH0KICAgICAgfQogICAgfSk7CiAgfQogIGNvbnN0cnVjdG9yKHdyaXRlKSB7CiAgICBzdXBlcigpOwogICAgdGhpcy53cml0ZSA9IHdyaXRlOwogIH0KfTsKCi8vIG5vZGVfbW9kdWxlcy93YXNtLWltcG9ydHMtcGFyc2VyL2luZGV4LmpzCmZ1bmN0aW9uIHBhcnNlSW1wb3J0cyhtb2R1bGVCeXRlcykgewogIGlmIChtb2R1bGVCeXRlcyBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHsKICB9IGVsc2UgaWYgKG1vZHVsZUJ5dGVzIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHsKICAgIG1vZHVsZUJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkobW9kdWxlQnl0ZXMpOwogIH0gZWxzZSBpZiAobW9kdWxlQnl0ZXMuYnVmZmVyIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHsKICAgIG1vZHVsZUJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkobW9kdWxlQnl0ZXMuYnVmZmVyKTsKICB9IGVsc2UgewogICAgdGhyb3cgbmV3IEVycm9yKCJBcmd1bWVudCBtdXN0IGJlIGEgYnVmZmVyIHNvdXJjZSwgbGlrZSBVaW50OEFycmF5IG9yIEFycmF5QnVmZmVyIik7CiAgfQogIGNvbnN0IHBhcnNlU3RhdGUgPSBuZXcgUGFyc2VTdGF0ZShtb2R1bGVCeXRlcyk7CiAgcGFyc2VNYWdpY051bWJlcihwYXJzZVN0YXRlKTsKICBwYXJzZVZlcnNpb24ocGFyc2VTdGF0ZSk7CiAgY29uc3QgdHlwZXMgPSBbXTsKICBjb25zdCBpbXBvcnRzID0gW107CiAgd2hpbGUgKHBhcnNlU3RhdGUuaGFzTW9yZUJ5dGVzKCkpIHsKICAgIGNvbnN0IHNlY3Rpb25JZCA9IHBhcnNlU3RhdGUucmVhZEJ5dGUoKTsKICAgIGNvbnN0IHNlY3Rpb25TaXplID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICAgIHN3aXRjaCAoc2VjdGlvbklkKSB7CiAgICAgIGNhc2UgMTogewogICAgICAgIGNvbnN0IHR5cGVDb3VudCA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0eXBlQ291bnQ7IGkrKykgewogICAgICAgICAgdHlwZXMucHVzaChwYXJzZUZ1bmN0aW9uVHlwZShwYXJzZVN0YXRlKSk7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGNhc2UgMjogewogICAgICAgIGNvbnN0IGltcG9ydENvdW50ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGltcG9ydENvdW50OyBpKyspIHsKICAgICAgICAgIGNvbnN0IG1vZHVsZSA9IHBhcnNlU3RhdGUucmVhZE5hbWUoKTsKICAgICAgICAgIGNvbnN0IG5hbWUgPSBwYXJzZVN0YXRlLnJlYWROYW1lKCk7CiAgICAgICAgICBjb25zdCB0eXBlID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogICAgICAgICAgc3dpdGNoICh0eXBlKSB7CiAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICBjb25zdCBpbmRleCA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgICAgICAgICAgICAgaW1wb3J0cy5wdXNoKHsgbW9kdWxlLCBuYW1lLCBraW5kOiAiZnVuY3Rpb24iLCB0eXBlOiB0eXBlc1tpbmRleF0gfSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgICBpbXBvcnRzLnB1c2goeyBtb2R1bGUsIG5hbWUsIGtpbmQ6ICJ0YWJsZSIsIHR5cGU6IHBhcnNlVGFibGVUeXBlKHBhcnNlU3RhdGUpIH0pOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgaW1wb3J0cy5wdXNoKHsgbW9kdWxlLCBuYW1lLCBraW5kOiAibWVtb3J5IiwgdHlwZTogcGFyc2VMaW1pdHMocGFyc2VTdGF0ZSkgfSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgICBpbXBvcnRzLnB1c2goeyBtb2R1bGUsIG5hbWUsIGtpbmQ6ICJnbG9iYWwiLCB0eXBlOiBwYXJzZUdsb2JhbFR5cGUocGFyc2VTdGF0ZSkgfSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGltcG9ydCBkZXNjcmlwdG9yIHR5cGUgJHt0eXBlfWApOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gaW1wb3J0czsKICAgICAgfQogICAgICBkZWZhdWx0OiB7CiAgICAgICAgcGFyc2VTdGF0ZS5za2lwQnl0ZXMoc2VjdGlvblNpemUpOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfQogIHJldHVybiBbXTsKfQp2YXIgUGFyc2VTdGF0ZSA9IGNsYXNzIHsKICBjb25zdHJ1Y3Rvcihtb2R1bGVCeXRlcykgewogICAgdGhpcy5tb2R1bGVCeXRlcyA9IG1vZHVsZUJ5dGVzOwogICAgdGhpcy5vZmZzZXQgPSAwOwogICAgdGhpcy50ZXh0RGVjb2RlciA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKTsKICB9CiAgaGFzTW9yZUJ5dGVzKCkgewogICAgcmV0dXJuIHRoaXMub2Zmc2V0IDwgdGhpcy5tb2R1bGVCeXRlcy5sZW5ndGg7CiAgfQogIHJlYWRCeXRlKCkgewogICAgcmV0dXJuIHRoaXMubW9kdWxlQnl0ZXNbdGhpcy5vZmZzZXQrK107CiAgfQogIHNraXBCeXRlcyhjb3VudCkgewogICAgdGhpcy5vZmZzZXQgKz0gY291bnQ7CiAgfQogIHJlYWRVbnNpZ25lZExFQjEyOCgpIHsKICAgIGxldCByZXN1bHQgPSAwOwogICAgbGV0IHNoaWZ0ID0gMDsKICAgIGxldCBieXRlOwogICAgZG8gewogICAgICBieXRlID0gdGhpcy5yZWFkQnl0ZSgpOwogICAgICByZXN1bHQgfD0gKGJ5dGUgJiAxMjcpIDw8IHNoaWZ0OwogICAgICBzaGlmdCArPSA3OwogICAgfSB3aGlsZSAoYnl0ZSAmIDEyOCk7CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICByZWFkTmFtZSgpIHsKICAgIGNvbnN0IG5hbWVMZW5ndGggPSB0aGlzLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgY29uc3QgbmFtZUJ5dGVzID0gdGhpcy5tb2R1bGVCeXRlcy5zbGljZSh0aGlzLm9mZnNldCwgdGhpcy5vZmZzZXQgKyBuYW1lTGVuZ3RoKTsKICAgIGNvbnN0IG5hbWUgPSB0aGlzLnRleHREZWNvZGVyLmRlY29kZShuYW1lQnl0ZXMpOwogICAgdGhpcy5vZmZzZXQgKz0gbmFtZUxlbmd0aDsKICAgIHJldHVybiBuYW1lOwogIH0KICBhc3NlcnRCeXRlcyhleHBlY3RlZCkgewogICAgY29uc3QgYmFzZU9mZnNldCA9IHRoaXMub2Zmc2V0OwogICAgY29uc3QgZXhwZWN0ZWRMZW5ndGggPSBleHBlY3RlZC5sZW5ndGg7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGV4cGVjdGVkTGVuZ3RoOyBpKyspIHsKICAgICAgaWYgKHRoaXMubW9kdWxlQnl0ZXNbYmFzZU9mZnNldCArIGldICE9PSBleHBlY3RlZFtpXSkgewogICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgJHtleHBlY3RlZH0gYXQgb2Zmc2V0ICR7YmFzZU9mZnNldH1gKTsKICAgICAgfQogICAgfQogICAgdGhpcy5vZmZzZXQgKz0gZXhwZWN0ZWRMZW5ndGg7CiAgfQp9OwpmdW5jdGlvbiBwYXJzZU1hZ2ljTnVtYmVyKHBhcnNlU3RhdGUpIHsKICBjb25zdCBleHBlY3RlZCA9IFswLCA5NywgMTE1LCAxMDldOwogIHBhcnNlU3RhdGUuYXNzZXJ0Qnl0ZXMoZXhwZWN0ZWQpOwp9CmZ1bmN0aW9uIHBhcnNlVmVyc2lvbihwYXJzZVN0YXRlKSB7CiAgY29uc3QgZXhwZWN0ZWQgPSBbMSwgMCwgMCwgMF07CiAgcGFyc2VTdGF0ZS5hc3NlcnRCeXRlcyhleHBlY3RlZCk7Cn0KZnVuY3Rpb24gcGFyc2VUYWJsZVR5cGUocGFyc2VTdGF0ZSkgewogIGNvbnN0IGVsZW1lbnRUeXBlID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogIGxldCBlbGVtZW50OwogIHN3aXRjaCAoZWxlbWVudFR5cGUpIHsKICAgIGNhc2UgMTEyOgogICAgICBlbGVtZW50ID0gImZ1bmNyZWYiOwogICAgICBicmVhazsKICAgIGNhc2UgMTExOgogICAgICBlbGVtZW50ID0gImV4dGVybnJlZiI7CiAgICAgIGJyZWFrOwogICAgZGVmYXVsdDoKICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIHRhYmxlIGVsZW1lbnQgdHlwZSAke2VsZW1lbnRUeXBlfWApOwogIH0KICBjb25zdCB7IG1pbmltdW0sIG1heGltdW0gfSA9IHBhcnNlTGltaXRzKHBhcnNlU3RhdGUpOwogIGlmIChtYXhpbXVtKSB7CiAgICByZXR1cm4geyBlbGVtZW50LCBtaW5pbXVtLCBtYXhpbXVtIH07CiAgfSBlbHNlIHsKICAgIHJldHVybiB7IGVsZW1lbnQsIG1pbmltdW0gfTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VMaW1pdHMocGFyc2VTdGF0ZSkgewogIGNvbnN0IGZsYWdzID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogIGNvbnN0IG1pbmltdW0gPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogIGNvbnN0IGhhc01heGltdW0gPSBmbGFncyAmIDE7CiAgY29uc3Qgc2hhcmVkID0gKGZsYWdzICYgMikgIT09IDA7CiAgY29uc3QgaXNNZW1vcnk2NCA9IChmbGFncyAmIDQpICE9PSAwOwogIGNvbnN0IGluZGV4ID0gaXNNZW1vcnk2NCA/ICJpNjQiIDogImkzMiI7CiAgaWYgKGhhc01heGltdW0pIHsKICAgIGNvbnN0IG1heGltdW0gPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgcmV0dXJuIHsgbWluaW11bSwgc2hhcmVkLCBpbmRleCwgbWF4aW11bSB9OwogIH0gZWxzZSB7CiAgICByZXR1cm4geyBtaW5pbXVtLCBzaGFyZWQsIGluZGV4IH07CiAgfQp9CmZ1bmN0aW9uIHBhcnNlR2xvYmFsVHlwZShwYXJzZVN0YXRlKSB7CiAgY29uc3QgdmFsdWUgPSBwYXJzZVZhbHVlVHlwZShwYXJzZVN0YXRlKTsKICBjb25zdCBtdXRhYmxlID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpID09PSAxOwogIHJldHVybiB7IHZhbHVlLCBtdXRhYmxlIH07Cn0KZnVuY3Rpb24gcGFyc2VWYWx1ZVR5cGUocGFyc2VTdGF0ZSkgewogIGNvbnN0IHR5cGUgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgc3dpdGNoICh0eXBlKSB7CiAgICBjYXNlIDEyNzoKICAgICAgcmV0dXJuICJpMzIiOwogICAgY2FzZSAxMjY6CiAgICAgIHJldHVybiAiaTY0IjsKICAgIGNhc2UgMTI1OgogICAgICByZXR1cm4gImYzMiI7CiAgICBjYXNlIDEyNDoKICAgICAgcmV0dXJuICJmNjQiOwogICAgY2FzZSAxMTI6CiAgICAgIHJldHVybiAiZnVuY3JlZiI7CiAgICBjYXNlIDExMToKICAgICAgcmV0dXJuICJleHRlcm5yZWYiOwogICAgY2FzZSAxMjM6CiAgICAgIHJldHVybiAidjEyOCI7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gdmFsdWUgdHlwZSAke3R5cGV9YCk7CiAgfQp9CmZ1bmN0aW9uIHBhcnNlRnVuY3Rpb25UeXBlKHBhcnNlU3RhdGUpIHsKICBjb25zdCBmb3JtID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogIGlmIChmb3JtICE9PSA5NikgewogICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBmdW5jdGlvbiB0eXBlIGZvcm0gMHg2MCwgZ290ICR7Zm9ybX1gKTsKICB9CiAgY29uc3QgcGFyYW1ldGVycyA9IFtdOwogIGNvbnN0IHBhcmFtZXRlckNvdW50ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICBmb3IgKGxldCBpID0gMDsgaSA8IHBhcmFtZXRlckNvdW50OyBpKyspIHsKICAgIHBhcmFtZXRlcnMucHVzaChwYXJzZVZhbHVlVHlwZShwYXJzZVN0YXRlKSk7CiAgfQogIGNvbnN0IHJlc3VsdHMgPSBbXTsKICBjb25zdCByZXN1bHRDb3VudCA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgZm9yIChsZXQgaSA9IDA7IGkgPCByZXN1bHRDb3VudDsgaSsrKSB7CiAgICByZXN1bHRzLnB1c2gocGFyc2VWYWx1ZVR5cGUocGFyc2VTdGF0ZSkpOwogIH0KICByZXR1cm4geyBwYXJhbWV0ZXJzLCByZXN1bHRzIH07Cn0KCi8vIG5vZGVfbW9kdWxlcy93YXNtLWltcG9ydHMtcGFyc2VyL3BvbHlmaWxsLmpzCnZhciBoYXNXYXNtVHlwZVJlZmxlY3Rpb25TdXBwb3J0ID0gKCgpID0+IHsKICBjb25zdCBtb2R1bGVCeXRlcyA9IG5ldyBVaW50OEFycmF5KFsKICAgIDAsCiAgICA5NywKICAgIDExNSwKICAgIDEwOSwKICAgIDEsCiAgICAwLAogICAgMCwKICAgIDAsCiAgICAyLAogICAgNiwKICAgIDEsCiAgICAwLAogICAgMCwKICAgIDIsCiAgICAwLAogICAgMQogIF0pOwogIGNvbnN0IG1vZHVsZSA9IG5ldyBXZWJBc3NlbWJseS5Nb2R1bGUobW9kdWxlQnl0ZXMpOwogIGNvbnN0IGltcG9ydHMgPSBXZWJBc3NlbWJseS5Nb2R1bGUuaW1wb3J0cyhtb2R1bGUpOwogIGNvbnN0IG1lbW9yeUltcG9ydCA9IGltcG9ydHNbMF07CiAgcmV0dXJuIHR5cGVvZiBtZW1vcnlJbXBvcnQudHlwZSA9PT0gIm9iamVjdCI7Cn0pKCk7CmZ1bmN0aW9uIHBvbHlmaWxsKFdlYkFzc2VtYmx5MykgewogIGlmIChoYXNXYXNtVHlwZVJlZmxlY3Rpb25TdXBwb3J0KSB7CiAgICByZXR1cm4gV2ViQXNzZW1ibHkzOwogIH0KICBjb25zdCBuZXdXZWJBc3NlbWJseSA9IHt9OwogIGZvciAoY29uc3Qga2V5IGluIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzKFdlYkFzc2VtYmx5MykpIHsKICAgIG5ld1dlYkFzc2VtYmx5W2tleV0gPSBXZWJBc3NlbWJseTNba2V5XTsKICB9CiAgY29uc3QgcG9seWZpbGxlZEltcG9ydHNTeW1ib2wgPSBTeW1ib2woInBvbHlmaWxsZWRJbXBvcnRzU3ltYm9sIik7CiAgY29uc3QgYXNzaWduSW1wb3J0cyA9IChtb2R1bGUsIHNvdXJjZUJ5dGVzKSA9PiB7CiAgICBtb2R1bGVbcG9seWZpbGxlZEltcG9ydHNTeW1ib2xdID0gcGFyc2VJbXBvcnRzKHNvdXJjZUJ5dGVzKTsKICB9OwogIGNvbnN0IG5ld01vZHVsZSA9IG5ld1dlYkFzc2VtYmx5Lk1vZHVsZSA9IGZ1bmN0aW9uKGJ5dGVzKSB7CiAgICBjb25zdCBtb2R1bGUgPSBuZXcgV2ViQXNzZW1ibHkzLk1vZHVsZShieXRlcyk7CiAgICBhc3NpZ25JbXBvcnRzKG1vZHVsZSwgYnl0ZXMpOwogICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKG1vZHVsZSwgbmV3TW9kdWxlLnByb3RvdHlwZSk7CiAgICByZXR1cm4gbW9kdWxlOwogIH07CiAgT2JqZWN0LnNldFByb3RvdHlwZU9mKG5ld01vZHVsZS5wcm90b3R5cGUsIFdlYkFzc2VtYmx5My5Nb2R1bGUucHJvdG90eXBlKTsKICBuZXdXZWJBc3NlbWJseS5jb21waWxlID0gYXN5bmMgKHNvdXJjZSkgPT4gewogICAgY29uc3QgbW9kdWxlID0gYXdhaXQgV2ViQXNzZW1ibHkzLmNvbXBpbGUoc291cmNlKTsKICAgIGFzc2lnbkltcG9ydHMobW9kdWxlLCBzb3VyY2UpOwogICAgcmV0dXJuIG1vZHVsZTsKICB9OwogIGlmIChXZWJBc3NlbWJseTMuY29tcGlsZVN0cmVhbWluZykgewogICAgbmV3V2ViQXNzZW1ibHkuY29tcGlsZVN0cmVhbWluZyA9IGFzeW5jIChzb3VyY2UpID0+IHsKICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBzb3VyY2U7CiAgICAgIGNvbnN0IGNsb25lID0gcmVzcG9uc2UuY2xvbmUoKTsKICAgICAgY29uc3QgbW9kdWxlID0gYXdhaXQgV2ViQXNzZW1ibHkzLmNvbXBpbGVTdHJlYW1pbmcocmVzcG9uc2UpOwogICAgICBhc3NpZ25JbXBvcnRzKG1vZHVsZSwgbmV3IFVpbnQ4QXJyYXkoYXdhaXQgY2xvbmUuYXJyYXlCdWZmZXIoKSkpOwogICAgICByZXR1cm4gbW9kdWxlOwogICAgfTsKICB9CiAgbmV3TW9kdWxlLmltcG9ydHMgPSAobW9kdWxlKSA9PiB7CiAgICBjb25zdCBwYXJzZWRJbXBvcnRzID0gbW9kdWxlW3BvbHlmaWxsZWRJbXBvcnRzU3ltYm9sXTsKICAgIGlmICghcGFyc2VkSW1wb3J0cykgewogICAgICByZXR1cm4gV2ViQXNzZW1ibHkzLk1vZHVsZS5pbXBvcnRzKG1vZHVsZSk7CiAgICB9CiAgICByZXR1cm4gcGFyc2VkSW1wb3J0czsKICB9OwogIHJldHVybiBuZXdXZWJBc3NlbWJseTsKfQoKLy8gZW50cnlwb2ludC9pbnRyaW5zaWNzLnRzCnZhciBXZWJBc3NlbWJseTIgPSBwb2x5ZmlsbChnbG9iYWxUaGlzLldlYkFzc2VtYmx5KTsKdmFyIExpbmVEZWNvZGVyID0gY2xhc3MgewogIGNvbnN0cnVjdG9yKG9uTGluZSkgewogICAgdGhpcy5kZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIsIHsgZmF0YWw6IGZhbHNlIH0pOwogICAgdGhpcy5idWZmZXIgPSAiIjsKICAgIHRoaXMub25MaW5lID0gb25MaW5lOwogIH0KICBkZWNvZGVyOwogIGJ1ZmZlcjsKICBvbkxpbmU7CiAgc2VuZChjaHVuaykgewogICAgdGhpcy5idWZmZXIgKz0gdGhpcy5kZWNvZGVyLmRlY29kZShjaHVuaywgeyBzdHJlYW06IHRydWUgfSk7CiAgICBjb25zdCBsaW5lcyA9IHRoaXMuYnVmZmVyLnNwbGl0KCJcbiIpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGggLSAxOyBpKyspIHsKICAgICAgdGhpcy5vbkxpbmUobGluZXNbaV0pOwogICAgfQogICAgdGhpcy5idWZmZXIgPSBsaW5lc1tsaW5lcy5sZW5ndGggLSAxXTsKICB9Cn07CmFzeW5jIGZ1bmN0aW9uIGluc3RhbnRpYXRlKHJhd09wdGlvbnMsIGV4dHJhV2FzbUltcG9ydHMpIHsKICBjb25zdCBvcHRpb25zID0gZGVmYXVsdEluc3RhbnRpYXRpb25PcHRpb25zKHJhd09wdGlvbnMpOwogIGxldCBzd2lmdCA9IG9wdGlvbnMuc3dpZnQ7CiAgaWYgKCFzd2lmdCAmJiBvcHRpb25zLlN3aWZ0UnVudGltZSkgewogICAgc3dpZnQgPSBuZXcgb3B0aW9ucy5Td2lmdFJ1bnRpbWUoKTsKICB9CiAgbGV0IHN0ZG91dExpbmUgPSB2b2lkIDA7CiAgaWYgKG9wdGlvbnMub25TdGRvdXRMaW5lICE9IG51bGwpIHsKICAgIHN0ZG91dExpbmUgPSBuZXcgTGluZURlY29kZXIob3B0aW9ucy5vblN0ZG91dExpbmUpOwogIH0KICBjb25zdCBzdGRvdXQgPSBuZXcgQ29uc29sZVN0ZG91dCgoY2h1bmspID0+IHsKICAgIG9wdGlvbnMub25TdGRvdXQ/LmNhbGwodm9pZCAwLCBjaHVuayk7CiAgICBzdGRvdXRMaW5lPy5zZW5kKGNodW5rKTsKICB9KTsKICBsZXQgc3RkZXJyTGluZSA9IHZvaWQgMDsKICBpZiAob3B0aW9ucy5vblN0ZGVyckxpbmUgIT0gbnVsbCkgewogICAgc3RkZXJyTGluZSA9IG5ldyBMaW5lRGVjb2RlcihvcHRpb25zLm9uU3RkZXJyTGluZSk7CiAgfQogIGNvbnN0IHN0ZGVyciA9IG5ldyBDb25zb2xlU3Rkb3V0KChjaHVuaykgPT4gewogICAgb3B0aW9ucy5vblN0ZGVycj8uY2FsbCh2b2lkIDAsIGNodW5rKTsKICAgIHN0ZGVyckxpbmU/LnNlbmQoY2h1bmspOwogIH0pOwogIGNvbnN0IGFyZ3MgPSBvcHRpb25zLmFyZ3MgfHwgW107CiAgY29uc3QgZmRzID0gWwogICAgbmV3IE9wZW5GaWxlKG5ldyBGaWxlKFtdKSksCiAgICBzdGRvdXQsCiAgICBzdGRlcnIsCiAgICBuZXcgUHJlb3BlbkRpcmVjdG9yeSgiLyIsIC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCkpCiAgXTsKICBjb25zdCBlbnZzID0gb3B0aW9ucy5lbnYgPyBPYmplY3QuZW50cmllcyhvcHRpb25zLmVudikubWFwKChba2V5LCB2YWx1ZV0pID0+IGAke2tleX09JHt2YWx1ZX1gKSA6IFtdOwogIGNvbnN0IHdhc2kgPSBuZXcgV0FTSShhcmdzLCBlbnZzLCBmZHMsIHsKICAgIGRlYnVnOiBmYWxzZQogIH0pOwogIGNvbnN0IGNyZWF0ZVdhc21JbXBvcnRPYmplY3QgPSAoZXh0cmFXYXNtSW1wb3J0czIsIG1vZHVsZSkgPT4gewogICAgY29uc3QgaW1wb3J0T2JqZWN0MiA9IHsKICAgICAgd2FzaV9zbmFwc2hvdF9wcmV2aWV3MTogd2FzaS53YXNpSW1wb3J0CiAgICB9OwogICAgaWYgKHN3aWZ0KSB7CiAgICAgIGltcG9ydE9iamVjdDIuamF2YXNjcmlwdF9raXQgPSBzd2lmdC53YXNtSW1wb3J0czsKICAgIH0KICAgIGlmIChleHRyYVdhc21JbXBvcnRzMikgewogICAgICBmb3IgKGNvbnN0IG1vZHVsZU5hbWUgaW4gZXh0cmFXYXNtSW1wb3J0czIpIHsKICAgICAgICBpZiAoIWltcG9ydE9iamVjdDJbbW9kdWxlTmFtZV0pIHsKICAgICAgICAgIGltcG9ydE9iamVjdDJbbW9kdWxlTmFtZV0gPSB7fTsKICAgICAgICB9CiAgICAgICAgZm9yIChjb25zdCBlbnRyeSBpbiBleHRyYVdhc21JbXBvcnRzMlttb2R1bGVOYW1lXSkgewogICAgICAgICAgaW1wb3J0T2JqZWN0Mlttb2R1bGVOYW1lXVtlbnRyeV0gPSBleHRyYVdhc21JbXBvcnRzMlttb2R1bGVOYW1lXVtlbnRyeV07CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBmb3IgKGNvbnN0IF9pbXBvcnRFbnRyeSBvZiBXZWJBc3NlbWJseTIuTW9kdWxlLmltcG9ydHMobW9kdWxlKSkgewogICAgICBjb25zdCBpbXBvcnRFbnRyeSA9IF9pbXBvcnRFbnRyeTsKICAgICAgaWYgKCFpbXBvcnRPYmplY3QyW2ltcG9ydEVudHJ5Lm1vZHVsZV0pIHsKICAgICAgICBpbXBvcnRPYmplY3QyW2ltcG9ydEVudHJ5Lm1vZHVsZV0gPSB7fTsKICAgICAgfQogICAgICBpZiAoaW1wb3J0T2JqZWN0MltpbXBvcnRFbnRyeS5tb2R1bGVdW2ltcG9ydEVudHJ5Lm5hbWVdKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGltcG9ydEVudHJ5LmtpbmQgPT0gImZ1bmN0aW9uIikgewogICAgICAgIGltcG9ydE9iamVjdDJbaW1wb3J0RW50cnkubW9kdWxlXVtpbXBvcnRFbnRyeS5uYW1lXSA9ICgpID0+IHsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW1wb3J0ZWQgZnVuY3Rpb24gJHtpbXBvcnRFbnRyeS5tb2R1bGV9LiR7aW1wb3J0RW50cnkubmFtZX0gbm90IGltcGxlbWVudGVkYCk7CiAgICAgICAgfTsKICAgICAgfSBlbHNlIGlmIChpbXBvcnRFbnRyeS5raW5kID09ICJtZW1vcnkiICYmIGltcG9ydEVudHJ5Lm1vZHVsZSA9PSAiZW52IiAmJiBpbXBvcnRFbnRyeS5uYW1lID09ICJtZW1vcnkiKSB7CiAgICAgICAgY29uc3QgdHlwZSA9IGltcG9ydEVudHJ5LnR5cGU7CiAgICAgICAgY29uc3QgZGVzY3JpcHRvciA9IHsKICAgICAgICAgIGluaXRpYWw6IHR5cGUubWluaW11bSwKICAgICAgICAgIG1heGltdW06IHR5cGUubWF4aW11bSwKICAgICAgICAgIHNoYXJlZDogdHlwZS5zaGFyZWQKICAgICAgICB9OwogICAgICAgIGltcG9ydE9iamVjdDJbaW1wb3J0RW50cnkubW9kdWxlXVtpbXBvcnRFbnRyeS5uYW1lXSA9IG5ldyBXZWJBc3NlbWJseTIuTWVtb3J5KGRlc2NyaXB0b3IpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gaW1wb3J0T2JqZWN0MjsKICB9OwogIGNvbnN0IGltcG9ydE9iamVjdCA9IGNyZWF0ZVdhc21JbXBvcnRPYmplY3QoZXh0cmFXYXNtSW1wb3J0cywgb3B0aW9ucy5tb2R1bGUpOwogIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgV2ViQXNzZW1ibHkyLmluc3RhbnRpYXRlKG9wdGlvbnMubW9kdWxlLCBpbXBvcnRPYmplY3QpOwogIGlmIChzd2lmdCAmJiBpbnN0YW5jZS5leHBvcnRzLnN3anNfbGlicmFyeV92ZXJzaW9uKSB7CiAgICBzd2lmdC5zZXRJbnN0YW5jZShpbnN0YW5jZSk7CiAgfQogIGlmICh0eXBlb2YgaW5zdGFuY2UuZXhwb3J0cy5fc3RhcnQgPT09ICJmdW5jdGlvbiIpIHsKICAgIHdhc2kuc3RhcnQoaW5zdGFuY2UpOwogIH0gZWxzZSBpZiAodHlwZW9mIGluc3RhbmNlLmV4cG9ydHMuX2luaXRpYWxpemUgPT0gImZ1bmN0aW9uIikgewogICAgd2FzaS5pbml0aWFsaXplKGluc3RhbmNlKTsKICAgIGlmIChzd2lmdCAmJiBzd2lmdC5tYWluKSB7CiAgICAgIHN3aWZ0Lm1haW4oKTsKICAgIH0gZWxzZSB7CiAgICAgIGlmICh0eXBlb2YgaW5zdGFuY2UuZXhwb3J0cy5tYWluID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgaW5zdGFuY2UuZXhwb3J0cy5tYWluKCk7CiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGluc3RhbmNlLmV4cG9ydHMuX19tYWluX2FyZ2NfYXJndiA9PT0gImZ1bmN0aW9uIikgewogICAgICAgIGluc3RhbmNlLmV4cG9ydHMuX19tYWluX2FyZ2NfYXJndigwLCAwKTsKICAgICAgfQogICAgfQogIH0KICByZXR1cm4geyBpbnN0YW5jZSB9Owp9CmZ1bmN0aW9uIGRlZmF1bHRJbnN0YW50aWF0aW9uT3B0aW9ucyhvcHRpb25zKSB7CiAgaWYgKG9wdGlvbnMuYXJncyA9PSBudWxsKSB7CiAgICBvcHRpb25zLmFyZ3MgPSBbIm1haW4ud2FzbSJdOwogIH0KICBjb25zdCBpc05vZGVKcyA9IHR5cGVvZiBwcm9jZXNzICE9PSAidW5kZWZpbmVkIiAmJiBwcm9jZXNzLnJlbGVhc2UubmFtZSA9PT0gIm5vZGUiOwogIGNvbnN0IGlzV2ViQnJvd3NlciA9IHR5cGVvZiB3aW5kb3cgIT09ICJ1bmRlZmluZWQiOwogIGlmIChpc05vZGVKcykgewogICAgaWYgKCFvcHRpb25zLm9uU3Rkb3V0KSB7CiAgICAgIG9wdGlvbnMub25TdGRvdXQgPSAoY2h1bmspID0+IHByb2Nlc3Muc3Rkb3V0LndyaXRlKGNodW5rKTsKICAgIH0KICAgIGlmICghb3B0aW9ucy5vblN0ZGVycikgewogICAgICBvcHRpb25zLm9uU3RkZXJyID0gKGNodW5rKSA9PiBwcm9jZXNzLnN0ZGVyci53cml0ZShjaHVuayk7CiAgICB9CiAgfSBlbHNlIGlmIChpc1dlYkJyb3dzZXIpIHsKICAgIGlmICghb3B0aW9ucy5vblN0ZG91dExpbmUpIHsKICAgICAgb3B0aW9ucy5vblN0ZG91dExpbmUgPSAobGluZSkgPT4gY29uc29sZS5sb2cobGluZSk7CiAgICB9CiAgICBpZiAoIW9wdGlvbnMub25TdGRlcnJMaW5lKSB7CiAgICAgIG9wdGlvbnMub25TdGRlcnJMaW5lID0gKGxpbmUpID0+IGNvbnNvbGUud2FybihsaW5lKTsKICAgIH0KICB9CiAgcmV0dXJuIG9wdGlvbnM7Cn0KCi8vIGVudHJ5cG9pbnQvZGV2LnRzCnZhciBzb2NrZXQgPSBuZXcgcmVjb25uZWN0aW5nX3dlYnNvY2tldF9tanNfZGVmYXVsdChgd3M6Ly8ke2xvY2F0aW9uLmhvc3R9L3dhdGNoZXJgKTsKc29ja2V0LmFkZEV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLCAobWVzc2FnZSkgPT4gewogIGlmIChtZXNzYWdlLmRhdGEgPT09ICJyZWxvYWQiKSB7CiAgICBsb2NhdGlvbi5yZWxvYWQoKTsKICB9Cn0pOwp2YXIgc3RhcnRXYXNpVGFzayA9IGFzeW5jICgpID0+IHsKICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKCIvbWFpbi53YXNtIik7CiAgbGV0IHJ1bnRpbWVDb25zdHJ1Y3RvciA9IHZvaWQgMDsKICB0cnkgewogICAgY29uc3QgeyBTd2lmdFJ1bnRpbWUgfSA9IGF3YWl0IGltcG9ydCgKICAgICAgLy8gQHRzLWlnbm9yZQogICAgICAiLi9KYXZhU2NyaXB0S2l0X0phdmFTY3JpcHRLaXQucmVzb3VyY2VzL1J1bnRpbWUvaW5kZXgubWpzIgogICAgKTsKICAgIHJ1bnRpbWVDb25zdHJ1Y3RvciA9IFN3aWZ0UnVudGltZTsKICB9IGNhdGNoIHsKICAgIGNvbnNvbGUubG9nKCJKYXZhU2NyaXB0S2l0IG1vZHVsZSBub3QgYXZhaWxhYmxlLCBydW5uaW5nIHdpdGhvdXQgSmF2YVNjcmlwdEtpdCBydW50aW1lLiIpOwogIH0KICBhd2FpdCBpbnN0YW50aWF0ZSh7CiAgICBtb2R1bGU6IGF3YWl0IFdlYkFzc2VtYmx5Mi5jb21waWxlU3RyZWFtaW5nKHJlc3BvbnNlKSwKICAgIG9uU3Rkb3V0KGNodW5rKSB7CiAgICAgIGNvbnN0IGtpbmRCdWZmZXIgPSBuZXcgQXJyYXlCdWZmZXIoMik7CiAgICAgIG5ldyBEYXRhVmlldyhraW5kQnVmZmVyKS5zZXRVaW50MTYoMCwgMTAwMSwgdHJ1ZSk7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBVaW50OEFycmF5KDIgKyBjaHVuay5sZW5ndGgpOwogICAgICBidWZmZXIuc2V0KG5ldyBVaW50OEFycmF5KGtpbmRCdWZmZXIpLCAwKTsKICAgICAgYnVmZmVyLnNldChjaHVuaywgMik7CiAgICAgIHNvY2tldC5zZW5kKGJ1ZmZlcik7CiAgICB9LAogICAgb25TdGRvdXRMaW5lKGxpbmUpIHsKICAgICAgY29uc29sZS5sb2cobGluZSk7CiAgICB9LAogICAgb25TdGRlcnIoY2h1bmspIHsKICAgICAgY29uc3Qga2luZEJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcigyKTsKICAgICAgbmV3IERhdGFWaWV3KGtpbmRCdWZmZXIpLnNldFVpbnQxNigwLCAxMDAyLCB0cnVlKTsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IFVpbnQ4QXJyYXkoMiArIGNodW5rLmxlbmd0aCk7CiAgICAgIGJ1ZmZlci5zZXQobmV3IFVpbnQ4QXJyYXkoa2luZEJ1ZmZlciksIDApOwogICAgICBidWZmZXIuc2V0KGNodW5rLCAyKTsKICAgICAgc29ja2V0LnNlbmQoYnVmZmVyKTsKICAgIH0sCiAgICBvblN0ZGVyckxpbmUobGluZSkgewogICAgICBjb25zb2xlLmVycm9yKGxpbmUpOwogICAgfSwKICAgIFN3aWZ0UnVudGltZTogcnVudGltZUNvbnN0cnVjdG9yCiAgfSk7Cn07CmZ1bmN0aW9uIGhhbmRsZUVycm9yKGUpIHsKICBpZiAoZSBpbnN0YW5jZW9mIEVycm9yKSB7CiAgICBjb25zdCBzdGFjayA9IGUuc3RhY2s7CiAgICBpZiAoc3RhY2sgIT0gbnVsbCkgewogICAgICBzb2NrZXQuc2VuZChKU09OLnN0cmluZ2lmeSh7CiAgICAgICAga2luZDogInN0YWNrVHJhY2UiLAogICAgICAgIHN0YWNrVHJhY2U6IHN0YWNrCiAgICAgIH0pKTsKICAgIH0KICB9Cn0KYXN5bmMgZnVuY3Rpb24gbWFpbigpIHsKICB0cnkgewogICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoImVycm9yIiwgKGV2ZW50KSA9PiB7CiAgICAgIGhhbmRsZUVycm9yKGV2ZW50LmVycm9yKTsKICAgIH0pOwogICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoInVuaGFuZGxlZHJlamVjdGlvbiIsIChldmVudCkgPT4gewogICAgICBoYW5kbGVFcnJvcihldmVudC5yZWFzb24pOwogICAgfSk7CiAgICBhd2FpdCBzdGFydFdhc2lUYXNrKCk7CiAgfSBjYXRjaCAoZSkgewogICAgaGFuZGxlRXJyb3IoZSk7CiAgICB0aHJvdyBlOwogIH0KfQptYWluKCk7Ci8qIQogKiBSZWNvbm5lY3RpbmcgV2ViU29ja2V0CiAqIGJ5IFBlZHJvIExhZGFyaWEgPHBlZHJvLmxhZGFyaWFAZ21haWwuY29tPgogKiBodHRwczovL2dpdGh1Yi5jb20vcGxhZGFyaWEvcmVjb25uZWN0aW5nLXdlYnNvY2tldAogKiBMaWNlbnNlIE1JVAogKi8KLyohICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCkNvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLgpMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlCnRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlCkxpY2Vuc2UgYXQgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCgpUSElTIENPREUgSVMgUFJPVklERUQgT04gQU4gKkFTIElTKiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZCktJTkQsIEVJVEhFUiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBXSVRIT1VUIExJTUlUQVRJT04gQU5ZIElNUExJRUQKV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIFRJVExFLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSwKTUVSQ0hBTlRBQkxJVFkgT1IgTk9OLUlORlJJTkdFTUVOVC4KClNlZSB0aGUgQXBhY2hlIFZlcnNpb24gMi4wIExpY2Vuc2UgZm9yIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucwphbmQgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuCioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovCg==")! + public static let bundle: Data = Data(base64Encoded: "Ly8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC93YXNpX2RlZnMuanMKdmFyIENMT0NLSURfUkVBTFRJTUUgPSAwOwp2YXIgQ0xPQ0tJRF9NT05PVE9OSUMgPSAxOwp2YXIgRVJSTk9fU1VDQ0VTUyA9IDA7CnZhciBFUlJOT19CQURGID0gODsKdmFyIEVSUk5PX0VYSVNUID0gMjA7CnZhciBFUlJOT19JTlZBTCA9IDI4Owp2YXIgRVJSTk9fSVNESVIgPSAzMTsKdmFyIEVSUk5PX05BTUVUT09MT05HID0gMzc7CnZhciBFUlJOT19OT0VOVCA9IDQ0Owp2YXIgRVJSTk9fTk9TWVMgPSA1MjsKdmFyIEVSUk5PX05PVERJUiA9IDU0Owp2YXIgRVJSTk9fTk9URU1QVFkgPSA1NTsKdmFyIEVSUk5PX05PVFNVUCA9IDU4Owp2YXIgRVJSTk9fUEVSTSA9IDYzOwp2YXIgRVJSTk9fTk9UQ0FQQUJMRSA9IDc2Owp2YXIgUklHSFRTX0ZEX0RBVEFTWU5DID0gMSA8PCAwOwp2YXIgUklHSFRTX0ZEX1JFQUQgPSAxIDw8IDE7CnZhciBSSUdIVFNfRkRfU0VFSyA9IDEgPDwgMjsKdmFyIFJJR0hUU19GRF9GRFNUQVRfU0VUX0ZMQUdTID0gMSA8PCAzOwp2YXIgUklHSFRTX0ZEX1NZTkMgPSAxIDw8IDQ7CnZhciBSSUdIVFNfRkRfVEVMTCA9IDEgPDwgNTsKdmFyIFJJR0hUU19GRF9XUklURSA9IDEgPDwgNjsKdmFyIFJJR0hUU19GRF9BRFZJU0UgPSAxIDw8IDc7CnZhciBSSUdIVFNfRkRfQUxMT0NBVEUgPSAxIDw8IDg7CnZhciBSSUdIVFNfUEFUSF9DUkVBVEVfRElSRUNUT1JZID0gMSA8PCA5Owp2YXIgUklHSFRTX1BBVEhfQ1JFQVRFX0ZJTEUgPSAxIDw8IDEwOwp2YXIgUklHSFRTX1BBVEhfTElOS19TT1VSQ0UgPSAxIDw8IDExOwp2YXIgUklHSFRTX1BBVEhfTElOS19UQVJHRVQgPSAxIDw8IDEyOwp2YXIgUklHSFRTX1BBVEhfT1BFTiA9IDEgPDwgMTM7CnZhciBSSUdIVFNfRkRfUkVBRERJUiA9IDEgPDwgMTQ7CnZhciBSSUdIVFNfUEFUSF9SRUFETElOSyA9IDEgPDwgMTU7CnZhciBSSUdIVFNfUEFUSF9SRU5BTUVfU09VUkNFID0gMSA8PCAxNjsKdmFyIFJJR0hUU19QQVRIX1JFTkFNRV9UQVJHRVQgPSAxIDw8IDE3Owp2YXIgUklHSFRTX1BBVEhfRklMRVNUQVRfR0VUID0gMSA8PCAxODsKdmFyIFJJR0hUU19QQVRIX0ZJTEVTVEFUX1NFVF9TSVpFID0gMSA8PCAxOTsKdmFyIFJJR0hUU19QQVRIX0ZJTEVTVEFUX1NFVF9USU1FUyA9IDEgPDwgMjA7CnZhciBSSUdIVFNfRkRfRklMRVNUQVRfR0VUID0gMSA8PCAyMTsKdmFyIFJJR0hUU19GRF9GSUxFU1RBVF9TRVRfU0laRSA9IDEgPDwgMjI7CnZhciBSSUdIVFNfRkRfRklMRVNUQVRfU0VUX1RJTUVTID0gMSA8PCAyMzsKdmFyIFJJR0hUU19QQVRIX1NZTUxJTksgPSAxIDw8IDI0Owp2YXIgUklHSFRTX1BBVEhfUkVNT1ZFX0RJUkVDVE9SWSA9IDEgPDwgMjU7CnZhciBSSUdIVFNfUEFUSF9VTkxJTktfRklMRSA9IDEgPDwgMjY7CnZhciBSSUdIVFNfUE9MTF9GRF9SRUFEV1JJVEUgPSAxIDw8IDI3Owp2YXIgUklHSFRTX1NPQ0tfU0hVVERPV04gPSAxIDw8IDI4Owp2YXIgSW92ZWMgPSBjbGFzcyB7CiAgc3RhdGljIHJlYWRfYnl0ZXModmlldywgcHRyKSB7CiAgICBjb25zdCBpb3ZlYyA9IG5ldyBJb3ZlYygpOwogICAgaW92ZWMuYnVmID0gdmlldy5nZXRVaW50MzIocHRyLCB0cnVlKTsKICAgIGlvdmVjLmJ1Zl9sZW4gPSB2aWV3LmdldFVpbnQzMihwdHIgKyA0LCB0cnVlKTsKICAgIHJldHVybiBpb3ZlYzsKICB9CiAgc3RhdGljIHJlYWRfYnl0ZXNfYXJyYXkodmlldywgcHRyLCBsZW4pIHsKICAgIGNvbnN0IGlvdmVjcyA9IFtdOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgICBpb3ZlY3MucHVzaChJb3ZlYy5yZWFkX2J5dGVzKHZpZXcsIHB0ciArIDggKiBpKSk7CiAgICB9CiAgICByZXR1cm4gaW92ZWNzOwogIH0KfTsKdmFyIENpb3ZlYyA9IGNsYXNzIHsKICBzdGF0aWMgcmVhZF9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIGNvbnN0IGlvdmVjID0gbmV3IENpb3ZlYygpOwogICAgaW92ZWMuYnVmID0gdmlldy5nZXRVaW50MzIocHRyLCB0cnVlKTsKICAgIGlvdmVjLmJ1Zl9sZW4gPSB2aWV3LmdldFVpbnQzMihwdHIgKyA0LCB0cnVlKTsKICAgIHJldHVybiBpb3ZlYzsKICB9CiAgc3RhdGljIHJlYWRfYnl0ZXNfYXJyYXkodmlldywgcHRyLCBsZW4pIHsKICAgIGNvbnN0IGlvdmVjcyA9IFtdOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgICBpb3ZlY3MucHVzaChDaW92ZWMucmVhZF9ieXRlcyh2aWV3LCBwdHIgKyA4ICogaSkpOwogICAgfQogICAgcmV0dXJuIGlvdmVjczsKICB9Cn07CnZhciBXSEVOQ0VfU0VUID0gMDsKdmFyIFdIRU5DRV9DVVIgPSAxOwp2YXIgV0hFTkNFX0VORCA9IDI7CnZhciBGSUxFVFlQRV9DSEFSQUNURVJfREVWSUNFID0gMjsKdmFyIEZJTEVUWVBFX0RJUkVDVE9SWSA9IDM7CnZhciBGSUxFVFlQRV9SRUdVTEFSX0ZJTEUgPSA0Owp2YXIgRGlyZW50ID0gY2xhc3MgewogIGhlYWRfbGVuZ3RoKCkgewogICAgcmV0dXJuIDI0OwogIH0KICBuYW1lX2xlbmd0aCgpIHsKICAgIHJldHVybiB0aGlzLmRpcl9uYW1lLmJ5dGVMZW5ndGg7CiAgfQogIHdyaXRlX2hlYWRfYnl0ZXModmlldywgcHRyKSB7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIsIHRoaXMuZF9uZXh0LCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDgsIHRoaXMuZF9pbm8sIHRydWUpOwogICAgdmlldy5zZXRVaW50MzIocHRyICsgMTYsIHRoaXMuZGlyX25hbWUubGVuZ3RoLCB0cnVlKTsKICAgIHZpZXcuc2V0VWludDgocHRyICsgMjAsIHRoaXMuZF90eXBlKTsKICB9CiAgd3JpdGVfbmFtZV9ieXRlcyh2aWV3OCwgcHRyLCBidWZfbGVuKSB7CiAgICB2aWV3OC5zZXQodGhpcy5kaXJfbmFtZS5zbGljZSgwLCBNYXRoLm1pbih0aGlzLmRpcl9uYW1lLmJ5dGVMZW5ndGgsIGJ1Zl9sZW4pKSwgcHRyKTsKICB9CiAgY29uc3RydWN0b3IobmV4dF9jb29raWUsIG5hbWUsIHR5cGUpIHsKICAgIHRoaXMuZF9pbm8gPSAwbjsKICAgIGNvbnN0IGVuY29kZWRfbmFtZSA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShuYW1lKTsKICAgIHRoaXMuZF9uZXh0ID0gbmV4dF9jb29raWU7CiAgICB0aGlzLmRfbmFtbGVuID0gZW5jb2RlZF9uYW1lLmJ5dGVMZW5ndGg7CiAgICB0aGlzLmRfdHlwZSA9IHR5cGU7CiAgICB0aGlzLmRpcl9uYW1lID0gZW5jb2RlZF9uYW1lOwogIH0KfTsKdmFyIEZERkxBR1NfQVBQRU5EID0gMSA8PCAwOwp2YXIgRkRGTEFHU19EU1lOQyA9IDEgPDwgMTsKdmFyIEZERkxBR1NfTk9OQkxPQ0sgPSAxIDw8IDI7CnZhciBGREZMQUdTX1JTWU5DID0gMSA8PCAzOwp2YXIgRkRGTEFHU19TWU5DID0gMSA8PCA0Owp2YXIgRmRzdGF0ID0gY2xhc3MgewogIHdyaXRlX2J5dGVzKHZpZXcsIHB0cikgewogICAgdmlldy5zZXRVaW50OChwdHIsIHRoaXMuZnNfZmlsZXR5cGUpOwogICAgdmlldy5zZXRVaW50MTYocHRyICsgMiwgdGhpcy5mc19mbGFncywgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA4LCB0aGlzLmZzX3JpZ2h0c19iYXNlLCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDE2LCB0aGlzLmZzX3JpZ2h0c19pbmhlcml0ZWQsIHRydWUpOwogIH0KICBjb25zdHJ1Y3RvcihmaWxldHlwZSwgZmxhZ3MpIHsKICAgIHRoaXMuZnNfcmlnaHRzX2Jhc2UgPSAwbjsKICAgIHRoaXMuZnNfcmlnaHRzX2luaGVyaXRlZCA9IDBuOwogICAgdGhpcy5mc19maWxldHlwZSA9IGZpbGV0eXBlOwogICAgdGhpcy5mc19mbGFncyA9IGZsYWdzOwogIH0KfTsKdmFyIEZTVEZMQUdTX0FUSU0gPSAxIDw8IDA7CnZhciBGU1RGTEFHU19BVElNX05PVyA9IDEgPDwgMTsKdmFyIEZTVEZMQUdTX01USU0gPSAxIDw8IDI7CnZhciBGU1RGTEFHU19NVElNX05PVyA9IDEgPDwgMzsKdmFyIE9GTEFHU19DUkVBVCA9IDEgPDwgMDsKdmFyIE9GTEFHU19ESVJFQ1RPUlkgPSAxIDw8IDE7CnZhciBPRkxBR1NfRVhDTCA9IDEgPDwgMjsKdmFyIE9GTEFHU19UUlVOQyA9IDEgPDwgMzsKdmFyIEZpbGVzdGF0ID0gY2xhc3MgewogIHdyaXRlX2J5dGVzKHZpZXcsIHB0cikgewogICAgdmlldy5zZXRCaWdVaW50NjQocHRyLCB0aGlzLmRldiwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA4LCB0aGlzLmlubywgdHJ1ZSk7CiAgICB2aWV3LnNldFVpbnQ4KHB0ciArIDE2LCB0aGlzLmZpbGV0eXBlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDI0LCB0aGlzLm5saW5rLCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDMyLCB0aGlzLnNpemUsIHRydWUpOwogICAgdmlldy5zZXRCaWdVaW50NjQocHRyICsgMzgsIHRoaXMuYXRpbSwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA0NiwgdGhpcy5tdGltLCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDUyLCB0aGlzLmN0aW0sIHRydWUpOwogIH0KICBjb25zdHJ1Y3RvcihmaWxldHlwZSwgc2l6ZSkgewogICAgdGhpcy5kZXYgPSAwbjsKICAgIHRoaXMuaW5vID0gMG47CiAgICB0aGlzLm5saW5rID0gMG47CiAgICB0aGlzLmF0aW0gPSAwbjsKICAgIHRoaXMubXRpbSA9IDBuOwogICAgdGhpcy5jdGltID0gMG47CiAgICB0aGlzLmZpbGV0eXBlID0gZmlsZXR5cGU7CiAgICB0aGlzLnNpemUgPSBzaXplOwogIH0KfTsKdmFyIEVWRU5UUldGTEFHU19GRF9SRUFEV1JJVEVfSEFOR1VQID0gMSA8PCAwOwp2YXIgU1VCQ0xPQ0tGTEFHU19TVUJTQ1JJUFRJT05fQ0xPQ0tfQUJTVElNRSA9IDEgPDwgMDsKdmFyIFJJRkxBR1NfUkVDVl9QRUVLID0gMSA8PCAwOwp2YXIgUklGTEFHU19SRUNWX1dBSVRBTEwgPSAxIDw8IDE7CnZhciBST0ZMQUdTX1JFQ1ZfREFUQV9UUlVOQ0FURUQgPSAxIDw8IDA7CnZhciBTREZMQUdTX1JEID0gMSA8PCAwOwp2YXIgU0RGTEFHU19XUiA9IDEgPDwgMTsKdmFyIFBSRU9QRU5UWVBFX0RJUiA9IDA7CnZhciBQcmVzdGF0RGlyID0gY2xhc3MgewogIHdyaXRlX2J5dGVzKHZpZXcsIHB0cikgewogICAgdmlldy5zZXRVaW50MzIocHRyLCB0aGlzLnByX25hbWUuYnl0ZUxlbmd0aCwgdHJ1ZSk7CiAgfQogIGNvbnN0cnVjdG9yKG5hbWUpIHsKICAgIHRoaXMucHJfbmFtZSA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShuYW1lKTsKICB9Cn07CnZhciBQcmVzdGF0ID0gY2xhc3MgewogIHN0YXRpYyBkaXIobmFtZSkgewogICAgY29uc3QgcHJlc3RhdCA9IG5ldyBQcmVzdGF0KCk7CiAgICBwcmVzdGF0LnRhZyA9IFBSRU9QRU5UWVBFX0RJUjsKICAgIHByZXN0YXQuaW5uZXIgPSBuZXcgUHJlc3RhdERpcihuYW1lKTsKICAgIHJldHVybiBwcmVzdGF0OwogIH0KICB3cml0ZV9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIHZpZXcuc2V0VWludDMyKHB0ciwgdGhpcy50YWcsIHRydWUpOwogICAgdGhpcy5pbm5lci53cml0ZV9ieXRlcyh2aWV3LCBwdHIgKyA0KTsKICB9Cn07CgovLyBub2RlX21vZHVsZXMvQGJqb3JuMy9icm93c2VyX3dhc2lfc2hpbS9kaXN0L2RlYnVnLmpzCnZhciBEZWJ1ZyA9IGNsYXNzIERlYnVnMiB7CiAgZW5hYmxlKGVuYWJsZWQpIHsKICAgIHRoaXMubG9nID0gY3JlYXRlTG9nZ2VyKGVuYWJsZWQgPT09IHZvaWQgMCA/IHRydWUgOiBlbmFibGVkLCB0aGlzLnByZWZpeCk7CiAgfQogIGdldCBlbmFibGVkKCkgewogICAgcmV0dXJuIHRoaXMuaXNFbmFibGVkOwogIH0KICBjb25zdHJ1Y3Rvcihpc0VuYWJsZWQpIHsKICAgIHRoaXMuaXNFbmFibGVkID0gaXNFbmFibGVkOwogICAgdGhpcy5wcmVmaXggPSAid2FzaToiOwogICAgdGhpcy5lbmFibGUoaXNFbmFibGVkKTsKICB9Cn07CmZ1bmN0aW9uIGNyZWF0ZUxvZ2dlcihlbmFibGVkLCBwcmVmaXgpIHsKICBpZiAoZW5hYmxlZCkgewogICAgY29uc3QgYSA9IGNvbnNvbGUubG9nLmJpbmQoY29uc29sZSwgIiVjJXMiLCAiY29sb3I6ICMyNjVCQTAiLCBwcmVmaXgpOwogICAgcmV0dXJuIGE7CiAgfSBlbHNlIHsKICAgIHJldHVybiAoKSA9PiB7CiAgICB9OwogIH0KfQp2YXIgZGVidWcgPSBuZXcgRGVidWcoZmFsc2UpOwoKLy8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC93YXNpLmpzCnZhciBXQVNJUHJvY0V4aXQgPSBjbGFzcyBleHRlbmRzIEVycm9yIHsKICBjb25zdHJ1Y3Rvcihjb2RlKSB7CiAgICBzdXBlcigiZXhpdCB3aXRoIGV4aXQgY29kZSAiICsgY29kZSk7CiAgICB0aGlzLmNvZGUgPSBjb2RlOwogIH0KfTsKdmFyIFdBU0kgPSBjbGFzcyBXQVNJMiB7CiAgc3RhcnQoaW5zdGFuY2UpIHsKICAgIHRoaXMuaW5zdCA9IGluc3RhbmNlOwogICAgdHJ5IHsKICAgICAgaW5zdGFuY2UuZXhwb3J0cy5fc3RhcnQoKTsKICAgICAgcmV0dXJuIDA7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIGlmIChlIGluc3RhbmNlb2YgV0FTSVByb2NFeGl0KSB7CiAgICAgICAgcmV0dXJuIGUuY29kZTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aHJvdyBlOwogICAgICB9CiAgICB9CiAgfQogIGluaXRpYWxpemUoaW5zdGFuY2UpIHsKICAgIHRoaXMuaW5zdCA9IGluc3RhbmNlOwogICAgaWYgKGluc3RhbmNlLmV4cG9ydHMuX2luaXRpYWxpemUpIHsKICAgICAgaW5zdGFuY2UuZXhwb3J0cy5faW5pdGlhbGl6ZSgpOwogICAgfQogIH0KICBjb25zdHJ1Y3RvcihhcmdzLCBlbnYsIGZkcywgb3B0aW9ucyA9IHt9KSB7CiAgICB0aGlzLmFyZ3MgPSBbXTsKICAgIHRoaXMuZW52ID0gW107CiAgICB0aGlzLmZkcyA9IFtdOwogICAgZGVidWcuZW5hYmxlKG9wdGlvbnMuZGVidWcpOwogICAgdGhpcy5hcmdzID0gYXJnczsKICAgIHRoaXMuZW52ID0gZW52OwogICAgdGhpcy5mZHMgPSBmZHM7CiAgICBjb25zdCBzZWxmID0gdGhpczsKICAgIHRoaXMud2FzaUltcG9ydCA9IHsgYXJnc19zaXplc19nZXQoYXJnYywgYXJndl9idWZfc2l6ZSkgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYXJnYywgc2VsZi5hcmdzLmxlbmd0aCwgdHJ1ZSk7CiAgICAgIGxldCBidWZfc2l6ZSA9IDA7CiAgICAgIGZvciAoY29uc3QgYXJnIG9mIHNlbGYuYXJncykgewogICAgICAgIGJ1Zl9zaXplICs9IGFyZy5sZW5ndGggKyAxOwogICAgICB9CiAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYXJndl9idWZfc2l6ZSwgYnVmX3NpemUsIHRydWUpOwogICAgICBkZWJ1Zy5sb2coYnVmZmVyLmdldFVpbnQzMihhcmdjLCB0cnVlKSwgYnVmZmVyLmdldFVpbnQzMihhcmd2X2J1Zl9zaXplLCB0cnVlKSk7CiAgICAgIHJldHVybiAwOwogICAgfSwgYXJnc19nZXQoYXJndiwgYXJndl9idWYpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IG9yaWdfYXJndl9idWYgPSBhcmd2X2J1ZjsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxmLmFyZ3MubGVuZ3RoOyBpKyspIHsKICAgICAgICBidWZmZXIuc2V0VWludDMyKGFyZ3YsIGFyZ3ZfYnVmLCB0cnVlKTsKICAgICAgICBhcmd2ICs9IDQ7CiAgICAgICAgY29uc3QgYXJnID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHNlbGYuYXJnc1tpXSk7CiAgICAgICAgYnVmZmVyOC5zZXQoYXJnLCBhcmd2X2J1Zik7CiAgICAgICAgYnVmZmVyLnNldFVpbnQ4KGFyZ3ZfYnVmICsgYXJnLmxlbmd0aCwgMCk7CiAgICAgICAgYXJndl9idWYgKz0gYXJnLmxlbmd0aCArIDE7CiAgICAgIH0KICAgICAgaWYgKGRlYnVnLmVuYWJsZWQpIHsKICAgICAgICBkZWJ1Zy5sb2cobmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG9yaWdfYXJndl9idWYsIGFyZ3ZfYnVmKSkpOwogICAgICB9CiAgICAgIHJldHVybiAwOwogICAgfSwgZW52aXJvbl9zaXplc19nZXQoZW52aXJvbl9jb3VudCwgZW52aXJvbl9zaXplKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgYnVmZmVyLnNldFVpbnQzMihlbnZpcm9uX2NvdW50LCBzZWxmLmVudi5sZW5ndGgsIHRydWUpOwogICAgICBsZXQgYnVmX3NpemUgPSAwOwogICAgICBmb3IgKGNvbnN0IGVudmlyb24gb2Ygc2VsZi5lbnYpIHsKICAgICAgICBidWZfc2l6ZSArPSBlbnZpcm9uLmxlbmd0aCArIDE7CiAgICAgIH0KICAgICAgYnVmZmVyLnNldFVpbnQzMihlbnZpcm9uX3NpemUsIGJ1Zl9zaXplLCB0cnVlKTsKICAgICAgZGVidWcubG9nKGJ1ZmZlci5nZXRVaW50MzIoZW52aXJvbl9jb3VudCwgdHJ1ZSksIGJ1ZmZlci5nZXRVaW50MzIoZW52aXJvbl9zaXplLCB0cnVlKSk7CiAgICAgIHJldHVybiAwOwogICAgfSwgZW52aXJvbl9nZXQoZW52aXJvbiwgZW52aXJvbl9idWYpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IG9yaWdfZW52aXJvbl9idWYgPSBlbnZpcm9uX2J1ZjsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxmLmVudi5sZW5ndGg7IGkrKykgewogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIoZW52aXJvbiwgZW52aXJvbl9idWYsIHRydWUpOwogICAgICAgIGVudmlyb24gKz0gNDsKICAgICAgICBjb25zdCBlID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHNlbGYuZW52W2ldKTsKICAgICAgICBidWZmZXI4LnNldChlLCBlbnZpcm9uX2J1Zik7CiAgICAgICAgYnVmZmVyLnNldFVpbnQ4KGVudmlyb25fYnVmICsgZS5sZW5ndGgsIDApOwogICAgICAgIGVudmlyb25fYnVmICs9IGUubGVuZ3RoICsgMTsKICAgICAgfQogICAgICBpZiAoZGVidWcuZW5hYmxlZCkgewogICAgICAgIGRlYnVnLmxvZyhuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2Uob3JpZ19lbnZpcm9uX2J1ZiwgZW52aXJvbl9idWYpKSk7CiAgICAgIH0KICAgICAgcmV0dXJuIDA7CiAgICB9LCBjbG9ja19yZXNfZ2V0KGlkLCByZXNfcHRyKSB7CiAgICAgIGxldCByZXNvbHV0aW9uVmFsdWU7CiAgICAgIHN3aXRjaCAoaWQpIHsKICAgICAgICBjYXNlIENMT0NLSURfTU9OT1RPTklDOiB7CiAgICAgICAgICByZXNvbHV0aW9uVmFsdWUgPSA1MDAwbjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjYXNlIENMT0NLSURfUkVBTFRJTUU6IHsKICAgICAgICAgIHJlc29sdXRpb25WYWx1ZSA9IDEwMDAwMDBuOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICByZXR1cm4gRVJSTk9fTk9TWVM7CiAgICAgIH0KICAgICAgY29uc3QgdmlldyA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgdmlldy5zZXRCaWdVaW50NjQocmVzX3B0ciwgcmVzb2x1dGlvblZhbHVlLCB0cnVlKTsKICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICB9LCBjbG9ja190aW1lX2dldChpZCwgcHJlY2lzaW9uLCB0aW1lKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKGlkID09PSBDTE9DS0lEX1JFQUxUSU1FKSB7CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NCh0aW1lLCBCaWdJbnQobmV3IERhdGUoKS5nZXRUaW1lKCkpICogMTAwMDAwMG4sIHRydWUpOwogICAgICB9IGVsc2UgaWYgKGlkID09IENMT0NLSURfTU9OT1RPTklDKSB7CiAgICAgICAgbGV0IG1vbm90b25pY190aW1lOwogICAgICAgIHRyeSB7CiAgICAgICAgICBtb25vdG9uaWNfdGltZSA9IEJpZ0ludChNYXRoLnJvdW5kKHBlcmZvcm1hbmNlLm5vdygpICogMWU2KSk7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgbW9ub3RvbmljX3RpbWUgPSAwbjsKICAgICAgICB9CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NCh0aW1lLCBtb25vdG9uaWNfdGltZSwgdHJ1ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NCh0aW1lLCAwbiwgdHJ1ZSk7CiAgICAgIH0KICAgICAgcmV0dXJuIDA7CiAgICB9LCBmZF9hZHZpc2UoZmQsIG9mZnNldCwgbGVuLCBhZHZpY2UpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfYWxsb2NhdGUoZmQsIG9mZnNldCwgbGVuKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9hbGxvY2F0ZShvZmZzZXQsIGxlbik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Nsb3NlKGZkKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcmV0ID0gc2VsZi5mZHNbZmRdLmZkX2Nsb3NlKCk7CiAgICAgICAgc2VsZi5mZHNbZmRdID0gdm9pZCAwOwogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2RhdGFzeW5jKGZkKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9zeW5jKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Zkc3RhdF9nZXQoZmQsIGZkc3RhdF9wdHIpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgZmRzdGF0IH0gPSBzZWxmLmZkc1tmZF0uZmRfZmRzdGF0X2dldCgpOwogICAgICAgIGlmIChmZHN0YXQgIT0gbnVsbCkgewogICAgICAgICAgZmRzdGF0LndyaXRlX2J5dGVzKG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKSwgZmRzdGF0X3B0cik7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Zkc3RhdF9zZXRfZmxhZ3MoZmQsIGZsYWdzKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9mZHN0YXRfc2V0X2ZsYWdzKGZsYWdzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfZmRzdGF0X3NldF9yaWdodHMoZmQsIGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZykgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfZmRzdGF0X3NldF9yaWdodHMoZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfZmlsZXN0YXRfZ2V0KGZkLCBmaWxlc3RhdF9wdHIpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgZmlsZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9maWxlc3RhdF9nZXQoKTsKICAgICAgICBpZiAoZmlsZXN0YXQgIT0gbnVsbCkgewogICAgICAgICAgZmlsZXN0YXQud3JpdGVfYnl0ZXMobmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpLCBmaWxlc3RhdF9wdHIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9maWxlc3RhdF9zZXRfc2l6ZShmZCwgc2l6ZSkgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfZmlsZXN0YXRfc2V0X3NpemUoc2l6ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2ZpbGVzdGF0X3NldF90aW1lcyhmZCwgYXRpbSwgbXRpbSwgZnN0X2ZsYWdzKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9maWxlc3RhdF9zZXRfdGltZXMoYXRpbSwgbXRpbSwgZnN0X2ZsYWdzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcHJlYWQoZmQsIGlvdnNfcHRyLCBpb3ZzX2xlbiwgb2Zmc2V0LCBucmVhZF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgaW92ZWNzID0gSW92ZWMucmVhZF9ieXRlc19hcnJheShidWZmZXIsIGlvdnNfcHRyLCBpb3ZzX2xlbik7CiAgICAgICAgbGV0IG5yZWFkID0gMDsKICAgICAgICBmb3IgKGNvbnN0IGlvdmVjIG9mIGlvdmVjcykgewogICAgICAgICAgY29uc3QgeyByZXQsIGRhdGEgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wcmVhZChpb3ZlYy5idWZfbGVuLCBvZmZzZXQpOwogICAgICAgICAgaWYgKHJldCAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobnJlYWRfcHRyLCBucmVhZCwgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgICB9CiAgICAgICAgICBidWZmZXI4LnNldChkYXRhLCBpb3ZlYy5idWYpOwogICAgICAgICAgbnJlYWQgKz0gZGF0YS5sZW5ndGg7CiAgICAgICAgICBvZmZzZXQgKz0gQmlnSW50KGRhdGEubGVuZ3RoKTsKICAgICAgICAgIGlmIChkYXRhLmxlbmd0aCAhPSBpb3ZlYy5idWZfbGVuKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgbnJlYWQsIHRydWUpOwogICAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9wcmVzdGF0X2dldChmZCwgYnVmX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIHByZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wcmVzdGF0X2dldCgpOwogICAgICAgIGlmIChwcmVzdGF0ICE9IG51bGwpIHsKICAgICAgICAgIHByZXN0YXQud3JpdGVfYnl0ZXMoYnVmZmVyLCBidWZfcHRyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcHJlc3RhdF9kaXJfbmFtZShmZCwgcGF0aF9wdHIsIHBhdGhfbGVuKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIHByZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wcmVzdGF0X2dldCgpOwogICAgICAgIGlmIChwcmVzdGF0ID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHByZXN0YXRfZGlyX25hbWUgPSBwcmVzdGF0LmlubmVyLnByX25hbWU7CiAgICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICAgIGJ1ZmZlcjguc2V0KHByZXN0YXRfZGlyX25hbWUuc2xpY2UoMCwgcGF0aF9sZW4pLCBwYXRoX3B0cik7CiAgICAgICAgcmV0dXJuIHByZXN0YXRfZGlyX25hbWUuYnl0ZUxlbmd0aCA+IHBhdGhfbGVuID8gRVJSTk9fTkFNRVRPT0xPTkcgOiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9wd3JpdGUoZmQsIGlvdnNfcHRyLCBpb3ZzX2xlbiwgb2Zmc2V0LCBud3JpdHRlbl9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgaW92ZWNzID0gQ2lvdmVjLnJlYWRfYnl0ZXNfYXJyYXkoYnVmZmVyLCBpb3ZzX3B0ciwgaW92c19sZW4pOwogICAgICAgIGxldCBud3JpdHRlbiA9IDA7CiAgICAgICAgZm9yIChjb25zdCBpb3ZlYyBvZiBpb3ZlY3MpIHsKICAgICAgICAgIGNvbnN0IGRhdGEgPSBidWZmZXI4LnNsaWNlKGlvdmVjLmJ1ZiwgaW92ZWMuYnVmICsgaW92ZWMuYnVmX2xlbik7CiAgICAgICAgICBjb25zdCB7IHJldCwgbndyaXR0ZW46IG53cml0dGVuX3BhcnQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG53cml0dGVuX3B0ciwgbndyaXR0ZW4sIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgbndyaXR0ZW4gKz0gbndyaXR0ZW5fcGFydDsKICAgICAgICAgIG9mZnNldCArPSBCaWdJbnQobndyaXR0ZW5fcGFydCk7CiAgICAgICAgICBpZiAobndyaXR0ZW5fcGFydCAhPSBkYXRhLmJ5dGVMZW5ndGgpIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobndyaXR0ZW5fcHRyLCBud3JpdHRlbiwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3JlYWQoZmQsIGlvdnNfcHRyLCBpb3ZzX2xlbiwgbnJlYWRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IGlvdmVjcyA9IElvdmVjLnJlYWRfYnl0ZXNfYXJyYXkoYnVmZmVyLCBpb3ZzX3B0ciwgaW92c19sZW4pOwogICAgICAgIGxldCBucmVhZCA9IDA7CiAgICAgICAgZm9yIChjb25zdCBpb3ZlYyBvZiBpb3ZlY3MpIHsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBkYXRhIH0gPSBzZWxmLmZkc1tmZF0uZmRfcmVhZChpb3ZlYy5idWZfbGVuKTsKICAgICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgbnJlYWQsIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgYnVmZmVyOC5zZXQoZGF0YSwgaW92ZWMuYnVmKTsKICAgICAgICAgIG5yZWFkICs9IGRhdGEubGVuZ3RoOwogICAgICAgICAgaWYgKGRhdGEubGVuZ3RoICE9IGlvdmVjLmJ1Zl9sZW4pIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobnJlYWRfcHRyLCBucmVhZCwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3JlYWRkaXIoZmQsIGJ1ZiwgYnVmX2xlbiwgY29va2llLCBidWZ1c2VkX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBsZXQgYnVmdXNlZCA9IDA7CiAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBkaXJlbnQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9yZWFkZGlyX3NpbmdsZShjb29raWUpOwogICAgICAgICAgaWYgKHJldCAhPSAwKSB7CiAgICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYnVmdXNlZF9wdHIsIGJ1ZnVzZWQsIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgaWYgKGRpcmVudCA9PSBudWxsKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGJ1Zl9sZW4gLSBidWZ1c2VkIDwgZGlyZW50LmhlYWRfbGVuZ3RoKCkpIHsKICAgICAgICAgICAgYnVmdXNlZCA9IGJ1Zl9sZW47CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgaGVhZF9ieXRlcyA9IG5ldyBBcnJheUJ1ZmZlcihkaXJlbnQuaGVhZF9sZW5ndGgoKSk7CiAgICAgICAgICBkaXJlbnQud3JpdGVfaGVhZF9ieXRlcyhuZXcgRGF0YVZpZXcoaGVhZF9ieXRlcyksIDApOwogICAgICAgICAgYnVmZmVyOC5zZXQobmV3IFVpbnQ4QXJyYXkoaGVhZF9ieXRlcykuc2xpY2UoMCwgTWF0aC5taW4oaGVhZF9ieXRlcy5ieXRlTGVuZ3RoLCBidWZfbGVuIC0gYnVmdXNlZCkpLCBidWYpOwogICAgICAgICAgYnVmICs9IGRpcmVudC5oZWFkX2xlbmd0aCgpOwogICAgICAgICAgYnVmdXNlZCArPSBkaXJlbnQuaGVhZF9sZW5ndGgoKTsKICAgICAgICAgIGlmIChidWZfbGVuIC0gYnVmdXNlZCA8IGRpcmVudC5uYW1lX2xlbmd0aCgpKSB7CiAgICAgICAgICAgIGJ1ZnVzZWQgPSBidWZfbGVuOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGRpcmVudC53cml0ZV9uYW1lX2J5dGVzKGJ1ZmZlcjgsIGJ1ZiwgYnVmX2xlbiAtIGJ1ZnVzZWQpOwogICAgICAgICAgYnVmICs9IGRpcmVudC5uYW1lX2xlbmd0aCgpOwogICAgICAgICAgYnVmdXNlZCArPSBkaXJlbnQubmFtZV9sZW5ndGgoKTsKICAgICAgICAgIGNvb2tpZSA9IGRpcmVudC5kX25leHQ7CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYnVmdXNlZF9wdHIsIGJ1ZnVzZWQsIHRydWUpOwogICAgICAgIHJldHVybiAwOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9yZW51bWJlcihmZCwgdG8pIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDAgJiYgc2VsZi5mZHNbdG9dICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHJldCA9IHNlbGYuZmRzW3RvXS5mZF9jbG9zZSgpOwogICAgICAgIGlmIChyZXQgIT0gMCkgewogICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICB9CiAgICAgICAgc2VsZi5mZHNbdG9dID0gc2VsZi5mZHNbZmRdOwogICAgICAgIHNlbGYuZmRzW2ZkXSA9IHZvaWQgMDsKICAgICAgICByZXR1cm4gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfc2VlayhmZCwgb2Zmc2V0LCB3aGVuY2UsIG9mZnNldF9vdXRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgb2Zmc2V0OiBvZmZzZXRfb3V0IH0gPSBzZWxmLmZkc1tmZF0uZmRfc2VlayhvZmZzZXQsIHdoZW5jZSk7CiAgICAgICAgYnVmZmVyLnNldEJpZ0ludDY0KG9mZnNldF9vdXRfcHRyLCBvZmZzZXRfb3V0LCB0cnVlKTsKICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9zeW5jKGZkKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9zeW5jKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3RlbGwoZmQsIG9mZnNldF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHsgcmV0LCBvZmZzZXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF90ZWxsKCk7CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NChvZmZzZXRfcHRyLCBvZmZzZXQsIHRydWUpOwogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3dyaXRlKGZkLCBpb3ZzX3B0ciwgaW92c19sZW4sIG53cml0dGVuX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBpb3ZlY3MgPSBDaW92ZWMucmVhZF9ieXRlc19hcnJheShidWZmZXIsIGlvdnNfcHRyLCBpb3ZzX2xlbik7CiAgICAgICAgbGV0IG53cml0dGVuID0gMDsKICAgICAgICBmb3IgKGNvbnN0IGlvdmVjIG9mIGlvdmVjcykgewogICAgICAgICAgY29uc3QgZGF0YSA9IGJ1ZmZlcjguc2xpY2UoaW92ZWMuYnVmLCBpb3ZlYy5idWYgKyBpb3ZlYy5idWZfbGVuKTsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBud3JpdHRlbjogbndyaXR0ZW5fcGFydCB9ID0gc2VsZi5mZHNbZmRdLmZkX3dyaXRlKGRhdGEpOwogICAgICAgICAgaWYgKHJldCAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobndyaXR0ZW5fcHRyLCBud3JpdHRlbiwgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgICB9CiAgICAgICAgICBud3JpdHRlbiArPSBud3JpdHRlbl9wYXJ0OwogICAgICAgICAgaWYgKG53cml0dGVuX3BhcnQgIT0gZGF0YS5ieXRlTGVuZ3RoKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKG53cml0dGVuX3B0ciwgbndyaXR0ZW4sIHRydWUpOwogICAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX2NyZWF0ZV9kaXJlY3RvcnkoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0ucGF0aF9jcmVhdGVfZGlyZWN0b3J5KHBhdGgpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX2ZpbGVzdGF0X2dldChmZCwgZmxhZ3MsIHBhdGhfcHRyLCBwYXRoX2xlbiwgZmlsZXN0YXRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICBjb25zdCB7IHJldCwgZmlsZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5wYXRoX2ZpbGVzdGF0X2dldChmbGFncywgcGF0aCk7CiAgICAgICAgaWYgKGZpbGVzdGF0ICE9IG51bGwpIHsKICAgICAgICAgIGZpbGVzdGF0LndyaXRlX2J5dGVzKGJ1ZmZlciwgZmlsZXN0YXRfcHRyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9maWxlc3RhdF9zZXRfdGltZXMoZmQsIGZsYWdzLCBwYXRoX3B0ciwgcGF0aF9sZW4sIGF0aW0sIG10aW0sIGZzdF9mbGFncykgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0ucGF0aF9maWxlc3RhdF9zZXRfdGltZXMoZmxhZ3MsIHBhdGgsIGF0aW0sIG10aW0sIGZzdF9mbGFncyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfbGluayhvbGRfZmQsIG9sZF9mbGFncywgb2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9sZW4sIG5ld19mZCwgbmV3X3BhdGhfcHRyLCBuZXdfcGF0aF9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbb2xkX2ZkXSAhPSB2b2lkIDAgJiYgc2VsZi5mZHNbbmV3X2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBvbGRfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX3B0ciArIG9sZF9wYXRoX2xlbikpOwogICAgICAgIGNvbnN0IG5ld19wYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfcHRyICsgbmV3X3BhdGhfbGVuKSk7CiAgICAgICAgY29uc3QgeyByZXQsIGlub2RlX29iaiB9ID0gc2VsZi5mZHNbb2xkX2ZkXS5wYXRoX2xvb2t1cChvbGRfcGF0aCwgb2xkX2ZsYWdzKTsKICAgICAgICBpZiAoaW5vZGVfb2JqID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzZWxmLmZkc1tuZXdfZmRdLnBhdGhfbGluayhuZXdfcGF0aCwgaW5vZGVfb2JqLCBmYWxzZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfb3BlbihmZCwgZGlyZmxhZ3MsIHBhdGhfcHRyLCBwYXRoX2xlbiwgb2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcsIGZkX2ZsYWdzLCBvcGVuZWRfZmRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICBkZWJ1Zy5sb2cocGF0aCk7CiAgICAgICAgY29uc3QgeyByZXQsIGZkX29iaiB9ID0gc2VsZi5mZHNbZmRdLnBhdGhfb3BlbihkaXJmbGFncywgcGF0aCwgb2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcsIGZkX2ZsYWdzKTsKICAgICAgICBpZiAocmV0ICE9IDApIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIHNlbGYuZmRzLnB1c2goZmRfb2JqKTsKICAgICAgICBjb25zdCBvcGVuZWRfZmQgPSBzZWxmLmZkcy5sZW5ndGggLSAxOwogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIob3BlbmVkX2ZkX3B0ciwgb3BlbmVkX2ZkLCB0cnVlKTsKICAgICAgICByZXR1cm4gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9yZWFkbGluayhmZCwgcGF0aF9wdHIsIHBhdGhfbGVuLCBidWZfcHRyLCBidWZfbGVuLCBucmVhZF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIGRlYnVnLmxvZyhwYXRoKTsKICAgICAgICBjb25zdCB7IHJldCwgZGF0YSB9ID0gc2VsZi5mZHNbZmRdLnBhdGhfcmVhZGxpbmsocGF0aCk7CiAgICAgICAgaWYgKGRhdGEgIT0gbnVsbCkgewogICAgICAgICAgY29uc3QgZGF0YV9idWYgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoZGF0YSk7CiAgICAgICAgICBpZiAoZGF0YV9idWYubGVuZ3RoID4gYnVmX2xlbikgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgMCwgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICAgICAgfQogICAgICAgICAgYnVmZmVyOC5zZXQoZGF0YV9idWYsIGJ1Zl9wdHIpOwogICAgICAgICAgYnVmZmVyLnNldFVpbnQzMihucmVhZF9wdHIsIGRhdGFfYnVmLmxlbmd0aCwgdHJ1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfcmVtb3ZlX2RpcmVjdG9yeShmZCwgcGF0aF9wdHIsIHBhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBwYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5wYXRoX3JlbW92ZV9kaXJlY3RvcnkocGF0aCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfcmVuYW1lKGZkLCBvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX2xlbiwgbmV3X2ZkLCBuZXdfcGF0aF9wdHIsIG5ld19wYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwICYmIHNlbGYuZmRzW25ld19mZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3Qgb2xkX3BhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2Uob2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9wdHIgKyBvbGRfcGF0aF9sZW4pKTsKICAgICAgICBjb25zdCBuZXdfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShuZXdfcGF0aF9wdHIsIG5ld19wYXRoX3B0ciArIG5ld19wYXRoX2xlbikpOwogICAgICAgIGxldCB7IHJldCwgaW5vZGVfb2JqIH0gPSBzZWxmLmZkc1tmZF0ucGF0aF91bmxpbmsob2xkX3BhdGgpOwogICAgICAgIGlmIChpbm9kZV9vYmogPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICB9CiAgICAgICAgcmV0ID0gc2VsZi5mZHNbbmV3X2ZkXS5wYXRoX2xpbmsobmV3X3BhdGgsIGlub2RlX29iaiwgdHJ1ZSk7CiAgICAgICAgaWYgKHJldCAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICBpZiAoc2VsZi5mZHNbZmRdLnBhdGhfbGluayhvbGRfcGF0aCwgaW5vZGVfb2JqLCB0cnVlKSAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICAgIHRocm93ICJwYXRoX2xpbmsgc2hvdWxkIGFsd2F5cyByZXR1cm4gc3VjY2VzcyB3aGVuIHJlbGlua2luZyBhbiBpbm9kZSBiYWNrIHRvIHRoZSBvcmlnaW5hbCBwbGFjZSI7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfc3ltbGluayhvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX2xlbiwgZmQsIG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBvbGRfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX3B0ciArIG9sZF9wYXRoX2xlbikpOwogICAgICAgIGNvbnN0IG5ld19wYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfcHRyICsgbmV3X3BhdGhfbGVuKSk7CiAgICAgICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF91bmxpbmtfZmlsZShmZCwgcGF0aF9wdHIsIHBhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBwYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5wYXRoX3VubGlua19maWxlKHBhdGgpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwb2xsX29uZW9mZihpbl8sIG91dCwgbnN1YnNjcmlwdGlvbnMpIHsKICAgICAgdGhyb3cgImFzeW5jIGlvIG5vdCBzdXBwb3J0ZWQiOwogICAgfSwgcHJvY19leGl0KGV4aXRfY29kZSkgewogICAgICB0aHJvdyBuZXcgV0FTSVByb2NFeGl0KGV4aXRfY29kZSk7CiAgICB9LCBwcm9jX3JhaXNlKHNpZykgewogICAgICB0aHJvdyAicmFpc2VkIHNpZ25hbCAiICsgc2lnOwogICAgfSwgc2NoZWRfeWllbGQoKSB7CiAgICB9LCByYW5kb21fZ2V0KGJ1ZiwgYnVmX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnVmX2xlbjsgaSsrKSB7CiAgICAgICAgYnVmZmVyOFtidWYgKyBpXSA9IE1hdGgucmFuZG9tKCkgKiAyNTYgfCAwOwogICAgICB9CiAgICB9LCBzb2NrX3JlY3YoZmQsIHJpX2RhdGEsIHJpX2ZsYWdzKSB7CiAgICAgIHRocm93ICJzb2NrZXRzIG5vdCBzdXBwb3J0ZWQiOwogICAgfSwgc29ja19zZW5kKGZkLCBzaV9kYXRhLCBzaV9mbGFncykgewogICAgICB0aHJvdyAic29ja2V0cyBub3Qgc3VwcG9ydGVkIjsKICAgIH0sIHNvY2tfc2h1dGRvd24oZmQsIGhvdykgewogICAgICB0aHJvdyAic29ja2V0cyBub3Qgc3VwcG9ydGVkIjsKICAgIH0sIHNvY2tfYWNjZXB0KGZkLCBmbGFncykgewogICAgICB0aHJvdyAic29ja2V0cyBub3Qgc3VwcG9ydGVkIjsKICAgIH0gfTsKICB9Cn07CgovLyBub2RlX21vZHVsZXMvQGJqb3JuMy9icm93c2VyX3dhc2lfc2hpbS9kaXN0L2ZkLmpzCnZhciBGZCA9IGNsYXNzIHsKICBmZF9hbGxvY2F0ZShvZmZzZXQsIGxlbikgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfY2xvc2UoKSB7CiAgICByZXR1cm4gMDsKICB9CiAgZmRfZmRzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBmZHN0YXQ6IG51bGwgfTsKICB9CiAgZmRfZmRzdGF0X3NldF9mbGFncyhmbGFncykgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfZmRzdGF0X3NldF9yaWdodHMoZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nKSB7CiAgICByZXR1cm4gRVJSTk9fTk9UU1VQOwogIH0KICBmZF9maWxlc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZmlsZXN0YXQ6IG51bGwgfTsKICB9CiAgZmRfZmlsZXN0YXRfc2V0X3NpemUoc2l6ZSkgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfZmlsZXN0YXRfc2V0X3RpbWVzKGF0aW0sIG10aW0sIGZzdF9mbGFncykgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfcHJlYWQoc2l6ZSwgb2Zmc2V0KSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZGF0YTogbmV3IFVpbnQ4QXJyYXkoKSB9OwogIH0KICBmZF9wcmVzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBwcmVzdGF0OiBudWxsIH07CiAgfQogIGZkX3B3cml0ZShkYXRhLCBvZmZzZXQpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBud3JpdHRlbjogMCB9OwogIH0KICBmZF9yZWFkKHNpemUpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBkYXRhOiBuZXcgVWludDhBcnJheSgpIH07CiAgfQogIGZkX3JlYWRkaXJfc2luZ2xlKGNvb2tpZSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGRpcmVudDogbnVsbCB9OwogIH0KICBmZF9zZWVrKG9mZnNldCwgd2hlbmNlKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgb2Zmc2V0OiAwbiB9OwogIH0KICBmZF9zeW5jKCkgewogICAgcmV0dXJuIDA7CiAgfQogIGZkX3RlbGwoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgb2Zmc2V0OiAwbiB9OwogIH0KICBmZF93cml0ZShkYXRhKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgbndyaXR0ZW46IDAgfTsKICB9CiAgcGF0aF9jcmVhdGVfZGlyZWN0b3J5KHBhdGgpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfZmlsZXN0YXRfZ2V0KGZsYWdzLCBwYXRoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZmlsZXN0YXQ6IG51bGwgfTsKICB9CiAgcGF0aF9maWxlc3RhdF9zZXRfdGltZXMoZmxhZ3MsIHBhdGgsIGF0aW0sIG10aW0sIGZzdF9mbGFncykgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgcGF0aF9saW5rKHBhdGgsIGlub2RlLCBhbGxvd19kaXIpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfdW5saW5rKHBhdGgpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBpbm9kZV9vYmo6IG51bGwgfTsKICB9CiAgcGF0aF9sb29rdXAocGF0aCwgZGlyZmxhZ3MpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBpbm9kZV9vYmo6IG51bGwgfTsKICB9CiAgcGF0aF9vcGVuKGRpcmZsYWdzLCBwYXRoLCBvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZywgZmRfZmxhZ3MpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9URElSLCBmZF9vYmo6IG51bGwgfTsKICB9CiAgcGF0aF9yZWFkbGluayhwYXRoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZGF0YTogbnVsbCB9OwogIH0KICBwYXRoX3JlbW92ZV9kaXJlY3RvcnkocGF0aCkgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgcGF0aF9yZW5hbWUob2xkX3BhdGgsIG5ld19mZCwgbmV3X3BhdGgpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfdW5saW5rX2ZpbGUocGF0aCkgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9Cn07CnZhciBJbm9kZSA9IGNsYXNzIHsKfTsKCi8vIG5vZGVfbW9kdWxlcy9AYmpvcm4zL2Jyb3dzZXJfd2FzaV9zaGltL2Rpc3QvZnNfbWVtLmpzCnZhciBPcGVuRmlsZSA9IGNsYXNzIGV4dGVuZHMgRmQgewogIGZkX2FsbG9jYXRlKG9mZnNldCwgbGVuKSB7CiAgICBpZiAodGhpcy5maWxlLnNpemUgPiBvZmZzZXQgKyBsZW4pIHsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IG5ld19kYXRhID0gbmV3IFVpbnQ4QXJyYXkoTnVtYmVyKG9mZnNldCArIGxlbikpOwogICAgICBuZXdfZGF0YS5zZXQodGhpcy5maWxlLmRhdGEsIDApOwogICAgICB0aGlzLmZpbGUuZGF0YSA9IG5ld19kYXRhOwogICAgfQogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIGZkX2Zkc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIGZkc3RhdDogbmV3IEZkc3RhdChGSUxFVFlQRV9SRUdVTEFSX0ZJTEUsIDApIH07CiAgfQogIGZkX2ZpbGVzdGF0X3NldF9zaXplKHNpemUpIHsKICAgIGlmICh0aGlzLmZpbGUuc2l6ZSA+IHNpemUpIHsKICAgICAgdGhpcy5maWxlLmRhdGEgPSBuZXcgVWludDhBcnJheSh0aGlzLmZpbGUuZGF0YS5idWZmZXIuc2xpY2UoMCwgTnVtYmVyKHNpemUpKSk7CiAgICB9IGVsc2UgewogICAgICBjb25zdCBuZXdfZGF0YSA9IG5ldyBVaW50OEFycmF5KE51bWJlcihzaXplKSk7CiAgICAgIG5ld19kYXRhLnNldCh0aGlzLmZpbGUuZGF0YSwgMCk7CiAgICAgIHRoaXMuZmlsZS5kYXRhID0gbmV3X2RhdGE7CiAgICB9CiAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICB9CiAgZmRfcmVhZChzaXplKSB7CiAgICBjb25zdCBzbGljZSA9IHRoaXMuZmlsZS5kYXRhLnNsaWNlKE51bWJlcih0aGlzLmZpbGVfcG9zKSwgTnVtYmVyKHRoaXMuZmlsZV9wb3MgKyBCaWdJbnQoc2l6ZSkpKTsKICAgIHRoaXMuZmlsZV9wb3MgKz0gQmlnSW50KHNsaWNlLmxlbmd0aCk7CiAgICByZXR1cm4geyByZXQ6IDAsIGRhdGE6IHNsaWNlIH07CiAgfQogIGZkX3ByZWFkKHNpemUsIG9mZnNldCkgewogICAgY29uc3Qgc2xpY2UgPSB0aGlzLmZpbGUuZGF0YS5zbGljZShOdW1iZXIob2Zmc2V0KSwgTnVtYmVyKG9mZnNldCArIEJpZ0ludChzaXplKSkpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBkYXRhOiBzbGljZSB9OwogIH0KICBmZF9zZWVrKG9mZnNldCwgd2hlbmNlKSB7CiAgICBsZXQgY2FsY3VsYXRlZF9vZmZzZXQ7CiAgICBzd2l0Y2ggKHdoZW5jZSkgewogICAgICBjYXNlIFdIRU5DRV9TRVQ6CiAgICAgICAgY2FsY3VsYXRlZF9vZmZzZXQgPSBvZmZzZXQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgV0hFTkNFX0NVUjoKICAgICAgICBjYWxjdWxhdGVkX29mZnNldCA9IHRoaXMuZmlsZV9wb3MgKyBvZmZzZXQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgV0hFTkNFX0VORDoKICAgICAgICBjYWxjdWxhdGVkX29mZnNldCA9IEJpZ0ludCh0aGlzLmZpbGUuZGF0YS5ieXRlTGVuZ3RoKSArIG9mZnNldDsKICAgICAgICBicmVhazsKICAgICAgZGVmYXVsdDoKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0lOVkFMLCBvZmZzZXQ6IDBuIH07CiAgICB9CiAgICBpZiAoY2FsY3VsYXRlZF9vZmZzZXQgPCAwKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fSU5WQUwsIG9mZnNldDogMG4gfTsKICAgIH0KICAgIHRoaXMuZmlsZV9wb3MgPSBjYWxjdWxhdGVkX29mZnNldDsKICAgIHJldHVybiB7IHJldDogMCwgb2Zmc2V0OiB0aGlzLmZpbGVfcG9zIH07CiAgfQogIGZkX3RlbGwoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIG9mZnNldDogdGhpcy5maWxlX3BvcyB9OwogIH0KICBmZF93cml0ZShkYXRhKSB7CiAgICBpZiAodGhpcy5maWxlLnJlYWRvbmx5KQogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG53cml0dGVuOiAwIH07CiAgICBpZiAodGhpcy5maWxlX3BvcyArIEJpZ0ludChkYXRhLmJ5dGVMZW5ndGgpID4gdGhpcy5maWxlLnNpemUpIHsKICAgICAgY29uc3Qgb2xkID0gdGhpcy5maWxlLmRhdGE7CiAgICAgIHRoaXMuZmlsZS5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoTnVtYmVyKHRoaXMuZmlsZV9wb3MgKyBCaWdJbnQoZGF0YS5ieXRlTGVuZ3RoKSkpOwogICAgICB0aGlzLmZpbGUuZGF0YS5zZXQob2xkKTsKICAgIH0KICAgIHRoaXMuZmlsZS5kYXRhLnNldChkYXRhLCBOdW1iZXIodGhpcy5maWxlX3BvcykpOwogICAgdGhpcy5maWxlX3BvcyArPSBCaWdJbnQoZGF0YS5ieXRlTGVuZ3RoKTsKICAgIHJldHVybiB7IHJldDogMCwgbndyaXR0ZW46IGRhdGEuYnl0ZUxlbmd0aCB9OwogIH0KICBmZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KSB7CiAgICBpZiAodGhpcy5maWxlLnJlYWRvbmx5KQogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG53cml0dGVuOiAwIH07CiAgICBpZiAob2Zmc2V0ICsgQmlnSW50KGRhdGEuYnl0ZUxlbmd0aCkgPiB0aGlzLmZpbGUuc2l6ZSkgewogICAgICBjb25zdCBvbGQgPSB0aGlzLmZpbGUuZGF0YTsKICAgICAgdGhpcy5maWxlLmRhdGEgPSBuZXcgVWludDhBcnJheShOdW1iZXIob2Zmc2V0ICsgQmlnSW50KGRhdGEuYnl0ZUxlbmd0aCkpKTsKICAgICAgdGhpcy5maWxlLmRhdGEuc2V0KG9sZCk7CiAgICB9CiAgICB0aGlzLmZpbGUuZGF0YS5zZXQoZGF0YSwgTnVtYmVyKG9mZnNldCkpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBud3JpdHRlbjogZGF0YS5ieXRlTGVuZ3RoIH07CiAgfQogIGZkX2ZpbGVzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgZmlsZXN0YXQ6IHRoaXMuZmlsZS5zdGF0KCkgfTsKICB9CiAgY29uc3RydWN0b3IoZmlsZSkgewogICAgc3VwZXIoKTsKICAgIHRoaXMuZmlsZV9wb3MgPSAwbjsKICAgIHRoaXMuZmlsZSA9IGZpbGU7CiAgfQp9Owp2YXIgT3BlbkRpcmVjdG9yeSA9IGNsYXNzIGV4dGVuZHMgRmQgewogIGZkX3NlZWsob2Zmc2V0LCB3aGVuY2UpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fQkFERiwgb2Zmc2V0OiAwbiB9OwogIH0KICBmZF90ZWxsKCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBvZmZzZXQ6IDBuIH07CiAgfQogIGZkX2FsbG9jYXRlKG9mZnNldCwgbGVuKSB7CiAgICByZXR1cm4gRVJSTk9fQkFERjsKICB9CiAgZmRfZmRzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgZmRzdGF0OiBuZXcgRmRzdGF0KEZJTEVUWVBFX0RJUkVDVE9SWSwgMCkgfTsKICB9CiAgZmRfcmVhZGRpcl9zaW5nbGUoY29va2llKSB7CiAgICBpZiAoZGVidWcuZW5hYmxlZCkgewogICAgICBkZWJ1Zy5sb2coInJlYWRkaXJfc2luZ2xlIiwgY29va2llKTsKICAgICAgZGVidWcubG9nKGNvb2tpZSwgdGhpcy5kaXIuY29udGVudHMua2V5cygpKTsKICAgIH0KICAgIGlmIChjb29raWUgPT0gMG4pIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBkaXJlbnQ6IG5ldyBEaXJlbnQoMW4sICIuIiwgRklMRVRZUEVfRElSRUNUT1JZKSB9OwogICAgfSBlbHNlIGlmIChjb29raWUgPT0gMW4pIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBkaXJlbnQ6IG5ldyBEaXJlbnQoMm4sICIuLiIsIEZJTEVUWVBFX0RJUkVDVE9SWSkgfTsKICAgIH0KICAgIGlmIChjb29raWUgPj0gQmlnSW50KHRoaXMuZGlyLmNvbnRlbnRzLnNpemUpICsgMm4pIHsKICAgICAgcmV0dXJuIHsgcmV0OiAwLCBkaXJlbnQ6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IFtuYW1lLCBlbnRyeV0gPSBBcnJheS5mcm9tKHRoaXMuZGlyLmNvbnRlbnRzLmVudHJpZXMoKSlbTnVtYmVyKGNvb2tpZSAtIDJuKV07CiAgICByZXR1cm4geyByZXQ6IDAsIGRpcmVudDogbmV3IERpcmVudChjb29raWUgKyAxbiwgbmFtZSwgZW50cnkuc3RhdCgpLmZpbGV0eXBlKSB9OwogIH0KICBwYXRoX2ZpbGVzdGF0X2dldChmbGFncywgcGF0aF9zdHIpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX2VyciwgcGF0aCB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXRoX2VyciwgZmlsZXN0YXQ6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0LCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgpOwogICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0LCBmaWxlc3RhdDogbnVsbCB9OwogICAgfQogICAgcmV0dXJuIHsgcmV0OiAwLCBmaWxlc3RhdDogZW50cnkuc3RhdCgpIH07CiAgfQogIHBhdGhfbG9va3VwKHBhdGhfc3RyLCBkaXJmbGFncykgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhdGhfcmV0LCBpbm9kZV9vYmo6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0LCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgpOwogICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0LCBpbm9kZV9vYmo6IG51bGwgfTsKICAgIH0KICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgaW5vZGVfb2JqOiBlbnRyeSB9OwogIH0KICBwYXRoX29wZW4oZGlyZmxhZ3MsIHBhdGhfc3RyLCBvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZywgZmRfZmxhZ3MpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX3JldCwgcGF0aCB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXRoX3JldCwgZmRfb2JqOiBudWxsIH07CiAgICB9CiAgICBsZXQgeyByZXQsIGVudHJ5IH0gPSB0aGlzLmRpci5nZXRfZW50cnlfZm9yX3BhdGgocGF0aCk7CiAgICBpZiAoZW50cnkgPT0gbnVsbCkgewogICAgICBpZiAocmV0ICE9IEVSUk5PX05PRU5UKSB7CiAgICAgICAgcmV0dXJuIHsgcmV0LCBmZF9vYmo6IG51bGwgfTsKICAgICAgfQogICAgICBpZiAoKG9mbGFncyAmIE9GTEFHU19DUkVBVCkgPT0gT0ZMQUdTX0NSRUFUKSB7CiAgICAgICAgY29uc3QgeyByZXQ6IHJldDIsIGVudHJ5OiBuZXdfZW50cnkgfSA9IHRoaXMuZGlyLmNyZWF0ZV9lbnRyeV9mb3JfcGF0aChwYXRoX3N0ciwgKG9mbGFncyAmIE9GTEFHU19ESVJFQ1RPUlkpID09IE9GTEFHU19ESVJFQ1RPUlkpOwogICAgICAgIGlmIChuZXdfZW50cnkgPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHsgcmV0OiByZXQyLCBmZF9vYmo6IG51bGwgfTsKICAgICAgICB9CiAgICAgICAgZW50cnkgPSBuZXdfZW50cnk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT0VOVCwgZmRfb2JqOiBudWxsIH07CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoKG9mbGFncyAmIE9GTEFHU19FWENMKSA9PSBPRkxBR1NfRVhDTCkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0VYSVNULCBmZF9vYmo6IG51bGwgfTsKICAgIH0KICAgIGlmICgob2ZsYWdzICYgT0ZMQUdTX0RJUkVDVE9SWSkgPT0gT0ZMQUdTX0RJUkVDVE9SWSAmJiBlbnRyeS5zdGF0KCkuZmlsZXR5cGUgIT09IEZJTEVUWVBFX0RJUkVDVE9SWSkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgZmRfb2JqOiBudWxsIH07CiAgICB9CiAgICByZXR1cm4gZW50cnkucGF0aF9vcGVuKG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZkX2ZsYWdzKTsKICB9CiAgcGF0aF9jcmVhdGVfZGlyZWN0b3J5KHBhdGgpIHsKICAgIHJldHVybiB0aGlzLnBhdGhfb3BlbigwLCBwYXRoLCBPRkxBR1NfQ1JFQVQgfCBPRkxBR1NfRElSRUNUT1JZLCAwbiwgMG4sIDApLnJldDsKICB9CiAgcGF0aF9saW5rKHBhdGhfc3RyLCBpbm9kZSwgYWxsb3dfZGlyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXRoX3JldDsKICAgIH0KICAgIGlmIChwYXRoLmlzX2RpcikgewogICAgICByZXR1cm4gRVJSTk9fTk9FTlQ7CiAgICB9CiAgICBjb25zdCB7IHJldDogcGFyZW50X3JldCwgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9wYXJlbnRfZGlyX2FuZF9lbnRyeV9mb3JfcGF0aChwYXRoLCB0cnVlKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCB8fCBmaWxlbmFtZSA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXJlbnRfcmV0OwogICAgfQogICAgaWYgKGVudHJ5ICE9IG51bGwpIHsKICAgICAgY29uc3Qgc291cmNlX2lzX2RpciA9IGlub2RlLnN0YXQoKS5maWxldHlwZSA9PSBGSUxFVFlQRV9ESVJFQ1RPUlk7CiAgICAgIGNvbnN0IHRhcmdldF9pc19kaXIgPSBlbnRyeS5zdGF0KCkuZmlsZXR5cGUgPT0gRklMRVRZUEVfRElSRUNUT1JZOwogICAgICBpZiAoc291cmNlX2lzX2RpciAmJiB0YXJnZXRfaXNfZGlyKSB7CiAgICAgICAgaWYgKGFsbG93X2RpciAmJiBlbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkgewogICAgICAgICAgaWYgKGVudHJ5LmNvbnRlbnRzLnNpemUgPT0gMCkgewogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIEVSUk5PX05PVEVNUFRZOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gRVJSTk9fRVhJU1Q7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKHNvdXJjZV9pc19kaXIgJiYgIXRhcmdldF9pc19kaXIpIHsKICAgICAgICByZXR1cm4gRVJSTk9fTk9URElSOwogICAgICB9IGVsc2UgaWYgKCFzb3VyY2VfaXNfZGlyICYmIHRhcmdldF9pc19kaXIpIHsKICAgICAgICByZXR1cm4gRVJSTk9fSVNESVI7CiAgICAgIH0gZWxzZSBpZiAoaW5vZGUuc3RhdCgpLmZpbGV0eXBlID09IEZJTEVUWVBFX1JFR1VMQVJfRklMRSAmJiBlbnRyeS5zdGF0KCkuZmlsZXR5cGUgPT0gRklMRVRZUEVfUkVHVUxBUl9GSUxFKSB7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0VYSVNUOwogICAgICB9CiAgICB9CiAgICBpZiAoIWFsbG93X2RpciAmJiBpbm9kZS5zdGF0KCkuZmlsZXR5cGUgPT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgIHJldHVybiBFUlJOT19QRVJNOwogICAgfQogICAgcGFyZW50X2VudHJ5LmNvbnRlbnRzLnNldChmaWxlbmFtZSwgaW5vZGUpOwogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIHBhdGhfdW5saW5rKHBhdGhfc3RyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogcGF0aF9yZXQsIGlub2RlX29iajogbnVsbCB9OwogICAgfQogICAgY29uc3QgeyByZXQ6IHBhcmVudF9yZXQsIHBhcmVudF9lbnRyeSwgZmlsZW5hbWUsIGVudHJ5IH0gPSB0aGlzLmRpci5nZXRfcGFyZW50X2Rpcl9hbmRfZW50cnlfZm9yX3BhdGgocGF0aCwgdHJ1ZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhcmVudF9yZXQsIGlub2RlX29iajogbnVsbCB9OwogICAgfQogICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT0VOVCwgaW5vZGVfb2JqOiBudWxsIH07CiAgICB9CiAgICBwYXJlbnRfZW50cnkuY29udGVudHMuZGVsZXRlKGZpbGVuYW1lKTsKICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgaW5vZGVfb2JqOiBlbnRyeSB9OwogIH0KICBwYXRoX3VubGlua19maWxlKHBhdGhfc3RyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXRoX3JldDsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBwYXJlbnRfcmV0LCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIGZhbHNlKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCB8fCBmaWxlbmFtZSA9PSBudWxsIHx8IGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHBhcmVudF9yZXQ7CiAgICB9CiAgICBpZiAoZW50cnkuc3RhdCgpLmZpbGV0eXBlID09PSBGSUxFVFlQRV9ESVJFQ1RPUlkpIHsKICAgICAgcmV0dXJuIEVSUk5PX0lTRElSOwogICAgfQogICAgcGFyZW50X2VudHJ5LmNvbnRlbnRzLmRlbGV0ZShmaWxlbmFtZSk7CiAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICB9CiAgcGF0aF9yZW1vdmVfZGlyZWN0b3J5KHBhdGhfc3RyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXRoX3JldDsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBwYXJlbnRfcmV0LCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIGZhbHNlKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCB8fCBmaWxlbmFtZSA9PSBudWxsIHx8IGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHBhcmVudF9yZXQ7CiAgICB9CiAgICBpZiAoIShlbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkgfHwgZW50cnkuc3RhdCgpLmZpbGV0eXBlICE9PSBGSUxFVFlQRV9ESVJFQ1RPUlkpIHsKICAgICAgcmV0dXJuIEVSUk5PX05PVERJUjsKICAgIH0KICAgIGlmIChlbnRyeS5jb250ZW50cy5zaXplICE9PSAwKSB7CiAgICAgIHJldHVybiBFUlJOT19OT1RFTVBUWTsKICAgIH0KICAgIGlmICghcGFyZW50X2VudHJ5LmNvbnRlbnRzLmRlbGV0ZShmaWxlbmFtZSkpIHsKICAgICAgcmV0dXJuIEVSUk5PX05PRU5UOwogICAgfQogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIGZkX2ZpbGVzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgZmlsZXN0YXQ6IHRoaXMuZGlyLnN0YXQoKSB9OwogIH0KICBmZF9maWxlc3RhdF9zZXRfc2l6ZShzaXplKSB7CiAgICByZXR1cm4gRVJSTk9fQkFERjsKICB9CiAgZmRfcmVhZChzaXplKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIGRhdGE6IG5ldyBVaW50OEFycmF5KCkgfTsKICB9CiAgZmRfcHJlYWQoc2l6ZSwgb2Zmc2V0KSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIGRhdGE6IG5ldyBVaW50OEFycmF5KCkgfTsKICB9CiAgZmRfd3JpdGUoZGF0YSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBud3JpdHRlbjogMCB9OwogIH0KICBmZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG53cml0dGVuOiAwIH07CiAgfQogIGNvbnN0cnVjdG9yKGRpcikgewogICAgc3VwZXIoKTsKICAgIHRoaXMuZGlyID0gZGlyOwogIH0KfTsKdmFyIFByZW9wZW5EaXJlY3RvcnkgPSBjbGFzcyBleHRlbmRzIE9wZW5EaXJlY3RvcnkgewogIGZkX3ByZXN0YXRfZ2V0KCkgewogICAgcmV0dXJuIHsgcmV0OiAwLCBwcmVzdGF0OiBQcmVzdGF0LmRpcih0aGlzLnByZXN0YXRfbmFtZSkgfTsKICB9CiAgY29uc3RydWN0b3IobmFtZSwgY29udGVudHMpIHsKICAgIHN1cGVyKG5ldyBEaXJlY3RvcnkoY29udGVudHMpKTsKICAgIHRoaXMucHJlc3RhdF9uYW1lID0gbmFtZTsKICB9Cn07CnZhciBGaWxlID0gY2xhc3MgZXh0ZW5kcyBJbm9kZSB7CiAgcGF0aF9vcGVuKG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZkX2ZsYWdzKSB7CiAgICBpZiAodGhpcy5yZWFkb25seSAmJiAoZnNfcmlnaHRzX2Jhc2UgJiBCaWdJbnQoUklHSFRTX0ZEX1dSSVRFKSkgPT0gQmlnSW50KFJJR0hUU19GRF9XUklURSkpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19QRVJNLCBmZF9vYmo6IG51bGwgfTsKICAgIH0KICAgIGlmICgob2ZsYWdzICYgT0ZMQUdTX1RSVU5DKSA9PSBPRkxBR1NfVFJVTkMpIHsKICAgICAgaWYgKHRoaXMucmVhZG9ubHkpCiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19QRVJNLCBmZF9vYmo6IG51bGwgfTsKICAgICAgdGhpcy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoW10pOwogICAgfQogICAgY29uc3QgZmlsZSA9IG5ldyBPcGVuRmlsZSh0aGlzKTsKICAgIGlmIChmZF9mbGFncyAmIEZERkxBR1NfQVBQRU5EKQogICAgICBmaWxlLmZkX3NlZWsoMG4sIFdIRU5DRV9FTkQpOwogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBmZF9vYmo6IGZpbGUgfTsKICB9CiAgZ2V0IHNpemUoKSB7CiAgICByZXR1cm4gQmlnSW50KHRoaXMuZGF0YS5ieXRlTGVuZ3RoKTsKICB9CiAgc3RhdCgpIHsKICAgIHJldHVybiBuZXcgRmlsZXN0YXQoRklMRVRZUEVfUkVHVUxBUl9GSUxFLCB0aGlzLnNpemUpOwogIH0KICBjb25zdHJ1Y3RvcihkYXRhLCBvcHRpb25zKSB7CiAgICBzdXBlcigpOwogICAgdGhpcy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoZGF0YSk7CiAgICB0aGlzLnJlYWRvbmx5ID0gISFvcHRpb25zPy5yZWFkb25seTsKICB9Cn07CnZhciBQYXRoID0gY2xhc3MgUGF0aDIgewogIHN0YXRpYyBmcm9tKHBhdGgpIHsKICAgIGNvbnN0IHNlbGYgPSBuZXcgUGF0aDIoKTsKICAgIHNlbGYuaXNfZGlyID0gcGF0aC5lbmRzV2l0aCgiLyIpOwogICAgaWYgKHBhdGguc3RhcnRzV2l0aCgiLyIpKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UQ0FQQUJMRSwgcGF0aDogbnVsbCB9OwogICAgfQogICAgaWYgKHBhdGguaW5jbHVkZXMoIlwwIikpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19JTlZBTCwgcGF0aDogbnVsbCB9OwogICAgfQogICAgZm9yIChjb25zdCBjb21wb25lbnQgb2YgcGF0aC5zcGxpdCgiLyIpKSB7CiAgICAgIGlmIChjb21wb25lbnQgPT09ICIiIHx8IGNvbXBvbmVudCA9PT0gIi4iKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGNvbXBvbmVudCA9PT0gIi4uIikgewogICAgICAgIGlmIChzZWxmLnBhcnRzLnBvcCgpID09IHZvaWQgMCkgewogICAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RDQVBBQkxFLCBwYXRoOiBudWxsIH07CiAgICAgICAgfQogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHNlbGYucGFydHMucHVzaChjb21wb25lbnQpOwogICAgfQogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBwYXRoOiBzZWxmIH07CiAgfQogIHRvX3BhdGhfc3RyaW5nKCkgewogICAgbGV0IHMgPSB0aGlzLnBhcnRzLmpvaW4oIi8iKTsKICAgIGlmICh0aGlzLmlzX2RpcikgewogICAgICBzICs9ICIvIjsKICAgIH0KICAgIHJldHVybiBzOwogIH0KICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMucGFydHMgPSBbXTsKICAgIHRoaXMuaXNfZGlyID0gZmFsc2U7CiAgfQp9Owp2YXIgRGlyZWN0b3J5ID0gY2xhc3MgZXh0ZW5kcyBJbm9kZSB7CiAgcGF0aF9vcGVuKG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZkX2ZsYWdzKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGZkX29iajogbmV3IE9wZW5EaXJlY3RvcnkodGhpcykgfTsKICB9CiAgc3RhdCgpIHsKICAgIHJldHVybiBuZXcgRmlsZXN0YXQoRklMRVRZUEVfRElSRUNUT1JZLCAwbik7CiAgfQogIGdldF9lbnRyeV9mb3JfcGF0aChwYXRoKSB7CiAgICBsZXQgZW50cnkgPSB0aGlzOwogICAgZm9yIChjb25zdCBjb21wb25lbnQgb2YgcGF0aC5wYXJ0cykgewogICAgICBpZiAoIShlbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkpIHsKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgICBjb25zdCBjaGlsZCA9IGVudHJ5LmNvbnRlbnRzLmdldChjb21wb25lbnQpOwogICAgICBpZiAoY2hpbGQgIT09IHZvaWQgMCkgewogICAgICAgIGVudHJ5ID0gY2hpbGQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZGVidWcubG9nKGNvbXBvbmVudCk7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT0VOVCwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgfQogICAgaWYgKHBhdGguaXNfZGlyKSB7CiAgICAgIGlmIChlbnRyeS5zdGF0KCkuZmlsZXR5cGUgIT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIGVudHJ5OiBudWxsIH07CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZW50cnkgfTsKICB9CiAgZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIGFsbG93X3VuZGVmaW5lZCkgewogICAgY29uc3QgZmlsZW5hbWUgPSBwYXRoLnBhcnRzLnBvcCgpOwogICAgaWYgKGZpbGVuYW1lID09PSB2b2lkIDApIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19JTlZBTCwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBlbnRyeV9yZXQsIGVudHJ5OiBwYXJlbnRfZW50cnkgfSA9IHRoaXMuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgpOwogICAgaWYgKHBhcmVudF9lbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogZW50cnlfcmV0LCBwYXJlbnRfZW50cnk6IG51bGwsIGZpbGVuYW1lOiBudWxsLCBlbnRyeTogbnVsbCB9OwogICAgfQogICAgaWYgKCEocGFyZW50X2VudHJ5IGluc3RhbmNlb2YgRGlyZWN0b3J5KSkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IGVudHJ5ID0gcGFyZW50X2VudHJ5LmNvbnRlbnRzLmdldChmaWxlbmFtZSk7CiAgICBpZiAoZW50cnkgPT09IHZvaWQgMCkgewogICAgICBpZiAoIWFsbG93X3VuZGVmaW5lZCkgewogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9FTlQsIHBhcmVudF9lbnRyeTogbnVsbCwgZmlsZW5hbWU6IG51bGwsIGVudHJ5OiBudWxsIH07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeTogbnVsbCB9OwogICAgICB9CiAgICB9CiAgICBpZiAocGF0aC5pc19kaXIpIHsKICAgICAgaWYgKGVudHJ5LnN0YXQoKS5maWxldHlwZSAhPSBGSUxFVFlQRV9ESVJFQ1RPUlkpIHsKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9OwogIH0KICBjcmVhdGVfZW50cnlfZm9yX3BhdGgocGF0aF9zdHIsIGlzX2RpcikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhdGhfcmV0LCBlbnRyeTogbnVsbCB9OwogICAgfQogICAgbGV0IHsgcmV0OiBwYXJlbnRfcmV0LCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9ID0gdGhpcy5nZXRfcGFyZW50X2Rpcl9hbmRfZW50cnlfZm9yX3BhdGgocGF0aCwgdHJ1ZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhcmVudF9yZXQsIGVudHJ5OiBudWxsIH07CiAgICB9CiAgICBpZiAoZW50cnkgIT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0VYSVNULCBlbnRyeTogbnVsbCB9OwogICAgfQogICAgZGVidWcubG9nKCJjcmVhdGUiLCBwYXRoKTsKICAgIGxldCBuZXdfY2hpbGQ7CiAgICBpZiAoIWlzX2RpcikgewogICAgICBuZXdfY2hpbGQgPSBuZXcgRmlsZShuZXcgQXJyYXlCdWZmZXIoMCkpOwogICAgfSBlbHNlIHsKICAgICAgbmV3X2NoaWxkID0gbmV3IERpcmVjdG9yeSgvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpKTsKICAgIH0KICAgIHBhcmVudF9lbnRyeS5jb250ZW50cy5zZXQoZmlsZW5hbWUsIG5ld19jaGlsZCk7CiAgICBlbnRyeSA9IG5ld19jaGlsZDsKICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZW50cnkgfTsKICB9CiAgY29uc3RydWN0b3IoY29udGVudHMpIHsKICAgIHN1cGVyKCk7CiAgICBpZiAoY29udGVudHMgaW5zdGFuY2VvZiBBcnJheSkgewogICAgICB0aGlzLmNvbnRlbnRzID0gbmV3IE1hcChjb250ZW50cyk7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmNvbnRlbnRzID0gY29udGVudHM7CiAgICB9CiAgfQp9Owp2YXIgQ29uc29sZVN0ZG91dCA9IGNsYXNzIGV4dGVuZHMgRmQgewogIGZkX2ZpbGVzdGF0X2dldCgpIHsKICAgIGNvbnN0IGZpbGVzdGF0ID0gbmV3IEZpbGVzdGF0KEZJTEVUWVBFX0NIQVJBQ1RFUl9ERVZJQ0UsIEJpZ0ludCgwKSk7CiAgICByZXR1cm4geyByZXQ6IDAsIGZpbGVzdGF0IH07CiAgfQogIGZkX2Zkc3RhdF9nZXQoKSB7CiAgICBjb25zdCBmZHN0YXQgPSBuZXcgRmRzdGF0KEZJTEVUWVBFX0NIQVJBQ1RFUl9ERVZJQ0UsIDApOwogICAgZmRzdGF0LmZzX3JpZ2h0c19iYXNlID0gQmlnSW50KFJJR0hUU19GRF9XUklURSk7CiAgICByZXR1cm4geyByZXQ6IDAsIGZkc3RhdCB9OwogIH0KICBmZF93cml0ZShkYXRhKSB7CiAgICB0aGlzLndyaXRlKGRhdGEpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBud3JpdHRlbjogZGF0YS5ieXRlTGVuZ3RoIH07CiAgfQogIHN0YXRpYyBsaW5lQnVmZmVyZWQod3JpdGUpIHsKICAgIGNvbnN0IGRlYyA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiLCB7IGZhdGFsOiBmYWxzZSB9KTsKICAgIGxldCBsaW5lX2J1ZiA9ICIiOwogICAgcmV0dXJuIG5ldyBDb25zb2xlU3Rkb3V0KChidWZmZXIpID0+IHsKICAgICAgbGluZV9idWYgKz0gZGVjLmRlY29kZShidWZmZXIsIHsgc3RyZWFtOiB0cnVlIH0pOwogICAgICBjb25zdCBsaW5lcyA9IGxpbmVfYnVmLnNwbGl0KCJcbiIpOwogICAgICBmb3IgKGNvbnN0IFtpLCBsaW5lXSBvZiBsaW5lcy5lbnRyaWVzKCkpIHsKICAgICAgICBpZiAoaSA8IGxpbmVzLmxlbmd0aCAtIDEpIHsKICAgICAgICAgIHdyaXRlKGxpbmUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBsaW5lX2J1ZiA9IGxpbmU7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICB9CiAgY29uc3RydWN0b3Iod3JpdGUpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLndyaXRlID0gd3JpdGU7CiAgfQp9OwoKLy8gbm9kZV9tb2R1bGVzL3dhc20taW1wb3J0cy1wYXJzZXIvaW5kZXguanMKZnVuY3Rpb24gcGFyc2VJbXBvcnRzKG1vZHVsZUJ5dGVzKSB7CiAgaWYgKG1vZHVsZUJ5dGVzIGluc3RhbmNlb2YgVWludDhBcnJheSkgewogIH0gZWxzZSBpZiAobW9kdWxlQnl0ZXMgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikgewogICAgbW9kdWxlQnl0ZXMgPSBuZXcgVWludDhBcnJheShtb2R1bGVCeXRlcyk7CiAgfSBlbHNlIGlmIChtb2R1bGVCeXRlcy5idWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikgewogICAgbW9kdWxlQnl0ZXMgPSBuZXcgVWludDhBcnJheShtb2R1bGVCeXRlcy5idWZmZXIpOwogIH0gZWxzZSB7CiAgICB0aHJvdyBuZXcgRXJyb3IoIkFyZ3VtZW50IG11c3QgYmUgYSBidWZmZXIgc291cmNlLCBsaWtlIFVpbnQ4QXJyYXkgb3IgQXJyYXlCdWZmZXIiKTsKICB9CiAgY29uc3QgcGFyc2VTdGF0ZSA9IG5ldyBQYXJzZVN0YXRlKG1vZHVsZUJ5dGVzKTsKICBwYXJzZU1hZ2ljTnVtYmVyKHBhcnNlU3RhdGUpOwogIHBhcnNlVmVyc2lvbihwYXJzZVN0YXRlKTsKICBjb25zdCB0eXBlcyA9IFtdOwogIGNvbnN0IGltcG9ydHMgPSBbXTsKICB3aGlsZSAocGFyc2VTdGF0ZS5oYXNNb3JlQnl0ZXMoKSkgewogICAgY29uc3Qgc2VjdGlvbklkID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogICAgY29uc3Qgc2VjdGlvblNpemUgPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgc3dpdGNoIChzZWN0aW9uSWQpIHsKICAgICAgY2FzZSAxOiB7CiAgICAgICAgY29uc3QgdHlwZUNvdW50ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHR5cGVDb3VudDsgaSsrKSB7CiAgICAgICAgICB0eXBlcy5wdXNoKHBhcnNlRnVuY3Rpb25UeXBlKHBhcnNlU3RhdGUpKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY2FzZSAyOiB7CiAgICAgICAgY29uc3QgaW1wb3J0Q291bnQgPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW1wb3J0Q291bnQ7IGkrKykgewogICAgICAgICAgY29uc3QgbW9kdWxlID0gcGFyc2VTdGF0ZS5yZWFkTmFtZSgpOwogICAgICAgICAgY29uc3QgbmFtZSA9IHBhcnNlU3RhdGUucmVhZE5hbWUoKTsKICAgICAgICAgIGNvbnN0IHR5cGUgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICAgICAgICAgICAgICBpbXBvcnRzLnB1c2goeyBtb2R1bGUsIG5hbWUsIGtpbmQ6ICJmdW5jdGlvbiIsIHR5cGU6IHR5cGVzW2luZGV4XSB9KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgIGltcG9ydHMucHVzaCh7IG1vZHVsZSwgbmFtZSwga2luZDogInRhYmxlIiwgdHlwZTogcGFyc2VUYWJsZVR5cGUocGFyc2VTdGF0ZSkgfSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgICBpbXBvcnRzLnB1c2goeyBtb2R1bGUsIG5hbWUsIGtpbmQ6ICJtZW1vcnkiLCB0eXBlOiBwYXJzZUxpbWl0cyhwYXJzZVN0YXRlKSB9KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAzOgogICAgICAgICAgICAgIGltcG9ydHMucHVzaCh7IG1vZHVsZSwgbmFtZSwga2luZDogImdsb2JhbCIsIHR5cGU6IHBhcnNlR2xvYmFsVHlwZShwYXJzZVN0YXRlKSB9KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gaW1wb3J0IGRlc2NyaXB0b3IgdHlwZSAke3R5cGV9YCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBpbXBvcnRzOwogICAgICB9CiAgICAgIGRlZmF1bHQ6IHsKICAgICAgICBwYXJzZVN0YXRlLnNraXBCeXRlcyhzZWN0aW9uU2l6ZSk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICB9CiAgcmV0dXJuIFtdOwp9CnZhciBQYXJzZVN0YXRlID0gY2xhc3MgewogIGNvbnN0cnVjdG9yKG1vZHVsZUJ5dGVzKSB7CiAgICB0aGlzLm1vZHVsZUJ5dGVzID0gbW9kdWxlQnl0ZXM7CiAgICB0aGlzLm9mZnNldCA9IDA7CiAgICB0aGlzLnRleHREZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpOwogIH0KICBoYXNNb3JlQnl0ZXMoKSB7CiAgICByZXR1cm4gdGhpcy5vZmZzZXQgPCB0aGlzLm1vZHVsZUJ5dGVzLmxlbmd0aDsKICB9CiAgcmVhZEJ5dGUoKSB7CiAgICByZXR1cm4gdGhpcy5tb2R1bGVCeXRlc1t0aGlzLm9mZnNldCsrXTsKICB9CiAgc2tpcEJ5dGVzKGNvdW50KSB7CiAgICB0aGlzLm9mZnNldCArPSBjb3VudDsKICB9CiAgcmVhZFVuc2lnbmVkTEVCMTI4KCkgewogICAgbGV0IHJlc3VsdCA9IDA7CiAgICBsZXQgc2hpZnQgPSAwOwogICAgbGV0IGJ5dGU7CiAgICBkbyB7CiAgICAgIGJ5dGUgPSB0aGlzLnJlYWRCeXRlKCk7CiAgICAgIHJlc3VsdCB8PSAoYnl0ZSAmIDEyNykgPDwgc2hpZnQ7CiAgICAgIHNoaWZ0ICs9IDc7CiAgICB9IHdoaWxlIChieXRlICYgMTI4KTsKICAgIHJldHVybiByZXN1bHQ7CiAgfQogIHJlYWROYW1lKCkgewogICAgY29uc3QgbmFtZUxlbmd0aCA9IHRoaXMucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgICBjb25zdCBuYW1lQnl0ZXMgPSB0aGlzLm1vZHVsZUJ5dGVzLnNsaWNlKHRoaXMub2Zmc2V0LCB0aGlzLm9mZnNldCArIG5hbWVMZW5ndGgpOwogICAgY29uc3QgbmFtZSA9IHRoaXMudGV4dERlY29kZXIuZGVjb2RlKG5hbWVCeXRlcyk7CiAgICB0aGlzLm9mZnNldCArPSBuYW1lTGVuZ3RoOwogICAgcmV0dXJuIG5hbWU7CiAgfQogIGFzc2VydEJ5dGVzKGV4cGVjdGVkKSB7CiAgICBjb25zdCBiYXNlT2Zmc2V0ID0gdGhpcy5vZmZzZXQ7CiAgICBjb25zdCBleHBlY3RlZExlbmd0aCA9IGV4cGVjdGVkLmxlbmd0aDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZXhwZWN0ZWRMZW5ndGg7IGkrKykgewogICAgICBpZiAodGhpcy5tb2R1bGVCeXRlc1tiYXNlT2Zmc2V0ICsgaV0gIT09IGV4cGVjdGVkW2ldKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCAke2V4cGVjdGVkfSBhdCBvZmZzZXQgJHtiYXNlT2Zmc2V0fWApOwogICAgICB9CiAgICB9CiAgICB0aGlzLm9mZnNldCArPSBleHBlY3RlZExlbmd0aDsKICB9Cn07CmZ1bmN0aW9uIHBhcnNlTWFnaWNOdW1iZXIocGFyc2VTdGF0ZSkgewogIGNvbnN0IGV4cGVjdGVkID0gWzAsIDk3LCAxMTUsIDEwOV07CiAgcGFyc2VTdGF0ZS5hc3NlcnRCeXRlcyhleHBlY3RlZCk7Cn0KZnVuY3Rpb24gcGFyc2VWZXJzaW9uKHBhcnNlU3RhdGUpIHsKICBjb25zdCBleHBlY3RlZCA9IFsxLCAwLCAwLCAwXTsKICBwYXJzZVN0YXRlLmFzc2VydEJ5dGVzKGV4cGVjdGVkKTsKfQpmdW5jdGlvbiBwYXJzZVRhYmxlVHlwZShwYXJzZVN0YXRlKSB7CiAgY29uc3QgZWxlbWVudFR5cGUgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgbGV0IGVsZW1lbnQ7CiAgc3dpdGNoIChlbGVtZW50VHlwZSkgewogICAgY2FzZSAxMTI6CiAgICAgIGVsZW1lbnQgPSAiZnVuY3JlZiI7CiAgICAgIGJyZWFrOwogICAgY2FzZSAxMTE6CiAgICAgIGVsZW1lbnQgPSAiZXh0ZXJucmVmIjsKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gdGFibGUgZWxlbWVudCB0eXBlICR7ZWxlbWVudFR5cGV9YCk7CiAgfQogIGNvbnN0IHsgbWluaW11bSwgbWF4aW11bSB9ID0gcGFyc2VMaW1pdHMocGFyc2VTdGF0ZSk7CiAgaWYgKG1heGltdW0pIHsKICAgIHJldHVybiB7IGVsZW1lbnQsIG1pbmltdW0sIG1heGltdW0gfTsKICB9IGVsc2UgewogICAgcmV0dXJuIHsgZWxlbWVudCwgbWluaW11bSB9OwogIH0KfQpmdW5jdGlvbiBwYXJzZUxpbWl0cyhwYXJzZVN0YXRlKSB7CiAgY29uc3QgZmxhZ3MgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgY29uc3QgbWluaW11bSA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgY29uc3QgaGFzTWF4aW11bSA9IGZsYWdzICYgMTsKICBjb25zdCBzaGFyZWQgPSAoZmxhZ3MgJiAyKSAhPT0gMDsKICBjb25zdCBpc01lbW9yeTY0ID0gKGZsYWdzICYgNCkgIT09IDA7CiAgY29uc3QgaW5kZXggPSBpc01lbW9yeTY0ID8gImk2NCIgOiAiaTMyIjsKICBpZiAoaGFzTWF4aW11bSkgewogICAgY29uc3QgbWF4aW11bSA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgICByZXR1cm4geyBtaW5pbXVtLCBzaGFyZWQsIGluZGV4LCBtYXhpbXVtIH07CiAgfSBlbHNlIHsKICAgIHJldHVybiB7IG1pbmltdW0sIHNoYXJlZCwgaW5kZXggfTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VHbG9iYWxUeXBlKHBhcnNlU3RhdGUpIHsKICBjb25zdCB2YWx1ZSA9IHBhcnNlVmFsdWVUeXBlKHBhcnNlU3RhdGUpOwogIGNvbnN0IG11dGFibGUgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCkgPT09IDE7CiAgcmV0dXJuIHsgdmFsdWUsIG11dGFibGUgfTsKfQpmdW5jdGlvbiBwYXJzZVZhbHVlVHlwZShwYXJzZVN0YXRlKSB7CiAgY29uc3QgdHlwZSA9IHBhcnNlU3RhdGUucmVhZEJ5dGUoKTsKICBzd2l0Y2ggKHR5cGUpIHsKICAgIGNhc2UgMTI3OgogICAgICByZXR1cm4gImkzMiI7CiAgICBjYXNlIDEyNjoKICAgICAgcmV0dXJuICJpNjQiOwogICAgY2FzZSAxMjU6CiAgICAgIHJldHVybiAiZjMyIjsKICAgIGNhc2UgMTI0OgogICAgICByZXR1cm4gImY2NCI7CiAgICBjYXNlIDExMjoKICAgICAgcmV0dXJuICJmdW5jcmVmIjsKICAgIGNhc2UgMTExOgogICAgICByZXR1cm4gImV4dGVybnJlZiI7CiAgICBjYXNlIDEyMzoKICAgICAgcmV0dXJuICJ2MTI4IjsKICAgIGRlZmF1bHQ6CiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biB2YWx1ZSB0eXBlICR7dHlwZX1gKTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VGdW5jdGlvblR5cGUocGFyc2VTdGF0ZSkgewogIGNvbnN0IGZvcm0gPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgaWYgKGZvcm0gIT09IDk2KSB7CiAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGZ1bmN0aW9uIHR5cGUgZm9ybSAweDYwLCBnb3QgJHtmb3JtfWApOwogIH0KICBjb25zdCBwYXJhbWV0ZXJzID0gW107CiAgY29uc3QgcGFyYW1ldGVyQ291bnQgPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogIGZvciAobGV0IGkgPSAwOyBpIDwgcGFyYW1ldGVyQ291bnQ7IGkrKykgewogICAgcGFyYW1ldGVycy5wdXNoKHBhcnNlVmFsdWVUeXBlKHBhcnNlU3RhdGUpKTsKICB9CiAgY29uc3QgcmVzdWx0cyA9IFtdOwogIGNvbnN0IHJlc3VsdENvdW50ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICBmb3IgKGxldCBpID0gMDsgaSA8IHJlc3VsdENvdW50OyBpKyspIHsKICAgIHJlc3VsdHMucHVzaChwYXJzZVZhbHVlVHlwZShwYXJzZVN0YXRlKSk7CiAgfQogIHJldHVybiB7IHBhcmFtZXRlcnMsIHJlc3VsdHMgfTsKfQoKLy8gbm9kZV9tb2R1bGVzL3dhc20taW1wb3J0cy1wYXJzZXIvcG9seWZpbGwuanMKdmFyIGhhc1dhc21UeXBlUmVmbGVjdGlvblN1cHBvcnQgPSAoKCkgPT4gewogIGNvbnN0IG1vZHVsZUJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoWwogICAgMCwKICAgIDk3LAogICAgMTE1LAogICAgMTA5LAogICAgMSwKICAgIDAsCiAgICAwLAogICAgMCwKICAgIDIsCiAgICA2LAogICAgMSwKICAgIDAsCiAgICAwLAogICAgMiwKICAgIDAsCiAgICAxCiAgXSk7CiAgY29uc3QgbW9kdWxlID0gbmV3IFdlYkFzc2VtYmx5Lk1vZHVsZShtb2R1bGVCeXRlcyk7CiAgY29uc3QgaW1wb3J0cyA9IFdlYkFzc2VtYmx5Lk1vZHVsZS5pbXBvcnRzKG1vZHVsZSk7CiAgY29uc3QgbWVtb3J5SW1wb3J0ID0gaW1wb3J0c1swXTsKICByZXR1cm4gdHlwZW9mIG1lbW9yeUltcG9ydC50eXBlID09PSAib2JqZWN0IjsKfSkoKTsKZnVuY3Rpb24gcG9seWZpbGwoV2ViQXNzZW1ibHkzKSB7CiAgaWYgKGhhc1dhc21UeXBlUmVmbGVjdGlvblN1cHBvcnQpIHsKICAgIHJldHVybiBXZWJBc3NlbWJseTM7CiAgfQogIGNvbnN0IG5ld1dlYkFzc2VtYmx5ID0ge307CiAgZm9yIChjb25zdCBrZXkgaW4gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMoV2ViQXNzZW1ibHkzKSkgewogICAgbmV3V2ViQXNzZW1ibHlba2V5XSA9IFdlYkFzc2VtYmx5M1trZXldOwogIH0KICBjb25zdCBwb2x5ZmlsbGVkSW1wb3J0c1N5bWJvbCA9IFN5bWJvbCgicG9seWZpbGxlZEltcG9ydHNTeW1ib2wiKTsKICBjb25zdCBhc3NpZ25JbXBvcnRzID0gKG1vZHVsZSwgc291cmNlQnl0ZXMpID0+IHsKICAgIG1vZHVsZVtwb2x5ZmlsbGVkSW1wb3J0c1N5bWJvbF0gPSBwYXJzZUltcG9ydHMoc291cmNlQnl0ZXMpOwogIH07CiAgY29uc3QgbmV3TW9kdWxlID0gbmV3V2ViQXNzZW1ibHkuTW9kdWxlID0gZnVuY3Rpb24oYnl0ZXMpIHsKICAgIGNvbnN0IG1vZHVsZSA9IG5ldyBXZWJBc3NlbWJseTMuTW9kdWxlKGJ5dGVzKTsKICAgIGFzc2lnbkltcG9ydHMobW9kdWxlLCBieXRlcyk7CiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YobW9kdWxlLCBuZXdNb2R1bGUucHJvdG90eXBlKTsKICAgIHJldHVybiBtb2R1bGU7CiAgfTsKICBPYmplY3Quc2V0UHJvdG90eXBlT2YobmV3TW9kdWxlLnByb3RvdHlwZSwgV2ViQXNzZW1ibHkzLk1vZHVsZS5wcm90b3R5cGUpOwogIG5ld1dlYkFzc2VtYmx5LmNvbXBpbGUgPSBhc3luYyAoc291cmNlKSA9PiB7CiAgICBjb25zdCBtb2R1bGUgPSBhd2FpdCBXZWJBc3NlbWJseTMuY29tcGlsZShzb3VyY2UpOwogICAgYXNzaWduSW1wb3J0cyhtb2R1bGUsIHNvdXJjZSk7CiAgICByZXR1cm4gbW9kdWxlOwogIH07CiAgaWYgKFdlYkFzc2VtYmx5My5jb21waWxlU3RyZWFtaW5nKSB7CiAgICBuZXdXZWJBc3NlbWJseS5jb21waWxlU3RyZWFtaW5nID0gYXN5bmMgKHNvdXJjZSkgPT4gewogICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHNvdXJjZTsKICAgICAgY29uc3QgY2xvbmUgPSByZXNwb25zZS5jbG9uZSgpOwogICAgICBjb25zdCBtb2R1bGUgPSBhd2FpdCBXZWJBc3NlbWJseTMuY29tcGlsZVN0cmVhbWluZyhyZXNwb25zZSk7CiAgICAgIGFzc2lnbkltcG9ydHMobW9kdWxlLCBuZXcgVWludDhBcnJheShhd2FpdCBjbG9uZS5hcnJheUJ1ZmZlcigpKSk7CiAgICAgIHJldHVybiBtb2R1bGU7CiAgICB9OwogIH0KICBuZXdNb2R1bGUuaW1wb3J0cyA9IChtb2R1bGUpID0+IHsKICAgIGNvbnN0IHBhcnNlZEltcG9ydHMgPSBtb2R1bGVbcG9seWZpbGxlZEltcG9ydHNTeW1ib2xdOwogICAgaWYgKCFwYXJzZWRJbXBvcnRzKSB7CiAgICAgIHJldHVybiBXZWJBc3NlbWJseTMuTW9kdWxlLmltcG9ydHMobW9kdWxlKTsKICAgIH0KICAgIHJldHVybiBwYXJzZWRJbXBvcnRzOwogIH07CiAgcmV0dXJuIG5ld1dlYkFzc2VtYmx5Owp9CgovLyBlbnRyeXBvaW50L2ludHJpbnNpY3MudHMKdmFyIFdlYkFzc2VtYmx5MiA9IHBvbHlmaWxsKGdsb2JhbFRoaXMuV2ViQXNzZW1ibHkpOwp2YXIgTGluZURlY29kZXIgPSBjbGFzcyB7CiAgY29uc3RydWN0b3Iob25MaW5lKSB7CiAgICB0aGlzLmRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IiwgeyBmYXRhbDogZmFsc2UgfSk7CiAgICB0aGlzLmJ1ZmZlciA9ICIiOwogICAgdGhpcy5vbkxpbmUgPSBvbkxpbmU7CiAgfQogIGRlY29kZXI7CiAgYnVmZmVyOwogIG9uTGluZTsKICBzZW5kKGNodW5rKSB7CiAgICB0aGlzLmJ1ZmZlciArPSB0aGlzLmRlY29kZXIuZGVjb2RlKGNodW5rLCB7IHN0cmVhbTogdHJ1ZSB9KTsKICAgIGNvbnN0IGxpbmVzID0gdGhpcy5idWZmZXIuc3BsaXQoIlxuIik7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aCAtIDE7IGkrKykgewogICAgICB0aGlzLm9uTGluZShsaW5lc1tpXSk7CiAgICB9CiAgICB0aGlzLmJ1ZmZlciA9IGxpbmVzW2xpbmVzLmxlbmd0aCAtIDFdOwogIH0KfTsKYXN5bmMgZnVuY3Rpb24gaW5zdGFudGlhdGUocmF3T3B0aW9ucywgZXh0cmFXYXNtSW1wb3J0cykgewogIGNvbnN0IG9wdGlvbnMgPSBkZWZhdWx0SW5zdGFudGlhdGlvbk9wdGlvbnMocmF3T3B0aW9ucyk7CiAgbGV0IHN3aWZ0ID0gb3B0aW9ucy5zd2lmdDsKICBpZiAoIXN3aWZ0ICYmIG9wdGlvbnMuU3dpZnRSdW50aW1lKSB7CiAgICBzd2lmdCA9IG5ldyBvcHRpb25zLlN3aWZ0UnVudGltZSgpOwogIH0KICBsZXQgc3Rkb3V0TGluZSA9IHZvaWQgMDsKICBpZiAob3B0aW9ucy5vblN0ZG91dExpbmUgIT0gbnVsbCkgewogICAgc3Rkb3V0TGluZSA9IG5ldyBMaW5lRGVjb2RlcihvcHRpb25zLm9uU3Rkb3V0TGluZSk7CiAgfQogIGNvbnN0IHN0ZG91dCA9IG5ldyBDb25zb2xlU3Rkb3V0KChjaHVuaykgPT4gewogICAgb3B0aW9ucy5vblN0ZG91dD8uY2FsbCh2b2lkIDAsIGNodW5rKTsKICAgIHN0ZG91dExpbmU/LnNlbmQoY2h1bmspOwogIH0pOwogIGxldCBzdGRlcnJMaW5lID0gdm9pZCAwOwogIGlmIChvcHRpb25zLm9uU3RkZXJyTGluZSAhPSBudWxsKSB7CiAgICBzdGRlcnJMaW5lID0gbmV3IExpbmVEZWNvZGVyKG9wdGlvbnMub25TdGRlcnJMaW5lKTsKICB9CiAgY29uc3Qgc3RkZXJyID0gbmV3IENvbnNvbGVTdGRvdXQoKGNodW5rKSA9PiB7CiAgICBvcHRpb25zLm9uU3RkZXJyPy5jYWxsKHZvaWQgMCwgY2h1bmspOwogICAgc3RkZXJyTGluZT8uc2VuZChjaHVuayk7CiAgfSk7CiAgY29uc3QgYXJncyA9IG9wdGlvbnMuYXJncyB8fCBbXTsKICBjb25zdCBmZHMgPSBbCiAgICBuZXcgT3BlbkZpbGUobmV3IEZpbGUoW10pKSwKICAgIHN0ZG91dCwKICAgIHN0ZGVyciwKICAgIG5ldyBQcmVvcGVuRGlyZWN0b3J5KCIvIiwgLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKSkKICBdOwogIGNvbnN0IGVudnMgPSBvcHRpb25zLmVudiA/IE9iamVjdC5lbnRyaWVzKG9wdGlvbnMuZW52KS5tYXAoKFtrZXksIHZhbHVlXSkgPT4gYCR7a2V5fT0ke3ZhbHVlfWApIDogW107CiAgY29uc3Qgd2FzaSA9IG5ldyBXQVNJKGFyZ3MsIGVudnMsIGZkcywgewogICAgZGVidWc6IGZhbHNlCiAgfSk7CiAgY29uc3QgY3JlYXRlV2FzbUltcG9ydE9iamVjdCA9IChleHRyYVdhc21JbXBvcnRzMiwgbW9kdWxlKSA9PiB7CiAgICBjb25zdCBpbXBvcnRPYmplY3QyID0gewogICAgICB3YXNpX3NuYXBzaG90X3ByZXZpZXcxOiB3YXNpLndhc2lJbXBvcnQKICAgIH07CiAgICBpZiAoc3dpZnQpIHsKICAgICAgaW1wb3J0T2JqZWN0Mi5qYXZhc2NyaXB0X2tpdCA9IHN3aWZ0Lndhc21JbXBvcnRzOwogICAgfQogICAgaWYgKGV4dHJhV2FzbUltcG9ydHMyKSB7CiAgICAgIGZvciAoY29uc3QgbW9kdWxlTmFtZSBpbiBleHRyYVdhc21JbXBvcnRzMikgewogICAgICAgIGlmICghaW1wb3J0T2JqZWN0Mlttb2R1bGVOYW1lXSkgewogICAgICAgICAgaW1wb3J0T2JqZWN0Mlttb2R1bGVOYW1lXSA9IHt9OwogICAgICAgIH0KICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IGluIGV4dHJhV2FzbUltcG9ydHMyW21vZHVsZU5hbWVdKSB7CiAgICAgICAgICBpbXBvcnRPYmplY3QyW21vZHVsZU5hbWVdW2VudHJ5XSA9IGV4dHJhV2FzbUltcG9ydHMyW21vZHVsZU5hbWVdW2VudHJ5XTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGZvciAoY29uc3QgX2ltcG9ydEVudHJ5IG9mIFdlYkFzc2VtYmx5Mi5Nb2R1bGUuaW1wb3J0cyhtb2R1bGUpKSB7CiAgICAgIGNvbnN0IGltcG9ydEVudHJ5ID0gX2ltcG9ydEVudHJ5OwogICAgICBpZiAoIWltcG9ydE9iamVjdDJbaW1wb3J0RW50cnkubW9kdWxlXSkgewogICAgICAgIGltcG9ydE9iamVjdDJbaW1wb3J0RW50cnkubW9kdWxlXSA9IHt9OwogICAgICB9CiAgICAgIGlmIChpbXBvcnRPYmplY3QyW2ltcG9ydEVudHJ5Lm1vZHVsZV1baW1wb3J0RW50cnkubmFtZV0pIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoaW1wb3J0RW50cnkua2luZCA9PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgaW1wb3J0T2JqZWN0MltpbXBvcnRFbnRyeS5tb2R1bGVdW2ltcG9ydEVudHJ5Lm5hbWVdID0gKCkgPT4gewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbXBvcnRlZCBmdW5jdGlvbiAke2ltcG9ydEVudHJ5Lm1vZHVsZX0uJHtpbXBvcnRFbnRyeS5uYW1lfSBub3QgaW1wbGVtZW50ZWRgKTsKICAgICAgICB9OwogICAgICB9IGVsc2UgaWYgKGltcG9ydEVudHJ5LmtpbmQgPT0gIm1lbW9yeSIgJiYgaW1wb3J0RW50cnkubW9kdWxlID09ICJlbnYiICYmIGltcG9ydEVudHJ5Lm5hbWUgPT0gIm1lbW9yeSIpIHsKICAgICAgICBjb25zdCB0eXBlID0gaW1wb3J0RW50cnkudHlwZTsKICAgICAgICBjb25zdCBkZXNjcmlwdG9yID0gewogICAgICAgICAgaW5pdGlhbDogdHlwZS5taW5pbXVtLAogICAgICAgICAgbWF4aW11bTogdHlwZS5tYXhpbXVtLAogICAgICAgICAgc2hhcmVkOiB0eXBlLnNoYXJlZAogICAgICAgIH07CiAgICAgICAgaW1wb3J0T2JqZWN0MltpbXBvcnRFbnRyeS5tb2R1bGVdW2ltcG9ydEVudHJ5Lm5hbWVdID0gbmV3IFdlYkFzc2VtYmx5Mi5NZW1vcnkoZGVzY3JpcHRvcik7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBpbXBvcnRPYmplY3QyOwogIH07CiAgY29uc3QgaW1wb3J0T2JqZWN0ID0gY3JlYXRlV2FzbUltcG9ydE9iamVjdChleHRyYVdhc21JbXBvcnRzLCBvcHRpb25zLm1vZHVsZSk7CiAgY29uc3QgaW5zdGFuY2UgPSBhd2FpdCBXZWJBc3NlbWJseTIuaW5zdGFudGlhdGUob3B0aW9ucy5tb2R1bGUsIGltcG9ydE9iamVjdCk7CiAgaWYgKHN3aWZ0ICYmIGluc3RhbmNlLmV4cG9ydHMuc3dqc19saWJyYXJ5X3ZlcnNpb24pIHsKICAgIHN3aWZ0LnNldEluc3RhbmNlKGluc3RhbmNlKTsKICB9CiAgaWYgKHR5cGVvZiBpbnN0YW5jZS5leHBvcnRzLl9zdGFydCA9PT0gImZ1bmN0aW9uIikgewogICAgd2FzaS5zdGFydChpbnN0YW5jZSk7CiAgfSBlbHNlIGlmICh0eXBlb2YgaW5zdGFuY2UuZXhwb3J0cy5faW5pdGlhbGl6ZSA9PSAiZnVuY3Rpb24iKSB7CiAgICB3YXNpLmluaXRpYWxpemUoaW5zdGFuY2UpOwogICAgaWYgKHN3aWZ0ICYmIHN3aWZ0Lm1haW4pIHsKICAgICAgc3dpZnQubWFpbigpOwogICAgfSBlbHNlIHsKICAgICAgaWYgKHR5cGVvZiBpbnN0YW5jZS5leHBvcnRzLm1haW4gPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICBpbnN0YW5jZS5leHBvcnRzLm1haW4oKTsKICAgICAgfSBlbHNlIGlmICh0eXBlb2YgaW5zdGFuY2UuZXhwb3J0cy5fX21haW5fYXJnY19hcmd2ID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgaW5zdGFuY2UuZXhwb3J0cy5fX21haW5fYXJnY19hcmd2KDAsIDApOwogICAgICB9CiAgICB9CiAgfQogIHJldHVybiB7IGluc3RhbmNlIH07Cn0KZnVuY3Rpb24gZGVmYXVsdEluc3RhbnRpYXRpb25PcHRpb25zKG9wdGlvbnMpIHsKICBpZiAob3B0aW9ucy5hcmdzID09IG51bGwpIHsKICAgIG9wdGlvbnMuYXJncyA9IFsibWFpbi53YXNtIl07CiAgfQogIGNvbnN0IGlzTm9kZUpzID0gdHlwZW9mIHByb2Nlc3MgIT09ICJ1bmRlZmluZWQiICYmIHByb2Nlc3MucmVsZWFzZS5uYW1lID09PSAibm9kZSI7CiAgY29uc3QgaXNXZWJCcm93c2VyID0gdHlwZW9mIHdpbmRvdyAhPT0gInVuZGVmaW5lZCI7CiAgaWYgKGlzTm9kZUpzKSB7CiAgICBpZiAoIW9wdGlvbnMub25TdGRvdXQpIHsKICAgICAgb3B0aW9ucy5vblN0ZG91dCA9IChjaHVuaykgPT4gcHJvY2Vzcy5zdGRvdXQud3JpdGUoY2h1bmspOwogICAgfQogICAgaWYgKCFvcHRpb25zLm9uU3RkZXJyKSB7CiAgICAgIG9wdGlvbnMub25TdGRlcnIgPSAoY2h1bmspID0+IHByb2Nlc3Muc3RkZXJyLndyaXRlKGNodW5rKTsKICAgIH0KICB9IGVsc2UgaWYgKGlzV2ViQnJvd3NlcikgewogICAgaWYgKCFvcHRpb25zLm9uU3Rkb3V0TGluZSkgewogICAgICBvcHRpb25zLm9uU3Rkb3V0TGluZSA9IChsaW5lKSA9PiBjb25zb2xlLmxvZyhsaW5lKTsKICAgIH0KICAgIGlmICghb3B0aW9ucy5vblN0ZGVyckxpbmUpIHsKICAgICAgb3B0aW9ucy5vblN0ZGVyckxpbmUgPSAobGluZSkgPT4gY29uc29sZS53YXJuKGxpbmUpOwogICAgfQogIH0KICByZXR1cm4gb3B0aW9uczsKfQoKLy8gZW50cnlwb2ludC9idW5kbGUudHMKdmFyIHN0YXJ0V2FzaVRhc2sgPSBhc3luYyAoKSA9PiB7CiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCgiUkVQTEFDRV9USElTX1dJVEhfVEhFX01BSU5fV0VCQVNTRU1CTFlfTU9EVUxFIik7CiAgbGV0IHJ1bnRpbWVDb25zdHJ1Y3RvciA9IHZvaWQgMDsKICB0cnkgewogICAgY29uc3QgeyBTd2lmdFJ1bnRpbWUgfSA9IGF3YWl0IGltcG9ydCgKICAgICAgLy8gQHRzLWlnbm9yZQogICAgICAiLi9KYXZhU2NyaXB0S2l0X0phdmFTY3JpcHRLaXQucmVzb3VyY2VzL1J1bnRpbWUvaW5kZXgubWpzIgogICAgKTsKICAgIHJ1bnRpbWVDb25zdHJ1Y3RvciA9IFN3aWZ0UnVudGltZTsKICB9IGNhdGNoIHsKICB9CiAgYXdhaXQgaW5zdGFudGlhdGUoewogICAgbW9kdWxlOiBhd2FpdCBXZWJBc3NlbWJseTIuY29tcGlsZVN0cmVhbWluZyhyZXNwb25zZSksCiAgICBvblN0ZG91dExpbmUobGluZSkgewogICAgICBjb25zb2xlLmxvZyhsaW5lKTsKICAgIH0sCiAgICBvblN0ZGVyckxpbmUobGluZSkgewogICAgICBjb25zb2xlLmVycm9yKGxpbmUpOwogICAgfSwKICAgIFN3aWZ0UnVudGltZTogcnVudGltZUNvbnN0cnVjdG9yCiAgfSk7Cn07CmFzeW5jIGZ1bmN0aW9uIG1haW4oKSB7CiAgYXdhaXQgc3RhcnRXYXNpVGFzaygpOwp9Cm1haW4oKTsK")! + public static let intrinsics: Data = Data(base64Encoded: "Ly8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC93YXNpX2RlZnMuanMKdmFyIENMT0NLSURfUkVBTFRJTUUgPSAwOwp2YXIgQ0xPQ0tJRF9NT05PVE9OSUMgPSAxOwp2YXIgRVJSTk9fU1VDQ0VTUyA9IDA7CnZhciBFUlJOT19CQURGID0gODsKdmFyIEVSUk5PX0VYSVNUID0gMjA7CnZhciBFUlJOT19JTlZBTCA9IDI4Owp2YXIgRVJSTk9fSVNESVIgPSAzMTsKdmFyIEVSUk5PX05BTUVUT09MT05HID0gMzc7CnZhciBFUlJOT19OT0VOVCA9IDQ0Owp2YXIgRVJSTk9fTk9TWVMgPSA1MjsKdmFyIEVSUk5PX05PVERJUiA9IDU0Owp2YXIgRVJSTk9fTk9URU1QVFkgPSA1NTsKdmFyIEVSUk5PX05PVFNVUCA9IDU4Owp2YXIgRVJSTk9fUEVSTSA9IDYzOwp2YXIgRVJSTk9fTk9UQ0FQQUJMRSA9IDc2Owp2YXIgUklHSFRTX0ZEX0RBVEFTWU5DID0gMSA8PCAwOwp2YXIgUklHSFRTX0ZEX1JFQUQgPSAxIDw8IDE7CnZhciBSSUdIVFNfRkRfU0VFSyA9IDEgPDwgMjsKdmFyIFJJR0hUU19GRF9GRFNUQVRfU0VUX0ZMQUdTID0gMSA8PCAzOwp2YXIgUklHSFRTX0ZEX1NZTkMgPSAxIDw8IDQ7CnZhciBSSUdIVFNfRkRfVEVMTCA9IDEgPDwgNTsKdmFyIFJJR0hUU19GRF9XUklURSA9IDEgPDwgNjsKdmFyIFJJR0hUU19GRF9BRFZJU0UgPSAxIDw8IDc7CnZhciBSSUdIVFNfRkRfQUxMT0NBVEUgPSAxIDw8IDg7CnZhciBSSUdIVFNfUEFUSF9DUkVBVEVfRElSRUNUT1JZID0gMSA8PCA5Owp2YXIgUklHSFRTX1BBVEhfQ1JFQVRFX0ZJTEUgPSAxIDw8IDEwOwp2YXIgUklHSFRTX1BBVEhfTElOS19TT1VSQ0UgPSAxIDw8IDExOwp2YXIgUklHSFRTX1BBVEhfTElOS19UQVJHRVQgPSAxIDw8IDEyOwp2YXIgUklHSFRTX1BBVEhfT1BFTiA9IDEgPDwgMTM7CnZhciBSSUdIVFNfRkRfUkVBRERJUiA9IDEgPDwgMTQ7CnZhciBSSUdIVFNfUEFUSF9SRUFETElOSyA9IDEgPDwgMTU7CnZhciBSSUdIVFNfUEFUSF9SRU5BTUVfU09VUkNFID0gMSA8PCAxNjsKdmFyIFJJR0hUU19QQVRIX1JFTkFNRV9UQVJHRVQgPSAxIDw8IDE3Owp2YXIgUklHSFRTX1BBVEhfRklMRVNUQVRfR0VUID0gMSA8PCAxODsKdmFyIFJJR0hUU19QQVRIX0ZJTEVTVEFUX1NFVF9TSVpFID0gMSA8PCAxOTsKdmFyIFJJR0hUU19QQVRIX0ZJTEVTVEFUX1NFVF9USU1FUyA9IDEgPDwgMjA7CnZhciBSSUdIVFNfRkRfRklMRVNUQVRfR0VUID0gMSA8PCAyMTsKdmFyIFJJR0hUU19GRF9GSUxFU1RBVF9TRVRfU0laRSA9IDEgPDwgMjI7CnZhciBSSUdIVFNfRkRfRklMRVNUQVRfU0VUX1RJTUVTID0gMSA8PCAyMzsKdmFyIFJJR0hUU19QQVRIX1NZTUxJTksgPSAxIDw8IDI0Owp2YXIgUklHSFRTX1BBVEhfUkVNT1ZFX0RJUkVDVE9SWSA9IDEgPDwgMjU7CnZhciBSSUdIVFNfUEFUSF9VTkxJTktfRklMRSA9IDEgPDwgMjY7CnZhciBSSUdIVFNfUE9MTF9GRF9SRUFEV1JJVEUgPSAxIDw8IDI3Owp2YXIgUklHSFRTX1NPQ0tfU0hVVERPV04gPSAxIDw8IDI4Owp2YXIgSW92ZWMgPSBjbGFzcyB7CiAgc3RhdGljIHJlYWRfYnl0ZXModmlldywgcHRyKSB7CiAgICBjb25zdCBpb3ZlYyA9IG5ldyBJb3ZlYygpOwogICAgaW92ZWMuYnVmID0gdmlldy5nZXRVaW50MzIocHRyLCB0cnVlKTsKICAgIGlvdmVjLmJ1Zl9sZW4gPSB2aWV3LmdldFVpbnQzMihwdHIgKyA0LCB0cnVlKTsKICAgIHJldHVybiBpb3ZlYzsKICB9CiAgc3RhdGljIHJlYWRfYnl0ZXNfYXJyYXkodmlldywgcHRyLCBsZW4pIHsKICAgIGNvbnN0IGlvdmVjcyA9IFtdOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgICBpb3ZlY3MucHVzaChJb3ZlYy5yZWFkX2J5dGVzKHZpZXcsIHB0ciArIDggKiBpKSk7CiAgICB9CiAgICByZXR1cm4gaW92ZWNzOwogIH0KfTsKdmFyIENpb3ZlYyA9IGNsYXNzIHsKICBzdGF0aWMgcmVhZF9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIGNvbnN0IGlvdmVjID0gbmV3IENpb3ZlYygpOwogICAgaW92ZWMuYnVmID0gdmlldy5nZXRVaW50MzIocHRyLCB0cnVlKTsKICAgIGlvdmVjLmJ1Zl9sZW4gPSB2aWV3LmdldFVpbnQzMihwdHIgKyA0LCB0cnVlKTsKICAgIHJldHVybiBpb3ZlYzsKICB9CiAgc3RhdGljIHJlYWRfYnl0ZXNfYXJyYXkodmlldywgcHRyLCBsZW4pIHsKICAgIGNvbnN0IGlvdmVjcyA9IFtdOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgICBpb3ZlY3MucHVzaChDaW92ZWMucmVhZF9ieXRlcyh2aWV3LCBwdHIgKyA4ICogaSkpOwogICAgfQogICAgcmV0dXJuIGlvdmVjczsKICB9Cn07CnZhciBXSEVOQ0VfU0VUID0gMDsKdmFyIFdIRU5DRV9DVVIgPSAxOwp2YXIgV0hFTkNFX0VORCA9IDI7CnZhciBGSUxFVFlQRV9DSEFSQUNURVJfREVWSUNFID0gMjsKdmFyIEZJTEVUWVBFX0RJUkVDVE9SWSA9IDM7CnZhciBGSUxFVFlQRV9SRUdVTEFSX0ZJTEUgPSA0Owp2YXIgRGlyZW50ID0gY2xhc3MgewogIGhlYWRfbGVuZ3RoKCkgewogICAgcmV0dXJuIDI0OwogIH0KICBuYW1lX2xlbmd0aCgpIHsKICAgIHJldHVybiB0aGlzLmRpcl9uYW1lLmJ5dGVMZW5ndGg7CiAgfQogIHdyaXRlX2hlYWRfYnl0ZXModmlldywgcHRyKSB7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIsIHRoaXMuZF9uZXh0LCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDgsIHRoaXMuZF9pbm8sIHRydWUpOwogICAgdmlldy5zZXRVaW50MzIocHRyICsgMTYsIHRoaXMuZGlyX25hbWUubGVuZ3RoLCB0cnVlKTsKICAgIHZpZXcuc2V0VWludDgocHRyICsgMjAsIHRoaXMuZF90eXBlKTsKICB9CiAgd3JpdGVfbmFtZV9ieXRlcyh2aWV3OCwgcHRyLCBidWZfbGVuKSB7CiAgICB2aWV3OC5zZXQodGhpcy5kaXJfbmFtZS5zbGljZSgwLCBNYXRoLm1pbih0aGlzLmRpcl9uYW1lLmJ5dGVMZW5ndGgsIGJ1Zl9sZW4pKSwgcHRyKTsKICB9CiAgY29uc3RydWN0b3IobmV4dF9jb29raWUsIG5hbWUsIHR5cGUpIHsKICAgIHRoaXMuZF9pbm8gPSAwbjsKICAgIGNvbnN0IGVuY29kZWRfbmFtZSA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShuYW1lKTsKICAgIHRoaXMuZF9uZXh0ID0gbmV4dF9jb29raWU7CiAgICB0aGlzLmRfbmFtbGVuID0gZW5jb2RlZF9uYW1lLmJ5dGVMZW5ndGg7CiAgICB0aGlzLmRfdHlwZSA9IHR5cGU7CiAgICB0aGlzLmRpcl9uYW1lID0gZW5jb2RlZF9uYW1lOwogIH0KfTsKdmFyIEZERkxBR1NfQVBQRU5EID0gMSA8PCAwOwp2YXIgRkRGTEFHU19EU1lOQyA9IDEgPDwgMTsKdmFyIEZERkxBR1NfTk9OQkxPQ0sgPSAxIDw8IDI7CnZhciBGREZMQUdTX1JTWU5DID0gMSA8PCAzOwp2YXIgRkRGTEFHU19TWU5DID0gMSA8PCA0Owp2YXIgRmRzdGF0ID0gY2xhc3MgewogIHdyaXRlX2J5dGVzKHZpZXcsIHB0cikgewogICAgdmlldy5zZXRVaW50OChwdHIsIHRoaXMuZnNfZmlsZXR5cGUpOwogICAgdmlldy5zZXRVaW50MTYocHRyICsgMiwgdGhpcy5mc19mbGFncywgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA4LCB0aGlzLmZzX3JpZ2h0c19iYXNlLCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDE2LCB0aGlzLmZzX3JpZ2h0c19pbmhlcml0ZWQsIHRydWUpOwogIH0KICBjb25zdHJ1Y3RvcihmaWxldHlwZSwgZmxhZ3MpIHsKICAgIHRoaXMuZnNfcmlnaHRzX2Jhc2UgPSAwbjsKICAgIHRoaXMuZnNfcmlnaHRzX2luaGVyaXRlZCA9IDBuOwogICAgdGhpcy5mc19maWxldHlwZSA9IGZpbGV0eXBlOwogICAgdGhpcy5mc19mbGFncyA9IGZsYWdzOwogIH0KfTsKdmFyIEZTVEZMQUdTX0FUSU0gPSAxIDw8IDA7CnZhciBGU1RGTEFHU19BVElNX05PVyA9IDEgPDwgMTsKdmFyIEZTVEZMQUdTX01USU0gPSAxIDw8IDI7CnZhciBGU1RGTEFHU19NVElNX05PVyA9IDEgPDwgMzsKdmFyIE9GTEFHU19DUkVBVCA9IDEgPDwgMDsKdmFyIE9GTEFHU19ESVJFQ1RPUlkgPSAxIDw8IDE7CnZhciBPRkxBR1NfRVhDTCA9IDEgPDwgMjsKdmFyIE9GTEFHU19UUlVOQyA9IDEgPDwgMzsKdmFyIEZpbGVzdGF0ID0gY2xhc3MgewogIHdyaXRlX2J5dGVzKHZpZXcsIHB0cikgewogICAgdmlldy5zZXRCaWdVaW50NjQocHRyLCB0aGlzLmRldiwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA4LCB0aGlzLmlubywgdHJ1ZSk7CiAgICB2aWV3LnNldFVpbnQ4KHB0ciArIDE2LCB0aGlzLmZpbGV0eXBlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDI0LCB0aGlzLm5saW5rLCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDMyLCB0aGlzLnNpemUsIHRydWUpOwogICAgdmlldy5zZXRCaWdVaW50NjQocHRyICsgMzgsIHRoaXMuYXRpbSwgdHJ1ZSk7CiAgICB2aWV3LnNldEJpZ1VpbnQ2NChwdHIgKyA0NiwgdGhpcy5tdGltLCB0cnVlKTsKICAgIHZpZXcuc2V0QmlnVWludDY0KHB0ciArIDUyLCB0aGlzLmN0aW0sIHRydWUpOwogIH0KICBjb25zdHJ1Y3RvcihmaWxldHlwZSwgc2l6ZSkgewogICAgdGhpcy5kZXYgPSAwbjsKICAgIHRoaXMuaW5vID0gMG47CiAgICB0aGlzLm5saW5rID0gMG47CiAgICB0aGlzLmF0aW0gPSAwbjsKICAgIHRoaXMubXRpbSA9IDBuOwogICAgdGhpcy5jdGltID0gMG47CiAgICB0aGlzLmZpbGV0eXBlID0gZmlsZXR5cGU7CiAgICB0aGlzLnNpemUgPSBzaXplOwogIH0KfTsKdmFyIEVWRU5UUldGTEFHU19GRF9SRUFEV1JJVEVfSEFOR1VQID0gMSA8PCAwOwp2YXIgU1VCQ0xPQ0tGTEFHU19TVUJTQ1JJUFRJT05fQ0xPQ0tfQUJTVElNRSA9IDEgPDwgMDsKdmFyIFJJRkxBR1NfUkVDVl9QRUVLID0gMSA8PCAwOwp2YXIgUklGTEFHU19SRUNWX1dBSVRBTEwgPSAxIDw8IDE7CnZhciBST0ZMQUdTX1JFQ1ZfREFUQV9UUlVOQ0FURUQgPSAxIDw8IDA7CnZhciBTREZMQUdTX1JEID0gMSA8PCAwOwp2YXIgU0RGTEFHU19XUiA9IDEgPDwgMTsKdmFyIFBSRU9QRU5UWVBFX0RJUiA9IDA7CnZhciBQcmVzdGF0RGlyID0gY2xhc3MgewogIHdyaXRlX2J5dGVzKHZpZXcsIHB0cikgewogICAgdmlldy5zZXRVaW50MzIocHRyLCB0aGlzLnByX25hbWUuYnl0ZUxlbmd0aCwgdHJ1ZSk7CiAgfQogIGNvbnN0cnVjdG9yKG5hbWUpIHsKICAgIHRoaXMucHJfbmFtZSA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShuYW1lKTsKICB9Cn07CnZhciBQcmVzdGF0ID0gY2xhc3MgewogIHN0YXRpYyBkaXIobmFtZSkgewogICAgY29uc3QgcHJlc3RhdCA9IG5ldyBQcmVzdGF0KCk7CiAgICBwcmVzdGF0LnRhZyA9IFBSRU9QRU5UWVBFX0RJUjsKICAgIHByZXN0YXQuaW5uZXIgPSBuZXcgUHJlc3RhdERpcihuYW1lKTsKICAgIHJldHVybiBwcmVzdGF0OwogIH0KICB3cml0ZV9ieXRlcyh2aWV3LCBwdHIpIHsKICAgIHZpZXcuc2V0VWludDMyKHB0ciwgdGhpcy50YWcsIHRydWUpOwogICAgdGhpcy5pbm5lci53cml0ZV9ieXRlcyh2aWV3LCBwdHIgKyA0KTsKICB9Cn07CgovLyBub2RlX21vZHVsZXMvQGJqb3JuMy9icm93c2VyX3dhc2lfc2hpbS9kaXN0L2RlYnVnLmpzCnZhciBEZWJ1ZyA9IGNsYXNzIERlYnVnMiB7CiAgZW5hYmxlKGVuYWJsZWQpIHsKICAgIHRoaXMubG9nID0gY3JlYXRlTG9nZ2VyKGVuYWJsZWQgPT09IHZvaWQgMCA/IHRydWUgOiBlbmFibGVkLCB0aGlzLnByZWZpeCk7CiAgfQogIGdldCBlbmFibGVkKCkgewogICAgcmV0dXJuIHRoaXMuaXNFbmFibGVkOwogIH0KICBjb25zdHJ1Y3Rvcihpc0VuYWJsZWQpIHsKICAgIHRoaXMuaXNFbmFibGVkID0gaXNFbmFibGVkOwogICAgdGhpcy5wcmVmaXggPSAid2FzaToiOwogICAgdGhpcy5lbmFibGUoaXNFbmFibGVkKTsKICB9Cn07CmZ1bmN0aW9uIGNyZWF0ZUxvZ2dlcihlbmFibGVkLCBwcmVmaXgpIHsKICBpZiAoZW5hYmxlZCkgewogICAgY29uc3QgYSA9IGNvbnNvbGUubG9nLmJpbmQoY29uc29sZSwgIiVjJXMiLCAiY29sb3I6ICMyNjVCQTAiLCBwcmVmaXgpOwogICAgcmV0dXJuIGE7CiAgfSBlbHNlIHsKICAgIHJldHVybiAoKSA9PiB7CiAgICB9OwogIH0KfQp2YXIgZGVidWcgPSBuZXcgRGVidWcoZmFsc2UpOwoKLy8gbm9kZV9tb2R1bGVzL0Biam9ybjMvYnJvd3Nlcl93YXNpX3NoaW0vZGlzdC93YXNpLmpzCnZhciBXQVNJUHJvY0V4aXQgPSBjbGFzcyBleHRlbmRzIEVycm9yIHsKICBjb25zdHJ1Y3Rvcihjb2RlKSB7CiAgICBzdXBlcigiZXhpdCB3aXRoIGV4aXQgY29kZSAiICsgY29kZSk7CiAgICB0aGlzLmNvZGUgPSBjb2RlOwogIH0KfTsKdmFyIFdBU0kgPSBjbGFzcyBXQVNJMiB7CiAgc3RhcnQoaW5zdGFuY2UpIHsKICAgIHRoaXMuaW5zdCA9IGluc3RhbmNlOwogICAgdHJ5IHsKICAgICAgaW5zdGFuY2UuZXhwb3J0cy5fc3RhcnQoKTsKICAgICAgcmV0dXJuIDA7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIGlmIChlIGluc3RhbmNlb2YgV0FTSVByb2NFeGl0KSB7CiAgICAgICAgcmV0dXJuIGUuY29kZTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aHJvdyBlOwogICAgICB9CiAgICB9CiAgfQogIGluaXRpYWxpemUoaW5zdGFuY2UpIHsKICAgIHRoaXMuaW5zdCA9IGluc3RhbmNlOwogICAgaWYgKGluc3RhbmNlLmV4cG9ydHMuX2luaXRpYWxpemUpIHsKICAgICAgaW5zdGFuY2UuZXhwb3J0cy5faW5pdGlhbGl6ZSgpOwogICAgfQogIH0KICBjb25zdHJ1Y3RvcihhcmdzLCBlbnYsIGZkcywgb3B0aW9ucyA9IHt9KSB7CiAgICB0aGlzLmFyZ3MgPSBbXTsKICAgIHRoaXMuZW52ID0gW107CiAgICB0aGlzLmZkcyA9IFtdOwogICAgZGVidWcuZW5hYmxlKG9wdGlvbnMuZGVidWcpOwogICAgdGhpcy5hcmdzID0gYXJnczsKICAgIHRoaXMuZW52ID0gZW52OwogICAgdGhpcy5mZHMgPSBmZHM7CiAgICBjb25zdCBzZWxmID0gdGhpczsKICAgIHRoaXMud2FzaUltcG9ydCA9IHsgYXJnc19zaXplc19nZXQoYXJnYywgYXJndl9idWZfc2l6ZSkgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYXJnYywgc2VsZi5hcmdzLmxlbmd0aCwgdHJ1ZSk7CiAgICAgIGxldCBidWZfc2l6ZSA9IDA7CiAgICAgIGZvciAoY29uc3QgYXJnIG9mIHNlbGYuYXJncykgewogICAgICAgIGJ1Zl9zaXplICs9IGFyZy5sZW5ndGggKyAxOwogICAgICB9CiAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYXJndl9idWZfc2l6ZSwgYnVmX3NpemUsIHRydWUpOwogICAgICBkZWJ1Zy5sb2coYnVmZmVyLmdldFVpbnQzMihhcmdjLCB0cnVlKSwgYnVmZmVyLmdldFVpbnQzMihhcmd2X2J1Zl9zaXplLCB0cnVlKSk7CiAgICAgIHJldHVybiAwOwogICAgfSwgYXJnc19nZXQoYXJndiwgYXJndl9idWYpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IG9yaWdfYXJndl9idWYgPSBhcmd2X2J1ZjsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxmLmFyZ3MubGVuZ3RoOyBpKyspIHsKICAgICAgICBidWZmZXIuc2V0VWludDMyKGFyZ3YsIGFyZ3ZfYnVmLCB0cnVlKTsKICAgICAgICBhcmd2ICs9IDQ7CiAgICAgICAgY29uc3QgYXJnID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHNlbGYuYXJnc1tpXSk7CiAgICAgICAgYnVmZmVyOC5zZXQoYXJnLCBhcmd2X2J1Zik7CiAgICAgICAgYnVmZmVyLnNldFVpbnQ4KGFyZ3ZfYnVmICsgYXJnLmxlbmd0aCwgMCk7CiAgICAgICAgYXJndl9idWYgKz0gYXJnLmxlbmd0aCArIDE7CiAgICAgIH0KICAgICAgaWYgKGRlYnVnLmVuYWJsZWQpIHsKICAgICAgICBkZWJ1Zy5sb2cobmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG9yaWdfYXJndl9idWYsIGFyZ3ZfYnVmKSkpOwogICAgICB9CiAgICAgIHJldHVybiAwOwogICAgfSwgZW52aXJvbl9zaXplc19nZXQoZW52aXJvbl9jb3VudCwgZW52aXJvbl9zaXplKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgYnVmZmVyLnNldFVpbnQzMihlbnZpcm9uX2NvdW50LCBzZWxmLmVudi5sZW5ndGgsIHRydWUpOwogICAgICBsZXQgYnVmX3NpemUgPSAwOwogICAgICBmb3IgKGNvbnN0IGVudmlyb24gb2Ygc2VsZi5lbnYpIHsKICAgICAgICBidWZfc2l6ZSArPSBlbnZpcm9uLmxlbmd0aCArIDE7CiAgICAgIH0KICAgICAgYnVmZmVyLnNldFVpbnQzMihlbnZpcm9uX3NpemUsIGJ1Zl9zaXplLCB0cnVlKTsKICAgICAgZGVidWcubG9nKGJ1ZmZlci5nZXRVaW50MzIoZW52aXJvbl9jb3VudCwgdHJ1ZSksIGJ1ZmZlci5nZXRVaW50MzIoZW52aXJvbl9zaXplLCB0cnVlKSk7CiAgICAgIHJldHVybiAwOwogICAgfSwgZW52aXJvbl9nZXQoZW52aXJvbiwgZW52aXJvbl9idWYpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IG9yaWdfZW52aXJvbl9idWYgPSBlbnZpcm9uX2J1ZjsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxmLmVudi5sZW5ndGg7IGkrKykgewogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIoZW52aXJvbiwgZW52aXJvbl9idWYsIHRydWUpOwogICAgICAgIGVudmlyb24gKz0gNDsKICAgICAgICBjb25zdCBlID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHNlbGYuZW52W2ldKTsKICAgICAgICBidWZmZXI4LnNldChlLCBlbnZpcm9uX2J1Zik7CiAgICAgICAgYnVmZmVyLnNldFVpbnQ4KGVudmlyb25fYnVmICsgZS5sZW5ndGgsIDApOwogICAgICAgIGVudmlyb25fYnVmICs9IGUubGVuZ3RoICsgMTsKICAgICAgfQogICAgICBpZiAoZGVidWcuZW5hYmxlZCkgewogICAgICAgIGRlYnVnLmxvZyhuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2Uob3JpZ19lbnZpcm9uX2J1ZiwgZW52aXJvbl9idWYpKSk7CiAgICAgIH0KICAgICAgcmV0dXJuIDA7CiAgICB9LCBjbG9ja19yZXNfZ2V0KGlkLCByZXNfcHRyKSB7CiAgICAgIGxldCByZXNvbHV0aW9uVmFsdWU7CiAgICAgIHN3aXRjaCAoaWQpIHsKICAgICAgICBjYXNlIENMT0NLSURfTU9OT1RPTklDOiB7CiAgICAgICAgICByZXNvbHV0aW9uVmFsdWUgPSA1MDAwbjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjYXNlIENMT0NLSURfUkVBTFRJTUU6IHsKICAgICAgICAgIHJlc29sdXRpb25WYWx1ZSA9IDEwMDAwMDBuOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICByZXR1cm4gRVJSTk9fTk9TWVM7CiAgICAgIH0KICAgICAgY29uc3QgdmlldyA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgdmlldy5zZXRCaWdVaW50NjQocmVzX3B0ciwgcmVzb2x1dGlvblZhbHVlLCB0cnVlKTsKICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICB9LCBjbG9ja190aW1lX2dldChpZCwgcHJlY2lzaW9uLCB0aW1lKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKGlkID09PSBDTE9DS0lEX1JFQUxUSU1FKSB7CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NCh0aW1lLCBCaWdJbnQobmV3IERhdGUoKS5nZXRUaW1lKCkpICogMTAwMDAwMG4sIHRydWUpOwogICAgICB9IGVsc2UgaWYgKGlkID09IENMT0NLSURfTU9OT1RPTklDKSB7CiAgICAgICAgbGV0IG1vbm90b25pY190aW1lOwogICAgICAgIHRyeSB7CiAgICAgICAgICBtb25vdG9uaWNfdGltZSA9IEJpZ0ludChNYXRoLnJvdW5kKHBlcmZvcm1hbmNlLm5vdygpICogMWU2KSk7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgbW9ub3RvbmljX3RpbWUgPSAwbjsKICAgICAgICB9CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NCh0aW1lLCBtb25vdG9uaWNfdGltZSwgdHJ1ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NCh0aW1lLCAwbiwgdHJ1ZSk7CiAgICAgIH0KICAgICAgcmV0dXJuIDA7CiAgICB9LCBmZF9hZHZpc2UoZmQsIG9mZnNldCwgbGVuLCBhZHZpY2UpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfYWxsb2NhdGUoZmQsIG9mZnNldCwgbGVuKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9hbGxvY2F0ZShvZmZzZXQsIGxlbik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Nsb3NlKGZkKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcmV0ID0gc2VsZi5mZHNbZmRdLmZkX2Nsb3NlKCk7CiAgICAgICAgc2VsZi5mZHNbZmRdID0gdm9pZCAwOwogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2RhdGFzeW5jKGZkKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9zeW5jKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Zkc3RhdF9nZXQoZmQsIGZkc3RhdF9wdHIpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgZmRzdGF0IH0gPSBzZWxmLmZkc1tmZF0uZmRfZmRzdGF0X2dldCgpOwogICAgICAgIGlmIChmZHN0YXQgIT0gbnVsbCkgewogICAgICAgICAgZmRzdGF0LndyaXRlX2J5dGVzKG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKSwgZmRzdGF0X3B0cik7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2Zkc3RhdF9zZXRfZmxhZ3MoZmQsIGZsYWdzKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9mZHN0YXRfc2V0X2ZsYWdzKGZsYWdzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfZmRzdGF0X3NldF9yaWdodHMoZmQsIGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZykgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfZmRzdGF0X3NldF9yaWdodHMoZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfZmlsZXN0YXRfZ2V0KGZkLCBmaWxlc3RhdF9wdHIpIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgZmlsZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9maWxlc3RhdF9nZXQoKTsKICAgICAgICBpZiAoZmlsZXN0YXQgIT0gbnVsbCkgewogICAgICAgICAgZmlsZXN0YXQud3JpdGVfYnl0ZXMobmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpLCBmaWxlc3RhdF9wdHIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9maWxlc3RhdF9zZXRfc2l6ZShmZCwgc2l6ZSkgewogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0uZmRfZmlsZXN0YXRfc2V0X3NpemUoc2l6ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX2ZpbGVzdGF0X3NldF90aW1lcyhmZCwgYXRpbSwgbXRpbSwgZnN0X2ZsYWdzKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9maWxlc3RhdF9zZXRfdGltZXMoYXRpbSwgbXRpbSwgZnN0X2ZsYWdzKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcHJlYWQoZmQsIGlvdnNfcHRyLCBpb3ZzX2xlbiwgb2Zmc2V0LCBucmVhZF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgaW92ZWNzID0gSW92ZWMucmVhZF9ieXRlc19hcnJheShidWZmZXIsIGlvdnNfcHRyLCBpb3ZzX2xlbik7CiAgICAgICAgbGV0IG5yZWFkID0gMDsKICAgICAgICBmb3IgKGNvbnN0IGlvdmVjIG9mIGlvdmVjcykgewogICAgICAgICAgY29uc3QgeyByZXQsIGRhdGEgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wcmVhZChpb3ZlYy5idWZfbGVuLCBvZmZzZXQpOwogICAgICAgICAgaWYgKHJldCAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobnJlYWRfcHRyLCBucmVhZCwgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgICB9CiAgICAgICAgICBidWZmZXI4LnNldChkYXRhLCBpb3ZlYy5idWYpOwogICAgICAgICAgbnJlYWQgKz0gZGF0YS5sZW5ndGg7CiAgICAgICAgICBvZmZzZXQgKz0gQmlnSW50KGRhdGEubGVuZ3RoKTsKICAgICAgICAgIGlmIChkYXRhLmxlbmd0aCAhPSBpb3ZlYy5idWZfbGVuKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgbnJlYWQsIHRydWUpOwogICAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9wcmVzdGF0X2dldChmZCwgYnVmX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIHByZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wcmVzdGF0X2dldCgpOwogICAgICAgIGlmIChwcmVzdGF0ICE9IG51bGwpIHsKICAgICAgICAgIHByZXN0YXQud3JpdGVfYnl0ZXMoYnVmZmVyLCBidWZfcHRyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfcHJlc3RhdF9kaXJfbmFtZShmZCwgcGF0aF9wdHIsIHBhdGhfbGVuKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgeyByZXQsIHByZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wcmVzdGF0X2dldCgpOwogICAgICAgIGlmIChwcmVzdGF0ID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHByZXN0YXRfZGlyX25hbWUgPSBwcmVzdGF0LmlubmVyLnByX25hbWU7CiAgICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICAgIGJ1ZmZlcjguc2V0KHByZXN0YXRfZGlyX25hbWUuc2xpY2UoMCwgcGF0aF9sZW4pLCBwYXRoX3B0cik7CiAgICAgICAgcmV0dXJuIHByZXN0YXRfZGlyX25hbWUuYnl0ZUxlbmd0aCA+IHBhdGhfbGVuID8gRVJSTk9fTkFNRVRPT0xPTkcgOiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9wd3JpdGUoZmQsIGlvdnNfcHRyLCBpb3ZzX2xlbiwgb2Zmc2V0LCBud3JpdHRlbl9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgaW92ZWNzID0gQ2lvdmVjLnJlYWRfYnl0ZXNfYXJyYXkoYnVmZmVyLCBpb3ZzX3B0ciwgaW92c19sZW4pOwogICAgICAgIGxldCBud3JpdHRlbiA9IDA7CiAgICAgICAgZm9yIChjb25zdCBpb3ZlYyBvZiBpb3ZlY3MpIHsKICAgICAgICAgIGNvbnN0IGRhdGEgPSBidWZmZXI4LnNsaWNlKGlvdmVjLmJ1ZiwgaW92ZWMuYnVmICsgaW92ZWMuYnVmX2xlbik7CiAgICAgICAgICBjb25zdCB7IHJldCwgbndyaXR0ZW46IG53cml0dGVuX3BhcnQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG53cml0dGVuX3B0ciwgbndyaXR0ZW4sIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgbndyaXR0ZW4gKz0gbndyaXR0ZW5fcGFydDsKICAgICAgICAgIG9mZnNldCArPSBCaWdJbnQobndyaXR0ZW5fcGFydCk7CiAgICAgICAgICBpZiAobndyaXR0ZW5fcGFydCAhPSBkYXRhLmJ5dGVMZW5ndGgpIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobndyaXR0ZW5fcHRyLCBud3JpdHRlbiwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3JlYWQoZmQsIGlvdnNfcHRyLCBpb3ZzX2xlbiwgbnJlYWRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IGlvdmVjcyA9IElvdmVjLnJlYWRfYnl0ZXNfYXJyYXkoYnVmZmVyLCBpb3ZzX3B0ciwgaW92c19sZW4pOwogICAgICAgIGxldCBucmVhZCA9IDA7CiAgICAgICAgZm9yIChjb25zdCBpb3ZlYyBvZiBpb3ZlY3MpIHsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBkYXRhIH0gPSBzZWxmLmZkc1tmZF0uZmRfcmVhZChpb3ZlYy5idWZfbGVuKTsKICAgICAgICAgIGlmIChyZXQgIT0gRVJSTk9fU1VDQ0VTUykgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgbnJlYWQsIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgYnVmZmVyOC5zZXQoZGF0YSwgaW92ZWMuYnVmKTsKICAgICAgICAgIG5yZWFkICs9IGRhdGEubGVuZ3RoOwogICAgICAgICAgaWYgKGRhdGEubGVuZ3RoICE9IGlvdmVjLmJ1Zl9sZW4pIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobnJlYWRfcHRyLCBucmVhZCwgdHJ1ZSk7CiAgICAgICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3JlYWRkaXIoZmQsIGJ1ZiwgYnVmX2xlbiwgY29va2llLCBidWZ1c2VkX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBsZXQgYnVmdXNlZCA9IDA7CiAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBkaXJlbnQgfSA9IHNlbGYuZmRzW2ZkXS5mZF9yZWFkZGlyX3NpbmdsZShjb29raWUpOwogICAgICAgICAgaWYgKHJldCAhPSAwKSB7CiAgICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYnVmdXNlZF9wdHIsIGJ1ZnVzZWQsIHRydWUpOwogICAgICAgICAgICByZXR1cm4gcmV0OwogICAgICAgICAgfQogICAgICAgICAgaWYgKGRpcmVudCA9PSBudWxsKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGJ1Zl9sZW4gLSBidWZ1c2VkIDwgZGlyZW50LmhlYWRfbGVuZ3RoKCkpIHsKICAgICAgICAgICAgYnVmdXNlZCA9IGJ1Zl9sZW47CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgaGVhZF9ieXRlcyA9IG5ldyBBcnJheUJ1ZmZlcihkaXJlbnQuaGVhZF9sZW5ndGgoKSk7CiAgICAgICAgICBkaXJlbnQud3JpdGVfaGVhZF9ieXRlcyhuZXcgRGF0YVZpZXcoaGVhZF9ieXRlcyksIDApOwogICAgICAgICAgYnVmZmVyOC5zZXQobmV3IFVpbnQ4QXJyYXkoaGVhZF9ieXRlcykuc2xpY2UoMCwgTWF0aC5taW4oaGVhZF9ieXRlcy5ieXRlTGVuZ3RoLCBidWZfbGVuIC0gYnVmdXNlZCkpLCBidWYpOwogICAgICAgICAgYnVmICs9IGRpcmVudC5oZWFkX2xlbmd0aCgpOwogICAgICAgICAgYnVmdXNlZCArPSBkaXJlbnQuaGVhZF9sZW5ndGgoKTsKICAgICAgICAgIGlmIChidWZfbGVuIC0gYnVmdXNlZCA8IGRpcmVudC5uYW1lX2xlbmd0aCgpKSB7CiAgICAgICAgICAgIGJ1ZnVzZWQgPSBidWZfbGVuOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGRpcmVudC53cml0ZV9uYW1lX2J5dGVzKGJ1ZmZlcjgsIGJ1ZiwgYnVmX2xlbiAtIGJ1ZnVzZWQpOwogICAgICAgICAgYnVmICs9IGRpcmVudC5uYW1lX2xlbmd0aCgpOwogICAgICAgICAgYnVmdXNlZCArPSBkaXJlbnQubmFtZV9sZW5ndGgoKTsKICAgICAgICAgIGNvb2tpZSA9IGRpcmVudC5kX25leHQ7CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIoYnVmdXNlZF9wdHIsIGJ1ZnVzZWQsIHRydWUpOwogICAgICAgIHJldHVybiAwOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9yZW51bWJlcihmZCwgdG8pIHsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDAgJiYgc2VsZi5mZHNbdG9dICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHJldCA9IHNlbGYuZmRzW3RvXS5mZF9jbG9zZSgpOwogICAgICAgIGlmIChyZXQgIT0gMCkgewogICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICB9CiAgICAgICAgc2VsZi5mZHNbdG9dID0gc2VsZi5mZHNbZmRdOwogICAgICAgIHNlbGYuZmRzW2ZkXSA9IHZvaWQgMDsKICAgICAgICByZXR1cm4gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgZmRfc2VlayhmZCwgb2Zmc2V0LCB3aGVuY2UsIG9mZnNldF9vdXRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCB7IHJldCwgb2Zmc2V0OiBvZmZzZXRfb3V0IH0gPSBzZWxmLmZkc1tmZF0uZmRfc2VlayhvZmZzZXQsIHdoZW5jZSk7CiAgICAgICAgYnVmZmVyLnNldEJpZ0ludDY0KG9mZnNldF9vdXRfcHRyLCBvZmZzZXRfb3V0LCB0cnVlKTsKICAgICAgICByZXR1cm4gcmV0OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBmZF9zeW5jKGZkKSB7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5mZF9zeW5jKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3RlbGwoZmQsIG9mZnNldF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHsgcmV0LCBvZmZzZXQgfSA9IHNlbGYuZmRzW2ZkXS5mZF90ZWxsKCk7CiAgICAgICAgYnVmZmVyLnNldEJpZ1VpbnQ2NChvZmZzZXRfcHRyLCBvZmZzZXQsIHRydWUpOwogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIGZkX3dyaXRlKGZkLCBpb3ZzX3B0ciwgaW92c19sZW4sIG53cml0dGVuX3B0cikgewogICAgICBjb25zdCBidWZmZXIgPSBuZXcgRGF0YVZpZXcoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBpb3ZlY3MgPSBDaW92ZWMucmVhZF9ieXRlc19hcnJheShidWZmZXIsIGlvdnNfcHRyLCBpb3ZzX2xlbik7CiAgICAgICAgbGV0IG53cml0dGVuID0gMDsKICAgICAgICBmb3IgKGNvbnN0IGlvdmVjIG9mIGlvdmVjcykgewogICAgICAgICAgY29uc3QgZGF0YSA9IGJ1ZmZlcjguc2xpY2UoaW92ZWMuYnVmLCBpb3ZlYy5idWYgKyBpb3ZlYy5idWZfbGVuKTsKICAgICAgICAgIGNvbnN0IHsgcmV0LCBud3JpdHRlbjogbndyaXR0ZW5fcGFydCB9ID0gc2VsZi5mZHNbZmRdLmZkX3dyaXRlKGRhdGEpOwogICAgICAgICAgaWYgKHJldCAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICAgIGJ1ZmZlci5zZXRVaW50MzIobndyaXR0ZW5fcHRyLCBud3JpdHRlbiwgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgICB9CiAgICAgICAgICBud3JpdHRlbiArPSBud3JpdHRlbl9wYXJ0OwogICAgICAgICAgaWYgKG53cml0dGVuX3BhcnQgIT0gZGF0YS5ieXRlTGVuZ3RoKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBidWZmZXIuc2V0VWludDMyKG53cml0dGVuX3B0ciwgbndyaXR0ZW4sIHRydWUpOwogICAgICAgIHJldHVybiBFUlJOT19TVUNDRVNTOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX2NyZWF0ZV9kaXJlY3RvcnkoZmQsIHBhdGhfcHRyLCBwYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0ucGF0aF9jcmVhdGVfZGlyZWN0b3J5KHBhdGgpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwYXRoX2ZpbGVzdGF0X2dldChmZCwgZmxhZ3MsIHBhdGhfcHRyLCBwYXRoX2xlbiwgZmlsZXN0YXRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICBjb25zdCB7IHJldCwgZmlsZXN0YXQgfSA9IHNlbGYuZmRzW2ZkXS5wYXRoX2ZpbGVzdGF0X2dldChmbGFncywgcGF0aCk7CiAgICAgICAgaWYgKGZpbGVzdGF0ICE9IG51bGwpIHsKICAgICAgICAgIGZpbGVzdGF0LndyaXRlX2J5dGVzKGJ1ZmZlciwgZmlsZXN0YXRfcHRyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9maWxlc3RhdF9zZXRfdGltZXMoZmQsIGZsYWdzLCBwYXRoX3B0ciwgcGF0aF9sZW4sIGF0aW0sIG10aW0sIGZzdF9mbGFncykgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIHJldHVybiBzZWxmLmZkc1tmZF0ucGF0aF9maWxlc3RhdF9zZXRfdGltZXMoZmxhZ3MsIHBhdGgsIGF0aW0sIG10aW0sIGZzdF9mbGFncyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfbGluayhvbGRfZmQsIG9sZF9mbGFncywgb2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9sZW4sIG5ld19mZCwgbmV3X3BhdGhfcHRyLCBuZXdfcGF0aF9sZW4pIHsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbb2xkX2ZkXSAhPSB2b2lkIDAgJiYgc2VsZi5mZHNbbmV3X2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBvbGRfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX3B0ciArIG9sZF9wYXRoX2xlbikpOwogICAgICAgIGNvbnN0IG5ld19wYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfcHRyICsgbmV3X3BhdGhfbGVuKSk7CiAgICAgICAgY29uc3QgeyByZXQsIGlub2RlX29iaiB9ID0gc2VsZi5mZHNbb2xkX2ZkXS5wYXRoX2xvb2t1cChvbGRfcGF0aCwgb2xkX2ZsYWdzKTsKICAgICAgICBpZiAoaW5vZGVfb2JqID09IG51bGwpIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzZWxmLmZkc1tuZXdfZmRdLnBhdGhfbGluayhuZXdfcGF0aCwgaW5vZGVfb2JqLCBmYWxzZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfb3BlbihmZCwgZGlyZmxhZ3MsIHBhdGhfcHRyLCBwYXRoX2xlbiwgb2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcsIGZkX2ZsYWdzLCBvcGVuZWRfZmRfcHRyKSB7CiAgICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBEYXRhVmlldyhzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBpZiAoc2VsZi5mZHNbZmRdICE9IHZvaWQgMCkgewogICAgICAgIGNvbnN0IHBhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2UocGF0aF9wdHIsIHBhdGhfcHRyICsgcGF0aF9sZW4pKTsKICAgICAgICBkZWJ1Zy5sb2cocGF0aCk7CiAgICAgICAgY29uc3QgeyByZXQsIGZkX29iaiB9ID0gc2VsZi5mZHNbZmRdLnBhdGhfb3BlbihkaXJmbGFncywgcGF0aCwgb2ZsYWdzLCBmc19yaWdodHNfYmFzZSwgZnNfcmlnaHRzX2luaGVyaXRpbmcsIGZkX2ZsYWdzKTsKICAgICAgICBpZiAocmV0ICE9IDApIHsKICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgfQogICAgICAgIHNlbGYuZmRzLnB1c2goZmRfb2JqKTsKICAgICAgICBjb25zdCBvcGVuZWRfZmQgPSBzZWxmLmZkcy5sZW5ndGggLSAxOwogICAgICAgIGJ1ZmZlci5zZXRVaW50MzIob3BlbmVkX2ZkX3B0ciwgb3BlbmVkX2ZkLCB0cnVlKTsKICAgICAgICByZXR1cm4gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF9yZWFkbGluayhmZCwgcGF0aF9wdHIsIHBhdGhfbGVuLCBidWZfcHRyLCBidWZfbGVuLCBucmVhZF9wdHIpIHsKICAgICAgY29uc3QgYnVmZmVyID0gbmV3IERhdGFWaWV3KHNlbGYuaW5zdC5leHBvcnRzLm1lbW9yeS5idWZmZXIpOwogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3QgcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShwYXRoX3B0ciwgcGF0aF9wdHIgKyBwYXRoX2xlbikpOwogICAgICAgIGRlYnVnLmxvZyhwYXRoKTsKICAgICAgICBjb25zdCB7IHJldCwgZGF0YSB9ID0gc2VsZi5mZHNbZmRdLnBhdGhfcmVhZGxpbmsocGF0aCk7CiAgICAgICAgaWYgKGRhdGEgIT0gbnVsbCkgewogICAgICAgICAgY29uc3QgZGF0YV9idWYgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoZGF0YSk7CiAgICAgICAgICBpZiAoZGF0YV9idWYubGVuZ3RoID4gYnVmX2xlbikgewogICAgICAgICAgICBidWZmZXIuc2V0VWludDMyKG5yZWFkX3B0ciwgMCwgdHJ1ZSk7CiAgICAgICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICAgICAgfQogICAgICAgICAgYnVmZmVyOC5zZXQoZGF0YV9idWYsIGJ1Zl9wdHIpOwogICAgICAgICAgYnVmZmVyLnNldFVpbnQzMihucmVhZF9wdHIsIGRhdGFfYnVmLmxlbmd0aCwgdHJ1ZSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfcmVtb3ZlX2RpcmVjdG9yeShmZCwgcGF0aF9wdHIsIHBhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBwYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5wYXRoX3JlbW92ZV9kaXJlY3RvcnkocGF0aCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfcmVuYW1lKGZkLCBvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX2xlbiwgbmV3X2ZkLCBuZXdfcGF0aF9wdHIsIG5ld19wYXRoX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGlmIChzZWxmLmZkc1tmZF0gIT0gdm9pZCAwICYmIHNlbGYuZmRzW25ld19mZF0gIT0gdm9pZCAwKSB7CiAgICAgICAgY29uc3Qgb2xkX3BhdGggPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IikuZGVjb2RlKGJ1ZmZlcjguc2xpY2Uob2xkX3BhdGhfcHRyLCBvbGRfcGF0aF9wdHIgKyBvbGRfcGF0aF9sZW4pKTsKICAgICAgICBjb25zdCBuZXdfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShuZXdfcGF0aF9wdHIsIG5ld19wYXRoX3B0ciArIG5ld19wYXRoX2xlbikpOwogICAgICAgIGxldCB7IHJldCwgaW5vZGVfb2JqIH0gPSBzZWxmLmZkc1tmZF0ucGF0aF91bmxpbmsob2xkX3BhdGgpOwogICAgICAgIGlmIChpbm9kZV9vYmogPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICB9CiAgICAgICAgcmV0ID0gc2VsZi5mZHNbbmV3X2ZkXS5wYXRoX2xpbmsobmV3X3BhdGgsIGlub2RlX29iaiwgdHJ1ZSk7CiAgICAgICAgaWYgKHJldCAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICBpZiAoc2VsZi5mZHNbZmRdLnBhdGhfbGluayhvbGRfcGF0aCwgaW5vZGVfb2JqLCB0cnVlKSAhPSBFUlJOT19TVUNDRVNTKSB7CiAgICAgICAgICAgIHRocm93ICJwYXRoX2xpbmsgc2hvdWxkIGFsd2F5cyByZXR1cm4gc3VjY2VzcyB3aGVuIHJlbGlua2luZyBhbiBpbm9kZSBiYWNrIHRvIHRoZSBvcmlnaW5hbCBwbGFjZSI7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0JBREY7CiAgICAgIH0KICAgIH0sIHBhdGhfc3ltbGluayhvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX2xlbiwgZmQsIG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBvbGRfcGF0aCA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiKS5kZWNvZGUoYnVmZmVyOC5zbGljZShvbGRfcGF0aF9wdHIsIG9sZF9wYXRoX3B0ciArIG9sZF9wYXRoX2xlbikpOwogICAgICAgIGNvbnN0IG5ld19wYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKG5ld19wYXRoX3B0ciwgbmV3X3BhdGhfcHRyICsgbmV3X3BhdGhfbGVuKSk7CiAgICAgICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gRVJSTk9fQkFERjsKICAgICAgfQogICAgfSwgcGF0aF91bmxpbmtfZmlsZShmZCwgcGF0aF9wdHIsIHBhdGhfbGVuKSB7CiAgICAgIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheShzZWxmLmluc3QuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKTsKICAgICAgaWYgKHNlbGYuZmRzW2ZkXSAhPSB2b2lkIDApIHsKICAgICAgICBjb25zdCBwYXRoID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpLmRlY29kZShidWZmZXI4LnNsaWNlKHBhdGhfcHRyLCBwYXRoX3B0ciArIHBhdGhfbGVuKSk7CiAgICAgICAgcmV0dXJuIHNlbGYuZmRzW2ZkXS5wYXRoX3VubGlua19maWxlKHBhdGgpOwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBFUlJOT19CQURGOwogICAgICB9CiAgICB9LCBwb2xsX29uZW9mZihpbl8sIG91dCwgbnN1YnNjcmlwdGlvbnMpIHsKICAgICAgdGhyb3cgImFzeW5jIGlvIG5vdCBzdXBwb3J0ZWQiOwogICAgfSwgcHJvY19leGl0KGV4aXRfY29kZSkgewogICAgICB0aHJvdyBuZXcgV0FTSVByb2NFeGl0KGV4aXRfY29kZSk7CiAgICB9LCBwcm9jX3JhaXNlKHNpZykgewogICAgICB0aHJvdyAicmFpc2VkIHNpZ25hbCAiICsgc2lnOwogICAgfSwgc2NoZWRfeWllbGQoKSB7CiAgICB9LCByYW5kb21fZ2V0KGJ1ZiwgYnVmX2xlbikgewogICAgICBjb25zdCBidWZmZXI4ID0gbmV3IFVpbnQ4QXJyYXkoc2VsZi5pbnN0LmV4cG9ydHMubWVtb3J5LmJ1ZmZlcik7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnVmX2xlbjsgaSsrKSB7CiAgICAgICAgYnVmZmVyOFtidWYgKyBpXSA9IE1hdGgucmFuZG9tKCkgKiAyNTYgfCAwOwogICAgICB9CiAgICB9LCBzb2NrX3JlY3YoZmQsIHJpX2RhdGEsIHJpX2ZsYWdzKSB7CiAgICAgIHRocm93ICJzb2NrZXRzIG5vdCBzdXBwb3J0ZWQiOwogICAgfSwgc29ja19zZW5kKGZkLCBzaV9kYXRhLCBzaV9mbGFncykgewogICAgICB0aHJvdyAic29ja2V0cyBub3Qgc3VwcG9ydGVkIjsKICAgIH0sIHNvY2tfc2h1dGRvd24oZmQsIGhvdykgewogICAgICB0aHJvdyAic29ja2V0cyBub3Qgc3VwcG9ydGVkIjsKICAgIH0sIHNvY2tfYWNjZXB0KGZkLCBmbGFncykgewogICAgICB0aHJvdyAic29ja2V0cyBub3Qgc3VwcG9ydGVkIjsKICAgIH0gfTsKICB9Cn07CgovLyBub2RlX21vZHVsZXMvQGJqb3JuMy9icm93c2VyX3dhc2lfc2hpbS9kaXN0L2ZkLmpzCnZhciBGZCA9IGNsYXNzIHsKICBmZF9hbGxvY2F0ZShvZmZzZXQsIGxlbikgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfY2xvc2UoKSB7CiAgICByZXR1cm4gMDsKICB9CiAgZmRfZmRzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBmZHN0YXQ6IG51bGwgfTsKICB9CiAgZmRfZmRzdGF0X3NldF9mbGFncyhmbGFncykgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfZmRzdGF0X3NldF9yaWdodHMoZnNfcmlnaHRzX2Jhc2UsIGZzX3JpZ2h0c19pbmhlcml0aW5nKSB7CiAgICByZXR1cm4gRVJSTk9fTk9UU1VQOwogIH0KICBmZF9maWxlc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZmlsZXN0YXQ6IG51bGwgfTsKICB9CiAgZmRfZmlsZXN0YXRfc2V0X3NpemUoc2l6ZSkgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfZmlsZXN0YXRfc2V0X3RpbWVzKGF0aW0sIG10aW0sIGZzdF9mbGFncykgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgZmRfcHJlYWQoc2l6ZSwgb2Zmc2V0KSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZGF0YTogbmV3IFVpbnQ4QXJyYXkoKSB9OwogIH0KICBmZF9wcmVzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBwcmVzdGF0OiBudWxsIH07CiAgfQogIGZkX3B3cml0ZShkYXRhLCBvZmZzZXQpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBud3JpdHRlbjogMCB9OwogIH0KICBmZF9yZWFkKHNpemUpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBkYXRhOiBuZXcgVWludDhBcnJheSgpIH07CiAgfQogIGZkX3JlYWRkaXJfc2luZ2xlKGNvb2tpZSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RTVVAsIGRpcmVudDogbnVsbCB9OwogIH0KICBmZF9zZWVrKG9mZnNldCwgd2hlbmNlKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgb2Zmc2V0OiAwbiB9OwogIH0KICBmZF9zeW5jKCkgewogICAgcmV0dXJuIDA7CiAgfQogIGZkX3RlbGwoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgb2Zmc2V0OiAwbiB9OwogIH0KICBmZF93cml0ZShkYXRhKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgbndyaXR0ZW46IDAgfTsKICB9CiAgcGF0aF9jcmVhdGVfZGlyZWN0b3J5KHBhdGgpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfZmlsZXN0YXRfZ2V0KGZsYWdzLCBwYXRoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZmlsZXN0YXQ6IG51bGwgfTsKICB9CiAgcGF0aF9maWxlc3RhdF9zZXRfdGltZXMoZmxhZ3MsIHBhdGgsIGF0aW0sIG10aW0sIGZzdF9mbGFncykgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgcGF0aF9saW5rKHBhdGgsIGlub2RlLCBhbGxvd19kaXIpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfdW5saW5rKHBhdGgpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBpbm9kZV9vYmo6IG51bGwgfTsKICB9CiAgcGF0aF9sb29rdXAocGF0aCwgZGlyZmxhZ3MpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UU1VQLCBpbm9kZV9vYmo6IG51bGwgfTsKICB9CiAgcGF0aF9vcGVuKGRpcmZsYWdzLCBwYXRoLCBvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZywgZmRfZmxhZ3MpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9URElSLCBmZF9vYmo6IG51bGwgfTsKICB9CiAgcGF0aF9yZWFkbGluayhwYXRoKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVFNVUCwgZGF0YTogbnVsbCB9OwogIH0KICBwYXRoX3JlbW92ZV9kaXJlY3RvcnkocGF0aCkgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9CiAgcGF0aF9yZW5hbWUob2xkX3BhdGgsIG5ld19mZCwgbmV3X3BhdGgpIHsKICAgIHJldHVybiBFUlJOT19OT1RTVVA7CiAgfQogIHBhdGhfdW5saW5rX2ZpbGUocGF0aCkgewogICAgcmV0dXJuIEVSUk5PX05PVFNVUDsKICB9Cn07CnZhciBJbm9kZSA9IGNsYXNzIHsKfTsKCi8vIG5vZGVfbW9kdWxlcy9AYmpvcm4zL2Jyb3dzZXJfd2FzaV9zaGltL2Rpc3QvZnNfbWVtLmpzCnZhciBPcGVuRmlsZSA9IGNsYXNzIGV4dGVuZHMgRmQgewogIGZkX2FsbG9jYXRlKG9mZnNldCwgbGVuKSB7CiAgICBpZiAodGhpcy5maWxlLnNpemUgPiBvZmZzZXQgKyBsZW4pIHsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IG5ld19kYXRhID0gbmV3IFVpbnQ4QXJyYXkoTnVtYmVyKG9mZnNldCArIGxlbikpOwogICAgICBuZXdfZGF0YS5zZXQodGhpcy5maWxlLmRhdGEsIDApOwogICAgICB0aGlzLmZpbGUuZGF0YSA9IG5ld19kYXRhOwogICAgfQogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIGZkX2Zkc3RhdF9nZXQoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIGZkc3RhdDogbmV3IEZkc3RhdChGSUxFVFlQRV9SRUdVTEFSX0ZJTEUsIDApIH07CiAgfQogIGZkX2ZpbGVzdGF0X3NldF9zaXplKHNpemUpIHsKICAgIGlmICh0aGlzLmZpbGUuc2l6ZSA+IHNpemUpIHsKICAgICAgdGhpcy5maWxlLmRhdGEgPSBuZXcgVWludDhBcnJheSh0aGlzLmZpbGUuZGF0YS5idWZmZXIuc2xpY2UoMCwgTnVtYmVyKHNpemUpKSk7CiAgICB9IGVsc2UgewogICAgICBjb25zdCBuZXdfZGF0YSA9IG5ldyBVaW50OEFycmF5KE51bWJlcihzaXplKSk7CiAgICAgIG5ld19kYXRhLnNldCh0aGlzLmZpbGUuZGF0YSwgMCk7CiAgICAgIHRoaXMuZmlsZS5kYXRhID0gbmV3X2RhdGE7CiAgICB9CiAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICB9CiAgZmRfcmVhZChzaXplKSB7CiAgICBjb25zdCBzbGljZSA9IHRoaXMuZmlsZS5kYXRhLnNsaWNlKE51bWJlcih0aGlzLmZpbGVfcG9zKSwgTnVtYmVyKHRoaXMuZmlsZV9wb3MgKyBCaWdJbnQoc2l6ZSkpKTsKICAgIHRoaXMuZmlsZV9wb3MgKz0gQmlnSW50KHNsaWNlLmxlbmd0aCk7CiAgICByZXR1cm4geyByZXQ6IDAsIGRhdGE6IHNsaWNlIH07CiAgfQogIGZkX3ByZWFkKHNpemUsIG9mZnNldCkgewogICAgY29uc3Qgc2xpY2UgPSB0aGlzLmZpbGUuZGF0YS5zbGljZShOdW1iZXIob2Zmc2V0KSwgTnVtYmVyKG9mZnNldCArIEJpZ0ludChzaXplKSkpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBkYXRhOiBzbGljZSB9OwogIH0KICBmZF9zZWVrKG9mZnNldCwgd2hlbmNlKSB7CiAgICBsZXQgY2FsY3VsYXRlZF9vZmZzZXQ7CiAgICBzd2l0Y2ggKHdoZW5jZSkgewogICAgICBjYXNlIFdIRU5DRV9TRVQ6CiAgICAgICAgY2FsY3VsYXRlZF9vZmZzZXQgPSBvZmZzZXQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgV0hFTkNFX0NVUjoKICAgICAgICBjYWxjdWxhdGVkX29mZnNldCA9IHRoaXMuZmlsZV9wb3MgKyBvZmZzZXQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgV0hFTkNFX0VORDoKICAgICAgICBjYWxjdWxhdGVkX29mZnNldCA9IEJpZ0ludCh0aGlzLmZpbGUuZGF0YS5ieXRlTGVuZ3RoKSArIG9mZnNldDsKICAgICAgICBicmVhazsKICAgICAgZGVmYXVsdDoKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0lOVkFMLCBvZmZzZXQ6IDBuIH07CiAgICB9CiAgICBpZiAoY2FsY3VsYXRlZF9vZmZzZXQgPCAwKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fSU5WQUwsIG9mZnNldDogMG4gfTsKICAgIH0KICAgIHRoaXMuZmlsZV9wb3MgPSBjYWxjdWxhdGVkX29mZnNldDsKICAgIHJldHVybiB7IHJldDogMCwgb2Zmc2V0OiB0aGlzLmZpbGVfcG9zIH07CiAgfQogIGZkX3RlbGwoKSB7CiAgICByZXR1cm4geyByZXQ6IDAsIG9mZnNldDogdGhpcy5maWxlX3BvcyB9OwogIH0KICBmZF93cml0ZShkYXRhKSB7CiAgICBpZiAodGhpcy5maWxlLnJlYWRvbmx5KQogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG53cml0dGVuOiAwIH07CiAgICBpZiAodGhpcy5maWxlX3BvcyArIEJpZ0ludChkYXRhLmJ5dGVMZW5ndGgpID4gdGhpcy5maWxlLnNpemUpIHsKICAgICAgY29uc3Qgb2xkID0gdGhpcy5maWxlLmRhdGE7CiAgICAgIHRoaXMuZmlsZS5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoTnVtYmVyKHRoaXMuZmlsZV9wb3MgKyBCaWdJbnQoZGF0YS5ieXRlTGVuZ3RoKSkpOwogICAgICB0aGlzLmZpbGUuZGF0YS5zZXQob2xkKTsKICAgIH0KICAgIHRoaXMuZmlsZS5kYXRhLnNldChkYXRhLCBOdW1iZXIodGhpcy5maWxlX3BvcykpOwogICAgdGhpcy5maWxlX3BvcyArPSBCaWdJbnQoZGF0YS5ieXRlTGVuZ3RoKTsKICAgIHJldHVybiB7IHJldDogMCwgbndyaXR0ZW46IGRhdGEuYnl0ZUxlbmd0aCB9OwogIH0KICBmZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KSB7CiAgICBpZiAodGhpcy5maWxlLnJlYWRvbmx5KQogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG53cml0dGVuOiAwIH07CiAgICBpZiAob2Zmc2V0ICsgQmlnSW50KGRhdGEuYnl0ZUxlbmd0aCkgPiB0aGlzLmZpbGUuc2l6ZSkgewogICAgICBjb25zdCBvbGQgPSB0aGlzLmZpbGUuZGF0YTsKICAgICAgdGhpcy5maWxlLmRhdGEgPSBuZXcgVWludDhBcnJheShOdW1iZXIob2Zmc2V0ICsgQmlnSW50KGRhdGEuYnl0ZUxlbmd0aCkpKTsKICAgICAgdGhpcy5maWxlLmRhdGEuc2V0KG9sZCk7CiAgICB9CiAgICB0aGlzLmZpbGUuZGF0YS5zZXQoZGF0YSwgTnVtYmVyKG9mZnNldCkpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBud3JpdHRlbjogZGF0YS5ieXRlTGVuZ3RoIH07CiAgfQogIGZkX2ZpbGVzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgZmlsZXN0YXQ6IHRoaXMuZmlsZS5zdGF0KCkgfTsKICB9CiAgY29uc3RydWN0b3IoZmlsZSkgewogICAgc3VwZXIoKTsKICAgIHRoaXMuZmlsZV9wb3MgPSAwbjsKICAgIHRoaXMuZmlsZSA9IGZpbGU7CiAgfQp9Owp2YXIgT3BlbkRpcmVjdG9yeSA9IGNsYXNzIGV4dGVuZHMgRmQgewogIGZkX3NlZWsob2Zmc2V0LCB3aGVuY2UpIHsKICAgIHJldHVybiB7IHJldDogRVJSTk9fQkFERiwgb2Zmc2V0OiAwbiB9OwogIH0KICBmZF90ZWxsKCkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBvZmZzZXQ6IDBuIH07CiAgfQogIGZkX2FsbG9jYXRlKG9mZnNldCwgbGVuKSB7CiAgICByZXR1cm4gRVJSTk9fQkFERjsKICB9CiAgZmRfZmRzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgZmRzdGF0OiBuZXcgRmRzdGF0KEZJTEVUWVBFX0RJUkVDVE9SWSwgMCkgfTsKICB9CiAgZmRfcmVhZGRpcl9zaW5nbGUoY29va2llKSB7CiAgICBpZiAoZGVidWcuZW5hYmxlZCkgewogICAgICBkZWJ1Zy5sb2coInJlYWRkaXJfc2luZ2xlIiwgY29va2llKTsKICAgICAgZGVidWcubG9nKGNvb2tpZSwgdGhpcy5kaXIuY29udGVudHMua2V5cygpKTsKICAgIH0KICAgIGlmIChjb29raWUgPT0gMG4pIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBkaXJlbnQ6IG5ldyBEaXJlbnQoMW4sICIuIiwgRklMRVRZUEVfRElSRUNUT1JZKSB9OwogICAgfSBlbHNlIGlmIChjb29raWUgPT0gMW4pIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBkaXJlbnQ6IG5ldyBEaXJlbnQoMm4sICIuLiIsIEZJTEVUWVBFX0RJUkVDVE9SWSkgfTsKICAgIH0KICAgIGlmIChjb29raWUgPj0gQmlnSW50KHRoaXMuZGlyLmNvbnRlbnRzLnNpemUpICsgMm4pIHsKICAgICAgcmV0dXJuIHsgcmV0OiAwLCBkaXJlbnQ6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IFtuYW1lLCBlbnRyeV0gPSBBcnJheS5mcm9tKHRoaXMuZGlyLmNvbnRlbnRzLmVudHJpZXMoKSlbTnVtYmVyKGNvb2tpZSAtIDJuKV07CiAgICByZXR1cm4geyByZXQ6IDAsIGRpcmVudDogbmV3IERpcmVudChjb29raWUgKyAxbiwgbmFtZSwgZW50cnkuc3RhdCgpLmZpbGV0eXBlKSB9OwogIH0KICBwYXRoX2ZpbGVzdGF0X2dldChmbGFncywgcGF0aF9zdHIpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX2VyciwgcGF0aCB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXRoX2VyciwgZmlsZXN0YXQ6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0LCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgpOwogICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0LCBmaWxlc3RhdDogbnVsbCB9OwogICAgfQogICAgcmV0dXJuIHsgcmV0OiAwLCBmaWxlc3RhdDogZW50cnkuc3RhdCgpIH07CiAgfQogIHBhdGhfbG9va3VwKHBhdGhfc3RyLCBkaXJmbGFncykgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhdGhfcmV0LCBpbm9kZV9vYmo6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0LCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgpOwogICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0LCBpbm9kZV9vYmo6IG51bGwgfTsKICAgIH0KICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgaW5vZGVfb2JqOiBlbnRyeSB9OwogIH0KICBwYXRoX29wZW4oZGlyZmxhZ3MsIHBhdGhfc3RyLCBvZmxhZ3MsIGZzX3JpZ2h0c19iYXNlLCBmc19yaWdodHNfaW5oZXJpdGluZywgZmRfZmxhZ3MpIHsKICAgIGNvbnN0IHsgcmV0OiBwYXRoX3JldCwgcGF0aCB9ID0gUGF0aC5mcm9tKHBhdGhfc3RyKTsKICAgIGlmIChwYXRoID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBwYXRoX3JldCwgZmRfb2JqOiBudWxsIH07CiAgICB9CiAgICBsZXQgeyByZXQsIGVudHJ5IH0gPSB0aGlzLmRpci5nZXRfZW50cnlfZm9yX3BhdGgocGF0aCk7CiAgICBpZiAoZW50cnkgPT0gbnVsbCkgewogICAgICBpZiAocmV0ICE9IEVSUk5PX05PRU5UKSB7CiAgICAgICAgcmV0dXJuIHsgcmV0LCBmZF9vYmo6IG51bGwgfTsKICAgICAgfQogICAgICBpZiAoKG9mbGFncyAmIE9GTEFHU19DUkVBVCkgPT0gT0ZMQUdTX0NSRUFUKSB7CiAgICAgICAgY29uc3QgeyByZXQ6IHJldDIsIGVudHJ5OiBuZXdfZW50cnkgfSA9IHRoaXMuZGlyLmNyZWF0ZV9lbnRyeV9mb3JfcGF0aChwYXRoX3N0ciwgKG9mbGFncyAmIE9GTEFHU19ESVJFQ1RPUlkpID09IE9GTEFHU19ESVJFQ1RPUlkpOwogICAgICAgIGlmIChuZXdfZW50cnkgPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIHsgcmV0OiByZXQyLCBmZF9vYmo6IG51bGwgfTsKICAgICAgICB9CiAgICAgICAgZW50cnkgPSBuZXdfZW50cnk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT0VOVCwgZmRfb2JqOiBudWxsIH07CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoKG9mbGFncyAmIE9GTEFHU19FWENMKSA9PSBPRkxBR1NfRVhDTCkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0VYSVNULCBmZF9vYmo6IG51bGwgfTsKICAgIH0KICAgIGlmICgob2ZsYWdzICYgT0ZMQUdTX0RJUkVDVE9SWSkgPT0gT0ZMQUdTX0RJUkVDVE9SWSAmJiBlbnRyeS5zdGF0KCkuZmlsZXR5cGUgIT09IEZJTEVUWVBFX0RJUkVDVE9SWSkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgZmRfb2JqOiBudWxsIH07CiAgICB9CiAgICByZXR1cm4gZW50cnkucGF0aF9vcGVuKG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZkX2ZsYWdzKTsKICB9CiAgcGF0aF9jcmVhdGVfZGlyZWN0b3J5KHBhdGgpIHsKICAgIHJldHVybiB0aGlzLnBhdGhfb3BlbigwLCBwYXRoLCBPRkxBR1NfQ1JFQVQgfCBPRkxBR1NfRElSRUNUT1JZLCAwbiwgMG4sIDApLnJldDsKICB9CiAgcGF0aF9saW5rKHBhdGhfc3RyLCBpbm9kZSwgYWxsb3dfZGlyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXRoX3JldDsKICAgIH0KICAgIGlmIChwYXRoLmlzX2RpcikgewogICAgICByZXR1cm4gRVJSTk9fTk9FTlQ7CiAgICB9CiAgICBjb25zdCB7IHJldDogcGFyZW50X3JldCwgcGFyZW50X2VudHJ5LCBmaWxlbmFtZSwgZW50cnkgfSA9IHRoaXMuZGlyLmdldF9wYXJlbnRfZGlyX2FuZF9lbnRyeV9mb3JfcGF0aChwYXRoLCB0cnVlKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCB8fCBmaWxlbmFtZSA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXJlbnRfcmV0OwogICAgfQogICAgaWYgKGVudHJ5ICE9IG51bGwpIHsKICAgICAgY29uc3Qgc291cmNlX2lzX2RpciA9IGlub2RlLnN0YXQoKS5maWxldHlwZSA9PSBGSUxFVFlQRV9ESVJFQ1RPUlk7CiAgICAgIGNvbnN0IHRhcmdldF9pc19kaXIgPSBlbnRyeS5zdGF0KCkuZmlsZXR5cGUgPT0gRklMRVRZUEVfRElSRUNUT1JZOwogICAgICBpZiAoc291cmNlX2lzX2RpciAmJiB0YXJnZXRfaXNfZGlyKSB7CiAgICAgICAgaWYgKGFsbG93X2RpciAmJiBlbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkgewogICAgICAgICAgaWYgKGVudHJ5LmNvbnRlbnRzLnNpemUgPT0gMCkgewogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmV0dXJuIEVSUk5PX05PVEVNUFRZOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gRVJSTk9fRVhJU1Q7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKHNvdXJjZV9pc19kaXIgJiYgIXRhcmdldF9pc19kaXIpIHsKICAgICAgICByZXR1cm4gRVJSTk9fTk9URElSOwogICAgICB9IGVsc2UgaWYgKCFzb3VyY2VfaXNfZGlyICYmIHRhcmdldF9pc19kaXIpIHsKICAgICAgICByZXR1cm4gRVJSTk9fSVNESVI7CiAgICAgIH0gZWxzZSBpZiAoaW5vZGUuc3RhdCgpLmZpbGV0eXBlID09IEZJTEVUWVBFX1JFR1VMQVJfRklMRSAmJiBlbnRyeS5zdGF0KCkuZmlsZXR5cGUgPT0gRklMRVRZUEVfUkVHVUxBUl9GSUxFKSB7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIEVSUk5PX0VYSVNUOwogICAgICB9CiAgICB9CiAgICBpZiAoIWFsbG93X2RpciAmJiBpbm9kZS5zdGF0KCkuZmlsZXR5cGUgPT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgIHJldHVybiBFUlJOT19QRVJNOwogICAgfQogICAgcGFyZW50X2VudHJ5LmNvbnRlbnRzLnNldChmaWxlbmFtZSwgaW5vZGUpOwogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIHBhdGhfdW5saW5rKHBhdGhfc3RyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogcGF0aF9yZXQsIGlub2RlX29iajogbnVsbCB9OwogICAgfQogICAgY29uc3QgeyByZXQ6IHBhcmVudF9yZXQsIHBhcmVudF9lbnRyeSwgZmlsZW5hbWUsIGVudHJ5IH0gPSB0aGlzLmRpci5nZXRfcGFyZW50X2Rpcl9hbmRfZW50cnlfZm9yX3BhdGgocGF0aCwgdHJ1ZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhcmVudF9yZXQsIGlub2RlX29iajogbnVsbCB9OwogICAgfQogICAgaWYgKGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT0VOVCwgaW5vZGVfb2JqOiBudWxsIH07CiAgICB9CiAgICBwYXJlbnRfZW50cnkuY29udGVudHMuZGVsZXRlKGZpbGVuYW1lKTsKICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgaW5vZGVfb2JqOiBlbnRyeSB9OwogIH0KICBwYXRoX3VubGlua19maWxlKHBhdGhfc3RyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXRoX3JldDsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBwYXJlbnRfcmV0LCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIGZhbHNlKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCB8fCBmaWxlbmFtZSA9PSBudWxsIHx8IGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHBhcmVudF9yZXQ7CiAgICB9CiAgICBpZiAoZW50cnkuc3RhdCgpLmZpbGV0eXBlID09PSBGSUxFVFlQRV9ESVJFQ1RPUlkpIHsKICAgICAgcmV0dXJuIEVSUk5PX0lTRElSOwogICAgfQogICAgcGFyZW50X2VudHJ5LmNvbnRlbnRzLmRlbGV0ZShmaWxlbmFtZSk7CiAgICByZXR1cm4gRVJSTk9fU1VDQ0VTUzsKICB9CiAgcGF0aF9yZW1vdmVfZGlyZWN0b3J5KHBhdGhfc3RyKSB7CiAgICBjb25zdCB7IHJldDogcGF0aF9yZXQsIHBhdGggfSA9IFBhdGguZnJvbShwYXRoX3N0cik7CiAgICBpZiAocGF0aCA9PSBudWxsKSB7CiAgICAgIHJldHVybiBwYXRoX3JldDsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBwYXJlbnRfcmV0LCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9ID0gdGhpcy5kaXIuZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIGZhbHNlKTsKICAgIGlmIChwYXJlbnRfZW50cnkgPT0gbnVsbCB8fCBmaWxlbmFtZSA9PSBudWxsIHx8IGVudHJ5ID09IG51bGwpIHsKICAgICAgcmV0dXJuIHBhcmVudF9yZXQ7CiAgICB9CiAgICBpZiAoIShlbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkgfHwgZW50cnkuc3RhdCgpLmZpbGV0eXBlICE9PSBGSUxFVFlQRV9ESVJFQ1RPUlkpIHsKICAgICAgcmV0dXJuIEVSUk5PX05PVERJUjsKICAgIH0KICAgIGlmIChlbnRyeS5jb250ZW50cy5zaXplICE9PSAwKSB7CiAgICAgIHJldHVybiBFUlJOT19OT1RFTVBUWTsKICAgIH0KICAgIGlmICghcGFyZW50X2VudHJ5LmNvbnRlbnRzLmRlbGV0ZShmaWxlbmFtZSkpIHsKICAgICAgcmV0dXJuIEVSUk5PX05PRU5UOwogICAgfQogICAgcmV0dXJuIEVSUk5PX1NVQ0NFU1M7CiAgfQogIGZkX2ZpbGVzdGF0X2dldCgpIHsKICAgIHJldHVybiB7IHJldDogMCwgZmlsZXN0YXQ6IHRoaXMuZGlyLnN0YXQoKSB9OwogIH0KICBmZF9maWxlc3RhdF9zZXRfc2l6ZShzaXplKSB7CiAgICByZXR1cm4gRVJSTk9fQkFERjsKICB9CiAgZmRfcmVhZChzaXplKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIGRhdGE6IG5ldyBVaW50OEFycmF5KCkgfTsKICB9CiAgZmRfcHJlYWQoc2l6ZSwgb2Zmc2V0KSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIGRhdGE6IG5ldyBVaW50OEFycmF5KCkgfTsKICB9CiAgZmRfd3JpdGUoZGF0YSkgewogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19CQURGLCBud3JpdHRlbjogMCB9OwogIH0KICBmZF9wd3JpdGUoZGF0YSwgb2Zmc2V0KSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX0JBREYsIG53cml0dGVuOiAwIH07CiAgfQogIGNvbnN0cnVjdG9yKGRpcikgewogICAgc3VwZXIoKTsKICAgIHRoaXMuZGlyID0gZGlyOwogIH0KfTsKdmFyIFByZW9wZW5EaXJlY3RvcnkgPSBjbGFzcyBleHRlbmRzIE9wZW5EaXJlY3RvcnkgewogIGZkX3ByZXN0YXRfZ2V0KCkgewogICAgcmV0dXJuIHsgcmV0OiAwLCBwcmVzdGF0OiBQcmVzdGF0LmRpcih0aGlzLnByZXN0YXRfbmFtZSkgfTsKICB9CiAgY29uc3RydWN0b3IobmFtZSwgY29udGVudHMpIHsKICAgIHN1cGVyKG5ldyBEaXJlY3RvcnkoY29udGVudHMpKTsKICAgIHRoaXMucHJlc3RhdF9uYW1lID0gbmFtZTsKICB9Cn07CnZhciBGaWxlID0gY2xhc3MgZXh0ZW5kcyBJbm9kZSB7CiAgcGF0aF9vcGVuKG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZkX2ZsYWdzKSB7CiAgICBpZiAodGhpcy5yZWFkb25seSAmJiAoZnNfcmlnaHRzX2Jhc2UgJiBCaWdJbnQoUklHSFRTX0ZEX1dSSVRFKSkgPT0gQmlnSW50KFJJR0hUU19GRF9XUklURSkpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19QRVJNLCBmZF9vYmo6IG51bGwgfTsKICAgIH0KICAgIGlmICgob2ZsYWdzICYgT0ZMQUdTX1RSVU5DKSA9PSBPRkxBR1NfVFJVTkMpIHsKICAgICAgaWYgKHRoaXMucmVhZG9ubHkpCiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19QRVJNLCBmZF9vYmo6IG51bGwgfTsKICAgICAgdGhpcy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoW10pOwogICAgfQogICAgY29uc3QgZmlsZSA9IG5ldyBPcGVuRmlsZSh0aGlzKTsKICAgIGlmIChmZF9mbGFncyAmIEZERkxBR1NfQVBQRU5EKQogICAgICBmaWxlLmZkX3NlZWsoMG4sIFdIRU5DRV9FTkQpOwogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBmZF9vYmo6IGZpbGUgfTsKICB9CiAgZ2V0IHNpemUoKSB7CiAgICByZXR1cm4gQmlnSW50KHRoaXMuZGF0YS5ieXRlTGVuZ3RoKTsKICB9CiAgc3RhdCgpIHsKICAgIHJldHVybiBuZXcgRmlsZXN0YXQoRklMRVRZUEVfUkVHVUxBUl9GSUxFLCB0aGlzLnNpemUpOwogIH0KICBjb25zdHJ1Y3RvcihkYXRhLCBvcHRpb25zKSB7CiAgICBzdXBlcigpOwogICAgdGhpcy5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoZGF0YSk7CiAgICB0aGlzLnJlYWRvbmx5ID0gISFvcHRpb25zPy5yZWFkb25seTsKICB9Cn07CnZhciBQYXRoID0gY2xhc3MgUGF0aDIgewogIHN0YXRpYyBmcm9tKHBhdGgpIHsKICAgIGNvbnN0IHNlbGYgPSBuZXcgUGF0aDIoKTsKICAgIHNlbGYuaXNfZGlyID0gcGF0aC5lbmRzV2l0aCgiLyIpOwogICAgaWYgKHBhdGguc3RhcnRzV2l0aCgiLyIpKSB7CiAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9UQ0FQQUJMRSwgcGF0aDogbnVsbCB9OwogICAgfQogICAgaWYgKHBhdGguaW5jbHVkZXMoIlwwIikpIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19JTlZBTCwgcGF0aDogbnVsbCB9OwogICAgfQogICAgZm9yIChjb25zdCBjb21wb25lbnQgb2YgcGF0aC5zcGxpdCgiLyIpKSB7CiAgICAgIGlmIChjb21wb25lbnQgPT09ICIiIHx8IGNvbXBvbmVudCA9PT0gIi4iKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGNvbXBvbmVudCA9PT0gIi4uIikgewogICAgICAgIGlmIChzZWxmLnBhcnRzLnBvcCgpID09IHZvaWQgMCkgewogICAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RDQVBBQkxFLCBwYXRoOiBudWxsIH07CiAgICAgICAgfQogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHNlbGYucGFydHMucHVzaChjb21wb25lbnQpOwogICAgfQogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBwYXRoOiBzZWxmIH07CiAgfQogIHRvX3BhdGhfc3RyaW5nKCkgewogICAgbGV0IHMgPSB0aGlzLnBhcnRzLmpvaW4oIi8iKTsKICAgIGlmICh0aGlzLmlzX2RpcikgewogICAgICBzICs9ICIvIjsKICAgIH0KICAgIHJldHVybiBzOwogIH0KICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMucGFydHMgPSBbXTsKICAgIHRoaXMuaXNfZGlyID0gZmFsc2U7CiAgfQp9Owp2YXIgRGlyZWN0b3J5ID0gY2xhc3MgZXh0ZW5kcyBJbm9kZSB7CiAgcGF0aF9vcGVuKG9mbGFncywgZnNfcmlnaHRzX2Jhc2UsIGZkX2ZsYWdzKSB7CiAgICByZXR1cm4geyByZXQ6IEVSUk5PX1NVQ0NFU1MsIGZkX29iajogbmV3IE9wZW5EaXJlY3RvcnkodGhpcykgfTsKICB9CiAgc3RhdCgpIHsKICAgIHJldHVybiBuZXcgRmlsZXN0YXQoRklMRVRZUEVfRElSRUNUT1JZLCAwbik7CiAgfQogIGdldF9lbnRyeV9mb3JfcGF0aChwYXRoKSB7CiAgICBsZXQgZW50cnkgPSB0aGlzOwogICAgZm9yIChjb25zdCBjb21wb25lbnQgb2YgcGF0aC5wYXJ0cykgewogICAgICBpZiAoIShlbnRyeSBpbnN0YW5jZW9mIERpcmVjdG9yeSkpIHsKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgICBjb25zdCBjaGlsZCA9IGVudHJ5LmNvbnRlbnRzLmdldChjb21wb25lbnQpOwogICAgICBpZiAoY2hpbGQgIT09IHZvaWQgMCkgewogICAgICAgIGVudHJ5ID0gY2hpbGQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZGVidWcubG9nKGNvbXBvbmVudCk7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT0VOVCwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgfQogICAgaWYgKHBhdGguaXNfZGlyKSB7CiAgICAgIGlmIChlbnRyeS5zdGF0KCkuZmlsZXR5cGUgIT0gRklMRVRZUEVfRElSRUNUT1JZKSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19OT1RESVIsIGVudHJ5OiBudWxsIH07CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZW50cnkgfTsKICB9CiAgZ2V0X3BhcmVudF9kaXJfYW5kX2VudHJ5X2Zvcl9wYXRoKHBhdGgsIGFsbG93X3VuZGVmaW5lZCkgewogICAgY29uc3QgZmlsZW5hbWUgPSBwYXRoLnBhcnRzLnBvcCgpOwogICAgaWYgKGZpbGVuYW1lID09PSB2b2lkIDApIHsKICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19JTlZBTCwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IHsgcmV0OiBlbnRyeV9yZXQsIGVudHJ5OiBwYXJlbnRfZW50cnkgfSA9IHRoaXMuZ2V0X2VudHJ5X2Zvcl9wYXRoKHBhdGgpOwogICAgaWYgKHBhcmVudF9lbnRyeSA9PSBudWxsKSB7CiAgICAgIHJldHVybiB7IHJldDogZW50cnlfcmV0LCBwYXJlbnRfZW50cnk6IG51bGwsIGZpbGVuYW1lOiBudWxsLCBlbnRyeTogbnVsbCB9OwogICAgfQogICAgaWYgKCEocGFyZW50X2VudHJ5IGluc3RhbmNlb2YgRGlyZWN0b3J5KSkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgIH0KICAgIGNvbnN0IGVudHJ5ID0gcGFyZW50X2VudHJ5LmNvbnRlbnRzLmdldChmaWxlbmFtZSk7CiAgICBpZiAoZW50cnkgPT09IHZvaWQgMCkgewogICAgICBpZiAoIWFsbG93X3VuZGVmaW5lZCkgewogICAgICAgIHJldHVybiB7IHJldDogRVJSTk9fTk9FTlQsIHBhcmVudF9lbnRyeTogbnVsbCwgZmlsZW5hbWU6IG51bGwsIGVudHJ5OiBudWxsIH07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeTogbnVsbCB9OwogICAgICB9CiAgICB9CiAgICBpZiAocGF0aC5pc19kaXIpIHsKICAgICAgaWYgKGVudHJ5LnN0YXQoKS5maWxldHlwZSAhPSBGSUxFVFlQRV9ESVJFQ1RPUlkpIHsKICAgICAgICByZXR1cm4geyByZXQ6IEVSUk5PX05PVERJUiwgcGFyZW50X2VudHJ5OiBudWxsLCBmaWxlbmFtZTogbnVsbCwgZW50cnk6IG51bGwgfTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHsgcmV0OiBFUlJOT19TVUNDRVNTLCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9OwogIH0KICBjcmVhdGVfZW50cnlfZm9yX3BhdGgocGF0aF9zdHIsIGlzX2RpcikgewogICAgY29uc3QgeyByZXQ6IHBhdGhfcmV0LCBwYXRoIH0gPSBQYXRoLmZyb20ocGF0aF9zdHIpOwogICAgaWYgKHBhdGggPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhdGhfcmV0LCBlbnRyeTogbnVsbCB9OwogICAgfQogICAgbGV0IHsgcmV0OiBwYXJlbnRfcmV0LCBwYXJlbnRfZW50cnksIGZpbGVuYW1lLCBlbnRyeSB9ID0gdGhpcy5nZXRfcGFyZW50X2Rpcl9hbmRfZW50cnlfZm9yX3BhdGgocGF0aCwgdHJ1ZSk7CiAgICBpZiAocGFyZW50X2VudHJ5ID09IG51bGwgfHwgZmlsZW5hbWUgPT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IHBhcmVudF9yZXQsIGVudHJ5OiBudWxsIH07CiAgICB9CiAgICBpZiAoZW50cnkgIT0gbnVsbCkgewogICAgICByZXR1cm4geyByZXQ6IEVSUk5PX0VYSVNULCBlbnRyeTogbnVsbCB9OwogICAgfQogICAgZGVidWcubG9nKCJjcmVhdGUiLCBwYXRoKTsKICAgIGxldCBuZXdfY2hpbGQ7CiAgICBpZiAoIWlzX2RpcikgewogICAgICBuZXdfY2hpbGQgPSBuZXcgRmlsZShuZXcgQXJyYXlCdWZmZXIoMCkpOwogICAgfSBlbHNlIHsKICAgICAgbmV3X2NoaWxkID0gbmV3IERpcmVjdG9yeSgvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpKTsKICAgIH0KICAgIHBhcmVudF9lbnRyeS5jb250ZW50cy5zZXQoZmlsZW5hbWUsIG5ld19jaGlsZCk7CiAgICBlbnRyeSA9IG5ld19jaGlsZDsKICAgIHJldHVybiB7IHJldDogRVJSTk9fU1VDQ0VTUywgZW50cnkgfTsKICB9CiAgY29uc3RydWN0b3IoY29udGVudHMpIHsKICAgIHN1cGVyKCk7CiAgICBpZiAoY29udGVudHMgaW5zdGFuY2VvZiBBcnJheSkgewogICAgICB0aGlzLmNvbnRlbnRzID0gbmV3IE1hcChjb250ZW50cyk7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmNvbnRlbnRzID0gY29udGVudHM7CiAgICB9CiAgfQp9Owp2YXIgQ29uc29sZVN0ZG91dCA9IGNsYXNzIGV4dGVuZHMgRmQgewogIGZkX2ZpbGVzdGF0X2dldCgpIHsKICAgIGNvbnN0IGZpbGVzdGF0ID0gbmV3IEZpbGVzdGF0KEZJTEVUWVBFX0NIQVJBQ1RFUl9ERVZJQ0UsIEJpZ0ludCgwKSk7CiAgICByZXR1cm4geyByZXQ6IDAsIGZpbGVzdGF0IH07CiAgfQogIGZkX2Zkc3RhdF9nZXQoKSB7CiAgICBjb25zdCBmZHN0YXQgPSBuZXcgRmRzdGF0KEZJTEVUWVBFX0NIQVJBQ1RFUl9ERVZJQ0UsIDApOwogICAgZmRzdGF0LmZzX3JpZ2h0c19iYXNlID0gQmlnSW50KFJJR0hUU19GRF9XUklURSk7CiAgICByZXR1cm4geyByZXQ6IDAsIGZkc3RhdCB9OwogIH0KICBmZF93cml0ZShkYXRhKSB7CiAgICB0aGlzLndyaXRlKGRhdGEpOwogICAgcmV0dXJuIHsgcmV0OiAwLCBud3JpdHRlbjogZGF0YS5ieXRlTGVuZ3RoIH07CiAgfQogIHN0YXRpYyBsaW5lQnVmZmVyZWQod3JpdGUpIHsKICAgIGNvbnN0IGRlYyA9IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiLCB7IGZhdGFsOiBmYWxzZSB9KTsKICAgIGxldCBsaW5lX2J1ZiA9ICIiOwogICAgcmV0dXJuIG5ldyBDb25zb2xlU3Rkb3V0KChidWZmZXIpID0+IHsKICAgICAgbGluZV9idWYgKz0gZGVjLmRlY29kZShidWZmZXIsIHsgc3RyZWFtOiB0cnVlIH0pOwogICAgICBjb25zdCBsaW5lcyA9IGxpbmVfYnVmLnNwbGl0KCJcbiIpOwogICAgICBmb3IgKGNvbnN0IFtpLCBsaW5lXSBvZiBsaW5lcy5lbnRyaWVzKCkpIHsKICAgICAgICBpZiAoaSA8IGxpbmVzLmxlbmd0aCAtIDEpIHsKICAgICAgICAgIHdyaXRlKGxpbmUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBsaW5lX2J1ZiA9IGxpbmU7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICB9CiAgY29uc3RydWN0b3Iod3JpdGUpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLndyaXRlID0gd3JpdGU7CiAgfQp9OwoKLy8gbm9kZV9tb2R1bGVzL3dhc20taW1wb3J0cy1wYXJzZXIvaW5kZXguanMKZnVuY3Rpb24gcGFyc2VJbXBvcnRzKG1vZHVsZUJ5dGVzKSB7CiAgaWYgKG1vZHVsZUJ5dGVzIGluc3RhbmNlb2YgVWludDhBcnJheSkgewogIH0gZWxzZSBpZiAobW9kdWxlQnl0ZXMgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikgewogICAgbW9kdWxlQnl0ZXMgPSBuZXcgVWludDhBcnJheShtb2R1bGVCeXRlcyk7CiAgfSBlbHNlIGlmIChtb2R1bGVCeXRlcy5idWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikgewogICAgbW9kdWxlQnl0ZXMgPSBuZXcgVWludDhBcnJheShtb2R1bGVCeXRlcy5idWZmZXIpOwogIH0gZWxzZSB7CiAgICB0aHJvdyBuZXcgRXJyb3IoIkFyZ3VtZW50IG11c3QgYmUgYSBidWZmZXIgc291cmNlLCBsaWtlIFVpbnQ4QXJyYXkgb3IgQXJyYXlCdWZmZXIiKTsKICB9CiAgY29uc3QgcGFyc2VTdGF0ZSA9IG5ldyBQYXJzZVN0YXRlKG1vZHVsZUJ5dGVzKTsKICBwYXJzZU1hZ2ljTnVtYmVyKHBhcnNlU3RhdGUpOwogIHBhcnNlVmVyc2lvbihwYXJzZVN0YXRlKTsKICBjb25zdCB0eXBlcyA9IFtdOwogIGNvbnN0IGltcG9ydHMgPSBbXTsKICB3aGlsZSAocGFyc2VTdGF0ZS5oYXNNb3JlQnl0ZXMoKSkgewogICAgY29uc3Qgc2VjdGlvbklkID0gcGFyc2VTdGF0ZS5yZWFkQnl0ZSgpOwogICAgY29uc3Qgc2VjdGlvblNpemUgPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgc3dpdGNoIChzZWN0aW9uSWQpIHsKICAgICAgY2FzZSAxOiB7CiAgICAgICAgY29uc3QgdHlwZUNvdW50ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHR5cGVDb3VudDsgaSsrKSB7CiAgICAgICAgICB0eXBlcy5wdXNoKHBhcnNlRnVuY3Rpb25UeXBlKHBhcnNlU3RhdGUpKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY2FzZSAyOiB7CiAgICAgICAgY29uc3QgaW1wb3J0Q291bnQgPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW1wb3J0Q291bnQ7IGkrKykgewogICAgICAgICAgY29uc3QgbW9kdWxlID0gcGFyc2VTdGF0ZS5yZWFkTmFtZSgpOwogICAgICAgICAgY29uc3QgbmFtZSA9IHBhcnNlU3RhdGUucmVhZE5hbWUoKTsKICAgICAgICAgIGNvbnN0IHR5cGUgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICAgICAgICAgICAgICBpbXBvcnRzLnB1c2goeyBtb2R1bGUsIG5hbWUsIGtpbmQ6ICJmdW5jdGlvbiIsIHR5cGU6IHR5cGVzW2luZGV4XSB9KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgIGltcG9ydHMucHVzaCh7IG1vZHVsZSwgbmFtZSwga2luZDogInRhYmxlIiwgdHlwZTogcGFyc2VUYWJsZVR5cGUocGFyc2VTdGF0ZSkgfSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgICBpbXBvcnRzLnB1c2goeyBtb2R1bGUsIG5hbWUsIGtpbmQ6ICJtZW1vcnkiLCB0eXBlOiBwYXJzZUxpbWl0cyhwYXJzZVN0YXRlKSB9KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAzOgogICAgICAgICAgICAgIGltcG9ydHMucHVzaCh7IG1vZHVsZSwgbmFtZSwga2luZDogImdsb2JhbCIsIHR5cGU6IHBhcnNlR2xvYmFsVHlwZShwYXJzZVN0YXRlKSB9KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gaW1wb3J0IGRlc2NyaXB0b3IgdHlwZSAke3R5cGV9YCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBpbXBvcnRzOwogICAgICB9CiAgICAgIGRlZmF1bHQ6IHsKICAgICAgICBwYXJzZVN0YXRlLnNraXBCeXRlcyhzZWN0aW9uU2l6ZSk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICB9CiAgcmV0dXJuIFtdOwp9CnZhciBQYXJzZVN0YXRlID0gY2xhc3MgewogIGNvbnN0cnVjdG9yKG1vZHVsZUJ5dGVzKSB7CiAgICB0aGlzLm1vZHVsZUJ5dGVzID0gbW9kdWxlQnl0ZXM7CiAgICB0aGlzLm9mZnNldCA9IDA7CiAgICB0aGlzLnRleHREZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpOwogIH0KICBoYXNNb3JlQnl0ZXMoKSB7CiAgICByZXR1cm4gdGhpcy5vZmZzZXQgPCB0aGlzLm1vZHVsZUJ5dGVzLmxlbmd0aDsKICB9CiAgcmVhZEJ5dGUoKSB7CiAgICByZXR1cm4gdGhpcy5tb2R1bGVCeXRlc1t0aGlzLm9mZnNldCsrXTsKICB9CiAgc2tpcEJ5dGVzKGNvdW50KSB7CiAgICB0aGlzLm9mZnNldCArPSBjb3VudDsKICB9CiAgcmVhZFVuc2lnbmVkTEVCMTI4KCkgewogICAgbGV0IHJlc3VsdCA9IDA7CiAgICBsZXQgc2hpZnQgPSAwOwogICAgbGV0IGJ5dGU7CiAgICBkbyB7CiAgICAgIGJ5dGUgPSB0aGlzLnJlYWRCeXRlKCk7CiAgICAgIHJlc3VsdCB8PSAoYnl0ZSAmIDEyNykgPDwgc2hpZnQ7CiAgICAgIHNoaWZ0ICs9IDc7CiAgICB9IHdoaWxlIChieXRlICYgMTI4KTsKICAgIHJldHVybiByZXN1bHQ7CiAgfQogIHJlYWROYW1lKCkgewogICAgY29uc3QgbmFtZUxlbmd0aCA9IHRoaXMucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgICBjb25zdCBuYW1lQnl0ZXMgPSB0aGlzLm1vZHVsZUJ5dGVzLnNsaWNlKHRoaXMub2Zmc2V0LCB0aGlzLm9mZnNldCArIG5hbWVMZW5ndGgpOwogICAgY29uc3QgbmFtZSA9IHRoaXMudGV4dERlY29kZXIuZGVjb2RlKG5hbWVCeXRlcyk7CiAgICB0aGlzLm9mZnNldCArPSBuYW1lTGVuZ3RoOwogICAgcmV0dXJuIG5hbWU7CiAgfQogIGFzc2VydEJ5dGVzKGV4cGVjdGVkKSB7CiAgICBjb25zdCBiYXNlT2Zmc2V0ID0gdGhpcy5vZmZzZXQ7CiAgICBjb25zdCBleHBlY3RlZExlbmd0aCA9IGV4cGVjdGVkLmxlbmd0aDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZXhwZWN0ZWRMZW5ndGg7IGkrKykgewogICAgICBpZiAodGhpcy5tb2R1bGVCeXRlc1tiYXNlT2Zmc2V0ICsgaV0gIT09IGV4cGVjdGVkW2ldKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCAke2V4cGVjdGVkfSBhdCBvZmZzZXQgJHtiYXNlT2Zmc2V0fWApOwogICAgICB9CiAgICB9CiAgICB0aGlzLm9mZnNldCArPSBleHBlY3RlZExlbmd0aDsKICB9Cn07CmZ1bmN0aW9uIHBhcnNlTWFnaWNOdW1iZXIocGFyc2VTdGF0ZSkgewogIGNvbnN0IGV4cGVjdGVkID0gWzAsIDk3LCAxMTUsIDEwOV07CiAgcGFyc2VTdGF0ZS5hc3NlcnRCeXRlcyhleHBlY3RlZCk7Cn0KZnVuY3Rpb24gcGFyc2VWZXJzaW9uKHBhcnNlU3RhdGUpIHsKICBjb25zdCBleHBlY3RlZCA9IFsxLCAwLCAwLCAwXTsKICBwYXJzZVN0YXRlLmFzc2VydEJ5dGVzKGV4cGVjdGVkKTsKfQpmdW5jdGlvbiBwYXJzZVRhYmxlVHlwZShwYXJzZVN0YXRlKSB7CiAgY29uc3QgZWxlbWVudFR5cGUgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgbGV0IGVsZW1lbnQ7CiAgc3dpdGNoIChlbGVtZW50VHlwZSkgewogICAgY2FzZSAxMTI6CiAgICAgIGVsZW1lbnQgPSAiZnVuY3JlZiI7CiAgICAgIGJyZWFrOwogICAgY2FzZSAxMTE6CiAgICAgIGVsZW1lbnQgPSAiZXh0ZXJucmVmIjsKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gdGFibGUgZWxlbWVudCB0eXBlICR7ZWxlbWVudFR5cGV9YCk7CiAgfQogIGNvbnN0IHsgbWluaW11bSwgbWF4aW11bSB9ID0gcGFyc2VMaW1pdHMocGFyc2VTdGF0ZSk7CiAgaWYgKG1heGltdW0pIHsKICAgIHJldHVybiB7IGVsZW1lbnQsIG1pbmltdW0sIG1heGltdW0gfTsKICB9IGVsc2UgewogICAgcmV0dXJuIHsgZWxlbWVudCwgbWluaW11bSB9OwogIH0KfQpmdW5jdGlvbiBwYXJzZUxpbWl0cyhwYXJzZVN0YXRlKSB7CiAgY29uc3QgZmxhZ3MgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgY29uc3QgbWluaW11bSA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgY29uc3QgaGFzTWF4aW11bSA9IGZsYWdzICYgMTsKICBjb25zdCBzaGFyZWQgPSAoZmxhZ3MgJiAyKSAhPT0gMDsKICBjb25zdCBpc01lbW9yeTY0ID0gKGZsYWdzICYgNCkgIT09IDA7CiAgY29uc3QgaW5kZXggPSBpc01lbW9yeTY0ID8gImk2NCIgOiAiaTMyIjsKICBpZiAoaGFzTWF4aW11bSkgewogICAgY29uc3QgbWF4aW11bSA9IHBhcnNlU3RhdGUucmVhZFVuc2lnbmVkTEVCMTI4KCk7CiAgICByZXR1cm4geyBtaW5pbXVtLCBzaGFyZWQsIGluZGV4LCBtYXhpbXVtIH07CiAgfSBlbHNlIHsKICAgIHJldHVybiB7IG1pbmltdW0sIHNoYXJlZCwgaW5kZXggfTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VHbG9iYWxUeXBlKHBhcnNlU3RhdGUpIHsKICBjb25zdCB2YWx1ZSA9IHBhcnNlVmFsdWVUeXBlKHBhcnNlU3RhdGUpOwogIGNvbnN0IG11dGFibGUgPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCkgPT09IDE7CiAgcmV0dXJuIHsgdmFsdWUsIG11dGFibGUgfTsKfQpmdW5jdGlvbiBwYXJzZVZhbHVlVHlwZShwYXJzZVN0YXRlKSB7CiAgY29uc3QgdHlwZSA9IHBhcnNlU3RhdGUucmVhZEJ5dGUoKTsKICBzd2l0Y2ggKHR5cGUpIHsKICAgIGNhc2UgMTI3OgogICAgICByZXR1cm4gImkzMiI7CiAgICBjYXNlIDEyNjoKICAgICAgcmV0dXJuICJpNjQiOwogICAgY2FzZSAxMjU6CiAgICAgIHJldHVybiAiZjMyIjsKICAgIGNhc2UgMTI0OgogICAgICByZXR1cm4gImY2NCI7CiAgICBjYXNlIDExMjoKICAgICAgcmV0dXJuICJmdW5jcmVmIjsKICAgIGNhc2UgMTExOgogICAgICByZXR1cm4gImV4dGVybnJlZiI7CiAgICBjYXNlIDEyMzoKICAgICAgcmV0dXJuICJ2MTI4IjsKICAgIGRlZmF1bHQ6CiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biB2YWx1ZSB0eXBlICR7dHlwZX1gKTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VGdW5jdGlvblR5cGUocGFyc2VTdGF0ZSkgewogIGNvbnN0IGZvcm0gPSBwYXJzZVN0YXRlLnJlYWRCeXRlKCk7CiAgaWYgKGZvcm0gIT09IDk2KSB7CiAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGZ1bmN0aW9uIHR5cGUgZm9ybSAweDYwLCBnb3QgJHtmb3JtfWApOwogIH0KICBjb25zdCBwYXJhbWV0ZXJzID0gW107CiAgY29uc3QgcGFyYW1ldGVyQ291bnQgPSBwYXJzZVN0YXRlLnJlYWRVbnNpZ25lZExFQjEyOCgpOwogIGZvciAobGV0IGkgPSAwOyBpIDwgcGFyYW1ldGVyQ291bnQ7IGkrKykgewogICAgcGFyYW1ldGVycy5wdXNoKHBhcnNlVmFsdWVUeXBlKHBhcnNlU3RhdGUpKTsKICB9CiAgY29uc3QgcmVzdWx0cyA9IFtdOwogIGNvbnN0IHJlc3VsdENvdW50ID0gcGFyc2VTdGF0ZS5yZWFkVW5zaWduZWRMRUIxMjgoKTsKICBmb3IgKGxldCBpID0gMDsgaSA8IHJlc3VsdENvdW50OyBpKyspIHsKICAgIHJlc3VsdHMucHVzaChwYXJzZVZhbHVlVHlwZShwYXJzZVN0YXRlKSk7CiAgfQogIHJldHVybiB7IHBhcmFtZXRlcnMsIHJlc3VsdHMgfTsKfQoKLy8gbm9kZV9tb2R1bGVzL3dhc20taW1wb3J0cy1wYXJzZXIvcG9seWZpbGwuanMKdmFyIGhhc1dhc21UeXBlUmVmbGVjdGlvblN1cHBvcnQgPSAoKCkgPT4gewogIGNvbnN0IG1vZHVsZUJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoWwogICAgMCwKICAgIDk3LAogICAgMTE1LAogICAgMTA5LAogICAgMSwKICAgIDAsCiAgICAwLAogICAgMCwKICAgIDIsCiAgICA2LAogICAgMSwKICAgIDAsCiAgICAwLAogICAgMiwKICAgIDAsCiAgICAxCiAgXSk7CiAgY29uc3QgbW9kdWxlID0gbmV3IFdlYkFzc2VtYmx5Lk1vZHVsZShtb2R1bGVCeXRlcyk7CiAgY29uc3QgaW1wb3J0cyA9IFdlYkFzc2VtYmx5Lk1vZHVsZS5pbXBvcnRzKG1vZHVsZSk7CiAgY29uc3QgbWVtb3J5SW1wb3J0ID0gaW1wb3J0c1swXTsKICByZXR1cm4gdHlwZW9mIG1lbW9yeUltcG9ydC50eXBlID09PSAib2JqZWN0IjsKfSkoKTsKZnVuY3Rpb24gcG9seWZpbGwoV2ViQXNzZW1ibHkzKSB7CiAgaWYgKGhhc1dhc21UeXBlUmVmbGVjdGlvblN1cHBvcnQpIHsKICAgIHJldHVybiBXZWJBc3NlbWJseTM7CiAgfQogIGNvbnN0IG5ld1dlYkFzc2VtYmx5ID0ge307CiAgZm9yIChjb25zdCBrZXkgaW4gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMoV2ViQXNzZW1ibHkzKSkgewogICAgbmV3V2ViQXNzZW1ibHlba2V5XSA9IFdlYkFzc2VtYmx5M1trZXldOwogIH0KICBjb25zdCBwb2x5ZmlsbGVkSW1wb3J0c1N5bWJvbCA9IFN5bWJvbCgicG9seWZpbGxlZEltcG9ydHNTeW1ib2wiKTsKICBjb25zdCBhc3NpZ25JbXBvcnRzID0gKG1vZHVsZSwgc291cmNlQnl0ZXMpID0+IHsKICAgIG1vZHVsZVtwb2x5ZmlsbGVkSW1wb3J0c1N5bWJvbF0gPSBwYXJzZUltcG9ydHMoc291cmNlQnl0ZXMpOwogIH07CiAgY29uc3QgbmV3TW9kdWxlID0gbmV3V2ViQXNzZW1ibHkuTW9kdWxlID0gZnVuY3Rpb24oYnl0ZXMpIHsKICAgIGNvbnN0IG1vZHVsZSA9IG5ldyBXZWJBc3NlbWJseTMuTW9kdWxlKGJ5dGVzKTsKICAgIGFzc2lnbkltcG9ydHMobW9kdWxlLCBieXRlcyk7CiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YobW9kdWxlLCBuZXdNb2R1bGUucHJvdG90eXBlKTsKICAgIHJldHVybiBtb2R1bGU7CiAgfTsKICBPYmplY3Quc2V0UHJvdG90eXBlT2YobmV3TW9kdWxlLnByb3RvdHlwZSwgV2ViQXNzZW1ibHkzLk1vZHVsZS5wcm90b3R5cGUpOwogIG5ld1dlYkFzc2VtYmx5LmNvbXBpbGUgPSBhc3luYyAoc291cmNlKSA9PiB7CiAgICBjb25zdCBtb2R1bGUgPSBhd2FpdCBXZWJBc3NlbWJseTMuY29tcGlsZShzb3VyY2UpOwogICAgYXNzaWduSW1wb3J0cyhtb2R1bGUsIHNvdXJjZSk7CiAgICByZXR1cm4gbW9kdWxlOwogIH07CiAgaWYgKFdlYkFzc2VtYmx5My5jb21waWxlU3RyZWFtaW5nKSB7CiAgICBuZXdXZWJBc3NlbWJseS5jb21waWxlU3RyZWFtaW5nID0gYXN5bmMgKHNvdXJjZSkgPT4gewogICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHNvdXJjZTsKICAgICAgY29uc3QgY2xvbmUgPSByZXNwb25zZS5jbG9uZSgpOwogICAgICBjb25zdCBtb2R1bGUgPSBhd2FpdCBXZWJBc3NlbWJseTMuY29tcGlsZVN0cmVhbWluZyhyZXNwb25zZSk7CiAgICAgIGFzc2lnbkltcG9ydHMobW9kdWxlLCBuZXcgVWludDhBcnJheShhd2FpdCBjbG9uZS5hcnJheUJ1ZmZlcigpKSk7CiAgICAgIHJldHVybiBtb2R1bGU7CiAgICB9OwogIH0KICBuZXdNb2R1bGUuaW1wb3J0cyA9IChtb2R1bGUpID0+IHsKICAgIGNvbnN0IHBhcnNlZEltcG9ydHMgPSBtb2R1bGVbcG9seWZpbGxlZEltcG9ydHNTeW1ib2xdOwogICAgaWYgKCFwYXJzZWRJbXBvcnRzKSB7CiAgICAgIHJldHVybiBXZWJBc3NlbWJseTMuTW9kdWxlLmltcG9ydHMobW9kdWxlKTsKICAgIH0KICAgIHJldHVybiBwYXJzZWRJbXBvcnRzOwogIH07CiAgcmV0dXJuIG5ld1dlYkFzc2VtYmx5Owp9CgovLyBlbnRyeXBvaW50L2ludHJpbnNpY3MudHMKdmFyIFdlYkFzc2VtYmx5MiA9IHBvbHlmaWxsKGdsb2JhbFRoaXMuV2ViQXNzZW1ibHkpOwp2YXIgTGluZURlY29kZXIgPSBjbGFzcyB7CiAgY29uc3RydWN0b3Iob25MaW5lKSB7CiAgICB0aGlzLmRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoInV0Zi04IiwgeyBmYXRhbDogZmFsc2UgfSk7CiAgICB0aGlzLmJ1ZmZlciA9ICIiOwogICAgdGhpcy5vbkxpbmUgPSBvbkxpbmU7CiAgfQogIGRlY29kZXI7CiAgYnVmZmVyOwogIG9uTGluZTsKICBzZW5kKGNodW5rKSB7CiAgICB0aGlzLmJ1ZmZlciArPSB0aGlzLmRlY29kZXIuZGVjb2RlKGNodW5rLCB7IHN0cmVhbTogdHJ1ZSB9KTsKICAgIGNvbnN0IGxpbmVzID0gdGhpcy5idWZmZXIuc3BsaXQoIlxuIik7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aCAtIDE7IGkrKykgewogICAgICB0aGlzLm9uTGluZShsaW5lc1tpXSk7CiAgICB9CiAgICB0aGlzLmJ1ZmZlciA9IGxpbmVzW2xpbmVzLmxlbmd0aCAtIDFdOwogIH0KfTsKYXN5bmMgZnVuY3Rpb24gaW5zdGFudGlhdGUocmF3T3B0aW9ucywgZXh0cmFXYXNtSW1wb3J0cykgewogIGNvbnN0IG9wdGlvbnMgPSBkZWZhdWx0SW5zdGFudGlhdGlvbk9wdGlvbnMocmF3T3B0aW9ucyk7CiAgbGV0IHN3aWZ0ID0gb3B0aW9ucy5zd2lmdDsKICBpZiAoIXN3aWZ0ICYmIG9wdGlvbnMuU3dpZnRSdW50aW1lKSB7CiAgICBzd2lmdCA9IG5ldyBvcHRpb25zLlN3aWZ0UnVudGltZSgpOwogIH0KICBsZXQgc3Rkb3V0TGluZSA9IHZvaWQgMDsKICBpZiAob3B0aW9ucy5vblN0ZG91dExpbmUgIT0gbnVsbCkgewogICAgc3Rkb3V0TGluZSA9IG5ldyBMaW5lRGVjb2RlcihvcHRpb25zLm9uU3Rkb3V0TGluZSk7CiAgfQogIGNvbnN0IHN0ZG91dCA9IG5ldyBDb25zb2xlU3Rkb3V0KChjaHVuaykgPT4gewogICAgb3B0aW9ucy5vblN0ZG91dD8uY2FsbCh2b2lkIDAsIGNodW5rKTsKICAgIHN0ZG91dExpbmU/LnNlbmQoY2h1bmspOwogIH0pOwogIGxldCBzdGRlcnJMaW5lID0gdm9pZCAwOwogIGlmIChvcHRpb25zLm9uU3RkZXJyTGluZSAhPSBudWxsKSB7CiAgICBzdGRlcnJMaW5lID0gbmV3IExpbmVEZWNvZGVyKG9wdGlvbnMub25TdGRlcnJMaW5lKTsKICB9CiAgY29uc3Qgc3RkZXJyID0gbmV3IENvbnNvbGVTdGRvdXQoKGNodW5rKSA9PiB7CiAgICBvcHRpb25zLm9uU3RkZXJyPy5jYWxsKHZvaWQgMCwgY2h1bmspOwogICAgc3RkZXJyTGluZT8uc2VuZChjaHVuayk7CiAgfSk7CiAgY29uc3QgYXJncyA9IG9wdGlvbnMuYXJncyB8fCBbXTsKICBjb25zdCBmZHMgPSBbCiAgICBuZXcgT3BlbkZpbGUobmV3IEZpbGUoW10pKSwKICAgIHN0ZG91dCwKICAgIHN0ZGVyciwKICAgIG5ldyBQcmVvcGVuRGlyZWN0b3J5KCIvIiwgLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKSkKICBdOwogIGNvbnN0IGVudnMgPSBvcHRpb25zLmVudiA/IE9iamVjdC5lbnRyaWVzKG9wdGlvbnMuZW52KS5tYXAoKFtrZXksIHZhbHVlXSkgPT4gYCR7a2V5fT0ke3ZhbHVlfWApIDogW107CiAgY29uc3Qgd2FzaSA9IG5ldyBXQVNJKGFyZ3MsIGVudnMsIGZkcywgewogICAgZGVidWc6IGZhbHNlCiAgfSk7CiAgY29uc3QgY3JlYXRlV2FzbUltcG9ydE9iamVjdCA9IChleHRyYVdhc21JbXBvcnRzMiwgbW9kdWxlKSA9PiB7CiAgICBjb25zdCBpbXBvcnRPYmplY3QyID0gewogICAgICB3YXNpX3NuYXBzaG90X3ByZXZpZXcxOiB3YXNpLndhc2lJbXBvcnQKICAgIH07CiAgICBpZiAoc3dpZnQpIHsKICAgICAgaW1wb3J0T2JqZWN0Mi5qYXZhc2NyaXB0X2tpdCA9IHN3aWZ0Lndhc21JbXBvcnRzOwogICAgfQogICAgaWYgKGV4dHJhV2FzbUltcG9ydHMyKSB7CiAgICAgIGZvciAoY29uc3QgbW9kdWxlTmFtZSBpbiBleHRyYVdhc21JbXBvcnRzMikgewogICAgICAgIGlmICghaW1wb3J0T2JqZWN0Mlttb2R1bGVOYW1lXSkgewogICAgICAgICAgaW1wb3J0T2JqZWN0Mlttb2R1bGVOYW1lXSA9IHt9OwogICAgICAgIH0KICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IGluIGV4dHJhV2FzbUltcG9ydHMyW21vZHVsZU5hbWVdKSB7CiAgICAgICAgICBpbXBvcnRPYmplY3QyW21vZHVsZU5hbWVdW2VudHJ5XSA9IGV4dHJhV2FzbUltcG9ydHMyW21vZHVsZU5hbWVdW2VudHJ5XTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGZvciAoY29uc3QgX2ltcG9ydEVudHJ5IG9mIFdlYkFzc2VtYmx5Mi5Nb2R1bGUuaW1wb3J0cyhtb2R1bGUpKSB7CiAgICAgIGNvbnN0IGltcG9ydEVudHJ5ID0gX2ltcG9ydEVudHJ5OwogICAgICBpZiAoIWltcG9ydE9iamVjdDJbaW1wb3J0RW50cnkubW9kdWxlXSkgewogICAgICAgIGltcG9ydE9iamVjdDJbaW1wb3J0RW50cnkubW9kdWxlXSA9IHt9OwogICAgICB9CiAgICAgIGlmIChpbXBvcnRPYmplY3QyW2ltcG9ydEVudHJ5Lm1vZHVsZV1baW1wb3J0RW50cnkubmFtZV0pIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoaW1wb3J0RW50cnkua2luZCA9PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgaW1wb3J0T2JqZWN0MltpbXBvcnRFbnRyeS5tb2R1bGVdW2ltcG9ydEVudHJ5Lm5hbWVdID0gKCkgPT4gewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbXBvcnRlZCBmdW5jdGlvbiAke2ltcG9ydEVudHJ5Lm1vZHVsZX0uJHtpbXBvcnRFbnRyeS5uYW1lfSBub3QgaW1wbGVtZW50ZWRgKTsKICAgICAgICB9OwogICAgICB9IGVsc2UgaWYgKGltcG9ydEVudHJ5LmtpbmQgPT0gIm1lbW9yeSIgJiYgaW1wb3J0RW50cnkubW9kdWxlID09ICJlbnYiICYmIGltcG9ydEVudHJ5Lm5hbWUgPT0gIm1lbW9yeSIpIHsKICAgICAgICBjb25zdCB0eXBlID0gaW1wb3J0RW50cnkudHlwZTsKICAgICAgICBjb25zdCBkZXNjcmlwdG9yID0gewogICAgICAgICAgaW5pdGlhbDogdHlwZS5taW5pbXVtLAogICAgICAgICAgbWF4aW11bTogdHlwZS5tYXhpbXVtLAogICAgICAgICAgc2hhcmVkOiB0eXBlLnNoYXJlZAogICAgICAgIH07CiAgICAgICAgaW1wb3J0T2JqZWN0MltpbXBvcnRFbnRyeS5tb2R1bGVdW2ltcG9ydEVudHJ5Lm5hbWVdID0gbmV3IFdlYkFzc2VtYmx5Mi5NZW1vcnkoZGVzY3JpcHRvcik7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBpbXBvcnRPYmplY3QyOwogIH07CiAgY29uc3QgaW1wb3J0T2JqZWN0ID0gY3JlYXRlV2FzbUltcG9ydE9iamVjdChleHRyYVdhc21JbXBvcnRzLCBvcHRpb25zLm1vZHVsZSk7CiAgY29uc3QgaW5zdGFuY2UgPSBhd2FpdCBXZWJBc3NlbWJseTIuaW5zdGFudGlhdGUob3B0aW9ucy5tb2R1bGUsIGltcG9ydE9iamVjdCk7CiAgaWYgKHN3aWZ0ICYmIGluc3RhbmNlLmV4cG9ydHMuc3dqc19saWJyYXJ5X3ZlcnNpb24pIHsKICAgIHN3aWZ0LnNldEluc3RhbmNlKGluc3RhbmNlKTsKICB9CiAgaWYgKHR5cGVvZiBpbnN0YW5jZS5leHBvcnRzLl9zdGFydCA9PT0gImZ1bmN0aW9uIikgewogICAgd2FzaS5zdGFydChpbnN0YW5jZSk7CiAgfSBlbHNlIGlmICh0eXBlb2YgaW5zdGFuY2UuZXhwb3J0cy5faW5pdGlhbGl6ZSA9PSAiZnVuY3Rpb24iKSB7CiAgICB3YXNpLmluaXRpYWxpemUoaW5zdGFuY2UpOwogICAgaWYgKHN3aWZ0ICYmIHN3aWZ0Lm1haW4pIHsKICAgICAgc3dpZnQubWFpbigpOwogICAgfSBlbHNlIHsKICAgICAgaWYgKHR5cGVvZiBpbnN0YW5jZS5leHBvcnRzLm1haW4gPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICBpbnN0YW5jZS5leHBvcnRzLm1haW4oKTsKICAgICAgfSBlbHNlIGlmICh0eXBlb2YgaW5zdGFuY2UuZXhwb3J0cy5fX21haW5fYXJnY19hcmd2ID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgaW5zdGFuY2UuZXhwb3J0cy5fX21haW5fYXJnY19hcmd2KDAsIDApOwogICAgICB9CiAgICB9CiAgfQogIHJldHVybiB7IGluc3RhbmNlIH07Cn0KZnVuY3Rpb24gZGVmYXVsdEluc3RhbnRpYXRpb25PcHRpb25zKG9wdGlvbnMpIHsKICBpZiAob3B0aW9ucy5hcmdzID09IG51bGwpIHsKICAgIG9wdGlvbnMuYXJncyA9IFsibWFpbi53YXNtIl07CiAgfQogIGNvbnN0IGlzTm9kZUpzID0gdHlwZW9mIHByb2Nlc3MgIT09ICJ1bmRlZmluZWQiICYmIHByb2Nlc3MucmVsZWFzZS5uYW1lID09PSAibm9kZSI7CiAgY29uc3QgaXNXZWJCcm93c2VyID0gdHlwZW9mIHdpbmRvdyAhPT0gInVuZGVmaW5lZCI7CiAgaWYgKGlzTm9kZUpzKSB7CiAgICBpZiAoIW9wdGlvbnMub25TdGRvdXQpIHsKICAgICAgb3B0aW9ucy5vblN0ZG91dCA9IChjaHVuaykgPT4gcHJvY2Vzcy5zdGRvdXQud3JpdGUoY2h1bmspOwogICAgfQogICAgaWYgKCFvcHRpb25zLm9uU3RkZXJyKSB7CiAgICAgIG9wdGlvbnMub25TdGRlcnIgPSAoY2h1bmspID0+IHByb2Nlc3Muc3RkZXJyLndyaXRlKGNodW5rKTsKICAgIH0KICB9IGVsc2UgaWYgKGlzV2ViQnJvd3NlcikgewogICAgaWYgKCFvcHRpb25zLm9uU3Rkb3V0TGluZSkgewogICAgICBvcHRpb25zLm9uU3Rkb3V0TGluZSA9IChsaW5lKSA9PiBjb25zb2xlLmxvZyhsaW5lKTsKICAgIH0KICAgIGlmICghb3B0aW9ucy5vblN0ZGVyckxpbmUpIHsKICAgICAgb3B0aW9ucy5vblN0ZGVyckxpbmUgPSAobGluZSkgPT4gY29uc29sZS53YXJuKGxpbmUpOwogICAgfQogIH0KICByZXR1cm4gb3B0aW9uczsKfQphc3luYyBmdW5jdGlvbiB0ZXN0QnJvd3NlcihpbnN0YW50aWF0ZTIsIHdhc21GaWxlTmFtZSwgYXJncywgaW5kZXhKc1VybCwgaW5QYWdlKSB7CiAgaWYgKGluUGFnZSkgewogICAgcmV0dXJuIGF3YWl0IHRlc3RCcm93c2VySW5QYWdlKGluc3RhbnRpYXRlMiwgd2FzbUZpbGVOYW1lLCBhcmdzKTsKICB9CiAgY29uc3QgcGxheXdyaWdodCA9IGF3YWl0IChhc3luYyAoKSA9PiB7CiAgICB0cnkgewogICAgICByZXR1cm4gYXdhaXQgaW1wb3J0KCJwbGF5d3JpZ2h0Iik7CiAgICB9IGNhdGNoIHsKICAgICAgY29uc29sZS5lcnJvcihgUGxheXdyaWdodCBpcyBub3QgYXZhaWxhYmxlIGluIHRoZSBjdXJyZW50IGVudmlyb25tZW50LgpQbGVhc2UgcnVuIHRoZSBmb2xsb3dpbmcgY29tbWFuZCB0byBpbnN0YWxsIGl0OgoKICAgICQgbnBtIGluc3RhbGwgcGxheXdyaWdodCAmJiBucHggcGxheXdyaWdodCBpbnN0YWxsIGNocm9taXVtCmApOwogICAgICBwcm9jZXNzLmV4aXQoMSk7CiAgICB9CiAgfSkoKTsKICBjb25zdCBicm93c2VyID0gYXdhaXQgcGxheXdyaWdodC5jaHJvbWl1bS5sYXVuY2goKTsKICBjb25zdCBjb250ZXh0ID0gYXdhaXQgYnJvd3Nlci5uZXdDb250ZXh0KCk7CiAgY29uc3QgcGFnZSA9IGF3YWl0IGNvbnRleHQubmV3UGFnZSgpOwogIGNvbnN0IHsgZmlsZVVSTFRvUGF0aCB9ID0gYXdhaXQgaW1wb3J0KCJub2RlOnVybCIpOwogIGNvbnN0IHBhdGggPSBhd2FpdCBpbXBvcnQoIm5vZGU6cGF0aCIpOwogIGNvbnN0IGluZGV4SnNQYXRoID0gZmlsZVVSTFRvUGF0aChpbmRleEpzVXJsKTsKICBjb25zdCB3ZWJSb290ID0gcGF0aC5kaXJuYW1lKGluZGV4SnNQYXRoKTsKICBwYWdlLm9uKCJjb25zb2xlIiwgKG1lc3NhZ2UpID0+IHsKICAgIGNvbnNvbGUubG9nKG1lc3NhZ2UudGV4dCgpKTsKICB9KTsKICBhd2FpdCBwYWdlLnJvdXRlKCJodHRwOi8vZXhhbXBsZS5jb20vKiovKiIsIGFzeW5jIChyb3V0ZSkgPT4gewogICAgY29uc3QgdXJsID0gcm91dGUucmVxdWVzdCgpLnVybCgpOwogICAgY29uc3QgdXJsUGF0aCA9IG5ldyBVUkwodXJsKS5wYXRobmFtZTsKICAgIGlmICh1cmxQYXRoID09PSAiL3Byb2Nlc3MtaW5mby5qc29uIikgewogICAgICByb3V0ZS5mdWxmaWxsKHsgYm9keTogSlNPTi5zdHJpbmdpZnkoeyBlbnY6IHByb2Nlc3MuZW52IH0pIH0pOwogICAgICByZXR1cm47CiAgICB9CiAgICByb3V0ZS5mdWxmaWxsKHsgcGF0aDogcGF0aC5qb2luKHdlYlJvb3QsIHVybFBhdGguc2xpY2UoMSkpIH0pOwogIH0pOwogIGNvbnN0IG9uRXhpdCA9IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7CiAgICBwYWdlLmV4cG9zZUZ1bmN0aW9uKCJleGl0VGVzdCIsIHJlc29sdmUpOwogIH0pOwogIGF3YWl0IHBhZ2UuZ290bygiaHR0cDovL2V4YW1wbGUuY29tL3Rlc3QuYnJvd3Nlci5odG1sIik7CiAgY29uc3QgZXhpdENvZGUgPSBhd2FpdCBvbkV4aXQ7CiAgYXdhaXQgYnJvd3Nlci5jbG9zZSgpOwogIHByb2Nlc3MuZXhpdChleGl0Q29kZSk7Cn0KYXN5bmMgZnVuY3Rpb24gdGVzdEJyb3dzZXJJblBhZ2UoaW5zdGFudGlhdGUyLCB3YXNtRmlsZU5hbWUsIGFyZ3MpIHsKICBjb25zdCBsb2dFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgicHJlIik7CiAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChsb2dFbGVtZW50KTsKICBjb25zdCBleGl0VGVzdCA9IChjb2RlKSA9PiB7CiAgICBjb25zdCBmbiA9IHdpbmRvdy5leGl0VGVzdDsKICAgIGlmIChmbikgewogICAgICBmbihjb2RlKTsKICAgIH0KICB9OwogIGNvbnN0IGNvbmZpZyA9IGF3YWl0IGZldGNoKCIvcHJvY2Vzcy1pbmZvLmpzb24iKS50aGVuKChyZXNwb25zZSkgPT4gcmVzcG9uc2UuanNvbigpKTsKICBjb25zdCBoYW5kbGVFcnJvciA9IChlcnJvcikgPT4gewogICAgY29uc29sZS5lcnJvcihlcnJvcik7CiAgICBleGl0VGVzdCgxKTsKICB9OwogIGNvbnN0IGhhbmRsZUV4aXRPckVycm9yID0gKGVycm9yKSA9PiB7CiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBXQVNJUHJvY0V4aXQpIHsKICAgICAgaWYgKGVycm9yLmNvZGUgPT09IDApIHsKICAgICAgICBleGl0VGVzdCgwKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBoYW5kbGVFcnJvcihlcnJvcik7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGhhbmRsZUVycm9yKGVycm9yKTsKICAgIH0KICB9OwogIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJ1bmhhbmRsZWRyZWplY3Rpb24iLCAoZXZlbnQpID0+IHsKICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7CiAgICBjb25zdCBlcnJvciA9IGV2ZW50LnJlYXNvbjsKICAgIGhhbmRsZUV4aXRPckVycm9yKGVycm9yKTsKICB9KTsKICB0cnkgewogICAgYXdhaXQgaW5zdGFudGlhdGUyKHsKICAgICAgZW52OiBjb25maWcuZW52LAogICAgICBhcmdzOiBbd2FzbUZpbGVOYW1lXS5jb25jYXQoYXJncyksCiAgICAgIG9uU3Rkb3V0TGluZShsaW5lKSB7CiAgICAgICAgY29uc29sZS5sb2cobGluZSk7CiAgICAgICAgbG9nRWxlbWVudC50ZXh0Q29udGVudCArPSBsaW5lICsgIlxuIjsKICAgICAgfSwKICAgICAgb25TdGRlcnJMaW5lKGxpbmUpIHsKICAgICAgICBjb25zb2xlLndhcm4obGluZSk7CiAgICAgICAgbG9nRWxlbWVudC50ZXh0Q29udGVudCArPSBsaW5lICsgIlxuIjsKICAgICAgfQogICAgfSwgewogICAgICAid2FzaV9zbmFwc2hvdF9wcmV2aWV3MSI6IHsKICAgICAgICBwcm9jX2V4aXQ6IChjb2RlKSA9PiB7CiAgICAgICAgICBleGl0VGVzdChjb2RlKTsKICAgICAgICAgIHRocm93IG5ldyBXQVNJUHJvY0V4aXQoY29kZSk7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICB9IGNhdGNoIChlcnJvcikgewogICAgaGFuZGxlRXhpdE9yRXJyb3IoZXJyb3IpOwogIH0KfQphc3luYyBmdW5jdGlvbiB0ZXN0Tm9kZShpbnN0YW50aWF0ZTIsIHdhc21GaWxlTmFtZSwgYXJncykgewogIGNvbnN0IGVudiA9IHt9OwogIGZvciAoY29uc3Qga2V5IGluIHByb2Nlc3MuZW52KSB7CiAgICBjb25zdCB2YWx1ZSA9IHByb2Nlc3MuZW52W2tleV07CiAgICBpZiAodmFsdWUpIHsKICAgICAgZW52W2tleV0gPSB2YWx1ZTsKICAgIH0KICB9CiAgbGV0IHByb2NFeGl0Q2FsbGVkID0gZmFsc2U7CiAgY29uc3QgeyBjcmVhdGVSZXF1aXJlIH0gPSBhd2FpdCBpbXBvcnQoIm5vZGU6bW9kdWxlIik7CiAgY29uc3QgcmVxdWlyZTIgPSBjcmVhdGVSZXF1aXJlKGltcG9ydC5tZXRhLnVybCk7CiAgZ2xvYmFsVGhpcy5yZXF1aXJlID0gcmVxdWlyZTI7CiAgcHJvY2Vzcy5vbigiYmVmb3JlRXhpdCIsICgpID0+IHsKICAgIGlmICghcHJvY0V4aXRDYWxsZWQpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKGBUZXN0IGhhcm5lc3MgcHJvY2VzcyBleGl0ZWQgYmVmb3JlIHRlc3QgcHJvY2Vzcy4KVGhpcyB1c3VhbGx5IG1lYW5zIHRoZXJlIGFyZSBzb21lIGRhbmdsaW5nIGNvbnRpbnVhdGlvbnMsIHdoaWNoIGFyZSBhd2FpdGVkIGJ1dCBuZXZlciByZXN1bWVkLmApOwogICAgfQogIH0pOwogIGF3YWl0IGluc3RhbnRpYXRlMih7IGVudiwgYXJnczogW3dhc21GaWxlTmFtZV0uY29uY2F0KGFyZ3MpIH0sIHsKICAgICJ3YXNpX3NuYXBzaG90X3ByZXZpZXcxIjogewogICAgICBwcm9jX2V4aXQ6IChjb2RlKSA9PiB7CiAgICAgICAgcHJvY0V4aXRDYWxsZWQgPSB0cnVlOwogICAgICAgIHByb2Nlc3MuZXhpdChjb2RlKTsKICAgICAgfQogICAgfQogIH0pOwp9CmV4cG9ydCB7CiAgV2ViQXNzZW1ibHkyIGFzIFdlYkFzc2VtYmx5LAogIGluc3RhbnRpYXRlLAogIHRlc3RCcm93c2VyLAogIHRlc3ROb2RlCn07Cg==")! } \ No newline at end of file diff --git a/Sources/CartonKit/Parsers/DiagnosticsParser.swift b/Sources/CartonKit/Parsers/DiagnosticsParser.swift index 7732a326..a0097fc2 100644 --- a/Sources/CartonKit/Parsers/DiagnosticsParser.swift +++ b/Sources/CartonKit/Parsers/DiagnosticsParser.swift @@ -13,30 +13,3 @@ // limitations under the License. import Foundation - -/// Parses and re-formats diagnostics output by the Swift compiler. -/// -/// The compiler output often repeats itself, and the diagnostics can sometimes be -/// difficult to read. -/// This reformats them to a more readable output. -struct DiagnosticsParser { - struct CustomDiagnostic { - let kind: Kind - let file: String - let line: String.SubSequence - let char: String.SubSequence - let code: String - let message: String - - enum Kind: String { - case error, warning, note - var color: String { - switch self { - case .error: return "[41;1m" // bright red background - case .warning: return "[43;1m" // bright yellow background - case .note: return "[7m" // reversed - } - } - } - } -} diff --git a/Sources/CartonKit/Server/Server.swift b/Sources/CartonKit/Server/Server.swift index fa58581f..e2fdc7aa 100644 --- a/Sources/CartonKit/Server/Server.swift +++ b/Sources/CartonKit/Server/Server.swift @@ -23,20 +23,15 @@ private enum Event { enum CodingKeys: String, CodingKey { case kind case stackTrace - case testRunOutput case errorReport } enum Kind: String, Decodable { case stackTrace - case testRunOutput - case testPassed case errorReport } case stackTrace(String) - case testRunOutput(String) - case testPassed case errorReport(String) } @@ -50,11 +45,6 @@ extension Event: Decodable { case .stackTrace: let rawStackTrace = try container.decode(String.self, forKey: .stackTrace) self = .stackTrace(rawStackTrace) - case .testRunOutput: - let output = try container.decode(String.self, forKey: .testRunOutput) - self = .testRunOutput(output) - case .testPassed: - self = .testPassed case .errorReport: let output = try container.decode(String.self, forKey: .errorReport) self = .errorReport(output) @@ -135,7 +125,7 @@ public actor Server { self.version = version self.pid = pid } - + public var name: String public var version: String public var pid: Int32 @@ -148,7 +138,8 @@ public actor Server { public static func parse(_ string: String) throws -> ServerNameField { guard let m = try regex.wholeMatch(in: string), - let pid = Int32(m.output.3) else { + let pid = Int32(m.output.3) + else { throw CartonCoreError("invalid server name: \(string)") } @@ -178,9 +169,6 @@ public actor Server { /// Whether a subsequent build is currently scheduled on top of a currently running build. private var isSubsequentBuildScheduled = false - /// Continuation for waitUntilTestFinished, passing `hadError: Bool` - private var onTestFinishedContinuation: CheckedContinuation? - private let configuration: Configuration private let serverName: ServerNameField @@ -392,16 +380,6 @@ public actor Server { try closeSockets() } - /// Wait and handle the shutdown - public func waitUntilTestFinished() async throws -> Bool { - let hadError = await withCheckedContinuation { cont in - self.onTestFinishedContinuation = cont - } - self.onTestFinishedContinuation = nil - try closeSockets() - return hadError - } - func closeSockets() throws { for conn in connections { try conn.close().wait() @@ -428,10 +406,6 @@ public actor Server { terminal.logLookup("The app is currently hosted at ", localURL) connections.forEach { $0.reload() } } - - private func stopTest(hadError: Bool) { - self.onTestFinishedContinuation?.resume(returning: hadError) - } } extension Server { @@ -461,23 +435,15 @@ extension Server { terminal.write("\nAn error occurred, here's the raw stack trace for it:\n", inColor: .red) terminal.write( " Please create an issue or PR to the Carton repository\n" - + " with your browser name and this raw stack trace so\n" - + " we can add support for it: https://github.com/swiftwasm/carton\n", inColor: .gray + + " with your browser name and this raw stack trace so\n" + + " we can add support for it: https://github.com/swiftwasm/carton\n", inColor: .gray ) terminal.write(rawStackTrace + "\n") } - case let .testRunOutput(output): - TestsParser().parse(output, terminal) - - case .testPassed: - Task { await self.stopTest(hadError: false) } - case let .errorReport(output): terminal.write("\nAn error occurred:\n", inColor: .red) terminal.write(output + "\n") - - Task { await self.stopTest(hadError: true) } } } diff --git a/Sources/CartonKit/Utilities/EnvironmentEx.swift b/Sources/CartonKit/Utilities/EnvironmentEx.swift deleted file mode 100644 index db1e470e..00000000 --- a/Sources/CartonKit/Utilities/EnvironmentEx.swift +++ /dev/null @@ -1,4 +0,0 @@ -import ArgumentParser -import CartonCore - -extension Environment: ArgumentParser.ExpressibleByArgument {} diff --git a/Sources/carton-frontend-slim/BundleLayout.swift b/Sources/carton-frontend-slim/BundleLayout.swift new file mode 100644 index 00000000..3d586c5a --- /dev/null +++ b/Sources/carton-frontend-slim/BundleLayout.swift @@ -0,0 +1,230 @@ +// Copyright 2024 Carton 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. + +import CartonCore +import CartonHelpers +import Foundation + +struct BundleLayout { + + var mainModuleBaseName: String + var wasmSourcePath: AbsolutePath + var buildDirectory: AbsolutePath + var bundleDirectory: AbsolutePath + var topLevelResourcePaths: [String] + + func copyAppEntrypoint(customIndexPage: String?, contentHash: Bool, terminal: InteractiveWriter) + throws + { + let wasmDestinationPath = try computeWasmDestinationPath(contentHash: contentHash) + if wasmSourcePath != wasmDestinationPath { + try localFileSystem.move(from: wasmSourcePath, to: wasmDestinationPath) + } + try copyResources(wasmDestinationPath: wasmDestinationPath, terminal: terminal) + // Copy the bundle entrypoint, point to the binary, and give it a cachebuster name. + let entrypoint = ByteString( + encodingAsUTF8: String(decoding: StaticResource.bundle, as: UTF8.self) + .replacingOccurrences( + of: "REPLACE_THIS_WITH_THE_MAIN_WEBASSEMBLY_MODULE", + with: wasmDestinationPath.basename + ) + ) + let entrypointName = contentHash ? "app.\(entrypoint.hexChecksum).js" : "app.js" + try localFileSystem.writeFileContents( + AbsolutePath(validating: entrypointName, relativeTo: bundleDirectory), + bytes: entrypoint + ) + + try localFileSystem.writeFileContents( + AbsolutePath(validating: "index.html", relativeTo: bundleDirectory), + bytes: ByteString( + encodingAsUTF8: HTML.indexPage( + customContent: HTML.readCustomIndexPage(at: customIndexPage, on: localFileSystem), + entrypointName: entrypointName + )) + ) + } + + func copyTestEntrypoint(contentHash: Bool, terminal: InteractiveWriter) throws { + let wasmDestinationPath = try computeWasmDestinationPath(contentHash: contentHash) + if wasmSourcePath != wasmDestinationPath { + try localFileSystem.copy(from: wasmSourcePath, to: wasmDestinationPath) + } + try copyResources(wasmDestinationPath: wasmDestinationPath, terminal: terminal) + + let contents: [String: String] = [ + "test.browser.js": """ + import { testBrowser } from "./index.js"; + testBrowser(process.argv.slice(2)); + + """, + "test.node.js": """ + import { testNode } from "./index.js"; + testNode(process.argv.slice(2)) + + """, + "test.browser.html": """ + + + + + + + + + + """, + ] + for (filename, content) in contents { + try localFileSystem.writeFileContents( + AbsolutePath(validating: filename, relativeTo: bundleDirectory), + bytes: ByteString(encodingAsUTF8: content) + ) + } + } + + func computeWasmDestinationPath(contentHash: Bool) throws -> AbsolutePath { + let wasmFileHash = try localFileSystem.readFileContents(wasmSourcePath).hexChecksum + // Rename the final binary to use a part of its hash to bust browsers and CDN caches. + let mainModuleName = contentHash ? "\(mainModuleBaseName).\(wasmFileHash).wasm" : "\(mainModuleBaseName).wasm" + return try AbsolutePath(validating: mainModuleName, relativeTo: bundleDirectory) + } + + func copyResources(wasmDestinationPath: AbsolutePath, terminal: InteractiveWriter) throws { + try localFileSystem.writeFileContents( + AbsolutePath(validating: "intrinsics.js", relativeTo: bundleDirectory), + bytes: ByteString(StaticResource.intrinsics) + ) + + let resourcesDirectoryNames = try FileManager.default.resourcesDirectoryNames( + relativeTo: buildDirectory.asURL) + let hasJavaScriptKitResources = resourcesDirectoryNames.contains( + "JavaScriptKit_JavaScriptKit.resources") + + try localFileSystem.writeFileContents( + AbsolutePath(validating: "index.js", relativeTo: bundleDirectory), + bytes: ByteString( + encodingAsUTF8: indexJsContent( + mainModuleName: wasmDestinationPath.basename, hasJavaScriptKitResources: hasJavaScriptKitResources) + ) + ) + + try localFileSystem.writeFileContents( + AbsolutePath(validating: "package.json", relativeTo: bundleDirectory), + bytes: ByteString( + encodingAsUTF8: """ + { + "type": "module", + "main": "./index.js" + } + """ + ) + ) + + for directoryName in resourcesDirectoryNames { + let resourcesPath = buildDirectory.appending(component: directoryName) + let targetDirectory = bundleDirectory.appending(component: directoryName) + + guard localFileSystem.exists(resourcesPath, followSymlink: true) else { continue } + terminal.logLookup("Copying resources to ", targetDirectory) + try localFileSystem.copy(from: resourcesPath, to: targetDirectory) + } + + for resourcesPath in topLevelResourcePaths { + let resourcesPath = try AbsolutePath( + validating: resourcesPath, relativeTo: localFileSystem.currentWorkingDirectory!) + for file in try FileManager.default.traverseRecursively(resourcesPath.asURL) { + let targetPath = bundleDirectory.appending(component: file.lastPathComponent) + let sourcePath = bundleDirectory.appending(component: resourcesPath.basename).appending( + component: file.lastPathComponent) + + guard localFileSystem.exists(sourcePath, followSymlink: true), + !localFileSystem.exists(targetPath, followSymlink: true) + else { continue } + + terminal.logLookup("Creating symlink ", targetPath) + try localFileSystem.createSymbolicLink(targetPath, pointingAt: sourcePath, relative: true) + } + } + } + + private func indexJsContent(mainModuleName: String, hasJavaScriptKitResources: Bool) -> String { + var content = """ + import { WebAssembly, instantiate as internalInstantiate, testBrowser as internalTestBrowser, testNode as internalTestNode } from './intrinsics.js'; + + """ + if hasJavaScriptKitResources { + content += """ + import { SwiftRuntime } from './JavaScriptKit_JavaScriptKit.resources/Runtime/index.mjs'; + + """ + } + content += """ + export const wasmFileName = '\(mainModuleName)'; + + export async function instantiate(options, imports) { + if (!options) { + options = {}; + } + const isNodeJs = (typeof process !== 'undefined') && (process.release.name === 'node'); + const isWebBrowser = (typeof window !== 'undefined'); + + if (!options.module) { + if (isNodeJs) { + const module = await import(/* webpackIgnore: true */'node:module'); + const importMeta = import.meta; + const fs = await import('fs/promises'); + const url = await import('url'); + const filePath = import.meta.resolve('./' + wasmFileName); + options.module = await WebAssembly.compile(await fs.readFile(url.fileURLToPath(filePath))); + } else if (isWebBrowser) { + options.module = await WebAssembly.compileStreaming(fetch(wasmFileName)); + } else { + throw new Error('Unsupported environment to automatically load the WebAssembly module. Please provide the \"module\" option with the compiled WebAssembly module manually.'); + } + } + + """ + if hasJavaScriptKitResources { + content += """ + options.SwiftRuntime = SwiftRuntime; + + """ + } + content += """ + return internalInstantiate(options, imports); + } + + export async function testBrowser(args, inPage = false) { + await internalTestBrowser(instantiate, wasmFileName, args, import.meta.url, inPage); + } + + export async function testNode(args) { + await internalTestNode(instantiate, wasmFileName, args); + } + + """ + + return content + } +} + +extension ByteString { + fileprivate var hexChecksum: String { + String(SHA256().hash(self).hexadecimalRepresentation.prefix(16)) + } +} diff --git a/Sources/carton-frontend-slim/CartonFrontendBundleCommand.swift b/Sources/carton-frontend-slim/CartonFrontendBundleCommand.swift index 6c6d4d3a..1231e800 100644 --- a/Sources/carton-frontend-slim/CartonFrontendBundleCommand.swift +++ b/Sources/carton-frontend-slim/CartonFrontendBundleCommand.swift @@ -13,8 +13,8 @@ // limitations under the License. import ArgumentParser -import CartonHelpers import CartonCore +import CartonHelpers import Foundation import WasmTransformer @@ -82,6 +82,7 @@ struct CartonFrontendBundleCommand: AsyncParsableCommand { var mainWasmPath = try AbsolutePath( validating: mainWasmPath, relativeTo: localFileSystem.currentWorkingDirectory!) + let mainModuleBaseName = mainWasmPath.basenameWithoutExt let buildDirectory = mainWasmPath.parentDirectory try terminal.logLookup( "Right after building the main binary size is ", @@ -127,13 +128,15 @@ struct CartonFrontendBundleCommand: AsyncParsableCommand { } } - try copyToBundle( - terminal: terminal, - wasmOutputFilePath: wasmOutputFilePath, + let bundle = BundleLayout( + mainModuleBaseName: mainModuleBaseName, + wasmSourcePath: wasmOutputFilePath, buildDirectory: buildDirectory, bundleDirectory: bundleDirectory, topLevelResourcePaths: resources ) + try bundle.copyAppEntrypoint( + customIndexPage: customIndexPage, contentHash: contentHash, terminal: terminal) terminal.write( "Bundle successfully generated at \(bundleDirectory)\n", inColor: .green, bold: true) @@ -163,160 +166,6 @@ struct CartonFrontendBundleCommand: AsyncParsableCommand { let strippedBinary = try stripCustomSections(binary.contents) try localFileSystem.writeFileContents(output, bytes: .init(strippedBinary)) } - - func copyToBundle( - terminal: InteractiveWriter, - wasmOutputFilePath: AbsolutePath, - buildDirectory: AbsolutePath, - bundleDirectory: AbsolutePath, - topLevelResourcePaths: [String] - ) throws { - // Rename the final binary to use a part of its hash to bust browsers and CDN caches. - let wasmFileHash = try localFileSystem.readFileContents(wasmOutputFilePath).hexChecksum - let mainModuleBaseName = URL(fileURLWithPath: mainWasmPath).deletingPathExtension() - .lastPathComponent - let mainModuleName = - contentHash ? "\(mainModuleBaseName).\(wasmFileHash).wasm" : "\(mainModuleBaseName).wasm" - let mainModulePath = try AbsolutePath(validating: mainModuleName, relativeTo: bundleDirectory) - try localFileSystem.move(from: wasmOutputFilePath, to: mainModulePath) - - // Copy the bundle entrypoint, point to the binary, and give it a cachebuster name. - let entrypoint = ByteString( - encodingAsUTF8: String(decoding: StaticResource.bundle, as: UTF8.self) - .replacingOccurrences( - of: "REPLACE_THIS_WITH_THE_MAIN_WEBASSEMBLY_MODULE", - with: mainModuleName - ) - ) - let entrypointName = contentHash ? "app.\(entrypoint.hexChecksum).js" : "app.js" - try localFileSystem.writeFileContents( - AbsolutePath(validating: entrypointName, relativeTo: bundleDirectory), - bytes: entrypoint - ) - - try localFileSystem.writeFileContents( - AbsolutePath(validating: "index.html", relativeTo: bundleDirectory), - bytes: ByteString( - encodingAsUTF8: HTML.indexPage( - customContent: HTML.readCustomIndexPage(at: customIndexPage, on: localFileSystem), - entrypointName: entrypointName - )) - ) - - try localFileSystem.writeFileContents( - AbsolutePath(validating: "intrinsics.js", relativeTo: bundleDirectory), - bytes: ByteString(StaticResource.intrinsics) - ) - - let resourcesDirectoryNames = try FileManager.default.resourcesDirectoryNames( - relativeTo: buildDirectory.asURL) - let hasJavaScriptKitResources = resourcesDirectoryNames.contains( - "JavaScriptKit_JavaScriptKit.resources") - - try localFileSystem.writeFileContents( - AbsolutePath(validating: "index.js", relativeTo: bundleDirectory), - bytes: ByteString( - encodingAsUTF8: indexJsContent( - mainModuleName: mainModuleName, hasJavaScriptKitResources: hasJavaScriptKitResources) - ) - ) - - try localFileSystem.writeFileContents( - AbsolutePath(validating: "package.json", relativeTo: bundleDirectory), - bytes: ByteString( - encodingAsUTF8: """ - { - "type": "module", - "main": "./index.js" - } - """ - ) - ) - - for directoryName in resourcesDirectoryNames { - let resourcesPath = buildDirectory.appending(component: directoryName) - let targetDirectory = bundleDirectory.appending(component: directoryName) - - guard localFileSystem.exists(resourcesPath, followSymlink: true) else { continue } - terminal.logLookup("Copying resources to ", targetDirectory) - try localFileSystem.copy(from: resourcesPath, to: targetDirectory) - } - - for resourcesPath in topLevelResourcePaths { - let resourcesPath = try AbsolutePath( - validating: resourcesPath, relativeTo: localFileSystem.currentWorkingDirectory!) - for file in try FileManager.default.traverseRecursively(resourcesPath.asURL) { - let targetPath = bundleDirectory.appending(component: file.lastPathComponent) - let sourcePath = bundleDirectory.appending(component: resourcesPath.basename).appending( - component: file.lastPathComponent) - - guard localFileSystem.exists(sourcePath, followSymlink: true), - !localFileSystem.exists(targetPath, followSymlink: true) - else { continue } - - terminal.logLookup("Creating symlink ", targetPath) - try localFileSystem.createSymbolicLink(targetPath, pointingAt: sourcePath, relative: true) - } - } - } - - private func indexJsContent(mainModuleName: String, hasJavaScriptKitResources: Bool) -> String { - var content = """ - import { instantiate as internalInstantiate } from './intrinsics.js'; - - """ - if hasJavaScriptKitResources { - content += """ - import { SwiftRuntime } from './JavaScriptKit_JavaScriptKit.resources/Runtime/index.mjs'; - - """ - } - content += """ - export const wasmFileName = '\(mainModuleName)'; - - export async function instantiate(options, imports) { - if (!options) { - options = {}; - } - const isNodeJs = (typeof process !== 'undefined') && (process.release.name === 'node'); - const isWebBrowser = (typeof window !== 'undefined'); - - if (!options.module) { - if (isNodeJs) { - const module = await import(/* webpackIgnore: true */'node:module'); - const importMeta = import.meta; - const require = module.default.createRequire(importMeta.url); - const fs = require('fs/promises'); - const url = require('url'); - const filePath = import.meta.resolve('./' + wasmFileName); - options.module = await WebAssembly.compile(await fs.readFile(url.fileURLToPath(filePath))); - } else if (isWebBrowser) { - options.module = await WebAssembly.compileStreaming(fetch(wasmFileName)); - } else { - throw new Error('Unsupported environment to automatically load the WebAssembly module. Please provide the \"module\" option with the compiled WebAssembly module manually.'); - } - } - - """ - if hasJavaScriptKitResources { - content += """ - options.SwiftRuntime = SwiftRuntime; - - """ - } - content += """ - return internalInstantiate(options, imports); - } - """ - - return content - } -} - -extension ByteString { - fileprivate var hexChecksum: String { - String(SHA256().hash(self).hexadecimalRepresentation.prefix(16)) - } } extension FileSystem { diff --git a/Sources/carton-frontend-slim/CartonFrontendSlimCommand.swift b/Sources/carton-frontend-slim/CartonFrontendSlimCommand.swift index ba188fab..d516058d 100644 --- a/Sources/carton-frontend-slim/CartonFrontendSlimCommand.swift +++ b/Sources/carton-frontend-slim/CartonFrontendSlimCommand.swift @@ -26,6 +26,7 @@ public struct CartonFrontendSlimCommand: AsyncParsableCommand { version: cartonVersion, subcommands: [ CartonFrontendBundleCommand.self, + CartonFrontendTestCommand.self, ] ) diff --git a/Sources/CartonFrontend/Commands/CartonFrontendTestCommand.swift b/Sources/carton-frontend-slim/CartonFrontendTestCommand.swift similarity index 91% rename from Sources/CartonFrontend/Commands/CartonFrontendTestCommand.swift rename to Sources/carton-frontend-slim/CartonFrontendTestCommand.swift index 2525298c..8f66bfc5 100644 --- a/Sources/CartonFrontend/Commands/CartonFrontendTestCommand.swift +++ b/Sources/carton-frontend-slim/CartonFrontendTestCommand.swift @@ -15,7 +15,6 @@ import ArgumentParser import CartonCore import CartonHelpers -import CartonKit import Foundation enum SanitizeVariant: String, CaseIterable, ExpressibleByArgument { @@ -26,6 +25,8 @@ struct TestError: Error, CustomStringConvertible { let description: String } +extension Environment: ArgumentParser.ExpressibleByArgument {} + struct CartonFrontendTestCommand: AsyncParsableCommand { static let configuration = CommandConfiguration( @@ -161,27 +162,23 @@ struct CartonFrontendTestCommand: AsyncParsableCommand { case .command: return CommandTestRunner( testFilePath: bundlePath, - listTestCases: list, - testCases: testCases, terminal: terminal ) case .browser: - return BrowserTestRunner( + return try JavaScriptTestRunner( + testHarness: "test.browser.js", + pluginWorkDirectory: AbsolutePath(validating: pluginWorkDirectory, relativeTo: cwd), testFilePath: bundlePath, - bindingAddress: bind, - host: Server.Configuration.host(bindOption: bind, hostOption: host), - port: port, - headless: headless, resourcesPaths: resources, - pid: pid, + nodeArguments: nodeArguments, terminal: terminal ) case .node: - return try NodeTestRunner( + return try JavaScriptTestRunner( + testHarness: "test.node.js", pluginWorkDirectory: AbsolutePath(validating: pluginWorkDirectory, relativeTo: cwd), testFilePath: bundlePath, - listTestCases: list, - testCases: testCases, + resourcesPaths: resources, nodeArguments: nodeArguments, terminal: terminal ) @@ -190,7 +187,7 @@ struct CartonFrontendTestCommand: AsyncParsableCommand { func deriveRunnerOptions() -> TestRunnerOptions { let parentEnv = ProcessInfo.processInfo.environment - var env: [String: String] = parentEnv + var env: [String: String] = [:] for (key, value) in self.env { if let value = value { env[key] = value @@ -198,6 +195,6 @@ struct CartonFrontendTestCommand: AsyncParsableCommand { env[key] = parentEnv[key] } } - return TestRunnerOptions(env: env) + return TestRunnerOptions(env: env, listTestCases: list, testCases: testCases) } } diff --git a/Sources/CartonFrontend/Commands/TestRunners/CommandTestRunner.swift b/Sources/carton-frontend-slim/TestRunners/CommandTestRunner.swift similarity index 66% rename from Sources/CartonFrontend/Commands/TestRunners/CommandTestRunner.swift rename to Sources/carton-frontend-slim/TestRunners/CommandTestRunner.swift index 2a4751f4..6e4f953d 100644 --- a/Sources/CartonFrontend/Commands/TestRunners/CommandTestRunner.swift +++ b/Sources/carton-frontend-slim/TestRunners/CommandTestRunner.swift @@ -12,9 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import CartonHelpers import CartonCore -import CartonKit +import CartonHelpers import Foundation struct CommandTestRunnerError: Error, CustomStringConvertible { @@ -27,32 +26,28 @@ struct CommandTestRunnerError: Error, CustomStringConvertible { struct CommandTestRunner: TestRunner { let testFilePath: AbsolutePath - let listTestCases: Bool - let testCases: [String] let terminal: InteractiveWriter func run(options: TestRunnerOptions) async throws { - let program = try ProcessInfo.processInfo.environment["CARTON_TEST_RUNNER"] ?? defaultWASIRuntime() + let program = + try ProcessInfo.processInfo.environment["CARTON_TEST_RUNNER"] ?? defaultWASIRuntime() terminal.write("\nRunning the test bundle with \"\(program)\":\n", inColor: .yellow) var arguments = [program] var xctestArgs: [String] = [] - if listTestCases { - xctestArgs.append(contentsOf: ["--", "-l"]) - } else { - let programName = URL(fileURLWithPath: program).lastPathComponent - if programName == "wasmtime" { - arguments += ["--dir", "."] - } - for (key, value) in options.env { - arguments += ["--env", "\(key)=\(value)"] - } - - if !testCases.isEmpty { - xctestArgs.append("--") - xctestArgs.append(contentsOf: testCases) - } + options.applyXCTestArguments(to: &xctestArgs) + if !xctestArgs.isEmpty { + xctestArgs = ["--"] + xctestArgs } + let programName = URL(fileURLWithPath: program).lastPathComponent + if programName == "wasmtime" { + arguments += ["--dir", "."] + } + arguments += ["--wasi", "inherit-env"] + for (key, value) in options.env { + arguments += ["--env", "\(key)=\(value)"] + } + arguments += [testFilePath.pathString] + xctestArgs try await Process.run(arguments, parser: TestsParser(), terminal) } @@ -60,7 +55,9 @@ struct CommandTestRunner: TestRunner { func defaultWASIRuntime() throws -> String { let candidates = ["wasmtime", "wasmer"] guard let found = candidates.lazy.compactMap({ try? Foundation.Process.which($0) }).first else { - throw CommandTestRunnerError("No WASI runtime found. Please install one of the following: \(candidates.joined(separator: ", "))") + throw CommandTestRunnerError( + "No WASI runtime found. Please install one of the following: \(candidates.joined(separator: ", "))" + ) } return found.path } diff --git a/Sources/carton-frontend-slim/TestRunners/JavaScriptTestRunner.swift b/Sources/carton-frontend-slim/TestRunners/JavaScriptTestRunner.swift new file mode 100644 index 00000000..ba41b67d --- /dev/null +++ b/Sources/carton-frontend-slim/TestRunners/JavaScriptTestRunner.swift @@ -0,0 +1,63 @@ +// Copyright 2020 Carton 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. + +import CartonCore +import CartonHelpers +import Foundation + +#if canImport(FoundationNetworking) + import FoundationNetworking +#endif + +struct JavaScriptTestRunner: TestRunner { + let testHarness: String + let pluginWorkDirectory: AbsolutePath + let testFilePath: AbsolutePath + let resourcesPaths: [String] + let nodeArguments: [String] + let terminal: InteractiveWriter + + init( + testHarness: String, + pluginWorkDirectory: AbsolutePath, + testFilePath: AbsolutePath, + resourcesPaths: [String], + nodeArguments: [String], + terminal: InteractiveWriter + ) { + self.testHarness = testHarness + self.pluginWorkDirectory = pluginWorkDirectory + self.testFilePath = testFilePath + self.resourcesPaths = resourcesPaths + self.nodeArguments = nodeArguments + self.terminal = terminal + } + + func run(options: TestRunnerOptions) async throws { + try localFileSystem.removeFileTree(pluginWorkDirectory) + try localFileSystem.createDirectory(pluginWorkDirectory, recursive: false) + let buildDirectory = testFilePath.parentDirectory + try BundleLayout( + mainModuleBaseName: "test", wasmSourcePath: testFilePath, + buildDirectory: buildDirectory, + bundleDirectory: pluginWorkDirectory, + topLevelResourcePaths: resourcesPaths + ).copyTestEntrypoint(contentHash: false, terminal: terminal) + + var arguments = + ["node"] + nodeArguments + [pluginWorkDirectory.appending(component: testHarness).pathString] + options.applyXCTestArguments(to: &arguments) + try await Process.run(arguments, environment: options.env, parser: TestsParser(), terminal) + } +} diff --git a/Sources/CartonKit/Parsers/String+Regex.swift b/Sources/carton-frontend-slim/TestRunners/String+Regex.swift similarity index 100% rename from Sources/CartonKit/Parsers/String+Regex.swift rename to Sources/carton-frontend-slim/TestRunners/String+Regex.swift diff --git a/Sources/CartonKit/Parsers/String+color.swift b/Sources/carton-frontend-slim/TestRunners/String+color.swift similarity index 100% rename from Sources/CartonKit/Parsers/String+color.swift rename to Sources/carton-frontend-slim/TestRunners/String+color.swift diff --git a/Sources/CartonFrontend/Commands/TestRunners/TestRunner.swift b/Sources/carton-frontend-slim/TestRunners/TestRunner.swift similarity index 68% rename from Sources/CartonFrontend/Commands/TestRunners/TestRunner.swift rename to Sources/carton-frontend-slim/TestRunners/TestRunner.swift index 3ae44297..1ac940ef 100644 --- a/Sources/CartonFrontend/Commands/TestRunners/TestRunner.swift +++ b/Sources/carton-frontend-slim/TestRunners/TestRunner.swift @@ -15,6 +15,18 @@ struct TestRunnerOptions { /// The environment variables to pass to the test process. let env: [String: String] + /// When specified, list all available test cases. + let listTestCases: Bool + /// Filter the test cases to run. + let testCases: [String] + + func applyXCTestArguments(to arguments: inout [String]) { + if listTestCases { + arguments.append(contentsOf: ["--", "-l"]) + } else if !testCases.isEmpty { + arguments.append(contentsOf: testCases) + } + } } protocol TestRunner { diff --git a/Sources/CartonKit/Parsers/TestsParser.swift b/Sources/carton-frontend-slim/TestRunners/TestsParser.swift similarity index 94% rename from Sources/CartonKit/Parsers/TestsParser.swift rename to Sources/carton-frontend-slim/TestRunners/TestsParser.swift index 84f0c429..129e5f8a 100644 --- a/Sources/CartonKit/Parsers/TestsParser.swift +++ b/Sources/carton-frontend-slim/TestRunners/TestsParser.swift @@ -12,10 +12,37 @@ // See the License for the specific language governing permissions and // limitations under the License. -import CartonHelpers import CartonCore +import CartonHelpers import Foundation +/// Parses and re-formats diagnostics output by the Swift compiler. +/// +/// The compiler output often repeats itself, and the diagnostics can sometimes be +/// difficult to read. +/// This reformats them to a more readable output. +struct DiagnosticsParser { + struct CustomDiagnostic { + let kind: Kind + let file: String + let line: String.SubSequence + let char: String.SubSequence + let code: String + let message: String + + enum Kind: String { + case error, warning, note + var color: String { + switch self { + case .error: return "[41;1m" // bright red background + case .warning: return "[43;1m" // bright yellow background + case .note: return "[7m" // reversed + } + } + } + } +} + extension String.StringInterpolation { fileprivate mutating func appendInterpolation(_ regexLabel: TestsParser.Regex.Label) { appendInterpolation("<\(regexLabel.rawValue)>") diff --git a/Sources/carton-release/HashArchive.swift b/Sources/carton-release/HashArchive.swift index 0a3d9052..34b901b2 100644 --- a/Sources/carton-release/HashArchive.swift +++ b/Sources/carton-release/HashArchive.swift @@ -44,25 +44,17 @@ struct HashArchive: AsyncParsableCommand { """ - for entrypoint in ["dev", "bundle", "test", "testNode", "intrinsics"] { + for entrypoint in ["dev", "bundle", "intrinsics"] { let tsFilename = "\(entrypoint).ts" let filename = "\(entrypoint).js" - var arguments = [ + let arguments = [ "esbuild", "--bundle", "entrypoint/\(tsFilename)", "--outfile=static/\(filename)", + "--external:node:url", "--external:node:path", + "--external:node:module", "--external:playwright", + "--format=esm", + "--external:./JavaScriptKit_JavaScriptKit.resources/Runtime/index.mjs", ] - if entrypoint == "testNode" { - arguments.append(contentsOf: [ - "--format=cjs", "--platform=node", - "--external:./JavaScriptKit_JavaScriptKit.resources/Runtime/index.js", - ]) - } else { - arguments.append(contentsOf: [ - "--format=esm", - "--external:./JavaScriptKit_JavaScriptKit.resources/Runtime/index.mjs", - ]) - } - let npx = try Process.which("npx") try Foundation.Process.run(npx, arguments: arguments).waitUntilExit() let entrypointPath = URL(fileURLWithPath: filename, relativeTo: staticPath) @@ -80,6 +72,7 @@ struct HashArchive: AsyncParsableCommand { } """ - try fileContent.write(toFile: "Sources/CartonHelpers/StaticArchive.swift", atomically: true, encoding: .utf8) + try fileContent.write( + toFile: "Sources/CartonHelpers/StaticArchive.swift", atomically: true, encoding: .utf8) } } diff --git a/Tests/CartonCommandTests/TestCommandTests.swift b/Tests/CartonCommandTests/TestCommandTests.swift index 39b5ddf2..d9007985 100644 --- a/Tests/CartonCommandTests/TestCommandTests.swift +++ b/Tests/CartonCommandTests/TestCommandTests.swift @@ -46,7 +46,15 @@ final class TestCommandTests: XCTestCase { try result.checkNonZeroExit() let stdout = try result.utf8Output() let stderr = try result.utf8stderrOutput() - let expectedContent = "Test Suite 'All tests' passed" + let expectedTestSuiteCount = 1 + let expectedTestsCount = 1 + let expectedContent = + """ + Test Suites: \(ControlCode.CSI)32m\(expectedTestSuiteCount) passed\(ControlCode + .CSI)0m, \(expectedTestSuiteCount) total + Tests: \(ControlCode.CSI)32m\(expectedTestsCount) passed\(ControlCode + .CSI)0m, \(expectedTestsCount) total + """ // SwiftPM changed the output destination of SwiftPM Plugin in 6.0 XCTAssertTrue(stdout.contains(expectedContent) || stderr.contains(expectedContent)) } diff --git a/entrypoint/bundle.ts b/entrypoint/bundle.ts index 9f2930f6..d6023099 100644 --- a/entrypoint/bundle.ts +++ b/entrypoint/bundle.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { instantiate } from "./intrinsics.js"; +import { instantiate, WebAssembly } from "./intrinsics.js"; import type { SwiftRuntimeConstructor } from "./JavaScriptKit_JavaScriptKit.resources/Runtime"; const startWasiTask = async () => { diff --git a/entrypoint/dev.ts b/entrypoint/dev.ts index 9e503c79..a21d13d1 100644 --- a/entrypoint/dev.ts +++ b/entrypoint/dev.ts @@ -13,7 +13,7 @@ // limitations under the License. import ReconnectingWebSocket from "reconnecting-websocket"; -import { instantiate } from "./intrinsics"; +import { instantiate, WebAssembly } from "./intrinsics"; import type { SwiftRuntimeConstructor } from "./JavaScriptKit_JavaScriptKit.resources/Runtime"; const socket = new ReconnectingWebSocket(`ws://${location.host}/watcher`); diff --git a/entrypoint/intrinsics.ts b/entrypoint/intrinsics.ts index db5e4547..c726d3f4 100644 --- a/entrypoint/intrinsics.ts +++ b/entrypoint/intrinsics.ts @@ -12,14 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { WASI, File, OpenFile, ConsoleStdout, PreopenDirectory } from "@bjorn3/browser_wasi_shim"; -import type { SwiftRuntime, SwiftRuntimeConstructor } from "./JavaScriptKit_JavaScriptKit.resources/Runtime"; +import { WASI, File, OpenFile, ConsoleStdout, PreopenDirectory, WASIProcExit } from "@bjorn3/browser_wasi_shim"; +import type { SwiftRuntime, SwiftRuntimeConstructor } from "./JavaScriptKit_JavaScriptKit.resources/Runtime/index"; import { polyfill as polyfillWebAssemblyTypeReflection } from "wasm-imports-parser/polyfill"; import type { ImportEntry } from "wasm-imports-parser"; // Apply polyfill for WebAssembly Type Reflection JS API to inspect imported memory info. // https://github.com/WebAssembly/js-types/blob/main/proposals/js-types/Overview.md -const WebAssembly = polyfillWebAssemblyTypeReflection(globalThis.WebAssembly); +export const WebAssembly = polyfillWebAssemblyTypeReflection(globalThis.WebAssembly); class LineDecoder { constructor(onLine: (line: string) => void) { @@ -203,3 +203,170 @@ function defaultInstantiationOptions(options: InstantiationOptions): Instantiati } return options; } + +type Instantiate = (options: Omit, extraWasmImports?: WebAssembly.Imports) => Promise<{ + instance: WebAssembly.Instance; +}>; + +export async function testBrowser(instantiate: Instantiate, wasmFileName: string, args: string[], indexJsUrl: string, inPage: boolean) { + if (inPage) { + return await testBrowserInPage(instantiate, wasmFileName, args); + } + const playwright = await (async () => { + try { + // @ts-ignore + return await import("playwright") + } catch { + // Playwright is not available in the current environment + console.error(`Playwright is not available in the current environment. +Please run the following command to install it: + + $ npm install playwright && npx playwright install chromium +`); + process.exit(1); + } + })(); + const browser = await playwright.chromium.launch(); + const context = await browser.newContext(); + const page = await context.newPage(); + const { fileURLToPath } = await import("node:url"); + const path = await import("node:path"); + const indexJsPath = fileURLToPath(indexJsUrl); + const webRoot = path.dirname(indexJsPath); + + // Forward console messages in the page to the Node.js console + page.on("console", (message: any) => { + console.log(message.text()); + }); + + await page.route("http://example.com/**/*", async (route: any) => { + const url = route.request().url(); + const urlPath = new URL(url).pathname; + if (urlPath === "/process-info.json") { + route.fulfill({ body: JSON.stringify({ env: process.env }) }); + return; + } + route.fulfill({ path: path.join(webRoot, urlPath.slice(1)) }); + }); + const onExit = new Promise((resolve) => { + page.exposeFunction("exitTest", resolve); + }); + await page.goto("http://example.com/test.browser.html"); + const exitCode = await onExit; + await browser.close(); + process.exit(exitCode); +} + +async function testBrowserInPage(instantiate: Instantiate, wasmFileName: string, args: string[]) { + const logElement = document.createElement("pre"); + document.body.appendChild(logElement); + + const exitTest = (code: number) => { + const fn = (window as any).exitTest; + if (fn) { fn(code); } + } + + const config = await fetch("/process-info.json").then((response) => response.json()); + + const handleError = (error: any) => { + console.error(error); + exitTest(1); + }; + + // There are 6 cases to exit test + // 1. Successfully finished XCTest with `exit(0)` synchronously + // 2. Unsuccessfully finished XCTest with `exit(non-zero)` synchronously + // 3. Successfully finished XCTest with `exit(0)` asynchronously + // 4. Unsuccessfully finished XCTest with `exit(non-zero)` asynchronously + // 5. Crash by throwing JS exception synchronously + // 6. Crash by throwing JS exception asynchronously + + const handleExitOrError = (error: any) => { + // XCTest always calls `exit` at the end when no crash + if (error instanceof WASIProcExit) { + // pass the output to the server in any case + if (error.code === 0) { + exitTest(0); + } else { + handleError(error) // test failed + } + } else { + handleError(error) // something wrong happens during test + } + } + + // Handle asynchronous exits (case 3, 4, 6) + window.addEventListener("unhandledrejection", event => { + event.preventDefault(); + const error = event.reason; + handleExitOrError(error); + }); + + try { + // Instantiate the WebAssembly file + await instantiate( + { + env: config.env, + args: [wasmFileName].concat(args), + onStdoutLine(line) { + console.log(line); + logElement.textContent += line + "\n"; + }, + onStderrLine(line) { + console.warn(line); + logElement.textContent += line + "\n"; + }, + }, + { + "wasi_snapshot_preview1": { + proc_exit: (code: number) => { + exitTest(code); + throw new WASIProcExit(code); + }, + } + } + ); + } catch (error) { + // Handle synchronous exits (case 1, 2, 5) + handleExitOrError(error); + } + // When JavaScriptEventLoop executor is still running, + // reachable here without catch (case 3, 4, 6) +} + +export async function testNode(instantiate: Instantiate, wasmFileName: string, args: string[]) { + const env: Record = {}; + for (const key in process.env) { + const value = process.env[key]; + if (value) { + env[key] = value; + } + } + + let procExitCalled = false; + + // Make `require` function available in the Swift environment. By default it's only available in the local scope, + // but not on the `global` object. + // @ts-ignore + const { createRequire } = await import("node:module"); + const require = createRequire(import.meta.url); + globalThis.require = require; + + process.on("beforeExit", () => { + if (!procExitCalled) { + throw new Error(`Test harness process exited before test process. +This usually means there are some dangling continuations, which are awaited but never resumed.`); + } + }); + + await instantiate({ env, args: [wasmFileName].concat(args) }, { + "wasi_snapshot_preview1": { + // @bjorn3/browser_wasi_shim raises an exception when + // the process exits, but we just want to exit the process itself. + proc_exit: (code: number) => { + procExitCalled = true; + process.exit(code); + }, + } + }); +} diff --git a/entrypoint/test.ts b/entrypoint/test.ts deleted file mode 100644 index a38c87fc..00000000 --- a/entrypoint/test.ts +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2020 Carton 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. - -import ReconnectingWebSocket from "reconnecting-websocket"; -import { WASIProcExit } from "@bjorn3/browser_wasi_shim"; -import { instantiate } from "./intrinsics.js"; -import type { SwiftRuntimeConstructor } from "./JavaScriptKit_JavaScriptKit.resources/Runtime"; - -const socket = new ReconnectingWebSocket(`ws://${location.host}/watcher`); -socket.addEventListener("message", (message) => { - if (message.data === "reload") { - location.reload(); - } -}); - -const startWasiTask = async () => { - // Fetch our Wasm File - const response = await fetch("/main.wasm"); - - let runtimeConstructor: SwiftRuntimeConstructor | undefined = undefined; - try { - const { SwiftRuntime } = await import( - // @ts-ignore - "./JavaScriptKit_JavaScriptKit.resources/Runtime/index.mjs" - ); - runtimeConstructor = SwiftRuntime; - } catch { - console.log( - "JavaScriptKit module not available, running without JavaScriptKit runtime." - ); - } - - // Load configuration from the server - const config = await fetch("/process-info.json").then((response) => response.json()); - - let testRunOutput = ""; - - // There are 6 cases to exit test - // 1. Successfully finished XCTest with `exit(0)` synchronously - // 2. Unsuccessfully finished XCTest with `exit(non-zero)` synchronously - // 3. Successfully finished XCTest with `exit(0)` asynchronously - // 4. Unsuccessfully finished XCTest with `exit(non-zero)` asynchronously - // 5. Crash by throwing JS exception synchronously - // 6. Crash by throwing JS exception asynchronously - - const handleExitOrError = (error: any) => { - // XCTest always calls `exit` at the end when no crash - if (error instanceof WASIProcExit) { - // pass the output to the server in any case - socket.send(JSON.stringify({ kind: "testRunOutput", testRunOutput })); - if (error.code === 0) { - socket.send(JSON.stringify({ kind: "testPassed" })); - } else { - handleError(error) // test failed - } - } else { - handleError(error) // something wrong happens during test - } - const divElement = document.createElement("p"); - divElement.innerHTML = - "Test run finished. Check the output of carton test for details."; - document.body.appendChild(divElement); - } - // Handle asynchronous exits (case 3, 4, 6) - window.addEventListener("unhandledrejection", event => { - event.preventDefault(); - const error = event.reason; - handleExitOrError(error); - }); - // Start the WebAssembly WASI instance - try { - // Instantiate the WebAssembly file - await instantiate( - { - module: await WebAssembly.compileStreaming(response), - env: config.env, - onStdoutLine: (line) => { - console.log(line); - testRunOutput += line + "\n"; - }, - onStderrLine: (line) => { - console.error(line); - }, - SwiftRuntime: runtimeConstructor, - } - ); - } catch (error) { - // Handle synchronous exits (case 1, 2, 5) - handleExitOrError(error) - return - } - // When JavaScriptEventLoop executor is still running, - // reachable here without catch (case 3, 4, 6) -}; - -function handleError(e: any) { - console.error(e); - - if (e instanceof Error) { - const stack = e.stack; - if (stack != null) { - socket.send( - JSON.stringify({ - kind: "stackTrace", - stackTrace: stack, - }) - ); - } - } - - socket.send( - JSON.stringify({ - kind: "errorReport", - errorReport: e.toString() - }) - ); -} - -async function main(): Promise { - try { - await startWasiTask(); - } catch (e) { - handleError(e); - } -} - -main(); diff --git a/entrypoint/testNode.ts b/entrypoint/testNode.ts deleted file mode 100644 index 019793c8..00000000 --- a/entrypoint/testNode.ts +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2022 Carton 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. - -import fs from "fs/promises"; -import path from "path"; -import { instantiate } from "./intrinsics.js"; -import type { SwiftRuntimeConstructor } from "./JavaScriptKit_JavaScriptKit.resources/Runtime"; - -const args = [...process.argv]; -args.shift(); -args.shift(); -const [wasmFile, ...testArgs] = args; -testArgs.unshift(path.basename(wasmFile)); - -if (!wasmFile) { - throw Error("No WASM test file specified, can not run tests"); -} - -const startWasiTask = async () => { - const wasmBytes = await fs.readFile(wasmFile); - - let runtimeConstructor: SwiftRuntimeConstructor | undefined = undefined; - try { - const { SwiftRuntime } = await import( - // @ts-ignore - "./JavaScriptKit_JavaScriptKit.resources/Runtime/index.mjs" - ); - - runtimeConstructor = SwiftRuntime; - - // Make `require` function available in the Swift environment. By default it's only available in the local scope, - // but not on the `global` object. - global.require = require; - } catch { - // No JavaScriptKit module found, run the Wasm module without JSKit - } - - // carton-frontend passes all environment variables to the test Node process. - const env: Record = {}; - for (const key in process.env) { - const value = process.env[key]; - if (value) { - env[key] = value; - } - } - - let procExitCalled = false; - - process.on("beforeExit", () => { - if (!procExitCalled) { - throw new Error(`Test harness process exited before test process. -This usually means there are some dangling continuations, which are awaited but never resumed.`); - } - }); - - await instantiate( - { - module: await WebAssembly.compile(wasmBytes), - args: testArgs, - env, - onStdoutLine: (line) => { - console.log(line); - }, - onStderrLine: (line) => { - console.error(line); - }, - SwiftRuntime: runtimeConstructor, - }, - { - "wasi_snapshot_preview1": { - // @bjorn3/browser_wasi_shim raises an exception when - // the process exits, but we just want to exit the process itself. - proc_exit: (code: number) => { - procExitCalled = true; - process.exit(code); - }, - } - } - ); -}; - -startWasiTask().catch((e) => { - throw e; -}); diff --git a/package-lock.json b/package-lock.json index e446bf58..01f0e461 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@types/reconnectingwebsocket": "^1.0.10", "esbuild": "^0.14.38", "npm-run-all": "^4.1.5", + "playwright": "^1.48.2", "reconnecting-websocket": "^4.4.0", "typescript": "^5.4.5", "wasm-imports-parser": "1.0.4" @@ -568,6 +569,20 @@ "node": ">=0.8.0" } }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -1042,6 +1057,36 @@ "node": ">=4" } }, + "node_modules/playwright": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", + "integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", + "dev": true, + "dependencies": { + "playwright-core": "1.48.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", + "integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", + "dev": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -1649,6 +1694,13 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -1983,6 +2035,22 @@ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, + "playwright": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", + "integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", + "dev": true, + "requires": { + "fsevents": "2.3.2", + "playwright-core": "1.48.2" + } + }, + "playwright-core": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", + "integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", + "dev": true + }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", diff --git a/package.json b/package.json index 507b34e7..192854d3 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "npm-run-all": "^4.1.5", "reconnecting-websocket": "^4.4.0", "typescript": "^5.4.5", + "playwright": "^1.48.2", "wasm-imports-parser": "1.0.4" } } diff --git a/tsconfig.json b/tsconfig.json index d85b2b97..f991fae0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,9 +1,10 @@ { "compilerOptions": { - "module": "CommonJS", + "module": "ES2020", "strict": true, "target": "ESNext", "esModuleInterop": true, + "moduleResolution": "node", "lib": [ "DOM", "ES2020", @@ -16,4 +17,4 @@ "include": [ "entrypoint/**/*.ts" ] -} \ No newline at end of file +}