LINUX.ORG.RU

Предсказуемость математики и луа

 ,


1

1
function hashStr (nome)
	hours, minutes = GetGameTime()
	count1=hours* 3,1415926535
	count2=minutes* 3,1415926535
	count3=count1*count2
	count3=string.sub(count3, 1, 3)
	count3=string.format("%03d",count3)
	hNik=string.byte(nome,1)
	hNik2=string.byte(nome,2)
	hNome=hNik*hNik2
	hNome=string.sub(hNome, 1, 3)
	hNome=string.format("%03d",hNome)
	r1=string.sub(count3, 1, 1)
	r2=string.sub(hNome, 1, 1)
	r3=string.sub(count3, 2, 2)
	r4=string.sub(hNome, 2, 2)
	r5=string.sub(count3, 3, 3)
	r6=string.sub(hNome, 3, 3)
	r=r1 .. r2 .. r3 .. r4 .. r5 .. r6
	return r
end

hours, minutes = GetGameTime() получает текущие час и минуту в формате: 01 22

Скармливаем слово на одном компе - получаем предсказуемо одинаковый результат. Скармливаем на другом компе получаем тоже предсказуемо одинаковый результат, но не такой, как на предыдущем компе. Это как вообще? Данные одинаковые. Ник один и тот же. Время одно и то же. Результат всегда разный. Это вообще законно?! Время возвращается серверное - одинаковое и там и там.

Перемещено Dimez из general

★★★★★

Последнее исправление: hobbit (всего исправлений: 2)
Ответ на: комментарий от LightDiver

Тебе уже всё ответили, отвечу подругому поводу, вместо перебирания в for элементов можно хранить значение как ключ и искать по ключу типа

-- сейчас так
gmList[индекс] = "значение" 

и так (старый код как есть)


function gmTest (gmTestNome)
	for i=1,#gmList do
		if gmTestNome==gmList[i] then
			gmTestRez = "гм"
			break
		else
			gmTestNome = nil
		end
		i=i+1
	end
	return gmTestRez
end


Можно сделать так

gmList["значение"] = true -- вместо true что угодно кроме nil 

Тогда дальше будет так

unction gmTest (gmTestNome)
    if gmList[gmTestNome] then -- или gmList[gmTestNome] == нечто как доп условие 
       return "гм" 
    else
       return nil;
    end
end

Так ты по ключу сможешь брать значение в котром например хранить контекст или что угодно иное или просто true дабы показав что включ активен, или false/nil дабы просто выключить из диалога что-то конкретное или индекс сообщения там хранить или ссылаться на другую таблицу в котрой эти же сообщения уже лежать по индексам например.

Это я так к слову. Так как в lua можно так

local dialog["Привет я принёс тебе рыбу"] = 
{ quest_ribov_norm=10;
  uspeh="Класс вот тебе денег";
  proval="Мало рыбов неси есчё";
  reject="Мне больше твоих рыбов не надо, я сыт";
  quest_done=false;
}

if dialog[message] then
  if dialog[message].quest_done then
    print(dialog[message].reject);
    return;
  end

  if dialog[message].quest_ribov_norm >= user.num_ribi then
   print(dialog[message].proval)
      dialog[message].quest_done = false;
  else
   print(dialog[message].uspeh)
   dialog[message].quest_done = true;
  end
end

Писал прям тут может криво, но суть думаю тебе понятна. Порой так оч удобно делать. Хотя порой и нет =) Сам смотри.

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

Блин, а шикарная идея. Но это не универсально. С одним ключом без параметров я могу любоую таблиу независимо от содержимого перебрать и выбрать нужное. А если я назначаю ключу сразу трушность, то нужно уже помнить где у меня что.. Хм. Но идея хороша, спасибо. Я подумаю. Я уже начинаю применять такие вот условия, где сама переменная является условием своей трушности, но не очень широко. Я эту возможность узнал три дня назад.

if WorldMapDetailFrame:IsMouseOver() then
LightDiver ★★★★★
() автор топика
Ответ на: комментарий от Ceiling_QB

Кстати, кому не нравится синтаксис Lua, но по какой-то причине нужно на нём писать (и желательно вы один занимаетесь проектом), то можно попробовать Moonscript — такой Coffeescript для Lua. Есть мнение, что он не нужен, но мне норм. Там есть локальные переменные по умолчанию, классы, блоки отступами, +=, и прочие радости.

Есть ещё пачка Лиспов, ML и чего-то ещё, но не знаю, насколько они рабочие.

Ceiling_QB ★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

Смотри, сейчас я делаю вот так:

if testQ[myNome]["инст_начат"] == 1 then
	btnMM[99]:Hide()
	testInf=1
	btnMM[1]:Show()
	if testQ[myNome]["инст_время"] == nil then
		testQ[myNome]["инст_время"] = time()
		timeMMtestI = GetInstanceInfo()
		mioLv = UnitLevel("Player")
		if testQ[myNome][testMM] == nil then
			testQ[myNome]["время_кнопки"] = mmList[timeMMtestI]["время_прохождения_1"]
		else
			if testQ[myNome][testMM][mioLv]["время"] == nil then
				testQ[myNome]["время_кнопки"] = mmList[timeMMtestI]["время_прохождения_1"]
			elseif testQ[myNome][testMM][mioLv]["время"] ~= nil then
				testQ[myNome]["время_кнопки"] = testQ[myNome][testMM][mioLv]["время"]
			end
		end
	end
	curTime = time()
	local tempTime = testQ[myNome]["время_кнопки"]
	tempTime = tonumber(tempTime)
	local tempTimeInst = testQ[myNome]["инст_время"]
	tempTimeInst = tonumber(tempTimeInst)
	curTime = curTime - tempTimeInst
	btnTime = tempTime - curTime

	btnMM[1]:SetText(btnTime)
	elseif testQ[myNome]["инст_начат"] == nil then
		testQ[myNome]["инст_время"] = nil
	end
