Здравствуйте, гость ( Вход | Регистрация )

11 страниц V « < 4 5 6 7 8 > »   
Ответить в эту темуОткрыть новую тему
> Поиск числа с помощью Findimage, Готовый скрипт
cirus
сообщение 22.9.2017, 12:44
Сообщение #101


**********

Elder
Сообщений: 3.480
Регистрация: 18.8.2014
Группа: Пользователи
Наличность: 26576
Пользователь №: 16.971
Возраст: 29



Исправь:
Код
DeleteImage(buffer[filePath])

На:
Код
deleteimage(buffer[filePath])

Вроде как Кнайт не правил deleteimage. Он хоть работает?
Похоже что не работает, память жрёт.
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 22.9.2017, 15:12
Сообщение #102


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



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

2 темы по двум аналогичным скриптам? Я понимаю, что это твой уголок и бессовестно вторгаться не буду, но как тогда это лучше сделать, чтобы не получился бардак с кучей тем?

Цитата
Если используется getimage, то в findimage указываются координаты 0, 0, ширина, высота. Где ширина и высота это размер изображения полученного getimage.
Т. е. при crds={100,100,250,350}, getimage(100,100,250,350) , а findimage не (100,100,250,350), а (0, 0, 151, 251).

спасибо

Код
for i=1, 10000, 1 do
    v = getimage(0, 0, 1920, 1080, workwindow)
    deleteimage(v)
end

Все исправно работает. Там чуть-чуть растет память, потом уменьшается. Это луа и его сборщик мусора.

-- Удаляем изображение, если делали скриншот.
if options.source == nil then
deleteimage(screenshot)
end
тут была ошибка) поправил.


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
cirus
сообщение 22.9.2017, 15:16
Сообщение #103


**********

Elder
Сообщений: 3.480
Регистрация: 18.8.2014
Группа: Пользователи
Наличность: 26576
Пользователь №: 16.971
Возраст: 29



Передавая в findimage options.path .. symbolName .. options.ext загрузка картинок в память не имеет смысла.
Передавать нужно адрес в памяти, а с учётом что картинок одного символа может быть несколько, то нужен ещё один цикл, для перебора всех адресов.
код
Код
for symbolName, imageAddress in pairs(images) do
    for _, j in pairs(imageAddress) do     -- цикл, если для одного символа несколько картинок
        tmp = {}
        findResult = findimage(
        options.crds[1] .. " " .. options.crds[2] .. " " ..
        options.crds[3] .. " " .. options.crds[4] .. " " ..
        "(" .. j .. ") " ..                         -- передаём j - адрес в памяти
        "%tmp " .. screenshot .. " " .. options.accuracy .. " -1 " .. options.deviation .. " " .. options.abs)
        -- log("symoblName: ".. symbolName .. " findResult: " .. findResult)
        -- проверяем на возрват нуля или ошбики, со стрингом нормально не сравнить.

        if  findResult ~= "0" and not string.find(findResult, "-") then
        -- Добавляем найденные значения в общий результат поисков.
        --table.show(tmp,"tmp")
            for i = 1, #tmp, 1 do
                -- Напрямую вернуть таблицу в функцию нельзя из-за синтаксиса.
                -- FIX. Нужен фикс функции findimage пилота (возвращает координаты стрингом)
                -- после фикса просто удалить "tonumber(parm)" оставив parm.
                table.insert(crdsRaw,{x=tonumber(tmp[i][1]),y=tonumber(tmp[i][2]),symbolName=symbolName})
            end
        end
    end
end

Цитата
2 темы по двум аналогичным скриптам? Я понимаю, что это твой уголок и бессовестно вторгаться не буду, но как тогда это лучше сделать, чтобы не получился бардак с кучей тем?

Имелось ввиду для обсуждения багов отдельная тема, которую потом можно и удалить. Растягивать эту тему постами, которые будут не актуальны после исправления багов смысла нет. Или придётся потом эту тему чистить.
Когда скрипт будет доделан первый пост отредактируешь, останется мой скрипт на языке пилота и твой на луа.
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 22.9.2017, 15:23
Сообщение #104


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



А по адресу можно определить высоту/ширину изображения? Чтобы не передавать кучу параметров вместо одного, если в функцию передается источник изображения? Всмысле по-человечески. Понятно, что можно взять readmem и понеслался...

Цитата
Передавая в findimage options.path .. symbolName .. options.ext загрузка картинок в память не имеет смысла.

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


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
cirus
сообщение 22.9.2017, 15:45
Сообщение #105


**********

Elder
Сообщений: 3.480
Регистрация: 18.8.2014
Группа: Пользователи
Наличность: 26576
Пользователь №: 16.971
Возраст: 29



Код
symbols = {
           "0" = {"zero1", "zero2"},
           "1" = {"1a", "1b"},
           "2" = {"two", "second"}
          }

Нужны квадратные скобки.
Код
symbols = {
           ["0"] = {"zero1", "zero2"},
           ["1"] = {"1a", "1b"},
           ["2"] = {"two", "second"}
          }
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 22.9.2017, 17:28
Сообщение #106


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



Цитата
Нужны квадратные скобки.

Ща переделаю. Не нужны будут кавычки)


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
cirus
сообщение 23.9.2017, 3:09
Сообщение #107


**********

Elder
Сообщений: 3.480
Регистрация: 18.8.2014
Группа: Пользователи
Наличность: 26576
Пользователь №: 16.971
Возраст: 29



Первый пост почистил.
Код
default.loadPath     = nil                -- Путь по которому будут загружены все изображения с указанными расширением. Имя файла будет соответсвовать имени символа.

Для чего это? Оно нигде не используется.
Как сделать чтобы картинки загружались только при первом вызове функции?
Код
fileList = dir(options.path, options.ext)

Исправить на:
Код
fileList = dir(options.path, "*" .. options.ext .. "*")

Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 23.9.2017, 10:21
Сообщение #108


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



Цитата
Для чего это? Оно нигде не используется.
Как сделать чтобы картинки загружались только при первом вызове функции?

Я не смог заставить работать dir. По плану указываешь папку и вся папка загружается. dir у меня почему-то работает только с корнем диска. Кхе... Сейчас сразу завелся... Вызывал без фильтров при тестах. В чем проблема была не понятно.


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 25.9.2017, 19:32
Сообщение #109


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



Кое-что пофиксил, добавил, переработал. В целом можно назвать релиз кандидатом. По функционалу есть вопрос: нужна ли возможность одновременно указать несколько источников изображений? Умолчательные, перечисленные, папку? Несколько папок (подпапки можно уже сейчас)?
Lua распознавание текста
Код
-- Баг:  из-за особенностей костыля финдимиджа создается НЕ локальня переменная tmp.
-- Фикс: изображение не добавлялось в буфер.
-- Фикс: расчет пробела от конечной х координаты.
-- Фикс: очистка буфера после захвата изображения.
-- Фикс: область поиска при источнике из getimage должна быть с нуля.
-- Фикс: искалось только одно изображение из-за недостающего вложенного цикла.
-- Фикс: буфер теперь действительно буферезует.
-- Переработно преобразование из упрощенного синтаксиса в полнеценный. Добавлена защита от дурка (типы данных).
-- Добавлено: загрузка папки с изображениями.
-- Добавлено: ожидание прогрузки изображений (options.secondFrame).
-- Добавлено: чтение из буфера.

