Module:RankedWars/data/doc

From NPOWiki
Revision as of 03:10, 15 October 2025 by Bobogoobo (talk | contribs) (for safekeeping)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
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.

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.

Expand to show code
//Get each of our factions' RW history from the Torn API, calculate stats, and output json format for storage.
//By Bobogoobo [2618206] for NPOWiki
(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
	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.
	//Dates are approximate due to transition time, merely following official announcements.
	//Ranges are contiguous to avoid missing any events.
	var factions = {
		strength: [
			{
				label: 'Current shell',
				id: 10610,
				start: '2022-10-03',
				end: '',
			},
			{
				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.
	//	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"
		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) {
			var relevant = false;
			//todo: simplify?
			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 usData = war.factions[+!usFirst];
				var themData = war.factions[+usFirst];
				// "chain" property appears to be worthless. Not sure about forfeit?
				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() {
		Object.keys(factions).forEach(function (faction) {
			wars.overall[faction] = {
				wars: 0,
				wins: 0,
				losses: 0,
				termedWins: 0,
				termedLosses: 0,
			};
			var stats = wars.overall[faction];
			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;
					}
				}
			});
		});
		console.log(JSON.stringify({factions, wars, corrections}, null, '\t'));
		console.log(requests);
		//todo
	}
	
	Object.keys(factions).forEach(function (faction, i) {
		var limit = 100;// maximum limit
		
		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 would be nice
	//todo: war 14015 was fought by END on May 10-11 2024, need to adjust shell move date to Serenity.
})();