local tempTime = testQ[myNome]["время_кнопки"]
tempTime = tonumber(tempTime)
local tempTimeInst = testQ[myNome]["инст_время"]
tempTimeInst = tonumber(tempTimeInst)

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

Например: btnTime = tonumber(testQ[myNome]["время_кнопки"]) - curTime

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 3)
Ответ на: комментарий от LightDiver

Я непонял, понял ли я, но

local tempTime = tonumber(testQ[myNome]["время_кнопки"])

Или если поменять в самом значении

testQ[myNome]["время_кнопки"] = tonumber(testQ[myNome]["время_кнопки"])

Например: btnTime = tonumber(testQ[myNome]["время_кнопки"]) - curTime

Так, так и делай =)

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 2)
Ответ на: комментарий от Ceiling_QB

Порой на той же луа проще написать транслятор с того чего тебе надо в луа, ей же транслировать и ей же исполнять результат =)

И ничего не надо тащить, а если луа у тебя прям своя вшитая то парсер подправить и всё, ну для синтаксических мелочей всяких только конечно типа != и подобного. Хотя лучше в это всё не ввязываться.

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

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

if testQ[myNome]["квест_лвл2"][msg1] ~= nil then
	mozhnoLiSdatChislo11=testQ[myNome]["квест_лвл2"][msg1]
else
	msg1=tostring(msg1)
	mozhnoLiSdatChislo11=testQ[myNome]["квест_лвл2"][msg1]
end

Что то вроде такого, но более универсально. Чтобы вообще пофиг было - строка там или число.

LightDiver ★★★★★
() автор топика
Ответ на: комментарий от LightDiver

Если в строке только число то при операциях с числом строка будет автоматически приведена к числу.

local struct = {}
struct['hello']="50";

print(struct.hello + 50)
print(struct.hello - 50)

print(50 + struct.hello)
print(50 - struct.hello)

if struct.hello == 50 then
  print('yes is 50')
end

if struct.hello == "50" then
  print('yes is 50')
end

if struct.hello+50 == "100" then
  print('yes is 100')
end

if 50+struct.hello == 100 then
  print('yes is 100')
end

if type(struct.hello) == 'number' then -- не исполнится
  print('no, it is not number')
end

if type(struct.hello) == 'string' then
  print('yess, struct.hello is string')
end

if type(struct.hello) ~= type(50) then
  print('yes it is different types')
end

print(type(struct.hello))
print(type(50))
dron@gnu:~$ lua test.lua
100
0
100
0
yes is 50
yes is 100
yess, struct.hello is string
yes is different types
string
number
dron@gnu:~$ 

Если ты конкатенируешь число со строкой то число будет приведено к строке.

print("50"+50)
print("50"..50)
dron@gnu:~$ lua test.lua
100
5050

Суть проста и гениальна. И то и то содержат одинаковый тип значения просто в разном представлении типов.

Конечно это не будет работать с видом "гы50"+50

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 6)
Ответ на: комментарий от LINUX-ORG-RU

Простоя играл с типами данных в таблицах и проиграл. Смотри:

["квест_лвл2"] = {
	[1257] = 5,
	["2557"] = 4,
	[1206] = 11,
	[6579] = 3,
	[1956] = 3,
	[150] = 2,
	[2556] = 13,
	[6808] = 4,
	[6584] = 6,
	[1225] = 4,
},

Заметил, да? Я хз как так вышло, но у меня где то в коде квесты иногда прописываются строкой, а иногда числом. И вот берет игрок квест, сдает, а квест не сдается. Я начинаю с ним разбираться. Ага! Да у тебя тут число, а должна быть строка. Исправляю.

На следущий день игрок берет квест, идет сдавать - не сдается!!! Я начинаю разбираться - да у тебя тут строка, а должно быть число…исправляю. На десятой итерации я и задумался что что то тут не так. В итоге сделал проверку и автоматическую смену типа. Вроде начало работать.

LightDiver ★★★★★
() автор топика
Ответ на: комментарий от LightDiver

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

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)
Ответ на: комментарий от LINUX-ORG-RU

Меня уже напрягает ситуация с ютф. Ну это ненормально.

local backMSG = "П0:ПЖ1:М5160" --исходная строка
local revMSG = string.reverse(backMSG) --разворачиваем
for i=1,#backMSG do -от конца строки до начала
  local testB = string.utf8sub(revMSG,i,i) --перебираем символы
  if testB == "М" then --..пока не найдем букву "М"
    break --если нашли - стоп
  end
