local isActive = true

local memory = require 'memory'
require "socket"
require"lib.sampfuncs"


local colors = {

	-- светлая тема
	tmpTheme1 = {
	background = 0xD9FFFFFF, -- белый цвет с 85% прозрачностью
	text = 0xff000000, -- черный цвет с 100% прозрачностью
	border = 0xff000000, -- черный цвет с 100% прозрачностью
	
	speed1 = 0x800000FF, -- синий цвет с 50% прозрачностью
	speed2 = 0x80FF00FF, -- фиолетовый цвет с 50% прозрачностью
	},
	
	-- темная тема
	tmpTheme2 = {
	background = 0xD9000000, -- черный цвет с 85% прозрачностью
	text = 0xFFFFFFFF, -- белый цвет
	border = 0xFFFFFFFF, -- белый цвет
	
	speed1 = 0x80505FFF, -- синий цвет с 50% прозрачностью
	speed2 = 0x80FF50FF, -- фиолетовый цвет с 50% прозрачностью
	},
	
	-- полупрозрачная темная тема
	tmpTheme3 = {
	background = 0x1A000000, -- черный цвет с 10% прозрачностью
	text = 0xFFFFFFFF, -- белый цвет
	border = 0xFFFFFFFF, -- белый цвет
	
	speed1 = 0x80505FFF, -- синий цвет с 50% прозрачностью
	speed2 = 0x80FF50FF, -- фиолетовый цвет с 50% прозрачностью
	}
	
}

local fonts = {
    small = renderCreateFont('Arial', 6.5, 0),
    medium = renderCreateFont('Arial', 8.125),
    large = renderCreateFont('Arial', 16.25, 0)
}


local сanvases = {
	speedometer = {
		maxSpeed 	= 160,
		width 		= 200,
		height 		= 70,
		posX 		= 1200,
		posY 		= 730,
		borderWidth = 1.1,
		color		= 0xD9FFFFFF,
		bars		= {
			speedBar = {
				minValue	= 0,
				maxValue	= 160,
				calcValue	= calculateSpeed,
				allign 		= 'center', 
				padding 	= 20,
				--width 		= 160,
				height 		= 25,
				offsetX 	= 100,
				offsetY 	= 10,
				color		= 0x80505FFF,
				ticks = {
					main = {
						milesPerTick  = 20,
						milesOffset   = 0,
						allign        = 'end',
						height        = 5,
						width         = 1,
						text          = true,
						textOffset	  = 8
					},
					secondary = {
						milesPerTick  = 20,
						milesOffset   = 10,
						allign        = 'end',
						height        = 3,
						width         = 1,
						text          = false,
						textOffset	  = false
					}
				}
			}
		}
	}
}

local labels = {
    labelOffsetY = 62
}

