function RandomBool()
    return math.random(0, 1)
end

function RandomTableSort(t)
    table_size = table.getn(t)
    for i = 1, table_size, 1 do
        ind1 = math.random(1, table_size)
        ind2 = math.random(1, table_size)
        tmp = t[ind1]
        t[ind1] = t[ind2]
        t[ind2] = tmp
    end
end

function CEntity:Move(dx, dy, time)
    -- TODO: Need using adopt policy
    local af = CreateAnimationEffector()--AnimationEffector()
    af:AttachTo(self)
    af:SetKey(_TRACK_X, 0.0, self:GetX())
    af:SetKey(_TRACK_Y, 0.0, self:GetY())
    af:SetKey(_TRACK_X, time, self:GetX() + dx)
    af:SetKey(_TRACK_Y, time, self:GetY() + dy)
    af:Play()
end

function CEntity:Rotate(dangle, time)
    local af = CreateAnimationEffector()--AnimationEffector()
    af:AttachTo(self)
    af:SetKey(_TRACK_A, 0.0, self:GetAngle())
    af:SetKey(_TRACK_A, time, self:GetAngle() + dangle)
    af:Play()
end

function CEntity:ChangeOpacity(start, finish, time)
    local af = CreateAnimationEffector()--AnimationEffector()
    af:AttachTo(self)
    af:SetKey(_TRACK_O, 0.0, start)
    af:SetKey(_TRACK_O, time, finish)
    af:Play()
end

function CreateCloseButton(pos, message, listener, parent)
    local up = CreateAnimation('data/Texture/GUI/Zoom/Close.png',0,0,44,38,1,0)
	up:SetHotSpot(22,19);
    local over = CreateAnimation('data/Texture/GUI/Zoom/Close.png',0,38,44,38,1,0)
    over:SetHotSpot(22,19);
    local down = CreateAnimation('data/Texture/GUI/Zoom/Close.png',0,76,44,38,1,0)
    down:SetHotSpot(22,19);
	local button = CreateButton(up, over, down, message, listener)
	button:AttachTo(parent)
	button:SetX(pos.x)
	button:SetY(pos.y)
	button:SetZ(500)
	--button:SetRect(-17, -14, 34, 28)
    return button
end

--////////////////////////////////////////////////////////////////////////////////////////////////////////
function AddMiniGamesGUI(screen)
	GUI_Z = 100000;
	
	SKIP_START_TIME = 0.4;
	
	play_field:GetLevelScreen():GetPanel():Stop();
	play_field:SetEnabled(false);
		
	minigames_gui = {};
	minigames_gui.screen = screen;
	minigames_gui.skip_flag = false;
	minigames_gui.anim_skip = nil;
	minigames_gui.segment_amount = 0;
	minigames_gui.skip_time = SKIP_DELAY_TIME / 73;
	
	TimerDoString("minigames_gui.screen:Stop()", SKIP_START_TIME, minigames_gui.screen:GetTimer());
	TimerDoString("load_screen('data/Lua/Screens/DialogMiniGameHelp.lua')", SKIP_START_TIME, minigames_gui.screen:GetTimer());
	
	--менюшка
	local anim = CreateAnimation('data/Texture/GUI/MiniGames/win.png',0,0,166,197,1,0)
	minigames_gui.screen:CreateObject('win',anim,858,0,GUI_Z,0,1,1)
	--шкала
	local anim = CreateAnimation('data/Texture/GUI/MiniGames/st.png',0,0,69,69,1,0)
	minigames_gui.screen:CreateObject('st',anim,893,14,GUI_Z + 200,0,1,1)
	-------------------------------------------------------------------------------------------
	
	ShowGameHelpButton(minigames_gui.screen);
	
	--кнопка Down
	local up = CreateAnimation('data/Texture/GUI/MiniGames/done.png',0,0,71,46,1,0)
	local over = CreateAnimation('data/Texture/GUI/MiniGames/done.png',0,46,71,46,1,0)
	local down = CreateAnimation('data/Texture/GUI/MiniGames/done.png',0,92,71,46,1,0)
	local ButtonDown = CreateButton(up, over, down, "Down", screen)
	ButtonDown:AttachTo(screen);
	ButtonDown:SetOpacity(0.0);
	ButtonDown:SetXY(-100, -100);
	ButtonDown:SetZ(GUI_Z + 205);
	minigames_gui.button_down = ButtonDown;
	-------------------------------------------------------------------------------------------

	--кнопка Skip
	
	local shadow = CreateAnimation('data/Texture/GUI/MiniGames/skip1.png',0,0,43,17,1,0)
	minigames_gui.skip_shadow = minigames_gui.screen:CreateObject('shadow', shadow,907,39,GUI_Z + 201,0,1,1)
	
	TimerDo(minigames_gui.screen:GetTimer(), SKIP_START_TIME + 0.1, StartSkipInit)
	
	minigames_gui.skip_pause = false;
	-------------------------------------------------------------------------------------------
