پودمان:Location map
توضیحات پودمان[ایجاد]
در صورت تمایل یک صفحهٔ توضیحات برای این پودمان اسکریبونتو ایجاد کنید. ویرایشگران میتوانند در صفحات تمرین (ایجاد | آینه) و آزمایشی (ایجاد) این پودمان را آزمایش کنند. لطفاً ردهها را به زیرصفحهٔ /توضیحات بیافزایید. زیرصفحههای این پودمان. |
local locMap = {}
-- Internationalization
local api = {
apiLocationMap = 'locationMap',
apiAddLocation = 'addLocation',
apiAddObject = 'addObject',
apiGetMapValue = 'getMapValue',
apiGetMapValueSet = 'getMapValueSet',
}
local quickbarMapType = 'relief'
local errMsgs = {
anError = 'Fehler',
unknownMap = 'Keine Karte für Region <em>%s</em> vorhanden',
noMapImage = 'Kein Kartenbild spezifiziert',
wrongLat = 'Breite %f liegt außerhalb der Kartenbegrenzungen',
wrongLong = 'Länge %f liegt außerhalb der Kartenbegrenzungen',
wrongXBorders = 'Fehlende oder falsche horizontale Kartengrenzen',
wrongYBorders = 'Fehlende oder falsche vertikale Kartengrenzen',
noObject = 'Kein Objekt angegeben',
noXPos = 'Keine horizontale Lage angegeben',
noYPos = 'Keine vertikale Lage angegeben',
noParam = 'Kein Parameter für getMapValue angegeben',
notDefined = 'Parameter nicht definiert',
}
local mapDocs = {
tableClass = 'prettytable',
name = 'Name',
description = 'Beschreibung',
projection = 'Projektion',
top = 'oben',
bottom = 'unten',
left = 'links',
right = 'rechts',
default = 'Standardkarte',
relief = 'Physische Karte',
quickbar = 'Standardkarte Quickbar',
mark = 'Marker',
marksize = 'Markergröße',
linear = '[[:w:Plattkarte|Plattkarte]]',
nonlinear = 'Nichtlineare Projektion',
}
-- Style aliases
local mapStyles = {
mitte = "margin: 0 auto !important",
center = "margin: 0 auto !important",
left = "clear: left; margin: 0 1em 1em 0; float: left",
links = "clear: left; margin: 0 1em 1em 0; float: left",
right = "clear: right; margin: 0 0 1em 1em; float: right",
rechts = "clear: right; margin: 0 0 1em 1em; float: right",
}
local labelStyles = {
bold = "font-weight: bold",
fett = "font-weight: bold",
italic = "font-style: italic",
kursiv = "font-style: italic",
underline = "text-decoration: underline",
letterspacing = "letter-spacing: 0.1em",
wordspacing = "word-spacing: 0.5em",
smallcaps = "font-variant: small-caps",
uppercase = "text-transform: uppercase",
region = "font-weight: bold; text-transform: uppercase; color: #646464",
subregion = "font-weight: bold; color: #646464",
waterbody = "font-weight: bold; font-style: italic; letter-spacing: 0.1em; text-transform: uppercase; color: #2A6DB5",
mountain = "font-weight: bold; font-style: italic; letter-spacing: 0.1em; color: #704040",
}
local labelPositions1 = {
["1"] = "left: 0; bottom: msize_px;",
["2"] = "left: msize3_px; bottom: -2px;",
["3"] = "left: msize5_px; top: -2em; height: 4em;",
right = "left: msize5_px; top: -2em; height: 4em;",
rechts = "left: msize5_px; top: -2em; height: 4em;",
["4"] = "left: msize3_px; top: -2px;",
["5"] = "left: 0; top: msize_px;",
["6"] = "left: -3em; top: msize3_px;",
bottom = "left: -3em; top: msize3_px;",
unten = "left: -3em; top: msize3_px;",
["7"] = "right: 0; top: msize_px;",
["8"] = "right: msize3_px; top: -2px;",
["9"] = "right: msize5_px; top: -2em; height: 4em;",
left = "right: msize5_px; top: -2em; height: 4em;",
links = "right: msize5_px; top: -2em; height: 4em;",
["10"] = "right: msize3_px; bottom: -2px;",
["11"] = "right: 0; bottom: msize_px;",
["12"] = "left: -3em; bottom: msize3_px;",
top = "left: -3em; bottom: msize3_px;",
oben = "left: -3em; bottom: msize3_px;",
center = "top: -2em; height: 4em; left: -3em;",
mitte = "top: -2em; height: 4em; left: -3em;",
}
local labelPositions2 = {
["1"] = "text-align: left;",
["2"] = "text-align: left;",
["3"] = "text-align: left; height: 4em;",
right = "text-align: left; height: 4em;",
rechts = "text-align: left; height: 4em;",
["4"] = "text-align: left;",
["5"] = "text-align: left;",
["6"] = "text-align: center;",
bottom = "text-align: center;",
unten = "text-align: center;",
["7"] = "text-align: right;",
["8"] = "text-align: right;",
["9"] = "text-align: right; height: 4em;",
left = "text-align: right; height: 4em;",
links = "text-align: right; height: 4em;",
["10"] = "text-align: right;",
["11"] = "text-align: right;",
["12"] = "text-align: center;",
top = "text-align: center;",
oben = "text-align: center;",
center = "text-align: center; height: 4em;",
mitte = "text-align: center; height: 4em;",
}
-- Local functions, please do not call them directly
local function split(s)
local split = mw.text.split(s, ';')
local result = {}
for key,value in pairs(split) do
tr = mw.text.trim(value)
if tr ~= '' then table.insert(result, tr) end
end
return result;
end
local function analyzeLabelStyle(style)
local split = split(style)
for key,value in pairs(split) do
if labelStyles[value] ~= nil then split[key] = labelStyles[value] end
end
return table.concat(split, '; ') .. ';'
end
local function analyzeMapStyle(style)
local split = split(style)
for key,value in pairs(split) do
if mapStyles[value] ~= nil then split[key] = mapStyles[value] end
end
return table.concat(split, '; ') .. ';'
end
local function setLocation(x, y, name, label, mark, marksize, labelStyle, labelWrap, labelPosition)
local lmarksize = math.floor(marksize + 0.5)
local msize = math.floor((marksize - 1) / 2 + 0.5)
local msize3 = math.floor((marksize + 2) / 2 + 0.5)
local msize5 = math.floor((marksize + 4) / 2 + 0.5)
local halfMarkSize = -msize .. 'px'
-- Setting a marker
local sCode = '<div style="position: absolute; border-style: none; padding: 0; overflow: visible; top: '
.. y*100 .. '%; left: ' .. x*100 .. '%;">'
if mark ~= 'none' then
sCode = sCode .. '<div style="position: absolute; padding: 0; top: ' .. halfMarkSize .. '; left: '
.. halfMarkSize .. '; min-width: ' .. lmarksize .. 'px; min-height: ' .. lmarksize .. 'px;">'
.. '[[Image:' .. mark .. '|' .. lmarksize .. 'x' .. lmarksize
.. 'px|top|link=' .. name .. '|' .. name .. ']]'
.. '</div>'
end
-- Adding a label
if (label ~= '') and (label ~= 'none') then
sCode = sCode .. '<table style="position: absolute; border: none; margin: 0; background-color: transparent; border-collapse: collapse;'
if (labelWrap ~= nil) and (labelWrap == 'manual') then
sCode = sCode .. ' white-space: nowrap; width: 10em !important; '
else
sCode = sCode .. ' width: 6em !important; '
end
if labelPositions1[labelPosition] ~= nil then
local posStyles = labelPositions1[labelPosition]
posStyles = string.gsub(posStyles, 'msize_', msize)
posStyles = string.gsub(posStyles, 'msize3_', msize3)
posStyles = string.gsub(posStyles, 'msize5_', msize5)
sCode = sCode .. posStyles .. '"><tr><td style="border: none; padding: 0; vertical-align: middle; '
.. labelPositions2[labelPosition]
else
-- Automatic Estimation
if y<=0.5 then
sCode = sCode .. 'top: ' .. msize3 .. 'px; '
else
sCode = sCode .. 'bottom: ' .. msize3 .. 'px; '
end
if x<0.25 then
sCode = sCode .. 'text-align: left; left: ' .. math.floor(3 - 60*x)/10 .. 'em;'
.. '"><tr><td style="border: none; padding: 0; vertical-align: middle; text-align: left;'
else if x<0.75 then
sCode = sCode .. 'text-align: center; left: -3em;'
.. '"><tr><td style="border: none; padding: 0; vertical-align: middle; text-align: center;'
else
sCode = sCode .. 'text-align: right; right: ' .. math.floor(10*(0.3 - (1 - x) * 6))/10 .. 'em;'
.. '"><tr><td style="border: none; padding: 0; vertical-align: middle; text-align: right;'
end
end
end
if (labelWrap ~= nil) and (labelWrap == 'manual') then
sCode = sCode .. ' white-space: nowrap; width: 10em !important;'
else
sCode = sCode .. ' width: 6em !important;'
end
sCode = sCode .. '"><span style="' .. analyzeLabelStyle(labelStyle) .. '">'
.. label .. '</span></td></tr></table>'
end
sCode = sCode .. '</div>'
return sCode
end
local function baseMap(mapImage, description, mapStyle, width, caption, captionStyle,
captionInnerBorder, captionOuterBorder, x, y, name, label, mark, marksize, labelStyle,
labelWrap, labelPosition, places)
local sCode = '<table class="locationMap" style="overflow: visible; max-width: none !important; border-collapse: collapse;'
-- Test if fixed or variable width (..x..). Force width if fixed and a caption is specified
if (string.find(width, 'x') == nil) and (caption ~= '') then
sCode = sCode .. ' width: ' .. tostring(tonumber(width)+10) ..'px !important;'
else
sCode = sCode .. ' width: auto !important;'
end
if caption ~= '' then sCode = sCode .. ' border: ' .. captionOuterBorder .. ';' end
sCode = sCode .. ' ' .. analyzeMapStyle(mapStyle) .. '"><tr><td class="thumb" style="overflow: visible; border: none; padding: '
if caption ~= '' then sCode = sCode .. '3px 3px 0;">' else sCode = sCode .. '0;">' end
sCode = sCode .. '<div class="noresize" style="overflow: visible; max-width: none !important; padding: 0; margin: 0 auto !important; position: relative; border: '
if caption ~= '' then sCode = sCode .. captionInnerBorder .. ';' else sCode = sCode .. 'none;' end
-- Test if fixed or variable width (..x..). Force width if fixed
if string.find(width, 'x') == nil then sCode = sCode .. ' width: ' .. width ..'px !important;">' else sCode = sCode .. ' width: auto !important;">' end
sCode = sCode .. '[[Image:' .. mapImage .. '|' .. width .. 'px|center|' .. description .. ']]'
if (x<0) or (x>1) or (y<0) or (y>1) then
sCode = sCode .. '<div style="position: absolute; width: 50%; top: 50%; left: 25%; color: #ff0000; font-weight: bold; text-align: center;">'
.. 'Fehlerhafte Koordinate ' .. name .. '</div>'
else
sCode = sCode .. setLocation(x, y, name, label, mark, marksize, labelStyle, labelWrap, labelPosition)
end
sCode = sCode .. places .. '</div></td>'
if caption ~= '' then
sCode = sCode .. '<tr><td class="thumbcaption"'
if captionStyle ~= '' then
sCode = sCode .. ' style="'.. captionStyle .. '"'
end
sCode = sCode .. '>' .. caption .. '</td></tr>'
end
sCode = sCode .. '</table>'
return sCode
end
-- Handling regional map data
local function getMapData(id)
local region = require('Modul:Location map data ' .. id)
if (region ~= nil) and (region.data ~= nil) then
region.data['id'] = id
return region.data
else
return nil
end
end
local function getMapObject(id)
local region = require('Modul:Location map data ' .. id)
if (region ~= nil) and (region.data ~= nil) then
region.data['id'] = id
return region
else
return nil
end
end
local function linearX(data, long)
local left = data['left']
local right = data['right']
if (data == nil) or (left == nil) or (right == nil) or (left == right) then
-- Error
return -1
else if left < right then
return (long - left) / (right - left)
else
if long < 0 then
return (360 + long - left) / (360 + right - left)
else
return (long - left) / (360 + right - left)
end
end
end
end
local function linearY(data, lat)
local top = data['top']
local bottom = data['bottom']
if (data == nil) or (top == nil) or (bottom == nil) or (top == bottom) then
-- Error
return -1
else
return (lat - top) / (bottom - top)
end
end
local function getX(anObject, long, lat)
if anObject.x ~= nil then
return anObject.x(lat, long)
else
return linearX(anObject.data, long)
end
end
local function getY(anObject, long, lat)
if anObject.y ~= nil then
return anObject.y(lat, long)
else
return linearY(anObject.data, lat)
end
end
local function getMapImage(data, which)
local image = data['default']
local w = which
if w == 'quickbar' then
w = quickbarMapType
if (data['quickbar'] ~= nil) and (data['quickbar'] ~= '') then
w = data['quickbar']
end
end
if (w ~= '') and (data[w] ~= nil) and (data[w] ~= '') then
image = data[w]
end
return image
end
-- Parameters and error handling
local function argCheck(param, altValue)
if param == nil then
return altValue
else
local val = mw.text.trim(param)
if val == '' then val = altValue end
return val
end
end
local function errorStr(s)
return '<strong class="error">Fehler im Modul <em>Location map</em>: ' .. s .. '</strong>'
end
-- Map functions
local function apiLocationMap(args)
local map = argCheck(args['map'], 'missing')
local success, mObject = pcall(getMapObject, map)
if not success then
return errorStr(string.format(errMsgs['unknownMap'], map))
else
-- Error handling
local errorMsgs = {}
success = true
-- Parameters check
local mData = mObject.data
local description = ''
if mData['description'] ~= nil then description = mData['description'] end
local lat = tonumber(argCheck(tostring(args['lat']), 0))
local long = tonumber(argCheck(tostring(args['long']), 0))
local x = getX(mObject, long, lat)
if (x<0) or (x>1) then
success = false
if x == -1 then
table.insert(errorMsgs, errorStr(errMsgs['wrongXBorders']))
else
table.insert(errorMsgs, errorStr(string.format(errMsgs['wrongLong'], long)))
end
end
local y = getY(mObject, long, lat)
if (y<0) or (y>1) then
success = false
if y == -1 then
table.insert(errorMsgs, errorStr(errMsgs['wrongYBorders']))
else
table.insert(errorMsgs, errorStr(string.format(errMsgs['wrongLat'], lat)))
end
end
local maptype = argCheck(args['maptype'], 'default')
local mapImage = argCheck(args['alternativeMap'], getMapImage(mData, maptype))
if (mapImage == nil) or (mapImage == '') then
success = false
table.insert(errorMsgs, errorStr(errMsgs['noMapImage']))
end
if not success then
return table.concat(errorMsgs, '<br />')
else
local name = argCheck(args['name'], '')
local label = argCheck(args['label'], '')
-- Checking width syntax
local width = argCheck(tostring(args['width']), '')
if (string.match(width, '^%d+$') == nil) and (string.match(width, '^%d*x%d+$') == nil) then
width = '200x200'
end
if mData['mark'] ~= nil then mark = mData['mark'] else mark = 'Reddot.svg' end
mark = argCheck(args['mark'], mark)
if mData['marksize'] ~= nil then marksize = mData['marksize'] else marksize = 5 end
local marksize = argCheck(args['marksize'], marksize)
local mapStyle = argCheck(args['mapStyle'], 'mitte')
local labelStyle = argCheck(args['labelStyle'], '')
local labelBackground = argCheck(args['labelBackground'], '')
if labelBackground ~='' then
labelBackground = 'background: ' .. labelBackground
if labelStyle ~='' then
labelStyle = labelStyle .. '; ' .. labelBackground
else
labelStyle = labelBackground
end
end
local labelWrap = argCheck(args['labelWrap'], 'auto')
local labelPosition = argCheck(args['labelPosition'], 'auto')
local caption = argCheck(args['caption'], '')
local captionStyle = argCheck(args['captionStyle'], '')
local captionInnerBorder = argCheck(args['captionInnerBorder'], '1px solid #cccccc')
local captionOuterBorder = argCheck(args['captionOuterBorder'], '1px solid #cccccc')
local places = argCheck(args['places'], '')
return baseMap(mapImage, description, mapStyle, width, caption, captionStyle,
captionInnerBorder, captionOuterBorder, x, y, name, label, mark, marksize,
labelStyle, labelWrap, labelPosition, places)
end
end
end
local function apiAddLocation(args)
local map = argCheck(args['map'], 'missing')
local success, mObject = pcall(getMapObject, map)
if not success then
return errorStr(string.format(errMsgs['unknownMap'], map))
else
-- Error handling
local errorMsgs = {}
success = true
-- Parameters check
local mData = mObject.data
local lat = tonumber(argCheck(tostring(args['lat']), 0))
local long = tonumber(argCheck(tostring(args['long']), 0))
local x = getX(mObject, long, lat)
if (x<0) or (x>1) then
success = false
if x == -1 then
table.insert(errorMsgs, errorStr(errMsgs['wrongXBorders']))
else
table.insert(errorMsgs, errorStr(string.format(errMsgs['wrongLong'], long)))
end
end
local y = getY(mObject, long, lat)
if (y<0) or (y>1) then
success = false
if y == -1 then
table.insert(errorMsgs, errorStr(errMsgs['wrongYBorders']))
else
table.insert(errorMsgs, errorStr(string.format(errMsgs['wrongLat'], lat)))
end
end
if not success then
return table.concat(errorMsgs, '<br />')
else
local name = argCheck(args['name'], '')
local label = argCheck(args['label'], '')
if mData['mark'] ~= nil then mark = mData['mark'] else mark = 'Reddot.svg' end
mark = argCheck(args['mark'], mark)
if mData['marksize'] ~= nil then marksize = mData['marksize'] else marksize = 5 end
local marksize = argCheck(args['marksize'], marksize)
local mapStyle = argCheck(args['mapStyle'], 'mitte')
local labelStyle = argCheck(args['labelStyle'], '')
local labelBackground = argCheck(args['labelBackground'], '')
if labelBackground ~='' then
labelBackground = 'background: ' .. labelBackground
if labelStyle ~='' then
labelStyle = labelStyle .. '; ' .. labelBackground
else
labelStyle = labelBackground
end
end
local labelWrap = argCheck(args['labelWrap'], 'auto')
local labelPosition = argCheck(args['labelPosition'], 'auto')
return setLocation(x, y, name, label, mark, marksize, labelStyle, labelWrap, labelPosition)
end
end
end
local function apiAddObject(args)
local anObject = argCheck(args['object'], '')
if anOject == '' then
return errorStr(errMsgs['noObject'])
else
local success = true
local errorMsgs = {}
local right = argCheck(args['right'], '')
local left = argCheck(args['left'], '')
if (right == '') and (left == '') then
success = false
table.insert(errorMsgs, errorStr(errMsgs['noXPos']))
end
local top = argCheck(args['top'], '')
local bottom = argCheck(args['bottom'], '')
if (top == '') and (bottom == '') then
success = false
table.insert(errorMsgs, errorStr(errMsgs['noYPos']))
end
if not success then
return table.concat(errorMsgs, '<br />')
else
local objectStyle = argCheck(args['objectStyle'], '')
local objectBackground = argCheck(args['objectBackground'], '')
if objectBackground ~='' then
objectBackground = 'background: ' .. objectBackground
if objectStyle ~='' then
objectStyle = objectStyle .. '; ' .. objectBackground
else
objectStyle = objectBackground
end
end
sCode = '<table style="border-collapse: collapse; margin: 0; padding: 0; width: auto !important; overflow: visible; position: absolute; background: transparent; '
if (left ~='') then
sCode = sCode .. 'left: ' .. left .. '; '
else
sCode = sCode .. 'right: ' .. right .. '; '
end
if (top ~='') then
sCode = sCode .. 'top: ' .. top .. ';"><tr><td style="border: none; padding: 0; '
else
sCode = sCode .. 'bottom: ' .. bottom .. ';"><tr><td style="border: none; padding: 0; '
end
sCode = sCode .. analyzeLabelStyle(objectStyle)
.. '">' .. anObject .. '</td></tr></table>'
return sCode
end
end
end
-- Documentation of map data
local function apiGetMapValue(args)
local map = argCheck(args['map'], 'missing')
local success, mData = pcall(getMapData, map)
if not success then
return errorStr(string.format(errMsgs['unknownMap'], map))
else
local param = argCheck(args['param'], '')
if param == '' then
return errorStr(errMsgs['noParam'])
else
if mData[param] == nil then
return errMsgs['anError']
else
return mData[param]
end
end
end
end
local function apiGetMapValueSet(args)
local map = argCheck(args['map'], 'missing')
local success, mData = pcall(getMapData, map)
if not success then
return errorStr(string.format(errMsgs['unknownMap'], map))
else
local paramList = {'name', 'description', 'projection', 'top', 'bottom',
'left', 'right', 'default', 'relief', 'quickbar', 'mark', 'marksize'}
local sCode = '<table class="' .. mapDocs['tableClass'] .. '">'
for i = 1, #paramList, 1 do
sCode = sCode .. '<tr><th style="text-align: left">' .. mapDocs[paramList[i]] .. '</th><td>'
if mData[paramList[i]] == nil then
sCode = sCode .. errMsgs['notDefined'] .. '</td></tr>'
else
local v = mData[paramList[i]]
if mapDocs[v] ~= nil then v = mapDocs[v] end
sCode = sCode .. v .. '</td></tr>'
end
end
return sCode .. '</table>'
end
end
-- API function calls
locMap[api.apiLocationMap] = function (frame)
return apiLocationMap(frame.args)
end
locMap[api.apiAddLocation] = function (frame)
return apiAddLocation(frame.args)
end
locMap[api.apiAddObject] = function (frame)
return apiAddObject(frame.args)
end
locMap[api.apiGetMapValue] = function (frame)
return apiGetMapValue(frame.args)
end
locMap[api.apiGetMapValueSet] = function (frame)
return apiGetMapValueSet(frame.args)
end
-- Example for usage in a Lua script
function locMap.exampleLuaCall()
local frame = {}
frame.args = {
map = 'de',
lat = 52.51789,
long = 13.38873,
name = 'Berlin',
label = '[[Berlin]]',
}
return locMap.locationMap(frame)
end
return locMap