Commit 38b84ace authored by nanahira's avatar nanahira

Merge branch 'master' into tcg_random

parents c3880a46 7fb1cfbb
......@@ -16,6 +16,7 @@ const DuelLogPlayer_1 = require("./entities/DuelLogPlayer");
const User_1 = require("./entities/User");
const VipKey_1 = require("./entities/VipKey");
const UserDialog_1 = require("./entities/UserDialog");
const RandomDuelScore_1 = require("./entities/RandomDuelScore");
class DataManager {
constructor(config, log) {
this.config = config;
......@@ -563,6 +564,79 @@ class DataManager {
}
});
}
async getRandomDuelScore(name) {
const repo = this.db.getRepository(RandomDuelScore_1.RandomDuelScore);
try {
const score = await repo.findOne(name);
return score;
}
catch (e) {
this.log.warn(`Failed to fetch random duel score ${name}: ${e.toString()}`);
return null;
}
}
async saveRandomDuelScore(score) {
const repo = this.db.getRepository(RandomDuelScore_1.RandomDuelScore);
try {
return await repo.save(score);
}
catch (e) {
this.log.warn(`Failed to save random duel score: ${e.toString()}`);
return null;
}
}
async getOrCreateRandomDuelScore(name) {
const score = await this.getRandomDuelScore(name);
if (score) {
return score;
}
const newScore = new RandomDuelScore_1.RandomDuelScore();
newScore.name = name;
return await this.saveRandomDuelScore(newScore);
}
async getRandomDuelScoreDisplay(name) {
const score = await this.getRandomDuelScore(name);
if (!score) {
return `${name.split("$")[0]} \${random_score_blank}`;
}
return score.getScoreText();
}
async randomDuelPlayerWin(name) {
const score = await this.getOrCreateRandomDuelScore(name);
score.win();
await this.saveRandomDuelScore(score);
}
async randomDuelPlayerLose(name) {
const score = await this.getOrCreateRandomDuelScore(name);
score.lose();
await this.saveRandomDuelScore(score);
}
async randomDuelPlayerFlee(name) {
const score = await this.getOrCreateRandomDuelScore(name);
score.flee();
await this.saveRandomDuelScore(score);
}
async getRandomScoreTop10() {
try {
const scores = await this.db.getRepository(RandomDuelScore_1.RandomDuelScore)
.createQueryBuilder("score")
.orderBy("score.win", "DESC")
.addOrderBy("score.lose", "ASC")
.addOrderBy("score.flee", "ASC")
.limit(10)
.getMany();
return scores.map(score => [score.getDisplayName(), {
win: score.winCount,
lose: score.loseCount,
flee: score.fleeCount,
combo: score.winCombo
}]);
}
catch (e) {
this.log.warn(`Failed to fetch random duel score ${name}: ${e.toString()}`);
return [];
}
}
}
exports.DataManager = DataManager;
//# sourceMappingURL=DataManager.js.map
\ No newline at end of file
......@@ -12,6 +12,7 @@ import {DuelLogPlayer} from "./entities/DuelLogPlayer";
import {User} from "./entities/User";
import {VipKey} from "./entities/VipKey";
import {UserDialog} from "./entities/UserDialog";
import {RandomDuelScore} from "./entities/RandomDuelScore";
interface BasePlayerInfo {
name: string;
......@@ -542,10 +543,10 @@ export class DataManager {
try {
const vipKeyList = vipInfo.cdkeys;
const newKeys: VipKey[] = [];
for(let keyTypeString in vipKeyList) {
for (let keyTypeString in vipKeyList) {
const keyType = parseInt(keyTypeString);
const keysTexts: string[] = vipKeyList[keyTypeString];
for(let keyText of keysTexts) {
for (let keyText of keysTexts) {
const newKey = new VipKey()
newKey.type = keyType;
newKey.key = keyText;
......@@ -553,14 +554,14 @@ export class DataManager {
}
}
await mdb.save(newKeys);
for(let vipUserName in vipInfo.players) {
for (let vipUserName in vipInfo.players) {
const oldVipUserInfo = vipInfo.players[vipUserName];
const userKey = vipUserName + '$' + oldVipUserInfo.password;
let user = await mdb.findOne(User, userKey);
if(user && user.isVip()) {
if (user && user.isVip()) {
continue;
}
if(!user) {
if (!user) {
user = new User();
user.key = userKey;
}
......@@ -569,7 +570,7 @@ export class DataManager {
user.words = oldVipUserInfo.words || null;
user = await mdb.save(user);
const newDialogues: UserDialog[] = [];
for(let dialogueCardCodeText in oldVipUserInfo.dialogues) {
for (let dialogueCardCodeText in oldVipUserInfo.dialogues) {
const cardCode = parseInt(dialogueCardCodeText);
const dialogueText = oldVipUserInfo.dialogues[dialogueCardCodeText];
const dialogue = new UserDialog();
......@@ -587,4 +588,74 @@ export class DataManager {
}
});
}
async getRandomDuelScore(name: string) {
const repo = this.db.getRepository(RandomDuelScore);
try {
const score = await repo.findOne(name);
return score;
} catch (e) {
this.log.warn(`Failed to fetch random duel score ${name}: ${e.toString()}`);
return null;
}
}
async saveRandomDuelScore(score: RandomDuelScore) {
const repo = this.db.getRepository(RandomDuelScore);
try {
return await repo.save(score);
} catch (e) {
this.log.warn(`Failed to save random duel score: ${e.toString()}`);
return null;
}
}
async getOrCreateRandomDuelScore(name: string) {
const score = await this.getRandomDuelScore(name);
if(score) {
return score;
}
const newScore = new RandomDuelScore();
newScore.name = name;
return await this.saveRandomDuelScore(newScore);
}
async getRandomDuelScoreDisplay(name: string) {
const score = await this.getRandomDuelScore(name);
if(!score) {
return `${name.split("$")[0]} \${random_score_blank}`;
}
return score.getScoreText();
}
async randomDuelPlayerWin(name: string) {
const score = await this.getOrCreateRandomDuelScore(name);
score.win();
await this.saveRandomDuelScore(score);
}
async randomDuelPlayerLose(name: string) {
const score = await this.getOrCreateRandomDuelScore(name);
score.lose();
await this.saveRandomDuelScore(score);
}
async randomDuelPlayerFlee(name: string) {
const score = await this.getOrCreateRandomDuelScore(name);
score.flee();
await this.saveRandomDuelScore(score);
}
async getRandomScoreTop10() {
try {
const scores = await this.db.getRepository(RandomDuelScore)
.createQueryBuilder("score")
.orderBy("score.win", "DESC")
.addOrderBy("score.lose", "ASC")
.addOrderBy("score.flee", "ASC")
.limit(10)
.getMany();
return scores.map(score => [score.getDisplayName(), {
win: score.winCount,
lose: score.loseCount,
flee: score.fleeCount,
combo: score.winCombo
}]);
} catch (e) {
this.log.warn(`Failed to fetch random duel score ${name}: ${e.toString()}`);
return [];
}
}
}
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RandomDuelScore = void 0;
const typeorm_1 = require("typeorm");
let RandomDuelScore = class RandomDuelScore {
getDisplayName() {
return this.name.split("$")[0];
}
win() {
++this.winCount;
++this.winCombo;
}
lose() {
++this.loseCount;
this.winCombo = 0;
}
flee() {
++this.fleeCount;
this.lose();
}
getScoreText() {
const displayName = this.getDisplayName();
const total = this.winCount + this.loseCount;
if (this.winCount < 2 && total < 3) {
return `${displayName} \${random_this_not_enough}`;
}
if (this.winCombo >= 2) {
return `\${random_this_part1}${displayName} \${random_this_part2} ${Math.ceil(this.winCount / total * 100)}\${random_this_part3} ${Math.ceil(this.fleeCount / total * 100)}\${random_this_part4_combo}${this.winCombo}\${random_this_part5_combo}`;
}
else {
//return displayName + " 的今日战绩:胜率" + Math.ceil(this.winCount/total*100) + "%,逃跑率" + Math.ceil(this.fleeCount/total*100) + "%," + this.winCombo + "连胜中!"
return `\${random_this_part1}${displayName} \${random_this_part2} ${Math.ceil(this.winCount / total * 100)}\${random_this_part3} ${Math.ceil(this.fleeCount / total * 100)}\${random_this_part4}`;
}
}
};
__decorate([
typeorm_1.PrimaryColumn({ type: "varchar", length: 20 }),
__metadata("design:type", String)
], RandomDuelScore.prototype, "name", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column("int", { unsigned: true, default: 0 }),
__metadata("design:type", Number)
], RandomDuelScore.prototype, "winCount", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column("int", { unsigned: true, default: 0 }),
__metadata("design:type", Number)
], RandomDuelScore.prototype, "loseCount", void 0);
__decorate([
typeorm_1.Index(),
typeorm_1.Column("int", { unsigned: true, default: 0 }),
__metadata("design:type", Number)
], RandomDuelScore.prototype, "fleeCount", void 0);
__decorate([
typeorm_1.Column("int", { unsigned: true, default: 0 }),
__metadata("design:type", Number)
], RandomDuelScore.prototype, "winCombo", void 0);
RandomDuelScore = __decorate([
typeorm_1.Entity()
], RandomDuelScore);
exports.RandomDuelScore = RandomDuelScore;
//# sourceMappingURL=RandomDuelScore.js.map
\ No newline at end of file
import {Column, Entity, Index, PrimaryColumn} from "typeorm";
@Entity()
export class RandomDuelScore {
@PrimaryColumn({type: "varchar", length: 20})
name: string;
@Index()
@Column("int", {unsigned: true, default: 0})
winCount: number;
@Index()
@Column("int", {unsigned: true, default: 0})
loseCount: number;
@Index()
@Column("int", {unsigned: true, default: 0})
fleeCount: number;
@Column("int", {unsigned: true, default: 0})
winCombo: number;
getDisplayName() {
return this.name.split("$")[0];
}
win() {
++this.winCount;
++this.winCombo;
}
lose() {
++this.loseCount;
this.winCombo = 0;
}
flee() {
++this.fleeCount;
this.lose();
}
getScoreText() {
const displayName = this.getDisplayName();
const total = this.winCount + this.loseCount;
if (this.winCount < 2 && total < 3) {
return `${displayName} \${random_score_not_enough}`;
}
if (this.winCombo >= 2) {
return `\${random_score_part1}${displayName} \${random_score_part2} ${Math.ceil(this.winCount / total * 100)}\${random_score_part3} ${Math.ceil(this.fleeCount / total * 100)}\${random_score_part4_combo}${this.winCombo}\${random_score_part5_combo}`;
} else {
//return displayName + " 的今日战绩:胜率" + Math.ceil(this.winCount/total*100) + "%,逃跑率" + Math.ceil(this.fleeCount/total*100) + "%," + this.winCombo + "连胜中!"
return `\${random_score_part1}${displayName} \${random_score_part2} ${Math.ceil(this.winCount / total * 100)}\${random_score_part3} ${Math.ceil(this.fleeCount / total * 100)}\${random_score_part4}`;
}
}
}
\ No newline at end of file
......@@ -67,14 +67,14 @@
"exp_value_part2": " exp",
"exp_value_part3": ", your score is ",
"exp_value_part4": ". These points may be reset after the stable release of MyCard.",
"random_score_part1": "Today's record of ",
"random_score_part1": "Record of ",
"random_score_part2": ": ",
"random_score_part3": "% WIN, ",
"random_score_part4_combo": "% RAGE QUIT, WIN COMBO ",
"random_score_part5_combo": " !",
"random_score_part4": "%",
"random_score_blank": " didn't have enough duel record today.",
"random_score_not_enough": " didn't have enough duel record today.",
"random_score_blank": " didn't have enough duel record.",
"random_score_not_enough": " didn't have enough duel record.",
"lp_low_opponent": "もはやお前のライフは風前の灯!",
"lp_low_self": "*Low LP Alert*",
"kicked_by_player": "was evicted from the game.",
......@@ -419,13 +419,13 @@
"exp_value_part3": ",你的战斗力是",
"exp_value_part4": "。竞技场部分积分按赛季重置。",
"random_score_part1": "",
"random_score_part2": "的今日战绩:胜率",
"random_score_part2": "的战绩:胜率",
"random_score_part3": "%,逃跑率",
"random_score_part4_combo": "%,",
"random_score_part5_combo": "连胜中!",
"random_score_part4": "%",
"random_score_blank": "的今日战绩:正在统计中",
"random_score_not_enough": "的今日战绩:正在统计中",
"random_score_blank": "的战绩:正在统计中",
"random_score_not_enough": "的战绩:正在统计中",
"lp_low_opponent": "你的生命已经如风中残烛了!",
"lp_low_self": "背水一战!",
"kicked_by_player": "被请出了房间",
......
......@@ -102,8 +102,11 @@ checkFileExists = (path) =>
return false
createDirectoryIfNotExists = (path) =>
if !await checkFileExists(path)
await fs.promises.mkdir(path, {recursive: true})
try
if path and !await checkFileExists(path)
await fs.promises.mkdir(path, {recursive: true})
catch e
log.warn("Failed to create directory #{path}: #{e.toString()}")
setting_save = global.setting_save = (settings) ->
try
......@@ -401,6 +404,11 @@ init = () ->
settings.modules.vip.enabled = false
await setting_save(settings)
log.warn("VIP mode cannot be enabled because no MySQL.")
if settings.modules.random_duel.record_match_scores
settings.modules.random_duel.record_match_scores = false
await setting_save(settings)
log.warn("Cannot record random match scores because no MySQL.")
# 读取数据
default_data = await loadJSONAsync('./data/default_data.json')
try
......@@ -582,13 +590,9 @@ init = () ->
if settings.modules.words.get
load_words()
if settings.modules.random_duel.post_match_scores
if settings.modules.random_duel.post_match_scores and settings.modules.mysql.enabled
setInterval(()->
scores_pair = _.pairs ROOM_players_scores
scores_by_lose = _.sortBy(scores_pair, (score)-> return score[1].lose).reverse() # 败场由高到低
scores_by_win = _.sortBy(scores_by_lose, (score)-> return score[1].win).reverse() # 然后胜场由低到高,再逆转,就是先排胜场再排败场
scores = _.first(scores_by_win, 10)
#log.info scores
scores = await dataManager.getRandomScoreTop10()
try
await axios.post(settings.modules.random_duel.post_match_scores, {
......@@ -721,7 +725,6 @@ setInterval(get_memory_usage, 3000)
ROOM_all = global.ROOM_all = []
ROOM_players_oppentlist = global.ROOM_players_oppentlist = {}
ROOM_players_scores = global.ROOM_players_scores = {}
ROOM_connected_ip = global.ROOM_connected_ip = {}
ROOM_bad_ip = global.ROOM_bad_ip = {}
......@@ -764,40 +767,27 @@ ROOM_kick = (name, callback)->
ROOM_player_win = global.ROOM_player_win = (name)->
if !ROOM_players_scores[name]
ROOM_players_scores[name]={win:0, lose:0, flee:0, combo:0}
ROOM_players_scores[name].win = ROOM_players_scores[name].win + 1
ROOM_players_scores[name].combo = ROOM_players_scores[name].combo + 1
if !settings.modules.mysql.enabled
return
await dataManager.randomDuelPlayerWin(name)
return
ROOM_player_lose = global.ROOM_player_lose = (name)->
if !ROOM_players_scores[name]
ROOM_players_scores[name]={win:0, lose:0, flee:0, combo:0}
ROOM_players_scores[name].lose = ROOM_players_scores[name].lose + 1
ROOM_players_scores[name].combo = 0
if !settings.modules.mysql.enabled
return
await dataManager.randomDuelPlayerLose(name)
return
ROOM_player_flee = global.ROOM_player_flee = (name)->
if !ROOM_players_scores[name]
ROOM_players_scores[name]={win:0, lose:0, flee:0, combo:0}
ROOM_players_scores[name].flee = ROOM_players_scores[name].flee + 1
ROOM_players_scores[name].combo = 0
if !settings.modules.mysql.enabled
return
await dataManager.randomDuelPlayerFlee(name)
return
ROOM_player_get_score = global.ROOM_player_get_score = (player)->
name = player.name_vpass
score = ROOM_players_scores[name]
if !score
return "#{player.name} ${random_score_blank}"
total = score.win + score.lose
if score.win < 2 and total < 3
return "#{player.name} ${random_score_not_enough}"
if score.combo >= 2
return "${random_score_part1}#{player.name} ${random_score_part2} #{Math.ceil(score.win/total*100)}${random_score_part3} #{Math.ceil(score.flee/total*100)}${random_score_part4_combo}#{score.combo}${random_score_part5_combo}"
#return player.name + " 的今日战绩:胜率" + Math.ceil(score.win/total*100) + "%,逃跑率" + Math.ceil(score.flee/total*100) + "%," + score.combo + "连胜中!"
else
return "${random_score_part1}#{player.name} ${random_score_part2} #{Math.ceil(score.win/total*100)}${random_score_part3} #{Math.ceil(score.flee/total*100)}${random_score_part4}"
return
if !settings.modules.mysql.enabled
return ""
return await dataManager.getRandomDuelScoreDisplay(player.name_vpass)
ROOM_find_or_create_by_name = global.ROOM_find_or_create_by_name = (name, player_ip)->
uname=name.toUpperCase()
......@@ -2647,9 +2637,9 @@ ygopro.stoc_follow 'JOIN_GAME', false, (buffer, info, client, server, datas)->
#client.score_shown = true
return
if settings.modules.random_duel.record_match_scores and room.random_type == 'M'
ygopro.stoc_send_chat_to_room(room, ROOM_player_get_score(client), ygopro.constants.COLORS.GREEN)
ygopro.stoc_send_chat_to_room(room, await ROOM_player_get_score(client), ygopro.constants.COLORS.GREEN)
for player in room.players when player.pos != 7 and player != client
ygopro.stoc_send_chat(client, ROOM_player_get_score(player), ygopro.constants.COLORS.GREEN)
ygopro.stoc_send_chat(client, await ROOM_player_get_score(player), ygopro.constants.COLORS.GREEN)
if !room.recorder
room.recorder = recorder = net.connect room.port, ->
ygopro.ctos_send recorder, 'PLAYER_INFO', {
......
This diff is collapsed.
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