Module:RankedWars/data/doc: Difference between revisions

From NPOWiki
Jump to navigation Jump to search
for safekeeping
 
updated the updating
Line 1: Line 1:
{{documentation subpage}}
{{documentation subpage}}


Run the following code on the /data page and copy the result from the console to [[Module:RankedWars/data.json]]. Be sure to fill in your public API key on the second line.
Faction shell and RW corrections information are updated directly in this module. To update ranked war history data, see below.
 
==Updating ranked wars==
To update ranked wars data, run the following code on this page and copy the result from the console to [[Module:RankedWars/data.json]]. Be sure to fill in your public API key on the second line. Make sure there are no errors in the editor or the saved page.


{{collapsible content|title=Expand to show code|state=collapsed|width=50%|
{{collapsible content|title=Expand to show code|state=collapsed|width=50%|
<syntaxhighlight lang="javascript" copy="copy">
<syntaxhighlight lang="javascript" copy="copy">
//Get each of our factions' RW history from the Torn API, calculate stats, and output json format for storage.
//Get each of our factions' RW history from the Torn API, calculate stats, and output json format for storage.
//Requires faction and war correction data, which instead of requesting through the MediaWiki API, we grab from the module page.
// Meaning this script must be run on either Module:RankedWars/data or that page's /doc page.
//By Bobogoobo [2618206] for NPOWiki
//By Bobogoobo [2618206] for NPOWiki
(function () {
(function () {
//todo: store constants in a data module and run script from that page, instead of having to update two places every time. Easier to import elsewhere also. JSON would be 'wars' only.
var apiKey = '';// requires public access key
var apiKey = '';// requires public access key
if (!apiKey) return 'API key required';
if (!apiKey) return 'API key required';
var rw_release = '2021-12-07';
//Full list of shells we have used. Please keep shell lists in reverse chronological order.
//JS generally does, but is not guaranteed to, give things back in the order you do them.
//Dates are approximate due to transition time, merely following official announcements.
//Things get mixed up in between Lua -> JSON - > JS, so we want to be sure to iterate in this order when generating the output.
//Ranges are contiguous to avoid missing any events.
var factionOrder = ['strength', 'prosperity', 'endurance', 'valour', 'serenity', 'peace'];
var factions = {
strength: [
var jsonData = document.getElementById('rw-json-data');
{
if (!jsonData) {
label: 'Current shell',
return 'JSON not found. Are you running this on the "Module:RankedWars/data" page?';
id: 10610,
}
start: '2022-10-03',
jsonData = JSON.parse(jsonData.firstElementChild.textContent);
end: '',
var factions = jsonData.factions;
},
var corrections = jsonData.corrections;
{
label: 'Old shell (now Prosperity)',
id: 44758,
start: '2020-02-09',
end: '2022-10-03',
},
],
prosperity: [
{
label: 'Current shell',
id: 44758,
start: '2022-10-14',
end: '',
},
{
label: 'Old shell (sold to PimpChu)',
id: 11162,
start: '2021-10-16',
end: '2022-10-14',
},
{
label: 'Older shell (now Cry of the Lost)',
id: 44751,
start: '2020-02-09',
end: '2021-10-16',
},
],
endurance: [
{
label: 'Current shell',
id: 12645,
start: '2024-05-05',
end: '',
},
{
label: 'Old shell (now Serenity)',
id: 14052,
start: '2022-08-03',
end: '2024-05-05',
},
],
valour: [
{
label: 'Current shell',
id: 26885,
start: '2023-12-31',
end: '',
},
],
serenity: [
{
label: 'Current shell',
id: 14052,
start: '2024-05-05',
end: '',
},
],
peace: [
{
label: 'Current shell',
id: 18714,
start: '2022-07-16',
end: '',
},
],
};
//Indexed by RW id, please keep in reverse chronological order (i.e. descending).
//Note that NPO faction name will be automatically corrected from the shell list.
//Only note termed if it WAS termed. Use notes only in extreme cases.
//Possible keys: opponent (string), termed (boolean), note (string)
//***** LAST UPDATED: STR V NAUGHTY SOULS 19 SEP *****//
var corrections = {
30645: { termed: true },
29810: { termed: true },
29532: { termed: true },
29101: { termed: true },
26763: { termed: true },
26698: { termed: true },
26378: { termed: true },
25785: { termed: true },
25233: { termed: true },
25092: { termed: true },
24748: { termed: true },
23498: { termed: true },
23168: { termed: true },
22993: { termed: true },
22809: { termed: true },
22648: { termed: true },
22621: { termed: true },
22547: { termed: true },
22408: { termed: true },
21844: { termed: true },
21648: { termed: true },
21417: { termed: true },
21146: { note: 'uncontested' },
19540: { termed: true },
18181: { termed: true },
17986: { termed: true },
17544: { termed: true },
17403: { termed: true },
17128: { termed: true },
16972: { termed: true },
16603: { termed: true },
16061: { termed: true },
15850: { termed: true },
15559: { termed: true },
15425: { termed: true },
15107: { termed: true },
15016: { termed: true },
11546: { termed: true },
11136: { termed: true },
9765: { termed: true },
9588: { termed: true },
9418: { termed: true },
9310: { termed: true },
9302: { termed: true },
7633: { termed: true },
7066: { termed: true },
7103: { termed: true },
7015: { termed: true },
6444: { termed: true },
6384: { termed: true },
5536: { termed: true },
5341: { termed: true },
5307: { termed: true },
5190: { termed: true },
3706: { termed: true },
3632: { termed: true },
3536: { termed: true },
3439: { termed: true },
3305: { termed: true },
3253: { termed: true },
1592: { opponent: '39th Street Killers XR' },
};
//todo: add corrections from history file - just need to look at names next. May need to make some exceptions for when we fight ourselves?
//todo: I put termed for anything that says Derank, but some of the early ones predate terming and there may not have been an official agreement.
//todo: I put termed for anything that says Derank, but some of the early ones predate terming and there may not have been an official agreement.
// Can usually tell from score anyway, but may want to put notes where needed
// Can usually tell from score anyway, but may want to put notes where needed
var wars = {// wars by faction, newest first; keys same as in "factions"
// wars by faction, newest first (gets reversed in JSON); keys same as in "factions"
var wars = {
overall: {},
overall: {},
};
};
Line 214: Line 84:
function processWarHistory(data, shell, facName, offset, limit) {
function processWarHistory(data, shell, facName, offset, limit) {
data.rankedwars.forEach(function (war) {
data.rankedwars.forEach(function (war) {
var relevant = false;
//Wars that started or ended outside of the shell's range will not be included
//todo: simplify?
if (war.start > shell.startUnix && (war.end || Infinity) < (shell.endUnix || Infinity)) {
if (war.start > shell.startUnix && (!shell.endUnix || war.start < shell.endUnix)) {
//War started after shell, and shell is current or war started before shell ended
relevant = true;
} else if ((shell.endUnix && war.end && war.end < shell.endUnix) || (!shell.endUnix && !war.end)) {
//Shell ended and war ended before it, or shell and war are current
relevant = true;
} else if (war.end && war.end > shell.startUnix && war.end < shell.endUnix) {
//War ended after shell started but before it ended
relevant = true;
}
if (relevant) {
var usFirst = war.factions[0].id === shell.id;
var usFirst = war.factions[0].id === shell.id;
var usData = war.factions[+!usFirst];
var usData = war.factions[+!usFirst];
var themData = war.factions[+usFirst];
var themData = war.factions[+usFirst];
// "chain" property appears to be worthless. Not sure about forfeit?
// "chain" property appears to be worthless, and "forfeit" very unlikely.
var warData = {
var warData = {
id: war.id,
id: war.id,
Line 270: Line 129:
function finalize() {
function finalize() {
Object.keys(factions).forEach(function (faction) {
factionOrder.forEach(function (faction) {
wars.overall[faction] = {
var stats = {
wars: 0,
wars: 0,
wins: 0,
wins: 0,
Line 278: Line 137:
termedLosses: 0,
termedLosses: 0,
};
};
var stats = wars.overall[faction];
Object.keys(wars[faction]).forEach(function (war) {
Object.keys(wars[faction]).forEach(function (war) {
war = wars[faction][war]
war = wars[faction][war];
stats.wars += 1;
stats.wars += 1;
if (war.win) {
if (war.win) {
Line 294: Line 152:
}
}
});
});
wars.overall[faction] = stats;
});
});
console.log(JSON.stringify({factions, wars, corrections}, null, '\t'));
var output = {
_meta: {
documentation: ' https://wiki.npowned.net/view/Module:RankedWars/data.json/doc '
},
wars,
}
console.log(JSON.stringify(output, null, '\t'));
console.log(requests);
console.log(requests);
//todo
//todo
}
}
Object.keys(factions).forEach(function (faction, i) {
factionOrder.forEach(function (faction, i) {
var limit = 100;// maximum limit
var limit = 100;// maximum limit for Torn RW API
wars[faction] = {};
wars[faction] = {};
Line 315: Line 180:
});
});
//todo: consider if worth calling rankedwarreport - definitely would be nice to have full stats.
//todo: consider if worth calling rankedwarreport - definitely would be nice to have full stats.
// Maybe a separate script that can pull from this one's output? Although having it all together and only one script to run would be nice
// Maybe a separate script that can pull from this one's output? Although having it all together and only one script to run/page to update would be nice
//todo: war 14015 was fought by END on May 10-11 2024, need to adjust shell move date to Serenity.
//todo: war graphs for in-family wars will be duplicate files
//need more ways to make the pages visually interesting and not samey - point out important/contested wars. Could color code things for at a glance? (With icons perhaps)
//todo for module: fun stats - most fought opponents, ...
//should have something to get at least the appropriate section link for a given war, or just name+disambig in general, since they can change
//don't have anything to handle having pages for wars against the same opponent by different NPO factions...
//adding blurbs needs to be done...
})();
})();
</syntaxhighlight>
</syntaxhighlight>
}}
==JSON==
This is taken from the module content and used by the script. It does not need to be expanded for the script to work.
{{collapsible content|title=Expand to show JSON data|state=collapsed|width=50%|
{{#tag:syntaxhighlight|{{ranked war|mode=json}}|lang=json|copy=copy|id=rw-json-data}}
}}
}}


<includeonly>[[Category:Lua data modules]]</includeonly>
<includeonly>[[Category:Lua data modules]]</includeonly>

Revision as of 20:19, 17 October 2025

This page contains the documentation for Module:RankedWars/data. It includes information about the module, such as usage and categories, and is not displayed when using the module itself.

Faction shell and RW corrections information are updated directly in this module. To update ranked war history data, see below.

Updating ranked wars

To update ranked wars data, run the following code on this page and copy the result from the console to Module:RankedWars/data.json. Be sure to fill in your public API key on the second line. Make sure there are no errors in the editor or the saved page.

Expand to show code
//Get each of our factions' RW history from the Torn API, calculate stats, and output json format for storage.
//Requires faction and war correction data, which instead of requesting through the MediaWiki API, we grab from the module page.
//	Meaning this script must be run on either Module:RankedWars/data or that page's /doc page.
//By Bobogoobo [2618206] for NPOWiki
(function () {
	var apiKey = '';// requires public access key
	if (!apiKey) return 'API key required';
	
	//JS generally does, but is not guaranteed to, give things back in the order you do them.
	//Things get mixed up in between Lua -> JSON - > JS, so we want to be sure to iterate in this order when generating the output.
	var factionOrder = ['strength', 'prosperity', 'endurance', 'valour', 'serenity', 'peace'];
	
	var jsonData = document.getElementById('rw-json-data');
	if (!jsonData) {
		return 'JSON not found. Are you running this on the "Module:RankedWars/data" page?';
	}
	jsonData = JSON.parse(jsonData.firstElementChild.textContent);
	var factions = jsonData.factions;
	var corrections = jsonData.corrections;
	//todo: I put termed for anything that says Derank, but some of the early ones predate terming and there may not have been an official agreement.
	//	Can usually tell from score anyway, but may want to put notes where needed
	
	// wars by faction, newest first (gets reversed in JSON); keys same as in "factions"
	var wars = {
		overall: {},
	};
	var requests = {
		pending: 0,
		completed: 0,
		failed: 0,
		ignoredWars: 0,
	};
	
	async function requestWarHistory(shell, facName, offset, limit) {
		var url = 'https://api.torn.com/v2/faction/';
		url = url.concat(
			shell.id,
			'/rankedwars?offset=',
			offset,
			'&limit=',
			limit,
			'&key=',
			apiKey,
			'&comment=NPOWiki-RW',
		);
		try {
			var response = await fetch(url);
			if (!response.ok) {
				var error = 'Request error:';
				error = error.concat(
					' status ',
					response.status,
					' for faction ',
					shell.id,
					' with offset ',
					offset,
				);
				throw new Error(err);
			}
			var data = await response.json();
			requests.completed += 1;
			processWarHistory(data, shell, facName, offset, limit);
		} catch (err) {
			requests.failed += 1;
			console.error(err);
			//todo: handle error
		} finally {
			requests.pending -= 1;
			if (requests.pending < 1 && requests.completed + requests.failed > 0) {
				finalize();
			}
		}
	}
	
	function processWarHistory(data, shell, facName, offset, limit) {
		data.rankedwars.forEach(function (war) {
			//Wars that started or ended outside of the shell's range will not be included
			if (war.start > shell.startUnix && (war.end || Infinity) < (shell.endUnix || Infinity)) {
				var usFirst = war.factions[0].id === shell.id;
				var usData = war.factions[+!usFirst];
				var themData = war.factions[+usFirst];
				// "chain" property appears to be worthless, and "forfeit" very unlikely.
				var warData = {
					id: war.id,
					start: war.start,
					end: war.end,
					shell: usData.id,
					opponent: themData.id,
					oppName: themData.name,
					win: war.winner === shell.id,
					termed: false,
					target: war.target,
					ourScore: usData.score,
					oppScore: themData.score,
				};
				var correction = corrections[war.id];
				if (correction) {
					if (correction.opponent) {
						warData.oppName = correction.opponent;
					}
					if (correction.termed) {
						warData.termed = true;
					}
					if (correction.note) {
						warData.note = correction.note;
					}
				}
				wars[facName][war.id] = warData;
			} else {
				requests.ignoredWars += 1;
				//todo: track ignored wars, but maybe handle when looking up same shell multiple times
			}
		});
		if (data._metadata.links.next) {
			offset += limit;
			requests.pending += 1;
			setTimeout(requestWarHistory, 750, shell, facName, offset, limit);
		}
	}
	
	function finalize() {
		factionOrder.forEach(function (faction) {
			var stats = {
				wars: 0,
				wins: 0,
				losses: 0,
				termedWins: 0,
				termedLosses: 0,
			};
			Object.keys(wars[faction]).forEach(function (war) {
				war = wars[faction][war];
				stats.wars += 1;
				if (war.win) {
					stats.wins += 1;
					if (war.termed) {
						stats.termedWins += 1;
					}
				} else {
					stats.losses += 1;
					if (war.termed) {
						stats.termedLosses += 1;
					}
				}
			});
			wars.overall[faction] = stats;
		});
		var output = {
			_meta: {
				documentation: ' https://wiki.npowned.net/view/Module:RankedWars/data.json/doc '
			},
			wars,
		}
		console.log(JSON.stringify(output, null, '\t'));
		console.log(requests);
		//todo
	}
	
	factionOrder.forEach(function (faction, i) {
		var limit = 100;// maximum limit for Torn RW API
		
		wars[faction] = {};
		factions[faction].forEach(function (shell, j) {
			//Torn and Lua use seconds, not milliseconds
			shell.startUnix = Date.parse(shell.start) / 1000;
			shell.endUnix = Date.parse(shell.end) / 1000;
			
			var offset = 0;
			requests.pending += 1;
			setTimeout(requestWarHistory, 500 * (i + 1) * (j + 1), shell, faction, offset, limit);
		});
	});
	//todo: consider if worth calling rankedwarreport - definitely would be nice to have full stats.
	//	Maybe a separate script that can pull from this one's output? Although having it all together and only one script to run/page to update would be nice
	//todo: war graphs for in-family wars will be duplicate files
	//need more ways to make the pages visually interesting and not samey - point out important/contested wars. Could color code things for at a glance? (With icons perhaps)
	//todo for module: fun stats - most fought opponents, ...
	//should have something to get at least the appropriate section link for a given war, or just name+disambig in general, since they can change
	//don't have anything to handle having pages for wars against the same opponent by different NPO factions...
	//adding blurbs needs to be done...
})();

JSON

This is taken from the module content and used by the script. It does not need to be expanded for the script to work.

Expand to show JSON data
{
    "factions": {
        "prosperity": [
            {
                "id": 44758,
                "end": "",
                "start": "2022-10-14",
                "label": "Current shell"
            },
            {
                "id": 11162,
                "end": "2022-10-14",
                "start": "2021-10-16",
                "label": "Old shell (sold to PimpChu)"
            },
            {
                "id": 44751,
                "end": "2021-10-16",
                "start": "2020-02-09",
                "label": "Older shell (now Cry of the Lost)"
            }
        ],
        "endurance": [
            {
                "id": 12645,
                "end": "",
                "start": "2024-05-15",
                "label": "Current shell"
            },
            {
                "id": 14052,
                "end": "2024-05-15",
                "start": "2022-08-03",
                "label": "Old shell (now Serenity)"
            }
        ],
        "peace": [
            {
                "id": 18714,
                "end": "",
                "start": "2022-07-16",
                "label": "Current shell"
            }
        ],
        "valour": [
            {
                "id": 26885,
                "end": "",
                "start": "2023-12-31",
                "label": "Current shell"
            }
        ],
        "strength": [
            {
                "id": 10610,
                "end": "",
                "start": "2022-10-03",
                "label": "Current shell"
            },
            {
                "id": 44758,
                "end": "2022-10-03",
                "start": "2020-02-09",
                "label": "Old shell (now Prosperity)"
            }
        ],
        "serenity": [
            {
                "id": 14052,
                "end": "",
                "start": "2024-05-15",
                "label": "Current shell"
            }
        ]
    },
    "corrections": {
        "339": {
            "opponent": "IA Green"
        },
        "401": {
            "opponent": "War Sluts"
        },
        "1009": {
            "opponent": "Legacy"
        },
        "1081": {
            "opponent": "Goodnight Moon"
        },
        "1592": {
            "opponent": "39th Street Killers XR"
        },
        "2072": {
            "opponent": "709's RugRats"
        },
        "2389": {
            "opponent": "Chaos Rising"
        },
        "3253": {
            "opponent": "DropBears",
            "termed": true
        },
        "3305": {
            "termed": true
        },
        "3439": {
            "termed": true
        },
        "3536": {
            "termed": true
        },
        "3632": {
            "termed": true
        },
        "3706": {
            "termed": true
        },
        "3980": {
            "opponent": "The Unwoke"
        },
        "4218": {
            "opponent": "NNGO Deja 2"
        },
        "4286": {
            "opponent": "Clockwork Orange"
        },
        "4305": {
            "opponent": "Forged In Fire"
        },
        "4684": {
            "opponent": "Riot"
        },
        "5006": {
            "opponent": "Ouroboros"
        },
        "5190": {
            "opponent": "Hello High",
            "termed": true
        },
        "5307": {
            "termed": true
        },
        "5341": {
            "termed": true
        },
        "5536": {
            "termed": true
        },
        "5610": {
            "opponent": "Infernum Legion"
        },
        "5823": {
            "opponent": "SWISS COVERT CORPS"
        },
        "6038": {
            "note": "This faction is now NSO II but was still their second faction at the time.",
            "opponent": "New Sith Order"
        },
        "6384": {
            "termed": true
        },
        "6425": {
            "opponent": "Nuova Famiglia"
        },
        "6444": {
            "termed": true
        },
        "7015": {
            "termed": true
        },
        "7066": {
            "termed": true
        },
        "7074": {
            "opponent": "Nuova Famiglia"
        },
        "7103": {
            "termed": true
        },
        "7633": {
            "termed": true
        },
        "8534": {
            "opponent": "Ghost Ship"
        },
        "9302": {
            "termed": true
        },
        "9310": {
            "termed": true
        },
        "9418": {
            "termed": true
        },
        "9588": {
            "termed": true
        },
        "9765": {
            "termed": true
        },
        "10953": {
            "opponent": "WIT-Ranger"
        },
        "11136": {
            "opponent": "Little Stompers",
            "termed": true
        },
        "11546": {
            "termed": true
        },
        "13284": {
            "opponent": "Elements"
        },
        "13875": {
            "opponent": "Monarch Army of Light"
        },
        "14015": {
            "opponent": "The Corporation"
        },
        "14329": {
            "opponent": "The Corporation"
        },
        "14405": {
            "opponent": "Ass, Grass or Cache"
        },
        "14681": {
            "opponent": "WTF Ducks"
        },
        "15016": {
            "termed": true
        },
        "15107": {
            "termed": true
        },
        "15425": {
            "termed": true
        },
        "15559": {
            "termed": true
        },
        "15850": {
            "termed": true
        },
        "16061": {
            "termed": true
        },
        "16603": {
            "termed": true
        },
        "16972": {
            "termed": true
        },
        "17128": {
            "termed": true
        },
        "17403": {
            "termed": true
        },
        "17544": {
            "termed": true
        },
        "17942": {
            "opponent": "Clockwork Orange"
        },
        "17986": {
            "opponent": "FREE PALESTINE",
            "termed": true
        },
        "18181": {
            "opponent": "Happy Vegemites",
            "termed": true
        },
        "19540": {
            "termed": true
        },
        "21146": {
            "note": "Strength did not contest this war."
        },
        "21417": {
            "termed": true
        },
        "21648": {
            "opponent": "Luscious Estuary",
            "termed": true
        },
        "21844": {
            "termed": true
        },
        "22408": {
            "termed": true
        },
        "22547": {
            "termed": true
        },
        "22621": {
            "termed": true
        },
        "22648": {
            "termed": true
        },
        "22809": {
            "termed": true
        },
        "22993": {
            "opponent": "AQUA-Neptune",
            "termed": true
        },
        "23168": {
            "termed": true
        },
        "23498": {
            "termed": true
        },
        "24005": {
            "opponent": "Neon Cartel"
        },
        "24748": {
            "termed": true
        },
        "25092": {
            "termed": true
        },
        "25233": {
            "termed": true
        },
        "25785": {
            "termed": true
        },
        "26378": {
            "termed": true
        },
        "26698": {
            "termed": true
        },
        "26763": {
            "termed": true
        },
        "29101": {
            "termed": true
        },
        "29532": {
            "termed": true
        },
        "29810": {
            "termed": true
        },
        "30645": {
            "termed": true
        },
        "31075": {
            "termed": true
        },
        "31536": {
            "termed": true
        }
    },
    "rw_release": "2021-12-07"
}