한국   대만   중국   일본 
모듈:Infobox mapframe - 위키百科, 우리 모두의 百科事典 本文으로 移動

모듈 : Infobox mapframe

이 페이지는 준보호되어 있습니다.
위키百科, 우리 모두의 百科事典.

local
 mf
 =
 require
(
'Module:Mapframe'
)

local
 getArgs
 =
 require
(
'Module:Arguments'
).
getArgs

local
 yesno
 =
 require
(
'Module:Yesno'
)

local
 infoboxImage
 =
 require
(
'Module:InfoboxImage'
).
InfoboxImage


-- Defaults

local
 DEFAULT_FRAME_WIDTH
 =
 "270"

local
 DEFAULT_FRAME_HEIGHT
 =
 "200"

local
 DEFAULT_ZOOM
 =
 10

local
 DEFAULT_GEOMASK_STROKE_WIDTH
 =
 "1"

local
 DEFAULT_GEOMASK_STROKE_COLOR
 =
 "#777777"

local
 DEFAULT_GEOMASK_FILL
 =
 "#888888"

local
 DEFAULT_GEOMASK_FILL_OPACITY
 =
 "0.5"

local
 DEFAULT_SHAPE_STROKE_WIDTH
 =
 "3"

local
 DEFAULT_SHAPE_STROKE_COLOR
 =
 "#FF0000"

local
 DEFAULT_SHAPE_FILL
 =
 "#606060"

local
 DEFAULT_SHAPE_FILL_OPACITY
 =
 "0.5"

local
 DEFAULT_LINE_STROKE_WIDTH
 =
 "5"

local
 DEFAULT_LINE_STROKE_COLOR
 =
 "#FF0000"

local
 DEFAULT_MARKER_COLOR
 =
 "#5E74F3"



-- Trim whitespace from args, and remove empty args

function
 trimArgs
(
argsTable
)

	local
 cleanArgs
 =
 {}

	for
 key
,
 val
 in
 pairs
(
argsTable
)
 do

		if
 type
(
val
)
 ==
 'string'
 then

			val
 =
 val
:
match
(
'^%s*(.-)%s*$'
)

			if
 val
 ~=
 ''
 then

				cleanArgs
[
key
]
 =
 val

			end

		else

			cleanArgs
[
key
]
 =
 val

		end

	end

	return
 cleanArgs

end


function
 getBestStatement
(
item_id
,
 property_id
)

	if
 not
(
item_id
)
 or
 not
(
mw
.
wikibase
.
isValidEntityId
(
item_id
))
 or
 not
(
mw
.
wikibase
.
entityExists
(
item_id
))
 then

		return
 false

	end

	local
 statements
 =
 mw
.
wikibase
.
getBestStatements
(
item_id
,
 property_id
)

	if
 not
 statements
 or
 #
statements
 ==
 0
 then

		return
 false

	end

	local
 hasNoValue
 =
 (
 statements
[
1
].
mainsnak
 and
 statements
[
1
].
mainsnak
.
snaktype
 ==
 'novalue'
 )

	if
 hasNoValue
 then

		return
 false

	end

	return
 statements
[
1
]

end


function
 hasWikidataProperty
(
item_id
,
 property_id
)

	return
 getBestStatement
(
item_id
,
 property_id
)
 and
 true
 or
 false

end


function
 getStatementValue
(
statement
)

	return
 statement
 and
 statement
.
mainsnak
 and
 statement
.
mainsnak
.
datavalue
 and
 statement
.
mainsnak
.
datavalue
.
value
 or
 nil

end


function
 relatedEntity
(
item_id
,
 property_id
)

	local
 value
 =
 getStatementValue
(
 getBestStatement
(
item_id
,
 property_id
)
 )

	return
 value
 and
 value
.
id
 or
 false

end


function
 idType
(
id
)

	if
 not
 id
 then
 
		return
 nil

	elseif
 mw
.
ustring
.
match
(
id
,
 "[Pp]%d+"
)
 then

		return
 "property"

	elseif
 mw
.
ustring
.
match
(
id
,
 "[Qq]%d+"
)
 then

		return
 "item"

	else

		return
 nil

	end

end


function
 getZoom
(
value
,
 unit
)

	local
 length_km

	if
 unit
 ==
 'km'
 then

		length_km
 =
 tonumber
(
value
)

	elseif
 unit
 ==
 'mi'
 then

		length_km
 =
 tonumber
(
value
)
*
1.609344

	elseif
 unit
 ==
 'km2'
 then

		length_km
 =
 math.sqrt
