Module:Adjacent stations/sandbox

From Wikimedia Commons, the free media repository
Jump to navigation Jump to search
Lua

CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules


North / westbound ChâteletView and edit data on Wikidata South / eastbound
Louvre - Rivoli
towards La Défense
Paris Métro Line 1[1]
Q679ß before ― Q684ß after
Hôtel de Ville
towards Château de Vincennes
Les Halles
towards Porte de Clignancourt
Paris Métro Line 4[2]
Q659ß before ― Q667ß after
Cité
towards Bagneux–Lucie Aubrac
Pont Neuf
towards La Courneuve - 8 Mai 1945
Paris Métro Line 7[3]
Q659ß of after <=> Q667ß of before
Pont Marie
towards Villejuif - Louis Aragon and Mairie d'Ivry
Paris Métro Line 11[4]
terminus
ß of after <=> Q684ß of before
Hôtel de Ville
towards Mairie des Lilas
Pyramides
towards Mairie de Saint-Ouen
Paris Métro Line 14[5]
ß before ― ß after
Gare de Lyon
towards Olympiades
North / westbound GraskruidView and edit data on Wikidata South / eastbound
Romeynshof
towards Binnenhof
Line A[6]
Q659ß before ― Q679ß after
Alexander
towards Vlaardingen West
Hesseplaats
towards Nesselande
Line B[7]
Q684ß of after <=> Q679ß of before
Alexander
towards Hoek van Holland Strand metro station
North / westbound RockwellView and edit data on Wikidata South / eastbound
Francisco
towards Kimball station
Brown Line[8]
ß of after <=> ß of before
Western
towards Kimball station
via Clark/Lake
North / westbound Kennington tube stationView and edit data on Wikidata South / eastbound
Elephant & Castle tube station
towards Edgware tube station, High Barnet tube station and Mill Hill East tube station
via Bank and Monument stations
Northern line[9]
ß before ― ß after
Oval tube station
towards Morden tube station
Waterloo tube station
towards Edgware tube station, Mill Hill East tube station and High Barnet tube station
via Charing Cross tube station
Northern line
ß before ― ß after
Nine Elms tube station
towards Battersea Power Station tube station
North / westbound DanubeView and edit data on Wikidata South / eastbound
Botzaris
towards Louis Blanc
Paris Métro Line 7bis
ß before ― ß after
Pré Saint-Gervais
North / westbound Barbès - RochechouartView and edit data on Wikidata South / eastbound
Anvers
towards Porte Dauphine
Paris Métro Line 2
Q679ß before ― Q684ß after
La Chapelle
towards Nation
Château Rouge
towards Porte de Clignancourt
Paris Métro Line 4
Q659ß before ― Q667ß after
Gare du Nord
towards Bagneux–Lucie Aubrac
North / westbound Cheongnyangni StationView and edit data on Wikidata South / eastbound
Jegi-dong Station
towards Incheon Station and Sinchang station
Seoul Metropolitan Subway Line 1
ß of after <=> ß of before
Hoegi Station
towards Soyosan Station
Jegi-dong Station
towards Sinchang station
Gyeongbu Express
terminus
ß before ― ß after
Jegi-dong Station
towards Incheon Station
Gyeongwon Express
ß of after <=> ß of before
Hoegi Station
towards Dongducheon Station
Metro Gyeongchun Line
terminus
ß of after <=> ß of before
Hoegi Station
towards Chuncheon Station
Hoegi Station
towards Jipyeong Station‎
Metro Gyeongui–Jungang Line
Q684ß of after <=> Q679ß of before
Wangsimni Station
towards Munsan Station
Hoegi Station
towards Jipyeong Station‎
Gyeongui Express (Yongsan)
ß of after <=> Q679ß of before
Wangsimni Station
towards Munsan Station
Hoegi Station
towards Yongmun Station
Jungang Express
Q684ß before ― Q679ß after
Wangsimni Station
towards Munsan Station
Suin–Bundang Line
terminus
ß of after <=> Q679ß of before
Wangsimni Station
towards Incheon Station
North / westbound Montparnasse – BienvenüeView and edit data on Wikidata South / eastbound
Saint-Placide
towards Porte de Clignancourt
Paris Métro Line 4
Q659ß before ― Q667ß after
Vavin
towards Bagneux–Lucie Aubrac
Pasteur
towards Charles de Gaulle - Étoile
Paris Métro Line 6
Q679ß before ― Q684ß after
Edgar Quinet
towards Nation
Falguière
towards Mairie d'Issy
Paris Métro Line 12
Q667ß of after <=> Q659ß of before
Notre-Dame-des-Champs
towards Mairie d'Aubervilliers
Duroc
towards Les Courtilles and Saint-Denis – Université
Paris Métro Line 13
Q659ß before ― Q667ß after
Gaîté
towards Châtillon - Montrouge
North / westbound NationView and edit data on Wikidata South / eastbound
Reuilly - Diderot
towards La Défense
Paris Métro Line 1
Q679ß before ― Q684ß after
Porte de Vincennes
towards Château de Vincennes
Paris Métro Line 2
terminus
ß of after <=> Q679ß of before
Avron
towards Porte Dauphine
Paris Métro Line 6
terminus
ß of after <=> Q679ß of before
Picpus
towards Charles de Gaulle - Étoile
Rue des Boulets
towards Pont de Sèvres
Paris Métro Line 9
Q679ß before ― Q684ß after
Buzenval
towards Mairie de Montreuil
North / westbound Hanzhong Road stationView and edit data on Wikidata South / eastbound
Shanghai Railway Station station
towards Fujin Road station
Line 1
ß before ― ß after
Xinzha Road station
towards Xinzhuang Station
West Nanjing Road station
towards Qixin Road station
Line 12
ß before ― ß after
Qufu Road station
towards Jinhai Road station
Jiangning Road station
towards Jinyun Road station
Line 13
ß before ― ß after
Shanghai Natural History Museum station
towards Zhangjiang Road Station
North / westbound Bank and Monument stationsView and edit data on Wikidata South / eastbound
St. Paul's tube station
towards Ealing Broadway station and West Ruislip station
Central line[10]
ß of after <=> ß of before
Liverpool Street tube station
towards Epping, Hainault tube station and Woodford tube station
Moorgate station
towards Edgware tube station, Mill Hill East tube station and High Barnet tube station
Northern line[11]
ß of after <=> ß of before
London Bridge tube station
towards Morden tube station
Waterloo tube station
(terminus)
Waterloo & City line[12]
terminus
ß before ― ß after
North / westbound King's Cross St Pancras tube stationView and edit data on Wikidata South / eastbound
Euston Square tube station
towards Hammersmith tube station
Circle line
ß of after <=> ß of before
Farringdon station
towards Edgware Road tube station
Euston Square tube station
towards Hammersmith tube station
Hammersmith & City line[13]
ß of after <=> ß of before
Farringdon station
towards Barking station
Euston Square tube station
towards Amersham station, Chesham tube station, Uxbridge tube station and Watford tube station
Metropolitan line[14]
ß before ― ß after
Farringdon station
towards Aldgate tube station
Euston tube station
towards Edgware tube station, Mill Hill East tube station and High Barnet tube station
Northern line[15]
ß of after <=> ß of before
Angel tube station
towards Morden tube station
Caledonian Road tube station
towards Cockfosters tube station
Piccadilly line[16]
Q684ß before ― Q679ß after
Russell Square tube station
towards Uxbridge tube station, Heathrow Terminal 4 tube station and Heathrow Terminal 5 station
Euston tube station
towards Brixton tube station
Victoria line[17]
ß of after <=> ß of before
Highbury & Islington tube station
towards Walthamstow Central tube station

