Modul:PopulationChart: razlika između inačica
Prijeđi na navigaciju
Prijeđi na pretraživanje
mNema sažetka uređivanja |
mNema sažetka uređivanja |
||
| Redak 3: | Redak 3: | ||
local function splitCSV(str) | local function splitCSV(str) | ||
local t = {} | local t = {} | ||
-- Čisti whitespace i prelama po zarezu | |||
for value in string.gmatch(str or "", "([^,]+)") do | for value in string.gmatch(str or "", "([^,]+)") do | ||
value = mw.text.trim(value) | value = mw.text.trim(value) | ||
table.insert(t, | local num = tonumber(value) | ||
if num then | |||
table.insert(t, num) | |||
end | |||
end | end | ||
return t | return t | ||
| Redak 11: | Redak 15: | ||
function p.render(frame) | function p.render(frame) | ||
local args | -- Dohvaćanje argumenata iz predloška | ||
local args = frame:getParent() and frame:getParent().args or frame.args | |||
local years = splitCSV(args.years) | local years = splitCSV(args.years) | ||
local pops = splitCSV(args.pops) | local pops = splitCSV(args.pops) | ||
local n = #years | |||
-- Validacija podataka | |||
if n == 0 or #pops ~= n then | if n == 0 or #pops ~= n then | ||
return | return '<strong class="error">Greška: Broj godina (' .. n .. ') i broj stanovnika (' .. #pops .. ') se ne podudara ili su podaci neispravni.</strong>' | ||
end | end | ||
-- Konfiguracija | -- Konfiguracija | ||
local svgWidth = tonumber(args.svg_width) or 800 | local svgWidth = tonumber(args.svg_width) or 800 | ||
local svgHeight = tonumber(args.svg_height) or 300 | local svgHeight = tonumber(args.svg_height) or 300 | ||
| Redak 31: | Redak 36: | ||
local minv = pops[1] | local minv = pops[1] | ||
local sum = 0 | local sum = 0 | ||
for _, v in ipairs(pops) do | |||
for _,v in ipairs(pops) do | |||
if v > maxv then maxv = v end | if v > maxv then maxv = v end | ||
if v < minv then minv = v end | if v < minv then minv = v end | ||
| Redak 38: | Redak 42: | ||
end | end | ||
local innerHeight = svgHeight - svgPadding * 2 | -- Izračun raspona za SVG (unutar paddinga) | ||
local innerWidth = svgWidth - (svgPadding * 2) | |||
local innerHeight = svgHeight - (svgPadding * 2) | |||
-- SVG | -- Ako je maxv 0, postavi na 1 da izbjegnemo dijeljenje s nulom | ||
local divisor = maxv > 0 and maxv or 1 | |||
-- SVG linija i točke | |||
local points = {} | local points = {} | ||
local circles = {} | local circles = {} | ||
for i, v in ipairs(pops) do | |||
for i,v in ipairs(pops) do | -- X se raspoređuje linearno unutar innerWidth, počevši od svgPadding | ||
local x = (i-1) * ( | local x = svgPadding | ||
local y = svgHeight - svgPadding - (v / | if n > 1 then | ||
x = svgPadding + ((i - 1) * (innerWidth / (n - 1))) | |||
end | |||
-- Y ide odozgo prema dolje (0 je vrh SVG-a) | |||
local y = svgHeight - svgPadding - ((v / divisor) * innerHeight) | |||
table.insert(points, string.format("%.1f,%.1f", x, y)) | table.insert(points, string.format("%.1f,%.1f", x, y)) | ||
table.insert(circles, string.format( | table.insert(circles, string.format( | ||
'<circle cx="%.1f" cy="%.1f" r=" | '<circle cx="%.1f" cy="%.1f" r="5" fill="%s" stroke="#fff" stroke-width="1.5"><title>Godina %d: %d stanovnika</title></circle>', | ||
x, y, lineColor, years[i], v | x, y, lineColor, years[i], v | ||
)) | )) | ||
end | end | ||
local svg = string.format([[ | local svg = string.format([[<svg class="population-linechart" viewBox="0 0 %d %d" style="width:100%%; height:auto;"> | ||
<svg class="population-linechart" viewBox="0 0 %d %d" | <polyline fill="none" stroke="%s" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" points="%s" /> | ||
<polyline fill="none" stroke="%s" stroke-width="3" points="%s" /> | |||
%s | %s | ||
</svg> | </svg>]], svgWidth, svgHeight, lineColor, table.concat(points, " "), table.concat(circles, "\n")) | ||
]], svgWidth, svgHeight, lineColor, table.concat(points, " "), table.concat(circles, "\n")) | |||
-- Bar chart | -- Bar chart (Stupci) | ||
local bars = {} | local bars = {} | ||
for i = 1, n do | |||
for i=1,n do | |||
local trend = "equal" | local trend = "equal" | ||
if i > 1 then | if i > 1 then | ||
| Redak 75: | Redak 84: | ||
end | end | ||
end | end | ||
local width = math.floor((pops[i] / | local width = math.floor((pops[i] / divisor) * 100) | ||
table.insert(bars, string.format([[<div class="population-bar"> | |||
table.insert(bars, string.format([[ | |||
<div class="population-bar"> | |||
<div class="population-year">%d</div> | <div class="population-year">%d</div> | ||
<div class="population-value %s" style="width:%d%%;" | <div class="population-bar-wrapper"> | ||
<div class="population-value %s" style="width:%d%%;" title="Godina %d: %d stanovnika"> | |||
<span>%d</span> | |||
</div> | |||
</div> | </div> | ||
</div> | </div>]], years[i], trend, width, years[i], pops[i], pops[i])) | ||
]], years[i], trend, width, years[i], pops[i], pops[i])) | |||
end | end | ||
local stats = string.format([[ | local stats = string.format([[<div class="population-stats"> | ||
<div class="population-stats"> | <strong>Najviše:</strong> %d stanovnika<br> | ||
Najviše: %d stanovnika<br> | <strong>Najmanje:</strong> %d stanovnika<br> | ||
Najmanje: %d stanovnika<br> | <strong>Prosjek:</strong> %d stanovnika<br> | ||
Prosjek: %d stanovnika<br> | <strong>Ukupno godina:</strong> %d | ||
Ukupno godina: %d | </div>]], maxv, minv, math.floor(sum / n), n) | ||
</div> | |||
]], maxv, minv, math.floor(sum/n), n) | |||
return '<div class="population-wrapper">' .. table.concat(bars, "\n") .. svg .. stats .. '</div>' | return '<div class="population-wrapper">\n' .. table.concat(bars, "\n") .. '\n' .. svg .. '\n' .. stats .. '\n' .. '</div>' | ||
end | end | ||
return p | return p | ||
Inačica od 19. srpanj 2026. u 08:33
local p = {}
local function splitCSV(str)
local t = {}
-- Čisti whitespace i prelama po zarezu
for value in string.gmatch(str or "", "([^,]+)") do
value = mw.text.trim(value)
local num = tonumber(value)
if num then
table.insert(t, num)
end
end
return t
end
function p.render(frame)
-- Dohvaćanje argumenata iz predloška
local args = frame:getParent() and frame:getParent().args or frame.args
local years = splitCSV(args.years)
local pops = splitCSV(args.pops)
local n = #years
-- Validacija podataka
if n == 0 or #pops ~= n then
return '<strong class="error">Greška: Broj godina (' .. n .. ') i broj stanovnika (' .. #pops .. ') se ne podudara ili su podaci neispravni.</strong>'
end
-- Konfiguracija
local svgWidth = tonumber(args.svg_width) or 800
local svgHeight = tonumber(args.svg_height) or 300
local svgPadding = tonumber(args.svg_padding) or 20
local lineColor = args.line_color or "#007bff"
-- Statistika
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
-- Izračun raspona za SVG (unutar paddinga)
local innerWidth = svgWidth - (svgPadding * 2)
local innerHeight = svgHeight - (svgPadding * 2)
-- Ako je maxv 0, postavi na 1 da izbjegnemo dijeljenje s nulom
local divisor = maxv > 0 and maxv or 1
-- SVG linija i točke
local points = {}
local circles = {}
for i, v in ipairs(pops) do
-- X se raspoređuje linearno unutar innerWidth, počevši od svgPadding
local x = svgPadding
if n > 1 then
x = svgPadding + ((i - 1) * (innerWidth / (n - 1)))
end
-- Y ide odozgo prema dolje (0 je vrh SVG-a)
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="#fff" stroke-width="1.5"><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;">
<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"))
-- Bar chart (Stupci)
local bars = {}
for i = 1, n do
local trend = "equal"
if i > 1 then
if pops[i] > pops[i-1] then
trend = "up"
elseif pops[i] < pops[i-1] then
trend = "down"
end
end
local width = math.floor((pops[i] / divisor) * 100)
table.insert(bars, string.format([[<div class="population-bar">
<div class="population-year">%d</div>
<div class="population-bar-wrapper">
<div class="population-value %s" style="width:%d%%;" title="Godina %d: %d stanovnika">
<span>%d</span>
</div>
</div>
</div>]], years[i], trend, width, years[i], pops[i], pops[i]))
end
local stats = string.format([[<div class="population-stats">
<strong>Najviše:</strong> %d stanovnika<br>
<strong>Najmanje:</strong> %d stanovnika<br>
<strong>Prosjek:</strong> %d stanovnika<br>
<strong>Ukupno godina:</strong> %d
</div>]], maxv, minv, math.floor(sum / n), n)
return '<div class="population-wrapper">\n' .. table.concat(bars, "\n") .. '\n' .. svg .. '\n' .. stats .. '\n' .. '</div>'
end
return p