(
tonumber
(
value
))

	elseif
 unit
 ==
 'mi2'
 then

		length_km
 =
 math.sqrt
(
tonumber
(
value
))
*
1.609344

	end

	-- max for zoom 2 is 6400km, for zoom 3 is 3200km, for zoom 4 is 1600km, etc

	local
 zoom
 =
 math.floor
(
8
 -
 (
math
.
log10
(
length_km
)
 -
 2
)
/
(
math
.
log10
(
2
)))

	-- limit to values below 17

	zoom
 =
 math.min
(
17
,
 zoom
)

	-- take off 1 when calculated from area, to account for unusual shapes

	if
 unit
 ==
 'km2'
 or
 unit
 ==
 'mi2'
 then

		zoom
 =
 zoom
 -
 1

	end

	-- minimum value is 1

	return
 math.max
(
1
,
 zoom
)

end


function
 shouldAutoRun
(
frame
)

	-- Check if should be running

	local
 explicitlyOn
 =
 yesno
(
mw
.
text
.
trim
(
frame
.
getParent
(
frame
).
args
.
mapframe
 or
 ""
))
 -- true of false or nil

	local
 onByDefault
 =
 (
explicitlyOn
 ==
 nil
)
 and
 yesno
(
mw
.
text
.
trim
(
frame
.
args
.
onByDefault
 or
 ""
),
 false
)
 -- true or false

	return
 explicitlyOn
 or
 onByDefault

end


function
 argsFromAuto
(
frame
)

	-- Get args from the frame (invoke call) and the parent (template call).

	-- Frame arguments are default values which are overridden by parent values

	-- when both are present

	local
 args
 =
 getArgs
(
frame
,
 {
parentFirst
 =
 true
})

	
	-- Discard args not prefixed with "mapframe-", remove that prefix from those that remain

	local
 fixedArgs
 =
 {}

	for
 name
,
 val
 in
 pairs
(
args
)
 do

		local
 fixedName
 =
 string.match
(
name
,
 "^mapframe%-(.+)$"
 )

		if
 fixedName
 then

			fixedArgs
[
fixedName
]
 =
 val

		-- allow coord, coordinates, etc to be unprefixed

		elseif
 name
 ==
 "coordinates"
 or
 name
 ==
 "coord"
 or
 name
 ==
 "coordinate"
 and
 not
 fixedArgs
.
coord
 then

			fixedArgs
.
coord
 =
 val

		-- allow id, qid to be unprefixed, map to id (if not already present)

		elseif
 name
 ==
 "id"
 or
 name
 ==
 "qid"
 and
 not
 fixedArgs
.
id
 then

			fixedArgs
.
id
 =
 val

		end

	end

	return
 fixedArgs

end


local
 p
 =
 {}


p
.
autocaption
 =
 function
(
frame
)

	if
 not
 shouldAutoRun
(
frame
)
 then
 return
 ""
 end

	local
 args
 =
 argsFromAuto
(
frame
)

	if
 args
.
caption
 then

		return
 args
.
caption

	elseif
 args
.
switcher
 then
 
		return
 ""

	end

	local
 maskItem

	local
 maskType
 =
 idType
(
args
.
geomask
)

	if
 maskType
 ==
 'item'
 then

		maskItem
 =
 args
.
geomask

	elseif
 maskType
 ==
 "property"
 then

		maskItem
 =
 relatedEntity
(
args
.
id
 or
 mw
.
wikibase
.
getEntityIdForCurrentPage
(),
 args
.
geomask
)

	end

	local
 maskItemLabel
 =
 maskItem
 and
 mw
.
wikibase
.
getLabel
(
 maskItem
 )

	return
 maskItemLabel
 and
 "Location in "
..
maskItemLabel
 or
 ""

end


function
 parseCustomWikitext
(
customWikitext
)

	-- infoboxImage will format an image if given wikitext containing an

	-- image, or else pass through the wikitext unmodified

	return
 infoboxImage
({

		args
 =
 {

			image
 =
 customWikitext

		}

	})

end


p
.
auto
 =
 function
(
frame
)

	if
 not
 shouldAutoRun
(
frame
)
 then
 return
 ""
 end

	local
 args
 =
 argsFromAuto
(
frame
)

	if
 args
.
custom
 then

		return
 frame
:
preprocess
(
parseCustomWikitext
(
args
.
custom
))

	end

	local
 mapframe
 =
 p
.
_main
(
args
)

	return
 frame
:
preprocess
(
mapframe
)

end


p
.
main
 =
 function
(
frame
)

	local
 parent
 =
 frame
