diff options
| author | schneefux <schneefux+commit@schneefux.xyz> | 2017-07-14 18:56:30 +0200 |
|---|---|---|
| committer | schneefux <schneefux+commit@schneefux.xyz> | 2017-07-14 18:56:30 +0200 |
| commit | dd6c4c39440982e2943906f2fa30dbbb8260540b (patch) | |
| tree | 19e6e1732c4b2cb368d9f1a61e65472a6878143d /service_analyze.js | |
| parent | 40afdde86f8b9369c2f3e1ef73176c347ccef5f6 (diff) | |
| download | bridge-dd6c4c39440982e2943906f2fa30dbbb8260540b.tar.gz bridge-dd6c4c39440982e2943906f2fa30dbbb8260540b.zip | |
2.14.0 rewrite: modularization
Diffstat (limited to 'service_analyze.js')
| -rw-r--r-- | service_analyze.js | 83 |
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 })); + } +} |
