Module:Jctrdt

local p = {}

-- Change to "" upon deployment.
local moduleSuffix = ""

local parserModuleName = "Module:Road data/parser" .. moduleSuffix
local statenameModuleName = "Module:Jct/statename" .. moduleSuffix -- TODO transition
local cityModuleName = "Module:Jct/city" .. moduleSuffix

local concat = table.concat
local insert = table.insert
local format = mw.ustring.format
local trim = mw.text.trim

local parserModule = require(parserModuleName)
local parser = parserModule.parser
local util = require("Module:Road data/util")

-- Shields
local defaultShieldSize = 17

local function addContextBanner(route, name, suffix, bannerSpec)
	local bannerModule = 'Module:Road data/banners/' .. string.upper(route.country)
	local shieldfield = name .. 'shield'
	local shield = parser(route, shieldfield)
	if shield == nil then
		-- This route type does not define shield.
		-- Find shield in the default banner table.
		shield = parser(route, 'shield', name, bannerModule)
		if shield and shield ~= '' then
			if suffix == nil then
				suffix = parser(route, 'shield', 'suffix', bannerModule)
			end
			if suffix and suffix ~= '' then
				shield = shield .. " " .. suffix
			end
			shield = shield .. ".svg"
		end
	end
	if shield and shield ~= '' then
		local shieldSize = defaultShieldSize
		-- Add banner plate.
		insert(bannerSpec, {shield, shieldSize})
	end
end

local function bannerSpec(banner, bannerSize, bannerSuffix, route)
	local banners = {}
	if type(banner) == "table" then
		local bannerSizeIsNotTable = type(bannerSize) ~= "table"
		for i,filename in ipairs(banner) do
			local bannersize = bannerSizeIsNotTable and bannerSize or bannerSize[i] or defaultShieldSize
			insert(banners, {filename, bannersize})
		end
	elseif banner ~= '' then
		insert(banners, {banner, bannerSize})
	end

	if route.dir then
		addContextBanner(route, 'dir', bannerSuffix, banners)
	end
	if route.to then
		addContextBanner(route, 'to', bannerSuffix, banners)
	end

	return banners
end

local function shieldSpec(route, mainShield)
	local shieldSpec = {}

	local shield
	if mainShield then shield = parser(route, "shieldmain") end
	if not shield then shield = parser(route, 'shield') or '' end
	if shield == '' then return shieldSpec end
	local orientation = parser(route, 'orientation')

	local shieldsize = defaultShieldSize
	
	local banner = parser(route, 'banner') or {}
	local bannersize = defaultShieldSize
	local bannersuffix = parser(route, 'bannersuffix')

	local bannerIsNotTable = type(banner) ~= "table"
	local bannersizeIsNotTable = type(bannersize) ~= "table"
	local bannersuffixIsNotTable = type(bannersuffix) ~= "table"

	if type(shield) == "table" then
		for i,filename in ipairs(shield) do
			local size = shieldsize or shieldsize[i]
			if size == "" then size = nil end
			-- banner.all describes banners that apply to all multiple shields.
			local shieldBanner = bannerIsNotTable and banner or (banner[i] or banner.all or {})
			-- Banner size is default if the corresponding entry
			-- in bannerSize table is not set.
			local shieldBannerSize =
				bannersizeIsNotTable and bannersize
				or (bannersize[i] or bannersize.all or defaultShieldSize)
			local shieldBannerSuffix = bannersuffix and (bannersuffixIsNotTable and bannersuffix or bannersuffix[i])
			insert(shieldSpec, {
				shield = {filename, size},
				banners = bannerSpec(shieldBanner, shieldBannerSize, shieldBannerSuffix, route)
			})
		end
	elseif shield ~= '' then
		if shieldsize == "" then shieldsize = nil end
		insert(shieldSpec, {
			shield = {shield, shieldsize},
			banners = bannerSpec(banner, bannersize,  bannersuffix, route)
		})
	end

	return shieldSpec
end

local missingShields

local shieldExistsCache = {}

-- Return up to two booleans.
-- The first boolean is false if `shield` does not exist, and true otherwise.
-- If the first boolean is true, the second boolean is true if the shield is
-- landscape (width >= height), and false otherwise.
local function shieldExists(shield)
	local result = shieldExistsCache[shield]
	if result == nil then
		local file = mw.title.new(shield, 'Media').file
		-- Cache result.
		local exists = file.exists
		result = {exists}
		if exists then result[2] = file.width >= file.height end
		shieldExistsCache[shield] = result
	end
	if result[1] then return true, result[2] end
	insert(missingShields, shield)
	return false
end

