Difference between pages "Module:Convert" and "Module:Convert/sandbox"

(Difference between pages)
Jump to navigation Jump to search
Page 1
Page 2
m (1 revision imported)
 
m (1 revision imported)
 
Line 411: Line 411:
 
-- If no altitude given, use default (zero altitude = sea level).
 
-- If no altitude given, use default (zero altitude = sea level).
 
-- Table gives speed of sound in miles per hour at various altitudes:
 
-- Table gives speed of sound in miles per hour at various altitudes:
--  altitude = -17,499 to 402,499 feet
+
--  altitude = -17,499 to 302,499 feet
 
-- mach_table[a + 4] = s where
 
-- mach_table[a + 4] = s where
--  a = (altitude / 5000) rounded to nearest integer (-3 to 80)
+
--  a = (altitude / 5000) rounded to nearest integer (-3 to 60)
 
--  s = speed of sound (mph) at that altitude
 
--  s = speed of sound (mph) at that altitude
 
-- LATER: Should calculate result from an interpolation between the next
 
-- LATER: Should calculate result from an interpolation between the next
Line 423: Line 423:
 
660.1, 660.1, 660.1, 662.0, 664.3, 666.5, 668.9, 671.1, 673.4, 675.6,  -- 11 to 20
 
660.1, 660.1, 660.1, 662.0, 664.3, 666.5, 668.9, 671.1, 673.4, 675.6,  -- 11 to 20
 
677.9, 683.7, 689.9, 696.0, 702.1, 708.1, 714.0, 719.9, 725.8, 731.6,  -- 21 to 30
 
677.9, 683.7, 689.9, 696.0, 702.1, 708.1, 714.0, 719.9, 725.8, 731.6,  -- 21 to 30
737.3, 737.7, 737.7, 736.2, 730.5, 724.6, 718.8, 712.9, 707.0, 701.0,  -- 31 to 40
+
737.3, 737.7, 737.7, 736.2, 730.5, 724.6, 718.8, 712.9, 707.0, 701.1,  -- 31 to 40
 
695.0, 688.9, 682.8, 676.6, 670.4, 664.1, 657.8, 652.9, 648.3, 643.7,  -- 41 to 50
 
695.0, 688.9, 682.8, 676.6, 670.4, 664.1, 657.8, 652.9, 648.3, 643.7,  -- 41 to 50
 
639.1, 634.4, 629.6, 624.8, 620.0, 615.2, 613.2, 613.2, 613.2, 613.5,  -- 51 to 60
 
639.1, 634.4, 629.6, 624.8, 620.0, 615.2, 613.2, 613.2, 613.2, 613.5,  -- 51 to 60
614.4, 615.3, 616.7, 619.8, 623.4, 629.7, 635.0, 641.1, 650.6, 660.0,  -- 61 to 70
 
672.5, 674.3, 676.1, 677.9, 679.7, 681.5, 683.3, 685.1, 686.8, 688.6,  -- 71 to 80
 
 
}
 
}
 
altitude = altitude or 0
 
altitude = altitude or 0
Line 437: Line 435:
 
if a < -3 then
 
if a < -3 then
 
a = -3
 
a = -3
elseif a > 80 then
+
elseif a > 60 then
a = 80
+
a = 60
 
end
 
end
 
return mach_table[a + 4] * 0.44704  -- mph converted to m/s
 
return mach_table[a + 4] * 0.44704  -- mph converted to m/s
Line 444: Line 442:
 
-- END: Code required only for built-in units.
 
-- END: Code required only for built-in units.
 
------------------------------------------------------------------------
 
------------------------------------------------------------------------
 
local function add_style(parms, class)
 
-- Add selected template style to parms if not already present.
 
parms.templatestyles = parms.templatestyles or {}
 
if not parms.templatestyles[class] then
 
parms.templatestyles[class] = parms.frame:extensionTag({
 
name = 'templatestyles', args = { src = text_code.titles[class] }
 
})
 
end
 
end
 
 
local function get_styles(parms)
 
-- Return string of required template styles, empty if none.
 
if parms.templatestyles then
 
local t = {}
 
for _, v in pairs(parms.templatestyles) do
 
table.insert(t, v)
 
end
 
return table.concat(t)
 
end
 
return ''
 
end
 
  
 
local function get_range(word)
 
local function get_range(word)
Line 1,141: Line 1,117:
 
