Module:Mountains Prism

--[[ v1.3

This module builds a wiki table that lists information pertinent to mountains. This module accomodates up to 500 lines

of mountains where each line consists of the elevation, wiki-linked name and optional notes information. This

module uses the wiki-linked name to find its corresponding Wikidata item (eid) and then retrieve the following

information from Wikidata: elevation, prominence, isolation, range, first ascent, country, coordinates

Version Changes

===== =======

1.0 Initial release

1.1 Various fixes for metric and imperial units

1.2 Don't display entity id not found for non-existent wiki pages, fixed custom1 and coordinates bugs

1.3 Support qid after page name for items that exist on Wikidata but not on Wikipedia

]]

local p = {}

--require('Module:Wd')

local Titled_coords = require('Module:Titled_coords')

local newBuffer = require('Module:OutputBuffer')

-- Wikidata properties

local WD_PROPERTIES = {

elevation = "P2044",

prominence = "P2660",

mtn_range = "P4552",

coords = "P625",

sig_event = "P793",

pt_in_time = "P585",

isolation = "P2659",

country = "P17"

}

-- Table column titles for easier translation

local COL_TITLES = {

rank = "Rank",

name = "Mountain / Peak",

elev = "Elevation",

prom = "Prominence",

isoltn = "Isolation",

range = "Subrange",

fa = "FA",

coords = "Coordinates",

country = "Country",

custom = "Notes"

}

-- ** Runtime Option names **

local OPT_NAMES = {

NAME = "name",

RANK = "rank",

PROM = "prom",

ISOLTN = "isolation",

RANGE = "range",

FA = "fa",

COORDS = "coords",

TCOORDS= "tcoords",

CUSTOM1= "custom1",

CUSTOM2= "custom2",

COUNTRY= "country",

ORDER = "order",

DEBUG = "debug"

}

local OPTIONS_SEP = ","

local RANK_ORDER = { ELEV = "E", PROM = "P"}

local UNITS = {

METRE = "m", FOOT = "ft",

KILOMETRE = "km", MILE = "mi"

}

-- Runtime options about what information to display

local Options = { debug = false, test = false, showFA = false, showProm = false,

showCoord = false, showTCoord = false, rankOrder = RANK_ORDER.ELEV,

showRank = false, showRange = false, showIsolation = false,

showCountry = false, showCustom1 = false, showCustom2 = false }

-- Information about a mountain from Module arguments and Wikidata.

local Mountain = { rank, wiki_link, page, name, eid, qid, elevation, elevation_wd = 0, elev_wd_unit,

prominence, prom_unit, range = "", isolation = "", fa = "",

coords, custom, country }

-- "Constants" (Wikipedia not using LUA 5.4)

local QID_FIRST_ASCENT = "Q1194369"

local FA_UNKNOWN = "Unk"

local FA_ERROR = "????"

local FS = "^" -- field separator

local NBSP = " "

local COL_TITLE_SEP = ":" -- do not use "="

local OPTIONS_SEP = ","

local NEWLINE = "\n"

local BR_NEWLINE ="
"..NEWLINE

local TD = '|'

local TD_NL = NEWLINE .. TD

local WD_NOT_FOUND = -1 -- Not found on Wikidata

local WD_NF_TEXT = "Not Found"

local Errors, Dbgout

local function debug(msg)

mw.log(msg)

Dbgout = Dbgout .. msg .. BR_NEWLINE

end

local function debugv(var, value)

local s = var .. "=" .. value

mw.log(s)

Dbgout = Dbgout .. s .. BR_NEWLINE

end

local function addError(msg)

Errors = Errors .. msg .. BR_NEWLINE

debug(msg)

end

local function colorize(text, color)

return '' .. text .. ""

end

local function errorStyle(text)

return colorize(text, "red")

end

local function infoStyle(text)

return colorize(text, "green")

end

-- *** Split a string based on a separator ***

local function split(istring, sep)

-- if sep is null, use default

if sep == nil then sep = FS end

local t = {}

for str in string.gmatch(istring, '([^'..sep..']+)') do

table.insert(t, str)

end

return t

end