do
    -- Символы для поиска.
    -- Возможно указать в двух вариантах синтаксиса: упрощенном и полном.
    -- Упрощенный синтаксис:
    -- В упрощенном варианте синтаксиса допускается не указывать
    -- соответствие имен файлов и строке/символу,
    -- который они обозначают: считается, что они идентичны.
    -- Пример упрощенного синтаксиса:
    -- local symbols = {"0", "1", "2", "3", "a", "b", "c", "test"}
    -- Полный синтаксис:
    -- Полный синтаксис бывает необходим при использовании
    -- нескольких изображений соответсвующих одной и той же строке/символу.
    -- Допускаются переносы строк:
    -- local symbols = {
    --       ["0"] = {"zero1", "zero2"},
    --       ["1"] = {"1a", "1b"},
    --       ["2"] = {"two", "second"}
    --      }
    -- Оба варианта синтаксиса можно сочетать:
    -- local symbols = {"0", "1", ["2"] = {"two", "second"}, "3"}


    local default = {}
    default.crds         = {0, 0, 1920, 1080} -- Координаты поиска
    default.path         = "c:\\image"        -- Папка с картинками
    default.ext          = ".bmp"             -- Расширение картинок
    default.loadFolder   = nil                -- Путь по которому будут загружены все изображения с указанными расширением {path=путь, mask=маска, sub=1|0}(sub - подпапки). Имя файла будет соответсвовать имени символа.
    default.deltaY       = 8                  -- Расстояние между строками (можно указать высоту картинок)
    default.deltaSpace   = 2                  -- Допустимое расстояние между цифрами, иначе будет считаться что это не одно число
    default.accuracy     = 95                 -- Точность поиска для Findimage
    default.deviation    = 3                  -- Погрешность оттенка  для Findimage
    default.wait         = 2                  -- Пауза между поиском картинок, если указать меньше искать будет быстрее, но нагрузит процессор
    default.timeProc     = 2                  -- Время в секундах (может быть не целым) для поиска картинок, если -1 не выйдет из процедуры пока не найдётся хотя бы 1 картинка
    default.repeatImage  = 2                  -- Допустимое смещение координат, если используется несколько видов одной картинки
    default.window       = "workwindow"       -- Метод|хендл_окна в котором происходит поиск (если указан источник изображения(source), то параметр будет проигнорирован)
    default.abs          = 0                  -- Использовать abs координаты.
    default.source       = nil                -- Изображение в котором производится поиск. Должен быть задан таблицей {адрес, ширина, высота}, nil вместо таблицы приведет к захвату изображения с экрана.
    default.bufferAddNew = 1                  -- Добавлять изображения в буфер
    default.bufferIgnore = 0                  -- Игнорировать изображения находящиеся в буфере
    default.bufferUpdate = 0                  -- Обновить изображения содержащиеся в буфере.
    default.secondFrame  = 0                  -- Ожидание прогрузки значений. Изображение будет проанализировано только после secondFrame секунд с первой успешной попытки считать любое из избражений.
    -- набор стандартных символов
    default.symbols      = {["0"]={"0"}, ["1"]={"1"}, ["2"]={"2"}, ["3"]={"3"}, ["4"]={"4"}, ["5"]={"5"}, ["6"]={"6"}, ["7"]={"7"}, ["8"]={"8"}, ["9"]={"9"}}


    -- Буфер
    -- Буфер
    -- Буфер

    local buffer = {} -- Массив с загруженными картинками.
    imageToStringBuffer = {} -- набор функций по управлению буфером.
    -- Полностью очищаем массив.
    function imageToStringBuffer.flush()
        for k,_ in pairs(buffer) do buffer[v] = nil end
    end
    -- Удаляем элемент из буфера
    function imageToStringBuffer.flush(element)
        buffer[element] = nil
    end
    -- Добавляем изображение в буфер
    function imageToStringBuffer.flush(element, val)
        buffer[element] = val
    end
    -- Читаем изображение из буфера
    function imageToStringBuffer.flush(element)
        return buffer[element]
    end


    -- Поиск
    -- Поиск
    -- Поиск

    function imageToString(options)

        -- Проверяем переданные параметры. Если они отсутствуют - подставляем параметры по умолчанию.
        if  options              == nil then local options        = {}                    end
        if  options.crds         == nil then options.crds         = default.crds          end
        if  options.path         == nil then options.path         = default.path          end
        if  options.ext          == nil then options.ext          = default.ext           end
        if  options.loadFolder   == nil then options.loadFolder   = default.loadFolder    end
        if  options.deltaY       == nil then options.deltaY       = default.deltaY        end
        if  options.deltaSpace   == nil then options.deltaSpace   = default.deltaSpace    end
        if  options.accuracy     == nil then options.accuracy     = default.accuracy      end
        if  options.deviation    == nil then options.deviation    = default.deviation     end
        if  options.wait         == nil then options.wait         = default.wait          end
        if  options.timeProc     == nil then options.timeProc     = default.timeProc      end
        if  options.repeatImage  == nil then options.repeatImage  = default.repeatImage   end
        if  options.window       == nil then options.window       = default.window        end
        if  options.abs          == nil then options.abs          = default.abs           end
        if  options.source       == nil then options.source       = default.source        end
        if  options.bufferAddNew == nil then options.bufferAddNew = default.bufferAddNew  end
        if  options.bufferIgnore == nil then options.bufferIgnore = default.bufferIgnore  end
        if  options.bufferUpdate == nil then options.bufferUpdate = default.bufferUpdate  end
        if  options.secondFrame  == nil then options.secondFrame  = default.secondFrame   end
        if  options.symbols      == nil then
            if  options.loadFolder   == nil then
                options.symbols = default.symbols
            else
                options.symbols = {}
            end
        end


        --Добавляем при необходимости обратный слэш в путь.
        if  string.sub(options.path, -1) ~= "\\" then options.path = options.path .. "\\" end

        -- Папка для загрузки изображений не задана, загружаем обычным методом.
        if  options.loadFolder.path == nil then

            -- Преобразуем урощенный синтаксис в полноценный, преобразуем пути в полные.
            do
                local tmp = {} --Массив в который временно помещаются преобразованные данные.
                for symbolName, imageName in pairs(options.symbols) do
                    -- Если занчение задано строкой/числом, приводим его к таблице, дописываем путь до полного.
                    if  type(options.symbols[symbolName]) == "number" then
                        options.symbols[symbolName] = {options.path..tostring(imageName)..options.ext}
                    elseif  type(options.symbols[symbolName]) == "string" then
                        options.symbols[symbolName] = {options.path..imageName..options.ext}
                    --  Значение задано таблицей, преобразоываем числа в строки, дописываем путь до полного.
                    elseif  type(options.symbols[symbolName]) == "table" then
                        for n=1, #options.symbols[symbolName] do
                            if  type(options.symbols[symbolName][n]) == "number" then
                                options.symbols[symbolName][n] = options.path..tostring(options.symbols[symbolName][n])..options.ext
                            elseif  type(options.symbols[symbolName][n]) == "string" then
                                options.symbols[symbolName][n] = options.path..options.symbols[symbolName][n]..options.ext
                            else
                                msg ("Ошибочный тип значения картинок символов в таблице. Остановка скрипта")
                                stop_script()
                            end
                        end
                    else
                        msg ("Ошибочный тип значения картинок символов. Остановка скрипта")
                        stop_script()
                    end

                    -- Если ключ цифровой, преобразуем к строке
                    if  type(symbolName) == "number" then
                        tmp[tostring(symbolName)] = options.symbols[symbolName]
                    elseif  type(symbolName) == "string" then
                        tmp[symbolName] = options.symbols[symbolName]
                    else
                        msg ("Ошибочный тип ключа символов. Остановка скрипта")
                        stop_script()
                    end
                end
                options.symbols = tmp
            end
        else
            -- Загружаем папку с изображениями.
            -- Имя файла = имя символа.
            -- Допускается несколько одинаковых символов в различных подпапках.
            -- Приводим к понятному для пилота виду флаг чтение подпапок.

            -- Прилепляем кавычки к пути чтобы пилот не путал путь и маску.
            options.loadFolder.path = '"'..options.loadFolder.path..'"'
            if options.loadFolder.sub ~= 0 then options.loadFolder.sub = "norecursion" else options.loadFolder.sub = nil end
            -- Приводим маску к надлежащему виду, если она не задана.
            if options.loadFolder.mask == nil then options.loadFolder.mask = "*" end

            fileList = dir(options.loadFolder.path, options.loadFolder.mask, options.loadFolder.sub)
            for k, v in pairs (fileList) do
                -- символ уже существует (несколько вариантов изображения)
                if  options.symbols[v[3]] ~= nil then
                    table.insert(options.symbols[v[3]], v[1])
                else
                    options.symbols[v[3]] = {v[1]}
                end
            end
        end
        --table.show(options.symbols)
        --if 1 then return end



        -- Приводим options.abs к виду пригодному для финдимиджа.
        if     options.abs == 1 then options.abs = "abs"
        elseif options.abs == 0 then options.abs = ""
        end
        --table.show(options.symbols)


        -- Загрузка картинок
        local images={}     --Загружает в память изображения {имя символа, {адреса в памяти}}
        local loadError = 0
        for symbolName, fileList in pairs(options.symbols) do
            images[symbolName] = {}
            for i=1, #fileList, 1 do
                -- Загружен ли файл в буфер, если нет, то подгружаем.
                local filePath = fileList[i]
                if  options.bufferIgnore == 0 and options.bufferUpdate == 0 and buffer[filePath] ~= nil then
                    images[symbolName][i] = buffer[filePath]
                else
                    -- В буфере изображения нет, загружаем с диска.
                    --log(filePath.."В буфере изображения нет, загружаем с диска.")
                    images[symbolName][i] = loadimage(filePath)
                    -- Обновляем загруженное в буфер изображение
                    if  buffer[filePath] ~= nil then
                        deleteimage(buffer[filePath])
                        buffer[filePath] =  images[symbolName][i]
                    elseif options.bufferAddNew == 1 and options.bufferIgnore == 0 then
                        -- Добавляем в буфер новое изображение.
                        buffer[filePath] = images[symbolName][i]
                    end
                end
                -- Поиск ошибок загрузки.
                if images[symbolName][i] < 0  then
                    loadError = loadError + 1
                    log("Image loading fail. Error file: "..filePath..'.')
                end
            end
        end
        -- При загрузке изображений произошли ошибки. Останавливаем скрипт.
        if  loadError > 0 then
            log("Error loading count: "..loadError..'.')
            stop_script()
        end
        --table.show(images)


        local timeout = os.clock() + options.timeProc

        -- log(options.secondFrame)
        -- Таймаут на прогрузку. Поиск для детекта изображений.
        if options.secondFrame > 0 then
            -- Создаем карман области видимости.
            -- Реузльататы блока не нужны для остального скрипта.
            do
                local catch = 0
                -- Если вермя ожидания после детекта не уложится в общий
                -- таймаут, то выходим из цикла без дальшейших попыток найти изображение.
                secondFrameTimeout = timeout - options.secondFrame
                while true do -- выход внутри цикла  timeout < os.clock()
                    local screenshot, width, height = nil, nil, nil
                    if  options.source == nil then
                        screenshot, width, height = getimage(options.crds[1],options.crds[2],options.crds[3],options.crds[4], options.window)
                    else
                        screenshot, width, height = options.source[1],options.source[2],options.source[3]
                    end
                    for symbolName, imageAddressArray in pairs(images) do
                        for _, imageAddress in pairs(imageAddressArray) do
                            local tmp = {}
                            findResult = findimage(
                                0 .. " " .. 0 .. " " ..
                                width .. " " .. height .. " " ..
                                "(" .. imageAddress .. ") " ..
                                "%tmp " .. screenshot .. " " .. options.accuracy .. " -1 " .. options.deviation .. " " .. options.abs)
                            --log("symoblName: ".. symbolName .. " findResult: " .. findResult)
                            -- проверяем на возрват нуля или ошбики, со стрингом нормально не сравнить.
                            if  findResult ~= "0" and not string.find(findResult, "-") then
                                catch = 1
                                --log("break")
                                wait(math.floor(options.secondFrame * 1000))
                                break
                            end
                            -- Время на всю функцию истекло
                            if  timeout - options.secondFrame < os.clock() then
                                return
                            end
                        end
                        if catch == 1 then break end
                    end
                    if catch == 1 then break end
                end
            end
        end


        -- Ищем изображения
        local crdsRaw={} -- Массив со всеми найденными изображениями, возможны дубли, не сортированный.
        repeat  -- Повторяем пока что-то не найдем или не выйдет время на поиск (options.timeProc).
            -- Получаем изображение с экрана, если источник не указан.
            local screenshot, width, height = nil
            if  options.source == nil then
                screenshot, width, height = getimage(options.crds[1],options.crds[2],options.crds[3],options.crds[4], options.window)
            else
                screenshot, width, height = options.source[1],options.source[2],options.source[3]
            end
            --log(screenshot)
            for symbolName, imageAddressArray in pairs(images) do
                for _, imageAddress in pairs(imageAddressArray) do
                    tmp = {}
                    findResult = findimage(
                        0 .. " " .. 0 .. " " ..
                        width .. " " .. height .. " " ..
                        "(" .. imageAddress .. ") " ..
                        "%tmp " .. screenshot .. " " .. options.accuracy .. " -1 " .. options.deviation .. " " .. options.abs)
                    --log("symoblName: ".. symbolName .. " findResult: " .. findResult)
                    -- проверяем на возрват нуля или ошбики, со стрингом нормально не сравнить.
                    if  findResult ~= "0" and not string.find(findResult, "-") then
                        -- Добавляем найденные значения в общий результат поисков.
                        table.show(tmp,"tmp")
                        for i = 1, #tmp, 1 do
                            -- Напрямую вернуть таблицу в функцию нельзя из-за синтаксиса.
                            -- FIX. Нужен фикс функции findimage пилота (возвращает координаты стрингом)
                            -- после фикса просто удалить "tonumber(parm)" оставив parm.
                            table.insert(crdsRaw,{x=tonumber(tmp[i][1]),y=tonumber(tmp[i][2]),xEnd=tonumber(tmp[i][3]),symbolName=symbolName})
                        end
                    end
                end
            end

            -- Удаляем изображение, если делали скриншот.
            if  options.source == nil then
                deleteimage(screenshot)
            end

            --table.show(images, "images")
            --log (#crdsRaw, timeout, os.clock(), options.timeProc)
            log ("until")
            local clock = os.clock()
        until not ((#crdsRaw == 0) and (timeout > clock or options.timeProc == -1))
        --table.show(crdsRaw, "crdsRaw")

        --  Изображения не были найдены, выходим из поиска.
        if  #crdsRaw < 1 then
            return nil
        end
        -- Удаляем дубли.
        local crdsClear={} -- Массив без дублей.
        for i=1, #crdsRaw, 1 do
            local catch = 0 -- Флаг найденного дубля.
            for n=i+1, #crdsRaw, 1 do
                --log(
                --  crdsRaw[i].symbolName.." == "..crdsRaw[n].symbolName.." and "..
                --  math.abs(crdsRaw[i].x - crdsRaw[n].x).." <= "..options.repeatImage.." and "..
                --  math.abs(crdsRaw[i].y - crdsRaw[n].y).." <= "..options.repeatImage
                --)
                if  crdsRaw[i].symbolName == crdsRaw[n].symbolName and
                  math.abs(crdsRaw[i].x - crdsRaw[n].x) <= options.repeatImage and
                  math.abs(crdsRaw[i].y - crdsRaw[n].y) <= options.repeatImage then
                    catch = 1
                    break
                end
            end
            --log(catch)
            if  catch == 0 then -- не дубль, копируем значение в чистый массив.
                table.insert(crdsClear,crdsRaw[i])
            end
        end

        -- Сортируем элементы.
        -- Сортировка происходит, как по X координате,
        -- так и по Y учитывая возможность нескольких строк.
        -- Межстрочный интервал задается с помощью options.deltaY.
        -- Для уплотнения поиска options.deltaY может быть отрицательным.
        -- Отрицательный options.deltaY в первую очередь необходим,
        -- если изображения символов содержат сверху и снизу от символа фон.
        -- crdsClear был предварительно очищен от дублей, теперь сортируется.

        --table.show(crdsClear,"crdsClear")
        --table.toInit(crdsClear)
        table.sort(crdsClear,
            function(a,b)
                if  math.abs(a.y - b.y) <= options.deltaY then
                    if  a.x < b.x then
                        return true
                    else
                        return false
                    end
                else
                    if a.y < b.y then
                        return true
                    else
                        return false
                    end
                end
            end
        )
        --table.show(crdsClear,"crdsClear")

        -- Собираем строку
        --log(#crdsClear)
        local result = {{crdsClear[1].symbolName}}
        local resultX, resultY = 1, 1
        for i=2, #crdsClear, 1 do
            -- Добавляем перенос и символ, возрващем каретку.
            if  crdsClear[i-1].y  + options.deltaY < crdsClear[i].y then
                resultX = resultX + 1
                resultY = 1 -- возврат картеки
                result[resultX]={crdsClear[i].symbolName}
            -- Добавляем пробел и символ
            elseif crdsClear[i-1].xEnd  + options.deltaSpace < crdsClear[i].x then
                resultY = resultY + 1
                result[resultX][resultY] = crdsClear[i].symbolName
            -- Добавляем символ
            else
                result[resultX][resultY] = result[resultX][resultY].. crdsClear[i].symbolName
            end
            --table.show(result,"result")
        end
        --table.show(result,"result")
        return result
    end
end


Погоняй, пожалуйста.

Сообщение отредактировал DarkMaster - 25.9.2017, 23:38


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
cirus
сообщение 26.9.2017, 4:20
Сообщение #110


**********

Elder
Сообщений: 3.480
Регистрация: 18.8.2014
Группа: Пользователи
Наличность: 26576
Пользователь №: 16.971
Возраст: 29



Цитата
if options.loadFolder.path == nil then

Обращение к несуществующему элементу таблицы? Есть только options.path и options.loadFolder.
Код
log ("until")
table.show(tmp,"tmp")

Закомментировать.
Код
--if 1 then return end

Лишнее.
Код
secondFrameTimeout = timeout - options.secondFrame

Переменная глобальная и нигде не используется.
Подозреваю что должна быть тут (если она вообще нужна):
Код
if  timeout - options.secondFrame < os.clock() then

Т. е.
Код
if secondFrameTimeout < os.clock() then

При default.timeProc = -1 и default.secondFrame = 1 сразу выходит из функции.
Цитата
По функционалу есть вопрос: нужна ли возможность одновременно указать несколько источников изображений? Умолчательные, перечисленные, папку? Несколько папок (подпапки можно уже сейчас)?

Если можно подпапки, то не вижу смысла.
Если указать папку без картинок, то пилот закрывается. Хотя это наверное косяки 10 бетки, а не скрипта.
Добавить возможность сохранить изображение, в котором производился поиск (screenshot).
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 26.9.2017, 12:05
Сообщение #111


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



Цитата
Обращение к несуществующему элементу таблицы? Есть только options.path и options.loadFolder.

Вообще в этом и был смысл, т.к. планировалось loadFolder по умолчанию задавать пустой таблицей, но потом я ушел от этого. При этом обращение к несуществующему элементу, если он загружен по умолчанию, но обязательно заданному, если loadFolder использовался при вызове, дало бы нужный результат. Поправил.
Цитата
Переменная глобальная и нигде не используется.
Подозреваю что должна быть тут (если она вообще нужна):

Все правильно понял, локал проставил.
Цитата
При default.timeProc = -1 и default.secondFrame = 1 сразу выходит из функции.

Фиксанул.


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 26.9.2017, 12:17
Сообщение #112


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



Цитата
Если указать папку без картинок, то пилот закрывается. Хотя это наверное косяки 10 бетки, а не скрипта.

Это бетки проблемы. Пока пытался понять на каком этапе вылетает (по факту там скорее всего на один из stop_script() скрипт наступал) вылетать перестало. Сделал принудительную проверку на наличие изображений, если их нет, то будет stop_script(). Т.е. скрипт точно так же выбьет пилот, но теперь будет ясно где и в лог пофлудит.


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 26.9.2017, 12:43
Сообщение #113


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



Если замечаний нет, то можно в первый пост, да начну документацию писать.
Распознавание текста Lua.
Код
// Автор скрипта DarkMaster.
-- Написано по мотивам скрипта Cirus.
-- Тестирование Cirus.
-- Вопросы, баги, предложения на форум
-- в специальную тему по этому скрипту
-- https://forum.uokit.com/index.php?showtopic=30000

-- Фикс: флаг чтения подпапок был инвертирован.
-- Фикс: secondFrameTimeout больше не глобальная и используется по назначению.
-- Фикс: При default.timeProc = -1 и default.secondFrame > 0 не выходит преждевременно из функции.
-- Фикс: Почистил отладочные выводы в лог.
-- Добавлено сохранение изображение в котором происходил поиск.

-- Баг:  из-за особенностей костыля финдимиджа создается НЕ локальня переменная tmp.
-- Фикс: изображение не добавлялось в буфер.
-- Фикс: расчет пробела от конечной х координаты.
-- Фикс: очистка буфера после захвата изображения.
-- Фикс: область поиска при источнике из getimage должна быть с нуля.
-- Фикс: искалось только одно изображение из-за недостающего вложенного цикла.
-- Фикс: буфер теперь действительно буферезует.
-- Переработно преобразование из упрощенного синтаксиса в полнеценный. Добавлена защита от дурка (типы данных).
-- Добавлено: загрузка папки с изображениями.
-- Добавлено: ожидание прогрузки изображений (options.secondFrame).
-- Добавлено: чтение из буфера.

do

-- Раскомментировать, если в отладке будет использоват table.show.
--[[do
    local tab = ""
    local deep = 0
    function table.show(t, comment)
        -- Пишем в лог комментарий.
        deep = deep + 1 -- Уровень вложенности вызовов функции.
        --log(comment .. commentSended .. deep)
        if  comment ~= nil and deep == 1 then
            log(comment)
        end


        if     type(t) == "nil"     then log("table is nil")
        elseif type(t) == "string"  then log('table is string: "'..t..'"')
        elseif type(t) == "number"  then log('table is number: '..t)
        elseif type(t) == "table"   then
            local elementsInTable = 0
            for k,v in pairs(t) do
                if  type (v) == "table" then
                    if type(k) == "string" then
                        log(tab..'table: "'..k..'"')
                    else
                        log(tab..'table: '..k)
                    end
                    tab = tab .. "    "
                    table.show(v)
                    tab = string.sub(tab, 1, -5)
                    elementsInTable = elementsInTable + 1
                else
                    elementsInTable = elementsInTable + 1
                    if type(v) == "string" then v = '"'..v..'"' end
                    if type(k) == "string" then k = '"'..k..'"' end
                    log(tab..""..k.." = "..v)
                end
            end
            if elementsInTable == 0 then log("table is empty") end
        else
            log('table is unknow data type')
        end
        -- Пишем в лог комментарий.
        deep = deep - 1 -- Уровень вложенности вызовов функции.
    end
end
]]


    -- Символы для поиска.
    -- Возможно указать в двух вариантах синтаксиса: упрощенном и полном.
    -- Упрощенный синтаксис:
    -- В упрощенном варианте синтаксиса допускается не указывать
    -- соответствие имен файлов и строке/символу,
    -- который они обозначают: считается, что они идентичны.
    -- Пример упрощенного синтаксиса:
    -- local symbols = {"0", "1", "2", "3", "a", "b", "c", "test"}
    -- Полный синтаксис:
    -- Полный синтаксис бывает необходим при использовании
    -- нескольких изображений соответсвующих одной и той же строке/символу.
    -- Допускаются переносы строк:
    -- local symbols = {
    --       ["0"] = {"zero1", "zero2"},
    --       ["1"] = {"1a", "1b"},
    --       ["2"] = {"two", "second"}
    --      }
    -- Оба варианта синтаксиса можно сочетать:
    -- local symbols = {"0", "1", ["2"] = {"two", "second"}, "3"}


    local default = {}
    default.crds         = {0, 0, 1920, 1080} -- Координаты поиска
    default.path         = "c:\\image"        -- Папка с картинками
    default.ext          = ".bmp"             -- Расширение картинок
    default.loadFolder   = nil                -- Путь по которому будут загружены все изображения с указанной маской {path=путь, mask=маска, sub=1|0}(sub - подпапки). Имя файла будет соответсвовать имени символа.
    default.deltaY       = 8                  -- Расстояние между строками (можно указать высоту картинок)
    default.deltaSpace   = 2                  -- Допустимое расстояние между цифрами, иначе будет считаться что это не одно число
    default.accuracy     = 95                 -- Точность поиска для Findimage
    default.deviation    = 3                  -- Погрешность оттенка  для Findimage
    default.wait         = 2                  -- Пауза между поиском картинок, если указать меньше искать будет быстрее, но нагрузит процессор
    default.timeProc     = 2                  -- Время в секундах (может быть не целым) для поиска картинок, если -1 не выйдет из процедуры пока не найдётся хотя бы 1 картинка
    default.repeatImage  = 2                  -- Допустимое смещение координат, если используется несколько видов одной картинки
    default.window       = "workwindow"       -- Метод|хендл_окна в котором происходит поиск (если указан источник изображения(source), то параметр будет проигнорирован)
    default.abs          = 0                  -- Использовать abs координаты.
    default.source       = nil                -- Изображение в котором производится поиск. Должен быть задан таблицей {адрес, ширина, высота}, nil вместо таблицы приведет к захвату изображения с экрана.
    default.bufferAddNew = 1                  -- Добавлять изображения в буфер
    default.bufferIgnore = 0                  -- Игнорировать изображения находящиеся в буфере
    default.bufferUpdate = 0                  -- Обновить изображения содержащиеся в буфере.
    default.secondFrame  = 0                  -- Ожидание прогрузки значений. Изображение будет проанализировано только после secondFrame секунд с первой успешной попытки считать любое из избражений.
    default.saveImage    = nil                -- Путь по которому будет сохранено изображение в котором происходит поиск.
    -- набор стандартных символов
    default.symbols      = {["0"]={"0"}, ["1"]={"1"}, ["2"]={"2"}, ["3"]={"3"}, ["4"]={"4"}, ["5"]={"5"}, ["6"]={"6"}, ["7"]={"7"}, ["8"]={"8"}, ["9"]={"9"}}


    -- Буфер
    -- Буфер
    -- Буфер

    local buffer = {} -- Массив с загруженными картинками.
    imageToStringBuffer = {} -- набор функций по управлению буфером.
    -- Полностью очищаем массив.
    function imageToStringBuffer.flush()
        for k,_ in pairs(buffer) do buffer[v] = nil end
    end
    -- Удаляем элемент из буфера
    function imageToStringBuffer.flush(element)
        buffer[element] = nil
    end
    -- Добавляем изображение в буфер
    function imageToStringBuffer.flush(element, val)
        buffer[element] = val
    end
    -- Читаем изображение из буфера
    function imageToStringBuffer.flush(element)
        return buffer[element]
    end


    -- Поиск
    -- Поиск
    -- Поиск

    function imageToString(options)

        -- Проверяем переданные параметры. Если они отсутствуют - подставляем параметры по умолчанию.
        if  options              == nil then local options        = {}                    end
        if  options.crds         == nil then options.crds         = default.crds          end
        if  options.path         == nil then options.path         = default.path          end
        if  options.ext          == nil then options.ext          = default.ext           end
        if  options.loadFolder   == nil then options.loadFolder   = default.loadFolder    end
        if  options.deltaY       == nil then options.deltaY       = default.deltaY        end
        if  options.deltaSpace   == nil then options.deltaSpace   = default.deltaSpace    end
        if  options.accuracy     == nil then options.accuracy     = default.accuracy      end
        if  options.deviation    == nil then options.deviation    = default.deviation     end
        if  options.wait         == nil then options.wait         = default.wait          end
        if  options.timeProc     == nil then options.timeProc     = default.timeProc      end
        if  options.repeatImage  == nil then options.repeatImage  = default.repeatImage   end
        if  options.window       == nil then options.window       = default.window        end
        if  options.abs          == nil then options.abs          = default.abs           end
        if  options.source       == nil then options.source       = default.source        end
        if  options.bufferAddNew == nil then options.bufferAddNew = default.bufferAddNew  end
        if  options.bufferIgnore == nil then options.bufferIgnore = default.bufferIgnore  end
        if  options.bufferUpdate == nil then options.bufferUpdate = default.bufferUpdate  end
        if  options.secondFrame  == nil then options.secondFrame  = default.secondFrame   end
        if  options.saveImage    == nil then options.saveImage    = default.saveImage     end
        if  options.symbols      == nil then
            if  options.loadFolder   == nil then
                options.symbols = default.symbols
            else
                options.symbols = {}
            end
        end


        --Добавляем при необходимости обратный слэш в путь.
        if  string.sub(options.path, -1) ~= "\\" then options.path = options.path .. "\\" end

        -- Папка для загрузки изображений не задана, загружаем обычным методом.
        if  options.loadFolder == nil then
            -- Преобразуем урощенный синтаксис в полноценный, преобразуем пути в полные.
            do
                local tmp = {} --Массив в который временно помещаются преобразованные данные.
                for symbolName, imageName in pairs(options.symbols) do
                    -- Если занчение задано строкой/числом, приводим его к таблице, дописываем путь до полного.
                    if  type(options.symbols[symbolName]) == "number" then
                        options.symbols[symbolName] = {options.path..tostring(imageName)..options.ext}
                    elseif  type(options.symbols[symbolName]) == "string" then
                        options.symbols[symbolName] = {options.path..imageName..options.ext}
                    --  Значение задано таблицей, преобразоываем числа в строки, дописываем путь до полного.
                    elseif  type(options.symbols[symbolName]) == "table" then
                        for n=1, #options.symbols[symbolName] do
                            if  type(options.symbols[symbolName][n]) == "number" then
                                options.symbols[symbolName][n] = options.path..tostring(options.symbols[symbolName][n])..options.ext
                            elseif  type(options.symbols[symbolName][n]) == "string" then
                                options.symbols[symbolName][n] = options.path..options.symbols[symbolName][n]..options.ext
                            else
                                msg ("Ошибочный тип значения картинок символов в таблице. Остановка скрипта")
                                stop_script()
                            end
                        end
                    else
                        msg ("Ошибочный тип значения картинок символов. Остановка скрипта")
                        stop_script()
                    end

                    -- Если ключ цифровой, преобразуем к строке
                    if  type(symbolName) == "number" then
                        tmp[tostring(symbolName)] = options.symbols[symbolName]
                    elseif  type(symbolName) == "string" then
                        tmp[symbolName] = options.symbols[symbolName]
                    else
                        msg ("Ошибочный тип ключа символов. Остановка скрипта")
                        stop_script()
                    end
                end
                options.symbols = tmp
            end
        else
            -- Загружаем папку с изображениями.
            -- Имя файла = имя символа.
            -- Допускается несколько одинаковых символов в различных подпапках.
            -- Приводим к понятному для пилота виду флаг чтение подпапок.

            -- Прилепляем кавычки к пути чтобы пилот не путал путь и маску.
            options.loadFolder.path = '"'..options.loadFolder.path..'"'
            if options.loadFolder.sub == 1 then options.loadFolder.sub = nil else options.loadFolder.sub = "norecursion" end
            -- Приводим маску к надлежащему виду, если она не задана.
            if options.loadFolder.mask == nil then options.loadFolder.mask = "*" end
            fileList = dir(options.loadFolder.path, options.loadFolder.mask, options.loadFolder.sub)
            --table.show(fileList, "fileList")
            for k, v in pairs (fileList) do
                -- символ уже существует (несколько вариантов изображения)
                if  options.symbols[v[3]] ~= nil then
                    table.insert(options.symbols[v[3]], v[1])
                else
                    options.symbols[v[3]] = {v[1]}
                end
            end
        end
        --table.show(options.symbols)


        -- Приводим options.abs к виду пригодному для финдимиджа.
        if      options.abs == 1 then options.abs = "abs"
        elseif  options.abs == 0 then options.abs = ""
        end


        -- Загрузка картинок
        local images={}     --Загружает в память изображения {имя символа, {адреса в памяти}}
        local loadError = 0
        for symbolName, fileList in pairs(options.symbols) do
            images[symbolName] = {}
            for i=1, #fileList, 1 do
                -- Загружен ли файл в буфер, если нет, то подгружаем.
                local filePath = fileList[i]
                if  options.bufferIgnore == 0 and options.bufferUpdate == 0 and buffer[filePath] ~= nil then
                    images[symbolName][i] = buffer[filePath]
                else
                    -- В буфере изображения нет, загружаем с диска.
                    --log(filePath.."В буфере изображения нет, загружаем с диска.")
                    images[symbolName][i] = loadimage(filePath)
                    -- Обновляем загруженное в буфер изображение
                    if  buffer[filePath] ~= nil then
                        deleteimage(buffer[filePath])
                        buffer[filePath] =  images[symbolName][i]
                    elseif options.bufferAddNew == 1 and options.bufferIgnore == 0 then
                        -- Добавляем в буфер новое изображение.
                        buffer[filePath] = images[symbolName][i]
                    end
                end
                -- Поиск ошибок загрузки.
                if images[symbolName][i] < 0  then
                    loadError = loadError + 1
                    log("Image loading fail. Error file: "..filePath..'.')
                end
            end
        end
        -- При загрузке изображений произошли ошибки. Останавливаем скрипт.
        if  loadError > 0 then
            log("Error loading count: "..loadError..'.')
            stop_script()
        end
        if  images == nil then
            log("Файлы изображений не найдены. Скрипт остановлен.")
            stop_script()
        end
        --table.show(images,"images")


        local timeout = os.clock() + options.timeProc


        -- log(options.secondFrame)
        -- Таймаут на прогрузку. Поиск для детекта изображений.
        if options.secondFrame > 0 then
            -- Создаем карман области видимости.
            -- Реузльататы блока не нужны для остального скрипта.
            do
                local catch = 0
                -- Если вермя ожидания после детекта не уложится в общий
                -- таймаут, то выходим из цикла без дальшейших попыток найти изображение.
                local secondFrameTimeout = timeout - options.secondFrame
                while true do -- выход внутри цикла  timeout < os.clock()
                    local screenshot, width, height = nil, nil, nil
                    if  options.source == nil then
                        screenshot, width, height = getimage(options.crds[1],options.crds[2],options.crds[3],options.crds[4], options.window)
                    else
                        screenshot, width, height = options.source[1],options.source[2],options.source[3]
                    end
                    for symbolName, imageAddressArray in pairs(images) do
                        for _, imageAddress in pairs(imageAddressArray) do
                            local tmp = {}
                            findResult = findimage(
                                0 .. " " .. 0 .. " " ..
                                width .. " " .. height .. " " ..
                                "(" .. imageAddress .. ") " ..
                                "%tmp " .. screenshot .. " " .. options.accuracy .. " -1 " .. options.deviation .. " " .. options.abs)
                            --log("symoblName: ".. symbolName .. " findResult: " .. findResult)
                            -- проверяем на возрват нуля или ошбики, со стрингом нормально не сравнить.
                            if  findResult ~= "0" and not string.find(findResult, "-") then
                                catch = 1
                                --log("break")
                                wait(math.floor(options.secondFrame * 1000))
                                break
                            end
                            -- Время на всю функцию истекло
                            if  secondFrameTimeout < os.clock() and options.timeProc ~= -1 then
                                return
                            end
                        end
                        if catch == 1 then break end
                    end
                    if catch == 1 then break end
                end
            end
        end


        -- Ищем изображения
        local crdsRaw={} -- Массив со всеми найденными изображениями, возможны дубли, не сортированный.
        repeat  -- Повторяем пока что-то не найдем или не выйдет время на поиск (options.timeProc).
            -- Получаем изображение с экрана, если источник не указан.
            local screenshot, width, height = nil
            if  options.source == nil then
                screenshot, width, height = getimage(options.crds[1],options.crds[2],options.crds[3],options.crds[4], options.window)
            else
                screenshot, width, height = options.source[1],options.source[2],options.source[3]
            end
            --log(screenshot)
            for symbolName, imageAddressArray in pairs(images) do
                for _, imageAddress in pairs(imageAddressArray) do
                    tmp = {}
                    findResult = findimage(
                        0 .. " " .. 0 .. " " ..
                        width .. " " .. height .. " " ..
                        "(" .. imageAddress .. ") " ..
                        "%tmp " .. screenshot .. " " .. options.accuracy .. " -1 " .. options.deviation .. " " .. options.abs)
                    --log("symoblName: ".. symbolName .. " findResult: " .. findResult)
                    -- проверяем на возрват нуля или ошбики, со стрингом нормально не сравнить.
                    if  findResult ~= "0" and not string.find(findResult, "-") then
                        -- Добавляем найденные значения в общий результат поисков.
                        --table.show(tmp,"tmp")
                        for i = 1, #tmp, 1 do
                            -- Напрямую вернуть таблицу в функцию нельзя из-за синтаксиса.
                            -- FIX. Нужен фикс функции findimage пилота (возвращает координаты стрингом)
                            -- после фикса просто удалить "tonumber(parm)" оставив parm.
                            table.insert(crdsRaw,{x=tonumber(tmp[i][1]),y=tonumber(tmp[i][2]),xEnd=tonumber(tmp[i][3]),symbolName=symbolName})
                        end
                    end
                end
            end

            -- Сохраняем изображение.
            if  options.saveImage ~= nil then
                saveimage(screenshot, options.saveImage)
            end
            -- Удаляем изображение, если получали его из приложения.
            if  options.source == nil then
                deleteimage(screenshot)
            end

            --table.show(images, "images")
            --log (#crdsRaw, timeout, os.clock(), options.timeProc)
            --log ("until")
            local clock = os.clock()
        until not ((#crdsRaw == 0) and (timeout > clock or options.timeProc == -1))
        --table.show(crdsRaw, "crdsRaw")

        --  Изображения не были найдены, выходим из поиска.
        if  #crdsRaw < 1 then
            return nil
        end
        -- Удаляем дубли.
        local crdsClear={} -- Массив без дублей.
        for i=1, #crdsRaw, 1 do
            local catch = 0 -- Флаг найденного дубля.
            for n=i+1, #crdsRaw, 1 do
                --log(
                --  crdsRaw[i].symbolName.." == "..crdsRaw[n].symbolName.." and "..
                --  math.abs(crdsRaw[i].x - crdsRaw[n].x).." <= "..options.repeatImage.." and "..
                --  math.abs(crdsRaw[i].y - crdsRaw[n].y).." <= "..options.repeatImage
                --)
                if  crdsRaw[i].symbolName == crdsRaw[n].symbolName and
                  math.abs(crdsRaw[i].x - crdsRaw[n].x) <= options.repeatImage and
                  math.abs(crdsRaw[i].y - crdsRaw[n].y) <= options.repeatImage then
                    catch = 1
                    break
                end
            end
            --log(catch)
            if  catch == 0 then -- не дубль, копируем значение в чистый массив.
                table.insert(crdsClear,crdsRaw[i])
            end
        end

        -- Сортируем элементы.
        -- Сортировка происходит, как по X координате,
        -- так и по Y учитывая возможность нескольких строк.
        -- Межстрочный интервал задается с помощью options.deltaY.
        -- Для уплотнения поиска options.deltaY может быть отрицательным.
        -- Отрицательный options.deltaY в первую очередь необходим,
        -- если изображения символов содержат сверху и снизу от символа фон.
        -- crdsClear был предварительно очищен от дублей, теперь сортируется.

        --table.show(crdsClear,"crdsClear")
        --table.toInit(crdsClear)
        table.sort(crdsClear,
            function(a,b)
                if  math.abs(a.y - b.y) <= options.deltaY then
                    if  a.x < b.x then
                        return true
                    else
                        return false
                    end
                else
                    if a.y < b.y then
                        return true
                    else
                        return false
                    end
                end
            end
        )
        --table.show(crdsClear,"crdsClear")

        -- Собираем строку
        --log(#crdsClear)
        local result = {{crdsClear[1].symbolName}}
        local resultX, resultY = 1, 1
        for i=2, #crdsClear, 1 do
            -- Добавляем перенос и символ, возрващем каретку.
            if  crdsClear[i-1].y  + options.deltaY < crdsClear[i].y then
                resultX = resultX + 1
                resultY = 1 -- возврат картеки
                result[resultX]={crdsClear[i].symbolName}
            -- Добавляем пробел и символ
            elseif crdsClear[i-1].xEnd  + options.deltaSpace < crdsClear[i].x then
                resultY = resultY + 1
                result[resultX][resultY] = crdsClear[i].symbolName
            -- Добавляем символ
            else
                result[resultX][resultY] = result[resultX][resultY].. crdsClear[i].symbolName
            end
            --table.show(result,"result")
        end
        --table.show(result,"result")
        return result
    end
end


Сообщение отредактировал DarkMaster - 26.9.2017, 12:45


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
cirus
сообщение 26.9.2017, 14:22
Сообщение #114


**********

Elder
Сообщений: 3.480
Регистрация: 18.8.2014
Группа: Пользователи
Наличность: 26576
Пользователь №: 16.971
Возраст: 29



Цитата
// Автор

Исправь на комментарий луа --
Добавь --lua в начало скрипта.
Если маска задана: mask="bmp", то не найдёт картинки. Допиши проверку на наличие и добавление * к маске, если * нет.
Код
result = imageToString{crds={33, 189 ,292, 255}}
result = imageToString{crds={33, 189 ,292, 255}}

При втором вызове функции массив с картинками пуст.
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 26.9.2017, 15:32
Сообщение #115


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



Цитата
Исправь на комментарий луа --

Исправил через секунду после поста) Слишком быстрый ты (IMG:style_emoticons/default/smile.gif)
Цитата
Если маска задана: mask="bmp", то не найдёт картинки. Допиши проверку на наличие и добавление * к маске, если * нет.

И не должно находить. Это стандартный синтаксис маски, где буквенное сочетание предполагает полное совпадение, а возможные отсутствующие символы задаются с помощью * - (любое количество любых символов) и ? - один неизвестный символ. Я даже хз как этот синтаксис называется и где его полная версия, но эти подстановки еще со времен 95 винды помню.


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 26.9.2017, 16:27
Сообщение #116


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



Фишки луа, которые не учел. Тут же arr={} не таблица, а только ссылка на таблицу и копирование arr2=arr1 не проходит - данные не копируются.
Распознавание текста Lua
Код
--lua
-- Автор скрипта DarkMaster.
-- Написано по мотивам скрипта Cirus.
-- Тестирование Cirus.
-- Вопросы, баги, предложения на форум
-- в специальную тему по этому скрипту
-- https://forum.uokit.com/index.php?showtopic=30000

-- Фикс: символы по умолчанию больше не изменятся, сделано корректное копирование массива.

-- Фикс: флаг чтения подпапок был инвертирован.
-- Фикс: secondFrameTimeout больше не глобальная и используется по назначению.
-- Фикс: При default.timeProc = -1 и default.secondFrame > 0 не выходит преждевременно из функции.
-- Фикс: Почистил отладочные выводы в лог.
-- Добавлено сохранение изображение в котором происходил поиск.

-- Баг:  из-за особенностей костыля финдимиджа создается НЕ локальня переменная tmp.
-- Фикс: изображение не добавлялось в буфер.
-- Фикс: расчет пробела от конечной х координаты.
-- Фикс: очистка буфера после захвата изображения.
-- Фикс: область поиска при источнике из getimage должна быть с нуля.
-- Фикс: искалось только одно изображение из-за недостающего вложенного цикла.
-- Фикс: буфер теперь действительно буферезует.
-- Переработно преобразование из упрощенного синтаксиса в полнеценный. Добавлена защита от дурка (типы данных).
-- Добавлено: загрузка папки с изображениями.
-- Добавлено: ожидание прогрузки изображений (options.secondFrame).
-- Добавлено: чтение из буфера.

do

    -- Раскомментировать, если в отладке будет использоват table.show.
    --[[do
        local tab = ""
        local deep = 0
        function table.show(t, comment)
            -- Пишем в лог комментарий.
            deep = deep + 1 -- Уровень вложенности вызовов функции.
            --log(comment .. commentSended .. deep)
            if  comment ~= nil and deep == 1 then
                log(comment)
            end


            if     type(t) == "nil"     then log("table is nil")
            elseif type(t) == "string"  then log('table is string: "'..t..'"')
            elseif type(t) == "number"  then log('table is number: '..t)
            elseif type(t) == "table"   then
                local elementsInTable = 0
                for k,v in pairs(t) do
                    if  type (v) == "table" then
                        if type(k) == "string" then
                            log(tab..'table: "'..k..'"')
                        else
                            log(tab..'table: '..k)
                        end
                        tab = tab .. "    "
                        table.show(v)
                        tab = string.sub(tab, 1, -5)
                        elementsInTable = elementsInTable + 1
                    else
                        elementsInTable = elementsInTable + 1
                        if type(v) == "string" then v = '"'..v..'"' end
                        if type(k) == "string" then k = '"'..k..'"' end
                        log(tab..""..k.." = "..v)
                    end
                end
                if elementsInTable == 0 then log("table is empty") end
            else
                log('table is unknow data type')
            end
            -- Пишем в лог комментарий.
            deep = deep - 1 -- Уровень вложенности вызовов функции.
        end
    end
    ]]

    local function deepcopy(orig)
        local orig_type = type(orig)
        local copy
        if orig_type == 'table' then
            copy = {}
            for orig_key, orig_value in next, orig, nil do
                copy[deepcopy(orig_key)] = deepcopy(orig_value)
            end
            setmetatable(copy, deepcopy(getmetatable(orig)))
        else -- number, string, boolean, etc
            copy = orig
        end
        return copy
    end

    -- Символы для поиска.
    -- Возможно указать в двух вариантах синтаксиса: упрощенном и полном.
    -- Упрощенный синтаксис:
    -- В упрощенном варианте синтаксиса допускается не указывать
    -- соответствие имен файлов и строке/символу,
    -- который они обозначают: считается, что они идентичны.
    -- Пример упрощенного синтаксиса:
    -- local symbols = {"0", "1", "2", "3", "a", "b", "c", "test"}
    -- Полный синтаксис:
    -- Полный синтаксис бывает необходим при использовании
    -- нескольких изображений соответсвующих одной и той же строке/символу.
    -- Допускаются переносы строк:
    -- local symbols = {
    --       ["0"] = {"zero1", "zero2"},
    --       ["1"] = {"1a", "1b"},
    --       ["2"] = {"two", "second"}
    --      }
    -- Оба варианта синтаксиса можно сочетать:
    -- local symbols = {"0", "1", ["2"] = {"two", "second"}, "3"}


    local default = {}
    default.crds         = {0, 0, 1920, 1080} -- Координаты поиска
    default.path         = "c:\\image"        -- Папка с картинками
    default.ext          = ".bmp"             -- Расширение картинок
    default.loadFolder   = nil                -- Путь по которому будут загружены все изображения с указанной маской {path=путь, mask=маска, sub=1|0}(sub - подпапки). Имя файла будет соответсвовать имени символа.
    default.deltaY       = 8                  -- Расстояние между строками (можно указать высоту картинок)
    default.deltaSpace   = 2                  -- Допустимое расстояние между цифрами, иначе будет считаться что это не одно число
    default.accuracy     = 95                 -- Точность поиска для Findimage
    default.deviation    = 3                  -- Погрешность оттенка  для Findimage
    default.wait         = 2                  -- Пауза между поиском картинок, если указать меньше искать будет быстрее, но нагрузит процессор
    default.timeProc     = 2                  -- Время в секундах (может быть не целым) для поиска картинок, если -1 не выйдет из процедуры пока не найдётся хотя бы 1 картинка
    default.repeatImage  = 2                  -- Допустимое смещение координат, если используется несколько видов одной картинки
    default.window       = "workwindow"       -- Метод|хендл_окна в котором происходит поиск (если указан источник изображения(source), то параметр будет проигнорирован)
    default.abs          = 0                  -- Использовать abs координаты.
    default.source       = nil                -- Изображение в котором производится поиск. Должен быть задан таблицей {адрес, ширина, высота}, nil вместо таблицы приведет к захвату изображения с экрана.
    default.bufferAddNew = 1                  -- Добавлять изображения в буфер
    default.bufferIgnore = 0                  -- Игнорировать изображения находящиеся в буфере
    default.bufferUpdate = 0                  -- Обновить изображения содержащиеся в буфере.
    default.secondFrame  = 0                  -- Ожидание прогрузки значений. Изображение будет проанализировано только после secondFrame секунд с первой успешной попытки считать любое из избражений.
    default.saveImage    = nil                -- Путь по которому будет сохранено изображение в котором происходит поиск.
    -- набор стандартных символов
    default.symbols      = {["0"]={"0"}, ["1"]={"1"}, ["2"]={"2"}, ["3"]={"3"}, ["4"]={"4"}, ["5"]={"5"}, ["6"]={"6"}, ["7"]={"7"}, ["8"]={"8"}, ["9"]={"9"}}


    -- Буфер
    -- Буфер
    -- Буфер

    local buffer = {} -- Массив с загруженными картинками.
    imageToStringBuffer = {} -- набор функций по управлению буфером.
    -- Полностью очищаем массив.
    function imageToStringBuffer.flush()
        for k,_ in pairs(buffer) do buffer[v] = nil end
    end
    -- Удаляем элемент из буфера
    function imageToStringBuffer.flush(element)
        buffer[element] = nil
    end
    -- Добавляем изображение в буфер
    function imageToStringBuffer.flush(element, val)
        buffer[element] = val
    end
    -- Читаем изображение из буфера
    function imageToStringBuffer.flush(element)
        return buffer[element]
    end


    -- Поиск
    -- Поиск
    -- Поиск

    function imageToString(options)

        -- Проверяем переданные параметры. Если они отсутствуют - подставляем параметры по умолчанию.
        if  options              == nil then local options        = {}                    end
        if  options.crds         == nil then options.crds         = default.crds          end
        if  options.path         == nil then options.path         = default.path          end
        if  options.ext          == nil then options.ext          = default.ext           end
        if  options.loadFolder   == nil then options.loadFolder   = default.loadFolder    end
        if  options.deltaY       == nil then options.deltaY       = default.deltaY        end
        if  options.deltaSpace   == nil then options.deltaSpace   = default.deltaSpace    end
        if  options.accuracy     == nil then options.accuracy     = default.accuracy      end
        if  options.deviation    == nil then options.deviation    = default.deviation     end
        if  options.wait         == nil then options.wait         = default.wait          end
        if  options.timeProc     == nil then options.timeProc     = default.timeProc      end
        if  options.repeatImage  == nil then options.repeatImage  = default.repeatImage   end
        if  options.window       == nil then options.window       = default.window        end
        if  options.abs          == nil then options.abs          = default.abs           end
        if  options.source       == nil then options.source       = default.source        end
        if  options.bufferAddNew == nil then options.bufferAddNew = default.bufferAddNew  end
        if  options.bufferIgnore == nil then options.bufferIgnore = default.bufferIgnore  end
        if  options.bufferUpdate == nil then options.bufferUpdate = default.bufferUpdate  end
        if  options.secondFrame  == nil then options.secondFrame  = default.secondFrame   end
        if  options.saveImage    == nil then options.saveImage    = default.saveImage     end
        if  options.symbols      == nil then
            if  options.loadFolder   == nil then
                options.symbols = deepcopy(default.symbols)
            else
                options.symbols = {}
            end
        end

        --Добавляем при необходимости обратный слэш в путь.
        if  string.sub(options.path, -1) ~= "\\" then options.path = options.path .. "\\" end

        -- Папка для загрузки изображений не задана, загружаем обычным методом.
        if  options.loadFolder == nil then
            -- Преобразуем урощенный синтаксис в полноценный, преобразуем пути в полные.
            do
                local tmp = {} --Массив в который временно помещаются преобразованные данные.
                for symbolName, imageName in pairs(options.symbols) do
                    -- Если занчение задано строкой/числом, приводим его к таблице, дописываем путь до полного.
                    if  type(options.symbols[symbolName]) == "number" then
                        options.symbols[symbolName] = {options.path..tostring(imageName)..options.ext}
                    elseif  type(options.symbols[symbolName]) == "string" then
                        options.symbols[symbolName] = {options.path..imageName..options.ext}
                    --  Значение задано таблицей, преобразоываем числа в строки, дописываем путь до полного.
                    elseif  type(options.symbols[symbolName]) == "table" then
                        for n=1, #options.symbols[symbolName] do
                            if  type(options.symbols[symbolName][n]) == "number" then
                                options.symbols[symbolName][n] = options.path..tostring(options.symbols[symbolName][n])..options.ext
                            elseif  type(options.symbols[symbolName][n]) == "string" then
                                options.symbols[symbolName][n] = options.path..options.symbols[symbolName][n]..options.ext
                            else
                                msg ("Ошибочный тип значения картинок символов в таблице. Остановка скрипта")
                                stop_script()
                            end
                        end
                    else
                        msg ("Ошибочный тип значения картинок символов. Остановка скрипта")
                        stop_script()
                    end

                    -- Если ключ цифровой, преобразуем к строке
                    if  type(symbolName) == "number" then
                        tmp[tostring(symbolName)] = options.symbols[symbolName]
                    elseif  type(symbolName) == "string" then
                        tmp[symbolName] = options.symbols[symbolName]
                    else
                        msg ("Ошибочный тип ключа символов. Остановка скрипта")
                        stop_script()
                    end
                end
                options.symbols = tmp
            end
        else
            -- Загружаем папку с изображениями.
            -- Имя файла = имя символа.
            -- Допускается несколько одинаковых символов в различных подпапках.
            -- Приводим к понятному для пилота виду флаг чтение подпапок.

            -- Прилепляем кавычки к пути чтобы пилот не путал путь и маску.
            options.loadFolder.path = '"'..options.loadFolder.path..'"'
            if options.loadFolder.sub == 1 then options.loadFolder.sub = nil else options.loadFolder.sub = "norecursion" end
            -- Приводим маску к надлежащему виду, если она не задана.
            if options.loadFolder.mask == nil then options.loadFolder.mask = "*" end
            fileList = dir(options.loadFolder.path, options.loadFolder.mask, options.loadFolder.sub)
            --table.show(fileList, "fileList")
            for k, v in pairs (fileList) do
                -- символ уже существует (несколько вариантов изображения)
                if  options.symbols[v[3]] ~= nil then
                    table.insert(options.symbols[v[3]], v[1])
                else
                    options.symbols[v[3]] = {v[1]}
                end
            end
        end
        --table.show(options.symbols)


        -- Приводим options.abs к виду пригодному для финдимиджа.
        if      options.abs == 1 then options.abs = "abs"
        elseif  options.abs == 0 then options.abs = ""
        end


        -- Загрузка картинок
        local images={}     --Загружает в память изображения {имя символа, {адреса в памяти}}
        local loadError = 0
        for symbolName, fileList in pairs(options.symbols) do
            images[symbolName] = {}
            for i=1, #fileList, 1 do
                -- Загружен ли файл в буфер, если нет, то подгружаем.
                local filePath = fileList[i]
                if  options.bufferIgnore == 0 and options.bufferUpdate == 0 and buffer[filePath] ~= nil then
                    images[symbolName][i] = buffer[filePath]
                else
                    -- В буфере изображения нет, загружаем с диска.
                    --log(filePath.."В буфере изображения нет, загружаем с диска.")
                    images[symbolName][i] = loadimage(filePath)
                    -- Обновляем загруженное в буфер изображение
                    if  buffer[filePath] ~= nil then
                        deleteimage(buffer[filePath])
                        buffer[filePath] =  images[symbolName][i]
                    elseif options.bufferAddNew == 1 and options.bufferIgnore == 0 then
                        -- Добавляем в буфер новое изображение.
                        buffer[filePath] = images[symbolName][i]
                    end
                end
                -- Поиск ошибок загрузки.
                if images[symbolName][i] < 0  then
                    loadError = loadError + 1
                    log("Image loading fail. Error file: "..filePath..'.')
                end
            end
        end
        -- При загрузке изображений произошли ошибки. Останавливаем скрипт.
        if  loadError > 0 then
            log("Error loading count: "..loadError..'.')
            stop_script()
        end
        if  images == nil then
            log("Файлы изображений не найдены. Скрипт остановлен.")
            stop_script()
        end
        --table.show(images,"images")


        local timeout = os.clock() + options.timeProc


        -- log(options.secondFrame)
        -- Таймаут на прогрузку. Поиск для детекта изображений.
        if options.secondFrame > 0 then
            -- Создаем карман области видимости.
            -- Реузльататы блока не нужны для остального скрипта.
            do
                local catch = 0
                -- Если вермя ожидания после детекта не уложится в общий
                -- таймаут, то выходим из цикла без дальшейших попыток найти изображение.
                local secondFrameTimeout = timeout - options.secondFrame
                while true do -- выход внутри цикла  timeout < os.clock()
                    local screenshot, width, height = nil, nil, nil
                    if  options.source == nil then
                        screenshot, width, height = getimage(options.crds[1],options.crds[2],options.crds[3],options.crds[4], options.window)
                    else
                        screenshot, width, height = options.source[1],options.source[2],options.source[3]
                    end
                    for symbolName, imageAddressArray in pairs(images) do
                        for _, imageAddress in pairs(imageAddressArray) do
                            local tmp = {}
                            findResult = findimage(
                                0 .. " " .. 0 .. " " ..
                                width .. " " .. height .. " " ..
                                "(" .. imageAddress .. ") " ..
                                "%tmp " .. screenshot .. " " .. options.accuracy .. " -1 " .. options.deviation .. " " .. options.abs)
                            --log("symoblName: ".. symbolName .. " findResult: " .. findResult)
                            -- проверяем на возрват нуля или ошбики, со стрингом нормально не сравнить.
                            if  findResult ~= "0" and not string.find(findResult, "-") then
                                catch = 1
                                --log("break")
                                wait(math.floor(options.secondFrame * 1000))
                                break
                            end
                            -- Время на всю функцию истекло
                            if  secondFrameTimeout < os.clock() and options.timeProc ~= -1 then
                                return
                            end
                        end
                        if catch == 1 then break end
                    end
                    if catch == 1 then break end
                end
            end
        end


        -- Ищем изображения
        local crdsRaw={} -- Массив со всеми найденными изображениями, возможны дубли, не сортированный.
        repeat  -- Повторяем пока что-то не найдем или не выйдет время на поиск (options.timeProc).
            -- Получаем изображение с экрана, если источник не указан.
            local screenshot, width, height = nil
            if  options.source == nil then
                screenshot, width, height = getimage(options.crds[1],options.crds[2],options.crds[3],options.crds[4], options.window)
            else
                screenshot, width, height = options.source[1],options.source[2],options.source[3]
            end
            --log(screenshot)
            for symbolName, imageAddressArray in pairs(images) do
                for _, imageAddress in pairs(imageAddressArray) do
                    tmp = {}
                    findResult = findimage(
                        0 .. " " .. 0 .. " " ..
                        width .. " " .. height .. " " ..
                        "(" .. imageAddress .. ") " ..
                        "%tmp " .. screenshot .. " " .. options.accuracy .. " -1 " .. options.deviation .. " " .. options.abs)
                    --log("symoblName: ".. symbolName .. " findResult: " .. findResult)
                    -- проверяем на возрват нуля или ошбики, со стрингом нормально не сравнить.
                    if  findResult ~= "0" and not string.find(findResult, "-") then
                        -- Добавляем найденные значения в общий результат поисков.
                        --table.show(tmp,"tmp")
                        for i = 1, #tmp, 1 do
                            -- Напрямую вернуть таблицу в функцию нельзя из-за синтаксиса.
                            -- FIX. Нужен фикс функции findimage пилота (возвращает координаты стрингом)
                            -- после фикса просто удалить "tonumber(parm)" оставив parm.
                            table.insert(crdsRaw,{x=tonumber(tmp[i][1]),y=tonumber(tmp[i][2]),xEnd=tonumber(tmp[i][3]),symbolName=symbolName})
                        end
                    end
                end
            end

            -- Сохраняем изображение.
            if  options.saveImage ~= nil then
                saveimage(screenshot, options.saveImage)
            end
            -- Удаляем изображение, если получали его из приложения.
            if  options.source == nil then
                deleteimage(screenshot)
            end

            --table.show(images, "images")
            --log (#crdsRaw, timeout, os.clock(), options.timeProc)
            --log ("until")
            local clock = os.clock()
        until not ((#crdsRaw == 0) and (timeout > clock or options.timeProc == -1))
        --table.show(crdsRaw, "crdsRaw")

        --  Изображения не были найдены, выходим из поиска.
        if  #crdsRaw < 1 then
            return nil
        end
        -- Удаляем дубли.
        local crdsClear={} -- Массив без дублей.
        for i=1, #crdsRaw, 1 do
            local catch = 0 -- Флаг найденного дубля.
            for n=i+1, #crdsRaw, 1 do
                --log(
                --  crdsRaw[i].symbolName.." == "..crdsRaw[n].symbolName.." and "..
                --  math.abs(crdsRaw[i].x - crdsRaw[n].x).." <= "..options.repeatImage.." and "..
                --  math.abs(crdsRaw[i].y - crdsRaw[n].y).." <= "..options.repeatImage
                --)
                if  crdsRaw[i].symbolName == crdsRaw[n].symbolName and
                  math.abs(crdsRaw[i].x - crdsRaw[n].x) <= options.repeatImage and
                  math.abs(crdsRaw[i].y - crdsRaw[n].y) <= options.repeatImage then
                    catch = 1
                    break
                end
            end
            --log(catch)
            if  catch == 0 then -- не дубль, копируем значение в чистый массив.
                table.insert(crdsClear,crdsRaw[i])
            end
        end

        -- Сортируем элементы.
        -- Сортировка происходит, как по X координате,
        -- так и по Y учитывая возможность нескольких строк.
        -- Межстрочный интервал задается с помощью options.deltaY.
        -- Для уплотнения поиска options.deltaY может быть отрицательным.
        -- Отрицательный options.deltaY в первую очередь необходим,
        -- если изображения символов содержат сверху и снизу от символа фон.
        -- crdsClear был предварительно очищен от дублей, теперь сортируется.

        --table.show(crdsClear,"crdsClear")
        --table.toInit(crdsClear)
        table.sort(crdsClear,
            function(a,b)
                if  math.abs(a.y - b.y) <= options.deltaY then
                    if  a.x < b.x then
                        return true
                    else
                        return false
                    end
                else
                    if a.y < b.y then
                        return true
                    else
                        return false
                    end
                end
            end
        )
        --table.show(crdsClear,"crdsClear")

        -- Собираем строку
        --log(#crdsClear)
        local result = {{crdsClear[1].symbolName}}
        local resultX, resultY = 1, 1
        for i=2, #crdsClear, 1 do
            -- Добавляем перенос и символ, возрващем каретку.
            if  crdsClear[i-1].y  + options.deltaY < crdsClear[i].y then
                resultX = resultX + 1
                resultY = 1 -- возврат картеки
                result[resultX]={crdsClear[i].symbolName}
            -- Добавляем пробел и символ
            elseif crdsClear[i-1].xEnd  + options.deltaSpace < crdsClear[i].x then
                resultY = resultY + 1
                result[resultX][resultY] = crdsClear[i].symbolName
            -- Добавляем символ
            else
                result[resultX][resultY] = result[resultX][resultY].. crdsClear[i].symbolName
            end
            --table.show(result,"result")
        end
        --table.show(result,"result")
        return result
    end
end


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
cirus
сообщение 27.9.2017, 3:48
Сообщение #117


**********

Elder
Сообщений: 3.480
Регистрация: 18.8.2014
Группа: Пользователи
Наличность: 26576
Пользователь №: 16.971
Возраст: 29



Цитата
При втором вызове функции массив с картинками пуст.

Если используется default.path нормально стало. Для default.loadFolder тоже ведь надо.
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 27.9.2017, 13:13
Сообщение #118


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



Цитата
Для default.loadFolder тоже ведь надо.

Эмм... там же nil вроде как, что исключает вообще какое-либо копирование. Ну сейчас на всех массивах проставлю.

Распознавание текста Lua
Код
-- Автор скрипта DarkMaster.
-- Написано по мотивам скрипта Cirus.
-- Тестирование Cirus.
-- Вопросы, баги, предложения на форум
-- в специальную тему по этому скрипту
-- https://forum.uokit.com/index.php?showtopic=30000

-- Фикс: символы по умолчанию больше не переписываются, сделано корректное копирование массива.

-- Фикс: флаг чтения подпапок был инвертирован.
-- Фикс: secondFrameTimeout больше не глобальная и используется по назначению.
-- Фикс: При default.timeProc = -1 и default.secondFrame > 0 не выходит преждевременно из функции.
-- Фикс: Почистил отладочные выводы в лог.
-- Добавлено сохранение изображение в котором происходил поиск.

-- Баг:  из-за особенностей костыля финдимиджа создается НЕ локальня переменная tmp.
-- Фикс: изображение не добавлялось в буфер.
-- Фикс: расчет пробела от конечной х координаты.
-- Фикс: очистка буфера после захвата изображения.
-- Фикс: область поиска при источнике из getimage должна быть с нуля.
-- Фикс: искалось только одно изображение из-за недостающего вложенного цикла.
-- Фикс: буфер теперь действительно буферезует.
-- Переработно преобразование из упрощенного синтаксиса в полнеценный. Добавлена защита от дурка (типы данных).
-- Добавлено: загрузка папки с изображениями.
-- Добавлено: ожидание прогрузки изображений (options.secondFrame).
-- Добавлено: чтение из буфера.

do

-- Раскомментировать, если в отладке будет использоват table.show.
--[[do
    local tab = ""
    local deep = 0
    function table.show(t, comment)
        -- Пишем в лог комментарий.
        deep = deep + 1 -- Уровень вложенности вызовов функции.
        --log(comment .. commentSended .. deep)
        if  comment ~= nil and deep == 1 then
            log(comment)
        end


        if     type(t) == "nil"     then log("table is nil")
        elseif type(t) == "string"  then log('table is string: "'..t..'"')
        elseif type(t) == "number"  then log('table is number: '..t)
        elseif type(t) == "table"   then
            local elementsInTable = 0
            for k,v in pairs(t) do
                if  type (v) == "table" then
                    if type(k) == "string" then
                        log(tab..'table: "'..k..'"')
                    else
                        log(tab..'table: '..k)
                    end
                    tab = tab .. "    "
                    table.show(v)
                    tab = string.sub(tab, 1, -5)
                    elementsInTable = elementsInTable + 1
                else
                    elementsInTable = elementsInTable + 1
                    if type(v) == "string" then v = '"'..v..'"' end
                    if type(k) == "string" then k = '"'..k..'"' end
                    log(tab..""..k.." = "..v)
                end
            end
            if elementsInTable == 0 then log("table is empty") end
        else
            log('table is unknow data type')
        end
        -- Пишем в лог комментарий.
        deep = deep - 1 -- Уровень вложенности вызовов функции.
    end
end
]]

function dc(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in next, orig, nil do
            copy[dc(orig_key)] = dc(orig_value)
        end
        setmetatable(copy, dc(getmetatable(orig)))
    else -- number, string, boolean, etc
        copy = orig
    end
    return copy
end

    -- Символы для поиска.
    -- Возможно указать в двух вариантах синтаксиса: упрощенном и полном.
    -- Упрощенный синтаксис:
    -- В упрощенном варианте синтаксиса допускается не указывать
    -- соответствие имен файлов и строке/символу,
    -- который они обозначают: считается, что они идентичны.
    -- Пример упрощенного синтаксиса:
    -- local symbols = {"0", "1", "2", "3", "a", "b", "c", "test"}
    -- Полный синтаксис:
    -- Полный синтаксис бывает необходим при использовании
    -- нескольких изображений соответсвующих одной и той же строке/символу.
    -- Допускаются переносы строк:
    -- local symbols = {
    --       ["0"] = {"zero1", "zero2"},
    --       ["1"] = {"1a", "1b"},
    --       ["2"] = {"two", "second"}
    --      }
    -- Оба варианта синтаксиса можно сочетать:
    -- local symbols = {"0", "1", ["2"] = {"two", "second"}, "3"}


    local default = {}
    default.crds         = {0, 0, 1920, 1080} -- Координаты поиска
    default.path         = "c:\\image"        -- Папка с картинками
    default.ext          = ".bmp"             -- Расширение картинок
    default.loadFolder   = nil                -- Путь по которому будут загружены все изображения с указанной маской {path=путь, mask=маска, sub=1|0}(sub - подпапки). Имя файла будет соответсвовать имени символа.
    default.deltaY       = 8                  -- Расстояние между строками (можно указать высоту картинок)
    default.deltaSpace   = 2                  -- Допустимое расстояние между цифрами, иначе будет считаться что это не одно число
    default.accuracy     = 95                 -- Точность поиска для Findimage
    default.deviation    = 3                  -- Погрешность оттенка  для Findimage
    default.wait         = 2                  -- Пауза между поиском картинок, если указать меньше искать будет быстрее, но нагрузит процессор
    default.timeProc     = 2                  -- Время в секундах (может быть не целым) для поиска картинок, если -1 не выйдет из процедуры пока не найдётся хотя бы 1 картинка
    default.repeatImage  = 2                  -- Допустимое смещение координат, если используется несколько видов одной картинки
    default.window       = "workwindow"       -- Метод|хендл_окна в котором происходит поиск (если указан источник изображения(source), то параметр будет проигнорирован)
    default.abs          = 0                  -- Использовать abs координаты.
    default.source       = nil                -- Изображение в котором производится поиск. Должен быть задан таблицей {адрес, ширина, высота}, nil вместо таблицы приведет к захвату изображения с экрана.
    default.bufferAddNew = 1                  -- Добавлять изображения в буфер
    default.bufferIgnore = 0                  -- Игнорировать изображения находящиеся в буфере
    default.bufferUpdate = 0                  -- Обновить изображения содержащиеся в буфере.
    default.secondFrame  = 0                  -- Ожидание прогрузки значений. Изображение будет проанализировано только после secondFrame секунд с первой успешной попытки считать любое из избражений.
    default.saveImage    = nil                -- Путь по которому будет сохранено изображение в котором происходит поиск.
    -- набор стандартных символов
    default.symbols      = {["0"]={"0"}, ["1"]={"1"}, ["2"]={"2"}, ["3"]={"3"}, ["4"]={"4"}, ["5"]={"5"}, ["6"]={"6"}, ["7"]={"7"}, ["8"]={"8"}, ["9"]={"9"}}


    -- Буфер
    -- Буфер
    -- Буфер

    local buffer = {} -- Массив с загруженными картинками.
    imageToStringBuffer = {} -- набор функций по управлению буфером.
    -- Полностью очищаем массив.
    function imageToStringBuffer.flush()
        for k,_ in pairs(buffer) do buffer[v] = nil end
    end
    -- Удаляем элемент из буфера
    function imageToStringBuffer.flush(element)
        buffer[element] = nil
    end
    -- Добавляем изображение в буфер
    function imageToStringBuffer.flush(element, val)
        buffer[element] = val
    end
    -- Читаем изображение из буфера
    function imageToStringBuffer.flush(element)
        return buffer[element]
    end


    -- Поиск
    -- Поиск
    -- Поиск

    function imageToString(options)

        -- Проверяем переданные параметры. Если они отсутствуют - подставляем параметры по умолчанию.
        if  options              == nil then local options        = {}                     end
        if  options.crds         == nil then options.crds         = default.crds           end
        if  options.path         == nil then options.path         = default.path           end
        if  options.ext          == nil then options.ext          = default.ext            end
        if  options.loadFolder   == nil then options.loadFolder   = dc(default.loadFolder) end
        if  options.deltaY       == nil then options.deltaY       = default.deltaY         end
        if  options.deltaSpace   == nil then options.deltaSpace   = default.deltaSpace     end
        if  options.accuracy     == nil then options.accuracy     = default.accuracy       end
        if  options.deviation    == nil then options.deviation    = default.deviation      end
        if  options.wait         == nil then options.wait         = default.wait           end
        if  options.timeProc     == nil then options.timeProc     = default.timeProc       end
        if  options.repeatImage  == nil then options.repeatImage  = default.repeatImage    end
        if  options.window       == nil then options.window       = default.window         end
        if  options.abs          == nil then options.abs          = default.abs            end
        if  options.source       == nil then options.source       = dc(default.source)     end
        if  options.bufferAddNew == nil then options.bufferAddNew = default.bufferAddNew   end
        if  options.bufferIgnore == nil then options.bufferIgnore = default.bufferIgnore   end
        if  options.bufferUpdate == nil then options.bufferUpdate = default.bufferUpdate   end
        if  options.secondFrame  == nil then options.secondFrame  = default.secondFrame    end
        if  options.saveImage    == nil then options.saveImage    = default.saveImage      end
        if  options.symbols      == nil then
            if  options.loadFolder   == nil then
                options.symbols = dc(default.symbols)
            else
                options.symbols = {}
            end
        end

        --Добавляем при необходимости обратный слэш в путь.
        if  string.sub(options.path, -1) ~= "\\" then options.path = options.path .. "\\" end

        -- Папка для загрузки изображений не задана, загружаем обычным методом.
        if  options.loadFolder == nil then
            -- Преобразуем урощенный синтаксис в полноценный, преобразуем пути в полные.
            do
                local tmp = {} --Массив в который временно помещаются преобразованные данные.
                for symbolName, imageName in pairs(options.symbols) do
                    -- Если занчение задано строкой/числом, приводим его к таблице, дописываем путь до полного.
                    if  type(options.symbols[symbolName]) == "number" then
                        options.symbols[symbolName] = {options.path..tostring(imageName)..options.ext}
                    elseif  type(options.symbols[symbolName]) == "string" then
                        options.symbols[symbolName] = {options.path..imageName..options.ext}
                    --  Значение задано таблицей, преобразоываем числа в строки, дописываем путь до полного.
                    elseif  type(options.symbols[symbolName]) == "table" then
                        for n=1, #options.symbols[symbolName] do
                            if  type(options.symbols[symbolName][n]) == "number" then
                                options.symbols[symbolName][n] = options.path..tostring(options.symbols[symbolName][n])..options.ext
                            elseif  type(options.symbols[symbolName][n]) == "string" then
                                options.symbols[symbolName][n] = options.path..options.symbols[symbolName][n]..options.ext
                            else
                                msg ("Ошибочный тип значения картинок символов в таблице. Остановка скрипта")
                                stop_script()
                            end
                        end
                    else
                        msg ("Ошибочный тип значения картинок символов. Остановка скрипта")
                        stop_script()
                    end

                    -- Если ключ цифровой, преобразуем к строке
                    if  type(symbolName) == "number" then
                        tmp[tostring(symbolName)] = options.symbols[symbolName]
                    elseif  type(symbolName) == "string" then
                        tmp[symbolName] = options.symbols[symbolName]
                    else
                        msg ("Ошибочный тип ключа символов. Остановка скрипта")
                        stop_script()
                    end
                end
                options.symbols = tmp
            end
        else
            -- Загружаем папку с изображениями.
            -- Имя файла = имя символа.
            -- Допускается несколько одинаковых символов в различных подпапках.
            -- Приводим к понятному для пилота виду флаг чтение подпапок.

            -- Прилепляем кавычки к пути чтобы пилот не путал путь и маску.
            options.loadFolder.path = '"'..options.loadFolder.path..'"'
            if options.loadFolder.sub == 1 then options.loadFolder.sub = nil else options.loadFolder.sub = "norecursion" end
            -- Приводим маску к надлежащему виду, если она не задана.
            if options.loadFolder.mask == nil then options.loadFolder.mask = "*" end
            fileList = dir(options.loadFolder.path, options.loadFolder.mask, options.loadFolder.sub)
            --table.show(fileList, "fileList")
            for k, v in pairs (fileList) do
                -- символ уже существует (несколько вариантов изображения)
                if  options.symbols[v[3]] ~= nil then
                    table.insert(options.symbols[v[3]], v[1])
                else
                    options.symbols[v[3]] = {v[1]}
                end
            end
        end
        --table.show(options.symbols)


        -- Приводим options.abs к виду пригодному для финдимиджа.
        if      options.abs == 1 then options.abs = "abs"
        elseif  options.abs == 0 then options.abs = ""
        end


        -- Загрузка картинок
        local images={}     --Загружает в память изображения {имя символа, {адреса в памяти}}
        local loadError = 0
        for symbolName, fileList in pairs(options.symbols) do
            images[symbolName] = {}
            for i=1, #fileList, 1 do
                -- Загружен ли файл в буфер, если нет, то подгружаем.
                local filePath = fileList[i]
                if  options.bufferIgnore == 0 and options.bufferUpdate == 0 and buffer[filePath] ~= nil then
                    images[symbolName][i] = buffer[filePath]
                else
                    -- В буфере изображения нет, загружаем с диска.
                    --log(filePath.."В буфере изображения нет, загружаем с диска.")
                    images[symbolName][i] = loadimage(filePath)
                    -- Обновляем загруженное в буфер изображение
                    if  buffer[filePath] ~= nil then
                        deleteimage(buffer[filePath])
                        buffer[filePath] =  images[symbolName][i]
                    elseif options.bufferAddNew == 1 and options.bufferIgnore == 0 then
                        -- Добавляем в буфер новое изображение.
                        buffer[filePath] = images[symbolName][i]
                    end
                end
                -- Поиск ошибок загрузки.
                if images[symbolName][i] < 0  then
                    loadError = loadError + 1
                    log("Image loading fail. Error file: "..filePath..'.')
                end
            end
        end
        -- При загрузке изображений произошли ошибки. Останавливаем скрипт.
        if  loadError > 0 then
            log("Error loading count: "..loadError..'.')
            stop_script()
        end
        if  images == nil then
            log("Файлы изображений не найдены. Скрипт остановлен.")
            stop_script()
        end
        --table.show(images,"images")


        local timeout = os.clock() + options.timeProc


        -- log(options.secondFrame)
        -- Таймаут на прогрузку. Поиск для детекта изображений.
        if options.secondFrame > 0 then
            -- Создаем карман области видимости.
            -- Реузльататы блока не нужны для остального скрипта.
            do
                local catch = 0
                -- Если вермя ожидания после детекта не уложится в общий
                -- таймаут, то выходим из цикла без дальшейших попыток найти изображение.
                local secondFrameTimeout = timeout - options.secondFrame
                while true do -- выход внутри цикла  timeout < os.clock()
                    local screenshot, width, height = nil, nil, nil
                    if  options.source == nil then
                        screenshot, width, height = getimage(options.crds[1],options.crds[2],options.crds[3],options.crds[4], options.window)
                    else
                        screenshot, width, height = options.source[1],options.source[2],options.source[3]
                    end
                    for symbolName, imageAddressArray in pairs(images) do
                        for _, imageAddress in pairs(imageAddressArray) do
                            local tmp = {}
                            findResult = findimage(
                                0 .. " " .. 0 .. " " ..
                                width .. " " .. height .. " " ..
                                "(" .. imageAddress .. ") " ..
                                "%tmp " .. screenshot .. " " .. options.accuracy .. " -1 " .. options.deviation .. " " .. options.abs)
                            --log("symoblName: ".. symbolName .. " findResult: " .. findResult)
                            -- проверяем на возрват нуля или ошбики, со стрингом нормально не сравнить.
                            if  findResult ~= "0" and not string.find(findResult, "-") then
                                catch = 1
                                --log("break")
                                wait(math.floor(options.secondFrame * 1000))
                                break
                            end
                            -- Время на всю функцию истекло
                            if  secondFrameTimeout < os.clock() and options.timeProc ~= -1 then
                                return
                            end
                        end
                        if catch == 1 then break end
                    end
                    if catch == 1 then break end
                end
            end
        end


        -- Ищем изображения
        local crdsRaw={} -- Массив со всеми найденными изображениями, возможны дубли, не сортированный.
        repeat  -- Повторяем пока что-то не найдем или не выйдет время на поиск (options.timeProc).
            -- Получаем изображение с экрана, если источник не указан.
            local screenshot, width, height = nil
            if  options.source == nil then
                screenshot, width, height = getimage(options.crds[1],options.crds[2],options.crds[3],options.crds[4], options.window)
            else
                screenshot, width, height = options.source[1],options.source[2],options.source[3]
            end
            --log(screenshot)
            for symbolName, imageAddressArray in pairs(images) do
                for _, imageAddress in pairs(imageAddressArray) do
                    tmp = {}
                    findResult = findimage(
                        0 .. " " .. 0 .. " " ..
                        width .. " " .. height .. " " ..
                        "(" .. imageAddress .. ") " ..
                        "%tmp " .. screenshot .. " " .. options.accuracy .. " -1 " .. options.deviation .. " " .. options.abs)
                    --log("symoblName: ".. symbolName .. " findResult: " .. findResult)
                    -- проверяем на возрват нуля или ошбики, со стрингом нормально не сравнить.
                    if  findResult ~= "0" and not string.find(findResult, "-") then
                        -- Добавляем найденные значения в общий результат поисков.
                        --table.show(tmp,"tmp")
                        for i = 1, #tmp, 1 do
                            -- Напрямую вернуть таблицу в функцию нельзя из-за синтаксиса.
                            -- FIX. Нужен фикс функции findimage пилота (возвращает координаты стрингом)
                            -- после фикса просто удалить "tonumber(parm)" оставив parm.
                            table.insert(crdsRaw,{x=tonumber(tmp[i][1]),y=tonumber(tmp[i][2]),xEnd=tonumber(tmp[i][3]),symbolName=symbolName})
                        end
                    end
                end
            end

            -- Сохраняем изображение.
            if  options.saveImage ~= nil then
                saveimage(screenshot, options.saveImage)
            end
            -- Удаляем изображение, если получали его из приложения.
            if  options.source == nil then
                deleteimage(screenshot)
            end

            --table.show(images, "images")
            --log (#crdsRaw, timeout, os.clock(), options.timeProc)
            --log ("until")
            local clock = os.clock()
        until not ((#crdsRaw == 0) and (timeout > clock or options.timeProc == -1))
        --table.show(crdsRaw, "crdsRaw")

        --  Изображения не были найдены, выходим из поиска.
        if  #crdsRaw < 1 then
            return nil
        end
        -- Удаляем дубли.
        local crdsClear={} -- Массив без дублей.
        for i=1, #crdsRaw, 1 do
            local catch = 0 -- Флаг найденного дубля.
            for n=i+1, #crdsRaw, 1 do
                --log(
                --  crdsRaw[i].symbolName.." == "..crdsRaw[n].symbolName.." and "..
                --  math.abs(crdsRaw[i].x - crdsRaw[n].x).." <= "..options.repeatImage.." and "..
                --  math.abs(crdsRaw[i].y - crdsRaw[n].y).." <= "..options.repeatImage
                --)
                if  crdsRaw[i].symbolName == crdsRaw[n].symbolName and
                  math.abs(crdsRaw[i].x - crdsRaw[n].x) <= options.repeatImage and
                  math.abs(crdsRaw[i].y - crdsRaw[n].y) <= options.repeatImage then
                    catch = 1
                    break
                end
            end
            --log(catch)
            if  catch == 0 then -- не дубль, копируем значение в чистый массив.
                table.insert(crdsClear,crdsRaw[i])
            end
        end

        -- Сортируем элементы.
        -- Сортировка происходит, как по X координате,
        -- так и по Y учитывая возможность нескольких строк.
        -- Межстрочный интервал задается с помощью options.deltaY.
        -- Для уплотнения поиска options.deltaY может быть отрицательным.
        -- Отрицательный options.deltaY в первую очередь необходим,
        -- если изображения символов содержат сверху и снизу от символа фон.
        -- crdsClear был предварительно очищен от дублей, теперь сортируется.

        --table.show(crdsClear,"crdsClear")
        --table.toInit(crdsClear)
        table.sort(crdsClear,
            function(a,b)
                if  math.abs(a.y - b.y) <= options.deltaY then
                    if  a.x < b.x then
                        return true
                    else
                        return false
                    end
                else
                    if a.y < b.y then
                        return true
                    else
                        return false
                    end
                end
            end
        )
        --table.show(crdsClear,"crdsClear")

        -- Собираем строку
        --log(#crdsClear)
        local result = {{crdsClear[1].symbolName}}
        local resultX, resultY = 1, 1
        for i=2, #crdsClear, 1 do
            -- Добавляем перенос и символ, возрващем каретку.
            if  crdsClear[i-1].y  + options.deltaY < crdsClear[i].y then
                resultX = resultX + 1
                resultY = 1 -- возврат картеки
                result[resultX]={crdsClear[i].symbolName}
            -- Добавляем пробел и символ
            elseif crdsClear[i-1].xEnd  + options.deltaSpace < crdsClear[i].x then
                resultY = resultY + 1
                result[resultX][resultY] = crdsClear[i].symbolName
            -- Добавляем символ
            else
                result[resultX][resultY] = result[resultX][resultY].. crdsClear[i].symbolName
            end
            --table.show(result,"result")
        end
        --table.show(result,"result")
        return result
    end
end


Сообщение отредактировал DarkMaster - 27.9.2017, 22:30


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
cirus
сообщение 27.9.2017, 13:19
Сообщение #119


**********

Elder
Сообщений: 3.480
Регистрация: 18.8.2014
Группа: Пользователи
Наличность: 26576
Пользователь №: 16.971
Возраст: 29



Если так понятнее:
Код
result = imageToString{crds={33, 189, 292, 255},
                       loadFolder = {path="C:\\l2number3", mask="*bmp", sub=1}}
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 27.9.2017, 13:27
Сообщение #120


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



Эмм? И как это может привести к перезаписи значений по умолчанию? Более того у меня два подобных вызова подряд стоят еще с прошлого теста (т.е. всего 4: два на символы, два на папки).

Вообще проблема была вызвана обработкой при которой синтаксис приводился к единообразию и это единообразие запихивалось в умлочание. С остальными таблицами этого даже представить не могу, т.к. их значения нигде не изменяются и ссылки там на самом деле достаточно. Даже если в умлочаниях вместо nil'ов что-то задать, то это не приведет как каким-то последствиям. Там весь скрипт общается с переданными параметрами только в режиме read-only. Исключение было в символах и это даже где-то ошибка проектирования ибо входящие параметры в моем понимании скорее не стоит изменять и проще завести новый массив под это дело, но проблему бы это не решило, т.к. все равно пришлось бы копирование прикручивать.


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения

11 страниц V « < 4 5 6 7 8 > » 
Ответить в эту темуОткрыть новую тему
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 

- Текстовая версия | Версия для КПК Сейчас: 29.3.2024, 4:37
Designed by Nickostyle