Commit c7e92124 authored by nanahira's avatar nanahira

athletic check

parent c6056e21
Pipeline #887 failed with stage
in 6 minutes and 54 seconds
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AthleticChecker = void 0;
const axios_1 = __importDefault(require("axios"));
const querystring_1 = __importDefault(require("querystring"));
const moment_1 = __importDefault(require("moment"));
class AthleticChecker {
constructor(config) {
this.config = config;
}
deckToString(deck) {
const deckText = '#ygopro-server deck log\n#main\n' + deck.main.join('\n') + '\n!side\n' + deck.side.join('\n') + '\n';
return deckText;
}
async getAthleticDecks() {
if (this.athleticDeckCache && moment_1.default().diff(this.lastAthleticDeckFetchTime, "seconds") < this.config.ttl) {
return this.athleticDeckCache;
}
const { data } = await axios_1.default.get(this.config.rankURL, {
timeout: 10000,
responseType: "json",
paramsSerializer: querystring_1.default.stringify,
params: this.config.athleticFetchParams
});
const athleticDecks = data.slice(0, this.config.rankCount).map(m => m.name);
this.athleticDeckCache = athleticDecks;
this.lastAthleticDeckFetchTime = moment_1.default();
return athleticDecks;
}
async getDeckType(deck) {
const deckString = this.deckToString(deck);
const { data } = await axios_1.default.post(this.config.identifierURL, querystring_1.default.stringify({ deck: deckString }), {
timeout: 10000,
responseType: "json"
});
return data.deck;
}
async checkAthletic(deck) {
try {
const athleticDecks = await this.getAthleticDecks();
const deckType = await this.getDeckType(deck);
const athletic = athleticDecks.includes(deckType);
return { success: true, athletic, message: null };
}
catch (e) {
return { success: false, message: e.toString() };
}
}
}
exports.AthleticChecker = AthleticChecker;
//# sourceMappingURL=athletic-check.js.map
\ No newline at end of file
import axios from "axios";
import qs from "querystring";
import moment, {Moment} from "moment";
interface Deck {
main: number[];
side: number[];
}
interface Config {
rankURL: string;
identifierURL: string;
athleticFetchParams: any;
rankCount: number;
ttl: number;
}
interface AthleticDecksReturnData {
name: string
}
interface ReturnMessage {
success: boolean;
athletic?: boolean;
message: string;
}
export class AthleticChecker {
config: Config;
athleticDeckCache: string[];
lastAthleticDeckFetchTime: Moment;
constructor(config: Config) {
this.config = config;
}
deckToString(deck: Deck) {
const deckText = '#ygopro-server deck log\n#main\n' + deck.main.join('\n') + '\n!side\n' + deck.side.join('\n') + '\n';
return deckText;
}
async getAthleticDecks(): Promise<string[]> {
if (this.athleticDeckCache && moment().diff(this.lastAthleticDeckFetchTime, "seconds") < this.config.ttl) {
return this.athleticDeckCache;
}
const { data } = await axios.get(this.config.rankURL, {
timeout: 10000,
responseType: "json",
paramsSerializer: qs.stringify,
params: this.config.athleticFetchParams
});
const athleticDecks = (data as AthleticDecksReturnData[]).slice(0, this.config.rankCount).map(m => m.name);
this.athleticDeckCache = athleticDecks;
this.lastAthleticDeckFetchTime = moment();
return athleticDecks;
}
async getDeckType(deck: Deck): Promise<string> {
const deckString = this.deckToString(deck);
const { data } = await axios.post(this.config.identifierURL, qs.stringify({ deck: deckString }), {
timeout: 10000,
responseType: "json"
});
return data.deck;
}
async checkAthletic(deck: Deck): Promise<ReturnMessage> {
try {
const athleticDecks = await this.getAthleticDecks();
const deckType = await this.getDeckType(deck);
const athletic = athleticDecks.includes(deckType);
return { success: true, athletic, message: null }
} catch (e) {
return { success: false, message: e.toString() };
}
}
}
......@@ -177,6 +177,17 @@
"log_save_path": "./config/",
"port": 7933
},
"athletic_check": {
"enabled": false,
"rankURL": "https://api.mycard.moe/ygopro/analytics/deck/type",
"identifierURL": "https://api.mycard.moe/ygopro/identifier/production",
"athleticFetchParams": {
"type": "week",
"source": "mycard-athletic"
},
"rankCount": 10,
"ttl": 600
},
"test_mode": {
"watch_public_hand": false,
"no_connect_count_limit": false,
......
......@@ -168,7 +168,8 @@
"auto_death_part1": "This room is an auto-extra-duel room. The Extra Duel will begin after ",
"auto_death_part2": " minutes.",
"athletic_arena_tip": "During an athletic match, a game quit behavior is regarded as a surrender.",
"windbot_disable_random_room": "By adding the AI, this random game won't get any new player unless they enter the room name:"
"windbot_disable_random_room": "By adding the AI, this random game won't get any new player unless they enter the room name:",
"using_athletic_deck": " is using an athletic deck."
},
"es-es": {
"random_duel_enter_room_waiting": "Tu oponente esta listo, Iniciar!",
......@@ -485,7 +486,8 @@
"auto_death_part1": "本房间为自动加时赛房间。比赛开始",
"auto_death_part2": "分钟后,将自动进入加时赛。",
"athletic_arena_tip": "在竞技匹配中,比赛开始前退出游戏也会视为投降。",
"windbot_disable_random_room": "因为添加了AI,本随机对战房间将只能通过房间名加入:"
"windbot_disable_random_room": "因为添加了AI,本随机对战房间将只能通过房间名加入:",
"using_athletic_deck": " 正在使用竞技卡组。"
},
"ko-kr": {
"random_duel_enter_room_waiting": "땅콩: 게임을 진행하게 준비 또는 시작을 하십시오.",
......
......@@ -324,6 +324,10 @@ if settings.modules.heartbeat_detection.enabled
if settings.modules.tournament_mode.enable_recover
ReplayParser = global.ReplayParser = require "./Replay.js"
if settings.modules.athletic_check.enabled
AthleticChecker = require("./athletic-check.js").AthleticChecker
athleticChecker = global.athleticChecker = new AthleticChecker(settings.modules.athletic_check)
# 组件
ygopro = global.ygopro = require './ygopro.js'
roomlist = global.roomlist = require './roomlist.js' if settings.modules.http.websocket_roomlist
......@@ -1609,6 +1613,20 @@ class Room
for buffer in @recover_buffers[player.pos]
ygopro.stoc_send(player, "GAME_MSG", buffer)
check_athletic: ->
players = @get_playing_player()
room = this
await Promise.all(players.map((player) ->
main = _.clone(player.main)
side = _.clone(player.side)
using_athletic = await athleticChecker.checkAthletic({main: main, side: side})
if !using_athletic.success
log.warn("GET ATHLETIC FAIL", player.name, using_athletic.message)
else if using_athletic.athletic
ygopro.stoc_send_chat_to_room(room, "#{player.name}${using_athletic_deck}", ygopro.constants.COLORS.BABYBLUE)
))
await return
# 网络连接
net.createServer (client) ->
client.ip = client.remoteAddress
......@@ -2800,15 +2818,24 @@ ygopro.stoc_follow 'HS_PLAYER_ENTER', true, (buffer, info, client, server, datas
ygopro.stoc_follow 'HS_PLAYER_CHANGE', true, (buffer, info, client, server, datas)->
room=ROOM_all[client.rid]
return unless room and room.max_player and client.pos == 0
return unless room and client.pos == 0
pos = info.status >> 4
is_ready = (info.status & 0xf) == 9
if pos < room.max_player
if room.arena
room.ready_player_count = 0
for player in room.players
if player.pos == pos
player.is_ready = is_ready
room.ready_player_count = 0
room.ready_player_count_without_host = 0
for player in room.players
if player.pos == pos
player.is_ready = is_ready
if player.is_ready
++room.ready_player_count
unless player.is_host
++room.ready_player_count_without_host
if settings.modules.athletic_check.enabled
possibly_max_player = if room.hostinfo.mode == 2 then 4 else 2
if room.ready_player_count >= possibly_max_player
room.check_athletic()
if room.max_player and pos < room.max_player
if room.arena # mycard
p1 = room.players[0]
p2 = room.players[1]
if !p1 or !p2
......@@ -2832,13 +2859,7 @@ ygopro.stoc_follow 'HS_PLAYER_CHANGE', true, (buffer, info, client, server, data
clearInterval room.waiting_for_player_interval
room.waiting_for_player_interval = null
room.waiting_for_player_time = settings.modules.arena_mode.ready_time
else
room.ready_player_count_without_host = 0
for player in room.players
if player.pos == pos
player.is_ready = is_ready
unless player.is_host
room.ready_player_count_without_host += player.is_ready
else # random duel
if room.ready_player_count_without_host >= room.max_player - 1
#log.info "all ready"
setTimeout (()-> wait_room_start(ROOM_all[client.rid], settings.modules.random_duel.ready_time);return), 1000
......
// Generated by CoffeeScript 2.5.1
(function() {
// 标准库
var CLIENT_get_authorize_key, CLIENT_get_kick_reconnect_target, CLIENT_heartbeat_register, CLIENT_heartbeat_unregister, CLIENT_import_data, CLIENT_is_able_to_kick_reconnect, CLIENT_is_able_to_reconnect, CLIENT_is_banned_by_mc, CLIENT_is_player, CLIENT_kick, CLIENT_kick_reconnect, CLIENT_pre_reconnect, CLIENT_reconnect, CLIENT_reconnect_register, CLIENT_reconnect_unregister, CLIENT_send_pre_reconnect_info, CLIENT_send_reconnect_info, CLIENT_send_replays, Cloud_replay_ids, ROOM_all, ROOM_bad_ip, ROOM_ban_player, ROOM_clear_disconnect, ROOM_connected_ip, ROOM_find_by_name, ROOM_find_by_pid, ROOM_find_by_port, ROOM_find_by_title, ROOM_find_or_create_ai, ROOM_find_or_create_by_name, ROOM_find_or_create_random, ROOM_kick, ROOM_player_flee, ROOM_player_get_score, ROOM_player_lose, ROOM_player_win, ROOM_players_banned, ROOM_players_oppentlist, ROOM_players_scores, ROOM_unwelcome, ROOM_validate, ReplayParser, ResolveData, Room, SERVER_clear_disconnect, SERVER_kick, SOCKET_flush_data, _, _async, addCallback, auth, axios, badwords, ban_user, bunyan, challonge, challonge_cache, challonge_module_name, challonge_queue_callbacks, challonge_type, chat_color, config, cppversion, crypto, date, deck_name_match, default_config, default_data, dialogues, disconnect_list, dns, duel_log, e, exec, execFile, fs, geoip, getSeedTimet, get_callback, get_memory_usage, http, http_server, https, https_server, import_datas, imported, is_challonge_requesting, j, l, len, len1, len2, len3, lflists, list, loadJSON, load_dialogues, load_tips, log, long_resolve_cards, m, memory_usage, merge, moment, n, net, oldbadwords, oldconfig, olddialogues, oldduellog, oldtips, options, os, path, pgClient, pg_client, pg_query, plugin_filename, plugin_list, plugin_path, qs, real_windbot_server_ip, redis, redisdb, ref, ref1, ref2, refresh_challonge_cache, release_disconnect, replaced_index, report_to_big_brother, request, requestListener, roomlist, setting_change, setting_save, settings, spawn, spawnSync, spawn_windbot, tips, url, users_cache, util, wait_room_start, wait_room_start_arena, windbot_looplimit, windbot_process, windbots, ygopro, zlib;
var AthleticChecker, CLIENT_get_authorize_key, CLIENT_get_kick_reconnect_target, CLIENT_heartbeat_register, CLIENT_heartbeat_unregister, CLIENT_import_data, CLIENT_is_able_to_kick_reconnect, CLIENT_is_able_to_reconnect, CLIENT_is_banned_by_mc, CLIENT_is_player, CLIENT_kick, CLIENT_kick_reconnect, CLIENT_pre_reconnect, CLIENT_reconnect, CLIENT_reconnect_register, CLIENT_reconnect_unregister, CLIENT_send_pre_reconnect_info, CLIENT_send_reconnect_info, CLIENT_send_replays, Cloud_replay_ids, ROOM_all, ROOM_bad_ip, ROOM_ban_player, ROOM_clear_disconnect, ROOM_connected_ip, ROOM_find_by_name, ROOM_find_by_pid, ROOM_find_by_port, ROOM_find_by_title, ROOM_find_or_create_ai, ROOM_find_or_create_by_name, ROOM_find_or_create_random, ROOM_kick, ROOM_player_flee, ROOM_player_get_score, ROOM_player_lose, ROOM_player_win, ROOM_players_banned, ROOM_players_oppentlist, ROOM_players_scores, ROOM_unwelcome, ROOM_validate, ReplayParser, ResolveData, Room, SERVER_clear_disconnect, SERVER_kick, SOCKET_flush_data, _, _async, addCallback, athleticChecker, auth, axios, badwords, ban_user, bunyan, challonge, challonge_cache, challonge_module_name, challonge_queue_callbacks, challonge_type, chat_color, config, cppversion, crypto, date, deck_name_match, default_config, default_data, dialogues, disconnect_list, dns, duel_log, e, exec, execFile, fs, geoip, getSeedTimet, get_callback, get_memory_usage, http, http_server, https, https_server, import_datas, imported, is_challonge_requesting, j, l, len, len1, len2, len3, lflists, list, loadJSON, load_dialogues, load_tips, log, long_resolve_cards, m, memory_usage, merge, moment, n, net, oldbadwords, oldconfig, olddialogues, oldduellog, oldtips, options, os, path, pgClient, pg_client, pg_query, plugin_filename, plugin_list, plugin_path, qs, real_windbot_server_ip, redis, redisdb, ref, ref1, ref2, refresh_challonge_cache, release_disconnect, replaced_index, report_to_big_brother, request, requestListener, roomlist, setting_change, setting_save, settings, spawn, spawnSync, spawn_windbot, tips, url, users_cache, util, wait_room_start, wait_room_start_arena, windbot_looplimit, windbot_process, windbots, ygopro, zlib;
net = require('net');
......@@ -417,6 +417,11 @@
ReplayParser = global.ReplayParser = require("./Replay.js");
}
if (settings.modules.athletic_check.enabled) {
AthleticChecker = require("./athletic-check.js").AthleticChecker;
athleticChecker = global.athleticChecker = new AthleticChecker(settings.modules.athletic_check);
}
// 组件
ygopro = global.ygopro = require('./ygopro.js');
......@@ -2185,6 +2190,26 @@
}
}
async check_athletic() {
var players, room;
players = this.get_playing_player();
room = this;
await Promise.all(players.map(async function(player) {
var main, side, using_athletic;
main = _.clone(player.main);
side = _.clone(player.side);
using_athletic = (await athleticChecker.checkAthletic({
main: main,
side: side
}));
if (!using_athletic.success) {
return log.warn("GET ATHLETIC FAIL", player.name, using_athletic.message);
} else if (using_athletic.athletic) {
return ygopro.stoc_send_chat_to_room(room, `${player.name}\${using_athletic_deck}`, ygopro.constants.COLORS.BABYBLUE);
}
}));
}
};
// 网络连接
......@@ -3668,23 +3693,36 @@
});
ygopro.stoc_follow('HS_PLAYER_CHANGE', true, async function(buffer, info, client, server, datas) {
var is_ready, len3, len4, n, o, p1, p2, player, pos, ref3, ref4, room;
var is_ready, len3, n, p1, p2, player, pos, possibly_max_player, ref3, room;
room = ROOM_all[client.rid];
if (!(room && room.max_player && client.pos === 0)) {
if (!(room && client.pos === 0)) {
return;
}
pos = info.status >> 4;
is_ready = (info.status & 0xf) === 9;
if (pos < room.max_player) {
if (room.arena) {
room.ready_player_count = 0;
ref3 = room.players;
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
if (player.pos === pos) {
player.is_ready = is_ready;
}
room.ready_player_count = 0;
room.ready_player_count_without_host = 0;
ref3 = room.players;
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
if (player.pos === pos) {
player.is_ready = is_ready;
}
if (player.is_ready) {
++room.ready_player_count;
if (!player.is_host) {
++room.ready_player_count_without_host;
}
}
}
if (settings.modules.athletic_check.enabled) {
possibly_max_player = room.hostinfo.mode === 2 ? 4 : 2;
if (room.ready_player_count >= possibly_max_player) {
room.check_athletic();
}
}
if (room.max_player && pos < room.max_player) {
if (room.arena) { // mycard
p1 = room.players[0];
p2 = room.players[1];
if (!p1 || !p2) {
......@@ -3714,20 +3752,9 @@
} else if (!room.waiting_for_player && room.waiting_for_player_interval) {
clearInterval(room.waiting_for_player_interval);
room.waiting_for_player_interval = null;
room.waiting_for_player_time = settings.modules.arena_mode.ready_time;
room.waiting_for_player_time = settings.modules.arena_mode.ready_time; // random duel
}
} else {
room.ready_player_count_without_host = 0;
ref4 = room.players;
for (o = 0, len4 = ref4.length; o < len4; o++) {
player = ref4[o];
if (player.pos === pos) {
player.is_ready = is_ready;
}
if (!player.is_host) {
room.ready_player_count_without_host += player.is_ready;
}
}
if (room.ready_player_count_without_host >= room.max_player - 1) {
//log.info "all ready"
setTimeout((function() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment