نماد توضیحات توضیحات پودمان[ایجاد]
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