Перейти к содержимому

Лидеры


Популярный контент

Показан контент с высокой репутацией 26.06.2020 в Сообщения

  1. 6 баллов
    Чтобы решить проблему, надо оформить код. entity = require("component").os_entdetector alarm = require("component").os_alarm door = require("component").os_rolldoorcontroller local e = entity.scanPlayers(3) local whitelist = {{}} alarm.setAlarm("klaxon2") alarm.setRange(15) whitelist[1] = "Arsean" whitelist[2] = "sherlock2202" function open() door.open() os.sleep(5) door.close() detect() end function detect() if type(q[1]) == type(nil) then print("Нету") os.sleep(2) q = e detect() else print("Есть") q = e check() end end function check() x = e[1].name if x == "Arsean" then open() else alarm.activate() os.sleep(5) alarm.deactivate() end detect() end q = e detect() Тяк, сначала починим обозначенную неполадку. Функция detect, согласно названию, должна при каждом вызове пересканировать игроков. Однако сканирование игроков это происходит в самом начале программы (4 строка) и один раз. Гм. Ещё раз, при каждом вызове функции надо выполнять определённый код. При каждом вызове... а почему бы не поместить сканирование внутрь функции? Разве это не тем и занимается? entity = require("component").os_entdetector alarm = require("component").os_alarm door = require("component").os_rolldoorcontroller local e = entity.scanPlayers(3) local whitelist = {{}} alarm.setAlarm("klaxon2") alarm.setRange(15) whitelist[1] = "Arsean" whitelist[2] = "sherlock2202" function open() door.open() os.sleep(5) door.close() detect() end function detect() e = entity.scanPlayers(3) q = e if type(q[1]) == type(nil) then print("Нету") os.sleep(2) q = e detect() else print("Есть") q = e check() end end function check() x = e[1].name if x == "Arsean" then open() else alarm.activate() os.sleep(5) alarm.deactivate() end detect() end q = e detect() Ну да, почти. Пришлось только ещё q = e перетащить туда же. Но теперь должно работать. ... Должно ли? Исправляем другие проблемы, которые здесь заютились. Проблема 1. Есть переменные q и e, которые во всех местах устанавливаются одинаковыми, при этом непонятно, чем они отличаются. Объединим их в одну переменную. Заодно назовём её по-человечески, а не для машины, то есть понятно: entity = require("component").os_entdetector alarm = require("component").os_alarm door = require("component").os_rolldoorcontroller local scan = entity.scanPlayers(3) local whitelist = {{}} alarm.setAlarm("klaxon2") alarm.setRange(15) whitelist[1] = "Arsean" whitelist[2] = "sherlock2202" function open() door.open() os.sleep(5) door.close() detect() end function detect() scan = entity.scanPlayers(3) if type(scan[1]) == type(nil) then print("Нету") os.sleep(2) detect() else print("Есть") check() end end function check() x = scan[1].name if x == "Arsean" then open() else alarm.activate() os.sleep(5) alarm.deactivate() end detect() end detect() Проблема 2. Куча переменных не локальны. Допустим такую ситуацию: в коде переименовали переменную, а в одном месте имя сменить забыли. Если эта переменная была локальной, то программа пропишет ошибку, стопнется, и проблему легко локализовать и починить. Если глобальной, то она никуда не денется до рестарта компьютера. Каково этого — поменял переменную, а в одном месте как будто одно и то же значение застряло? Чинить такие вещи — боль. Как правило, все переменные делать надо локальными. У глобальных есть несколько применений, но без них обходиться можно всегда. И лучше это делать. Чиним, короче: local entity = require("component").os_entdetector local alarm = require("component").os_alarm local door = require("component").os_rolldoorcontroller local scan = entity.scanPlayers(3) local whitelist = {{}} alarm.setAlarm("klaxon2") alarm.setRange(15) whitelist[1] = "Arsean" whitelist[2] = "sherlock2202" local function open() door.open() os.sleep(5) door.close() detect() end local function detect() scan = entity.scanPlayers(3) if type(scan[1]) == type(nil) then print("Нету") os.sleep(2) detect() else print("Есть") check() end end local function check() local x = scan[1].name if x == "Arsean" then open() else alarm.activate() os.sleep(5) alarm.deactivate() end detect() end detect() Проблема 3. Переполнение стэка из-за рекурсии. Во всех функциях в коде вызывается detect. В том числе внутри самой detect — когда функция саму себя зовёт, это зовут рекурсией. У меня есть подозрение, то функциональное программирование непрограммирующему обывателю концептуально проще, чем императивное. Вот взять этот код. Откуда тут рекурсия? Думаю, автор рассуждал так: после проверки на пробежчиков мы хотим снова отсканировать игроков. То есть перейти в detect. А как перейти в функцию? Вызовом же. Проблема в том, что Lua — язык императивный по большей части. А ещё оптимизаций делает мало. Поэтому не получится в луа сколь угодно много раз вызывать функции рекурсивно. Упрёмся в лимит и словим ошибку. Один способ починить — использовать хвостовую рекурсию, которую Lua оптимизировать умеет. Мы вместо этого воспользуемся циклами. local entity = require("component").os_entdetector local alarm = require("component").os_alarm local door = require("component").os_rolldoorcontroller local scan = entity.scanPlayers(3) local whitelist = {{}} alarm.setAlarm("klaxon2") alarm.setRange(15) whitelist[1] = "Arsean" whitelist[2] = "sherlock2202" local function open() door.open() os.sleep(5) door.close() end local function detect() while true do scan = entity.scanPlayers(3) if type(scan[1]) == type(nil) then print("Нету") os.sleep(2) else print("Есть") check() end end end local function check() local x = scan[1].name if x == "Arsean" then open() else alarm.activate() os.sleep(5) alarm.deactivate() end end detect() Если в первой функции вызвать вторую, то Луа будет выполнять код второй функции. Когды мы дойдём до конца кода её, Луа вернётся в первую функцию. То есть Lua не забывает, кто вызвал любую функцию. Таким образом, open вернётся в check, а check — в detect. В detect появился while true do ... end. Эта конструкция называется бесконечным циклом. Цикл — повторение одного и того же кода. Бесконечный — нет условия, при котором программа покинет цикл. (Формально есть ^[C, то есть цикл покинуть можно, но оставим это в стороне.) Проблема 4. Нелокальность переменных. Это не повторение проблемы #2, хотя на определённом уровне абстракции всё начинает казаться молотками и гвоздями они очень похожи. Переменная scan общая для всех функций. По сути, это тоже "глобальная" переменная, только живёт она не дольше, чем программа (статическая она, наверное, лучше сказать). Если нет веских причин, лучше всё-таки такие переменные передавать явно. То есть аргументом функций. local entity = require("component").os_entdetector local alarm = require("component").os_alarm local door = require("component").os_rolldoorcontroller local whitelist = {{}} alarm.setAlarm("klaxon2") alarm.setRange(15) whitelist[1] = "Arsean" whitelist[2] = "sherlock2202" local function open() door.open() os.sleep(5) door.close() end local function detect() while true do local scan = entity.scanPlayers(3) if type(scan[1]) == type(nil) then print("Нету") os.sleep(2) else print("Есть") check(scan) end end end local function check(scan) local x = scan[1].name if x == "Arsean" then open() else alarm.activate() os.sleep(5) alarm.deactivate() end end detect() Теперь scan определяется в detect и передаётся в check аргументом. Проблема 5. Программа страшно боится одиночества. Предлагаю взглянуть на эту строку пристально, можно без микроскопа: local x = scan[1].name Я утверждаю, что тут ошибка. Разберём строку. scan — это таблица с игроками. Она хранит внутри себя ещё таблицы. В последних инфа о конкретном игроке. scan[1] — это тогда таблица с инфой о первом игроке. А если вокруг радара пустыня, случайных прохожих нет, а последний местный подох под палящим пустынным солнцем где-то в лаве? scan будет пустой таблицей, и scan[1] будет nil. scan[1].name — эта штука безусловно полагает, что scan[1] можно индексировать, то есть это таблица (или что-то вроде неё). Нет, не scan — то, что это таблица, мы уже знаем безусловно. scan[1] — первый элемент таблицы scan. Выше мы определили, что этот элемент — или ещё одна таблица, или nil. Таблицу индексировать можно. Если проиндексировать nil, программа завершится с ошибкой. Напомню, nil у нас бывает только тогда, когда игроков вокруг нет. Следовательно, на необитаемом острове программа упадёт. Чтобы починить, подумаем, что надо делать на этом необитаемом острове. Визжать сиреной? Думаю, вряд ли. Лучше просто промолчать и ничего не делать. Добавим проверку. local entity = require("component").os_entdetector local alarm = require("component").os_alarm local door = require("component").os_rolldoorcontroller local whitelist = {{}} alarm.setAlarm("klaxon2") alarm.setRange(15) whitelist[1] = "Arsean" whitelist[2] = "sherlock2202" local function open() door.open() os.sleep(5) door.close() end local function detect() while true do local scan = entity.scanPlayers(3) if type(scan[1]) == type(nil) then print("Нету") os.sleep(2) else print("Есть") check(scan) end end end local function check(scan) if scan[1] then local name = scan[1].name if name == "Arsean" then open() else alarm.activate() os.sleep(5) alarm.deactivate() end end end detect() Не удержался, переменовал x и name, чтобы не потеряться. Проблема 6... Пожалуй, всё. Нет, код ещё можно улучшать и улучшать. Например, белый список не используется и задаётся странно. Но так и я не автор программы. В этом посте я попытался описать только "сложные" проблемы, то есть для определениях которых нужен какой-нибудь опыт программирования. Проблема 3, например, означает, что программа крашилась бы через час после включения. Стабильно. Со странной ошибкой. Проблему 5 вообще сложно было бы дебажить, так как игрока рядом с компьютером быть не должно, иначе и проблема не проявится.
  2. 1 балл
    на нашем сервере много пк, работать с дискетами работать очень не удобно, (я использую карту гринфилд), мы решили сделать "nas" системму, но дело в том что в "lua" мы полный ноль. работать должно так: пк по беспроводной сети подключается у серверу, (к серверу подключено 2 raid один с системмой а второй пустой), сервер дает доступ ко второму raid и на пк который запросил доступ открывается папка 2 рейд масива. права удаленных пк можно только записывать, скачивать. права сервера: удалять, записывать, скачивать.
  3. 1 балл
    осталось whitelist допилить что то типа этого
  4. 1 балл
    ок код выполняется построчно, а так как функции теперь локальные а не глобальные, у верхней функции нет доступа к нижней также можно завернуть весь код в одну функцию, так будет проще ориентироваться в коде, функции обычно выносят при частом обращении из разных мест в коде, чтоб не повторять её по 100 раз
  5. 1 балл
    попробуй в коде поменять местами функции local function check(scan) и local function detect()
  6. 1 балл
    @Alex ясно. Зачем на форуме 2 кнопки для спойлеров?
Эта таблица лидеров рассчитана в Москва/GMT+03:00
×
×
  • Создать...