[go: nahoru, domu]

Przejdź do zawartości

Moduł:Lista utworów2

Z Wikipedii, wolnej encyklopedii
 Dokumentacja modułu [zobacz] [edytuj] [historia] [odśwież]
Moduł implementuje logikę szablonu {{Lista utworów2}}, udostępniając jedną funkcję: tabela. Dokumentacja parametrów wywołania znajduje się na stronie szablonu.
local p = {}
local arguments = require('Moduł:Arguments')

function applyDefault(...)
    local n = select('#', ...)
    local args = {...}
    for i = 1, n - 1 do
        if args[i] ~= nil and args[i] ~= '' then
            return args[i]
        end
    end
    return args[n]
end

function parseTime(timeString)
    -- Według dokumentacji, czas trwania jest opcjonalny, więc zwróć 0, które nie popsuje rachunków
    if timeString == nil then
        return 0
    end

    local hours, minutes, seconds = mw.ustring.match(timeString, '(%d+):(%d+):(%d+)')
    if hours then
        return tonumber(hours) * 3600 + tonumber(minutes) * 60 + tonumber(seconds)
    end
    local minutes, seconds = mw.ustring.match(timeString, '(%d+):(%d+)')
    if minutes then
        return tonumber(minutes) * 60 + tonumber(seconds)
    end
    local seconds = mw.ustring.match(timeString, '(%d+)')
    if seconds then
        return tonumber(seconds)
    end
    return nil
end

function displayTime(seconds)
    if seconds == nil or seconds == 0 then
        return ''
    end

    local hours = math.floor(seconds / 3600)
    local minutes = math.floor((seconds % 3600) / 60)
    local seconds = seconds % 60
    local timeString = ''
    if hours > 0 then
        timeString = string.format('%d:%02d:%02d', hours, minutes, seconds)
    else
    	timeString = string.format('%d:%02d', minutes, seconds)
    end
    return timeString
end

-- Przetwarza argumenty szablonu i zwraca listę utworów
-- Każdy utwór jest reprezentowany przez tablicę z kluczami:
--  * spanId - identyfikator elementu HTML, w którym znajduje się utwór (TODO: czy potrzebne?) (8n + 1)
--  * title - tytuł utworu (8n + 2)
--  * note - dodatkowe informacje o utworze (8n + 3)
--  * col1..4 - dodatkowe kolumny (8n + 4..7)
--  * time - czas trwania utworu (przeparsowana liczba, w sekundach) (8n + 8)
-- Dodatkowo, zwracana jest tablica, określająca, które kolumny wykorzystano
function p.readEntries(args)
    local entries = {}
    local extraColumns = {
        col1 = false,
        col2 = false,
        col3 = false,
        col4 = false,
    }
    local i = 0
    while true do
        local entry = {}
        entry.spanId = args[i * 8 + 1]
        entry.title = args[i * 8 + 2]
        entry.note = args[i * 8 + 3]
        entry.col1 = args[i * 8 + 4]
        entry.col2 = args[i * 8 + 5]
        entry.col3 = args[i * 8 + 6]
        entry.col4 = args[i * 8 + 7]
        entry.timeString = args[i * 8 + 8] -- przechowywany jest oryginalny zapis czasu, aby np. dało się wstawić przypis
        entry.time = parseTime(entry.timeString)
        if entry.title == nil then
            -- Kontynuuj, dopóki istnieją utwory (tytuł jest wymagany)
            break
        end
        i = i + 1

        table.insert(entries, entry)

        extraColumns.col1 = extraColumns.col1 or (entry.col1 ~= nil and entry.col1 ~= '')
        extraColumns.col2 = extraColumns.col2 or (entry.col2 ~= nil and entry.col2 ~= '')
        extraColumns.col3 = extraColumns.col3 or (entry.col3 ~= nil and entry.col3 ~= '')
        extraColumns.col4 = extraColumns.col4 or (entry.col4 ~= nil and entry.col4 ~= '')
    end
    return entries, extraColumns
end

