Модуль:Aggregator

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

Module:Aggregator

Модуль Aggregator — учебный Lua-модуль для курса «Программирование» в MediaWiki/Scribunto. Он показывает, как страница вики может рассматриваться как источник данных для анализа.

Назначение

Модуль поддерживает 5 базовых режимов:

Режим Что делает
args считает количество переданных аргументов
chars считает длину исходного вики-текста страницы в байтах
words считает количество слов в исходном вики-тексте страницы
links считает количество wikilinks вида ...
headings считает количество заголовков вида == ... ==

Базовый вызов

{{#invoke:Aggregator|main|mode=args|a=Lua|b=SMW|c=NetLogo}}

Результат: количество переданных аргументов.

Примеры

Вики-текст Назначение
{{#invoke:Aggregator|main|mode=args|a=1|b=2|c=3}} Подсчёт аргументов
{{#invoke:Aggregator|main|mode=chars|title=Lua/Tutorial}} Подсчёт длины страницы
{{#invoke:Aggregator|main|mode=words|title=Lua/Tutorial}} Подсчёт слов
{{#invoke:Aggregator|main|mode=links|title=Lua/Tutorial}} Подсчёт wiki-ссылок
{{#invoke:Aggregator|main|mode=headings|title=Lua/Tutorial}} Подсчёт заголовков

Отдельные функции

Можно вызывать функции напрямую:

{{#invoke:Aggregator|args|x=1|y=2}}
{{#invoke:Aggregator|words|title=Lua/Tutorial}}
{{#invoke:Aggregator|links|title=Lua/Tutorial}}

Ограничения

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

Remix-задания

Студент может создать модуль вида:

  • Module:Ivanov_Aggregator
  • Module:Student/Ivanov/Aggregator

и добавить новые режимы:

Новый режим Идея
templates считать шаблоны Шаблон:...
categories считать категории
files считать вхождения файлов
sentences считать предложения
externallinks считать внешние ссылки

Учебный смысл

Этот модуль показывает переход:

  1. от подсчёта аргументов
  2. к анализу страницы
  3. к созданию собственной метрики текста
  4. к remix-программированию внутри wiki-страниц

local p = {}

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

local function getTitleObject(titleText)
    if not titleText or titleText == '' then
        return mw.title.getCurrentTitle()
    end
    return mw.title.new(titleText)
end

local function getContent(titleText)
    local titleObj = getTitleObject(titleText)
    if not titleObj then
        return nil, 'Ошибка: некорректное имя страницы'
    end

    local content = titleObj:getContent()
    if not content then
        return nil, 'Ошибка: страница не существует или содержимое недоступно'
    end

    return content, nil
end

local function countArgs(args)
    local n = 0
    for _ in pairs(args) do
        n = n + 1
    end
    return n
end

local function countWords(text)
    local n = 0
    for _ in mw.ustring.gmatch(text, '%S+') do
        n = n + 1
    end
    return n
end

local function countLinks(text)
    local n = 0
    for _ in mw.ustring.gmatch(text, '%[%[[^%]]+%]%]') do
        n = n + 1
    end
    return n
end

local function countHeadings(text)
    local n = 0
    for _ in mw.ustring.gmatch(text, '\n==+[^=\n]+==+') do
        n = n + 1
    end
    if mw.ustring.match(text, '^==+[^=\n]+==+') then
        n = n + 1
    end
    return n
end

function p.args(frame)
    local args = getArgs(frame)
    return 'Всего передано аргументов: ' .. countArgs(args)
end

function p.chars(frame)
    local args = getArgs(frame)
    local text, err = getContent(args.title)
    if not text then
        return err
    end
    return 'Длина исходного вики-текста в байтах: ' .. #text
end

function p.words(frame)
    local args = getArgs(frame)
    local text, err = getContent(args.title)
    if not text then
        return err
    end
    return 'Количество слов в исходном вики-тексте: ' .. countWords(text)
end

function p.links(frame)
    local args = getArgs(frame)
    local text, err = getContent(args.title)
    if not text then
        return err
    end
    return 'Количество wikilinks [[...]]: ' .. countLinks(text)
end

function p.headings(frame)
    local args = getArgs(frame)
    local text, err = getContent(args.title)
    if not text then
        return err
    end
    return 'Количество заголовков ==...== : ' .. countHeadings(text)
end

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

    if mode == 'args' then
        return p.args(frame)
    elseif mode == 'chars' then
        return p.chars(frame)
    elseif mode == 'words' then
        return p.words(frame)
    elseif mode == 'links' then
        return p.links(frame)
    elseif mode == 'headings' then
        return p.headings(frame)
    else
        return 'Ошибка: неизвестный режим. Допустимо: args, chars, words, links, headings'
    end
end

return p