function main()
    repeat wait(0) until isSampAvailable()

	local theme = colors.tmpTheme1

    while true do wait(0)
        if isCharInAnyCar(playerPed) then
            renderSetRenderState(161 --[[D3DRS_MULTISAMPLEANTIALIAS]], 1)

			for _, canvas in pairs(сanvases) do
				
				--local offsetX
			
				-- отрисовка фона спидометра
				renderDrawBox(canvas.posX, canvas.posY, canvas.width, canvas.height, theme.background)
			
				for _, bar in pairs(canvas.bars) do
					
					-- отрисовка спидбара
					local width = canvas.width - (bar.padding * 2)
					local offsetX = (bar.allign == 'start' and bar.offsetX) or 
									(bar.allign == 'center' and bar.offsetX - width/2) or 
									(bar.allign == 'end' and bar.offsetX - width)
					--local offsetX = canvas.width - (canvas.width/2)
					--local offsetX = offsetX - width/2
						
					local calcVal = bar.calcValue
					local calculatedVal = calculateSpeed()
					local minValue = calculatedVal > bar.maxValue and bar.maxValue * math.floor(calculatedVal / canvas.maxSpeed) or 0
					local maxValue = minValue + bar.maxValue
						
					local barWidth = (calculatedVal - minValue) / maxValue * width
					renderDrawBox(canvas.posX + offsetX, canvas.posY + bar.offsetY, barWidth, bar.height, theme.speed1)


					-- отрисовка границ спидбара
					renderDrawLine(canvas.posX + offsetX, canvas.posY + bar.offsetY, canvas.posX + offsetX + width, canvas.posY + bar.offsetY, canvas.borderWidth, theme.border)
					renderDrawLine(canvas.posX + offsetX, canvas.posY + bar.offsetY + bar.height, canvas.posX + offsetX + width, canvas.posY + bar.offsetY + bar.height, canvas.borderWidth, theme.border)
					renderDrawLine(canvas.posX + offsetX, canvas.posY + bar.offsetY, canvas.posX + offsetX, canvas.posY + bar.offsetY + bar.height, canvas.borderWidth, theme.border)
					renderDrawLine(canvas.posX + offsetX + width, canvas.posY + bar.offsetY, canvas.posX + offsetX + width, canvas.posY + bar.offsetY + bar.height, canvas.borderWidth, theme.border)


					-- отрисовка текущей скорости			
					renderFontDrawTextEx(fonts.large, tostring(calculatedVal), canvas.posX + offsetX + width/2, canvas.posY + ((bar.height / 2)+bar.offsetY), theme.text, _, 'center', 'center')


					-- отрисовка делений и чисел под ними
					for _, tick in pairs(bar.ticks) do
						local startX = canvas.posX + bar.padding
						local startY = ((tick.allign == 'start' and 0) or 
									   (tick.allign == 'center' and bar.height / 2) or 
									   (tick.allign == 'end' and bar.height)) + canvas.posY + bar.offsetY
						local endY = startY + tick.height
						local speedBarWidth = (canvas.width - (bar.padding * 2))
						local pixelsPerMile = speedBarWidth / (canvas.maxSpeed) -- деление ширины спидбара на максимальную на нем скорость
						local pixelsOffset = tick.milesOffset * pixelsPerMile -- смещение от начала в пикселях
						local ticksSpacing = tick.milesPerTick * pixelsPerMile -- расстояние между делениями
						local numTicks = math.floor((speedBarWidth-pixelsOffset) / ticksSpacing) -- деление ширины спидбара на ширину тика
						if tick.milesPerTick then
							for i = 0, numTicks  do
								local x = startX + ticksSpacing * i + pixelsOffset
								renderDrawLine(x, startY, x, endY, tick.width, theme.text)
								if tick.text then -- отрисовка текста под(над) черточкой скорости
									local speed = tick.milesPerTick * i + tick.milesOffset + minValue
									local textY = endY + tick.textOffset
									
									renderFontDrawTextEx(fonts.small, tostring(speed), x, textY, theme.text, _, 'center', 'center') -- !! НАПИСАТЬЬ ВЫРАВНИЕ ПО ЦЕНТРУ ПО ОБЕИМ(?) ОСЯМ ЧЕРЕЗ КАСТОМНУЮ ФУНКЦИЮ РЕНДЕРА !!
								end
							end
						end
					end
						
					-- отрисовка надписи "Speed(MPH)"
					renderFontDrawTextEx(				fonts.medium,				'Speed(MPH)',				canvas.posX + canvas.width / 2,				canvas.posY + labels.labelOffsetY,				theme.text,				_, 'center', 'center')
				
				end
			end
		end
	end
end

--      'start'      'center'      'end'

-- 1 значение - одинаковый отступ со всех сторон
-- 2 значения - первое для верха и низа, второе для левой и правой сторон
-- 3 значения - первое для верха, второе для правой и левой, третье для низа
-- 4 значения - отступы по часовой стрелке: верх, правая, низ, левая

function renderFontDrawTextEx(font, text, posX, posY, color, ignoreColorTags, allignX, allignY)
    local length = renderGetFontDrawTextLength(font, text)
    local height = renderGetFontDrawHeight(font)

    if allignX == "center" then
        posX = posX - length / 2
    elseif allignX == "end" then
        posX = posX - length
    end

    if allignY == "center" then
        posY = posY - height / 2
    elseif allignY == "end" then
        posY = posY - height
    end

    return renderFontDrawText(font, text, posX, posY, color, ignoreColorTags)
end


-- примеры вызова drawStar:
-- drawStar(100, 100, 100, 5, 0xFFDD0000, 0xFFFFFFFF, 55)
-- drawStar(50, 230, 45, 7, 0xFFDD0000, 0xFFFFFFFF, 65)
-- drawStar(230, 200, 100, 4, 0xFFCC0000, 0xAAFF00FF, 65)

function calculateSpeed()
	local car = storeCarCharIsInNoSave(playerPed)
    local speedUnits = math.floor(getCarSpeed(car) * 2)
	
	return speedUnits
end как я могу улучшить этот код?