enhance(reversi): 変則なしマッチングを可能に

This commit is contained in:
syuilo
2024-01-24 16:37:06 +09:00
parent 2b6bf074c6
commit 5719a929ad
15 changed files with 159 additions and 77 deletions

View File

@@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class Reversi61706081514499 {
name = 'Reversi61706081514499'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "reversi_game" ADD "noIrregularRules" boolean NOT NULL DEFAULT false`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "reversi_game" DROP COLUMN "noIrregularRules"`);
}
}

View File

@@ -85,6 +85,7 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
map: game.map,
bw: game.bw,
crc32: game.crc32,
noIrregularRules: game.noIrregularRules,
} satisfies Partial<MiReversiGame>;
}
@@ -138,7 +139,7 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
}
@bindThis
public async matchAnyUser(me: MiUser, multiple = false): Promise<MiReversiGame | null> {
public async matchAnyUser(me: MiUser, options: { noIrregularRules: boolean }, multiple = false): Promise<MiReversiGame | null> {
if (!multiple) {
// 既にマッチしている対局が無いか探す(3分以内)
const games = await this.reversiGamesRepository.find({
@@ -177,19 +178,29 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
2, // 自分自身のIDが入っている場合もあるので2つ取得
'REV');
const userIds = matchings.filter(id => id !== me.id);
const items = matchings.filter(id => !id.startsWith(me.id));
if (userIds.length > 0) {
const matchedUserId = userIds[0];
if (items.length > 0) {
const [matchedUserId, option] = items[0].split(':');
await this.redisClient.zrem('reversi:matchAny', me.id, matchedUserId);
await this.redisClient.zrem('reversi:matchAny',
me.id,
matchedUserId,
me.id + ':noIrregularRules',
matchedUserId + ':noIrregularRules');
const game = await this.matched(matchedUserId, me.id);
const game = await this.matched(matchedUserId, me.id, {
noIrregularRules: options.noIrregularRules || option === 'noIrregularRules',
});
return game;
} else {
const redisPipeline = this.redisClient.pipeline();
redisPipeline.zadd('reversi:matchAny', Date.now(), me.id);
if (options.noIrregularRules) {
redisPipeline.zadd('reversi:matchAny', Date.now(), me.id + ':noIrregularRules');
} else {
redisPipeline.zadd('reversi:matchAny', Date.now(), me.id);
}
redisPipeline.expire('reversi:matchAny', 15, 'NX');
await redisPipeline.exec();
return null;
@@ -203,7 +214,10 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
@bindThis
public async matchAnyUserCancel(user: MiUser) {
await this.redisClient.zrem('reversi:matchAny', user.id);
const redisPipeline = this.redisClient.pipeline();
redisPipeline.zrem('reversi:matchAny', user.id);
redisPipeline.zrem('reversi:matchAny', user.id + ':noIrregularRules');
await redisPipeline.exec();
}
@bindThis
@@ -265,7 +279,7 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
}
@bindThis
private async matched(parentId: MiUser['id'], childId: MiUser['id']): Promise<MiReversiGame> {
private async matched(parentId: MiUser['id'], childId: MiUser['id'], options: { noIrregularRules: boolean; }): Promise<MiReversiGame> {
const game = await this.reversiGamesRepository.insert({
id: this.idService.gen(),
user1Id: parentId,
@@ -278,6 +292,7 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
map: Reversi.maps.eighteight.data,
bw: 'random',
isLlotheo: false,
noIrregularRules: options.noIrregularRules,
}).then(x => this.reversiGamesRepository.findOneOrFail({
where: { id: x.identifiers[0].id },
relations: ['user1', 'user2'],

View File

@@ -61,6 +61,7 @@ export class ReversiGameEntityService {
canPutEverywhere: game.canPutEverywhere,
loopedBoard: game.loopedBoard,
timeLimitForEachTurn: game.timeLimitForEachTurn,
noIrregularRules: game.noIrregularRules,
logs: game.logs,
map: game.map,
});
@@ -105,6 +106,7 @@ export class ReversiGameEntityService {
canPutEverywhere: game.canPutEverywhere,
loopedBoard: game.loopedBoard,
timeLimitForEachTurn: game.timeLimitForEachTurn,
noIrregularRules: game.noIrregularRules,
});
}

View File

@@ -106,6 +106,11 @@ export class MiReversiGame {
})
public bw: string;
@Column('boolean', {
default: false,
})
public noIrregularRules: boolean;
@Column('boolean', {
default: false,
})

View File

@@ -82,6 +82,10 @@ export const packedReversiGameLiteSchema = {
type: 'string',
optional: false, nullable: false,
},
noIrregularRules: {
type: 'boolean',
optional: false, nullable: false,
},
isLlotheo: {
type: 'boolean',
optional: false, nullable: false,
@@ -196,6 +200,10 @@ export const packedReversiGameDetailedSchema = {
type: 'string',
optional: false, nullable: false,
},
noIrregularRules: {
type: 'boolean',
optional: false, nullable: false,
},
isLlotheo: {
type: 'boolean',
optional: false, nullable: false,

View File

@@ -37,6 +37,7 @@ export const paramDef = {
type: 'object',
properties: {
userId: { type: 'string', format: 'misskey:id', nullable: true },
noIrregularRules: { type: 'boolean', default: false },
multiple: { type: 'boolean', default: false },
},
required: [],
@@ -57,7 +58,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
throw err;
}) : null;
const game = target ? await this.reversiService.matchSpecificUser(me, target, ps.multiple) : await this.reversiService.matchAnyUser(me, ps.multiple);
const game = target
? await this.reversiService.matchSpecificUser(me, target, ps.multiple)
: await this.reversiService.matchAnyUser(me, { noIrregularRules: ps.noIrregularRules }, ps.multiple);
if (game == null) return;