local fracfmt = {
 
local fracfmt = {
 
{ -- Like {{frac}} (fraction slash).
 
{ -- Like {{frac}} (fraction slash).
'<span class="frac" role="math">{SIGN}<span class="num">{NUM}</span>&frasl;<span class="den">{DEN}</span></span>', -- 1/2
+
-- 1/2    : sign, numerator, denominator
'<span class="frac" role="math">{SIGN}{WHOLE}<span class="sr-only">+</span><span class="num">{NUM}</span>&frasl;<span class="den">{DEN}</span></span>',  -- 1+2/3
+
-- 1+2/3  : signed_wholenumber, numerator, denominator
style = 'frac',
+
'<span class="frac nowrap">%s<sup>%s</sup>&frasl;<sub>%s</sub></span>',
 +
'<span class="frac nowrap">%s<span class="visualhide">&nbsp;</span><sup>%s</sup>&frasl;<sub>%s</sub></span>',
 
},
 
},
{ -- Like {{sfrac}} (stacked fraction, that is, horizontal bar).
+
{ -- Like {{sfrac}} (fraction horizontal bar).
'<span class="sfrac tion" role="math">{SIGN}<span class="num">{NUM}</span><span class="sr-only">/</span><span class="den">{DEN}</span></span>', -- 1//2
+
-- 1//2  : sign, numerator, denominator (sign should probably be before the fraction, but then it can wrap, and html is already too long)
'<span class="sfrac" role="math">{SIGN}{WHOLE}<span class="sr-only">+</span><span class="tion"><span class="num">{NUM}</span><span class="sr-only">/</span><span class="den">{DEN}</span></span></span>',  -- 1+2//3
+
-- 1+2//3 : signed_wholenumber, numerator, denominator
style = 'sfrac',
+
'<span class="sfrac nowrap" style="display:inline-block; vertical-align:-0.5em; font-size:85%%; text-align:center;"><span style="display:block; line-height:1em; padding:0 0.1em;">%s%s</span><span class="visualhide">/</span><span style="display:block; line-height:1em; padding:0 0.1em; border-top:1px solid;">%s</span></span>',
 +
'<span class="sfrac nowrap">%s<span class="visualhide">&nbsp;</span><span style="display:inline-block; vertical-align:-0.5em; font-size:85%%; text-align:center;"><span style="display:block; line-height:1em; padding:0 0.1em;">%s</span><span class="visualhide">/</span><span style="display:block; line-height:1em; padding:0 0.1em; border-top:1px solid;">%s</span></span></span>',
 
},
 
},
 
}
 
}
Line 1,162: Line 1,140:
 
wholestr = nil
 
wholestr = nil
 
end
 
end
local substitute = {
+
if wholestr then
SIGN = negative and MINUS or '',
+
local decorated = with_separator(parms, wholestr)
WHOLE = wholestr and with_separator(parms, wholestr),
+
if negative then
NUM = from_en(numstr),
+
decorated = MINUS .. decorated
DEN = from_en(denstr),
+
end
}
+
local fmt = fracfmt[style][2]
wikitext = fracfmt[style][wholestr and 2 or 1]:gsub('{(%u+)}', substitute)
+
wikitext = format(fmt, decorated, from_en(numstr), from_en(denstr))
 +
else
 +
local sign = negative and MINUS or ''
 +
wikitext = format(fracfmt[style][1], sign, from_en(numstr), from_en(denstr))
 +
end
 
if do_spell then
 
if do_spell then
 
if negative then
 
if negative then
Line 1,177: Line 1,159:
 
end
 
end
 
end
 
end
local s = spell_number(parms, inout, wholestr, numstr, denstr)
+
wikitext = spell_number(parms, inout, wholestr, numstr, denstr) or wikitext
if s then
 
return s
 
end
 
 
end
 
end
add_style(parms, fracfmt[style].style)
 
 
return wikitext
 
return wikitext
 
end
 
end
Line 1,550: Line 1,528:
 
--  v = value of text (text is a number)
 
--  v = value of text (text is a number)
 
--  f = true if value is an integer
 
--  f = true if value is an integer
-- Input can use en digits or digits in local language or separators,
+
-- Input can use en digits or digits in local language,
-- but no Unicode minus, and no fraction.
+
-- but no separators, no Unicode minus, and no fraction.
 
if text then
 
if text then
 
local number = tonumber(to_en(text))
 
local number = tonumber(to_en(text))
Line 1,691: Line 1,669:
 
end
 
end
  
local function range_text(range, want_name, parms, before, after, inout, options)
+
local function range_text(range, want_name, parms, before, after, inout)
 
-- Return before .. rtext .. after
 
-- Return before .. rtext .. after
 
-- where rtext is the text that separates two values in a range.
 
-- where rtext is the text that separates two values in a range.
 
local rtext, adj_text, exception
 
local rtext, adj_text, exception
options = options or {}
 
 
if type(range) == 'table' then
 
if type(range) == 'table' then
 
-- Table must specify range text for ('off' and 'on') or ('input' and 'output'),
 
-- Table must specify range text for ('off' and 'on') or ('input' and 'output'),
Line 1,712: Line 1,689:
 
end
 
end
 
end
 