.
getParent
(
frame
)

	local
 parentArgs
 =
 parent
.
args

	local
 mapframe
 =
 p
.
_main
(
parentArgs
)

	return
 frame
:
preprocess
(
mapframe
)

end


p
.
_main
 =
 function
(
_config
)

	-- `config` is the args passed to this module

	local
 config
 =
 trimArgs
(
_config
)

	
	-- Require wikidata item, or specified coords

	local
 wikidataId
 =
 config
.
id
 or
 mw
.
wikibase
.
getEntityIdForCurrentPage
()

	if
 not
(
wikidataId
)
 and
 not
(
config
.
coord
)
 then

		return
 ''

	end


	-- Require coords (specified or from wikidata), so that map will be centred somewhere

	-- (P625 = coordinate location)

	local
 hasCoordinates
 =
 hasWikidataProperty
(
wikidataId
,
 'P625'
)
 or
 config
.
coordinates
 or
 config
.
coord

	if
 not
 hasCoordinates
 then
  
		return
 ''

	end


	-- `args` is the arguments which will be passed to the mapframe module

	local
 args
 =
 {}


	-- Some defaults/overrides for infobox presentation

	args
.
display
 =
 "inline"

	args
.
frame
 =
 "yes"

	args
.
plain
 =
 "yes"

	args
[
"frame-width"
]
  =
 config
[
"frame-width"
]
 or
 config
.
width
 or
 DEFAULT_FRAME_WIDTH

	args
[
"frame-height"
]
 =
 config
[
"frame-height"
]
 or
 config
.
height
 or
 DEFAULT_FRAME_HEIGHT

	args
[
"frame-align"
]
  =
 "center"


	args
[
"frame-coord"
]
 =
 config
[
"frame-coordinates"
]
 or
 config