end
i=i-1 --число равно номер буквы "М" минус один
mnMsg = string.sub(revMSG,1,i) --получаем все от конца строки до буквы "М"
mnMsgOst = string.utf8sub(revMSG,i,#revMSG) --получаем все остальное
mnMsg = string.reverse(mnMsg) --разворачиваем полученное число

И тут я сталкиваюсь с ситуацией. Стринг.саб не работает с кириллицей. Стринг.ютф8саб не работает с числами. Ну это же идиотизм. Может есть проще решение?

Задача: получить число после «М», увеличить его на #, вернуть в исходную строку.

LightDiver ★★★★★
() автор топика
Ответ на: комментарий от LightDiver

string.reverse если у тебя не переопределён переворачивает байты, а один символ в utf-8 может состоять из нескольких байтов. Кирилица состоит из байтов (uint16_t, а не uint8_t) на символ. Их порядок следования должен быть сохранён при развороте строки, а string.reverse() работает только с одиночными байтами, поэтому превращает utf-8 кодировку в мусор.

dron@gnu:~$ lua
Lua 5.2.4  Copyright (C) 1994-2015 Lua.org, PUC-Rio
> print(string.reverse('П0:ПЖ1:М5160'))
0615��:1��:0��
> print(string.reverse('hello my friend'))
dneirf ym olleh

Возьми функцию которая переворачиват utf-8 строку для utf-8

function utf8.reverse(str)
    local out = "";
    for id,code in utf8.codes(str) do
        out = utf8.char(code)..out;
    end
    return out;
end

print(utf8.reverse('П0:ПЖ1:М5160'));
dron@gnu:~$ lua5.4  ttt.lua 
0615М:1ЖП:0П
dron@gnu:~$ 

Работай с utf8 только через utf8 функции, если чего не хватает дописывай сам. Как пример с utf8.reverse так как символ может состоять из 1,2,3,4 байтов.

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 4)
Ответ на: комментарий от LINUX-ORG-RU

Хм.. Message: Interface\AddOns\GuildChat\roll.lua:29: attempt to perform arithmetic on global ‘i’ (a nil value)

А какого хрена он счетчик мне обнуляет?

for i=1,#backMSG do

А вот сбойная строка: i=i-1

То есть после цикла эта глобальная переменная становится пустой.

Я перед брейком ввел вторую переменную глобальну: iKus = i и с ней уже могу работать. Просто интересно почему обнуляется i.

Судя повсему, обнуляет ее именно брейк.

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 1)
Ответ на: комментарий от LightDiver
print("В большую сторону от меньшего")
for i=1,10,1 do -- начало,конец,шаг (шаг по умолчанию равен 1 обычно его вообще не пишут)
    print('A-'..i)
end

print("В меньшую сторону от большего")
for i=10,1,-1 do
    print('B-'..i)
end

print("Через два")

for i=1,10,2 do
    print('C-'..i)
end

-- Домашнее задание:
-- Напишите цикл который будет выводить числа от 10 до 1
-- так что вывод должен быть таким:
-- 10
-- 7
-- 4
-- 1
dron@gnu:~$ lua ttt.lua 
В большую сторону от меньшего
A-1
A-2
A-3
A-4
A-5
A-6
A-7
A-8
A-9
A-10
В меньшую сторону от большего
B-10
B-9
B-8
B-7
B-6
B-5
B-4
B-3
B-2
B-1
Через два
C-1
C-3
C-5
C-7
C-9
dron@gnu:~$ 

А вот сбойная строка: i=i-1

Нет никакого смысла интерировать счётчик внучную

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)
Ответ на: комментарий от LINUX-ORG-RU

А, да. Я как то это не использовал. Не подумал даже, что можно крутить в обратную сторону цикл. Но я эту возможность теоретически знал.

Просто я беру i как номер нужной мне буквы и после цикла пытался ее же использовать. Но после брейка она nil.

Да и если брать цикл в обратную сторону, придется всю логику переделывать. Проверять - работает ли так стринг.саб. Прочитает ли он строку от конца до начала. А так уже все сделано.

if string.find (message, "Кусяо исключает из гильдии") then
    for Zc=1,GetNumGuildMembers(true) do
            local name, rankName, rankIndex, level, classDisplayName, zone, publicNote, officerNote, isOnline, status, class, achievementPoints, achievementRank, isMobile, canSoR, repStanding, guid = GetGuildRosterInfo(Zc)
            local msgZ3n = tonumber (msgZ3)
            if name == "Кусяо" then
                local backMSG = officerNote
                revMSG = string.utf8reverse(backMSG)
                for iKus=1,#backMSG do
                    local testB = string.utf8sub(revMSG,iKus,iKus)
                    if testB == "М" then
                        iKus1 = iKus
                        break
                    end
                    iKus = iKus + 1
                end
                iKus1=iKus1-1
                mnMsg = string.sub(revMSG,1,iKus1)
                mnMsgOst = string.utf8sub(revMSG,iKus1+1,#revMSG)
                mnMsg = string.reverse(mnMsg)
                mnMsg =tonumber(mnMsg)
                mnMsg = mnMsg + 3
                mnMsgOst= string.utf8reverse(mnMsgOst)
                local rezultat = mnMsgOst .. mnMsg
                GuildRosterSetOfficerNote(Zc, rezultat)


            else--конец проверки ника
            end--конец проверки ника

        end
end

Я читаю офицерскую инфу и при определенной фразе прибавляю нужное число.

Лишние прибавления это я пытался понять почему обнуляется переменнная. Я знаю, что их можно убрать.

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 2)
Ответ на: комментарий от LINUX-ORG-RU

А, я кажется понял как сделать лучше. Читаем в цикле от «размер строки» до начала. Если встречаем «М» - запоминаем число. Затем читаем сабом от начала строки до «число» и от «число» до конца строки. Меняем что нужно и склеиваем. Да, так было бы гораздо проще. Потом переделаю.

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 1)
Ответ на: комментарий от LightDiver

Область видимости счётчика ограничена телом цикла.

i = "global" -- глобальная ай
----------------------------
do --создаём локальную область видимости
  local i = "local" -- создадим в локальной области локальную переменную
