Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const Mika = require('mika');
- const util = require('util');
- const squel = require('squel');
- const fs = require('fs');
- const Bottleneck = require('bottleneck');
- const Moment = require('moment');
- const MomentRange = require('moment-range');
- const mika = new Mika();
- const moment = MomentRange.extendMoment(Moment);
- const shared = new Int32Array(new SharedArrayBuffer(4));
- class MatchesRetriever {
- constructor() {
- this.matchesTypes = {
- all: 'all',
- pro: 'pro',
- players: 'players'
- };
- this.matches_ids = [];
- this.heroes_players = {};
- this.players_matches = {};
- this.heroes = [];
- this.iterator = 0;
- this.timeoutOnError = 30;
- this.limiter = new Bottleneck({
- maxConcurrent: 60,
- minTime: 500,
- strategy: Bottleneck.strategy.BLOCK,
- reservoir: null
- });
- }
- static unique(arr) {
- return [...new Set(arr)];
- }
- static msleep(n) {
- Atomics.wait(shared, 0, 0, n);
- }
- static sleep(n) {
- MatchesRetriever.msleep(n * 1000);
- }
- removeEmpty(obj, filteredValues = []) {
- Object.keys(obj).forEach((k) => ((!obj[k] || (obj[k] && filteredValues.includes(obj[k]))) && obj[k] !== undefined) && delete obj[k]);
- return obj;
- };
- static _getQueryForProMatches() {
- return squel.select({separator: '\n'})
- .field('matches.match_id')
- .field('matches.start_time')
- .field('((player_matches.player_slot < 128) = matches.radiant_win) win')
- .field('player_matches.hero_id')
- .field('player_matches.account_id')
- .field('leagues.name leaguename')
- .from('matches')
- .join('match_patch using(match_id)')
- .join('leagues using(leagueid)')
- .join('player_matches using(match_id)')
- .join('heroes on heroes.id = player_matches.hero_id')
- .left_join('notable_players', null, 'notable_players.account_id = player_matches.account_id AND notable_players.locked_until = ' +
- '(' +
- squel.select()
- .from('notable_players')
- .field('MAX(locked_until)')
- .toString()
- + ')'
- )
- .left_join('teams using(team_id)')
- .where('TRUE')
- .order('matches.match_id DESC NULLS LAST', null);
- }
- getTopPlayersForAllHeroes(playersLimit = 10, from = null) {
- let that = this;
- let date = from ? moment(from, "DD.MM.YYYY") : moment();
- let days = date.diff(moment(), 'days');
- that.matches_ids = [];
- mika.getHeroes()
- .then((data) => {
- if (data !== null) {
- that.heroes = {...data};
- that._getTopPlayersForAllHeroes(that.heroes, playersLimit);
- that.limiter.once('empty', function () {
- util.log('Start to get all players matches');
- that.limiter.schedule(() => Promise.resolve()
- .then(() => {
- that._getAllHeroesTopPlayersMatches(that.heroes_players, days);
- that.limiter.once('empty', function () {
- util.log('Retrieving of players matches has been finished');
- that.limiter.schedule(() => Promise.resolve()
- .then(() => {
- that.heroes_players.total_matches = that.matches_ids.length;
- util.log('total matches: ', that.heroes_players.total_matches);
- that.matches_ids = MatchesRetriever.unique(that.matches_ids);
- that.heroes_players.unique_matches = that.matches_ids.length;
- util.log('unique matches: ', that.heroes_players.unique_matches);
- fs.writeFile('./heroes_players_matches.json', JSON.stringify(that.heroes_players), (err) => {
- if (err) throw err;
- });
- fs.writeFile('./matches.json', JSON.stringify(that.matches_ids), (err) => {
- if (err) throw err;
- });
- util.log('All matches has been saved');
- }));
- });
- }));
- });
- }
- }).catch((err) => {
- util.log('getHeroes: ', err);
- });
- }
- _getTopPlayersForAllHeroes(data, playersLimit) {
- let that = this;
- that.limiter.updateSettings({reservoir: null});
- Object.keys(data).forEach(function (key) {
- let hero = that.heroes[key];
- that.limiter.schedule(hero => mika.getRankings(hero.id), hero)
- .then((players) => {
- that.iterator = 0;
- that.heroes_players[hero.id] = {};
- util.log('heroId: ', hero.id);
- players.rankings.every(function (player) {
- that.heroes_players[hero.id][player.account_id] = {
- 'id': player.account_id,
- 'score': player.score,
- 'rank': player.rank_tier
- };
- that.iterator++;
- if (that.iterator < playersLimit) {
- return true;
- }
- });
- })
- .catch(err => {
- util.log('getTopPlayers: ', err, 'id=' + hero.id);
- that.limiter.updateSettings({reservoir: 0});
- util.log('sleep for ' + (that.timeoutOnError) + ' sec');
- MatchesRetriever.sleep(that.timeoutOnError);
- let new_data = {
- [key]: hero
- };
- that._getTopPlayersForAllHeroes(new_data, playersLimit);
- });
- });
- };
- _getPlayersMatches(player, days, game_modes) {
- let that = this;
- that.limiter.updateSettings({reservoir: null});
- let date = moment();
- that.players_matches[player] = that.players_matches[player] || {
- game_modes: game_modes,
- player_id: player,
- days: days,
- date: date.format('DD.MM.YYYY'),
- matches: {}
- };
- game_modes.forEach((game_mode) => {
- that.limiter.schedule((player) => mika.getPlayerMatches(player, that.removeEmpty({
- date: days,
- game_mode: game_mode
- }, ['all'])), player)
- .then((matches) => {
- that.iterator += matches.length;
- util.log('playerMatches: ', matches.length, player);
- that.players_matches[player].matches[game_mode] = matches;
- that.players_matches[player].matches.total_matches = matches.length;
- if (game_mode === game_modes[game_modes.length - 1]) {
- fs.writeFile('./players/matches_' + player + '.json', JSON.stringify(that.players_matches[player]), (err) => {
- delete that.players_matches[player];
- if (err) throw err;
- });
- }
- })
- .catch(err => {
- util.log('getPlayerMatches: ', err, 'player: ', player);
- that.limiter.updateSettings({reservoir: 0});
- util.log('sleep for ' + (that.timeoutOnError) + ' sec');
- MatchesRetriever.sleep(that.timeoutOnError);
- that._getPlayersMatches(player, days, game_modes);
- });
- })
- }
- getPlayersMatches(players, days, game_modes = ['all']) {
- let that = this;
- that.iterator = 0;
- let run = (player, days, game_modes) => {
- players.forEach((player) => {
- that._getPlayersMatches(player, days, game_modes);
- });
- that.limiter.once('empty', () => {
- util.log('Retrieving of player\'s matches has been finished');
- that.limiter.schedule(() => Promise.resolve()
- .then(() => {
- /* Object.keys(that.players_matches).forEach((player) => {
- fs.writeFile('./players/matches_' + player + '.json', JSON.stringify(that.players_matches[player]), (err) => {
- if (err) throw err;
- });
- });*/
- util.log('total matches: ', that.iterator);
- util.log('All matches has been saved');
- }));
- });
- };
- if (!Array.isArray(players)) {
- fs.readFile('./players/players.json', (err, data) => {
- if (data) {
- players = JSON.parse(data);
- run(players, days, game_modes)
- }
- });
- }
- else {
- run(players, days, game_modes)
- }
- }
- _getAllHeroesTopPlayersMatches(heroes, days) {
- let that = this;
- that.iterator = 0;
- that.limiter.updateSettings({reservoir: null});
- Object.keys(heroes).forEach(function (key) {
- let hero = heroes[key];
- Object.keys(hero).forEach(function (index) {
- let player = hero[index];
- that.limiter.schedule(player => mika.getPlayerMatches(player, {date: days}), player.id)
- .then((matches) => {
- that.iterator++;
- util.log('playerMatches: ', that.iterator, player.id);
- that.heroes_players[key][index].matches = [];
- matches.forEach(function (match) {
- that.heroes_players[key][index].matches.push(match.match_id);
- that.matches_ids.push(match.match_id);
- });
- })
- .catch(err => {
- util.log('getPlayerMatches: ', err, 'hero: ', key, 'player: ', player.id);
- that.limiter.updateSettings({reservoir: 0});
- util.log('sleep for ' + (that.timeoutOnError) + ' sec');
- MatchesRetriever.sleep(that.timeoutOnError);
- let heroes_new = {
- [key]: {
- [index]: player
- }
- };
- that._getAllHeroesTopPlayersMatches(heroes_new, days);
- });
- });
- });
- };
- getProLeagueMatches(from = null, limit = 100) {
- let that = this;
- limit *= 10;
- fs.readFile('./matches_pro.json', (err, data) => {
- if (!data) {
- that.matches_ids = [];
- }
- else {
- that.matches_ids = JSON.parse(data);
- }
- let date = from ? moment(from, 'DD.MM.YYYY') : moment();
- let range = moment().range(date, moment());
- let array = Array.from(range.by('months'));
- array.push(moment().add(1, 'day'));
- let query = MatchesRetriever._getQueryForProMatches();
- array.reverse().some((date, index, array) => {
- if (!Object.is(array.length - 1, index)) {
- let newQuery = query.clone();
- newQuery = newQuery
- .where('matches.start_time >= extract(epoch from timestamp \'' + array[index + 1].format('MM-DD-YYYY') + 'T00:00:00.000Z\')')
- .where('matches.start_time < extract(epoch from timestamp \'' + date.format('MM-DD-YYYY') + 'T00:00:00.000Z\')')
- .toString();
- that.limiter.schedule((query) => mika.explorer(query, true), newQuery)
- .then((data) => {
- util.log('start job');
- if (data !== null) {
- let lastIterations = false;
- if (limit > 0) {
- let uniqueMatches = data.rows.length;
- if (limit < uniqueMatches) {
- lastIterations = true;
- }
- else {
- limit -= data.rows.length;
- }
- }
- data.rows.some(match => {
- that.matches_ids.push(match.match_id);
- if (lastIterations) {
- limit--;
- if (limit <= 0) {
- util.log('limit');
- return true;
- }
- }
- });
- that.matches_ids = MatchesRetriever.unique(that.matches_ids);
- util.log('matches: ', that.matches_ids.length);
- fs.writeFile('./matches_pro.json', JSON.stringify(that.matches_ids), (err) => {
- if (err) throw err;
- if (limit <= 0) {
- that.limiter.stop({dropErrorMessage: 'Matches limit'})
- .then(() => {
- util.log('Shutdown completed!');
- });
- }
- util.log('pro matches ids saved');
- });
- }
- }
- )
- .catch(function (err) {
- util.log(err);
- });
- }
- });
- });
- }
- downloadMatches(types = 'all', offset = 0, limit = null) {
- let that = this;
- that.iterator = 0;
- switch (types) {
- case that.matchesTypes.players:
- let playersMatches = [];
- util.log('trying to retrieve matches');
- fs.readdir('./players', function (err, files) {
- playersMatches = files.filter(el => /^matches_.*\.json$/.test(el));
- let matches = null;
- let index = 0;
- const iMax = playersMatches.length;
- for (; index < iMax; index++) {
- matches = playersMatches[index];
- try {
- let data = fs.readFileSync('./players/' + matches);
- that.players_matches = JSON.parse(data);
- that.players_matches.game_modes.forEach((game_mode) => {
- that.players_matches.matches[game_mode].forEach((match) => {
- that.matches_ids.push(match.match_id);
- })
- });
- }
- catch (err) {
- throw err;
- }
- }
- that.matches_ids = MatchesRetriever.unique(that.matches_ids);
- util.log('total unique:', that.matches_ids.length, 'matches');
- that._getMatchesData(that.matches_ids, 'E:\\pro_pub_matches\\');
- });
- break;
- case that.matchesTypes.pro:
- fs.readFile('./matches_pro.json', function (err, data) {
- that.matches_ids = JSON.parse(data);
- that.matches_ids = MatchesRetriever.unique(that.matches_ids);
- if (offset > 0 || limit !== null) {
- that.matches_ids = that.matches_ids.slice(offset, limit);
- }
- util.log('total unique:', that.matches_ids.length, 'matches');
- that._getMatchesData(that.matches_ids, './matches/');
- });
- break;
- case that.matchesTypes.all:
- default:
- fs.readFile('./matches.json', function (err, data) {
- that.matches_ids = JSON.parse(data);
- that.matches_ids = MatchesRetriever.unique(that.matches_ids);
- if (offset > 0 || limit !== null) {
- that.matches_ids = that.matches_ids.slice(offset, limit);
- }
- util.log('total unique:', that.matches_ids.length, 'matches');
- /*fs.writeFile('./unique_matches.json', JSON.stringify(that.matches_ids), (err) => {
- if (err) throw err;
- });*/
- that._getMatchesData(that.matches_ids, './matches/');
- });
- }
- }
- _getMatchesData(matches, path, parse = true) {
- let that = this;
- that.limiter.updateSettings({reservoir: null});
- try {
- let index = 0;
- let percentage = 0;
- if(parse){
- !fs.existsSync(path) && fs.mkdirSync(path);
- util.log('reading matches folder');
- let files = fs.readdirSync(path);
- let file = '';
- let matchIndex;
- let iterator = 0;
- const iMax = files.length;
- for (; index < iMax; index++) {
- file = files[index];
- if(/\.json$/.test(file)){
- file = parseInt(file.replace('.json',''));
- matchIndex = matches.indexOf(file);
- if (matchIndex > -1){
- iterator++;
- delete matches[matchIndex];
- }
- }
- }
- let filtered = matches.filter(function (el) {
- return el != null;
- });
- matches = filtered;
- util.log('filtered matches:', iterator);
- util.log('total unique matches after filtering of downloaded files:', matches.length);
- util.log('receiving matches in loop');
- }
- let match = {};
- index = 0;
- percentage = 0;
- const iMax2 = matches.length;
- const percent = Math.floor(iMax2 / 100);
- (async function loop() {
- for (; index < iMax2; index++) {
- match = matches[index];
- if (index % percent === 0) {
- percentage++;
- util.log('past:', percentage + '%', 'index:', '#' + index, 'last match_id:', match);
- }
- if (match !== undefined && typeof match !== 'undefined') {
- await that.limiter.schedule((id) => mika.getMatch(id), match)
- .then((match) => {
- fs.writeFile(path + match.match_id + '.json', JSON.stringify(match), (err) => {
- if (err) throw err;
- util.log('downloaded:', '#' + index, 'match_id:', match.match_id);
- });
- })
- .catch(err => {
- util.log('getMatches: ', err, 'match: ', match, 'index: ', index);
- that.limiter.updateSettings({reservoir: 0});
- util.log('sleep for ' + (that.timeoutOnError) + ' sec');
- MatchesRetriever.sleep(that.timeoutOnError);
- let matches_new = [match];
- that._getMatchesData(matches_new, path, false);
- });
- }
- }
- })();
- }
- catch (err) {
- util.log(err);
- throw err;
- }
- }
- }
- module.exports = MatchesRetriever;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement