Module:Climate chart
Appearance
![]() | This module is rated as ready for general use. It has reached a mature form and is thought to be relatively bug-free and ready for use wherever appropriate. It is ready to mention on help pages and other Wikipedia resources as an option for new users to learn. To reduce server load and bad output, it should be improved by sandbox testing rather than repeated trial-and-error editing. |
![]() | This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
![]() | This module depends on the following other modules: |
![]() | This module uses TemplateStyles: |
Implements {{climate chart}}. At some point.
Usage
{{#invoke:Climate chart|function_name}}
local p = {}
local cfg = mw.loadData('Module:Climate chart/configuration')
-- from https://lua-users.org/wiki/SimpleRound
local function round(num, decimal_places)
local mult = 10^(decimal_places or 0)
return math.floor(num * mult + 0.5) / mult
end
local function c_to_f(temperature_in_c)
return temperature_in_c * 1.8 + 32
end
local function mm_to_in(precipitation_in_mm)
return precipitation_in_mm / 25.4
end
-- this implements the fahrenheit subtemplate, will need to look into what the
-- celsius template is doing
-- unit_system currently unused accordingly
local function month_column(low_temp, high_temp, precipitation, max_precipitation, unit_system)
local precipitation = precipitation or 80
local base_precipitation = max_precipitation or 500
local precipitation_scale = math.max(1, base_precipitation / 750) -- 750 mm is the maximum for height
local precipitation_bar_height = precipitation / 50 / precipitation_scale -- 50 is a magic constant
local precipitation_in_inches = precipitation / 25.4
local decimal_places = 0
if precipitation_in_inches < 10 then decimal_places = 1 end
local rounded_precipitation_inches = round(precipitation_in_inches, decimal_places)
local low_temp = low_temp or 10
local high_temp = high_temp or 20
local low_temp_shift_for_bar = low_temp / 5 + 8 -- magic numbers
local temp_bar_height = (high_temp - low_temp) / 5 -- magic numbers
local high_temp_shift = high_temp / 5 + 8
local low_temp_shift = low_temp / 5 + 6.5
local high_temp_f = c_to_f(high_temp)
local rounded_high_temp_f = round(high_temp_f, 0)
local high_temp_sign = ''
if rounded_high_temp_f < 0 then high_temp_sign = '−' end
local abs_high_temp = math.abs(rounded_high_temp_f)
local low_temp_f = c_to_f(low_temp)
local rounded_low_temp_f = round(low_temp_f, 0)
local low_temp_sign = ''
if rounded_low_temp_f < 0 then low_temp_sign = '−' end
local abs_low_temp = math.abs(rounded_low_temp_f)
local column = mw.html.create('div')
column:addClass('climate-chart-column')
:tag('div')
:addClass('climate-chart-column-spacer')
:wikitext(' ')
:done()
:tag('div')
:addClass('climate-chart-column-precip-bar')
:wikitext(' ')
:css('height', precipitation_bar_height .. 'em')
:css('print-color-adjust', 'exact') -- css sanitizer doesn't accept yet
:done()
:tag('div')
:addClass('climiate-chart-column-precip')
:tag('span')
:wikitext(rounded_precipitation_inches)
:done()
:done()
:tag('div')
:addClass('climate-chart-column-spacer2')
:wikitext(' ')
:done()
:tag('div')
:addClass('climate-chart-column-temp-bar')
:wikitext(' ')
:css('bottom', low_temp_shift_for_bar .. 'em' )
:css('height', temp_bar_height .. 'em')
:css('print-color-adjust', 'exact') -- css sanitizer doesn't accept yet
:done()
:tag('div')
:addClass('climate-chart-column-high-temp')
:css('bottom', high_temp_shift .. 'em')
:tag('span')
:wikitext(high_temp_sign .. abs_high_temp)
:done()
:done()
:tag('div')
:addClass('climate-chart-column-low-temp')
:css('bottom', low_temp_shift .. 'em')
:tag('span')
:wikitext(low_temp_sign .. abs_low_temp)
:done()
:done()
:done()
return column
end
local function header_row()
local month_row = mw.html.create('tr')
for month in ipairs(cfg.i18n.months) do
month_row:tag('th')
:attr('scope', 'col')
:wikitext(month)
:done()
end
return month_row:allDone()
end
local function arg_or_default(args, from_arg, default)
local arg = mw.text.trim(args[from_arg] or '')
if arg ~= '' then
return arg
else
return default
end
end
-- TODO: implement
local function table_insanity(args, imperial)
local primary = mw.html.create('table')
:addClass('climate-chart-primary climate-chart-internal')
:node(header_row())
:done()
local secondary_chart = mw.html.create('table')
:addClass('climate-chart-secondary climate-chart-internal')
:node(header_row())
:done()
local secondary_title = imperial and cfg.i18n.secondary_title_metric or cfg.i18n.secondary_title_imperial
-- primary has html_chart
return primary, {
title = secondary_title,
chart = secondary_chart
}
end
local function wrap_secondary_content(chart_content, temp_explanation, precip_explanation)
local ret = mw.html.create('div')
ret:addClass('climate-chart-secondary mw-collapsible mw-collapsed')
:tag('div')
:addClass('climate-chart-secondary-title')
:wikitext(chart_content.title)
:done()
:tag('div')
:addClass('mw-collapsible-content')
:node(chart_content.chart)
:node(temp_explanation)
:node(precip_explanation)
:done()
return ret
end
local function explain_bar(bar_type, text)
local ret = mw.html.create('p')
ret:addClass('climate-change-explain-bar-' .. bar_type)
:tag('span')
:wikitext(cfg.i18n.explainer_key)
:done()
:wikitext(text)
:done()
return ret
end
local function explain(imperial, bar_type, imperial_explanation, metric_explanation)
if imperial then
return explain_bar(bar_type, imperial_explanation),
explain_bar(bar_type, metric_explanation)
else
return explain_bar(bar_type, metric_explanation),
explain_bar(bar_type, imperial_explanation)
end
end
local function add_source(source)
if not source then return end
return mw.html.create('p'):wikitext(string.format(cfg.i18n.source, source))
end
local function add_title_content(title)
local ret = mw.html.create()
ret:tag('div')
:addClass('climate-chart-title')
:wikitext(title)
:done()
:tag('div')
:addClass('climate-chart-explainer')
:wikitext(cfg.i18n.explainer)
:done()
return ret
end
function p._main(args)
local float = arg_or_default(args, cfg.arg.float, nil)
local float_class = nil
if float then
if float == 'right' then
float_class = 'climate-chart-right'
elseif float == 'left' then
float_class = 'climate-chart-left'
end
end
local clear = arg_or_default(args, cfg.arg.clear, nil) or float
local width = arg_or_default(args, cfg.arg.width, nil)
local climate_chart = mw.html.create('div')
climate_chart:addClass('climate-chart')
:css('width', width)
:css('clear', clear)
local units = string.lower(arg_or_default(args, cfg.arg.units, ''))
local is_imperial_primary = units == cfg.keyword.imperial and true or false
local title = arg_or_default(args, cfg.arg.title, '')
local title_content = add_title_content(title)
local primary_chart, secondary_chart_content = table_insanity(
args,
is_imperial_primary
)
local primary_temp_explanation, secondary_temp_explanation = explain(
is_imperial_primary,
'temp',
cfg.i18n.explainer_fahrenheit,
cfg.i18n.explainer_celsius
)
local primary_precip_explanation, secondary_precip_explanation = explain(
is_imperial_primary,
'precip',
cfg.i18n.explainer_in,
cfg.i18n.explainer_mm
)
local source = arg_or_default(args, 'source', nil)
local wrapped_source = add_source(source)
local secondary_content = wrap_secondary_content(
secondary_chart_content,
secondary_temp_explanation,
secondary_precip_explanation
)
climate_chart:node(title_content)
:node(primary_chart)
:node(primary_temp_explanation)
:node(primary_precip_explanation)
:node(wrapped_source)
:node(secondary_content)
:allDone()
return mw.getCurrentFrame():extensionTag{
name = 'templatestyles', args = { src = 'Module:Climate chart/styles.css' }
} .. tostring(climate_chart)
end
function p.main(frame)
return p._main(frame:getParent().args)
end
return p