end
print(i) -- вывод будет 'global'
-----------------------------
do 
    local i = i;
    print(i) -- в локальную переменну. локальной области видимости 
             -- копируем значение глобальной пеменной.
    i = "6451654861561"
end
print(i) -- вывод будет 'global'
------------------------------
i=nil -- уничтожаем глобальную переменную, как будто бы её и небыло

-- тож самое происходит тут
for i=1,10 do
    
end
print(i) -- цикл прошёл, i более не существует
------------------------------


-- А мы её сделаем и даже глобальную!
i = 1;
x = 42
for i=1,10 do -- но что толку ведь в for своя область видимости
    print(i)
    x=i;
end

print(i); -- как был 1 так и остался
print(x); -- а вот тут мы сохранили то что хотели.

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

-- циклу пофиг он будет крутится
for i=1,10 do 
    print(i)
    local i = "hello";--просто после такого
    print(i)
    i = "lololo";--или такого ты потеряешь значение счётчика в текущей итерации
    print(i)
    -- Но лучше так не делать, ибо UB!!!!!!!!!!!!!! )))))))))))
end
LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)
Ответ на: комментарий от LINUX-ORG-RU

Хм… У меня куча мест в коде, где я использую i вне цикла. И ведь это работает как то. Нужно будет перечитать и глянуть чего я там натворил. Спасибо, суть я понял.

LightDiver ★★★★★
() автор топика
Ответ на: комментарий от LINUX-ORG-RU

Ахахахха! Я придумал! Ютф8саб не работает с числами, только со строками. Но! i = tostring(12345); print (string.utf8sub(i,2,2))

Никто же не мешает сделать из чисел строку. Офигенно.

LightDiver ★★★★★
() автор топика
25 июня 2023 г.
Ответ на: комментарий от LINUX-ORG-RU

Слушай, смотри какая фигня:

https://pastebin.com/wnrKVq44

#! /bin/env lua
os.execute("sh servMesg.sh");
while(true) do
local two_null = io.popen("netstat |grep 7776 | awk '{print $3}'", 'r');
 
    for line in two_null:lines() do
        if line ~= nil then
            line = tonumber (line);
            if line > 1000 then
                os.execute("sh alarm.sh");
                print ("количество пакетов превышено");
                print (os.date());
                print (line)
            else
            end
        else
            os.execute("sh alarm.sh");
        end
    end;
    two_null:close();
 
    local two_null1 = io.popen("netstat |grep 7776 | awk '{print $2}'", 'r');
 
    for line in two_null1:lines() do
        if line ~= nil then
            line = tonumber (line);
            if line > 50000 then
                os.execute("sh alarm.sh");
                print ("количество пакетов превышено");
                print (os.date());
                print (line)
            else
            end
        else
            os.execute("sh alarm.sh");
        end
    end;
    two_null1:close();
 
 
    local two_str = io.popen('netstat |grep "7776" | wc -l', 'r');
    local data_two_str = two_str:read('*a');
    local number_data_two_stat = tonumber(data_two_str);
    if number_data_two_stat ~= nil then
        if number_data_two_stat < 2 then
            os.execute("sh alarm1.sh");
            print ("строк меньше двух");
            print (os.date());
            print (number_data_two_stat)
        else
        end
    else
    end
    two_str:close();
    os.execute("sleep 30");
end;
 
lua: ./offn.lua:9: attempt to compare number with nil
stack traceback:
        ./offn.lua:9: in main chunk
        [C]: ?
diver@calculate ~ $ netstat |grep 7776
tcp        0      0 192.168.0.92:55784      sir8.antoshin.exam:7776 ESTABLISHED
tcp        0      0 192.168.0.92:39794      sir8.antoshin.exam:7776 ESTABLISHED

Скрипт проверяет, когда сервер падает или клиент игровой падает. И все работает, кроме первого блока кода. Когда начинает расти Send-Q - третий столбец нетстат, происходит ошибка и скрипт умирает. Не понимать.

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 3)
Ответ на: комментарий от LightDiver

Умня башка болит ничего не соображаю =0

В line строка, но не число. tonumber выдаёт nil всё падает.

Я не запускал. Проверяй после tonumber на if type(line) == 'number' и только тогда действуй дальше, ну или на nil

Я в awk не секу я так понимаю $2 это извлечение столбца. Ну вот почему то.

В любой непонятной ситуации делай дебаг принтами.

Данные из строки можно получить явно из lua типа

local port = 7776;
local stat = io.popen('netstat | grep '..port);
local line = stat:read('*l');
stat:close();
local sock,resv_q, send_q = line:match("(%w+)%s+(%d+)%s+(%d+)%s+");
if sock == 'tcp' then
    print('req='..resv_q,'seq='..send_q);
else
    print("PORT IS DEEEEADDDD");
end

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

Я пока сделал вот так:

 for line in two_null:lines() do
        if line then
            line = tonumber (line);
            if line > 1000 then
                os.execute("sh alarm.sh");
                print ("количество пакетов превышено");
                print (os.date());
                print (line)
            else
            end
        else
            os.execute("sh alarm.sh");
        end
    end;
    two_null:close();

То есть заменил проверку на if line then.. хз поможет ли.

Проблема в том, что оно падает, когда я сплю и я не могу отследить момент падения скрипта. Скорее всего оно даже срабатывает, предупреждает, а потом когда сервер исчезает из проверок - падает. Хер знает.