Usage

[edit]

{{#invoke:Adjacent stations/sandbox|function_name}}


Code

  1. www.ratp.fr/sites/default/files/lines-assets/plan-de-ligne/metro/plan-de-ligne_metro_ligne-1.1616803202.pdf
  2. www.ratp.fr/sites/default/files/lines-assets/plan-de-ligne/metro/plan-de-ligne_metro_ligne-4.1504859392.pdf
  3. www.ratp.fr/sites/default/files/lines-assets/plan-de-ligne/metro/plan-de-ligne_metro_ligne-7.1618237892.pdf
  4. www.ratp.fr/sites/default/files/lines-assets/plan-de-ligne/metro/plan-de-ligne_metro_ligne-11.1504859591.pdf
  5. www.ratp.fr/sites/default/files/lines-assets/plan-de-ligne/metro/plan-de-ligne_metro_ligne-14.1616513031.pdf
  6. bestanden.ret.nl/user_upload/Documenten/PDF/Kaarten_en_plattegronden/RET_metrolijnenkaart.pdf
  7. bestanden.ret.nl/user_upload/Documenten/PDF/Kaarten_en_plattegronden/RET_metrolijnenkaart.pdf
  8. www.transitchicago.com/brownline/#map
  9. markdunne.github.io/2016/04/10/The-London-Tube-as-a-Graph
  10. markdunne.github.io/2016/04/10/The-London-Tube-as-a-Graph
  11. markdunne.github.io/2016/04/10/The-London-Tube-as-a-Graph
  12. markdunne.github.io/2016/04/10/The-London-Tube-as-a-Graph
  13. markdunne.github.io/2016/04/10/The-London-Tube-as-a-Graph
  14. markdunne.github.io/2016/04/10/The-London-Tube-as-a-Graph
  15. markdunne.github.io/2016/04/10/The-London-Tube-as-a-Graph
  16. markdunne.github.io/2016/04/10/The-London-Tube-as-a-Graph
  17. markdunne.github.io/2016/04/10/The-London-Tube-as-a-Graph
local p = {}
--Lua code made by Eru aimed at presenting preceding and following subway stations, sorted by geographical order and by service/line number/name. 
--For time being, still in bêta. Original code at https://commons.wikimedia.org/wiki/Module:Adjacent_stations
--If any requests or comments, please add them to (where?)
--Do not copy for time being

-- default params

local defaultLang = mw.language.getContentLanguage().code
local defaultLink = 'commons' -- modify to your local wiki, like frwiki
local size_logo = 12
local showdebug = false
local ignoreCoordinate = false
local linkback
local showsource = true--parameter to help present sources, if they are present in Wikidata
local with_bearing=true--parameter to help decide to calculate with bearing or with classic line direction method (false)

-- module loading

local function loadModule(name, name2)
	local exist, res = pcall(require, name)
	if not exist then
		exist, res = pcall(require, name2)
	end
	return exist and res
end
local wikidata
if defaultLink == 'eowiki' or defaultLink == 'wikidata' or defaultLink == 'ptwiki'  then -- too much incompatibilities in [[Module:Wikidata]]
	wikidata = loadModule( 'Module:Wikidata frwiki' ) -- original code at https://fr.wikipedia.org/wiki/Module:Wikidata
	wikidata.getReferences = nil
	wikidata.sourceStr = nil
else
	wikidata = loadModule( 'Module:Wikidata' ) -- original code at https://fr.wikipedia.org/wiki/Module:Wikidata or https://commons.wikimedia.org/wiki/Module:Wikidata
end

local tools = loadModule( 'Module:Wikidata/Tools' ) -- original code at https://commons.wikimedia.org/wiki/Module:Wikidata/Tools
local TNT = require 'Module:TNT' -- https://www.mediawiki.org/wiki/Module:TNT

-- compatiblity of [[Module:Wikidata]] on various wiki

wikidata.formatEntity = wikidata.formatEntity -- frwiki
	or wikidata._getLabel -- commons
wikidata.getId = wikidata.getId -- frwiki
	or ( tools and tools.getId ) -- commons
wikidata.getFormattedQualifiers = wikidata.getFormattedQualifiers -- frwiki
	or wikidata.formatStatementQualifiers -- commons
wikidata.sourceStr = wikidata.sourceStr -- frwiki
	or function( sources, hashes ) -- commons
	return sources
end
wikidata.stringTable = wikidata.stringTable -- commons
	or wikidatafr.stringTable -- eowiki
wikidata.getClaims = wikidata.getClaims -- commons
	or wikidatafr.getClaims -- eowiki

-- private functions

local function getMessage(key, ...)
	return TNT.formatInLanguage(defaultLang, 'I18n/Template:Stations-voisines.tab', key, {...}) -- loading of https://commons.wikimedia.org/wiki/Data:I18n/Template:Stations-voisines.tab
end
--from https://commons.wikimedia.org/wiki/Module:Bearing
require('strict');

local function bearing (from_lat, from_long, to_lat, to_long)
	local from_lat_rad = math.rad (from_lat);									-- convert degree inputs to radians
	local from_long_rad = math.rad (from_long);
	local to_lat_rad = math.rad (to_lat);
	local to_long_rad = math.rad (to_long);
	
	local delta_long_rad = to_long_rad - from_long_rad;
	local x = math.cos (to_lat_rad) * math.sin (delta_long_rad);
	local y = (math.cos (from_lat_rad) * math.sin (to_lat_rad)) - (math.sin (from_lat_rad) * math.cos (to_lat_rad) * math.cos (delta_long_rad));
	local beta = math.atan2 (x, y);												-- result in radians
	beta = math.deg (beta);														-- convert to degrees
	return (0.0 > beta) and (beta + 360.0) or beta;								-- when beta is negative, add 360 degrees to make a positive bearing
end

--[[--------------------------< E X P O R T S >----------------------------------------------------------------
]]


-- from [[fr:Module:Outils]]

local function trim( texte )
	if type( texte ) == 'string' and texte ~= '' then
		texte = texte:gsub( '^%s*(%S?.-)%s*$', '%1' )
		if texte ~= '' then
			return texte
		end
	end
	return nil
end

local function validTextArg( args, name, ... )
	local texte = trim( args[name] )
	if texte then
		return texte
	end
	if select( '#', ... ) > 0 then
		return validTextArg( args, ... )
	end
	return nil
end

local function extractArgs ( frame )
	if type( frame.getParent ) == 'function' then
		local args = frame:getParent().args
		for k,v in pairs( frame.args ) do
			args[k] = v;
		end
		return args
	else
		return frame
	end
end

-- from [[fr:Module:Wikidata]]

local function getMainId(claim)
	return wikidata.getId(claim.mainsnak)
end

local function entityId(entity)
	if type(entity) == 'string' then
		return entity
	elseif type(entity) == 'table' then
		return entity.id
	end
end

local function addLinkBack(str, id, property)
	if not id or id == '' then
		id = wikidata.getEntityIdForCurrentPage()
	end
	if not id then
		return str
	end
	if type(property) == 'table' then
		property = property[1]
	end
	
	id = entityId(id)

	local class = ''
	if property then
		class = 'wd_' .. string.lower(property)
	end
	local icon = '[[File:Blue pencil.svg|%s|10px|baseline|class=noviewer|link=%s]]'--pencil icon to help modify Wikidata
	local title = getMessage('see-wikidata-value')
	local url = mw.uri.fullUrl('d:' .. id, 'uselang=fr')
	url.fragment = property -- ajoute une #ancre si paramètre "property" défini
	url = tostring(url)
	local v = mw.html.create('span')
		:addClass(class)
		:wikitext(str)
		:tag('span')
			:addClass('noprint wikidata-linkback')
			:wikitext(icon:format(title, url))
		:allDone()
	return tostring(v)
end

-- from [[commons:Module:Wikidata]]

local function getQualifiers(statement, qualifs, params)
	if not statement.qualifiers then
		return nil
	end
	local vals = {}
	for i, j in pairs(qualifs) do
		j = string.upper(j)
		if statement.qualifiers[j] then
			local inserted = false
			if statement.qualifiers[j][1].datatype == 'monolingualtext' then
				local in_preferred_lang
				for _, language in ipairs(fb.fblist(params.lang or defaultlang, true)) do
					for _, snak in ipairs(statement.qualifiers[j]) do
						if isInLanguage(snak, language) then
							in_preferred_lang = snak
							break
						end
					end
					if in_preferred_lang then
						break
					end
				end
				if in_preferred_lang then
					table.insert(vals, in_preferred_lang)
					inserted = true
				end
			end
			if not inserted then
				for _, snak in pairs(statement.qualifiers[j]) do
					table.insert(vals, snak)
				end
			end
		end
	end
	if #vals == 0 then
		return nil
	end
	return vals
end

wikidata.getReferences = wikidata.getReferences or function(statement)
	local cite = loadModule( 'Module:Cite' )
	local isSpecial = wikidata.isSpecial or ( tools and tools.isSpecial )
	if not isSpecial or not cite or not statement.references then
		return ''	
	end
	local frame = mw.getCurrentFrame()
	local sourcestring = ''
	for i, ref in pairs(statement.references) do
		local s
		if ref.snaks.P248 then
			for j, source in pairs(ref.snaks.P248) do
				if not isSpecial(source) then
					local page
					if ref.snaks.P304 and not isSpecial(ref.snaks.P304[1]) then
						page = ref.snaks.P304[1].datavalue.value
					end
					s = cite.citeitem('Q' .. source.datavalue.value['numeric-id'], lang, page)
					s = frame:extensionTag('ref', s)
					sourcestring = sourcestring .. s
				end
			end
		elseif ref.snaks.P854 and not isSpecial(ref.snaks.P854[1]) then
			s = frame:extensionTag('ref', wikidata.formatSnak(ref.snaks.P854[1], {}))
			sourcestring = sourcestring .. s
		end
	end
	return sourcestring
end

-- public functions

function p.Adjacent_stations( id, onlyLineService, rows )
	if not id then
		id = mw.wikibase.getEntityIdForCurrentPage()
	end
	local argsData = { entity = id, property = 'P197' }
	if onlyLineService then
		argsData.qualifier = { 'P1192', 'P81' } -- ligne or service
		argsData.qualifiervalue = onlyLineService
	end
	--localisation principale
	local mainCoordinate = ( not ignoreCoordinate ) and wikidata.stringTable( { entity = id, property = 'P625', numval = 1 } )
	if mainCoordinate and #mainCoordinate > 0 then -- si des coordonnées pour la présente station sont présentes / if coordinates are present for the current subway
		mainCoordinate = mainCoordinate[ 1 ]
	end

	-- ajout d'une ligne dans le tableau / add a line in the table
	local function addLineDetail( lineDetail )
		if lineDetail.color then
			lineDetail.color = 'style="background:#' .. lineDetail.color .. ';" width="1*" |'
		else
			lineDetail.color = ''
		end
		local textBefore = { '| ' }
		local textAfter = { '| ' }
		local textLine = { '| ' }
		if lineDetail.logo then
			for _, logo in ipairs( lineDetail.logo ) do
				textLine[ #textLine + 1 ] = '[[Image:' .. logo .. '|' .. size_logo .. ' px]] '
			end
		end
		textLine[ #textLine + 1 ] = lineDetail.name
		if lineDetail.source then
			textLine[ #textLine + 1 ] = lineDetail.source
		end
		
		local isTerminus = false
		if lineDetail.after and lineDetail.after ~= '-' then -- no value
			textAfter[ #textAfter + 1 ] = lineDetail.after
			if lineDetail.afterDestination and lineDetail.afterDestination ~= '-' then
				textAfter[ #textAfter + 1 ] = "<br /><small>"
				if lineDetail.after == lineDetail.afterDestination then
					textAfter[ #textAfter + 1 ] = getMessage( 'if_terminus' )
				else
					textAfter[ #textAfter + 1 ] = getMessage( 'towards' )
					textAfter[ #textAfter + 1 ] = " ''"
					textAfter[ #textAfter + 1 ] = lineDetail.afterDestination
					textAfter[ #textAfter + 1 ] = "''"
				end
				textAfter[ #textAfter + 1 ] = "</small>"
			end
			if lineDetail.afterVia and lineDetail.afterVia ~= '-' then
				textAfter[ #textAfter + 1 ] = "<br /><small>"
				textAfter[ #textAfter + 1 ] = getMessage( 'via' )
				textAfter[ #textAfter + 1 ] = " ''"
				textAfter[ #textAfter + 1 ] = lineDetail.afterVia
				textAfter[ #textAfter + 1 ] = "''</small>"
			end
			lineDetail.colorAfter = lineDetail.color
		elseif lineDetail.Y then
			lineDetail.colorAfter = ''
		else
			isTerminus = true
			textLine[ #textLine + 1 ] = "<br /><small>"
			textLine[ #textLine + 1 ] = getMessage( 'terminus' )
			textLine[ #textLine + 1 ] = "</small>"
			lineDetail.colorAfter = ''
		end
		if lineDetail.before and lineDetail.before ~= '-' then -- no value
			textBefore[ #textBefore + 1 ] = lineDetail.before
			if lineDetail.beforeDestination and lineDetail.beforeDestination ~= '-' then
				textBefore[ #textBefore + 1 ] = "<br /><small>"
				if lineDetail.before == lineDetail.beforeDestination then
					textBefore[ #textBefore + 1 ] = getMessage( 'if_terminus' )
				else
					textBefore[ #textBefore + 1 ] = getMessage( 'towards' )
					textBefore[ #textBefore + 1 ] = " ''"
					textBefore[ #textBefore + 1 ] = lineDetail.beforeDestination 
					textBefore[ #textBefore + 1 ] = "''"
				end
				textBefore[ #textBefore + 1 ] = "</small>"
			end
			if lineDetail.beforeVia and lineDetail.beforeVia ~= '-' then
				textBefore[ #textBefore + 1 ] = "<br /><small>"
				textBefore[ #textBefore + 1 ] = getMessage( 'via' )
				textBefore[ #textBefore + 1 ] = " ''"
				textBefore[ #textBefore + 1 ] = lineDetail.beforeVia 
				textBefore[ #textBefore + 1 ] = "''</small>"
			end
			lineDetail.colorBefore  = lineDetail.color
		else
			isTerminus = true
			textLine[ #textLine + 1 ] = "<br /><small>"
			textLine[ #textLine + 1 ] = getMessage( 'terminus' )
			textLine[ #textLine + 1 ] = "</small>"
			lineDetail.colorBefore  = ''
		end	
		local inverted
		--new decision tree with bearings to help decide  how to build the table, provided both neighbours have coordinates, disable it with 'with_bearing'
		if with_bearing and (lineDetail.beforeCoordinate or lineDetail.afterCoordinate) then 
			local bearingbefore
			local bearingafter
			local angle
			if lineDetail.beforeCoordinate then
				bearingbefore=bearing ( mainCoordinate.latitude,  mainCoordinate.longitude, lineDetail.beforeCoordinate.latitude, lineDetail.beforeCoordinate.longitude)
			end
			if lineDetail.afterCoordinate then
				bearingafter=bearing ( mainCoordinate.latitude,  mainCoordinate.longitude, lineDetail.afterCoordinate.latitude, lineDetail.afterCoordinate.longitude)
				angle = 180 - math.abs(math.abs(bearingbefore - bearingafter) - 180) 
			end
		if bearingafter==nil then--termini case, only with bearingbefore
				if bearingbefore<=205 --not too close to 180°
				--(bearingbefore<135.0 or  bearingbefore>315.0)		--truely heading North for "after"
			--	or (bearingbefore>45.0 and  bearingbefore>135.0)	--truely heading West for "after"
				then inverted=true 
				else inverted=false end
			elseif (bearingbefore<45.0 or bearingbefore>315.0)  	--truely heading North for "before" for 90°
				then 
					if (bearingafter>=45.0 and bearingafter<=225.0)	--lazily heading South or East for "after" for 180°
						then if angle>45.0 then inverted=false		--their angle should be more than 45° so it is more of simple direction
						else inverted=true	end							--then ↕
					elseif (bearingbefore<45.0 and bearingafter>225.0)	--before in North and after in East/South
						then if angle>45.0 then inverted=true		--their angle should be more than 45° so it is more of simple direction
						else inverted=false	end		
					elseif ( bearingbefore>315.0 and bearingafter<45.0) --before in North and after in North too? bizarre
						then inverted=true	
					else inverted=false								--
					end
			elseif (bearingbefore>135.0 and bearingbefore<225.0)	--truely heading South for "before" for 90°
				then 
					if (bearingafter<=45.0 or bearingafter>=225.0)	--lazily heading North or East for "after" for 180°
						then if angle>45.0 then inverted=true							--then ↕
							else inverted=false end
					elseif (bearingbefore>=180.0 and bearingafter<135.0)	--probably ┌
						then inverted=false
					elseif ( bearingbefore<=180.0 and bearingafter<225.0) --probably ┐ , hard to tell
						then inverted=false	
					else inverted=true
					end

			elseif (bearingbefore>45.0 and bearingbefore<135.0) 	--truely heading West for "before" for 90°
				then  
					if (bearingafter>=225.0 or bearingafter<=45.0)--lazily heading East or North for "after" for 180°
						then if angle>45.0 then inverted=true							--then ↕
							else inverted=false end						--then ↔
						else inverted=true							--probably ┌ or ┐
					end
			elseif (bearingbefore>225.0 and bearingbefore<315.0)	--truely heading East for "before" for 90°
				then  if (bearingafter>=45.0 and bearingafter<=225.0)	--lazily heading West or North for "after" for 180°
						then if angle>45.0 then inverted=false							--then ↕
							else inverted=true end						--then ↔
						else inverted=false							--probably ┌ or ┐
					end
			elseif (bearingbefore<135.0)							--lazily heading NorthWest for "before"
				or (bearingafter>135.0)	 							--lazily heading SouthEast for "after"
				then  inverted=false		
			elseif (bearingbefore>=135.0)							--lazily heading SouthEast for "before"
				or (bearingafter<=135.0)	 						--lazily heading NorthWest for "after"
				then  inverted=true
			elseif bearingbefore>bearingafter
				then inverted=true --cas des bearings presques identiques
			--else inverted=true  --what about those having almost same bearing? 
			end
--decision tree without bearing consideration
		elseif lineDetail.beforeCoordinate and lineDetail.afterCoordinate then
			local direction = lineDetail.beforeDirection or lineDetail.afterDirection
			if direction == 'Q679' -- west
				or direction == 'Q684' then -- est
				if lineDetail.beforeCoordinate.longitude and lineDetail.afterCoordinate.longitude
						and lineDetail.beforeCoordinate.longitude > lineDetail.afterCoordinate.longitude then
					inverted = true
				end
			else -- north or south
				if lineDetail.beforeCoordinate.latitude and lineDetail.afterCoordinate.latitude
						and lineDetail.beforeCoordinate.latitude < lineDetail.afterCoordinate.latitude then
					inverted = true
				end
			end
		elseif isTerminus and lineDetail.beforeCoordinate and not lineDetail.after and mainCoordinate then
			local direction = lineDetail.beforeDirection
			if direction == 'Q679' -- west
				or direction == 'Q684' then -- est
				if lineDetail.beforeCoordinate.longitude and mainCoordinate.longitude
						and lineDetail.beforeCoordinate.longitude > mainCoordinate.longitude then
					inverted = true
				end
			else -- north or south
				if lineDetail.beforeCoordinate.latitude and mainCoordinate.latitude
						and lineDetail.beforeCoordinate.latitude < mainCoordinate.latitude then
					inverted = true
				end
			end
		end

		rows[ #rows + 1 ] = '|-'
		if inverted then
			if showdebug then
				textLine[ #textLine + 1 ] = '<br>'
				if lineDetail.afterDirection then
					textLine[ #textLine + 1 ] = lineDetail.afterDirection end
					textLine[ #textLine + 1 ] =	'ß of after' 
			--	if bearingafter then	textLine[ #textLine + 1 ] = bearingafter end
				textLine[ #textLine + 1 ] = ' <=> '
				if lineDetail.beforeDirection then
					textLine[ #textLine + 1 ] = lineDetail.beforeDirection end
					textLine[ #textLine + 1 ] =	'ß of before' 
			--	if bearingbefore then	textLine[ #textLine + 1 ] =	bearingbefore end
			end
			rows[ #rows + 1 ] = table.concat( textAfter )
			rows[ #rows + 1 ] = '| ' .. lineDetail.colorAfter
			rows[ #rows + 1 ] = table.concat( textLine )
			rows[ #rows + 1 ] = '| ' .. lineDetail.colorBefore
			rows[ #rows + 1 ] = table.concat( textBefore )
		else
			if showdebug then
				textLine[ #textLine + 1 ] = '<br>'
				if lineDetail.beforeDirection then
					textLine[ #textLine + 1 ] = lineDetail.beforeDirection	end
				  	textLine[ #textLine + 1 ] =	'ß before' 
			--	if bearingbefore and bearingafter  then	textLine[ #textLine + 1 ] =	bearingbefore end
				
				textLine[ #textLine + 1 ] = ' ― '
				if lineDetail.afterDirection then
					textLine[ #textLine + 1 ] = lineDetail.afterDirection end
				textLine[ #textLine + 1 ] =	'ß after' 
			--	if bearingbefore and bearingafter  then	textLine[ #textLine + 1 ] =	bearingafter end
			end
			rows[ #rows + 1 ] = table.concat( textBefore )
			rows[ #rows + 1 ] = '| ' .. lineDetail.colorBefore
			rows[ #rows + 1 ] = table.concat( textLine )
			rows[ #rows + 1 ] = '| ' .. lineDetail.colorAfter
			rows[ #rows + 1 ] = table.concat( textAfter )
		end
	end

	local claims = wikidata.getClaims( argsData )
	local function getClaimDetail( claim )
		claim.lineid = wikidata.getId( claim.currentline )
		claim.lineName = wikidata.formatSnak( claim.currentline, { link = defaultLink } )
		if not claim.lineName or claim.lineName == '-' then -- no value
			claim.lineName = ''
		end
		local routenumber = wikidata.formatStatements( { entity = claim.lineid, property = 'P1671', numval = 1 } )
		if routenumber then
			claim.sortKey = tonumber( routenumber ) -- 570000
				or tonumber( tostring( routenumber:gsub( ' ', '' ) ) ) -- 655 000
				or routenumber:upper() -- KBS 566
		else
			claim.sortKey = claim.lineName:upper()
		end
	end

	if claims and #claims > 0 then
		-- récupération des données de bases et de tri des lignes / recovery of basic data and line sorting
		local newClaims = { }
		local defaultSortKey = 1
		for _, claim in ipairs( claims ) do
			claim.defaultSortKey = defaultSortKey
			defaultSortKey = defaultSortKey + 1
			local currentlines = getQualifiers( claim, { 'P1192', 'P81' }, { } ) -- ligne or service
			if currentlines and #currentlines > 0 then
				for _,currentline in ipairs( currentlines ) do
					local newClaim = mw.clone( claim )
					newClaim.currentline = currentline
					getClaimDetail( newClaim )
					if not onlyLineService or onlyLineService == newClaim.lineid then
						newClaims[ #newClaims + 1 ] = newClaim
					end
				end
			else
				claim.lineName = ''
				claim.sortKey = claim.lineName:upper()
				newClaims[ #newClaims + 1 ] = claim
			end
		end
		table.sort( newClaims,
			function( c1, c2 )
				if c1.sortKey == c2.sortKey then
					return c1.defaultSortKey < c2.defaultSortKey
				elseif type( c1.sortKey ) == 'number' and type( c2.sortKey ) == 'number' then
					return c1.sortKey < c2.sortKey
				else
					return tostring( c1.sortKey ) < tostring( c2.sortKey )
				end
			end
		)

		-- parcours de toutes les gares et stations / loop of all stations
		local lineDetail = { }
		for _, claim in ipairs( newClaims ) do
			 -- nouvelle ligne
			if claim.lineName ~= lineDetail.name then
				if lineDetail.name ~= nil then
					addLineDetail( lineDetail )
				end
				lineDetail = { }
				lineDetail.name = claim.lineName
				if claim.currentline then
					lineDetail.color = wikidata.formatStatements( { entity = claim.lineid, property = 'P465', numval = 1} )
					lineDetail.logo = wikidata.stringTable( { entity = claim.lineid, property = 'P154' } )
				end
				if showsource then
					lineDetail.source = wikidata.sourceStr( wikidata.getReferences(claim) )
				end
			end

			local station = wikidata.formatStatement( claim, { link = defaultLink }  )
			local destination = wikidata.getFormattedQualifiers( claim, { 'P5051' }, { conjtype = getMessage( 'or', ' ' ), link = defaultLink } )
			local via = wikidata.getFormattedQualifiers( claim, { 'P2825' }, { conjtype = getMessage( 'and' ), link = defaultLink } )
			local coordinate = ( not ignoreCoordinate ) and wikidata.stringTable( { entity = getMainId( claim ), property = 'P625', numval = 1 } )
			local terminusDirection
			if claim.lineid and coordinate and #coordinate > 0 then -- si des coordonnées sont présentes / if coordinates are present
				coordinate = coordinate[ 1 ]
				local terminusDirections = wikidata.getClaims( { entity = claim.lineid, property = 'P559', showqualifier = 'P560' } ) -- récupérer la liste des terminus et des directions de la ligne
				if terminusDirections and #terminusDirections > 0 then 
					local terminus = getQualifiers( claim, { 'P5051' } ) -- récupérer les terminus de la connexion en cours / retrieve the terminus of the current connection
					local terminusQid = { }
					if terminus then
						for i, t in ipairs( terminus ) do
							local tid = wikidata.getId( t )
							if tid then
								terminusQid[ tid ] = true
							end
						end
					end
					for _, td in ipairs( terminusDirections ) do
						local d = wikidata.getFormattedQualifiers( td, { 'P560' }, { displayformat = 'raw' } )
						local t = getMainId( td )
						if not terminusDirection and d and terminusQid[ t ] then -- si ce terminus de la ligne fait partie des terminus de ma connexion, prendre cette direction
							terminusDirection = d -- plusieurs résultats possibles, prendre le premier / several possible result, take the first
						end
					end
				end
			end

			if not lineDetail.before then -- station 1
				lineDetail.before = station
				lineDetail.beforeDestination = destination
				lineDetail.beforeVia = via
				lineDetail.beforeCoordinate = coordinate
			--	lineDetail.beforeBearing=bearingbefore does not work, why?
				lineDetail.beforeDirection = terminusDirection
			elseif not lineDetail.after then -- station 2	
				lineDetail.after = station
				lineDetail.afterDestination = destination
				lineDetail.afterVia = via
				lineDetail.afterCoordinate = coordinate
			--	lineDetail.afterBearing=bearingafter does not work, why?
				lineDetail.afterDirection = terminusDirection
			else -- station 3 > nouvelle ligne dans le tableau
				local newLineDetail = { }
				newLineDetail.name = lineDetail.name
				newLineDetail.color = lineDetail.color
				newLineDetail.logo = lineDetail.logo
				newLineDetail.before = station
				newLineDetail.beforeDestination = destination
				newLineDetail.beforeVia = via
				newLineDetail.beforeCoordinate = coordinate
				newLineDetail.beforeDirection = terminusDirection
				newLineDetail.Y = true
				addLineDetail( lineDetail )
				lineDetail = newLineDetail
			end
		end
		addLineDetail( lineDetail ) -- ajout de la dernière ligne construite / addition of the last line constructed

		local lb = ''
		if linkback ~= '-' then
			lb = '[[d:' .. id  .. '#P197|' .. getMessage( 'edit_wikidata' ) .. ']]'
			rows[ #rows + 1 ] = '|-'
			rows[ #rows + 1 ] = '| class="noprint navigation-not-searchable tfoot" colspan="5" | ' .. lb
		end
		return true
	else
		return false
	end
end

function p.main( frame )
	local rows = {}
	local args = extractArgs( frame )
	local id = validTextArg( args, 1, 'id', 'wikidata', 'entity' )
	local onlyLineService = validTextArg( args, 2, 'ligne', 'line', 'service' )
	linkback = validTextArg( args, 'linkback' )
	local ssource = validTextArg( args, 'showsource' )
	if ssource and ( ssource == '-' or ssource == 'non' or ssource == 'no' or ssource == 'false' ) then
		showsource = false
	end
	local title = validTextArg( args, 'titre', 'title', 3 ) or ''
	if id and title == '' then
		title = wikidata.formatEntity( id , { link = defaultLink } )
		if linkback ~= '-' and defaultLink ~= 'wikidata' then
			title = addLinkBack( title, id, 'P197' )
			linkback = '-'
		end
	elseif title == '-' then
		title = ''
	end
	ignoreCoordinate = validTextArg( args, 'ignore coordinate', 'ignore coordonnées' )
	showdebug = validTextArg( args, 'debug' ) -- pour les tests uniquement / for testing only

	rows[ #rows + 1 ] = '{| class="wikitable adjacent-stations"'
	rows[ #rows + 1 ] = '! scope=col | ' .. getMessage( 'station_before', '<abbr title="', '">', '</abbr> <abbr title="', '">', '</abbr> ', ' <abbr title="', '">', '</abbr> ')
	rows[ #rows + 1 ] = '! scope=col colspan="3" | ' .. title
	rows[ #rows + 1 ] = '! scope=col | ' .. getMessage( 'station_after', '<abbr title="', '">', '</abbr> <abbr title="', '">', '</abbr> ', ' <abbr title="', '">', '</abbr> ' )

	local found = p.Adjacent_stations( id, onlyLineService, rows )

	if found then
		rows[ #rows + 1 ] = '|}'
		return table.concat( rows, '\n' )
	else
		return nil
	end
end

return p