[
"frame-coord"
]
 or
 ""

	-- Note: config["coordinates"] or config["coord"] should not be used for the alignment of the frame;

	-- see talk page ( https://en.wikipedia.org/wiki/Special:Diff/876492931 )


	-- deprecated lat and long parameters

	args
[
"frame-lat"
]
    =
 config
[
"frame-lat"
]
 or
 config
[
"frame-latitude"
]
 or
 ""

	args
[
"frame-long"
]
   =
 config
[
"frame-long"
]
 or
 config
[
"frame-longitude"
]
 or
 ""


	-- Calculate zoom from length or area (converted to km or km2)

	if
 config
.
length_km
 then

		args
.
zoom
 =
 getZoom
(
config
.
length_km
,
 'km'
)

	elseif
 config
.
length_mi
 then

		args
.
zoom
 =
 getZoom
(
config
.
length_mi
,
 'mi'
)

	elseif
 config
.
area_km2
 then

		args
.
zoom
 =
 getZoom
(
config
.
area_km2
,
 'km2'
)

	elseif
 config
.
area_mi2
 then

		args
.
zoom
 =
 getZoom
(
config
.
area_mi2
,
 'mi2'
)

	else

		args
.
zoom
 =
 config
.
zoom
 or
 DEFAULT_ZOOM

	end


	-- Conditionals: whether point, geomask should be shown

	local
 hasOsmRelationId
 =
 hasWikidataProperty
(
wikidataId
,
 'P402'
)
 -- P402 is OSM relation ID

	local
 shouldShowPointMarker
;

	if
 config
.
point
 ==
 "on"
 then

		shouldShowPointMarker
 =
 true
 
	elseif
 config
.
point
 ==
 "none"
 then

		shouldShowPointMarker
 =
 false

	else

		shouldShowPointMarker
 =
 not
(
hasOsmRelationId
)
 or
 (
config
.
marker
 and
 config
.
marker
 ~=
 'none'
)
 or
 (
config
.
coordinates
 or
 config
.
coord
)

	end

	local
 shouldShowShape
 =
 config
.
shape
 ~=
 'none'

	local
 shapeType
 =
 config
.
shape
 ==
 'inverse'
 and
 'shape-inverse'
 or
 'shape'

	local
 shouldShowLine
 =
 config
.
line
 ~=
 'none'

	local
 maskItem

	local
 useWikidata
 =
 true
 -- Use shapes/lines based on wikidata id

	-- Do not use wikidata when coords are specified (and not turned off), unless explicitly set

	if
 config
.
coord
 and
 shouldShowPointMarker
 then

		useWikidata
 =
 config
.
wikidata
 and
 true
 or
 false

	end

	
	-- Switcher

	if
 config
.
switcher
 ==
 "zooms"
 then

		-- switching between zoom levels

		local
 maxZoom
 =
 math.max
(
tonumber
(
args
.
zoom
),
 3
)
 -- what zoom would have otherwise been (if 3 or more, otherwise 3)

		local
 minZoom
 =
 1
 -- completely zoomed out

		local
 midZoom
 =
 math.floor
((
maxZoom
 +
 minZoom
)
/
2
)
 -- midway between maxn and min

		args
.
switch
 =
 "zoomed in, zoomed midway, zoomed out"

		args
.
zoom
 =
 string.format
(
"SWITCH:%d,%d,%d"
,
 maxZoom
,
 midZoom
,
 minZoom
)

	elseif
 config
.
switcher
 ==
 "auto"
 then

		-- switching between P276 and P131 areas with recursive lookup, e.g. item's city,

		-- that city's state, and that state's country

		args
.
zoom
 =
 nil
 -- let kartographer determine the zoom

		local
 maskLabels
 =
 {}

		local
 maskItems
 =
 {}

		local
 maskItemId
 =
 relatedEntity
(
wikidataId
,
 "P276"
)
 or
  relatedEntity
(
wikidataId
,
 "P131"
)
 
		local
 maskLabel
 =
 mw
.
wikibase
.
getLabel
(
maskItemId
)

		while
 maskItemId
 and
 maskLabel
 and
 mw
.
text
.
trim
(
maskLabel
)
 ~=
 ""
 do

			table.insert
(
maskLabels
,
 maskLabel
)

			table.insert
(
maskItems
,
 maskItemId
)

			maskItemId
 =
 maskItemId
 and
 relatedEntity
(
maskItemId
,
 "P131"
)

			maskLabel
 =
 maskItemId
 and
 mw
.
wikibase
.
getLabel
(
maskItemId
)

		end

		if
 #
maskLabels
 >
 1
 then

			args
.
switch
 =
 table.concat
(
maskLabels
,
 "###"
)

			maskItem
 =
 "SWITCH:"
 ..
 table.concat
(
maskItems
,
 ","
)

		elseif
 #
maskLabels
 ==
 1
 then

			maskItem
 =
 maskItemId
[
1
]

		end

	elseif
 config
.
switcher
 ==
 "geomasks"
 and
 config
.
geomask
 then

		-- switching between items in geomask parameter

		args
.
zoom
 =
 nil
 -- let kartographer determine the zoom

		local
 separator
 =
 (
mw
.
ustring
.
find
(
config
.
geomask
,
 "###"
,
 0
,
 true
 )
 and
 "###"
)
 or

			(
mw
.
ustring
.
find
(
config
.
geomask
,
 ";"
,
 0
,
 true
 )
 and
 ";"
)
 or
 ","

		local
 pattern
 =
 "%s*"
..
separator
..
"%s*"

		local
 maskItems
 =
 mw
.
text
.
split
(
mw
.
ustring
.
gsub
(
config
.
geomask
,
 "SWITCH:"
,
 ""
),
 pattern
)

		local
 maskLabels
 =
 {}

		if
 #
maskItems
 >
 1
 then

			for
 i
,
 item
 in
 ipairs
(
maskItems
)
 do

				table.insert
(
maskLabels
,
 mw
.
wikibase
.
getLabel
(
item
))

			end

			args
.
switch
 =
 table.concat
(
maskLabels
,
 "###"
)

			maskItem
 =
 "SWITCH:"
 ..
 table.concat
(
maskItems
,
 ","
)

		end

	end

	
	-- resolve geomask item id (if not using geomask switcher)

	if
 not
 maskItem
 then
 --  

		local
 maskType
 =
 idType
(
config
.
geomask
)

		if
 maskType
 ==
 'item'
 then

			maskItem
 =
 config
.
geomask

		elseif
 maskType
 ==
 "property"
 then

			maskItem
 =
 relatedEntity
(
wikidataId
,
 config
.
geomask
)

		end

	end

	
	-- Keep track of arg numbering

	local
 argNumber
 =
 ''

	local
 function
 incrementArgNumber
()

		if
 argNumber
 ==
 ''
 then

			argNumber
 =
 2

		else

			argNumber
 =
 argNumber
 +
 1

		end

	end

	
	-- Geomask

	if
 maskItem
 then

		args
[
"type"
..
argNumber
]
 =
 "shape-inverse"

		args
[
"id"
..
argNumber
]
 =
 maskItem

		args
[
"stroke-width"
..
argNumber
]
 =
 config
[
"geomask-stroke-width"
]
 or
 DEFAULT_GEOMASK_STROKE_WIDTH

		args
[
"stroke-color"
..
argNumber
]
 =
 config
[
"geomask-stroke-color"
]
 or
 config
[
"geomask-stroke-colour"
]
 or
 DEFAULT_GEOMASK_STROKE_COLOR

		args
[
"fill"
..
argNumber
]
 =
 config
[
"geomask-fill"
]
 or
 DEFAULT_GEOMASK_FILL

		args
[
"fill-opacity"
..
argNumber
]
 =
 config
[
"geomask-fill-opacity"
]
 or
 DEFAULT_SHAPE_FILL_OPACITY

		-- Let kartographer determine zoom and position, unless it is explicitly set in config

		if
 not
 config
.
zoom
 and
 not
 config
.
switcher
 then

			args
.
zoom
 =
 nil

			args
[
"frame-coord"
]
 =
 nil

			args
[
"frame-lat"
]
 =
 nil

			args
[
"frame-long"
]
 =
 nil
 	
			local
 maskArea
 =
 getStatementValue
(
 getBestStatement
(
maskItem
,
 'P2046'
)
 )

		end

		incrementArgNumber
()

		-- Hack to fix phab:T255932

		if
 not
 args
.
zoom
 then

			args
[
"type"
..
argNumber
]
 =
 "line"

			args
[
"id"
..
argNumber
]
 =
 maskItem

			args
[
"stroke-width"
..
argNumber
]
 =
 0

			incrementArgNumber
()

		end

	end

	
	-- Shape (or shape-inverse)

	if
 useWikidata
 and
 shouldShowShape
 then

		args
[
"type"
..
argNumber
]
 =
 shapeType

		if
 config
.
id
 then
 args
[
"id"
..
argNumber
]
 =
 config
.
id
 end

		args
[
"stroke-width"
..
argNumber
]
 =
 config
[
"shape-stroke-width"
]
 or
 config
[
"stroke-width"
]
 or
 DEFAULT_SHAPE_STROKE_WIDTH

		args
[
"stroke-color"
..
argNumber
]
 =
 config
[
"shape-stroke-color"
]
 or
 config
[
"shape-stroke-colour"
]
 or
 config
[
"stroke-color"
]
 or
 config
[
"stroke-colour"
]
 or
 DEFAULT_SHAPE_STROKE_COLOR

		args
[
"fill"
..
argNumber
]
 =
 config
[
"shape-fill"
]
 or
 DEFAULT_SHAPE_FILL

		args
[
"fill-opacity"
..
argNumber
]
 =
 config
[
"shape-fill-opacity"
]
 or
 DEFAULT_SHAPE_FILL_OPACITY

		incrementArgNumber
()

	end

	
	-- Line

	if
 useWikidata
 and
 shouldShowLine
 then

		args
[
"type"
..
argNumber
]
 =
 "line"

		if
 config
.
id
 then
 args
[
"id"
..
argNumber
]
 =
 config
.
id
 end

		args
[
"stroke-width"
..
argNumber
]
 =
 config
[
"line-stroke-width"
]
 or
 config
[
"stroke-width"
]
 or
 DEFAULT_LINE_STROKE_WIDTH

		args
[
"stroke-color"
..
argNumber
]
 =
 config
[
"line-stroke-color"
]
 or
 config
[
"line-stroke-colour"
]
 or
 config
[
"stroke-color"
]
 or
 config
[
"stroke-colour"
]
 or
 DEFAULT_LINE_STROKE_COLOR

		incrementArgNumber
()

	end


	-- Point

	if
 shouldShowPointMarker
 then

		args
[
"type"
..
argNumber
]
 =
 "point"

		if
 config
.
id
 then
 args
[
"id"
..
argNumber
]
 =
 config
.
id
 end

		if
 config
.
coord
 then
 args
[
"coord"
..
argNumber
]
 =
 config
.
coord
 end

		if
 config
.
marker
 then
 args
[
"marker"
..
argNumber
]
 =
 config
.
marker
 end

		args
[
"marker-color"
..
argNumber
]
 =
 config
[
"marker-color"
]
 or
 config
[
"marker-colour"
]
 or
 DEFAULT_MARKER_COLOR

		incrementArgNumber
()

	end


	local
 mapframe
 =
 args
.
switch
 and
 mf
.
multi
(
args
)
 or
 mf
.
_main
(
args
)

	local
 tracking
 =
 hasOsmRelationId
 and
 ''
 or
 '<!--[[Category:Infobox mapframe without OSM relation ID on Wikidata]]-->'

	return
 mapframe
 ..
 tracking

end


return
 p