Module:Gradient

g = {};

convert = require( "Module:BaseConvert" ); math_mod = require( "Module:Math" );

function hexToDec( val ) return convert.convert( { n = val, base = 10, from = 16, precision = 0, width = 3 } ); end

function decToHex( val ) return convert.convert( { n = val, base = 16, precision = 0, width = 2 } ); end

function getTriplet( hex_code ) local v1, v2, v3; v1 = hexToDec( hex_code:sub(1,2) ); v2 = hexToDec( hex_code:sub(3,4) ); v3 = hexToDec( hex_code:sub(5,6) ); return v1, v2, v3; end

function makeTriplet( v1, v2, v3 ) local val = { decToHex( v1 ), decToHex( v2 ), decToHex( v3 ) }   return table.concat( val ); end

function g.export_gradient( frame ) local result = {}; local index = 1; local pos, color; local v1,v2,v3; while true do       pos = frame.args[index]; color = frame.args[index + 1]; index = index + 2; if color == nil or pos == nil then break; end pos = tonumber( pos ); color = color:match( "^%s*(.-)%s*$" ); if color:sub(1,1) == '#' then color = color:sub(2); end v1, v2, v3 = getTriplet( color ); table.insert( result, pos .. ': ' .. v1 .. ', ' .. v2 .. ', ' .. v3 .. '; ' ); end return table.concat( result ); end function importGradient( gradientString ) local pattern_table = {}; gradientString = gradientString:gsub( ' ', '' ); for pos, v1, v2, v3 in string.gmatch( gradientString, "([-%d%.]*):(%d+),(%d+),(%d+);") do           table.insert( pattern_table, { tonumber(pos), tonumber(v1), tonumber(v2), tonumber(v3) } ); end comp = function( a, b ) return a[1] < b[1]; end table.sort( pattern_table, comp ); return pattern_table; end

function getGradientValue( value, gradient_table ) local last_pos = nil; local last_item = nil; for _, v in ipairs( gradient_table ) do       if v[1] >= value then if last_item == nil then return v[2], v[3], v[4]; else local shift = (value - last_item[1]) / (v[1] - last_item[1]); return shift*v[2] + (1-shift)*last_item[2], shift*v[3] + (1-shift)*last_item[3], shift*v[4] + (1-shift)*last_item[4] end end last_item = v;   end return last_item[2], last_item[3], last_item[4]; end

function g.gradient_value( frame ) local gradient = frame.args.gradient; local value = tonumber( frame.args[1] or frame.args.value ); local v1, v2, v3; if gradient == nil then return ''; end gradient = importGradient( gradient ); v1, v2, v3 = getGradientValue( value, gradient ); return makeTriplet( v1, v2, v3 ); end

function g.gradient_test( frame ) local gradient = frame.args.gradient; local step = frame.args.step; local row_break = tonumber( frame.args.cells_per_row or 20 ); if gradient == nil then return ''; end gradient = importGradient( gradient );

local min_value = nil; local max_value = nil; for _, v in ipairs( gradient ) do       if min_value == nil or min_value > v[1] then min_value = v[1]; end if max_value == nil or max_value < v[1] then max_value = v[1]; end end if step == nil then step = (max_value - min_value)/30; step = math_mod._round( step, math.max( math_mod._precision( max_value ), math_mod._precision( min_value ) ) + 1 ); end local result = "{| class=wikitable \n"; local v1, v2, v3, color; local count = 0; for i = min_value,max_value+step/2,step do       v1, v2, v3 = getGradientValue( i, gradient ); color = makeTriplet( v1, v2, v3 ); result = result .. '| style="background:#' .. color .. '; width:2em; text-align:center;" | ' .. i .. ' ' .. i .. ' \n'; count = count + 1; if count == row_break then result = result .. '|- \n'; count = 0; end end result = result .. "|}"   return result; end

return g;