Module:Adjacent stations

This is an old revision of this page, as edited by Szqecs (talk | contribs) at 10:30, 1 May 2018 (Implemented new version). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

local yesno = require("Module:Yesno")
local _style = {
	['3'] = 'style="width: 30%;',
	['c'] = 'style="text-align: center;',
	['v'] = 'vertical-align: middle;',
	['bd'] = 'border:',
	['t'] = 'border-top:',
	['bb'] = 'border-bottom:',
	['L'] = 'border-left:',
	['R'] = 'border-right:',
	['n'] = 'none;',
	['0'] = '0px none;',
	['1'] = '1px solid #aaa;'
}
local style = {
	['table'] = table.concat({'style="width: 55%; max-width: 50em; margin:0.5em auto; font-size:95%; clear:both;',
		_style['t'], _style['0'],
		'border-collapse: separate;" cellspacing="0" cellpadding="-1"'
	}),
	['header leftcell'] = table.concat({_style['3'], _style['v'],
		_style['bd'], _style['1'],
		_style['L'], _style['n'],
		_style['bb'], _style['n'],
		'"|'
	}),
	['header banner'] = table.concat({'style="',
		_style['bd'], _style['n'],
		_style['t'], _style['1'],
		'"|'
	}),
	['header midcell'] = table.concat({'colspan="3" style="', _style['v'],
		_style['bd'], _style['n'],
		_style['t'], _style['1'],
		'"|'
	}),
	['header rightcell'] = table.concat({_style['3'], _style['v'],
		_style['bd'], _style['1'],
		_style['R'], _style['n'],
		_style['bb'], _style['n'],
		'"|'
	}),
	['body leftcell'] = table.concat({_style['c'], _style['v'],
		_style['L'], _style['0'],
		_style['bb'], _style['0'],
		_style['R'], _style['1'],
		_style['t'], _style['1'],
		'"|'
	}),
	['body banner'] = table.concat({_style['c'],
		_style['L'], _style['0'],
		_style['bb'], _style['0'],
		_style['R'], _style['0'],
		_style['t'], _style['1'],
		'width: 8px; min-width: 8px; background-color: #'
	}),
	['body midcell'] = table.concat({_style['c'], _style['v'],
		_style['bb'], _style['0'],
		'"|'
	}),
	['body rightcell'] = table.concat({_style['c'], _style['v'],
		_style['L'], _style['1'],
		_style['bb'], _style['0'],
		_style['R'], _style['0'],
		_style['t'], _style['1'],
		'"|'
	})
}

local function subFormat(s)
	return '<div style="font-size: smaller; font-style: italic">' .. s .. '</div>'
end

local p = {}

function p.top()
	return table.concat({'{| class="wikitable" ', style['table']})
end