Хм.. Попробуюеще вывести line принтом и посмотреть что в нем.. Но надо ждать падения серверов. Это еще проблема. Не угадаешь когда он упадет.

Эм.. Слушай, line это два нуля, разделенные переносом строки:

0
0

А как оно вообще у меня тогда работает? Ведь сравнивает и выдает результат.. Что то я намудрил.

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 3)
Ответ на: комментарий от LightDiver

Я выше дал пример парсинга строки через string.match выкинь awk грепни по порту и занеси строку в line потом по приведённому мной шаблону достань переменные тип соединения отослано принято и всё, если тип соединения (tcp) равен nil значит активных портов нет и alarm, если tcp есть то можешь проверять сколько там пакетов туда/сюда.

Эм.. Слушай, line это два нуля, разделенные переносом строки:

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

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LightDiver

Тип так

while(true) do
    local strs = io.popen('netstat | grep 7776');
    local line = strs:read('*l');

    local sock,resv_q, send_q = line:match("(%w+)%s+(%d+)%s+(%d+)%s+");
    if sock == 'tcp' then
       if tonumber(send_q) > 1000 then
           os.execute("sh alarm.sh");
           print ("количество пакетов превышено",send_q, os.date());
       end
       if tonumber(resv_q) > 5000 then
           os.execute("sh alarm.sh");
           print ("количество пакетов превышено",resv_q,os.date());
       end
    else
        print("PORT IS DEEEEADDDD");
        os.execute("sh alarm.sh");
    end
    -- читаем вторую строку если есть, если нет, алярм
    if not strs:read('*l') then
       os.execute("sh alarm.sh");
       print ("соединений меньше двух",os.date());
    end

    strs:close();
    os.execute('sleep 30');
end

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

https://cdn.discordapp.com/attachments/811217303378329643/1122895362202546246/fdfdsfdsafdsafds.png

Жесть какая. Вот откуда оно это высрало?

ха! local strs = io.popen(‘netstat | grep 7776’);

Твой вариант тоже бы падал! Как мы поняли, иногда какая то софтина вклинивается в греп: unix 3 [ ] STREAM CONNECTED 7776

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 2)
Ответ на: комментарий от LINUX-ORG-RU

Я тут решил кое что модифицировать слегка.. Только не надо делать работу за меня. Скажи где я в логике неправ. Смотри: вот управляющий файл:

https://pastebin.com/knSUn9um

Что он должен делать по моей логике: запускать основной файл и проверять время. Если время совпадает минута в минуту - перезапускать основной файл тут же. Чтобы он отработал с нуля.

Теперь основной файл:

https://pastebin.com/fpmY11cT

Что должен делать основной файл: проверяем время, если час не совпадает - выставляем таймер от 9 до 12 минут примерно и выполняем заданный скрипт.

Если совпадает час, но не совпадает минута, выставляем иной таймер (костыль, от этого условия надо избавиться).

Если совпадают минута и час, выставляем таймер в 100-300мс и запускаем по этому таймеру заданный скрипт.

По нажатию один раз должен запускаться управляющий файл, запускать основной файл. Основной файл должен работать. По второму нажатию управляющий файл должен завершать основной файл и завершаться сам…

Но чот нихрена это не работает.

LightDiver ★★★★★
() автор топика
19 декабря 2024 г.
Ответ на: комментарий от LINUX-ORG-RU

Я полтора года пользовался вот этим твоим конфигуром. Создавал новые типа «объекты». Прописывал все внутри. На каждый новый тип кнопок делал отдельный код.

А 20 минут назад у меня что то перещелкнуло в голове и я будтопознал дзен. Я осознал как применять ООП!!! Это же гениально! Это просто чит. Магия. Смотри!

nBtn = {}

function nBtn:new(id,posex,posey,sizex,sizey,message)

    local obj = {}
    self[id] = CreateFrame("Button", nil, iYaBtn[i], "UIPanelButtonTemplate");
    self[id]:SetPoint("CENTER", UIParent,"CENTER",posex, posey)
    self[id]:SetSize(sizex, sizey)
    self[id]:SetText(message)

    function obj:setXY(x,y)
    	self[id]:SetPoint("CENTER", UIParent,"CENTER",x, y) 
    end
    function obj:getID()
    	print(id)
    end

    self[id]:SetScript("OnClick",function(self, button)
        print(id)
    end)
    setmetatable(obj, self)
    self.__index = self; return obj
end

А теперь мы просто присваиваем переменной объект и работаем с ним!!! Мы назначаем новому классу предком этот объект, переназначаем ему функции и вот у нас без лишнего кода новый тип кнопок. С нужными параметрами, функциями. Другими.

Это вообще законно?!

А еще я все эти полтора года прописывал все в функции внутри. Берем айди и пишем там железно параметры прямо в кода. Как можно было так криво работать?! Можно же функции подсунуть таблицу. В таблицу аккуратненько по шаблонам все параметры прописать и все.

Я сейчас читаю старый код в ужасе. Надо все переделывать. У меня уже 36 тысяч строк кода, представь. И если это все переделать.. уфф..

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 2)
Ответ на: комментарий от LightDiver

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

У меня уже 36 тысяч строк кода, представь.

O_o мощно, ну если ты в них хорошо ориентируешься, поздравляю, у тебя хорошая память, я таким похвастаться не могу =)

Я уже не помню ты пользовательский мод для вовки делаешь, или серверный аддон на своём сервере?

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 2)
Ответ на: комментарий от LINUX-ORG-RU

