```lua
local sampev = require 'lib.samp.events' -- TramBot by Tectrex
local imgui = require 'imgui'
local encoding = require 'encoding'
encoding.default = 'CP1251'
local u8 = encoding.UTF8

-- Функция для имитации нажатия клавиши
local function pressKey(key, duration)
    setGameKeyState(key, 255)
    wait(0)
    setGameKeyState(key, 0)
    wait(duration)
end

-- Главная таблица бота TramBot
local TramBot = {
    isActive = false,
    station = 0,
    completedRoutes = 0,
    steps = {
        {'RUNFIX', -2094.7727050781, 515.27862548828, 1487.6927490234},
        {'RUNFIX', -2099.2482910156, 511.8908996582, 1487.6927490234},
        {'RUNHAVKA', -2097.4533691406, 512.04766845703, 1487.6927490234},
        {'EAT'},
        {'RUNREYS', -2102.4099121094, 512.92535400391, 1487.6927490234},
        {'TAKEREYS'}
    },
    stationTimes = {},
    autoEat = true,
    eatAfterRoutes = 1,
    isFree = false,
    logs = {} -- Таблица для хранения логов
}

-- Переключение состояния бота
function TramBot:toggle()
    self.isActive = not self.isActive
    table.insert(self.logs, os.date('%H:%M:%S') .. ' - TramBot ' .. (self.isActive and 'активирован' or 'деактивирован'))
    printStringNow('~p~Tram BOT: ' .. (self.isActive and '~G~ON' or '~r~OFF'), 2000)
    if self.isActive then
        self:generateStationTimes()
    end
end

-- Генерация времени остановок на станциях
function TramBot:generateStationTimes()
    local totalTime = 180000 -- общее время ожидания в миллисекундах
    self.stationTimes = {}
    local remainingTime = totalTime

    for i = 1, 4 do
        local maxTime = math.floor(remainingTime / (5 - i))
        local time = math.random(math.floor(maxTime * 0.8), maxTime) -- добавление вариативности
        table.insert(self.stationTimes, time)
        remainingTime = remainingTime - time
    end

    table.insert(self.stationTimes, remainingTime)
    table.insert(self.logs, os.date('%H:%M:%S') .. ' - Генерация времени остановок завершена')
end

-- Обработка логики внутри транспорта
function TramBot:handleInCar()
    local hasMarker, markerX, markerY, markerZ = self:searchMarker()
    if not hasMarker then return end

    local playerX, playerY, playerZ = getCharCoordinates(PLAYER_PED)
    local distance = getDistanceBetweenCoords3d(playerX, playerY, playerZ, markerX, markerY, markerZ)
    local car = storeCarCharIsInNoSave(PLAYER_PED)

    if car then
        setTrainSpeed(car, distance > 1 and 24.0 or 0.0)
    end

    if distance <= 1 then
        self.station = self.station + 1
        if self.station >= #self.steps then
            self.station = 0
            self.completedRoutes = self.completedRoutes + 1
            table.insert(self.logs, os.date('%H:%M:%S') .. ' - Рейс завершен. Всего рейсов: ' .. self.completedRoutes)
            printStringNow('Route done. Routes completed: ' .. self.completedRoutes, 6000)
        else
            local waitTime = self.stationTimes[self.station] or 1000
            table.insert(self.logs, string.format(os.date('%H:%M:%S') .. ' - Станция: %d / Время ожидания: %d секунд', self.station, waitTime / 1000))
            printStringNow(string.format('Station: %d / Wait time: %d seconds', self.station, waitTime / 1000), 1000)
            wait(waitTime)
        end
    end
end

-- Обработка логики на ногах
function TramBot:handleOnFoot()
    self.station = 0
    for _, step in ipairs(self.steps) do
        local action, x, y, z = table.unpack(step)
        if action == 'EAT' then
            if self.autoEat and self.completedRoutes % self.eatAfterRoutes == 0 then
                self:eat()
            end
        elseif action == 'TAKEREYS' then
            if self.isFree then
                self:takeReys()
            end
        else
            self:moveToCoordinates(x, y, z)
        end
    end
end

-- Функция автоеды
function TramBot:eat()
    pressKey(21, 300)
    sampSendDialogResponse(sampGetCurrentDialogId(), 1, 3, '')
    wait(2000)
    table.insert(self.logs, os.date('%H:%M:%S') .. ' - Выполнена автоеда')
end

-- Функция для принятия рейсов
function TramBot:takeReys()
    while not isCharInAnyCar(PLAYER_PED) and self.isActive do
        pressKey(21, 100)
        sampSendDialogResponse(sampGetCurrentDialogId(), 1, 0, '')
        wait(500)
    end
    table.insert(self.logs, os.date('%H:%M:%S') .. ' - Принят рейс')
end

-- Поиск ближайшей метки
function TramBot:searchMarker()
    for id = 0, 31 do
        local markerStruct = 0xC7F168 + id * 56
        local markerPosX = representIntAsFloat(readMemory(markerStruct, 4, false))
        if markerPosX ~= 0.0 then
            local markerPosY = representIntAsFloat(readMemory(markerStruct + 4, 4, false))
            local markerPosZ = representIntAsFloat(readMemory(markerStruct + 8, 4, false))
            return true, markerPosX, markerPosY, markerPosZ
        end
    end
    return false, 0.0, 0.0, 0.0
end

-- Перемещение персонажа к координатам
function TramBot:moveToCoordinates(px, py, pz)
    local step = 1.0
    local x, y, z = getCharCoordinates(PLAYER_PED)
    while getDistanceBetweenCoords3d(px, py, pz, x, y, z) > step do
        if not self.isActive then return end

        local distance = getDistanceBetweenCoords3d(px, py, pz, x, y, z)
        local dx, dy, dz = (px - x) / distance, (py - y) / distance, (pz - z) / distance
        x = x + dx * step
        y = y + dy * step
        z = z + dz * step

        setCharCoordinates(PLAYER_PED, x, y, z)
        wait(100)
    end

    setCharCoordinates(PLAYER_PED, px, py, pz)
    table.insert(self.logs, os.date('%H:%M:%S') .. ' - Переместился к координатам (' .. px .. ', ' .. py .. ', ' .. pz .. ')')
end

-- Инициализация стиля imgui (выполняется один раз)
local function apply_custom_style()
    local style = imgui.GetStyle()
    local colors = style.Colors
    local clr = imgui.Col
    local ImVec4 = imgui.ImVec4

    style.WindowRounding = 8.0
    style.FrameRounding = 5.0
    style.ScrollbarSize = 12.0
    style.WindowTitleAlign = imgui.ImVec2(0.5, 0.5)
    style.ChildWindowRounding = 5.0
    style.FramePadding = imgui.ImVec2(8, 8)
    style.ItemSpacing = imgui.ImVec2(10.0, 10.0)

    colors[clr.WindowBg] = ImVec4(0.05, 0.05, 0.05, 0.95)
    colors[clr.TitleBg] = ImVec4(0.2, 0.2, 0.2, 1.0)
    colors[clr.TitleBgActive] = ImVec4(0.3, 0.3, 0.3, 1.0)
    colors[clr.Button] = ImVec4(0.1, 0.1, 0.1, 1.0)
    colors[clr.ButtonHovered] = ImVec4(0.2, 0.2, 0.2, 1.0)
    colors[clr.ButtonActive] = ImVec4(0.3, 0.3, 0.3, 1.0)
    colors[clr.FrameBg] = ImVec4(0.1, 0.1, 0.1, 1.0)
    colors[clr.FrameBgHovered] = ImVec4(0.2, 0.2, 0.2, 1.0)
    colors[clr.FrameBgActive] = ImVec4(0.3, 0.3, 0.3, 1.0)
    colors[clr.CheckMark] = ImVec4(0.0, 0.5, 0.0, 1.0)
    colors[clr.Header] = ImVec4(0.2, 0.2, 0.2, 1.0)
    colors[clr.HeaderHovered] = ImVec4(0.3, 0.3, 0.3, 1.0)
    colors[clr.HeaderActive] = ImVec4(0.4, 0.4, 0.4, 1.0)
end

apply_custom_style()

-- Интерфейс с imgui
local showWindow = imgui.ImBool(false)
local eatAfterRoutes = imgui.ImInt(TramBot.eatAfterRoutes)
local tabNames = { 'Основные', 'Настройки', 'Логи' }

function imgui.OnDrawFrame()
    if showWindow.v then
        -- Полупрозрачный затемнённый фон
        imgui.GetBackgroundDrawList():AddRectFilled(
            imgui.GetMainViewport().Pos,
            imgui.GetMainViewport().Pos + imgui.GetMainViewport().Size,
            imgui.ImColor(0, 0, 0, 150)
        )

        imgui.SetNextWindowPos(imgui.GetMainViewport().Pos + imgui.ImVec2(
            (imgui.GetMainViewport().Size.x - 400) / 2,
            (imgui.GetMainViewport().Size.y - 600) / 2
        ), imgui.Cond.FirstUseEver)
        imgui.SetNextWindowSize(imgui.ImVec2(400, 600), imgui.Cond.FirstUseEver)

        if imgui.Begin('TramBot By Tectrex', showWindow, imgui.WindowFlags.NoResize + imgui.WindowFlags.NoCollapse + imgui.WindowFlags.NoScrollbar) then
            -- Вкладки
            if imgui.BeginTabBar('Tabs') then
                for i, tab in ipairs(tabNames) do
                    if imgui.BeginTabItem(tab) then
                        currentTab = i
                        if i == 1 then
                            -- Основные
                            imgui.PushStyleVar(imgui.StyleVar.FramePadding, imgui.ImVec2(10, 10))
                            if imgui.Button(u8 'Включить TramBot', imgui.ImVec2(350, 50)) then
                                TramBot:toggle()
                            end
                            imgui.PopStyleVar()

                            imgui.Separator()
                            imgui.Text('TramBot ' .. (TramBot.isActive and u8 'Активен' or u8 'Неактивен'))

                            if TramBot.isActive then
                                imgui.Text(string.format(u8 'Текущая станция: %d', TramBot.station))
                                if TramBot.station <= #TramBot.stationTimes then
                                    local waitTime = TramBot.stationTimes[TramBot.station] or 0
                                    imgui.Text(string.format(u8 'Время ожидания: %d секунд', waitTime / 1000))
                                end
                                imgui.Text(string.format(u8 'Рейсов сделано: %d', TramBot.completedRoutes))
                            end
                        elseif i == 2 then
                            -- Настройки
                            imgui.Text(u8 'Настройки автоеды')
                            if imgui.Checkbox(u8 'Включить автоеду', imgui.ImBool(TramBot.autoEat)) then
                                TramBot.autoEat = not TramBot.autoEat
                                table.insert(TramBot.logs, os.date('%H:%M:%S') .. ' - Автоеда ' .. (TramBot.autoEat and 'включена' or 'выключена'))
                            end

                            imgui.Text(u8 'Еда через N рейсов:')
                            if imgui.InputInt('', eatAfterRoutes, 1, 10) then
                                TramBot.eatAfterRoutes = math.max(1, eatAfterRoutes.v)
                                table.insert(TramBot.logs, os.date('%H:%M:%S') .. ' - Настроено автоеда через ' .. TramBot.eatAfterRoutes .. ' рейсов')
                            end

                            imgui.Separator()

                            imgui.Text(u8 'Дополнительные настройки')
                            -- Пример дополнительной настройки: Скорость поезда
                            local trainSpeed = 24.0
                            if imgui.InputFloat(u8 'Скорость поезда', trainSpeed, 0.1, 1.0, '%.1f') then
                                -- Сохранение или обработка нового значения
                                table.insert(TramBot.logs, os.date('%H:%M:%S') .. ' - Изменена скорость поезда на ' .. trainSpeed)
                            end
                        elseif i == 3 then
                            -- Логи
                            imgui.BeginChild('LogWindow', imgui.ImVec2(0, -ImGui.GetFrameHeightWithSpacing()), false, imgui.WindowFlags.HorizontalScrollbar)
                            for _, log in ipairs(TramBot.logs) do
                                imgui.TextWrapped(u8(log))
                            end
                            imgui.EndChild()
                        end
                        imgui.EndTabItem()
                    end
                end
                imgui.EndTabBar()
            end

            imgui.End()
        end
    end
end

-- Главная функция
function main()
    math.randomseed(os.clock())
    repeat
        wait(0)
    until isSampAvailable()

    sampAddChatMessage('Tram bot by Tectrex', -1)
    sampRegisterChatCommand('trambot', function()
        showWindow.v = not showWindow.v
        imgui.Process = showWindow.v
    end)

    while true do
        wait(0)
        if TramBot.isActive then
            if isCharInAnyCar(PLAYER_PED) then
                TramBot:handleInCar()
            else
                TramBot:handleOnFoot()
            end
        end
    end
end

-- Обработка синхронизации игрока
function sampev.onSendPlayerSync(data)
    if TramBot.isActive then
        data.moveSpeed.x = -0.42
        data.moveSpeed.y = 0.81
        data.moveSpeed.z = 0
    end
end

-- Обработка изменения текста материала объекта
function sampev.onSetObjectMaterialText(id, data)
    local handle = sampGetObjectHandleBySampId(id)
    if handle then
        local modelId = getObjectModel(handle)
        TramBot.isFree = (modelId == 19483) and (string.find(data.text, 'Свободно') ~= nil)
        table.insert(TramBot.logs, os.date('%H:%M:%S') .. ' - Изменено состояние рейсов: ' .. (TramBot.isFree and 'Свободно' or 'Занято'))
    end
end
```
[ML] (system) crytp.lua: Loaded successfully.
[ML] (error) crytp.lua: ...loads\cleaned originalSA by kichiro\moonloader\crytp.lua:203: attempt to call field 'GetBackgroundDrawList' (a nil value)
stack traceback:
	...loads\cleaned originalSA by kichiro\moonloader\crytp.lua:203: in function 'OnDrawFrame'
	...s\cleaned originalSA by kichiro\moonloader\lib\imgui.lua:1378: in function <...s\cleaned originalSA by kichiro\moonloader\lib\imgui.lua:1367>
[ML] (error) crytp.lua: Script died due to an error. (1D92173C)