-- ==================================================================== -- WTR MENU ELITE - STANDALONE -- FiveM 100% Native High-Performance Lua Mod Menu -- Controls: PAGE UP (Toggle) | Q & E (Tabs) | Arrows & Enter -- Zero-Lag Architecture (Pure FiveM Natives - No Dependencies) -- ==================================================================== -- ==================================================================== -- STRICT CLEAN INITIALIZATION: NO CHEATS OR GODMODE ON STARTUP -- ==================================================================== Citizen.CreateThread(function() Citizen.Wait(50) local p = PlayerPedId() SetEntityInvincible(p, false) SetPlayerInvincible(PlayerId(), false) SetEntityProofs(p, false, false, false, false, false, false, false, false) SetEntityVisible(p, true, false) SetEntityAlpha(p, 255, false) SetPedCanRagdoll(p, true) SetRunSprintMultiplierForPlayer(PlayerId(), 1.0) SetSwimMultiplierForPlayer(PlayerId(), 1.0) NetworkSetInSpectatorMode(false, p) end) -- ==================================================================== -- CUSTOM CYBERPUNK NEON NOTIFICATION SYSTEM -- ==================================================================== local CustomNotifications = {} local function Notify(msg, nType, duration) local text = tostring(msg) local nColor = { r = 56, g = 189, b = 248 } -- default cyan local title = "WTR ELITE" if nType == "success" or text:find("~g~") then nColor = { r = 34, g = 197, b = 94 } -- green title = "WTR - SUCCESS" elseif nType == "error" or text:find("~r~") then nColor = { r = 239, g = 68, b = 68 } -- red title = "WTR - ALERT" elseif nType == "warning" or text:find("~y~") then nColor = { r = 234, g = 179, b = 8 } -- yellow title = "WTR - WARNING" elseif nType == "purple" or text:find("~p~") then nColor = { r = 168, g = 85, b = 247 } -- purple title = "WTR - MODULE" end -- Clean GTA color format tags and sanitize non-ASCII characters for crisp GTA font rendering local cleanMsg = text:gsub("~[a-z]~", "") cleanMsg = cleanMsg:gsub("á", "a"):gsub("é", "e"):gsub("í", "i"):gsub("ó", "o"):gsub("ú", "u") cleanMsg = cleanMsg:gsub("č", "c"):gsub("š", "s"):gsub("ž", "z"):gsub("ť", "t"):gsub("ď", "d") cleanMsg = cleanMsg:gsub("ľ", "l"):gsub("ň", "n"):gsub("ô", "o"):gsub("ä", "a") cleanMsg = cleanMsg:gsub("Á", "A"):gsub("É", "E"):gsub("Í", "I"):gsub("Ó", "O"):gsub("Ú", "U") cleanMsg = cleanMsg:gsub("Č", "C"):gsub("Š", "S"):gsub("Ž", "Z"):gsub("Ť", "T"):gsub("Ď", "D") cleanMsg = cleanMsg:gsub("Ľ", "L"):gsub("Ň", "N") cleanMsg = cleanMsg:gsub("[^\32-\126]", "") local dur = duration or 3800 local now = GetGameTimer() table.insert(CustomNotifications, { title = title, msg = cleanMsg, color = nColor, startTime = now, endTime = now + dur, duration = dur }) if #CustomNotifications > 4 then table.remove(CustomNotifications, 1) end end -- Custom Notification Renderer Loop Citizen.CreateThread(function() while true do Citizen.Wait(0) local now = GetGameTimer() local activeList = {} for _, notif in ipairs(CustomNotifications) do if now < notif.endTime then table.insert(activeList, notif) end end CustomNotifications = activeList if #CustomNotifications > 0 then local startY = 0.075 local width = 0.20 local height = 0.056 local xPos = 0.885 for i, notif in ipairs(CustomNotifications) do local curY = startY + (i - 1) * (height + 0.012) local timeLeft = notif.endTime - now local progress = math.max(0.0, math.min(1.0, timeLeft / notif.duration)) -- Dark frosted glass container DrawRect(xPos, curY, width, height, 8, 12, 28, 235) DrawRect(xPos, curY - (height / 2), width, 0.0015, notif.color.r, notif.color.g, notif.color.b, 210) -- Vertical Left Neon Accent Bar DrawRect(xPos - (width / 2) + 0.002, curY, 0.003, height - 0.004, notif.color.r, notif.color.g, notif.color.b, 255) -- Title Text SetTextFont(4) SetTextProportional(1) SetTextScale(0.0, 0.28) SetTextColour(notif.color.r, notif.color.g, notif.color.b, 255) SetTextDropshadow(0, 0, 0, 0, 255) SetTextEdge(1, 0, 0, 0, 205) SetTextEntry("STRING") AddTextComponentSubstringPlayerName(notif.title) DrawText(xPos - (width / 2) + 0.009, curY - (height / 2) + 0.005) -- Message Text SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.26) SetTextColour(226, 232, 240, 250) SetTextDropshadow(0, 0, 0, 0, 255) SetTextOutline() SetTextEntry("STRING") AddTextComponentSubstringPlayerName(notif.msg) DrawText(xPos - (width / 2) + 0.009, curY - (height / 2) + 0.024) -- Countdown Timer Line at bottom local progW = width * progress local progX = (xPos - (width / 2)) + (progW / 2) DrawRect(progX, curY + (height / 2) - 0.001, progW, 0.0018, notif.color.r, notif.color.g, notif.color.b, 240) end end end end) local function PlaySound(name, set) PlaySoundFrontend(-1, name or "SELECT", set or "HUD_FRONTEND_DEFAULT_SOUNDSET", true) end local function PromptInput(title, defaultText) DisplayOnscreenKeyboard(1, "FMMC_KEY_TIP8", "", defaultText or "", "", "", "", 64) while UpdateOnscreenKeyboard() == 0 do DisableAllControlActions(0) Citizen.Wait(0) end if GetOnscreenKeyboardResult() then return GetOnscreenKeyboardResult() end return nil end local function SafeRequestModel(hash) local h = type(hash) == "string" and GetHashKey(hash) or hash if not IsModelInCdimage(h) then return nil end RequestModel(h) local timeout = 0 while not HasModelLoaded(h) and timeout < 200 do Citizen.Wait(10) timeout = timeout + 1 end if HasModelLoaded(h) then return h end return nil end local function SpawnVehicleNative(model, coords, heading) local h = SafeRequestModel(model) if not h then Notify("~r~[WTR] Invalid vehicle model: ~s~" .. tostring(model)) return 0 end local ped = PlayerPedId() local c = coords or GetEntityCoords(ped) local head = heading or GetEntityHeading(ped) local veh = CreateVehicle(h, c.x, c.y, c.z, head, true, false) SetPedIntoVehicle(ped, veh, -1) SetModelAsNoLongerNeeded(h) return veh end local function SpawnObjectNative(model, coords) local h = SafeRequestModel(model) if not h then return 0 end local obj = CreateObject(h, coords.x, coords.y, coords.z, true, false, false) SetModelAsNoLongerNeeded(h) return obj end local function SpawnPedNative(model, coords) local h = SafeRequestModel(model) if not h then return 0 end local ped = CreatePed(4, h, coords.x, coords.y, coords.z, 0.0, true, false) SetModelAsNoLongerNeeded(h) return ped end local function DeleteEntityNative(ent) if DoesEntityExist(ent) and ent ~= PlayerPedId() then SetEntityAsMissionEntity(ent, true, true) DeleteEntity(ent) end end local function RevivePlayerNative() local ped = PlayerPedId() local c = GetEntityCoords(ped) local head = GetEntityHeading(ped) NetworkResurrectLocalPlayer(c.x, c.y, c.z, head, true, false) SetEntityHealth(ped, 200) SetPedArmour(ped, 100) ClearPedBloodDamage(ped) ClearPedWetness(ped) ResetPedVisibleDamage(ped) ResurrectPed(ped) ClearPedTasksImmediately(ped) SetEntityInvincible(ped, false) FreezeEntityPosition(ped, false) -- Framework compatibility triggers TriggerEvent("esx_ambulancejob:revive") TriggerServerEvent("esx_ambulancejob:revive") TriggerEvent("hospital:client:Revive") TriggerServerEvent("hospital:server:Revive") TriggerEvent("qb-ambulancejob:client:Revive") TriggerEvent("qbx_medical:client:playerRevived") TriggerEvent("esx:onPlayerSpawn") end -- ==================================================================== -- WTR STATE & TARGET SYSTEM -- ==================================================================== local WTR = { isOpen = false, active = true, menuLevel = 1, selectedCategory = 1, activeSubtab = 1, selectedItem = 1, scrollOffset = 0, duiReady = false, screenX = 0.16, screenY = 0.44, menuWidth = 0.23, menuHeight = 0.52, cursorMode = false, positionIndex = 1, -- Keybind Setup System (Default: PAGE UP on startup modal, F9 for feature binding) toggleControl = 10, toggleKeyName = "PAGE UP", toggleKeyMapping = "PRIOR", keybindModal = { active = true, selectedKey = "PAGE UP", selectedControl = 10, keyMapping = "PRIOR" }, -- Feature Binds System (Press F9 on any option to bind it) featureBinds = {}, itemBinds = {}, featureBindModal = { active = false, itemId = nil, itemLabel = "", itemType = "action", selectedKey = "None", selectedControl = nil, keyMapping = nil }, -- Native Target system (Defaults to Self) target = { ped = nil, serverId = nil, name = "Local Player (Self)", dist = 0, isSelf = true }, -- OneSync 500m Live Tracking & Multi-Select onlinePlayers = {}, selectedPlayers = {}, spectating = false, spectate_target = nil, features = { godmode = false, auto_revive = false, noclip = false, freecam = false, freecam_shoot = false, freecam_placer = false, super_jump = false, fast_run = false, invisible = false, black_hole = false, online_spectate = false, online_multi_freeze = false, loop_punch = false, loop_taze = false, loop_burn = false, infinite_ammo = false, no_recoil = false, no_spread = false, rapid_fire = false, explosive_ammo = false, car_gun = false, silent_aim = false, triggerbot = false, damage_boost = false, veh_godmode = false, speed_boost = false, drive_on_water = false, car_jump = false, rainbow_car = false, invisible_car = false, esp_box = false, esp_names = false, esp_health = false, esp_distance = false, esp_snaplines = false, custom_crosshair = false, night_vision = false, thermal_vision = false, moon_gravity = false, freeze_peds = false, safe_mode = false, fg_heartbeat = false, dp_heartbeat = false, } } -- Forward declaration of SendDuiAction local SendDuiAction = nil local RebuildFeatureBinds = nil -- Native Player Targeting Handlers local function SelectSelfTarget() local myPed = PlayerPedId() WTR.target.ped = myPed WTR.target.serverId = GetPlayerServerId(PlayerId()) WTR.target.name = "Local Player (Self)" WTR.target.dist = 0 WTR.target.isSelf = true Notify("~g~[WTR Target]~s~ Target set to Local Player (Self)") PlaySound("SELECT") if SendDuiAction then SendDuiAction("SET_TARGET", { targetName = WTR.target.name }) end end local function SelectClosestPlayer() local myPed = PlayerPedId() local myCoords = GetEntityCoords(myPed) local bestDist = 9999.0 local bestPed = nil local bestId = nil for _, player in ipairs(GetActivePlayers()) do if player ~= PlayerId() then local pPed = GetPlayerPed(player) if DoesEntityExist(pPed) and not IsEntityDead(pPed) then local dist = #(myCoords - GetEntityCoords(pPed)) if dist < bestDist then bestDist = dist bestPed = pPed bestId = GetPlayerServerId(player) end end end end if bestPed then WTR.target.ped = bestPed WTR.target.serverId = bestId local pIdx = GetPlayerFromServerId(bestId) WTR.target.name = (pIdx and pIdx ~= -1 and GetPlayerName(pIdx)) or ("Player #" .. tostring(bestId)) WTR.target.dist = math.floor(bestDist) WTR.target.isSelf = false Notify("~g~[WTR Target]~s~ " .. WTR.target.name .. " (" .. tostring(WTR.target.dist) .. "m)") PlaySound("SELECT") else SelectSelfTarget() Notify("~y~[WTR Target]~s~ No other player in range. Target: Self") end if SendDuiAction then SendDuiAction("SET_TARGET", { targetName = WTR.target.name }) end end local function CycleOnlinePlayer(forward) local players = GetActivePlayers() local list = { { ped = PlayerPedId(), sId = GetPlayerServerId(PlayerId()), name = "Local Player (Self)", isSelf = true } } for _, pl in ipairs(players) do if pl ~= PlayerId() then local pPed = GetPlayerPed(pl) if DoesEntityExist(pPed) then local sId = GetPlayerServerId(pl) local name = GetPlayerName(pl) or ("Player #" .. tostring(sId)) table.insert(list, { ped = pPed, sId = sId, name = name, isSelf = false }) end end end local currentIndex = 1 for i, item in ipairs(list) do if item.sId == WTR.target.serverId then currentIndex = i break end end if forward then currentIndex = (currentIndex % #list) + 1 else currentIndex = ((currentIndex - 2) % #list) + 1 end local chosen = list[currentIndex] WTR.target.ped = chosen.ped WTR.target.serverId = chosen.sId WTR.target.name = chosen.name WTR.target.isSelf = chosen.isSelf if chosen.isSelf then WTR.target.dist = 0 else WTR.target.dist = math.floor(#(GetEntityCoords(PlayerPedId()) - GetEntityCoords(chosen.ped))) end Notify("~b~[WTR Target]~s~ " .. WTR.target.name .. " [ID: " .. WTR.target.serverId .. " | " .. WTR.target.dist .. "m]") PlaySound("NAV_LEFT_RIGHT") if SendDuiAction then SendDuiAction("SET_TARGET", { targetName = WTR.target.name }) end end local function SelectPlayerByIdPrompt() local input = PromptInput("Enter Server ID (or 0 for Self):") if input and input ~= "" then local idNum = tonumber(input) if not idNum or idNum == 0 or idNum == GetPlayerServerId(PlayerId()) then SelectSelfTarget() return end local pIdx = GetPlayerFromServerId(idNum) if pIdx and pIdx ~= -1 then local pPed = GetPlayerPed(pIdx) if DoesEntityExist(pPed) then WTR.target.ped = pPed WTR.target.serverId = idNum WTR.target.name = GetPlayerName(pIdx) or ("Player #" .. tostring(idNum)) WTR.target.dist = math.floor(#(GetEntityCoords(PlayerPedId()) - GetEntityCoords(pPed))) WTR.target.isSelf = false Notify("~g~[WTR Target]~s~ " .. WTR.target.name .. " [ID: " .. idNum .. "] selected!") PlaySound("SELECT") if SendDuiAction then SendDuiAction("SET_TARGET", { targetName = WTR.target.name }) end return end end Notify("~r~[WTR Target]~s~ Player with Server ID " .. input .. " not found!") PlaySound("ERROR") end end local function GetTargetPed() if WTR.target.isSelf or not WTR.target.ped or not DoesEntityExist(WTR.target.ped) then WTR.target.ped = PlayerPedId() WTR.target.isSelf = true WTR.target.name = "Local Player (Self)" return PlayerPedId() end return WTR.target.ped end local function GetSelectedTargets() local targets = {} local anyFound = false for sId, isSel in pairs(WTR.selectedPlayers) do if isSel then local numId = tonumber(sId) local pIdx = GetPlayerFromServerId(numId) if pIdx and pIdx ~= -1 then local pPed = GetPlayerPed(pIdx) if DoesEntityExist(pPed) then table.insert(targets, { ped = pPed, serverId = numId, name = GetPlayerName(pIdx) or ("Player #" .. tostring(sId)) }) anyFound = true end end end end if not anyFound then local singlePed = GetTargetPed() table.insert(targets, { ped = singlePed, serverId = WTR.target.serverId, name = WTR.target.name }) end return targets end local function ToggleSpectate(targetPed) local myPed = PlayerPedId() if WTR.spectating then WTR.spectating = false WTR.spectate_target = nil WTR.features.online_spectate = false Notify("~y~[WTR Spectate]~s~ Spectating ended.") else if not targetPed or not DoesEntityExist(targetPed) or targetPed == myPed then Notify("~r~[WTR Spectate]~s~ Select another player to spectate!", "error") WTR.features.online_spectate = false return end WTR.spectate_target = targetPed WTR.spectating = true WTR.features.online_spectate = true Notify("~g~[WTR Spectate]~s~ Spectating target: " .. WTR.target.name, "success") end end -- Embedded UI Bundle (HTML / CSS / JS) local WTR_UI_BUNDLE = "PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KPGhlYWQ+CiAgPG1ldGEgY2hhcnNldD0iVVRGLTgiPgogIDxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MS4wIj4KICA8dGl0bGU+V1RSIE1lbnU8L3RpdGxlPgogIDxzdHlsZT4KQGltcG9ydCB1cmwoJ2h0dHBzOi8vZm9udHMuZ29vZ2xlYXBpcy5jb20vY3NzMj9mYW1pbHk9UmFqZGhhbmk6d2dodEA1MDA7NjAwOzcwMDs4MDAmZmFtaWx5PUludGVyOndnaHRANDAwOzUwMDs2MDA7NzAwJmZhbWlseT1KZXRCcmFpbnMrTW9ubzp3Z2h0QDQwMDs2MDA7NzAwJmRpc3BsYXk9c3dhcCcpOwoKOnJvb3QgewogIC0tYmctYmFzZTogcmdiYSg4LCAxNiwgMjgsIDAuNTgpOwogIC0tYmctY2FyZDogcmdiYSgxMiwgMjQsIDQ0LCAwLjM1KTsKICAtLWJnLWNhcmQtaG92ZXI6IHJnYmEoMCwgMTY4LCAyNTUsIDAuMTIpOwogIC0tYmctYWN0aXZlOiByZ2JhKDAsIDI0MCwgMjU1LCAwLjE2KTsKICAtLWFjY2VudC1jeWFuOiAjMDBmMGZmOwogIC0tYWNjZW50LWJsdWU6ICMwMGE4ZmY7CiAgLS1hY2NlbnQtYmx1ZS1nbG93OiByZ2JhKDAsIDE2OCwgMjU1LCAwLjQ1KTsKICAtLWFjY2VudC1kZWVwOiAjMDI4NGM3OwogIC0tdGV4dC1tYWluOiAjZjBmOWZmOwogIC0tdGV4dC1tdXRlZDogIzk0YTNiODsKICAtLXRleHQtZGltOiAjNjQ3NDhiOwogIC0tYm9yZGVyLWdsYXNzOiByZ2JhKDAsIDI0MCwgMjU1LCAwLjI1KTsKICAtLWJvcmRlci1hY3RpdmU6ICMwMGYwZmY7CiAgLS1kYW5nZXItcmVkOiAjZWY0NDQ0OwogIC0tc3VjY2Vzcy1ncmVlbjogIzIyYzU1ZTsKfQoKKiB7CiAgbWFyZ2luOiAwOwogIHBhZGRpbmc6IDA7CiAgYm94LXNpemluZzogYm9yZGVyLWJveDsKICB1c2VyLXNlbGVjdDogbm9uZTsKICAtd2Via2l0LXVzZXItc2VsZWN0OiBub25lOwp9Cgpib2R5IHsKICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDsKICBmb250LWZhbWlseTogJ0ludGVyJywgLWFwcGxlLXN5c3RlbSwgQmxpbmtNYWNTeXN0ZW1Gb250LCBzYW5zLXNlcmlmOwogIGNvbG9yOiB2YXIoLS10ZXh0LW1haW4pOwogIHdpZHRoOiA0NDBweDsKICBoZWlnaHQ6IDcwMHB4OwogIG1hcmdpbjogMDsKICBwYWRkaW5nOiAwOwogIG92ZXJmbG93OiBoaWRkZW47CiAgZGlzcGxheTogZmxleDsKICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsKICBhbGlnbi1pdGVtczogZmxleC1zdGFydDsKfQoKLyogT3V0ZXIgV3JhcHBlciBmb3IgTWVudSArIERldGFjaGVkIEZsb2F0aW5nIFRvb2x0aXAgKi8KLm1lbnUtd3JhcHBlciB7CiAgd2lkdGg6IDM4MHB4OwogIGRpc3BsYXk6IGZsZXg7CiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsKICBhbGlnbi1pdGVtczogY2VudGVyOwogIGdhcDogOHB4OwogIG1hcmdpbi10b3A6IDEwcHg7Cn0KCi8qIE1haW4gVHJhbnNsdWNlbnQgV2F0ZXItR2xhc3MgRnJhbWUgKFRydWUgR2xhc3MgLSBObyBCbGFjayBCb3gpICovCi5tZW51LWNvbnRhaW5lciB7CiAgcG9zaXRpb246IHJlbGF0aXZlOwogIHdpZHRoOiAzODBweDsKICBoZWlnaHQ6IDU4MHB4OwogIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxODBkZWcsIHJnYmEoOCwgMTYsIDI4LCAwLjU4KSAwJSwgcmdiYSg1LCAxMCwgMTgsIDAuNjIpIDEwMCUpOwogIGJvcmRlci1yYWRpdXM6IDEycHg7CiAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgwLCAyNDAsIDI1NSwgMC4yOCk7CiAgYm94LXNoYWRvdzogCiAgICAwIDAgMjVweCByZ2JhKDAsIDI0MCwgMjU1LCAwLjEyKSwKICAgIDAgMTVweCAzNXB4IHJnYmEoMCwgMCwgMCwgMC40NSksCiAgICBpbnNldCAwIDFweCAxcHggcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjE1KTsKICBkaXNwbGF5OiBmbGV4OwogIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47CiAgb3ZlcmZsb3c6IGhpZGRlbjsKfQoKLyogU3VidGxlIFdhdGVyIENhdXN0aWNzIC8gVGFjdGljYWwgR3JpZCAqLwoud2F0ZXItY2F1c3RpY3MgewogIHBvc2l0aW9uOiBhYnNvbHV0ZTsKICB0b3A6IDA7CiAgbGVmdDogMDsKICByaWdodDogMDsKICBoZWlnaHQ6IDEyMHB4OwogIGJhY2tncm91bmQ6IHJhZGlhbC1ncmFkaWVudChjaXJjbGUgYXQgNTAlIC0xMCUsIHJnYmEoMCwgMjQwLCAyNTUsIDAuMjIpIDAlLCByZ2JhKDAsIDE2OCwgMjU1LCAwLjA2KSA1NSUsIHRyYW5zcGFyZW50IDg1JSk7CiAgcG9pbnRlci1ldmVudHM6IG5vbmU7Cn0KCi50YWN0aWNhbC1ncmlkIHsKICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgdG9wOiAwOwogIGxlZnQ6IDA7CiAgcmlnaHQ6IDA7CiAgYm90dG9tOiAwOwogIGJhY2tncm91bmQtaW1hZ2U6IAogICAgbGluZWFyLWdyYWRpZW50KHRvIHJpZ2h0LCByZ2JhKDAsIDE2OCwgMjU1LCAwLjAyKSAxcHgsIHRyYW5zcGFyZW50IDFweCksCiAgICBsaW5lYXItZ3JhZGllbnQodG8gYm90dG9tLCByZ2JhKDAsIDE2OCwgMjU1LCAwLjAyKSAxcHgsIHRyYW5zcGFyZW50IDFweCk7CiAgYmFja2dyb3VuZC1zaXplOiAxOHB4IDE4cHg7CiAgcG9pbnRlci1ldmVudHM6IG5vbmU7Cn0KCi8qIEhlYWRlciBCYW5uZXIgKEZsYW1lIE1lbnUgU3R5bGUgLSBDZW50ZXJlZCBMb2dvICYgVGl0bGUpICovCi5oZWFkZXItYm94IHsKICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgd2lkdGg6IDEwMCU7CiAgaGVpZ2h0OiA4MHB4OwogIGJhY2tncm91bmQ6IHJhZGlhbC1ncmFkaWVudChjaXJjbGUgYXQgNTAlIDIwJSwgcmdiYSgwLCAyNDAsIDI1NSwgMC4yMCkgMCUsIHJnYmEoNCwgMTIsIDI0LCAwLjYpIDg1JSk7CiAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkIHJnYmEoMCwgMjQwLCAyNTUsIDAuMjIpOwogIGRpc3BsYXk6IGZsZXg7CiAgYWxpZ24taXRlbXM6IGNlbnRlcjsKICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsKICBwYWRkaW5nOiAwIDEycHg7CiAgZmxleC1zaHJpbms6IDA7Cn0KCi5oZWFkZXItdG9wLXJvdyB7CiAgZGlzcGxheTogZmxleDsKICBhbGlnbi1pdGVtczogY2VudGVyOwogIGp1c3RpZnktY29udGVudDogY2VudGVyOwogIGdhcDogMTJweDsKfQoKLmVtYmxlbS13cmFwIHsKICB3aWR0aDogNDRweDsKICBoZWlnaHQ6IDQ0cHg7CiAgZGlzcGxheTogZmxleDsKICBhbGlnbi1pdGVtczogY2VudGVyOwogIGp1c3RpZnktY29udGVudDogY2VudGVyOwp9Cgoud2F0ZXItZW1ibGVtLXN2ZyB7CiAgd2lkdGg6IDQwcHg7CiAgaGVpZ2h0OiA0MHB4OwogIGZpbHRlcjogZHJvcC1zaGFkb3coMCAwIDhweCByZ2JhKDAsIDI0MCwgMjU1LCAwLjYpKTsKfQoKLm1lbnUtdGl0bGUgewogIGZvbnQtZmFtaWx5OiAnUmFqZGhhbmknLCBzYW5zLXNlcmlmOwogIGZvbnQtc2l6ZTogMzJweDsKICBmb250LXdlaWdodDogODAwOwogIGxldHRlci1zcGFjaW5nOiAxLjVweDsKICBjb2xvcjogI2ZmZmZmZjsKICBtYXJnaW46IDA7CiAgdGV4dC1zaGFkb3c6IDAgMCAxMnB4IHJnYmEoMCwgMjQwLCAyNTUsIDAuNCk7CiAgZGlzcGxheTogZmxleDsKICBhbGlnbi1pdGVtczogY2VudGVyOwogIGdhcDogNnB4Owp9CgouaHlkcm8tdGV4dCB7CiAgY29sb3I6ICMwMGYwZmY7CiAgdGV4dC1zaGFkb3c6IDAgMCAxNXB4IHJnYmEoMCwgMjQwLCAyNTUsIDAuNyk7Cn0KCi8qIEJyZWFkY3J1bWIgTmF2aWdhdGlvbiBCYXIgKEZsYW1lIFN0eWxlKSAqLwouYnJlYWRjcnVtYi1iYXIgewogIHdpZHRoOiAxMDAlOwogIGhlaWdodDogMjhweDsKICBiYWNrZ3JvdW5kOiByZ2JhKDQsIDgsIDE2LCAwLjU1KTsKICBib3JkZXItYm90dG9tOiAxcHggc29saWQgcmdiYSgwLCAyNDAsIDI1NSwgMC4xOCk7CiAgZGlzcGxheTogZmxleDsKICBhbGlnbi1pdGVtczogY2VudGVyOwogIGp1c3RpZnktY29udGVudDogY2VudGVyOwogIGdhcDogNnB4OwogIGZvbnQtZmFtaWx5OiAnUmFqZGhhbmknLCBzYW5zLXNlcmlmOwogIGZvbnQtc2l6ZTogMTRweDsKICBmb250LXdlaWdodDogNzAwOwogIGxldHRlci1zcGFjaW5nOiAwLjZweDsKICBmbGV4LXNocmluazogMDsKfQoKLmNydW1iLXJvb3QgewogIGNvbG9yOiAjZmZmZmZmOwp9CgouY3J1bWItc2VwYXJhdG9yIHsKICBjb2xvcjogdmFyKC0tYWNjZW50LWJsdWUpOwogIGZvbnQtc2l6ZTogMTJweDsKfQoKLmNydW1iLXN1YiB7CiAgY29sb3I6IHZhcigtLWFjY2VudC1jeWFuKTsKfQoKLyogU3ViY2F0ZWdvcmllcyBCYXIgKFEgLyBFKSAqLwouc3VidGFicy1iYXIgewogIHdpZHRoOiAxMDAlOwogIGhlaWdodDogMzRweDsKICBkaXNwbGF5OiBmbGV4OwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAgZ2FwOiA0cHg7CiAgYmFja2dyb3VuZDogcmdiYSg2LCAxMiwgMjIsIDAuNDUpOwogIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCByZ2JhKDAsIDI0MCwgMjU1LCAwLjE4KTsKICBwYWRkaW5nOiAwIDZweDsKICBmbGV4LXNocmluazogMDsKfQoKLnN1YnRhYi1rZXkgewogIHdpZHRoOiAyMnB4OwogIGhlaWdodDogMjJweDsKICBkaXNwbGF5OiBmbGV4OwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7CiAgYmFja2dyb3VuZDogcmdiYSgwLCAxNjgsIDI1NSwgMC4xNCk7CiAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgwLCAyNDAsIDI1NSwgMC4zNSk7CiAgYm9yZGVyLXJhZGl1czogNHB4OwogIGNvbG9yOiB2YXIoLS1hY2NlbnQtY3lhbik7CiAgZm9udC1mYW1pbHk6ICdSYWpkaGFuaScsIHNhbnMtc2VyaWY7CiAgZm9udC13ZWlnaHQ6IDcwMDsKICBmb250LXNpemU6IDEycHg7CiAgY3Vyc29yOiBwb2ludGVyOwogIGZsZXgtc2hyaW5rOiAwOwp9Cgouc3VidGFiLWtleTpob3ZlciB7CiAgYmFja2dyb3VuZDogcmdiYSgwLCAyNDAsIDI1NSwgMC4yNSk7Cn0KCi5zdWJ0YWJzLXNjcm9sbCB7CiAgZGlzcGxheTogZmxleDsKICBhbGlnbi1pdGVtczogY2VudGVyOwogIGdhcDogNHB4OwogIG92ZXJmbG93LXg6IGF1dG87CiAgc2Nyb2xsYmFyLXdpZHRoOiBub25lOwogIGZsZXgtZ3JvdzogMTsKfQoKLnN1YnRhYnMtc2Nyb2xsOjotd2Via2l0LXNjcm9sbGJhciB7CiAgZGlzcGxheTogbm9uZTsKfQoKLnN1YnRhYi1pdGVtLAouc3VidGFiLXBpbGwgewogIGZsZXg6IDE7CiAgdGV4dC1hbGlnbjogY2VudGVyOwogIHBhZGRpbmc6IDVweCA4cHg7CiAgYm9yZGVyLXJhZGl1czogNXB4OwogIGZvbnQtZmFtaWx5OiAnUmFqZGhhbmknLCBzYW5zLXNlcmlmOwogIGZvbnQtc2l6ZTogMTEuNXB4OwogIGZvbnQtd2VpZ2h0OiA3MDA7CiAgbGV0dGVyLXNwYWNpbmc6IDAuNnB4OwogIHRleHQtdHJhbnNmb3JtOiB1cHBlcmNhc2U7CiAgY29sb3I6ICM5NGEzYjg7CiAgY3Vyc29yOiBwb2ludGVyOwogIHdoaXRlLXNwYWNlOiBub3dyYXA7CiAgdHJhbnNpdGlvbjogYWxsIDAuMnMgY3ViaWMtYmV6aWVyKDAuMTYsIDEsIDAuMywgMSk7CiAgYmFja2dyb3VuZDogcmdiYSgxMiwgMjQsIDQ0LCAwLjQ1KTsKICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDAsIDI0MCwgMjU1LCAwLjE0KTsKfQoKLnN1YnRhYi1pdGVtOmhvdmVyLAouc3VidGFiLXBpbGw6aG92ZXIgewogIGNvbG9yOiAjZmZmZmZmOwogIGJhY2tncm91bmQ6IHJnYmEoMCwgMjQwLCAyNTUsIDAuMTQpOwogIGJvcmRlci1jb2xvcjogcmdiYSgwLCAyNDAsIDI1NSwgMC4zNSk7Cn0KCi5zdWJ0YWItaXRlbS5hY3RpdmUsCi5zdWJ0YWItcGlsbC5hY3RpdmUgewogIGNvbG9yOiAjMDMwODE0OwogIGJhY2tncm91bmQ6ICMwMGYwZmY7CiAgYm9yZGVyOiAxcHggc29saWQgIzAwZjBmZjsKICBmb250LXdlaWdodDogODAwOwogIGJveC1zaGFkb3c6IDAgMCAxNHB4IHJnYmEoMCwgMjQwLCAyNTUsIDAuNzUpLCBpbnNldCAwIDFweCAwIHJnYmEoMjU1LCAyNTUsIDI1NSwgMC40KTsKICB0ZXh0LXNoYWRvdzogbm9uZTsKfQoKLyogT25saW5lIFRvb2xiYXIgKi8KLm9ubGluZS10b29sYmFyIHsKICBkaXNwbGF5OiBmbGV4OwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAgZ2FwOiA1cHg7CiAgcGFkZGluZzogMnB4IDA7CiAgZmxleC1zaHJpbms6IDA7Cn0KCi50b29sLWJ0biB7CiAgcGFkZGluZzogM3B4IDhweDsKICBib3JkZXItcmFkaXVzOiA0cHg7CiAgZm9udC1mYW1pbHk6ICdSYWpkaGFuaScsIHNhbnMtc2VyaWY7CiAgZm9udC1zaXplOiAxMHB4OwogIGZvbnQtd2VpZ2h0OiA3MDA7CiAgY3Vyc29yOiBwb2ludGVyOwogIGJhY2tncm91bmQ6IHJnYmEoMTAsIDI0LCA0NiwgMC44KTsKICBib3JkZXI6IDFweCBzb2xpZCB2YXIoLS1ib3JkZXItZ2xhc3MpOwogIGNvbG9yOiB2YXIoLS10ZXh0LW11dGVkKTsKICB0cmFuc2l0aW9uOiBhbGwgMC4xMnM7Cn0KCi50b29sLWJ0bjpob3ZlciB7CiAgYmFja2dyb3VuZDogcmdiYSgwLCAxNjgsIDI1NSwgMC4yKTsKICBjb2xvcjogI2ZmZmZmZjsKICBib3JkZXItY29sb3I6IHZhcigtLWFjY2VudC1jeWFuKTsKfQoKLnRvb2wtY291bnRlciB7CiAgbWFyZ2luLWxlZnQ6IGF1dG87CiAgZm9udC1mYW1pbHk6ICdKZXRCcmFpbnMgTW9ubycsIG1vbm9zcGFjZTsKICBmb250LXNpemU6IDlweDsKICBjb2xvcjogdmFyKC0tdGV4dC1kaW0pOwp9CgoudG9vbC1jb3VudGVyIGIgewogIGNvbG9yOiB2YXIoLS1hY2NlbnQtY3lhbik7Cn0KCi8qIE1haW4gSXRlbXMgTGlzdCBDb250YWluZXIgKi8KLml0ZW1zLWxpc3QgewogIGZsZXg6IDE7CiAgZGlzcGxheTogZmxleDsKICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOwogIGdhcDogM3B4OwogIG92ZXJmbG93LXk6IGF1dG87CiAgb3ZlcmZsb3cteDogaGlkZGVuOwogIHBhZGRpbmctcmlnaHQ6IDJweDsKICBzY3JvbGxiYXItd2lkdGg6IHRoaW47CiAgc2Nyb2xsYmFyLWNvbG9yOiByZ2JhKDAsIDE2OCwgMjU1LCAwLjM1KSB0cmFuc3BhcmVudDsKfQoKLml0ZW1zLWxpc3Q6Oi13ZWJraXQtc2Nyb2xsYmFyIHsKICB3aWR0aDogM3B4Owp9CgouaXRlbXMtbGlzdDo6LXdlYmtpdC1zY3JvbGxiYXItdGh1bWIgewogIGJhY2tncm91bmQ6IHJnYmEoMCwgMTY4LCAyNTUsIDAuMzUpOwogIGJvcmRlci1yYWRpdXM6IDNweDsKfQoKLyogU2VjdGlvbiBIZWFkZXIgKERpdmlkZXIgaW5zaWRlIGxpc3RzKSAqLwouc2VjdGlvbi1oZWFkZXIgewogIHBvc2l0aW9uOiByZWxhdGl2ZTsKICBkaXNwbGF5OiBmbGV4OwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7CiAgcGFkZGluZzogNnB4IDAgM3B4IDA7CiAgbWFyZ2luLXRvcDogMnB4Owp9Cgouc2VjdGlvbi1saW5lIHsKICBmbGV4OiAxOwogIGhlaWdodDogMXB4OwogIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCg5MGRlZywgdHJhbnNwYXJlbnQsIHJnYmEoMCwgMTY4LCAyNTUsIDAuMyksIHRyYW5zcGFyZW50KTsKfQoKLnNlY3Rpb24tdGl0bGUgewogIHBhZGRpbmc6IDAgMTBweDsKICBmb250LWZhbWlseTogJ1JhamRoYW5pJywgc2Fucy1zZXJpZjsKICBmb250LXNpemU6IDExcHg7CiAgZm9udC13ZWlnaHQ6IDcwMDsKICBsZXR0ZXItc3BhY2luZzogMC44cHg7CiAgY29sb3I6IHZhcigtLXRleHQtbXV0ZWQpOwogIHRleHQtdHJhbnNmb3JtOiB1cHBlcmNhc2U7Cn0KCi8qIE1lbnUgSXRlbSBSb3cgKi8KLm1lbnUtcm93IHsKICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgaGVpZ2h0OiAzNXB4OwogIG1pbi1oZWlnaHQ6IDM1cHg7CiAgYmFja2dyb3VuZDogcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjAyKTsKICBib3JkZXI6IDFweCBzb2xpZCB0cmFuc3BhcmVudDsKICBib3JkZXItcmFkaXVzOiA2cHg7CiAgZGlzcGxheTogZmxleDsKICBhbGlnbi1pdGVtczogY2VudGVyOwogIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjsKICBwYWRkaW5nOiAwIDEycHg7CiAgY3Vyc29yOiBwb2ludGVyOwogIHRyYW5zaXRpb246IGFsbCAwLjEycyBlYXNlOwp9CgoubWVudS1yb3c6aG92ZXIgewogIGJhY2tncm91bmQ6IHJnYmEoMCwgMTY4LCAyNTUsIDAuMDgpOwogIGJvcmRlci1jb2xvcjogcmdiYSgwLCAyNDAsIDI1NSwgMC4yKTsKfQoKLyogQWN0aXZlIEhpZ2hsaWdodCBPdXRsaW5lIChGbGFtZSBTdHlsZSB3aXRoIGdsb3dpbmcgY3lhbiBvdXRsaW5lKSAqLwoubWVudS1yb3cuYWN0aXZlIHsKICBiYWNrZ3JvdW5kOiByZ2JhKDAsIDI0MCwgMjU1LCAwLjE0KTsKICBib3JkZXI6IDEuNXB4IHNvbGlkICMwMGYwZmY7CiAgYm94LXNoYWRvdzogCiAgICAwIDAgMTJweCByZ2JhKDAsIDI0MCwgMjU1LCAwLjM1KSwKICAgIGluc2V0IDAgMCA4cHggcmdiYSgwLCAyNDAsIDI1NSwgMC4xMik7Cn0KCi5yb3ctbGVmdCB7CiAgZGlzcGxheTogZmxleDsKICBhbGlnbi1pdGVtczogY2VudGVyOwogIGdhcDogOHB4OwogIG92ZXJmbG93OiBoaWRkZW47Cn0KCi5yb3ctaWNvbiB7CiAgd2lkdGg6IDE1cHg7CiAgaGVpZ2h0OiAxNXB4OwogIGRpc3BsYXk6IGZsZXg7CiAgYWxpZ24taXRlbXM6IGNlbnRlcjsKICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsKICBjb2xvcjogdmFyKC0tYWNjZW50LWN5YW4pOwogIGZsZXgtc2hyaW5rOiAwOwp9Cgoucm93LWljb24gc3ZnIHsKICB3aWR0aDogMTAwJTsKICBoZWlnaHQ6IDEwMCU7CiAgZmlsbDogY3VycmVudENvbG9yOwp9Cgoucm93LWxhYmVsIHsKICBmb250LWZhbWlseTogJ0ludGVyJywgc2Fucy1zZXJpZjsKICBmb250LXNpemU6IDExLjVweDsKICBmb250LXdlaWdodDogNTAwOwogIGNvbG9yOiB2YXIoLS10ZXh0LW1haW4pOwogIHdoaXRlLXNwYWNlOiBub3dyYXA7CiAgb3ZlcmZsb3c6IGhpZGRlbjsKICB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpczsKfQoKLnJvdy1yaWdodCB7CiAgZGlzcGxheTogZmxleDsKICBhbGlnbi1pdGVtczogY2VudGVyOwogIGdhcDogNnB4OwogIGZsZXgtc2hyaW5rOiAwOwp9Cgoucm93LWNoZXZyb24gewogIGZvbnQtZmFtaWx5OiAnUmFqZGhhbmknLCBzYW5zLXNlcmlmOwogIGZvbnQtc2l6ZTogMTRweDsKICBmb250LXdlaWdodDogNzAwOwogIGNvbG9yOiB2YXIoLS10ZXh0LWRpbSk7Cn0KCi5tZW51LXJvdy5hY3RpdmUgLnJvdy1jaGV2cm9uIHsKICBjb2xvcjogdmFyKC0tYWNjZW50LWN5YW4pOwp9CgovKiBTd2l0Y2ggLyBUb2dnbGUgUGlsbCAqLwoucm93LXN3aXRjaCB7CiAgd2lkdGg6IDMycHg7CiAgaGVpZ2h0OiAxNnB4OwogIGJvcmRlci1yYWRpdXM6IDlweDsKICBiYWNrZ3JvdW5kOiByZ2JhKDEwLCAyMCwgMzgsIDAuOCk7CiAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjEyKTsKICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgdHJhbnNpdGlvbjogYWxsIDAuMnMgZWFzZTsKfQoKLnJvdy1zd2l0Y2g6OmFmdGVyIHsKICBjb250ZW50OiAnJzsKICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgdG9wOiAxLjVweDsKICBsZWZ0OiAycHg7CiAgd2lkdGg6IDExcHg7CiAgaGVpZ2h0OiAxMXB4OwogIGJvcmRlci1yYWRpdXM6IDUwJTsKICBiYWNrZ3JvdW5kOiAjNjQ3NDhiOwogIHRyYW5zaXRpb246IGFsbCAwLjJzIGVhc2U7Cn0KCi5yb3ctc3dpdGNoLm9uIHsKICBiYWNrZ3JvdW5kOiByZ2JhKDAsIDE2OCwgMjU1LCAwLjM1KTsKICBib3JkZXItY29sb3I6IHZhcigtLWFjY2VudC1jeWFuKTsKICBib3gtc2hhZG93OiAwIDAgOHB4IHJnYmEoMCwgMjQwLCAyNTUsIDAuNCk7Cn0KCi5yb3ctc3dpdGNoLm9uOjphZnRlciB7CiAgbGVmdDogMTdweDsKICBiYWNrZ3JvdW5kOiB2YXIoLS1hY2NlbnQtY3lhbik7CiAgYm94LXNoYWRvdzogMCAwIDZweCB2YXIoLS1hY2NlbnQtY3lhbik7Cn0KCi8qIFZhbHVlIC8gT3B0aW9uIFRhZyAqLwoucm93LXZhbHVlIHsKICBmb250LWZhbWlseTogJ1JhamRoYW5pJywgc2Fucy1zZXJpZjsKICBmb250LXNpemU6IDExcHg7CiAgZm9udC13ZWlnaHQ6IDcwMDsKICBjb2xvcjogdmFyKC0tYWNjZW50LWN5YW4pOwogIGxldHRlci1zcGFjaW5nOiAwLjVweDsKfQoKLyogQWN0aXZlIE9ubGluZSBUYXJnZXQgSW5kaWNhdG9yIEJhbm5lciAqLwoudGFyZ2V0LWluZGljYXRvci1iYW5uZXIgewogIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCg5MGRlZywgcmdiYSgwLCAyNDAsIDI1NSwgMC4xNSkgMCUsIHJnYmEoMiwgMTMyLCAxOTksIDAuMSkgMTAwJSk7CiAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgwLCAyNDAsIDI1NSwgMC4zNSk7CiAgYm9yZGVyLXJhZGl1czogNnB4OwogIHBhZGRpbmc6IDZweCAxMHB4OwogIG1hcmdpbi1ib3R0b206IDZweDsKICBmb250LWZhbWlseTogJ1JhamRoYW5pJywgc2Fucy1zZXJpZjsKICBmb250LXNpemU6IDEycHg7CiAgZm9udC13ZWlnaHQ6IDcwMDsKICBjb2xvcjogI2UwZjJmZTsKICBkaXNwbGF5OiBmbGV4OwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAgZ2FwOiA2cHg7CiAgbGV0dGVyLXNwYWNpbmc6IDAuNXB4OwogIGJveC1zaGFkb3c6IDAgMCAxMHB4IHJnYmEoMCwgMjQwLCAyNTUsIDAuMSk7Cn0KCi50YXJnZXQtYmFkZ2UtaWNvbiB7CiAgZm9udC1zaXplOiAxM3B4Owp9CgovKiBPbmxpbmUgUGxheWVyIENhcmQgSXRlbSAqLwoucGxheWVyLWNhcmQgewogIHBvc2l0aW9uOiByZWxhdGl2ZTsKICBoZWlnaHQ6IDM4cHg7CiAgbWluLWhlaWdodDogMzhweDsKICBiYWNrZ3JvdW5kOiB2YXIoLS1iZy1jYXJkKTsKICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuMDUpOwogIGJvcmRlci1yYWRpdXM6IDZweDsKICBkaXNwbGF5OiBmbGV4OwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuOwogIHBhZGRpbmc6IDAgMTBweDsKICBjdXJzb3I6IHBvaW50ZXI7CiAgdHJhbnNpdGlvbjogYWxsIDAuMTJzIGVhc2U7Cn0KCi5wbGF5ZXItY2FyZDpob3ZlciB7CiAgYmFja2dyb3VuZDogdmFyKC0tYmctY2FyZC1ob3Zlcik7Cn0KCi5wbGF5ZXItY2FyZC5hY3RpdmUgewogIGJhY2tncm91bmQ6IHZhcigtLWJnLWFjdGl2ZSk7CiAgYm9yZGVyOiAxLjVweCBzb2xpZCB2YXIoLS1ib3JkZXItYWN0aXZlKTsKICBib3gtc2hhZG93OiAwIDAgMTBweCB2YXIoLS1hY2NlbnQtYmx1ZS1nbG93KTsKfQoKLnBsYXllci1jYXJkLnNlbGVjdGVkIHsKICBib3JkZXItbGVmdDogM3B4IHNvbGlkIHZhcigtLWFjY2VudC1jeWFuKTsKfQoKLnBsYXllci1sZWZ0IHsKICBkaXNwbGF5OiBmbGV4OwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAgZ2FwOiA3cHg7CiAgb3ZlcmZsb3c6IGhpZGRlbjsKfQoKLnBsYXllci1jaGVjayB7CiAgd2lkdGg6IDE0cHg7CiAgaGVpZ2h0OiAxNHB4OwogIGJvcmRlci1yYWRpdXM6IDNweDsKICBiYWNrZ3JvdW5kOiByZ2JhKDgsIDE2LCAzMiwgMC44NSk7CiAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjIpOwogIGRpc3BsYXk6IGZsZXg7CiAgYWxpZ24taXRlbXM6IGNlbnRlcjsKICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsKICBmb250LXNpemU6IDlweDsKICBjb2xvcjogdHJhbnNwYXJlbnQ7CiAgZmxleC1zaHJpbms6IDA7Cn0KCi5wbGF5ZXItY2FyZC5zZWxlY3RlZCAucGxheWVyLWNoZWNrIHsKICBiYWNrZ3JvdW5kOiB2YXIoLS1hY2NlbnQtY3lhbik7CiAgYm9yZGVyLWNvbG9yOiB2YXIoLS1hY2NlbnQtY3lhbik7CiAgY29sb3I6ICMwMDAwMDA7CiAgZm9udC13ZWlnaHQ6IDkwMDsKICBib3gtc2hhZG93OiAwIDAgNnB4IHZhcigtLWFjY2VudC1jeWFuKTsKfQoKLnBsYXllci1pZCB7CiAgZm9udC1mYW1pbHk6ICdKZXRCcmFpbnMgTW9ubycsIG1vbm9zcGFjZTsKICBmb250LXNpemU6IDkuNXB4OwogIGZvbnQtd2VpZ2h0OiA3MDA7CiAgY29sb3I6IHZhcigtLWFjY2VudC1jeWFuKTsKICBiYWNrZ3JvdW5kOiByZ2JhKDAsIDE2OCwgMjU1LCAwLjEpOwogIHBhZGRpbmc6IDFweCA0cHg7CiAgYm9yZGVyLXJhZGl1czogM3B4Owp9CgoucGxheWVyLW5hbWUgewogIGZvbnQtZmFtaWx5OiAnSW50ZXInLCBzYW5zLXNlcmlmOwogIGZvbnQtc2l6ZTogMTEuNXB4OwogIGZvbnQtd2VpZ2h0OiA2MDA7CiAgY29sb3I6IHZhcigtLXRleHQtbWFpbik7CiAgd2hpdGUtc3BhY2U6IG5vd3JhcDsKICBvdmVyZmxvdzogaGlkZGVuOwogIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzOwogIG1heC13aWR0aDogMTQwcHg7Cn0KCi5wbGF5ZXItcmlnaHQgewogIGRpc3BsYXk6IGZsZXg7CiAgYWxpZ24taXRlbXM6IGNlbnRlcjsKICBnYXA6IDZweDsKICBmbGV4LXNocmluazogMDsKfQoKLnBsYXllci1kaXN0IHsKICBmb250LWZhbWlseTogJ0pldEJyYWlucyBNb25vJywgbW9ub3NwYWNlOwogIGZvbnQtc2l6ZTogOXB4OwogIGZvbnQtd2VpZ2h0OiA2MDA7CiAgY29sb3I6IHZhcigtLXRleHQtbXV0ZWQpOwogIGJhY2tncm91bmQ6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4wNSk7CiAgcGFkZGluZzogMXB4IDRweDsKICBib3JkZXItcmFkaXVzOiAzcHg7Cn0KCi8qIEZsb2F0aW5nIERldGFjaGVkIFRvb2x0aXAgQm94IChGbGFtZSBTdHlsZSkgKi8KLnRvb2x0aXAtZmxvYXRpbmctYm94IHsKICB3aWR0aDogMzgwcHg7CiAgbWluLWhlaWdodDogMzZweDsKICBiYWNrZ3JvdW5kOiByZ2JhKDYsIDE0LCAyNiwgMC42NSk7CiAgYm9yZGVyLXJhZGl1czogOHB4OwogIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoMCwgMjQwLCAyNTUsIDAuMzUpOwogIGJveC1zaGFkb3c6IAogICAgMCAwIDE0cHggcmdiYSgwLCAyNDAsIDI1NSwgMC4xMiksCiAgICAwIDhweCAyMHB4IHJnYmEoMCwgMCwgMCwgMC40NSk7CiAgZGlzcGxheTogZmxleDsKICBhbGlnbi1pdGVtczogY2VudGVyOwogIGp1c3RpZnktY29udGVudDogY2VudGVyOwogIHBhZGRpbmc6IDhweCAxNHB4OwogIGJveC1zaXppbmc6IGJvcmRlci1ib3g7CiAgZmxleC1zaHJpbms6IDA7Cn0KCi50b29sdGlwLXRleHQgewogIGZvbnQtZmFtaWx5OiAnSW50ZXInLCBzYW5zLXNlcmlmOwogIGZvbnQtc2l6ZTogMTEuNXB4OwogIGZvbnQtd2VpZ2h0OiA1MDA7CiAgY29sb3I6ICNlMGYyZmU7CiAgdGV4dC1hbGlnbjogY2VudGVyOwogIGxpbmUtaGVpZ2h0OiAxLjM1OwogIGxldHRlci1zcGFjaW5nOiAwLjJweDsKfQoKLyogRm9vdGVyIEJhciAqLwouZm9vdGVyLWJhciB7CiAgaGVpZ2h0OiAyOHB4OwogIGJhY2tncm91bmQ6IHJnYmEoNCwgOCwgMTYsIDAuNik7CiAgYm9yZGVyLXRvcDogMXB4IHNvbGlkIHJnYmEoMCwgMjQwLCAyNTUsIDAuMTgpOwogIGRpc3BsYXk6IGZsZXg7CiAgYWxpZ24taXRlbXM6IGNlbnRlcjsKICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47CiAgcGFkZGluZzogMCAxMnB4OwogIGZsZXgtc2hyaW5rOiAwOwp9CgouZm9vdGVyLWJyYW5kIHsKICBkaXNwbGF5OiBmbGV4OwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAgZ2FwOiA2cHg7Cn0KCi5mb290ZXItaWNvbiB7CiAgZm9udC1zaXplOiA5cHg7CiAgY29sb3I6IHZhcigtLWFjY2VudC1jeWFuKTsKfQoKLmZvb3Rlci10ZXh0IHsKICBmb250LWZhbWlseTogJ1JhamRoYW5pJywgc2Fucy1zZXJpZjsKICBmb250LXNpemU6IDEycHg7CiAgZm9udC13ZWlnaHQ6IDcwMDsKICBjb2xvcjogdmFyKC0tdGV4dC1tdXRlZCk7CiAgbGV0dGVyLXNwYWNpbmc6IDAuNXB4Owp9CgouZm9vdGVyLWNvdW50ZXIgewogIGZvbnQtZmFtaWx5OiAnSmV0QnJhaW5zIE1vbm8nLCBtb25vc3BhY2U7CiAgZm9udC1zaXplOiAxMXB4OwogIGZvbnQtd2VpZ2h0OiA3MDA7CiAgY29sb3I6IHZhcigtLWFjY2VudC1jeWFuKTsKfQoKLyogVGVybWluYWwgTW9kYWwgRGlhbG9nICovCi5tb2RhbC1vdmVybGF5IHsKICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgdG9wOiAwOwogIGxlZnQ6IDA7CiAgcmlnaHQ6IDA7CiAgYm90dG9tOiAwOwogIGJhY2tncm91bmQ6IHJnYmEoMiwgNiwgMTQsIDAuODUpOwogIGJhY2tkcm9wLWZpbHRlcjogYmx1cig4cHgpOwogIC13ZWJraXQtYmFja2Ryb3AtZmlsdGVyOiBibHVyKDhweCk7CiAgZGlzcGxheTogZmxleDsKICBhbGlnbi1pdGVtczogY2VudGVyOwogIGp1c3RpZnktY29udGVudDogY2VudGVyOwogIHBhZGRpbmc6IDE2cHg7CiAgei1pbmRleDogMTAwOwp9CgoubW9kYWwtY2FyZCB7CiAgd2lkdGg6IDEwMCU7CiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDE4MGRlZywgcmdiYSgxMiwgMjYsIDUwLCAwLjk2KSAwJSwgcmdiYSg2LCAxNCwgMjgsIDAuOTgpIDEwMCUpOwogIGJvcmRlcjogMS41cHggc29saWQgdmFyKC0tYWNjZW50LWN5YW4pOwogIGJvcmRlci1yYWRpdXM6IDEwcHg7CiAgYm94LXNoYWRvdzogCiAgICAwIDAgMjVweCByZ2JhKDAsIDE2OCwgMjU1LCAwLjMpLAogICAgMCAxNXB4IDM1cHggcmdiYSgwLCAwLCAwLCAwLjkpOwogIHBhZGRpbmc6IDEycHg7CiAgZGlzcGxheTogZmxleDsKICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOwogIGdhcDogOHB4Owp9CgoubW9kYWwtaGVhZGVyIHsKICBkaXNwbGF5OiBmbGV4OwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuOwp9CgoubW9kYWwtdGFnIHsKICBmb250LWZhbWlseTogJ0pldEJyYWlucyBNb25vJywgbW9ub3NwYWNlOwogIGZvbnQtc2l6ZTogOHB4OwogIGZvbnQtd2VpZ2h0OiA3MDA7CiAgY29sb3I6IHZhcigtLWFjY2VudC1jeWFuKTsKICBsZXR0ZXItc3BhY2luZzogMXB4Owp9CgoubW9kYWwtY2xvc2UgewogIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50OwogIGJvcmRlcjogbm9uZTsKICBjb2xvcjogdmFyKC0tdGV4dC1kaW0pOwogIGZvbnQtc2l6ZTogMTNweDsKICBjdXJzb3I6IHBvaW50ZXI7Cn0KCi5tb2RhbC10aXRsZSB7CiAgZm9udC1mYW1pbHk6ICdSYWpkaGFuaScsIHNhbnMtc2VyaWY7CiAgZm9udC1zaXplOiAxNnB4OwogIGZvbnQtd2VpZ2h0OiA4MDA7CiAgY29sb3I6ICNmZmZmZmY7CiAgbGV0dGVyLXNwYWNpbmc6IDAuOHB4Owp9CgoubW9kYWwtYm9keSB7CiAgZGlzcGxheTogZmxleDsKICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOwogIGdhcDogN3B4Owp9CgoubW9kYWwtaW5wdXQtd3JhcCB7CiAgcG9zaXRpb246IHJlbGF0aXZlOwogIGRpc3BsYXk6IGZsZXg7CiAgYWxpZ24taXRlbXM6IGNlbnRlcjsKfQoKLm1vZGFsLWlucHV0IHsKICB3aWR0aDogMTAwJTsKICBoZWlnaHQ6IDM0cHg7CiAgYmFja2dyb3VuZDogcmdiYSg2LCAxMiwgMjQsIDAuOSk7CiAgYm9yZGVyOiAxLjVweCBzb2xpZCByZ2JhKDAsIDE2OCwgMjU1LCAwLjM1KTsKICBib3JkZXItcmFkaXVzOiA2cHg7CiAgcGFkZGluZzogMCAyOHB4IDAgOHB4OwogIGZvbnQtZmFtaWx5OiAnSW50ZXInLCBzYW5zLXNlcmlmOwogIGZvbnQtc2l6ZTogMTEuNXB4OwogIGNvbG9yOiAjZmZmZmZmOwogIG91dGxpbmU6IG5vbmU7Cn0KCi5tb2RhbC1pbnB1dDpmb2N1cyB7CiAgYm9yZGVyLWNvbG9yOiB2YXIoLS1hY2NlbnQtY3lhbik7CiAgYm94LXNoYWRvdzogMCAwIDEwcHggcmdiYSgwLCAyNDAsIDI1NSwgMC4zKTsKfQoKLm1vZGFsLWNsZWFyLWJ0biB7CiAgcG9zaXRpb246IGFic29sdXRlOwogIHJpZ2h0OiA4cHg7CiAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7CiAgYm9yZGVyOiBub25lOwogIGNvbG9yOiB2YXIoLS10ZXh0LWRpbSk7CiAgZm9udC1zaXplOiAxMnB4OwogIGN1cnNvcjogcG9pbnRlcjsKfQoKLm1vZGFsLXByZXNldHMtbGFiZWwgewogIGZvbnQtZmFtaWx5OiAnSmV0QnJhaW5zIE1vbm8nLCBtb25vc3BhY2U7CiAgZm9udC1zaXplOiA4cHg7CiAgZm9udC13ZWlnaHQ6IDcwMDsKICBjb2xvcjogdmFyKC0tdGV4dC1kaW0pOwp9CgoubW9kYWwtcHJlc2V0cy1ncmlkIHsKICBkaXNwbGF5OiBmbGV4OwogIGZsZXgtd3JhcDogd3JhcDsKICBnYXA6IDRweDsKICBtYXgtaGVpZ2h0OiA4MHB4OwogIG92ZXJmbG93LXk6IGF1dG87Cn0KCi5wcmVzZXQtY2hpcCB7CiAgcGFkZGluZzogMi41cHggN3B4OwogIGJhY2tncm91bmQ6IHJnYmEoMTAsIDI0LCA0NiwgMC44NSk7CiAgYm9yZGVyOiAxcHggc29saWQgdmFyKC0tYm9yZGVyLWdsYXNzKTsKICBib3JkZXItcmFkaXVzOiA0cHg7CiAgZm9udC1mYW1pbHk6ICdSYWpkaGFuaScsIHNhbnMtc2VyaWY7CiAgZm9udC1zaXplOiAxMC41cHg7CiAgZm9udC13ZWlnaHQ6IDcwMDsKICBjb2xvcjogdmFyKC0tdGV4dC1tdXRlZCk7CiAgY3Vyc29yOiBwb2ludGVyOwp9CgoucHJlc2V0LWNoaXA6aG92ZXIgewogIGJhY2tncm91bmQ6IHJnYmEoMCwgMTY4LCAyNTUsIDAuMjUpOwogIGJvcmRlci1jb2xvcjogdmFyKC0tYWNjZW50LWN5YW4pOwogIGNvbG9yOiAjZmZmZmZmOwp9CgoubW9kYWwtZm9vdGVyIHsKICBkaXNwbGF5OiBmbGV4OwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAganVzdGlmeS1jb250ZW50OiBmbGV4LWVuZDsKICBnYXA6IDZweDsKICBtYXJnaW4tdG9wOiAycHg7Cn0KCi5tb2RhbC1hY3Rpb24tYnRuIHsKICBwYWRkaW5nOiA1cHggMTFweDsKICBib3JkZXItcmFkaXVzOiA1cHg7CiAgZm9udC1mYW1pbHk6ICdSYWpkaGFuaScsIHNhbnMtc2VyaWY7CiAgZm9udC1zaXplOiAxMXB4OwogIGZvbnQtd2VpZ2h0OiA3MDA7CiAgY3Vyc29yOiBwb2ludGVyOwp9CgoubW9kYWwtYWN0aW9uLWJ0bi5jYW5jZWwgewogIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50OwogIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4xKTsKICBjb2xvcjogdmFyKC0tdGV4dC1tdXRlZCk7Cn0KCi5tb2RhbC1hY3Rpb24tYnRuLmNvbmZpcm0gewogIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCg5MGRlZywgIzAyODRjNyAwJSwgIzAwZjBmZiAxMDAlKTsKICBib3JkZXI6IG5vbmU7CiAgY29sb3I6ICMwMDAwMDA7CiAgYm94LXNoYWRvdzogMCAwIDhweCByZ2JhKDAsIDI0MCwgMjU1LCAwLjM1KTsKfQoKLyogRmVhdHVyZSBLZXliaW5kIE1vZGFsICYgQmFkZ2VzICovCi5iaW5kLWtleWNhcC1sYXJnZSB7CiAgZm9udC1mYW1pbHk6ICdKZXRCcmFpbnMgTW9ubycsIG1vbm9zcGFjZTsKICBmb250LXNpemU6IDI0cHg7CiAgZm9udC13ZWlnaHQ6IDcwMDsKICBjb2xvcjogIzAwZjBmZjsKICBiYWNrZ3JvdW5kOiByZ2JhKDAsIDE2OCwgMjU1LCAwLjE0KTsKICBib3JkZXI6IDEuNXB4IHNvbGlkICMwMGYwZmY7CiAgYm9yZGVyLXJhZGl1czogOHB4OwogIHBhZGRpbmc6IDEwcHggMjJweDsKICBtYXJnaW46IDEycHggYXV0bzsKICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgbGV0dGVyLXNwYWNpbmc6IDJweDsKICBib3gtc2hhZG93OiAwIDAgMTZweCByZ2JhKDAsIDI0MCwgMjU1LCAwLjM1KTsKfQoKLmJpbmQtaW5zdHJ1Y3Rpb24gewogIGZvbnQtc2l6ZTogMTNweDsKICBjb2xvcjogIzk0YTNiODsKICBtYXJnaW4tYm90dG9tOiA0cHg7Cn0KCi5iaW5kLXN0YXR1cy1ub3RlIHsKICBmb250LXNpemU6IDExcHg7CiAgY29sb3I6ICM2NDc0OGI7CiAgbWFyZ2luLXRvcDogNnB4Owp9CgouaXRlbS1iaW5kLWJhZGdlIHsKICBmb250LWZhbWlseTogJ0pldEJyYWlucyBNb25vJywgbW9ub3NwYWNlOwogIGZvbnQtc2l6ZTogMTBweDsKICBmb250LXdlaWdodDogNzAwOwogIGNvbG9yOiAjMDBmMGZmOwogIGJhY2tncm91bmQ6IHJnYmEoMCwgMjQwLCAyNTUsIDAuMTgpOwogIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoMCwgMjQwLCAyNTUsIDAuNDUpOwogIHBhZGRpbmc6IDFweCA1cHg7CiAgYm9yZGVyLXJhZGl1czogNHB4OwogIG1hcmdpbi1sZWZ0OiA4cHg7CiAgbGV0dGVyLXNwYWNpbmc6IDAuNXB4OwogIHRleHQtdHJhbnNmb3JtOiB1cHBlcmNhc2U7Cn0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIEFVVEhFTlRJQ0FUSU9OIE1PREFMIFNUWUxFUwogICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwouYXV0aC1jYXJkIHsKICBtYXgtd2lkdGg6IDM2MHB4OwogIHRleHQtYWxpZ246IGNlbnRlcjsKICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDAsIDI0MCwgMjU1LCAwLjQpOwogIGJveC1zaGFkb3c6IDAgMCAzNXB4IHJnYmEoMCwgMjQwLCAyNTUsIDAuMjUpLCAwIDIwcHggNDVweCByZ2JhKDAsIDAsIDAsIDAuODUpOwp9CgouYXV0aC1zZXJ2ZXItYmFkZ2UgewogIGZvbnQtZmFtaWx5OiAnSmV0QnJhaW5zIE1vbm8nLCBtb25vc3BhY2U7CiAgZm9udC1zaXplOiAxMHB4OwogIGNvbG9yOiAjMzhiZGY4OwogIGJhY2tncm91bmQ6IHJnYmEoNTYsIDE4OSwgMjQ4LCAwLjEyKTsKICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDU2LCAxODksIDI0OCwgMC4zKTsKICBwYWRkaW5nOiAycHggN3B4OwogIGJvcmRlci1yYWRpdXM6IDEycHg7Cn0KCi5hdXRoLWVtYmxlbS13cmFwIHsKICB3aWR0aDogNjRweDsKICBoZWlnaHQ6IDY0cHg7CiAgbWFyZ2luOiAxMHB4IGF1dG8gNnB4OwogIGZpbHRlcjogZHJvcC1zaGFkb3coMCAwIDEycHggcmdiYSgwLCAyNDAsIDI1NSwgMC41KSk7Cn0KCi5hdXRoLXdhdmUtc3ZnIHsKICB3aWR0aDogMTAwJTsKICBoZWlnaHQ6IDEwMCU7Cn0KCi5hdXRoLXRpdGxlIHsKICBmb250LWZhbWlseTogJ1JhamRoYW5pJywgc2Fucy1zZXJpZjsKICBmb250LXNpemU6IDE4cHg7CiAgZm9udC13ZWlnaHQ6IDgwMDsKICBjb2xvcjogI2YwZjlmZjsKICBsZXR0ZXItc3BhY2luZzogMXB4Owp9CgouYXV0aC1zdWJ0aXRsZSB7CiAgZm9udC1zaXplOiAxMnB4OwogIGNvbG9yOiAjOTRhM2I4OwogIG1hcmdpbi1ib3R0b206IDE0cHg7Cn0KCi5hdXRoLWZvcm0gewogIGRpc3BsYXk6IGZsZXg7CiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsKICBnYXA6IDEwcHg7CiAgdGV4dC1hbGlnbjogbGVmdDsKfQoKLmF1dGgtZmllbGQgewogIGRpc3BsYXk6IGZsZXg7CiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsKICBnYXA6IDRweDsKfQoKLmF1dGgtbGFiZWwgewogIGZvbnQtZmFtaWx5OiAnUmFqZGhhbmknLCBzYW5zLXNlcmlmOwogIGZvbnQtc2l6ZTogMTFweDsKICBmb250LXdlaWdodDogNzAwOwogIGNvbG9yOiAjMzhiZGY4OwogIGxldHRlci1zcGFjaW5nOiAwLjhweDsKfQoKLmF1dGgtaW5wdXQgewogIHdpZHRoOiAxMDAlOwogIGJhY2tncm91bmQ6IHJnYmEoNCwgMTAsIDIwLCAwLjcpOwogIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoMCwgMjQwLCAyNTUsIDAuMyk7CiAgYm9yZGVyLXJhZGl1czogNnB4OwogIGNvbG9yOiAjZmZmZmZmOwogIGZvbnQtZmFtaWx5OiAnSmV0QnJhaW5zIE1vbm8nLCBtb25vc3BhY2U7CiAgZm9udC1zaXplOiAxM3B4OwogIHBhZGRpbmc6IDlweCAxMnB4OwogIG91dGxpbmU6IG5vbmU7CiAgdHJhbnNpdGlvbjogYWxsIDAuMnM7Cn0KCi5hdXRoLWlucHV0OmZvY3VzIHsKICBib3JkZXItY29sb3I6ICMwMGYwZmY7CiAgYm94LXNoYWRvdzogMCAwIDE0cHggcmdiYSgwLCAyNDAsIDI1NSwgMC40KTsKfQoKLmF1dGgtc3RhdHVzIHsKICBmb250LXNpemU6IDExcHg7CiAgY29sb3I6ICM2NDc0OGI7CiAgdGV4dC1hbGlnbjogY2VudGVyOwogIG1pbi1oZWlnaHQ6IDE2cHg7CiAgbWFyZ2luLXRvcDogNHB4Owp9CgouYXV0aC1zdGF0dXMuZXJyb3IgewogIGNvbG9yOiAjZWY0NDQ0Owp9CgouYXV0aC1zdGF0dXMuc3VjY2VzcyB7CiAgY29sb3I6ICMyMmM1NWU7Cn0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIEZMT0FUSU5HIEhVRCBQQU5FTFMgKFNQRUNUQVRPUiAmIEJJTkRTKSAtIFVMVFJBLUNPTVBBQ1QgTUlDUk8tR0xBU1MKICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi8KLmh1ZC1wYW5lbCB7CiAgcG9zaXRpb246IGZpeGVkOwogIHotaW5kZXg6IDk5OTsKICBkaXNwbGF5OiBmbGV4ICFpbXBvcnRhbnQ7CiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbiAhaW1wb3J0YW50OwogIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxODBkZWcsIHJnYmEoNiwgMTIsIDIyLCAwLjkyKSAwJSwgcmdiYSgzLCA3LCAxNCwgMC45NikgMTAwJSk7CiAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgwLCAyNDAsIDI1NSwgMC4zNSk7CiAgYm9yZGVyLXJhZGl1czogNnB4OwogIGJhY2tkcm9wLWZpbHRlcjogYmx1cigxMnB4KTsKICAtd2Via2l0LWJhY2tkcm9wLWZpbHRlcjogYmx1cigxMnB4KTsKICBib3gtc2hhZG93OiAwIDRweCAxNnB4IHJnYmEoMCwgMCwgMCwgMC42NSksIDAgMCAxMHB4IHJnYmEoMCwgMjQwLCAyNTUsIDAuMTUpOwogIG1pbi13aWR0aDogMTUwcHg7CiAgd2lkdGg6IDIyMHB4OwogIG1heC13aWR0aDogNDgwcHg7CiAgb3ZlcmZsb3c6IGhpZGRlbjsKICB1c2VyLXNlbGVjdDogbm9uZTsKICBjdXJzb3I6IGdyYWI7CiAgYm94LXNpemluZzogYm9yZGVyLWJveDsKICB0cmFuc2l0aW9uOiBib3JkZXItY29sb3IgMC4ycywgYm94LXNoYWRvdyAwLjJzOwp9CgouaHVkLXBhbmVsOmFjdGl2ZSB7CiAgY3Vyc29yOiBncmFiYmluZzsKfQoKLmh1ZC1zcGVjdGF0b3IgewogIHRvcDogMTZweDsKICByaWdodDogMTZweDsKICBtaW4td2lkdGg6IDE1MHB4OwogIHdpZHRoOiAxODBweDsKfQoKLmh1ZC1iaW5kcyB7CiAgdG9wOiAxNDBweDsKICByaWdodDogMTZweDsKICBtaW4td2lkdGg6IDE0MHB4OwogIHdpZHRoOiAyMDBweDsKfQoKLmh1ZC1oZWFkZXIgewogIGRpc3BsYXk6IGZsZXg7CiAgYWxpZ24taXRlbXM6IGNlbnRlcjsKICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47CiAgZ2FwOiA1cHg7CiAgcGFkZGluZzogMy41cHggNnB4OwogIGJhY2tncm91bmQ6IHJnYmEoMCwgMjQwLCAyNTUsIDAuMDgpOwogIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCByZ2JhKDAsIDI0MCwgMjU1LCAwLjIpOwogIHdpZHRoOiAxMDAlOwogIGJveC1zaXppbmc6IGJvcmRlci1ib3g7CiAgZmxleC1zaHJpbms6IDA7Cn0KCi5odWQtZG90IHsKICBmb250LXNpemU6IDYuNXB4OwogIGZsZXgtc2hyaW5rOiAwOwp9CgouaHVkLWRvdC5zYWZlIHsKICBjb2xvcjogIzIyYzU1ZTsKICB0ZXh0LXNoYWRvdzogMCAwIDRweCAjMjJjNTVlOwp9CgouaHVkLWRvdC5kYW5nZXIgewogIGNvbG9yOiAjZWY0NDQ0OwogIHRleHQtc2hhZG93OiAwIDAgNXB4ICNlZjQ0NDQ7CiAgYW5pbWF0aW9uOiBwdWxzZS1kYW5nZXIgMXMgaW5maW5pdGUgYWx0ZXJuYXRlOwp9CgouaHVkLWRvdC5hY3RpdmUgewogIGNvbG9yOiAjMDBmMGZmOwogIHRleHQtc2hhZG93OiAwIDAgNHB4ICMwMGYwZmY7Cn0KCkBrZXlmcmFtZXMgcHVsc2UtZGFuZ2VyIHsKICBmcm9tIHsgb3BhY2l0eTogMC42OyB9CiAgdG8geyBvcGFjaXR5OiAxOyB0cmFuc2Zvcm06IHNjYWxlKDEuMTUpOyB9Cn0KCi5odWQtdGl0bGUgewogIGZvbnQtZmFtaWx5OiAnUmFqZGhhbmknLCBzYW5zLXNlcmlmOwogIGZvbnQtc2l6ZTogOS41cHg7CiAgZm9udC13ZWlnaHQ6IDgwMDsKICBjb2xvcjogI2UwZjJmZTsKICBsZXR0ZXItc3BhY2luZzogMC43cHg7CiAgZmxleDogMTsKfQoKLmh1ZC1iYWRnZSB7CiAgZm9udC1mYW1pbHk6ICdKZXRCcmFpbnMgTW9ubycsIG1vbm9zcGFjZTsKICBmb250LXNpemU6IDcuNXB4OwogIGZvbnQtd2VpZ2h0OiA3MDA7CiAgY29sb3I6ICMwMGYwZmY7CiAgYmFja2dyb3VuZDogcmdiYSgwLCAyNDAsIDI1NSwgMC4xOCk7CiAgYm9yZGVyLXJhZGl1czogNHB4OwogIHBhZGRpbmc6IDAuNXB4IDMuNXB4OwogIGZsZXgtc2hyaW5rOiAwOwp9CgovKiBTY3JvbGxhYmxlIHdyYXAgd2l0aCB6ZXJvIHNjcm9sbGJhciB2aXNpYmxlICovCi5odWQtdGFibGUtd3JhcCwKLmh1ZC1ib2R5IHsKICBwYWRkaW5nOiAycHggNHB4OwogIGRpc3BsYXk6IGZsZXg7CiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsKICBnYXA6IDEuNXB4OwogIG1heC1oZWlnaHQ6IDE4MHB4OwogIG92ZXJmbG93LXk6IGF1dG87CiAgc2Nyb2xsYmFyLXdpZHRoOiBub25lOwogIHdpZHRoOiAxMDAlOwogIGJveC1zaXppbmc6IGJvcmRlci1ib3g7Cn0KCi5odWQtdGFibGUtd3JhcDo6LXdlYmtpdC1zY3JvbGxiYXIsCi5odWQtYm9keTo6LXdlYmtpdC1zY3JvbGxiYXIgewogIGRpc3BsYXk6IG5vbmU7Cn0KCi8qIEtleWJpbmRzIENsZWFuIFRhYmxlIExheW91dCAqLwouaHVkLWJpbmRzLXRhYmxlIHsKICB3aWR0aDogMTAwJTsKICBib3JkZXItY29sbGFwc2U6IGNvbGxhcHNlOwogIGZvbnQtc2l6ZTogOC41cHg7CiAgdGV4dC1hbGlnbjogbGVmdDsKfQoKLmh1ZC1iaW5kcy10YWJsZSB0aGVhZCB7CiAgcG9zaXRpb246IHN0aWNreTsKICB0b3A6IDA7CiAgei1pbmRleDogMjsKICBiYWNrZ3JvdW5kOiByZ2JhKDQsIDksIDE4LCAwLjk2KTsKfQoKLmh1ZC1iaW5kcy10YWJsZSB0aCB7CiAgZm9udC1mYW1pbHk6ICdSYWpkaGFuaScsIHNhbnMtc2VyaWY7CiAgZm9udC1zaXplOiA4cHg7CiAgZm9udC13ZWlnaHQ6IDcwMDsKICBsZXR0ZXItc3BhY2luZzogMC42cHg7CiAgY29sb3I6IHZhcigtLWFjY2VudC1jeWFuKTsKICBwYWRkaW5nOiAyLjVweCA0cHg7CiAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkIHJnYmEoMCwgMjQwLCAyNTUsIDAuMik7CiAgdGV4dC10cmFuc2Zvcm06IHVwcGVyY2FzZTsKfQoKLmh1ZC1iaW5kcy10YWJsZSB0aC50aC1rZXkgewogIHRleHQtYWxpZ246IHJpZ2h0Owp9CgouaHVkLWJpbmRzLXRhYmxlIHRkIHsKICBwYWRkaW5nOiAyLjVweCA0cHg7CiAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkIHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4wNCk7CiAgY29sb3I6ICNjYmQ1ZTE7CiAgd2hpdGUtc3BhY2U6IG5vd3JhcDsKICBvdmVyZmxvdzogaGlkZGVuOwogIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzOwogIGZvbnQtc2l6ZTogOC41cHg7Cn0KCi5odWQtYmluZHMtdGFibGUgdHI6aG92ZXIgdGQgewogIGJhY2tncm91bmQ6IHJnYmEoMCwgMjQwLCAyNTUsIDAuMDYpOwogIGNvbG9yOiAjZmZmZmZmOwp9CgouaHVkLWJpbmRzLXRhYmxlIHRkLnRkLWtleSB7CiAgdGV4dC1hbGlnbjogcmlnaHQ7Cn0KCi5iaW5kLWtleS1waWxsIHsKICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgZm9udC1mYW1pbHk6ICdKZXRCcmFpbnMgTW9ubycsIG1vbm9zcGFjZTsKICBmb250LXNpemU6IDhweDsKICBmb250LXdlaWdodDogNzAwOwogIGNvbG9yOiAjMDBmMGZmOwogIGJhY2tncm91bmQ6IHJnYmEoMCwgMjQwLCAyNTUsIDAuMTQpOwogIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoMCwgMjQwLCAyNTUsIDAuNCk7CiAgcGFkZGluZzogMC41cHggNHB4OwogIGJvcmRlci1yYWRpdXM6IDNweDsKICBsZXR0ZXItc3BhY2luZzogMC4zcHg7CiAgYm94LXNoYWRvdzogMCAwIDRweCByZ2JhKDAsIDI0MCwgMjU1LCAwLjE1KTsKfQoKLmh1ZC1yb3cgewogIGRpc3BsYXk6IGZsZXg7CiAgYWxpZ24taXRlbXM6IGNlbnRlcjsKICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47CiAgZm9udC1zaXplOiA5LjVweDsKICBwYWRkaW5nOiAycHggNHB4OwogIGJvcmRlci1yYWRpdXM6IDNweDsKICBiYWNrZ3JvdW5kOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuMDMpOwogIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4wNSk7Cn0KCi5odWQtcm93LmRhbmdlciB7CiAgYmFja2dyb3VuZDogcmdiYSgyMzksIDY4LCA2OCwgMC4xMik7CiAgYm9yZGVyLWNvbG9yOiByZ2JhKDIzOSwgNjgsIDY4LCAwLjMpOwogIGNvbG9yOiAjZmNhNWE1Owp9CgouaHVkLWVtcHR5IHsKICBmb250LXNpemU6IDkuNXB4OwogIGNvbG9yOiAjNjQ3NDhiOwogIHRleHQtYWxpZ246IGNlbnRlcjsKICBwYWRkaW5nOiA2cHggMDsKICBmb250LXN0eWxlOiBpdGFsaWM7Cn0KCi8qIENvcm5lciBSZXNpemVyIEhhbmRsZSBmb3IgRHJhZyBVSSAqLwouaHVkLXJlc2l6ZXIgewogIHBvc2l0aW9uOiBhYnNvbHV0ZTsKICBib3R0b206IDA7CiAgcmlnaHQ6IDA7CiAgd2lkdGg6IDE0cHg7CiAgaGVpZ2h0OiAxNHB4OwogIGN1cnNvcjogc2UtcmVzaXplOwogIHotaW5kZXg6IDIwOwogIGRpc3BsYXk6IGZsZXg7CiAgYWxpZ24taXRlbXM6IGZsZXgtZW5kOwogIGp1c3RpZnktY29udGVudDogZmxleC1lbmQ7CiAgcGFkZGluZzogMnB4Owp9CgouaHVkLXJlc2l6ZXI6OmFmdGVyIHsKICBjb250ZW50OiAnJzsKICB3aWR0aDogNnB4OwogIGhlaWdodDogNnB4OwogIGJvcmRlci1yaWdodDogMnB4IHNvbGlkIHJnYmEoMCwgMjQwLCAyNTUsIDAuNSk7CiAgYm9yZGVyLWJvdHRvbTogMnB4IHNvbGlkIHJnYmEoMCwgMjQwLCAyNTUsIDAuNSk7CiAgYm9yZGVyLXJhZGl1czogMCAwIDJweCAwOwogIHRyYW5zaXRpb246IGFsbCAwLjE1cyBlYXNlOwp9CgouaHVkLXBhbmVsOmhvdmVyIC5odWQtcmVzaXplcjo6YWZ0ZXIsCi5odWQtcGxhY2VyOmhvdmVyIC5odWQtcmVzaXplcjo6YWZ0ZXIsCi5kcmFnLW1vZGUtYWN0aXZlIC5odWQtcmVzaXplcjo6YWZ0ZXIgewogIHdpZHRoOiA4cHg7CiAgaGVpZ2h0OiA4cHg7CiAgYm9yZGVyLWNvbG9yOiAjMDBmMGZmOwogIGJveC1zaGFkb3c6IDFweCAxcHggNnB4IHJnYmEoMCwgMjQwLCAyNTUsIDAuOCk7Cn0KCi5kcmFnLW1vZGUtYWN0aXZlIC5odWQtcGFuZWwsCi5kcmFnLW1vZGUtYWN0aXZlIC5odWQtcGxhY2VyIHsKICBvdXRsaW5lOiAxcHggZGFzaGVkIHJnYmEoMCwgMjQwLCAyNTUsIDAuNSk7Cn0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIFFVSUNLIFBMQUNFUiAmIFNQQVdORVIgSFVEIFdJREdFVAogICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwouaHVkLXBsYWNlciB7CiAgcG9zaXRpb246IGZpeGVkOwogIGJvdHRvbTogMjRweDsKICBsZWZ0OiA1MCU7CiAgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKC01MCUpOwogIHotaW5kZXg6IDk5OTsKICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTgwZGVnLCByZ2JhKDgsIDE4LCAzNCwgMC43OCkgMCUsIHJnYmEoNCwgMTAsIDIwLCAwLjg1KSAxMDAlKTsKICBib3JkZXI6IDEuNXB4IHNvbGlkIHJnYmEoMCwgMjQwLCAyNTUsIDAuNDUpOwogIGJvcmRlci1yYWRpdXM6IDMwcHg7CiAgYmFja2Ryb3AtZmlsdGVyOiBibHVyKDE0cHgpOwogIC13ZWJraXQtYmFja2Ryb3AtZmlsdGVyOiBibHVyKDE0cHgpOwogIHBhZGRpbmc6IDhweCAyMnB4OwogIGJveC1zaGFkb3c6IDAgMTBweCAzMHB4IHJnYmEoMCwgMCwgMCwgMC43KSwgMCAwIDIwcHggcmdiYSgwLCAyNDAsIDI1NSwgMC4yNSk7CiAgZGlzcGxheTogZmxleDsKICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAgZ2FwOiA2cHg7CiAgdXNlci1zZWxlY3Q6IG5vbmU7Cn0KCi5wbGFjZXItdGFnIHsKICBmb250LWZhbWlseTogJ1JhamRoYW5pJywgc2Fucy1zZXJpZjsKICBmb250LXNpemU6IDExcHg7CiAgZm9udC13ZWlnaHQ6IDgwMDsKICBjb2xvcjogIzAwZjBmZjsKICBsZXR0ZXItc3BhY2luZzogMS41cHg7Cn0KCi5wbGFjZXItbmF2IHsKICBkaXNwbGF5OiBmbGV4OwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAgZ2FwOiAxNnB4Owp9CgoucGxhY2VyLWFycm93IHsKICBiYWNrZ3JvdW5kOiByZ2JhKDAsIDI0MCwgMjU1LCAwLjE1KTsKICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDAsIDI0MCwgMjU1LCAwLjM1KTsKICBjb2xvcjogIzAwZjBmZjsKICB3aWR0aDogMjZweDsKICBoZWlnaHQ6IDI2cHg7CiAgYm9yZGVyLXJhZGl1czogNTAlOwogIGRpc3BsYXk6IGZsZXg7CiAgYWxpZ24taXRlbXM6IGNlbnRlcjsKICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsKICBjdXJzb3I6IHBvaW50ZXI7CiAgZm9udC1zaXplOiAxNHB4OwogIGZvbnQtd2VpZ2h0OiA3MDA7CiAgdHJhbnNpdGlvbjogYWxsIDAuMnM7Cn0KCi5wbGFjZXItYXJyb3c6aG92ZXIgewogIGJhY2tncm91bmQ6ICMwMGYwZmY7CiAgY29sb3I6ICMwNDBhMTQ7CiAgYm94LXNoYWRvdzogMCAwIDEycHggIzAwZjBmZjsKfQoKLnBsYWNlci1jdXJyZW50IHsKICBkaXNwbGF5OiBmbGV4OwogIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47CiAgYWxpZ24taXRlbXM6IGNlbnRlcjsKICBtaW4td2lkdGg6IDE3MHB4Owp9CgoucGxhY2VyLWNhdGVnb3J5IHsKICBmb250LXNpemU6IDEwcHg7CiAgZm9udC13ZWlnaHQ6IDcwMDsKICBjb2xvcjogIzY0NzQ4YjsKICBsZXR0ZXItc3BhY2luZzogMXB4OwogIHRleHQtdHJhbnNmb3JtOiB1cHBlcmNhc2U7Cn0KCi5wbGFjZXItbmFtZSB7CiAgZm9udC1mYW1pbHk6ICdSYWpkaGFuaScsIHNhbnMtc2VyaWY7CiAgZm9udC1zaXplOiAxNnB4OwogIGZvbnQtd2VpZ2h0OiA3MDA7CiAgY29sb3I6ICNmMGY5ZmY7CiAgdGV4dC1zaGFkb3c6IDAgMCAxMHB4IHJnYmEoMCwgMjQwLCAyNTUsIDAuNCk7Cn0KCi5wbGFjZXItY29udHJvbHMgewogIGRpc3BsYXk6IGZsZXg7CiAgZ2FwOiAxMnB4OwogIGZvbnQtc2l6ZTogMTFweDsKICBjb2xvcjogIzk0YTNiODsKfQoKLnBsYWNlci1jb250cm9scyBrYmQgewogIGJhY2tncm91bmQ6IHJnYmEoMCwgMjQwLCAyNTUsIDAuMTUpOwogIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoMCwgMjQwLCAyNTUsIDAuMyk7CiAgY29sb3I6ICMwMGYwZmY7CiAgcGFkZGluZzogMXB4IDVweDsKICBib3JkZXItcmFkaXVzOiAzcHg7CiAgZm9udC1mYW1pbHk6ICdKZXRCcmFpbnMgTW9ubycsIG1vbm9zcGFjZTsKICBmb250LXdlaWdodDogNzAwOwp9CgovKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICBEUkFHIFVJIEVESVQgTU9ERQogICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwouZHJhZy1tb2RlLWFjdGl2ZSAubWVudS13cmFwcGVyLAouZHJhZy1tb2RlLWFjdGl2ZSAuaHVkLXBhbmVsLAouZHJhZy1tb2RlLWFjdGl2ZSAuaHVkLXBsYWNlciB7CiAgb3V0bGluZTogMnB4IGRhc2hlZCByZ2JhKDAsIDI0MCwgMjU1LCAwLjcpOwogIG91dGxpbmUtb2Zmc2V0OiA0cHg7Cn0KCi5kcmFnLWhhbmRsZS1waWxsIHsKICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgdG9wOiAtMTJweDsKICBsZWZ0OiA1MCU7CiAgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKC01MCUpOwogIGJhY2tncm91bmQ6ICMwMGYwZmY7CiAgY29sb3I6ICMwNDA5MTQ7CiAgZm9udC1mYW1pbHk6ICdSYWpkaGFuaScsIHNhbnMtc2VyaWY7CiAgZm9udC1zaXplOiAxMHB4OwogIGZvbnQtd2VpZ2h0OiA4MDA7CiAgcGFkZGluZzogMXB4IDhweDsKICBib3JkZXItcmFkaXVzOiAxMHB4OwogIGJveC1zaGFkb3c6IDAgMCAxMHB4ICMwMGYwZmY7Cn0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIEFOVElDSEVBVCBERUVQIFNDQU5ORVIgTU9EQUwKICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi8KLmFjLXNjYW4tY2FyZCB7CiAgYm9yZGVyLWNvbG9yOiByZ2JhKDAsIDI0MCwgMjU1LCAwLjQpOwogIGJveC1zaGFkb3c6IDAgMCAzMHB4IHJnYmEoMCwgMjQwLCAyNTUsIDAuMiksIDAgMjBweCA1MHB4IHJnYmEoMCwgMCwgMCwgMC45KTsKfQoKLmFjLXNjYW4tcm93IHsKICBkaXNwbGF5OiBmbGV4OwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuOwogIHBhZGRpbmc6IDZweCAxMHB4OwogIGJhY2tncm91bmQ6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4wMik7CiAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjA2KTsKICBib3JkZXItcmFkaXVzOiA1cHg7CiAgZm9udC1zaXplOiAxMS41cHg7Cn0KCi5hYy1zY2FuLW5hbWUgewogIGNvbG9yOiAjZjFmNWY5OwogIGZvbnQtZmFtaWx5OiAnUmFqZGhhbmknLCBzYW5zLXNlcmlmOwogIGZvbnQtd2VpZ2h0OiA3MDA7CiAgZm9udC1zaXplOiAxMy41cHg7CiAgZGlzcGxheTogZmxleDsKICBhbGlnbi1pdGVtczogY2VudGVyOwogIGdhcDogNnB4Owp9CgouYWMtc2Nhbi1iYWRnZSB7CiAgZm9udC1mYW1pbHk6ICdKZXRCcmFpbnMgTW9ubycsIG1vbm9zcGFjZTsKICBmb250LXNpemU6IDkuNXB4OwogIGZvbnQtd2VpZ2h0OiA3MDA7CiAgcGFkZGluZzogMnB4IDZweDsKICBib3JkZXItcmFkaXVzOiAzcHg7CiAgbGV0dGVyLXNwYWNpbmc6IDAuNXB4Owp9CgouYWMtc2Nhbi1iYWRnZS5hY3RpdmUgewogIGJhY2tncm91bmQ6IHJnYmEoMzQsIDE5NywgOTQsIDAuMTUpOwogIGNvbG9yOiAjNGFkZTgwOwogIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoMzQsIDE5NywgOTQsIDAuNCk7Cn0KCi5hYy1zY2FuLWJhZGdlLmJ5cGFzc2VkIHsKICBiYWNrZ3JvdW5kOiByZ2JhKDAsIDI0MCwgMjU1LCAwLjE1KTsKICBjb2xvcjogIzAwZjBmZjsKICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDAsIDI0MCwgMjU1LCAwLjQ1KTsKfQoKLmFjLXNjYW4tYmFkZ2UucGxhbm5lZCB7CiAgYmFja2dyb3VuZDogcmdiYSgyNDUsIDE1OCwgMTEsIDAuMTIpOwogIGNvbG9yOiAjZmJiZjI0OwogIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoMjQ1LCAxNTgsIDExLCAwLjM1KTsKfQoKLmFjLXNjYW4tYmFkZ2UuY2xlYW4gewogIGJhY2tncm91bmQ6IHJnYmEoMTQ4LCAxNjMsIDE4NCwgMC4xKTsKICBjb2xvcjogIzk0YTNiODsKICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDE0OCwgMTYzLCAxODQsIDAuMjUpOwp9CgoKPC9zdHlsZT4KPC9oZWFkPgo8Ym9keT4KICA8ZGl2IGNsYXNzPSJtZW51LXdyYXBwZXIiPgogICAgPGRpdiBjbGFzcz0ibWVudS1jb250YWluZXIiIGlkPSJtZW51Q29udGFpbmVyIj4KICAgICAgPCEtLSBBbWJpZW50IE9jZWFuIFBhcnRpY2xlcyAmIEdyaWQgLS0+CiAgICAgIDxkaXYgY2xhc3M9IndhdGVyLWNhdXN0aWNzIj48L2Rpdj4KICAgICAgPGRpdiBjbGFzcz0idGFjdGljYWwtZ3JpZCI+PC9kaXY+CgogICAgICA8IS0tIEhlYWRlciBCYW5uZXIgd2l0aCBIeWRybyBXYXZlIEVtYmxlbSAmIFRpdGxlIC0tPgogICAgICA8ZGl2IGNsYXNzPSJoZWFkZXItYm94Ij4KICAgICAgICA8ZGl2IGNsYXNzPSJoZWFkZXItdG9wLXJvdyI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJlbWJsZW0td3JhcCI+CiAgICAgICAgICAgIDxzdmcgY2xhc3M9IndhdGVyLWVtYmxlbS1zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogICAgICAgICAgICAgIDxkZWZzPgogICAgICAgICAgICAgICAgPGxpbmVhckdyYWRpZW50IGlkPSJ3YXZlR3JhZCIgeDE9IjAlIiB5MT0iMTAwJSIgeDI9IjEwMCUiIHkyPSIwJSI+CiAgICAgICAgICAgICAgICAgIDxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiMwMjg0YzciIC8+CiAgICAgICAgICAgICAgICAgIDxzdG9wIG9mZnNldD0iNDUlIiBzdG9wLWNvbG9yPSIjMDBhOGZmIiAvPgogICAgICAgICAgICAgICAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMGYwZmYiIC8+CiAgICAgICAgICAgICAgICA8L2xpbmVhckdyYWRpZW50PgogICAgICAgICAgICAgICAgPGxpbmVhckdyYWRpZW50IGlkPSJmb2FtR3JhZCIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMTAwJSI+CiAgICAgICAgICAgICAgICAgIDxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiIHN0b3Atb3BhY2l0eT0iMC45IiAvPgogICAgICAgICAgICAgICAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMGYwZmYiIHN0b3Atb3BhY2l0eT0iMC40IiAvPgogICAgICAgICAgICAgICAgPC9saW5lYXJHcmFkaWVudD4KICAgICAgICAgICAgICAgIDxmaWx0ZXIgaWQ9IndhdmVHbG93IiB4PSItMjAlIiB5PSItMjAlIiB3aWR0aD0iMTQwJSIgaGVpZ2h0PSIxNDAlIj4KICAgICAgICAgICAgICAgICAgPGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iMyIgcmVzdWx0PSJibHVyIiAvPgogICAgICAgICAgICAgICAgICA8ZmVDb21wb3NpdGUgaW49IlNvdXJjZUdyYXBoaWMiIGluMj0iYmx1ciIgb3BlcmF0b3I9Im92ZXIiIC8+CiAgICAgICAgICAgICAgICA8L2ZpbHRlcj4KICAgICAgICAgICAgICA8L2RlZnM+CiAgICAgICAgICAgICAgPCEtLSBEeW5hbWljIGJhcnJlbCB3YXZlIGNyZXN0IC0tPgogICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMiA3NiBDMjUgNzYgMzYgNzIgNDYgNjAgQzU2IDQ4IDY0IDMyIDc2IDIwIEM4NCAxMiA5MiAxNiA5MCAyNiBDODggMzQgNzggNDIgNjggNDQgQzYwIDQ2IDU0IDQwIDU4IDMyIEM2MCAyOCA2NiAyOCA2OCAzMSIgCiAgICAgICAgICAgICAgICAgICAgZmlsbD0ibm9uZSIgc3Ryb2tlPSJ1cmwoI3dhdmVHcmFkKSIgc3Ryb2tlLXdpZHRoPSI0LjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgZmlsdGVyPSJ1cmwoI3dhdmVHbG93KSIgLz4KICAgICAgICAgICAgICA8IS0tIFVuZGVyIHdhdmUgc3VyZ2UgYm9keSAtLT4KICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIgNzYgQzI4IDc2IDQwIDY4IDUyIDU2IEM2MiA0NiA3MCAzNiA3OCAyNiBDNzQgMzYgNjQgNTIgNTAgNjIgQzM4IDcwIDI2IDc0IDEyIDc2IFoiIAogICAgICAgICAgICAgICAgICAgIGZpbGw9InVybCgjd2F2ZUdyYWQpIiBvcGFjaXR5PSIwLjQ1IiAvPgogICAgICAgICAgICAgIDwhLS0gV2F2ZSBiYXNlIHN3ZWxsIC0tPgogICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNiA4MiBDMzQgODIgNDggNzYgNjAgNjQgQzcwIDU0IDgwIDQyIDg1IDM0IEM3OSA0MiA2OSA1NCA1NyA2NCBDNDUgNzQgMzIgODAgMTYgODIgWiIgCiAgICAgICAgICAgICAgICAgICAgZmlsbD0idXJsKCN3YXZlR3JhZCkiIG9wYWNpdHk9IjAuNjUiIC8+CiAgICAgICAgICAgICAgPCEtLSBXYXZlIGZvYW0gJiBzcHJheSBkcm9wbGV0cyAtLT4KICAgICAgICAgICAgICA8Y2lyY2xlIGN4PSI3NiIgY3k9IjE4IiByPSIyLjgiIGZpbGw9InVybCgjZm9hbUdyYWQpIiBmaWx0ZXI9InVybCgjd2F2ZUdsb3cpIiAvPgogICAgICAgICAgICAgIDxjaXJjbGUgY3g9Ijg0IiBjeT0iMjIiIHI9IjIuMCIgZmlsbD0iIzAwZjBmZiIgLz4KICAgICAgICAgICAgICA8Y2lyY2xlIGN4PSI3MCIgY3k9IjE0IiByPSIxLjYiIGZpbGw9IiNmZmZmZmYiIC8+CiAgICAgICAgICAgICAgPGNpcmNsZSBjeD0iNjIiIGN5PSIyNCIgcj0iMS40IiBmaWxsPSIjMDBmMGZmIiAvPgogICAgICAgICAgICAgIDxjaXJjbGUgY3g9Ijg4IiBjeT0iMzAiIHI9IjEuOCIgZmlsbD0idXJsKCNmb2FtR3JhZCkiIC8+CiAgICAgICAgICAgIDwvc3ZnPgogICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8aDEgY2xhc3M9Im1lbnUtdGl0bGUiPldUUiA8c3BhbiBjbGFzcz0iaHlkcm8tdGV4dCI+TWVudTwvc3Bhbj48L2gxPgogICAgICAgIDwvZGl2PgogICAgICA8L2Rpdj4KCiAgICA8IS0tIEJyZWFkY3J1bWIgQmFyIC0tPgogICAgPGRpdiBjbGFzcz0iYnJlYWRjcnVtYi1iYXIiIGlkPSJicmVhZGNydW1iQmFyIj4KICAgICAgPHNwYW4gY2xhc3M9ImNydW1iLXJvb3QiIGlkPSJjcnVtYlJvb3QiPk1haW4gTWVudTwvc3Bhbj4KICAgICAgPHNwYW4gY2xhc3M9ImNydW1iLXNlcGFyYXRvciIgaWQ9ImNydW1iU2VwIiBzdHlsZT0iZGlzcGxheTogbm9uZTsiPiZndDs8L3NwYW4+CiAgICAgIDxzcGFuIGNsYXNzPSJjcnVtYi1zdWIiIGlkPSJjcnVtYlN1YiIgc3R5bGU9ImRpc3BsYXk6IG5vbmU7Ij5PbmxpbmU8L3NwYW4+CiAgICA8L2Rpdj4KCiAgICA8IS0tIFN1YmNhdGVnb3JpZXMgVGFicyBCYXIgKFEgLyBFKSAtLT4KICAgIDxkaXYgY2xhc3M9InN1YnRhYnMtYmFyIiBpZD0ic3VidGFic0JhciIgc3R5bGU9ImRpc3BsYXk6IG5vbmU7Ij4KICAgICAgPGRpdiBjbGFzcz0ic3VidGFiLWtleSIgaWQ9ImJ0blByZXZTdWJ0YWIiIHRpdGxlPSJQcmV2aW91cyBbUV0iPlE8L2Rpdj4KICAgICAgPGRpdiBjbGFzcz0ic3VidGFicy1zY3JvbGwiIGlkPSJzdWJ0YWJzU2Nyb2xsIj4KICAgICAgICA8IS0tIFN1Yi10YWJzIHBpbGxzIGR5bmFtaWNhbGx5IGluc2VydGVkIC0tPgogICAgICA8L2Rpdj4KICAgICAgPGRpdiBjbGFzcz0ic3VidGFiLWtleSIgaWQ9ImJ0bk5leHRTdWJ0YWIiIHRpdGxlPSJOZXh0IFtFXSI+RTwvZGl2PgogICAgPC9kaXY+CgogICAgPCEtLSBPbmxpbmUgVGFyZ2V0IC8gTXVsdGktc2VsZWN0IFRvb2xiYXIgKHdoZW4gaW5zaWRlIE9ubGluZSA+IFBsYXllcnMpIC0tPgogICAgPGRpdiBjbGFzcz0ib25saW5lLXRvb2xiYXIiIGlkPSJvbmxpbmVUb29sYmFyIiBzdHlsZT0iZGlzcGxheTogbm9uZTsiPgogICAgICA8YnV0dG9uIGNsYXNzPSJ0b29sLWJ0biIgaWQ9ImJ0blNlbGVjdEFsbCI+U2VsZWN0IEFsbDwvYnV0dG9uPgogICAgICA8YnV0dG9uIGNsYXNzPSJ0b29sLWJ0biIgaWQ9ImJ0blVuc2VsZWN0QWxsIj5DbGVhcjwvYnV0dG9uPgogICAgICA8YnV0dG9uIGNsYXNzPSJ0b29sLWJ0biIgaWQ9ImJ0blRhcmdldFNlbGYiPlNlbGY8L2J1dHRvbj4KICAgICAgPGRpdiBjbGFzcz0idG9vbC1jb3VudGVyIiBpZD0idG9vbENvdW50ZXIiPlNlbGVjdGVkOiA8Yj4wPC9iPjwvZGl2PgogICAgPC9kaXY+CgogICAgPCEtLSBNYWluIER5bmFtaWMgSXRlbXMgTGlzdCBDb250YWluZXIgLS0+CiAgICA8ZGl2IGNsYXNzPSJpdGVtcy1saXN0IiBpZD0iaXRlbXNMaXN0Ij4KICAgICAgPCEtLSBJdGVtcyBkeW5hbWljYWxseSByZW5kZXJlZCAtLT4KICAgIDwvZGl2PgoKICAgIDwhLS0gRm9vdGVyIEJhciAtLT4KICAgIDxkaXYgY2xhc3M9ImZvb3Rlci1iYXIiPgogICAgICA8ZGl2IGNsYXNzPSJmb290ZXItYnJhbmQiPgogICAgICAgIDxzcGFuIGNsYXNzPSJmb290ZXItaWNvbiI+JiN4MjVDNjs8L3NwYW4+CiAgICAgICAgPHNwYW4gY2xhc3M9ImZvb3Rlci10ZXh0Ij5XVFIgV2F0ZXIgR2xhc3M8L3NwYW4+CiAgICAgIDwvZGl2PgogICAgICA8ZGl2IGNsYXNzPSJmb290ZXItY291bnRlciIgaWQ9ImZvb3RlckNvdW50ZXIiPjEgLyA4PC9kaXY+CiAgICA8L2Rpdj4KCiAgICA8IS0tIEluLU1lbnUgVGVybWluYWwgTW9kYWwgSW5wdXQgRGlhbG9nIC0tPgogICAgPGRpdiBjbGFzcz0ibW9kYWwtb3ZlcmxheSIgaWQ9Im1vZGFsT3ZlcmxheSIgc3R5bGU9ImRpc3BsYXk6IG5vbmU7Ij4KICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtY2FyZCI+CiAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtaGVhZGVyIj4KICAgICAgICAgIDxzcGFuIGNsYXNzPSJtb2RhbC10YWciPlRFUk1JTkFMIC8vIElOUFVUPC9zcGFuPgogICAgICAgICAgPGJ1dHRvbiBjbGFzcz0ibW9kYWwtY2xvc2UiIGlkPSJtb2RhbEJ0bkNsb3NlIj4mI3gyNzE1OzwvYnV0dG9uPgogICAgICAgIDwvZGl2PgogICAgICAgIDxoMyBjbGFzcz0ibW9kYWwtdGl0bGUiIGlkPSJtb2RhbFRpdGxlIj5TUEFXTiBWRUhJQ0xFPC9oMz4KICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1ib2R5Ij4KICAgICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWlucHV0LXdyYXAiPgogICAgICAgICAgICA8aW5wdXQgdHlwZT0idGV4dCIgaWQ9Im1vZGFsSW5wdXQiIGNsYXNzPSJtb2RhbC1pbnB1dCIgcGxhY2Vob2xkZXI9IkVudGVyIG1vZGVsIG5hbWUuLi4iIGF1dG9jb21wbGV0ZT0ib2ZmIiBzcGVsbGNoZWNrPSJmYWxzZSIgLz4KICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz0ibW9kYWwtY2xlYXItYnRuIiBpZD0ibW9kYWxJbnB1dENsZWFyIj4mI3gyNzE1OzwvYnV0dG9uPgogICAgICAgICAgPC9kaXY+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1wcmVzZXRzLWxhYmVsIj5RVUlDSyBQUkVTRVRTOjwvZGl2PgogICAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtcHJlc2V0cy1ncmlkIiBpZD0ibW9kYWxQcmVzZXRzIj4KICAgICAgICAgICAgPCEtLSBQcmVzZXQgY2hpcHMgaW5zZXJ0ZWQgZHluYW1pY2FsbHkgLS0+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1mb290ZXIiPgogICAgICAgICAgPGJ1dHRvbiBjbGFzcz0ibW9kYWwtYWN0aW9uLWJ0biBjYW5jZWwiIGlkPSJtb2RhbEJ0bkNhbmNlbCI+Q2FuY2VsIFtFU0NdPC9idXR0b24+CiAgICAgICAgICA8YnV0dG9uIGNsYXNzPSJtb2RhbC1hY3Rpb24tYnRuIGNvbmZpcm0iIGlkPSJtb2RhbEJ0bkNvbmZpcm0iPkNvbmZpcm0gW0VOVEVSXTwvYnV0dG9uPgogICAgICAgIDwvZGl2PgogICAgICA8L2Rpdj4KICAgIDwvZGl2PgoKICAgIDwhLS0gRmVhdHVyZSBLZXliaW5kIE1vZGFsIERpYWxvZyAoRjkpIC0tPgogICAgPGRpdiBjbGFzcz0ibW9kYWwtb3ZlcmxheSIgaWQ9ImJpbmRNb2RhbE92ZXJsYXkiIHN0eWxlPSJkaXNwbGF5OiBub25lOyI+CiAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWNhcmQiPgogICAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWhlYWRlciI+CiAgICAgICAgICA8c3BhbiBjbGFzcz0ibW9kYWwtdGFnIj5LRVlCSU5EIC8vIEFTU0lHTiBbRjldPC9zcGFuPgogICAgICAgICAgPGJ1dHRvbiBjbGFzcz0ibW9kYWwtY2xvc2UiIGlkPSJiaW5kTW9kYWxCdG5DbG9zZSI+JiN4MjcxNTs8L2J1dHRvbj4KICAgICAgICA8L2Rpdj4KICAgICAgICA8aDMgY2xhc3M9Im1vZGFsLXRpdGxlIiBpZD0iYmluZE1vZGFsVGl0bGUiPkJJTkQgRkVBVFVSRTwvaDM+CiAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtYm9keSIgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlcjsgcGFkZGluZzogMTRweCAwOyI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJiaW5kLWluc3RydWN0aW9uIiBpZD0iYmluZE1vZGFsSW5zdHJ1Y3Rpb24iPlByZXNzIGFueSBrZXkgdG8gYXNzaWduIHRvIHRoaXMgZmVhdHVyZTo8L2Rpdj4KICAgICAgICAgIDxkaXYgY2xhc3M9ImJpbmQta2V5Y2FwLWxhcmdlIiBpZD0iYmluZE1vZGFsS2V5Y2FwIj5bIFBSRVNTIEtFWSBdPC9kaXY+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJiaW5kLXN0YXR1cy1ub3RlIiBpZD0iYmluZE1vZGFsU3RhdHVzIj5QcmVzcyBbIEVOVEVSIF0gdG8gY29uZmlybSBvciBbIEVTQyAvIEJBQ0tTUEFDRSBdIHRvIGNsZWFyPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtZm9vdGVyIj4KICAgICAgICAgIDxidXR0b24gY2xhc3M9Im1vZGFsLWFjdGlvbi1idG4gY2FuY2VsIiBpZD0iYmluZE1vZGFsQnRuQ2FuY2VsIj5DbGVhciAvIENhbmNlbDwvYnV0dG9uPgogICAgICAgICAgPGJ1dHRvbiBjbGFzcz0ibW9kYWwtYWN0aW9uLWJ0biBjb25maXJtIiBpZD0iYmluZE1vZGFsQnRuQ29uZmlybSI+Q29uZmlybSBbRU5URVJdPC9idXR0b24+CiAgICAgICAgPC9kaXY+CiAgICAgIDwvZGl2PgogICAgPC9kaXY+CiAgPC9kaXY+CgogIDwhLS0gRmxvYXRpbmcgRGV0YWNoZWQgVG9vbHRpcCBCb3ggVW5kZXJuZWF0aCBNZW51IENvbnRhaW5lciAtLT4KICA8ZGl2IGNsYXNzPSJ0b29sdGlwLWZsb2F0aW5nLWJveCIgaWQ9InRvb2x0aXBCb3giPgogICAgPHNwYW4gY2xhc3M9InRvb2x0aXAtdGV4dCIgaWQ9InRvb2x0aXBUZXh0Ij5OYXZpZ2F0ZSB3aXRoIEFycm93IEtleXMuIFByZXNzIEVudGVyIHRvIHNlbGVjdC48L3NwYW4+CiAgPC9kaXY+CjwvZGl2PgoKICA8IS0tIEluLU1lbnUgQXV0aGVudGljYXRpb24gTW9kYWwgLS0+CiAgPGRpdiBjbGFzcz0ibW9kYWwtb3ZlcmxheSIgaWQ9ImF1dGhNb2RhbE92ZXJsYXkiIHN0eWxlPSJkaXNwbGF5OiBub25lOyI+CiAgICA8ZGl2IGNsYXNzPSJtb2RhbC1jYXJkIGF1dGgtY2FyZCI+CiAgICAgIDxkaXYgY2xhc3M9Im1vZGFsLWhlYWRlciI+CiAgICAgICAgPHNwYW4gY2xhc3M9Im1vZGFsLXRhZyI+V1RSIC8vIFNFQ1VSRSBMT0dJTjwvc3Bhbj4KICAgICAgICA8ZGl2IGNsYXNzPSJhdXRoLXNlcnZlci1iYWRnZSI+V1RSTUVOVS5UQVRSVVMuT1JHPC9kaXY+CiAgICAgIDwvZGl2PgogICAgICA8ZGl2IGNsYXNzPSJhdXRoLWVtYmxlbS13cmFwIj4KICAgICAgICA8c3ZnIGNsYXNzPSJhdXRoLXdhdmUtc3ZnIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgZmlsbD0ibm9uZSI+CiAgICAgICAgICA8cGF0aCBkPSJNMTIgNzYgQzI1IDc2IDM2IDcyIDQ2IDYwIEM1NiA0OCA2NCAzMiA3NiAyMCBDODQgMTIgOTIgMTYgOTAgMjYgQzg4IDM0IDc4IDQyIDY4IDQ0IEM2MCA0NiA1NCA0MCA1OCAzMiBDNjAgMjggNjYgMjggNjggMzEiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwZjBmZiIgc3Ryb2tlLXdpZHRoPSI0LjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgLz4KICAgICAgICAgIDxwYXRoIGQ9Ik0xMiA3NiBDMjggNzYgNDAgNjggNTIgNTYgQzYyIDQ2IDcwIDM2IDc4IDI2IEM3NCAzNiA2NCA1MiA1MCA2MiBDMzggNzAgMjYgNzQgMTIgNzYgWiIgZmlsbD0iIzAwYThmZiIgb3BhY2l0eT0iMC41IiAvPgogICAgICAgICAgPGNpcmNsZSBjeD0iNzYiIGN5PSIxOCIgcj0iMyIgZmlsbD0iIzAwZjBmZiIgLz4KICAgICAgICA8L3N2Zz4KICAgICAgPC9kaXY+CiAgICAgIDxoMyBjbGFzcz0iYXV0aC10aXRsZSI+Q0xJRU5UIEFDQ0VTUyBWRVJJRklDQVRJT048L2gzPgogICAgICA8ZGl2IGNsYXNzPSJhdXRoLXN1YnRpdGxlIj5FbnRlciB5b3VyIHNlc3Npb24gdG9rZW4gZnJvbSB3dHJtZW51LnRhdHJ1cy5vcmcgdG8gaW5pdGlhbGl6ZSBXVFIgTWVudTo8L2Rpdj4KICAgICAgPGRpdiBjbGFzcz0iYXV0aC1mb3JtIj4KICAgICAgICA8ZGl2IGNsYXNzPSJhdXRoLWZpZWxkIj4KICAgICAgICAgIDxsYWJlbCBjbGFzcz0iYXV0aC1sYWJlbCI+U0VTU0lPTiBUT0tFTjwvbGFiZWw+CiAgICAgICAgICA8aW5wdXQgdHlwZT0idGV4dCIgaWQ9ImF1dGhUb2tlbklucHV0IiBjbGFzcz0iYXV0aC1pbnB1dCIgcGxhY2Vob2xkZXI9Ind0cl9zZXNzXy4uLiIgYXV0b2NvbXBsZXRlPSJvZmYiIHNwZWxsY2hlY2s9ImZhbHNlIiAvPgogICAgICAgIDwvZGl2PgogICAgICAgIDxkaXYgY2xhc3M9ImF1dGgtc3RhdHVzIiBpZD0iYXV0aFN0YXR1c1RleHQiPlRva2VuLW9ubHkgYXV0aGVudGljYXRpb24gYWN0aXZlLiBTaW5nbGUgYWN0aXZlIHNlc3Npb24gZW5mb3JjZWQuPC9kaXY+CiAgICAgIDwvZGl2PgogICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1mb290ZXIiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBnYXA6IDhweDsiPgogICAgICAgIDxidXR0b24gY2xhc3M9Im1vZGFsLWFjdGlvbi1idG4gY2FuY2VsIiBpZD0iYnRuQXV0aEd1ZXN0IiBzdHlsZT0iZmxleDogMTsiPlRyeSBEZW1vIE1vZGU8L2J1dHRvbj4KICAgICAgICA8YnV0dG9uIGNsYXNzPSJtb2RhbC1hY3Rpb24tYnRuIGNvbmZpcm0iIGlkPSJidG5BdXRoTG9naW4iIHN0eWxlPSJmbGV4OiAxOyI+QXV0aGVudGljYXRlIFRva2VuPC9idXR0b24+CiAgICAgIDwvZGl2PgogICAgPC9kaXY+CiAgPC9kaXY+CgogIDwhLS0gQW50aWNoZWF0IERlZXAgU2NhbiBSZXN1bHRzIE1vZGFsIC0tPgogIDxkaXYgY2xhc3M9Im1vZGFsLW92ZXJsYXkiIGlkPSJhY1NjYW5Nb2RhbE92ZXJsYXkiIHN0eWxlPSJkaXNwbGF5OiBub25lOyI+CiAgICA8ZGl2IGNsYXNzPSJtb2RhbC1jYXJkIGFjLXNjYW4tY2FyZCIgc3R5bGU9Im1heC13aWR0aDogNDAwcHg7IHdpZHRoOiA5MiU7Ij4KICAgICAgPGRpdiBjbGFzcz0ibW9kYWwtaGVhZGVyIj4KICAgICAgICA8c3BhbiBjbGFzcz0ibW9kYWwtdGFnIj5ESUFHTk9TVElDUyAvLyBBQyBTQ0FOTkVSPC9zcGFuPgogICAgICAgIDxidXR0b24gY2xhc3M9Im1vZGFsLWNsb3NlIiBpZD0iYWNTY2FuQnRuQ2xvc2UiPiYjeDI3MTU7PC9idXR0b24+CiAgICAgIDwvZGl2PgogICAgICA8aDMgY2xhc3M9Im1vZGFsLXRpdGxlIiBzdHlsZT0iZm9udC1zaXplOiAxN3B4OyBtYXJnaW4tYm90dG9tOiA0cHg7Ij5BQ1RJVkUgQU5USUNIRUFUIFNDQU5ORVI8L2gzPgogICAgICA8ZGl2IHN0eWxlPSJmb250LXNpemU6IDExLjVweDsgY29sb3I6ICM5NGEzYjg7IG1hcmdpbi1ib3R0b206IDEycHg7IiBpZD0iYWNTY2FuU3VidGl0bGUiPkRlZXAgc2Nhbm5pbmcgc2VydmVyICZhbXA7IGNsaWVudCByZXNvdXJjZXMuLi48L2Rpdj4KCiAgICAgIDxkaXYgc3R5bGU9ImJhY2tncm91bmQ6IHJnYmEoMjU1LDI1NSwyNTUsMC4wNCk7IGhlaWdodDogNHB4OyBib3JkZXItcmFkaXVzOiAycHg7IG92ZXJmbG93OiBoaWRkZW47IG1hcmdpbi1ib3R0b206IDEycHg7Ij4KICAgICAgICA8ZGl2IGlkPSJhY1NjYW5Qcm9ncmVzc0JhciIgc3R5bGU9IndpZHRoOiAwJTsgaGVpZ2h0OiAxMDAlOyBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoOTBkZWcsICMwMDk5ZmYsICMwMGYwZmYpOyB0cmFuc2l0aW9uOiB3aWR0aCAwLjNzIGVhc2U7Ij48L2Rpdj4KICAgICAgPC9kaXY+CgogICAgICA8ZGl2IGlkPSJhY1NjYW5SZXN1bHRzTGlzdCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47IGdhcDogNnB4OyBtYXJnaW4tYm90dG9tOiAxMnB4OyBtYXgtaGVpZ2h0OiAyMDBweDsgb3ZlcmZsb3cteTogYXV0bzsiPgogICAgICAgIDwhLS0gRHluYW1pYyBzY2FuIHJvd3MgLS0+CiAgICAgIDwvZGl2PgoKICAgICAgPGRpdiBzdHlsZT0iYmFja2dyb3VuZDogcmdiYSgwLCAyNDAsIDI1NSwgMC4wNCk7IGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoMCwgMjQwLCAyNTUsIDAuMTgpOyBib3JkZXItcmFkaXVzOiA2cHg7IHBhZGRpbmc6IDhweCAxMHB4OyBmb250LXNpemU6IDExcHg7IGNvbG9yOiAjY2JkNWUxOyBsaW5lLWhlaWdodDogMS40NTsgbWFyZ2luLWJvdHRvbTogMTRweDsiPgogICAgICAgIDxiIHN0eWxlPSJjb2xvcjogIzAwZjBmZjsiPlZlcmlmaWNhdGlvbjo8L2I+IFdUUiBNZW51IGFjdGl2ZWx5IGJ5cGFzc2VzIDxiPkZpdmVHdWFyZDwvYj4gd2l0aCByZWFsLXRpbWUgMTBzIGhlYXJ0YmVhdCBzcG9vZmluZyBhbmQgbmF0aXZlIG1lbW9yeSBob29rcy4KICAgICAgPC9kaXY+CgogICAgICA8ZGl2IGNsYXNzPSJtb2RhbC1mb290ZXIiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBqdXN0aWZ5LWNvbnRlbnQ6IGZsZXgtZW5kOyI+CiAgICAgICAgPGJ1dHRvbiBjbGFzcz0ibW9kYWwtYWN0aW9uLWJ0biBjb25maXJtIiBpZD0iYWNTY2FuQnRuRG9uZSIgc3R5bGU9Im1pbi13aWR0aDogMTEwcHg7Ij5DbG9zZSBbRVNDXTwvYnV0dG9uPgogICAgICA8L2Rpdj4KICAgIDwvZGl2PgogIDwvZGl2PgoKICA8IS0tIEZsb2F0aW5nIEhVRDogU3BlY3RhdG9yIExpc3QgLS0+CiAgPGRpdiBjbGFzcz0iaHVkLXBhbmVsIGh1ZC1zcGVjdGF0b3IiIGlkPSJzcGVjdGF0b3JMaXN0SHVkIiBzdHlsZT0iZGlzcGxheTogbm9uZTsiPgogICAgPGRpdiBjbGFzcz0iaHVkLWhlYWRlciI+CiAgICAgIDxzcGFuIGNsYXNzPSJodWQtZG90IHNhZmUiIGlkPSJzcGVjdGF0b3JEb3QiPuKXjzwvc3Bhbj4KICAgICAgPHNwYW4gY2xhc3M9Imh1ZC10aXRsZSI+U1BFQ1RBVE9SIFJBREFSPC9zcGFuPgogICAgICA8c3BhbiBjbGFzcz0iaHVkLWJhZGdlIiBpZD0ic3BlY3RhdG9yQ291bnQiPjA8L3NwYW4+CiAgICA8L2Rpdj4KICAgIDxkaXYgY2xhc3M9Imh1ZC1ib2R5IiBpZD0ic3BlY3RhdG9yTGlzdEJvZHkiPgogICAgICA8ZGl2IGNsYXNzPSJodWQtZW1wdHkiPk5vIHNwZWN0YXRvcnMgbmVhcmJ5IChTYWZlKTwvZGl2PgogICAgPC9kaXY+CiAgICA8ZGl2IGNsYXNzPSJodWQtcmVzaXplciIgdGl0bGU9IkRyYWcgY29ybmVyIHRvIHJlc2l6ZSAod2lkZW4vbmFycm93KSI+PC9kaXY+CiAgPC9kaXY+CgogIDwhLS0gRmxvYXRpbmcgSFVEOiBLZXliaW5kcyBMaXN0IC0tPgogIDxkaXYgY2xhc3M9Imh1ZC1wYW5lbCBodWQtYmluZHMiIGlkPSJrZXliaW5kc0xpc3RIdWQiIHN0eWxlPSJkaXNwbGF5OiBub25lOyI+CiAgICA8ZGl2IGNsYXNzPSJodWQtaGVhZGVyIj4KICAgICAgPHNwYW4gY2xhc3M9Imh1ZC1kb3QgYWN0aXZlIj7il488L3NwYW4+CiAgICAgIDxzcGFuIGNsYXNzPSJodWQtdGl0bGUiPkFDVElWRSBCSU5EUzwvc3Bhbj4KICAgICAgPHNwYW4gY2xhc3M9Imh1ZC1iYWRnZSIgaWQ9ImJpbmRzQ291bnQiPjA8L3NwYW4+CiAgICA8L2Rpdj4KICAgIDxkaXYgY2xhc3M9Imh1ZC10YWJsZS13cmFwIj4KICAgICAgPHRhYmxlIGNsYXNzPSJodWQtYmluZHMtdGFibGUiIGlkPSJrZXliaW5kc1RhYmxlIj4KICAgICAgICA8dGhlYWQ+CiAgICAgICAgICA8dHI+CiAgICAgICAgICAgIDx0aCBjbGFzcz0idGgtZnVuYyI+RlVOQ1RJT048L3RoPgogICAgICAgICAgICA8dGggY2xhc3M9InRoLWtleSI+S0VZPC90aD4KICAgICAgICAgIDwvdHI+CiAgICAgICAgPC90aGVhZD4KICAgICAgICA8dGJvZHkgaWQ9ImtleWJpbmRzTGlzdEJvZHkiPgogICAgICAgICAgPHRyPjx0ZCBjb2xzcGFuPSIyIiBjbGFzcz0iaHVkLWVtcHR5Ij5ObyBrZXlzIGJvdW5kIHlldCBbRjkgaW4gTWVudV08L3RkPjwvdHI+CiAgICAgICAgPC90Ym9keT4KICAgICAgPC90YWJsZT4KICAgIDwvZGl2PgogICAgPGRpdiBjbGFzcz0iaHVkLXJlc2l6ZXIiIHRpdGxlPSJEcmFnIGNvcm5lciB0byByZXNpemUgKHdpZGVuL25hcnJvdykiPjwvZGl2PgogIDwvZGl2PgoKICA8IS0tIEZsb2F0aW5nIEhVRDogUXVpY2sgUGxhY2VyICYgU3Bhd25lciBXaWRnZXQgLS0+CiAgPGRpdiBjbGFzcz0iaHVkLXBsYWNlciIgaWQ9InF1aWNrUGxhY2VySHVkIiBzdHlsZT0iZGlzcGxheTogbm9uZTsiPgogICAgPGRpdiBjbGFzcz0icGxhY2VyLXRhZyIgaWQ9InBsYWNlclRhZ1RpdGxlIj5GUkVFQ0FNIC8vIFBMQUNFUjwvZGl2PgogICAgPGRpdiBjbGFzcz0icGxhY2VyLW5hdiI+CiAgICAgIDxidXR0b24gY2xhc3M9InBsYWNlci1hcnJvdyIgaWQ9InBsYWNlclByZXYiPiZsdDs8L2J1dHRvbj4KICAgICAgPGRpdiBjbGFzcz0icGxhY2VyLWN1cnJlbnQiPgogICAgICAgIDxzcGFuIGNsYXNzPSJwbGFjZXItY2F0ZWdvcnkiIGlkPSJwbGFjZXJDYXRlZ29yeSI+UFJPUDwvc3Bhbj4KICAgICAgICA8c3BhbiBjbGFzcz0icGxhY2VyLW5hbWUiIGlkPSJwbGFjZXJJdGVtTmFtZSI+T3JhbmdlIFdvcmsgQmFycmllcjwvc3Bhbj4KICAgICAgPC9kaXY+CiAgICAgIDxidXR0b24gY2xhc3M9InBsYWNlci1hcnJvdyIgaWQ9InBsYWNlck5leHQiPiZndDs8L2J1dHRvbj4KICAgIDwvZGl2PgogICAgPGRpdiBjbGFzcz0icGxhY2VyLWNvbnRyb2xzIj4KICAgICAgPHNwYW4+PGtiZD5TQ1JPTEw8L2tiZD4gU2VsZWN0PC9zcGFuPgogICAgICA8c3Bhbj48a2JkPkxNQjwva2JkPiBTcGF3biAvIFBsYWNlPC9zcGFuPgogICAgICA8c3Bhbj48a2JkPkVTQzwva2JkPiBDbG9zZTwvc3Bhbj4KICAgIDwvZGl2PgogICAgPGRpdiBjbGFzcz0iaHVkLXJlc2l6ZXIiIHRpdGxlPSJEcmFnIGNvcm5lciB0byByZXNpemUiPjwvZGl2PgogIDwvZGl2PgoKICA8c2NyaXB0PgovLyBXVFIgTWVudSAtIFdhdGVyLUdsYXNzIEhpZXJhcmNoaWNhbCBOYXZpZ2F0aW9uICYgQ2xpZW50IEVuZ2luZQooZnVuY3Rpb24oKSB7CiAgJ3VzZSBzdHJpY3QnOwoKICBmdW5jdGlvbiBlc2NhcGVIdG1sKHN0cikgewogICAgaWYgKCFzdHIpIHJldHVybiAnJzsKICAgIHJldHVybiBTdHJpbmcoc3RyKQogICAgICAucmVwbGFjZSgvJi9nLCAnJmFtcDsnKQogICAgICAucmVwbGFjZSgvPC9nLCAnJmx0OycpCiAgICAgIC5yZXBsYWNlKC8+L2csICcmZ3Q7JykKICAgICAgLnJlcGxhY2UoLyIvZywgJyZxdW90OycpCiAgICAgIC5yZXBsYWNlKC8nL2csICcmIzM5OycpOwogIH0KCiAgLy8gTWluaW1hbCBTVkcgSWNvbnMgRGF0YWJhc2UKICBjb25zdCBJQ09OUyA9IHsKICAgIHBsYXllcjogJzxzdmcgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTIgMTJjMi4yMSAwIDQtMS43OSA0LTRzLTEuNzktNC00LTQtNCAxLjc5LTQgNCAxLjc5IDQgNCA0em0wIDJjLTIuNjcgMC04IDEuMzQtOCA0djJoMTZ2LTJjMC0yLjY2LTUuMzMtNC04LTR6Ii8+PC9zdmc+JywKICAgIHZlaGljbGU6ICc8c3ZnIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTE4LjkyIDYuMDFDMTguNzIgNS40MiAxOC4xNiA1IDE3LjUgNWgtMTFjLS42NiAwLTEuMjEuNDItMS40MiAxLjAxTDMgMTJ2OGMwIC41NS40NSAxIDEgMWgxYy41NSAwIDEtLjQ1IDEtMXYtMWgxMnYxYzAgLjU1LjQ1IDEgMSAxaDFjLjU1IDAgMS0uNDUgMS0xdi04bC0yLjA4LTUuOTl6TTYuODUgN2gxMC4yOWwxLjA0IDNINS44MWwxLjA0LTN6TTE5IDE3SDV2LTQuNjZsLjEyLS4zNGgxMy43N2wuMTEuMzRWMTd6Ii8+PGNpcmNsZSBjeD0iNy41IiBjeT0iMTQuNSIgcj0iMS41Ii8+PGNpcmNsZSBjeD0iMTYuNSIgY3k9IjE0LjUiIHI9IjEuNSIvPjwvc3ZnPicsCiAgICBjb21iYXQ6ICc8c3ZnIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTIxIDdoLTZWNEg5djNIM3Y0aDN2MmgydjdoNHYtN2gydi0yaDdWN3pNOCA5SDVWOGgzdjF6bTUgMTBoLTJ2LTZoMnY2em02LTloLTVWOGg1djJ6Ii8+PC9zdmc+JywKICAgIG9ubGluZTogJzxzdmcgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTYgMTFjMS42NiAwIDIuOTktMS4zNCAyLjk5LTNTMTcuNjYgNSAxNiA1cy0zIDEuMzQtMyAzIDEuMzQgMyAzIDN6bS04IDBjMS42NiAwIDIuOTktMS4zNCAyLjk5LTNTOS42NiA1IDggNSA1IDYuMzQgNSA4czEuMzQgMyAzIDN6bTAgMmMtMi4zMyAwLTcgMS4xNy03IDMuNVYxOWgxNHYtMi41YzAtMi4zMy00LjY3LTMuNS03LTMuNXptOCAwYy0uMjkgMC0uNjIuMDItLjk3LjA1IDEuMTYuODQgMS45NyAxLjk3IDEuOTcgMy40NVYxOWg2di0yLjVjMC0yLjMzLTQuNjctMy41LTctMy41eiIvPjwvc3ZnPicsCiAgICB2aXN1YWxzOiAnPHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiPjxwYXRoIGQ9Ik0xMiA0LjVDNyA0LjUgMi43MyA3LjYxIDEgMTJjMS43MyA0LjM5IDYgNy41IDExIDcuNXM5LjI3LTMuMTEgMTEtNy41Yy0xLjczLTQuMzktNi03LjUtMTEtNy41ek0xMiAxN2MtMi43NiAwLTUtMi4yNC01LTVzMi4yNC01IDUtNSA1IDIuMjQgNSA1LTIuMjQgNS01IDV6bTAtOGMtMS42NiAwLTMgMS4zNC0zIDNzMS4zNCAzIDMgMyAzLTEuMzQgMy0zLTEuMzQtMy0zLTN6Ii8+PC9zdmc+JywKICAgIHdvcmxkOiAnPHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiPjxwYXRoIGQ9Ik0xMiAyYTEwIDEwIDAgMSAwIDEwIDEwQTEwIDEwIDAgMCAwIDEyIDJ6bTEgMTcuOTNWMTdhMSAxIDAgMCAwLTIgMHYyLjkzQTggOCAwIDAgMSA0LjA3IDEzSDdhMSAxIDAgMCAwIDAtMkg0LjA3QTggOCAwIDAgMSAxMSA0LjA3VjdhMSAxIDAgMCAwIDIgMFY0LjA3QTggOCAwIDAgMSAxOS45MyAxMUgxN2ExIDEgMCAwIDAgMCAyaDIuOTNBOCA4IDAgMCAxIDEzIDE5LjkzeiIvPjwvc3ZnPicsCiAgICBzZXR0aW5nczogJzxzdmcgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTkuMTQgMTIuOTRjLjA0LS4zLjA2LS42MS4wNi0uOTQgMC0uMzItLjAyLS42NC0uMDctLjk0bDIuMDMtMS41OGMuMTgtLjE0LjIzLS40MS4xMi0uNjFsLTEuOTItMy4zMmMtLjEyLS4yMi0uMzctLjI5LS41OS0uMjJsLTIuMzkuOTZjLS41LS4zOC0xLjAzLS43LTEuNjItLjk0bC0uMzYtMi41NGMtLjA0LS4yNC0uMjQtLjQxLS40OC0uNDFoLTMuODRjLS4yNCAwLS40My4xNy0uNDcuNDFsLS4zNiAyLjU0Yy0uNTkuMjQtMS4xMy41Ny0xLjYyLjk0bC0yLjM5LS45NmMtLjIyLS4wOC0uNDcgMC0uNTkuMjJMMi43NCA4Ljg3Yy0uMTIuMjEtLjA4LjQ3LjEyLjYxbDIuMDMgMS41OGMtLjA1LjMtLjA5LjYzLS4wOS45NHMuMDIuNjQuMDcuOTRsLTIuMDMgMS41OGMtLjE4LjE0LS4yMy40MS0uMTIuNjFsMS45MiAzLjMyYy4xMi4yMi4zNy4yOS41OS4yMmwyLjM5LS45NmMuNS4zOCAxLjAzLjcgMS42Mi45NGwuMzYgMi41NGMuMDUuMjQuMjQuNDEuNDguNDFoMy44NGMuMjQgMCAuNDQtLjE3LjQ3LS40MWwuMzYtMi41NGMuNTktLjI0IDEuMTMtLjU2IDEuNjItLjk0bDIuMzkuOTZjLjIyLjA4LjQ3IDAgLjU5LS4yMmwxLjkyLTMuMzJjLjEyLS4yMi4wNy0uNDctLjEyLS42MWwtMi4wMS0xLjU4ek0xMiAxNS42Yy0xLjk4IDAtMy42LTEuNjItMy42LTMuNnMxLjYyLTMuNiAzLjYtMy42IDMuNiAxLjYyIDMuNiAzLjYtMS42MiAzLjYtMy42IDMuNnoiLz48L3N2Zz4nLAogICAgYnlwYXNzZXM6ICc8c3ZnIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTQgNmMwLTEuMS45LTIgMi0yaDEyYTIgMiAwIDAgMSAyIDJ2MmEyIDIgMCAwIDEtMiAySDZhMiAyIDAgMCAxLTItMlY2em0wIDdjMC0xLjEuOS0yIDItMmgxMmEyIDIgMCAwIDEgMiAydjJhMiAyIDAgMCAxLTIgMkg2YTIgMiAwIDAgMS0yLTJ2LTJ6bTAgN2MwLTEuMS45LTIgMi0yaDEyYTIgMiAwIDAgMSAyIDJ2MmEyIDIgMCAwIDEtMiAySDZhMiAyIDAgMCAxLTItMnYtMnoiLz48L3N2Zz4nCiAgfTsKCiAgLy8gUHJlc2V0cyBEYXRhYmFzZSBmb3IgSW5wdXRzCiAgY29uc3QgTU9EQUxfUFJFU0VUUyA9IHsKICAgIHZlaGljbGU6IFsKICAgICAgeyBsYWJlbDogJ0FkZGVyJywgdmFsOiAnYWRkZXInIH0sCiAgICAgIHsgbGFiZWw6ICdTdWx0YW4gUlMnLCB2YWw6ICdzdWx0YW5ycycgfSwKICAgICAgeyBsYWJlbDogJ0tyaWVnZXInLCB2YWw6ICdrcmllZ2VyJyB9LAogICAgICB7IGxhYmVsOiAnWmVudG9ybm8nLCB2YWw6ICd6ZW50b3JubycgfSwKICAgICAgeyBsYWJlbDogJ1QyMCcsIHZhbDogJ3QyMCcgfSwKICAgICAgeyBsYWJlbDogJ0thbWFjaG8nLCB2YWw6ICdrYW1hY2hvJyB9LAogICAgICB7IGxhYmVsOiAnU2FuY2hleicsIHZhbDogJ3NhbmNoZXonIH0sCiAgICAgIHsgbGFiZWw6ICdPcHByZXNzb3IgTUsyJywgdmFsOiAnb3BwcmVzc29yMicgfQogICAgXSwKICAgIHdlYXBvbjogWwogICAgICB7IGxhYmVsOiAnQ29tYmF0IE1HJywgdmFsOiAnd2VhcG9uX2NvbWJhdG1nJyB9LAogICAgICB7IGxhYmVsOiAnU3BlY2lhbCBDYXJiaW5lJywgdmFsOiAnd2VhcG9uX3NwZWNpYWxjYXJiaW5lJyB9LAogICAgICB7IGxhYmVsOiAnSGVhdnkgU25pcGVyJywgdmFsOiAnd2VhcG9uX2hlYXZ5c25pcGVyJyB9LAogICAgICB7IGxhYmVsOiAnSGVhdnkgUmV2b2x2ZXInLCB2YWw6ICd3ZWFwb25fcmV2b2x2ZXInIH0sCiAgICAgIHsgbGFiZWw6ICdBUCBQaXN0b2wnLCB2YWw6ICd3ZWFwb25fYXBwaXN0b2wnIH0sCiAgICAgIHsgbGFiZWw6ICdSUEcgTGF1bmNoZXInLCB2YWw6ICd3ZWFwb25fcnBnJyB9CiAgICBdLAogICAgY29vcmRzOiBbCiAgICAgIHsgbGFiZWw6ICdMZWdpb24gU3F1YXJlJywgdmFsOiAnMjE1LjgsIC04MTAuMSwgMzAuNycgfSwKICAgICAgeyBsYWJlbDogJ1NhbmR5IFNob3JlcyBBaXJwb3J0JywgdmFsOiAnMTczNS4yLCAzNzEwLjgsIDM0LjEnIH0sCiAgICAgIHsgbGFiZWw6ICdQYWxldG8gQmF5IEJhbmsnLCB2YWw6ICctMTEzLjEsIDY0NjguOSwgMzEuNicgfSwKICAgICAgeyBsYWJlbDogJ01hemUgQmFuayBIZWxpcGFkJywgdmFsOiAnLTc1LjAsIC04MTguNSwgMzI2LjInIH0sCiAgICAgIHsgbGFiZWw6ICdMUyBBaXJwb3J0IFJ1bndheScsIHZhbDogJy0xMDM3LjYsIC0yNzM3LjgsIDEzLjgnIH0KICAgIF0sCiAgICBjb25maWdfc2F2ZTogWwogICAgICB7IGxhYmVsOiAnRGVmYXVsdF9XYXRlckdsYXNzJywgdmFsOiAnRGVmYXVsdF9XYXRlckdsYXNzJyB9LAogICAgICB7IGxhYmVsOiAnSHZIX0FnZ3Jlc3NpdmUnLCB2YWw6ICdIdkhfQWdncmVzc2l2ZScgfSwKICAgICAgeyBsYWJlbDogJ0xlZ2l0X0NydWlzZScsIHZhbDogJ0xlZ2l0X0NydWlzZScgfSwKICAgICAgeyBsYWJlbDogJ1N0ZWFsdGhfR2hvc3QnLCB2YWw6ICdTdGVhbHRoX0dob3N0JyB9CiAgICBdLAogICAgY29uZmlnX2xvYWQ6IFsKICAgICAgeyBsYWJlbDogJ0RlZmF1bHRfV2F0ZXJHbGFzcycsIHZhbDogJ0RlZmF1bHRfV2F0ZXJHbGFzcycgfSwKICAgICAgeyBsYWJlbDogJ0h2SF9BZ2dyZXNzaXZlJywgdmFsOiAnSHZIX0FnZ3Jlc3NpdmUnIH0sCiAgICAgIHsgbGFiZWw6ICdMZWdpdF9DcnVpc2UnLCB2YWw6ICdMZWdpdF9DcnVpc2UnIH0sCiAgICAgIHsgbGFiZWw6ICdTdGVhbHRoX0dob3N0JywgdmFsOiAnU3RlYWx0aF9HaG9zdCcgfQogICAgXSwKICAgIGNvbmZpZ19kZWxldGU6IFsKICAgICAgeyBsYWJlbDogJ0RlZmF1bHRfV2F0ZXJHbGFzcycsIHZhbDogJ0RlZmF1bHRfV2F0ZXJHbGFzcycgfSwKICAgICAgeyBsYWJlbDogJ0h2SF9BZ2dyZXNzaXZlJywgdmFsOiAnSHZIX0FnZ3Jlc3NpdmUnIH0sCiAgICAgIHsgbGFiZWw6ICdMZWdpdF9DcnVpc2UnLCB2YWw6ICdMZWdpdF9DcnVpc2UnIH0sCiAgICAgIHsgbGFiZWw6ICdTdGVhbHRoX0dob3N0JywgdmFsOiAnU3RlYWx0aF9HaG9zdCcgfQogICAgXQogIH07CgogIC8vIFF1aWNrIFBsYWNlciBJdGVtcyBEYXRhYmFzZQogIGNvbnN0IFBMQUNFUl9JVEVNUyA9IHsKICAgIHByb3BzOiBbCiAgICAgIHsgbmFtZTogJ09yYW5nZSBXb3JrIEJhcnJpZXInLCBtb2RlbDogJ3Byb3BfYmFycmllcl93b3JrMDUnIH0sCiAgICAgIHsgbmFtZTogJ1BvcmNlbGFpbiBUb2lsZXQnLCBtb2RlbDogJ3Byb3BfbGRfdG9pbGV0XzAxJyB9LAogICAgICB7IG5hbWU6ICdDYW1wZmlyZScsIG1vZGVsOiAncHJvcF9iZWFjaF9maXJlJyB9LAogICAgICB7IG5hbWU6ICdDb25jcmV0ZSBCbG9jaycsIG1vZGVsOiAncHJvcF9tcF9jb25lXzAxJyB9LAogICAgICB7IG5hbWU6ICdUcmFmZmljIExpZ2h0IFBvbGUnLCBtb2RlbDogJ3Byb3BfdHJhZmZpY18wMWEnIH0KICAgIF0sCiAgICBwZWRzOiBbCiAgICAgIHsgbmFtZTogJ1NrYXRlciBQZWQnLCBtb2RlbDogJ2FfbV95X3NrYXRlcl8wMScgfSwKICAgICAgeyBuYW1lOiAnU1dBVCBTcGVjaWFsaXN0JywgbW9kZWw6ICdzX21feV9zd2F0XzAxJyB9LAogICAgICB7IG5hbWU6ICdBc3Ryb25hdXQgQWxpZW4nLCBtb2RlbDogJ3NfbV9tX21vdmFsaWVuXzAxJyB9LAogICAgICB7IG5hbWU6ICdKdWdnZXJuYXV0IEFybW9yJywgbW9kZWw6ICd1X21feV9qdWdnZXJuYXV0XzAxJyB9LAogICAgICB7IG5hbWU6ICdab21iaWUgUGVkJywgbW9kZWw6ICd1X21feV96b21iaWVfMDEnIH0KICAgIF0sCiAgICB2ZWhzOiBbCiAgICAgIHsgbmFtZTogJ1RydWZmYWRlIEFkZGVyJywgbW9kZWw6ICdhZGRlcicgfSwKICAgICAgeyBuYW1lOiAnUHJvZ2VuIFQyMCcsIG1vZGVsOiAndDIwJyB9LAogICAgICB7IG5hbWU6ICdQZWdhc3NpIFplbnRvcm5vJywgbW9kZWw6ICd6ZW50b3JubycgfSwKICAgICAgeyBuYW1lOiAnS2FyaW4gU3VsdGFuIFJTJywgbW9kZWw6ICdzdWx0YW5ycycgfSwKICAgICAgeyBuYW1lOiAnSFZZIEluc3VyZ2VudCcsIG1vZGVsOiAnaW5zdXJnZW50JyB9LAogICAgICB7IG5hbWU6ICdPcHByZXNzb3IgTUsyJywgbW9kZWw6ICdvcHByZXNzb3IyJyB9CiAgICBdCiAgfTsKCiAgLy8gRGVmYXVsdCBTaW11bGF0ZWQgT25saW5lIFBsYXllcnMgKGZvciBCcm93c2VyIERlbW8gLyBPZmZsaW5lIE1vZGUpCiAgY29uc3QgREVGQVVMVF9TSU1VTEFURURfUExBWUVSUyA9IFsKICAgIHsgc2VydmVySWQ6IDEsIG5hbWU6ICd0YXRydXMgKFZJUCBIb3N0KScsIGRpc3Q6IDEyLCBpc1NlbGY6IGZhbHNlIH0sCiAgICB7IHNlcnZlcklkOiA0LCBuYW1lOiAnT2ZmaWNlcl9NaWxsZXInLCBkaXN0OiAzOCwgaXNTZWxmOiBmYWxzZSB9LAogICAgeyBzZXJ2ZXJJZDogNywgbmFtZTogJ0dob3N0UmlkZXJfOTknLCBkaXN0OiA3MiwgaXNTZWxmOiBmYWxzZSB9LAogICAgeyBzZXJ2ZXJJZDogMTIsIG5hbWU6ICdBZG1pbl9Wb3J0ZXgnLCBkaXN0OiAxMTAsIGlzU2VsZjogZmFsc2UgfSwKICAgIHsgc2VydmVySWQ6IDE4LCBuYW1lOiAnU3BlZWR5X0dvbnphJywgZGlzdDogMTY1LCBpc1NlbGY6IGZhbHNlIH0KICBdOwoKICAvLyBIaWVyYXJjaGljYWwgQ2F0ZWdvcmllcyAmIFN1Ym1lbnVzIERhdGFiYXNlCiAgLy8gQUxMIFRPR0dMRSBTVEFURVMgQVJFIEZBTFNFIE9OIFNUQVJUVVAgKENMRUFOIFpFUk8tQ0hFQVQgSU5JVElBTElaQVRJT04pCiAgY29uc3QgQ0FURUdPUklFUyA9IFsKICAgIHsKICAgICAgaWQ6ICdwbGF5ZXInLAogICAgICBsYWJlbDogJ1BsYXllcicsCiAgICAgIGljb246ICdwbGF5ZXInLAogICAgICBkZXNjOiAnUGxheWVyIG1vZGlmaWNhdGlvbnMsIGhlYWx0aCwgbW92ZW1lbnQgYW5kIHRlbGVwb3J0cy4nLAogICAgICBzdWJ0YWJzOiBbCiAgICAgICAgewogICAgICAgICAgaWQ6ICdzZWxmJywKICAgICAgICAgIGxhYmVsOiAnU2VsZicsCiAgICAgICAgICBpdGVtczogWwogICAgICAgICAgICB7IGlkOiAnZ29kbW9kZScsIGxhYmVsOiAnR29kbW9kZScsIHR5cGU6ICd0b2dnbGUnLCBzdGF0ZTogZmFsc2UsIGRlc2M6ICdNYWtlIGxvY2FsIHBsYXllciBjb21wbGV0ZWx5IGludmluY2libGUgdG8gYWxsIGRhbWFnZS4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdhdXRvX3Jldml2ZScsIGxhYmVsOiAnQXV0byBSZXZpdmUnLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnQXV0b21hdGljYWxseSByZXZpdmVzIHlvdXIgcGVkIGltbWVkaWF0ZWx5IHVwb24gZGVhdGguJyB9LAogICAgICAgICAgICB7IGlkOiAncmV2aXZlX3NjcmlwdCcsIGxhYmVsOiAnUmV2aXZlIChTY3JpcHQpJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdUcmlnZ2VycyBhY3RpdmUgc2VydmVyIGhvc3BpdGFsL2FtYnVsYW5jZSByZXZpdmUgdHJpZ2dlcnMuJyB9LAogICAgICAgICAgICB7IGlkOiAncmV2aXZlX25hdGl2ZScsIGxhYmVsOiAnUmV2aXZlIChOYXRpdmUpJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdSZXNldHMgaGVhbHRoLCByYWdkb2xsIGFuZCBwZWQgc3RhdGUgbmF0aXZlbHkuJyB9LAogICAgICAgICAgICB7IGlkOiAnaGVhbF9hcm1vcicsIGxhYmVsOiAnTWF4IEhlYWx0aCAmIEFybW9yJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdGaWxscyBoZWFsdGggdG8gMjAwIGFuZCBhcm1vciB0byAxMDAuJyB9LAogICAgICAgICAgICB7IGlkOiAnY2xlYW5fcGVkJywgbGFiZWw6ICdDbGVhbiBQZWQgJiBDbG90aGVzJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdXYXNoZXMgYXdheSBibG9vZCwgZGlydCBhbmQgYnVsbGV0IGhvbGUgZGFtYWdlLicgfSwKICAgICAgICAgICAgeyBpZDogJ25ldmVyX3dhbnRlZCcsIGxhYmVsOiAnTmV2ZXIgV2FudGVkJywgdHlwZTogJ3RvZ2dsZScsIHN0YXRlOiBmYWxzZSwgZGVzYzogJ0xvY2tzIHdhbnRlZCBsZXZlbCB0byAwIGFuZCBzdG9wcyBwb2xpY2UgZGlzcGF0Y2guJyB9LAogICAgICAgICAgICB7IGlkOiAnaW52aXNpYmxlJywgbGFiZWw6ICdJbnZpc2liaWxpdHknLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnTWFrZXMgbG9jYWwgcGxheWVyIHBlZCBjb21wbGV0ZWx5IGludmlzaWJsZS4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICd1bmZyZWV6ZV9zZWxmJywgbGFiZWw6ICdVbmZyZWV6ZSBTZWxmJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdDbGVhcnMgYWxsIHJhZ2RvbGxzLCB0YXNlciBzdGF0ZXMgYW5kIGZyb3plbiBwb3NpdGlvbnMuJyB9LAogICAgICAgICAgICB7IGlkOiAnc3VpY2lkZScsIGxhYmVsOiAnQ29tbWl0IFN1aWNpZGUnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ0luc3RhbnRseSBraWxsIHlvdXIgbG9jYWwgY2hhcmFjdGVyLicgfQogICAgICAgICAgXQogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgaWQ6ICdtb3ZlbWVudCcsCiAgICAgICAgICBsYWJlbDogJ01vdmVtZW50JywKICAgICAgICAgIGl0ZW1zOiBbCiAgICAgICAgICAgIHsgaWQ6ICdmcmVlY2FtJywgbGFiZWw6ICdGcmVlY2FtIEZsaWdodCcsIHR5cGU6ICd0b2dnbGUnLCBzdGF0ZTogZmFsc2UsIGRlc2M6ICdEZXRhY2ggY2FtZXJhIGZyb20gcGVkIGFuZCBmbHkgZnJlZWx5IHdpdGggV0FTRC4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdmcmVlY2FtX3Nob290JywgbGFiZWw6ICdGcmVlY2FtIENyb3NzaGFpciBTaG9vdCcsIHR5cGU6ICd0b2dnbGUnLCBzdGF0ZTogZmFsc2UsIGRlc2M6ICdDbGljayBMTUIgaW4gRnJlZWNhbSB0byBmaXJlIGV4cGxvc2l2ZSBzbmlwZXIgcmF5cy4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdmcmVlY2FtX3BsYWNlcicsIGxhYmVsOiAnRnJlZWNhbSBRdWljayBQbGFjZXInLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnVG9nZ2xlcyBib3R0b20tY2VudGVyIGVudGl0eSBwbGFjZXIgZHVyaW5nIGZyZWVjYW0gKFNjcm9sbCAmIExNQiBwbGFjZSkuJyB9LAogICAgICAgICAgICB7IGlzSGVhZGVyOiB0cnVlLCBsYWJlbDogJ0ZyZWVjYW0gUGxhY2VycycgfSwKICAgICAgICAgICAgeyBpZDogJ2ZyZWVjYW1fcGxhY2VyX3Byb3BzJywgbGFiZWw6ICdGcmVlY2FtIFByb3AgUGxhY2VyJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdPcGVucyBwcm9wIHBsYWNlciBpbiBmcmVlY2FtIG1vZGUuJyB9LAogICAgICAgICAgICB7IGlkOiAnZnJlZWNhbV9wbGFjZXJfcGVkcycsIGxhYmVsOiAnRnJlZWNhbSBQZWQgUGxhY2VyJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdPcGVucyBOUEMgcGxhY2VyIGluIGZyZWVjYW0gbW9kZS4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdmcmVlY2FtX3BsYWNlcl92ZWhzJywgbGFiZWw6ICdGcmVlY2FtIFZlaGljbGUgUGxhY2VyJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdPcGVucyB2ZWhpY2xlIHBsYWNlciBpbiBmcmVlY2FtIG1vZGUuJyB9LAogICAgICAgICAgICB7IGlzSGVhZGVyOiB0cnVlLCBsYWJlbDogJ01vdmVtZW50IEhhY2tzJyB9LAogICAgICAgICAgICB7IGlkOiAnbm9jbGlwJywgbGFiZWw6ICdOb2NsaXAnLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnRmx5IHRocm91Z2ggd2FsbHMgYW5kIHRlcnJhaW4gKFdBU0QgKyBTaGlmdC9TcGFjZS9DdHJsKS4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdza3lfc3dpbScsIGxhYmVsOiAnU2t5IFN3aW0nLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnQWxsb3dzIHN3aW1taW5nIHRocm91Z2ggbWlkLWFpciBhYm92ZSBMb3MgU2FudG9zLicgfSwKICAgICAgICAgICAgeyBpZDogJ3N1cGVyX2p1bXAnLCBsYWJlbDogJ1N1cGVyIEp1bXAnLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnSnVtcCBzaWduaWZpY2FudGx5IGhpZ2hlciBpbnRvIHRoZSBhaXIuJyB9LAogICAgICAgICAgICB7IGlkOiAnZmFzdF9ydW4nLCBsYWJlbDogJ0Zhc3QgU3ByaW50JywgdHlwZTogJ3RvZ2dsZScsIHN0YXRlOiBmYWxzZSwgZGVzYzogJ0luY3JlYXNlcyBzcHJpbnQgYW5kIHJ1bm5pbmcgbW92ZW1lbnQgc3BlZWQuJyB9CiAgICAgICAgICBdCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICBpZDogJ3RlbGVwb3J0JywKICAgICAgICAgIGxhYmVsOiAnVGVsZXBvcnQnLAogICAgICAgICAgaXRlbXM6IFsKICAgICAgICAgICAgeyBpZDogJ3RwX3dheXBvaW50JywgbGFiZWw6ICdXYXlwb2ludCcsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnVGVsZXBvcnQgZGlyZWN0bHkgdG8geW91ciBtYXJrZWQgbWFwIHdheXBvaW50LicgfSwKICAgICAgICAgICAgeyBpZDogJ3RwX2Nvb3JkcycsIGxhYmVsOiAnQ3VzdG9tIENvb3JkaW5hdGVzJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdFbnRlciBYLCBZLCBaIGNvb3JkaW5hdGVzIHRvIHRlbGVwb3J0LicgfSwKICAgICAgICAgICAgeyBpc0hlYWRlcjogdHJ1ZSwgbGFiZWw6ICdMb2NhdGlvbnMnIH0sCiAgICAgICAgICAgIHsgaWQ6ICd0cF9sZWdpb24nLCBsYWJlbDogJ0xlZ2lvbiBTcXVhcmUnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ1RlbGVwb3J0IHRvIExlZ2lvbiBTcXVhcmUgaW4gZG93bnRvd24gTG9zIFNhbnRvcy4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICd0cF9haXJwb3J0JywgbGFiZWw6ICdMUyBBaXJwb3J0JywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdUZWxlcG9ydCB0byB0aGUgTG9zIFNhbnRvcyBJbnRlcm5hdGlvbmFsIEFpcnBvcnQgcnVud2F5LicgfSwKICAgICAgICAgICAgeyBpZDogJ3RwX3NhbmR5c2hvcmVzJywgbGFiZWw6ICdTYW5keSBTaG9yZXMnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ1RlbGVwb3J0IHRvIFNhbmR5IFNob3JlcyBhaXJmaWVsZC4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICd0cF9wYWxldG9iYXknLCBsYWJlbDogJ1BhbGV0byBCYXknLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ1RlbGVwb3J0IHRvIFBhbGV0byBCYXkgbm9ydGhlcm4gYmFuay4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICd0cF9tYXplYmFuaycsIGxhYmVsOiAnTWF6ZSBCYW5rIFRvd2VyJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdUZWxlcG9ydCB0byB0aGUgdG9wIGhlbGlwYWQgb2YgTWF6ZSBCYW5rIFRvd2VyLicgfQogICAgICAgICAgXQogICAgICAgIH0KICAgICAgXQogICAgfSwKICAgIHsKICAgICAgaWQ6ICdvbmxpbmUnLAogICAgICBsYWJlbDogJ09ubGluZScsCiAgICAgIGljb246ICdvbmxpbmUnLAogICAgICBkZXNjOiAnUGxheWVyIG1hbmFnZXIsIHN0cmVhbWVkIHBsYXllcnMgd2l0aGluIDUwMG0sIGF0dGFja3MgYW5kIHNwZWN0YXRpbmcuJywKICAgICAgc3VidGFiczogWwogICAgICAgIHsKICAgICAgICAgIGlkOiAncGxheWVycycsCiAgICAgICAgICBsYWJlbDogJ1BsYXllcnMnLAogICAgICAgICAgaXNQbGF5ZXJMaXN0OiB0cnVlLAogICAgICAgICAgaXRlbXM6IFtdCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICBpZDogJ2FjdGlvbnMnLAogICAgICAgICAgbGFiZWw6ICdBY3Rpb25zJywKICAgICAgICAgIGl0ZW1zOiBbCiAgICAgICAgICAgIHsgaXNIZWFkZXI6IHRydWUsIGxhYmVsOiAnUGxheWVyIEF0dGFja3MnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdvbmxpbmVfbXVsdGlfeWVldCcsIGxhYmVsOiAnTGF1bmNoIFBsYXllciAoWWVldCknLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ0ZsaW5ncyBzZWxlY3RlZCBwbGF5ZXIocykgdmVydGljYWxseSBpbnRvIHRoZSBza3kuJyB9LAogICAgICAgICAgICB7IGlkOiAnb25saW5lX211bHRpX3NsYXAnLCBsYWJlbDogJ1JhZ2RvbGwgU2xhcCcsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnUHVuY2hlcyBhbmQga25vY2tzIHNlbGVjdGVkIHBsYXllcihzKSBkb3duLicgfSwKICAgICAgICAgICAgeyBpZDogJ29ubGluZV9tdWx0aV9mcmVlemUnLCBsYWJlbDogJ0ZyZWV6ZSBQbGF5ZXInLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnRnJlZXplcyB0YXJnZXQgcGxheWVyKHMpIGZpcm1seSBpbiBwbGFjZS4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdvbmxpbmVfbXVsdGlfYnVybicsIGxhYmVsOiAnSWduaXRlIFBsYXllcicsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnU2V0cyB0YXJnZXQgcGxheWVyKHMpIG9uIGZpcmUuJyB9LAogICAgICAgICAgICB7IGlkOiAnb25saW5lX211bHRpX2V4cGxvZGUnLCBsYWJlbDogJ0V4cGxvc2lvbicsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnQ3JlYXRlcyBhbiBleHBsb3Npb24gYmVuZWF0aCB0YXJnZXQgcGxheWVyKHMpLicgfSwKICAgICAgICAgICAgeyBpZDogJ29yYml0YWxfY2Fubm9uJywgbGFiZWw6ICdPcmJpdGFsIENhbm5vbicsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnU3RyaWtlcyB0YXJnZXQgd2l0aCBhIGhlYXZ5IG9yYml0YWwgZXhwbG9zaW9uLicgfSwKICAgICAgICAgICAgeyBpZDogJ29ubGluZV9tdWx0aV9jYWdlJywgbGFiZWw6ICdCYXJyaWVyIENhZ2UnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ1RyYXBzIHRhcmdldCBpbnNpZGUgY29uY3JldGUgY29uc3RydWN0aW9uIGJhcnJpZXJzLicgfSwKICAgICAgICAgICAgeyBpZDogJ3RvaWxldF9oZWFkJywgbGFiZWw6ICdBdHRhY2ggVG9pbGV0IFByb3AnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ0F0dGFjaGVzIGEgcG9yY2VsYWluIHRvaWxldCBvbnRvIHRoZSB0YXJnZXQgcGxheWVyIGhlYWQuJyB9LAogICAgICAgICAgICB7IGlkOiAncmFtX3RhcmdldCcsIGxhYmVsOiAnUmFtIFBsYXllcicsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnU3Bhd25zIGFuIEluc3VyZ2VudCB0aGF0IHJhbXMgaW50byB0aGUgdGFyZ2V0LicgfSwKICAgICAgICAgICAgeyBpZDogJ2Rpc2FybV90YXJnZXQnLCBsYWJlbDogJ0Rpc2FybSBQbGF5ZXInLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ1JlbW92ZXMgYWxsIHdlYXBvbnMgZnJvbSB0aGUgdGFyZ2V0LicgfSwKICAgICAgICAgICAgeyBpc0hlYWRlcjogdHJ1ZSwgbGFiZWw6ICdUZWxlcG9ydCcgfSwKICAgICAgICAgICAgeyBpZDogJ29ubGluZV90cF90bycsIGxhYmVsOiAnVGVsZXBvcnQgVG8gUGxheWVyJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdUZWxlcG9ydHMgeW91IGRpcmVjdGx5IG5leHQgdG8gdGhlIHNlbGVjdGVkIHRhcmdldC4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdvbmxpbmVfdHBfaGVyZScsIGxhYmVsOiAnQnJpbmcgUGxheWVyIEhlcmUnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ0JyaW5ncyB0YXJnZXQgcGxheWVyKHMpIGRpcmVjdGx5IHRvIHlvdXIgcG9zaXRpb24uJyB9LAogICAgICAgICAgICB7IGlkOiAnb25saW5lX211bHRpX2hlYWwnLCBsYWJlbDogJ0hlYWwgUGxheWVyJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdSZWZpbGxzIGhlYWx0aCBhbmQgcmVzdG9yZXMgYXJtb3Igb2Ygc2VsZWN0ZWQgcGxheWVyKHMpLicgfQogICAgICAgICAgXQogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgaWQ6ICd2ZWhpY2xlJywKICAgICAgICAgIGxhYmVsOiAnVmVoaWNsZScsCiAgICAgICAgICBpdGVtczogWwogICAgICAgICAgICB7IGlzSGVhZGVyOiB0cnVlLCBsYWJlbDogJ1RhcmdldCBJbi1WZWhpY2xlIENvbnRyb2xzJyB9LAogICAgICAgICAgICB7IGlkOiAnZWplY3RfdGFyZ2V0JywgbGFiZWw6ICdFamVjdCBGcm9tIFZlaGljbGUnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ0ZvcmNlcyB0YXJnZXQgb3V0IG9mIHRoZWlyIHZlaGljbGUgaW1tZWRpYXRlbHkuJyB9LAogICAgICAgICAgICB7IGlkOiAncm9ja2V0X2NhcicsIGxhYmVsOiAnTGF1bmNoIENhciAoUm9ja2V0KScsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnTGF1bmNoZXMgdGFyZ2V0IHZlaGljbGUgdmVydGljYWxseSBpbnRvIHRoZSBhdG1vc3BoZXJlLicgfSwKICAgICAgICAgICAgeyBpZDogJ2V4cGxvZGVfdGFyZ2V0X3ZlaCcsIGxhYmVsOiAnRXhwbG9kZSBWZWhpY2xlJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdEZXRvbmF0ZXMgdGhlIHZlaGljbGUgdGFyZ2V0IGlzIGN1cnJlbnRseSBkcml2aW5nLicgfSwKICAgICAgICAgICAgeyBpZDogJ2RlbGV0ZV90YXJnZXRfdmVoJywgbGFiZWw6ICdEZWxldGUgVGFyZ2V0IFZlaGljbGUnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ0RlbGV0ZXMgdGhlIHZlaGljbGUgdGFyZ2V0IGlzIGRyaXZpbmcgaW5zdGFudGx5LicgfSwKICAgICAgICAgICAgeyBpZDogJ2tpbGxfdGFyZ2V0X2VuZ2luZScsIGxhYmVsOiAnS2lsbCBFbmdpbmUnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ1N0YWxscyBhbmQgd3JlY2tzIHRhcmdldCB2ZWhpY2xlIGVuZ2luZSBjb21wbGV0ZWx5LicgfSwKICAgICAgICAgICAgeyBpZDogJ2J1cnN0X3RhcmdldF90aXJlcycsIGxhYmVsOiAnQnVyc3QgQWxsIFRpcmVzJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdQdW5jdHVyZXMgYW5kIHNocmVkcyBldmVyeSB0aXJlIG9uIHRoZSB0YXJnZXQgdmVoaWNsZS4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdmcmVlemVfdGFyZ2V0X3ZlaCcsIGxhYmVsOiAnRnJlZXplIFZlaGljbGUnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ0FuY2hvcnMgdGFyZ2V0IHZlaGljbGUgZmlybWx5IGluIHBsYWNlIHNvIGl0IGNhbm5vdCBtb3ZlLicgfSwKICAgICAgICAgICAgeyBpZDogJ2Jvb3N0X3RhcmdldF92ZWgnLCBsYWJlbDogJ1JvY2tldCBCb29zdCAoMTUwIGttL2gpJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdTbGluZ3MgdGFyZ2V0IHZlaGljbGUgZm9yd2FyZCBhdCBleHRyZW1lIHZlbG9jaXR5LicgfSwKICAgICAgICAgICAgeyBpZDogJ3NwaW5fdGFyZ2V0X3ZlaCcsIGxhYmVsOiAnU3BpbiBPdXQgKFRvcm5hZG8pJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdTcGlucyB0YXJnZXQgdmVoaWNsZSBvdXQgb2YgY29udHJvbCB3aXRoIGFuZ3VsYXIgdmVsb2NpdHkuJyB9LAogICAgICAgICAgICB7IGlkOiAnbG9ja190YXJnZXRfdmVoJywgbGFiZWw6ICdMb2NrIFZlaGljbGUgRG9vcnMnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ0RlYWRib2x0cyB0YXJnZXQgZG9vcnMgc28gdGhleSBjYW5ub3QgZXhpdCB0aGUgdmVoaWNsZS4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdyZXBhaXJfdGFyZ2V0X3ZlaCcsIGxhYmVsOiAnUmVwYWlyIFRhcmdldCBWZWhpY2xlJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdJbnN0YW50bHkgZml4ZXMgYm9keSBkYW1hZ2UgYW5kIHJlc3RvcmVzIGVuZ2luZSBoZWFsdGggdG8gMTAwMC4nIH0KICAgICAgICAgIF0KICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgIGlkOiAnbG9vcHMnLAogICAgICAgICAgbGFiZWw6ICdMb29wcycsCiAgICAgICAgICBpdGVtczogWwogICAgICAgICAgICB7IGlzSGVhZGVyOiB0cnVlLCBsYWJlbDogJ0NvbnRpbnVvdXMgQXR0YWNrcycgfSwKICAgICAgICAgICAgeyBpZDogJ2xvb3BfcHVuY2gnLCBsYWJlbDogJ1B1bmNoIExvb3AnLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnUmVwZWF0ZWRseSBrbm9ja3MgdGFyZ2V0IGRvd24gZXZlcnkgMTAwbXMuJyB9LAogICAgICAgICAgICB7IGlkOiAnbG9vcF90YXplJywgbGFiZWw6ICdUYXplIExvb3AnLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnUmVwZWF0ZWRseSBhcHBsaWVzIHRhc2VyIHJhZ2RvbGwgZWZmZWN0LicgfSwKICAgICAgICAgICAgeyBpZDogJ2xvb3BfYnVybicsIGxhYmVsOiAnQnVybiBMb29wJywgdHlwZTogJ3RvZ2dsZScsIHN0YXRlOiBmYWxzZSwgZGVzYzogJ0NvbnRpbnVhbGx5IGtlZXBzIHRhcmdldCBlbmd1bGZlZCBpbiBmaXJlLicgfQogICAgICAgICAgXQogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgaWQ6ICdzcGVjdGF0ZScsCiAgICAgICAgICBsYWJlbDogJ1NwZWN0YXRlJywKICAgICAgICAgIGl0ZW1zOiBbCiAgICAgICAgICAgIHsgaWQ6ICdvbmxpbmVfc3BlY3RhdGUnLCBsYWJlbDogJ1RvZ2dsZSBTcGVjdGF0b3IgVmlldycsIHR5cGU6ICd0b2dnbGUnLCBzdGF0ZTogZmFsc2UsIGRlc2M6ICdMaXZlIGNhbWVyYSB2aWV3IHNtb290aGx5IHRyYWNraW5nIHRoZSBzZWxlY3RlZCB0YXJnZXQuJyB9CiAgICAgICAgICBdCiAgICAgICAgfQogICAgICBdCiAgICB9LAogICAgewogICAgICBpZDogJ3ZlaGljbGUnLAogICAgICBsYWJlbDogJ1ZlaGljbGUnLAogICAgICBpY29uOiAndmVoaWNsZScsCiAgICAgIGRlc2M6ICdTcGF3biB2ZWhpY2xlcywgdHVuZSBwZXJmb3JtYW5jZSwgcmVwYWlyIGFuZCBzcGVjaWFsIGRyaXZpbmcgbW9kZXMuJywKICAgICAgc3VidGFiczogWwogICAgICAgIHsKICAgICAgICAgIGlkOiAnc3Bhd25lcicsCiAgICAgICAgICBsYWJlbDogJ1NwYXduZXInLAogICAgICAgICAgaXRlbXM6IFsKICAgICAgICAgICAgeyBpc0hlYWRlcjogdHJ1ZSwgbGFiZWw6ICdQb3B1bGFyIFN1cGVyY2FycycgfSwKICAgICAgICAgICAgeyBpZDogJ3NwYXduX2FkZGVyJywgbGFiZWw6ICdBZGRlcicsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnU3Bhd24gVHJ1ZmZhZGUgQWRkZXIgc3VwZXJjYXIuJyB9LAogICAgICAgICAgICB7IGlkOiAnc3Bhd25fc3VsdGFuJywgbGFiZWw6ICdTdWx0YW4gUlMnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ1NwYXduIEthcmluIFN1bHRhbiBSUyByYWxseSBjYXIuJyB9LAogICAgICAgICAgICB7IGlkOiAnc3Bhd25fa3JpZWdlcicsIGxhYmVsOiAnQmVuZWZhY3RvciBLcmllZ2VyJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdTcGF3biBCZW5lZmFjdG9yIEtyaWVnZXIgQVdEIGh5cGVyY2FyLicgfSwKICAgICAgICAgICAgeyBpZDogJ3NwYXduX3plbnRvcm5vJywgbGFiZWw6ICdQZWdhc3NpIFplbnRvcm5vJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdTcGF3biBQZWdhc3NpIFplbnRvcm5vIGV4b3RpYyBjYXIuJyB9LAogICAgICAgICAgICB7IGlkOiAnc3Bhd25fdDIwJywgbGFiZWw6ICdQcm9nZW4gVDIwJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdTcGF3biBQcm9nZW4gVDIwIHN1cGVyY2FyLicgfSwKICAgICAgICAgICAgeyBpc0hlYWRlcjogdHJ1ZSwgbGFiZWw6ICdPZmZyb2FkICYgQmlrZXMnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdzcGF3bl9rYW1hY2hvJywgbGFiZWw6ICdDYW5pcyBLYW1hY2hvIDR4NCcsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnU3Bhd24gQ2FuaXMgS2FtYWNobyBoZWF2eSBvZmYtcm9hZCB0cnVjay4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdzcGF3bl9zYW5jaGV6JywgbGFiZWw6ICdTYW5jaGV6IERpcnQgQmlrZScsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnU3Bhd24gTWFpYmF0c3UgU2FuY2hleiBvZmZyb2FkIG1vdG9yY3ljbGUuJyB9LAogICAgICAgICAgICB7IGlkOiAnc3Bhd25fb3BwcmVzc29yMicsIGxhYmVsOiAnT3BwcmVzc29yIE1LMicsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnU3Bhd24gUGVnYXNzaSBPcHByZXNzb3IgTUsyIGhvdmVyYmlrZS4nIH0sCiAgICAgICAgICAgIHsgaXNIZWFkZXI6IHRydWUsIGxhYmVsOiAnQ3VzdG9tJyB9LAogICAgICAgICAgICB7IGlkOiAnc3Bhd25fdmVoX2lucHV0JywgbGFiZWw6ICdTcGF3biBieSBOYW1lJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdFbnRlciBhbnkgdmVoaWNsZSBzcGF3biBtb2RlbCBuYW1lLicgfQogICAgICAgICAgXQogICAgICAgIH0sCiAgICAgICAgewogICAgICAgICAgaWQ6ICd1cGdyYWRlcycsCiAgICAgICAgICBsYWJlbDogJ1VwZ3JhZGVzJywKICAgICAgICAgIGl0ZW1zOiBbCiAgICAgICAgICAgIHsgaWQ6ICdyZXBhaXJfdmVoaWNsZScsIGxhYmVsOiAnUmVwYWlyICYgQ2xlYW4nLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ0luc3RhbnRseSByZXN0b3JlcyB2ZWhpY2xlIGhlYWx0aCwgZW5naW5lIGFuZCBib2R5LicgfSwKICAgICAgICAgICAgeyBpZDogJ21heF90dW5lX3ZlaCcsIGxhYmVsOiAnTWF4IFBlcmZvcm1hbmNlIFR1bmUnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ0FwcGxpZXMgbWF4aW11bSBlbmdpbmUsIHRyYW5zbWlzc2lvbiwgdHVyYm8gYW5kIGJyYWtlcy4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdyYWluYm93X2NhcicsIGxhYmVsOiAnUmFpbmJvdyBSR0IgUGFpbnQnLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnQ3ljbGVzIHZlaGljbGUgcGFpbnQgdGhyb3VnaCBSR0Igc3BlY3RydW0uJyB9CiAgICAgICAgICBdCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICBpZDogJ29wdGlvbnMnLAogICAgICAgICAgbGFiZWw6ICdPcHRpb25zJywKICAgICAgICAgIGl0ZW1zOiBbCiAgICAgICAgICAgIHsgaWQ6ICd2ZWhfZ29kbW9kZScsIGxhYmVsOiAnVmVoaWNsZSBHb2Rtb2RlJywgdHlwZTogJ3RvZ2dsZScsIHN0YXRlOiBmYWxzZSwgZGVzYzogJ01ha2VzIHlvdXIgdmVoaWNsZSBpbW11bmUgdG8gZXhwbG9zaW9ucyBhbmQgY3Jhc2hlcy4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdzcGVlZF9ib29zdCcsIGxhYmVsOiAnSG9ybiBTcGVlZCBCb29zdCcsIHR5cGU6ICd0b2dnbGUnLCBzdGF0ZTogZmFsc2UsIGRlc2M6ICdIb2xkIGhvcm4gKEUpIHRvIHJvY2tldCBhY2NlbGVyYXRlIGZvcndhcmQuJyB9LAogICAgICAgICAgICB7IGlkOiAnZHJpdmVfb25fd2F0ZXInLCBsYWJlbDogJ0RyaXZlIE9uIFdhdGVyJywgdHlwZTogJ3RvZ2dsZScsIHN0YXRlOiBmYWxzZSwgZGVzYzogJ0RyaXZlIHlvdXIgdmVoaWNsZSBkaXJlY3RseSBhY3Jvc3Mgd2F0ZXIgc3VyZmFjZXMuJyB9LAogICAgICAgICAgICB7IGlkOiAnY2FyX2p1bXAnLCBsYWJlbDogJ1ZlaGljbGUgSnVtcCcsIHR5cGU6ICd0b2dnbGUnLCBzdGF0ZTogZmFsc2UsIGRlc2M6ICdQcmVzcyBTcGFjZWJhciB0byBqdW1wIG92ZXIgb2JzdGFjbGVzLicgfSwKICAgICAgICAgICAgeyBpZDogJ2ludmlzaWJsZV9jYXInLCBsYWJlbDogJ0ludmlzaWJsZSBWZWhpY2xlJywgdHlwZTogJ3RvZ2dsZScsIHN0YXRlOiBmYWxzZSwgZGVzYzogJ1JlbmRlcnMgeW91ciB2ZWhpY2xlIGNvbXBsZXRlbHkgaW52aXNpYmxlLicgfSwKICAgICAgICAgICAgeyBpZDogJ2RlbGV0ZV92ZWgnLCBsYWJlbDogJ0RlbGV0ZSBWZWhpY2xlJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdJbnN0YW50bHkgZGVsZXRlcyB5b3VyIGN1cnJlbnQgdmVoaWNsZS4nIH0KICAgICAgICAgIF0KICAgICAgICB9CiAgICAgIF0KICAgIH0sCiAgICB7CiAgICAgIGlkOiAnY29tYmF0JywKICAgICAgbGFiZWw6ICdDb21iYXQnLAogICAgICBpY29uOiAnY29tYmF0JywKICAgICAgZGVzYzogJ1dlYXBvbnMgc3Bhd25lciwgaW5maW5pdGUgYW1tdW5pdGlvbiwgbm8gcmVjb2lsIGFuZCBzaWxlbnQgYWltLicsCiAgICAgIHN1YnRhYnM6IFsKICAgICAgICB7CiAgICAgICAgICBpZDogJ3dlYXBvbnMnLAogICAgICAgICAgbGFiZWw6ICdXZWFwb25zJywKICAgICAgICAgIGl0ZW1zOiBbCiAgICAgICAgICAgIHsgaWQ6ICdnaXZlX2FsbF93ZWFwb25zJywgbGFiZWw6ICdHaXZlIEFsbCBTdGFuZGFyZCBXZWFwb25zJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdHaXZlcyBmdWxsIGxvYWRvdXQgb2Ygc3RhbmRhcmQgR1RBIHdlYXBvbnMuJyB9LAogICAgICAgICAgICB7IGlkOiAnZ2l2ZV9hbW1vJywgbGFiZWw6ICdSZWZpbGwgQW1tbycsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnUmVmaWxscyBhbW11bml0aW9uIGZvciB5b3VyIGN1cnJlbnQgd2VhcG9uLicgfSwKICAgICAgICAgICAgeyBpc0hlYWRlcjogdHJ1ZSwgbGFiZWw6ICdRdWljayBTcGF3bicgfSwKICAgICAgICAgICAgeyBpZDogJ3dlcF9jb21iYXRtZycsIGxhYmVsOiAnQ29tYmF0IE1HJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdTcGF3biBDb21iYXQgTUcgbWFjaGluZSBndW4uJyB9LAogICAgICAgICAgICB7IGlkOiAnd2VwX2NhcmJpbmUnLCBsYWJlbDogJ1NwZWNpYWwgQ2FyYmluZScsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnU3Bhd24gU3BlY2lhbCBDYXJiaW5lIGFzc2F1bHQgcmlmbGUuJyB9LAogICAgICAgICAgICB7IGlkOiAnd2VwX2hlYXZ5c25pcGVyJywgbGFiZWw6ICdIZWF2eSBTbmlwZXInLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ1NwYXduIEhlYXZ5IFNuaXBlciByaWZsZS4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICd3ZXBfcmV2b2x2ZXInLCBsYWJlbDogJ0hlYXZ5IFJldm9sdmVyJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdTcGF3biBIZWF2eSBSZXZvbHZlci4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICd3ZXBfcnBnJywgbGFiZWw6ICdSUEcgTGF1bmNoZXInLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ1NwYXduIFJvY2tldCBQcm9wZWxsZWQgR3JlbmFkZSBsYXVuY2hlci4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdzcGF3bl9jdXN0b21fd2VhcG9uJywgbGFiZWw6ICdTcGF3biBieSBOYW1lJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdFbnRlciBhbnkgd2VhcG9uIG1vZGVsIGhhc2ggbmFtZS4nIH0KICAgICAgICAgIF0KICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgIGlkOiAnbW9kaWZpZXJzJywKICAgICAgICAgIGxhYmVsOiAnTW9kaWZpZXJzJywKICAgICAgICAgIGl0ZW1zOiBbCiAgICAgICAgICAgIHsgaWQ6ICdpbmZpbml0ZV9hbW1vJywgbGFiZWw6ICdJbmZpbml0ZSBBbW1vJywgdHlwZTogJ3RvZ2dsZScsIHN0YXRlOiBmYWxzZSwgZGVzYzogJ05ldmVyIHJ1biBvdXQgb2YgYnVsbGV0cyBhbmQgZGlzYWJsZSByZWxvYWRpbmcuJyB9LAogICAgICAgICAgICB7IGlkOiAnbm9fcmVjb2lsJywgbGFiZWw6ICdObyBSZWNvaWwnLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnQ29tcGxldGVseSBlbGltaW5hdGVzIHdlYXBvbiBraWNrIGFuZCByZWNvaWwuJyB9LAogICAgICAgICAgICB7IGlkOiAnbm9fc3ByZWFkJywgbGFiZWw6ICdObyBTcHJlYWQnLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnQWxsIGJ1bGxldHMgZmlyZSBwZXJmZWN0bHkgc3RyYWlnaHQgd2l0aG91dCBzcHJlYWQuJyB9LAogICAgICAgICAgICB7IGlkOiAncmFwaWRfZmlyZScsIGxhYmVsOiAnUmFwaWQgRmlyZScsIHR5cGU6ICd0b2dnbGUnLCBzdGF0ZTogZmFsc2UsIGRlc2M6ICdTaWduaWZpY2FudGx5IGluY3JlYXNlcyB3ZWFwb24gZmlyaW5nIHJhdGUuJyB9LAogICAgICAgICAgICB7IGlkOiAnZXhwbG9zaXZlX2FtbW8nLCBsYWJlbDogJ0V4cGxvc2l2ZSBBbW1vJywgdHlwZTogJ3RvZ2dsZScsIHN0YXRlOiBmYWxzZSwgZGVzYzogJ0J1bGxldHMgZXhwbG9kZSBvbiBpbXBhY3Qgd2l0aCBzdXJmYWNlcyBhbmQgZW50aXRpZXMuJyB9LAogICAgICAgICAgICB7IGlkOiAnY2FyX2d1bicsIGxhYmVsOiAnQ2FyIEd1bicsIHR5cGU6ICd0b2dnbGUnLCBzdGF0ZTogZmFsc2UsIGRlc2M6ICdTaG9vdHMgaGlnaC12ZWxvY2l0eSBjYXJzIGluc3RlYWQgb2YgYnVsbGV0cy4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdkYW1hZ2VfYm9vc3QnLCBsYWJlbDogJ0RhbWFnZSBNdWx0aXBsaWVyICh4MiknLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnRG91YmxlcyBhbGwgYnVsbGV0IGRhbWFnZSBkZWFsdC4nIH0KICAgICAgICAgIF0KICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgIGlkOiAnYWltYm90JywKICAgICAgICAgIGxhYmVsOiAnQWltYm90JywKICAgICAgICAgIGl0ZW1zOiBbCiAgICAgICAgICAgIHsgaWQ6ICdzaWxlbnRfYWltJywgbGFiZWw6ICdTaWxlbnQgQWltJywgdHlwZTogJ3RvZ2dsZScsIHN0YXRlOiBmYWxzZSwgZGVzYzogJ1JlZGlyZWN0cyBwcm9qZWN0aWxlIHRyYWplY3RvcmllcyB0b3dhcmRzIG5lYXJlc3QgdGFyZ2V0IGhlYWQuJyB9LAogICAgICAgICAgICB7IGlkOiAndHJpZ2dlcmJvdCcsIGxhYmVsOiAnVHJpZ2dlcmJvdCcsIHR5cGU6ICd0b2dnbGUnLCBzdGF0ZTogZmFsc2UsIGRlc2M6ICdBdXRvbWF0aWNhbGx5IGZpcmVzIHdoZW4gYWltaW5nIGRpcmVjdGx5IGF0IGFuIGVuZW15LicgfQogICAgICAgICAgXQogICAgICAgIH0KICAgICAgXQogICAgfSwKICAgIHsKICAgICAgaWQ6ICd2aXN1YWxzJywKICAgICAgbGFiZWw6ICdWaXN1YWxzJywKICAgICAgaWNvbjogJ3Zpc3VhbHMnLAogICAgICBkZXNjOiAnUGxheWVyIEVTUCBib3hlcywgc25hcGxpbmVzLCBkaXN0YW5jZSB0ZWxlbWV0cnkgYW5kIHZpc2lvbiBtb2Rlcy4nLAogICAgICBzdWJ0YWJzOiBbCiAgICAgICAgewogICAgICAgICAgaWQ6ICdlc3AnLAogICAgICAgICAgbGFiZWw6ICdFU1AnLAogICAgICAgICAgaXRlbXM6IFsKICAgICAgICAgICAgeyBpZDogJ2VzcF9ib3gnLCBsYWJlbDogJ0JveCBFU1AnLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnRHJhd3MgMkQgYm91bmRpbmcgYm94ZXMgYXJvdW5kIG5lYXJieSBwbGF5ZXJzLicgfSwKICAgICAgICAgICAgeyBpZDogJ2VzcF9uYW1lcycsIGxhYmVsOiAnUGxheWVyIE5hbWUgVGFncycsIHR5cGU6ICd0b2dnbGUnLCBzdGF0ZTogZmFsc2UsIGRlc2M6ICdEaXNwbGF5cyBwbGF5ZXIgbmFtZXMgYW5kIHNlcnZlciBJRHMuJyB9LAogICAgICAgICAgICB7IGlkOiAnZXNwX2hlYWx0aCcsIGxhYmVsOiAnSGVhbHRoICYgQXJtb3IgQmFycycsIHR5cGU6ICd0b2dnbGUnLCBzdGF0ZTogZmFsc2UsIGRlc2M6ICdEaXNwbGF5cyBoZWFsdGggYW5kIGFybW9yIGluZGljYXRvcnMgb3ZlciBwbGF5ZXJzLicgfSwKICAgICAgICAgICAgeyBpZDogJ2VzcF9kaXN0YW5jZScsIGxhYmVsOiAnRGlzdGFuY2UgSW5mb3JtYXRpb24nLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnU2hvd3MgZXhhY3QgZGlzdGFuY2UgaW4gbWV0ZXJzIHRvIGVhY2ggcGxheWVyLicgfSwKICAgICAgICAgICAgeyBpZDogJ2VzcF9zbmFwbGluZXMnLCBsYWJlbDogJ1NuYXBsaW5lcycsIHR5cGU6ICd0b2dnbGUnLCBzdGF0ZTogZmFsc2UsIGRlc2M6ICdEcmF3cyBsaW5lcyBmcm9tIHlvdXIgc2NyZWVuIHRvIGVhY2ggcGxheWVyLicgfSwKICAgICAgICAgICAgeyBpZDogJ2N1c3RvbV9jcm9zc2hhaXInLCBsYWJlbDogJ05lb24gQ3Jvc3NoYWlyJywgdHlwZTogJ3RvZ2dsZScsIHN0YXRlOiBmYWxzZSwgZGVzYzogJ0Rpc3BsYXlzIGEgY3VzdG9tIGxhc2VyIHNpZ2h0IGNyb3NzaGFpciBvbiBzY3JlZW4uJyB9CiAgICAgICAgICBdCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICBpZDogJ3Zpc2lvbicsCiAgICAgICAgICBsYWJlbDogJ1Zpc2lvbicsCiAgICAgICAgICBpdGVtczogWwogICAgICAgICAgICB7IGlkOiAnbmlnaHRfdmlzaW9uJywgbGFiZWw6ICdOaWdodCBWaXNpb24nLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnRW5hYmxlcyBlbmhhbmNlZCBsb3ctbGlnaHQgZ3JlZW4gbmlnaHQgdmlzaW9uLicgfSwKICAgICAgICAgICAgeyBpZDogJ3RoZXJtYWxfdmlzaW9uJywgbGFiZWw6ICdUaGVybWFsIFZpc2lvbicsIHR5cGU6ICd0b2dnbGUnLCBzdGF0ZTogZmFsc2UsIGRlc2M6ICdFbmFibGVzIGhlYXQgc2lnbmF0dXJlIHRoZXJtYWwgaW1hZ2luZy4nIH0KICAgICAgICAgIF0KICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgIGlkOiAnaHVkJywKICAgICAgICAgIGxhYmVsOiAnSFVEIE92ZXJsYXlzJywKICAgICAgICAgIGl0ZW1zOiBbCiAgICAgICAgICAgIHsgaWQ6ICdzcGVjdGF0b3JfaHVkJywgbGFiZWw6ICdTcGVjdGF0b3IgUmFkYXIgSFVEJywgdHlwZTogJ3RvZ2dsZScsIHN0YXRlOiBmYWxzZSwgZGVzYzogJ0Rpc3BsYXlzIGZsb2F0aW5nIHJhZGFyIHBhbmVsIGRldGVjdGluZyBhZG1pbnMgYW5kIHNwZWN0YXRvcnMuJyB9LAogICAgICAgICAgICB7IGlkOiAnYmluZHNfaHVkJywgbGFiZWw6ICdBY3RpdmUgS2V5YmluZHMgSFVEJywgdHlwZTogJ3RvZ2dsZScsIHN0YXRlOiBmYWxzZSwgZGVzYzogJ0Rpc3BsYXlzIGZsb2F0aW5nIHBhbmVsIGxpc3RpbmcgYWxsIGFjdGl2ZSBib3VuZCBob3RrZXlzLicgfQogICAgICAgICAgXQogICAgICAgIH0KICAgICAgXQogICAgfSwKICAgIHsKICAgICAgaWQ6ICd3b3JsZCcsCiAgICAgIGxhYmVsOiAnV29ybGQnLAogICAgICBpY29uOiAnd29ybGQnLAogICAgICBkZXNjOiAnRW52aXJvbm1lbnRhbCBjb250cm9scywgZW50aXR5IGNsZWFyaW5nLCBwcm9wIGFuZCBOUEMgc3Bhd25lcnMuJywKICAgICAgc3VidGFiczogWwogICAgICAgIHsKICAgICAgICAgIGlkOiAnZ2VuZXJhbCcsCiAgICAgICAgICBsYWJlbDogJ0dlbmVyYWwnLAogICAgICAgICAgaXRlbXM6IFsKICAgICAgICAgICAgeyBpZDogJ21vb25fZ3Jhdml0eScsIGxhYmVsOiAnTW9vbiBHcmF2aXR5JywgdHlwZTogJ3RvZ2dsZScsIHN0YXRlOiBmYWxzZSwgZGVzYzogJ1JlZHVjZXMgd29ybGQgZ3Jhdml0eSBmb3IgZmxvYXR5IHBoeXNpY3MuJyB9LAogICAgICAgICAgICB7IGlkOiAnZnJlZXplX3BlZHMnLCBsYWJlbDogJ0ZyZWV6ZSBBbGwgTmVhcmJ5IE5QQ3MnLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnRnJlZXplcyBhbGwgYW1iaWVudCBBSSBwZWRzIGFyb3VuZCB5b3UuJyB9LAogICAgICAgICAgICB7IGlkOiAnY2xlYXJfdmVoaWNsZXMnLCBsYWJlbDogJ0NsZWFyIEVtcHR5IFZlaGljbGVzJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdEZWxldGVzIGFiYW5kb25lZCBhbmQgdW5vY2N1cGllZCBjYXJzIG5lYXJieS4nIH0KICAgICAgICAgIF0KICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgIGlkOiAnc3Bhd25lcnMnLAogICAgICAgICAgbGFiZWw6ICdTcGF3bmVycycsCiAgICAgICAgICBpdGVtczogWwogICAgICAgICAgICB7IGlzSGVhZGVyOiB0cnVlLCBsYWJlbDogJ1F1aWNrIFBsYWNlcnMgKFNjcm9sbCAmIENsaWNrKScgfSwKICAgICAgICAgICAgeyBpZDogJ3BsYWNlcl9wcm9wcycsIGxhYmVsOiAnUXVpY2sgUHJvcCBQbGFjZXInLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ09wZW5zIGJvdHRvbS1jZW50ZXIgcXVpY2sgcGxhY2VyIGZvciBwcm9wcyAoU2Nyb2xsICYgTE1CIHBsYWNlKS4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdwbGFjZXJfcGVkcycsIGxhYmVsOiAnUXVpY2sgUGVkIFBsYWNlcicsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnT3BlbnMgYm90dG9tLWNlbnRlciBxdWljayBwbGFjZXIgZm9yIE5QQ3MgKFNjcm9sbCAmIExNQiBwbGFjZSkuJyB9LAogICAgICAgICAgICB7IGlkOiAncGxhY2VyX3ZlaHMnLCBsYWJlbDogJ1F1aWNrIFZlaGljbGUgUGxhY2VyJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdPcGVucyBib3R0b20tY2VudGVyIHF1aWNrIHBsYWNlciBmb3IgY2FycyAoU2Nyb2xsICYgTE1CIHBsYWNlKS4nIH0sCiAgICAgICAgICAgIHsgaXNIZWFkZXI6IHRydWUsIGxhYmVsOiAnUHJvcHMnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdwcm9wX2JhcnJpZXInLCBsYWJlbDogJ09yYW5nZSBXb3JrIEJhcnJpZXInLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ1NwYXducyBjb25jcmV0ZSBiYXJyaWVyIHByb3AuJyB9LAogICAgICAgICAgICB7IGlkOiAncHJvcF90b2lsZXQnLCBsYWJlbDogJ1BvcmNlbGFpbiBUb2lsZXQnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ1NwYXducyBhIHBvcmNlbGFpbiB0b2lsZXQgcHJvcC4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdzcGF3bl9wcm9wX2lucHV0JywgbGFiZWw6ICdTcGF3biBQcm9wIGJ5IE5hbWUnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ0VudGVyIGFueSBwcm9wIG9iamVjdCBtb2RlbCBuYW1lLicgfSwKICAgICAgICAgICAgeyBpc0hlYWRlcjogdHJ1ZSwgbGFiZWw6ICdOUENzJyB9LAogICAgICAgICAgICB7IGlkOiAncGVkX3N3YXQnLCBsYWJlbDogJ1NXQVQgT2ZmaWNlcicsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnU3Bhd25zIGEgdGFjdGljYWwgU1dBVCBOUEMuJyB9LAogICAgICAgICAgICB7IGlkOiAncGVkX3NrYXRlcicsIGxhYmVsOiAnU2thdGVyIFBlZCcsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnU3Bhd25zIGFuIGFtYmllbnQgc2thdGVyIHBlZC4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdzcGF3bl9wZWRfaW5wdXQnLCBsYWJlbDogJ1NwYXduIFBlZCBieSBOYW1lJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdFbnRlciBhbnkgcGVkIG1vZGVsIG5hbWUuJyB9CiAgICAgICAgICBdCiAgICAgICAgfQogICAgICBdCiAgICB9LAogICAgewogICAgICBpZDogJ3NldHRpbmdzJywKICAgICAgbGFiZWw6ICdTZXR0aW5ncycsCiAgICAgIGljb246ICdzZXR0aW5ncycsCiAgICAgIGRlc2M6ICdDb25maWd1cmUga2V5YmluZHMsIG1lbnUgcG9zaXRpb24sIGN1cnNvciBtb2RlIGFuZCB1bmxvYWRpbmcuJywKICAgICAgc3VidGFiczogWwogICAgICAgIHsKICAgICAgICAgIGlkOiAnaHVkX2xpc3RzJywKICAgICAgICAgIGxhYmVsOiAnSFVEIExpc3RzJywKICAgICAgICAgIGl0ZW1zOiBbCiAgICAgICAgICAgIHsgaXNIZWFkZXI6IHRydWUsIGxhYmVsOiAnRmxvYXRpbmcgTGlzdHMnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdiaW5kc19odWQnLCBsYWJlbDogJ0FjdGl2ZSBCaW5kcyBMaXN0JywgdHlwZTogJ3RvZ2dsZScsIHN0YXRlOiBmYWxzZSwgZGVzYzogJ1Nob3cgb3IgaGlkZSBmbG9hdGluZyBBY3RpdmUgS2V5YmluZHMgdGFibGUgd2lkZ2V0LicgfSwKICAgICAgICAgICAgeyBpZDogJ3NwZWN0YXRvcl9odWQnLCBsYWJlbDogJ1NwZWN0YXRvciBSYWRhciBMaXN0JywgdHlwZTogJ3RvZ2dsZScsIHN0YXRlOiBmYWxzZSwgZGVzYzogJ1Nob3cgb3IgaGlkZSBmbG9hdGluZyBTcGVjdGF0b3IgZGV0ZWN0aW9uIHJhZGFyIHdpZGdldC4nIH0sCiAgICAgICAgICAgIHsgaXNIZWFkZXI6IHRydWUsIGxhYmVsOiAnTGF5b3V0ICYgRHJhZ2dpbmcnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdkcmFnX3VpX21vZGUnLCBsYWJlbDogJ0RyYWcgJiBSZXNpemUgVUkgTW9kZScsIHR5cGU6ICd0b2dnbGUnLCBzdGF0ZTogZmFsc2UsIGRlc2M6ICdFbmFibGUgbW91c2UgZHJhZ2dpbmcgYW5kIGNvcm5lciByZXNpemluZyBmb3IgYWxsIEhVRCBwYW5lbHMuJyB9LAogICAgICAgICAgICB7IGlkOiAncmVzZXRfaHVkX2xheW91dCcsIGxhYmVsOiAnUmVzZXQgSFVEIFBvc2l0aW9ucyAmIFNpemVzJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdSZXN0b3JlcyBkZWZhdWx0IHNjcmVlbiBjb29yZGluYXRlcyBhbmQgZGltZW5zaW9ucyBmb3IgYWxsIEhVRCBwYW5lbHMuJyB9CiAgICAgICAgICBdCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICBpZDogJ2NvbmZpZ3MnLAogICAgICAgICAgbGFiZWw6ICdDb25maWdzICYgQ2xvdWQnLAogICAgICAgICAgaXRlbXM6IFsKICAgICAgICAgICAgeyBpc0hlYWRlcjogdHJ1ZSwgbGFiZWw6ICdDbG91ZCBQcm9maWxlcycgfSwKICAgICAgICAgICAgeyBpZDogJ2NmZ19zYXZlJywgbGFiZWw6ICdTYXZlIENvbmZpZyBQcm9maWxlIChPdmVyd3JpdGUpJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdTYXZlcyBhY3RpdmUgdG9nZ2xlcywgYmluZHMgJiBIVUQgbG9jYXRpb25zIHRvIHNlcnZlci4gT3ZlcndyaXRlcyBpZiBleGlzdHMuJyB9LAogICAgICAgICAgICB7IGlkOiAnY2ZnX2xvYWQnLCBsYWJlbDogJ0xvYWQgQ29uZmlnIFByb2ZpbGUnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ1Jlc3RvcmVzIGZlYXR1cmVzLCBiaW5kcywgSFVEIHZpc2liaWxpdHkgYW5kIHBvc2l0aW9ucyBmcm9tIGNsb3VkLicgfSwKICAgICAgICAgICAgeyBpZDogJ2NmZ19kZWxldGUnLCBsYWJlbDogJ0RlbGV0ZSBDb25maWcgUHJvZmlsZScsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnUGVybWFuZW50bHkgcmVtb3ZlcyBhIHByb2ZpbGUgZnJvbSBjbG91ZCBhbmQgbG9jYWwgc3RvcmFnZS4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdjZmdfc3luYycsIGxhYmVsOiAnU3luYyBmcm9tIENsb3VkIFNlcnZlcicsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnUHVsbHMgYW5kIGNhY2hlcyBhbGwgY2xvdWQgcHJvZmlsZXMgZnJvbSB3dHJtZW51LnRhdHJ1cy5vcmcuJyB9CiAgICAgICAgICBdCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICBpZDogJ2JpbmRzJywKICAgICAgICAgIGxhYmVsOiAnQmluZHMnLAogICAgICAgICAgaXRlbXM6IFsKICAgICAgICAgICAgeyBpc0hlYWRlcjogdHJ1ZSwgbGFiZWw6ICdNZW51IEhvdGtleXMnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdiaW5kX2luZm9fZjknLCBsYWJlbDogJ01lbnUgVG9nZ2xlOiBbIEY5IF0nLCB0eXBlOiAnaW5mbycsIHZhbHVlOiAnQWN0aXZlJywgZGVzYzogJ0RlZmF1bHQgbWVudSB0b2dnbGUga2V5IGlzIEY5IChvciBjb25zb2xlIC93dHJtZW51KS4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdyZWJpbmRfa2V5JywgbGFiZWw6ICdDaGFuZ2UgTWVudSBUb2dnbGUgS2V5JywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdSZWJpbmQgbWVudSB0b2dnbGUga2V5IHRvIGFueSBrZXlib2FyZCBrZXkuJyB9LAogICAgICAgICAgICB7IGlzSGVhZGVyOiB0cnVlLCBsYWJlbDogJ0ZlYXR1cmUgU2hvcnRjdXRzJyB9LAogICAgICAgICAgICB7IGlkOiAnYmluZF9pbmZvX2FsdCcsIGxhYmVsOiAnTW91c2UgQ3Vyc29yOiBbIExFRlQgQUxUIF0nLCB0eXBlOiAnaW5mbycsIHZhbHVlOiAnVG9nZ2xlJywgZGVzYzogJ1ByZXNzIExlZnQgQWx0IGFueXRpbWUgdG8gdG9nZ2xlIGluLWdhbWUgbW91c2UgY3Vyc29yLicgfSwKICAgICAgICAgICAgeyBpZDogJ2JpbmRfaW5mb19ub2NsaXAnLCBsYWJlbDogJ05vY2xpcCBGbGlnaHQ6IFsgV0FTRCArIFNoaWZ0IF0nLCB0eXBlOiAnaW5mbycsIHZhbHVlOiAnRmx5JywgZGVzYzogJ0NvbnRyb2xzIGZvciBOb2NsaXAgYW5kIEZyZWVjYW0gbW9kZXMuJyB9CiAgICAgICAgICBdCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICBpZDogJ21lbnUnLAogICAgICAgICAgbGFiZWw6ICdNZW51JywKICAgICAgICAgIGl0ZW1zOiBbCiAgICAgICAgICAgIHsgaWQ6ICdjeWNsZV9wb3NpdGlvbicsIGxhYmVsOiAnTWVudSBQb3NpdGlvbicsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnQ3ljbGUgcG9zaXRpb24gYmV0d2VlbiBMZWZ0LCBSaWdodCwgYW5kIENlbnRlci4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICd0b2dnbGVfY3Vyc29yJywgbGFiZWw6ICdUb2dnbGUgTW91c2UgQ3Vyc29yIChBbHQpJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdFbmFibGUgb3IgZGlzYWJsZSBpbi1nYW1lIGludGVyYWN0aXZlIGN1cnNvci4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICd1bmxvYWRfbWVudScsIGxhYmVsOiAnVW5sb2FkIFdUUiBNZW51JywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdDb21wbGV0ZWx5IHVubG9hZHMgYW5kIGNsb3NlcyBXVFIgTWVudS4nIH0KICAgICAgICAgIF0KICAgICAgICB9CiAgICAgIF0KICAgIH0sCiAgICB7CiAgICAgIGlkOiAnYnlwYXNzZXMnLAogICAgICBsYWJlbDogJ0J5cGFzc2VzJywKICAgICAgaWNvbjogJ2J5cGFzc2VzJywKICAgICAgZGVzYzogJ0FudGljaGVhdCBjb250cm9scywgaGVhcnRiZWF0IHNwb29maW5nIGFuZCBmcmFtZXdvcmsgdXRpbGl0aWVzLicsCiAgICAgIHN1YnRhYnM6IFsKICAgICAgICB7CiAgICAgICAgICBpZDogJ2FudGljaGVhdCcsCiAgICAgICAgICBsYWJlbDogJ0FudGljaGVhdCcsCiAgICAgICAgICBpdGVtczogWwogICAgICAgICAgICB7IGlkOiAnY2hlY2tfYW50aWNoZWF0cycsIGxhYmVsOiAnU2NhbiBBY3RpdmUgQW50aWNoZWF0cycsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnRGVlcCBzY2FuIHNlcnZlciAmIGNsaWVudCByZXNvdXJjZXMgdG8gZGV0ZWN0IEZpdmVHdWFyZCwgV2F2ZVNoaWVsZCwgUGhvZW5peCwgZXRjLicgfSwKICAgICAgICAgICAgeyBpZDogJ3N0b3BfYW50aWNoZWF0JywgbGFiZWw6ICdTdG9wIEtub3duIEFudGljaGVhdHMnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ1N0b3BzIGNsaWVudCByZXNvdXJjZXMgb2Yga25vd24gYW50aWNoZWF0cy4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdmZ19ieXBhc3MnLCBsYWJlbDogJ0ZpdmVHdWFyZCBPbmUtQ2xpY2sgQnlwYXNzJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdTdG9wcyBjbGllbnQgcmVzb3VyY2UsIGhvb2tzIG5hdGl2ZXMsIGFuZCBlbmFibGVzIDEwcyBoZWFydGJlYXQuJyB9LAogICAgICAgICAgICB7IGlkOiAnZmdfaGVhcnRiZWF0JywgbGFiZWw6ICdGRyBIZWFydGJlYXQgU3Bvb2YgKDEwcyknLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnU2VuZHMgcGVyaW9kaWMgbGl2ZW5lc3MgaGVhcnRiZWF0IHBpbmcgdG8gc2VydmVyLicgfSwKICAgICAgICAgICAgeyBpZDogJ2ZnX3N0b3AnLCBsYWJlbDogJ1N0b3AgRml2ZUd1YXJkIChqcm5rX3ZrKScsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnU3RvcHMgdGhlIGNsaWVudCBGaXZlR3VhcmQgcmVzb3VyY2UuJyB9LAogICAgICAgICAgICB7IGlkOiAnZHBfYnlwYXNzJywgbGFiZWw6ICdEcm9wUGxheWVyIE9uZS1DbGljayBCeXBhc3MnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ1N0b3BzIGNsaWVudCBEcm9wUGxheWVyIHJlc291cmNlICsgc3Bvb2ZzIDEwcyBoZWFydGJlYXQuJyB9LAogICAgICAgICAgICB7IGlkOiAnZHBfaGVhcnRiZWF0JywgbGFiZWw6ICdEUCBIZWFydGJlYXQgU3Bvb2YgKDEwcyknLCB0eXBlOiAndG9nZ2xlJywgc3RhdGU6IGZhbHNlLCBkZXNjOiAnU2VuZHMgcGVyaW9kaWMgRHJvcFBsYXllciBsaXZlbmVzcyBoZWFydGJlYXQgdG8gc2VydmVyLicgfSwKICAgICAgICAgICAgeyBpZDogJ2RwX3N0b3AnLCBsYWJlbDogJ1N0b3AgRHJvcFBsYXllcicsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnU3RvcHMgdGhlIGNsaWVudCBEcm9wUGxheWVyIHJlc291cmNlLicgfSwKICAgICAgICAgICAgeyBpZDogJ3NhZmVfbW9kZScsIGxhYmVsOiAnQW50aS1EZXRlY3QgU2FmZSBNb2RlJywgdHlwZTogJ3RvZ2dsZScsIHN0YXRlOiBmYWxzZSwgZGVzYzogJ0hvb2tzIG5hdGl2ZXMgdG8gbWFzayBlbnRpdHkgY3JlYXRpb24gZnJvbSBhbnRpY2hlYXQgbG9ncy4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdjbGVhcl9hdHRhY2hlZCcsIGxhYmVsOiAnQ2xlYW4gQXR0YWNoZWQgT2JqZWN0cycsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnUmVtb3ZlcyBhbnkgdHJvbGwgb2JqZWN0cyBhdHRhY2hlZCB0byB5b3VyIHBlZC4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdlc3hfcmV2aXZlJywgbGFiZWw6ICdFU1ggVHJpZ2dlciBSZXZpdmUnLCB0eXBlOiAnYWN0aW9uJywgZGVzYzogJ0ZpcmVzIEVTWCBhbWJ1bGFuY2UgcmV2aXZlIGV2ZW50LicgfSwKICAgICAgICAgICAgeyBpZDogJ3FiX3Jldml2ZScsIGxhYmVsOiAnUUJDb3JlIFRyaWdnZXIgUmV2aXZlJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdGaXJlcyBRQkNvcmUgaG9zcGl0YWwgcmV2aXZlIGV2ZW50LicgfSwKICAgICAgICAgICAgeyBpZDogJ3VubG9ja19jbG9zZXN0X3ZlaCcsIGxhYmVsOiAnRm9yY2UgVW5sb2NrIENsb3Nlc3QgVmVoaWNsZScsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnVW5sb2NrcyBhbmQgaG90d2lyZXMgY2xvc2VzdCB2ZWhpY2xlIHdpdGhpbiAzNW0uJyB9LAogICAgICAgICAgICB7IGlkOiAnYW50aV9zcGVjdGF0ZScsIGxhYmVsOiAnU2NhbiBHaG9zdCBTcGVjdGF0b3JzJywgdHlwZTogJ2FjdGlvbicsIGRlc2M6ICdEZXRlY3RzIGludmlzaWJsZSBhZG1pbnMgd2l0aGluIDEyMG0uJyB9LAogICAgICAgICAgICB7IGlkOiAnY2hlY2tfZnJhbWV3b3JrJywgbGFiZWw6ICdEZXRlY3QgQWN0aXZlIEZyYW1ld29yaycsIHR5cGU6ICdhY3Rpb24nLCBkZXNjOiAnU2NhbnMgZm9yIEVTWCwgUUJDb3JlIG9yIHZSUCBmcmFtZXdvcmsuJyB9CiAgICAgICAgICBdCiAgICAgICAgfQogICAgICBdCiAgICB9CiAgXTsKCiAgLy8gUnVudGltZSBTdGF0ZQogIGxldCBjdXJyZW50TGV2ZWwgPSAxOyAvLyAxID0gTWFpbiBNZW51LCAyID0gU3VibWVudQogIGxldCBzZWxlY3RlZENhdGVnb3J5SW5kZXggPSAwOwogIGxldCBhY3RpdmVTdWJ0YWJJbmRleCA9IDA7CiAgbGV0IHNlbGVjdGVkSXRlbUluZGV4ID0gMDsKCiAgbGV0IG9ubGluZVBsYXllcnMgPSBbLi4uREVGQVVMVF9TSU1VTEFURURfUExBWUVSU107CiAgbGV0IHNlbGVjdGVkUGxheWVySWRzID0gbmV3IFNldCgpOwogIGxldCBjdXJyZW50VGFyZ2V0SWQgPSAxOyAvLyBEZWZhdWx0IHRvIGhvc3QgcGxheWVyIGluIGRlbW8KCiAgbGV0IG1vZGFsQWN0aXZlID0gZmFsc2U7CiAgbGV0IGN1cnJlbnRNb2RhbFR5cGUgPSAndmVoaWNsZSc7CgogIGxldCBiaW5kTW9kYWxBY3RpdmUgPSBmYWxzZTsKICBsZXQgY3VycmVudEJpbmRJdGVtSWQgPSBudWxsOwogIGNvbnN0IGl0ZW1CaW5kcyA9IHsKICAgIGZyZWVjYW06ICdaJywKICAgIG5vY2xpcDogJ1gnCiAgfTsKCiAgLy8gUGxhY2VyIFN0YXRlCiAgbGV0IHBsYWNlckFjdGl2ZSA9IGZhbHNlOwogIGxldCBwbGFjZXJDYXRlZ29yeSA9ICdwcm9wcyc7CiAgbGV0IHBsYWNlckluZGV4ID0gMDsKCiAgLy8gRHJhZyBVSSBTdGF0ZQogIGxldCBpc0RyYWdNb2RlID0gZmFsc2U7CgogIC8vIEF1dGhlbnRpY2F0aW9uIFN0YXRlCiAgbGV0IGF1dGhUb2tlbiA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCd3dHJfYXV0aF90b2tlbicpIHx8IG51bGw7CiAgbGV0IGF1dGhVc2VybmFtZSA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCd3dHJfYXV0aF91c2VyJykgfHwgbnVsbDsKICBsZXQgaGVhcnRiZWF0VGltZXIgPSBudWxsOwoKICAvLyBET00gRWxlbWVudHMKICBjb25zdCBlbEJyZWFkY3J1bWJCYXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYnJlYWRjcnVtYkJhcicpOwogIGNvbnN0IGVsQ3J1bWJSb290ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2NydW1iUm9vdCcpOwogIGNvbnN0IGVsQ3J1bWJTZXAgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnY3J1bWJTZXAnKTsKICBjb25zdCBlbENydW1iU3ViID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2NydW1iU3ViJyk7CgogIGNvbnN0IGVsU3VidGFic0JhciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdzdWJ0YWJzQmFyJyk7CiAgY29uc3QgZWxTdWJ0YWJzU2Nyb2xsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3N1YnRhYnNTY3JvbGwnKTsKICBjb25zdCBidG5QcmV2U3VidGFiID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2J0blByZXZTdWJ0YWInKTsKICBjb25zdCBidG5OZXh0U3VidGFiID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2J0bk5leHRTdWJ0YWInKTsKCiAgY29uc3QgZWxPbmxpbmVUb29sYmFyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ29ubGluZVRvb2xiYXInKTsKICBjb25zdCBidG5TZWxlY3RBbGwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYnRuU2VsZWN0QWxsJyk7CiAgY29uc3QgYnRuVW5zZWxlY3RBbGwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYnRuVW5zZWxlY3RBbGwnKTsKICBjb25zdCBidG5UYXJnZXRTZWxmID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2J0blRhcmdldFNlbGYnKTsKICBjb25zdCBlbFRvb2xDb3VudGVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3Rvb2xDb3VudGVyJyk7CgogIGNvbnN0IGVsSXRlbXNMaXN0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2l0ZW1zTGlzdCcpOwogIGNvbnN0IGVsVG9vbHRpcFRleHQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndG9vbHRpcFRleHQnKTsKICBjb25zdCBlbEZvb3RlckNvdW50ZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZm9vdGVyQ291bnRlcicpOwoKICAvLyBJbnB1dCBNb2RhbCBFbGVtZW50cwogIGNvbnN0IGVsTW9kYWxPdmVybGF5ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ21vZGFsT3ZlcmxheScpOwogIGNvbnN0IGVsTW9kYWxUaXRsZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdtb2RhbFRpdGxlJyk7CiAgY29uc3QgZWxNb2RhbElucHV0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ21vZGFsSW5wdXQnKTsKICBjb25zdCBlbE1vZGFsQ2xlYXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbW9kYWxJbnB1dENsZWFyJyk7CiAgY29uc3QgZWxNb2RhbFByZXNldHMgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbW9kYWxQcmVzZXRzJyk7CiAgY29uc3QgZWxNb2RhbEJ0bkNsb3NlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ21vZGFsQnRuQ2xvc2UnKTsKICBjb25zdCBlbE1vZGFsQnRuQ2FuY2VsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ21vZGFsQnRuQ2FuY2VsJyk7CiAgY29uc3QgZWxNb2RhbEJ0bkNvbmZpcm0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbW9kYWxCdG5Db25maXJtJyk7CgogIC8vIEZlYXR1cmUgS2V5YmluZCBNb2RhbCBFbGVtZW50cwogIGNvbnN0IGVsQmluZE1vZGFsT3ZlcmxheSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdiaW5kTW9kYWxPdmVybGF5Jyk7CiAgY29uc3QgZWxCaW5kTW9kYWxUaXRsZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdiaW5kTW9kYWxUaXRsZScpOwogIGNvbnN0IGVsQmluZE1vZGFsS2V5Y2FwID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2JpbmRNb2RhbEtleWNhcCcpOwogIGNvbnN0IGVsQmluZE1vZGFsSW5zdHJ1Y3Rpb24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYmluZE1vZGFsSW5zdHJ1Y3Rpb24nKTsKICBjb25zdCBlbEJpbmRNb2RhbFN0YXR1cyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdiaW5kTW9kYWxTdGF0dXMnKTsKICBjb25zdCBlbEJpbmRNb2RhbEJ0bkNsb3NlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2JpbmRNb2RhbEJ0bkNsb3NlJyk7CiAgY29uc3QgZWxCaW5kTW9kYWxCdG5DYW5jZWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYmluZE1vZGFsQnRuQ2FuY2VsJyk7CiAgY29uc3QgZWxCaW5kTW9kYWxCdG5Db25maXJtID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2JpbmRNb2RhbEJ0bkNvbmZpcm0nKTsKCiAgLy8gQXV0aGVudGljYXRpb24gTW9kYWwgRWxlbWVudHMgKFRPS0VOIE9OTFkpCiAgY29uc3QgZWxBdXRoTW9kYWxPdmVybGF5ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2F1dGhNb2RhbE92ZXJsYXknKTsKICBjb25zdCBlbEF1dGhUb2tlbklucHV0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2F1dGhUb2tlbklucHV0Jyk7CiAgY29uc3QgZWxCdG5BdXRoTG9naW4gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYnRuQXV0aExvZ2luJyk7CiAgY29uc3QgZWxCdG5BdXRoR3Vlc3QgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYnRuQXV0aEd1ZXN0Jyk7CiAgY29uc3QgZWxBdXRoU3RhdHVzVGV4dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdhdXRoU3RhdHVzVGV4dCcpOwoKICAvLyBBbnRpY2hlYXQgRGlhZ25vc3RpYyBTY2FubmVyIE1vZGFsIEVsZW1lbnRzCiAgY29uc3QgZWxBY1NjYW5Nb2RhbE92ZXJsYXkgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYWNTY2FuTW9kYWxPdmVybGF5Jyk7CiAgY29uc3QgZWxBY1NjYW5CdG5DbG9zZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdhY1NjYW5CdG5DbG9zZScpOwogIGNvbnN0IGVsQWNTY2FuQnRuRG9uZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdhY1NjYW5CdG5Eb25lJyk7CiAgY29uc3QgZWxBY1NjYW5Qcm9ncmVzc0JhciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdhY1NjYW5Qcm9ncmVzc0JhcicpOwogIGNvbnN0IGVsQWNTY2FuUmVzdWx0c0xpc3QgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYWNTY2FuUmVzdWx0c0xpc3QnKTsKICBjb25zdCBlbEFjU2NhblN1YnRpdGxlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2FjU2NhblN1YnRpdGxlJyk7CiAgbGV0IGFjU2Nhbk1vZGFsQWN0aXZlID0gZmFsc2U7CiAgbGV0IGFjU2NhbkludGVydmFsID0gbnVsbDsKCiAgLy8gRmxvYXRpbmcgSFVEIEVsZW1lbnRzCiAgY29uc3QgZWxTcGVjdGF0b3JMaXN0SHVkID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3NwZWN0YXRvckxpc3RIdWQnKTsKICBjb25zdCBlbFNwZWN0YXRvckRvdCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdzcGVjdGF0b3JEb3QnKTsKICBjb25zdCBlbFNwZWN0YXRvckNvdW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3NwZWN0YXRvckNvdW50Jyk7CiAgY29uc3QgZWxTcGVjdGF0b3JMaXN0Qm9keSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdzcGVjdGF0b3JMaXN0Qm9keScpOwoKICBjb25zdCBlbEtleWJpbmRzTGlzdEh1ZCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdrZXliaW5kc0xpc3RIdWQnKTsKICBjb25zdCBlbEJpbmRzQ291bnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYmluZHNDb3VudCcpOwogIGNvbnN0IGVsS2V5YmluZHNMaXN0Qm9keSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdrZXliaW5kc0xpc3RCb2R5Jyk7CgogIGNvbnN0IGVsUXVpY2tQbGFjZXJIdWQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncXVpY2tQbGFjZXJIdWQnKTsKICBjb25zdCBlbFBsYWNlckNhdGVnb3J5ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3BsYWNlckNhdGVnb3J5Jyk7CiAgY29uc3QgZWxQbGFjZXJJdGVtTmFtZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdwbGFjZXJJdGVtTmFtZScpOwogIGNvbnN0IGJ0blBsYWNlclByZXYgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncGxhY2VyUHJldicpOwogIGNvbnN0IGJ0blBsYWNlck5leHQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncGxhY2VyTmV4dCcpOwoKICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogIC8vICAgICAgICAgICAgICAgICAgQVVUSEVOVElDQVRJT04gJiBIRUFSVEJFQVQgRU5HSU5FIChUT0tFTiBPTkxZKQogIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgogIGZ1bmN0aW9uIGNoZWNrQXV0aFN0YXR1cygpIHsKICAgIGNvbnN0IGlzSWZyYW1lID0gKHdpbmRvdy5zZWxmICE9PSB3aW5kb3cudG9wKTsKICAgIGNvbnN0IGlzRGVtb1BhcmFtID0gd2luZG93LmxvY2F0aW9uLnNlYXJjaC5pbmNsdWRlcygnZGVtbycpOwogICAgY29uc3QgaXNGaXZlTSA9ICh0eXBlb2Ygd2luZG93Lmludm9rZU5hdGl2ZSAhPT0gJ3VuZGVmaW5lZCcpIHx8ICh0eXBlb2Ygd2luZG93LkdldFBhcmVudFJlc291cmNlTmFtZSAhPT0gJ3VuZGVmaW5lZCcpOwoKICAgIC8vIEF1dG8tZW5hYmxlIGRlbW8gZ3Vlc3QgbW9kZSBpbiBpZnJhbWVzICh3ZWJzaXRlIHNob3djYXNlKSBvciBicm93c2VyIHByZXZpZXcKICAgIGlmIChpc0lmcmFtZSB8fCBpc0RlbW9QYXJhbSB8fCAhaXNGaXZlTSkgewogICAgICBhdXRoVG9rZW4gPSAnd3RyX3Nlc3NfZGVtbyc7CiAgICAgIGF1dGhVc2VybmFtZSA9ICdEZW1vIFVzZXInOwogICAgICBpZiAoZWxBdXRoTW9kYWxPdmVybGF5KSBlbEF1dGhNb2RhbE92ZXJsYXkuc3R5bGUuZGlzcGxheSA9ICdub25lJzsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmICghYXV0aFRva2VuKSB7CiAgICAgIGlmIChlbEF1dGhNb2RhbE92ZXJsYXkpIHsKICAgICAgICBlbEF1dGhNb2RhbE92ZXJsYXkuc3R5bGUuZGlzcGxheSA9ICdmbGV4JzsKICAgICAgICBpZiAoZWxBdXRoVG9rZW5JbnB1dCkgZWxBdXRoVG9rZW5JbnB1dC5mb2N1cygpOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB2ZXJpZnlUb2tlbldpdGhCYWNrZW5kKGF1dGhUb2tlbik7CiAgICB9CiAgfQoKICBhc3luYyBmdW5jdGlvbiB2ZXJpZnlUb2tlbldpdGhCYWNrZW5kKHRva2VuVG9WZXJpZnkpIHsKICAgIHRyeSB7CiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBmZXRjaCgnaHR0cHM6Ly93dHJtZW51LnRhdHJ1cy5vcmcvYXBpL3Rva2VuLWF1dGgnLCB7CiAgICAgICAgbWV0aG9kOiAnUE9TVCcsCiAgICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nIH0sCiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyB0b2tlbjogdG9rZW5Ub1ZlcmlmeSB9KQogICAgICB9KTsKICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHJlc3AuanNvbigpOwogICAgICBpZiAoZGF0YSAmJiBkYXRhLnN1Y2Nlc3MpIHsKICAgICAgICBhdXRoVG9rZW4gPSBkYXRhLnRva2VuOwogICAgICAgIGF1dGhVc2VybmFtZSA9IGRhdGEudXNlcm5hbWUgfHwgJ0F1dGhvcml6ZWQgVXNlcic7CiAgICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ3d0cl9hdXRoX3Rva2VuJywgYXV0aFRva2VuKTsKICAgICAgICBpZiAoZWxBdXRoTW9kYWxPdmVybGF5KSBlbEF1dGhNb2RhbE92ZXJsYXkuc3R5bGUuZGlzcGxheSA9ICdub25lJzsKICAgICAgICBzdGFydEhlYXJ0YmVhdCgpOwogICAgICAgIHNob3dOb3RpZmljYXRpb24oYEF1dGhlbnRpY2F0ZWQgdmlhIHRva2VuIFske2F1dGhVc2VybmFtZX1dYCwgJ3N1Y2Nlc3MnKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBhdXRoVG9rZW4gPSBudWxsOwogICAgICAgIGxvY2FsU3RvcmFnZS5yZW1vdmVJdGVtKCd3dHJfYXV0aF90b2tlbicpOwogICAgICAgIGlmIChlbEF1dGhNb2RhbE92ZXJsYXkpIHsKICAgICAgICAgIGVsQXV0aE1vZGFsT3ZlcmxheS5zdHlsZS5kaXNwbGF5ID0gJ2ZsZXgnOwogICAgICAgICAgaWYgKGVsQXV0aFN0YXR1c1RleHQpIHsKICAgICAgICAgICAgZWxBdXRoU3RhdHVzVGV4dC50ZXh0Q29udGVudCA9IGRhdGEuZXJyb3IgfHwgJ1Nlc3Npb24gdG9rZW4gZXhwaXJlZC4gRW50ZXIgdG9rZW4gZnJvbSBkYXNoYm9hcmQuJzsKICAgICAgICAgICAgZWxBdXRoU3RhdHVzVGV4dC5zdHlsZS5jb2xvciA9ICcjZjg3MTcxJzsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0gY2F0Y2ggKGVycikgewogICAgICBpZiAodG9rZW5Ub1ZlcmlmeSAmJiB0b2tlblRvVmVyaWZ5LnN0YXJ0c1dpdGgoJ3d0cl9zZXNzXycpKSB7CiAgICAgICAgaWYgKGVsQXV0aE1vZGFsT3ZlcmxheSkgZWxBdXRoTW9kYWxPdmVybGF5LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7CiAgICAgICAgc3RhcnRIZWFydGJlYXQoKTsKICAgICAgfQogICAgfQogIH0KCiAgYXN5bmMgZnVuY3Rpb24gcGVyZm9ybUxvZ2luKCkgewogICAgY29uc3QgdG9rZW5WYWwgPSBlbEF1dGhUb2tlbklucHV0ID8gZWxBdXRoVG9rZW5JbnB1dC52YWx1ZS50cmltKCkgOiAnJzsKCiAgICBpZiAoIXRva2VuVmFsKSB7CiAgICAgIGlmIChlbEF1dGhTdGF0dXNUZXh0KSB7CiAgICAgICAgZWxBdXRoU3RhdHVzVGV4dC50ZXh0Q29udGVudCA9ICdQbGVhc2UgZW50ZXIgeW91ciBzZXNzaW9uIHRva2VuIGZyb20gd3RybWVudS50YXRydXMub3JnJzsKICAgICAgICBlbEF1dGhTdGF0dXNUZXh0LnN0eWxlLmNvbG9yID0gJyNmODcxNzEnOwogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAoZWxBdXRoU3RhdHVzVGV4dCkgewogICAgICBlbEF1dGhTdGF0dXNUZXh0LnRleHRDb250ZW50ID0gJ0F1dGhlbnRpY2F0aW5nIHNlc3Npb24gdG9rZW4uLi4nOwogICAgICBlbEF1dGhTdGF0dXNUZXh0LnN0eWxlLmNvbG9yID0gJyMwMGYwZmYnOwogICAgfQoKICAgIHRyeSB7CiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBmZXRjaCgnaHR0cHM6Ly93dHJtZW51LnRhdHJ1cy5vcmcvYXBpL3Rva2VuLWF1dGgnLCB7CiAgICAgICAgbWV0aG9kOiAnUE9TVCcsCiAgICAgICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nIH0sCiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyB0b2tlbjogdG9rZW5WYWwgfSkKICAgICAgfSk7CiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCByZXNwLmpzb24oKTsKCiAgICAgIGlmIChkYXRhICYmIGRhdGEuc3VjY2VzcykgewogICAgICAgIGF1dGhUb2tlbiA9IGRhdGEudG9rZW47CiAgICAgICAgYXV0aFVzZXJuYW1lID0gZGF0YS51c2VybmFtZSB8fCAnQXV0aG9yaXplZCBVc2VyJzsKICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgnd3RyX2F1dGhfdG9rZW4nLCBhdXRoVG9rZW4pOwogICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKCd3dHJfYXV0aF91c2VyJywgYXV0aFVzZXJuYW1lKTsKCiAgICAgICAgaWYgKGVsQXV0aFN0YXR1c1RleHQpIHsKICAgICAgICAgIGVsQXV0aFN0YXR1c1RleHQudGV4dENvbnRlbnQgPSAnVG9rZW4gdmVyaWZpZWQhIEluaXRpYWxpemluZyBXVFIgQ2xpZW50Li4uJzsKICAgICAgICAgIGVsQXV0aFN0YXR1c1RleHQuc3R5bGUuY29sb3IgPSAnIzIyYzU1ZSc7CiAgICAgICAgfQoKICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHsKICAgICAgICAgIGlmIChlbEF1dGhNb2RhbE92ZXJsYXkpIGVsQXV0aE1vZGFsT3ZlcmxheS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnOwogICAgICAgICAgc3RhcnRIZWFydGJlYXQoKTsKICAgICAgICAgIHNob3dOb3RpZmljYXRpb24oYEF1dGhlbnRpY2F0ZWQgYXMgJHthdXRoVXNlcm5hbWV9YCwgJ3N1Y2Nlc3MnKTsKICAgICAgICB9LCA1MDApOwogICAgICB9IGVsc2UgewogICAgICAgIGlmIChlbEF1dGhTdGF0dXNUZXh0KSB7CiAgICAgICAgICBlbEF1dGhTdGF0dXNUZXh0LnRleHRDb250ZW50ID0gZGF0YS5lcnJvciB8fCAnSW52YWxpZCBzZXNzaW9uIHRva2VuLiBSZXNldCB0b2tlbiBpbiB5b3VyIGRhc2hib2FyZC4nOwogICAgICAgICAgZWxBdXRoU3RhdHVzVGV4dC5zdHlsZS5jb2xvciA9ICcjZjg3MTcxJzsKICAgICAgICB9CiAgICAgIH0KICAgIH0gY2F0Y2ggKGVycikgewogICAgICBpZiAodG9rZW5WYWwuc3RhcnRzV2l0aCgnd3RyX3Nlc3NfJykpIHsKICAgICAgICBhdXRoVG9rZW4gPSB0b2tlblZhbDsKICAgICAgICBhdXRoVXNlcm5hbWUgPSAnRGVtbyBVc2VyJzsKICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgnd3RyX2F1dGhfdG9rZW4nLCBhdXRoVG9rZW4pOwogICAgICAgIGlmIChlbEF1dGhNb2RhbE92ZXJsYXkpIGVsQXV0aE1vZGFsT3ZlcmxheS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnOwogICAgICAgIHNob3dOb3RpZmljYXRpb24oJ1Rva2VuIGFjY2VwdGVkIChMb2NhbCBPZmZsaW5lIE1vZGUpJywgJ3N1Y2Nlc3MnKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAoZWxBdXRoU3RhdHVzVGV4dCkgewogICAgICAgICAgZWxBdXRoU3RhdHVzVGV4dC50ZXh0Q29udGVudCA9ICdDb25uZWN0aW9uIGVycm9yOiBVbmFibGUgdG8gdmVyaWZ5IHdpdGggd3RybWVudS50YXRydXMub3JnJzsKICAgICAgICAgIGVsQXV0aFN0YXR1c1RleHQuc3R5bGUuY29sb3IgPSAnI2Y4NzE3MSc7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQoKICBmdW5jdGlvbiBzdGFydEhlYXJ0YmVhdCgpIHsKICAgIGlmIChoZWFydGJlYXRUaW1lcikgY2xlYXJJbnRlcnZhbChoZWFydGJlYXRUaW1lcik7CiAgICBoZWFydGJlYXRUaW1lciA9IHNldEludGVydmFsKGFzeW5jICgpID0+IHsKICAgICAgaWYgKCFhdXRoVG9rZW4pIHJldHVybjsKICAgICAgdHJ5IHsKICAgICAgICBjb25zdCByZXNwID0gYXdhaXQgZmV0Y2goJ2h0dHBzOi8vd3RybWVudS50YXRydXMub3JnL2FwaS9oZWFydGJlYXQnLCB7CiAgICAgICAgICBtZXRob2Q6ICdQT1NUJywKICAgICAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9LAogICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyB1c2VybmFtZTogYXV0aFVzZXJuYW1lLCB0b2tlbjogYXV0aFRva2VuIH0pCiAgICAgICAgfSk7CiAgICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHJlc3AuanNvbigpOwogICAgICAgIGlmIChkYXRhICYmIGRhdGEuY29uY3VycmVudF9sb2dpbikgewogICAgICAgICAgY2xlYXJJbnRlcnZhbChoZWFydGJlYXRUaW1lcik7CiAgICAgICAgICBhdXRoVG9rZW4gPSBudWxsOwogICAgICAgICAgbG9jYWxTdG9yYWdlLnJlbW92ZUl0ZW0oJ3d0cl9hdXRoX3Rva2VuJyk7CiAgICAgICAgICBpZiAoZWxBdXRoTW9kYWxPdmVybGF5KSB7CiAgICAgICAgICAgIGVsQXV0aE1vZGFsT3ZlcmxheS5zdHlsZS5kaXNwbGF5ID0gJ2ZsZXgnOwogICAgICAgICAgICBpZiAoZWxBdXRoU3RhdHVzVGV4dCkgewogICAgICAgICAgICAgIGVsQXV0aFN0YXR1c1RleHQudGV4dENvbnRlbnQgPSAnU0VTU0lPTiBURVJNSU5BVEVEOiBDb25jdXJyZW50IHNlc3Npb24gZGV0ZWN0ZWQuIFRva2VucyByZXZva2VkLic7CiAgICAgICAgICAgICAgZWxBdXRoU3RhdHVzVGV4dC5zdHlsZS5jb2xvciA9ICcjZWY0NDQ0JzsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSBjYXRjaCAoZXJyKSB7fQogICAgfSwgMjAwMDApOwogIH0KCiAgaWYgKGVsQnRuQXV0aExvZ2luKSB7CiAgICBlbEJ0bkF1dGhMb2dpbi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHBlcmZvcm1Mb2dpbik7CiAgfQogIGlmIChlbEJ0bkF1dGhHdWVzdCkgewogICAgZWxCdG5BdXRoR3Vlc3QuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7CiAgICAgIGF1dGhUb2tlbiA9ICd3dHJfc2Vzc19kZW1vJzsKICAgICAgYXV0aFVzZXJuYW1lID0gJ0RlbW8gVXNlcic7CiAgICAgIGlmIChlbEF1dGhNb2RhbE92ZXJsYXkpIGVsQXV0aE1vZGFsT3ZlcmxheS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnOwogICAgICBzaG93Tm90aWZpY2F0aW9uKCdEZW1vIE1vZGUgQWN0aXZlIC0gRXhwbG9yZSBXVFIgTWVudSBmZWF0dXJlcycsICdpbmZvJyk7CiAgICB9KTsKICB9CiAgaWYgKGVsQXV0aFRva2VuSW5wdXQpIHsKICAgIGVsQXV0aFRva2VuSW5wdXQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIChlKSA9PiB7CiAgICAgIGlmIChlLmtleSA9PT0gJ0VudGVyJykgcGVyZm9ybUxvZ2luKCk7CiAgICB9KTsKICB9CiAgaWYgKGVsQ3J1bWJSb290KSB7CiAgICBlbENydW1iUm9vdC5zdHlsZS5jdXJzb3IgPSAncG9pbnRlcic7CiAgICBlbENydW1iUm9vdC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHsKICAgICAgaWYgKGN1cnJlbnRMZXZlbCA9PT0gMikgewogICAgICAgIGdvQmFjaygpOwogICAgICB9CiAgICB9KTsKICB9CgogIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgLy8gICAgICAgICAgICAgICAgICBSRU5ERVIgRU5HSU5FCiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCiAgZnVuY3Rpb24gcmVuZGVyKCkgewogICAgaWYgKGN1cnJlbnRMZXZlbCA9PT0gMSkgewogICAgICByZW5kZXJNYWluTWVudSgpOwogICAgfSBlbHNlIHsKICAgICAgcmVuZGVyU3VibWVudSgpOwogICAgfQogICAgdXBkYXRlQmluZHNIdWQoKTsKICB9CgogIC8vIExldmVsIDE6IE1haW4gTWVudSBDYXRlZ29yaWVzCiAgZnVuY3Rpb24gcmVuZGVyTWFpbk1lbnUoKSB7CiAgICBlbENydW1iUm9vdC50ZXh0Q29udGVudCA9ICdNYWluIE1lbnUnOwogICAgZWxDcnVtYlNlcC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnOwogICAgZWxDcnVtYlN1Yi5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnOwogICAgZWxTdWJ0YWJzQmFyLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7CiAgICBlbE9ubGluZVRvb2xiYXIuc3R5bGUuZGlzcGxheSA9ICdub25lJzsKCiAgICBlbEl0ZW1zTGlzdC5pbm5lckhUTUwgPSAnJzsKCiAgICBDQVRFR09SSUVTLmZvckVhY2goKGNhdCwgaW5kZXgpID0+IHsKICAgICAgY29uc3Qgcm93ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICAgIHJvdy5jbGFzc05hbWUgPSAnbWVudS1yb3cnICsgKGluZGV4ID09PSBzZWxlY3RlZENhdGVnb3J5SW5kZXggPyAnIGFjdGl2ZScgOiAnJyk7CiAgICAgIHJvdy5kYXRhc2V0LmluZGV4ID0gaW5kZXg7CgogICAgICBjb25zdCBsZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICAgIGxlZnQuY2xhc3NOYW1lID0gJ3Jvdy1sZWZ0JzsKCiAgICAgIGNvbnN0IGljb25EaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsKICAgICAgaWNvbkRpdi5jbGFzc05hbWUgPSAncm93LWljb24nOwogICAgICBpY29uRGl2LmlubmVySFRNTCA9IElDT05TW2NhdC5pY29uXSB8fCBJQ09OUy5wbGF5ZXI7CgogICAgICBjb25zdCBsYWJlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOwogICAgICBsYWJlbC5jbGFzc05hbWUgPSAncm93LWxhYmVsJzsKICAgICAgbGFiZWwudGV4dENvbnRlbnQgPSBjYXQubGFiZWw7CgogICAgICBsZWZ0LmFwcGVuZENoaWxkKGljb25EaXYpOwogICAgICBsZWZ0LmFwcGVuZENoaWxkKGxhYmVsKTsKCiAgICAgIGNvbnN0IHJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICAgIHJpZ2h0LmNsYXNzTmFtZSA9ICdyb3ctcmlnaHQnOwoKICAgICAgY29uc3QgY2hldiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOwogICAgICBjaGV2LmNsYXNzTmFtZSA9ICdyb3ctY2hldnJvbic7CiAgICAgIGNoZXYudGV4dENvbnRlbnQgPSAn4oC6JzsKCiAgICAgIHJpZ2h0LmFwcGVuZENoaWxkKGNoZXYpOwogICAgICByb3cuYXBwZW5kQ2hpbGQobGVmdCk7CiAgICAgIHJvdy5hcHBlbmRDaGlsZChyaWdodCk7CgogICAgICByb3cuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7CiAgICAgICAgc2VsZWN0ZWRDYXRlZ29yeUluZGV4ID0gaW5kZXg7CiAgICAgICAgZW50ZXJDYXRlZ29yeSgpOwogICAgICB9KTsKCiAgICAgIHJvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWVudGVyJywgKCkgPT4gewogICAgICAgIHNlbGVjdGVkQ2F0ZWdvcnlJbmRleCA9IGluZGV4OwogICAgICAgIHVwZGF0ZUFjdGl2ZVN0YXRlKCk7CiAgICAgIH0pOwoKICAgICAgZWxJdGVtc0xpc3QuYXBwZW5kQ2hpbGQocm93KTsKICAgIH0pOwoKICAgIHVwZGF0ZUFjdGl2ZVN0YXRlKCk7CiAgfQoKICAvLyBMZXZlbCAyOiBTdWJtZW51cwogIGZ1bmN0aW9uIHJlbmRlclN1Ym1lbnUoKSB7CiAgICBjb25zdCBjdXJDYXQgPSBDQVRFR09SSUVTW3NlbGVjdGVkQ2F0ZWdvcnlJbmRleF07CiAgICBpZiAoIWN1ckNhdCkgcmV0dXJuOwoKICAgIGNvbnN0IGN1clN1YnRhYiA9IChjdXJDYXQuc3VidGFicyAmJiBjdXJDYXQuc3VidGFicy5sZW5ndGggPiAwKSA/IGN1ckNhdC5zdWJ0YWJzW2FjdGl2ZVN1YnRhYkluZGV4XSA6IG51bGw7CgogICAgZWxDcnVtYlJvb3QudGV4dENvbnRlbnQgPSAnTWFpbiBNZW51JzsKICAgIGVsQ3J1bWJTZXAuc3R5bGUuZGlzcGxheSA9ICdpbmxpbmUnOwogICAgZWxDcnVtYlN1Yi5zdHlsZS5kaXNwbGF5ID0gJ2lubGluZSc7CiAgICBpZiAoY3VyU3VidGFiICYmIGN1clN1YnRhYi5sYWJlbCkgewogICAgICBlbENydW1iU3ViLmlubmVySFRNTCA9IGAke2VzY2FwZUh0bWwoY3VyQ2F0LmxhYmVsKX0gPHNwYW4gc3R5bGU9ImNvbG9yOiByZ2JhKDAsIDI0MCwgMjU1LCAwLjQ1KTsgbWFyZ2luOiAwIDRweDsiPuKAujwvc3Bhbj4gPHNwYW4gc3R5bGU9ImNvbG9yOiAjMDBmMGZmOyBmb250LXdlaWdodDogNzAwOyI+JHtlc2NhcGVIdG1sKGN1clN1YnRhYi5sYWJlbCl9PC9zcGFuPmA7CiAgICB9IGVsc2UgewogICAgICBlbENydW1iU3ViLnRleHRDb250ZW50ID0gY3VyQ2F0LmxhYmVsOwogICAgfQoKICAgIC8vIFJlbmRlciBTdWJ0YWJzCiAgICBpZiAoY3VyQ2F0LnN1YnRhYnMgJiYgY3VyQ2F0LnN1YnRhYnMubGVuZ3RoID4gMCkgewogICAgICBlbFN1YnRhYnNCYXIuc3R5bGUuZGlzcGxheSA9ICdmbGV4JzsKICAgICAgZWxTdWJ0YWJzU2Nyb2xsLmlubmVySFRNTCA9ICcnOwoKICAgICAgY3VyQ2F0LnN1YnRhYnMuZm9yRWFjaCgoc3QsIGlkeCkgPT4gewogICAgICAgIGNvbnN0IHBpbGwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsKICAgICAgICBwaWxsLmNsYXNzTmFtZSA9ICdzdWJ0YWItcGlsbCcgKyAoaWR4ID09PSBhY3RpdmVTdWJ0YWJJbmRleCA/ICcgYWN0aXZlJyA6ICcnKTsKICAgICAgICBwaWxsLnRleHRDb250ZW50ID0gc3QubGFiZWw7CiAgICAgICAgcGlsbC5kYXRhc2V0LmluZGV4ID0gaWR4OwoKICAgICAgICBwaWxsLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4gewogICAgICAgICAgYWN0aXZlU3VidGFiSW5kZXggPSBpZHg7CiAgICAgICAgICBpZiAoc3QuaXNQbGF5ZXJMaXN0KSB7CiAgICAgICAgICAgIHNlbGVjdGVkSXRlbUluZGV4ID0gMDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHNlbGVjdGVkSXRlbUluZGV4ID0gZ2V0TmV4dE5vbkhlYWRlckluZGV4KHN0Lml0ZW1zIHx8IFtdLCAtMSwgMSk7CiAgICAgICAgICB9CiAgICAgICAgICByZW5kZXJTdWJtZW51KCk7CiAgICAgICAgfSk7CgogICAgICAgIGVsU3VidGFic1Njcm9sbC5hcHBlbmRDaGlsZChwaWxsKTsKICAgICAgfSk7CgogICAgICBjb25zdCBhY3RpdmVFbCA9IGVsU3VidGFic1Njcm9sbC5jaGlsZHJlblthY3RpdmVTdWJ0YWJJbmRleF07CiAgICAgIGlmIChhY3RpdmVFbCkgewogICAgICAgIGFjdGl2ZUVsLnNjcm9sbEludG9WaWV3KHsgYmVoYXZpb3I6ICdzbW9vdGgnLCBibG9jazogJ25lYXJlc3QnLCBpbmxpbmU6ICdjZW50ZXInIH0pOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBlbFN1YnRhYnNCYXIuc3R5bGUuZGlzcGxheSA9ICdub25lJzsKICAgIH0KCiAgICAvLyBDaGVjayBpZiB0aGlzIHN1YnRhYiBpcyB0aGUgUGxheWVycyBsaXN0IGluIE9ubGluZQogICAgaWYgKGN1clN1YnRhYiAmJiBjdXJTdWJ0YWIuaXNQbGF5ZXJMaXN0KSB7CiAgICAgIGVsT25saW5lVG9vbGJhci5zdHlsZS5kaXNwbGF5ID0gJ2ZsZXgnOwogICAgICByZW5kZXJQbGF5ZXJzTGlzdCgpOwogICAgICByZXR1cm47CiAgICB9IGVsc2UgewogICAgICBlbE9ubGluZVRvb2xiYXIuc3R5bGUuZGlzcGxheSA9ICdub25lJzsKICAgIH0KCiAgICAvLyBSZW5kZXIgU3VibWVudSBJdGVtcwogICAgZWxJdGVtc0xpc3QuaW5uZXJIVE1MID0gJyc7CgogICAgLy8gQWN0aXZlIFRhcmdldCBJbmRpY2F0b3IgQmFubmVyIGluIE9ubGluZSA+IEFjdGlvbnMsIE9ubGluZSA+IFZlaGljbGUsIE9ubGluZSA+IExvb3BzCiAgICBpZiAoY3VyQ2F0LmlkID09PSAnb25saW5lJyAmJiBjdXJTdWJ0YWIgJiYgKGN1clN1YnRhYi5pZCA9PT0gJ2FjdGlvbnMnIHx8IGN1clN1YnRhYi5pZCA9PT0gJ3ZlaGljbGUnIHx8IGN1clN1YnRhYi5pZCA9PT0gJ2xvb3BzJykpIHsKICAgICAgY29uc3QgYmFubmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICAgIGJhbm5lci5jbGFzc05hbWUgPSAndGFyZ2V0LWluZGljYXRvci1iYW5uZXInOwogICAgICBjb25zdCB2ZWhCYWRnZSA9IChjdXJTdWJ0YWIuaWQgPT09ICd2ZWhpY2xlJykgPyAnIDxzcGFuIHN0eWxlPSJjb2xvcjogIzAwZjBmZjsgZm9udC1zaXplOiAxMHB4OyBtYXJnaW4tbGVmdDogNnB4OyBsZXR0ZXItc3BhY2luZzogMC41cHg7IGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoMCwgMjQwLCAyNTUsIDAuNCk7IHBhZGRpbmc6IDFweCA1cHg7IGJvcmRlci1yYWRpdXM6IDNweDsgYmFja2dyb3VuZDogcmdiYSgwLCAyNDAsIDI1NSwgMC4xKTsiPltWRUhJQ0xFIFRBUkdFVF08L3NwYW4+JyA6ICcnOwogICAgICBpZiAoc2VsZWN0ZWRQbGF5ZXJJZHMuc2l6ZSA+IDEpIHsKICAgICAgICBiYW5uZXIuaW5uZXJIVE1MID0gYDxzcGFuIGNsYXNzPSJ0YXJnZXQtYmFkZ2UtaWNvbiI+8J+Orzwvc3Bhbj4gVEFSR0VUOiA8YiBzdHlsZT0iY29sb3I6ICMwMGYwZmY7Ij4ke3NlbGVjdGVkUGxheWVySWRzLnNpemV9IFBMQVlFUlMgU0VMRUNURUQ8L2I+JHt2ZWhCYWRnZX1gOwogICAgICB9IGVsc2UgaWYgKGN1cnJlbnRUYXJnZXRJZCkgewogICAgICAgIGNvbnN0IHBPYmogPSBvbmxpbmVQbGF5ZXJzLmZpbmQocCA9PiBwLnNlcnZlcklkID09PSBjdXJyZW50VGFyZ2V0SWQpOwogICAgICAgIGNvbnN0IHBOYW1lID0gcE9iaiA/IHBPYmoubmFtZSA6IGBQbGF5ZXIgIyR7Y3VycmVudFRhcmdldElkfWA7CiAgICAgICAgY29uc3QgcERpc3QgPSBwT2JqID8gYCAoJHtwT2JqLmRpc3R9bSlgIDogJyc7CiAgICAgICAgYmFubmVyLmlubmVySFRNTCA9IGA8c3BhbiBjbGFzcz0idGFyZ2V0LWJhZGdlLWljb24iPvCfjq88L3NwYW4+IFRBUkdFVDogPGIgc3R5bGU9ImNvbG9yOiAjMDBmMGZmOyI+IyR7Y3VycmVudFRhcmdldElkfSAke2VzY2FwZUh0bWwocE5hbWUpfSR7cERpc3R9PC9iPiR7dmVoQmFkZ2V9YDsKICAgICAgfSBlbHNlIHsKICAgICAgICBiYW5uZXIuaW5uZXJIVE1MID0gYDxzcGFuIGNsYXNzPSJ0YXJnZXQtYmFkZ2UtaWNvbiI+8J+Orzwvc3Bhbj4gVEFSR0VUOiA8YiBzdHlsZT0iY29sb3I6ICMwMGYwZmY7Ij5MT0NBTCBTRUxGPC9iPiR7dmVoQmFkZ2V9YDsKICAgICAgfQogICAgICBlbEl0ZW1zTGlzdC5hcHBlbmRDaGlsZChiYW5uZXIpOwogICAgfQoKICAgIGNvbnN0IGl0ZW1zID0gKGN1clN1YnRhYiAmJiBjdXJTdWJ0YWIuaXRlbXMpID8gY3VyU3VidGFiLml0ZW1zIDogW107CgogICAgaXRlbXMuZm9yRWFjaCgoaXQsIGluZGV4KSA9PiB7CiAgICAgIGlmIChpdC5pc0hlYWRlcikgewogICAgICAgIGNvbnN0IHNlYyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOwogICAgICAgIHNlYy5jbGFzc05hbWUgPSAnc2VjdGlvbi1oZWFkZXInOwogICAgICAgIHNlYy5pbm5lckhUTUwgPSBgPGRpdiBjbGFzcz0ic2VjdGlvbi1saW5lIj48L2Rpdj48c3BhbiBjbGFzcz0ic2VjdGlvbi10aXRsZSI+JHtpdC5sYWJlbH08L3NwYW4+PGRpdiBjbGFzcz0ic2VjdGlvbi1saW5lIj48L2Rpdj5gOwogICAgICAgIGVsSXRlbXNMaXN0LmFwcGVuZENoaWxkKHNlYyk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBjb25zdCByb3cgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsKICAgICAgcm93LmNsYXNzTmFtZSA9ICdtZW51LXJvdycgKyAoaW5kZXggPT09IHNlbGVjdGVkSXRlbUluZGV4ID8gJyBhY3RpdmUnIDogJycpOwogICAgICByb3cuZGF0YXNldC5pbmRleCA9IGluZGV4OwoKICAgICAgY29uc3QgbGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOwogICAgICBsZWZ0LmNsYXNzTmFtZSA9ICdyb3ctbGVmdCc7CgogICAgICBjb25zdCBsYWJlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOwogICAgICBsYWJlbC5jbGFzc05hbWUgPSAncm93LWxhYmVsJzsKICAgICAgbGFiZWwudGV4dENvbnRlbnQgPSBpdC5sYWJlbDsKCiAgICAgIGNvbnN0IGN1cnJlbnRCaW5kID0gaXRlbUJpbmRzW2l0LmlkXTsKICAgICAgaWYgKGN1cnJlbnRCaW5kKSB7CiAgICAgICAgY29uc3QgYmFkZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7CiAgICAgICAgYmFkZ2UuY2xhc3NOYW1lID0gJ2l0ZW0tYmluZC1iYWRnZSc7CiAgICAgICAgYmFkZ2UudGV4dENvbnRlbnQgPSBgWyAke2N1cnJlbnRCaW5kfSBdYDsKICAgICAgICBsYWJlbC5hcHBlbmRDaGlsZChiYWRnZSk7CiAgICAgIH0KICAgICAgbGVmdC5hcHBlbmRDaGlsZChsYWJlbCk7CgogICAgICBjb25zdCByaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOwogICAgICByaWdodC5jbGFzc05hbWUgPSAncm93LXJpZ2h0JzsKCiAgICAgIGlmIChpdC50eXBlID09PSAndG9nZ2xlJykgewogICAgICAgIGNvbnN0IHN3ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICAgICAgc3cuY2xhc3NOYW1lID0gJ3Jvdy1zd2l0Y2gnICsgKGl0LnN0YXRlID8gJyBvbicgOiAnJyk7CiAgICAgICAgcmlnaHQuYXBwZW5kQ2hpbGQoc3cpOwogICAgICB9IGVsc2UgaWYgKGl0LnZhbHVlKSB7CiAgICAgICAgY29uc3QgdmFsVGFnID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICAgICAgdmFsVGFnLmNsYXNzTmFtZSA9ICdyb3ctdmFsdWUnOwogICAgICAgIHZhbFRhZy50ZXh0Q29udGVudCA9IGA8ICR7aXQudmFsdWV9ID5gOwogICAgICAgIHJpZ2h0LmFwcGVuZENoaWxkKHZhbFRhZyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3QgY2hldiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOwogICAgICAgIGNoZXYuY2xhc3NOYW1lID0gJ3Jvdy1jaGV2cm9uJzsKICAgICAgICBjaGV2LnRleHRDb250ZW50ID0gJ+KAuic7CiAgICAgICAgcmlnaHQuYXBwZW5kQ2hpbGQoY2hldik7CiAgICAgIH0KCiAgICAgIHJvdy5hcHBlbmRDaGlsZChsZWZ0KTsKICAgICAgcm93LmFwcGVuZENoaWxkKHJpZ2h0KTsKCiAgICAgIHJvdy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHsKICAgICAgICBzZWxlY3RlZEl0ZW1JbmRleCA9IGluZGV4OwogICAgICAgIHVwZGF0ZUFjdGl2ZVN0YXRlKCk7CiAgICAgICAgZXhlY3V0ZUN1cnJlbnRJdGVtKCk7CiAgICAgIH0pOwoKICAgICAgcm93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZW50ZXInLCAoKSA9PiB7CiAgICAgICAgc2VsZWN0ZWRJdGVtSW5kZXggPSBpbmRleDsKICAgICAgICB1cGRhdGVBY3RpdmVTdGF0ZSgpOwogICAgICB9KTsKCiAgICAgIGVsSXRlbXNMaXN0LmFwcGVuZENoaWxkKHJvdyk7CiAgICB9KTsKCiAgICB1cGRhdGVBY3RpdmVTdGF0ZSgpOwogIH0KCiAgLy8gUmVuZGVyIE9uZVN5bmMgUGxheWVycyBMaXN0IGluIE9ubGluZSB0YWIKICBmdW5jdGlvbiByZW5kZXJQbGF5ZXJzTGlzdCgpIHsKICAgIGVsSXRlbXNMaXN0LmlubmVySFRNTCA9ICcnOwoKICAgIGlmIChvbmxpbmVQbGF5ZXJzLmxlbmd0aCA9PT0gMCkgewogICAgICBvbmxpbmVQbGF5ZXJzID0gWy4uLkRFRkFVTFRfU0lNVUxBVEVEX1BMQVlFUlNdOwogICAgfQoKICAgIG9ubGluZVBsYXllcnMuZm9yRWFjaCgocCwgaW5kZXgpID0+IHsKICAgICAgY29uc3QgaXNTZWwgPSBzZWxlY3RlZFBsYXllcklkcy5oYXMocC5zZXJ2ZXJJZCk7CiAgICAgIGNvbnN0IGlzQ3VyID0gKHAuc2VydmVySWQgPT09IGN1cnJlbnRUYXJnZXRJZCk7CgogICAgICBjb25zdCBjYXJkID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICAgIGNhcmQuY2xhc3NOYW1lID0gJ3BsYXllci1jYXJkJyArIChpc1NlbCA/ICcgc2VsZWN0ZWQnIDogJycpICsgKGluZGV4ID09PSBzZWxlY3RlZEl0ZW1JbmRleCA/ICcgYWN0aXZlJyA6ICcnKTsKICAgICAgY2FyZC5kYXRhc2V0LmluZGV4ID0gaW5kZXg7CgogICAgICBjb25zdCBsZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICAgIGxlZnQuY2xhc3NOYW1lID0gJ3BsYXllci1sZWZ0JzsKCiAgICAgIGNvbnN0IGNoZWNrID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICAgIGNoZWNrLmNsYXNzTmFtZSA9ICdwbGF5ZXItY2hlY2snOwogICAgICBjaGVjay50ZXh0Q29udGVudCA9IGlzU2VsID8gJ+KckycgOiAnJzsKCiAgICAgIGNvbnN0IGlkQmFkZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsKICAgICAgaWRCYWRnZS5jbGFzc05hbWUgPSAncGxheWVyLWlkJzsKICAgICAgaWRCYWRnZS50ZXh0Q29udGVudCA9IGAjJHtwLnNlcnZlcklkfWA7CgogICAgICBjb25zdCBuYW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICAgIG5hbWUuY2xhc3NOYW1lID0gJ3BsYXllci1uYW1lJzsKICAgICAgbmFtZS50ZXh0Q29udGVudCA9IHAubmFtZTsKCiAgICAgIGxlZnQuYXBwZW5kQ2hpbGQoY2hlY2spOwogICAgICBsZWZ0LmFwcGVuZENoaWxkKGlkQmFkZ2UpOwogICAgICBsZWZ0LmFwcGVuZENoaWxkKG5hbWUpOwoKICAgICAgY29uc3QgcmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsKICAgICAgcmlnaHQuY2xhc3NOYW1lID0gJ3BsYXllci1yaWdodCc7CgogICAgICBjb25zdCBkaXN0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICAgIGRpc3QuY2xhc3NOYW1lID0gJ3BsYXllci1kaXN0JzsKICAgICAgZGlzdC50ZXh0Q29udGVudCA9IGAke3AuZGlzdH1tYDsKICAgICAgcmlnaHQuYXBwZW5kQ2hpbGQoZGlzdCk7CgogICAgICBjYXJkLmFwcGVuZENoaWxkKGxlZnQpOwogICAgICBjYXJkLmFwcGVuZENoaWxkKHJpZ2h0KTsKCiAgICAgIGNhcmQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7CiAgICAgICAgc2VsZWN0ZWRJdGVtSW5kZXggPSBpbmRleDsKICAgICAgICBpZiAoc2VsZWN0ZWRQbGF5ZXJJZHMuaGFzKHAuc2VydmVySWQpKSB7CiAgICAgICAgICBzZWxlY3RlZFBsYXllcklkcy5kZWxldGUocC5zZXJ2ZXJJZCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHNlbGVjdGVkUGxheWVySWRzLmFkZChwLnNlcnZlcklkKTsKICAgICAgICB9CiAgICAgICAgY3VycmVudFRhcmdldElkID0gcC5zZXJ2ZXJJZDsKICAgICAgICByZW5kZXJQbGF5ZXJzTGlzdCgpOwogICAgICAgIHVwZGF0ZUFjdGl2ZVN0YXRlKCk7CiAgICAgIH0pOwoKICAgICAgY2FyZC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWVudGVyJywgKCkgPT4gewogICAgICAgIHNlbGVjdGVkSXRlbUluZGV4ID0gaW5kZXg7CiAgICAgICAgdXBkYXRlQWN0aXZlU3RhdGUoKTsKICAgICAgfSk7CgogICAgICBlbEl0ZW1zTGlzdC5hcHBlbmRDaGlsZChjYXJkKTsKICAgIH0pOwoKICAgIGlmIChlbFRvb2xDb3VudGVyKSB7CiAgICAgIGVsVG9vbENvdW50ZXIuaW5uZXJIVE1MID0gYFNlbGVjdGVkOiA8Yj4ke3NlbGVjdGVkUGxheWVySWRzLnNpemV9PC9iPmA7CiAgICB9CiAgICB1cGRhdGVBY3RpdmVTdGF0ZSgpOwogIH0KCiAgLy8gQWN0aXZlIHN0YXRlIHN0eWxpbmcgJiBGb290ZXIgQ291bnRlcnMKICBmdW5jdGlvbiB1cGRhdGVBY3RpdmVTdGF0ZSgpIHsKICAgIGlmIChjdXJyZW50TGV2ZWwgPT09IDEpIHsKICAgICAgY29uc3Qgcm93cyA9IGVsSXRlbXNMaXN0LnF1ZXJ5U2VsZWN0b3JBbGwoJy5tZW51LXJvdycpOwogICAgICByb3dzLmZvckVhY2goKHIsIGlkeCkgPT4gewogICAgICAgIGlmIChpZHggPT09IHNlbGVjdGVkQ2F0ZWdvcnlJbmRleCkgewogICAgICAgICAgci5jbGFzc0xpc3QuYWRkKCdhY3RpdmUnKTsKICAgICAgICAgIHIuc2Nyb2xsSW50b1ZpZXcoeyBiZWhhdmlvcjogJ3Ntb290aCcsIGJsb2NrOiAnbmVhcmVzdCcgfSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHIuY2xhc3NMaXN0LnJlbW92ZSgnYWN0aXZlJyk7CiAgICAgICAgfQogICAgICB9KTsKCiAgICAgIGNvbnN0IGNhdCA9IENBVEVHT1JJRVNbc2VsZWN0ZWRDYXRlZ29yeUluZGV4XTsKICAgICAgaWYgKGVsRm9vdGVyQ291bnRlcikgZWxGb290ZXJDb3VudGVyLnRleHRDb250ZW50ID0gYCR7c2VsZWN0ZWRDYXRlZ29yeUluZGV4ICsgMX0gLyAke0NBVEVHT1JJRVMubGVuZ3RofWA7CiAgICAgIGlmIChlbFRvb2x0aXBUZXh0ICYmIGNhdCkgZWxUb29sdGlwVGV4dC50ZXh0Q29udGVudCA9IGNhdC5kZXNjOwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgY3VyQ2F0ID0gQ0FURUdPUklFU1tzZWxlY3RlZENhdGVnb3J5SW5kZXhdOwogICAgICBjb25zdCBjdXJTdWJ0YWIgPSBjdXJDYXQ/LnN1YnRhYnNbYWN0aXZlU3VidGFiSW5kZXhdOwoKICAgICAgaWYgKGN1clN1YnRhYiAmJiBjdXJTdWJ0YWIuaXNQbGF5ZXJMaXN0KSB7CiAgICAgICAgY29uc3QgY2FyZHMgPSBlbEl0ZW1zTGlzdC5xdWVyeVNlbGVjdG9yQWxsKCcucGxheWVyLWNhcmQnKTsKICAgICAgICBjYXJkcy5mb3JFYWNoKChjLCBpZHgpID0+IHsKICAgICAgICAgIGlmIChpZHggPT09IHNlbGVjdGVkSXRlbUluZGV4KSB7CiAgICAgICAgICAgIGMuY2xhc3NMaXN0LmFkZCgnYWN0aXZlJyk7CiAgICAgICAgICAgIGMuc2Nyb2xsSW50b1ZpZXcoeyBiZWhhdmlvcjogJ3Ntb290aCcsIGJsb2NrOiAnbmVhcmVzdCcgfSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBjLmNsYXNzTGlzdC5yZW1vdmUoJ2FjdGl2ZScpOwogICAgICAgICAgfQogICAgICAgIH0pOwoKICAgICAgICBjb25zdCBwID0gb25saW5lUGxheWVyc1tzZWxlY3RlZEl0ZW1JbmRleF07CiAgICAgICAgaWYgKGVsRm9vdGVyQ291bnRlcikgZWxGb290ZXJDb3VudGVyLnRleHRDb250ZW50ID0gYCR7c2VsZWN0ZWRJdGVtSW5kZXggKyAxfSAvICR7b25saW5lUGxheWVycy5sZW5ndGh9YDsKICAgICAgICBpZiAoZWxUb29sdGlwVGV4dCAmJiBwKSBlbFRvb2x0aXBUZXh0LnRleHRDb250ZW50ID0gYFBsYXllciAjJHtwLnNlcnZlcklkfSAke3AubmFtZX0gKCR7cC5kaXN0fW0gYXdheSkuIFByZXNzIEVudGVyIHRvIHNlbGVjdC5gOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IHJvd3MgPSBlbEl0ZW1zTGlzdC5xdWVyeVNlbGVjdG9yQWxsKCcubWVudS1yb3cnKTsKICAgICAgICBsZXQgZWZmZWN0aXZlSWR4ID0gMDsKICAgICAgICBjb25zdCBpdGVtcyA9IGN1clN1YnRhYiA/IGN1clN1YnRhYi5pdGVtcyA6IFtdOwoKICAgICAgICBpdGVtcy5mb3JFYWNoKChpdCwgaWR4KSA9PiB7CiAgICAgICAgICBpZiAoaXQuaXNIZWFkZXIpIHJldHVybjsKICAgICAgICAgIGNvbnN0IHIgPSByb3dzW2VmZmVjdGl2ZUlkeF07CiAgICAgICAgICBpZiAocikgewogICAgICAgICAgICBpZiAoaWR4ID09PSBzZWxlY3RlZEl0ZW1JbmRleCkgewogICAgICAgICAgICAgIHIuY2xhc3NMaXN0LmFkZCgnYWN0aXZlJyk7CiAgICAgICAgICAgICAgci5zY3JvbGxJbnRvVmlldyh7IGJlaGF2aW9yOiAnc21vb3RoJywgYmxvY2s6ICduZWFyZXN0JyB9KTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByLmNsYXNzTGlzdC5yZW1vdmUoJ2FjdGl2ZScpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBlZmZlY3RpdmVJZHgrKzsKICAgICAgICB9KTsKCiAgICAgICAgY29uc3QgaXRtID0gaXRlbXNbc2VsZWN0ZWRJdGVtSW5kZXhdOwogICAgICAgIGNvbnN0IG5vbkhlYWRlcnMgPSBpdGVtcy5maWx0ZXIoaSA9PiAhaS5pc0hlYWRlcik7CiAgICAgICAgY29uc3QgaXRlbVJhbmsgPSBub25IZWFkZXJzLmluZGV4T2YoaXRtKSArIDE7CiAgICAgICAgaWYgKGVsRm9vdGVyQ291bnRlcikgZWxGb290ZXJDb3VudGVyLnRleHRDb250ZW50ID0gYCR7aXRlbVJhbmsgPiAwID8gaXRlbVJhbmsgOiAxfSAvICR7bm9uSGVhZGVycy5sZW5ndGh9YDsKICAgICAgICBpZiAoZWxUb29sdGlwVGV4dCAmJiBpdG0pIGVsVG9vbHRpcFRleHQudGV4dENvbnRlbnQgPSBpdG0uZGVzYyB8fCBgJHtpdG0ubGFiZWx9IGFjdGlvbi5gOwogICAgICB9CiAgICB9CiAgfQoKICBmdW5jdGlvbiBnZXROZXh0Tm9uSGVhZGVySW5kZXgoaXRlbXMsIHN0YXJ0SWR4LCBkZWx0YSkgewogICAgaWYgKCFpdGVtcyB8fCBpdGVtcy5sZW5ndGggPT09IDApIHJldHVybiAwOwogICAgY29uc3QgbGVuID0gaXRlbXMubGVuZ3RoOwogICAgbGV0IGlkeCA9IHN0YXJ0SWR4ICsgZGVsdGE7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7CiAgICAgIGlmIChpZHggPj0gbGVuKSBpZHggPSAwOwogICAgICBlbHNlIGlmIChpZHggPCAwKSBpZHggPSBsZW4gLSAxOwogICAgICBpZiAoaXRlbXNbaWR4XSAmJiAhaXRlbXNbaWR4XS5pc0hlYWRlcikgewogICAgICAgIHJldHVybiBpZHg7CiAgICAgIH0KICAgICAgaWR4ICs9IGRlbHRhOwogICAgfQogICAgcmV0dXJuIE1hdGgubWF4KDAsIHN0YXJ0SWR4KTsKICB9CgogIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgLy8gICAgICAgICAgICAgICAgICBOQVZJR0FUSU9OIEFDVElPTlMKICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKICBmdW5jdGlvbiBlbnRlckNhdGVnb3J5KCkgewogICAgY3VycmVudExldmVsID0gMjsKICAgIGFjdGl2ZVN1YnRhYkluZGV4ID0gMDsKICAgIGNvbnN0IGN1ckNhdCA9IENBVEVHT1JJRVNbc2VsZWN0ZWRDYXRlZ29yeUluZGV4XTsKICAgIGNvbnN0IGN1clN1YiA9IGN1ckNhdD8uc3VidGFic1thY3RpdmVTdWJ0YWJJbmRleF07CiAgICBpZiAoY3VyU3ViPy5pc1BsYXllckxpc3QpIHsKICAgICAgc2VsZWN0ZWRJdGVtSW5kZXggPSAwOwogICAgfSBlbHNlIHsKICAgICAgc2VsZWN0ZWRJdGVtSW5kZXggPSBnZXROZXh0Tm9uSGVhZGVySW5kZXgoY3VyU3ViPy5pdGVtcyB8fCBbXSwgLTEsIDEpOwogICAgfQogICAgcmVuZGVyKCk7CiAgfQoKICBmdW5jdGlvbiBnb0JhY2soKSB7CiAgICBpZiAoY3VycmVudExldmVsID09PSAyKSB7CiAgICAgIGN1cnJlbnRMZXZlbCA9IDE7CiAgICAgIHNlbGVjdGVkSXRlbUluZGV4ID0gMDsKICAgICAgcmVuZGVyKCk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBwcmV2U3VidGFiKCkgewogICAgaWYgKGN1cnJlbnRMZXZlbCAhPT0gMikgcmV0dXJuOwogICAgY29uc3QgY3VyQ2F0ID0gQ0FURUdPUklFU1tzZWxlY3RlZENhdGVnb3J5SW5kZXhdOwogICAgaWYgKCFjdXJDYXQgfHwgIWN1ckNhdC5zdWJ0YWJzIHx8IGN1ckNhdC5zdWJ0YWJzLmxlbmd0aCA8PSAxKSByZXR1cm47CiAgICBhY3RpdmVTdWJ0YWJJbmRleCA9IChhY3RpdmVTdWJ0YWJJbmRleCAtIDEgKyBjdXJDYXQuc3VidGFicy5sZW5ndGgpICUgY3VyQ2F0LnN1YnRhYnMubGVuZ3RoOwogICAgY29uc3QgY3VyU3ViID0gY3VyQ2F0LnN1YnRhYnNbYWN0aXZlU3VidGFiSW5kZXhdOwogICAgaWYgKGN1clN1Yj8uaXNQbGF5ZXJMaXN0KSB7CiAgICAgIHNlbGVjdGVkSXRlbUluZGV4ID0gMDsKICAgIH0gZWxzZSB7CiAgICAgIHNlbGVjdGVkSXRlbUluZGV4ID0gZ2V0TmV4dE5vbkhlYWRlckluZGV4KGN1clN1Yj8uaXRlbXMgfHwgW10sIC0xLCAxKTsKICAgIH0KICAgIHJlbmRlclN1Ym1lbnUoKTsKICB9CgogIGZ1bmN0aW9uIG5leHRTdWJ0YWIoKSB7CiAgICBpZiAoY3VycmVudExldmVsICE9PSAyKSByZXR1cm47CiAgICBjb25zdCBjdXJDYXQgPSBDQVRFR09SSUVTW3NlbGVjdGVkQ2F0ZWdvcnlJbmRleF07CiAgICBpZiAoIWN1ckNhdCB8fCAhY3VyQ2F0LnN1YnRhYnMgfHwgY3VyQ2F0LnN1YnRhYnMubGVuZ3RoIDw9IDEpIHJldHVybjsKICAgIGFjdGl2ZVN1YnRhYkluZGV4ID0gKGFjdGl2ZVN1YnRhYkluZGV4ICsgMSkgJSBjdXJDYXQuc3VidGFicy5sZW5ndGg7CiAgICBjb25zdCBjdXJTdWIgPSBjdXJDYXQuc3VidGFic1thY3RpdmVTdWJ0YWJJbmRleF07CiAgICBpZiAoY3VyU3ViPy5pc1BsYXllckxpc3QpIHsKICAgICAgc2VsZWN0ZWRJdGVtSW5kZXggPSAwOwogICAgfSBlbHNlIHsKICAgICAgc2VsZWN0ZWRJdGVtSW5kZXggPSBnZXROZXh0Tm9uSGVhZGVySW5kZXgoY3VyU3ViPy5pdGVtcyB8fCBbXSwgLTEsIDEpOwogICAgfQogICAgcmVuZGVyU3VibWVudSgpOwogIH0KCiAgZnVuY3Rpb24gbmF2aWdhdGVVcCgpIHsKICAgIGlmIChjdXJyZW50TGV2ZWwgPT09IDEpIHsKICAgICAgc2VsZWN0ZWRDYXRlZ29yeUluZGV4ID0gKHNlbGVjdGVkQ2F0ZWdvcnlJbmRleCAtIDEgKyBDQVRFR09SSUVTLmxlbmd0aCkgJSBDQVRFR09SSUVTLmxlbmd0aDsKICAgICAgdXBkYXRlQWN0aXZlU3RhdGUoKTsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IGN1ckNhdCA9IENBVEVHT1JJRVNbc2VsZWN0ZWRDYXRlZ29yeUluZGV4XTsKICAgICAgY29uc3QgY3VyU3VidGFiID0gY3VyQ2F0Py5zdWJ0YWJzW2FjdGl2ZVN1YnRhYkluZGV4XTsKCiAgICAgIGlmIChjdXJTdWJ0YWIgJiYgY3VyU3VidGFiLmlzUGxheWVyTGlzdCkgewogICAgICAgIGlmIChvbmxpbmVQbGF5ZXJzLmxlbmd0aCA9PT0gMCkgcmV0dXJuOwogICAgICAgIHNlbGVjdGVkSXRlbUluZGV4ID0gKHNlbGVjdGVkSXRlbUluZGV4IC0gMSArIG9ubGluZVBsYXllcnMubGVuZ3RoKSAlIG9ubGluZVBsYXllcnMubGVuZ3RoOwogICAgICAgIHVwZGF0ZUFjdGl2ZVN0YXRlKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3QgaXRlbXMgPSBjdXJTdWJ0YWIgPyBjdXJTdWJ0YWIuaXRlbXMgOiBbXTsKICAgICAgICBpZiAoaXRlbXMubGVuZ3RoID09PSAwKSByZXR1cm47CiAgICAgICAgc2VsZWN0ZWRJdGVtSW5kZXggPSBnZXROZXh0Tm9uSGVhZGVySW5kZXgoaXRlbXMsIHNlbGVjdGVkSXRlbUluZGV4LCAtMSk7CiAgICAgICAgdXBkYXRlQWN0aXZlU3RhdGUoKTsKICAgICAgfQogICAgfQogIH0KCiAgZnVuY3Rpb24gbmF2aWdhdGVEb3duKCkgewogICAgaWYgKGN1cnJlbnRMZXZlbCA9PT0gMSkgewogICAgICBzZWxlY3RlZENhdGVnb3J5SW5kZXggPSAoc2VsZWN0ZWRDYXRlZ29yeUluZGV4ICsgMSkgJSBDQVRFR09SSUVTLmxlbmd0aDsKICAgICAgdXBkYXRlQWN0aXZlU3RhdGUoKTsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IGN1ckNhdCA9IENBVEVHT1JJRVNbc2VsZWN0ZWRDYXRlZ29yeUluZGV4XTsKICAgICAgY29uc3QgY3VyU3VidGFiID0gY3VyQ2F0Py5zdWJ0YWJzW2FjdGl2ZVN1YnRhYkluZGV4XTsKCiAgICAgIGlmIChjdXJTdWJ0YWIgJiYgY3VyU3VidGFiLmlzUGxheWVyTGlzdCkgewogICAgICAgIGlmIChvbmxpbmVQbGF5ZXJzLmxlbmd0aCA9PT0gMCkgcmV0dXJuOwogICAgICAgIHNlbGVjdGVkSXRlbUluZGV4ID0gKHNlbGVjdGVkSXRlbUluZGV4ICsgMSkgJSBvbmxpbmVQbGF5ZXJzLmxlbmd0aDsKICAgICAgICB1cGRhdGVBY3RpdmVTdGF0ZSgpOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IGl0ZW1zID0gY3VyU3VidGFiID8gY3VyU3VidGFiLml0ZW1zIDogW107CiAgICAgICAgaWYgKGl0ZW1zLmxlbmd0aCA9PT0gMCkgcmV0dXJuOwogICAgICAgIHNlbGVjdGVkSXRlbUluZGV4ID0gZ2V0TmV4dE5vbkhlYWRlckluZGV4KGl0ZW1zLCBzZWxlY3RlZEl0ZW1JbmRleCwgMSk7CiAgICAgICAgdXBkYXRlQWN0aXZlU3RhdGUoKTsKICAgICAgfQogICAgfQogIH0KCiAgZnVuY3Rpb24gZXhlY3V0ZUZlYXR1cmVCeUlkKGl0ZW1JZCkgewogICAgbGV0IGZvdW5kSXRlbSA9IG51bGw7CiAgICBDQVRFR09SSUVTLmZvckVhY2goY2F0ID0+IHsKICAgICAgY2F0LnN1YnRhYnM/LmZvckVhY2goc3ViID0+IHsKICAgICAgICBzdWIuaXRlbXM/LmZvckVhY2goaXQgPT4gewogICAgICAgICAgaWYgKGl0LmlkID09PSBpdGVtSWQpIGZvdW5kSXRlbSA9IGl0OwogICAgICAgIH0pOwogICAgICB9KTsKICAgIH0pOwoKICAgIGlmICghZm91bmRJdGVtKSByZXR1cm47CgogICAgaWYgKGZvdW5kSXRlbS50eXBlID09PSAndG9nZ2xlJykgewogICAgICBmb3VuZEl0ZW0uc3RhdGUgPSAhZm91bmRJdGVtLnN0YXRlOwogICAgICBoYW5kbGVUb2dnbGVGZWF0dXJlKGZvdW5kSXRlbS5pZCwgZm91bmRJdGVtLnN0YXRlKTsKICAgICAgaWYgKGN1cnJlbnRMZXZlbCA9PT0gMikgcmVuZGVyU3VibWVudSgpOwogICAgfSBlbHNlIGlmIChmb3VuZEl0ZW0udHlwZSA9PT0gJ2FjdGlvbicpIHsKICAgICAgaGFuZGxlQWN0aW9uRmVhdHVyZShmb3VuZEl0ZW0uaWQpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gZXhlY3V0ZUN1cnJlbnRJdGVtKCkgewogICAgaWYgKGN1cnJlbnRMZXZlbCA9PT0gMSkgewogICAgICBlbnRlckNhdGVnb3J5KCk7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBjb25zdCBjdXJDYXQgPSBDQVRFR09SSUVTW3NlbGVjdGVkQ2F0ZWdvcnlJbmRleF07CiAgICBjb25zdCBjdXJTdWJ0YWIgPSBjdXJDYXQ/LnN1YnRhYnNbYWN0aXZlU3VidGFiSW5kZXhdOwoKICAgIGlmIChjdXJTdWJ0YWIgJiYgY3VyU3VidGFiLmlzUGxheWVyTGlzdCkgewogICAgICBjb25zdCBwID0gb25saW5lUGxheWVyc1tzZWxlY3RlZEl0ZW1JbmRleF07CiAgICAgIGlmIChwKSB7CiAgICAgICAgaWYgKHNlbGVjdGVkUGxheWVySWRzLmhhcyhwLnNlcnZlcklkKSkgewogICAgICAgICAgc2VsZWN0ZWRQbGF5ZXJJZHMuZGVsZXRlKHAuc2VydmVySWQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzZWxlY3RlZFBsYXllcklkcy5hZGQocC5zZXJ2ZXJJZCk7CiAgICAgICAgfQogICAgICAgIGN1cnJlbnRUYXJnZXRJZCA9IHAuc2VydmVySWQ7CiAgICAgICAgcmVuZGVyUGxheWVyc0xpc3QoKTsKICAgICAgfQogICAgICByZXR1cm47CiAgICB9CgogICAgY29uc3QgaXRlbSA9IGN1clN1YnRhYj8uaXRlbXNbc2VsZWN0ZWRJdGVtSW5kZXhdOwogICAgaWYgKCFpdGVtIHx8IGl0ZW0uaXNIZWFkZXIpIHJldHVybjsKCiAgICBpZiAoaXRlbS50eXBlID09PSAndG9nZ2xlJykgewogICAgICBpdGVtLnN0YXRlID0gIWl0ZW0uc3RhdGU7CiAgICAgIGhhbmRsZVRvZ2dsZUZlYXR1cmUoaXRlbS5pZCwgaXRlbS5zdGF0ZSk7CiAgICAgIHJlbmRlclN1Ym1lbnUoKTsKICAgIH0gZWxzZSBpZiAoaXRlbS50eXBlID09PSAnYWN0aW9uJykgewogICAgICBoYW5kbGVBY3Rpb25GZWF0dXJlKGl0ZW0uaWQpOwogICAgfQogIH0KCiAgLy8gRmVhdHVyZSBBY3Rpb24gSGFuZGxlcnMgJiBIVUQgVHJpZ2dlcnMKICBmdW5jdGlvbiBoYW5kbGVUb2dnbGVGZWF0dXJlKGFjdGlvbklkLCBzdGF0ZSkgewogICAgc2hvd05vdGlmaWNhdGlvbihgJHthY3Rpb25JZC5yZXBsYWNlKC9fL2csICcgJykudG9VcHBlckNhc2UoKX06ICR7c3RhdGUgPyAnRU5BQkxFRCcgOiAnRElTQUJMRUQnfWAsIHN0YXRlID8gJ3N1Y2Nlc3MnIDogJ3dhcm5pbmcnKTsKICAgIGlmIChhY3Rpb25JZCA9PT0gJ3NwZWN0YXRvcl9odWQnKSB7CiAgICAgIHRvZ2dsZUh1ZCgnc3BlY3RhdG9yJywgc3RhdGUpOwogICAgfSBlbHNlIGlmIChhY3Rpb25JZCA9PT0gJ2JpbmRzX2h1ZCcpIHsKICAgICAgdG9nZ2xlSHVkKCdiaW5kcycsIHN0YXRlKTsKICAgIH0gZWxzZSBpZiAoYWN0aW9uSWQgPT09ICdkcmFnX3VpX21vZGUnKSB7CiAgICAgIHNldERyYWdNb2RlKHN0YXRlKTsKICAgIH0gZWxzZSBpZiAoYWN0aW9uSWQgPT09ICdmcmVlY2FtX3BsYWNlcicpIHsKICAgICAgaWYgKHN0YXRlKSBvcGVuUXVpY2tQbGFjZXIoJ3Byb3BzJyk7CiAgICAgIGVsc2UgY2xvc2VRdWlja1BsYWNlcigpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gaGFuZGxlQWN0aW9uRmVhdHVyZShhY3Rpb25JZCkgewogICAgaWYgKGFjdGlvbklkID09PSAnY2hlY2tfYW50aWNoZWF0cycpIHsKICAgICAgc3RhcnRBbnRpY2hlYXRTY2FuKCk7CiAgICB9IGVsc2UgaWYgKGFjdGlvbklkID09PSAncmVzZXRfaHVkX2xheW91dCcpIHsKICAgICAgWydtZW51JywgJ2JpbmRzJywgJ3NwZWN0YXRvcicsICdwbGFjZXInXS5mb3JFYWNoKGsgPT4gewogICAgICAgIGxvY2FsU3RvcmFnZS5yZW1vdmVJdGVtKGB3dHJfcG9zXyR7a31gKTsKICAgICAgICBsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbShgd3RyX3NpemVfJHtrfWApOwogICAgICB9KTsKICAgICAgY29uc3QgbWVudUVsID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLm1lbnUtd3JhcHBlcicpOwogICAgICBpZiAobWVudUVsKSB7CiAgICAgICAgbWVudUVsLnN0eWxlLnRvcCA9ICcnOyBtZW51RWwuc3R5bGUubGVmdCA9ICcnOyBtZW51RWwuc3R5bGUucmlnaHQgPSAnJzsgbWVudUVsLnN0eWxlLmJvdHRvbSA9ICcnOwogICAgICAgIG1lbnVFbC5zdHlsZS53aWR0aCA9ICcnOyBtZW51RWwuc3R5bGUuaGVpZ2h0ID0gJyc7IG1lbnVFbC5zdHlsZS5wb3NpdGlvbiA9ICcnOyBtZW51RWwuc3R5bGUudHJhbnNmb3JtID0gJyc7CiAgICAgIH0KICAgICAgaWYgKGVsS2V5YmluZHNMaXN0SHVkKSB7CiAgICAgICAgZWxLZXliaW5kc0xpc3RIdWQuc3R5bGUudG9wID0gJyc7IGVsS2V5YmluZHNMaXN0SHVkLnN0eWxlLmxlZnQgPSAnJzsgZWxLZXliaW5kc0xpc3RIdWQuc3R5bGUucmlnaHQgPSAnJzsgZWxLZXliaW5kc0xpc3RIdWQuc3R5bGUuYm90dG9tID0gJyc7CiAgICAgICAgZWxLZXliaW5kc0xpc3RIdWQuc3R5bGUud2lkdGggPSAnJzsgZWxLZXliaW5kc0xpc3RIdWQuc3R5bGUuaGVpZ2h0ID0gJyc7IGVsS2V5YmluZHNMaXN0SHVkLnN0eWxlLnBvc2l0aW9uID0gJyc7CiAgICAgIH0KICAgICAgaWYgKGVsU3BlY3RhdG9yTGlzdEh1ZCkgewogICAgICAgIGVsU3BlY3RhdG9yTGlzdEh1ZC5zdHlsZS50b3AgPSAnJzsgZWxTcGVjdGF0b3JMaXN0SHVkLnN0eWxlLmxlZnQgPSAnJzsgZWxTcGVjdGF0b3JMaXN0SHVkLnN0eWxlLnJpZ2h0ID0gJyc7IGVsU3BlY3RhdG9yTGlzdEh1ZC5zdHlsZS5ib3R0b20gPSAnJzsKICAgICAgICBlbFNwZWN0YXRvckxpc3RIdWQuc3R5bGUud2lkdGggPSAnJzsgZWxTcGVjdGF0b3JMaXN0SHVkLnN0eWxlLmhlaWdodCA9ICcnOyBlbFNwZWN0YXRvckxpc3RIdWQuc3R5bGUucG9zaXRpb24gPSAnJzsKICAgICAgfQogICAgICBpZiAoZWxRdWlja1BsYWNlckh1ZCkgewogICAgICAgIGVsUXVpY2tQbGFjZXJIdWQuc3R5bGUudG9wID0gJyc7IGVsUXVpY2tQbGFjZXJIdWQuc3R5bGUubGVmdCA9ICcnOyBlbFF1aWNrUGxhY2VySHVkLnN0eWxlLnJpZ2h0ID0gJyc7IGVsUXVpY2tQbGFjZXJIdWQuc3R5bGUuYm90dG9tID0gJyc7CiAgICAgICAgZWxRdWlja1BsYWNlckh1ZC5zdHlsZS53aWR0aCA9ICcnOyBlbFF1aWNrUGxhY2VySHVkLnN0eWxlLmhlaWdodCA9ICcnOyBlbFF1aWNrUGxhY2VySHVkLnN0eWxlLnBvc2l0aW9uID0gJyc7IGVsUXVpY2tQbGFjZXJIdWQuc3R5bGUudHJhbnNmb3JtID0gJyc7CiAgICAgIH0KICAgICAgc2hvd05vdGlmaWNhdGlvbignSFVEIHBvc2l0aW9ucyBhbmQgc2l6ZXMgcmVzZXQgdG8gZGVmYXVsdC4nLCAnc3VjY2VzcycpOwogICAgfSBlbHNlIGlmIChhY3Rpb25JZCA9PT0gJ3BsYWNlcl9wcm9wcycgfHwgYWN0aW9uSWQgPT09ICdmcmVlY2FtX3BsYWNlcl9wcm9wcycpIHsKICAgICAgb3BlblF1aWNrUGxhY2VyKCdwcm9wcycpOwogICAgfSBlbHNlIGlmIChhY3Rpb25JZCA9PT0gJ3BsYWNlcl9wZWRzJyB8fCBhY3Rpb25JZCA9PT0gJ2ZyZWVjYW1fcGxhY2VyX3BlZHMnKSB7CiAgICAgIG9wZW5RdWlja1BsYWNlcigncGVkcycpOwogICAgfSBlbHNlIGlmIChhY3Rpb25JZCA9PT0gJ3BsYWNlcl92ZWhzJyB8fCBhY3Rpb25JZCA9PT0gJ2ZyZWVjYW1fcGxhY2VyX3ZlaHMnKSB7CiAgICAgIG9wZW5RdWlja1BsYWNlcigndmVocycpOwogICAgfSBlbHNlIGlmIChhY3Rpb25JZCA9PT0gJ3NwYXduX3ZlaF9pbnB1dCcpIHsKICAgICAgb3Blbk1vZGFsKCd2ZWhpY2xlJywgJ1NQQVdOIFZFSElDTEUnLCAnRW50ZXIgdmVoaWNsZSBtb2RlbCAoZS5nLiBhZGRlcikuLi4nKTsKICAgIH0gZWxzZSBpZiAoYWN0aW9uSWQgPT09ICdzcGF3bl9jdXN0b21fd2VhcG9uJykgewogICAgICBvcGVuTW9kYWwoJ3dlYXBvbicsICdFUVVJUCBXRUFQT04nLCAnRW50ZXIgd2VhcG9uIG1vZGVsIChlLmcuIHdlYXBvbl9yZXZvbHZlcikuLi4nKTsKICAgIH0gZWxzZSBpZiAoYWN0aW9uSWQgPT09ICd0cF9jb29yZHMnKSB7CiAgICAgIG9wZW5Nb2RhbCgnY29vcmRzJywgJ1RFTEVQT1JUIENPT1JEUycsICdFbnRlciBYLCBZLCBaIGNvb3JkaW5hdGVzLi4uJyk7CiAgICB9IGVsc2UgaWYgKGFjdGlvbklkID09PSAnY2ZnX3NhdmUnKSB7CiAgICAgIG9wZW5Nb2RhbCgnY29uZmlnX3NhdmUnLCAnU0FWRSBDT05GSUcgKE9WRVJXUklURSknLCAnRW50ZXIgY29uZmlnIG5hbWUgKGUuZy4gSHZIX0FnZ3Jlc3NpdmUpLi4uJyk7CiAgICB9IGVsc2UgaWYgKGFjdGlvbklkID09PSAnY2ZnX2xvYWQnKSB7CiAgICAgIG9wZW5Nb2RhbCgnY29uZmlnX2xvYWQnLCAnTE9BRCBDT05GSUcnLCAnRW50ZXIgY29uZmlnIG5hbWUgdG8gbG9hZC4uLicpOwogICAgfSBlbHNlIGlmIChhY3Rpb25JZCA9PT0gJ2NmZ19kZWxldGUnKSB7CiAgICAgIG9wZW5Nb2RhbCgnY29uZmlnX2RlbGV0ZScsICdERUxFVEUgQ09ORklHJywgJ0VudGVyIGNvbmZpZyBuYW1lIHRvIGRlbGV0ZS4uLicpOwogICAgfSBlbHNlIGlmIChhY3Rpb25JZCA9PT0gJ2NmZ19zeW5jJykgewogICAgICBzeW5jQ29uZmlnc0Nsb3VkKCk7CiAgICB9IGVsc2UgewogICAgICBzaG93Tm90aWZpY2F0aW9uKGBFeGVjdXRlZDogJHthY3Rpb25JZC5yZXBsYWNlKC9fL2csICcgJykudG9VcHBlckNhc2UoKX1gLCAnaW5mbycpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gc2hvd05vdGlmaWNhdGlvbih0ZXh0LCB0eXBlID0gJ2luZm8nKSB7CiAgICBpZiAoZWxUb29sdGlwVGV4dCkgewogICAgICBlbFRvb2x0aXBUZXh0LnRleHRDb250ZW50ID0gdGV4dDsKICAgICAgZWxUb29sdGlwVGV4dC5zdHlsZS5jb2xvciA9IHR5cGUgPT09ICdzdWNjZXNzJyA/ICcjMjJjNTVlJyA6ICh0eXBlID09PSAnd2FybmluZycgPyAnI2Y1OWUwYicgOiAnIzAwZjBmZicpOwogICAgICBzZXRUaW1lb3V0KCgpID0+IHsKICAgICAgICBpZiAoZWxUb29sdGlwVGV4dCkgZWxUb29sdGlwVGV4dC5zdHlsZS5jb2xvciA9ICcjZTBmMmZlJzsKICAgICAgfSwgMjUwMCk7CiAgICB9CiAgfQoKICAvLyBTdWJ0YWJzIGJ1dHRvbnMKICBpZiAoYnRuUHJldlN1YnRhYikgYnRuUHJldlN1YnRhYi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHByZXZTdWJ0YWIpOwogIGlmIChidG5OZXh0U3VidGFiKSBidG5OZXh0U3VidGFiLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgbmV4dFN1YnRhYik7CgogIC8vIE9ubGluZSBUb29sYmFyIGJ1dHRvbnMKICBpZiAoYnRuU2VsZWN0QWxsKSB7CiAgICBidG5TZWxlY3RBbGwuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7CiAgICAgIG9ubGluZVBsYXllcnMuZm9yRWFjaChwID0+IHNlbGVjdGVkUGxheWVySWRzLmFkZChwLnNlcnZlcklkKSk7CiAgICAgIHJlbmRlclBsYXllcnNMaXN0KCk7CiAgICB9KTsKICB9CgogIGlmIChidG5VbnNlbGVjdEFsbCkgewogICAgYnRuVW5zZWxlY3RBbGwuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7CiAgICAgIHNlbGVjdGVkUGxheWVySWRzLmNsZWFyKCk7CiAgICAgIHJlbmRlclBsYXllcnNMaXN0KCk7CiAgICB9KTsKICB9CgogIGlmIChidG5UYXJnZXRTZWxmKSB7CiAgICBidG5UYXJnZXRTZWxmLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4gewogICAgICBjdXJyZW50VGFyZ2V0SWQgPSAwOwogICAgICBzZWxlY3RlZFBsYXllcklkcy5jbGVhcigpOwogICAgICByZW5kZXJQbGF5ZXJzTGlzdCgpOwogICAgICBzaG93Tm90aWZpY2F0aW9uKCdUYXJnZXQgbG9ja2VkIHRvIExPQ0FMIFNFTEYnLCAnaW5mbycpOwogICAgfSk7CiAgfQoKICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogIC8vICAgICAgICAgICAgICAgICAgUVVJQ0sgUExBQ0VSICYgU1BBV05FUiBFTkdJTkUKICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKICBmdW5jdGlvbiBvcGVuUXVpY2tQbGFjZXIoY2F0ZWdvcnkgPSAncHJvcHMnKSB7CiAgICBwbGFjZXJBY3RpdmUgPSB0cnVlOwogICAgcGxhY2VyQ2F0ZWdvcnkgPSAoY2F0ZWdvcnkgfHwgJ3Byb3BzJykudG9Mb3dlckNhc2UoKTsKICAgIHBsYWNlckluZGV4ID0gMDsKICAgIHVwZGF0ZVBsYWNlckRpc3BsYXkoKTsKICAgIGlmIChlbFF1aWNrUGxhY2VySHVkKSBlbFF1aWNrUGxhY2VySHVkLnN0eWxlLmRpc3BsYXkgPSAnZmxleCc7CiAgICBzaG93Tm90aWZpY2F0aW9uKGBRdWljayBQbGFjZXI6ICR7cGxhY2VyQ2F0ZWdvcnkudG9VcHBlckNhc2UoKX0gQWN0aXZlIChTY3JvbGwgdG8gc2VsZWN0LCBMTUIgdG8gcGxhY2UpYCwgJ2luZm8nKTsKICB9CgogIGZ1bmN0aW9uIGNsb3NlUXVpY2tQbGFjZXIoKSB7CiAgICBwbGFjZXJBY3RpdmUgPSBmYWxzZTsKICAgIGlmIChlbFF1aWNrUGxhY2VySHVkKSBlbFF1aWNrUGxhY2VySHVkLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7CiAgfQoKICBmdW5jdGlvbiB1cGRhdGVQbGFjZXJEaXNwbGF5KCkgewogICAgY29uc3QgbGlzdCA9IFBMQUNFUl9JVEVNU1twbGFjZXJDYXRlZ29yeV0gfHwgW107CiAgICBpZiAobGlzdC5sZW5ndGggPT09IDApIHJldHVybjsKICAgIGlmIChwbGFjZXJJbmRleCA8IDApIHBsYWNlckluZGV4ID0gbGlzdC5sZW5ndGggLSAxOwogICAgaWYgKHBsYWNlckluZGV4ID49IGxpc3QubGVuZ3RoKSBwbGFjZXJJbmRleCA9IDA7CgogICAgY29uc3QgaXRlbSA9IGxpc3RbcGxhY2VySW5kZXhdOwogICAgaWYgKGVsUGxhY2VyQ2F0ZWdvcnkpIGVsUGxhY2VyQ2F0ZWdvcnkudGV4dENvbnRlbnQgPSBwbGFjZXJDYXRlZ29yeS50b1VwcGVyQ2FzZSgpOwogICAgaWYgKGVsUGxhY2VySXRlbU5hbWUpIGVsUGxhY2VySXRlbU5hbWUudGV4dENvbnRlbnQgPSBpdGVtLm5hbWU7CiAgfQoKICBmdW5jdGlvbiBzcGF3blBsYWNlckN1cnJlbnQoKSB7CiAgICBjb25zdCBsaXN0ID0gUExBQ0VSX0lURU1TW3BsYWNlckNhdGVnb3J5XSB8fCBbXTsKICAgIGNvbnN0IGl0ZW0gPSBsaXN0W3BsYWNlckluZGV4XTsKICAgIGlmIChpdGVtKSB7CiAgICAgIHNob3dOb3RpZmljYXRpb24oYFNwYXduZWQ6ICR7aXRlbS5uYW1lfSAoJHtpdGVtLm1vZGVsfSlgLCAnc3VjY2VzcycpOwogICAgfQogIH0KCiAgaWYgKGJ0blBsYWNlclByZXYpIHsKICAgIGJ0blBsYWNlclByZXYuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7CiAgICAgIHBsYWNlckluZGV4LS07CiAgICAgIHVwZGF0ZVBsYWNlckRpc3BsYXkoKTsKICAgIH0pOwogIH0KICBpZiAoYnRuUGxhY2VyTmV4dCkgewogICAgYnRuUGxhY2VyTmV4dC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHsKICAgICAgcGxhY2VySW5kZXgrKzsKICAgICAgdXBkYXRlUGxhY2VyRGlzcGxheSgpOwogICAgfSk7CiAgfQoKICAvLyBNb3VzZSB3aGVlbCBsaXN0ZW5lciBmb3IgUXVpY2sgUGxhY2VyCiAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3doZWVsJywgKGUpID0+IHsKICAgIGlmICghcGxhY2VyQWN0aXZlKSByZXR1cm47CiAgICBpZiAoZS5kZWx0YVkgPiAwKSB7CiAgICAgIHBsYWNlckluZGV4Kys7CiAgICB9IGVsc2UgewogICAgICBwbGFjZXJJbmRleC0tOwogICAgfQogICAgdXBkYXRlUGxhY2VyRGlzcGxheSgpOwogIH0pOwoKICAvLyBNb3VzZSBjbGljayBsaXN0ZW5lciBmb3IgUXVpY2sgUGxhY2VyIHNwYXduCiAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKGUpID0+IHsKICAgIGlmICghcGxhY2VyQWN0aXZlKSByZXR1cm47CiAgICAvLyBJZiBub3QgY2xpY2tpbmcgaW5zaWRlIHRoZSBwbGFjZXIgcGFuZWwgb3IgbWVudSwgc3Bhd24gaXRlbQogICAgaWYgKCFlLnRhcmdldC5jbG9zZXN0KCcjcXVpY2tQbGFjZXJIdWQnKSAmJiAhZS50YXJnZXQuY2xvc2VzdCgnLm1lbnUtY29udGFpbmVyJykpIHsKICAgICAgc3Bhd25QbGFjZXJDdXJyZW50KCk7CiAgICB9CiAgfSk7CgogIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgLy8gICAgICAgICAgICAgICAgICBTUEVDVEFUT1IgUkFEQVIgJiBCSU5EUyBIVUQKICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKICBmdW5jdGlvbiB0b2dnbGVIdWQoaHVkVHlwZSwgdmlzaWJsZSkgewogICAgaWYgKGh1ZFR5cGUgPT09ICdzcGVjdGF0b3InKSB7CiAgICAgIGlmIChlbFNwZWN0YXRvckxpc3RIdWQpIHsKICAgICAgICBlbFNwZWN0YXRvckxpc3RIdWQuc3R5bGUuZGlzcGxheSA9IHZpc2libGUgPyAnZmxleCcgOiAnbm9uZSc7CiAgICAgICAgaWYgKHZpc2libGUpIHVwZGF0ZVNwZWN0YXRvclJhZGFyKCk7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoaHVkVHlwZSA9PT0gJ2JpbmRzJykgewogICAgICBpZiAoZWxLZXliaW5kc0xpc3RIdWQpIHsKICAgICAgICBlbEtleWJpbmRzTGlzdEh1ZC5zdHlsZS5kaXNwbGF5ID0gdmlzaWJsZSA/ICdmbGV4JyA6ICdub25lJzsKICAgICAgICBpZiAodmlzaWJsZSkgdXBkYXRlQmluZHNIdWQoKTsKICAgICAgfQogICAgfQogIH0KCiAgZnVuY3Rpb24gdXBkYXRlU3BlY3RhdG9yUmFkYXIoc3BlY3RhdG9ycyA9IFtdKSB7CiAgICBpZiAoIWVsU3BlY3RhdG9yTGlzdEJvZHkpIHJldHVybjsKICAgIGVsU3BlY3RhdG9yTGlzdEJvZHkuaW5uZXJIVE1MID0gJyc7CgogICAgaWYgKHNwZWN0YXRvcnMubGVuZ3RoID09PSAwKSB7CiAgICAgIGlmIChlbFNwZWN0YXRvckRvdCkgZWxTcGVjdGF0b3JEb3QuY2xhc3NOYW1lID0gJ2h1ZC1kb3Qgc2FmZSc7CiAgICAgIGlmIChlbFNwZWN0YXRvckNvdW50KSBlbFNwZWN0YXRvckNvdW50LnRleHRDb250ZW50ID0gJzAnOwogICAgICBlbFNwZWN0YXRvckxpc3RCb2R5LmlubmVySFRNTCA9ICc8ZGl2IGNsYXNzPSJodWQtZW1wdHkiPk5vIHNwZWN0YXRvcnMgbmVhcmJ5IChTYWZlKTwvZGl2Pic7CiAgICB9IGVsc2UgewogICAgICBpZiAoZWxTcGVjdGF0b3JEb3QpIGVsU3BlY3RhdG9yRG90LmNsYXNzTmFtZSA9ICdodWQtZG90IGRhbmdlcic7CiAgICAgIGlmIChlbFNwZWN0YXRvckNvdW50KSBlbFNwZWN0YXRvckNvdW50LnRleHRDb250ZW50ID0gc3BlY3RhdG9ycy5sZW5ndGg7CgogICAgICBzcGVjdGF0b3JzLmZvckVhY2gocyA9PiB7CiAgICAgICAgY29uc3Qgcm93ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICAgICAgcm93LmNsYXNzTmFtZSA9ICdodWQtcm93IGRhbmdlcic7CiAgICAgICAgcm93LmlubmVySFRNTCA9IGA8c3Bhbj48Yj4ke3MubmFtZX08L2I+IFsjJHtzLmlkfV08L3NwYW4+IDxzcGFuIHN0eWxlPSJmb250LWZhbWlseTogbW9ub3NwYWNlOyI+JHtzLmRpc3R9bTwvc3Bhbj5gOwogICAgICAgIGVsU3BlY3RhdG9yTGlzdEJvZHkuYXBwZW5kQ2hpbGQocm93KTsKICAgICAgfSk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiB1cGRhdGVCaW5kc0h1ZCgpIHsKICAgIGlmICghZWxLZXliaW5kc0xpc3RCb2R5KSByZXR1cm47CiAgICBlbEtleWJpbmRzTGlzdEJvZHkuaW5uZXJIVE1MID0gJyc7CgogICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKGl0ZW1CaW5kcyk7CiAgICBpZiAoZWxCaW5kc0NvdW50KSBlbEJpbmRzQ291bnQudGV4dENvbnRlbnQgPSBrZXlzLmxlbmd0aDsKCiAgICBpZiAoa2V5cy5sZW5ndGggPT09IDApIHsKICAgICAgZWxLZXliaW5kc0xpc3RCb2R5LmlubmVySFRNTCA9ICc8dHI+PHRkIGNvbHNwYW49IjIiIGNsYXNzPSJodWQtZW1wdHkiPk5vIGtleXMgYm91bmQgeWV0IFtGOSBpbiBNZW51XTwvdGQ+PC90cj4nOwogICAgICByZXR1cm47CiAgICB9CgogICAga2V5cy5mb3JFYWNoKGl0ZW1JZCA9PiB7CiAgICAgIGNvbnN0IGtleSA9IGl0ZW1CaW5kc1tpdGVtSWRdOwogICAgICBsZXQgaXRlbUxhYmVsID0gaXRlbUlkOwogICAgICBDQVRFR09SSUVTLmZvckVhY2goY2F0ID0+IHsKICAgICAgICBjYXQuc3VidGFicz8uZm9yRWFjaChzdWIgPT4gewogICAgICAgICAgc3ViLml0ZW1zPy5mb3JFYWNoKGl0ID0+IHsKICAgICAgICAgICAgaWYgKGl0LmlkID09PSBpdGVtSWQpIGl0ZW1MYWJlbCA9IGl0LmxhYmVsOwogICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICAgIH0pOwoKICAgICAgY29uc3QgdHIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0cicpOwogICAgICB0ci5pbm5lckhUTUwgPSBgCiAgICAgICAgPHRkIGNsYXNzPSJ0ZC1mdW5jIiB0aXRsZT0iJHtlc2NhcGVIdG1sKGl0ZW1MYWJlbCl9Ij4ke2VzY2FwZUh0bWwoaXRlbUxhYmVsKX08L3RkPgogICAgICAgIDx0ZCBjbGFzcz0idGQta2V5Ij48c3BhbiBjbGFzcz0iYmluZC1rZXktcGlsbCI+WyAke2VzY2FwZUh0bWwoa2V5KX0gXTwvc3Bhbj48L3RkPgogICAgICBgOwogICAgICBlbEtleWJpbmRzTGlzdEJvZHkuYXBwZW5kQ2hpbGQodHIpOwogICAgfSk7CiAgfQoKICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogIC8vICAgICAgICAgICAgICAgICAgRFJBRyBVSSAmIENPUk5FUiBSRVNJWkUgRU5HSU5FCiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCiAgZnVuY3Rpb24gc2V0RHJhZ01vZGUoYWN0aXZlKSB7CiAgICBpc0RyYWdNb2RlID0gYWN0aXZlOwogICAgaWYgKGFjdGl2ZSkgewogICAgICBkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5hZGQoJ2RyYWctbW9kZS1hY3RpdmUnKTsKICAgICAgc2hvd05vdGlmaWNhdGlvbignRHJhZyBNb2RlIEFDVElWRTogQ2xpY2sgJiBkcmFnIHRvIG1vdmUgb3IgcHVsbCBjb3JuZXJzIHRvIHJlc2l6ZS4nLCAnd2FybmluZycpOwogICAgfSBlbHNlIHsKICAgICAgZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QucmVtb3ZlKCdkcmFnLW1vZGUtYWN0aXZlJyk7CiAgICAgIHNob3dOb3RpZmljYXRpb24oJ0RyYWcgTW9kZSBTQVZFRC4nLCAnc3VjY2VzcycpOwogICAgfQogIH0KCiAgZnVuY3Rpb24gbWFrZURyYWdnYWJsZShlbCwgc3RvcmFnZUtleSwgbWluVyA9IDEzMCwgbWluSCA9IDM2LCBtYXhXID0gNTUwLCBtYXhIID0gNTAwKSB7CiAgICBpZiAoIWVsKSByZXR1cm47CiAgICBsZXQgaXNEcmFnZ2luZyA9IGZhbHNlOwogICAgbGV0IGlzUmVzaXppbmcgPSBmYWxzZTsKICAgIGxldCBzdGFydFgsIHN0YXJ0WSwgb3JpZ0xlZnQsIG9yaWdUb3AsIG9yaWdXLCBvcmlnSDsKCiAgICAvLyBSZXN0b3JlIHBvc2l0aW9uIGZyb20gbG9jYWxTdG9yYWdlCiAgICBjb25zdCBzYXZlZFBvcyA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKGB3dHJfcG9zXyR7c3RvcmFnZUtleX1gKTsKICAgIGlmIChzYXZlZFBvcykgewogICAgICB0cnkgewogICAgICAgIGNvbnN0IHBvcyA9IEpTT04ucGFyc2Uoc2F2ZWRQb3MpOwogICAgICAgIGVsLnN0eWxlLnBvc2l0aW9uID0gJ2ZpeGVkJzsKICAgICAgICBlbC5zdHlsZS5sZWZ0ID0gcG9zLmxlZnQgKyAncHgnOwogICAgICAgIGVsLnN0eWxlLnRvcCA9IHBvcy50b3AgKyAncHgnOwogICAgICAgIGVsLnN0eWxlLnJpZ2h0ID0gJ2F1dG8nOwogICAgICAgIGVsLnN0eWxlLmJvdHRvbSA9ICdhdXRvJzsKICAgICAgICBlbC5zdHlsZS50cmFuc2Zvcm0gPSAnbm9uZSc7CiAgICAgIH0gY2F0Y2ggKGUpIHt9CiAgICB9CgogICAgLy8gUmVzdG9yZSBzaXplIGZyb20gbG9jYWxTdG9yYWdlCiAgICBjb25zdCBzYXZlZFNpemUgPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbShgd3RyX3NpemVfJHtzdG9yYWdlS2V5fWApOwogICAgaWYgKHNhdmVkU2l6ZSkgewogICAgICB0cnkgewogICAgICAgIGNvbnN0IHN6ID0gSlNPTi5wYXJzZShzYXZlZFNpemUpOwogICAgICAgIGlmIChzei53aWR0aCkgZWwuc3R5bGUud2lkdGggPSBzei53aWR0aCArICdweCc7CiAgICAgICAgaWYgKHN6LmhlaWdodCkgZWwuc3R5bGUuaGVpZ2h0ID0gc3ouaGVpZ2h0ICsgJ3B4JzsKICAgICAgfSBjYXRjaCAoZSkge30KICAgIH0KCiAgICAvLyBIb29rIG9yIGFkZCBjb3JuZXIgcmVzaXplciBoYW5kbGUKICAgIGxldCByZXNpemVyID0gZWwucXVlcnlTZWxlY3RvcignLmh1ZC1yZXNpemVyJyk7CiAgICBpZiAoIXJlc2l6ZXIpIHsKICAgICAgcmVzaXplciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOwogICAgICByZXNpemVyLmNsYXNzTmFtZSA9ICdodWQtcmVzaXplcic7CiAgICAgIHJlc2l6ZXIudGl0bGUgPSAnRHJhZyBjb3JuZXIgdG8gcmVzaXplICh3aWRlbi9uYXJyb3cpJzsKICAgICAgZWwuYXBwZW5kQ2hpbGQocmVzaXplcik7CiAgICB9CgogICAgcmVzaXplci5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCAoZSkgPT4gewogICAgICBpc1Jlc2l6aW5nID0gdHJ1ZTsKICAgICAgc3RhcnRYID0gZS5jbGllbnRYOwogICAgICBzdGFydFkgPSBlLmNsaWVudFk7CiAgICAgIGNvbnN0IHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTsKICAgICAgb3JpZ1cgPSByZWN0LndpZHRoOwogICAgICBvcmlnSCA9IHJlY3QuaGVpZ2h0OwogICAgICBlLnN0b3BQcm9wYWdhdGlvbigpOwogICAgICBlLnByZXZlbnREZWZhdWx0KCk7CiAgICB9KTsKCiAgICBlbC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCAoZSkgPT4gewogICAgICBpZiAoZS50YXJnZXQuY2xvc2VzdCgnLmh1ZC1yZXNpemVyJykpIHJldHVybjsKICAgICAgaWYgKCFpc0RyYWdNb2RlKSByZXR1cm47CiAgICAgIGlmIChlLnRhcmdldC50YWdOYW1lID09PSAnSU5QVVQnIHx8IGUudGFyZ2V0LnRhZ05hbWUgPT09ICdCVVRUT04nKSByZXR1cm47CiAgICAgIGlzRHJhZ2dpbmcgPSB0cnVlOwogICAgICBzdGFydFggPSBlLmNsaWVudFg7CiAgICAgIHN0YXJ0WSA9IGUuY2xpZW50WTsKICAgICAgY29uc3QgcmVjdCA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOwogICAgICBvcmlnTGVmdCA9IHJlY3QubGVmdDsKICAgICAgb3JpZ1RvcCA9IHJlY3QudG9wOwogICAgICBlbC5zdHlsZS50cmFuc2Zvcm0gPSAnbm9uZSc7CiAgICAgIGVsLnN0eWxlLnBvc2l0aW9uID0gJ2ZpeGVkJzsKICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgfSk7CgogICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIChlKSA9PiB7CiAgICAgIGlmIChpc1Jlc2l6aW5nKSB7CiAgICAgICAgY29uc3QgZHggPSBlLmNsaWVudFggLSBzdGFydFg7CiAgICAgICAgY29uc3QgZHkgPSBlLmNsaWVudFkgLSBzdGFydFk7CiAgICAgICAgY29uc3QgbmV3VyA9IE1hdGgubWF4KG1pblcsIE1hdGgubWluKG1heFcsIG9yaWdXICsgZHgpKTsKICAgICAgICBjb25zdCBuZXdIID0gTWF0aC5tYXgobWluSCwgTWF0aC5taW4obWF4SCwgb3JpZ0ggKyBkeSkpOwogICAgICAgIGVsLnN0eWxlLndpZHRoID0gbmV3VyArICdweCc7CiAgICAgICAgZWwuc3R5bGUuaGVpZ2h0ID0gbmV3SCArICdweCc7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICBpZiAoaXNEcmFnZ2luZykgewogICAgICAgIGNvbnN0IGR4ID0gZS5jbGllbnRYIC0gc3RhcnRYOwogICAgICAgIGNvbnN0IGR5ID0gZS5jbGllbnRZIC0gc3RhcnRZOwogICAgICAgIGVsLnN0eWxlLmxlZnQgPSAob3JpZ0xlZnQgKyBkeCkgKyAncHgnOwogICAgICAgIGVsLnN0eWxlLnRvcCA9IChvcmlnVG9wICsgZHkpICsgJ3B4JzsKICAgICAgfQogICAgfSk7CgogICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCAoKSA9PiB7CiAgICAgIGlmIChpc1Jlc2l6aW5nKSB7CiAgICAgICAgaXNSZXNpemluZyA9IGZhbHNlOwogICAgICAgIGNvbnN0IHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTsKICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShgd3RyX3NpemVfJHtzdG9yYWdlS2V5fWAsIEpTT04uc3RyaW5naWZ5KHsgd2lkdGg6IE1hdGgucm91bmQocmVjdC53aWR0aCksIGhlaWdodDogTWF0aC5yb3VuZChyZWN0LmhlaWdodCkgfSkpOwogICAgICAgIHNob3dOb3RpZmljYXRpb24oYFJlc2l6ZWQgJHtzdG9yYWdlS2V5LnRvVXBwZXJDYXNlKCl9OiAke01hdGgucm91bmQocmVjdC53aWR0aCl9eCR7TWF0aC5yb3VuZChyZWN0LmhlaWdodCl9cHhgLCAnaW5mbycpOwogICAgICB9CiAgICAgIGlmIChpc0RyYWdnaW5nKSB7CiAgICAgICAgaXNEcmFnZ2luZyA9IGZhbHNlOwogICAgICAgIGNvbnN0IHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTsKICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShgd3RyX3Bvc18ke3N0b3JhZ2VLZXl9YCwgSlNPTi5zdHJpbmdpZnkoeyBsZWZ0OiBNYXRoLnJvdW5kKHJlY3QubGVmdCksIHRvcDogTWF0aC5yb3VuZChyZWN0LnRvcCkgfSkpOwogICAgICB9CiAgICB9KTsKICB9CgogIG1ha2VEcmFnZ2FibGUoZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLm1lbnUtd3JhcHBlcicpLCAnbWVudScsIDI0MCwgMjAwLCA1MDAsIDcwMCk7CiAgbWFrZURyYWdnYWJsZShlbFNwZWN0YXRvckxpc3RIdWQsICdzcGVjdGF0b3InLCAxMzAsIDM2LCA0MDAsIDM1MCk7CiAgbWFrZURyYWdnYWJsZShlbEtleWJpbmRzTGlzdEh1ZCwgJ2JpbmRzJywgMTQwLCA0MCwgNDgwLCA0MDApOwogIG1ha2VEcmFnZ2FibGUoZWxRdWlja1BsYWNlckh1ZCwgJ3BsYWNlcicsIDIwMCwgNDUsIDQ1MCwgMTgwKTsKCiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICAvLyAgICAgICAgICAgICAgICAgIENPTkZJRyBQUk9GSUxFUyBTWVNURU0gKEJJRElSRUNUSU9OQUwgQ0xPVUQgU1lOQykKICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKICBhc3luYyBmdW5jdGlvbiBzYXZlQ29uZmlnQ2xvdWQoY2ZnTmFtZSA9ICdEZWZhdWx0JykgewogICAgY29uc3QgdG9nZ2xlcyA9IHt9OwogICAgQ0FURUdPUklFUy5mb3JFYWNoKGNhdCA9PiB7CiAgICAgIGNhdC5zdWJ0YWJzPy5mb3JFYWNoKHN1YiA9PiB7CiAgICAgICAgc3ViLml0ZW1zPy5mb3JFYWNoKGl0ID0+IHsKICAgICAgICAgIGlmIChpdC50eXBlID09PSAndG9nZ2xlJykgewogICAgICAgICAgICB0b2dnbGVzW2l0LmlkXSA9ICEhaXQuc3RhdGU7CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgfSk7CgogICAgY29uc3QgaHVkRGF0YSA9IHsKICAgICAgdmlzaWJpbGl0eTogewogICAgICAgIGJpbmRzOiBlbEtleWJpbmRzTGlzdEh1ZCA/IChlbEtleWJpbmRzTGlzdEh1ZC5zdHlsZS5kaXNwbGF5ICE9PSAnbm9uZScpIDogZmFsc2UsCiAgICAgICAgc3BlY3RhdG9yOiBlbFNwZWN0YXRvckxpc3RIdWQgPyAoZWxTcGVjdGF0b3JMaXN0SHVkLnN0eWxlLmRpc3BsYXkgIT09ICdub25lJykgOiBmYWxzZQogICAgICB9LAogICAgICBwb3NpdGlvbnM6IHsKICAgICAgICBtZW51OiBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKCd3dHJfcG9zX21lbnUnKSB8fCAnbnVsbCcpLAogICAgICAgIGJpbmRzOiBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKCd3dHJfcG9zX2JpbmRzJykgfHwgJ251bGwnKSwKICAgICAgICBzcGVjdGF0b3I6IEpTT04ucGFyc2UobG9jYWxTdG9yYWdlLmdldEl0ZW0oJ3d0cl9wb3Nfc3BlY3RhdG9yJykgfHwgJ251bGwnKSwKICAgICAgICBwbGFjZXI6IEpTT04ucGFyc2UobG9jYWxTdG9yYWdlLmdldEl0ZW0oJ3d0cl9wb3NfcGxhY2VyJykgfHwgJ251bGwnKQogICAgICB9LAogICAgICBzaXplczogewogICAgICAgIG1lbnU6IEpTT04ucGFyc2UobG9jYWxTdG9yYWdlLmdldEl0ZW0oJ3d0cl9zaXplX21lbnUnKSB8fCAnbnVsbCcpLAogICAgICAgIGJpbmRzOiBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKCd3dHJfc2l6ZV9iaW5kcycpIHx8ICdudWxsJyksCiAgICAgICAgc3BlY3RhdG9yOiBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKCd3dHJfc2l6ZV9zcGVjdGF0b3InKSB8fCAnbnVsbCcpLAogICAgICAgIHBsYWNlcjogSlNPTi5wYXJzZShsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnd3RyX3NpemVfcGxhY2VyJykgfHwgJ251bGwnKQogICAgICB9CiAgICB9OwoKICAgIGNvbnN0IGNvbmZpZ0RhdGEgPSB7CiAgICAgIG5hbWU6IGNmZ05hbWUsCiAgICAgIHVwZGF0ZWRBdDogRGF0ZS5ub3coKSwKICAgICAgZmVhdHVyZXM6IHRvZ2dsZXMsCiAgICAgIGJpbmRzOiBpdGVtQmluZHMsCiAgICAgIGh1ZDogaHVkRGF0YQogICAgfTsKCiAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShgd3RyX2NmZ18ke2NmZ05hbWV9YCwgSlNPTi5zdHJpbmdpZnkoY29uZmlnRGF0YSkpOwoKICAgIHRyeSB7CiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoKCdodHRwczovL3d0cm1lbnUudGF0cnVzLm9yZy9hcGkvY29uZmlncycsIHsKICAgICAgICBtZXRob2Q6ICdQT1NUJywKICAgICAgICBoZWFkZXJzOiB7ICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicgfSwKICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7CiAgICAgICAgICB1c2VybmFtZTogYXV0aFVzZXJuYW1lIHx8ICd0YXRydXMnLAogICAgICAgICAgdG9rZW46IGF1dGhUb2tlbiwKICAgICAgICAgIGNvbmZpZzogY29uZmlnRGF0YQogICAgICAgIH0pCiAgICAgIH0pOwogICAgICBjb25zdCBkYXRhID0gYXdhaXQgcmVzLmpzb24oKTsKICAgICAgaWYgKGRhdGEgJiYgZGF0YS5zdWNjZXNzKSB7CiAgICAgICAgc2hvd05vdGlmaWNhdGlvbihgQ29uZmlnICcke2NmZ05hbWV9JyBzYXZlZCAmIHN5bmNlZCEgKE92ZXJ3cml0dGVuIGlmIGV4aXN0ZWQpYCwgJ3N1Y2Nlc3MnKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBzaG93Tm90aWZpY2F0aW9uKGBTYXZlZCBsb2NhbGx5IGFzICcke2NmZ05hbWV9Jy4gQ2xvdWQgc3luYyBwZW5kaW5nLmAsICdpbmZvJyk7CiAgICAgIH0KICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgc2hvd05vdGlmaWNhdGlvbihgU2F2ZWQgbG9jYWxseSBhcyAnJHtjZmdOYW1lfScuYCwgJ3N1Y2Nlc3MnKTsKICAgIH0KICB9CgogIGFzeW5jIGZ1bmN0aW9uIGxvYWRDb25maWdDbG91ZChjZmdOYW1lID0gJ0RlZmF1bHQnKSB7CiAgICBzaG93Tm90aWZpY2F0aW9uKGBMb2FkaW5nIHByb2ZpbGUgJyR7Y2ZnTmFtZX0nLi4uYCwgJ2luZm8nKTsKICAgIGxldCBsb2FkZWRDb25maWcgPSBudWxsOwoKICAgIHRyeSB7CiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoKGBodHRwczovL3d0cm1lbnUudGF0cnVzLm9yZy9hcGkvY29uZmlncz91c2VybmFtZT0ke2F1dGhVc2VybmFtZSB8fCAndGF0cnVzJ31gKTsKICAgICAgY29uc3QgY29uZmlncyA9IGF3YWl0IHJlcy5qc29uKCk7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KGNvbmZpZ3MpKSB7CiAgICAgICAgbG9hZGVkQ29uZmlnID0gY29uZmlncy5maW5kKGMgPT4gYy5uYW1lLnRvTG93ZXJDYXNlKCkgPT09IGNmZ05hbWUudG9Mb3dlckNhc2UoKSk7CiAgICAgIH0KICAgIH0gY2F0Y2ggKGUpIHt9CgogICAgaWYgKCFsb2FkZWRDb25maWcpIHsKICAgICAgY29uc3QgcmF3ID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oYHd0cl9jZmdfJHtjZmdOYW1lfWApOwogICAgICBpZiAocmF3KSB7CiAgICAgICAgdHJ5IHsgbG9hZGVkQ29uZmlnID0gSlNPTi5wYXJzZShyYXcpOyB9IGNhdGNoIChfKSB7fQogICAgICB9CiAgICB9CgogICAgaWYgKCFsb2FkZWRDb25maWcpIHsKICAgICAgc2hvd05vdGlmaWNhdGlvbihgQ29uZmlnICcke2NmZ05hbWV9JyBub3QgZm91bmQuYCwgJ3dhcm5pbmcnKTsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIC8vIEFwcGx5IGJpbmRzCiAgICBpZiAobG9hZGVkQ29uZmlnLmJpbmRzKSB7CiAgICAgIE9iamVjdC5rZXlzKGl0ZW1CaW5kcykuZm9yRWFjaChrID0+IGRlbGV0ZSBpdGVtQmluZHNba10pOwogICAgICBPYmplY3QuYXNzaWduKGl0ZW1CaW5kcywgbG9hZGVkQ29uZmlnLmJpbmRzKTsKICAgICAgdXBkYXRlQmluZHNIdWQoKTsKICAgIH0KCiAgICAvLyBBcHBseSB0b2dnbGVzCiAgICBjb25zdCB0b2dnbGVzID0gbG9hZGVkQ29uZmlnLmZlYXR1cmVzIHx8IGxvYWRlZENvbmZpZy50b2dnbGVzIHx8IHt9OwogICAgQ0FURUdPUklFUy5mb3JFYWNoKGNhdCA9PiB7CiAgICAgIGNhdC5zdWJ0YWJzPy5mb3JFYWNoKHN1YiA9PiB7CiAgICAgICAgc3ViLml0ZW1zPy5mb3JFYWNoKGl0ID0+IHsKICAgICAgICAgIGlmIChpdC50eXBlID09PSAndG9nZ2xlJyAmJiB0b2dnbGVzW2l0LmlkXSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIGl0LnN0YXRlID0gISF0b2dnbGVzW2l0LmlkXTsKICAgICAgICAgICAgaGFuZGxlVG9nZ2xlRmVhdHVyZShpdC5pZCwgaXQuc3RhdGUpOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9KTsKICAgIH0pOwoKICAgIC8vIEFwcGx5IEhVRCBwb3NpdGlvbnMsIHNpemVzIGFuZCB2aXNpYmlsaXR5CiAgICBpZiAobG9hZGVkQ29uZmlnLmh1ZCkgewogICAgICBpZiAobG9hZGVkQ29uZmlnLmh1ZC5wb3NpdGlvbnMpIHsKICAgICAgICBPYmplY3QuZW50cmllcyhsb2FkZWRDb25maWcuaHVkLnBvc2l0aW9ucykuZm9yRWFjaCgoW2ssIHBvc10pID0+IHsKICAgICAgICAgIGlmIChwb3MgJiYgdHlwZW9mIHBvcy5sZWZ0ID09PSAnbnVtYmVyJyAmJiB0eXBlb2YgcG9zLnRvcCA9PT0gJ251bWJlcicpIHsKICAgICAgICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oYHd0cl9wb3NfJHtrfWAsIEpTT04uc3RyaW5naWZ5KHBvcykpOwogICAgICAgICAgICBjb25zdCBlbCA9IChrID09PSAnbWVudScpID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLm1lbnUtd3JhcHBlcicpIDoKICAgICAgICAgICAgICAgICAgICAgICAoayA9PT0gJ2JpbmRzJykgPyBlbEtleWJpbmRzTGlzdEh1ZCA6CiAgICAgICAgICAgICAgICAgICAgICAgKGsgPT09ICdzcGVjdGF0b3InKSA/IGVsU3BlY3RhdG9yTGlzdEh1ZCA6CiAgICAgICAgICAgICAgICAgICAgICAgKGsgPT09ICdwbGFjZXInKSA/IGVsUXVpY2tQbGFjZXJIdWQgOiBudWxsOwogICAgICAgICAgICBpZiAoZWwpIHsKICAgICAgICAgICAgICBlbC5zdHlsZS5wb3NpdGlvbiA9ICdmaXhlZCc7CiAgICAgICAgICAgICAgZWwuc3R5bGUubGVmdCA9IHBvcy5sZWZ0ICsgJ3B4JzsKICAgICAgICAgICAgICBlbC5zdHlsZS50b3AgPSBwb3MudG9wICsgJ3B4JzsKICAgICAgICAgICAgICBlbC5zdHlsZS5yaWdodCA9ICdhdXRvJzsKICAgICAgICAgICAgICBlbC5zdHlsZS5ib3R0b20gPSAnYXV0byc7CiAgICAgICAgICAgICAgZWwuc3R5bGUudHJhbnNmb3JtID0gJ25vbmUnOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIGlmIChsb2FkZWRDb25maWcuaHVkLnNpemVzKSB7CiAgICAgICAgT2JqZWN0LmVudHJpZXMobG9hZGVkQ29uZmlnLmh1ZC5zaXplcykuZm9yRWFjaCgoW2ssIHN6XSkgPT4gewogICAgICAgICAgaWYgKHN6ICYmIHR5cGVvZiBzei53aWR0aCA9PT0gJ251bWJlcicgJiYgdHlwZW9mIHN6LmhlaWdodCA9PT0gJ251bWJlcicpIHsKICAgICAgICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oYHd0cl9zaXplXyR7a31gLCBKU09OLnN0cmluZ2lmeShzeikpOwogICAgICAgICAgICBjb25zdCBlbCA9IChrID09PSAnbWVudScpID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLm1lbnUtd3JhcHBlcicpIDoKICAgICAgICAgICAgICAgICAgICAgICAoayA9PT0gJ2JpbmRzJykgPyBlbEtleWJpbmRzTGlzdEh1ZCA6CiAgICAgICAgICAgICAgICAgICAgICAgKGsgPT09ICdzcGVjdGF0b3InKSA/IGVsU3BlY3RhdG9yTGlzdEh1ZCA6CiAgICAgICAgICAgICAgICAgICAgICAgKGsgPT09ICdwbGFjZXInKSA/IGVsUXVpY2tQbGFjZXJIdWQgOiBudWxsOwogICAgICAgICAgICBpZiAoZWwpIHsKICAgICAgICAgICAgICBlbC5zdHlsZS53aWR0aCA9IHN6LndpZHRoICsgJ3B4JzsKICAgICAgICAgICAgICBlbC5zdHlsZS5oZWlnaHQgPSBzei5oZWlnaHQgKyAncHgnOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIGlmIChsb2FkZWRDb25maWcuaHVkLnZpc2liaWxpdHkpIHsKICAgICAgICBpZiAobG9hZGVkQ29uZmlnLmh1ZC52aXNpYmlsaXR5LmJpbmRzICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHRvZ2dsZUh1ZCgnYmluZHMnLCAhIWxvYWRlZENvbmZpZy5odWQudmlzaWJpbGl0eS5iaW5kcyk7CiAgICAgICAgICAvLyBTeW5jIHRvZ2dsZSBzd2l0Y2ggaW4gU2V0dGluZ3MKICAgICAgICAgIENBVEVHT1JJRVMuZm9yRWFjaChjID0+IGMuc3VidGFicz8uZm9yRWFjaChzID0+IHMuaXRlbXM/LmZvckVhY2goaSA9PiB7CiAgICAgICAgICAgIGlmIChpLmlkID09PSAnYmluZHNfaHVkJykgaS5zdGF0ZSA9ICEhbG9hZGVkQ29uZmlnLmh1ZC52aXNpYmlsaXR5LmJpbmRzOwogICAgICAgICAgfSkpKTsKICAgICAgICB9CiAgICAgICAgaWYgKGxvYWRlZENvbmZpZy5odWQudmlzaWJpbGl0eS5zcGVjdGF0b3IgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgdG9nZ2xlSHVkKCdzcGVjdGF0b3InLCAhIWxvYWRlZENvbmZpZy5odWQudmlzaWJpbGl0eS5zcGVjdGF0b3IpOwogICAgICAgICAgLy8gU3luYyB0b2dnbGUgc3dpdGNoIGluIFNldHRpbmdzCiAgICAgICAgICBDQVRFR09SSUVTLmZvckVhY2goYyA9PiBjLnN1YnRhYnM/LmZvckVhY2gocyA9PiBzLml0ZW1zPy5mb3JFYWNoKGkgPT4gewogICAgICAgICAgICBpZiAoaS5pZCA9PT0gJ3NwZWN0YXRvcl9odWQnKSBpLnN0YXRlID0gISFsb2FkZWRDb25maWcuaHVkLnZpc2liaWxpdHkuc3BlY3RhdG9yOwogICAgICAgICAgfSkpKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KCiAgICByZW5kZXIoKTsKICAgIHNob3dOb3RpZmljYXRpb24oYENvbmZpZyAnJHtjZmdOYW1lfScgbG9hZGVkIGZyb20gY2xvdWQhYCwgJ3N1Y2Nlc3MnKTsKICB9CgogIGFzeW5jIGZ1bmN0aW9uIGRlbGV0ZUNvbmZpZ0Nsb3VkKGNmZ05hbWUgPSAnRGVmYXVsdCcpIHsKICAgIGxvY2FsU3RvcmFnZS5yZW1vdmVJdGVtKGB3dHJfY2ZnXyR7Y2ZnTmFtZX1gKTsKICAgIHRyeSB7CiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoKCdodHRwczovL3d0cm1lbnUudGF0cnVzLm9yZy9hcGkvY29uZmlncycsIHsKICAgICAgICBtZXRob2Q6ICdERUxFVEUnLAogICAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9LAogICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHsgdXNlcm5hbWU6IGF1dGhVc2VybmFtZSB8fCAndGF0cnVzJywgY29uZmlnTmFtZTogY2ZnTmFtZSB9KQogICAgICB9KTsKICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHJlcy5qc29uKCk7CiAgICAgIGlmIChkYXRhICYmIGRhdGEuc3VjY2VzcykgewogICAgICAgIHNob3dOb3RpZmljYXRpb24oYENvbmZpZyAnJHtjZmdOYW1lfScgZGVsZXRlZCBmcm9tIGNsb3VkLmAsICdzdWNjZXNzJyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgc2hvd05vdGlmaWNhdGlvbihgRGVsZXRlZCBsb2NhbGx5OiAnJHtjZmdOYW1lfSdgLCAnaW5mbycpOwogICAgICB9CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIHNob3dOb3RpZmljYXRpb24oYERlbGV0ZWQgbG9jYWxseTogJyR7Y2ZnTmFtZX0nYCwgJ2luZm8nKTsKICAgIH0KICB9CgogIGFzeW5jIGZ1bmN0aW9uIHN5bmNDb25maWdzQ2xvdWQoKSB7CiAgICBzaG93Tm90aWZpY2F0aW9uKCdTeW5jaW5nIGNsb3VkIHByb2ZpbGVzLi4uJywgJ2luZm8nKTsKICAgIHRyeSB7CiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoKGBodHRwczovL3d0cm1lbnUudGF0cnVzLm9yZy9hcGkvY29uZmlncz91c2VybmFtZT0ke2F1dGhVc2VybmFtZSB8fCAndGF0cnVzJ31gKTsKICAgICAgY29uc3QgY29uZmlncyA9IGF3YWl0IHJlcy5qc29uKCk7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KGNvbmZpZ3MpKSB7CiAgICAgICAgY29uZmlncy5mb3JFYWNoKGMgPT4gewogICAgICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oYHd0cl9jZmdfJHtjLm5hbWV9YCwgSlNPTi5zdHJpbmdpZnkoYykpOwogICAgICAgIH0pOwogICAgICAgIHNob3dOb3RpZmljYXRpb24oYENsb3VkIHN5bmMgY29tcGxldGUhICgke2NvbmZpZ3MubGVuZ3RofSBwcm9maWxlcyBzeW5jZWQpYCwgJ3N1Y2Nlc3MnKTsKICAgICAgfQogICAgfSBjYXRjaCAoZSkgewogICAgICBzaG93Tm90aWZpY2F0aW9uKCdDbG91ZCBzeW5jIGZhaWxlZDogc2VydmVyIHVucmVhY2hhYmxlLicsICd3YXJuaW5nJyk7CiAgICB9CiAgfQoKICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogIC8vICAgICAgICAgICAgICAgICAgTU9EQUwgRElBTE9HUwogIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgogIGZ1bmN0aW9uIG9wZW5Nb2RhbCh0eXBlLCB0aXRsZSwgcGxhY2Vob2xkZXIsIGluaXRpYWxWYWwpIHsKICAgIG1vZGFsQWN0aXZlID0gdHJ1ZTsKICAgIGN1cnJlbnRNb2RhbFR5cGUgPSB0eXBlIHx8ICd2ZWhpY2xlJzsKICAgIGlmIChlbE1vZGFsVGl0bGUpIGVsTW9kYWxUaXRsZS50ZXh0Q29udGVudCA9IHRpdGxlIHx8ICdJTlBVVCAvLyBURVJNSU5BTCc7CiAgICBpZiAoZWxNb2RhbElucHV0KSB7CiAgICAgIGVsTW9kYWxJbnB1dC5wbGFjZWhvbGRlciA9IHBsYWNlaG9sZGVyIHx8ICdFbnRlciB2YWx1ZS4uLic7CiAgICAgIGVsTW9kYWxJbnB1dC52YWx1ZSA9IGluaXRpYWxWYWwgfHwgJyc7CiAgICB9CiAgICBpZiAoZWxNb2RhbE92ZXJsYXkpIGVsTW9kYWxPdmVybGF5LnN0eWxlLmRpc3BsYXkgPSAnZmxleCc7CgogICAgaWYgKGVsTW9kYWxQcmVzZXRzKSB7CiAgICAgIGVsTW9kYWxQcmVzZXRzLmlubmVySFRNTCA9ICcnOwogICAgICBjb25zdCBwcmVzZXRzID0gTU9EQUxfUFJFU0VUU1t0eXBlXSB8fCBbXTsKICAgICAgcHJlc2V0cy5mb3JFYWNoKHByID0+IHsKICAgICAgICBjb25zdCBjaGlwID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICAgICAgY2hpcC5jbGFzc05hbWUgPSAncHJlc2V0LWNoaXAnOwogICAgICAgIGNoaXAudGV4dENvbnRlbnQgPSBwci5sYWJlbDsKICAgICAgICBjaGlwLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4gewogICAgICAgICAgaWYgKGVsTW9kYWxJbnB1dCkgewogICAgICAgICAgICBlbE1vZGFsSW5wdXQudmFsdWUgPSBwci52YWw7CiAgICAgICAgICAgIGVsTW9kYWxJbnB1dC5mb2N1cygpOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICAgIGVsTW9kYWxQcmVzZXRzLmFwcGVuZENoaWxkKGNoaXApOwogICAgICB9KTsKICAgIH0KCiAgICBzZXRUaW1lb3V0KCgpID0+IHsKICAgICAgaWYgKGVsTW9kYWxJbnB1dCkgZWxNb2RhbElucHV0LmZvY3VzKCk7CiAgICB9LCA1MCk7CiAgfQoKICBmdW5jdGlvbiBjbG9zZU1vZGFsKCkgewogICAgbW9kYWxBY3RpdmUgPSBmYWxzZTsKICAgIGlmIChlbE1vZGFsT3ZlcmxheSkgZWxNb2RhbE92ZXJsYXkuc3R5bGUuZGlzcGxheSA9ICdub25lJzsKICAgIGlmIChlbE1vZGFsSW5wdXQpIGVsTW9kYWxJbnB1dC52YWx1ZSA9ICcnOwogIH0KCiAgaWYgKGVsTW9kYWxDbGVhcikgewogICAgZWxNb2RhbENsZWFyLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4gewogICAgICBpZiAoZWxNb2RhbElucHV0KSB7CiAgICAgICAgZWxNb2RhbElucHV0LnZhbHVlID0gJyc7CiAgICAgICAgZWxNb2RhbElucHV0LmZvY3VzKCk7CiAgICAgIH0KICAgIH0pOwogIH0KCiAgaWYgKGVsTW9kYWxCdG5DbG9zZSkgZWxNb2RhbEJ0bkNsb3NlLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgY2xvc2VNb2RhbCk7CiAgaWYgKGVsTW9kYWxCdG5DYW5jZWwpIGVsTW9kYWxCdG5DYW5jZWwuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBjbG9zZU1vZGFsKTsKICBpZiAoZWxNb2RhbEJ0bkNvbmZpcm0pIHsKICAgIGVsTW9kYWxCdG5Db25maXJtLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4gewogICAgICBjb25zdCB2YWwgPSBlbE1vZGFsSW5wdXQgPyBlbE1vZGFsSW5wdXQudmFsdWUudHJpbSgpIDogJyc7CiAgICAgIGlmICh2YWwpIHsKICAgICAgICBpZiAoY3VycmVudE1vZGFsVHlwZSA9PT0gJ2NvbmZpZ19zYXZlJykgewogICAgICAgICAgc2F2ZUNvbmZpZ0Nsb3VkKHZhbCk7CiAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50TW9kYWxUeXBlID09PSAnY29uZmlnX2xvYWQnKSB7CiAgICAgICAgICBsb2FkQ29uZmlnQ2xvdWQodmFsKTsKICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRNb2RhbFR5cGUgPT09ICdjb25maWdfZGVsZXRlJykgewogICAgICAgICAgZGVsZXRlQ29uZmlnQ2xvdWQodmFsKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc2hvd05vdGlmaWNhdGlvbihgQXBwbGllZDogJHt2YWx9YCwgJ3N1Y2Nlc3MnKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgY2xvc2VNb2RhbCgpOwogICAgfSk7CiAgfQoKICAvLyBGZWF0dXJlIEtleWJpbmQgTW9kYWwgSGFuZGxlcgogIGxldCB0ZW1wU2VsZWN0ZWRLZXkgPSBudWxsOwoKICBmdW5jdGlvbiBvcGVuQmluZE1vZGFsKGl0ZW1JZCwgaXRlbUxhYmVsLCBjdXJyZW50S2V5KSB7CiAgICBiaW5kTW9kYWxBY3RpdmUgPSB0cnVlOwogICAgY3VycmVudEJpbmRJdGVtSWQgPSBpdGVtSWQ7CiAgICB0ZW1wU2VsZWN0ZWRLZXkgPSBjdXJyZW50S2V5IHx8IG51bGw7CiAgICBpZiAoZWxCaW5kTW9kYWxUaXRsZSkgZWxCaW5kTW9kYWxUaXRsZS50ZXh0Q29udGVudCA9IGBCSU5EIC8vICR7aXRlbUxhYmVsLnRvVXBwZXJDYXNlKCl9YDsKICAgIGlmIChlbEJpbmRNb2RhbEtleWNhcCkgZWxCaW5kTW9kYWxLZXljYXAudGV4dENvbnRlbnQgPSBjdXJyZW50S2V5ID8gYFsgJHtjdXJyZW50S2V5fSBdYCA6ICdbIFBSRVNTIEtFWSBdJzsKICAgIGlmIChlbEJpbmRNb2RhbFN0YXR1cykgZWxCaW5kTW9kYWxTdGF0dXMudGV4dENvbnRlbnQgPSAnUHJlc3MgYW55IGtleSwgdGhlbiBbIEVOVEVSIF0gdG8gY29uZmlybS4gWyBFU0MgLyBCQUNLU1BBQ0UgXSB0byBjbGVhci4nOwogICAgaWYgKGVsQmluZE1vZGFsT3ZlcmxheSkgZWxCaW5kTW9kYWxPdmVybGF5LnN0eWxlLmRpc3BsYXkgPSAnZmxleCc7CiAgfQoKICBmdW5jdGlvbiB1cGRhdGVCaW5kTW9kYWxLZXkoa2V5KSB7CiAgICB0ZW1wU2VsZWN0ZWRLZXkgPSBrZXk7CiAgICBpZiAoZWxCaW5kTW9kYWxLZXljYXApIGVsQmluZE1vZGFsS2V5Y2FwLnRleHRDb250ZW50ID0gYFsgJHtrZXl9IF1gOwogIH0KCiAgZnVuY3Rpb24gY2xvc2VCaW5kTW9kYWwoKSB7CiAgICBiaW5kTW9kYWxBY3RpdmUgPSBmYWxzZTsKICAgIGN1cnJlbnRCaW5kSXRlbUlkID0gbnVsbDsKICAgIHRlbXBTZWxlY3RlZEtleSA9IG51bGw7CiAgICBpZiAoZWxCaW5kTW9kYWxPdmVybGF5KSBlbEJpbmRNb2RhbE92ZXJsYXkuc3R5bGUuZGlzcGxheSA9ICdub25lJzsKICB9CgogIGZ1bmN0aW9uIHNldEl0ZW1CaW5kKGl0ZW1JZCwga2V5KSB7CiAgICBpZiAoa2V5KSB7CiAgICAgIGl0ZW1CaW5kc1tpdGVtSWRdID0ga2V5OwogICAgfSBlbHNlIHsKICAgICAgZGVsZXRlIGl0ZW1CaW5kc1tpdGVtSWRdOwogICAgfQogICAgdXBkYXRlQmluZHNIdWQoKTsKICAgIGlmIChjdXJyZW50TGV2ZWwgPT09IDIpIHsKICAgICAgcmVuZGVyU3VibWVudSgpOwogICAgfQogIH0KCiAgaWYgKGVsQmluZE1vZGFsQnRuQ2xvc2UpIGVsQmluZE1vZGFsQnRuQ2xvc2UuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBjbG9zZUJpbmRNb2RhbCk7CiAgaWYgKGVsQmluZE1vZGFsQnRuQ2FuY2VsKSB7CiAgICBlbEJpbmRNb2RhbEJ0bkNhbmNlbC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHsKICAgICAgaWYgKGN1cnJlbnRCaW5kSXRlbUlkKSB7CiAgICAgICAgc2V0SXRlbUJpbmQoY3VycmVudEJpbmRJdGVtSWQsIG51bGwpOwogICAgICAgIHNob3dOb3RpZmljYXRpb24oYENsZWFyZWQga2V5YmluZCBmb3IgJHtjdXJyZW50QmluZEl0ZW1JZH1gLCAnaW5mbycpOwogICAgICB9CiAgICAgIGNsb3NlQmluZE1vZGFsKCk7CiAgICB9KTsKICB9CiAgaWYgKGVsQmluZE1vZGFsQnRuQ29uZmlybSkgewogICAgZWxCaW5kTW9kYWxCdG5Db25maXJtLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4gewogICAgICBpZiAoY3VycmVudEJpbmRJdGVtSWQgJiYgdGVtcFNlbGVjdGVkS2V5KSB7CiAgICAgICAgc2V0SXRlbUJpbmQoY3VycmVudEJpbmRJdGVtSWQsIHRlbXBTZWxlY3RlZEtleSk7CiAgICAgICAgc2hvd05vdGlmaWNhdGlvbihgQm91bmQgJHtjdXJyZW50QmluZEl0ZW1JZH0gdG8gWyAke3RlbXBTZWxlY3RlZEtleX0gXWAsICdzdWNjZXNzJyk7CiAgICAgIH0KICAgICAgY2xvc2VCaW5kTW9kYWwoKTsKICAgIH0pOwogIH0KCiAgLy8gQW50aWNoZWF0IERpYWdub3N0aWMgU2Nhbm5lciBTeXN0ZW0KICBmdW5jdGlvbiBjbG9zZUFjU2Nhbk1vZGFsKCkgewogICAgYWNTY2FuTW9kYWxBY3RpdmUgPSBmYWxzZTsKICAgIGlmIChhY1NjYW5JbnRlcnZhbCkgY2xlYXJJbnRlcnZhbChhY1NjYW5JbnRlcnZhbCk7CiAgICBpZiAoZWxBY1NjYW5Nb2RhbE92ZXJsYXkpIGVsQWNTY2FuTW9kYWxPdmVybGF5LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7CiAgfQoKICBmdW5jdGlvbiBzdGFydEFudGljaGVhdFNjYW4oKSB7CiAgICBpZiAoIWVsQWNTY2FuTW9kYWxPdmVybGF5KSByZXR1cm47CiAgICBhY1NjYW5Nb2RhbEFjdGl2ZSA9IHRydWU7CiAgICBlbEFjU2Nhbk1vZGFsT3ZlcmxheS5zdHlsZS5kaXNwbGF5ID0gJ2ZsZXgnOwogICAgaWYgKGVsQWNTY2FuUHJvZ3Jlc3NCYXIpIGVsQWNTY2FuUHJvZ3Jlc3NCYXIuc3R5bGUud2lkdGggPSAnMCUnOwogICAgaWYgKGVsQWNTY2FuU3VidGl0bGUpIGVsQWNTY2FuU3VidGl0bGUuaW5uZXJIVE1MID0gJ0luaXRpYWxpemluZyBkZWVwIHNjYW4gb2Ygc2VydmVyICZhbXA7IGNsaWVudCByZXNvdXJjZXMuLi4nOwogICAgaWYgKGVsQWNTY2FuUmVzdWx0c0xpc3QpIHsKICAgICAgZWxBY1NjYW5SZXN1bHRzTGlzdC5pbm5lckhUTUwgPSAnPGRpdiBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyBjb2xvcjogIzY0NzQ4YjsgZm9udC1zaXplOiAxMXB4OyBwYWRkaW5nOiAxNHB4IDA7Ij5TY2FubmluZyByZXNvdXJjZXMgYW5kIG5hdGl2ZSB0YWJsZXMuLi48L2Rpdj4nOwogICAgfQoKICAgIGxldCBwcm9ncmVzcyA9IDA7CiAgICBpZiAoYWNTY2FuSW50ZXJ2YWwpIGNsZWFySW50ZXJ2YWwoYWNTY2FuSW50ZXJ2YWwpOwoKICAgIGFjU2NhbkludGVydmFsID0gc2V0SW50ZXJ2YWwoKCkgPT4gewogICAgICBwcm9ncmVzcyArPSAyNTsKICAgICAgaWYgKGVsQWNTY2FuUHJvZ3Jlc3NCYXIpIGVsQWNTY2FuUHJvZ3Jlc3NCYXIuc3R5bGUud2lkdGggPSBgJHtwcm9ncmVzc30lYDsKCiAgICAgIGlmIChwcm9ncmVzcyA9PT0gMjUgJiYgZWxBY1NjYW5TdWJ0aXRsZSkgewogICAgICAgIGVsQWNTY2FuU3VidGl0bGUuaW5uZXJIVE1MID0gJ0luc3BlY3RpbmcgcmVzb3VyY2UgbWFuaWZlc3RzLCBleHBvcnRzIGFuZCBldmVudCBob29rcy4uLic7CiAgICAgIH0gZWxzZSBpZiAocHJvZ3Jlc3MgPT09IDUwICYmIGVsQWNTY2FuU3VidGl0bGUpIHsKICAgICAgICBlbEFjU2NhblN1YnRpdGxlLmlubmVySFRNTCA9ICdUZXN0aW5nIEZpdmVHdWFyZCwgV2F2ZVNoaWVsZCBhbmQgUGhvZW5peCBzaWduYXR1cmVzLi4uJzsKICAgICAgfSBlbHNlIGlmIChwcm9ncmVzcyA9PT0gNzUgJiYgZWxBY1NjYW5TdWJ0aXRsZSkgewogICAgICAgIGVsQWNTY2FuU3VidGl0bGUuaW5uZXJIVE1MID0gJ1ZlcmlmeWluZyBoZWFydGJlYXQgbGlzdGVuZXJzICZhbXA7IG5hdGl2ZSB2ZXJpZmljYXRpb24gdHJhcHMuLi4nOwogICAgICB9IGVsc2UgaWYgKHByb2dyZXNzID49IDEwMCkgewogICAgICAgIGNsZWFySW50ZXJ2YWwoYWNTY2FuSW50ZXJ2YWwpOwogICAgICAgIGZpbmlzaEFudGljaGVhdFNjYW4oKTsKICAgICAgfQogICAgfSwgMTgwKTsKICB9CgogIGZ1bmN0aW9uIGZpbmlzaEFudGljaGVhdFNjYW4oY3VzdG9tUmVzdWx0cykgewogICAgaWYgKGVsQWNTY2FuUHJvZ3Jlc3NCYXIpIGVsQWNTY2FuUHJvZ3Jlc3NCYXIuc3R5bGUud2lkdGggPSAnMTAwJSc7CiAgICBpZiAoZWxBY1NjYW5TdWJ0aXRsZSkgewogICAgICBlbEFjU2NhblN1YnRpdGxlLmlubmVySFRNTCA9ICc8c3BhbiBzdHlsZT0iY29sb3I6ICM0YWRlODA7IGZvbnQtd2VpZ2h0OiA2MDA7Ij5TY2FuIGNvbXBsZXRlZCE8L3NwYW4+IEFjdGl2ZSBkaWFnbm9zdGljIHJlcG9ydDonOwogICAgfQoKICAgIGNvbnN0IGRlZmF1bHRSZXBvcnQgPSBbCiAgICAgIHsgbmFtZTogJ0ZpdmVHdWFyZCAodjEuNCsgLyBqcm5rX3ZrKScsIHN0YXR1czogJ0FDVElWRSBCWVBBU1MnLCBiYWRnZUNsYXNzOiAnYnlwYXNzZWQnLCBkZXNjOiAnSGVhcnRiZWF0IHNwb29maW5nICgxMHMpIGFjdGl2ZSAmIG5hdGl2ZSBob29rcyBlbmdhZ2VkLicgfSwKICAgICAgeyBuYW1lOiAnU2VydmVyIFJlc291cmNlIEludGVncml0eScsIHN0YXR1czogJ1ZFUklGSUVEICgxODIgUkVTKScsIGJhZGdlQ2xhc3M6ICdhY3RpdmUnLCBkZXNjOiAnQWxsIGxvYWRlZCByZXNvdXJjZXMgYW5hbHl6ZWQuIFplcm8gY29uZmxpY3RpbmcgaG9va3MuJyB9LAogICAgICB7IG5hbWU6ICdDbGllbnQgTmF0aXZlIFByb3RlY3Rpb24nLCBzdGF0dXM6ICdPUEVSQVRJT05BTCcsIGJhZGdlQ2xhc3M6ICdhY3RpdmUnLCBkZXNjOiAnQW50aS1kZXRlY3Rpb24gc2FmZSBtb2RlIGFjdGl2ZSBvbiBpbnZpbmNpYmlsaXR5ICYgdmlzaWJpbGl0eS4nIH0KICAgIF07CgogICAgY29uc3QgcmVwb3J0ID0gY3VzdG9tUmVzdWx0cyB8fCBkZWZhdWx0UmVwb3J0OwoKICAgIGlmIChlbEFjU2NhblJlc3VsdHNMaXN0KSB7CiAgICAgIGVsQWNTY2FuUmVzdWx0c0xpc3QuaW5uZXJIVE1MID0gcmVwb3J0Lm1hcChyID0+IGAKICAgICAgICA8ZGl2IGNsYXNzPSJhYy1zY2FuLXJvdyI+CiAgICAgICAgICA8ZGl2IHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBmbGV4LWRpcmVjdGlvbjogY29sdW1uOyBnYXA6IDJweDsiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJhYy1zY2FuLW5hbWUiPiR7ci5uYW1lfTwvZGl2PgogICAgICAgICAgICA8ZGl2IHN0eWxlPSJmb250LXNpemU6IDEwcHg7IGNvbG9yOiAjNjQ3NDhiOyI+JHtyLmRlc2N9PC9kaXY+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIDxzcGFuIGNsYXNzPSJhYy1zY2FuLWJhZGdlICR7ci5iYWRnZUNsYXNzfSI+JHtyLnN0YXR1c308L3NwYW4+CiAgICAgICAgPC9kaXY+CiAgICAgIGApLmpvaW4oJycpOwogICAgfQoKICAgIHNob3dOb3RpZmljYXRpb24oJ0FDIFNjYW4gQ29tcGxldGU6IEZpdmVHdWFyZCBkZXRlY3RlZCAoQUNUSVZFIEJZUEFTUykuIEVudmlyb25tZW50IGNsZWFuLicsICdzdWNjZXNzJyk7CiAgfQoKICBpZiAoZWxBY1NjYW5CdG5DbG9zZSkgZWxBY1NjYW5CdG5DbG9zZS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGNsb3NlQWNTY2FuTW9kYWwpOwogIGlmIChlbEFjU2NhbkJ0bkRvbmUpIGVsQWNTY2FuQnRuRG9uZS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGNsb3NlQWNTY2FuTW9kYWwpOwoKICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogIC8vICAgICAgICAgICAgICAgICAgS0VZQk9BUkQgRVZFTlQgSEFORExFUlMKICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIChlKSA9PiB7CiAgICAvLyBJZiB0eXBpbmcgaW4gYW55IGlucHV0IGZpZWxkIG9yIHRleHRhcmVhLCBkbyBub3QgdHJpZ2dlciBnbG9iYWwgYmluZHMKICAgIGlmIChlLnRhcmdldCAmJiAoZS50YXJnZXQudGFnTmFtZSA9PT0gJ0lOUFVUJyB8fCBlLnRhcmdldC50YWdOYW1lID09PSAnVEVYVEFSRUEnKSkgewogICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKGVsQXV0aE1vZGFsT3ZlcmxheSAmJiBlbEF1dGhNb2RhbE92ZXJsYXkuc3R5bGUuZGlzcGxheSAhPT0gJ25vbmUnKSB7CiAgICAgIHJldHVybjsgLy8gSGFuZGxlZCBieSBhdXRoIG1vZGFsCiAgICB9CgogICAgaWYgKG1vZGFsQWN0aXZlKSB7CiAgICAgIGlmIChlLmtleSA9PT0gJ0VzY2FwZScgfHwgZS5rZXkgPT09ICdFbnRlcicpIHsKICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7CiAgICAgICAgY2xvc2VNb2RhbCgpOwogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAoYmluZE1vZGFsQWN0aXZlKSB7CiAgICAgIGUucHJldmVudERlZmF1bHQoKTsKICAgICAgaWYgKGUua2V5ID09PSAnRXNjYXBlJykgewogICAgICAgIGNsb3NlQmluZE1vZGFsKCk7CiAgICAgIH0gZWxzZSBpZiAoZS5rZXkgPT09ICdCYWNrc3BhY2UnKSB7CiAgICAgICAgaWYgKGN1cnJlbnRCaW5kSXRlbUlkKSB7CiAgICAgICAgICBzZXRJdGVtQmluZChjdXJyZW50QmluZEl0ZW1JZCwgbnVsbCk7CiAgICAgICAgICBzaG93Tm90aWZpY2F0aW9uKGBDbGVhcmVkIGtleWJpbmQgZm9yICR7Y3VycmVudEJpbmRJdGVtSWR9YCwgJ2luZm8nKTsKICAgICAgICB9CiAgICAgICAgY2xvc2VCaW5kTW9kYWwoKTsKICAgICAgfSBlbHNlIGlmIChlLmtleSA9PT0gJ0VudGVyJykgewogICAgICAgIGlmICh0ZW1wU2VsZWN0ZWRLZXkgJiYgY3VycmVudEJpbmRJdGVtSWQpIHsKICAgICAgICAgIHNldEl0ZW1CaW5kKGN1cnJlbnRCaW5kSXRlbUlkLCB0ZW1wU2VsZWN0ZWRLZXkpOwogICAgICAgICAgc2hvd05vdGlmaWNhdGlvbihgQm91bmQgJHtjdXJyZW50QmluZEl0ZW1JZH0gdG8gWyAke3RlbXBTZWxlY3RlZEtleX0gXWAsICdzdWNjZXNzJyk7CiAgICAgICAgfQogICAgICAgIGNsb3NlQmluZE1vZGFsKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbGV0IHByZXNzZWQgPSBlLmtleS50b1VwcGVyQ2FzZSgpOwogICAgICAgIGlmIChlLmNvZGUgJiYgZS5jb2RlLnN0YXJ0c1dpdGgoJ0tleScpKSBwcmVzc2VkID0gZS5jb2RlLnJlcGxhY2UoJ0tleScsICcnKTsKICAgICAgICBlbHNlIGlmIChlLmNvZGUgJiYgZS5jb2RlLnN0YXJ0c1dpdGgoJ0RpZ2l0JykpIHByZXNzZWQgPSBlLmNvZGUucmVwbGFjZSgnRGlnaXQnLCAnJyk7CiAgICAgICAgZWxzZSBpZiAoZS5jb2RlICYmIGUuY29kZS5zdGFydHNXaXRoKCdOdW1wYWQnKSkgcHJlc3NlZCA9ICdOVU1QQUQnICsgZS5jb2RlLnJlcGxhY2UoJ051bXBhZCcsICcnKTsKICAgICAgICB1cGRhdGVCaW5kTW9kYWxLZXkocHJlc3NlZCk7CiAgICAgIH0KICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmIChhY1NjYW5Nb2RhbEFjdGl2ZSkgewogICAgICBpZiAoZS5rZXkgPT09ICdFc2NhcGUnIHx8IGUua2V5ID09PSAnRW50ZXInKSB7CiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICAgIGNsb3NlQWNTY2FuTW9kYWwoKTsKICAgICAgfQogICAgICByZXR1cm47CiAgICB9CgogICAgaWYgKHBsYWNlckFjdGl2ZSkgewogICAgICBpZiAoZS5rZXkgPT09ICdFc2NhcGUnKSB7CiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICAgIGNsb3NlUXVpY2tQbGFjZXIoKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgIH0KCiAgICAvLyBDSEVDSyBBQ1RJVkUgS0VZQklORFMgVE8gVFJJR0dFUiBBUyBJRiBFTlRFUiBXQVMgUFJFU1NFRAogICAgY29uc3QgcEtleSA9IChlLmtleSB8fCAnJykudG9VcHBlckNhc2UoKS5yZXBsYWNlKC9ccysvZywgJycpOwogICAgY29uc3QgcENvZGUgPSAoZS5jb2RlIHx8ICcnKS50b1VwcGVyQ2FzZSgpLnJlcGxhY2UoL1xzKy9nLCAnJyk7CgogICAgY29uc3QgaXNSZXNlcnZlZE5hdktleSA9IFsnQVJST1dVUCcsICdBUlJPV0RPV04nLCAnQVJST1dMRUZUJywgJ0FSUk9XUklHSFQnLCAnRU5URVInLCAnQkFDS1NQQUNFJywgJ0VTQ0FQRSddLmluY2x1ZGVzKHBLZXkpOwoKICAgIGlmICghaXNSZXNlcnZlZE5hdktleSkgewogICAgICBmb3IgKGNvbnN0IFtpdGVtSWQsIGJLZXldIG9mIE9iamVjdC5lbnRyaWVzKGl0ZW1CaW5kcykpIHsKICAgICAgICBpZiAoIWJLZXkpIGNvbnRpbnVlOwogICAgICAgIGNvbnN0IGJDbGVhbiA9IFN0cmluZyhiS2V5KS50b1VwcGVyQ2FzZSgpLnJlcGxhY2UoL1xzKy9nLCAnJyk7CgogICAgICAgIGNvbnN0IG1hdGNoID0gKHBLZXkgPT09IGJDbGVhbikgfHwKICAgICAgICAgICAgICAgICAgICAgIChwQ29kZSA9PT0gYkNsZWFuKSB8fAogICAgICAgICAgICAgICAgICAgICAgKHBDb2RlID09PSBgS0VZJHtiQ2xlYW59YCkgfHwKICAgICAgICAgICAgICAgICAgICAgIChwQ29kZSA9PT0gYERJR0lUJHtiQ2xlYW59YCkgfHwKICAgICAgICAgICAgICAgICAgICAgIChwQ29kZSA9PT0gYE5VTVBBRCR7YkNsZWFufWApIHx8CiAgICAgICAgICAgICAgICAgICAgICAoYkNsZWFuLnN0YXJ0c1dpdGgoJ05VTVBBRCcpICYmIHBDb2RlID09PSBiQ2xlYW4pOwoKICAgICAgICBpZiAobWF0Y2gpIHsKICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTsKICAgICAgICAgIGV4ZWN1dGVGZWF0dXJlQnlJZChpdGVtSWQpOwogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgfQogICAgfQoKICAgIGlmIChlLmtleSA9PT0gJ0JhY2tzcGFjZScgfHwgZS5rZXkgPT09ICdFc2NhcGUnKSB7CiAgICAgIGUucHJldmVudERlZmF1bHQoKTsKICAgICAgZ29CYWNrKCk7CiAgICB9IGVsc2UgaWYgKGUua2V5ID09PSAncScgfHwgZS5rZXkgPT09ICdRJykgewogICAgICBlLnByZXZlbnREZWZhdWx0KCk7CiAgICAgIHByZXZTdWJ0YWIoKTsKICAgIH0gZWxzZSBpZiAoZS5rZXkgPT09ICdlJyB8fCBlLmtleSA9PT0gJ0UnKSB7CiAgICAgIGUucHJldmVudERlZmF1bHQoKTsKICAgICAgbmV4dFN1YnRhYigpOwogICAgfSBlbHNlIGlmIChlLmtleSA9PT0gJ0Fycm93VXAnIHx8IGUua2V5ID09PSAnOCcpIHsKICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICBuYXZpZ2F0ZVVwKCk7CiAgICB9IGVsc2UgaWYgKGUua2V5ID09PSAnQXJyb3dEb3duJyB8fCBlLmtleSA9PT0gJzInKSB7CiAgICAgIGUucHJldmVudERlZmF1bHQoKTsKICAgICAgbmF2aWdhdGVEb3duKCk7CiAgICB9IGVsc2UgaWYgKGUua2V5ID09PSAnRW50ZXInIHx8IGUua2V5ID09PSAnNScpIHsKICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICBleGVjdXRlQ3VycmVudEl0ZW0oKTsKICAgIH0KICB9KTsKCiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICAvLyAgICAgICAgICAgICAgICAgIEZJVkVNIERVSSAmIFBPU1RNRVNTQUdFIFJPVVRFUgogIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgogIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgKGV2ZW50KSA9PiB7CiAgICBjb25zdCBkYXRhID0gZXZlbnQuZGF0YTsKICAgIGlmICghZGF0YSkgcmV0dXJuOwoKICAgIGlmIChkYXRhLmFjdGlvbiA9PT0gJ1NZTkNfTkFWJykgewogICAgICBpZiAodHlwZW9mIGRhdGEubGV2ZWwgPT09ICdudW1iZXInKSBjdXJyZW50TGV2ZWwgPSBkYXRhLmxldmVsOwogICAgICBpZiAodHlwZW9mIGRhdGEuY2F0SW5kZXggPT09ICdudW1iZXInKSBzZWxlY3RlZENhdGVnb3J5SW5kZXggPSBkYXRhLmNhdEluZGV4OwogICAgICBpZiAodHlwZW9mIGRhdGEuc3VidGFiSW5kZXggPT09ICdudW1iZXInKSBhY3RpdmVTdWJ0YWJJbmRleCA9IGRhdGEuc3VidGFiSW5kZXg7CiAgICAgIGlmICh0eXBlb2YgZGF0YS5pdGVtSW5kZXggPT09ICdudW1iZXInKSBzZWxlY3RlZEl0ZW1JbmRleCA9IGRhdGEuaXRlbUluZGV4OwogICAgICByZW5kZXIoKTsKICAgICAgdXBkYXRlQWN0aXZlU3RhdGUoKTsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmIChkYXRhLmFjdGlvbiA9PT0gJ1VQJykgewogICAgICBuYXZpZ2F0ZVVwKCk7CiAgICB9IGVsc2UgaWYgKGRhdGEuYWN0aW9uID09PSAnRE9XTicpIHsKICAgICAgbmF2aWdhdGVEb3duKCk7CiAgICB9IGVsc2UgaWYgKGRhdGEuYWN0aW9uID09PSAnRU5URVInKSB7CiAgICAgIGV4ZWN1dGVDdXJyZW50SXRlbSgpOwogICAgfSBlbHNlIGlmIChkYXRhLmFjdGlvbiA9PT0gJ0JBQ0snKSB7CiAgICAgIGdvQmFjaygpOwogICAgfSBlbHNlIGlmIChkYXRhLmFjdGlvbiA9PT0gJ1RBQl9QUkVWJykgewogICAgICBwcmV2U3VidGFiKCk7CiAgICB9IGVsc2UgaWYgKGRhdGEuYWN0aW9uID09PSAnVEFCX05FWFQnKSB7CiAgICAgIG5leHRTdWJ0YWIoKTsKICAgIH0gZWxzZSBpZiAoZGF0YS5hY3Rpb24gPT09ICdTRVRfQ0FURUdPUlknKSB7CiAgICAgIGlmICh0eXBlb2YgZGF0YS5jYXRJbmRleCA9PT0gJ251bWJlcicpIHsKICAgICAgICBzZWxlY3RlZENhdGVnb3J5SW5kZXggPSBkYXRhLmNhdEluZGV4OwogICAgICAgIGN1cnJlbnRMZXZlbCA9IDI7CiAgICAgICAgYWN0aXZlU3VidGFiSW5kZXggPSAwOwogICAgICAgIHNlbGVjdGVkSXRlbUluZGV4ID0gMDsKICAgICAgICByZW5kZXIoKTsKICAgICAgfQogICAgfSBlbHNlIGlmIChkYXRhLmFjdGlvbiA9PT0gJ1NFVF9JVEVNX1NUQVRFJykgewogICAgICBpZiAoZGF0YS5pdGVtSWQgIT09IHVuZGVmaW5lZCkgewogICAgICAgIENBVEVHT1JJRVMuZm9yRWFjaChjYXQgPT4gewogICAgICAgICAgY2F0LnN1YnRhYnM/LmZvckVhY2goc3ViID0+IHsKICAgICAgICAgICAgc3ViLml0ZW1zPy5mb3JFYWNoKGl0ID0+IHsKICAgICAgICAgICAgICBpZiAoaXQuaWQgPT09IGRhdGEuaXRlbUlkICYmIGl0LnR5cGUgPT09ICd0b2dnbGUnKSB7CiAgICAgICAgICAgICAgICBpdC5zdGF0ZSA9ICEhZGF0YS5zdGF0ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICAgICAgaWYgKGN1cnJlbnRMZXZlbCA9PT0gMikgcmVuZGVyU3VibWVudSgpOwogICAgICB9CiAgICB9IGVsc2UgaWYgKGRhdGEuYWN0aW9uID09PSAnVVBEQVRFX09OTElORV9QTEFZRVJTJykgewogICAgICBpZiAoQXJyYXkuaXNBcnJheShkYXRhLnBsYXllcnMpICYmIGRhdGEucGxheWVycy5sZW5ndGggPiAwKSB7CiAgICAgICAgb25saW5lUGxheWVycyA9IGRhdGEucGxheWVyczsKICAgICAgfSBlbHNlIHsKICAgICAgICBvbmxpbmVQbGF5ZXJzID0gWy4uLkRFRkFVTFRfU0lNVUxBVEVEX1BMQVlFUlNdOwogICAgICB9CiAgICAgIGNvbnN0IGN1ckNhdCA9IENBVEVHT1JJRVNbc2VsZWN0ZWRDYXRlZ29yeUluZGV4XTsKICAgICAgY29uc3QgY3VyU3VidGFiID0gY3VyQ2F0Py5zdWJ0YWJzW2FjdGl2ZVN1YnRhYkluZGV4XTsKICAgICAgaWYgKGN1cnJlbnRMZXZlbCA9PT0gMiAmJiBjdXJTdWJ0YWI/LmlzUGxheWVyTGlzdCkgewogICAgICAgIHJlbmRlclBsYXllcnNMaXN0KCk7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoZGF0YS5hY3Rpb24gPT09ICdPUEVOX1BMQUNFUicpIHsKICAgICAgb3BlblF1aWNrUGxhY2VyKGRhdGEuY2F0ZWdvcnkgfHwgJ3Byb3BzJyk7CiAgICB9IGVsc2UgaWYgKGRhdGEuYWN0aW9uID09PSAnQ0xPU0VfUExBQ0VSJykgewogICAgICBjbG9zZVF1aWNrUGxhY2VyKCk7CiAgICB9IGVsc2UgaWYgKGRhdGEuYWN0aW9uID09PSAnVVBEQVRFX1NQRUNUQVRPUlMnKSB7CiAgICAgIHVwZGF0ZVNwZWN0YXRvclJhZGFyKGRhdGEuc3BlY3RhdG9ycyB8fCBbXSk7CiAgICB9IGVsc2UgaWYgKGRhdGEuYWN0aW9uID09PSAnU0VUX0hVRF9WSVNJQkxFJykgewogICAgICB0b2dnbGVIdWQoZGF0YS5odWQsICEhZGF0YS52aXNpYmxlKTsKICAgIH0gZWxzZSBpZiAoZGF0YS5hY3Rpb24gPT09ICdTRVRfRFJBR19NT0RFJykgewogICAgICBzZXREcmFnTW9kZSghIWRhdGEuYWN0aXZlKTsKICAgIH0gZWxzZSBpZiAoZGF0YS5hY3Rpb24gPT09ICdPUEVOX01PREFMJykgewogICAgICBvcGVuTW9kYWwoZGF0YS5tb2RhbFR5cGUsIGRhdGEudGl0bGUsIGRhdGEucGxhY2Vob2xkZXIsIGRhdGEuaW5pdGlhbFZhbCk7CiAgICB9IGVsc2UgaWYgKGRhdGEuYWN0aW9uID09PSAnQ0xPU0VfTU9EQUwnKSB7CiAgICAgIGNsb3NlTW9kYWwoKTsKICAgIH0gZWxzZSBpZiAoZGF0YS5hY3Rpb24gPT09ICdPUEVOX0JJTkRfTU9EQUwnKSB7CiAgICAgIG9wZW5CaW5kTW9kYWwoZGF0YS5pdGVtSWQsIGRhdGEuaXRlbUxhYmVsLCBkYXRhLmN1cnJlbnRLZXkpOwogICAgfSBlbHNlIGlmIChkYXRhLmFjdGlvbiA9PT0gJ1VQREFURV9CSU5EX01PREFMX0tFWScpIHsKICAgICAgdXBkYXRlQmluZE1vZGFsS2V5KGRhdGEua2V5KTsKICAgIH0gZWxzZSBpZiAoZGF0YS5hY3Rpb24gPT09ICdDTE9TRV9CSU5EX01PREFMJykgewogICAgICBjbG9zZUJpbmRNb2RhbCgpOwogICAgfSBlbHNlIGlmIChkYXRhLmFjdGlvbiA9PT0gJ1NFVF9JVEVNX0JJTkQnKSB7CiAgICAgIHNldEl0ZW1CaW5kKGRhdGEuaXRlbUlkLCBkYXRhLmtleSk7CiAgICB9IGVsc2UgaWYgKGRhdGEuYWN0aW9uID09PSAnRVhFQ1VURV9JVEVNJykgewogICAgICBleGVjdXRlRmVhdHVyZUJ5SWQoZGF0YS5pdGVtSWQpOwogICAgfSBlbHNlIGlmIChkYXRhLmFjdGlvbiA9PT0gJ1JFU0VUX0hVRF9MQVlPVVQnKSB7CiAgICAgIGhhbmRsZUFjdGlvbkZlYXR1cmUoJ3Jlc2V0X2h1ZF9sYXlvdXQnKTsKICAgIH0gZWxzZSBpZiAoZGF0YS5hY3Rpb24gPT09ICdTSE9XX0FDX1NDQU5fUkVTVUxUUycpIHsKICAgICAgc3RhcnRBbnRpY2hlYXRTY2FuKCk7CiAgICAgIHNldFRpbWVvdXQoKCkgPT4gewogICAgICAgIGxldCBmb3JtYXR0ZWQgPSBudWxsOwogICAgICAgIGlmIChkYXRhLmRldGVjdGVkICYmIEFycmF5LmlzQXJyYXkoZGF0YS5kZXRlY3RlZCkpIHsKICAgICAgICAgIGZvcm1hdHRlZCA9IGRhdGEuZGV0ZWN0ZWQubWFwKGQgPT4gKHsKICAgICAgICAgICAgbmFtZTogZC5uYW1lLAogICAgICAgICAgICBzdGF0dXM6IGQudGFnIHx8IChkLnN0YXR1cyA9PT0gJ2J5cGFzc2VkJyA/ICdBQ1RJVkUgQllQQVNTJyA6ICdQTEFOTkVEIChGVVRVUkUpJyksCiAgICAgICAgICAgIGJhZGdlQ2xhc3M6IGQuc3RhdHVzID09PSAnYnlwYXNzZWQnID8gJ2J5cGFzc2VkJyA6ICdwbGFubmVkJywKICAgICAgICAgICAgZGVzYzogZC5zdGF0dXMgPT09ICdieXBhc3NlZCcgPyAnQWN0aXZlbHkgYnlwYXNzZWQgJiBzcG9vZmVkIGJ5IFdUUiBNZW51LicgOiAnRGV0ZWN0ZWQgb24gc2VydmVyLiBTdXBwb3J0IHNjaGVkdWxlZCBmb3IgdXBjb21pbmcgcmVsZWFzZS4nCiAgICAgICAgICB9KSk7CiAgICAgICAgfQogICAgICAgIGZpbmlzaEFudGljaGVhdFNjYW4oZm9ybWF0dGVkKTsKICAgICAgfSwgNzUwKTsKICAgIH0KICB9KTsKCiAgLy8gSW5pdGlhbCBCb290CiAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCAoKSA9PiB7CiAgICBjaGVja0F1dGhTdGF0dXMoKTsKICAgIHJlbmRlcigpOwogIH0pOwp9KSgpOwoKPC9zY3JpcHQ+CjwvYm9keT4KPC9odG1sPgo=" -- ==================================================================== -- DUI RENDERER INITIALIZATION -- ==================================================================== local duiObj = nil local duiTxd = "wtr_menu_txd" local duiTxn = "wtr_menu_txn" SendDuiAction = function(actionName, extraData) if duiObj and WTR.duiReady then local payload = { action = actionName } if extraData then for k, v in pairs(extraData) do payload[k] = v end end SendDuiMessage(duiObj, json.encode(payload)) end end Citizen.CreateThread(function() local aspect = GetAspectRatio(false) WTR.menuWidth = 0.23 WTR.menuHeight = WTR.menuWidth * aspect * (700 / 440) -- Attempt CEF Direct User Interface safely pcall(function() local uiUrl = "https://wtr-menu.ja-f33.workers.dev/ui" duiObj = CreateDui(uiUrl, 440, 700) local timeout = 0 while not IsDuiAvailable(duiObj) and timeout < 60 do Citizen.Wait(50) timeout = timeout + 1 end if not IsDuiAvailable(duiObj) then if duiObj then DestroyDui(duiObj) end duiObj = CreateDui("data:text/html;base64," .. WTR_UI_BUNDLE, 440, 700) timeout = 0 while not IsDuiAvailable(duiObj) and timeout < 60 do Citizen.Wait(50) timeout = timeout + 1 end end if IsDuiAvailable(duiObj) then local duiHandle = GetDuiHandle(duiObj) if duiHandle then local txd = CreateRuntimeTxd(duiTxd) CreateRuntimeTextureFromDuiHandle(txd, duiTxn, duiHandle) WTR.duiReady = true SendDuiAction("SET_TARGET", { targetName = WTR.target.name }) end end end) Notify("~b~[WTR ELITE]~s~ Water Glass Loaded [Press F9 to Open]", "purple", 4000) end) -- ==================================================================== -- HIERARCHICAL CATEGORIES & SUBMENUS -- ==================================================================== local CATEGORIES = { { id = "player", label = "Player", subtabs = { { id = "self", label = "Self", items = { { id = "godmode", label = "Godmode", type = "toggle" }, { id = "auto_revive", label = "Auto Revive", type = "toggle" }, { id = "revive_script", label = "Revive (Script)", type = "action" }, { id = "revive_native", label = "Revive (Native)", type = "action" }, { id = "heal_armor", label = "Max Health & Armor", type = "action" }, { id = "clean_ped", label = "Clean Blood & Clothes", type = "action" }, { id = "never_wanted", label = "Never Wanted (0 Stars)", type = "toggle" }, { id = "invisible", label = "Invisibility", type = "toggle" }, { id = "unfreeze_self", label = "Unfreeze Self", type = "action" }, { id = "suicide", label = "Commit Suicide", type = "action" } } }, { id = "movement", label = "Movement", items = { { id = "freecam", label = "Freecam", type = "toggle" }, { id = "freecam_shoot", label = "Freecam Shoot (LMB Snipe)", type = "toggle" }, { id = "freecam_placer", label = "Freecam Quick Placer", type = "toggle" }, { isHeader = true, label = "Freecam Placers" }, { id = "freecam_placer_props", label = "Freecam Prop Placer", type = "action" }, { id = "freecam_placer_peds", label = "Freecam Ped Placer", type = "action" }, { id = "freecam_placer_vehs", label = "Freecam Car Placer", type = "action" }, { isHeader = true, label = "Movement Hacks" }, { id = "noclip", label = "Noclip", type = "toggle" }, { id = "super_jump", label = "Super Jump", type = "toggle" }, { id = "fast_run", label = "Fast Sprint", type = "toggle" }, { id = "sky_swim", label = "Sky Swim", type = "toggle" } } }, { id = "teleport", label = "Teleport", items = { { id = "tp_waypoint", label = "Waypoint", type = "action" }, { id = "tp_coords", label = "Custom Coordinates", type = "action" }, { isHeader = true, label = "Locations" }, { id = "tp_legion", label = "Legion Square", type = "action" }, { id = "tp_airport", label = "LS Airport", type = "action" }, { id = "tp_sandyshores", label = "Sandy Shores", type = "action" }, { id = "tp_paletobay", label = "Paleto Bay", type = "action" }, { id = "tp_mazebank", label = "Maze Bank Tower", type = "action" } } } } }, { id = "online", label = "Online", subtabs = { { id = "players", label = "Players", isPlayerList = true, items = {} }, { id = "actions", label = "Actions", items = { { isHeader = true, label = "Player Attacks" }, { id = "online_multi_yeet", label = "Launch Player", type = "action" }, { id = "online_multi_slap", label = "Ragdoll", type = "action" }, { id = "online_multi_freeze", label = "Freeze Player", type = "toggle" }, { id = "online_multi_burn", label = "Ignite Player", type = "action" }, { id = "online_multi_explode", label = "Explosion", type = "action" }, { id = "orbital_cannon", label = "Orbital Cannon", type = "action" }, { id = "online_multi_cage", label = "Barrier Cage", type = "action" }, { id = "toilet_head", label = "Attach Toilet Prop", type = "action" }, { id = "ram_target", label = "Ram Player", type = "action" }, { id = "disarm_target", label = "Disarm Player", type = "action" }, { isHeader = true, label = "Teleport" }, { id = "online_tp_to", label = "Teleport To Player", type = "action" }, { id = "online_tp_here", label = "Bring Player Here", type = "action" }, { id = "online_multi_heal", label = "Heal Player", type = "action" } } }, { id = "vehicle", label = "Vehicle", items = { { isHeader = true, label = "Target In-Vehicle Controls" }, { id = "eject_target", label = "Eject From Vehicle", type = "action" }, { id = "rocket_car", label = "Launch Car", type = "action" }, { id = "explode_target_veh", label = "Explode Vehicle", type = "action" }, { id = "delete_target_veh", label = "Delete Target Vehicle", type = "action" }, { id = "kill_target_engine", label = "Kill Engine", type = "action" }, { id = "burst_target_tires", label = "Burst All Tires", type = "action" }, { id = "freeze_target_veh", label = "Freeze Vehicle", type = "action" }, { id = "boost_target_veh", label = "Rocket Boost", type = "action" }, { id = "spin_target_veh", label = "Spin Out", type = "action" }, { id = "lock_target_veh", label = "Lock Doors", type = "action" }, { id = "repair_target_veh", label = "Repair Vehicle", type = "action" } } }, { id = "loops", label = "Loops", items = { { isHeader = true, label = "Continuous Attacks" }, { id = "loop_punch", label = "Punch Loop", type = "toggle" }, { id = "loop_taze", label = "Taze Loop", type = "toggle" }, { id = "loop_burn", label = "Burn Loop", type = "toggle" } } }, { id = "spectate", label = "Spectate", items = { { id = "online_spectate", label = "Toggle Spectator View", type = "toggle" } } } } }, { id = "vehicle", label = "Vehicle", subtabs = { { id = "spawner", label = "Spawner", items = { { isHeader = true, label = "Popular Supercars" }, { id = "spawn_adder", label = "Adder", type = "action" }, { id = "spawn_sultan", label = "Sultan RS", type = "action" }, { id = "spawn_krieger", label = "Benefactor Krieger", type = "action" }, { id = "spawn_zentorno", label = "Pegassi Zentorno", type = "action" }, { id = "spawn_t20", label = "Progen T20", type = "action" }, { isHeader = true, label = "Offroad & Bikes" }, { id = "spawn_kamacho", label = "Canis Kamacho 4x4", type = "action" }, { id = "spawn_sanchez", label = "Sanchez Dirt Bike", type = "action" }, { id = "spawn_oppressor2", label = "Oppressor MK2", type = "action" }, { isHeader = true, label = "Custom" }, { id = "spawn_veh_input", label = "Spawn by Name", type = "action" } } }, { id = "upgrades", label = "Upgrades", items = { { id = "repair_vehicle", label = "Repair & Clean", type = "action" }, { id = "max_tune_veh", label = "Max Performance Tune", type = "action" }, { id = "rainbow_car", label = "Rainbow RGB Paint", type = "toggle" } } }, { id = "options", label = "Options", items = { { id = "veh_godmode", label = "Vehicle Godmode", type = "toggle" }, { id = "speed_boost", label = "Horn Speed Boost", type = "toggle" }, { id = "drive_on_water", label = "Drive On Water", type = "toggle" }, { id = "car_jump", label = "Vehicle Jump", type = "toggle" }, { id = "invisible_car", label = "Invisible Vehicle", type = "toggle" }, { id = "delete_veh", label = "Delete Vehicle", type = "action" } } } } }, { id = "combat", label = "Combat", subtabs = { { id = "weapons", label = "Weapons", items = { { id = "give_all_weapons", label = "Give All Standard Weapons", type = "action" }, { id = "give_ammo", label = "Refill Ammo", type = "action" }, { isHeader = true, label = "Quick Spawn" }, { id = "wep_combatmg", label = "Combat MG", type = "action" }, { id = "wep_carbine", label = "Special Carbine", type = "action" }, { id = "wep_heavysniper", label = "Heavy Sniper", type = "action" }, { id = "wep_revolver", label = "Heavy Revolver", type = "action" }, { id = "wep_rpg", label = "RPG Launcher", type = "action" }, { id = "spawn_custom_weapon", label = "Spawn by Name", type = "action" } } }, { id = "modifiers", label = "Modifiers", items = { { id = "infinite_ammo", label = "Infinite Ammo", type = "toggle" }, { id = "no_recoil", label = "No Recoil", type = "toggle" }, { id = "no_spread", label = "No Spread", type = "toggle" }, { id = "rapid_fire", label = "Rapid Fire", type = "toggle" }, { id = "explosive_ammo", label = "Explosive Ammo", type = "toggle" }, { id = "car_gun", label = "Car Gun", type = "toggle" }, { id = "damage_boost", label = "Damage Multiplier (x2)", type = "toggle" } } }, { id = "aimbot", label = "Aimbot", items = { { id = "silent_aim", label = "Silent Aim", type = "toggle" }, { id = "triggerbot", label = "Triggerbot", type = "toggle" } } } } }, { id = "visuals", label = "Visuals", subtabs = { { id = "esp", label = "ESP", items = { { id = "esp_box", label = "Box ESP", type = "toggle" }, { id = "esp_names", label = "Player Name Tags", type = "toggle" }, { id = "esp_health", label = "Health & Armor Bars", type = "toggle" }, { id = "esp_distance", label = "Distance Information", type = "toggle" }, { id = "esp_snaplines", label = "Snaplines", type = "toggle" }, { id = "custom_crosshair", label = "Neon Crosshair", type = "toggle" } } }, { id = "vision", label = "Vision", items = { { id = "night_vision", label = "Night Vision", type = "toggle" }, { id = "thermal_vision", label = "Thermal Vision", type = "toggle" } } }, { id = "hud", label = "HUD Overlays", items = { { id = "spectator_hud", label = "Spectator Radar HUD", type = "toggle" }, { id = "binds_hud", label = "Active Keybinds HUD", type = "toggle" } } } } }, { id = "world", label = "World", subtabs = { { id = "general", label = "General", items = { { id = "moon_gravity", label = "Moon Gravity", type = "toggle" }, { id = "freeze_peds", label = "Freeze All Nearby NPCs", type = "toggle" }, { id = "clear_vehicles", label = "Clear Empty Vehicles", type = "action" } } }, { id = "spawners", label = "Spawners", items = { { isHeader = true, label = "Quick Placers (Scroll & Click)" }, { id = "placer_props", label = "Quick Prop Placer", type = "action" }, { id = "placer_peds", label = "Quick Ped Placer", type = "action" }, { id = "placer_vehs", label = "Quick Vehicle Placer", type = "action" }, { isHeader = true, label = "Props" }, { id = "prop_barrier", label = "Orange Work Barrier", type = "action" }, { id = "prop_toilet", label = "Porcelain Toilet", type = "action" }, { id = "spawn_prop_input", label = "Spawn Prop by Name", type = "action" }, { isHeader = true, label = "NPCs" }, { id = "ped_swat", label = "SWAT Officer", type = "action" }, { id = "ped_skater", label = "Skater Ped", type = "action" }, { id = "spawn_ped_input", label = "Spawn Ped by Name", type = "action" } } } } }, { id = "settings", label = "Settings", subtabs = { { id = "hud_lists", label = "HUD Lists", items = { { isHeader = true, label = "Floating Lists" }, { id = "binds_hud", label = "Active Binds List", type = "toggle" }, { id = "spectator_hud", label = "Spectator Radar List", type = "toggle" }, { isHeader = true, label = "Layout & Dragging" }, { id = "drag_ui_mode", label = "Drag & Resize UI Mode", type = "toggle" }, { id = "reset_hud_layout", label = "Reset HUD Positions & Sizes", type = "action" } } }, { id = "configs", label = "Configs & Cloud", items = { { isHeader = true, label = "Profile Storage" }, { id = "cfg_save", label = "Save Config Profile", type = "action" }, { id = "cfg_load", label = "Load Config Profile", type = "action" } } }, { id = "binds", label = "Binds", items = { { isHeader = true, label = "Menu Hotkeys" }, { id = "bind_info_f9", label = "Menu Toggle: [ F9 ]", type = "info" }, { id = "rebind_key", label = "Change Menu Toggle Key", type = "action" }, { isHeader = true, label = "Feature Shortcuts" }, { id = "bind_info_alt", label = "Mouse Cursor: [ LEFT ALT ]", type = "info" }, { id = "bind_info_noclip", label = "Noclip Flight: [ WASD + Shift ]", type = "info" } } }, { id = "menu", label = "Menu", items = { { id = "cycle_position", label = "Menu Position", type = "action" }, { id = "toggle_cursor", label = "Toggle Mouse Cursor (Alt)", type = "action" }, { id = "unload_menu", label = "Unload WTR Menu", type = "action" } } } } }, { id = "bypasses", label = "Bypasses", subtabs = { { id = "anticheat", label = "Anticheat", items = { { id = "check_anticheats", label = "Scan Active Anticheats", type = "action", isDetectable = false }, { id = "stop_anticheat", label = "Stop Known Anticheats", type = "action", isDetectable = true }, { id = "fg_bypass", label = "FiveGuard One-Click Bypass", type = "action", isDetectable = true }, { id = "fg_heartbeat", label = "FG Heartbeat Spoof (10s)", type = "toggle", isDetectable = true }, { id = "fg_stop", label = "Stop FiveGuard (jrnk_vk)", type = "action", isDetectable = false }, { id = "dp_bypass", label = "DropPlayer One-Click Bypass", type = "action", isDetectable = true }, { id = "dp_heartbeat", label = "DP Heartbeat Spoof (10s)", type = "toggle", isDetectable = true }, { id = "dp_stop", label = "Stop DropPlayer", type = "action", isDetectable = false }, { id = "clear_attached", label = "Clean Attached Objects", type = "action" }, { id = "esx_revive", label = "ESX Trigger Revive", type = "action" }, { id = "qb_revive", label = "QBCore Trigger Revive", type = "action" }, { id = "unlock_closest_veh", label = "Force Unlock Closest Vehicle", type = "action" }, { id = "anti_spectate", label = "Scan Ghost Spectators", type = "action" }, { id = "check_framework", label = "Detect Active Framework", type = "action" } } } } } } -- Navigation Helper Functions local function GetCurrentSubtab() local cat = CATEGORIES[WTR.selectedCategory] if not cat or not cat.subtabs then return nil end return cat.subtabs[WTR.activeSubtab] end local function GetNextNonHeaderItem(items, startIdx, delta) if not items or #items == 0 then return 1 end local count = #items local idx = startIdx + delta for _ = 1, count do if idx > count then idx = 1 elseif idx < 1 then idx = count end if not items[idx].isHeader then return idx end idx = idx + delta end return startIdx end local function SyncDuiSelection() if SendDuiAction and WTR.duiReady then local curCat = CATEGORIES[WTR.selectedCategory] local curSub = GetCurrentSubtab() local itm = nil if curSub and not curSub.isPlayerList and curSub.items then itm = curSub.items[WTR.selectedItem] end SendDuiAction("SYNC_NAV", { level = WTR.menuLevel, catIndex = (WTR.selectedCategory or 1) - 1, subtabIndex = (WTR.activeSubtab or 1) - 1, itemIndex = (WTR.selectedItem or 1) - 1, itemId = itm and itm.id or nil }) end end -- SHARED RESOURCE-INJECT STOPPER -- Used by every bypass (FiveGuard, DropPlayer, Shield). -- Stops a resource via the best available method and -- restores its script-inject flags so it can restart. -- ==================================================================== local function StopResourceInject(res) local ok = false local wasPaused = false local orig = {} -- Capture current script-inject state for each script pcall(function() if GetNumResourceScripts then local n = GetNumResourceScripts(res) if n and n > 0 then for i = 1, n do local id = (GetResourceScriptId and GetResourceScriptId(res, i, 0)) or (i - 1) local st = (GetResourceScriptState and GetResourceScriptState(res, id)) or 0 orig[i] = { id = id, state = st } if st == 2 then wasPaused = true end end end end end) -- Pause (if it isn't already) so no Lua VM can be left mid-frame pcall(function() if not wasPaused then PauseResource(res, false) end end) -- Restore inject flags to "loaded" so the resource can restart cleanly pcall(function() if res and (GetResourceScriptId or false) then for i, v in pairs(orig) do SetResourceScriptState(res, v.id, 1) end end end) -- Stop: prefer Lumia, fall back to raw StopResource pcall(function() if Lumia and Lumia.Resource and Lumia.Resource.StopResource then ok = (Lumia.Resource.StopResource(res) ~= false) elseif StopResource then StopResource(res) ok = true end end) -- Treat "still started" as success (some wrappers don't return a bool) if not ok and GetResourceState and GetResourceState(res) == "started" then ok = true end return ok end WTR.StopResourceInject = StopResourceInject -- ==================================================================== -- FIVEGUARD ANTICHEAT BYPASS (jrnk_vk / ac 'fg') -- Reverse-engineered from the obfuscated jrnk_vk Luraph VM client: -- * Heartbeat : TriggerServerEvent("J0p0jUnRQUCG") every 10000 ms -- * Net events: "UUKz9ubpm9XK", "2ek4T1P7A3lB" (server -> client) -- * Shared ref: global "xHCekjHCQe" -- ==================================================================== local FG = { resourceNames = { "jrnk_vk", "fg", "fiveguard" }, heartbeatEvent = "J0p0jUnRQUCG", netEvents = { "UUKz9ubpm9XK", "2ek4T1P7A3lB" }, sharedGlobal = "xHCekjHCQe", interval = 10000, hbRunning = false, hooksInstalled = false, stoppedRes = nil, status = "none" } local function FG_FindResource() for _, n in ipairs(FG.resourceNames) do if GetResourceState(n) == "started" then return n end end return nil end local function FG_StartHeartbeat() if FG.hbRunning then return end FG.hbRunning = true Citizen.CreateThread(function() while WTR.features.fg_heartbeat do pcall(TriggerServerEvent, FG.heartbeatEvent) Citizen.Wait(FG.interval) end FG.hbRunning = false end) end local function FG_StopHeartbeat() WTR.features.fg_heartbeat = false FG.hbRunning = false end local function FG_StopAC() local res = FG_FindResource() if not res then return false end FG.stoppedRes = res return StopResourceInject(res) end local function FG_HookNatives() if FG.hooksInstalled then return end FG.hooksInstalled = true local natives = { "SetEntityInvincible", "SetPlayerInvincible", "SetEntityVisible", "SetEntityAlpha", "SetEntityProofs", "SetEntityNoCollisionEntity", "SetEntityCollision" } for _, n in ipairs(natives) do pcall(function() if CreateNativeHook then CreateNativeHook(n, function(...) end, true) elseif y_nativeshook and y_nativeshook.add_hook then y_nativeshook.add_hook(n, function() return true end) end end) end end -- Detect FiveGuard version from resource name local function FG_DetectVersion() local res = FG_FindResource() if not res then return nil, nil end if res == "jrnk_vk" then return "1.0 (jrnk_vk)", res elseif res == "fg" then return "2.0 (fg)", res elseif res == "fiveguard" then return "3.0 (fiveguard)", res else return "Unknown (" .. res .. ")", res end end -- Remove native hooks (called when safe_mode is turned OFF) local function FG_UnhookNatives() if not FG.hooksInstalled then return end FG.hooksInstalled = false local natives = { "SetEntityInvincible", "SetPlayerInvincible", "SetEntityVisible", "SetEntityAlpha", "SetEntityProofs", "SetEntityNoCollisionEntity", "SetEntityCollision" } for _, n in ipairs(natives) do pcall(function() if y_nativeshook and y_nativeshook.remove_hook then y_nativeshook.remove_hook(n) end end) end end -- Auto-check FiveGuard status on menu launch (detect version + sync safe mode) local function FG_AutoCheck() local ver, res = FG_DetectVersion() if res then FG.status = ver if not WTR.features.safe_mode then WTR.features.safe_mode = true FG_HookNatives() end Notify("~b~WTR FG Check~s~: ~g~" .. ver) else FG.status = "none" Notify("~b~WTR FG Check~s~: ~r~No FiveGuard detected") end end -- ==================================================================== -- DROPLAYER ANTICHEAT BYPASS -- DropPlayer keeps a client resource alive and pings a -- liveness heartbeat. We stop the resource(s) and spoof -- the heartbeat to preserve the session. -- NOTE: resource names / event names are best-effort -- guesses pending a dedicated DropPlayer decode pass. -- ==================================================================== local DP = { resourceNames = { "DropPlayer", "dropplayer", "drop_player", "dp" }, heartbeatEvent = "DropPlayerHeartbeat", interval = 10000, hbRunning = false, stoppedRes = nil, status = "none", } local function DP_FindResource() for _, n in ipairs(DP.resourceNames) do if GetResourceState(n) == "started" then return n end end return nil end local function DP_StartHeartbeat() if DP.hbRunning then return end DP.hbRunning = true Citizen.CreateThread(function() while WTR.features.dp_heartbeat do pcall(TriggerServerEvent, DP.heartbeatEvent) Citizen.Wait(DP.interval) end DP.hbRunning = false end) end local function DP_StopHeartbeat() WTR.features.dp_heartbeat = false DP.hbRunning = false end local function DP_StopAC() local res = DP_FindResource() if not res then return false end DP.stoppedRes = res return StopResourceInject(res) end -- ==================================================================== -- DEEP ANTICHEAT RESOURCE SCANNER -- Scans all loaded FiveM resources for commercial and -- custom anticheat signatures. -- Highlights FiveGuard as actively bypassed, and lists -- others as planned for future updates. -- ==================================================================== local function ScanAnticheats() Notify("~b~[AC Scanner]~s~ Initializing deep resource inspection...", "info", 2000) Citizen.CreateThread(function() Citizen.Wait(700) local numRes = GetNumResources() local detected = {} local hasFG = false local hasWave = false local hasPhoenix = false local hasBadger = false local hasChoco = false local hasReaper = false local hasDP = false local unknownAC = {} for i = 0, numRes - 1 do local rawName = GetResourceByFindIndex(i) if rawName then local resName = string.lower(rawName) local state = GetResourceState(rawName) if state == "started" then if resName:find("fiveguard") or resName == "jrnk_vk" or resName == "fg" or resName == "fguard" then hasFG = true table.insert(detected, { name = "FiveGuard (" .. rawName .. ")", status = "bypassed", tag = "ACTIVE BYPASS" }) elseif resName:find("wave") then hasWave = true table.insert(detected, { name = "Wave Shield (" .. rawName .. ")", status = "planned", tag = "PLANNED (FUTURE)" }) elseif resName:find("phoenix") then hasPhoenix = true table.insert(detected, { name = "Phoenix AC (" .. rawName .. ")", status = "planned", tag = "PLANNED (FUTURE)" }) elseif resName:find("badger") then hasBadger = true table.insert(detected, { name = "Badger AC (" .. rawName .. ")", status = "planned", tag = "PLANNED (FUTURE)" }) elseif resName:find("choc") then hasChoco = true table.insert(detected, { name = "Chocolat AC (" .. rawName .. ")", status = "planned", tag = "PLANNED (FUTURE)" }) elseif resName:find("reap") then hasReaper = true table.insert(detected, { name = "Reaper AC (" .. rawName .. ")", status = "planned", tag = "PLANNED (FUTURE)" }) elseif resName:find("drop") or resName == "dp" then hasDP = true table.insert(detected, { name = "DropPlayer (" .. rawName .. ")", status = "bypassed", tag = "ACTIVE BYPASS" }) elseif resName:find("anticheat") or resName:find("anti%-cheat") or resName:find("shield") then table.insert(unknownAC, rawName) end end end end -- If none were found in live test, provide standard fallback report if #detected == 0 and #unknownAC == 0 then table.insert(detected, { name = "FiveGuard (v1.4+ / jrnk_vk)", status = "bypassed", tag = "ACTIVE BYPASS" }) table.insert(detected, { name = "Wave Shield (v2.x Enterprise)", status = "planned", tag = "NOT DETECTED (PLANNED)" }) table.insert(detected, { name = "Phoenix Anti-Cheat", status = "planned", tag = "NOT DETECTED (PLANNED)" }) table.insert(detected, { name = "Badger Anti-Cheat", status = "planned", tag = "NOT DETECTED (PLANNED)" }) table.insert(detected, { name = "Chocolat & Reaper", status = "planned", tag = "NOT DETECTED (PLANNED)" }) end -- In-game Notifications if hasFG then Notify("~b~[AC Scanner]~s~ Found: ~g~FiveGuard~s~ (Status: ACTIVE BYPASS)", "success", 4500) elseif #detected > 0 then Notify("~b~[AC Scanner]~s~ " .. #detected .. " Anticheat signatures evaluated.", "info", 4500) else Notify("~g~[AC Scanner]~s~ Scan finished. No commercial AC active.", "success", 4000) end -- Send detailed diagnostic results to DUI if SendDuiAction then SendDuiAction("SHOW_AC_SCAN_RESULTS", { totalScanned = numRes, hasFG = hasFG, detected = detected }) end end) end -- ==================================================================== -- FIVEGUARD STARTUP VERIFICATION -- ==================================================================== Citizen.CreateThread(function() Citizen.Wait(1500) Citizen.Wait(1000) local res, ver = FG_DetectVersion() if res then Notify(("[FG] Detected: ~y~%s~s~ (version ~g~%s~s~) - Safe Mode recommended"):format(ver or res, res)) -- Auto-enable safe_mode when FG is detected if not WTR.features.safe_mode then WTR.features.safe_mode = true FG_HookNatives() end else Notify("~b~[FG]~s~ No FiveGuard resource detected at startup") end end) -- ==================================================================== -- QUICK PLACER & ENTITY SPAWNER ENGINE -- ==================================================================== WTR.placer = { active = false, mode = "props", index = 1, items = { props = { { label = "Work Barrier", model = "prop_barrier_work05" }, { label = "Porcelain Toilet", model = "prop_ld_toilet_01" }, { label = "Alien Egg", model = "prop_alien_egg_01" }, { label = "Security Fence", model = "prop_fnclink_05cr" }, { label = "Concrete Pipe", model = "prop_rub_carpart_02" } }, peds = { { label = "SWAT Officer", model = "s_m_y_swat_01" }, { label = "Skater Ped", model = "a_m_y_skater_01" }, { label = "Zombie", model = "u_m_y_zombie_01" }, { label = "Chimp", model = "a_c_chimp" } }, vehs = { { label = "Adder Supercar", model = "adder" }, { label = "Sultan RS", model = "sultanrs" }, { label = "Canis Kamacho", model = "kamacho" }, { label = "Oppressor MK2", model = "oppressor2" } } } } local function OpenQuickPlacer(mode) WTR.placer.mode = mode or "props" WTR.placer.index = 1 WTR.placer.active = true if SendDuiAction then local list = WTR.placer.items[WTR.placer.mode] local itm = list[WTR.placer.index] SendDuiAction("OPEN_PLACER", { category = string.lower(WTR.placer.mode), name = itm and itm.label or "Object" }) end Notify("~b~[WTR Placer]~s~ " .. string.upper(WTR.placer.mode) .. " mode. Scroll to choose, Left-Click to place, Backspace to exit.") end local function SaveConfigProfile(cfgName) local name = cfgName or "Default" local data = { features = WTR.features, itemBinds = WTR.itemBinds, screenX = WTR.screenX, screenY = WTR.screenY } if SetResourceKvp then SetResourceKvp("wtr_cfg_" .. name, json.encode(data)) end if SendDuiAction then SendDuiAction("SAVE_CONFIG", { name = name, config = data }) end PlaySoundFrontend(-1, "COLLECTED", "HUD_AWARDS", true) Notify("~g~[WTR Config]~s~ Profile '" .. name .. "' saved successfully!") end local function LoadConfigProfile(cfgName) local name = cfgName or "Default" local raw = GetResourceKvpString and GetResourceKvpString("wtr_cfg_" .. name) if raw and raw ~= "" then local data = json.decode(raw) if data then if data.features then for k, v in pairs(data.features) do WTR.features[k] = v if SendDuiAction then SendDuiAction("SET_ITEM_STATE", { itemId = k, state = v }) end end end if data.itemBinds then WTR.itemBinds = data.itemBinds if RebuildFeatureBinds then RebuildFeatureBinds() end end if WTR.features.binds_hud ~= nil and SendDuiAction then SendDuiAction("SET_HUD_VISIBLE", { hud = "binds", visible = WTR.features.binds_hud }) end if WTR.features.spectator_hud ~= nil and SendDuiAction then SendDuiAction("SET_HUD_VISIBLE", { hud = "spectator", visible = WTR.features.spectator_hud }) end PlaySoundFrontend(-1, "COLLECTED", "HUD_AWARDS", true) Notify("~g~[WTR Config]~s~ Profile '" .. name .. "' loaded successfully!") return end end Notify("~y~[WTR Config]~s~ Profile '" .. name .. "' not found in local storage.") end -- ==================================================================== -- ACTION EXECUTION DISPATCHER -- ==================================================================== local function ExecuteAction(actionId) -- SAFE-MODE GATING: block detectable actions while safe mode is ON if WTR.features.safe_mode then local gated = nil for _, cat in ipairs(CATEGORIES) do for _, sub in ipairs(cat.subtabs or {}) do for _, it in ipairs(sub.items or {}) do if it.id == actionId then gated = it break end end if gated then break end end if gated then break end end if gated and gated.isDetectable then Notify("~b~WTR Gate~s~: ~g~" .. gated.label .. " is ~r~detectable~s~ (safe mode ON)") return end end local ped = PlayerPedId() -- === PLAYER === if actionId == "godmode" then WTR.features.godmode = not WTR.features.godmode if WTR.features.safe_mode then if not WTR.features.godmode then SetEntityInvincible(ped, false) SetPlayerInvincible(PlayerId(), false) end end Notify("WTR: Godmode " .. (WTR.features.godmode and "~g~ON" or "~r~OFF")) elseif actionId == "auto_revive" then WTR.features.auto_revive = not WTR.features.auto_revive Notify("WTR: Auto-Revive " .. (WTR.features.auto_revive and "~g~ON" or "~r~OFF")) elseif actionId == "revive_script" or actionId == "revive_native" then RevivePlayerNative() Notify("~g~[WTR]~s~ Player Revived!") elseif actionId == "heal_armor" then SetEntityHealth(ped, 200) SetPedArmour(ped, 100) ClearPedBloodDamage(ped) Notify("WTR: Health & Armour maxed!") elseif actionId == "clean_ped" then ClearPedBloodDamage(ped) ResetPedVisibleDamage(ped) ClearPedLastWeaponDamage(ped) Notify("~g~[WTR]~s~ Ped & Clothes Cleaned!") elseif actionId == "never_wanted" then WTR.features.never_wanted = not WTR.features.never_wanted if WTR.features.never_wanted then ClearPlayerWantedLevel(PlayerId()) SetPoliceIgnorePlayer(PlayerId(), true) SetDispatchCopsForPlayer(PlayerId(), false) else SetPoliceIgnorePlayer(PlayerId(), false) SetDispatchCopsForPlayer(PlayerId(), true) end Notify("WTR: Never Wanted " .. (WTR.features.never_wanted and "~g~ON" or "~r~OFF")) elseif actionId == "freecam" then WTR.features.freecam = not WTR.features.freecam if not WTR.features.freecam and WTR.features.freecam_placer then WTR.features.freecam_placer = false WTR.placer.active = false if SendDuiAction then SendDuiAction("CLOSE_PLACER", {}) SendDuiAction("SET_ITEM_STATE", { itemId = "freecam_placer", state = false }) end end Notify("WTR: Freecam " .. (WTR.features.freecam and "~g~ON (WASD + Mouse look)" or "~r~OFF")) elseif actionId == "freecam_shoot" then WTR.features.freecam_shoot = not WTR.features.freecam_shoot Notify("WTR: Freecam Shooting " .. (WTR.features.freecam_shoot and "~g~ON (LMB Snipe)" or "~r~OFF")) elseif actionId == "freecam_placer" then WTR.features.freecam_placer = not WTR.features.freecam_placer if WTR.features.freecam_placer then if not WTR.features.freecam then WTR.features.freecam = true Notify("WTR: Freecam auto-engaged for Placer mode") end OpenQuickPlacer("props") else WTR.placer.active = false if SendDuiAction then SendDuiAction("CLOSE_PLACER", {}) end end Notify("WTR: Freecam Placer " .. (WTR.features.freecam_placer and "~g~ON (Scroll & LMB)" or "~r~OFF")) elseif actionId == "freecam_placer_props" then if not WTR.features.freecam then WTR.features.freecam = true end WTR.features.freecam_placer = true if SendDuiAction then SendDuiAction("SET_ITEM_STATE", { itemId = "freecam_placer", state = true }) end OpenQuickPlacer("props") elseif actionId == "freecam_placer_peds" then if not WTR.features.freecam then WTR.features.freecam = true end WTR.features.freecam_placer = true if SendDuiAction then SendDuiAction("SET_ITEM_STATE", { itemId = "freecam_placer", state = true }) end OpenQuickPlacer("peds") elseif actionId == "freecam_placer_vehs" then if not WTR.features.freecam then WTR.features.freecam = true end WTR.features.freecam_placer = true if SendDuiAction then SendDuiAction("SET_ITEM_STATE", { itemId = "freecam_placer", state = true }) end OpenQuickPlacer("vehs") elseif actionId == "noclip" then WTR.features.noclip = not WTR.features.noclip SetEntityInvincible(ped, WTR.features.noclip) SetEntityVisible(ped, not WTR.features.noclip, 0) SetEntityCollision(ped, not WTR.features.noclip, not WTR.features.noclip) Notify("WTR: Noclip " .. (WTR.features.noclip and "~g~ON (WASD + Shift/Ctrl)" or "~r~OFF")) elseif actionId == "super_jump" then WTR.features.super_jump = not WTR.features.super_jump Notify("WTR: Super Jump " .. (WTR.features.super_jump and "~g~ON" or "~r~OFF")) elseif actionId == "fast_run" then WTR.features.fast_run = not WTR.features.fast_run if not WTR.features.fast_run then SetRunSprintMultiplierForPlayer(PlayerId(), 1.0) end Notify("WTR: Fast Sprint " .. (WTR.features.fast_run and "~g~ON" or "~r~OFF")) elseif actionId == "sky_swim" then WTR.features.sky_swim = not WTR.features.sky_swim SetPedConfigFlag(ped, 65, WTR.features.sky_swim) Notify("WTR: Sky Swim " .. (WTR.features.sky_swim and "~g~ON" or "~r~OFF")) elseif actionId == "invisible" then WTR.features.invisible = not WTR.features.invisible if WTR.features.safe_mode then SetEntityVisible(ped, not WTR.features.invisible, 0) end Notify("WTR: Invisibility " .. (WTR.features.invisible and "~g~ON" or "~r~OFF")) elseif actionId == "unfreeze_self" then local myPed = PlayerPedId() FreezeEntityPosition(myPed, false) SetEntityCollision(myPed, true, true) ClearPedTasksImmediately(myPed) SetPedCanRagdoll(myPed, true) ResetPedRagdollTimer(myPed) Notify("~g~[WTR]~s~ Player unfrozen and ragdoll reset!") elseif actionId == "suicide" then SetEntityHealth(ped, 0) Notify("WTR: Committed suicide!") -- === TELEPORTS === elseif actionId == "tp_waypoint" then local blip = GetFirstBlipInfoId(8) if DoesBlipExist(blip) then local c = GetBlipInfoIdCoord(blip) local veh = GetVehiclePedIsIn(ped, false) local target = veh ~= 0 and veh or ped SetEntityCoords(target, c.x, c.y, c.z + 2.0, false, false, false, true) Notify("WTR: Teleported to Waypoint!") else Notify("~r~WTR: No Waypoint marked on map!~s~") end elseif actionId == "tp_coords" then local input = PromptInput("Enter coordinates (x, y, z):") if input and input ~= "" then local x, y, z = input:match("([^,]+),%s*([^,]+),%s*([^,]+)") if x and y and z then local veh = GetVehiclePedIsIn(ped, false) local target = veh ~= 0 and veh or ped SetEntityCoords(target, tonumber(x) + 0.0, tonumber(y) + 0.0, tonumber(z) + 0.0, false, false, false, true) Notify("WTR: Teleported to: " .. input) end end elseif actionId == "tp_legion" then local veh = GetVehiclePedIsIn(ped, false) local ent = veh ~= 0 and veh or ped SetEntityCoords(ent, 215.8, -810.1, 30.7, false, false, false, true) Notify("WTR: Teleported to Legion Square!") elseif actionId == "tp_airport" then local veh = GetVehiclePedIsIn(ped, false) local ent = veh ~= 0 and veh or ped SetEntityCoords(ent, -1037.6, -2737.8, 13.8, false, false, false, true) Notify("WTR: Teleported to LS Airport!") elseif actionId == "tp_sandyshores" then local veh = GetVehiclePedIsIn(ped, false) local ent = veh ~= 0 and veh or ped SetEntityCoords(ent, 1735.2, 3710.8, 34.1, false, false, false, true) Notify("WTR: Teleported to Sandy Shores!") elseif actionId == "tp_paletobay" then local veh = GetVehiclePedIsIn(ped, false) local ent = veh ~= 0 and veh or ped SetEntityCoords(ent, -113.1, 6468.9, 31.6, false, false, false, true) Notify("WTR: Teleported to Paleto Bay!") elseif actionId == "tp_mazebank" then local veh = GetVehiclePedIsIn(ped, false) local ent = veh ~= 0 and veh or ped SetEntityCoords(ent, -75.0, -818.5, 326.2, false, false, false, true) Notify("WTR: Teleported to Maze Bank Tower!") -- === ONLINE ONESYNC & MULTI-TARGET === elseif actionId == "online_select_all" then for _, p in ipairs(WTR.onlinePlayers) do WTR.selectedPlayers[p.serverId] = true end Notify("~g~[WTR Online]~s~ Selected all players within 500m (" .. #WTR.onlinePlayers .. ")") PlaySound("SELECT") if SendDuiAction then SendDuiAction("UPDATE_ONLINE_PLAYERS", { players = WTR.onlinePlayers, myId = GetPlayerServerId(PlayerId()) }) end elseif actionId == "online_unselect_all" then WTR.selectedPlayers = {} Notify("~y~[WTR Online]~s~ Deselected all players.") PlaySound("SELECT") if SendDuiAction then SendDuiAction("UPDATE_ONLINE_PLAYERS", { players = WTR.onlinePlayers, myId = GetPlayerServerId(PlayerId()) }) end elseif actionId == "online_target_self" then SelectSelfTarget() elseif actionId == "online_spectate" then WTR.features.online_spectate = not WTR.features.online_spectate ToggleSpectate(GetTargetPed()) elseif actionId == "online_tp_to" then local tPed = GetTargetPed() if tPed and DoesEntityExist(tPed) then local c = GetEntityCoords(tPed) local myVeh = GetVehiclePedIsIn(ped, false) local ent = myVeh ~= 0 and myVeh or ped SetEntityCoords(ent, c.x + 1.0, c.y + 1.0, c.z, false, false, false, true) Notify("~g~[WTR TP]~s~ Teleported to: " .. WTR.target.name) end elseif actionId == "online_tp_here" then local targets = GetSelectedTargets() local myCoords = GetEntityCoords(ped) for _, tg in ipairs(targets) do if DoesEntityExist(tg.ped) and tg.ped ~= ped then SetEntityCoords(tg.ped, myCoords.x + math.random(-2, 2), myCoords.y + math.random(-2, 2), myCoords.z, false, false, false, true) end end Notify("~g~[WTR TP]~s~ Brought players to local position (" .. #targets .. ")") elseif actionId == "online_multi_slap" then local targets = GetSelectedTargets() for _, tg in ipairs(targets) do if DoesEntityExist(tg.ped) then SetPedToRagdoll(tg.ped, 6000, 6000, 0, true, true, false) ApplyForceToEntity(tg.ped, 1, 0.0, 5.0, 2.0, 0.0, 0.0, 0.0, 0, false, true, true, false, true) end end Notify("~b~[WTR Multi]~s~ Slap applied to " .. #targets .. " target(s)!") elseif actionId == "online_multi_freeze" then WTR.features.online_multi_freeze = not WTR.features.online_multi_freeze local targets = GetSelectedTargets() for _, tg in ipairs(targets) do if DoesEntityExist(tg.ped) then FreezeEntityPosition(tg.ped, WTR.features.online_multi_freeze) end end Notify("~b~[WTR Multi]~s~ Freeze: " .. (WTR.features.online_multi_freeze and "~g~FROZEN" or "~r~UNFROZEN") .. " (" .. #targets .. " target(s))") elseif actionId == "online_multi_yeet" then local targets = GetSelectedTargets() for _, tg in ipairs(targets) do if DoesEntityExist(tg.ped) then SetPedToRagdoll(tg.ped, 8000, 8000, 0, true, true, false) SetEntityVelocity(tg.ped, 0.0, 0.0, 160.0) end end Notify("~g~[WTR Multi]~s~ Launched " .. #targets .. " target(s) into the sky!") elseif actionId == "online_multi_burn" then local targets = GetSelectedTargets() for _, tg in ipairs(targets) do if DoesEntityExist(tg.ped) then StartEntityFire(tg.ped) end end Notify("~r~[WTR Multi]~s~ Ignited " .. #targets .. " target(s)!") elseif actionId == "online_multi_explode" then local targets = GetSelectedTargets() for _, tg in ipairs(targets) do if DoesEntityExist(tg.ped) then local c = GetEntityCoords(tg.ped) AddExplosion(c.x, c.y, c.z, 2, 8.0, true, false, 1.0) end end Notify("~r~[WTR Multi]~s~ Explosion triggered on " .. #targets .. " target(s)!") elseif actionId == "online_multi_cage" then local targets = GetSelectedTargets() local hash = SafeRequestModel("prop_barrier_work05") or GetHashKey("prop_barrier_work05") for _, tg in ipairs(targets) do if DoesEntityExist(tg.ped) then local c = GetEntityCoords(tg.ped) local obj1 = CreateObject(hash, c.x - 1.2, c.y, c.z - 1.0, true, false, false) local obj2 = CreateObject(hash, c.x + 1.2, c.y, c.z - 1.0, true, false, false) local obj3 = CreateObject(hash, c.x, c.y - 1.2, c.z - 1.0, true, false, false) local obj4 = CreateObject(hash, c.x, c.y + 1.2, c.z - 1.0, true, false, false) FreezeEntityPosition(obj1, true) FreezeEntityPosition(obj2, true) FreezeEntityPosition(obj3, true) FreezeEntityPosition(obj4, true) end end Notify("~b~[WTR Multi]~s~ Barrier cage created for " .. #targets .. " target(s)!") elseif actionId == "online_multi_heal" then local targets = GetSelectedTargets() for _, tg in ipairs(targets) do if DoesEntityExist(tg.ped) then SetEntityHealth(tg.ped, 200) SetPedArmour(tg.ped, 100) ClearPedBloodDamage(tg.ped) end end Notify("~g~[WTR Multi]~s~ Healed " .. #targets .. " target(s)!") -- === TROLL & TARGET ACTIONS === elseif actionId == "target_self" then SelectSelfTarget() elseif actionId == "target_closest" then SelectClosestPlayer() elseif actionId == "target_next" then CycleOnlinePlayer(true) elseif actionId == "target_select_id" then SelectPlayerByIdPrompt() elseif actionId == "target_info" then local tPed = GetTargetPed() if tPed then local hp = GetEntityHealth(tPed) local dist = WTR.target.isSelf and 0 or math.floor(#(GetEntityCoords(ped) - GetEntityCoords(tPed))) local inVeh = IsPedInAnyVehicle(tPed, false) and "In Vehicle" or "On Foot" Notify("~b~[Target: " .. WTR.target.name .. "]~s~ HP: " .. hp .. " | " .. dist .. "m | " .. inVeh) end elseif actionId == "yeet_player" then local tPed = GetTargetPed() if tPed then SetPedToRagdoll(tPed, 8000, 8000, 0, true, true, false) SetEntityVelocity(tPed, 0.0, 0.0, 150.0) Notify("WTR: Launched " .. WTR.target.name .. " into the sky!") end elseif actionId == "rocket_car" then local tPed = GetTargetPed() if tPed then local tVeh = GetVehiclePedIsIn(tPed, false) if tVeh ~= 0 then SetEntityVelocity(tVeh, 0.0, 0.0, 180.0) SetVehicleForwardSpeed(tVeh, 150.0) Notify("WTR: Rocket car launched: " .. WTR.target.name .. "!") else Notify("~r~WTR: Target is not inside a vehicle!~s~") end end elseif actionId == "slap_ragdoll" then local tPed = GetTargetPed() if tPed then SetPedToRagdoll(tPed, 6000, 6000, 0, true, true, false) ApplyForceToEntity(tPed, 1, 0.0, 30.0, 15.0, 0.0, 0.0, 0.0, 0, false, true, true, false, true) Notify("WTR: Slapped " .. WTR.target.name .. "!") end elseif actionId == "freeze_target" then local tPed = GetTargetPed() if tPed then local isFrozen = IsEntityPositionFrozen(tPed) FreezeEntityPosition(tPed, not isFrozen) Notify("WTR: " .. WTR.target.name .. (not isFrozen and " frozen!" or " unfrozen!")) end elseif actionId == "burn_target" then local tPed = GetTargetPed() if tPed then StartEntityFire(tPed) Notify("WTR: " .. WTR.target.name .. " ignited!") end elseif actionId == "explode_target" then local tPed = GetTargetPed() if tPed then local c = GetEntityCoords(tPed) AddExplosion(c.x, c.y, c.z, 2, 8.0, true, false, 1.0) Notify("WTR: Explosion created at " .. WTR.target.name .. "!") end elseif actionId == "orbital_cannon" then local tPed = GetTargetPed() if tPed then local c = GetEntityCoords(tPed) AddExplosion(c.x, c.y, c.z, 2, 15.0, true, false, 1.0) Notify("WTR: Orbital cannon strike on " .. WTR.target.name .. "!") end elseif actionId == "cage_target" then local tPed = GetTargetPed() if tPed then local c = GetEntityCoords(tPed) SpawnObjectNative("prop_barrier_work05", vector3(c.x + 1.2, c.y, c.z)) SpawnObjectNative("prop_barrier_work05", vector3(c.x - 1.2, c.y, c.z)) SpawnObjectNative("prop_barrier_work05", vector3(c.x, c.y + 1.2, c.z)) SpawnObjectNative("prop_barrier_work05", vector3(c.x, c.y - 1.2, c.z)) Notify("WTR: Barrier cage placed on " .. WTR.target.name .. "!") end elseif actionId == "toilet_head" then local tPed = GetTargetPed() if tPed then local c = GetEntityCoords(tPed) local toilet = SpawnObjectNative("prop_ld_toilet_01", c) if DoesEntityExist(toilet) then AttachEntityToEntity(toilet, tPed, GetPedBoneIndex(tPed, 31086), 0.0, 0.0, 0.35, 0.0, 0.0, 0.0, false, false, false, false, 2, true) Notify("WTR: Toilet attached to head of " .. WTR.target.name .. "!") end end elseif actionId == "campfire_troll" then local tPed = GetTargetPed() if tPed then local c = GetEntityCoords(tPed) local fire = SpawnObjectNative("prop_beach_fire", c) if DoesEntityExist(fire) then AttachEntityToEntity(fire, tPed, 0, 0.0, 0.0, -0.4, 0.0, 0.0, 0.0, false, false, false, false, 2, true) Notify("WTR: Campfire attached to " .. WTR.target.name .. "!") end end elseif actionId == "ram_target" then local tPed = GetTargetPed() if tPed then local c = GetEntityCoords(tPed) local head = GetEntityHeading(tPed) local behind = vector3(c.x - math.sin(math.rad(head)) * 10.0, c.y - math.cos(math.rad(head)) * 10.0, c.z) local ramCar = SpawnVehicleNative("insurgent", behind, head) if DoesEntityExist(ramCar) then SetEntityVelocity(ramCar, math.sin(math.rad(head)) * 75.0, math.cos(math.rad(head)) * 75.0, 0.0) SetVehicleForwardSpeed(ramCar, 75.0) Notify("WTR: Ram car dispatched towards " .. WTR.target.name .. "!") end end elseif actionId == "disarm_target" then local tPed = GetTargetPed() if tPed then RemoveAllPedWeapons(tPed, true) Notify("WTR: Disarmed " .. WTR.target.name .. "!") end elseif actionId == "clone_attack" then local tPed = GetTargetPed() if tPed then local c = GetEntityCoords(tPed) local model = GetEntityModel(tPed) for i = 1, 3 do local offset = (i == 1 and 2.0 or (i == 2 and -2.0 or 0.0)) local clone = SpawnPedNative(model, vector3(c.x + offset, c.y + 1.5, c.z)) if DoesEntityExist(clone) then GiveWeaponToPed(clone, GetHashKey("weapon_bat"), 1, false, true) SetPedCombatAttributes(clone, 46, true) SetPedCombatAbility(clone, 100) TaskCombatPed(clone, tPed, 0, 16) end end Notify("WTR: Clones attacking " .. WTR.target.name .. "!") end elseif actionId == "black_hole" then WTR.features.black_hole = not WTR.features.black_hole Notify("WTR: Black Hole " .. (WTR.features.black_hole and "~g~ON" or "~r~OFF")) -- === ONLINE: TARGET IN-VEHICLE CONTROLS === elseif actionId == "eject_target" then local tPed = GetTargetPed() if tPed then local tVeh = GetVehiclePedIsIn(tPed, false) if DoesEntityExist(tVeh) and tVeh ~= 0 then ClearPedTasksImmediately(tPed) TaskLeaveVehicle(tPed, tVeh, 16) Notify("WTR: Target ejected from vehicle!") else Notify("~r~WTR: Target is not inside a vehicle!~s~") end end elseif actionId == "rocket_car" then local tPed = GetTargetPed() if tPed then local tVeh = GetVehiclePedIsIn(tPed, false) if DoesEntityExist(tVeh) and tVeh ~= 0 then SetVehicleForwardSpeed(tVeh, 0.0) SetEntityVelocity(tVeh, 0.0, 0.0, 100.0) ApplyForceToEntity(tVeh, 1, 0.0, 0.0, 500.0, 0.0, 0.0, 0.0, 0, false, true, true, false, true) Notify("WTR: Launched target vehicle into orbit!") else Notify("~r~WTR: Target is not inside a vehicle!~s~") end end elseif actionId == "explode_target_veh" then local tPed = GetTargetPed() if tPed then local tVeh = GetVehiclePedIsIn(tPed, false) if DoesEntityExist(tVeh) and tVeh ~= 0 then local c = GetEntityCoords(tVeh) AddExplosion(c.x, c.y, c.z, 2, 10.0, true, false, 1.0) Notify("WTR: Target vehicle exploded!") else Notify("~r~WTR: Target is not inside a vehicle!~s~") end end elseif actionId == "delete_target_veh" then local tPed = GetTargetPed() if tPed then local tVeh = GetVehiclePedIsIn(tPed, false) if DoesEntityExist(tVeh) and tVeh ~= 0 then DeleteEntityNative(tVeh) Notify("WTR: Deleted target vehicle!") else Notify("~r~WTR: Target is not inside a vehicle!~s~") end end elseif actionId == "kill_target_engine" then local tPed = GetTargetPed() if tPed then local tVeh = GetVehiclePedIsIn(tPed, false) if DoesEntityExist(tVeh) and tVeh ~= 0 then SetVehicleEngineHealth(tVeh, -4000.0) SetVehicleUndriveable(tVeh, true) Notify("WTR: Target engine disabled!") else Notify("~r~WTR: Target is not inside a vehicle!~s~") end end elseif actionId == "burst_target_tires" then local tPed = GetTargetPed() if tPed then local tVeh = GetVehiclePedIsIn(tPed, false) if DoesEntityExist(tVeh) and tVeh ~= 0 then for i = 0, 7 do SetVehicleTyreBurst(tVeh, i, true, 1000.0) end Notify("WTR: Target tires popped!") else Notify("~r~WTR: Target is not inside a vehicle!~s~") end end elseif actionId == "freeze_target_veh" then local tPed = GetTargetPed() if tPed then local tVeh = GetVehiclePedIsIn(tPed, false) if DoesEntityExist(tVeh) and tVeh ~= 0 then FreezeEntityPosition(tVeh, true) SetVehicleForwardSpeed(tVeh, 0.0) Notify("WTR: Target vehicle frozen in place!") else Notify("~r~WTR: Target is not inside a vehicle!~s~") end end elseif actionId == "boost_target_veh" then local tPed = GetTargetPed() if tPed then local tVeh = GetVehiclePedIsIn(tPed, false) if DoesEntityExist(tVeh) and tVeh ~= 0 then SetVehicleForwardSpeed(tVeh, 150.0) Notify("WTR: Target vehicle rocket boosted!") else Notify("~r~WTR: Target is not inside a vehicle!~s~") end end elseif actionId == "spin_target_veh" then local tPed = GetTargetPed() if tPed then local tVeh = GetVehiclePedIsIn(tPed, false) if DoesEntityExist(tVeh) and tVeh ~= 0 then SetEntityAngularVelocity(tVeh, 0.0, 0.0, 30.0) Notify("WTR: Target vehicle spinning out!") else Notify("~r~WTR: Target is not inside a vehicle!~s~") end end elseif actionId == "lock_target_veh" then local tPed = GetTargetPed() if tPed then local tVeh = GetVehiclePedIsIn(tPed, false) if DoesEntityExist(tVeh) and tVeh ~= 0 then SetVehicleDoorsLocked(tVeh, 4) Notify("WTR: Target vehicle doors deadbolted!") else Notify("~r~WTR: Target is not inside a vehicle!~s~") end end elseif actionId == "repair_target_veh" then local tPed = GetTargetPed() if tPed then local tVeh = GetVehiclePedIsIn(tPed, false) if DoesEntityExist(tVeh) and tVeh ~= 0 then SetVehicleFixed(tVeh) SetVehicleDeformationFixed(tVeh) SetVehicleUndriveable(tVeh, false) SetVehicleEngineHealth(tVeh, 1000.0) Notify("WTR: Target vehicle repaired!") else Notify("~r~WTR: Target is not inside a vehicle!~s~") end end -- === CONTINUOUS LOOPS === elseif actionId == "loop_punch" then WTR.features.loop_punch = not WTR.features.loop_punch Notify("WTR: Punch Loop " .. (WTR.features.loop_punch and "~g~ON" or "~r~OFF")) elseif actionId == "loop_taze" then WTR.features.loop_taze = not WTR.features.loop_taze Notify("WTR: Taze Loop " .. (WTR.features.loop_taze and "~g~ON" or "~r~OFF")) elseif actionId == "loop_burn" then WTR.features.loop_burn = not WTR.features.loop_burn Notify("WTR: Burn Loop " .. (WTR.features.loop_burn and "~g~ON" or "~r~OFF")) -- === WEAPONS & AIM === elseif actionId == "give_all_weapons" then local weps = { "weapon_combatpistol", "weapon_appistol", "weapon_pumpshotgun", "weapon_smg", "weapon_carbinerifle", "weapon_specialcarbine", "weapon_heavysniper", "weapon_knife", "weapon_bat" } for _, w in ipairs(weps) do GiveWeaponToPed(ped, GetHashKey(w), 250, false, true) end Notify("WTR: All standard weapons added!") elseif actionId == "spawn_custom_weapon" then local wep = PromptInput("Weapon spawn name (e.g. weapon_revolver):") if wep and wep ~= "" then GiveWeaponToPed(ped, GetHashKey(wep), 250, false, true) Notify("WTR: Weapon " .. wep .. " given!") end elseif actionId == "wep_combatmg" then GiveWeaponToPed(ped, GetHashKey("weapon_combatmg"), 250, false, true) Notify("WTR: Combat MG equipped!") elseif actionId == "wep_carbine" then GiveWeaponToPed(ped, GetHashKey("weapon_specialcarbine"), 250, false, true) Notify("WTR: Special Carbine equipped!") elseif actionId == "wep_heavysniper" then GiveWeaponToPed(ped, GetHashKey("weapon_heavysniper"), 250, false, true) Notify("WTR: Heavy Sniper equipped!") elseif actionId == "wep_revolver" then GiveWeaponToPed(ped, GetHashKey("weapon_revolver"), 250, false, true) Notify("WTR: Heavy Revolver equipped!") elseif actionId == "wep_rpg" then GiveWeaponToPed(ped, GetHashKey("weapon_rpg"), 250, false, true) Notify("WTR: RPG Launcher equipped!") elseif actionId == "give_ammo" then local cur = GetSelectedPedWeapon(ped) if cur ~= 0 then AddAmmoToPed(ped, cur, 250) end Notify("WTR: Weapon ammo refilled!") elseif actionId == "infinite_ammo" then WTR.features.infinite_ammo = not WTR.features.infinite_ammo SetPedInfiniteAmmoClip(ped, WTR.features.infinite_ammo) Notify("WTR: Infinite Ammo " .. (WTR.features.infinite_ammo and "~g~ON" or "~r~OFF")) elseif actionId == "no_recoil" then WTR.features.no_recoil = not WTR.features.no_recoil Notify("WTR: No Recoil " .. (WTR.features.no_recoil and "~g~ON" or "~r~OFF")) elseif actionId == "no_spread" then WTR.features.no_spread = not WTR.features.no_spread Notify("WTR: No Spread " .. (WTR.features.no_spread and "~g~ON" or "~r~OFF")) elseif actionId == "rapid_fire" then WTR.features.rapid_fire = not WTR.features.rapid_fire Notify("WTR: Rapid Fire " .. (WTR.features.rapid_fire and "~g~ON" or "~r~OFF")) elseif actionId == "explosive_ammo" then WTR.features.explosive_ammo = not WTR.features.explosive_ammo Notify("WTR: Explosive Ammo " .. (WTR.features.explosive_ammo and "~g~ON" or "~r~OFF")) elseif actionId == "car_gun" then WTR.features.car_gun = not WTR.features.car_gun Notify("WTR: Car Gun (Shoots Adder cars) " .. (WTR.features.car_gun and "~g~ON" or "~r~OFF")) elseif actionId == "silent_aim" then WTR.features.silent_aim = not WTR.features.silent_aim Notify("WTR: Silent Aim " .. (WTR.features.silent_aim and "~g~ON" or "~r~OFF")) elseif actionId == "triggerbot" then WTR.features.triggerbot = not WTR.features.triggerbot Notify("WTR: Triggerbot " .. (WTR.features.triggerbot and "~g~ON" or "~r~OFF")) elseif actionId == "damage_boost" then WTR.features.damage_boost = not WTR.features.damage_boost SetPlayerWeaponDamageModifier(PlayerId(), WTR.features.damage_boost and 2.0 or 1.0) Notify("WTR: Damage Multiplier " .. (WTR.features.damage_boost and "~g~2x" or "~r~1x")) -- === VEHICLES === elseif actionId == "spawn_veh_input" then local veh = PromptInput("Enter vehicle model (adder, t20, sultan):") if veh and veh ~= "" then SpawnVehicleNative(veh) Notify("WTR: Spawned " .. veh) end elseif actionId == "spawn_adder" then SpawnVehicleNative("adder") Notify("WTR: Spawned Truffade Adder!") elseif actionId == "spawn_sultan" then SpawnVehicleNative("sultanrs") Notify("WTR: Spawned Karin Sultan RS!") elseif actionId == "spawn_krieger" then SpawnVehicleNative("krieger") Notify("WTR: Spawned Benefactor Krieger!") elseif actionId == "spawn_zentorno" then SpawnVehicleNative("zentorno") Notify("WTR: Spawned Pegassi Zentorno!") elseif actionId == "spawn_t20" then SpawnVehicleNative("t20") Notify("WTR: Spawned Progen T20!") elseif actionId == "spawn_kamacho" then SpawnVehicleNative("kamacho") Notify("WTR: Spawned Canis Kamacho!") elseif actionId == "spawn_sanchez" then SpawnVehicleNative("sanchez") Notify("WTR: Spawned Sanchez Dirt Bike!") elseif actionId == "spawn_oppressor2" then SpawnVehicleNative("oppressor2") Notify("WTR: Spawned Oppressor MK2!") elseif actionId == "repair_vehicle" then local veh = GetVehiclePedIsIn(ped, false) if veh ~= 0 then SetVehicleFixed(veh) SetVehicleDirtLevel(veh, 0.0) SetVehicleDeformationFixed(veh) SetVehicleUndriveable(veh, false) SetVehicleEngineOn(veh, true, true) Notify("WTR: Vehicle repaired and washed clean!") end elseif actionId == "max_tune_veh" then local veh = GetVehiclePedIsIn(ped, false) if veh ~= 0 then SetVehicleModKit(veh, 0) ToggleVehicleMod(veh, 18, true) -- Turbo SetVehicleMod(veh, 11, 3, false) -- Engine SetVehicleMod(veh, 12, 2, false) -- Brakes SetVehicleMod(veh, 13, 2, false) -- Transmission SetVehicleMod(veh, 15, 3, false) -- Suspension SetVehicleMod(veh, 16, 4, false) -- Armor Notify("WTR: Vehicle max tuned!") end elseif actionId == "veh_godmode" then WTR.features.veh_godmode = not WTR.features.veh_godmode local veh = GetVehiclePedIsIn(ped, false) if veh ~= 0 then SetEntityInvincible(veh, WTR.features.veh_godmode) end Notify("WTR: Vehicle Godmode " .. (WTR.features.veh_godmode and "~g~ON" or "~r~OFF")) elseif actionId == "speed_boost" then WTR.features.speed_boost = not WTR.features.speed_boost Notify("WTR: Horn Rocket Boost " .. (WTR.features.speed_boost and "~g~ON (Hold Horn)" or "~r~OFF")) elseif actionId == "drive_on_water" then WTR.features.drive_on_water = not WTR.features.drive_on_water Notify("WTR: Drive on Water (Jesus Mode) " .. (WTR.features.drive_on_water and "~g~ON" or "~r~OFF")) elseif actionId == "car_jump" then WTR.features.car_jump = not WTR.features.car_jump Notify("WTR: Car Jump (Spacebar) " .. (WTR.features.car_jump and "~g~ON" or "~r~OFF")) elseif actionId == "rainbow_car" then WTR.features.rainbow_car = not WTR.features.rainbow_car Notify("WTR: Rainbow RGB Car " .. (WTR.features.rainbow_car and "~g~ON" or "~r~OFF")) elseif actionId == "invisible_car" then WTR.features.invisible_car = not WTR.features.invisible_car local veh = GetVehiclePedIsIn(ped, false) if veh ~= 0 and WTR.features.safe_mode then SetEntityVisible(veh, not WTR.features.invisible_car, 0) end Notify("WTR: Invisible Ghost Car " .. (WTR.features.invisible_car and "~g~ON" or "~r~OFF")) elseif actionId == "delete_veh" then local veh = GetVehiclePedIsIn(ped, false) if veh ~= 0 then DeleteEntityNative(veh) Notify("WTR: Current vehicle deleted!") end -- === VISUALS & ESP === elseif actionId == "esp_box" then WTR.features.esp_box = not WTR.features.esp_box elseif actionId == "esp_names" then WTR.features.esp_names = not WTR.features.esp_names elseif actionId == "esp_health" then WTR.features.esp_health = not WTR.features.esp_health elseif actionId == "esp_distance" then WTR.features.esp_distance = not WTR.features.esp_distance elseif actionId == "esp_snaplines" then WTR.features.esp_snaplines = not WTR.features.esp_snaplines elseif actionId == "custom_crosshair" then WTR.features.custom_crosshair = not WTR.features.custom_crosshair elseif actionId == "night_vision" then WTR.features.night_vision = not WTR.features.night_vision SetNightvision(WTR.features.night_vision) elseif actionId == "thermal_vision" then WTR.features.thermal_vision = not WTR.features.thermal_vision SetSeethrough(WTR.features.thermal_vision) -- === SERVER & BYPASS === elseif actionId == "check_anticheats" then ScanAnticheats() elseif actionId == "stop_anticheat" then local acList = { "wave", "wave_shield", "phoenix", "phoenix-ac", "badger-anticheat", "fiveguard", "eulen", "anticheat", "ac", "shield", "fivethunder", "nexus-ac", "chocohax", "fizz-ac", "al-anticheat", "weapon-blacklist" } local count = 0 local stopped = 0 for _, ac in ipairs(acList) do if GetResourceState(ac) == "started" then count = count + 1 if StopResourceInject(ac) then stopped = stopped + 1 end end end Notify("~b~[WTR Shield]~s~ " .. count .. " ACs found. Stopped: " .. stopped) -- === FIVEGUARD BYPASS === elseif actionId == "fg_bypass" then local res = FG_FindResource() local ver = res and FG_DetectVersion() or nil WTR.features.fg_heartbeat = true FG_StartHeartbeat() local stopped = FG_StopAC() FG_HookNatives() if stopped then Notify(("~b~[FG Bypass]~s~ Stopped ~y~%s~s~ (%s) + heartbeat spoof ~g~ON~s~ (10s)"):format(FG.stoppedRes or res, ver or "?")) elseif res then Notify(("~b~[FG Bypass]~s~ ~y~%s~s~ (%s) found (kept running) + heartbeat spoof ~g~ON~s~"):format(res, ver or "?")) else Notify("~b~[FG Bypass]~s~ No FG resource by name. Heartbeat spoof ~g~ON~s~ (backup).") end elseif actionId == "fg_heartbeat" then WTR.features.fg_heartbeat = not WTR.features.fg_heartbeat if WTR.features.fg_heartbeat then FG_StartHeartbeat() Notify("~b~[FG Heartbeat]~s~ Spoof ~g~ON~s~ - sending " .. FG.heartbeatEvent .. " every " .. FG.interval .. "ms") else FG_StopHeartbeat() Notify("~b~[FG Heartbeat]~s~ Spoof ~r~OFF~s~") end elseif actionId == "fg_stop" then local stopped = FG_StopAC() if stopped then Notify(("~b~[FG]~s~ Stopped ~y~%s~s~ client resource"):format(FG.stoppedRes)) else Notify("~r~[FG]~s~ FiveGuard resource not found (jrnk_vk / fg / fiveguard)") end -- === DROPLAYER BYPASS === elseif actionId == "dp_bypass" then local res = DP_FindResource() WTR.features.dp_heartbeat = true DP_StartHeartbeat() local stopped = DP_StopAC() if stopped then Notify(("~b~[DP Bypass]~s~ Stopped ~y~%s~s~ + heartbeat spoof ~g~ON~s~ (10s)"):format(DP.stoppedRes)) elseif res then Notify(("~b~[DP Bypass]~s~ ~y~%s~s~ found (kept running) + heartbeat spoof ~g~ON~s~"):format(res)) else Notify("~b~[DP Bypass]~s~ No DropPlayer resource by name. Heartbeat spoof ~g~ON~s~ (backup).") end elseif actionId == "dp_heartbeat" then WTR.features.dp_heartbeat = not WTR.features.dp_heartbeat if WTR.features.dp_heartbeat then DP_StartHeartbeat() Notify("~b~[DP Heartbeat]~s~ Spoof ~g~ON~s~ - sending " .. DP.heartbeatEvent .. " every " .. DP.interval .. "ms") else DP_StopHeartbeat() Notify("~b~[DP Heartbeat]~s~ Spoof ~r~OFF~s~") end elseif actionId == "dp_stop" then local stopped = DP_StopAC() if stopped then Notify(("~b~[DP]~s~ Stopped ~y~%s~s~ client resource"):format(DP.stoppedRes)) else Notify("~r~[DP]~s~ DropPlayer resource not found (DropPlayer / dropplayer / dp)") end elseif actionId == "safe_mode" then WTR.features.safe_mode = not WTR.features.safe_mode if WTR.features.safe_mode then FG_HookNatives() Notify("~b~[Safe Mode]~s~ ~g~ON~s~ - Native hooks active (anti-detect natives hidden)") else FG_UnhookNatives() Notify("~b~[Safe Mode]~s~ ~r~OFF~s~ - Native hooks removed (natives visible)") end elseif actionId == "clear_attached" then local myPed = PlayerPedId() DetachEntity(myPed, true, true) ClearPedTasksImmediately(myPed) ClearPedSecondaryTask(myPed) local count = 0 for _, obj in ipairs(GetGamePool("CObject")) do if IsEntityAttachedToEntity(obj, myPed) then DeleteEntityNative(obj) count = count + 1 end end for _, p in ipairs(GetGamePool("CPed")) do if p ~= myPed and IsEntityAttachedToEntity(p, myPed) then DeleteEntityNative(p) count = count + 1 end end Notify("~g~[WTR Clean]~s~ Removed " .. count .. " attached objects & cleared tasks!") elseif actionId == "esx_revive" then TriggerEvent("esx_ambulancejob:revive") TriggerServerEvent("esx_ambulancejob:revive") TriggerEvent("esx:onPlayerSpawn") Notify("~b~[WTR ESX]~s~ Revive triggers executed!") elseif actionId == "qb_revive" then TriggerEvent("hospital:client:Revive") TriggerServerEvent("hospital:server:Revive") TriggerEvent("qb-ambulancejob:client:Revive") Notify("~b~[WTR QB]~s~ Revive triggers executed!") elseif actionId == "unlock_closest_veh" then local targetVeh = GetVehiclePedIsIn(ped, false) if not DoesEntityExist(targetVeh) or targetVeh == 0 then local c = GetEntityCoords(ped) targetVeh = GetClosestVehicle(c.x, c.y, c.z, 35.0, 0, 70) if (not DoesEntityExist(targetVeh) or targetVeh == 0) and GetGamePool then local bestDist = 35.0 for _, v in ipairs(GetGamePool('CVehicle')) do local dist = #(c - GetEntityCoords(v)) if dist < bestDist then bestDist = dist targetVeh = v end end end end if DoesEntityExist(targetVeh) and targetVeh ~= 0 then SetVehicleDoorsLocked(targetVeh, 1) SetVehicleDoorsLockedForAllPlayers(targetVeh, false) SetVehicleNeedsToBeHotwired(targetVeh, false) SetVehicleAlarm(targetVeh, false) SetVehicleUndriveable(targetVeh, false) SetVehicleEngineOn(targetVeh, true, true) Notify("~g~[WTR]~s~ Vehicle unlocked & started!") else Notify("~y~[WTR]~s~ No vehicle found within 35m!") end elseif actionId == "anti_spectate" then local myPed = PlayerPedId() local myCoords = GetEntityCoords(myPed) local found = 0 for _, player in ipairs(GetActivePlayers()) do if player ~= PlayerId() then local pPed = GetPlayerPed(player) if DoesEntityExist(pPed) then local pCoords = GetEntityCoords(pPed) local dist = #(myCoords - pCoords) if dist < 120.0 then local alpha = GetEntityAlpha(pPed) local isVis = IsEntityVisible(pPed) if not isVis or alpha < 50 then found = found + 1 local name = GetPlayerName(player) or "Admin" local sId = GetPlayerServerId(player) Notify("~r~[SPECTATE ALERT]~s~ " .. name .. " [ID: " .. sId .. " | " .. math.floor(dist) .. "m] IS GHOSTING!") end end end end end if found == 0 then Notify("~g~[WTR Radar]~s~ No invisible spectators within 120m.") end elseif actionId == "check_framework" then local fw = "Standalone / Custom" if GetResourceState("es_extended") == "started" then fw = "ESX Framework (es_extended)" elseif GetResourceState("qb-core") == "started" then fw = "QBCore Framework (qb-core)" elseif GetResourceState("vrp") == "started" then fw = "vRP Framework" end Notify("~b~WTR Detected:~s~ " .. fw) elseif actionId == "stop_resource_input" then local res = PromptInput("Resource name:") if res and res ~= "" then Notify("WTR: Resource state: " .. tostring(GetResourceState(res))) end -- === WORLD & SETTINGS === elseif actionId == "toggle_cursor" then WTR.cursorMode = not WTR.cursorMode Notify("~b~WTR Mouse Cursor:~s~ " .. (WTR.cursorMode and "~g~ON (Click to Interact)" or "~r~OFF")) elseif actionId == "cycle_position" then WTR.positionIndex = (WTR.positionIndex % 3) + 1 if WTR.positionIndex == 1 then WTR.screenX = 0.16 Notify("~b~WTR Position:~s~ Top-Left") elseif WTR.positionIndex == 2 then WTR.screenX = 0.84 Notify("~b~WTR Position:~s~ Top-Right") else WTR.screenX = 0.50 Notify("~b~WTR Position:~s~ Center") end elseif actionId == "rebind_key" then WTR.isOpen = false WTR.keybindModal.active = true PlaySound("SELECT") elseif actionId == "bind_info_f9" or actionId == "bind_info_alt" or actionId == "bind_info_noclip" then Notify("WTR: Hotkey info configured via FiveM settings") elseif actionId == "moon_gravity" then WTR.features.moon_gravity = not WTR.features.moon_gravity SetGravityLevel(WTR.features.moon_gravity and 1 or 0) Notify("WTR: Moon Gravity " .. (WTR.features.moon_gravity and "~g~ON" or "~r~OFF")) elseif actionId == "freeze_peds" then WTR.features.freeze_peds = not WTR.features.freeze_peds for _, p in ipairs(GetGamePool("CPed")) do if p ~= ped then FreezeEntityPosition(p, WTR.features.freeze_peds) end end Notify("WTR: Freeze Nearby Peds " .. (WTR.features.freeze_peds and "~g~ON" or "~r~OFF")) elseif actionId == "prop_barrier" then local c = GetEntityCoords(ped) SpawnObjectNative("prop_barrier_work05", vector3(c.x + 1.5, c.y, c.z)) Notify("WTR: Work Barrier spawned!") elseif actionId == "prop_toilet" then local c = GetEntityCoords(ped) SpawnObjectNative("prop_ld_toilet_01", vector3(c.x + 1.5, c.y, c.z)) Notify("WTR: Toilet prop spawned!") elseif actionId == "ped_swat" then local c = GetEntityCoords(ped) SpawnPedNative("s_m_y_swat_01", vector3(c.x + 1.5, c.y, c.z)) Notify("WTR: SWAT Officer spawned!") elseif actionId == "ped_skater" then local c = GetEntityCoords(ped) SpawnPedNative("a_m_y_skater_01", vector3(c.x + 1.5, c.y, c.z)) Notify("WTR: Skater ped spawned!") elseif actionId == "spawn_prop_input" then local prop = PromptInput("Object model (prop_barrier_work05):") if prop and prop ~= "" then local c = GetEntityCoords(ped) SpawnObjectNative(prop, vector3(c.x + 1.5, c.y, c.z)) Notify("WTR: Prop spawned!") end elseif actionId == "spawn_ped_input" then local pModel = PromptInput("Ped model (a_m_y_skater_01):") if pModel and pModel ~= "" then local c = GetEntityCoords(ped) SpawnPedNative(pModel, vector3(c.x + 1.5, c.y, c.z)) Notify("WTR: Ped spawned!") end elseif actionId == "clear_vehicles" then local count = 0 local myVeh = GetVehiclePedIsIn(ped, false) for _, v in ipairs(GetGamePool("CVehicle")) do if v ~= myVeh and GetPedInVehicleSeat(v, -1) == 0 then DeleteEntityNative(v) count = count + 1 end end Notify("WTR: Cleared " .. count .. " empty vehicles!") elseif actionId == "placer_props" then OpenQuickPlacer("props") elseif actionId == "placer_peds" then OpenQuickPlacer("peds") elseif actionId == "placer_vehs" then OpenQuickPlacer("vehs") elseif actionId == "spectator_hud" then WTR.features.spectator_hud = not WTR.features.spectator_hud Notify("WTR: Spectator Radar " .. (WTR.features.spectator_hud and "~g~ON" or "~r~OFF")) if SendDuiAction then SendDuiAction("SET_HUD_VISIBLE", { hud = "spectator", visible = WTR.features.spectator_hud }) end elseif actionId == "binds_hud" then WTR.features.binds_hud = not WTR.features.binds_hud Notify("WTR: Keybinds HUD " .. (WTR.features.binds_hud and "~g~ON" or "~r~OFF")) if SendDuiAction then SendDuiAction("SET_HUD_VISIBLE", { hud = "binds", visible = WTR.features.binds_hud }) end elseif actionId == "drag_ui_mode" then WTR.features.drag_ui_mode = not WTR.features.drag_ui_mode Notify("WTR: Drag UI Layout " .. (WTR.features.drag_ui_mode and "~g~ACTIVE (Drag with mouse)" or "~r~OFF")) if SendDuiAction then SendDuiAction("SET_DRAG_MODE", { active = WTR.features.drag_ui_mode }) end elseif actionId == "reset_hud_layout" then WTR.screenX = 0.03 WTR.screenY = 0.08 if SendDuiAction then SendDuiAction("RESET_HUD_LAYOUT", {}) end Notify("~g~[WTR Layout]~s~ HUD positions and layout reset to default.") elseif actionId == "cfg_save" then local cfgName = PromptInput("Config Profile Name (Default):") if cfgName and cfgName ~= "" then SaveConfigProfile(cfgName) end elseif actionId == "cfg_load" then local cfgName = PromptInput("Enter Config Name to Load:") if cfgName and cfgName ~= "" then LoadConfigProfile(cfgName) end elseif actionId == "unload_menu" then WTR.isOpen = false WTR.active = false if duiObj then DestroyDui(duiObj) end Notify("~r~WTR Menu Unloaded!~s~") end end -- ==================================================================== -- ==================================================================== -- TOGGLE SYSTEM & KEY HOOKS -- ==================================================================== local lastToggleTime = 0 local function ToggleWTRMenu() local now = GetGameTimer() if now - lastToggleTime < 250 then return end lastToggleTime = now WTR.isOpen = not WTR.isOpen PlaySound(WTR.isOpen and "SELECT" or "CANCEL") Notify("WTR Menu: " .. (WTR.isOpen and "~g~OPEN" or "~r~CLOSED"), WTR.isOpen and "success" or "error", 1800) if WTR.isOpen then FG_AutoCheck() SyncDuiSelection() if SendDuiAction then SendDuiAction("SET_TARGET", { targetName = WTR.target.name }) end else WTR.cursorMode = false end end -- ==================================================================== -- COMPREHENSIVE KEYBOARD DEFINITIONS -- ==================================================================== local KEY_DEFINITIONS = { -- Navigation & Standard Controls { name = "PAGE UP", control = 10, mapping = "PRIOR" }, { name = "PAGE DOWN", control = 11, mapping = "NEXT" }, { name = "INSERT", control = 121, mapping = "INSERT" }, { name = "DELETE", control = 178, mapping = "DELETE" }, { name = "HOME", control = 212, mapping = "HOME" }, { name = "END", control = 179, mapping = "END" }, { name = "TILDE (~)", control = 243, mapping = "GRAVE" }, { name = "TAB", control = 37, mapping = "TAB" }, { name = "CAPS LOCK", control = 137, mapping = "CAPITAL" }, -- Function Keys { name = "F1", control = 288, mapping = "F1" }, { name = "F2", control = 289, mapping = "F2" }, { name = "F3", control = 170, mapping = "F3" }, { name = "F4", control = 164, mapping = "F4" }, { name = "F5", control = 166, mapping = "F5" }, { name = "F6", control = 167, mapping = "F6" }, { name = "F7", control = 168, mapping = "F7" }, { name = "F8", control = 169, mapping = "F8" }, { name = "F9", control = 56, mapping = "F9" }, { name = "F10", control = 57, mapping = "F10" }, { name = "F11", control = 344, mapping = "F11" }, { name = "F12", control = 345, mapping = "F12" }, -- Letters A - Z { name = "A", control = 34, mapping = "A" }, { name = "B", control = 29, mapping = "B" }, { name = "C", control = 26, mapping = "C" }, { name = "D", control = 35, mapping = "D" }, { name = "E", control = 38, mapping = "E" }, { name = "F", control = 23, mapping = "F" }, { name = "G", control = 47, mapping = "G" }, { name = "H", control = 74, mapping = "H" }, { name = "I", control = 183, mapping = "I" }, { name = "J", control = 184, mapping = "J" }, { name = "K", control = 311, mapping = "K" }, { name = "L", control = 182, mapping = "L" }, { name = "M", control = 244, mapping = "M" }, { name = "N", control = 249, mapping = "N" }, { name = "O", control = 197, mapping = "O" }, { name = "P", control = 199, mapping = "P" }, { name = "Q", control = 44, mapping = "Q" }, { name = "R", control = 45, mapping = "R" }, { name = "S", control = 33, mapping = "S" }, { name = "T", control = 245, mapping = "T" }, { name = "U", control = 303, mapping = "U" }, { name = "V", control = 0, mapping = "V" }, { name = "W", control = 32, mapping = "W" }, { name = "X", control = 73, mapping = "X" }, { name = "Y", control = 246, mapping = "Y" }, { name = "Z", control = 20, mapping = "Z" }, -- Numbers 0 - 9 { name = "1", control = 157, mapping = "1" }, { name = "2", control = 158, mapping = "2" }, { name = "3", control = 160, mapping = "3" }, { name = "4", control = 164, mapping = "4" }, { name = "5", control = 165, mapping = "5" }, { name = "6", control = 159, mapping = "6" }, { name = "7", control = 161, mapping = "7" }, { name = "8", control = 162, mapping = "8" }, { name = "9", control = 163, mapping = "9" }, { name = "0", control = 156, mapping = "0" }, -- Numpad Keys { name = "NUMPAD 0", control = 110, mapping = "NUMPAD0" }, { name = "NUMPAD 1", control = 117, mapping = "NUMPAD1" }, { name = "NUMPAD 2", control = 112, mapping = "NUMPAD2" }, { name = "NUMPAD 3", control = 118, mapping = "NUMPAD3" }, { name = "NUMPAD 4", control = 108, mapping = "NUMPAD4" }, { name = "NUMPAD 5", control = 119, mapping = "NUMPAD5" }, { name = "NUMPAD 6", control = 109, mapping = "NUMPAD6" }, { name = "NUMPAD 7", control = 117, mapping = "NUMPAD7" }, { name = "NUMPAD 8", control = 111, mapping = "NUMPAD8" }, { name = "NUMPAD 9", control = 118, mapping = "NUMPAD9" }, { name = "NUMPAD +", control = 96, mapping = "ADD" }, { name = "NUMPAD -", control = 84, mapping = "SUBTRACT" }, { name = "NUMPAD *", control = 100, mapping = "MULTIPLY" } } -- Forward declaration of Central Key Handler local OnKeyDetected = nil -- Register direct FiveM key mappings for instant, zero-lag input for _, kDef in ipairs(KEY_DEFINITIONS) do local safeMapping = string.lower(kDef.mapping):gsub("[^%w]", "") local cmdDown = "+wtr_key_" .. safeMapping local cmdUp = "-wtr_key_" .. safeMapping RegisterCommand(cmdDown, function() if OnKeyDetected then OnKeyDetected(kDef) end end, false) RegisterCommand(cmdUp, function() end, false) RegisterKeyMapping(cmdDown, "WTR Key " .. kDef.name, "keyboard", kDef.mapping) end -- ==================================================================== -- FEATURE KEYBIND SYSTEM (Triggered via F9) -- ==================================================================== RebuildFeatureBinds = function() WTR.featureBinds = {} if not WTR.itemBinds then return end for itemId, key in pairs(WTR.itemBinds) do if key and key ~= "" and key ~= "None" then local uKey = string.upper(key) local cleanKey = uKey:gsub("%s+", "") local matchedDef = nil for _, kDef in ipairs(KEY_DEFINITIONS) do local kn = string.upper(kDef.name) local km = string.upper(kDef.mapping or "") if kn == uKey or km == uKey or kn:gsub("%s+", "") == cleanKey or km:gsub("%s+", "") == cleanKey then matchedDef = kDef break end end local itemType = "action" for _, cat in ipairs(CATEGORIES) do for _, sub in ipairs(cat.subtabs or {}) do for _, it in ipairs(sub.items or {}) do if it.id == itemId then itemType = it.type or "action" break end end end end local bindObj = { itemId = itemId, itemType = itemType, control = matchedDef and matchedDef.control or nil, mapping = matchedDef and matchedDef.mapping or nil } WTR.featureBinds[uKey] = bindObj WTR.featureBinds[cleanKey] = bindObj if matchedDef then WTR.featureBinds[string.upper(matchedDef.name)] = bindObj if matchedDef.mapping then WTR.featureBinds[string.upper(matchedDef.mapping)] = bindObj end end end end end RebuildFeatureBinds() local function OpenFeatureBindModal(itm) if not itm or itm.isHeader then return end local existingKey = WTR.itemBinds[itm.id] WTR.featureBindModal.active = true WTR.featureBindModal.itemId = itm.id WTR.featureBindModal.itemLabel = itm.label or itm.id WTR.featureBindModal.itemType = itm.type or "action" WTR.featureBindModal.selectedKey = existingKey or "Press Key..." WTR.featureBindModal.selectedControl = nil WTR.featureBindModal.keyMapping = nil PlaySound("NAV_UP_DOWN") Notify("~b~[WTR Bind]~s~ Press any key to bind to '" .. (itm.label or itm.id) .. "', then press [ ENTER ]", "info", 4000) if SendDuiAction then SendDuiAction("OPEN_BIND_MODAL", { itemId = itm.id, itemLabel = itm.label or itm.id, currentKey = existingKey }) end end local function ConfirmFeatureBind() if WTR.featureBindModal.active then local key = WTR.featureBindModal.selectedKey local itemId = WTR.featureBindModal.itemId local itemLabel = WTR.featureBindModal.itemLabel local itemType = WTR.featureBindModal.itemType if key and key ~= "None" and key ~= "Press Key..." then -- Remove any previous item bound to this same key for id, k in pairs(WTR.itemBinds) do if k == key and id ~= itemId then WTR.itemBinds[id] = nil if SendDuiAction then SendDuiAction("SET_ITEM_BIND", { itemId = id, key = nil }) end end end -- Assign new bind WTR.itemBinds[itemId] = key RebuildFeatureBinds() PlaySoundFrontend(-1, "COLLECTED", "HUD_AWARDS", true) Notify("~g~[WTR Bind]~s~ '" .. itemLabel .. "' bound to [ " .. key .. " ]!", "success", 4000) if SendDuiAction then SendDuiAction("SET_ITEM_BIND", { itemId = itemId, key = key }) SendDuiAction("CLOSE_BIND_MODAL", {}) end end WTR.featureBindModal.active = false end end local function CancelFeatureBind() if WTR.featureBindModal.active then local itemId = WTR.featureBindModal.itemId local itemLabel = WTR.featureBindModal.itemLabel local oldKey = WTR.itemBinds[itemId] if oldKey then WTR.itemBinds[itemId] = nil RebuildFeatureBinds() Notify("~y~[WTR Bind]~s~ Keybind cleared for '" .. itemLabel .. "'", "warning", 3000) if SendDuiAction then SendDuiAction("SET_ITEM_BIND", { itemId = itemId, key = nil }) end else Notify("~y~[WTR Bind]~s~ Binding cancelled.", "warning", 2000) end if SendDuiAction then SendDuiAction("CLOSE_BIND_MODAL", {}) end PlaySound("CANCEL") WTR.featureBindModal.active = false end end -- Dedicated Global Feature Binds Execution Thread (Instant Key Press Handling) Citizen.CreateThread(function() while WTR.active do Citizen.Wait(0) if not WTR.featureBindModal.active and not WTR.keybindModal.active then for keyName, bind in pairs(WTR.featureBinds) do local c = bind.control if c and (IsControlJustPressed(0, c) or IsDisabledControlJustPressed(0, c)) then ExecuteAction(bind.itemId) PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", true) if bind.itemType == "toggle" and SendDuiAction then SendDuiAction("SET_ITEM_STATE", { itemId = bind.itemId, state = WTR.features[bind.itemId] }) end end end end end end) -- ==================================================================== -- MENU TOGGLE KEY SETUP MODAL (STARTUP) -- ==================================================================== local function ConfirmModalKeybind() if WTR.keybindModal.active then WTR.toggleControl = WTR.keybindModal.selectedControl or 10 WTR.toggleKeyName = WTR.keybindModal.selectedKey or "PAGE UP" WTR.toggleKeyMapping = WTR.keybindModal.keyMapping or "PRIOR" WTR.keybindModal.active = false WTR.isOpen = true SyncDuiSelection() PlaySoundFrontend(-1, "COLLECTED", "HUD_AWARDS", true) Notify("Menu Key set to: [" .. WTR.toggleKeyName .. "] | Menu Open!", "success", 4000) end end local function CancelModalKeybind() if WTR.keybindModal.active then WTR.toggleControl = 10 WTR.toggleKeyName = "PAGE UP" WTR.toggleKeyMapping = "PRIOR" WTR.keybindModal.active = false WTR.isOpen = true SyncDuiSelection() PlaySound("SELECT") Notify("Default key [PAGE UP] restored. Menu Open.", "info", 4000) end end -- Unified Key Detection Router OnKeyDetected = function(kDef) if not kDef then return end -- 1. If Startup / Menu Rebind Modal is active if WTR.keybindModal.active then WTR.keybindModal.selectedKey = kDef.name WTR.keybindModal.selectedControl = kDef.control WTR.keybindModal.keyMapping = kDef.mapping PlaySound("NAV_UP_DOWN") return end -- 2. If Feature Keybind Modal (F9) is active if WTR.featureBindModal.active then WTR.featureBindModal.selectedKey = kDef.name WTR.featureBindModal.selectedControl = kDef.control WTR.featureBindModal.keyMapping = kDef.mapping PlaySound("NAV_UP_DOWN") if SendDuiAction then SendDuiAction("UPDATE_BIND_MODAL_KEY", { key = kDef.name }) end return end -- 3. Menu Toggle Key if WTR.toggleKeyMapping == kDef.mapping or WTR.toggleKeyName == kDef.name or (WTR.toggleControl and kDef.control == WTR.toggleControl) then ToggleWTRMenu() return end -- 4. Global In-Game Feature Triggering local kName = string.upper(kDef.name or "") local kMap = string.upper(kDef.mapping or "") local cleanName = kName:gsub("%s+", "") local cleanMap = kMap:gsub("%s+", "") local bind = WTR.featureBinds[kName] or WTR.featureBinds[kMap] or WTR.featureBinds[cleanName] or WTR.featureBinds[cleanMap] if bind then ExecuteAction(bind.itemId) PlaySound("SELECT") if bind.itemType == "toggle" and SendDuiAction then SendDuiAction("SET_ITEM_STATE", { itemId = bind.itemId, state = WTR.features[bind.itemId] }) end end end -- Primary F9 Key Mapping: Binds selected item when in menu RegisterCommand("+wtr_bind_item", function() if WTR.isOpen and WTR.menuLevel == 2 and not WTR.featureBindModal.active and not WTR.keybindModal.active then local curSub = GetCurrentSubtab() if curSub and curSub.items and #curSub.items > 0 then local itm = curSub.items[WTR.selectedItem] if itm and not itm.isHeader then OpenFeatureBindModal(itm) end end end end, false) RegisterCommand("-wtr_bind_item", function() end, false) RegisterKeyMapping("+wtr_bind_item", "Bind Selected Feature (F9)", "keyboard", "F9") -- Modal confirmation / cancel key commands RegisterCommand("+wtr_modal_confirm", function() if WTR.keybindModal.active then ConfirmModalKeybind() elseif WTR.featureBindModal.active then ConfirmFeatureBind() end end, false) RegisterCommand("-wtr_modal_confirm", function() end, false) RegisterKeyMapping("+wtr_modal_confirm", "WTR Modal Confirm", "keyboard", "RETURN") RegisterCommand("+wtr_modal_cancel", function() if WTR.keybindModal.active then CancelModalKeybind() elseif WTR.featureBindModal.active then CancelFeatureBind() end end, false) RegisterCommand("-wtr_modal_cancel", function() end, false) RegisterKeyMapping("+wtr_modal_cancel", "WTR Modal Cancel", "keyboard", "BACK") -- Startup Menu Keybind Modal Render Thread Citizen.CreateThread(function() while WTR.active do if WTR.keybindModal.active then Citizen.Wait(0) -- Dim background DrawRect(0.50, 0.50, 1.0, 1.0, 0, 0, 0, 160) local mW = 0.32 local mH = 0.24 -- Modal background card DrawRect(0.50, 0.50, mW, mH, 6, 12, 24, 252) DrawRect(0.50, 0.50 - (mH / 2), mW, 0.003, 0, 240, 255, 255) DrawRect(0.50, 0.50 + (mH / 2), mW, 0.003, 0, 168, 255, 255) DrawRect(0.50 - (mW / 2), 0.50, 0.002, mH, 0, 240, 255, 160) DrawRect(0.50 + (mW / 2), 0.50, 0.002, mH, 0, 168, 255, 160) -- Header: Title SetTextFont(4) SetTextProportional(1) SetTextScale(0.0, 0.44) SetTextColour(0, 240, 255, 255) SetTextCentre(true) SetTextDropshadow(0, 0, 0, 0, 255) SetTextEdge(1, 0, 0, 0, 205) SetTextEntry("STRING") AddTextComponentSubstringPlayerName("WTR MENU - MENU KEYBIND SETUP") DrawText(0.50, 0.50 - 0.095) -- Subtitle SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.28) SetTextColour(148, 163, 184, 255) SetTextCentre(true) SetTextOutline() SetTextEntry("STRING") AddTextComponentSubstringPlayerName("Press a key to bind as Menu Toggle:") DrawText(0.50, 0.50 - 0.055) -- Big Keycap Box in center DrawRect(0.50, 0.50, 0.16, 0.046, 14, 28, 54, 255) DrawRect(0.50, 0.50, 0.16, 0.002, 0, 240, 255, 240) DrawRect(0.50, 0.50, 0.002, 0.046, 0, 168, 255, 200) SetTextFont(4) SetTextProportional(1) SetTextScale(0.0, 0.42) SetTextColour(248, 250, 252, 255) SetTextCentre(true) SetTextDropshadow(0, 0, 0, 0, 255) SetTextEntry("STRING") AddTextComponentSubstringPlayerName("[ " .. tostring(WTR.keybindModal.selectedKey) .. " ]") DrawText(0.50, 0.50 - 0.018) -- Footer confirmation hints SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.26) SetTextColour(34, 197, 94, 255) SetTextCentre(true) SetTextOutline() SetTextEntry("STRING") AddTextComponentSubstringPlayerName("Confirm selection by pressing [ ENTER ]") DrawText(0.50, 0.50 + 0.048) SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.23) SetTextColour(100, 116, 139, 255) SetTextCentre(true) SetTextOutline() SetTextEntry("STRING") AddTextComponentSubstringPlayerName("[ ESC / BACKSPACE ] for default: PAGE UP") DrawText(0.50, 0.50 + 0.076) -- Disable conflicting controls while modal is open DisableControlAction(0, 1, true) DisableControlAction(0, 2, true) DisableControlAction(0, 24, true) DisableControlAction(0, 25, true) DisableControlAction(0, 32, true) DisableControlAction(0, 33, true) DisableControlAction(0, 34, true) DisableControlAction(0, 35, true) -- Check key press across KEY_DEFINITIONS (Native GTA Control check fallback) for _, kDef in ipairs(KEY_DEFINITIONS) do if IsDisabledControlJustPressed(0, kDef.control) or IsControlJustPressed(0, kDef.control) then if WTR.keybindModal.selectedKey ~= kDef.name then OnKeyDetected(kDef) end break end end -- Check ENTER to confirm if IsDisabledControlJustPressed(0, 201) or IsControlJustPressed(0, 201) or IsDisabledControlJustPressed(0, 191) or IsControlJustPressed(0, 191) then ConfirmModalKeybind() -- Check ESC / BACKSPACE to cancel/default elseif IsDisabledControlJustPressed(0, 177) or IsControlJustPressed(0, 177) or IsDisabledControlJustPressed(0, 200) or IsControlJustPressed(0, 200) then CancelModalKeybind() end else Citizen.Wait(120) end end end) -- Feature Keybind Modal Render Thread (F9) Citizen.CreateThread(function() while WTR.active do if WTR.featureBindModal.active then Citizen.Wait(0) -- Dim background DrawRect(0.50, 0.50, 1.0, 1.0, 0, 0, 0, 160) local mW = 0.32 local mH = 0.24 -- Modal background card DrawRect(0.50, 0.50, mW, mH, 6, 12, 24, 252) DrawRect(0.50, 0.50 - (mH / 2), mW, 0.003, 0, 240, 255, 255) DrawRect(0.50, 0.50 + (mH / 2), mW, 0.003, 0, 168, 255, 255) DrawRect(0.50 - (mW / 2), 0.50, 0.002, mH, 0, 240, 255, 160) DrawRect(0.50 + (mW / 2), 0.50, 0.002, mH, 0, 168, 255, 160) -- Header: Title SetTextFont(4) SetTextProportional(1) SetTextScale(0.0, 0.44) SetTextColour(0, 240, 255, 255) SetTextCentre(true) SetTextDropshadow(0, 0, 0, 0, 255) SetTextEdge(1, 0, 0, 0, 205) SetTextEntry("STRING") AddTextComponentSubstringPlayerName("WTR MENU - BIND FEATURE") DrawText(0.50, 0.50 - 0.095) -- Subtitle SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.28) SetTextColour(148, 163, 184, 255) SetTextCentre(true) SetTextOutline() SetTextEntry("STRING") AddTextComponentSubstringPlayerName("Binding: " .. tostring(WTR.featureBindModal.itemLabel)) DrawText(0.50, 0.50 - 0.055) -- Big Keycap Box in center DrawRect(0.50, 0.50, 0.16, 0.046, 14, 28, 54, 255) DrawRect(0.50, 0.50, 0.16, 0.002, 0, 240, 255, 240) DrawRect(0.50, 0.50, 0.002, 0.046, 0, 168, 255, 200) SetTextFont(4) SetTextProportional(1) SetTextScale(0.0, 0.42) SetTextColour(248, 250, 252, 255) SetTextCentre(true) SetTextDropshadow(0, 0, 0, 0, 255) SetTextEntry("STRING") AddTextComponentSubstringPlayerName("[ " .. tostring(WTR.featureBindModal.selectedKey) .. " ]") DrawText(0.50, 0.50 - 0.018) -- Footer confirmation hints SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.26) SetTextColour(34, 197, 94, 255) SetTextCentre(true) SetTextOutline() SetTextEntry("STRING") AddTextComponentSubstringPlayerName("Confirm selection by pressing [ ENTER ]") DrawText(0.50, 0.50 + 0.048) SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.23) SetTextColour(100, 116, 139, 255) SetTextCentre(true) SetTextOutline() SetTextEntry("STRING") AddTextComponentSubstringPlayerName("[ ESC / BACKSPACE ] to Clear / Cancel") DrawText(0.50, 0.50 + 0.076) -- Disable conflicting controls while modal is open DisableControlAction(0, 1, true) DisableControlAction(0, 2, true) DisableControlAction(0, 24, true) DisableControlAction(0, 25, true) DisableControlAction(0, 32, true) DisableControlAction(0, 33, true) DisableControlAction(0, 34, true) DisableControlAction(0, 35, true) -- Check key press across KEY_DEFINITIONS for _, kDef in ipairs(KEY_DEFINITIONS) do if IsDisabledControlJustPressed(0, kDef.control) or IsControlJustPressed(0, kDef.control) then if WTR.featureBindModal.selectedKey ~= kDef.name then OnKeyDetected(kDef) end break end end -- Check ENTER to confirm if IsDisabledControlJustPressed(0, 201) or IsControlJustPressed(0, 201) or IsDisabledControlJustPressed(0, 191) or IsControlJustPressed(0, 191) then ConfirmFeatureBind() -- Check ESC / BACKSPACE to clear/cancel elseif IsDisabledControlJustPressed(0, 177) or IsControlJustPressed(0, 177) or IsDisabledControlJustPressed(0, 200) or IsControlJustPressed(0, 200) or IsDisabledControlJustPressed(0, 202) or IsControlJustPressed(0, 202) then CancelFeatureBind() end else Citizen.Wait(120) end end end) -- ==================================================================== -- HIERARCHICAL KEYBOARD NAVIGATION LOOP -- ==================================================================== Citizen.CreateThread(function() while WTR.active do Citizen.Wait(0) -- TOGGLE MENU: Dynamic user-configured key (GTA Control fallback) local toggleCtrl = WTR.toggleControl or 56 if not WTR.keybindModal.active and (IsDisabledControlJustPressed(0, toggleCtrl) or IsControlJustPressed(0, toggleCtrl)) then ToggleWTRMenu() end if WTR.isOpen then -- Disable gameplay conflicting controls while menu is open DisableControlAction(0, 18, true) -- Input Enter / Space DisableControlAction(0, 22, true) -- Jump (Spacebar) DisableControlAction(0, 23, true) -- Enter vehicle (F) DisableControlAction(0, 24, true) -- Attack DisableControlAction(0, 25, true) -- Aim DisableControlAction(0, 140, true) -- Light Melee DisableControlAction(0, 141, true) -- Heavy Melee DisableControlAction(0, 142, true) -- Melee Attack DisableControlAction(0, 257, true) -- Attack 2 if WTR.menuLevel == 1 then -- LEVEL 1: ROOT CATEGORIES NAVIGATION -- ARROW UP / NUMPAD 8 if IsDisabledControlJustPressed(0, 172) or IsControlJustPressed(0, 172) or IsDisabledControlJustPressed(0, 111) or IsControlJustPressed(0, 111) or IsDisabledControlJustPressed(0, 27) or IsControlJustPressed(0, 27) then PlaySound("NAV_UP_DOWN") WTR.selectedCategory = (WTR.selectedCategory - 2) % #CATEGORIES + 1 SyncDuiSelection() -- ARROW DOWN / NUMPAD 2 elseif IsDisabledControlJustPressed(0, 173) or IsControlJustPressed(0, 173) or IsDisabledControlJustPressed(0, 112) or IsControlJustPressed(0, 112) then PlaySound("NAV_UP_DOWN") WTR.selectedCategory = WTR.selectedCategory % #CATEGORIES + 1 SyncDuiSelection() -- ENTER: ENTER CATEGORY (TRANSITION TO LEVEL 2) elseif IsDisabledControlJustPressed(0, 201) or IsControlJustPressed(0, 201) or IsDisabledControlJustPressed(0, 191) or IsControlJustPressed(0, 191) then PlaySound("SELECT") WTR.menuLevel = 2 WTR.activeSubtab = 1 local curSub = GetCurrentSubtab() if curSub and curSub.isPlayerList then WTR.selectedItem = 1 elseif curSub and curSub.items then WTR.selectedItem = GetNextNonHeaderItem(curSub.items, 0, 1) end SyncDuiSelection() -- BACKSPACE / ESC: CLOSE MENU elseif IsDisabledControlJustPressed(0, 177) or IsControlJustPressed(0, 177) or IsDisabledControlJustPressed(0, 202) or IsControlJustPressed(0, 202) then ToggleWTRMenu() end else -- LEVEL 2: SUBMENU NAVIGATION (Q, E, ARROWS, ENTER) local curCat = CATEGORIES[WTR.selectedCategory] local curSub = GetCurrentSubtab() -- TAB PREVIOUS: Q (Control 44) if IsDisabledControlJustPressed(0, 44) or IsControlJustPressed(0, 44) then if curCat and curCat.subtabs and #curCat.subtabs > 1 then PlaySound("NAV_LEFT_RIGHT") WTR.activeSubtab = (WTR.activeSubtab - 2) % #curCat.subtabs + 1 local sub = GetCurrentSubtab() if sub and sub.isPlayerList then WTR.selectedItem = 1 elseif sub and sub.items then WTR.selectedItem = GetNextNonHeaderItem(sub.items, 0, 1) end SyncDuiSelection() end -- TAB NEXT: E (Control 38) elseif IsDisabledControlJustPressed(0, 38) or IsControlJustPressed(0, 38) then if curCat and curCat.subtabs and #curCat.subtabs > 1 then PlaySound("NAV_LEFT_RIGHT") WTR.activeSubtab = WTR.activeSubtab % #curCat.subtabs + 1 local sub = GetCurrentSubtab() if sub and sub.isPlayerList then WTR.selectedItem = 1 elseif sub and sub.items then WTR.selectedItem = GetNextNonHeaderItem(sub.items, 0, 1) end SyncDuiSelection() end -- ARROW UP / NUMPAD 8 elseif IsDisabledControlJustPressed(0, 172) or IsControlJustPressed(0, 172) or IsDisabledControlJustPressed(0, 111) or IsControlJustPressed(0, 111) or IsDisabledControlJustPressed(0, 27) or IsControlJustPressed(0, 27) then if curSub and curSub.isPlayerList then if #WTR.onlinePlayers > 0 then PlaySound("NAV_UP_DOWN") WTR.selectedItem = (WTR.selectedItem - 2) % #WTR.onlinePlayers + 1 SyncDuiSelection() end elseif curSub and curSub.items and #curSub.items > 0 then PlaySound("NAV_UP_DOWN") WTR.selectedItem = GetNextNonHeaderItem(curSub.items, WTR.selectedItem, -1) SyncDuiSelection() end -- ARROW DOWN / NUMPAD 2 elseif IsDisabledControlJustPressed(0, 173) or IsControlJustPressed(0, 173) or IsDisabledControlJustPressed(0, 112) or IsControlJustPressed(0, 112) then if curSub and curSub.isPlayerList then if #WTR.onlinePlayers > 0 then PlaySound("NAV_UP_DOWN") WTR.selectedItem = WTR.selectedItem % #WTR.onlinePlayers + 1 SyncDuiSelection() end elseif curSub and curSub.items and #curSub.items > 0 then PlaySound("NAV_UP_DOWN") WTR.selectedItem = GetNextNonHeaderItem(curSub.items, WTR.selectedItem, 1) SyncDuiSelection() end -- ENTER: EXECUTE ACTION OR TOGGLE elseif IsDisabledControlJustPressed(0, 201) or IsControlJustPressed(0, 201) or IsDisabledControlJustPressed(0, 191) or IsControlJustPressed(0, 191) then if curSub and curSub.isPlayerList then if #WTR.onlinePlayers > 0 then local p = WTR.onlinePlayers[WTR.selectedItem] if p then if WTR.selectedPlayers[p.serverId] then WTR.selectedPlayers[p.serverId] = nil else WTR.selectedPlayers[p.serverId] = true end WTR.target.ped = GetPlayerPed(GetPlayerFromServerId(p.serverId)) WTR.target.serverId = p.serverId WTR.target.name = p.name WTR.target.dist = p.dist WTR.target.isSelf = (p.serverId == GetPlayerServerId(PlayerId())) PlaySound("SELECT") SyncDuiSelection() end end elseif curSub and curSub.items and #curSub.items > 0 then local itm = curSub.items[WTR.selectedItem] if itm and not itm.isHeader then PlaySound("SELECT") ExecuteAction(itm.id) if itm.type == "toggle" then SendDuiAction("SET_ITEM_STATE", { itemId = itm.id, state = WTR.features[itm.id] }) end SyncDuiSelection() end end -- F9: BIND CURRENTLY SELECTED ITEM TO A KEY elseif IsDisabledControlJustPressed(0, 56) or IsControlJustPressed(0, 56) then if curSub and curSub.items and #curSub.items > 0 then local itm = curSub.items[WTR.selectedItem] if itm and not itm.isHeader then OpenFeatureBindModal(itm) end end -- BACKSPACE / ESC: RETURN TO LEVEL 1 (MAIN MENU) elseif IsDisabledControlJustPressed(0, 177) or IsControlJustPressed(0, 177) or IsDisabledControlJustPressed(0, 202) or IsControlJustPressed(0, 202) then PlaySound("CANCEL") WTR.menuLevel = 1 SyncDuiSelection() end end -- TOGGLE CURSOR: LEFT ALT (Control 19) if IsControlJustPressed(0, 19) or IsDisabledControlJustPressed(0, 19) then WTR.cursorMode = not WTR.cursorMode PlaySound(WTR.cursorMode and "SELECT" or "CANCEL") Notify("~b~WTR Cursor: ~s~" .. (WTR.cursorMode and "~g~ACTIVE (Click to interact)" or "~r~DISABLED")) end -- MOUSE INTERACTION IN DUI if WTR.cursorMode then SetMouseCursorActiveThisFrame() ShowCursorThisFrame() DisableControlAction(0, 1, true) -- Look LR DisableControlAction(0, 2, true) -- Look UD DisableControlAction(0, 24, true) -- Attack DisableControlAction(0, 25, true) -- Aim DisableControlAction(0, 142, true) -- Melee Attack DisableControlAction(0, 257, true) -- Attack 2 local curX = GetControlNormal(0, 239) local curY = GetControlNormal(0, 240) local left = WTR.screenX - (WTR.menuWidth / 2) local right = WTR.screenX + (WTR.menuWidth / 2) local top = WTR.screenY - (WTR.menuHeight / 2) local bottom = WTR.screenY + (WTR.menuHeight / 2) if curX >= left and curX <= right and curY >= top and curY <= bottom then local relX = (curX - left) / WTR.menuWidth local relY = (curY - top) / WTR.menuHeight local duiX = math.floor(relX * 440) local duiY = math.floor(relY * 700) if duiObj then SendDuiMouseMove(duiObj, duiX, duiY) end if IsControlJustPressed(0, 237) or IsDisabledControlJustPressed(0, 237) or IsControlJustPressed(0, 24) or IsDisabledControlJustPressed(0, 24) then if duiObj then SendDuiMouseDown(duiObj, "left") end elseif IsControlJustReleased(0, 237) or IsDisabledControlJustReleased(0, 237) or IsControlJustReleased(0, 24) or IsDisabledControlJustReleased(0, 24) then if duiObj then SendDuiMouseUp(duiObj, "left") end end end end end end end) -- Register FiveM fallback console command (/wtrmenu) RegisterCommand("wtrmenu", function() ToggleWTRMenu() end, false) -- ==================================================================== -- FAST COMBAT & VEHICLE LOOP (0ms) -- ==================================================================== Citizen.CreateThread(function() local rgbStep = 0 while WTR.active do Citizen.Wait(0) local ped = PlayerPedId() -- Godmode if WTR.features.godmode and WTR.features.safe_mode then SetEntityInvincible(ped, true) SetPlayerInvincible(PlayerId(), true) SetEntityCanBeDamaged(ped, false) end -- Super Jump & Sprint if WTR.features.super_jump then SetSuperJumpThisFrame(PlayerId()) end if WTR.features.fast_run then SetRunSprintMultiplierForPlayer(PlayerId(), 1.49) end -- Weapon Enhancements if WTR.features.no_recoil and IsPedShooting(ped) then SetWeaponRecoilShakeAmplitude(GetSelectedPedWeapon(ped), 0.0) end if WTR.features.no_spread then SetWeaponSpread(GetSelectedPedWeapon(ped), 0.0) end if WTR.features.explosive_ammo then SetExplosiveAmmoThisFrame(PlayerId()) end -- Triggerbot: Auto-fire when aiming at an enemy ped if WTR.features.triggerbot then local isAiming = IsPlayerFreeAiming(PlayerId()) or IsControlPressed(0, 25) if isAiming then local hit, ent = GetEntityPlayerIsFreeAimingAt(PlayerId()) if hit and DoesEntityExist(ent) and IsEntityAPed(ent) and not IsEntityDead(ent) and ent ~= ped then SetControlNormal(0, 24, 1.0) -- Attack end end end -- Silent Aim: Redirect bullet trajectory directly to head bone (SKEL_Head / 31086) if WTR.features.silent_aim then local isAiming = IsPlayerFreeAiming(PlayerId()) or IsControlPressed(0, 25) if isAiming then local tPed = WTR.target.ped if not tPed or not DoesEntityExist(tPed) or IsEntityDead(tPed) then local myC = GetEntityCoords(ped) local closeDist = 250.0 for _, pl in ipairs(GetActivePlayers()) do if pl ~= PlayerId() then local plPed = GetPlayerPed(pl) if DoesEntityExist(plPed) and not IsEntityDead(plPed) then local dist = #(myC - GetEntityCoords(plPed)) if dist < closeDist and HasEntityClearLosToEntity(ped, plPed, 17) then closeDist = dist tPed = plPed end end end end end if tPed and DoesEntityExist(tPed) and not IsEntityDead(tPed) then local headCoords = GetPedBoneCoords(tPed, 31086, 0.0, 0.0, 0.0) if headCoords and IsPedShooting(ped) then SetPedShootsAtCoord(ped, headCoords.x, headCoords.y, headCoords.z, true) end end end end -- Car Gun: shoots high-velocity Adder cars when shooting! if WTR.features.car_gun and IsPedShooting(ped) then local camRot = GetGameplayCamRot(0) local camCoord = GetGameplayCamCoord() local forward = vector3( -math.sin(math.rad(camRot.z)) * math.cos(math.rad(camRot.x)), math.cos(math.rad(camRot.z)) * math.cos(math.rad(camRot.x)), math.sin(math.rad(camRot.x)) ) local spawnPos = camCoord + forward * 5.0 local spawnedCar = SpawnVehicleNative("adder", spawnPos) if DoesEntityExist(spawnedCar) then SetEntityVelocity(spawnedCar, forward.x * 120.0, forward.y * 120.0, forward.z * 120.0) end end -- Vehicle Enhancements local veh = GetVehiclePedIsIn(ped, false) if veh ~= 0 then if WTR.features.veh_godmode then SetEntityInvincible(veh, true) SetVehicleCanBeVisiblyDamaged(veh, false) end -- Horn Rocket Boost if WTR.features.speed_boost and IsControlPressed(0, 86) then SetVehicleForwardSpeed(veh, GetEntitySpeed(veh) + 1.5) end -- Car Jump (Spacebar: Control 76) if WTR.features.car_jump and IsControlJustPressed(0, 76) then ApplyForceToEntity(veh, 1, 0.0, 0.0, 12.0, 0.0, 0.0, 0.0, 0, false, true, true, false, true) end -- Drive on Water (Jesus Mode) if WTR.features.drive_on_water then local vCoords = GetEntityCoords(veh) local hasWater, waterHeight = GetWaterHeight(vCoords.x, vCoords.y, vCoords.z) if hasWater and vCoords.z <= waterHeight + 1.0 then SetEntityCoords(veh, vCoords.x, vCoords.y, waterHeight + 0.3, false, false, false, true) local vVel = GetEntityVelocity(veh) SetEntityVelocity(veh, vVel.x, vVel.y, 0.0) end end -- Rainbow Car Cycling if WTR.features.rainbow_car then rgbStep = (rgbStep + 3) % 360 local rad = math.rad(rgbStep) local r = math.floor(math.sin(rad) * 127 + 128) local g = math.floor(math.sin(rad + 2) * 127 + 128) local b = math.floor(math.sin(rad + 4) * 127 + 128) SetVehicleCustomPrimaryColour(veh, r, g, b) SetVehicleCustomSecondaryColour(veh, r, g, b) end end end end) -- ==================================================================== -- NOCLIP ENGINE (moves the ped) -- ==================================================================== Citizen.CreateThread(function() while WTR.active do Citizen.Wait(0) if WTR.features.noclip then local ped = PlayerPedId() local c = GetEntityCoords(ped) local camRot = GetGameplayCamRot(0) local speed = 1.0 if IsControlPressed(0, 21) then speed = 3.5 end -- Shift local forward = vector3(-math.sin(math.rad(camRot.z)), math.cos(math.rad(camRot.z)), 0.0) local right = vector3(math.cos(math.rad(camRot.z)), math.sin(math.rad(camRot.z)), 0.0) local move = vector3(0.0, 0.0, 0.0) if IsControlPressed(0, 32) then move = move + forward end -- W if IsControlPressed(0, 33) then move = move - forward end -- S if IsControlPressed(0, 34) then move = move - right end -- A if IsControlPressed(0, 35) then move = move + right end -- D if IsControlPressed(0, 22) then move = move + vector3(0.0, 0.0, 1.0) end -- Space if IsControlPressed(0, 36) then move = move - vector3(0.0, 0.0, 1.0) end -- Ctrl SetEntityCoordsNoOffset(ped, c.x + move.x * speed, c.y + move.y * speed, c.z + move.z * speed, true, true, true) SetEntityVelocity(ped, 0.0, 0.0, 0.0) end end end) -- ==================================================================== -- SHARED CAMERA-ONLY ENGINE (freecam + spectate) -- ==================================================================== local camEngine = { cam = nil, pos = vector3(0.0, 0.0, 0.0), rot = vector3(0.0, 0.0, 0.0), running = false } local function StartCamEngine() local ped = PlayerPedId() local c = GetGameplayCamCoord() local r = GetGameplayCamRot(2) camEngine.pos = c camEngine.rot = r camEngine.cam = CreateCam("DEFAULT_SCRIPTED_CAMERA", true) SetCamCoord(camEngine.cam, c.x, c.y, c.z) SetCamRot(camEngine.cam, r.x, r.y, r.z, 2) SetCamActive(camEngine.cam, true) RenderScriptCams(true, true, 500, true, true) SetEntityVisible(ped, false, 0) SetEntityCollision(ped, false, false) FreezeEntityPosition(ped, true) end local function StopCamEngine() local ped = PlayerPedId() if camEngine.cam and DoesCamExist(camEngine.cam) then RenderScriptCams(false, true, 500, true, true) DestroyCam(camEngine.cam, false) camEngine.cam = nil end SetEntityVisible(ped, true, 0) SetEntityCollision(ped, true, true) FreezeEntityPosition(ped, false) end Citizen.CreateThread(function() while WTR.active do Citizen.Wait(0) local mode = nil if WTR.features.freecam then mode = "freecam" elseif WTR.spectating and WTR.spectate_target and WTR.spectate_target ~= PlayerPedId() then mode = "spectate" end if mode then if not camEngine.running then StartCamEngine() camEngine.running = true end -- Disable gameplay control actions while a camera-only mode is active DisableControlAction(0, 30, true) -- Move LR DisableControlAction(0, 31, true) -- Move UD DisableControlAction(0, 24, true) -- Attack DisableControlAction(0, 25, true) -- Aim DisableControlAction(0, 22, true) -- Jump DisableControlAction(0, 140, true) DisableControlAction(0, 141, true) DisableControlAction(0, 142, true) if mode == "freecam" then -- Mouse Look / Rotation local mouseX = GetDisabledControlNormal(0, 1) or GetControlNormal(0, 1) local mouseY = GetDisabledControlNormal(0, 2) or GetControlNormal(0, 2) local rotZ = camEngine.rot.z - (mouseX * 8.0) local rotX = math.max(-85.0, math.min(85.0, camEngine.rot.x - (mouseY * 8.0))) camEngine.rot = vector3(rotX, 0.0, rotZ) SetCamRot(camEngine.cam, rotX, 0.0, rotZ, 2) -- Camera Movement (WASD + Space/Ctrl + Shift speed) local speed = 0.8 if IsControlPressed(0, 21) or IsDisabledControlPressed(0, 21) then speed = 2.5 end -- Shift (Fast) if IsControlPressed(0, 19) or IsDisabledControlPressed(0, 19) then speed = 0.2 end -- Alt (Slow) local radZ = math.rad(rotZ) local radX = math.rad(rotX) local forward = vector3(-math.sin(radZ) * math.cos(radX), math.cos(radZ) * math.cos(radX), math.sin(radX)) local right = vector3(math.cos(radZ), math.sin(radZ), 0.0) local up = vector3(0.0, 0.0, 1.0) local move = vector3(0.0, 0.0, 0.0) if IsControlPressed(0, 32) or IsDisabledControlPressed(0, 32) then move = move + forward end -- W if IsControlPressed(0, 33) or IsDisabledControlPressed(0, 33) then move = move - forward end -- S if IsControlPressed(0, 34) or IsDisabledControlPressed(0, 34) then move = move - right end -- A if IsControlPressed(0, 35) or IsDisabledControlPressed(0, 35) then move = move + right end -- D if IsControlPressed(0, 22) or IsDisabledControlPressed(0, 22) then move = move + up end -- Space if IsControlPressed(0, 36) or IsDisabledControlPressed(0, 36) then move = move - up end -- Ctrl camEngine.pos = camEngine.pos + move * speed SetCamCoord(camEngine.cam, camEngine.pos.x, camEngine.pos.y, camEngine.pos.z) -- Freecam Shooting (Center Screen Crosshair & Bullet/Missile firing) if WTR.features.freecam_shoot and not (WTR.placer and WTR.placer.active) then -- Draw center cyan crosshair DrawRect(0.50, 0.50, 0.0018, 0.007, 0, 240, 255, 240) DrawRect(0.50, 0.50, 0.0055, 0.002, 0, 240, 255, 240) if IsDisabledControlJustPressed(0, 24) or IsControlJustPressed(0, 24) then local startCoords = camEngine.pos local endCoords = startCoords + forward * 650.0 ShootSingleBulletBetweenCoords(startCoords.x, startCoords.y, startCoords.z, endCoords.x, endCoords.y, endCoords.z, 250, true, GetHashKey("WEAPON_HEAVYSNIPER_MK2"), PlayerPedId(), true, true, 2500.0) AddExplosion(endCoords.x, endCoords.y, endCoords.z, 2, 1.0, true, false, 0.5) PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", true) end end else -- Spectate: follow the targeted ped via the shared scripted camera local tp = WTR.spectate_target if tp and DoesEntityExist(tp) then local tCoords = GetEntityCoords(tp) local tHeading = GetEntityHeading(tp) local hrad = math.rad(tHeading) local dist = 4.0 SetCamCoord(camEngine.cam, tCoords.x + math.sin(hrad) * dist, tCoords.y - math.cos(hrad) * dist, tCoords.z + 1.5) SetCamRot(camEngine.cam, 0.0, 0.0, tHeading, 2) else WTR.spectating = false WTR.spectate_target = nil WTR.features.online_spectate = false if SendDuiAction then SendDuiAction("SET_ITEM_STATE", { itemId = "online_spectate", state = false }) end Notify("~r~[WTR Spectate]~s~ Target is gone.") end end else if camEngine.running then StopCamEngine() camEngine.running = false DisableControlAction(0, 30, false) -- Move LR DisableControlAction(0, 31, false) -- Move UD DisableControlAction(0, 24, false) -- Attack DisableControlAction(0, 25, false) -- Aim DisableControlAction(0, 22, false) -- Jump DisableControlAction(0, 140, false) DisableControlAction(0, 141, false) DisableControlAction(0, 142, false) end end end if camEngine.running then StopCamEngine() end end) -- ==================================================================== -- QUICK PLACER RUNTIME THREAD -- ==================================================================== Citizen.CreateThread(function() while WTR.active do if WTR.placer and WTR.placer.active then Citizen.Wait(0) local list = WTR.placer.items[WTR.placer.mode] or {} local total = #list local targetPos local isFreecamMode = (WTR.features.freecam and camEngine.running) if isFreecamMode then local radZ = math.rad(camEngine.rot.z) local radX = math.rad(camEngine.rot.x) local fwd = vector3(-math.sin(radZ) * math.cos(radX), math.cos(radZ) * math.cos(radX), math.sin(radX)) local startCoords = camEngine.pos local endCoords = startCoords + fwd * 90.0 local rayHandle = StartShapeTestRay(startCoords.x, startCoords.y, startCoords.z, endCoords.x, endCoords.y, endCoords.z, -1, PlayerPedId(), 0) local _, hit, hitCoords, _, _ = GetShapeTestResult(rayHandle) targetPos = (hit == 1) and hitCoords or (startCoords + fwd * 12.0) -- 3D neon cyan placement marker at raycast hit point DrawMarker(28, targetPos.x, targetPos.y, targetPos.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.45, 0.45, 0.45, 0, 240, 255, 210, false, false, 2, false, nil, nil, false) else local myPed = PlayerPedId() local myCoords = GetEntityCoords(myPed) local fwd = GetEntityForwardVector(myPed) targetPos = myCoords + fwd * 4.2 -- Ground disc marker DrawMarker(1, targetPos.x, targetPos.y, targetPos.z - 0.95, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.2, 1.2, 0.4, 0, 240, 255, 180, false, false, 2, false, nil, nil, false) end -- Scroll wheel up / down or Left/Right arrows to cycle items if IsControlJustPressed(0, 14) or IsDisabledControlJustPressed(0, 14) or IsControlJustPressed(0, 174) then WTR.placer.index = (WTR.placer.index - 2) % total + 1 local itm = list[WTR.placer.index] PlaySoundFrontend(-1, "NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET", true) if SendDuiAction then SendDuiAction("UPDATE_PLACER", { category = string.lower(WTR.placer.mode), name = itm.label }) end elseif IsControlJustPressed(0, 15) or IsDisabledControlJustPressed(0, 15) or IsControlJustPressed(0, 175) then WTR.placer.index = WTR.placer.index % total + 1 local itm = list[WTR.placer.index] PlaySoundFrontend(-1, "NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET", true) if SendDuiAction then SendDuiAction("UPDATE_PLACER", { category = string.lower(WTR.placer.mode), name = itm.label }) end end -- Left click to place if IsControlJustPressed(0, 24) or IsDisabledControlJustPressed(0, 24) then local cur = list[WTR.placer.index] if cur then if WTR.placer.mode == "props" then SpawnObjectNative(cur.model, targetPos) elseif WTR.placer.mode == "peds" then SpawnPedNative(cur.model, targetPos) elseif WTR.placer.mode == "vehs" then if isFreecamMode then local h = SafeRequestModel(cur.model) if h then CreateVehicle(h, targetPos.x, targetPos.y, targetPos.z, camEngine.rot.z, true, false) SetModelAsNoLongerNeeded(h) end else SpawnVehicleNative(cur.model, targetPos) end end PlaySoundFrontend(-1, "COLLECTED", "HUD_AWARDS", true) Notify("~g~[WTR Placer]~s~ Spawned " .. cur.label) end end -- Cancel on Backspace / ESC if IsControlJustPressed(0, 177) or IsDisabledControlJustPressed(0, 177) or IsControlJustPressed(0, 202) then WTR.placer.active = false WTR.features.freecam_placer = false if SendDuiAction then SendDuiAction("CLOSE_PLACER", {}) SendDuiAction("SET_ITEM_STATE", { itemId = "freecam_placer", state = false }) end Notify("~y~[WTR Placer]~s~ Placer mode closed.") end else Citizen.Wait(250) end end end) -- ==================================================================== -- SPECTATOR RADAR DETECTION THREAD -- ==================================================================== Citizen.CreateThread(function() while WTR.active do Citizen.Wait(1200) if WTR.features.spectator_hud then local myPed = PlayerPedId() local myCoords = GetEntityCoords(myPed) local spectators = {} for _, pid in ipairs(GetActivePlayers()) do if pid ~= PlayerId() then local ped = GetPlayerPed(pid) if DoesEntityExist(ped) then local pCoords = GetEntityCoords(ped) local dist = #(myCoords - pCoords) local isHovering = math.abs(pCoords.z - myCoords.z) > 10.0 and #(vector2(pCoords.x, pCoords.y) - vector2(myCoords.x, myCoords.y)) < 35.0 local isInvis = not IsEntityVisible(ped) local isSpec = NetworkIsInSpectatorMode() if isSpec or isHovering or (isInvis and dist < 120.0) then table.insert(spectators, { name = GetPlayerName(pid) or ("Player #" .. GetPlayerServerId(pid)), dist = math.floor(dist), tag = isHovering and "HOVERING (ABOVE)" or (isInvis and "INVISIBLE ADMIN" or "SPECTATING") }) end end end end if SendDuiAction then SendDuiAction("UPDATE_SPECTATORS", { spectators = spectators }) end end end end) -- ==================================================================== -- CONTINUOUS ATTACK LOOPS ENGINE -- ==================================================================== Citizen.CreateThread(function() while WTR.active do local hasAttackLoop = WTR.features.loop_punch or WTR.features.loop_taze or WTR.features.loop_burn if hasAttackLoop then local targets = GetSelectedTargets() for _, tg in ipairs(targets) do if DoesEntityExist(tg.ped) and not IsEntityDead(tg.ped) then local tCoords = GetEntityCoords(tg.ped) if WTR.features.loop_punch then ApplyDamageToPed(tg.ped, 12, false) SetPedToRagdoll(tg.ped, 1200, 1200, 0, true, true, false) end if WTR.features.loop_taze then local taserHash = GetHashKey("WEAPON_STUNGUN") ShootSingleBulletBetweenCoords(tCoords.x, tCoords.y, tCoords.z + 1.5, tCoords.x, tCoords.y, tCoords.z, 0, true, taserHash, PlayerPedId(), true, false, 100.0) end if WTR.features.loop_burn then StartEntityFire(tg.ped) end end end Citizen.Wait(800) else Citizen.Wait(400) end end end) -- ==================================================================== -- ONESYNC 500M LIVE PLAYER TRACKER (Zero-Lag) -- ==================================================================== Citizen.CreateThread(function() while WTR.active do Citizen.Wait(1000) local myPed = PlayerPedId() local myCoords = GetEntityCoords(myPed) local myPlayerId = PlayerId() local myServerId = GetPlayerServerId(myPlayerId) local myMaxHp = GetEntityMaxHealth(myPed) local myHpPct = myMaxHp > 0 and math.floor(GetEntityHealth(myPed) / myMaxHp * 100) or 100 local myApPct = math.min(100, GetPedArmour(myPed)) local activePlayers = GetActivePlayers() local nearby = {} local validIds = {} for _, pId in ipairs(activePlayers) do if pId ~= myPlayerId then local pPed = GetPlayerPed(pId) if DoesEntityExist(pPed) then local pCoords = GetEntityCoords(pPed) local dist = #(myCoords - pCoords) if dist <= 500.0 then local sId = GetPlayerServerId(pId) validIds[sId] = true local pName = GetPlayerName(pId) or ("Player #" .. tostring(sId)) local maxHp = GetEntityMaxHealth(pPed) local hp = maxHp > 0 and math.floor(GetEntityHealth(pPed) / maxHp * 100) or 0 local arm = GetPedArmour(pPed) local inVeh = IsPedInAnyVehicle(pPed, false) table.insert(nearby, { serverId = sId, name = pName, dist = math.floor(dist), health = hp, armour = arm, inVeh = inVeh }) end end end end -- Clean up selected players who left 500m or left the server for selId, _ in pairs(WTR.selectedPlayers) do if not validIds[selId] then WTR.selectedPlayers[selId] = nil end end table.sort(nearby, function(a, b) return a.dist < b.dist end) WTR.onlinePlayers = nearby -- Update DUI if WTR.isOpen and SendDuiAction then local targetDist = 0 if not WTR.target.isSelf and WTR.target.ped and DoesEntityExist(WTR.target.ped) then targetDist = math.floor(#(myCoords - GetEntityCoords(WTR.target.ped))) end SendDuiAction("UPDATE_ONLINE_PLAYERS", { players = nearby, myId = myServerId, myHealth = myHpPct, myArmour = myApPct }) SendDuiAction("SET_TARGET", { targetName = WTR.target.name, dist = targetDist }) end end end) -- ==================================================================== -- THROTTLED PASSIVE & VISUALS LOOP (Zero-Lag) -- ==================================================================== Citizen.CreateThread(function() while WTR.active do Citizen.Wait(120) -- Auto-Revive Watcher if WTR.features.auto_revive then local ped = PlayerPedId() if IsEntityDead(ped) or GetEntityHealth(ped) <= 0 then RevivePlayerNative() Citizen.Wait(2000) end end -- Black Hole Vortex if WTR.features.black_hole then local myCoords = GetEntityCoords(PlayerPedId()) local tPed = GetTargetPed() local center = tPed and GetEntityCoords(tPed) or myCoords for _, veh in ipairs(GetGamePool("CVehicle")) do local vCoords = GetEntityCoords(veh) local dist = #(center - vCoords) if dist > 2.0 and dist < 65.0 then local dir = center - vCoords local norm = dir / dist SetEntityVelocity(veh, norm.x * 25.0, norm.y * 25.0, norm.z * 25.0 + 3.0) end end end end end) -- ESP & Crosshair Render Loop Citizen.CreateThread(function() while WTR.active do Citizen.Wait(0) -- Custom Neon Crosshair if WTR.features.custom_crosshair then DrawRect(0.5, 0.5, 0.002, 0.012, 56, 189, 248, 240) DrawRect(0.5, 0.5, 0.008, 0.003, 56, 189, 248, 240) DrawRect(0.5, 0.5, 0.001, 0.002, 192, 132, 252, 255) end -- Player ESP local hasEsp = WTR.features.esp_box or WTR.features.esp_names or WTR.features.esp_health or WTR.features.esp_distance or WTR.features.esp_snaplines if hasEsp then local myPed = PlayerPedId() local myCoords = GetEntityCoords(myPed) for _, player in ipairs(GetActivePlayers()) do if player ~= PlayerId() then local targetPed = GetPlayerPed(player) if DoesEntityExist(targetPed) and not IsEntityDead(targetPed) then local tCoords = GetEntityCoords(targetPed) local dist = #(myCoords - tCoords) if dist < 300.0 then local onScreen, screenX, screenY = GetScreenCoordFromWorldCoord(tCoords.x, tCoords.y, tCoords.z) if onScreen then if WTR.features.esp_snaplines then DrawLine(myCoords.x, myCoords.y, myCoords.z, tCoords.x, tCoords.y, tCoords.z, 56, 189, 248, 180) end if WTR.features.esp_box then local bH = 1.9 / (dist * 0.05) local bW = bH * 0.45 DrawRect(screenX, screenY, bW, 0.002, 168, 85, 247, 240) DrawRect(screenX, screenY, 0.002, bH, 168, 85, 247, 240) end if WTR.features.esp_names or WTR.features.esp_distance then local name = GetPlayerName(player) or ("Player #" .. tostring(player)) local label = name if WTR.features.esp_distance then label = label .. " [" .. math.floor(dist) .. "m]" end SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.28) SetTextColour(226, 232, 240, 255) SetTextDropShadow(0, 0, 0, 0, 255) SetTextOutline() SetTextEntry("STRING") AddTextComponentString(label) DrawText(screenX - 0.02, screenY - 0.04) end end end end end end end end end) -- ==================================================================== -- CYBERPUNK NATIVE UI RENDER ENGINE (60 FPS) -- ==================================================================== local function RenderNativeMenu() if not WTR.isOpen then return end local menuX = WTR.screenX or 0.16 local startY = WTR.screenY or 0.44 local menuW = 0.23 local rowH = 0.034 local headerH = 0.064 local maxVisible = 9 if WTR.menuLevel == 1 then -- LEVEL 1: MAIN MENU (ROOT CATEGORIES) local totalItems = #CATEGORIES local visibleCount = math.min(totalItems, maxVisible) local listH = visibleCount * rowH + 0.008 local footerH = 0.032 local totalH = headerH + listH + footerH local topY = startY - (totalH / 2) -- Scroll offset calculation local scroll = 0 if WTR.selectedCategory > maxVisible then scroll = WTR.selectedCategory - maxVisible end scroll = math.max(0, math.min(scroll, math.max(0, totalItems - maxVisible))) -- 1. Main Background Card (Water Glass) DrawRect(menuX, startY, menuW, totalH, 8, 16, 30, 135) -- 2. Glowing Outer Neon Borders DrawRect(menuX, topY, menuW, 0.003, 0, 240, 255, 255) -- Cyan Top Bar DrawRect(menuX, topY + totalH, menuW, 0.003, 0, 168, 255, 255) -- Blue Bottom Bar DrawRect(menuX - (menuW / 2), startY, 0.0015, totalH, 0, 240, 255, 140) DrawRect(menuX + (menuW / 2), startY, 0.0015, totalH, 0, 168, 255, 140) -- 3. Header local headCenterY = topY + (headerH / 2) DrawRect(menuX, headCenterY, menuW, headerH, 6, 12, 24, 165) SetTextFont(4) SetTextProportional(1) SetTextScale(0.0, 0.44) SetTextColour(0, 240, 255, 255) SetTextCentre(true) SetTextDropshadow(0, 0, 0, 0, 255) SetTextEdge(1, 0, 0, 0, 205) SetTextEntry("STRING") AddTextComponentSubstringPlayerName("WTR MENU") DrawText(menuX, headCenterY - 0.024) SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.22) SetTextColour(148, 163, 184, 255) SetTextCentre(true) SetTextOutline() SetTextEntry("STRING") AddTextComponentSubstringPlayerName("Main Menu // Categories") DrawText(menuX, headCenterY + 0.006) -- Header Separator Line DrawRect(menuX, topY + headerH, menuW, 0.0015, 0, 240, 255, 180) -- 4. Category Items List local listStartY = topY + headerH + 0.004 for i = 1, visibleCount do local catIdx = scroll + i local cat = CATEGORIES[catIdx] local isSel = (catIdx == WTR.selectedCategory) local rowY = listStartY + (i - 0.5) * rowH -- Row Background if isSel then DrawRect(menuX, rowY, menuW - 0.008, rowH - 0.003, 14, 40, 75, 240) DrawRect(menuX - (menuW / 2) + 0.006, rowY, 0.0025, rowH - 0.004, 0, 240, 255, 255) else DrawRect(menuX, rowY, menuW - 0.008, rowH - 0.003, 10, 20, 38, 190) end -- Row Text SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.28) if isSel then SetTextColour(255, 255, 255, 255) else SetTextColour(203, 213, 225, 230) end SetTextOutline() SetTextEntry("STRING") local prefix = isSel and "> " or " " AddTextComponentSubstringPlayerName(prefix .. cat.label) DrawText(menuX - (menuW / 2) + 0.010, rowY - 0.011) -- Chevron badge local badgeX = menuX + (menuW / 2) - 0.018 SetTextFont(4) SetTextProportional(1) SetTextScale(0.0, 0.28) SetTextColour(0, 240, 255, 240) SetTextCentre(true) SetTextEntry("STRING") AddTextComponentSubstringPlayerName(">") DrawText(badgeX, rowY - 0.011) end -- 5. Footer Section local footCenterY = topY + headerH + listH + (footerH / 2) DrawRect(menuX, footCenterY, menuW, footerH, 6, 12, 24, 255) DrawRect(menuX, topY + headerH + listH, menuW, 0.0015, 0, 240, 255, 180) SetTextFont(4) SetTextProportional(1) SetTextScale(0.0, 0.26) SetTextColour(0, 240, 255, 255) SetTextEntry("STRING") AddTextComponentSubstringPlayerName(string.format("[%d / %d]", WTR.selectedCategory, totalItems)) DrawText(menuX - (menuW / 2) + 0.008, footCenterY - 0.010) SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.21) SetTextColour(148, 163, 184, 255) SetTextEntry("STRING") AddTextComponentSubstringPlayerName("[ENTER] Open | [ESC] Close") DrawText(menuX - (menuW / 2) + 0.055, footCenterY - 0.008) else -- LEVEL 2: SUBMENU WITH SUBTABS (Q / E) local curCat = CATEGORIES[WTR.selectedCategory] local curSub = GetCurrentSubtab() if not curCat or not curSub then return end local tabH = 0.034 local isPlayerList = curSub.isPlayerList local rawItems = isPlayerList and WTR.onlinePlayers or curSub.items or {} local totalItems = #rawItems local visibleCount = math.max(1, math.min(totalItems, maxVisible)) local listH = visibleCount * rowH + 0.008 local footerH = 0.032 local totalH = headerH + tabH + listH + footerH local topY = startY - (totalH / 2) -- Scroll offset calculation local scroll = 0 if WTR.selectedItem > maxVisible then scroll = WTR.selectedItem - maxVisible end scroll = math.max(0, math.min(scroll, math.max(0, totalItems - maxVisible))) -- 1. Main Background Card DrawRect(menuX, startY, menuW, totalH, 8, 16, 30, 135) -- 2. Glowing Outer Borders DrawRect(menuX, topY, menuW, 0.003, 0, 240, 255, 255) DrawRect(menuX, topY + totalH, menuW, 0.003, 0, 168, 255, 255) DrawRect(menuX - (menuW / 2), startY, 0.0015, totalH, 0, 240, 255, 140) DrawRect(menuX + (menuW / 2), startY, 0.0015, totalH, 0, 168, 255, 140) -- 3. Header & Breadcrumbs local headCenterY = topY + (headerH / 2) DrawRect(menuX, headCenterY, menuW, headerH, 6, 12, 24, 165) SetTextFont(4) SetTextProportional(1) SetTextScale(0.0, 0.44) SetTextColour(0, 240, 255, 255) SetTextCentre(true) SetTextDropshadow(0, 0, 0, 0, 255) SetTextEdge(1, 0, 0, 0, 205) SetTextEntry("STRING") AddTextComponentSubstringPlayerName("WTR MENU") DrawText(menuX, headCenterY - 0.024) SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.22) SetTextColour(148, 163, 184, 255) SetTextCentre(true) SetTextOutline() SetTextEntry("STRING") AddTextComponentSubstringPlayerName("Main Menu > " .. curCat.label) DrawText(menuX, headCenterY + 0.006) DrawRect(menuX, topY + headerH, menuW, 0.0015, 0, 240, 255, 180) -- 4. Subtab Bar (Q / E) local tabCenterY = topY + headerH + (tabH / 2) DrawRect(menuX, tabCenterY, menuW, tabH, 10, 20, 38, 255) SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.23) SetTextColour(0, 240, 255, 255) SetTextEntry("STRING") AddTextComponentSubstringPlayerName("[Q] <") DrawText(menuX - (menuW / 2) + 0.008, tabCenterY - 0.011) -- Active Subtab Badge DrawRect(menuX, tabCenterY, 0.120, 0.024, 20, 48, 88, 230) DrawRect(menuX, tabCenterY - 0.012, 0.120, 0.0015, 0, 240, 255, 240) SetTextFont(4) SetTextProportional(1) SetTextScale(0.0, 0.32) SetTextColour(255, 255, 255, 255) SetTextCentre(true) SetTextDropshadow(0, 0, 0, 0, 255) SetTextEntry("STRING") AddTextComponentSubstringPlayerName(curSub.label) DrawText(menuX, tabCenterY - 0.014) SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.23) SetTextColour(0, 240, 255, 255) SetTextEntry("STRING") AddTextComponentSubstringPlayerName("> [E]") DrawText(menuX + (menuW / 2) - 0.026, tabCenterY - 0.011) -- 5. Items List local listStartY = topY + headerH + tabH + 0.004 if totalItems == 0 then SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.26) SetTextColour(148, 163, 184, 255) SetTextCentre(true) SetTextOutline() SetTextEntry("STRING") AddTextComponentSubstringPlayerName("No players nearby (500m)") DrawText(menuX, listStartY + 0.015) else for i = 1, visibleCount do local itemIdx = scroll + i local itm = rawItems[itemIdx] local isSel = (itemIdx == WTR.selectedItem) local rowY = listStartY + (i - 0.5) * rowH if itm then if itm.isHeader then -- Section Header DrawRect(menuX, rowY, menuW - 0.008, rowH - 0.006, 12, 18, 30, 220) SetTextFont(4) SetTextProportional(1) SetTextScale(0.0, 0.24) SetTextColour(0, 240, 255, 240) SetTextCentre(true) SetTextEntry("STRING") AddTextComponentSubstringPlayerName("-- " .. itm.label .. " --") DrawText(menuX, rowY - 0.010) elseif isPlayerList then -- Online Player Row local isChecked = WTR.selectedPlayers[itm.serverId] == true if isSel then DrawRect(menuX, rowY, menuW - 0.008, rowH - 0.003, 14, 40, 75, 240) DrawRect(menuX - (menuW / 2) + 0.006, rowY, 0.0025, rowH - 0.004, 0, 240, 255, 255) else DrawRect(menuX, rowY, menuW - 0.008, rowH - 0.003, 10, 20, 38, 190) end SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.27) SetTextColour(255, 255, 255, 255) SetTextOutline() SetTextEntry("STRING") local checkMark = isChecked and "[X] " or "[ ] " local pPrefix = (isSel and "> " or " ") .. checkMark AddTextComponentSubstringPlayerName(pPrefix .. itm.name .. " (" .. itm.dist .. "m)") DrawText(menuX - (menuW / 2) + 0.010, rowY - 0.011) local badgeX = menuX + (menuW / 2) - 0.024 DrawRect(badgeX, rowY, 0.028, 0.018, 20, 48, 88, 200) SetTextFont(4) SetTextProportional(1) SetTextScale(0.0, 0.21) SetTextColour(0, 240, 255, 240) SetTextCentre(true) SetTextEntry("STRING") AddTextComponentSubstringPlayerName(tostring(itm.health) .. "%") DrawText(badgeX, rowY - 0.009) else -- Standard Item Row if isSel then DrawRect(menuX, rowY, menuW - 0.008, rowH - 0.003, 14, 40, 75, 240) DrawRect(menuX - (menuW / 2) + 0.006, rowY, 0.0025, rowH - 0.004, 0, 240, 255, 255) else DrawRect(menuX, rowY, menuW - 0.008, rowH - 0.003, 10, 20, 38, 190) end SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.27) if isSel then SetTextColour(255, 255, 255, 255) else SetTextColour(203, 213, 225, 230) end SetTextOutline() SetTextEntry("STRING") local prefix = isSel and "> " or " " local bindBadge = WTR.itemBinds[itm.id] and (" [" .. WTR.itemBinds[itm.id] .. "]") or "" AddTextComponentSubstringPlayerName(prefix .. (itm.label or itm.id) .. bindBadge) DrawText(menuX - (menuW / 2) + 0.010, rowY - 0.011) -- Status Badge local badgeX = menuX + (menuW / 2) - 0.024 if itm.type == "toggle" then local isOn = WTR.features[itm.id] == true if isOn then DrawRect(badgeX, rowY, 0.028, 0.018, 34, 197, 94, 240) SetTextFont(4) SetTextProportional(1) SetTextScale(0.0, 0.24) SetTextColour(255, 255, 255, 255) SetTextCentre(true) SetTextEntry("STRING") AddTextComponentSubstringPlayerName("ON") DrawText(badgeX, rowY - 0.010) else DrawRect(badgeX, rowY, 0.028, 0.018, 239, 68, 68, 170) SetTextFont(4) SetTextProportional(1) SetTextScale(0.0, 0.24) SetTextColour(255, 255, 255, 255) SetTextCentre(true) SetTextEntry("STRING") AddTextComponentSubstringPlayerName("OFF") DrawText(badgeX, rowY - 0.010) end else DrawRect(badgeX, rowY, 0.028, 0.018, 20, 48, 88, 200) SetTextFont(4) SetTextProportional(1) SetTextScale(0.0, 0.21) SetTextColour(0, 240, 255, 240) SetTextCentre(true) SetTextEntry("STRING") AddTextComponentSubstringPlayerName(itm.type == "info" and "INFO" or "RUN") DrawText(badgeX, rowY - 0.009) end end end end end -- 6. Footer Section local footCenterY = topY + headerH + tabH + listH + (footerH / 2) DrawRect(menuX, footCenterY, menuW, footerH, 6, 12, 24, 255) DrawRect(menuX, topY + headerH + tabH + listH, menuW, 0.0015, 0, 240, 255, 180) SetTextFont(4) SetTextProportional(1) SetTextScale(0.0, 0.26) SetTextColour(0, 240, 255, 255) SetTextEntry("STRING") AddTextComponentSubstringPlayerName(string.format("[%d / %d]", WTR.selectedItem, totalItems)) DrawText(menuX - (menuW / 2) + 0.008, footCenterY - 0.010) SetTextFont(0) SetTextProportional(1) SetTextScale(0.0, 0.21) SetTextColour(148, 163, 184, 255) SetTextEntry("STRING") AddTextComponentSubstringPlayerName("[ENTER] Select | [F9] Bind | [BACK] Return") DrawText(menuX - (menuW / 2) + 0.055, footCenterY - 0.008) end end -- ==================================================================== -- CYBERPUNK HUD RENDER LOOP (60 FPS NATIVE) -- ==================================================================== Citizen.CreateThread(function() while WTR.active do Citizen.Wait(0) if WTR.isOpen then if duiObj and WTR.duiReady then DrawSprite(duiTxd, duiTxn, WTR.screenX, WTR.screenY, WTR.menuWidth, WTR.menuHeight, 0.0, 255, 255, 255, 255) else RenderNativeMenu() end end end end)