Module:Sandbox/Wnt/FindFeatures/displayDatabase
-- 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
Content Disclaimer
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.
- The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
- There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
- It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
- Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.