local p = local cfg = mw.loadData('Module:Climate chart/configuration')
-- from https://lua-users.org/wiki/SimpleRoundlocal function round(num, decimal_places) local mult = 10^(decimal_places or 0) return math.floor(num * mult + 0.5) / multend
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 endend
-- we only draw using the metric numberslocal function compute_column_draw_data(metric_year, max_precipitation) local column_draw_data = -- so many magic constants local precipitation_scale = math.max(1, max_precipitation / 750) -- 750 mm is the maximum for height for _, month in ipairs(metric_year) do local precipitation_bar_height = month.precipitation / 50 / precipitation_scale -- 50 is a magic constant local temperature_bar_displacement = month.minimum / 5 + 8 local temperature_bar_height = (month.maximum - month.minimum) / 5 local temperature_high_displacement = month.maximum / 5 + 8 local temperature_low_displacement = month.minimum / 5 + 6.5 table.insert(column_draw_data,) end return column_draw_dataend
local function present_monthly_temperature(temperature) local rounded_temp = round(temperature, 0) local temperature_sign = if rounded_temp < 0 then temperature_sign = '-' end local abs_temp = math.abs(rounded_temp) return temperature_sign .. abs_tempend
local function draw_column(month_draw_data, month_data) local precipitation = month_data.precipitation local precipitation_decimal_places = precipitation < 10 and 1 or 0 local rounded_precipitation = round(precipitation, precipitation_decimal_places) local high_temp = present_monthly_temperature(month_data.maximum) local low_temp = present_monthly_temperature(month_data.minimum) 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', month_draw_data.precipitation_height .. 'em') :css('print-color-adjust', 'exact') -- css sanitizer doesn't accept yet :done :tag('div') :addClass('climate-chart-column-value climate-chart-column-precip') :tag('span') :wikitext(rounded_precipitation) :done :done :tag('div') :addClass('climate-chart-column-spacer2') :wikitext(' ') :done :tag('div') :addClass('climate-chart-column-temp-bar') :wikitext(' ') :css('bottom', month_draw_data.temperature_displacement .. 'em') :css('height', month_draw_data.temperature_height .. 'em') :css('print-color-adjust', 'exact') -- css sanitizer doesn't accept yet :done :tag('div') :addClass('climate-chart-column-value climate-chart-column-high-temp') :css('bottom', month_draw_data.temperature_high_displacement .. 'em') :tag('span') :wikitext(high_temp) :done :done :tag('div') :addClass('climate-chart-column-value climate-chart-column-low-temp') :css('bottom', month_draw_data.temperature_low_displacement .. 'em') :tag('span') :wikitext(low_temp) :done :done :done return columnend
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:allDoneend
local function fill_nice_tables(args) local primary_table = local secondary_table = for n = 2, 37, 3 do local minimum = tonumber(args[n]) local maximum = tonumber(args[n+1]) local precipitation = tonumber(args[n+2]) -- we use the fact that `tonumber` returns nil if it gets not_a_string -- _OR_ the empty string later, since the defaults are unit-specific table.insert(primary_table,) table.insert(secondary_table,) end return primary_table, secondary_tableend
local function c_to_f(temperature_in_c) return temperature_in_c * 1.8 + 32end
local function f_to_c(temperature_in_f) return (temperature_in_f - 32) * 5/9end
local function mm_to_in(precipitation_in_mm) return precipitation_in_mm / 25.4 end
local function in_to_mm(precipitation_in_in) return precipitation_in_in * 25.4end
local function convert_inplace(t, convert_temperature, convert_precipitation) for _, month in ipairs(t) do month.minimum = convert_temperature(month.minimum) month.maximum = convert_temperature(month.maximum) month.precipitation = convert_precipitation(month.precipitation) endend
local function fill_in_nils(year_t, default_t) for _, month in ipairs(year_t) do if not month.precipitation then month.precipitation = default_t.precipitation end if not month.maximum then month.maximum = default_t.temperature_high end if not month.minimum then month.minimum = default_t.temperature_low end endend
local function chart_rows(args, imperial) local metric_t local imperial_t local maximum_precipitation = tonumber(args.maxprecip) local imperial_max_precipitation local metric_max_precipitation local default_max_precipitation = 1 if imperial then imperial_t, metric_t = fill_nice_tables(args) fill_in_nils(metric_t, cfg.metric_default) fill_in_nils(imperial_t, cfg.imperial_default) convert_inplace(metric_t, f_to_c, in_to_mm, imperial) if maximum_precipitation then imperial_max_precipitation = maximum_precipitation metric_max_precipitation = in_to_mm(maximum_precipitation) else imperial_max_precipitation = default_max_precipitation metric_max_precipitation = default_max_precipitation end else metric_t, imperial_t = fill_nice_tables(args) fill_in_nils(metric_t, cfg.metric_default) fill_in_nils(imperial_t, cfg.imperial_default) convert_inplace(imperial_t, c_to_f, mm_to_in, imperial) if maximum_precipitation then metric_max_precipitation = maximum_precipitation imperial_max_precipitation = mm_to_in(maximum_precipitation) else metric_max_precipitation = default_max_precipitation imperial_max_precipitation = default_max_precipitation end end local column_draw_data = compute_column_draw_data(metric_t, metric_max_precipitation) local metric_row = mw.html.create('tr') local imperial_row = mw.html.create('tr') local function add_columns(row, year) for i = 1, 12 do row:tag('td') :node(draw_column(column_draw_data[i], year[i])) :done end end add_columns(metric_row, metric_t) add_columns(imperial_row, imperial_t) return metric_row, imperial_row end
local function present_chart_content(args, imperial) local primary_row, secondary_row if imperial then secondary_row, primary_row = chart_rows(args, imperial) else primary_row, secondary_row = chart_rows(args, imperial) end local primary = mw.html.create('table') :addClass('climate-chart-primary climate-chart-internal') :node(header_row) :node(primary_row) :done local secondary_chart = mw.html.create('table') :addClass('climate-chart-secondary climate-chart-internal') :node(header_row) :node(secondary_row) :done local secondary_title = imperial and cfg.i18n.secondary_title_metric or cfg.i18n.secondary_title_imperial -- primary has html_chart return primary, 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 retend
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 retend
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) endend
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 retend
function p._main(args) local float = arg_or_default(args, cfg.arg.float, nil) local float_class = nil if float then if float
'left' then float_class = 'climate-chart-left' end end local clear = arg_or_default(args, cfg.arg.clear, nil) or float local units = string.lower(arg_or_default(args, cfg.arg.units, )) local is_imperial_primary = units
function p.main(frame) return p._main(frame:getParent.args)end
return p