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.

  1. 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:
  2. 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.
  3. 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.
  4. 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.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.