模块:WeatherGraph:修订间差异
来自Blockland Wiki
更多操作
无编辑摘要 |
无编辑摘要 |
||
| 第83行: | 第83行: | ||
local precips = {} | local precips = {} | ||
for i, m in ipairs(months) do | for i, m in ipairs(months) do | ||
table.insert(temps, tonumber(args[m .. ' mean C']) or 0) | table.insert(temps, tonumber(args[m .. ' mean C']) or 0) | ||
| 第92行: | 第91行: | ||
local title = args['location'] or "气候数据" | local title = args['location'] or "气候数据" | ||
-- | -- 生成内联 SVG 代码 | ||
local svg = '<svg width="100%" height="200" viewBox="0 0 360 200" style="background:#f8f9fa; border-radius:4px;">' | |||
local | |||
-- | -- 绘制柱状图 (降水) | ||
local | for i, p_val in ipairs(precips) do | ||
local height = p_val * 1.5 -- 降水比例尺 | |||
local x = (i - 1) * 30 + 5 | |||
local y = 200 - height | |||
svg = svg .. string.format('<rect x="%d" y="%d" width="20" height="%d" fill="#87CEFA" />', x, y, height) | |||
end | |||
-- | -- 绘制折线图 (气温) | ||
for i, | local points = "" | ||
for i, t_val in ipairs(temps) do | |||
local x = (i - 1) * | local x = (i - 1) * 30 + 15 | ||
local y = 200 - (t_val * 3) -- 气温比例尺 | |||
points = points .. string.format("%d,%d ", x, y) | |||
end | end | ||
svg = svg .. string.format('<polyline points="%s" fill="none" stroke="#FF6347" stroke-width="3" />', points) | |||
-- | -- 添加点 | ||
for i | for i, t_val in ipairs(temps) do | ||
local x = (i - 1) * 30 + 15 | |||
local | local y = 200 - (t_val * 3) | ||
local | svg = svg .. string.format('<circle cx="%d" cy="%d" r="4" fill="#DC143C" />', x, y) | ||
end | end | ||
svg = svg .. '</svg>' | |||
-- 关键:使用 MediaWiki Lua 接口调用 <html> 标签包裹 SVG,直接透传原生代码 | |||
local raw_html_svg = frame:extensionTag('html', svg) | |||
-- | -- 组装 Infobox 结构 | ||
local html = string.format([[ | local html = string.format([[ | ||
<div style="float: right; clear: right; margin: 0 0 1em 1em; width: 320px; border: 1px solid #c8ccd1; border-radius: 8px; padding: 10px; background-color: var(--background-color-base, #ffffff); box-shadow: 0 2px 4px rgba(0,0,0,0.1); font-size: 90%%;"> | <div style="float: right; clear: right; margin: 0 0 1em 1em; width: 320px; border: 1px solid #c8ccd1; border-radius: 8px; padding: 10px; background-color: var(--background-color-base, #ffffff); box-shadow: 0 2px 4px rgba(0,0,0,0.1); font-size: 90%%;"> | ||
<div style="text-align: center; font-weight: bold; font-size: 1.1em; margin-bottom: | <div style="text-align: center; font-weight: bold; font-size: 1.1em; margin-bottom: 10px; background: #eaecf0; padding: 5px; border-radius: 4px;">%s</div> | ||
%s | <div style="margin-bottom: 10px;">%s</div> | ||
<div style="text-align: center; font-weight: bold; color: #54595d | <div style="text-align: center; font-weight: bold; color: #54595d;">柯本气候分类:<br><span style="color: #2a4b8d;">%s</span></div> | ||
<div style="font-size: 0.85em; color: #72777d; text-align: right; margin-top: 8px;">来源:%s</div> | <div style="font-size: 0.85em; color: #72777d; text-align: right; margin-top: 8px;">来源:%s</div> | ||
</div> | </div> | ||
]], title, | ]], title, raw_html_svg, koppen, args['source'] or "未知") | ||
return html | return html | ||
2026年5月12日 (二) 16:35的版本
此模块的文档可以在模块:WeatherGraph/doc创建
local p = {}
-- 柯本气候分类计算器
local function calculateKoppen(temps, precips)
local t_mean = 0
local p_total = 0
local t_hot = -99
local t_cold = 99
local p_min_summer = 9999
local p_max_summer = 0
local p_min_winter = 9999
local p_max_winter = 0
local summer_p_total = 0
local winter_p_total = 0
for i = 1, 12 do
local t = tonumber(temps[i]) or 0
local p = tonumber(precips[i]) or 0
t_mean = t_mean + t
p_total = p_total + p
if t > t_hot then t_hot = t end
if t < t_cold then t_cold = t end
-- 简单划分夏冬半季(北半球:4-9月为夏,10-3月为冬)
if i >= 4 and i <= 9 then
summer_p_total = summer_p_total + p
if p < p_min_summer then p_min_summer = p end
if p > p_max_summer then p_max_summer = p end
else
winter_p_total = winter_p_total + p
if p < p_min_winter then p_min_winter = p end
if p > p_max_winter then p_max_winter = p end
end
end
t_mean = t_mean / 12
-- 计算干燥阈值 (Pth)
local pth = 20 * t_mean
if summer_p_total > (p_total * 0.7) then
pth = pth + 280
elseif winter_p_total > (p_total * 0.7) then
pth = pth
else
pth = pth + 140
end
-- B类:干旱气候
if p_total < pth then
if p_total < (pth / 2) then
return t_mean >= 18 and "BWh (热带沙漠气候)" or "BWk (温带沙漠气候)"
else
return t_mean >= 18 and "BSh (热带草原/半干旱气候)" or "BSk (温带草原/半干旱气候)"
end
end
-- A类:热带气候
if t_cold >= 18 then
if (p_min_winter < 60 and p_min_summer < 60) then return "Aw/As (热带干湿季气候)" end
return "Af (热带雨林气候)"
end
-- C类与D类
if t_hot >= 10 and t_cold > -3 and t_cold < 18 then
return "C 类 (温带气候)"
end
if t_hot >= 10 and t_cold <= -3 then
return "D 类 (大陆性气候)"
end
-- E类:极地气候
if t_hot < 10 then
return t_hot > 0 and "ET (苔原气候)" or "EF (冰原气候)"
end
return "未分类"
end
function p.render(frame)
local args = frame:getParent().args
local months = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}
local temps = {}
local precips = {}
for i, m in ipairs(months) do
table.insert(temps, tonumber(args[m .. ' mean C']) or 0)
table.insert(precips, tonumber(args[m .. ' rain mm']) or 0)
end
local koppen = calculateKoppen(temps, precips)
local title = args['location'] or "气候数据"
-- 生成内联 SVG 代码
local svg = '<svg width="100%" height="200" viewBox="0 0 360 200" style="background:#f8f9fa; border-radius:4px;">'
-- 绘制柱状图 (降水)
for i, p_val in ipairs(precips) do
local height = p_val * 1.5 -- 降水比例尺
local x = (i - 1) * 30 + 5
local y = 200 - height
svg = svg .. string.format('<rect x="%d" y="%d" width="20" height="%d" fill="#87CEFA" />', x, y, height)
end
-- 绘制折线图 (气温)
local points = ""
for i, t_val in ipairs(temps) do
local x = (i - 1) * 30 + 15
local y = 200 - (t_val * 3) -- 气温比例尺
points = points .. string.format("%d,%d ", x, y)
end
svg = svg .. string.format('<polyline points="%s" fill="none" stroke="#FF6347" stroke-width="3" />', points)
-- 添加点
for i, t_val in ipairs(temps) do
local x = (i - 1) * 30 + 15
local y = 200 - (t_val * 3)
svg = svg .. string.format('<circle cx="%d" cy="%d" r="4" fill="#DC143C" />', x, y)
end
svg = svg .. '</svg>'
-- 关键:使用 MediaWiki Lua 接口调用 <html> 标签包裹 SVG,直接透传原生代码
local raw_html_svg = frame:extensionTag('html', svg)
-- 组装 Infobox 结构
local html = string.format([[
<div style="float: right; clear: right; margin: 0 0 1em 1em; width: 320px; border: 1px solid #c8ccd1; border-radius: 8px; padding: 10px; background-color: var(--background-color-base, #ffffff); box-shadow: 0 2px 4px rgba(0,0,0,0.1); font-size: 90%%;">
<div style="text-align: center; font-weight: bold; font-size: 1.1em; margin-bottom: 10px; background: #eaecf0; padding: 5px; border-radius: 4px;">%s</div>
<div style="margin-bottom: 10px;">%s</div>
<div style="text-align: center; font-weight: bold; color: #54595d;">柯本气候分类:<br><span style="color: #2a4b8d;">%s</span></div>
<div style="font-size: 0.85em; color: #72777d; text-align: right; margin-top: 8px;">来源:%s</div>
</div>
]], title, raw_html_svg, koppen, args['source'] or "未知")
return html
end
return p