summaryrefslogtreecommitdiff
path: root/service_analyze.js
diff options
context:
space:
mode:
authorschneefux <schneefux+commit@schneefux.xyz>2017-07-14 18:56:30 +0200
committerschneefux <schneefux+commit@schneefux.xyz>2017-07-14 18:56:30 +0200
commitdd6c4c39440982e2943906f2fa30dbbb8260540b (patch)
tree19e6e1732c4b2cb368d9f1a61e65472a6878143d /service_analyze.js
parent40afdde86f8b9369c2f3e1ef73176c347ccef5f6 (diff)
downloadbridge-dd6c4c39440982e2943906f2fa30dbbb8260540b.tar.gz
bridge-dd6c4c39440982e2943906f2fa30dbbb8260540b.zip
2.14.0 rewrite: modularization
Diffstat (limited to 'service_analyze.js')
-rw-r--r--service_analyze.js83
1 files changed, 83 insertions, 0 deletions
diff --git a/service_analyze.js b/service_analyze.js
new file mode 100644
index 0000000..8e6ace8
--- /dev/null
+++ b/service_analyze.js
@@ -0,0 +1,83 @@
+#!/usr/bin/env node
+/* jshint esnext: true */
+"use strict";
+
+const Promise = require("bluebird"),
+ Service = require("./service_skeleton.js");
+
+const logger = global.logger,
+ ANALYZE_QUEUE = process.env.ANALYZE_QUEUE || "analyze",
+ ANALYZE_TOURNAMENT_QUEUE = process.env.ANALYZE_TOURNAMENT_QUEUE || "analyze_tournament",
+ SHOVEL_SIZE = parseInt(process.env.SHOVEL_SIZE) || 1000;
+
+module.exports = class Analyzer extends Service {
+ constructor() {
+ super();
+
+ this.setTargets({
+ "regular": ANALYZE_QUEUE,
+ "tournament": ANALYZE_TOURNAMENT_QUEUE
+ });
+
+ this.setRoutes({
+ // calculate TrueSkill for everyone
+ "/api/rank/:category*?": async (req, res) => {
+ this.analyzeGlobal(req.params.category || "regular");
+ res.sendStatus(204);
+ },
+ // calculate TrueSkill for one player
+ "/api/player/:name/rank/:category*?": async (req, res) => {
+ const category = req.params.category || "regular",
+ db = this.getDatabase(category),
+ players = await db.Player.findAll({ where: { name: req.params.name } });
+ if (players == undefined) {
+ logger.error("player not found in db, won't analyze",
+ { name: req.params.name });
+ res.sendStatus(404);
+ return;
+ }
+ logger.info("player in db, analyzing", { name: req.params.name });
+ players.forEach((player) => this.analyzePlayer(category, player.api_id));
+ res.sendStatus(204);
+ }
+ });
+ }
+
+ async analyzeGlobal(category) {
+ const db = this.getDatabase(category);
+ let offset = 0, matches;
+ do {
+ matches = await db.Match.findAll({
+ attributes: ["api_id"],
+ where: { trueskill_quality: null },
+ limit: SHOVEL_SIZE,
+ offset: offset,
+ order: [ ["created_at", "ASC"] ]
+ });
+ await Promise.each(matches, async (m) =>
+ await this.forward(this.getTarget(category), m.api_id,
+ { persistent: true }));
+ offset += SHOVEL_SIZE;
+ logger.info("loading more matches into analyzer",
+ { offset: offset, limit: SHOVEL_SIZE, size: matches.length });
+ } while (matches.length == SHOVEL_SIZE);
+ logger.info("done loading matches into analyzer");
+ }
+
+ async analyzePlayer(category, api_id) {
+ const db = this.getDatabase(category),
+ participations = await db.Participant.findAll({
+ attributes: ["match_api_id"],
+ where: {
+ player_api_id: api_id,
+ trueskill_mu: null // where not analyzed yet
+ },
+ order: [ ["created_at", "ASC"] ]
+ });
+ logger.info("sending matches to analyzer",
+ { length: participations.length });
+ await Promise.each(participations, async (p) =>
+ await this.forward(this.getTarget(category),
+ p.match_api_id, { persistent: true }));
+ }
+}