Я делаю пользовательский мод из двух частей:

  1. Клиентская часть у пользователей на компе. В ней как раз тысяч 30 строк без единого комметария. Ее приходится запутывать и обфусцировать, чтобы не читерили.

  2. Серверная часть у меня на компе, принимает команды от клиентской и отправляет сигналы обратно.

https://youtu.be/1qlzmW54woU

Это десяток эвентов различных, квесты со своей механикой - как на видео, например изучение испанского. Реализации валют для рейдов, системы репутаций, работа с фреймами игры, внутреигровая википедия.. И все, что вообще приходит в голову. Самое тяжкое было - как раз отрисовка интерфейса - приходилось все вот эти кнопки отдельным кодом оформлять. А вчера мне как бумкнуло что то в голове - я уже где то месяц пытался понять что такое ООП и нахрена его вообще кто то использует и тут до меня дошло.

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

function cepochkiQuestov(tabella,shablon,kont,lok,x,y,myNome)
    if t_cQ[tabella][testQ[myNome]['puteshestvie']]['sh'] == "поди туда" then
        --тут отработка шаблона "поди туда"
    end
    if t_cQ[tabella][testQ[myNome]['puteshestvie']]['sh'] == "добыча предметов" then
        --код проверки на добычу предметов
    end
end

В итоге формируем таблицу с квестами, а если нам нужно добавить новый квест - просто пишем новый модуль в функцию и все.

И вдрух как все фрагменты пазла сложились в голове и я внезапно понял как надо работать с ООП. Можно же сформировать объекты, определить им поведение, потом переназначать им наследование, менять некоторые функции без дублирования кода, без всего вот этого вот.

Это же какие возможности, работа с данными без постоянных проверок на существания таблиц - заворачиваем все проверки и обработки внутрь объекта и забываем об этом. Я тут себе еще и СУБД слегка пилить начал, хорошо хоть не далеко зашел, надо с ООП переписать.

function addDb(db,key,msg)
	if nsDb == nil then
		nsDb = {}
	end
	if nsDb[db] == nil then
		nsDb[db] = {}
	end	
	if nsDb[db][key] == nil then
		nsDb[db][key] = {}
	end
  	local test
  	local razmerDb = tablelength(nsDb[db][key])
  	if razmerDb > 0 then
	  	for k,v in pairs(nsDb[db][key]) do
	  		if v == msg then
	  			test = 1
	  		end
	  	end
	end
  	if test == nil then
  		local num = tostring(razmerDb+1)
  		nsDb[db][key][num] = msg
  	end
end

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

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 3)

Как-то тему новую открывать не хочется, поэтому спрошу тут, может кто знает.

У меня планируется большая хеш-таблица. number -> (price: number, date: number).

Как с точки зрения занимаемого размера лучше поступить?

Вариат 1: хранить очевидным образом. К примеру my_table[id].price, my_table[id].date. Тут меня смущает то, что каждый объект будет в хипе, будет много посторонних затрат.

Вариант 2: распилить структуру на несколько хеш-таблиц: my_table_price[id], my_table_date[id]. Чисто теоретически могу представить, что для таблиц number -> number в lua может быть оптимизированная структура данных без лишних накладных расходов.

vbr ★★★★★
()
Последнее исправление: vbr (всего исправлений: 1)
Ответ на: комментарий от vbr

если прям упарываться и доступен luajit вместо lua, то рекомендую ffi.

выиграешь не только в памяти, но еще и в скорости кратно.

ffi = require'ffi'
a = ffi.new('double[?]', 1 + n)
for i = 1, n do
  a[i] = i*i
end

src: https://habr.com/en/articles/113804/

ann_eesti
()
Последнее исправление: ann_eesti (всего исправлений: 1)
Ответ на: комментарий от vbr

У меня планируется большая хеш-таблица

Использовать SQLite? Например, https://github.com/shmuz/lsqlite3-s (это улучшенный форк http://lua.sqlite.org от автора интеграции Lua в Far3).

local sqlite3 = require("lsqlite3")

local db = sqlite3.open_memory()

db:exec[[
  CREATE TABLE my_table (id INTEGER PRIMARY KEY, price REAL, date DATE );

  INSERT INTO my_table VALUES (NULL, 1.0, "2024-12-28");
  INSERT INTO my_table VALUES (NULL, 2.0, "2024-12-28");
]]

for row in db:nrows("SELECT * FROM my_table") do
  print(row.id, row.price, row.date)
end
dataman ★★★★★
()
Ответ на: комментарий от vbr

Память это боль. Я сдуру начал сохранять логи чата. Причем друблируя: общий чат, плюс чат каждого персонажа отдельно.

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

Пытаюсь сейчас свою СУБД простенькую сделать и все продумать…

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 1)
Ответ на: комментарий от vbr

Короче, я тут подумал, у меня два хранилища данных уже занимают 1.3 МиБ (1,347,342) 9.7 МиБ (10,157,670)

Вот я и подумал, а что если хранить все в коде? Представь, вся работа с сохранением и чтением данных через функцию. Она сравнивает каждое слово со словарем. Если слова нет - назначаем ему номер в 91й системе счисления. В ней всего 4 символами можно зашифровать около 65 миллионов объектов.

И дальше работаем только по словарю. Это ж какая экономия должна быть или я неправ?

Проблема с числами разве что у меня.. Как бы их сжать..

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 1)
Ответ на: комментарий от vbr

Я сначала тут написал эссе как я провёл это лето, но стёр.

  • 1 Потребление памяти ты не оптимизируешь (сильно), исключение модуль на си
  • 2 Разбиением на отдельные таблицы ты деоптимизируешь доступ к таблицам
  • 3 Да непрерывные последовательности чисел могут хранится в особом виде
    • 3.3 Ты не должен на это надеятся, так как этот особый вид будет зависеть от денных, которые изменчивы
  • 4 Оптимизированное хранение непрерывных последовательностей чисел выигрывает ещё за счёт агрессивного кеширования в L1 L2 L3, но при этом оно же вымывает другие данные, при прифетче одних данных другие удаляются, такова жизнь
  • 5 Данных в куче боятся не надо, никуда ты от них не денешься, с этим разберётся L1 L2 L3 и то если места там хватит
  • 6 Одинаковые строковые данные переиспользуются если у тебя в миллион одинаковых дат, то будет 1 значение и 999999 указателей на него и данные при активном доступе по указателю уже и так будут в кэше, до кучи дело будет доходить далеко не всегда.

Нет смысла теоретизировать в твоём случае, теория не ляжет на несколько реализаций, сгенерируй два файла в одном 10 000 000 значений в 1 таблице, в другом две таблицы по 500 000 значений, засуть в цикл и в него ещё логики всякой, ибо, ifы в циклах для LuaJit например породить такие накладные расходы по прыжкам в vm и трассы и обратно такие что вся экономия на спичках улетит в трубу и Lua5.1 старый, ванильный будет быстрее джита проглатывать условия, не потому что он быстрее, а потому что тупо нет прыжков туда сюда.

Просто сделай тестовые данные, прогони на той версии луа что вшита в программу или на версиях (имплементациях) под которыми всё будет крутиться, выбери лучшие показатели и используй.

Если тебе нужно наиболее эффективное хранение в памяти данных и наиболее эффективный доступ к ним, то это прямой путь к сишному модулю, аля тупо библиотеке, которая будет хранить сверх оптимизированно всё и писать/доставать тоже и это уже не про луа, а вообще любой язык. Но это такое себе, так как сложно переплюнуть то как это уже реализовано в Lua. А если у тебя всё выйдет за рамки пары число/строка по ключу == число. То ты реализуешь ещё одну луа и пойдёшь по 30летним граблям эффективной работы с хеш таблями которые Lua уже по кругу 10 раз обошла :D

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

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

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

Итак, что я посчитал:

Число в луа это 8 байт. Строка в луа это 17 байт+каждый символ. Таблица в луа это 40 байт+содержимое.

Допустим я назначаю каждому слову код. Самое оптимальное, что я нашел - переводкода в 90ю систему счисления.

Допустим, слово «привет» = «1», «мир» = «7{j».

В итоге у меня фраза «Привет мир» будет через словарь записываться, как: «1 7{j»

В незашифрованном виде это 17+10 байт = 27 байт. В зашифрованном 17+5 байт = 23 байта.

На длинных фразах должно работать, вроде.

Как минимум 90 слово я смогу зашифровать одним байтом, затем 8100 слов двумя байтами, затем 710 тысяч слово тремя байтами и 65 миллионов слов 4 байтами.

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

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 2)
Ответ на: комментарий от LINUX-ORG-RU

У меня индексы не непрерывные.

А как мне проверить? Меня интересует объем занимаемых данных в оперативной памяти в первую очередь. При этом к C у меня доступа нет.

vbr ★★★★★
()
Последнее исправление: vbr (всего исправлений: 2)
Ответ на: комментарий от vbr

Я выше вижу что ты про игру говоришь, допустим ту Lua которую они в себя слинковали они не патчили (всякое бывает), узнай версию. Допустим это ванильная 5.1/5.2/5.3/5.4 или Luajit какая. Установи себе аналогичную. И проверяй на ней.

Сгенерируй большие данные типа, для случая когда всё вместе

very_big_table.lua

local ids =
{
    55,66,88,1,6,88,5,77,9 -- у тебя же ID произвольные, типа
}

return
{
   [ids[1]] = {price = 55, date = "2024-12-29"};
   [ids[2]] = {price = 55, date = "2024-12-29"};
   [ids[3]] = {price = 55, date = "2024-12-29"};
   [ids[4]] = {price = 55, date = "2024-12-29"};
   [ids[5]] = {price = 55, date = "2024-12-29"}; 
   [ids[6]] = {price = 55, date = "2024-12-29"};
   [ids[7]] = {price = 55, date = "2024-12-29"};
   [ids[8]] = {price = 55, date = "2024-12-29"};
   [ids[9]] = {price = 55, date = "2024-12-29"};
}

Для него напиши тест, типа

test_1.lua

local ctime = function() return os.clock() * 1000  end
-- посчитаем сколько реального времени жрут важные нам операции
local ttime = function() return os.time()  * 1000 end

local sttime = ttime()
local sctime = ctime()
-- грузишь сгенерированную таблицу монстр таблицу
local data = require("very_big_table")
local ectime = ctime()
local ettime = ttime()

print("Время CPU загрузки дуры",ectime-sctime) -- меньше == лучше
print("Время загрузки дуры",ectime-sctime) -- меньше == лучше


-- обходишь ещё через пары, а не ipairs ибо у тебя разреженно всё
sttime = ttime()
sctime = ctime()
for k,v in pairs(data) do
 -- что-то тут делаешь
 -- что будет делаться с таблицей
end
ectime = ctime()
ettime = ttime()

print("Время CPU обработки дуры",ectime-sctime) -- меньше == лучше
print("Время обработки дуры",ettime-sttime) -- меньше == лучше

-- почистить мусор, на всякий
collectgarbage("collect")

-- смотри сколько скушало памяти в байтах
print("Памяти сейчас скушано", collectgarbage("count")*1024,"байт")

Разные Lua могут давать разные результаты относительно друг друга, но воспроизводимо повторяемые в рамках одной версии

dron@gnu:~/Рабочий-стол$ alua test_1.lua 
☺─────────── luajit ────────────☺
Время CPU загрузки дуры	0.052
Время загрузки дуры	0.052
Время CPU обработки дуры	0.002
Время обработки дуры	0
Памяти сейчас скушано	41564	байт
☺─────────── lua5.1 ────────────☺
Время CPU загрузки дуры	0.067
Время загрузки дуры	0.067
Время CPU обработки дуры	0.0030000000000001
Время обработки дуры	0
Памяти сейчас скушано	31332	байт
☺─────────── lua5.2 ────────────☺
Время CPU загрузки дуры	0.072
Время загрузки дуры	0.072
Время CPU обработки дуры	0.002
Время обработки дуры	0
Памяти сейчас скушано	26701	байт
☺─────────── lua5.3 ────────────☺
Время CPU загрузки дуры	0.065
Время загрузки дуры	0.065
Время CPU обработки дуры	0.0030000000000001
Время обработки дуры	0
Памяти сейчас скушано	27322.0	байт
☺─────────── lua5.4 ────────────☺
Время CPU загрузки дуры	0.057
Время загрузки дуры	0.057
Время CPU обработки дуры	0.0050000000000001
Время обработки дуры	0
Памяти сейчас скушано	25298.0	байт

dron@gnu:~/Рабочий-стол$ cat ~/.local/bin/alua 
#! /bin/env lua
----------------------------------------------------------
local lua = {'luajit','lua5.1','lua5.2','lua5.3','lua5.4'}
----------------------------------------------------------
for idx,val in ipairs(lua) do
     print(('☺─────────── %s ────────────☺'):format(val));
     os.execute(("%s %s"):format(val,table.concat({...},' ')))
end

dron@gnu:~/Рабочий-стол$ 

Можешь в конце теста повесить while true do end открыть htop и глянуть сколько фактически всё потребляет ещё например. Затем пишешь тест для 2 табличек как ты хотел и тож самое, ну и сравнивай результаты, если у тебя много вариантов в голове напиши их все, результаты заполняй в таблицу а затем через table.sort выяви победителя :)