end

function StartSkipInit()
	ShowSkipButton(minigames_gui.screen:GetTimer(), 0, 0);
end

function ShowGameHelpButton(screen)
	--кнопка Help
	local up = CreateAnimation('data/Texture/GUI/MiniGames/help.png',  0,0, 77,47,1,0)
	local over = CreateAnimation('data/Texture/GUI/MiniGames/help.png',0,47,77,47,1,0)
	local down = CreateAnimation('data/Texture/GUI/MiniGames/help.png',0,94,77,47,1,0)
	minigames_gui.button_help = CreateButton(up, over, down, "MiniGameHelp", screen)
	minigames_gui.button_help:AttachTo(screen);
	minigames_gui.button_help:SetXY(941, 121);
	minigames_gui.button_help:SetZ(GUI_Z + 4);
	-------------------------------------------------------------------------------------------
end

function SkipCheat()
	if minigames_gui ~= nil and GetGameApp():AreCheatsEnabled() and minigames_gui.skip_pause == false then
		minigames_gui.skip_time = 0;
	end
end

function ShowSkipButton(timer, global_height, cur_height)
	local SEGMENT_AMOUNT = 50;
	if(cur_height < SEGMENT_AMOUNT and minigames_gui.skip_flag == false) then
		if(minigames_gui.skip_pause == false) then
			local anim = CreateAnimation('data/Texture/GUI/MiniGames/poloska1.png',0,0,4,16,1,0)
			anim:SetHotSpot(6,35)
			minigames_gui.screen:CreateObject('strelka_'..cur_height,anim,928,48,GUI_Z + cur_height + 1,0,1,1)
			minigames_gui.screen:GetObject('strelka_'..cur_height):SetAngle(-M_PI / 25 * cur_height);

			cur_height = cur_height + 1;
			minigames_gui.segment_amount =minigames_gui.segment_amount + 1; 
		end
		TimerDo(timer, minigames_gui.skip_time, ShowSkipButton, timer, global_height, cur_height)
	elseif(minigames_gui.skip_flag == false) then
		ActiveSkipButton();
	end
end

function HideMiniGameGUI()
	--HideSkipButton();
	--HideHelpButton();
	
	minigames_gui.skip_shadow:SetVisible(false);
	
	local HIDE_TIME = 0.3;
	
	if(minigames_gui.skip ~= nil) then
		minigames_gui.skip:SetVisible(false);
		minigames_gui.skip:SetEnabled(false);
	end
	
	if(minigames_gui.button_help ~= nil) then
		minigames_gui.button_help:SetVisible(false);
		minigames_gui.button_help:SetEnabled(false);
	end

	minigames_gui.screen:GetObject('win'):ChangeOpacity(1.0, 0.0, HIDE_TIME);
	minigames_gui.screen:GetObject('st'):ChangeOpacity(1.0, 0.0, HIDE_TIME);
	minigames_gui.skip_flag = true;
	local SEGMENT_AMOUNT = 50;
	for i = 0, minigames_gui.segment_amount - 1 do
		minigames_gui.screen:GetObject('strelka_'..i):ChangeOpacity(1.0, 0.0, HIDE_TIME);
	end
