Module:Temperature

-- Module for temperature conversion

local refgroup = 'Temp'

local output_temp = {
	f = function ( val )
		return val .. '°F'
	end,
	
	c = function ( val )
		return val .. '°C'
	end,
	
	gm = function ( val )
		return 'Gas mark ' .. val
	end,
	
	k = function ( val )
		return val .. 'K'
	end
}

-- All ranges in celsius
local gmranges = {
	{
		start = 93,
		finish = 120,
		best = 107,
		val = '1/4'
	},

	{
		start = 120,
		finish = 134,
		best = 121,
		val = '1/2'
	},

	{
		start = 135,
		finish = 140,
		best = 135,
		val = '1'
	},

	{
		start = 141,
		finish = 150,
		best = 149,
		val = '2'
	},

	{
		start = 151,
		finish = 170,
		best = 163,
		val = '3'
	},

	{
		start = 171,
		finish = 180,
		best = 177,
		val = '4'
	},

	{
		start = 181,
		finish = 191,
		best = 190,
		val = '5'
	},

	{
		start = 192,
		finish = 217,
		best = 200,
		val = '6'
	},

	{
		start = 205,
		finish = 220,
		best = 218,
		val = '7'
	},

	{
		start = 221,
		finish = 232,
		best = 230,
		val = '8'
	},

	{
		start = 233,
		finish = 250,
		best = 246,
		val = '9'
	},

	{
		start = 251,
		finish = 260,
		best = 260,
		val = '10'
	}
}

local build_ref_from_table = function ( frame, basetemp, temps )
	local reflist = {}
	local baseval

	for _, temp in ipairs( temps ) do
		local val = output_temp[temp[1]]( temp[2] )

		if temp[1] == basetemp then
			baseval = val
			table.insert( reflist, 1, val )
		else
			table.insert( reflist, val )
		end
	end

	return frame:expandTemplate{ title = 'H:title', args = { table.concat( reflist, ' = ' ), baseval } }
end

local conversions, convert

conversions = {
	f = {
		c = function ( val )
			return ( val - 32.0 ) * ( 5.0 / 9.0 )
		end,
		
		k = function ( val )
			return convert( 'c', 'k', convert( 'f', 'c', val ) )
		end,

		gm = function ( val )
			return convert( 'c', 'gm', convert( 'f', 'c', val ) )
		end
	},

	c = {
		f = function ( val )
			return ( val * ( 9.0 / 5.0 ) ) + 32.0
		end,
		
		k = function ( val )
			return val + 273.15;
		end,
		
		gm = function ( val )
			val = tonumber( val )

			if val == nil then
				return nil
			end

			for _, range in ipairs( gmranges ) do
				if val > range.start and val <= range.finish then
					return range.val
				end
			end

			return nil
		end
	},

	gm = {
		f = function ( val )
			return convert( 'c', 'f', convert( 'gm', 'c', val ) )
		end,
		
		c = function ( val )
			for _, range in ipairs( gmranges ) do
				if val == range.val then
					return range.best
				end
			end

			return nil
		end,
		
		k = function ( val )
			return convert( 'c', 'k', convert( 'gm', 'c', val ) )
		end
	},

	k = {
		f = function ( val )
			return convert( 'c', 'f', ( val - 273.15 ) )
		end,
		
		c = function ( val )
			return val - 273.15
		end,

		gm = function ( val )
			return convert( 'c', 'gm', convert( 'k', 'c', val ) )
		end
	}
}

convert = function ( from, to, val )
	return conversions[from][to]( val )
end

local templist = {
	'f',
	'c',
	'gm',
	'k'
}

local build_table = function ( basetemp, baseval )
	local tbl = {}
	local thisVal = nil

	for _, temp in ipairs( templist ) do
		if temp == basetemp then
			table.insert( tbl, { temp, baseval } )
		else
			thisVal = convert( basetemp, temp, baseval )
			if thisVal ~= nil then
				table.insert( tbl, { temp, math.floor( thisVal ) } )
			end
		end
	end

	return tbl
end

local build_ref = function ( basetemp, frame )
	return build_ref_from_table( frame, basetemp, build_table( basetemp, frame.args[1] ) )
end

return {
	f = function ( frame )
		return build_ref( 'f', frame )
	end,
	
	c = function ( frame )
		return build_ref( 'c', frame )
	end,
	
	k = function ( frame )
		return build_ref( 'k', frame )
	end,
	
	gm = function ( frame )
		return build_ref( 'gm', frame )
	end
}