Module:Sandbox/Bon

From OpenStreetMap Wiki
Jump to navigation Jump to search
-- The following module, intended to be used inside a table, creates all table rows needed to represent a public transport service line,
-- its variants and its routes along with its mapping progress, update, etc.

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

local p = {}

-- local translation = require('Module:Sandbox/Bon/Translations').translations
local translation = {}

translation['en'] = {
	name = 'name',		-- line name
	colour = 'colour',	-- line colour
	var = 'var',		-- variant
	varL = 'varL',		-- length of the variant
	upd = 'upd',		-- last update
	chk = 'chk',		-- last check
	tags = 'tags',		-- other tags
	notes = 'notes',	-- notes
	links = 'links'		-- links
	}

translation['it'] = {
	name = 'nome',		-- nome linea
	colour = 'colore',	-- colore linea
	var = 'var',		-- variante
	varL = 'Lvar',		-- lunghezza variante
	upd = 'agg',		-- aggiornamento
	chk = 'con',		-- controllo
	tags = 'tag',		-- altri tag
	notes = 'note',		-- note
	links = 'link'		-- link
	}


local function setLang(frame,args)
	local langCode = mw.text.trim(lang or args.lang or 'en')
	if not translation[langCode] then
		local fallbacks_table = mw.language.getFallbacksFor(langCode)
		for _, fb_code in ipairs(fallbacks_table) do
			if translation[fb_code] then langCode = fb_code break end
		end
	end
	local Wlang = mw.getLanguage(langCode)
	if not mw.language.isSupportedLanguage(langCode) then
		local fallbacks_table = mw.language.getFallbacksFor(langCode)
		for _, fb_code in ipairs(fallbacks_table) do
			if mw.language.isSupportedLanguage(fb_code) then
				Wlang = mw.getLanguage(fb_code) break
			end
		end
	end
	return langCode, Wlang
end

--	Given a table containing the template arguments indicised by keys in one of the languages listed above ("localised keys"), this function
--	creates and returns a table containing the same arguments but indicised by the corresponding keys in English, sometimes abbreviated,
--	as seen in the "translation" tables above and used in this module's code.
local function translateArgs(frame, loc_args)
	local langCode, Wlang = setLang(frame, loc_args)
	local args = {}				-- The "args" table will contain all values of the "loc_args" table, but indicised
								-- by the key used in this module's code rather than the template languages.
	local tl_table = translation[langCode]
	local backtl_table = {}
	for k,v in pairs(tl_table) do
		backtl_table[v] = k
	end
	
	-- copies all the loc_args values with a numerical key into the corresponding keys of the args table.
	for argkey in ipairs(loc_args) do
		args[argkey] = loc_args[argkey]
	end
	
	-- copies all the loc_args values with a text key into the corresponding translated keys of the args table.
	-- first 'for' cycle handles text keys with appended "1" as well.
	for loc_argkey in pairs(loc_args) do
		local argkey = backtl_table[loc_argkey] or backtl_table[mw.text.split(loc_argkey,'1')[1]] or nil
		if argkey then
			args[argkey] = loc_args[loc_argkey]
		end
	end
	-- second 'for' cycle handles text keys with numbers greater than "1" appended at their end.
	local i = 2
	while loc_args[tl_table['var']..i] do
		for loc_argkey in pairs(loc_args) do
			local loc_argname_parts = mw.text.split(loc_argkey,tostring(i))
			local argkey = backtl_table[loc_argname_parts[1]] or nil
			if argkey and loc_argname_parts[2] == '' then
				args[argkey..i] = loc_args[loc_argkey]
			end
		end
		i = i + 1
	end
	return args, Wlang, langCode
end


