Страница 16 из 18

Re: LuaScript - для RS

СообщениеДобавлено: 27.09.2018, 13:44
Skif
А еще можно просто писать данные в текстовый файл - и читать его асинхронно внешним софтом!


На основе этого метода работает моя система пульта для TS. Единственный на рынке желдорсим, который позволяет оживить приборную доску.

Re: LuaScript - для RS

СообщениеДобавлено: 16.10.2018, 19:58
радиомастер
Подскажите пожалуйста вот с чем . Имеется три переменных назовем test1, test2 и test3
Как их объединить и отправить одним сообщением сразу , типа так
Код: Выделить всё
Call( "SendConsistMessage", MSGID, test1test2test3,1 )

а на приеме как то разделить чтобы опять на выходе получились test1, test2 и test3 . типа так
Код: Выделить всё
if ( msg == MSGID ) then
      test1 = tonumber(string.sub(argument, 1, 5))
      test2 = tonumber(string.sub(argument, 6,10))
      test3 = tonumber(string.sub(argument, 11, 15))

Напишите простой пример и попроще , мне очень нужно , а то я в координатах и точках запутался много всего туда сюда отправляется (это для трамвая по СМЕ)

Re: LuaScript - для RS

СообщениеДобавлено: 16.10.2018, 20:49
Света
Вариант, может и не проще, но надежнее.
Отсылка. Все переменные записываются в одну строку, разделенные двоеточиями и отсылаются:
Код: Выделить всё
local message = test1..":"..test2..":"..test3
Call ("SendConsistMessage", MSGID, message, 1)

В месте приема эта строка разбивается на отдельные фрагменты, которые помещаются в специально созданную таблицу (table_tests) по порядку:
Код: Выделить всё
if (msg == MSGID) then
   local table_tests = string.split (argument, ":")
   test1 = tonumber (table_tests[1])
   test2 = tonumber (table_tests[2])
   test3 = tonumber (table_tests[3])
end

Тот кусок, что был в строке первым, будет в ячейке №1, второй - в ячейке №2 и т.д.. Преимущества метода - переменные test1, test2 и test3 никогда не перепутаются, так как они всегда будут рассортированы в порядке, по которому склеивались в строку. При этом их не надо форматировать, так как длина не имеет значения, хоть 1, хоть 1.001 - все будет разделено корректно.
Вот использованная функция string.split ():
Код: Выделить всё
function string:split(delimiter)
   local result = { }
   local from  = 1
   local index = 1
   local delim_from, delim_to = string.find( self, delimiter, from  )

   while delim_from do
      result[index] = string.sub(self, from , delim_from - 1)
      from  = delim_to + 1
      delim_from, delim_to = string.find( self, delimiter, from  )
      index = index + 1
   end

   result[index] = string.sub(self, from)

   return result
end
Её надо вставить в любое место скрипта.

Re: LuaScript - для RS

СообщениеДобавлено: 16.10.2018, 20:54
радиомастер
А две точки перед и за двоеточием обязательно ?

Re: LuaScript - для RS

СообщениеДобавлено: 16.10.2018, 20:58
Света
Да, это оператор, указывающий, что данные, между которыми находятся эти точки, надо соединить в одну строку. В результате получится одна строка "test1:test2:test3". Двоеточия же в этой строке - это метки, указывающие места, по которым надо разбивать строку.

Re: LuaScript - для RS

СообщениеДобавлено: 20.11.2018, 22:19
Света
Скрипт - генератор для автоматизированного создания номеров ПС обновлен. Добавлена возможность запретить отдельные цифры в рандомайзере и последовательного увеличения числа в блоке. Подробнее в блоге.
Идея добавленных методов генерации принадлежит Андрею (ака BooYa).

Re: LuaScript - для RS

СообщениеДобавлено: 23.12.2018, 13:43
Света
Удалось обнаружить один нюанс в работе скрипта. Оказывается, lua в симуляторе по логике работы отличается от стандартного lua. Отличие проявляется в обработке больших чисел, я предполагаю, что lua в симуляторе использует 32-й бит для своих нужд, ограничивая таким образом максимальную длину числа в 31 бит.
Мнение это у меня появилось после наблюдений, как скрипт, запущенный на lua "из коробки" дал один результат (правильный), этот же скрипт, запущенный в симуляторе, выдал совершенно другой результат. Например, если сделать простое арифметическое действие (4294967295 - 3534543), мы в симуляторе получим 4291432704, тогда как правильный ответ - 4291432752. Такие ошибки проявляются постоянно, если обрабатываются большие числа.
Этот нюанс сказывается в том числе на работе распространенных в сети функций битовых операций. Они или виснут, или возвращают некорректный результат.
Если, все же, требуется выполнить битовые операции, я могу предложить, как альтернативу, набор более "жестких" функций, по сравнению с другими. Они могут уступать в быстродействии, но зато, по крайней мере, обрабатывают 32-разрядные числа без проблем и заточены именно под них.
Код: Выделить всё
function To_Bin (num)
   local temp, bin, i = 0, {}, 0
   repeat
      temp = num
      num = math.floor(num / 2)
      table.insert (bin, 1, (temp - num * 2) ~= 0 and "1" or "0")
      i = i + 1
   until num == 0
   bin = string.rep("0", 32 - i)..table.concat(bin)
   return bin
end

function BitXOR (a, b)
   a = To_Bin (a)
   b = To_Bin (b)
   local res = {}
   for i = 1, 32 do
      table.insert (res, string.sub (a, i, i) == string.sub (b, i, i) and "0" or "1")
   end
   return tonumber (table.concat(res), 2)
end

function BitNOT (num)
   num = To_Bin (num)
   local res = {}
   for i = 1, 32 do
      table.insert (res, string.sub (num, i, i) == "1" and "0" or "1")
   end
   return tonumber (table.concat(res), 2)
end

function BitAND (a, b)
   a = To_Bin (a)
   b = To_Bin (b)
   local res = {}
   for i = 1, 32 do
      table.insert (res, (string.sub (a, i, i) == "1" and string.sub (b, i, i) == "1") and "1" or "0")
   end
   return tonumber (table.concat(res), 2)
end

function BitOR (a, b)
   a = To_Bin (a)
   b = To_Bin (b)
   local res = {}
   for i = 1, 32 do
      table.insert (res, (string.sub (a, i, i) == "1" or string.sub (b, i, i) == "1") and "1" or "0")
   end
   print (table.concat(res))
   return tonumber (table.concat(res), 2)
end

function rshift (x, by)
   return math.floor (x / 2 ^ by)
end

function lshift (x, by)
  return x * 2 ^ by
end

Функции сдвига не мои, я их выкладываю просто для комплектности, так как конкретно эти функции поддерживаются симулятором.

Добавлено спустя 7 часов 20 минут 3 секунды:
Также в симуляторном lua не работают функции math.fmod (a, b) string.reverse (s). Теоретически функцию math.fmod (a, b) можно заменить на math.mod (a, b). У меня же успешно работают эти функции:

Код: Выделить всё
function reverse (s)
   local table_char = {}
   for i = 1, string.len (s) do
      table.insert (table_char, 1, string.sub (s, i, i))
   end
   return table.concat(table_char)
end

function mod (a, b)
   return a - (math.floor(a/b)*b)
end

Re: LuaScript - для RS

СообщениеДобавлено: 20.03.2019, 14:26
Света
Если кому интересно, для определения максимального числа из нескольких, "тернарный оператор" в lua работает быстрее базовых функций примерно на 33%. Это если сравнивается 2 или 3 числа (0.159 против 0.215 и 0.168 против 0.222 мксек соответственно).
Если же чисел 4, то скорость "тернарного оператора" выше уже всего на 25% (0.196 против 0.245 мксек)
При этом, если в сравнении участвуют глобальные переменные, скорость работы очень сильно падает. Для сравнения 4 глобальных переменных потребовалось уже 0.332 и 0.327 мксек. При этом, если предварительно переписать глобальные переменные в локальные и сравнивать именно локальные, скорость повышается (0.239 и 0.332 мксек).
Вывод: быстрее всего обрабатываются локальные переменные. Даже перезагрузка значений из глобальных переменных в локальные выгоднее по времени. Для расчета минимального или максимального значения из группы до 5 переменных более быстрым будет "тернарный оператор".

Самый плохой код (затративший 0.334 мксек):
Код: Выделить всё
   A, B, C, D = 10, 40, 30, 20
   max = math.max (A, B, C, D)

Самый быстрый код (затративший 0.166 мксек):
Код: Выделить всё
   local a, b, c, d = 10, 40, 30, 20
   max = (a > b and a > c and a > d) and a or (b > c and b > d) and b or c > d and c or d

Re: LuaScript - для RS