function p.line(args, index, data)
	local lineTitle = {}
	local colour = {}
	local left = {}
	local right = {}
	local note = {}
	local leftTerminus = {}
	local rightTerminus = {}
	
	local t = {}
	
	for i, v in ipairs(index) do
		if args.system[v] then
			table.insert(t, table.concat({'\n|-',
				'\n!', style['header leftcell'], 'Preceding station',
				'\n!', style['header midcell'], (data[v]['system title'] or ('[['..args.system[v]..']]')),
				'\n!', style['header rightcell'], 'Following station'
			}))
			table.insert(t, '')
			table.insert(t, '')
			table.insert(t, '')
		end
		
		if args.line[v] or args.left[v] or args.right[v] then
			if not args.line[v] then args.line[v] = args.line[index[i-1]] end
			local _line = data[v]['lines'][args.line[v]]
			lineTitle[v] = _line['line title']
			colour[v] = _line.colour or _line.color
			note[v] = args.note[v] or ''
			
			if type(_line['left terminus']) == 'string' then
				_leftTerminus = _line['left terminus']
			elseif type(_line['left terminus']) == 'table' then
				_leftTerminus = _line['left terminus'][args.TypeL[v] or args.Type[v] or 1]
			end
			if type(_line['right terminus']) == 'string' then
				_rightTerminus = _line['right terminus']
			elseif type(_line['right terminus']) == 'table' then
				_rightTerminus = _line['right terminus'][args.TypeR[v] or args.Type[v] or 1]
			end
			
			local function station(var)
				local function subst(s)
					if s then
						if string.match(s, '%[%[') then
							return mw.ustring.gsub(s, '%%1', var)
						elseif type(var) == 'string' then
							return table.concat({'[[', mw.ustring.gsub(s, '%%1', var), '|', var, ']]'})
						elseif type(var) == 'table' and #var > 0 then
							local function _subst(k)
								return table.concat({mw.ustring.gsub(s, '%%1', var[k]), '|', var[k]})
							end
							
							local t = {}
							
							t[1] = table.concat({'[[', _subst(1), ']]'})
							
							for i = 2, #var - 1 do
								t[i] = table.concat({', [[', _subst(i), ']]'})
							end
							
							if #var > 1 then
								t[#var] = table.concat({' or [[', _subst(#var), ']]'})
							end
							
							if var['via'] then
								t[#var + 1] = table.concat({' via&nbsp;[[', _subst('via'), ']]'})
							end
							
							return table.concat(t)
						end
					end
				end
				
				if data[v]['station format'] then
					return subst(data[v]['station format'][var] or data[v]['station format'][1]) or ''
				else
					return var or ''
				end
			end
			
			if not args.left[v] then
				left[v] = "''Terminus''"
				leftTerminus[v] = ''
			else
				left[v] = station(args.left[v])
				if args.onewayL[v] == true then
					leftTerminus[v] = subFormat('One-way operation')
				elseif args.left[v] == _leftTerminus then
					leftTerminus[v] = subFormat('Terminus')
				else
					leftTerminus[v] = subFormat('towards ' .. station(_leftTerminus))
				end
			end
			
			if not args.right[v] then
				right[v] = "''Terminus''"
				rightTerminus[v] = ''
			else
				right[v] = station(args.right[v])
				if args.onewayR[v] == true then
					rightTerminus[v] = subFormat('One-way operation')
				elseif args.right[v] == _rightTerminus then
					rightTerminus[v] = subFormat('Terminus')
				else
					rightTerminus[v] = subFormat('towards ' .. station(_rightTerminus))
				end
			end
			
			table.insert(t, '\n|-')
			table.insert(t, table.concat({'\n|', style['body leftcell'], left[v], leftTerminus[v]}))
			table.insert(t, table.concat({'\n|', style['body banner'], colour[v], '"|',
				'\n|', style['body midcell'], lineTitle[v], '<div style="font-size: smaller">', note[v], '</div>',
				'\n|', style['body banner'], colour[v], '"|'}))
			table.insert(t, table.concat({'\n|', style['body rightcell'], right[v], rightTerminus[v]}))
		end
	end
	
	local function combine(t, i)
		if t[i + 4] ~= '' and t[i + 4] == t[i] then
			t[i + 4] = '' -- The cell in the next row is deleted
			local rowspan = 2
			while t[i + rowspan * 4] == t[i] do
				t[i + rowspan * 4] = ''
				rowspan = rowspan + 1
			end
			t[i] = mw.ustring.gsub(t[i], '\n|style="', table.concat({'\n|rowspan="', rowspan, '" style="'}))
		end
	end
	
	local max = #t
	for i = 2, max - 2, 4 do combine(t, i) end
	for i = 3, max - 1, 4 do combine(t, i) end
	for i = 4, max, 4 do combine(t, i) end
	
	return table.concat(t)
end

function p.bottom()
	return '\n|}'
end

function p.main(frame)
	local _args = frame:getParent().args
	local args = {
		system = {},
		line = {},
		left = {},
		right = {},
		Type = {},
		TypeL = {},
		TypeR = {},
		note = {},
		onewayL = {},
		onewayR = {},
		circular = {},
		circularL = {},
		circularR = {}
	}

--	to do: add rest of S-line parameters	
	local _index = {}
	local parameters = {
		['strings'] = {
			['system'] = 'system',
			['line'] = 'line',
			['left'] = 'left',
			['right'] = 'right'
		},
		['optional strings'] = {
			['note-mid'] = 'note',
			['type'] = 'Type',
			['type-left'] = 'TypeL',
			['type-right'] = 'TypeR',
--			['through'] = 'through', -- The way this would work is that it would replace either "Terminus" cell, rather than just one of them in particular.
--			['through-left'] = 'throughL',
--			['through-right'] = 'throughR',
--			['branch'] = 'branch',
--			['transfer'] = 'transfer'
		},
		['optional boolean'] = {
			['oneway-left'] = 'onewayL',
			['oneway-right'] = 'onewayR',
--			['round-left'] = 'roundL',
--			['round-right'] = 'roundR',
			['circular'] = 'circular',
			['circular-left'] = 'circularL',
			['circular-right'] = 'circularR',
			['through-left'] = 'throughL',
			['through-right'] = 'throughR'
		}
	}
	for k, v in pairs(_args) do
		_args[k] = v:match('^%s*(.-)%s*$')
		if _args[k] and _args[k] ~= '' then
			local a = string.match(k, '^(.*%D)%d+$') or k
			local b = tonumber(string.match(k, '^.*%D(%d+)$')) or 1
			
			if parameters['strings'][a] then
				args[parameters['strings'][a]][b] = v
				_index[b] = true
			elseif args[parameters['optional strings'][a]] then
				args[parameters['optional strings'][a]][b] = v
			elseif args[parameters['optional boolean'][a]] then
				args[parameters['optional boolean'][a]][b] = yesno(v)
			end
		end
	end

	local index = {}
	for k, v in pairs(_index) do
		table.insert(index, k)
	end
	table.sort(index)
	
	local data = {}
	for i, v in ipairs(index) do
		if args.system[v] then
--			data[v] = require('Module:Adjacent stations/' .. args.system[v])
			data[v] = require('Module:Adjacent stations/' .. args.system[v] .. '/sandbox')
		else
			data[v] = data[index[i-1]]
		end
	end
	
	local rows = { -- Included for mixed used with S-line.
		['all'] = table.concat({p.top(), p.line(args, index, data), p.bottom()}),
		['top'] = table.concat({p.top(), p.line(args, index, data)}),
		['mid'] = table.concat({p.line(args, index, data)}),
		['bottom'] = table.concat({p.line(args, index, data), p.bottom()})
	}
	
	return rows[_args.rows] or rows['all']
end

return p