local setParams = {
	
	general =
		function(frame, args, dateFormat, rP, nrP)
			local dF = dateFormat or 'j F Y'
			local rep_P = rP or frame.args[1] or 3
			local nrep_P = nrP or frame.args[2] or 1
			return dF, rep_P, nrep_P
		end,
	
	network =
		function(frame, args, network, operator)
			local nw = network or args.network or nil
			local op = operator or args.operator or nil
			return nw, op
		end,
	
	line =
		function(frame, args)
			local Lref = args[1] or ''
			local Lname = args.name or nil
			local Lcolour = args.colour ~= '' and args.colour or nil
			local Lnotes = args.notes or nil
			return Lref, Lname, Lcolour, Lnotes
		end,
	
	variants =
		function(frame, args)
			local Vlabel = {}
			local Vlength = {}
			local Vupdate = {}
			local Vcheck = {}
			local Vtags = {}
			Vlabel[1] = args.var or args.var1 or nil
			Vupdate[1] = args.upd or args.upd1 or nil
			Vcheck[1] = args.chk or args.chk1 or nil
			Vtags[1] = args.tags or args.tags1 or nil
			if Vlabel[1] then
				Vlength[1] = tonumber(args.varL or args.varL1 or 2)
				local i = 2
				while args['var'..i] do
					Vlabel[i] = args['var'..i]
					Vlength[i] = tonumber(args['varL'..i] or 2)
					Vupdate[i] = args['upd'..i] or nil
					Vcheck[i] = args['chk'..i] or nil
					Vtags[i] = args['tags'..i] or nil
					i = i + 1
				end
				local n_var = #Vlabel
			end
			return Vlabel, Vlength, Vupdate, Vcheck, Vtags, n_var
		end,
	
	routes =
		function(frame, args, rP, nrP)
			local rep_P = rP or frame.args[1] or 3
			local nrep_P = nrP or frame.args[2] or 1
			local Rroute = {}
			local Rrel = {}
			local Rprogr = {}
			local i,j = 1, nrep_P + 1
			while args[j] or args[j+1] do
				Rroute[i] = tostring(args[j] or '')
				Rrel[i] = mw.text.trim(args[j+1] or '')
				Rprogr[i] = tostring(args[j+2] or '')
				i = i + 1
				j = j + rep_P
			end
			local n_routes = #Rroute
			return Rroute, Rrel, Rprogr, n_routes
		end
	
}

local localisedCells = {}
-- local _, _, localisedCells = placeFunction()

local cells = {
	line = localisedCells.line or function(ref, length, name, hasVar)
		local s = '\n|-\n|rowspan='..length
		if hasVar
			then s = s..' style="width:6.5em; border-right:none; text-align:center; font-size:120%; font-weight:bold"| '
			else s = s..' colspan=2 style="width:6.5em; text-align:center; font-size:120%; font-weight:bold"|' end
		s = s..Lref
		if name then
			s = s..'<br/><span style="font-size:65%">'..name..'</span>' end
		return s
	end,
	
	var = localisedCells.var or function(label, length, isFirstVar)
		local s = ''
		if not isFirstVar then s = '\n|-' end
		s = s..'\n|rowspan='..length..' style="border-left:none; text-align:center; font-style:italic"|'..label
		return s
	end,
	
	operator = localisedCells.operator or function(operator, length)
		local s = '\n|rowspan='..length..' style= "text-align:center"|'..operator
		return s
	end,
	
	route = localisedCells.route or function (route, isFirstRoute, ref)
		local s = ''
		if isFirstRoute then
			s = '<span class="anchor" id="'..(ref or '')..'"></span>'
		end
		s = s..'\n| '..route
		return s
	end,
	
	relation = localisedCells.relation or function (relation)
		local s
		s = '\n|'..mw.getCurrentFrame():expandTemplate{ title = 'Relation', args = { relation } }
		return s
	end,
	
	rel_and_route = localisedCells.rel_and_route or function(relation, route, isFirstRoute, ref)
		local s = ''
		if isFirstRoute then
			s = '<span class="anchor" id="'..(ref or '')..'"></span>'
		end
		s = s..'\n|'..mw.getCurrentFrame():expandTemplate{ title = 'RelationIconLink', args = { relation } }..' '..route
		return s
	end,
	
	progress = localisedCells.progress or function(progress_state, display_text)
		local s
		if display_text then
			s = '\n|'..mw.getCurrentFrame():expandTemplate{ title = 'Progress', args = { progress_state, text = display_text } }
			else s = '\n|'..mw.getCurrentFrame():expandTemplate{ title = 'Progress', args = { progress_state } }
		end
		return s
	end,
	
	update_and_check = localisedCells.update_and_check or function(length, update_date, check_date, langObj, dateFormat)
		local s = '\n|rowspan='..length..' style="text-align:center" data-sort-value="'..(check_date or update_date or '')..'" | '
		if update_date then
			s = s..langObj:formatDate(dateFormat, update_date) end
		if check_date then
			s = s..'<br/> [[File:Yes check.svg|10px]] <span style="font-size:75%">'..langObj:formatDate(dateFormat, check_date)..'</span>'
		end
		return s
	end,
	
	other_tags = localisedCells.other_tags or function(length, tags, colour)
		local s = '\n|rowspan='..length..' style="vertical-align:top"| '
		if colour then
			s = s..mw.getCurrentFrame():expandTemplate { title = 'Tag', args = { 'colour', '', colour } }
			..' '..mw.getCurrentFrame():expandTemplate { title = 'Color sample', args = { colour } }
			if tags then s = s..'<br/>' end
		end
		if tags
		then s = s..tags end
		return s
	end,
	
	links = localisedCells.links or function(length, links)	-- links = { link1, link2,... } or { {link1, label1}, {link2,label2},... }
		local s = '\n|rowspan='..length..'| '
		if not links then return s end
		for i,l in ipairs(links) do
			if type(l) == 'table' then
				s = s..'['..l[1]..' '..l[2]..'] '
				else s = s..'['..l..' '..i..'] '
			end
		end
		return s
	end,
	
	notes = localisedCells.notes or function(length, notes)
		local s = '\n|rowspan='..length..'|'..(notes or '')
		return s
	end
}