end

function HideHelpButton()
	if(minigames_gui.button_help ~= nil) then
		minigames_gui.button_help:SetVisible(false);
		minigames_gui.button_help:SetEnabled(false);
	end
end

function HideSkipButton()
	if(minigames_gui.skip == nil)then
		ActiveSkipButton();
	end

	minigames_gui.skip:SetVisible(false);
	minigames_gui.skip:SetEnabled(false);
end

function HideDoneButton()
	if(minigames_gui.button_down ~= nil) then
		minigames_gui.button_down:SetVisible(false);
		minigames_gui.button_down:SetEnabled(false);
	end
end

function ActiveSkipButton()
	if(minigames_gui ~= nil) then
		minigames_gui.skip_shadow:SetVisible(false);
		
		local up =   CreateAnimation('data/Texture/GUI/MiniGames/skip.png', 0,0,72,48,1,0)
		local over = CreateAnimation('data/Texture/GUI/MiniGames/skip.png',	0,48,72,48,1,0)
		local down = CreateAnimation('data/Texture/GUI/MiniGames/skip.png',	0,96,72,48,1,0)
		local ButtonSkip = CreateButton(up, over, down, "Skip", minigames_gui.screen)
		ButtonSkip:AttachTo(minigames_gui.screen);
		ButtonSkip:SetXY(892, 23);
		ButtonSkip:SetZ(GUI_Z + 202);
		minigames_gui.skip = ButtonSkip;
		
		minigames_gui.skip:SetEnabled(false);
		local af = CreateAnimationEffector()        
		af:AttachTo(minigames_gui.skip);
		af:SetMode(_ANIM_FWD);
		af:SetKey(_TRACK_O, 0.0, 0.0);
		af:SetKey(_TRACK_O, 1.0, 1.0);
		af:Play();
		TimerDo(minigames_gui.screen:GetTimer(), 1.0, EnabledSkipButton);
	end
end

function ShowDoneButton()
	HideMiniGameGUI();
	--разкоментить если надо будет кнопка Done
	--[[minigames_gui.button_down:SetXY(893, 24);
	minigames_gui.button_down:SetEnabled(false);
	local af = CreateAnimationEffector()        
	af:AttachTo(minigames_gui.button_down);
	af:SetMode(_ANIM_FWD);
	af:SetKey(_TRACK_O, 0.0, 0.0);
	af:SetKey(_TRACK_O, 1.0, 1.0);
	af:Play();
	
	TimerDo(minigames_gui.screen:GetTimer(), 1.0, EnabledDoneButton);]]
	
	FinishDialog();
end

function EnabledDoneButton()
	minigames_gui.button_down:SetEnabled(true);
end

function EnabledSkipButton()
	minigames_gui.skip:SetEnabled(true);
end

function OnMiniGameButtonPress(title)
   --[[ if title == "Down" then   
		HideDoneButton();
        FinishDialog();
    end]]
    if title == "Menu" then   
		 minigames_gui.screen:Stop();
         load_screen('data/Lua/Screens/OptionsInGame.lua');
    end
    if title == "Skip" then
		HideSkipButton();
		local Time = SkipMiniGame();
		minigames_gui.skip_flag = true;
		if(Time >= -1) then
			HideMiniGameGUI();
			GTimerDoString('FinishDialog()', Time);
		end
		--GTimerDoString('ShowDoneButton()', Time);
    end
	if title == "MiniGameHelp" then  
		minigames_gui.screen:Stop();
		load_screen("data/Lua/Screens/DialogMiniGameHelp.lua")
    end
end


function FinishDialog()
	if(game_state.finish_dialog ~= nil) then
		game_state.finish_dialog.Start();
	else
		OnCompletedGame();
	end
