Jump to content

Module:Sandbox/Erutuon/Climate

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Erutuon (talk | contribs) at 19:09, 25 June 2018 (partial first draft of Köppen climate classification function). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)

local p = {}

local map = require "Module:Utility".map

local function errorf(level, ...)
	if type(level) == number then
		return error(string.format(...), level + 1)
	else -- level is actually the format string.
		return error(string.format(level, ...), 2)
	end
end

local function some(func, t)
	for _, v in ipairs(t) do
		if func(v) then
			return true
		end
	end
	return false
end

local function min_index(t)
	local index
	local min = math.huge
	for i, v in ipairs(t) do
		if v < min then
			min = v
			index = i
		end
	end
	return index
end

local function max_index(t)
	local index
	local max = -math.huge
	for i, v in ipairs(t) do
		if v > max then
			max = v
			index = i
		end
	end
	return index
end
			

local function mean (...)
	local n = select('#', ...)
	local sum = 0
	for i = 1, n do
		sum = sum + select(i, ...)
	end
	return sum / n
end

local function mean_of_highs_and_lows(highs, lows)
	local high_count, low_count = #highs, #lows
	if not (high_count == 12 or high_count == 13)
			or not (low_count == 12 or low_count == 13) then
		errorf("Wrong number of highs or lows (%d, %d): expected 12 or 13 each",
			high_count, low_count)
	elseif high_count ~= low_count then
		error("Number of highs and and number of lows are not equal")
	end
	
	local temperatures = {}
	
	for i = 1, high_count do
		if highs[i] <= lows[i] then
			error("High #%d (%d) is not greater than low #%d (%d)",
				i, highs[i], i, lows[i])
		end
		temperatures[i] = mean(highs[i], lows[i])
	end
	
	return temperatures
end

-- temperatures and precipitation are tables of mean monthly temperature and
-- precipitation. Or temperatures can be a table containing a table of monthly
-- mean of daily highs and monthly mean of daily lows.
function p.Koeppen(temperatures, precipitation, Southern_Hemisphere)
	if #temperatures == 2 then
		local highs_and_lows = temperatures
		temperatures = mean_of_highs_and_lows(unpack(temperatures))
	end
	
	local min_temp_index, max_temp_index =
		min_index(temperatures), max_index(temperatures)
	
	local min_precip_index, max_precip_index =
		min_index(precipitation), max_index(precipitation)
	
	local first_summer_month, last_winter_month
	if Southern_Hemisphere then
		first_summer_month, last_winter_month = 10, 3
	else
		first_summer_month, last_winter_month = 4, 9
	end
	
	local mean_temp = mean(unpack(temperatures))
	local total_precip = mean(unpack(precipitation))
	local mean_summer_precip =
		mean(unpack(precipitation, first_summer_month, last_winter_month))
	
	local threshold_addition
	if total_precip / mean_summer_precip >= 0.7 then
		threshold_addition = 280
	elseif total_precip / mean_summer_precip >= 0.3 then
		threshold_addition = 140
	else
		threshold_addition = 0
	end
	
	local threshold = mean_temp * 20 + threshold_addition
	if total_precip <= threshold then
		return "B"
			 .. (total_precip < threshold / 2 and "W" or "S") -- arid, semi-arid
			 .. (mean_temp < 0 and "k" or "h")
	end
	
	local min_month_temp, max_month_temp =
		temperatures[min_temp_index], temperatures[max_temp_index]
	
	local temp_letter = min_month_temp < 10 and "E"
		or min_month_temp < 0 and "D"
		or min_month_temp >= 18 and "A"
		or "C"
	
	if temp_letter == "E" then
		return temp_letter .. (max_month_temp < 0 and "F" or "T")
	elseif temp_letter == "D" then
		
	end
	
end

return p