end
if rtext == '–' and (options.spaced or after:sub(1, #MINUS) == MINUS) then
+
if rtext == '–' and after:sub(1, #MINUS) == MINUS then
 
rtext = '&nbsp;– '
 
rtext = '&nbsp;– '
 
end
 
end
Line 1,790: Line 1,767:
 
-- Return true if successful or return false, t where t is an error message table.
 
-- Return true if successful or return false, t where t is an error message table.
 
currency_text = nil  -- local testing can hold module in memory; must clear globals
 
currency_text = nil  -- local testing can hold module in memory; must clear globals
 +
local accept_any_text = {
 +
input = true,
 +
qid = true,
 +
qual = true,
 +
stylein = true,
 +
styleout = true,
 +
tracking = true,
 +
}
 
if kv_pairs.adj and kv_pairs.sing then
 
if kv_pairs.adj and kv_pairs.sing then
 
-- For enwiki (before translation), warn if attempt to use adj and sing
 
-- For enwiki (before translation), warn if attempt to use adj and sing
Line 1,802: Line 1,787:
 
local en_name = text_code.en_option_name[loc_name]
 
local en_name = text_code.en_option_name[loc_name]
 
if en_name then
 
if en_name then
local en_value = text_code.en_option_value[en_name]
+
local en_value
if en_value == 'INTEGER' then  -- altitude_ft, altitude_m, frac, sigfig
+
if en_name == '$' or en_name == 'frac' or en_name == 'sigfig' then
en_value = nil
 
 
if loc_value == '' then
 
if loc_value == '' then
 
add_warning(parms, 2, 'cvt_empty_option', loc_name)
 
add_warning(parms, 2, 'cvt_empty_option', loc_name)
 +
elseif en_name == '$' then
 +
-- Value should be a single character like "€" for the euro currency symbol, but anything is accepted.
 +
currency_text = (loc_value == 'euro') and '€' or loc_value
 
else
 
else
 
local minimum
 
local minimum
 
local number, is_integer = get_number(loc_value)
 
local number, is_integer = get_number(loc_value)
if en_name == 'sigfig' then
+
if en_name == 'frac' then
minimum = 1
 
elseif en_name == 'frac' then
 
 
minimum = 2
 
minimum = 2
 
if number and number < 0 then
 
if number and number < 0 then
Line 1,819: Line 1,804:
 
end
 
end
 
else
 
else
minimum = -1e6
+
minimum = 1
 
end
 
end
 
if number and is_integer and number >= minimum then
 
if number and is_integer and number >= minimum then
 
en_value = number
 
en_value = number
 
else
 
else
local m
+
add_warning(parms, 1, (en_name == 'frac' and 'cvt_bad_frac' or 'cvt_bad_sigfig'), loc_name .. '=' .. loc_value)
if en_name == 'frac' then
 
m = 'cvt_bad_frac'
 
elseif en_name == 'sigfig' then
 
m = 'cvt_bad_sigfig'
 
else
 
m = 'cvt_bad_altitude'
 
end
 
add_warning(parms, 1, m, loc_name .. '=' .. loc_value)
 
 
end
 
end
 
end
 
end
elseif en_value == 'TEXT' then -- $, input, qid, qual, stylein, styleout, tracking
+
elseif accept_any_text[en_name] then
 
en_value = loc_value ~= '' and loc_value or nil  -- accept non-empty user text with no validation
 
en_value = loc_value ~= '' and loc_value or nil  -- accept non-empty user text with no validation
if not en_value and (en_name == '$' or en_name == 'qid' or en_name == 'qual') then
+
if en_name == 'input' then
add_warning(parms, 2, 'cvt_empty_option', loc_name)
 
elseif en_name == '$' then
 
-- Value should be a single character like "€" for the euro currency symbol, but anything is accepted.
 
currency_text = (loc_value == 'euro') and '€' or loc_value
 
elseif en_name == 'input' then
 
 
-- May have something like {{convert|input=}} (empty input) if source is an infobox
 
-- May have something like {{convert|input=}} (empty input) if source is an infobox
 
-- with optional fields. In that case, want to output nothing rather than an error.
 
-- with optional fields. In that case, want to output nothing rather than an error.
Line 1,848: Line 1,820:
 
end
 
end
 
else
 
else
en_value = en_value[loc_value]
+
en_value = text_code.en_option_value[en_name][loc_value]
 
if en_value and en_value:sub(-1) == '?' then
 
if en_value and en_value:sub(-1) == '?' then
 
en_value = en_value:sub(1, -2)
 
en_value = en_value:sub(1, -2)
Line 2,200: Line 2,172:
 
end
 
end
 
if in_unit_table.builtin == 'mach' then
 
if in_unit_table.builtin == 'mach' then
-- As with old template, a number following Mach as the input unit is the altitude.
+
-- As with old template, a number following Mach as the input unit is the altitude,
-- That is deprecated: should use altitude_ft=NUMBER or altitude_m=NUMBER.
+
-- and there is no way to specify an altitude for the output unit.
local success, info
+
-- Could put more code in this function to get any output unit and check for
success = tonumber(parms[i])  -- this will often work and will give correct result for values like 2e4 without forcing output scientific notation
+
-- an altitude following that unit.
if success then
+
local success, info = extract_number(parms, parms[i], false, true)
info = { value = success }
 
else
 
success, info = extract_number(parms, parms[i], false, true)
 
end
 
 
if success then
 
if success then
 
i = i + 1
 
i = i + 1
Line 2,436: Line 2,404:
 
end
 
end
 
if in_builtin == 'mach' or out_builtin == 'mach' then
 
if in_builtin == 'mach' or out_builtin == 'mach' then
-- Should check that only one altitude is given but am planning to remove
+
local adjust
-- in_current.altitude (which can only occur when Mach is the input unit),
 
-- and out_current.altitude cannot occur.
 
local alt = parms.altitude_ft or in_current.altitude
 
if not alt and parms.altitude_m then
 
alt = parms.altitude_m / 0.3048  -- 1 ft = 0.3048 m
 
end
 
local spd = speed_of_sound(alt)
 
 
if in_builtin == 'mach' then
 
if in_builtin == 'mach' then
inscale = spd
+
inscale = speed_of_sound(in_current.altitude)
return invalue * (inscale / outscale)
+
adjust = outscale / 0.1
 +
else
 +
outscale = speed_of_sound(out_current.altitude)
 +
adjust = 0.1 / inscale
 
end
 
end
outscale = spd
 
local adjust = 0.1 / inscale
 
 
return true, {
 
return true, {
 
outvalue = invalue * (inscale / outscale),
 
outvalue = invalue * (inscale / outscale),
Line 2,649: Line 2,611:
 
show = format('%.0f', floor((outvalue / n) + 0.5) * n)
 
show = format('%.0f', floor((outvalue / n) + 0.5) * n)
 
end
 
end
elseif in_current.builtin == 'mach' then
 
local sigfig = info.clean:gsub('^[0.]+', ''):gsub('%.', ''):len() + 1
 
show, exponent = make_sigfig(outvalue, sigfig)
 
 
else
 
else
 
local inclean = info.clean
 
local inclean = info.clean
Line 3,275: Line 3,234:
 
-- For simplicity and because more not needed, handle one range item only.
 
-- For simplicity and because more not needed, handle one range item only.
 
local prefix2 = make_id(parms, 2, first_unit) .. '&nbsp;'
 
local prefix2 = make_id(parms, 2, first_unit) .. '&nbsp;'
result = range_text(range[1], want_name, parms, result, prefix2 .. valinfo[2].show, 'in', {spaced=true})
+
result = range_text(range[1], want_name, parms, result, prefix2 .. valinfo[2].show, 'in')
 
end
 
end
 
return preunit .. result
 
return preunit .. result
Line 3,365: Line 3,324:
 
if range then
 
if range then
 
-- For simplicity and because more not needed, handle one range item only.
 
-- For simplicity and because more not needed, handle one range item only.
result = range_text(range[1], want_name, parms, result, prefix .. valinfo[2].show, inout, {spaced=true})
+
result = range_text(range[1], want_name, parms, result, prefix .. valinfo[2].show, inout)
 
end
 
end
 
return preunit .. result
 
return preunit .. result
Line 3,571: Line 3,530:
 
local success, result2 = make_result(valinfo[i+1])
 
local success, result2 = make_result(valinfo[i+1])
 
if not success then return false, result2 end
 
if not success then return false, result2 end
result = range_text(range[i], want_name, parms, result, result2, inout, {spaced=true})
+
result = range_text(range[i], want_name, parms, result, result2, inout)
 
end
 
end
 
end
 
end
Line 3,701: Line 3,660:
 
wikitext = wikitext .. parms.warnings
 
wikitext = wikitext .. parms.warnings
 
end
 
end
return true, get_styles(parms) .. wikitext, out_unit_table
+
return true, wikitext, out_unit_table
 
end
 
end
  
Line 3,827: Line 3,786:
 
end
 
end
  
return { convert = main_convert, _unit = _unit }
+
local function _gramme(frame)
 +
local s = frame.args[1] or frame:getParent().args[1] or ""
 +
s = s:gsub("gram$", "gramme")
 +
s = s:gsub("gram(%A)", "gramme%1")
 +
s = s:gsub("grams$", "grammes")
 +
s = s:gsub("grams(%A)", "grammes%1")
 +
return s
 +
end
 +
 
 +
return { convert = main_convert, _unit = _unit, gramme = _gramme }