Home
Random
Recent changes
Special pages
Community portal
Preferences
About Stockhub
Disclaimers
Search
User menu
Talk
Contributions
Create account
Log in
Editing
Module:Sandbox/Wnt/FindFeatures/displayDatabase
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
-- This module finds features with coordinates in a certain area on a globe. -- current focus is Mars. Earth, celestial, etc. would be nice also. -- all three dimensionality is hereby banned from the procedure on account of requiring far too much intelligence to get working. local getArgs = require('Module:Arguments').getArgs local p = {} debuglog="" function tidyNum(text) text = mw.ustring.gsub(text, " ", "") text = mw.ustring.gsub(text, ",", ".") return tonumber(text) end function parseValue(text) -- extract 3 or 2 or 1 values from the string. Can contain . or , as a decimal, no spaces allowed. local d, m, s = mw.ustring.match(text,"(%-?%d+[%.,]?%d*)[%a%c%s%z!@#$%%^&%*%(%)%=|\~']+(%-?%d+[%.,]?%d*)[%a%c%s%z!@#$%%^&%*%(%)%=|\~']+(%-?%d+[%.,]?%d*)") if not d then d, m = mw.ustring.match(text,"(%-?%d+[%.,]?%d*)[%a%c%s%z!@#$%%^&%*%(%)%=|\~']+(%-?%d+[%.,]?%d*)") end if not d then d = mw.ustring.match(text,"(%-?%d+[%.,]?%d*)") end if d then d = tidyNum(d or "0") + tidyNum(m or "0")/60 + tidyNum(s or "0")/3600 end debuglog = debuglog .. tostring(d) return d end function parseDirection(text) local direction = mw.ustring.match(text,"%A([NSEWnsew])%A") or mw.ustring.match(text,"^([NSEWnsew])%A") or mw.ustring.match(text,"%A([NSEWnsew])$") if (not direction) then direction = mw.ustring.match(text,"([Nn])[Oo][Rr][Tt][Hh]") or mw.ustring.match(text,"([Ss])[Oo][Uu][Tt][Hh]") or mw.ustring.match(text,"([Ee])[Aa][Ss][Tt]") or mw.ustring.match(text,"([Ww])[Ee][Ss][Tt]") end if direction then direction = mw.ustring.upper(direction) end return direction end function parseCoord(text) local text = mw.ustring.upper(text) -- we're only getting direction letters and numbers here local coord = {} local ok -- maybe it's a Coord call like "{{Coord|37.3|N|259.0|E|globe:Mars_type:mountain}}" - then only search the template text = mw.ustring.match(text,"{{COORD(.-)}}") or text -- maybe it's a simple coordinate like 37N,33E? -- note: currently does NOT hunt for deg, min, sec variations. ASSuMEs that order. -- In this case, parsing what to do based on three numbers starts to fall apart (what if there are five?) -- Instead, look for the direction markers first, then split into two bound parsing problems local first, second = mw.ustring.match(text,"^(.-%A)[NSEW](%A.-)$") if first and second and mw.ustring.match(first,"%d") then coord[1] = parseValue(first) second = mw.ustring.match(second, "^(.-%A)[NSEW]%A.-$") or mw.ustring.match(second, "^(.-%A)[NSEW]$") or second coord[2] = parseValue(second) if (coord[1] and coord[2]) then ok = true end end if (ok) then -- at this point the amounts of coord[1] (lat) and coord[2] (lon) are set, but what directions? local firstdir = parseDirection(text) local seconddir = firstdir if firstdir then frag = text repeat -- I just keep the first letter of the direction, not the context, so need to run forward to it frag = mw.ustring.match(frag, firstdir .. "(.*)$") seconddir = parseDirection(frag) until seconddir ~= firstdir end else -- last ditch effort: take the first two numbers in the section, WHATEVER they are. Can be signed. No directions! coord[1], coord[2] = mw.ustring.match(text,"(%-?%d+[%.,]?%d*)[%a%c%s%z!@#$%%^&%*%(%)%=|'{}:;<>~`]+(%-?%d+[%.,]?%d*)") debuglog = debuglog .. "L" .. tostring(coord[1]) .. "D" .. tostring(coord[2]) if not (coord[1] and coord[2]) then return nil end coord[1] = tidyNum(coord[1]) coord[2] = tidyNum(coord[2]) debuglog = debuglog .. ">" end -- invert signs for west, south positions if (firstdir == "W" or firstdir == "S") then coord[1] = -1 * coord[1] end if (seconddir == "W" or seconddir == "S") then coord[2] = -1 * coord[2] end -- if first is E/W, put it second if (firstdir == "W" or firstdir == "E") then coord[1], coord[2] = coord[2], coord[1] end -- default without directions specified: first = latitude, no sign reversal if (not firstdir) then firstdir = "N" end if (not seconddir) then seconddir = "E" end debuglog = debuglog .. tostring(coord[1]) .. tostring(coord[2]) if mw.ustring.match(seconddir,"[NS]") or mw.ustring.match(firstdir,"[EW]") then return nil, "two of one direction in coordinate" end while coord[2] > 180 do coord[2] = coord[2] - 360 end while coord[2] < -180 do coord[2] = coord[2] + 360 end -- at this point firstdir and seconddir no longer mean anything - direction is in the + or - and first or second position return coord, warning end function getData(pagetitle, database, pRadius, eRadius) local pagecontent if pagetitle then pagecontent = pagetitle:getContent() end if not pagecontent then return database end pagecontent = mw.ustring.gsub(pagecontent, "^.-{|", "{|") -- remove all before first table if not pagecontent then return database end pagecontent = mw.ustring.gsub(pagecontent, "|}.-{|", "") or pagecontent -- remove all between tables pagecontent = mw.ustring.gsub(pagecontent, "|}.-$", "|}") or pagecontent -- remove all after table local pagerecord = mw.text.split(pagecontent,"|%-") -- separate all table rows into records for i = 1, #pagerecord do recordname = mw.ustring.match(pagerecord[i],"%[%[(.-)%]%]") recordcoord = parseCoord(pagerecord[i]) if recordname and recordcoord then table.insert(database,{recordname, recordcoord}) end end return database end function getDatabase(pages, pRadius, eRadius) local database = {} local page = mw.text.split(pages,"|") for i = 1, #page do local pagename = mw.text.trim(page[i] or "") local pagetitle = mw.title.new(pagename) database = getData(pagetitle,database, pRadius, eRadius) -- (so far as I know this is a self assignment, actually) end return database end function display(dataitem) local recordname, recordcoord = dataitem[1], dataitem[2] return '"'..recordname..'", {' .. recordcoord[1] .. ", " .. recordcoord[2] .. "}" end function displayDatabase(database) local outarray = {} local outprefix = "<nowiki><pre>\nreturn {{" local delimiter = "},\n{" local outsuffix = "}}\n</pre></nowiki>" for i = 1, #database do table.insert(outarray,display(database[i])) end return (outprefix .. table.concat(outarray, delimiter) .. outsuffix) end function p._main(frame, pRadius, eRadius, defaultdata) -- for now this is not really intended to be called except from other functions here - use planet name to call -- handle args in this module -- other parameters are REQUIRED. local args = getArgs(frame) data = args.data or defaultdata database = getDatabase(data, pRadius, eRadius) return displayDatabase(database) .. debuglog end function p.mars(frame) -- module name defines Mars - now set the radius accordingly local pRadius = 3376.2 -- km (polar) local eRadius = 3396.2 -- km (equatorial) local defaultdata = 'List of mountains on Mars|List of craters on Mars: A-G|List of craters on Mars: H-N|List of craters on Mars: O-Z|List of catenae on Mars' return p._main(frame, pRadius, eRadius, defaultdata) end function p.venus(frame) local pRadius = 6051.8 -- km local eRadius = 6051.8 -- km (doh, it doesn't spin much!) local defaultdata = 'List of craters on Venus|List of montes on Venus|List of coronae on Venus' return p._main(frame, pRadius, eRadius, defaultdata) end function p.moon(frame) -- NOTE: our articles listing craters on the Moon don't include coordinates! -- Also there are so many it might run out the clock on the module, we'd have to see local pRadius = 1735.97 -- km local eRadius = 1738.14 -- km local defaultdata = 'List of lunar features' -- (duplicates:) 'List of mountains on the Moon|List of valleys on the Moon|List of maria on the Moon' return p._main(frame, pRadius, eRadius, defaultdata) end function p.mercury(frame) local pRadius = 2439.7 -- km local eRadius = 2439.7 -- km local defaultdata = 'List of geological features on Mercury|List of craters on Mercury' -- no coord templates in these, watch for bad coordinates return p._main(frame, pRadius, eRadius, defaultdata) end function p.earthCraters(frame) -- a general list of all Earth features would be beyond a simple Lua module! local pRadius = 6356.8 -- km local eRadius = 6378.1 -- km local defaultdata = 'List of impact craters in Africa|List of impact craters in Antarctica|List of impact craters in Asia|List of impact craters in Australia|List of impact craters in Europe|List of impact craters in North America|List of impact craters in South America' return p._main(frame, pRadius, eRadius, defaultdata) end return p
Summary:
Please note that all contributions to Stockhub may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see
Stockhub:Copyrights
for details).
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Template used on this page:
Module:Sandbox/Wnt/FindFeatures/displayDatabase/doc
(
edit
)