Jump to content
Wikipedia The Free Encyclopedia

Module:Cyclone map

From Wikipedia, the free encyclopedia
Module documentation[view] [edit] [history] [purge]

Implements {{Cyclone map }}

The above documentation is transcluded from Module:Cyclone map/doc. (edit | history)
Editors can experiment in this module's sandbox (create | mirror) and testcases (create) pages.
Subpages of this module.

 require('strict')
 localfn=require('Module:Formatnum')
 --local mm = require('Module:Math')
 localDate=require('Module:Date')._Date
 localp={}

 -- N/A but possible option: keep cyclone data in subpage data files
 --local stormDatabase = require( "Module:Cyclone map/data" ) -- configuration module

 -- main function callable in Wikipedia via the #invoke command.
 p.main=function(frame)

 localstr=p.getMapframeString()
 returnframe:preprocess(str)-- the mapframe needs to be preprocessed!!!!!
 end-- End the function.

 --[[ function to construct mapframe string
  sets up the <mapframe> tags
  <mapframe width= height= latitude= longitude= zoom= >
  MAPDATA in form of geojson constucted with function getGeoJSON()
  </mapframe>
 --]]
 p.getMapframeString=function(frame)

 --get mapframe arguments from calling templates
 localparent=mw.getCurrentFrame():getParent()

 -- get JSON data for features to display
 localmapData=p.getGeoJSON()

 localmapString=""

 --mapString = '<mapframe text="London football stadia" width=800 height=650 align=left zoom=11 latitude=51.530 longitude=-0.16 >'
 ifmapData~=""then

 mapString='<mapframe'
 ifparent.args['frameless']then-- don't and text as this overrides frameless parameter
 mapString=mapString..' frameless'
 else
 mapString=mapString..' text="'..(parent.args['text']or"")..'"'
 end

 -- set width and height using noth parameters, one parameter assuming 4:3 aspect ratio, or defaults
 localaspect=4/3
 localwidth=parent.args['width']--or "220"
 localheight=parent.args['height']or(widthor220)/aspect--or "165"
 width=widthorheight*aspect-- if width null, use height

 localalign=parent.args['align']or"right"

 mapString=mapString..' width='..math.floor(width)..' height='..math.floor(height)..' align='..align

 localzoom=parent.args['zoom']--or "0" -- no longer set defaults (mapframe does automatically)
 locallatitude=parent.args['latitude']--or "0"
 locallongitude=parent.args['longitude']--or "0"

 --set if values, otherwise allow mapframe to set automatically (TODO check if longitude and latitude are independent)
 ifzoomthenmapString=mapString..' zoom='..zoomend
 iflatitudethenmapString=mapString..' latitude='..latitudeend
 iflongitudethenmapString=mapString..' longitude='..longitudeend

 mapString=mapString..' >'..mapData..'</mapframe>'-- add data and close tag
 else
 mapString="No data for map"
 end

 returnmapString

 end-- End the function.

 --[[ function getGeoJSON() - to construct JSON format data for markers on map.
  The information for each marker (coordinate, description and image for popup, etc) 
  can be set in several ways (in order of priority):
  (1) using arguments in the template (|imageN=, |descriptionN=)
  (2) from values in the data module (i.e. Module:Football map/data) [not function for cyclone map]
  (3) from Wikidata
 ]]
 p.getGeoJSON=function(frame)

 -- now we need to iterate through the stadiumN parameters and get data for the feature markers
 localmaxNumber=200-- maximum number looked for
 localmapData=""
 localcycloneName=nil
 localcycloneID=nil


 --get mapframe arguments from calling templates
 localparent=mw.getCurrentFrame():getParent()

 --[[There are three ways of getting data about the stadium features
  	(1) from a list in the module subpages (n/a but possible alternative)
  	(2) from wikidata 
  	(3) from the parameters in the template (these always override other)
  	The parameters useWikiData, useModule restrict use of source
  --]]
 localuseWikidata=true
 localuseModule=false

 ifparent.args['wikidata']thenuseWikidata=true;useModule=falseend-- use wikidata or template data (no module data)
 ifparent.args['moduledata']thenuseModule=true;useWikidata=falseend-- use module of template data (no wikidata)
 ifparent.args['templatedata']thenuseModule=false;useWikidata=falseend-- only use template data

 -- default parameters for marker color, size and symbol, etc (i.e. those without index suffix)
 localstrokeColor=parent.args['stroke']or"#000000"
 ifstrokeColor=="auto"thenstrokeColor=nilend-- if using auto color

 -- the default properties are set by the unindexed parameters and affect all objects
 localdefaultProperties={
 ['marker-color']=parent.args['marker-color'],-- default to nil --or "#0050d0",
 ['marker-size']=parent.args['marker-size']or"small",
 ['marker-symbol']=parent.args['marker-symbol']or"circle",
 ['stroke']=strokeColor,--parent.args['stroke'] or "#000000", -- nil default causes autocolor path; a value overrides autocolor
 ['stroke-width']=parent.args['stroke-width']or1,
 ['stroke-opacity']=parent.args['stroke-opacity']or1.0,

 -- these are for shapes drawn with polygon instead of the marker symbol
 ['symbol-stroke']=parent.args['symbol-stroke'],-- nil default causes autocolor path; a value overrides autocolor
 ['symbol-fill']=parent.args['symbol-fill'],-- nil default causes autocolor path; 
 ['symbol-shape']=parent.args['symbol-shape']or"circle",
 ['symbol-size']=parent.args['symbol-size']or0.4,
 ['symbol-stroke-width']=parent.args['symbol-stroke-width']or0,
 ['symbol-stroke-opacity']=parent.args['symbol-stroke-opacity']or1.0,
 ['symbol-fill-opacity']=parent.args['symbol-fill-opacity']or1.0
 }

 localindex=0
 whileindex<maxNumberdo

 index=index+1
 localcycloneID=""

 -- (1) get cyclone name 
 cycloneID=parent.args['id'..tostring(index)]
 cycloneName=parent.args['name'..tostring(index)]

 ifcycloneNameandnotcycloneIDthen
 cycloneID=mw.wikibase.getEntityIdForTitle(cycloneName)
 end
 ifcycloneIDandnotcycloneNamethen
 cycloneName=mw.wikibase.getLabel(cycloneID)
 --TODO get associated Wikipedia page for linking
 end
 -- if we have a valid cyclone id (note:Lua has no continue statement)
 ifcycloneIDthen

 localfeature={name="",alias="",latitude=0,longitude=0,description="",image="",valid=false,path={}}
 localvalidFeatureData=true-- assume now 

 -- (2) get feature parameters from module (n/a) or wikidata or both

 --[[if useModule then	-- get feature parameters from module data stadium list
 	 feature = p.getModuleData(frame, stadiumName)
 	 end]]

 ifuseWikidataandcycloneIDthen--and feature['name'] == "" then -- get feature parameters from wikidata
 feature=p.getDataFromWikiData(cycloneName,cycloneID)
 ifnotfeature['valid']then-- no valid coordinates
 validFeatureData=false
 mw.addWarning("No valid coordinates found for "..cycloneName.." ("..cycloneID..")")
 end
 end

 ----------------------------------------------------
 -- (3) data from template parameters will override those obtainied from a module table or wikidata
 localtemplateArgs={
 latitude=parent.args['latitude'..tostring(index)],
 longitude=parent.args['longitude'..tostring(index)],
 description=parent.args['description'..tostring(index)],
 image=parent.args['image'..tostring(index)]
 }

 iftemplateArgs['latitude']andtemplateArgs['longitude']then-- if both explicitly set by template
 feature['latitude']=templateArgs['latitude']
 feature['longitude']=templateArgs['longitude']
 feature['name']=cycloneName-- as we have valid coordinates
 validFeatureData=true
 end

 -- use specified description and image if provided
 iftemplateArgs['description']then
 feature['description']=templateArgs['description']
 end
 iftemplateArgs['image']then
 feature['image']=templateArgs['image']-- priority for image from template argument
 end
 iffeature['image']~=""thenfeature['image']='[['..feature['image']..']]'end

 -- wikilink - use redirect if alias
 iffeature['alias']~=''then
 feature['name']='[['..feature['name']..'|'..feature['alias']..']]'
 else
 feature['name']='[['..feature['name']..']]'
 end


 iffeature['image']~=""then
 feature['description']=feature['image']..feature['description']
 end

 --check if current feature marker has specified color, size or symbol
 localstrokeColor=parent.args['stroke'..tostring(index)]ordefaultProperties['stroke']
 ifstrokeColor=="auto"thenstrokeColor=nilend-- if using auto color

 -- the feature properties are set by the indexed parameters or defaults (see above)
 localfeatureProperties={
 ['marker-color']=parent.args['marker-color'..tostring(index)]ordefaultProperties['marker-color'],
 ['marker-symbol']=parent.args['marker-symbol'..tostring(index)]ordefaultProperties['marker-symbol'],
 ['marker-size']=parent.args['marker-size'..tostring(index)]ordefaultProperties['marker-size'],
 ['stroke']=strokeColor,--parent.args['stroke'..tostring(index)] or defaultProperties['stroke'],	
 ['stroke-width']=parent.args['stroke-width'..tostring(index)]ordefaultProperties['stroke-width'],
 ['stroke-opacity']=parent.args['stroke-opacity'..tostring(index)]ordefaultProperties['stroke-opacity'],

 -- these are for shapes drawn with polygon instead of the marker symbol
 ['symbol-stroke']=parent.args['symbol-stroke'..tostring(index)]ordefaultProperties['symbol-stroke'],-- nil default causes autocolor path; a value overrides autocolor
 ['symbol-fill']=parent.args['symbol-fill'..tostring(index)]ordefaultProperties['symbol-fill'],
 ['symbol-shape']=parent.args['symbol-shape'..tostring(index)]ordefaultProperties['symbol-shape'],
 ['symbol-size']=parent.args['symbol-size'..tostring(index)]ordefaultProperties['symbol-size'],
 ['symbol-stroke-width']=parent.args['symbol-stroke-width'..tostring(index)]ordefaultProperties['symbol-stroke-width'],
 ['symbol-stroke-opacity']=parent.args['symbol-stroke-opacity'..tostring(index)]ordefaultProperties['symbol-stroke-opacity'],
 ['symbol-fill-opacity']=parent.args['symbol-fill-opacity'..tostring(index)]ordefaultProperties['symbol-fill-opacity']
 }

 --(4) construct the json for the features (if we have a storm with valid coordinates)
 ifvalidFeatureDatathen

 localfeatureData=""

 iffeature.path[1]then-- add path if multiple coordinates
 featureData=p.addPathFeatureCollection(feature,featureProperties)
 else-- else show single marker
 -- make sure a marker color is set (if not set by template or not autocoloring storm path)
 -- note the default colour is left as nil for the auto coloring of paths by storm type
 -- and that this can be overriden with a value, but might be nil here
 localmarkerColor=featureProperties['marker-color']or"#0050d0"

 featureData='{ "type": "Feature", '
 ..' "geometry": { "type": "Point", "coordinates": ['
 ..feature['longitude']..','
 ..feature['latitude']
 ..'] }, '
 ..' "properties": { "title": "'..feature['name']..'", '
 ..'"description": "'..feature['description']..'", '
 ..'"marker-symbol": "'..featureProperties['marker-symbol']..'", '
 ..'"marker-size": "'..featureProperties['marker-size']..'", '
 ..'"marker-color": "'..markerColor..'" } '
 ..' } '

 end

 ifindex>1andmapData~=""then
 mapData=mapData..','..featureData
 else
 mapData=featureData
 end
 else
 --mapData = '{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [-0.066417, 51.60475] }, "properties": { "title": "White Hart Lane (default)", "description": "Stadium of Tottenham Hotspur F.C.", "marker-symbol": "soccer", "marker-size": "large", "marker-color": "0050d0" } } '
 mw.addWarning("No valid information found for "..cycloneName.." ("..cycloneID..")")
 end-- if valid parameters


 end-- end if if cycloneID
 end-- end while loop

 --[[ (5) check for external data (geoshape) 
 	 TODO add more than index=1 and generalise for any json feature
 	 --]]
 localgeoshape=parent.args['geoshape'..tostring(1)]or""
 ifgeoshape~=""then
 mapData=mapData..','..geoshape-- assumes at least one stadium
 end

 -- add outer bracket to json if more than one element
 ifindex>1then
 mapData='['..mapData..']'
 --mapData = ' {"type": "FeatureCollection", "features": [' .. mapData .. ']}' -- is there an advantage using this?
 end

 returnmapData

 end-- End the function.

 --[[ functions adding path to cyclone item 
 		p.addPathFeatureCollection() -- adds markers/symbols and lines for path of storm (cordinates from wikidata)
 		p.addShapeFeature() -- returns geoJson for the custom symbol
 		p.getPolygonCoordinates() -- returns coordinate set for the custom symbol (loop for diffent shapes)
 		p.calculatePolygonCoordinates() -- calculates the coordinates for the specified shape
 		p.getCycloneColor() -- sets color of symbols/lines based on storm type (from wikidata)

 --]]
 p.addPathFeatureCollection=function(feature,featureProperties)

 ifnotfeature.path[1]thenreturn""end-- shouldn't be necessary now

 localmode=mw.getCurrentFrame():getParent().args['mode']or"default"



 localfeatureCollection=""
 localsep=""
 locali=1
 table.sort(feature.path,function(a,b)
 if(a.timeStamp<b.timeStamp)then--- primary sort on timeStamp
 returntrue
 else
 returnfalse
 end
 end)

 fori,vinpairs(feature.path)do

 localautoColor=p.getCycloneColor(feature.path[i]['cycloneType'],featureProperties)
 localmarkerColor=featureProperties['marker-color']orautoColor
 localstrokeColor=featureProperties['stroke']orautoColor


 locallongitude=feature.path[i]['longitude']
 locallatitude=feature.path[i]['latitude']

 -- add a lines between the points (current point to the next point, if there is one)
 locallineFeature=""
 iffeature.path[i+1]then
 locallongitude2=feature.path[i+1]['longitude']
 locallatitude2=feature.path[i+1]['latitude']

 lineFeature='{ "type": "Feature", '
 ..' "geometry": { "type": "LineString", "coordinates": ['
 ..'['..longitude..','..latitude..'],'
 ..'['..longitude2..','..latitude2..']'
 ..'] }, '
 ..' "properties": { "stroke": "'..strokeColor..'" , '
 ..' "stroke-width": '..featureProperties['stroke-width']..' , '
 ..' "stroke-opacity": '..featureProperties['stroke-opacity']
 ..' } '
 ..' } '
 featureCollection=featureCollection..sep..lineFeature
 sep=","
 end

 --[[ place mapframe markers and custom symbols on each object
 		 mode="marker": use mapframe markers for mark storm objects
 		 mode="test": use marker on first point of path and linePoint symbol
 		 default: use custom polygons to mark storm objects
 		 ]]
 ifmode=="marker"or(mode=="test"andi==1)then


 localpointFeature='{ "type": "Feature", '
 ..' "geometry": { "type": "Point", "coordinates": ['..longitude..','..latitude..'] }, '
 ..' "properties": { "title": "'..feature['name']..'", '
 ..'"description": "'..feature['description']..'<br>Type: '..feature.path[i]['cycloneType']..'", '
 ..'"marker-symbol": "'..featureProperties['marker-symbol']..'", '
 ..'"marker-size": "'..featureProperties['marker-size']..'", '
 ..'"marker-color": "'..markerColor..'" } '
 ..' } '
 featureCollection=featureCollection..sep..pointFeature
 sep=","

 elseifmode=="test"then-- short lines (test) to mark with objects

 localdateString=" 2020-06"
 iffeature.path[i]['timeStamp']then
 localformattedDate=Date(feature.path[i]['timeStamp']):text("dmy hm")
 dateString='<br/>date and time: '..formattedDate--tostring( feature.path[i]['timeStamp'] )
 end
 localdescription='<div>latitude: '..tostring(latitude)
 ..'<br/>longitude: '..tostring(longitude)
 ..dateString
 ..'</div>'

 localcircleFeature='{ "type": "Feature", '
 ..' "geometry": { "type": "LineString", "coordinates": ['
 ..'['..longitude..','..latitude..'],'
 ..'['..(longitude)..','..(latitude)..']'
 ..'] }, '
 ..' "properties": { "stroke": "'..markerColor..'" , '
 ..' "stroke-width": 10, '-- TODO change size based on marker size
 ..' "description": "'..description..'"'
 ..' } '
 ..' } '
 featureCollection=featureCollection..sep..circleFeature
 sep=","

 else-- use polygons (default if not marker) to mark with objects

 featureCollection=featureCollection..sep..p.addShapeFeature(i,feature,featureProperties)
 sep=","
 end

 i=i+1-- increment for next point in storm path
 end-- while/for in pairs

 ifmw.getCurrentFrame():getParent().args['mode']=="test3"then
 featureCollection=
 '{"type": "FeatureCollection", "features": [ {"type": "Feature","properties": {"marker-color": "#bbccff", "marker-symbol": "-number"}, "geometry": { "type": "Point", "coordinates": [80.298888888889,6.3316666666667]}}, {"type": "Feature","properties": {"marker-color": "#bbccff", "marker-symbol": "-number"}, "geometry": { "type": "Point", "coordinates": [80.263888888889,6.6644444444444]}}, {"type": "Feature","properties": {"marker-color": "#bbccff", "marker-symbol": "-number"}, "geometry": { "type": "Point", "coordinates": [80.434444444444,7.1883333333333]}}, {"type": "Feature","properties": {"marker-color": "#bbccff", "marker-symbol": "-number"}, "geometry": { "type": "Point", "coordinates": [80.656111111111,8.1086111111111]}}, {"type": "Feature","properties": {"marker-color": "#bbccff", "marker-symbol": "-number"}, "geometry": { "type": "Point", "coordinates": [80.9025,8.2961111111111]}}, {"type":"Feature", "properties": { "stroke":"#D3D3D3", "stroke-opacity":0.7, "stroke-width":50}, "geometry": {"type":"LineString", "coordinates": [[80.298888888889,6.3316666666667],[80.263888888889,6.6644444444444],[80.434444444444,7.1883333333333],[80.656111111111,8.1086111111111],[80.9025,8.2961111111111]]}} ]}'
 end
 --return sep .. featureCollection
 returnfeatureCollection
 end
 --[[ function p.addShapeFeature(i, feature, featureProperties)

 		function adding shape features using polygon type: square, triangle, stars, etc 
 ]]
 p.addShapeFeature=function(i,feature,featureProperties)

 localsize=featureProperties['symbol-size']
 localshape=featureProperties['symbol-shape']-- symbol for tropical cyclone
 iffeature.path[i]['cycloneType2']=='extratropical cyclone'then
 shape='triangle'-- symbol for extratropical cyclone (Q1063457) 
 elseiffeature.path[i]['cycloneType2']=='subtropical cyclone'then
 shape='square'-- symbol for subtropical cyclone (Q2331851)
 end
 localautoColor=p.getCycloneColor(feature.path[i]['cycloneType'],featureProperties)
 --local markerColor = featureProperties['symbol-color'] or autoColor
 localstrokeColor=featureProperties['symbol-stroke']orautoColor
 localfillColor=featureProperties['symbol-fill']orautoColor

 locallongitude=feature.path[i]['longitude']
 locallatitude=feature.path[i]['latitude']

 localdescription='<div style=\\"text-align:left;\\"> '

 -- .. '<br/>date: ' .. mw.language.getContentLanguage():formatDate('d F Y', feature.path[i]['timeStamp']) 
 ..'<br/>date: '..Date(feature.path[i]['timeStamp']):text("dmy")-- :text("dmy hm") 
 ..'<br/>type: '..tostring(feature.path[i]['cycloneType'])
 ..'<br/>longitude: '..fn.formatNum(longitude,"en",6)
 ..'<br/>latitude: '..fn.formatNum(latitude,"en",6)
 ..'</div>'

 localshapeFeature=""
 --shape="circle"
 shapeFeature=' { "type": "Feature", '
 ..' "geometry": { "type": "Polygon", '
 ..' "coordinates": [ '..p.getPolygonCoordinates(shape,size,latitude,longitude)..' ] '
 ..' }, '
 ..' "properties": { "stroke": "'..strokeColor..'" , '
 ..' "fill": "'..fillColor..'" ,'
 ..' "fill-opacity": 1, '
 ..' "stroke-width": '..featureProperties['symbol-stroke-width']..','
 ..' "description": "'..description..'"'
 ..' } '
 ..' } '
 -- if shape==cyclone, a circle shape will have been drawn; now add the tails
 ifshape=="cyclone"then-- superimpose a second shape
 localshape2="cyclone_tails"
 shapeFeature=shapeFeature..', '
 ..'{ "type": "Feature", '
 ..' "geometry": { "type": "Polygon", '
 ..' "coordinates": [ '..p.getPolygonCoordinates(shape2,size,latitude,longitude)..' ] '
 ..' }, '
 ..' "properties": { "stroke": "'..strokeColor..'" , '
 ..' "fill": "'..fillColor..'" ,'
 ..' "fill-opacity": 1, '
 ..' "stroke-width": '..0..','
 ..' "description": "'..description..'"'
 ..' } '
 ..' } '

 end

 returnshapeFeature
 end
 p.getPolygonCoordinates=function(shape,size,latitude,longitude)

 -- shape = "circle"
 -- shape ="spiral"

 localcoordinates=""
 ifshape=="square"then
 coordinates='	[ '
 ..'['..(longitude+size)..','..(latitude+size)..'],'
 ..'['..(longitude+size)..','..(latitude-size)..'],'
 ..'['..(longitude-size)..','..(latitude-size)..'],'
 ..'['..(longitude-size)..','..(latitude+size)..'],'
 ..'['..(longitude+size)..','..(latitude+size)..']'
 ..'] '
 elseifshape=="triangle2"then
 coordinates='	[ '
 ..'['..(longitude)..','..(latitude+size)..'],'
 ..'['..(longitude+size)..','..(latitude-size)..'],'
 ..'['..(longitude-size)..','..(latitude-size)..'],'
 ..'['..(longitude)..','..(latitude+size)..']'
 ..'] '
 elseifshape=="inverse-triangle"then
 coordinates='	[ '
 ..'['..(longitude)..','..(latitude-size)..'],'
 ..'['..(longitude+size)..','..(latitude+size)..'],'
 ..'['..(longitude-size)..','..(latitude+size)..'],'
 ..'['..(longitude)..','..(latitude-size)..']'
 ..'] '
 elseifshape=="star2"then
 --size = size * 5
 coordinates=' [ '
 ..'['..longitude..','..latitude+(size*1.2)..'],'-- top point
 ..'['..longitude+(size*0.2)..','..latitude+(size*0.2)..'],'
 ..'['..longitude+(size*1.2)..','..latitude+(size*0.4)..'],'-- 2pm point
 ..'['..longitude+(size*0.3)..','..latitude-(size*0.1)..'],'
 ..'['..longitude+(size)..','..latitude-(size)..'],'-- 5pm point
 ..'['..longitude..','..latitude-(size*0.3)..'],'-- 6pm (innner)
 ..'['..longitude-(size)..','..latitude-(size)..'],'-- 7pm point
 ..'['..longitude-(size*0.3)..','..latitude-(size*0.1)..'],'
 ..'['..longitude-(size*1.2)..','..latitude+(size*0.4)..'],'-- 10pm point
 ..'['..longitude-(size*0.2)..','..latitude+(size*0.2)..'],'
 ..'['..longitude..','..latitude+(size*1.2)..']'-- top point (close)
 ..'] '

 elseifshape=="circle2"then

 localradius=size
 coordinates=coordinates..' [ '
 forangle=0,360,3do
 ifangle>0thencoordinates=coordinates..','end
 coordinates=coordinates..'['..longitude+(radius*math.cos(math.rad(angle)))..','
 ..latitude+(radius*math.sin(math.rad(angle)))
 ..']'
 end
 coordinates=coordinates..'] '

 elseifshape=="cyclone_tails"then

 localradius=size*2
 -- add tail at 3 o'clock
 coordinates=coordinates..' [ '
 forangle=0,60,3do
 ifangle>0thencoordinates=coordinates..','end
 coordinates=coordinates..'['..longitude-size+(radius*math.cos(math.rad(angle)))..','
 ..latitude+(radius*math.sin(math.rad(angle)))
 ..']'
 end
 coordinates=coordinates..'] '

 -- add tail at 9 o'clock
 coordinates=coordinates..', [ '
 forangle=180,240,3do
 ifangle>180thencoordinates=coordinates..','end
 coordinates=coordinates..'['..longitude+size+(radius*math.cos(math.rad(angle)))..','
 ..latitude+(radius*math.sin(math.rad(angle)))
 ..']'
 end
 coordinates=coordinates..'] '

 -- add tail at 6 o'clock
 coordinates=coordinates..', [ '
 forangle=270,330,3do
 ifangle>270thencoordinates=coordinates..','end
 coordinates=coordinates..'['..longitude+(radius*math.cos(math.rad(angle)))..','
 ..latitude+size+(radius*math.sin(math.rad(angle)))
 ..']'
 end
 coordinates=coordinates..'] '

 -- add tail at 6 o'clock
 coordinates=coordinates..', [ '
 forangle=90,150,3do
 ifangle>90thencoordinates=coordinates..','end
 coordinates=coordinates..'['..longitude+(radius*math.cos(math.rad(angle)))..','
 ..latitude-size+(radius*math.sin(math.rad(angle)))
 ..']'
 end
 coordinates=coordinates..'] '

 --[[ for adding circle
  local radius = size
 		coordinates = coordinates .. ', [ '
 		for angle = 0, 360, 3 do
  	if angle > 0 then coordinates = coordinates .. ',' end
  	coordinates = coordinates .. '[' .. longitude+(radius*math.cos(math.rad(angle))) .. ',' 
  	 .. latitude +(radius*math.sin(math.rad(angle))) 
  	 .. ']' 
  end
  coordinates = coordinates .. '] ' 
  --]]
 elseifshape=="spiral"then

 coordinates=' [ '
 localradius=size*0.01
 forangle=0,360*4,4do
 radius=radius+size*0.01
 ifangle>0thencoordinates=coordinates..','end
 coordinates=coordinates..'['..longitude+(radius*math.cos(math.rad(angle)))..','
 ..latitude+(radius*math.sin(math.rad(angle)))
 ..']'

 end
 coordinates=coordinates..'] '
 elseifshape=="circle"orshape=="cyclone"then-- circle as 120 sided polygon
 returnp.calculatePolygonCoordinates(120,1,size,latitude,longitude)
 elseifshape=="triangle"then
 returnp.calculatePolygonCoordinates(3,1,size,latitude,longitude)
 elseifshape=="diamond"then
 returnp.calculatePolygonCoordinates(4,1,size,latitude,longitude)
 elseifshape=="hexagon"then
 returnp.calculatePolygonCoordinates(6,1,size,latitude,longitude)
 elseifshape=="octagon"then
 returnp.calculatePolygonCoordinates(8,1,size,latitude,longitude)
 elseifshape=="star4"then
 returnp.calculatePolygonCoordinates(8,3,size,latitude,longitude)
 elseifshape=="star5"then
 returnp.calculatePolygonCoordinates(10,3,size,latitude,longitude)
 elseifshape=="star8"then
 returnp.calculatePolygonCoordinates(16,3,size,latitude,longitude)
 elseifshape=="star12"then
 returnp.calculatePolygonCoordinates(24,3,size,latitude,longitude)
 elseifshape=="star"then
 returnp.calculatePolygonCoordinates(10,2,size,latitude,longitude)
 end

 returncoordinates
 end
 --[[ p.calculatePolygonCoordinates(sides, ratio, size, latitude, longitude) 

  calculates coordinates for polygons or stars
  a star is a polygon with alternate points with different radii (determined by ratio)

  sides: number of sides on polygon
  for a star this is twice the number of points of the star
  ratio: ratio of inner and outer radii for a star (a higher number makes a more pointy star)
  use 1 for a simple polygon 
  size: the outer radius of the a circle surrounding the polygon
  latitude and longitude: self explanatory
 ]]
 p.calculatePolygonCoordinates=function(sides,ratio,size,latitude,longitude)

 localcoordinates=' [ '

 localouter=true
 localradius=size
 forangle=0,360,360/sidesdo
 ifangle>0thencoordinates=coordinates..','end-- important for geojson structure (unlike Lua)

 ifradius~=1then-- if a star
 ifouterthenradius=sizeelseradius=size/ratioend-- alternate inner and outer radius
 outer=notouter
 end

 coordinates=coordinates..'['..longitude+(radius*math.sin(math.rad(angle)))..','
 ..latitude+(radius*math.cos(math.rad(angle)))
 ..']'
 end
 returncoordinates..'] '

 end
 --[[ p.getCycloneColor=function(cycloneType, featureProperties)

  sets color of symbols/lines based on storm type (from wikidata)
 ]]
 p.getCycloneColor=function(cycloneType,featureProperties)

 --[[ codors from "Tropical cyclone scales" article
  	#80ccff		Depression, Zone of Disturbed Weather, Tropical Disturbance (?) 	
  	#5ebaff		Tropical Depression, Deep Depression 
  	 Tropical Disturbance (?), Tropical Depression, Tropical Low
  	#00faf4 	tropical storm, moderate tropical storm, cyclonic storm, Category 1 Tropical Cyclone
  	#ccffff 	severe cyclonic storm, severe tropical storm, Category 1 Hurricane 
  	#ffffcc		Very Severe Cyclonic Storm 	Tropical Cyclone 
 	 #fdaf9a		Typhoon
 	 #ffc140		Very Strong Typhoon, Extremely Severe Cyclonic Storm, Intense Tropical Cyclone 	Category 4
 			#ff6060 	Violent Typhoon, Category 5 Severe Tropical Cyclone, Super Typhoon, 
 						Super Cyclonic Storm, Very Intense Tropical Cyclone, Category 5 Major Hurricane 

 	]]
 localcolor="#000000"
 cycloneType=string.lower(cycloneType)
 ifcycloneType=="depression"orcycloneType=="zone of disturbed weather"orcycloneType=="Tropical disturbance"
 thencolor="#80ccff"
 elseifcycloneType=="tropical depression"orcycloneType=="deep depression"orcycloneType=="tropical Depression"
 orcycloneType=="tropical low"
 thencolor="#5ebaff"
 elseifcycloneType=="cyclonic storm"orcycloneType=="tropical storm"orcycloneType=="moderate tropical storm"
 orcycloneType=="category 1 tropical cyclone"
 thencolor="#00faf4"
 elseifcycloneType=="severe cyclonic storm"orcycloneType=="severe tropical storm"orcycloneType=="category 1 hurricane"
 thencolor="#ccffff"
 elseifcycloneType=="very severe cyclonic storm"orcycloneType=="tropical cyclone"
 thencolor="#ffffcc"
 elseifcycloneType=="typhoon"
 thencolor="#fdaf9a"
 elseifcycloneType=="very strong typhoon"orcycloneType=="extremely severe cyclonic storm"orcycloneType=="intense tropical cyclone"
 orcycloneType=="category 4 severe tropical storm"
 thencolor="#ffc140"
 elseifcycloneType=="violent typhoon"orcycloneType=="category 5 severe tropical cyclone"orcycloneType=="super typhoon"
 orcycloneType=="super cyclonic storm"orcycloneType=="very intense tropical cyclone"
 orcycloneType=="category 5 major hurricane"
 thencolor="#ff6060"





 end
 returncolor
 end



 --[[-------------------------------Retrieve information from wikidata-------------------------

 	statements of interest (datavalue element)
 		item = mw.wikibase.getEntity(WikidataId), 
 		statements = item:getBestStatements('P625')[1]
  	"claims":
 			P625 coordinate location (value.longitude/latitude)
 			 "P625":[{ "mainsnake": { ... "datavalue": { "value": {"latitude": 51.4, "longitude": -0.19] ...
 			 statements.mainsnak.datavalue.value.latitude
 			P18 image on commons (value, "File:value")
 		 	 "P18":[{ "mainsnake": { ... "datavalue": { "value": "Stamford Bridge Clear Skies.JPG"
 			P1566 GeoNames ID (value, "geonames.org/value")
 			P31 (instance of) Q483110 (stadium)
 			 "P18":[{ "mainsnake": { ... "datavalue": { "value": { "id": "Q483110"
 			 however also sports venue, olympic stadium, association football stadium
 			P159 headquarters location (for football club) 
 			 e..g. London
 			 qualifier property: coordinates(P625)
  page title on enwiki
  	mw.wikibase.getSitelink( itemId ) - gets local version
  	"sitelink": { "enwiki": { "title": "Hurricane Katrina" }
  other properties of possible interest:
  	P276 location
 		P17 country
 		P580 start time
 		P582 end time
 		P1120 number of deaths
 		P2630 cost of damage
 		P2532 lowest atmospheric pressure
 		P2895 maximum sustained winds

 --]]
 p.getDataFromWikiData=function(cycloneName,cycloneID)

 localwd={name="",latitude="",longitude="",description="",image="",alias="",type="",valid=false,path={}}

 -- 	get wikidata id corresponding to wikipedia stadium page
 --local WikidataId = mw.wikibase.getEntityIdForTitle(cycloneName)
 localWikidataId=cycloneID
 ifnotcycloneNamethencycloneName="unnamed"end--TODO get the name

 ifWikidataIdandmw.wikibase.isValidEntityId(WikidataId)then-- valid id

 localitem=mw.wikibase.getEntity(WikidataId)
 ifnotitemthenreturnwdend-- will test for wiki

 localenwikiTitle=mw.wikibase.getSitelink(WikidataId)-- name of local Wikipedia page
 localwikidataTitle=mw.wikibase.getLabel(WikidataId)-- name of Wikidata page
 ifenwikiTitleandwikidataTitleandenwikiTitle~=wikidataTitlethen
 wd['alias']=wikidataTitle
 wd['name']=cycloneName
 else
 wd['name']=cycloneName
 end

 -- get storm type P31 instance of 
 localstatements=item:getBestStatements('P31')--coordinate location 
 ifstatementsandstatements[2]then-- check cordinates available
 localtype=statements[2].mainsnak.datavalue.value.idor""
 wd['type']=mw.wikibase.getLabel(type)
 end

 -- get coordinates
 localstatements=item:getBestStatements('P625')[1]--coordinate location 
 ifstatements~=nilthen-- check cordinates available
 localcoord=statements.mainsnak.datavalue.value
 iftype(coord.latitude)=='number'andtype(coord.longitude)=='number'then
 -- add coordinate data from wikidata for unindexed stadium
 wd['latitude']=coord.latitude
 wd['longitude']=coord.longitude
 wd['valid']=true

 -- if we have a path of coordinates
 ifitem:getBestStatements('P625')[2]then-- TODO make sure ordinal number
 locali=1

 whileitem:getBestStatements('P625')[i]do
 -- get coordinates
 localstatements=item:getBestStatements('P625')[i]--coordinate location 
 ifstatements~=nilthen-- check cordinates available
 localcoord=statements.mainsnak.datavalue.value
 iftype(coord.latitude)=='number'andtype(coord.longitude)=='number'then
 -- add coordinate data from wikidata for path
 wd.path[i]={}
 wd.path[i].latitude=coord.latitude
 wd.path[i].longitude=coord.longitude

 -- get series ordinal as index (now removed so set to i)
 -- TODO sort based on point in time, i.e. wd.path(i).timeStamp 
 wd.path[i].index=i-- statements.qualifiers['P1545'][1]['datavalue']['value'] -- P1545 = series ordinal {a number]

 -- get storm type using instance of (P31)
 localcycloneType=statements.qualifiers['P31'][1]['datavalue']['value']['id']-- P31 = instance of [cyclone type]
 ifcycloneTypethenwd.path[i].cycloneType=mw.wikibase.getLabel(cycloneType)end
 -- get storm type using instance of (P31)
 ifstatements.qualifiers['P31'][2]then
 cycloneType=statements.qualifiers['P31'][2]['datavalue']['value']['id']-- P31 = instance of [cyclone type]
 ifcycloneTypethenwd.path[i].cycloneType2=mw.wikibase.getLabel(cycloneType)end
 end

 --get point in time (P585) qualifier
 localtimeStamp=statements.qualifiers['P585'][1]['datavalue']['value']['time']
 iftimeStampthenwd.path[i].timeStamp=timeStampend

 end
 end
 i=i+1
 end-- end while loop
 end


 end
 end-- end if coordinate statements


 --get image
 statements=item:getBestStatements('P18')[1]--image
 ifstatements~=nilthen
 wd['image']='File:'..statements.mainsnak.datavalue.value
 end


 end

 returnwd

 end


 --[[------------------------------------------------------------------------------
 	This function gets data from a module subpage (not implemented)
 --------------------------------------------------------------------------------]]
 p.getModuleData=function(frame,stormName)

 localfeature={}
 feature['name']=""
 --feature['data'] = ""
 feature['alias']=""
 feature['description']=""
 feature['image']=""

 -- check the module storm list for name match
 -- set feature parameters from the module data
 for_,paramsinpairs(stormDatabase.storm)do
 ifstormName==params[1]then-- if we have a match from the list
 feature['name']=params[1]
 feature['latitude']=params[2]
 feature['longitude']=params[3]
 feature['alias']=params[4]
 feature['description']=params[5]
 feature['image']=params[6]
 break
 end
 end
 returnfeature
 end

 -- All modules end by returning the variable containing its functions to Wikipedia.
 returnp

AltStyle によって変換されたページ (->オリジナル) /