Чёт типа такого. Можешь сам чёнить придумать.

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LightDiver

Число в луа это 8 байт.

Не обязательно, но ладно =)

Строка в луа это 17 байт+каждый символ.

Не всегда, 10 одинаковых строк это 1 строка и 9 указателей на неё. Если строка в таблице плюсуй таблицу, а она резиновая =)

В незашифрованном виде это 17+10 байт = 27 байт. В зашифрованном 17+5 байт = 23 байта.

А, ну вот у тебя ещё дополнительная логика, это уже другое, да.
Ну я тут ничего не скажу тогда, я думал ты хочешь сделать свои lookup таблицы в замен родных hash таблиц, а ты просто свои шифрованные lookup таблицы делаешь как тип данных поверх хештаблей. Ты можешь (если не обрезали тебе это) через string.pack/unpack в бинарник всё упаковывать если хочется. Но это отдельная тема, у тебя уже много написано и на это завязано, я даже соваться не буду =) Просто делай как знаешь, суть в том что тут может быть очень много частных случаев, косвенно, явно завязанных на то да на сё, включая логику, версию, реализацию, кода, игры, модулей, интерпретатора и ещё своя семантика + личные мысли в голове наперёд, нырнёшь в такое и утонешь нахрен, плавать тут можешь только ты =)

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

https://wowwiki-archive.fandom.com/wiki/Lua_object_memory_sizes

Ненене, данные точные. 18 лет ничего в этом плане не менялось. Версия 2008 года. А то и раньше.

This data is from WoW 2.0, Lua 5.1

Вот, возьмем длинную фразу: «Ghostkitty, просто чтобы им играть, надо самому понимать что делаешь, знать рейды, знать рейд и чтобы рейд был собран под тебя»

126 символов. 33 по 1 байту и 93 по 2 байта. Сейчас у меня эта фраза дублируется в личном логе. То есть - умножить на два плюс дата формата: «12/29/24 10:07:26». Еще 17 байт. Итого: (93*2+33)*2+17=455 байт. Полкилобайта на одну фразу.

Все цифры, разделители, кириллицу, латиницу я добавлю в изначальные 90 символов. Дальше пойдут наиболее мелкие и частоупотребляемые слова по 2 байта. Дальше уже по мере встречи в чате. 20 пробелов, 21 слово, дата в юникстайм, ссылка на основной чат из личного цифрой: 21*2+20+8+8=78.

В минимуме я смогу сжать 455 байт уже в 78. По идее должно же сработать.

Правда, еще словарь на пару мегабайт будет, но один раз.

Учитывая, что в частотном анализе латиницы вообще нет, ее можно не добавлять в первые 90 символов, а добавить туда длинные частые слова.

https://paste.techedubyte.com/xksal8alkr

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 8)
Ответ на: комментарий от LINUX-ORG-RU

Да банальное, посмотри первую сотню частотного анализа. Исключай ники - их я шифрую уже отдельно в 4 байта всегда.

Топ2: в

Топ4: и

Топ5: на

Вот такие вот кириллические слова из 1-4 символов перегнать в 1 байт и уже сжатие в 2-8 раз. Просто из ничего.

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 1)