end

function OnCompletedGame()
    game_state.timer:Clear()
    game_state.screen:ScreenDestroy()    
    game_state = play_field.game_state
    play_field:GainFocus()
    play_field:GetLevelScreen():GetPanel():Go();
    play_field:SetEnabled(true);
    minigames_gui = nil;
    
    if(OnMinigameCompleted ~= nil) then
        game_state.do_not_load_mini_game = true
        OnSceneStateChanged(play_field)
		OnMinigameCompleted();
	end
end

function OnMinigameComicsShown(comics1)
    comics1.proceed:Show()
    game_state.locker:AddRef()
end

--////////////////////////////////////////////////////////////////////////////////////////////////////////

function CreateNextButton(pos, message, listener)
	local button = CreateButton('ButtonNextUp',
								'ButtonNextOver',
								'ButtonNextDown',
								listener)
	button:AttachTo(play_field)
	button:SetX(pos.x)
	button:SetY(pos.y)
	button:SetZ(220)
	--button:SetRect(-17, -14, 34, 28)
    return button
end

function Vector:__tostring()
    return 'X: '..self.x..' Y: '..self.y
end

function CGameObject:__tostring()
    local str = 'Name: '..self:GetName().." X: "..self:GetX().." Y: "..self:GetY().." Z: "..self:GetZ().." Layer: "..self:GetLayer().." Angle: "..self:GetAngle()
    if self:GetAnimation():GetFrames() > 0 then
        str = str..' NFrames: '..self:GetAnimation():GetFrames()
    end
    str = str..' Color:'..tostring(self:GetAnimation():GetColorStr())
    return str
end

function Task:__tostring()
    return 'Text singular: '..self:GetTextSingular()
end

function vector_string:__tostring()
    return 'vector_string: '..self:size()
end

function GetAnimationLength(anim)
    assert(anim:GetSpeed() ~= 0.)
    return anim:GetFrames() / anim:GetSpeed()
end

function deepcopy(object)
    local lookup_table = {}
    local function _copy(object)
        if type(object) ~= "table" then
            return object
        elseif lookup_table[object] then
            return lookup_table[object]
        end
        local new_table = {}
        lookup_table[object] = new_table
        for index, value in pairs(object) do
            new_table[_copy(index)] = _copy(value)
        end
        return setmetatable(new_table, getmetatable(object))
    end
    return _copy(object)
end

function Size(w, h)
    local size = {}
    size.w = w
    size.h = h
    return size
end

function CScreenEx:__tostring()
    return self.GetName();
end

