Module:RankedWars: Difference between revisions

From NPOWiki
Jump to navigation Jump to search
use /data
use error module
 
(3 intermediate revisions by the same user not shown)
Line 1: Line 1:
--todo:
--todo:
-- Handle ongoing wars (end = 0)
-- Handle ongoing wars (end = 0) - existing logic is untested
-- Add function to get title+disambig of a war for easier linking to correct section, or full link including faction
-- War lookup without faction (special case for internal) - remember to use faction name not shell name.
-- War lookup without faction (special case for internal) - remember to use faction name not shell name.
-- Use "clear" template (need to make it)
-- Add overall and per-faction stats - most fought opponents, shortest/longest wars, most/least score, most contested (total score), etc
-- Fix "1 hours"/"1 wars"
-- See todos in JS
local data = mw.loadData('Module:RankedWars/data')
local data = mw.loadData('Module:RankedWars/data')
local jsonData = mw.loadJsonData('Module:RankedWars/data.json')
local jsonData = mw.loadJsonData('Module:RankedWars/data.json')
local err = require('Module:Error').call


local p = {}
local p = {}
Line 24: Line 26:
local capName = factionName(faction)
local capName = factionName(faction)
local overall = jsonData.wars.overall[faction]
local overall = jsonData.wars.overall[faction]
local warplural = 'wars'
if overall.wars == 1 then
warplural = 'war'
end
return table.concat({
return table.concat({
Line 29: Line 35:
'has participated in',
'has participated in',
overall.wars,
overall.wars,
'ranked wars, winning',
'ranked ' .. warplural .. ', winning',
overall.wins,
overall.wins,
'(' .. overall.termedWins .. ' termed)',
'(' .. overall.termedWins .. ' termed)',
Line 41: Line 47:
local capName = factionName(faction)
local capName = factionName(faction)
local warData = jsonData.wars[faction][warId]
local warData = jsonData.wars[faction][warId]
local frame = mw.getCurrentFrame()
local ongoing = false
if warData['end'] == 0 then
ongoing = true
warData.note = 'This war is ongoing.'
end
local outcome = 'fought'
local outcome = 'fought'
if warData.win then
if ongoing then
outcome = 'won against'
outcome = 'is fighting'
elseif warData.win then
outcome = frame:expandTemplate({
title = 'color',
args = { 'green', 'bold', 'won' }
}) .. ' against'
else
else
outcome = 'lost to'
outcome = frame:expandTemplate({
title = 'color',
args = { 'red', 'bold', 'lost' }
}) .. ' to'
end
end
local terms = 'war'
local terms = 'war'
if warData.termed then
if warData.termed then
terms = 'termed war'
terms = frame:expandTemplate({
title = 'color',
args = { 'sandybrown', 'termed' }
}) .. ' war'
end
end
local opponent = mw.getCurrentFrame():expandTemplate({
local opponent = frame:expandTemplate({
title = 'Tornp',
title = 'Tornp',
args = { warData.oppName }
args = { warData.oppName }
})
})
local hours = '?'
if not ongoing then
hours = string.format('%.0f', (warData['end'] - warData['start']) / 3600)
end
local hourplural = 'hours'
if tonumber(hours) == 1 then
hourplural = 'hour'
end
return mw.text.trim(table.concat({
return mw.text.trim(table.concat({
Line 66: Line 98:
os.date('!%F %T TCT', warData.start),
os.date('!%F %T TCT', warData.start),
'and lasted',
'and lasted',
string.format('%.0f', (warData['end'] - warData['start']) / 3600),
hours .. ' ' .. hourplural .. '.',
'hours. With a lead target of',
'With a lead target of',
warData.target .. ',',
warData.target .. ',',
capName,
capName,
Line 83: Line 115:
local wars = jsonData.wars[faction]
local wars = jsonData.wars[faction]
local out = ''
local out = ''
local frame = mw.getCurrentFrame()
--The JSON sorts the wars numerically and pairs is random, we want newest first
--The JSON sorts the wars numerically and pairs is random, we want newest first
Line 123: Line 156:
end
end
if warpage then
if warpage then
out = out .. mw.getCurrentFrame():expandTemplate({
out = out .. frame:expandTemplate({
title = 'main',
title = 'main',
args = { warpage }
args = { warpage }
Line 135: Line 168:
end
end
out = out .. '*[https://www.torn.com/war.php?step=rankreport&rankID=' .. warData.id .. ' War report on Torn]\n'
out = out .. '*[https://www.torn.com/war.php?step=rankreport&rankID=' .. warData.id .. ' War report on Torn]\n'
out = out .. '<br style="clear:both;" />\n'
out = out .. frame:expandTemplate({ title='clear' }) .. '\n'
out = out .. '\n'
out = out .. '\n'
end
end
Line 148: Line 181:
function p.call(args)
function p.call(args)
local faction, war, mode
local faction, war, mode
if not args then args = {} end
if args[1] then
if args[1] then
Line 155: Line 189:
war = tonumber(args[2])
war = tonumber(args[2])
end
end
mode = args.mode
mode = mw.ustring.lower(args.mode or '')
args['has page'] = mw.ustring.gsub(
args['has page'] = mw.ustring.gsub(
',' .. (args['has page'] or '') .. ',',
',' .. (args['has page'] or '') .. ',',
Line 162: Line 196:
)
)
if not faction and not (mode == 'json') then
if not faction and mode ~= 'json' then
return '<span class="error">faction is currently required</span>'
return err('faction is currently required')
end
end
if faction and not data.factions[faction] then
if faction and not data.factions[faction] then
return '<span class="error">incorrect faction name</span>'
return err('incorrect faction name')
end
end
if faction and war and not jsonData.wars[faction][war] then
if faction and war and not jsonData.wars[faction][war] then
return '<span class="error">specified war not found for the given faction</span>'
return err('specified war not found for the given faction')
end
end
Line 179: Line 213:
elseif mode == 'war' then
elseif mode == 'war' then
if not war then
if not war then
return '<span class="error">war id must be specified for war lookup</span>'
return err('war id must be specified for war lookup')
end
end
return displayWarData(faction, war)
return displayWarData(faction, war)
Line 185: Line 219:
return displayDataJson(args.ugly)
return displayDataJson(args.ugly)
elseif mode then
elseif mode then
return '<span class="error">unrecognized mode</span>'
return err('invalid mode')
else
else
return '<span class="error">mode is currently required</span>'
return err('mode is currently required')
end
end
end
end


return p
return p

Latest revision as of 10:53, 21 October 2025

Documentation [edit]

This page is a stub - it only covers the very basics of its subject. More information should be added to make the page informative and useful. If no more information is available, the page should be considered for a merge, redirect, or deletion.

Details: documentation to be written

If you can correct the issue, please edit the page to do so, then remove this notice.

Please see Template:Ranked war for usage information. Use the template rather than invoking the module. Data for this module is imported from Module:RankedWars/data and Module:RankedWars/data.json.

For how to update data, please see Module:RankedWars/data/doc.

The above documentation is transcluded from Module:RankedWars/doc.

--todo:
--	Handle ongoing wars (end = 0) - existing logic is untested
--	Add function to get title+disambig of a war for easier linking to correct section, or full link including faction
--	War lookup without faction (special case for internal) - remember to use faction name not shell name.
--	Add overall and per-faction stats - most fought opponents, shortest/longest wars, most/least score, most contested (total score), etc
--	See todos in JS
local data = mw.loadData('Module:RankedWars/data')
local jsonData = mw.loadJsonData('Module:RankedWars/data.json')
local err = require('Module:Error').call

local p = {}

local function factionName(facKey)
	return mw.ustring.upper(mw.ustring.sub(facKey, 1, 1)) .. mw.ustring.sub(facKey, 2)
end

local function displayDataJson(ugly)
	local flag = mw.text.JSON_PRETTY
	if ugly and ugly ~= '' then
		flag = 0
	end
	return mw.text.jsonEncode(data, flag)
end

local function displayFactionStats(faction)
	local capName = factionName(faction)
	local overall = jsonData.wars.overall[faction]
	local warplural = 'wars'
	if overall.wars == 1 then
		warplural = 'war'
	end
		
	return table.concat({
		'NPO - ' .. capName,
		'has participated in',
		overall.wars,
		'ranked ' .. warplural .. ', winning',
		overall.wins,
		'(' .. overall.termedWins .. ' termed)',
		'and losing',
		overall.losses,
		'(' .. overall.termedLosses .. ' termed).',
	}, ' ')
end

local function displayWarData(faction, warId)
	local capName = factionName(faction)
	local warData = jsonData.wars[faction][warId]
	local frame = mw.getCurrentFrame()
	
	local ongoing = false
	if warData['end'] == 0 then
		ongoing = true
		warData.note = 'This war is ongoing.'
	end
		
	local outcome = 'fought'
	if ongoing then
		outcome = 'is fighting'
	elseif warData.win then
		outcome = frame:expandTemplate({
			title = 'color',
			args = { 'green', 'bold', 'won' }
		}) .. ' against'
	else
		outcome = frame:expandTemplate({
			title = 'color',
			args = { 'red', 'bold', 'lost' }
		}) .. ' to'
	end
	local terms = 'war'
	if warData.termed then
		terms = frame:expandTemplate({
			title = 'color',
			args = { 'sandybrown', 'termed' }
		}) .. ' war'
	end
	local opponent = frame:expandTemplate({
		title = 'Tornp',
		args = { warData.oppName }
	})
	local hours = '?'
	if not ongoing then
		hours = string.format('%.0f', (warData['end'] - warData['start']) / 3600)
	end
	local hourplural = 'hours'
	if tonumber(hours) == 1 then
		hourplural = 'hour'
	end
	
	return mw.text.trim(table.concat({
		'NPO - ' .. capName,
		outcome,
		opponent,
		'in a',
		terms,
		'that started at',
		os.date('!%F %T TCT', warData.start),
		'and lasted',
		hours .. ' ' .. hourplural .. '.',
		'With a lead target of',
		warData.target .. ',',
		capName,
		'scored',
		warData.ourScore,
		'while the opponent scored',
		warData.oppScore .. '.',
		warData.note or '',
	}, ' '))
end

local function displayWarHistory(faction, args)
	local warIDs = {}
	local repeats = {}
	local wars = jsonData.wars[faction]
	local out = ''
	local frame = mw.getCurrentFrame()
	
	--The JSON sorts the wars numerically and pairs is random, we want newest first
	for warID, warData in pairs(wars) do
		table.insert(warIDs, 1, warID)
		if repeats[warData.oppName] then
			repeats[warData.oppName] = repeats[warData.oppName] + 1
		else
			repeats[warData.oppName] = 1
		end
	end
	table.sort(warIDs, function(wa, wb)
		return wb < wa
	end)
	
	for _, id in ipairs(warIDs) do
		local warData = wars[id]

		local heading = warData.oppName
		local disambig
		if repeats[warData.oppName] > 1 then
			disambig = os.date('!%b %Y', warData.start)
			heading = heading .. ' (' .. disambig .. ')'
		end
		out = out .. '===' .. heading .. '===\n'
		
		local filename = faction .. ' vs ' .. warData.oppName
		if disambig then
			filename = filename .. ' (' .. disambig .. ')'
		end
		filename = filename .. ' ranked war graph.png'
		out = out .. '[' .. '[' .. 'File:' .. filename .. '|right|400px|alt=Ranked war graph]]\n'
		
		local warpage
		if mw.ustring.find(args['has page'], ',' .. warData.id .. ',', 1, true) then
			warpage = warData.oppName .. ' Ranked War'
			if disambig then
				warpage = warpage .. ' (' .. disambig .. ')'
			end
		end
		if warpage then
			out = out .. frame:expandTemplate({
				title = 'main',
				args = { warpage }
			}) .. '\n'
		end
		
		out = out .. displayWarData(faction, warData.id) .. '\n'
		local blurb = args[tostring(warData.id)]
		if blurb then
			out = out .. '\n' .. blurb .. '\n'
		end
		out = out .. '*[https://www.torn.com/war.php?step=rankreport&rankID=' .. warData.id .. ' War report on Torn]\n'
		out = out .. frame:expandTemplate({ title='clear' }) .. '\n'
		out = out .. '\n'
	end
	
	return out
end

function p.main(frame)
	return p.call(frame:getParent().args)
end

function p.call(args)
	local faction, war, mode
	if not args then args = {} end
	
	if args[1] then
		faction = mw.ustring.lower(args[1])
	end
	if args[2] then
		war = tonumber(args[2])
	end
	mode = mw.ustring.lower(args.mode or '')
	args['has page'] = mw.ustring.gsub(
		',' .. (args['has page'] or '') .. ',',
		' ',
		''
	)
	
	if not faction and mode ~= 'json' then
		return err('faction is currently required')
	end
	
	if faction and not data.factions[faction] then
		return err('incorrect faction name')
	end
	if faction and war and not jsonData.wars[faction][war] then
		return err('specified war not found for the given faction')
	end
	
	if mode == 'history' then
		return displayWarHistory(faction,  args)
	elseif mode == 'overall' then
		return displayFactionStats(faction)
	elseif mode == 'war' then
		if not war then
			return err('war id must be specified for war lookup')
		end
		return displayWarData(faction, war)
	elseif mode == 'json' then
		return displayDataJson(args.ugly)
	elseif mode then
		return err('invalid mode')
	else
		return err('mode is currently required')
	end
end

return p