local function render(shieldEntry, scale, showLink)
	local shield = shieldEntry.shield
	local banners = shieldEntry.banners
	local exists, landscape = shieldExists(shield[1])
	if not exists then return '' end

	local size
	if shield[2] then
		local width, height = mw.ustring.match(shield[2], "(%d*)x?(%d*)")
		width = tonumber(width)
		height = tonumber(height)
		local sizeparts = {}
		if width then
			insert(sizeparts, format("%d", width * scale))
		end
		if height then
			insert(sizeparts, format("x%d", height * scale))
		end
		size = concat(sizeparts)
	else
		size = format("%s%d", landscape, defaultShieldSize * scale)
	end
	local link = showLink and "" or "|link="
	local shieldCode = format("[[File:%s|x%spx%s|%s]]", shield[1], size, link, shield[1])
	if not banners[1] then return shieldCode end

	for _,banner in ipairs(banners) do
		shieldCode = format("[[File:%s|%spx|link=|alt=]]<br>%s",
			banner[1],
			defaultShieldSize,
			shieldCode)
	end
	return '<span style="display: inline-block; vertical-align: baseline; line-height: 0; text-align: center;">' .. shieldCode .. '</span>'
end

function p.shield(route, scale, showLink, mainShield)
	missingShields = {}

	scale = 1

	local rendered = {}
	for _,entry in ipairs(shieldSpec(route, mainShield)) do
		insert(rendered, render(entry, scale, showLink))
	end
	return concat(rendered)
end

function p.link(route)
	local abbr, errMsg = parser(route, 'abbr')
	if not abbr then end
	if route.nolink then return abbr, abbr end

	local link = parser(route, 'link') or ''
	if link == '' then return abbr, abbr end

	return format("[[%s|%s]]", link, abbr), abbr
end

local function stateName(args)
	-- TODO transition
	local data = mw.loadData(statenameModuleName) 
	local abbr = args.state or args.province
	local countryData = data[args.country]
	return countryData and countryData[abbr]
end

-- Links/abbreviations
local function routeText(route, frame)
	local link
	local type = route.type
	if not type or type == '' then
		link = route.route
	else
		link = p.link(route)
	end

	local dir = route.dir and ' ' .. string.lower(route.dir) or ''
	local routeText = link .. dir

	local name = route.name
	if name and name ~= '' then
		local mainText = routeText
		local parenText = name

	return frame:expandTemplate{ title = 'BSsplit', args = {mainText, parenText, align = 'left', valign = 'middle' } }
	else
		return routeText
	end
end

local function parseArgs(args)
	local state = args.state or args.province or ''
	args.state = state
	local country
	if args.country and args.country ~= '' then
		country = string.upper(args.country)
	else
		local countryModule = mw.loadData("Module:Road data/countrymask")
		country = countryModule[state] or 'UNK'
	end
	args.country = country

	local params = {'denom', 'county', 'township', 'dab', 'nolink', 'noshield', 'to', 'dir', 'name'}
	local routes = {}
	local routeCount = 1
	local seenTo = false
	while true do
		local routeType = args[routeCount * 2 - 1]
		if not routeType then break end
		local route = {type = routeType, route = args[routeCount * 2]}
		for _,v in pairs(params) do
			route[v] = args[v .. routeCount]
		end
		route.country = country
		route.state = state

		-- Set the first .to to true.
		-- Set all following .to to ''.
		if seenTo then
			if route.to then
				-- Report duplicate to flag.
				route.toerror = true
			end
			route.to = ''
		elseif route.to then
			route.to = true
			seenTo = true
		end

		route.rdt = args.rdt
		insert(routes, route)
		routeCount = routeCount + 1
	end
	return routes
end

local function prefix(to, num)
	if to and to ~= '' then
		return num == 1 and 'To ' or ' to '
	end
	return num == 1 and '' or '&nbsp;/ '
end

function p._jctrdt(args, frame)
	local routes = parseArgs(args)
	local shields = {}
	local links = {}
	frame = frame or mw.getCurrentFrame()
	for num,route in ipairs(routes) do
		if not (args.noshield or route.noshield) then
			local shield = p.shield(route)
			insert(shields, shield)
		end
		local prefix = prefix(route.to, num)
		if prefix ~= '' then insert(links, prefix) end
		insert(links, routeText(route, frame))
	end
	local graphics = concat(shields) .. ' '
	local linkText = concat(links)
	local cities = ''
	if args.city1 or args.location1 then
		local citiesPrefix
		if args.citiesprefix then
			citiesPrefix = args.citiesprefix ~= '' and format(" %s ", args.citiesprefix) or ''
		else
			citiesPrefix = '&nbsp;'
		end
		local cityModule = require(cityModuleName)
		cities = citiesPrefix .. cityModule.city(args)
	end

	return graphics .. linkText .. cities
end

function p.jctrdt(frame)
	-- Import module function to work with passed arguments
	local getArgs = require('Module:Arguments').getArgs
	local args = getArgs(frame, {removeBlanks = false})
	return p._jctrdt(args, frame)
end

return p

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.