function MegoLightEffector()
    -- Layer MegoLight
    local effector = CreateAnimationEffector();
    effector:SetLifeTime(0, 6.56);
    effector:SetMode(_ANIM_LOOP);
    
    effector:SetKey(_TRACK_O, 0, 1);
    effector:SetKey(_TRACK_O, 0.04, 0.73423561480214);
    effector:SetKey(_TRACK_O, 0.0714453125, 1);
    effector:SetKey(_TRACK_O, 0.214296875, 1);
    effector:SetKey(_TRACK_O, 0.24, 0.90011838279464);
    effector:SetKey(_TRACK_O, 0.285703125, 1);
    effector:SetKey(_TRACK_O, 0.32, 0.9805644411393);
    effector:SetKey(_TRACK_O, 0.3571484375, 1);
    effector:SetKey(_TRACK_O, 0.48, 0.99999999643326);
    effector:SetKey(_TRACK_O, 0.52, 0.90386943545711);
    effector:SetKey(_TRACK_O, 0.5714453125, 1);
    effector:SetKey(_TRACK_O, 0.6428515625, 1);
    effector:SetKey(_TRACK_O, 0.68, 0.98434689294222);
    effector:SetKey(_TRACK_O, 0.714296875, 1);
    effector:SetKey(_TRACK_O, 0.76, 1);
    effector:SetKey(_TRACK_O, 0.8, 0.93540234133294);
    effector:SetKey(_TRACK_O, 0.84, 1);
    effector:SetKey(_TRACK_O, 0.88, 0.86698422081345);
    effector:SetKey(_TRACK_O, 0.9285546875, 1);
    effector:SetKey(_TRACK_O, 1, 1);
    effector:SetKey(_TRACK_O, 1.04, 0.90461958078056);
    effector:SetKey(_TRACK_O, 1.0714453125, 1);
    effector:SetKey(_TRACK_O, 1.16, 1);
    effector:SetKey(_TRACK_O, 1.2, 0.95833078063641);
    effector:SetKey(_TRACK_O, 1.24, 1);
    effector:SetKey(_TRACK_O, 1.28, 0.95334517697445);
    effector:SetKey(_TRACK_O, 1.3571484375, 1);
    effector:SetKey(_TRACK_O, 1.4285546875, 1);
    effector:SetKey(_TRACK_O, 1.48, 0.89434635593109);
    effector:SetKey(_TRACK_O, 1.5, 1);
    effector:SetKey(_TRACK_O, 1.5714453125, 1);
    effector:SetKey(_TRACK_O, 1.6, 0.95334518140708);
    effector:SetKey(_TRACK_O, 1.6428515625, 1);
    effector:SetKey(_TRACK_O, 1.68, 0.79366905942034);
    effector:SetKey(_TRACK_O, 1.714296875, 1);
    effector:SetKey(_TRACK_O, 1.76, 1);
    effector:SetKey(_TRACK_O, 1.8, 0.87545675366773);
    effector:SetKey(_TRACK_O, 1.8571484375, 1);
    effector:SetKey(_TRACK_O, 1.88, 0.90647931143558);
    effector:SetKey(_TRACK_O, 1.9285546875, 1);
    effector:SetKey(_TRACK_O, 1.96, 0.88110552865302);
    effector:SetKey(_TRACK_O, 2, 1);
    effector:SetKey(_TRACK_O, 2.04, 0.91012865280471);
    effector:SetKey(_TRACK_O, 2.0714453125, 1);
    effector:SetKey(_TRACK_O, 2.12, 1);
    effector:SetKey(_TRACK_O, 2.16, 0.98473982244643);
    effector:SetKey(_TRACK_O, 2.214296875, 1);
    effector:SetKey(_TRACK_O, 2.24, 0.93284967358106);
    effector:SetKey(_TRACK_O, 2.285703125, 1);
    effector:SetKey(_TRACK_O, 2.32, 0.9793423929897);
    effector:SetKey(_TRACK_O, 2.3571484375, 1);
    effector:SetKey(_TRACK_O, 2.4, 0.9072868003665);
    effector:SetKey(_TRACK_O, 2.4285546875, 1);
    effector:SetKey(_TRACK_O, 2.48, 1);
    effector:SetKey(_TRACK_O, 2.52, 0.92536451796441);
    effector:SetKey(_TRACK_O, 2.5714453125, 1);
    effector:SetKey(_TRACK_O, 2.68, 1);
    effector:SetKey(_TRACK_O, 2.72, 0.81098983140725);
    effector:SetKey(_TRACK_O, 2.76, 0.98864848001498);
    effector:SetKey(_TRACK_O, 2.8, 0.9528741070149);
    effector:SetKey(_TRACK_O, 2.8571484375, 1);
    effector:SetKey(_TRACK_O, 2.9285546875, 1);
    effector:SetKey(_TRACK_O, 2.96, 0.88925925065851);
    effector:SetKey(_TRACK_O, 3, 1);
    effector:SetKey(_TRACK_O, 3.04, 0.88925925417056);
    effector:SetKey(_TRACK_O, 3.0714453125, 1);
    effector:SetKey(_TRACK_O, 3.12, 0.96675283070009);
    effector:SetKey(_TRACK_O, 3.1428515625, 1);
    effector:SetKey(_TRACK_O, 3.214296875, 1);
    effector:SetKey(_TRACK_O, 3.24, 0.91219694032715);
    effector:SetKey(_TRACK_O, 3.285703125, 1);
    effector:SetKey(_TRACK_O, 3.32, 1);
    effector:SetKey(_TRACK_O, 3.36, 0.9651135803383);
    effector:SetKey(_TRACK_O, 3.4285546875, 1);
    effector:SetKey(_TRACK_O, 3.48, 1);
    effector:SetKey(_TRACK_O, 3.52, 0.81239613720518);
    effector:SetKey(_TRACK_O, 3.5714453125, 1);
    effector:SetKey(_TRACK_O, 3.714296875, 1);
    effector:SetKey(_TRACK_O, 3.76, 0.88648496661405);
    effector:SetKey(_TRACK_O, 3.785703125, 1);
    effector:SetKey(_TRACK_O, 3.8571484375, 1);
    effector:SetKey(_TRACK_O, 3.88, 0.81976590168044);
    effector:SetKey(_TRACK_O, 3.9285546875, 1);
    effector:SetKey(_TRACK_O, 3.96, 0.92305045149346);
    effector:SetKey(_TRACK_O, 4, 1);
    effector:SetKey(_TRACK_O, 4.04, 0.99999998432008);
    effector:SetKey(_TRACK_O, 4.08, 0.88685338588924);
    effector:SetKey(_TRACK_O, 4.12, 1);
    effector:SetKey(_TRACK_O, 4.16, 0.86121680917924);
    effector:SetKey(_TRACK_O, 4.214296875, 1);
    effector:SetKey(_TRACK_O, 4.28, 1);
    effector:SetKey(_TRACK_O, 4.32, 0.96469752288374);
    effector:SetKey(_TRACK_O, 4.3571484375, 1);
    effector:SetKey(_TRACK_O, 4.4, 0.97125654131964);
    effector:SetKey(_TRACK_O, 4.4285546875, 1);
    effector:SetKey(_TRACK_O, 4.48, 1);
    effector:SetKey(_TRACK_O, 4.52, 0.91110497042904);
    effector:SetKey(_TRACK_O, 4.5714453125, 1);
    effector:SetKey(_TRACK_O, 4.714296875, 1);
    effector:SetKey(_TRACK_O, 4.76, 0.78246823565464);
    effector:SetKey(_TRACK_O, 4.785703125, 1);
    effector:SetKey(_TRACK_O, 4.84, 1);
    effector:SetKey(_TRACK_O, 4.88, 0.93372821490669);
    effector:SetKey(_TRACK_O, 4.9285546875, 1);
    effector:SetKey(_TRACK_O, 4.96, 0.88335183144287);
    effector:SetKey(_TRACK_O, 5, 1);
    effector:SetKey(_TRACK_O, 5.04, 0.97306154354038);
    effector:SetKey(_TRACK_O, 5.0714453125, 1);
    effector:SetKey(_TRACK_O, 5.12, 1);
    effector:SetKey(_TRACK_O, 5.16, 0.8527871779432);
    effector:SetKey(_TRACK_O, 5.2, 1);
    effector:SetKey(_TRACK_O, 5.24, 0.89442471833603);
    effector:SetKey(_TRACK_O, 5.285703125, 1);
    effector:SetKey(_TRACK_O, 5.32, 0.94438705380508);
    effector:SetKey(_TRACK_O, 5.3571484375, 1);
    effector:SetKey(_TRACK_O, 5.4285546875, 1);
    effector:SetKey(_TRACK_O, 5.48, 0.95733118195582);
    effector:SetKey(_TRACK_O, 5.5, 1);
    effector:SetKey(_TRACK_O, 5.56, 0.94267273434959);
    effector:SetKey(_TRACK_O, 5.6, 0.99999999954505);
    effector:SetKey(_TRACK_O, 5.76, 1);
    effector:SetKey(_TRACK_O, 5.8, 0.9313411429224);
    effector:SetKey(_TRACK_O, 5.8571484375, 1);
    effector:SetKey(_TRACK_O, 6, 1);
    effector:SetKey(_TRACK_O, 6.04, 0.90708513600764);
    effector:SetKey(_TRACK_O, 6.0714453125, 1);
    effector:SetKey(_TRACK_O, 6.12, 0.93094210115203);
    effector:SetKey(_TRACK_O, 6.1428515625, 1);
    effector:SetKey(_TRACK_O, 6.214296875, 1);
    effector:SetKey(_TRACK_O, 6.24, 0.95189188083734);
    effector:SetKey(_TRACK_O, 6.285703125, 1);
    effector:SetKey(_TRACK_O, 6.32, 1);
    effector:SetKey(_TRACK_O, 6.36, 0.74701939137211);
    effector:SetKey(_TRACK_O, 6.4, 1);
    --[[
    effector:SetKey(_TRACK_O, 0.0, 0.0);
	effector:SetKey(_TRACK_O, 1.0, 1.0);
	effector:SetKey(_TRACK_O, 2.0, 0.0);]]

    return effector;
