Модуль:DatasetAggregator

Материал из Поле цифровой дидактики

Для документации этого модуля может быть создана страница Модуль:DatasetAggregator/doc

local p = {}

local function trim(s)
    if type(s) ~= 'string' then
        return s
    end
    return mw.text.trim(s)
end

local function getArgs(frame)
    local args = {}
    for k, v in pairs(frame.args) do
        if v ~= nil and v ~= '' then
            args[k] = trim(v)
        end
    end
    return args
end

local function getData(url)
    if not mw.ext or not mw.ext.externalData or not mw.ext.externalData.getExternalData then
        return nil, { 'Ошибка: Extension:External Data недоступен' }
    end

    local data, errors = mw.ext.externalData.getExternalData{
        source = url,
        format = 'csv with header'
    }

    if not data then
        return nil, errors or { 'Ошибка: данные не загружены' }
    end

    return data, nil
end

local function countRows(data)
    return #data
end

local function countDistinct(data, field)
    local seen = {}
    local n = 0

    for _, row in ipairs(data) do
        local value = row[field]
        if value ~= nil and value ~= '' and not seen[value] then
            seen[value] = true
            n = n + 1
        end
    end

    return n
end

local function countByValue(data, field, expected)
    local n = 0
    for _, row in ipairs(data) do
        if tostring(row[field] or '') == tostring(expected) then
            n = n + 1
        end
    end
    return n
end

local function buildSummaryTable(data)
    local rows = countRows(data)
    local authors = countDistinct(data, 'author_name')
    local objects = countDistinct(data, 'object_id')
    local pages = countDistinct(data, 'page_title')

    local out = '{| class="wikitable"\n'
    out = out .. '! Метрика !! Значение\n'
    out = out .. '|-\n| Строк в CSV || ' .. rows .. '\n'
    out = out .. '|-\n| Уникальных авторов || ' .. authors .. '\n'
    out = out .. '|-\n| Уникальных объектов || ' .. objects .. '\n'
    out = out .. '|-\n| Уникальных страниц || ' .. pages .. '\n'
    out = out .. '|}'

    return out
end

function p.rows(frame)
    local args = getArgs(frame)
    local data, errors = getData(args.url)
    if not data then
        return 'Ошибка: ' .. table.concat(errors, '; ')
    end
    return 'Строк в CSV: ' .. countRows(data)
end

function p.authors(frame)
    local args = getArgs(frame)
    local data, errors = getData(args.url)
    if not data then
        return 'Ошибка: ' .. table.concat(errors, '; ')
    end
    return 'Уникальных авторов: ' .. countDistinct(data, 'author_name')
end

function p.objects(frame)
    local args = getArgs(frame)
    local data, errors = getData(args.url)
    if not data then
        return 'Ошибка: ' .. table.concat(errors, '; ')
    end
    return 'Уникальных объектов: ' .. countDistinct(data, 'object_id')
end

function p.commits(frame)
    local args = getArgs(frame)
    local data, errors = getData(args.url)
    if not data then
        return 'Ошибка: ' .. table.concat(errors, '; ')
    end

    local commitType = args.type or 'wiki_minor_edit'
    return 'Правок типа "' .. commitType .. '": ' .. countByValue(data, 'commit_type', commitType)
end

function p.summary(frame)
    local args = getArgs(frame)
    local data, errors = getData(args.url)
    if not data then
        return 'Ошибка: ' .. table.concat(errors, '; ')
    end
    return buildSummaryTable(data)
end

function p.main(frame)
    local args = getArgs(frame)
    local mode = args.mode or 'summary'

    if not args.url or args.url == '' then
        return 'Ошибка: укажите параметр url'
    end

    if mode == 'rows' then
        return p.rows(frame)
    elseif mode == 'authors' then
        return p.authors(frame)
    elseif mode == 'objects' then
        return p.objects(frame)
    elseif mode == 'commits' then
        return p.commits(frame)
    elseif mode == 'summary' then
        return p.summary(frame)
    else
        return 'Ошибка: неизвестный режим. Допустимо: rows, authors, objects, commits, summary'
    end
end

return p