local function first_row(ref, n_routes, Vlabel, Vlength, relation, route, progress, update, check, langObj, dateFormat, name, operator, progress_display, notes, links, tags, colour)
	local s 
	s = cells.line(ref, n_routes, name, true)					-- hasVar -> true
	s = s..cells.var(Vlabel, Vlength, true)						-- isFirstVar -> true
	s = s..cells.operator(operator, n_routes)
	s = s..cells.rel_and_route(relation, route, true, ref)		-- isFirstRoute -> true
	s = s..cells.progress(progress, progress_display)
	s = s..cells.update_and_check(Vlength, update, check, langObj, dateFormat)	-- --> (update, check, Vlength, langObj, dateFormat)
	s = s..cells.other_tags(Vlength, tags, colour)
	s = s..cells.links(n_routes, links)
	s = s..cells.notes(n_routes, notes)
	return s
end

local function first_row_no_var(ref, n_routes, operator, relation, route, progress, update, check, notes, langObj, dateFormat, name, progress_display, links, tags, colour)
	local s
	s = cells.line(ref, n_routes, name, false)					-- hasVar -> false
	s = s..cells.operator(operator, n_routes)
	s = s..cells.rel_and_route(relation, route, true, ref)		-- isFirstRoute -> true
	s = s..cells.progress(progress, progress_display)
	s = s..cells.update_and_check(n_routes, update, check, langObj, dateFormat)	-- --> (update, check, n_routes, langObj, dateFormat)
	s = s..cells.other_tags(n_routes, tags, colour)
	s = s..cells.links(n_routes, links)
	s = s..cells.notes(n_routes, notes)
	return s
end

local function short_row(relation, route, progress, progress_display)
	local s
	s = s..cells.rel_and_route(relation, route)
	s = s..cells.progress(progress, progress_display)
	return s
end

local function long_row(Vlabel, Vlength, relation, route, progress, update, check, langObj, dateFormat, progress_display, tags, colour)
	local s
	s = s..cells.var(Vlabel, Vlength)
	s = s..short_row(relation, route, progress, progress_display)
	s = s..cells.update_and_check(Vlength, update, check, langObj, dateFormat)	-- --> (update, check, Vlength, langObj, dateFormat)
	s = s..cells.other_tags(Vlength, tags, colour)
	return s
end



local function print_table_with_var()
	local line = { ref = Lref, n_routes = n_routes, name = Lname, operator = Noperator }
	local var = { label = Vlabel, length = Vlength }
	local rel = { relation = Rrel, route = Rroute, progress = Rprogr, progress_display = {} }
	local upd = { update = Vupdate, check = Vcheck }
	local info = { notes = Lnotes, links = {}, tags = Vtags, colour = Lcolour }
	local loc = { langObj = Wlang, dateFormat = dateFormat }
	local rep_P, nrep_P = nP, nrP
	local s
	local Ri = 1
	s = first_row(line.ref, line.n_routes, var.label[1], var.length[1], rel.relation[1], rel.route[1], rel.progress[1], upd.update[1], upd.check[1], loc.langObj, loc.dateFormat, line.name, line.operator, rel.progress_display[1], info.notes, info.links[1], info.tags[1], info.colour)
	for j=Ri+1,var.length[1] do
		s = s..short_row(rel.relation[j], rel.route[j], rel.progress[j], rel.progress_display[j])
	end
	Ri = Ri + var.length[1]
	for Vi=2,#var.label do
		local Ui = Vi
		s = s..long_row(var.label[Vi], var.length[Vi], rel.relation[Ri], rel.route[Ri], rel.progress[Ri], upd.update[Ui], upd.check[Ui], loc.langObj, loc.dateFormat, rel.progress_display[Ri], info.tags[Ui], info.colour)
		for j=Ri+1,Ri-1+var.length[Vi] do
			s = s..short_row(rel.relation[j], rel.route[j], rel.progress[j], rel.progress_display[j])
		end
		Ri = Ri + var.length[Vi]
	end
	return s