end


function setFibrillationEffector(gameObject, timeOffset)
	eff = MegoLightEffector()
	eff:AttachTo(gameObject);
	eff:PlayAt(timeOffset)
end

--[[function setFibrillationEffector(gameObject, duration)
	eff= CreateAnimationEffector();
	eff:AttachTo(gameObject);
	eff:SetMode(_ANIM_LOOP);

	eff:SetKey(_TRACK_O, 0.0, 1.0);
	eff:SetKey(_TRACK_O, duration *1.0/4.0, 0.90);
	eff:SetKey(_TRACK_O, duration *2.0/4.0, 1.0);
	eff:SetKey(_TRACK_O, duration *3.0/4.0, 0.85);
	eff:SetKey(_TRACK_O, duration *4.0/4.0, 1.0);
	eff:Play();
end]]

-- функция создает эффектор для покачивания (перемещение по оси Х)
function SwayObjectByX(objName, amplitude, time)
    local swayObj = play_field:GetObject( objName )
    
    local af = CreateAnimationEffector()
    af:AttachTo(swayObj)
    af:SetMode(_ANIM_FWD + _ANIM_LOOP);
    
    local x = swayObj:GetX()
    local n = 20;
    for i=0, n do
         af:SetKey( _TRACK_X, time * i/n, x + math.sin(M_TWO_PI * i/n)*amplitude );
    end
    
    af:Play();