-- *** Strip newline character at end ***

local function stripNewline(value)

local n = string.find(value, NEWLINE)

if n then

return string.sub(value, 1, n-1)

end

return value

end

-- *** Extract raw elevation/prominence/isolation value and unit from WD value ***

local function extractRaw(wdValue)

local i, n

local units = { " metre", UNITS.METRE, " foot", UNITS.FOOT, " kilometre", UNITS.KILOMETRE, " mile", UNITS.MILE }

if wdValue == nil then return WD_NOT_FOUND end

for i=1,#units,2 do

n = string.find(wdValue, units[i])

if n then

-- remove thousands separator while we are it

return string.sub(wdValue, 1, n-1):gsub(',', ''), units[i+1]

end

end

return -1

end

-- *** Call {{convert}} ***

local function convert(frame, value, unit)

debug("Converting "..value..unit)

local result = frame:expandTemplate{title='convert', args= { value, unit, disp='out', abbr='values', comma='off'}}

debugv("result", result)

return result

end

-- *** Call {{elevation_cells} to format the values ***

local function getElevationCells(frame, elev, unit, flip)

if frame.expandTemplate then

if not flip then

return frame:expandTemplate{title='elevation_cells', args= { elev, unit}}

else

debug("Converting with order=flip")

return frame:expandTemplate{title='elevation_cells', args= { elev, unit, order='flip'}}

end

end

return "{{elevation_cells|" .. elev .. "|" .. unit .. "}}"

end

-- *** Call {{convert}} to get table formatted cells ***

local function getConvertCells(frame, value, from_unit, to_unit, flip)

local cells

if not flip then

cells = frame:expandTemplate{title='convert', args= { value, from_unit, to_unit, disp='table', sortable='on'}}

else

cells = frame:expandTemplate{title='convert', args= { value, from_unit, to_unit, disp='table', sortable='on', order='flip' }}

end

return cells

end

-- *** Get table formatted cells of the isolation ***

local function getIsolationCells(frame, isolation)

local isoltn_cells

if isolation and isolation ~= WD_NOT_FOUND and isolation ~= "" then

isoltn_cells = getConvertCells(frame, isolation, UNITS.KILOMETRE, UNITS.MILE)

else

isoltn_cells = " || "

end

debugv("isoltn_cells", isoltn_cells)

return isoltn_cells

end

-- *** Get table formatted cells of the topo prominence ***

local function getProminenceCells(frame, unit, prominence, prom_unit)

local prom_cells, to_unit

if prominence ~= nil and prominence ~= WD_NOT_FOUND and prominence ~= "" then

local flip = prom_unit ~= unit

debug("unit="..unit..";prom_unit="..prom_unit..";flip="..tostring(flip))

if not flip then

if unit == UNITS.FOOT then to_unit = UNITS.METRE else to_unit = UNITS.FOOT end

else

to_unit = unit

end

prom_cells = getConvertCells(frame, prominence, prom_unit, to_unit, flip)

else

prom_cells = " || "

end

debugv("prom_cells", prom_cells)

return prom_cells

end

local function stripBrackets(value)

local stripped = value;

-- strip leading brackets if found

local n = string.find(stripped, "%[%[")

if n then

stripped = string.sub(stripped, 3)

end

-- strip trailing brackets if found

n = string.find(stripped, "%]%]")

if n then

stripped = string.sub(stripped,1,n-1)

end

if stripped then return stripped

else return value end

end

-- *** Parse a wiki link ***

local function parseWikiLink(wikiLink, mtn)

local wiki_link = wikiLink

-- Extract a qid (optional) --

local n = string.find(wiki_link, "@qid:")

if n then

mtn.qid = string.sub(wiki_link, n+5)

wiki_link = string.sub(wiki_link, 1, n-1)

else

mtn.qid = nil

end

mtn.wiki_link = wiki_link

local parts = split(wiki_link, "|")

local page = parts[1]

n = string.find(page, "%[%[")

if n then

page = string.sub(page,3)

end

n = string.find(page, "%]%]")

if n then

page = string.sub(page,1,n-1)

end

mtn.page = page

if #parts == 2 then

mtn.name = stripBrackets(parts[2])

else

mtn.name = stripBrackets(parts[1])

end

local msg = "wikilink="..wikiLink..";page="..page..";name="..mtn.name

if mtn.qid then msg = msg .. ";qid="..mtn.qid end

debug(msg)

return page

end

--[[

Retrieve a entity's property value from Wikidata. Unfortunately

the interface only supports one property at a time.

]]

local function getWD(frame, eid, name, cmdFlag, multiple)

if not frame.preprocess then

return "{{Wikidata|property|" .. name .. "|eid=" .. eid .. "}}"

end

local args

if not multiple then args = "property|" else args = "properties|" end

if cmdFlag then args = args .. cmdFlag .. "|" end

args = args .. name .. "|eid=" .. eid

local invoke = "{{#invoke:Wd|" .. args .. "}}"

local value = frame:preprocess(invoke)

debug(invoke .. " => " .. value)

return value

end

-- ** Get a wiki linked property value **

local function getWDLinked(frame, eid, name)

return getWD(frame, eid, name, "linked", false)

end

-- ** Get the raw value of a property value **

local function getWDRaw(frame, eid, name)

return getWD(frame, eid, name, "raw", false)

end

-- ** Get an entity's property from Wikidata **

local function getWDProperty(frame, eid, name, linked)

debug("eid=" .. eid .. " name=" .. name)

--[[ local stmts = mw.wikibase.getBestStatements(eid, name)

if stmts ~= nil then

mw.logObject(stmts)

for i=1,#stmts do

mw.log("stmts["..i.."]="..stmts[i]);

end

end ]]

-- call Module:Wd using template syntax

if frame.preprocess then

local args = "property|"

if linked then args = args .. "linked|" end

args = args .. name .. "|eid=" .. eid

local invoke = "{{#invoke:Wd|" .. args .. "}}"

local value = frame:preprocess(invoke)

debug(invoke .. " => " .. value)

return value

end

return "{{Wikidata|property|" .. name .. "|eid=" .. eid .. "}}"

end

-- if frame.expandTemplate then

-- local args = { ['1'] = name, ['page'] = page }

-- return wd._property({eid, args})

-- local args = { ['1'] = 'property', ['2'] = name, ['page'] = page }

-- return frame:expandTemplate{title='Wikidata', args= args}

local function stripCoords(wdCoords)

--debugv("wdCoords", wdCoords)

if Options.test then -- this only shows up in console test mode

local stripped = string.gsub(wdCoords, "\"`UNIQ%-%-templatestyles%-%d+%-QINU`\"", "")

--debugv("stripped", stripped)

return stripped

end

return wdCoords

end

-- ** Get country from Wikidata **

local function getCountry(frame, eid)

local value = getWD(frame, eid, WD_PROPERTIES.country, nil, true)

return value

end

-- *** Get location coordinates from Wikidata ***

local function getCoords(frame, eid)

local wdCoords = getWDLinked(frame, eid, WD_PROPERTIES.coords)

return stripCoords(wdCoords)

end

-- *** Call Module:Titled_coords to get titled coordinates ***

local function getTitledCoords(frame, eid, title)

local raw_coords = getWDRaw(frame, eid, WD_PROPERTIES.coords)

local fmt_coords = Titled_coords.build(raw_coords, title, "")

debug(fmt_coords .. " => " .. fmt_coords)

return stripCoords(fmt_coords)

end

local function getElevationWD(frame, eid)

local value = getWD(frame, eid, WD_PROPERTIES.elevation, nil)

return extractRaw(value)

end

-- *** Get FA year from Wikidata ***

local function getFirstAscent(frame, eid)

if frame.preprocess == nil then return FA_ERROR end

local names = WD_PROPERTIES.sig_event .. "|" .. QID_FIRST_ASCENT .. "|" .. WD_PROPERTIES.pt_in_time

local value = frame:preprocess("{{#invoke:Wd|property|qualifier|" .. names .. "|eid=" .. eid .. "}}")

debugv("FA value", value)

if value == "" then

debugv("No FA on Wikidata for eid", eid)

return FA_UNKNOWN

end

-- FA deliberately set to unknown value

if string.find(value, "(unknown)") then

debugv("FA unknown for eid", eid)

return FA_UNKNOWN

end

-- Find date such as: 10 July 1913

local i1, i2 = string.find(value, "%(%d+%s%a*%s%d%d%d%d%)")

if i1 then

--mw.log("i1="..i1)

local date = string.sub(value, i1+1, i2-1)

debugv("FA date", date)

local len = string.len(date)

local year = string.sub(date, len-4, len)

return year

end

-- Find date with just the year; e.g. (2025)

i1, i2 = string.find(value, "%(%d+%)")

if i1 then

local year = string.sub(value, i1+1, i2-1)

return year

end

addError("Unknown FA date format for eid " .. eid .. ": " .. value)

return FA_ERROR

end

-- *** get topgraphic isolation from Wikidata ***

local function getIsolation(frame, eid)

local isoltn = getWD(frame, eid, WD_PROPERTIES.isolation, nil)

return extractRaw(isoltn)

end

-- *** get prominence from Wikidata ***

local function getProminenceWD(frame, eid)

local prom = getWD(frame, eid, WD_PROPERTIES.prominence, nil)

return extractRaw(prom)

end

-- get mountain range from Wikidata. We want it wiki-linked for

-- the first occurrence of it in the output.

local function getRange(frame, eid)

return getWDLinked(frame, eid, WD_PROPERTIES.mtn_range)

end

-- Check elevations from input and Wikidata. If not equal, add an info

-- message to the custom field. Note that this check is only done if

-- there is a custom field in the output.

local function checkElevations(frame, mtn, unit)

if not mtn.eid then return end -- v1.3 don't check if no WD item

local elevation_wd = mtn.elevation_wd

-- If output unit not the unit from WD, convert WD value to output unit

if unit ~= mtn.elev_wd_unit and elevation_wd ~= WD_NOT_FOUND then

elevation_wd = convert(frame, elevation_wd, mtn.elev_wd_unit)

end

if elevation_wd ~= 0 and mtn.elevation ~= elevation_wd then

if string.len(mtn.custom) ~= 0 then

mtn.custom = mtn.custom .. "
"

end

local elev_wd_v = elevation_wd

if elev_wd_v == WD_NOT_FOUND then elev_wd_v = WD_NF_TEXT end

local msg = 'Local/WD elevations: "' .. mtn.elevation .. '"/"' .. elev_wd_v .. '"'

mtn.custom = mtn.custom .. infoStyle(msg)

end

end

-- *** generate table header ***

local function genHeader(options, unit)

local unit_1, unit_2

if unit == nil or unit == "" then

unit = UNITS.METRE

end

if unit == UNITS.METRE then unit_1 = UNITS.METRE; unit_2 = UNITS.FOOT

else unit_1 = UNITS.FOOT; unit_2 = UNITS.METRE

end

local s = "

class=\"wikitable sortable\"\n!"

if options.showRank then

s = s .. " align=\"left\" rowspan=2|" ..COL_TITLES.rank .. "

"

end

s = s .. "rowspan=2|" .. COL_TITLES.name

if options.showCountry then s = s .. "

rowspan=2|" .. COL_TITLES.country end

if options.showCustom1 then s = s .. "

rowspan=2|" .. COL_TITLES.custom end

s = s .. "

colspan=2|" .. COL_TITLES.elev

if options.showProm then s = s .. "

colspan=2|" .. COL_TITLES.prom end

if options.showIsolation then s = s .. "

colspan=2|" .. COL_TITLES.isoltn end

if options.showRange then s = s .. "

rowspan=2|" .. COL_TITLES.range end

if options.showFA then s = s .. "

rowspan=2|" .. COL_TITLES.fa end

if options.showCustom2 then s = s .. "

rowspan=2|" .. COL_TITLES.custom end

if options.showCoord or options.showTCoord then s = s .. "

rowspan=2|" .. COL_TITLES.coords end

s = s .. "\n

\n"

s = s .. '!' .. unit_1 .. '

' .. unit_2 -- elevation cells

if options.showProm then s = s .. '

' .. unit_1 .. '' .. unit_2 end

if options.showIsolation then

local iso_u1, iso_u2

if unit == UNITS.METRE then iso_u1 = UNITS.KILOMETRE; iso_u2 = UNITS.MILE

else iso_u1 = UNITS.MILE; iso_u2 = UNITS.KILOMETRE

end

s = s .. '

' .. iso_u1 .. '' .. iso_u2

end

s = s .. NEWLINE

return s

end

local function finish()

return "

" -- table end

end

local function handleCustomOption(n, options, columnTitle)

if columnTitle then

COL_TITLES.custom = columnTitle

end

if n == 1 then options.showCustom1 = true else options.showCustom2 = true end

end

--[[ Process run options

rank - show ranking

name - override default name column title

elev - show elevation

prom - show prominence

isolation - show isolation

range - show mountain range or subrange from WD

fa - show first ascent (year only) from WD

coords - show coordinates from WD

tcoords - show titled coordinates from WD

custom[1|2]- show custom field (e.g. Notes)

country - show country

debug - generate debug information

]]

local function processOptions(runOptions)

local o = Options

if runOptions == nil then return o end

runOptions = stripNewline(runOptions)

debugv("runOptions", runOptions)

local parts = split(runOptions, OPTIONS_SEP)

for i=1,#parts do

option = parts[i]

debugv("option", option)

-- Strip out column title if given for an option

local colTitle

local n = string.find(option, COL_TITLE_SEP)

if n then

colTitle = string.sub(option, n+1)

debugv("colTitle", colTitle)

option = string.sub(option, 1, n-1)

end

local valid_option = true

if option == OPT_NAMES.RANK then o.showRank = true

elseif option == OPT_NAMES.PROM then o.showProm = true

elseif option == OPT_NAMES.FA then o.showFA = true

elseif option == OPT_NAMES.PROM then o.showProm = true

elseif option == OPT_NAMES.ISOLTN then o.showIsolation = true

elseif option == OPT_NAMES.COORDS then

o.showCoord = true

if colTitle then COL_TITLES.coords = colTitle end

elseif option == OPT_NAMES.TCOORDS then

o.showTCoord = true

if colTitle then COL_TITLES.coords = colTitle end

elseif option == OPT_NAMES.RANGE then

o.showRange = true

if colTitle then COL_TITLES.range = colTitle end

elseif option == OPT_NAMES.CUSTOM1 then

handleCustomOption(1, o, colTitle)

elseif option == OPT_NAMES.CUSTOM2 then

handleCustomOption(2, o, colTitle)

elseif option == OPT_NAMES.COUNTRY then o.showCountry = true

elseif option == OPT_NAMES.NAME then

if colTitle then COL_TITLES.name = colTitle end

elseif option == OPT_NAMES.ORDER then

if colTitle and colTitle == "prom" then

o.rankOrder = RANK_ORDER.PROM

end

elseif option == OPT_NAMES.DEBUG then o.debug = true

else

addError("Unknown option: " .. option)

valid_option = false

end

end

return o

end

-- *** Get the Wikidata entity id ***

local function getEntityId(mtn)

local page = mtn.page

local eid = mw.wikibase.getEntityIdForTitle(page)

if eid then return eid end

debug("Cannot find entity id for page " .. page)

if mw.title.new(page).exists then

mtn.name = mtn.name .. BR_NEWLINE .. errorStyle("Cannot find entity id")

else

debug("Page not found: " .. page)

end

return mtn.qid

end

local function initMountain(mtn, wikiLink, elev)

local page = parseWikiLink(wikiLink, mtn)

mtn.eid = nil

mtn.elevation = string.gsub(elev, " ", "") -- strip spaces

mtn.elevation_wd = 0

mtn.elev_wd_unit = ""

mtn.prominence = nil

mtn.isolation = nil

mtn.range = ""

mtn.fa = ""

mtn.coords = ""

return page

end

-- *** Process a mountain line ***

local function processLine(frame, options, line)

local parts, n, wl_name, elevatn, page, custom, has_custom

-- argument contains elevation, wiki link and optional custom value

parts = split(line, FS)

if #parts == 2 then

has_custom = false

elseif #parts < 3 then

local m = "
Bad format on argument (" .. line .. ") -- skipped"

Errors = Errors .. m

mw.log(m)

return nil

else

has_custom = true

end

elevatn = parts[1] -- either in metres or feet

wl_name = parts[2] -- wiki-linked name and optional qid

if not wl_name then

addError("wiki-linked name is empty")

return nil

end

local mtn = Mountain

page = initMountain(mtn, wl_name, elevatn)

if options.showCustom1 or options.showCustom2 then

if has_custom then

custom = stripNewline(parts[3])

debugv("custom", custom)

else

custom = ""

end

mtn.custom = custom

end

-- Get the Wikidata entity id

local eid = getEntityId(mtn)

if not eid then return mtn end

debug("page="..page .. ",eid=" .. eid)

mtn.eid = eid

mtn.elevation_wd, mtn.elev_wd_unit = getElevationWD(frame, eid)

if mtn.elevation_wd ~= WD_NOT_FOUND then

debug("WD elevation=" .. mtn.elevation_wd .. " unit=" .. mtn.elev_wd_unit)

else

debug("No elevation on Wikidata for eid=" .. eid)

end

if options.showProm then

mtn.prominence, mtn.prom_unit = getProminenceWD(frame, eid)

if mtn.prominence ~= WD_NOT_FOUND then

debug("WD prominence=" .. mtn.prominence .. " unit=" .. mtn.prom_unit)

else

debug("No prominence on Wikidata for eid=" .. eid)

end

end

if options.showIsolation then

mtn.isolation = getIsolation(frame, eid)

debugv("mtn.isolation", mtn.isolation)

end

if options.showRange then

mtn.range = getRange(frame, eid)

end

if options.showFA then

mtn.fa = getFirstAscent(frame, eid)

end

if options.showCoord then

mtn.coords = getCoords(frame, eid)

elseif options.showTCoord then

mtn.coords = getTitledCoords(frame, eid, mtn.name)

end

if options.showCountry then

mtn.country = getCountry(frame, eid)

end

return mtn

end

-- *** Process a mountain range. Only display the linked range once. ***

local function processRange(ranges, mtn)

local found = false;

local range = mtn.range

-- Do we already have it?

for k,v in pairs(ranges) do

if v == range then

found = true; break

end

end

if not found then

debug("Adding range " .. range)

table.insert(ranges, range)

else

local i1, i2 = string.find(range, "|")

if i1 then

local ei = string.len(range) - 2 -- strip ending brackets

name = string.sub(range, i1+1, ei)

else

local len = string.len(range)

name = string.sub(range, 3, len-2)

end

mtn.range = name

end

end

-- *** Main entry point ***

function p.list(frame)

local debug_on = false

local rank_number = 0

local last_elev, last_prom = ""

local same_rank = 0

Errors = ""; Dbgout = ""

--debugv("args[1]", frame.args[1])

--debugv("args[2]", frame.args[2])

--debugv("args[3]", frame.args[3])

local unit = frame.args[1]

local options = processOptions(frame.args[2])

if options.showCoord and options.showTCoord then

return "

" .. errorStyle("Can only specify one of coords or tcoords") .. "

"

end

-- Create the output buffer and add the table header

local getBuffer, print, printf = newBuffer()

print(genHeader(options, unit))

local ranges = {}

local rankOrderElev = options.rankOrder == RANK_ORDER.ELEV

-- Main processing loop

for i=3,502,1 do

local prom_cells, isoltn_cells

local line = frame.args[i]

if line == nil then break end

debugv("line", line)

local mtn = processLine(frame, options, line)

if mtn then -- only do if no error

if options.showRank then

if rankOrderElev then

if last_elev ~= mtn.elevation then

rank_number = rank_number + 1 + same_rank

mtn.rank = rank_number

last_elev = mtn.elevation

same_rank = 0

else

same_rank = same_rank + 1

end

else -- ranked by prominence

if last_prom ~= mtn.prominence then

rank_number = rank_number + 1 + same_rank

mtn.rank = rank_number

last_prom = mtn.prominence

same_rank = 0

else

same_rank = same_rank + 1

end

end

end

if options.showRange and mtn.eid then

processRange(ranges, mtn)

end

local elev_cells = getElevationCells(frame, mtn.elevation, unit)

if options.showIsolation then

isoltn_cells = getIsolationCells(frame, mtn.isolation)

end

debug("elev=" .. mtn.elevation ..";elev_wd="..mtn.elevation_wd)

if options.showCustom1 or options.showCustom2 then

checkElevations(frame, mtn, unit)

if mtn.custom == "" then mtn.custom = NBSP end

end

print("|-\n|")

if options.showRank then print("align=center|" .. mtn.rank .. "||") end

print(mtn.wiki_link)

if options.showCountry then printf(TD_NL .. "%s", mtn.country) end

if options.showCustom1 then printf(TD_NL .. "%s", mtn.custom) end

printf("\n|%s\n", elev_cells)

if options.showProm then

local prom_cells = getProminenceCells(frame, unit, mtn.prominence, mtn.prom_unit)

printf("|%s\n", prom_cells)

end

if options.showIsolation then printf(TD .. "%s\n", isoltn_cells) end

if options.showRange then printf(TD .. "%s\n", mtn.range) end

if options.showFA then printf(TD .. "%s\n", mtn.fa) end

if options.showCustom2 then printf(TD .. "%s\n", mtn.custom) end

if options.showCoord or options.showTCoord then printf(TD .. "%s\n", mtn.coords) end

end -- if mtn

end -- for

print(finish())

if debug_on then

printf("
%s\n")

end

if string.len(Errors) > 0 then

printf("%s\n", errorStyle(Errors))

end

if options.debug and string.len(Dbgout) > 0 and not options.test then

printf("
Debug output
\n%s
\n", Dbgout)

end

return getBuffer('')

end

--[[

Test via Preview Window Debug console

print(p.test())

]]

function p._test(doDebug)

local frame = mw.getCurrentFrame()

-- if frame then mw.logObject(frame) end

-- local test_data = { {["e"]="3954",["p"]="Mount Robson",

-- ["n"]="Highest point in the Canadian Rockies"},

-- {["e"]="3747",["p"]="Mount Columbia",

-- ["n"]="Highest point in Alberta"}

-- }

local sep = ","

frame.args = {}

frame.args[1] = 'm'

frame.args[2] = OPT_NAMES.RANK..sep..

OPT_NAMES.RANGE..COL_TITLE_SEP.."Mtn Range"..sep..OPT_NAMES.FA

..sep..OPT_NAMES.PROM

--..sep..OPT_NAMES.ISOLTN

..sep..OPT_NAMES.TCOORDS

..sep..OPT_NAMES.CUSTOM2..COL_TITLE_SEP.."Additional info"

-- ..sep..OPT_NAMES.COUNTRY

-- ..sep..OPT_NAMES.ORDER..COL_TITLE_SEP.."prom"

if doDebug then frame.args[2] = frame.args[2] ..sep .. OPT_NAMES.DEBUG end

frame.args[3] = "3954"..FS.."Mount Robson"..FS.."Highest point in the Canadian Rockies"

frame.args[4] = "3448"..FS.."Mount Saint Elias"..FS.."Canada/US border"

frame.args[5] = "3310"..FS.."Mount Vaux"..FS.."Ottertail Range"

frame.args[6] = "3204"..FS.."Ghost Mountain"..FS..""

frame.args[7] = "2433"..FS.."Saddle Mountain"..FS

--[===[

frame.args[3] = "3954"..FS.."Mount Robson"..FS.."Highest point in the Canadian Rockies"

frame.args[4] = "3747"..FS.."Mount Columbia"..FS.."Highest point in Alberta"

frame.args[5] = "3731"..FS.."North Twin Peak"..FS.."Highest peak of The Twins Massif"

frame.args[6] = "3648"..FS.."Mount Clemenceau"..FS.."Named for Georges Clemenceau, premier of France during WWI"

frame.args[7] = "3619"..FS.."Mount Alberta"..FS.."Most difficult +11,000 climbing objective"

frame.args[8] = "3618"..FS.."Mount Assiniboine"..FS.."Highest point in the Southern Rockies"

frame.args[9] = "3612"..FS.."Mount Forbes"..FS.."Highest point within the confines of Banff Nat'l Park"

frame.args[10] = "3567"..FS.."Mount Goodsir"..FS.."Two major summits: South Tower and North Tower (lowest)"

frame.args[11] = "3556"..FS.."South Twin Peak"..FS.."Lowest peak of The Twins Massif"

frame.args[12] = "3543"..FS.."Mount Temple"..FS.."Highest point near Lake Louise"

frame.args[13] = "3425"..FS.."Resplendent Mountain"..FS.."tbd"

frame.args[14] = "3204"..FS.."Ghost Mountain"..FS..""

--]===]

-- frame.args[7] = ""

-- frame.args[8] = " "

--[[ Commented out

local fi = 3

for i=1,#test_data do

frame.args[fi] = test_data[i]["e"] .. FS .. test_data[i]["l"] .. FS .. test_data[i]["n"]

fi = fi + 1

end ]]

Options.test = true

return p.list(frame)

end

function p.testd() -- test with debug

return p._test(true)

end

function p.test()

return p._test(false)

end

function p.test2()

local s = 'Rainbow Range'

--local i1,i2 = string.find(s,"%>(.*)%<%/a%>")

local i1,i2 = string.find(s,"%b><")

if i1 then

mw.log("i1=" .. i1 .. " i2=" .. i2)

mw.log(string.sub(s,i1+1,i2-1))

else

mw.log("not found")

end

end

function p.test3()

mw.log(stripBrackets("abc"))

mw.log(stripBrackets("def"))

mw.log(stripBrackets("Mount Victoria"))

end

function p.testF() -- test Feet unit

local frame = mw.getCurrentFrame()

frame.args = {}

local sep = OPTIONS_SEP

frame.args[1] = UNITS.FOOT

frame.args[2] = OPT_NAMES.DEBUG

..sep.. OPT_NAMES.PROM

..sep.. OPT_NAMES.FA

--sep.. OPT_NAMES_TCOORDS

..sep.. OPT_NAMES.CUSTOM2

frame.args[3] = "12726"..FS.."Mount Crillon"..FS.."C note"

frame.args[4] = "10728"..FS.."Mount La Perouse"..FS.."La P note"

-- frame.args[4] = " 8200"..FS.."Mount Abbe"..FS.."Abbe note"

-- frame.args[5] = " 6780"..FS.."Mount Cooper"

Options.test = true

return p.list(frame)

end

function p.testQ()

local frame = mw.getCurrentFrame()

frame.args = {}

frame.args[1] = UNITS.METRE

frame.args[2] = "debug,fa,tcoords,custom2:Easiest route"

frame.args[3] = "2736"..FS.."Angle Peak@qid:Q22418313"..FS..""

frame.args[4] = "2656"..FS.."Byward Peak@qid:Q22369121"..FS.."test"

Options.test = true

return p.list(frame)

end

function p.testR()

local frame = mw.getCurrentFrame()

frame.args = {}

frame.args[1] = UNITS.METRE

frame.args[2] = "debug,fa,tcoords,custom2:Easiest route"

frame.args[3] = "3543"..FS.."Mount Temple"..FS.."Moderate scramble on SW face"

frame.args[4] = "3492"..FS.."Hungabee Mountain"..FS.."UIAA III 5.4 on West ridge"

frame.args[5] = "3464"..FS.."Mount Victoria"..FS.."UIAA II on SE ridge, South Summitend"

frame.args[6] = "2860"..FS.."Aquila Mountain"..FS.."NA"

Options.test = true

return p.list(frame)

end

function p.testExists()

local title = "Mount Logan"

title = "Aquila Mountain (British Columbia)"

local page = mw.title.new(title)

local status;

if page.exists then status = "exists" else status = "not found" end

mw.log("page \"" .. title .. "\" " .. status)

end

return p