Modul:PopulationChart: razlika između inačica

Izvor: Hrvatska internetska enciklopedija
Prijeđi na navigaciju Prijeđi na pretraživanje
mNema sažetka uređivanja
mNema sažetka uređivanja
Redak 1: Redak 1:
local p = {}
local p = {}


-- Napredna funkcija koja agresivno čisti sve ne-numeričke skrivene znakove
-- Čišćenje skrivenih znakova i prelamanje po zarezu
local function splitCSV(str)
local function splitCSV(str)
     local t = {}
     local t = {}
     if not str then return t end
     if not str then return t end
   
     str = string.gsub(str, "<!--.--->", "") -- Ukloni HTML komentare
    -- Ukloni HTML komentare ako ih ima
     str = string.gsub(str, "<!--.--->", "")
   
    -- Razlomi niz preko zareza
     for value in string.gmatch(str, "([^,]+)") do
     for value in string.gmatch(str, "([^,]+)") do
        -- Očisti sve razmake, prijelome redaka (\n), tabulatore (\t) i skrivene znakove
         value = string.gsub(value, "[%s%c]", "") -- Ukloni razmake i skrivene prijelome
         value = string.gsub(value, "[%s%c]", "")
       
         local num = tonumber(value)
         local num = tonumber(value)
         if num then
         if num then
Redak 28: Redak 22:
     local n = #years
     local n = #years


    -- Ako modul ne nađe podatke, ispisat će točan broj koji je uspio pročitati radi lakšeg debugiranja
     if n == 0 or #pops ~= n then
     if n == 0 or #pops ~= n then
         return '<strong class="error">Greška u grafikonu: Broj učitanih godina (' .. n .. ') i broj stanovnika (' .. #pops .. ') se ne podudaraju. Provjerite jesu li svi zarezi ispravno postavljeni.</strong>'
         return '<strong class="error">Greška u grafikonu: Broj godina (' .. n .. ') i stanovnika (' .. #pops .. ') se ne podudara.</strong>'
     end
     end


     -- Konfiguracija grafikona
     -- Konfiguracija boje (zadano diskretna plava)
    local svgWidth  = tonumber(args.svg_width)   or 800
     local barColor = args.line_color or "#3366cc"
    local svgHeight  = tonumber(args.svg_height)  or 300
    local svgPadding = tonumber(args.svg_padding) or 25 -- Malo povećan padding za bolji izgled točaka
     local lineColor  = args.line_color           or "#007bff"


     -- Pronalaženje statistike
     -- Izračun statistike
     local maxv = pops[1]
     local maxv = pops[1]
     local minv = pops[1]
     local minv = pops[1]
Redak 48: Redak 38:
         sum = sum + v
         sum = sum + v
     end
     end
    local innerWidth  = svgWidth - (svgPadding * 2)
    local innerHeight = svgHeight - (svgPadding * 2)
     local divisor = maxv > 0 and maxv or 1
     local divisor = maxv > 0 and maxv or 1


     -- Izrada SVG-a
     -- Prazan tablični string (koristimo "wikitable" klasu)
    local points = {}
     local html = {}
     local circles = {}
     table.insert(html, '<table class="wikitable population-table" style="width: 100%; max-width: 500px; font-size: 90%; margin: 10px 0; border-collapse: collapse;">')
     for i, v in ipairs(pops) do
    table.insert(html, '<tr><th style="width: 15%; text-align: center;">Godina</th><th style="width: 25%; text-align: right;">Stanovnika</th><th style="width: 60%;">Trend / Grafikon</th></tr>')
        local x = svgPadding
        if n > 1 then
            x = svgPadding + ((i - 1) * (innerWidth / (n - 1)))
        end
        local y = svgHeight - svgPadding - ((v / divisor) * innerHeight)
       
        table.insert(points, string.format("%.1f,%.1f", x, y))
        table.insert(circles, string.format(
            '<circle cx="%.1f" cy="%.1f" r="5" fill="%s" stroke="#ffffff" stroke-width="2"><title>Godina %d: %d stanovnika</title></circle>',
            x, y, lineColor, years[i], v
        ))
    end
 
    local svg = string.format([[<svg class="population-linechart" viewBox="0 0 %d %d" style="width:100%%; height:auto;" xmlns="http://www.w3.org/2000/svg">
  <polyline fill="none" stroke="%s" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" points="%s" />
  %s
</svg>]], svgWidth, svgHeight, lineColor, table.concat(points, " "), table.concat(circles, "\n"))


     -- Izrada Bar Chart-a (Stupaca)
     -- Popunjavanje redaka tablice
    local bars = {}
     for i = 1, n do
     for i = 1, n do
         local trend = "equal"
         local percentage = math.floor((pops[i] / divisor) * 100)
       
        -- Određivanje indikatora trenda
        local trendIndicator = ""
         if i > 1 then
         if i > 1 then
             if pops[i] > pops[i-1] then
             if pops[i] > pops[i-1] then
                 trend = "up"
                 trendIndicator = ' <span style="color: #28a745; font-size: 85%;">▲</span>'
             elseif pops[i] < pops[i-1] then
             elseif pops[i] < pops[i-1] then
                 trend = "down"
                 trendIndicator = ' <span style="color: #dc3545; font-size: 85%;">▼</span>'
            else
                trendIndicator = ' <span style="color: #6c757d; font-size: 85%;">■</span>'
             end
             end
         end
         end
          
 
         local width = math.floor((pops[i] / divisor) * 100)
         -- Formatiranje broja s tisućnim razdjelnikom (npr. 1.234)
         table.insert(bars, string.format([[<div class="population-bar">
         local formattedPop = tostring(pops[i]):reverse():gsub("(%d%d%d)", "%1."):reverse():gsub("^%.", "")
   <div class="population-year">%d</div>
 
   <div class="population-bar-wrapper">
         table.insert(html, string.format([[<tr>
     <div class="population-value %s" style="width:%d%%;" title="Godina %d: %d stanovnika">
  <td style="text-align: center; font-weight: bold; background: #f8f9fa;">%d</td>
      <span>%d</span>
   <td style="text-align: right; white-space: nowrap; padding-right: 8px;">%s%s</td>
   <td style="vertical-align: middle; padding: 4px 8px;">
     <div style="background: #e9ecef; border-radius: 2px; width: 100%%; height: 12px;">
      <div style="background: %s; width: %d%%; height: 100%%; border-radius: 2px;" title="Godina %d: %s stanovnika"></div>
     </div>
     </div>
   </div>
   </td>
</div>]], years[i], trend, width, years[i], pops[i], pops[i]))
</tr>]], years[i], formattedPop, trendIndicator, barColor, percentage, years[i], formattedPop))
     end
     end


     local stats = string.format([[<div class="population-stats">
    -- Dodavanje kompaktne statistike na dno tablice
   <strong>Najviše:</strong> %d stanovnika<br>
     local avgPop = math.floor(sum / n)
  <strong>Najmanje:</strong> %d stanovnika<br>
    local formattedAvg = tostring(avgPop):reverse():gsub("(%d%d%d)", "%1."):reverse():gsub("^%.", "")
  <strong>Prosjek:</strong> %d stanovnika<br>
   
   <strong>Ukupno popisa:</strong> %d
    table.insert(html, string.format([[<tr style="background: #f8f9fa; font-weight: bold; border-top: 2px solid #a2a9b1;">
</div>]], maxv, minv, math.floor(sum / n), n)
   <td colspan="3" style="font-size: 85%; padding: 6px; text-align: left; color: #54595d;">
    Ukupno popisa: %d &nbsp;|&nbsp; Prosjek: %s &nbsp;|&nbsp; Raspon: %s - %s
   </td>
</tr>]], n, formattedAvg,  
    tostring(minv):reverse():gsub("(%d%d%d)", "%1."):reverse():gsub("^%.", ""),
    tostring(maxv):reverse():gsub("(%d%d%d)", "%1."):reverse():gsub("^%.", "")))
 
    table.insert(html, '</table>')


     return '<div class="population-wrapper">\n' .. table.concat(bars, "\n") .. '\n' .. svg .. '\n' .. stats .. '\n' .. '</div>'
     return table.concat(html, "\n")
end
end


return p
return p

Inačica od 19. srpanj 2026. u 10:04

Dokumentacija modula


local p = {}

