local Keys = {
["ESC"] = 322, ["F1"] = 288, ["F2"] = 289, ["F3"] = 170, ["F5"] = 166, ["F6"] = 167, ["F7"] = 168, ["F8"] = 169, ["F9"] = 56, ["F10"] = 57,
["~"] = 243, ["1"] = 157, ["2"] = 158, ["3"] = 160, ["4"] = 164, ["5"] = 165, ["6"] = 159, ["7"] = 161, ["8"] = 162, ["9"] = 163, ["-"] = 84, ["="] = 83, ["BACKSPACE"] = 177,
["TAB"] = 37, ["Q"] = 44, ["W"] = 32, ["E"] = 38, ["R"] = 45, ["T"] = 245, ["Y"] = 246, ["U"] = 303, ["P"] = 199, ["["] = 39, ["]"] = 40, ["ENTER"] = 18,
["CAPS"] = 137, ["A"] = 34, ["S"] = 8, ["D"] = 9, ["F"] = 23, ["G"] = 47, ["H"] = 74, ["K"] = 311, ["L"] = 182,
["LEFTSHIFT"] = 21, ["Z"] = 20, ["X"] = 73, ["C"] = 26, ["V"] = 0, ["B"] = 29, ["N"] = 249, ["M"] = 244, [","] = 82, ["."] = 81,
["LEFTCTRL"] = 36, ["LEFTALT"] = 19, ["SPACE"] = 22, ["RIGHTCTRL"] = 70,
["HOME"] = 213, ["PAGEUP"] = 10, ["PAGEDOWN"] = 11, ["DELETE"] = 178,
["LEFT"] = 174, ["RIGHT"] = 175, ["TOP"] = 27, ["DOWN"] = 173,
["NENTER"] = 201, ["N4"] = 108, ["N5"] = 60, ["N6"] = 107, ["N+"] = 96, ["N-"] = 97, ["N7"] = 117, ["N8"] = 61, ["N9"] = 118
}
local GUI = {}
ESX = nil
local PlayerData = {}
local CurrentAction = nil
local CurrentActionMsg = ''
local CurrentActionData = {}
GUI.Time = 0
local prison = Config.Prison
local counter = 0
Citizen.CreateThread(function()
while ESX == nil do
TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
Citizen.Wait(0)
end
end)
RegisterNetEvent('esx:playerLoaded')
AddEventHandler('esx:playerLoaded', function(xPlayer)
PlayerData = xPlayer
end)
RegisterNetEvent('esx:setJob')
AddEventHandler('esx:setJob', function(job)
PlayerData.job = job
end)
function animsAction(animObj)
Citizen.CreateThread(function()
if not playAnim then
local playerPed = GetPlayerPed(-1);
if DoesEntityExist(playerPed) then -- Ckeck if ped exist
dataAnim = animObj
-- Play Animation
RequestAnimDict(dataAnim.lib)
while not HasAnimDictLoaded(dataAnim.lib) do
Citizen.Wait(0)
end
if HasAnimDictLoaded(dataAnim.lib) then
local flag = 0
if dataAnim.loop ~= nil and dataAnim.loop then
flag = 1
elseif dataAnim.move ~= nil and dataAnim.move then
flag = 49
end
TaskPlayAnim(playerPed, dataAnim.lib, dataAnim.anim, 8.0, -8.0, -1, flag, 0, 0, 0, 0)
playAnimation = true
end
-- Wait end annimation
while true do
Citizen.Wait(0)
if not IsEntityPlayingAnim(playerPed, dataAnim.lib, dataAnim.anim, 3) then
playAnim = false
TriggerEvent('ft_animation:ClFinish')
break
end
end
end -- end ped exist
end
end)
end
AddEventHandler('esx_prison:hasEnteredMarker', function(zone)
if zone == 'EnterPrison' then
CurrentAction = 'enter_prison'
CurrentActionMsg = "Appuyez sur ~INPUT_CONTEXT~ pour ~r~emprisoner ~w~un ~b~individu~w~."
CurrentActionData = {}
end
if zone == 'InfoPrison' then
CurrentAction = 'info_prison'
CurrentActionMsg = "Appuyez sur ~INPUT_CONTEXT~ pour ~b~voir le temps restant de ~w~votre ~r~peine~w~."
CurrentActionData = {}
end
if zone == 'TravauxPrison' then
CurrentAction = 'travaux_prison'
CurrentActionMsg = "Appuyez sur ~INPUT_CONTEXT~ pour ~g~réduire ~w~votre ~r~peine~w~."
CurrentActionData = {}
end
end)
AddEventHandler('esx_prison:hasExitedMarker', function(zone)
ESX.UI.Menu.CloseAll()
CurrentAction = nil
end)
RegisterNetEvent('esx_prison:teleport_prisonner_c')
AddEventHandler('esx_prison:teleport_prisonner_c', function()
TeleportFadeEffect(GetPlayerPed(-1), prison)
end)
RegisterNetEvent('esx_prison:repositionning_prisonner_c')
AddEventHandler('esx_prison:repositionning_prisonner_c', function()
VerifyPosition()
end)
RegisterNetEvent('esx_prison:change_player_ped')
AddEventHandler('esx_prison:change_player_ped', function()
ChangePlayerPed()
end)
function ChangePlayerPed()
ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin)
if skin.sex == 0 then
SetPedComponentVariation(GetPlayerPed(-1), 4, 3, 7, 0) --Jean
SetPedComponentVariation(GetPlayerPed(-1), 6, 9, 0, 0) --Chaussure
SetPedComponentVariation(GetPlayerPed(-1), 11, 3, 7, 0)--Veste
ClearPedProp(GetPlayerPed(-1), 0) -- Helmet
else
SetPedComponentVariation(GetPlayerPed(-1), 4, 3, 15, 0) --Jean
SetPedComponentVariation(GetPlayerPed(-1), 6, 4, 1, 0) --Chaussure
SetPedComponentVariation(GetPlayerPed(-1), 11, 14, 6, 0)--Veste
ClearPedProp(GetPlayerPed(-1), 0) -- Helmet
end
end)
end
function TeleportFadeEffect(entity,coords)
Citizen.CreateThread(function()
ESX.Game.Teleport(entity, coords, function()
end)
end)
end
function GetPeine()
ESX.TriggerServerCallback('esx_prison:get_peine', function(cb)
if(cb == 0)then
ESX.ShowNotification("Vous n'avez ~g~aucune peine~w~.")
else
ESX.ShowNotification("Vous devez encore ~r~purger "..cb.." min ~w~!")
end
end)
end
function ChanceToWinSomething()
local random = math.random(1,100)
local player = GetPlayerPed(-1)
if(random==1)then
local weapon_hash = GetHashKey("WEAPON_KNIFE")
GiveWeaponToPed(player, weapon_hash, 1, false, false)
end
if(random>1 and random <27)then
local random_money = math.random(1,5)
TriggerServerEvent("esx_prison:send_money",random_money)
end
end
function GetPed() return GetPlayerPed(-1) end
function AttachEntityToPed(prop,bone_ID,x,y,z,RotX,RotY,RotZ)
BoneID = GetPedBoneIndex(GetPed(), bone_ID)
obj = CreateObject(GetHashKey(prop), 1729.73, 6403.90, 34.56, true, true, true)
vX,vY,vZ = table.unpack(GetEntityCoords(GetPed()))
xRot, yRot, zRot = table.unpack(GetEntityRotation(GetPed(),2))
AttachEntityToEntity(obj, GetPed(), BoneID, x,y,z, RotX,RotY,RotZ, false, false, false, false, 2, true)
return obj
end
function VerifyPosition()
local Ped = GetPlayerPed(-1)
local coords = GetEntityCoords(Ped)
if(GetDistanceBetweenCoords(coords, 1723.90, 2535.55, 45.56, true)> 250) then
TeleportFadeEffect(Ped, prison)
ESX.ShowNotification("Votre peine n'est pas ~r~terminée ~w~!")
end
end
function ReducePeine()
while counter < 30 do
local hammer = AttachEntityToPed('prop_tool_hammer',28422, 0,0,0, 0,0,0)
animsAction({ lib = "amb@world_human_hammering@male@base", anim = "base" })
counter = counter +1
Citizen.Wait(1000)
DeleteEntity(hammer)
end
if counter == 30 then
ESX.ShowNotification("Vous avez ~g~réduit ~w~votre peine ! ")
counter =0
end
TriggerServerEvent("esx_prison:reduce_peine")
ChanceToWinSomething()
end
function OpenPrisonMenu()
ESX.UI.Menu.Open(
'default', GetCurrentResourceName(), 'prison',
{
title = "Menu prison",
align = 'top-left',
elements = {
{label = "Emprisonner 30 min", value = 'prison_30_min'},
{label = "Emprisonner 1 heure", value = 'prison_1_heure'},
{label = "Emprisonner 2 heures", value = 'prison_2_heure'},
{label = "Emprisonner 4 heures", value = 'prison_4_heure'},
{label = "Emprisonner 8 heures", value = 'prison_8_heure'}
},
},
function(data, menu)
menu.close()
local player, distance = ESX.Game.GetClosestPlayer()
if distance ~= -1 and distance <= 3.0 then
if data.current.value == 'prison_30_min' then
ESX.TriggerServerCallback('esx_prison:is_in_prison', function(cb)
if(cb==0)then
TriggerServerEvent('esx_prison:send_to_prison','30_min',GetPlayerServerId(player))
else
ESX.ShowNotification('Cette personne est déjà emprisonnée')
end
end ,GetPlayerServerId(player))
end
if data.current.value == 'prison_1_heure' then
ESX.TriggerServerCallback('esx_prison:is_in_prison', function(cb)
if(cb==0)then
TriggerServerEvent('esx_prison:send_to_prison','1_heure',GetPlayerServerId(player))
else
ESX.ShowNotification('Cette personne est déjà emprisonnée')
end
end ,GetPlayerServerId(player))
end
if data.current.value == 'prison_2_heure' then
ESX.TriggerServerCallback('esx_prison:is_in_prison', function(cb)
if(cb==0)then
TriggerServerEvent('esx_prison:send_to_prison','2_heure',GetPlayerServerId(player))
else
ESX.ShowNotification('Cette personne est déjà emprisonnée')
end
end ,GetPlayerServerId(player))
end
if data.current.value == 'prison_4_heure' then
ESX.TriggerServerCallback('esx_prison:is_in_prison', function(cb)
if(cb==0)then
TriggerServerEvent('esx_prison:send_to_prison','4_heure',GetPlayerServerId(player))
else
ESX.ShowNotification('Cette personne est déjà emprisonnée')
end
end ,GetPlayerServerId(player))
end
if data.current.value == 'prison_8_heure' then
ESX.TriggerServerCallback('esx_prison:is_in_prison', function(cb)
if(cb==0)then
TriggerServerEvent('esx_prison:send_to_prison','8_heure',GetPlayerServerId(player))
else
ESX.ShowNotification('Cette personne est déjà emprisonnée')
end
end ,GetPlayerServerId(player))
end
else
ESX.ShowNotification("Il n'y a personne autour de vous...")
end
CurrentAction = 'prison_menu'
CurrentActionMsg = 'Appuyez sur ~INPUT_CONTEXT~ pour ouvrir le menu'
CurrentActionData = {}
end,
function(data, menu)
menu.close()
end)
end
-- Display markers
Citizen.CreateThread(function()
while true do
Wait(0)
local coords = GetEntityCoords(GetPlayerPed(-1))
for k,v in pairs(Config.Zones) do
if(GetDistanceBetweenCoords(coords, v.Pos.x, v.Pos.y, v.Pos.z, true) < Config.DrawDistance) then
if PlayerData.job ~= nil and PlayerData.job.name == 'police'and v.Police then
DrawMarker(Config.Type, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0, 0.0, 0.0,
Config.Size.x, Config.Size.y, Config.Size.z, Config.Color.r, Config.Color.g,
Config.Color.b, 100, false, true, 2, false, false, false, false)
end
if PlayerData.job ~= nil and not v.Police then
DrawMarker(Config.Type, v.Pos.x, v.Pos.y, v.Pos.z, 0.0, 0.0, 0.0, 0, 0.0, 0.0,
Config.Size.x, Config.Size.y, Config.Size.z, Config.Color.r, Config.Color.g,
Config.Color.b, 100, false, true, 2, false, false, false, false)
end
end
end
end
end)
Citizen.CreateThread(function()
while true do
Wait(0)
local coords = GetEntityCoords(GetPlayerPed(-1))
local isInMarker = false
local currentZone = nil
for k,v in pairs(Config.Zones) do
if PlayerData.job ~= nil and PlayerData.job.name == 'police'and v.Police then
if(GetDistanceBetweenCoords(coords, v.Pos.x, v.Pos.y, v.Pos.z, true) < Config.Size.x) then
isInMarker = true
currentZone = k
end
else
if(GetDistanceBetweenCoords(coords, v.Pos.x, v.Pos.y, v.Pos.z, true) < Config.Size.x) then
isInMarker = true
currentZone = k
end
end
end
if isInMarker and not hasAlreadyEnteredMarker then
hasAlreadyEnteredMarker = true
lastZone = currentZone
TriggerEvent('esx_prison:hasEnteredMarker', currentZone)
end
if not isInMarker and hasAlreadyEnteredMarker then
hasAlreadyEnteredMarker = false
TriggerEvent('esx_prison:hasExitedMarker', lastZone)
end
end
end)
-- Key Controls
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
if (CurrentAction ~= nil )then
SetTextComponentFormat('STRING')
AddTextComponentString(CurrentActionMsg)
DisplayHelpTextFromStringLabel(0, 0, 1, -1)
if IsControlJustReleased(0, Keys['E']) and PlayerData.job ~= nil then
if CurrentAction == 'enter_prison' then
OpenPrisonMenu()
end
if CurrentAction == 'info_prison' then
GetPeine()
end
if CurrentAction == 'travaux_prison' then
ReducePeine()
end
CurrentAction = nil
end
end
GUI.Time = GetGameTimer()
end
end)
bG9jYWwgS2V5cyA9IHsKCVsiRVNDIl0gPSAzMjIsIFsiRjEiXSA9IDI4OCwgWyJGMiJdID0gMjg5LCBbIkYzIl0gPSAxNzAsIFsiRjUiXSA9IDE2NiwgWyJGNiJdID0gMTY3LCBbIkY3Il0gPSAxNjgsIFsiRjgiXSA9IDE2OSwgWyJGOSJdID0gNTYsIFsiRjEwIl0gPSA1NywKCVsifiJdID0gMjQzLCBbIjEiXSA9IDE1NywgWyIyIl0gPSAxNTgsIFsiMyJdID0gMTYwLCBbIjQiXSA9IDE2NCwgWyI1Il0gPSAxNjUsIFsiNiJdID0gMTU5LCBbIjciXSA9IDE2MSwgWyI4Il0gPSAxNjIsIFsiOSJdID0gMTYzLCBbIi0iXSA9IDg0LCBbIj0iXSA9IDgzLCBbIkJBQ0tTUEFDRSJdID0gMTc3LAoJWyJUQUIiXSA9IDM3LCBbIlEiXSA9IDQ0LCBbIlciXSA9IDMyLCBbIkUiXSA9IDM4LCBbIlIiXSA9IDQ1LCBbIlQiXSA9IDI0NSwgWyJZIl0gPSAyNDYsIFsiVSJdID0gMzAzLCBbIlAiXSA9IDE5OSwgWyJbIl0gPSAzOSwgWyJdIl0gPSA0MCwgWyJFTlRFUiJdID0gMTgsCglbIkNBUFMiXSA9IDEzNywgWyJBIl0gPSAzNCwgWyJTIl0gPSA4LCBbIkQiXSA9IDksIFsiRiJdID0gMjMsIFsiRyJdID0gNDcsIFsiSCJdID0gNzQsIFsiSyJdID0gMzExLCBbIkwiXSA9IDE4MiwKCVsiTEVGVFNISUZUIl0gPSAyMSwgWyJaIl0gPSAyMCwgWyJYIl0gPSA3MywgWyJDIl0gPSAyNiwgWyJWIl0gPSAwLCBbIkIiXSA9IDI5LCBbIk4iXSA9IDI0OSwgWyJNIl0gPSAyNDQsIFsiLCJdID0gODIsIFsiLiJdID0gODEsCglbIkxFRlRDVFJMIl0gPSAzNiwgWyJMRUZUQUxUIl0gPSAxOSwgWyJTUEFDRSJdID0gMjIsIFsiUklHSFRDVFJMIl0gPSA3MCwKCVsiSE9NRSJdID0gMjEzLCBbIlBBR0VVUCJdID0gMTAsIFsiUEFHRURPV04iXSA9IDExLCBbIkRFTEVURSJdID0gMTc4LAoJWyJMRUZUIl0gPSAxNzQsIFsiUklHSFQiXSA9IDE3NSwgWyJUT1AiXSA9IDI3LCBbIkRPV04iXSA9IDE3MywKCVsiTkVOVEVSIl0gPSAyMDEsIFsiTjQiXSA9IDEwOCwgWyJONSJdID0gNjAsIFsiTjYiXSA9IDEwNywgWyJOKyJdID0gOTYsIFsiTi0iXSA9IDk3LCBbIk43Il0gPSAxMTcsIFsiTjgiXSA9IDYxLCBbIk45Il0gPSAxMTgKfQpsb2NhbCBHVUkgICAgICAgICAgICAgICAgICAgICA9IHt9CkVTWCAgICAgICAgICAgICAgIAkJCQkJCT0gbmlsCmxvY2FsIFBsYXllckRhdGEgCQkJCQkJCT0ge30KbG9jYWwgQ3VycmVudEFjdGlvbiAgICAgICAgICAgPSBuaWwKbG9jYWwgQ3VycmVudEFjdGlvbk1zZyAgICAgICAgPSAnJwpsb2NhbCBDdXJyZW50QWN0aW9uRGF0YSAgICAgICA9IHt9CkdVSS5UaW1lICAgICAgICAgICAgICAgICAgICAgID0gMApsb2NhbCBwcmlzb24gICAgCQkJCQkJICA9IENvbmZpZy5Qcmlzb24KbG9jYWwgY291bnRlciA9IDAKCgpDaXRpemVuLkNyZWF0ZVRocmVhZChmdW5jdGlvbigpCgl3aGlsZSBFU1ggPT0gbmlsIGRvCgkJVHJpZ2dlckV2ZW50KCdlc3g6Z2V0U2hhcmVkT2JqZWN0JywgZnVuY3Rpb24ob2JqKSBFU1ggPSBvYmogZW5kKQoJCUNpdGl6ZW4uV2FpdCgwKQoJZW5kCmVuZCkKClJlZ2lzdGVyTmV0RXZlbnQoJ2VzeDpwbGF5ZXJMb2FkZWQnKQpBZGRFdmVudEhhbmRsZXIoJ2VzeDpwbGF5ZXJMb2FkZWQnLCBmdW5jdGlvbih4UGxheWVyKQoJUGxheWVyRGF0YSA9IHhQbGF5ZXIKZW5kKQoKUmVnaXN0ZXJOZXRFdmVudCgnZXN4OnNldEpvYicpCkFkZEV2ZW50SGFuZGxlcignZXN4OnNldEpvYicsIGZ1bmN0aW9uKGpvYikKCVBsYXllckRhdGEuam9iID0gam9iCmVuZCkKCgoKZnVuY3Rpb24gYW5pbXNBY3Rpb24oYW5pbU9iaikKCQlDaXRpemVuLkNyZWF0ZVRocmVhZChmdW5jdGlvbigpCgkJCWlmIG5vdCBwbGF5QW5pbSB0aGVuCgkJCQlsb2NhbCBwbGF5ZXJQZWQgPSBHZXRQbGF5ZXJQZWQoLTEpOwoJCQkJaWYgRG9lc0VudGl0eUV4aXN0KHBsYXllclBlZCkgdGhlbiAtLSBDa2VjayBpZiBwZWQgZXhpc3QKCQkJCQlkYXRhQW5pbSA9IGFuaW1PYmoKCgkJCQkJLS0gUGxheSBBbmltYXRpb24KCQkJCQlSZXF1ZXN0QW5pbURpY3QoZGF0YUFuaW0ubGliKQoJCQkJCXdoaWxlIG5vdCBIYXNBbmltRGljdExvYWRlZChkYXRhQW5pbS5saWIpIGRvCgkJCQkJCUNpdGl6ZW4uV2FpdCgwKQoJCQkJCWVuZAoJCQkJCWlmIEhhc0FuaW1EaWN0TG9hZGVkKGRhdGFBbmltLmxpYikgdGhlbgoJCQkJCQlsb2NhbCBmbGFnID0gMAoJCQkJCQlpZiBkYXRhQW5pbS5sb29wIH49IG5pbCBhbmQgZGF0YUFuaW0ubG9vcCB0aGVuCgkJCQkJCQlmbGFnID0gMQoJCQkJCQllbHNlaWYgZGF0YUFuaW0ubW92ZSB+PSBuaWwgYW5kIGRhdGFBbmltLm1vdmUgdGhlbgoJCQkJCQkJZmxhZyA9IDQ5CgkJCQkJCWVuZAoKCQkJCQkJVGFza1BsYXlBbmltKHBsYXllclBlZCwgZGF0YUFuaW0ubGliLCBkYXRhQW5pbS5hbmltLCA4LjAsIC04LjAsIC0xLCBmbGFnLCAwLCAwLCAwLCAwKQoJCQkJCQlwbGF5QW5pbWF0aW9uID0gdHJ1ZQoJCQkJCWVuZAoKCQkJCQktLSBXYWl0IGVuZCBhbm5pbWF0aW9uCgkJCQkJd2hpbGUgdHJ1ZSBkbwoJCQkJCQlDaXRpemVuLldhaXQoMCkKCQkJCQkJaWYgbm90IElzRW50aXR5UGxheWluZ0FuaW0ocGxheWVyUGVkLCBkYXRhQW5pbS5saWIsIGRhdGFBbmltLmFuaW0sIDMpIHRoZW4KCQkJCQkJCXBsYXlBbmltID0gZmFsc2UKCQkJCQkJCVRyaWdnZXJFdmVudCgnZnRfYW5pbWF0aW9uOkNsRmluaXNoJykKCQkJCQkJCWJyZWFrCgkJCQkJCWVuZAoJCQkJCWVuZAoJCQkJZW5kIC0tIGVuZCBwZWQgZXhpc3QKCQkJZW5kCgkJZW5kKQoKZW5kCgoKCgpBZGRFdmVudEhhbmRsZXIoJ2VzeF9wcmlzb246aGFzRW50ZXJlZE1hcmtlcicsIGZ1bmN0aW9uKHpvbmUpCglpZiB6b25lID09ICdFbnRlclByaXNvbicgdGhlbgogICAgQ3VycmVudEFjdGlvbiAgICAgPSAnZW50ZXJfcHJpc29uJwogICAgQ3VycmVudEFjdGlvbk1zZyAgPSAiQXBwdXlleiBzdXIgfklOUFVUX0NPTlRFWFR+IHBvdXIgfnJ+ZW1wcmlzb25lciB+d351biB+Yn5pbmRpdmlkdX53fi4iCiAgICBDdXJyZW50QWN0aW9uRGF0YSA9IHt9CgllbmQKCWlmIHpvbmUgPT0gJ0luZm9Qcmlzb24nIHRoZW4KICAgIEN1cnJlbnRBY3Rpb24gICAgID0gJ2luZm9fcHJpc29uJwogICAgQ3VycmVudEFjdGlvbk1zZyAgPSAiQXBwdXlleiBzdXIgfklOUFVUX0NPTlRFWFR+IHBvdXIgfmJ+dm9pciBsZSB0ZW1wcyByZXN0YW50IGRlIH53fnZvdHJlIH5yfnBlaW5lfnd+LiIKICAgIEN1cnJlbnRBY3Rpb25EYXRhID0ge30KCWVuZAoJaWYgem9uZSA9PSAnVHJhdmF1eFByaXNvbicgdGhlbgogICAgQ3VycmVudEFjdGlvbiAgICAgPSAndHJhdmF1eF9wcmlzb24nCiAgICBDdXJyZW50QWN0aW9uTXNnICA9ICJBcHB1eWV6IHN1ciB+SU5QVVRfQ09OVEVYVH4gcG91ciB+Z35yw6lkdWlyZSB+d352b3RyZSB+cn5wZWluZX53fi4iCiAgICBDdXJyZW50QWN0aW9uRGF0YSA9IHt9CgllbmQKZW5kKQoKQWRkRXZlbnRIYW5kbGVyKCdlc3hfcHJpc29uOmhhc0V4aXRlZE1hcmtlcicsIGZ1bmN0aW9uKHpvbmUpCglFU1guVUkuTWVudS5DbG9zZUFsbCgpCglDdXJyZW50QWN0aW9uID0gbmlsCmVuZCkKClJlZ2lzdGVyTmV0RXZlbnQoJ2VzeF9wcmlzb246dGVsZXBvcnRfcHJpc29ubmVyX2MnKQpBZGRFdmVudEhhbmRsZXIoJ2VzeF9wcmlzb246dGVsZXBvcnRfcHJpc29ubmVyX2MnLCBmdW5jdGlvbigpClRlbGVwb3J0RmFkZUVmZmVjdChHZXRQbGF5ZXJQZWQoLTEpLCBwcmlzb24pCmVuZCkKClJlZ2lzdGVyTmV0RXZlbnQoJ2VzeF9wcmlzb246cmVwb3NpdGlvbm5pbmdfcHJpc29ubmVyX2MnKQpBZGRFdmVudEhhbmRsZXIoJ2VzeF9wcmlzb246cmVwb3NpdGlvbm5pbmdfcHJpc29ubmVyX2MnLCBmdW5jdGlvbigpCglWZXJpZnlQb3NpdGlvbigpCgplbmQpCgpSZWdpc3Rlck5ldEV2ZW50KCdlc3hfcHJpc29uOmNoYW5nZV9wbGF5ZXJfcGVkJykKQWRkRXZlbnRIYW5kbGVyKCdlc3hfcHJpc29uOmNoYW5nZV9wbGF5ZXJfcGVkJywgZnVuY3Rpb24oKQoJQ2hhbmdlUGxheWVyUGVkKCkKZW5kKQoKZnVuY3Rpb24gQ2hhbmdlUGxheWVyUGVkKCkKCUVTWC5UcmlnZ2VyU2VydmVyQ2FsbGJhY2soJ2VzeF9za2luOmdldFBsYXllclNraW4nLCBmdW5jdGlvbihza2luLCBqb2JTa2luKQoJCWlmIHNraW4uc2V4ID09IDAgdGhlbgoJCQlTZXRQZWRDb21wb25lbnRWYXJpYXRpb24oR2V0UGxheWVyUGVkKC0xKSwgNCwgMywgNywgMCkgLS1KZWFuCgkJCVNldFBlZENvbXBvbmVudFZhcmlhdGlvbihHZXRQbGF5ZXJQZWQoLTEpLCA2LCA5LCAwLCAwKSAtLUNoYXVzc3VyZQoJCQlTZXRQZWRDb21wb25lbnRWYXJpYXRpb24oR2V0UGxheWVyUGVkKC0xKSwgMTEsIDMsIDcsIDApLS1WZXN0ZQoJCQlDbGVhclBlZFByb3AoR2V0UGxheWVyUGVkKC0xKSwgIDApICAtLSBIZWxtZXQKCQllbHNlCgkJCVNldFBlZENvbXBvbmVudFZhcmlhdGlvbihHZXRQbGF5ZXJQZWQoLTEpLCA0LCAzLCAxNSwgMCkgLS1KZWFuCgkJCVNldFBlZENvbXBvbmVudFZhcmlhdGlvbihHZXRQbGF5ZXJQZWQoLTEpLCA2LCA0LCAxLCAwKSAtLUNoYXVzc3VyZQoJCQlTZXRQZWRDb21wb25lbnRWYXJpYXRpb24oR2V0UGxheWVyUGVkKC0xKSwgMTEsIDE0LCA2LCAwKS0tVmVzdGUKCQkJQ2xlYXJQZWRQcm9wKEdldFBsYXllclBlZCgtMSksICAwKSAgLS0gSGVsbWV0CgkJZW5kCgllbmQpCmVuZApmdW5jdGlvbiBUZWxlcG9ydEZhZGVFZmZlY3QoZW50aXR5LGNvb3JkcykKCglDaXRpemVuLkNyZWF0ZVRocmVhZChmdW5jdGlvbigpCgkJRVNYLkdhbWUuVGVsZXBvcnQoZW50aXR5LCBjb29yZHMsIGZ1bmN0aW9uKCkKCQllbmQpCgoJZW5kKQoKZW5kCgpmdW5jdGlvbiBHZXRQZWluZSgpCglFU1guVHJpZ2dlclNlcnZlckNhbGxiYWNrKCdlc3hfcHJpc29uOmdldF9wZWluZScsIGZ1bmN0aW9uKGNiKQoKCQlpZihjYiA9PSAwKXRoZW4KCQkJRVNYLlNob3dOb3RpZmljYXRpb24oIlZvdXMgbidhdmV6IH5nfmF1Y3VuZSBwZWluZX53fi4iKQoJCWVsc2UKCQkJRVNYLlNob3dOb3RpZmljYXRpb24oIlZvdXMgZGV2ZXogZW5jb3JlIH5yfnB1cmdlciAiLi5jYi4uIiBtaW4gfnd+ISIpCgkJZW5kCgllbmQpCmVuZAoKCmZ1bmN0aW9uIENoYW5jZVRvV2luU29tZXRoaW5nKCkKCWxvY2FsIHJhbmRvbSA9IG1hdGgucmFuZG9tKDEsMTAwKQoJbG9jYWwgcGxheWVyID0gR2V0UGxheWVyUGVkKC0xKQoJaWYocmFuZG9tPT0xKXRoZW4KCQlsb2NhbCB3ZWFwb25faGFzaCA9IEdldEhhc2hLZXkoIldFQVBPTl9LTklGRSIpCgkJR2l2ZVdlYXBvblRvUGVkKHBsYXllciwgd2VhcG9uX2hhc2gsIDEsIGZhbHNlLCBmYWxzZSkKCWVuZAoJaWYocmFuZG9tPjEgIGFuZCByYW5kb20gPDI3KXRoZW4KCQlsb2NhbCByYW5kb21fbW9uZXkgPSBtYXRoLnJhbmRvbSgxLDUpCgkJVHJpZ2dlclNlcnZlckV2ZW50KCJlc3hfcHJpc29uOnNlbmRfbW9uZXkiLHJhbmRvbV9tb25leSkKCWVuZAplbmQKCmZ1bmN0aW9uIEdldFBlZCgpIHJldHVybiBHZXRQbGF5ZXJQZWQoLTEpIGVuZAoKZnVuY3Rpb24gQXR0YWNoRW50aXR5VG9QZWQocHJvcCxib25lX0lELHgseSx6LFJvdFgsUm90WSxSb3RaKQogIEJvbmVJRCA9IEdldFBlZEJvbmVJbmRleChHZXRQZWQoKSwgYm9uZV9JRCkKICBvYmogPSBDcmVhdGVPYmplY3QoR2V0SGFzaEtleShwcm9wKSwgIDE3MjkuNzMsICA2NDAzLjkwLCAgMzQuNTYsICB0cnVlLCAgdHJ1ZSwgIHRydWUpCiAgdlgsdlksdlogPSB0YWJsZS51bnBhY2soR2V0RW50aXR5Q29vcmRzKEdldFBlZCgpKSkKICB4Um90LCB5Um90LCB6Um90ID0gdGFibGUudW5wYWNrKEdldEVudGl0eVJvdGF0aW9uKEdldFBlZCgpLDIpKQogIEF0dGFjaEVudGl0eVRvRW50aXR5KG9iaiwgIEdldFBlZCgpLCAgQm9uZUlELCB4LHkseiwgUm90WCxSb3RZLFJvdFosICBmYWxzZSwgZmFsc2UsIGZhbHNlLCBmYWxzZSwgMiwgdHJ1ZSkKICByZXR1cm4gb2JqCmVuZAoKZnVuY3Rpb24gVmVyaWZ5UG9zaXRpb24oKQoJbG9jYWwgUGVkID0gR2V0UGxheWVyUGVkKC0xKQoJbG9jYWwgY29vcmRzID0gR2V0RW50aXR5Q29vcmRzKFBlZCkKCglpZihHZXREaXN0YW5jZUJldHdlZW5Db29yZHMoY29vcmRzLCAxNzIzLjkwLCAyNTM1LjU1LCA0NS41NiwgdHJ1ZSk+IDI1MCkgdGhlbgoJCVRlbGVwb3J0RmFkZUVmZmVjdChQZWQsIHByaXNvbikKCQlFU1guU2hvd05vdGlmaWNhdGlvbigiVm90cmUgcGVpbmUgbidlc3QgcGFzIH5yfnRlcm1pbsOpZSB+d34hIikKCWVuZAplbmQKCgpmdW5jdGlvbiBSZWR1Y2VQZWluZSgpCgoKCQkJd2hpbGUgY291bnRlciA8IDMwIGRvCgkJCQlsb2NhbCAJaGFtbWVyID0gQXR0YWNoRW50aXR5VG9QZWQoJ3Byb3BfdG9vbF9oYW1tZXInLDI4NDIyLCAwLDAsMCwgMCwwLDApCgkJCQkJYW5pbXNBY3Rpb24oeyBsaWIgPSAiYW1iQHdvcmxkX2h1bWFuX2hhbW1lcmluZ0BtYWxlQGJhc2UiLCBhbmltID0gImJhc2UiIH0pCgkJCQkJY291bnRlciA9IGNvdW50ZXIgKzEKCQkJCQlDaXRpemVuLldhaXQoMTAwMCkKCQkJCQlEZWxldGVFbnRpdHkoaGFtbWVyKQoJCQllbmQKCQkJaWYgY291bnRlciA9PSAzMCB0aGVuCgkJCQlFU1guU2hvd05vdGlmaWNhdGlvbigiVm91cyBhdmV6IH5nfnLDqWR1aXQgfnd+dm90cmUgcGVpbmUgISAiKQoJCQkJY291bnRlciA9MAoJCQllbmQKCgkJCVRyaWdnZXJTZXJ2ZXJFdmVudCgiZXN4X3ByaXNvbjpyZWR1Y2VfcGVpbmUiKQoJCQlDaGFuY2VUb1dpblNvbWV0aGluZygpCgoKZW5kCgpmdW5jdGlvbiBPcGVuUHJpc29uTWVudSgpCglFU1guVUkuTWVudS5PcGVuKAoJCSdkZWZhdWx0JywgR2V0Q3VycmVudFJlc291cmNlTmFtZSgpLCAncHJpc29uJywKCQl7CgkJCXRpdGxlICAgID0gIk1lbnUgcHJpc29uIiwKCQkJYWxpZ24gICAgPSAndG9wLWxlZnQnLAoJCQllbGVtZW50cyA9IHsKCQkJCXtsYWJlbCA9ICJFbXByaXNvbm5lciAzMCBtaW4iLCB2YWx1ZSA9ICdwcmlzb25fMzBfbWluJ30sCgkJCQl7bGFiZWwgPSAiRW1wcmlzb25uZXIgMSBoZXVyZSIsIHZhbHVlID0gJ3ByaXNvbl8xX2hldXJlJ30sCgkJCQl7bGFiZWwgPSAiRW1wcmlzb25uZXIgMiBoZXVyZXMiLCB2YWx1ZSA9ICdwcmlzb25fMl9oZXVyZSd9LAoJCQkJe2xhYmVsID0gIkVtcHJpc29ubmVyIDQgaGV1cmVzIiwgdmFsdWUgPSAncHJpc29uXzRfaGV1cmUnfSwKCQkJCXtsYWJlbCA9ICJFbXByaXNvbm5lciA4IGhldXJlcyIsIHZhbHVlID0gJ3ByaXNvbl84X2hldXJlJ30KCQkJfSwKCQl9LAoJCWZ1bmN0aW9uKGRhdGEsIG1lbnUpCgkJCW1lbnUuY2xvc2UoKQoJCQlsb2NhbCBwbGF5ZXIsIGRpc3RhbmNlID0gRVNYLkdhbWUuR2V0Q2xvc2VzdFBsYXllcigpCgoJCQlpZiBkaXN0YW5jZSB+PSAtMSBhbmQgZGlzdGFuY2UgPD0gMy4wIHRoZW4KCgoJCQkJCQlpZiBkYXRhLmN1cnJlbnQudmFsdWUgPT0gJ3ByaXNvbl8zMF9taW4nIHRoZW4KCQkJCQkJCUVTWC5UcmlnZ2VyU2VydmVyQ2FsbGJhY2soJ2VzeF9wcmlzb246aXNfaW5fcHJpc29uJywgZnVuY3Rpb24oY2IpCgkJCQkJCQkJaWYoY2I9PTApdGhlbgoKCQkJCQkJCQkJVHJpZ2dlclNlcnZlckV2ZW50KCdlc3hfcHJpc29uOnNlbmRfdG9fcHJpc29uJywnMzBfbWluJyxHZXRQbGF5ZXJTZXJ2ZXJJZChwbGF5ZXIpKQoJCQkJCQkJCWVsc2UKCQkJCQkJCQkJRVNYLlNob3dOb3RpZmljYXRpb24oJ0NldHRlIHBlcnNvbm5lIGVzdCBkw6lqw6AgZW1wcmlzb25uw6llJykKCQkJCQkJCQllbmQKCQkJCQkJICBlbmQgLEdldFBsYXllclNlcnZlcklkKHBsYXllcikpCgoJCQkJCQllbmQKCgoJCQkJCQlpZiBkYXRhLmN1cnJlbnQudmFsdWUgPT0gJ3ByaXNvbl8xX2hldXJlJyB0aGVuCgkJCQkJCQlFU1guVHJpZ2dlclNlcnZlckNhbGxiYWNrKCdlc3hfcHJpc29uOmlzX2luX3ByaXNvbicsIGZ1bmN0aW9uKGNiKQoJCQkJCQkJCWlmKGNiPT0wKXRoZW4KCgkJCQkJCQkJCVRyaWdnZXJTZXJ2ZXJFdmVudCgnZXN4X3ByaXNvbjpzZW5kX3RvX3ByaXNvbicsJzFfaGV1cmUnLEdldFBsYXllclNlcnZlcklkKHBsYXllcikpCgkJCQkJCQkJZWxzZQoJCQkJCQkJCQlFU1guU2hvd05vdGlmaWNhdGlvbignQ2V0dGUgcGVyc29ubmUgZXN0IGTDqWrDoCBlbXByaXNvbm7DqWUnKQoJCQkJCQkJCWVuZAoJCQkJCQkgIGVuZCAsR2V0UGxheWVyU2VydmVySWQocGxheWVyKSkKCQkJCQkJZW5kCgkJCQkJCWlmIGRhdGEuY3VycmVudC52YWx1ZSA9PSAncHJpc29uXzJfaGV1cmUnIHRoZW4KCQkJCQkJCUVTWC5UcmlnZ2VyU2VydmVyQ2FsbGJhY2soJ2VzeF9wcmlzb246aXNfaW5fcHJpc29uJywgZnVuY3Rpb24oY2IpCgkJCQkJCQkJaWYoY2I9PTApdGhlbgoKCQkJCQkJCQkJVHJpZ2dlclNlcnZlckV2ZW50KCdlc3hfcHJpc29uOnNlbmRfdG9fcHJpc29uJywnMl9oZXVyZScsR2V0UGxheWVyU2VydmVySWQocGxheWVyKSkKCQkJCQkJCQllbHNlCgkJCQkJCQkJCUVTWC5TaG93Tm90aWZpY2F0aW9uKCdDZXR0ZSBwZXJzb25uZSBlc3QgZMOpasOgIGVtcHJpc29ubsOpZScpCgkJCQkJCQkJZW5kCgkJCQkJCSAgZW5kICxHZXRQbGF5ZXJTZXJ2ZXJJZChwbGF5ZXIpKQoKCQkJCQkJZW5kCgkJCQkJCWlmIGRhdGEuY3VycmVudC52YWx1ZSA9PSAncHJpc29uXzRfaGV1cmUnIHRoZW4KCQkJCQkJCUVTWC5UcmlnZ2VyU2VydmVyQ2FsbGJhY2soJ2VzeF9wcmlzb246aXNfaW5fcHJpc29uJywgZnVuY3Rpb24oY2IpCgkJCQkJCQkJaWYoY2I9PTApdGhlbgoKCQkJCQkJCQkJVHJpZ2dlclNlcnZlckV2ZW50KCdlc3hfcHJpc29uOnNlbmRfdG9fcHJpc29uJywnNF9oZXVyZScsR2V0UGxheWVyU2VydmVySWQocGxheWVyKSkKCQkJCQkJCQllbHNlCgkJCQkJCQkJCUVTWC5TaG93Tm90aWZpY2F0aW9uKCdDZXR0ZSBwZXJzb25uZSBlc3QgZMOpasOgIGVtcHJpc29ubsOpZScpCgkJCQkJCQkJZW5kCgkJCQkJCQllbmQgLEdldFBsYXllclNlcnZlcklkKHBsYXllcikpCgkJCQkJCWVuZAoKCQkJCQkJaWYgZGF0YS5jdXJyZW50LnZhbHVlID09ICdwcmlzb25fOF9oZXVyZScgdGhlbgoJCQkJCQkJRVNYLlRyaWdnZXJTZXJ2ZXJDYWxsYmFjaygnZXN4X3ByaXNvbjppc19pbl9wcmlzb24nLCBmdW5jdGlvbihjYikKCQkJCQkJCQlpZihjYj09MCl0aGVuCgoJCQkJCQkJCQlUcmlnZ2VyU2VydmVyRXZlbnQoJ2VzeF9wcmlzb246c2VuZF90b19wcmlzb24nLCc4X2hldXJlJyxHZXRQbGF5ZXJTZXJ2ZXJJZChwbGF5ZXIpKQoJCQkJCQkJCWVsc2UKCQkJCQkJCQkJRVNYLlNob3dOb3RpZmljYXRpb24oJ0NldHRlIHBlcnNvbm5lIGVzdCBkw6lqw6AgZW1wcmlzb25uw6llJykKCQkJCQkJCQllbmQKCQkJCQkJCWVuZCAsR2V0UGxheWVyU2VydmVySWQocGxheWVyKSkKCSAJCQkJCWVuZAoKCQkJCQllbHNlCgkJCQkJCUVTWC5TaG93Tm90aWZpY2F0aW9uKCJJbCBuJ3kgYSBwZXJzb25uZSBhdXRvdXIgZGUgdm91cy4uLiIpCgkJCQkJZW5kCgoJCQlDdXJyZW50QWN0aW9uICAgICA9ICdwcmlzb25fbWVudScKCQkJQ3VycmVudEFjdGlvbk1zZyAgPSAnQXBwdXlleiBzdXIgfklOUFVUX0NPTlRFWFR+IHBvdXIgb3V2cmlyIGxlIG1lbnUnCgkJCUN1cnJlbnRBY3Rpb25EYXRhID0ge30KCgkJZW5kLAoJCWZ1bmN0aW9uKGRhdGEsIG1lbnUpCgkJCW1lbnUuY2xvc2UoKQoJCWVuZCkKCmVuZAoKCi0tIERpc3BsYXkgbWFya2VycwpDaXRpemVuLkNyZWF0ZVRocmVhZChmdW5jdGlvbigpCgl3aGlsZSB0cnVlIGRvCgkJV2FpdCgwKQoJCWxvY2FsIGNvb3JkcyA9IEdldEVudGl0eUNvb3JkcyhHZXRQbGF5ZXJQZWQoLTEpKQoKCQlmb3Igayx2IGluIHBhaXJzKENvbmZpZy5ab25lcykgZG8KCQkJaWYoR2V0RGlzdGFuY2VCZXR3ZWVuQ29vcmRzKGNvb3Jkcywgdi5Qb3MueCwgdi5Qb3MueSwgdi5Qb3MueiwgdHJ1ZSkgPCBDb25maWcuRHJhd0Rpc3RhbmNlKSB0aGVuCiAgICAgICAgICAgICAgICBpZiBQbGF5ZXJEYXRhLmpvYiB+PSBuaWwgYW5kIFBsYXllckRhdGEuam9iLm5hbWUgPT0gJ3BvbGljZSdhbmQgdi5Qb2xpY2UgdGhlbgogICAgICAgICAgICAgICAgICAgIERyYXdNYXJrZXIoQ29uZmlnLlR5cGUsIHYuUG9zLngsIHYuUG9zLnksIHYuUG9zLnosIDAuMCwgMC4wLCAwLjAsIDAsIDAuMCwgMC4wLAogICAgICAgICAgICAgICAgICAgIENvbmZpZy5TaXplLngsIENvbmZpZy5TaXplLnksIENvbmZpZy5TaXplLnosIENvbmZpZy5Db2xvci5yLCBDb25maWcuQ29sb3IuZywKICAgICAgICAgICAgICAgICAgICBDb25maWcuQ29sb3IuYiwgMTAwLCBmYWxzZSwgdHJ1ZSwgMiwgZmFsc2UsIGZhbHNlLCBmYWxzZSwgZmFsc2UpCiAgICAgICAgICAgICAgICBlbmQKCQkJCQkJCQlpZiBQbGF5ZXJEYXRhLmpvYiB+PSBuaWwgYW5kIG5vdCB2LlBvbGljZSAgdGhlbgoJCQkJCQkJCQkJRHJhd01hcmtlcihDb25maWcuVHlwZSwgdi5Qb3MueCwgdi5Qb3MueSwgdi5Qb3MueiwgMC4wLCAwLjAsIDAuMCwgMCwgMC4wLCAwLjAsCgkJCQkJCQkJCQlDb25maWcuU2l6ZS54LCBDb25maWcuU2l6ZS55LCBDb25maWcuU2l6ZS56LCBDb25maWcuQ29sb3IuciwgQ29uZmlnLkNvbG9yLmcsCgkJCQkJCQkJCQlDb25maWcuQ29sb3IuYiwgMTAwLCBmYWxzZSwgdHJ1ZSwgMiwgZmFsc2UsIGZhbHNlLCBmYWxzZSwgZmFsc2UpCgkJCQkJCQkJZW5kCgoJCQllbmQKCQllbmQKCgllbmQKZW5kKQoKQ2l0aXplbi5DcmVhdGVUaHJlYWQoZnVuY3Rpb24oKQoJd2hpbGUgdHJ1ZSBkbwoJCVdhaXQoMCkKCgkJbG9jYWwgY29vcmRzICAgICAgPSBHZXRFbnRpdHlDb29yZHMoR2V0UGxheWVyUGVkKC0xKSkKCQlsb2NhbCBpc0luTWFya2VyICA9IGZhbHNlCgkJbG9jYWwgY3VycmVudFpvbmUgPSBuaWwKCiAgICBmb3Igayx2IGluIHBhaXJzKENvbmZpZy5ab25lcykgZG8KICAgICAgICAgICAgaWYgUGxheWVyRGF0YS5qb2Igfj0gbmlsIGFuZCBQbGF5ZXJEYXRhLmpvYi5uYW1lID09ICdwb2xpY2UnYW5kIHYuUG9saWNlIHRoZW4KICAgICAgICAgICAgICAgIGlmKEdldERpc3RhbmNlQmV0d2VlbkNvb3Jkcyhjb29yZHMsIHYuUG9zLngsIHYuUG9zLnksIHYuUG9zLnosIHRydWUpIDwgQ29uZmlnLlNpemUueCkgdGhlbgogICAgICAgICAgICAgICAgICAgIGlzSW5NYXJrZXIgID0gdHJ1ZQogICAgICAgICAgICAgICAgICAgIGN1cnJlbnRab25lID0gawogICAgICAgICAgICAgICAgZW5kCgkJCQkJCQllbHNlCgkJCQkJCQkJaWYoR2V0RGlzdGFuY2VCZXR3ZWVuQ29vcmRzKGNvb3Jkcywgdi5Qb3MueCwgdi5Qb3MueSwgdi5Qb3MueiwgdHJ1ZSkgPCBDb25maWcuU2l6ZS54KSB0aGVuCgkJCQkJCQkJCQlpc0luTWFya2VyICA9IHRydWUKCQkJCQkJCQkJCWN1cnJlbnRab25lID0gawoJCQkJCQkJCWVuZAoJCQkJCQkJZW5kCiAgICBlbmQKCiAgICBpZiBpc0luTWFya2VyIGFuZCBub3QgaGFzQWxyZWFkeUVudGVyZWRNYXJrZXIgdGhlbgogICAgICBoYXNBbHJlYWR5RW50ZXJlZE1hcmtlciA9IHRydWUKICAgICAgbGFzdFpvbmUgICAgICAgICAgICAgICAgPSBjdXJyZW50Wm9uZQogICAgICBUcmlnZ2VyRXZlbnQoJ2VzeF9wcmlzb246aGFzRW50ZXJlZE1hcmtlcicsIGN1cnJlbnRab25lKQogICAgZW5kCgogICAgaWYgbm90IGlzSW5NYXJrZXIgYW5kIGhhc0FscmVhZHlFbnRlcmVkTWFya2VyIHRoZW4KICAgICAgaGFzQWxyZWFkeUVudGVyZWRNYXJrZXIgPSBmYWxzZQogICAgICBUcmlnZ2VyRXZlbnQoJ2VzeF9wcmlzb246aGFzRXhpdGVkTWFya2VyJywgbGFzdFpvbmUpCiAgICBlbmQKCiAgZW5kCmVuZCkKCgotLSBLZXkgQ29udHJvbHMKQ2l0aXplbi5DcmVhdGVUaHJlYWQoZnVuY3Rpb24oKQoJd2hpbGUgdHJ1ZSBkbwoJCUNpdGl6ZW4uV2FpdCgwKQoKIGlmIChDdXJyZW50QWN0aW9uIH49IG5pbCApdGhlbgoKCgkJCVNldFRleHRDb21wb25lbnRGb3JtYXQoJ1NUUklORycpCgkJCUFkZFRleHRDb21wb25lbnRTdHJpbmcoQ3VycmVudEFjdGlvbk1zZykKCQkJRGlzcGxheUhlbHBUZXh0RnJvbVN0cmluZ0xhYmVsKDAsIDAsIDEsIC0xKQoKCQkJaWYgSXNDb250cm9sSnVzdFJlbGVhc2VkKDAsIEtleXNbJ0UnXSkgYW5kIFBsYXllckRhdGEuam9iIH49IG5pbCAgdGhlbgoKCQkJCWlmIEN1cnJlbnRBY3Rpb24gPT0gJ2VudGVyX3ByaXNvbicgdGhlbgoJCQkJCQlPcGVuUHJpc29uTWVudSgpCgkJCQllbmQKCQkJCWlmIEN1cnJlbnRBY3Rpb24gPT0gJ2luZm9fcHJpc29uJyB0aGVuCgkJCQkJCUdldFBlaW5lKCkKCQkJCWVuZAoJCQkJaWYgQ3VycmVudEFjdGlvbiA9PSAndHJhdmF1eF9wcmlzb24nIHRoZW4KCQkJCQkJUmVkdWNlUGVpbmUoKQoJCQkJZW5kCgoKCQkJCUN1cnJlbnRBY3Rpb24gPSBuaWwKCgkJCWVuZAoJCWVuZAoKCQlHVUkuVGltZSA9IEdldEdhbWVUaW1lcigpCgoJZW5kCmVuZCkK