end

-- функция создает эффектор для покачивания (поворот)
function SwayObjectByAngle(objName, amplitude, time)
    local swayObj = play_field:GetObject( objName )
    
    local af = CreateAnimationEffector()
    af:AttachTo(swayObj)
    af:SetMode(_ANIM_FWD + _ANIM_LOOP);
    
    amplitude = amplitude * M_PI / 180;
    local angle = swayObj:GetAngle()
    local n = 20;
    for i=0, n do
         af:SetKey( _TRACK_A, time * i/n, angle + math.sin(M_TWO_PI * i/n)*amplitude );
    end
    
    af:Play();
end

function GetProperCoordsForPuzzlePiece(x, y)
    local dx, dy = (1024 - x), y
	local r = math.sqrt(dx ^ 2 + dy ^ 2)
    local a = math.atan(dy / dx)
   
	local resX, resY = 1024 - 200 * math.cos(a), 200 * math.sin(a)
    return resX, resY
end

function CheckPuzzlePiecePos(DragObject)
    local r = math.sqrt((1024 - GetMouseX()) ^ 2 + GetMouseY() ^ 2)
    if DragObject and r < 200 then
        local ga = GetGameApp()
		local valX, valY = GetProperCoordsForPuzzlePiece(GetMouseX(), GetMouseY())
        ga:SetSystemMousePosEnabled(false)
        
		ga:SetMousePos(Vector(valX, valY))        
		return true
    end
	return false
end