-- Čišćenje skrivenih znakova i prelamanje po zarezu
local function splitCSV(str)
    local t = {}
    if not str then return t end
    str = string.gsub(str, "<!--.--->", "") -- Ukloni HTML komentare
    for value in string.gmatch(str, "([^,]+)") do
        value = string.gsub(value, "[%s%c]", "") -- Ukloni razmake i skrivene prijelome
        local num = tonumber(value)
        if num then
            table.insert(t, num)
        end
    end
    return t
end

function p.render(frame)
    local args = frame:getParent() and frame:getParent().args or frame.args
    local years = splitCSV(args.years)
    local pops  = splitCSV(args.pops)
    local n = #years

    if n == 0 or #pops ~= n then
        return '<strong class="error">Greška u grafikonu: Broj godina (' .. n .. ') i stanovnika (' .. #pops .. ') se ne podudara.</strong>'
    end

    -- Konfiguracija boje (zadano diskretna plava)
    local barColor = args.line_color or "#3366cc"

    -- Izračun statistike
    local maxv = pops[1]
    local minv = pops[1]
    local sum  = 0
    for _, v in ipairs(pops) do
        if v > maxv then maxv = v end
        if v < minv then minv = v end
        sum = sum + v
    end
    local divisor = maxv > 0 and maxv or 1

    -- Prazan tablični string (koristimo "wikitable" klasu)
    local html = {}
    table.insert(html, '<table class="wikitable population-table" style="width: 100%; max-width: 500px; font-size: 90%; margin: 10px 0; border-collapse: collapse;">')
    table.insert(html, '<tr><th style="width: 15%; text-align: center;">Godina</th><th style="width: 25%; text-align: right;">Stanovnika</th><th style="width: 60%;">Trend / Grafikon</th></tr>')

    -- Popunjavanje redaka tablice
    for i = 1, n do
        local percentage = math.floor((pops[i] / divisor) * 100)
        
        -- Određivanje indikatora trenda
        local trendIndicator = ""
        if i > 1 then
            if pops[i] > pops[i-1] then
                trendIndicator = ' <span style="color: #28a745; font-size: 85%;">▲</span>'
            elseif pops[i] < pops[i-1] then
                trendIndicator = ' <span style="color: #dc3545; font-size: 85%;">▼</span>'
            else
                trendIndicator = ' <span style="color: #6c757d; font-size: 85%;">■</span>'
            end
        end

        -- Formatiranje broja s tisućnim razdjelnikom (npr. 1.234)
        local formattedPop = tostring(pops[i]):reverse():gsub("(%d%d%d)", "%1."):reverse():gsub("^%.", "")

        table.insert(html, string.format([[<tr>
  <td style="text-align: center; font-weight: bold; background: #f8f9fa;">%d</td>
  <td style="text-align: right; white-space: nowrap; padding-right: 8px;">%s%s</td>
  <td style="vertical-align: middle; padding: 4px 8px;">
    <div style="background: #e9ecef; border-radius: 2px; width: 100%%; height: 12px;">
      <div style="background: %s; width: %d%%; height: 100%%; border-radius: 2px;" title="Godina %d: %s stanovnika"></div>
    </div>
  </td>
</tr>]], years[i], formattedPop, trendIndicator, barColor, percentage, years[i], formattedPop))
    end

    -- Dodavanje kompaktne statistike na dno tablice
    local avgPop = math.floor(sum / n)
    local formattedAvg = tostring(avgPop):reverse():gsub("(%d%d%d)", "%1."):reverse():gsub("^%.", "")
    
    table.insert(html, string.format([[<tr style="background: #f8f9fa; font-weight: bold; border-top: 2px solid #a2a9b1;">
  <td colspan="3" style="font-size: 85%; padding: 6px; text-align: left; color: #54595d;">
    Ukupno popisa: %d &nbsp;|&nbsp; Prosjek: %s &nbsp;|&nbsp; Raspon: %s - %s
  </td>
</tr>]], n, formattedAvg, 
    tostring(minv):reverse():gsub("(%d%d%d)", "%1."):reverse():gsub("^%.", ""), 
    tostring(maxv):reverse():gsub("(%d%d%d)", "%1."):reverse():gsub("^%.", "")))

    table.insert(html, '</table>')

    return table.concat(html, "\n")
end

return p