Retrieve weapon data from SplatNet

This will be used for
This commit is contained in:
Matt Isenhower 2017-09-01 10:11:14 -07:00
parent 1e2b865f1c
commit b9abcaf67c
5 changed files with 123 additions and 0 deletions

View File

@ -22,6 +22,7 @@
"copy-webpack-plugin": "^4.0.1",
"cron": "^1.2.1",
"css-loader": "^0.28.4",
"delay": "^2.0.0",
"dotenv": "^4.0.0",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^0.11.2",

View File

@ -0,0 +1,55 @@
const delay = require('delay');
const splatnet = require('./splatnet');
/**
* The SplatNet 2 API doesn't currently provide a way to retrieve weapon data directly.
* There are, however, several API endpoints that provide weapon data along with their results.
*
* This function retrieves recent league match rankings and parses weapon data from those results.
* This data is provided in blocks of 2 hours. Generally, retrieving the last 2-3 blocks of data
* is enough to retrieve all currently-available weapons.
*/
module.exports = async function retrieveWeapons(iterations = 1, useDelay = true) {
// Start from "now" and work backwards
let date = new Date();
date.setUTCMinutes(0);
date.setUTCSeconds(0);
// Hours must be in multiples of 2
if (date.getUTCHours() % 2 == 1)
date.setUTCHours(date.getUTCHours() - 1);
let weapons = {};
// We'll retrieve up to the number of iterations specified of result data.
// For example: 2017-09-01 06:00, then 2017-09-01 04:00, then 2017-09-01 02:00, etc.
for (let i = 0; i < iterations; i++) {
// Start with the previous time block (2 hours ago) even on the first run
date.setUTCHours(date.getUTCHours() - 2);
let year = date.getUTCFullYear();
let month = date.getUTCMonth() + 1;
let day = date.getUTCDate();
let hour = date.getUTCHours();
// Get both team and pair rankings
console.info(`Getting league rankings for ${year}-${month}-${day} hour ${hour}...`);
let teamRanking = await splatnet.getLeagueMatchRanking(year, month, day, hour, 'T');
let pairRanking = await splatnet.getLeagueMatchRanking(year, month, day, hour, 'P');
// Process the results
for (let ranking of [teamRanking, pairRanking]) {
for (rankInfo of ranking.rankings) {
for (player of rankInfo.tag_members)
weapons[player.weapon.id] = player.weapon;
}
}
if (useDelay && (i + 1) < iterations)
await delay(500);
}
return weapons;
}

View File

@ -50,6 +50,24 @@ async function getMerchandises() {
return response.data;
}
async function getLeagueMatchRanking(year, month, day, hour, type = 'T', region = 'ALL') {
// Hour should be in multiples of 2, e.g., 00, 02, 04, ..., 22.
// Type should be 'T' (team) or 'P' (pair).
// Region should be 'ALL', 'JP', 'US', or 'EU'.
// Make sure year is specified as two digits
year = year % 100;
// Make sure we have leading zeros
year = ('0' + year).substr(-2);
month = ('0' + month).substr(-2);
day = ('0' + day).substr(-2);
hour = ('0' + hour).substr(-2);
let response = await api.get(`league_match_ranking/${year}${month}${day}${hour}${type}/${region}`);
return response.data;
}
async function getImage(imagePath) {
let response = await axios.get(`${splatnetBaseUrl}${imagePath}`, { responseType: 'arraybuffer' });
return response.data;
@ -62,5 +80,6 @@ module.exports = {
getEUFestivals,
getJPFestivals,
getMerchandises,
getLeagueMatchRanking,
getImage,
}

View File

@ -3,6 +3,7 @@ const path = require('path');
const fs = require('fs');
const mkdirp = require('mkdirp');
const splatnet = require('./splatnet');
const retrieveWeapons = require('./retrieveWeapons');
const salmoncalendar = require('./salmoncalendar');
const raven = require('raven');
@ -100,6 +101,40 @@ async function updateMerchandises() {
}
}
async function updateWeapons() {
// This one is handled a little differently since we need to add to the existing data
// instead of just overwriting it. We don't have a way to retrieve a complete set
// of weapon data, so we have to make sure not to lose any weapons we already know about.
let filename = `${dataPath}/weapons.json`;
// Look for weapons used over the past 24 hours if we don't have an existing list of weapons.
let iterations = 12;
let weapons = {};
if (fs.existsSync(filename)) {
weapons = JSON.parse(fs.readFileSync(filename));
// If we already have a weapons file, only retrieve the most recent results
iterations = 1;
}
// We're now ready to update the weapons
await handleRequest({
title: 'weapons',
filename,
request: retrieveWeapons(iterations),
transformer: responseData => {
// Add the new weapons to the existing list of weapons
return Object.assign(weapons, responseData);
},
});
// Get weapon images
for (let weapon of Object.values(weapons))
await maybeDownloadImage(weapon.image);
}
function updateSalmonRunCalendar() {
return handleRequest({
title: 'Salmon Run calendar',
@ -113,6 +148,7 @@ async function updateAll() {
await updateTimeline();
await updateFestivals();
await updateMerchandises();
await updateWeapons();
await updateSalmonRunCalendar();
return 'Done.';
@ -150,6 +186,7 @@ async function handleRequest(options) {
} catch (e) {
raven.captureException(e);
console.error(`Couldn\'t update ${options.title}.`);
console.error(e);
}
}
@ -175,6 +212,7 @@ module.exports = {
updateTimeline,
updateFestivals,
updateMerchandises,
updateWeapons,
updateSalmonRunCalendar,
updateAll,
}

View File

@ -1550,6 +1550,12 @@ del@^3.0.0:
pify "^3.0.0"
rimraf "^2.2.8"
delay@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/delay/-/delay-2.0.0.tgz#9112eadc03e4ec7e00297337896f273bbd91fae5"
dependencies:
p-defer "^1.0.0"
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
@ -3348,6 +3354,10 @@ osenv@0, osenv@^0.1.4:
os-homedir "^1.0.0"
os-tmpdir "^1.0.0"
p-defer@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"