-- Zwraca konfigurację tabeli na podstawie przekazanych argumentów
-- oraz wartości domyślnych
function readConfig(args)
    local config = {
        year = applyDefault(args['rok'], ''),
        albumTitle = applyDefault(args['tytuł'], args['tytuł albumu'], ''),
        albumNote = applyDefault(args['nota'], args['nota albumu'], ''),
        tableWidth = applyDefault(args['szerokość'], '60%'),
        tableCollapsed = args['zwinięte'] == 'tak',
        col1Title = applyDefault(args['1-kolumna'], ''),
        col2Title = applyDefault(args['2-kolumna'], 'Tekst'),
        col3Title = applyDefault(args['3-kolumna'], 'Muzyka'),
        col4Title = applyDefault(args['4-kolumna'], ''),
        totalDuration = args['suma'] == 'tak',
    }
    return config
end

function createHeaderRow(extraColumns, config, styles)
    local row = mw.html.create('tr')

    -- style są dołączane tutaj, bo poza tabelą psułyby relację table + table w CSS
    row:tag('th'):wikitext('Nr', styles):css('width', '40px'):done()
        :tag('th'):wikitext('Tytuł utworu')
    
    for i = 1, 4 do
        if extraColumns['col'..i] then
            row:tag('th')
                :wikitext(config['col'..i..'Title'])
        end
    end
    row:tag('th'):wikitext('Długość'):css('width', '40px')
    return row
end

function createSongRow(song, extraColumns, config, rowNumber)
    local row = mw.html.create('tr')

    local titleText = '„'..song.title..'”'
    if song.note ~= '' and song.note ~= nil then
        titleText = titleText .. ' <small>('..song.note..')</small>'
    end

    row:tag('td'):wikitext(rowNumber .. '.'):css('text-align', 'right'):done()
        :tag('td'):wikitext(titleText):attr('id', song.spanId)

    for i = 1, 4 do
        if extraColumns['col'..i] then
            row:tag('td'):wikitext(song['col'..i])
        end
    end
    local timeCell = row:tag('td'):css('text-align', 'right')
    if song.time ~= nil then
    	timeCell:wikitext(song.timeString)
    else
    	-- Kiedy w komórce nie udało się wczytać czasu, wypisz błąd zamiast oryginalnego tekstu
    	timeCell:wikitext('<strong class="error">FORMAT?</strong>[[Kategoria:Szablony - błędy wywołań]]')
    end
    return row
end

function drawTable(entries, extraColumns, config, styles)
	local numColumns = 3 -- Tyle jest bez żadnych dodatkowych
	for i = 1, 4 do
        if extraColumns['col'..i] then
            numColumns = numColumns + 1
        end
    end
	
    local outTable = mw.html.create('table')
    outTable
        :addClass('wikitable')
        :addClass('szablon-lista_utworow_2')
        :css('width', config.tableWidth)

    if config.albumTitle ~= '' then
        local title = config.albumTitle
        if config.albumNote ~= '' then
            title = title .. ' <small>('..config.albumNote..')</small>'
        end
        if config.year ~= '' then
            title = title .. ' – [['..config.year..' w muzyce|'..config.year..']]'
        end
        outTable:addClass('mw-collapsible')
            :addClass(config.tableCollapsed and 'mw-collapsed' or nil)
            :tag('tr'):tag('th')
            	:attr('colspan', numColumns)
            	:wikitext(title)
    end

    outTable:node(createHeaderRow(extraColumns, config, styles))

    for i, song in ipairs(entries) do
        outTable:node(createSongRow(song, extraColumns, config, i))
    end

    if config.totalDuration then
        local totalDuration = 0
        for _, song in ipairs(entries) do
            totalDuration = totalDuration + song.time
        end

        -- Nie wyświetlaj sumy, jeśli nie udało się jej policzyć
        if totalDuration ~= 0 and totalDuration ~= nil then
            local row = outTable:tag('tr')
            row
            	:tag('td'):attr('colspan', numColumns - 1):done()
            	:tag('td'):wikitext("'''"..displayTime(totalDuration).."'''"):css('text-align', 'right')
        end
    end
    return outTable
end

-- Główna funkcja do rysowania tabeli dla listy utworów
function p.tabela(frame)
    local templateArgs = arguments.getArgs(frame)
    
    -- style są dołączane wewnątrz nagłówka, bo poza tabelą psułyby relację table + table w CSS
    local styles = frame:extensionTag{ name='TemplateStyles', args={ src='Szablon:Lista_utworów2/styles.css' } }

    local entries, extraColumns = p.readEntries(templateArgs)
    local config = readConfig(templateArgs)
    local outTable = drawTable(entries, extraColumns, config, styles)

    return tostring(outTable)
end

return p