summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorschneefux <schneefux+commit@schneefux.xyz>2018-05-22 14:07:25 +0200
committerschneefux <schneefux+commit@schneefux.xyz>2018-12-13 16:59:39 +0100
commit6382ed01e9db8f975b72c9c2c8db4013cd0156c2 (patch)
tree0007030148e27fe9152ccb28a91c3497d62b27d8
parent60186a7bb45a0063f605f8d4b05c2f08418733af (diff)
downloadbrokentalents-6382ed01e9db8f975b72c9c2c8db4013cd0156c2.tar.gz
brokentalents-6382ed01e9db8f975b72c9c2c8db4013cd0156c2.zip
Add metadata file to data
-rw-r--r--backend/config-brawl.js60
-rw-r--r--backend/config.js1
-rw-r--r--backend/index.js12
-rw-r--r--src/App.vue3
-rw-r--r--src/report-service.js8
5 files changed, 80 insertions, 4 deletions
diff --git a/backend/config-brawl.js b/backend/config-brawl.js
new file mode 100644
index 0000000..dc13956
--- /dev/null
+++ b/backend/config-brawl.js
@@ -0,0 +1,60 @@
+#!/usr/bin/node
+
+const crypto = require('crypto');
+
+const sha256 = (x) => crypto.createHash('sha256').update(x, 'utf8').digest('hex');
+
+const hashSettings = (config) => sha256(
+ config.api.regions +
+ config.api.modes +
+ config.api.requestsPerInterval +
+ config.api.interval +
+ config.api.intervalUnit
+).substring(0, 8);
+
+module.exports = {
+ api: {
+ baseUrl: 'https://api.dc01.gamelockerapp.com',
+ timeout: 3,
+ /* available: eu, na, sg, cn, sa, ea */
+ regions: ['sg', 'eu', 'na'],
+ /* available: casual, 5v5_pvp_casual, ranked, 5v5_pvp_ranked, blitz_pvp_ranked, casual_aral */
+ modes: ['blitz_pvp_ranked', 'casual_aral'],
+ /* available: 2, 3, 4, 5 */
+ matchesPerRequest: 5,
+ /* How many equidistant requests to create
+ * matchesPerRequest * requestsPerInterval = sample size for that interval
+ * currently requestsPerInterval <= API key rate limit but should work if it isn't significantly higher
+ * rough estimate of upper limits (na/eu/sg, depends on region and time of day):
+ * blitz: 240
+ * battle royale: 30
+ * 3v3 casual: 30
+ * 3v3 ranked: 100
+ * 5v5 casual: 30
+ * 5v5 ranked: 40
+ * if filtering for multiple game modes, use the sum of the upper limits */
+ requestsPerInterval: 50,
+ /* the size of a batch */
+ interval: 1,
+ intervalUnit: 'hours',
+ /* How many batches to request per minute
+ * requestsPerInterval * intervalsPer Minute <= API key rate limit */
+ intervalsPerMinute: 1,
+ },
+ etl: {
+ /* attributes to be extracted and renamed from main API data */
+ participant: [ ['Winner', ['attributes', 'stats', 'winner']] ],
+ roster: [ ],
+ match: [ ['Mode', ['attributes', 'gameMode']] ],
+ },
+ reduce: {
+ /* criteria or 'filters' */
+ group: ['Actor', 'Talent', 'Mode'],
+ /* stats */
+ sum: ['Level', 'Winner'],
+ },
+ file: {
+ pattern: (moment) => `./data/${hashSettings(module.exports)}/${moment.toISOString()}.json`,
+ reportPattern: () => `./data/${hashSettings(module.exports)}/report.json`,
+ },
+};
diff --git a/backend/config.js b/backend/config.js
index eaed3f7..86deed6 100644
--- a/backend/config.js
+++ b/backend/config.js
@@ -56,5 +56,6 @@ module.exports = {
file: {
pattern: (moment) => `./data/${hashSettings(module.exports)}/${moment.toISOString()}.json`,
reportPattern: () => `./data/${hashSettings(module.exports)}/report.json`,
+ metadataPattern: () => `./data/${hashSettings(module.exports)}/metadata.json`,
},
};
diff --git a/backend/index.js b/backend/index.js
index c8be64e..8480f28 100644
--- a/backend/index.js
+++ b/backend/index.js
@@ -3,6 +3,7 @@
const R = require('ramda'),
Future = require('fluture'),
moment = require('moment'),
+ fsPath = require('fs-path'),
reduce = require('./reduce'),
source = require('./source'),
file = require('./file'),
@@ -23,11 +24,20 @@ function main() {
const hours = R.range(0, Math.floor(duration.asHours()));
const laterMoments = R.map(later(start), hours);
+ const metadata = {
+ lastUpdate: moment().toISOString(),
+ config,
+ };
+ const saveMetadata = (path, data) =>
+ Future.node((cb) => fsPath.writeFile(path, JSON.stringify(data), cb))
+ .map(() => data);
+
const futures = R.map(loadFTimestamped, laterMoments);
Future.parallel(1, futures)
.map(R.compose(deriveStatistics, aggregatePayloads, cleanPayloads, R.unnest))
.chain(saveFPayloads(config.file.reportPattern()))
- .fork(console.error, (d) => console.log(JSON.stringify(d, null, 2)));
+ .chain((data) => saveMetadata(config.file.metadataPattern(), metadata))
+ .fork(console.error, (d) => {});
}
main();
diff --git a/src/App.vue b/src/App.vue
index ff6d081..4dcf698 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -19,7 +19,7 @@
<div class="container">
<div class="content has-text-centered">
<p>
- Last update: 2018-05-22, with {{ totalMatches }} matches total.
+ Last update: {{ lastUpdate }}, with {{ totalMatches }} matches total.
Join the <a href="https://discord.gg/txTchJY">Discord Server</a> if you have questions.
</p>
<p>
@@ -56,6 +56,7 @@ export default {
data: function() {
return {
totalMatches: Math.floor(this.reportService.getTotalMatches()/100)*100,
+ lastUpdate: this.reportService.getLastUpdate(),
};
},
};
diff --git a/src/report-service.js b/src/report-service.js
index 000080c..2469ea9 100644
--- a/src/report-service.js
+++ b/src/report-service.js
@@ -1,12 +1,12 @@
import * as maps from './maps/maps';
-const MODES = [ 'casual_aral', 'blitz_pvp_ranked', 'ranked', '5v5_pvp_ranked' ];
const POPULAR_THRESHOLD = 1.0; // percent
export default class ReportService {
constructor() {
this.report = require('../data/95fb1cdb/report.json')
.filter((entry) => entry.Actor != undefined); // bad data from API downtime
+ this.metadata = require('../data/95fb1cdb/metadata.json');
this.reports = new Map();
this.totalPicks = new Map();
@@ -21,7 +21,7 @@ export default class ReportService {
this.topUnpopularWins = new Map();
this.totalMatches = 0;
this.actors = [];
- this.modes = MODES;
+ this.modes = this.metadata.config.api.modes;
for(let mode of this.modes) {
const relevancy = (entry) => (entry.Count / this.totalPicks.get(mode)) * entry.Winner;
@@ -126,4 +126,8 @@ export default class ReportService {
getTotalMatches() {
return this.totalMatches;
}
+
+ getLastUpdate() {
+ return this.metadata.lastUpdate;
+ }
}