end

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

local function make_var(ref, label, length, update, check, Rroute, Rrel, Rprogr, Ri, colour, tags, notes, Wlang, dateFormat, isFirstVar)
		-- (line = { ref, colour}, var = { label, length, update, check, tags}, routes = { { Rroute, Rrel, Rprogr }, Ri }, general = { Wlang, dateFormat }, isFirstVar)
	local s = ''
	s = s..cells.var(label, length, isFirstVar)
	s = s..cells.rel_and_route(Rrel[Ri], Rroute[Ri], Ri==1, ref)
	s = s..cells.progress(Rprogr[Ri])
	s = s..cells.update_and_check(length, update, check, Wlang, dateFormat)
	s = s..cells.other_tags(length, tags, colour)
	if isFirstVar then
		s = s..cells.links(#Rroute)
		s = s..cells.notes(#Rroute, notes)
	end
	for i=1,length-1 do
		s = s..'\n|-'
		s = s..cells.rel_and_route(Rrel[Ri+i], Rroute[Ri+i])
		s = s..cells.progress(Rprogr[Ri+i])
	end
	return s
end

local function make_line()	--( line = { ref, ... })
	local s = ''
	local Ri = 1
	s = s..cells.line(Lref, n_routes, Lname, Vlabel[1])
	if Vlabel[1] then
		for Vi in ipairs(Vlabel) do
			s = s..make_var(Lref, Vlabel[Vi], Vlength[Vi], Vupdate[Vi], Vcheck[Vi], Rroute, Rrel, Rprogr, Ri, Lcolour, Vtags[Vi], Lnotes, Wlang, dateFormat, Vi==1)
			Ri = Ri + Vlength[Vi]
		end
	else
		s = s..cells.rel_and_route(Rrel[1], Rroute[1], true, Lref)
		s = s..cells.progress(Rprogr[1])
		s = s..cells.update_and_check(n_routes, Vupdate[1], Vcheck[1], Wlang, dateFormat)
		s = s..cells.other_tags(n_routes, Vtags[1], Lcolour)
		s = s..cells.links(n_routes)
		s = s..cells.notes(n_routes, Lnotes)
		Ri = Ri + 1
		for i=2,n_routes do
			s = s..'\n|-'
			s = s..cells.rel_and_route(Rrel[i], Rroute[i])
			s = s..cells.progress(Rprogr[i])
		end
	end
	return s
end

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

function p.generic(frame)
	
	local tmplt = {}
	local options = {}
	local loc = {}
	local line = {}
	local var = {}
	local rel = {}
	local upd = {}
	local info = {}
	
	args = getArgs(frame, {			--> local localisedArgs = ...
		trim = false,
		removeBlanks = false,
		frameOnly = false,
		parentOnly = false,
		parentFirst = true,
		readOnly = false,
		noOverwrite = false
	})
	
	_, Wlang, paramLangCode = translateArgs(frame, args)
	--	args, loc.langObj, loc.paramLangCode = translateArgs(frame, args) --> localisedArgs
	
	dateFormat, rP, nrP = setParams.general(frame, args)
	--	loc.dateFormat = args['dateFormat'] or 'j F Y'
	--	local tmplt.rep_P, tmplt.nrep_P = args['rep_p'] or 1, args['nrep_P'] or 3
	
	Nnetwork, Noperator = setParams.network(frame, args)
	--	line.operator = args['operator'] or ''
	
	Lref, Lname, Lcolour, Lnotes = setParams.line(frame, args)
	--	line.ref = args[1] or ''
	--	line.name = args['name'] or nil
	--	info.colour = args.colour ~= '' and args['colour'] or nil
	--	info.notes = args['notes'] or nil
	
	Vlabel, Vlength, Vupdate, Vcheck, Vtags, n_var = setParams.variants(frame, args)
	--	var = --> new function
	
	Rroute, Rrel, Rprogr, n_routes = setParams.routes(frame, args, rP, nrP)
	--	rel = --> new function
	--	var.count, rel.count = #var.label, #rel.route
	
	local s = make_line()
	--	local s = print_table(line,rel,upd,info,var,options,loc)
	return s
end


return p