СообщениеДобавлено: 28.05.2019, 10:22
Света
Небольшой лайфхак для скриптеров.
Если при тестировании LogMate показал ошибку, можно исходник скрипта закинуть в ассеты, вместо скомпилированного, и повторить ситуацию, при которой возникла ошибка. В этом случае LogMate выведет уже не общую информацию, а укажет имя сломанной переменной и номер строки, где это произошло.

Re: LuaScript - для RS

СообщениеДобавлено: 28.05.2019, 19:28
BooYa
Стоит добавить, что речь идёт о старом LogMate, который был до 2019 сима. 19 сима у Светы нет, насколько я знаю, не проверялось.

Новый логмейт говна кусок, лично у меня, когда явные ошибки скрипта были, он не писал вообще ничего.

Re: LuaScript - для RS

СообщениеДобавлено: 04.08.2019, 19:48
Света
Skif писал(а):
Skif, спасибо за примеры.
Один момент только насторожил. Вы, наверное, очень долго писали/пишете программы на ассемблере? Удивила вот эта конструкция из взаимоисключающих условий:

Код: Выделить всё
if (n_value > target) then
Call("*:SetControlValue", name, index, n_value - n_step + tremor);
end
if (n_value < target) then
Call("*:SetControlValue", name, index, n_value + n_step + tremor);
end

if (n_value == target) then
Call("*:SetControlValue", name, index, n_value + tremor);
return 1;
end


Это не ассемблер. Это SystemC - самый лучший подход при написании "тактируемых" скриптов (запускаемых с частотой кадра - что и имеет место в RW). Так удобнее в отладке и быстрее в работе на системах, где критична частота - три отдельных if работают быстрее, чем if-elseif-else . Ну, и самый универсальный ответ - А МНЕ ТАК УДОБНЕЕ. :olen:

Наконец-то дошли руки проверить утверждение, что три проверки взаимоисключающих условий работают быстрее, чем этажерка if-elseif-else-end. Как и следовало ожидать, как раз-таки этажерка работает быстрее, причем, почти в три раза. Код
Код: Выделить всё
   if max_count > 500000 then
   end
   if max_count < 500000 then
   end
   if max_count == 500000 then
   end
выполнялся 0.121 единицы времени против 0.047 единицы, которые потребовались этажерке:
Код: Выделить всё
   if max_count > 500000 then
   elseif max_count < 500000 then
   else
   end
Если коротко - очередная выдумка от "профессионала".
Поэтому, господа, не верьте бредовому утверждению, что "три отдельных if работают быстрее, чем if-elseif-else" - это не так.

Re: LuaScript - для RS

СообщениеДобавлено: 08.08.2019, 17:17
DB BR Class 101
Тут даже непрофессионал поймёт что в первом случае процессор должен выполнить 3 сравнения вместо 1 или 2 сравнений во втором случае.

Кстати, не много не в тему: объясните мне почему часто пишут сравнение вот в такой форме If (любая константа) (== / <= / =>) переменная ? (например If 0 == var )

Re: LuaScript - для RS

СообщениеДобавлено: 08.08.2019, 17:41
le Sandro
Потому что операция "=" - это присвоение значения переменной var. Например, var=0.
А операция "==" - это сравнение переменной var с каким-либо значением.

Re: LuaScript - для RS

СообщениеДобавлено: 28.10.2019, 12:00
Света
Всем доброго дня!
Есть ли в сообществе программисты на С (и разновидностях этого языка)? У меня возникли сложности с обработкой больших чисел в lua, одним из решений этой проблемы я вижу попытку подключения модуля (или библиотеки) на С, чтобы скрипт мог его запустить, передать данные на обработку и получить результат. То есть, чтобы произвести необходимые расчеты не движком TS, а на стороне. Судя по информации из сети, это делается достаточно просто, но я не владею языком С и даже примерно не представляю, как вообще выполняется запуск библиотек на С и что для этого нужно.
Может ли кто мне помочь?

Добавлено спустя 7 часов 41 минуту 44 секунды:
Исходник модуля на С у меня есть.

Re: LuaScript - для RS

СообщениеДобавлено: 28.10.2019, 23:09
maestro
Одним из решений проблемы больших чисел может являться уменьшение этих чисел (как бы странно это ни звучало) либо разделение их на части. Зависит от того, что в этих числах содержится и для чего это нужно.
Мне один раз нужно было решить задачу ( A - B ) / C, где A, B и C - 64-битные целые числа (в виде структур). Из возможностей платформы были доступны максимум 32-битное целое и 64-битное с плавающей точкой. В процессе решения выяснилось, что более 10 разрядов на деле оказались не нужны, и после определённого шаманства с битами уже хватало типа Double.