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

eu_tomat

Модераторы
  • Публикации

    2 666
  • Зарегистрирован

  • Посещение

  • Победитель дней

    331

Сообщения, опубликованные пользователем eu_tomat


  1. 42 минуты назад, Flays сказал:

    @eu_tomat То и то. Чтоб программа ожидала запрос, но и в этот же момент всё равно работала. А не только ожидала запрос и пока его не будет, сама программа не будет фукционировать. 

    Программа не может ждать и не ждать одновременно. Но, например, может пытаться получить очередную запись из очереди событий с некоторой периодичностью, если указать нулевое время ожидания: event.pull("modem_message", 0).

     

    Даже если назначить обработчик событий через event.listen(...), для его функционирования потребуется периодически вызывать os.sleep(). То есть, в этом случае ожидание тоже не постоянное, его размер и периодичность также задаётся программистом.

    • Одобряю 1

  2. 12 часа назад, Flays сказал:

    @Asior Пробовал отслеживать через принт, всё равно не хухры. На вики чекнул что там сначала цифра, а потом что нужно. А я хотел изначально чтоб всегда была проверка на есть ли какой-то сигнал, если нету то выводить на экран что его нету и ждать.

     

    12 часа назад, Flays сказал:

    а можно ли будет как-то обойти ожидание запроса сообщение или нет?

     

    Так что именно требуется? Ждать или не ждать?


  3. 1 минуту назад, Flays сказал:

    @eu_tomat Если драйвера имеются то как посмотреть как с ними работать? И есть ли OpenPeripheral на 1.12.2, а то я только на 1.7.10 находил?

    При наличии драйверов устройство отобразится в выводе утилиты components. API устройства можно посмотреть в выводе components -l.

     

    Для 1.12 есть Plethora Peripherals с другим набором драйверов, а про OpenPeripheral для 1.12 я тоже не слышал.

     


  4. Для обеспечения доступа компьютера к механизмам из других модов следует установить адаптер вплотную к механизму, а сам адаптер подключить к компьютеру, например, кабелем OpenComputes.

     

    Также имеет смысл проверить список устройств с помощью утилиты components до подключения устройства и после. Если в результате подключения новых устройств не появилось, то что-то пошло не так: либо адаптер оказался не в общей сети с компьютером, либо механизм не имеет драйвера для работы с OpenComputers. Драйверы многих механизмов поставляются модом OpenPeripheral.


  5. 9 минут назад, VladG24_YT сказал:

    Но тем не менее я не смогу применить SymVer к "релизам" OCLIDE по двум причинам:

    1. Я не считаю, что текущее состояние программы можно выводить на релиз. Слишком много мелких косяков.
    2. Меня не устраивает "максимальная свобода" нулевой мажорной версии, ибо мне хочется всё-таки связать себя обязательствами доведения продукта до относительной завершённости с целью недопущения повторения истории со всякими долгостроями, которые потом просто закрываются.

    Эти-то причины как раз и не мешают применять semver. Можешь смело переходить на 1.0.0. То была рекомендация а не требование. Semver не мешает начать хоть с версии 100500.0.0 или скакнуть на неё с 0.0.1. Желательно иметь разумное обоснование таких скачков, но это не требование semver.

     

    17 минут назад, VladG24_YT сказал:

    Графический интерфейс

    С GUI сложнее. Semver описывает систему версионирования применительно к API. В случае графических интерфейсов появляется широкое поле для субъективных интерпретаций. По идее, мажорная версия должна быть увеличена при глобальном изменении интерфейса. Минорная версия увеличивается при добавлении нового функционала без больших изменений интерфейса. А патч-версия увеличивается при баг-фиксах. Но всё это относительно.

     

    Если я переместил кнопку на 100 пикселей выше, это баг-фикс, или изменение интерфейса? С точки зрения пользователя это может быть баг-фиксом. А с точки зрения другого пользователя или какого-нибудь автокликера это может быть нарушением совместимости.

     

    А если я добавил так много мелкого функционала в очередную минорную версию, что графический интерфейс стал мало похож на прежний, то стоит ли считать это изменение глобальным и увеличивать мажорную версию?

     

    Тут чёткий рецепт вряд ли возможен, и в каждой команде разработчиков могут быть свои предпочтения в версионировании.

     

     

    • Спасибо 1

  6. 8 минут назад, VladG24_YT сказал:

    Так как в данном случае способ версионирования с нулевой мажорной версией можно назвать полезным лишь субъективно, а объективного взвешивания всех "за" и "против" использования такого способа не проводилось, то можно смело заявить что четвёртый пункт спецификации SemVer не переопределяет второй.

    Здесь закралась ошибка. Объективно запрета нет. Субъективно же как раз взвешивание "за" и "против". Также, говоря о пользе, имеет смысл уточнять, для кого именно полезно, для достижения какой цели, в какой ситуации. Также изначальный вопрос был "что полезно, и что неполезно", а что имеет право на существование.

    2 часа назад, NEO сказал:

    по спецификации semver, версия 0.0.3 имеет право на существование?

    FAQ спецификации semver содержит рекомендацию начинать разработку с версии 0.1.0, но она необязательна.

     

    17 минут назад, VladG24_YT сказал:

    Единственным возможным верным (с точки зрения RFC 2119) использованием нулевой мажорной версии SemVer в данном проекте (OCLIDE) я вижу лишь вариант, при котором в публичный доступ так же выкладывались бы INDEV-версии за период с Марта 2020 (коммит 9894b7a) до Января 2021 (коммит 3dc00f0, включительно).

    Тут вопрос не в публичности репозитория, а в том, какую из версий разработчик посчитает достойной назвать релизом. Нулевая мажорная версия обеспечивает разработчику максимальную свободу, не связывая его обязательствами по поддержке существующего API или формата данных.

     

    Кстати, какой API предоставляет твоя OCLIDE и с какими версиями API эмуляторов совместима?

    • Спасибо 1

  7. 1 час назад, VladG24_YT сказал:

    По спецификации 2.0.0 семантического версионирования, ни одна из версий 0.0.1, 0.0.2 или 0.0.3 не имеют право на существование.

    А какому пункту спецификации это противоречит?

     

    https://semver.org/lang/ru/

     

    Нулевые версии допустимы:

    Цитата

    Мажорная версия ноль (0.y.z) предназначена для начальной разработки. Всё может измениться в любой момент. Публичный API не должен рассматриваться как стабильный.

     

    Есть пункт, запрещающий ведущие нули в числах:

    Цитата

    Обычный номер версии ДОЛЖЕН иметь формат X.Y.Z, где X, Y и Z — неотрицательные целые числа и НЕ ДОЛЖНЫ начинаться с нуля. X — мажорная версия, Y — минорная версия и Z — патч-версия. Каждый элемент ДОЛЖЕН увеличиваться численно. Например: 1.9.0 ->1.10.0 -> 1.11.0.

    Эту формулировку можно понять так, будто бы запрещёны и нулевые числа, но приведённый пример опровергает это.


  8. 2 минуты назад, VladG24_YT сказал:

    IDE заточенная специально под OpenComputers

    ...

    - (нестабильная) Интеграция с OCEmu (билд с OpenOS 1.6)

    А в чём заключается заточка под OpenComputers кроме нестабильной интеграции с эмулятором? И в чём заключается интеграция?


  9. В 01.01.2021 в 22:00, ProgramCrafter сказал:

    Чтобы создать стабильную систему, проблему TLWY надо решить.

    Здесь идёт речь о системе OpenOS, или в целом об OpenComputers?

     

    В 01.01.2021 в 22:00, ProgramCrafter сказал:

    При лагах сервера эта ошибка может возникать совершенно случайным образом, иногда даже в консоли OpenOS.

    Имеется в виду консоль, ожидающая ввода команды? Какой в это время TPS на сервере?

     


  10. 1 минуту назад, ecyc сказал:

    как установить тогда не в /home, а в / ?

    Для начала надо сделать текущим корневой каталог.

    # cd /

    Если затем выполнить pastebin get, то программа установится в корневой каталог. Можно не устанавливать программу заново, а перенести её, воспользовавшись командой move.

     

    Решение с установкой в корневой каталог имеет недостаток: после перезагрузки компьютера перед запуском программы снова потребуется сменить текущий каталог на корневой. Проблему можно решить радикально, дописав в коде shell.resolve при вызове fs.exists.


  11. 6 минут назад, ecyc сказал:

    так в том и суть, что в корневой папке, я никакие папки вообще не создавал(если я правильно понял:))

    Суть в том, что при установке создаётся каталог /home, и программа, скорее всего, установилась именно в него, а не в корневой. Файлы создаются в каталоге /home, а их наличие проверяется в /.

     

    9 часов назад, vx13 сказал:

    проблема похоже в том, что fs.exists ничего не знает про рабочий каталог шелла

    Да, очень похоже. filesystem является слишком низкоуровневой библиотекой. Библиотека io, уровнем повыше, использует вспомогательную библиотеку shell:

    function io.open(path, mode)
      local resolved_path = require("shell").resolve(path)
      local stream, result = require("filesystem").open(resolved_path, mode)

    Благодаря этому io.open может открыть файл в текущем каталоге без указания полного пути.

    Но filesystem.open без указания пути откроет файл в корневом каталоге.

     

    Смешение кода, работающего то через io, то через filesystem обычно и приводит к описанной ошибке.


  12. 20 минут назад, hohserg сказал:

    Туда, куда возвращает управление computer.pullSignal и некоторые методы компонентов

    Но в конечном итоге управление вернётся в пользовательскую программу. И если она была зациклена по ошибке или со злым умыслом, то такое решение поддержит существование лагодрома. А так лагодром просто завершился бы с ошибкой.

     

    24 минуты назад, hohserg сказал:

    А можешь привести пример таких скриптов?

    Пример у меня есть, но опубликовать его не могу. Опасаюсь, что неадекватные игроки, недовольные действиями администраторов игровых серверов, будут кошмарить сервер моим скриптом. Защиты против него на данный момент нет кроме как удалить компы с сервера. А оно нам надо?

     

    Возможно, всё не так страшно, и админы могут оперативно вычислить таких нарушителей и устранять последствия. Просто я не знаю всей кухни майноводства. Что потребуется:

    • Как-то понять, что сервер лагает именно из-за компов;
    • Найти проблемные компы и их владельцев.

    Администраторы серверов располагают таким инструментарием?


  13. 4 часа назад, hohserg сказал:

    Почему механизм защиты от лагливого кода вообще должен вырубать компы

    В норме, кстати, компы не вырубаются. Обычно останавливается код, завёрнутый в pcall. Но pcall не спасает в случае сильных лагов. Вряд ли это так было задумано, но такое поведение не противоречит логике предохранения сервера от запредельной нагрузки. Когда игровой сервер дышит на ладан, то отрубившиеся компы выглядят не самой большой проблемой. И даже если сервер не лагает, всё равно надо как-то останавливать случайно или злонамеренно зацикленные скрипты.

     

    5 часов назад, hohserg сказал:

    Почему бы вместо error(tooLongWithoutYielding) не возвращать управление? Таким образом управление будет возвращаться всегда, даже если в выполняющемся коде оно не предусмотрено

    Куда возвращать управление? В зависшую программу while true do end?


  14. 13 часа назад, ProgramCrafter сказал:

    Переписать виртуальную машину Lua так, чтобы она сама уступала управление другим потокам (тогда ошибка TLWY уйдёт в прошлое). Для этого надо договориться с разработчиками OpenComputers и уметь программировать на Java.

    TLWY не следует воспринимать как какую-то недоработку OpenComputers, эта механика намеренно добавлена разработчиками мода для защиты игрового сервера от зависших или злонамеренно зацикленных скриптов. Что касается злонамеренности, то эта защита легко обходится в несколько строк кода. В рабочих же программах, которым недостаточно окна, предоставляемого TLWY, эта проблема решается не столь красиво, а само решение требует адаптации под задачу и условия сервера. Но во всех известных мне случаях задача решаемая. Если не смотря на принятые меры, программа всё же завершается по TLWY, это может означать лишь то, что нагрузка на игровой сервер превысила все разумные пределы. В этих условиях лучшее, что можно сделать, это прекратить любые действия в программе, тем самым снизив нагрузку на сервер, и, переждав проблемы и не завершившись с ошибкой, возобновить работу.

     

    Поэтому меня больше интересует не борьба с TLWY, а вопрос, как сделать механизм TLWY более гибким, чтобы, например, не выключались компы во время загрузки OpenOS, а скрипты с интенсивными вычислениями наоборот бы, блокировались.


  15. 1 час назад, Taruu сказал:

    А можно ли лаги сервера ловить при помощи реального времени?
    Или же там тоже будут жуткие неточности? 

    Конечно же, можно.

    В 29.07.2020 в 11:25, eu_tomat сказал:

    Оценка соотношения роста computer.uptime() и реального времени сервера позволяет вычислить значение TPS. Но падение TPS в чанке не всегда указывает на лаги сервера, так могут проявлять себя штатные механики Майнкрафта и модов.

     


  16. 1 час назад, vx13 сказал:

    Нужна обёртка вокруг функции component.robot.move, которая будет перехватывать эту ошибку и повторять перемещение.

    Да, теперь-то, когда проблема была локализована, стало понятно, что надо не swing() выполнять, а повторить forward().


  17. 4 часа назад, serafim сказал:

    причина возврата: already moving (уже движется) ,занятно

    Ага. Вот они, серверные нюансы, не проявляющие себя в одиночной игре. Программа уже получила управление после необходимой задержки, но движение робота до сих по не завершено из-за лагов сервера.

    Robot.scala:

        if (agent.isAnimatingMove) {
          // This shouldn't really happen due to delays being enforced, but just to
          // be on the safe side...
          result(Unit, "already moving")

    То, чего не должно происходить на практике благодаря принудительным задержкам, но проверка на всякий случай добавлена. Как оказалось, не зря.


  18. 1 час назад, serafim сказал:

    Если не сложно, можешь поменять значение с 10 на 1 и понаблюдать куда именно он там упирается,

    А ещё интересно было бы посмотреть, что именно там возвращают robot.forward() и robot.swing(). В случае неудачи обычно возвращается ещё и её причина.


  19. 6 минут назад, Doob сказал:

    Зачем так сложно?

    Почему сложно-то? Я же не предлагаю работать именно с этими фиксированными числами, а иллюстрирую пример с железной киркой. От эксперимента к эксперименту эти числа будут отличаться в силу случайности износа при использовании. По факту же мы с тобой оба предлагаем одинаковое решение, но я даже на два не делю. Какое число я получил от robot.durability(), столько же раз использую инструмент до следующей проверки.


  20. Продолжу заниматься осветлением тёмной магии. Мне в личку поступил вопрос о назначении конструкции (dura*1e6+0.5)//1/1e6. Подозреваю, что эта информация будет интересна более широкому кругу читателей, поэтому публикую свой ответ здесь.

     

    Встретив новую конструкцию в коде, порой сложно бывает даже сформулировать запрос для поисковика, чтобы выйти на какой-то вменяемый ответ. В этом случае я рекомендую следующие способы поиска информации:

     

    Что такое 1e6?

    Если рассуждать логически, то можно предположить, что это какая-то причудливая форма записи числа. Поиск по фразе «форма записи числа» быстро приводит к статьям, рассказывающим о форме записи, называемой формой записи числа с плавающей точкой. Синонимы: «экспоненциальная запись», «научная форма», «нормальная форма», «полулогарифмическая форма». Примеры:
    1e6 = 1 * 10^6 = 1000000.
    5e-3 = 5 *10^-3 = 0.005


    Я использую экспоненциальную запись для краткости. От обилия ноликов у меня рябит в глазах, а в экспоненциальной форме я сразу вижу количество нулей, что снижает вероятность ошибки.

     

    Что такое //?
    Это операция целочисленного деления. Как об этом узнать? Во-первых, можно загуглить фразу «lua double slash operator». Можно и на русском языке поискать, но шанс найти подобное упоминание будет ниже. Во-вторых, имеет смысл читать спецификации языка, это основной источник знаний: Lua 5.3 Reference Manual 3.4.1 – Arithmetic Operators. Также есть справочник по языку Lua5.3 на русском: http://antirek.github.io/luabook/.

     

    Что вообще делает конструкция (dura*1e6+0.5)//1/1e6?
    Я использую операцию целочисленного деления для получения целочисленной части числа. По-моему, это самый быстрый способ. Иначе говоря, это округление числа до целого вниз. Но перед этим я добавляю к числу 0.5, для того, чтобы получить округление до ближайшего целого.

    Перед  округлением до целого я умножаю исходное число на 1e6, а после округления делю результат на 1e6. Эта последовательность операций позволяет мне округлить число до 6 знака после запятой.

     

    Если кто-то знает более эффективный способ округления чисел, делитесь своими решениями. Я же использую эту конструкцию с тех пор, как перешёл на Lua5.3.


    Для вычисления прочности инструмента, скорее всего, достаточно было бы тупо округлять число до ближайшего целого, но в экспериментах я стараюсь округлять хотя бы до 6 знака, чтобы убедиться, что располагаю запасом точности, и меня не ждут сюрпризы с этой стороны.

     

    Когда мне требуется максимальная точность, я подбором ищу самый далёкий знак, чтобы округление искажало результаты минимальным образом, но было бы достаточным для получения устойчивых и воспроизводимых результатов. Такой подход иногда позволяет мне обнаруживать новые нюансы механик во время дальнейших экспериментов. Например, если сначала мне хватало округления до 9 знака, но на каком-то этапе вдруг потребовалось округление до 6. Такое изменение может означать встречу с каким-то новым эффектом. Или, например, может сигнализировать мне о том, что я использовал слишком громоздкие вычисления приводящие к сильному снижению точности.

     

    В рабочих программах по завершении экспериментов я обычно уменьшаю точность на несколько порядков, чтобы выполняющийся код не реагировал на непредвиденные флуктации погрешностей.

     

    Надеюсь, этот пост будет полезен более чем одному читателю форума.

     

    • Нравится 2

  21. @Asummonster я частенько вижу реакцию "в шоке" под своими постами, но мне ни разу не удалось понять, что она означает. Вот, скажи: выставляя реакцию "в шоке", какую мысль ты хочешь донести до автора поста и до его читателей? Что именно тебя шокирует? Ты с чем-то не согласен? Или согласен, но считаешь неприемлемым высказывать это? Или согласен, но не ожидал такого решения? Или наоборот, решение для тебя настолько очевидным, что тебя шокирует его обсуждение? Ты хочешь видеть подобные посты чаще, или наоборот, реже?


  22. Я сейчас повторил эксперимент в игре и обнаружил, что значимых проблем с точностью нет. Можно округлять до 6 знака после запятой, и всё будет сходиться. Но откуда могла взяться ошибка в моём прошлом эксперименте? Подозреваю, что в тот раз я не глядя взял значения с википедии, а увидев расхождение, не довёл эксперимент до конца.

     

    Рассмотрю проблему на примере алмазной кирки. Согласно вики, её прочность равна 1562. Проверка прочности через контроллер инвентаря:

    component.inventory_controller.getStackInInternalSlot(1).maxDamage
    1561.0

    Проверка прочности при использовании:

    d0=robot.durability()
    repeat
      robot.place()
      robot.swing()
      d=robot.durability()
    until d~=d0 dura=1/(d0-d)
    print(dura,(dura*1e6+0.5)//1/1e6)
    
    1560.9999999999 1561.0

    Значение максимальной прочности кирки, полученное экспериментально, совпадает со значением, полученным с помощью контроллера инвентаря с погрешностью до 6 знака после запятой. На самом деле погрешность ещё меньше, просто я не увидел смысла в её точном определении.

     

    Вики, к слову, тоже не врёт, если вникнуть в механику использования инструмента. После рубки алмазной киркой 1561 блока остаток прочности кирки будет равен нулю. Но даже нулевая прочность позволит сломать ещё один блок, при этом кирка окончательно сломается.

     

    • Спасибо 1
    • В шоке 1

  23. 9 часов назад, serafim сказал:

    Вместо очень примерных замеров, можно сделать "режим паника"

    Сначала делать замер износа инструмента только в начале и в конце линии, и в случае износа меньше определённого значения (например 20%) проверять износ при каждом движении, да это не так эффективно, но робот точно не застрянет

    Без паники! Тяжело точно измерить объём полной бочки напёрстками, даже заранее зная, что она содержит целое число напёрстков. Небольшая погрешность легко может накопиться в один-два лишних или недостающих напёрстка. Но когда ты измеряешь небольшой остаток воды в бочке, всё так же зная, что количество напёрстков должно быть целым, ошибиться почти невозможно. Погрешность вычислений снижается естественным образом, и округление до целого полностью решает эту проблему.

     

    А учитывая, что мы не доверяем шансам, то и частоту проверки остатка прочности мы также увеличиваем по мере падения прочности. Покажу это на примере всё той же железной кирки:

     

    robot.durability() показывает прочность примерно в 251 использование. В среднем кирка износится за 2510 использований. Поэтому даже  если мы получили слегка завышенную прочность, мы вряд ли сломаем кирку до конца, применив её, например 252 раза. Если тебя интересует вероятность неудачного исхода в таком применении, я могу потормошить голову и посчитать. Это как-то связано с биномом Ньютона, но мне требуется вспомнить, как именно.

     

    Но идём дальше. Предположим, мы использовали кирку 252 раза. За это время она износится в среднем на 25 единиц. Мы снова проверяем остаток через robot.durability() и получаем остаток прочности, равный, например, 226. И теперь мы используем кирку 226 раз.

     

    В следующий раз мы используем кирку 204 раз, затем 184 раза, затем 166 и т.д. Чем ниже остаток прочности, тем чаще выполняется его проверка. При таком алгоритме сложно проскочить критический момент. Особенно учитывая, что по мере приближения к нему точность вычислений возрастает по причине естественного снижения погрешности.

×
×
  • Создать...