@@ -24,7 +24,7 @@ import { Serialized } from '@/types.js';
24
24
import { ReversiGameEntityService } from './entities/ReversiGameEntityService.js' ;
25
25
import type { OnModuleInit } from '@nestjs/common' ;
26
26
27
- const MATCHING_TIMEOUT_MS = 1000 * 20 ; // 20sec
27
+ const INVITATION_TIMEOUT_MS = 1000 * 20 ; // 20sec
28
28
29
29
@Injectable ( )
30
30
export class ReversiService implements OnModuleInit {
@@ -85,6 +85,7 @@ export class ReversiService implements OnModuleInit {
85
85
map : game . map ,
86
86
bw : game . bw ,
87
87
crc32 : game . crc32 ,
88
+ noIrregularRules : game . noIrregularRules ,
88
89
} satisfies Partial < MiReversiGame > ;
89
90
}
90
91
@@ -112,14 +113,16 @@ export class ReversiService implements OnModuleInit {
112
113
//#region 相手から既に招待されてないか確認
113
114
const invitations = await this . redisClient . zrange (
114
115
`reversi:matchSpecific:${ me . id } ` ,
115
- Date . now ( ) - MATCHING_TIMEOUT_MS ,
116
+ Date . now ( ) - INVITATION_TIMEOUT_MS ,
116
117
'+inf' ,
117
118
'BYSCORE' ) ;
118
119
119
120
if ( invitations . includes ( targetUser . id ) ) {
120
121
await this . redisClient . zrem ( `reversi:matchSpecific:${ me . id } ` , targetUser . id ) ;
121
122
122
- const game = await this . matched ( targetUser . id , me . id ) ;
123
+ const game = await this . matched ( targetUser . id , me . id , {
124
+ noIrregularRules : false ,
125
+ } ) ;
123
126
124
127
return game ;
125
128
}
@@ -138,7 +141,7 @@ export class ReversiService implements OnModuleInit {
138
141
}
139
142
140
143
@bindThis
141
- public async matchAnyUser ( me : MiUser , multiple = false ) : Promise < MiReversiGame | null > {
144
+ public async matchAnyUser ( me : MiUser , options : { noIrregularRules : boolean } , multiple = false ) : Promise < MiReversiGame | null > {
142
145
if ( ! multiple ) {
143
146
// 既にマッチしている対局が無いか探す(3分以内)
144
147
const games = await this . reversiGamesRepository . find ( {
@@ -157,41 +160,52 @@ export class ReversiService implements OnModuleInit {
157
160
//#region まず自分宛ての招待を探す
158
161
const invitations = await this . redisClient . zrange (
159
162
`reversi:matchSpecific:${ me . id } ` ,
160
- Date . now ( ) - MATCHING_TIMEOUT_MS ,
163
+ Date . now ( ) - INVITATION_TIMEOUT_MS ,
161
164
'+inf' ,
162
165
'BYSCORE' ) ;
163
166
164
167
if ( invitations . length > 0 ) {
165
168
const invitorId = invitations [ Math . floor ( Math . random ( ) * invitations . length ) ] ;
166
169
await this . redisClient . zrem ( `reversi:matchSpecific:${ me . id } ` , invitorId ) ;
167
170
168
- const game = await this . matched ( invitorId , me . id ) ;
171
+ const game = await this . matched ( invitorId , me . id , {
172
+ noIrregularRules : false ,
173
+ } ) ;
169
174
170
175
return game ;
171
176
}
172
177
//#endregion
173
178
174
179
const matchings = await this . redisClient . zrange (
175
180
'reversi:matchAny' ,
176
- Date . now ( ) - MATCHING_TIMEOUT_MS ,
177
- '+inf' ,
178
- 'BYSCORE ' ) ;
181
+ 0 ,
182
+ 2 , // 自分自身のIDが入っている場合もあるので2つ取得
183
+ 'REV ' ) ;
179
184
180
- const userIds = matchings . filter ( id => id !== me . id ) ;
185
+ const items = matchings . filter ( id => ! id . startsWith ( me . id ) ) ;
181
186
182
- if ( userIds . length > 0 ) {
183
- // pick random
184
- const matchedUserId = userIds [ Math . floor ( Math . random ( ) * userIds . length ) ] ;
187
+ if ( items . length > 0 ) {
188
+ const [ matchedUserId , option ] = items [ 0 ] . split ( ':' ) ;
185
189
186
- await this . redisClient . zrem ( 'reversi:matchAny' , me . id , matchedUserId ) ;
190
+ await this . redisClient . zrem ( 'reversi:matchAny' ,
191
+ me . id ,
192
+ matchedUserId ,
193
+ me . id + ':noIrregularRules' ,
194
+ matchedUserId + ':noIrregularRules' ) ;
187
195
188
- const game = await this . matched ( matchedUserId , me . id ) ;
196
+ const game = await this . matched ( matchedUserId , me . id , {
197
+ noIrregularRules : options . noIrregularRules || option === 'noIrregularRules' ,
198
+ } ) ;
189
199
190
200
return game ;
191
201
} else {
192
202
const redisPipeline = this . redisClient . pipeline ( ) ;
193
- redisPipeline . zadd ( 'reversi:matchAny' , Date . now ( ) , me . id ) ;
194
- redisPipeline . expire ( 'reversi:matchAny' , 120 , 'NX' ) ;
203
+ if ( options . noIrregularRules ) {
204
+ redisPipeline . zadd ( 'reversi:matchAny' , Date . now ( ) , me . id + ':noIrregularRules' ) ;
205
+ } else {
206
+ redisPipeline . zadd ( 'reversi:matchAny' , Date . now ( ) , me . id ) ;
207
+ }
208
+ redisPipeline . expire ( 'reversi:matchAny' , 15 , 'NX' ) ;
195
209
await redisPipeline . exec ( ) ;
196
210
return null ;
197
211
}
@@ -204,7 +218,7 @@ export class ReversiService implements OnModuleInit {
204
218
205
219
@bindThis
206
220
public async matchAnyUserCancel ( user : MiUser ) {
207
- await this . redisClient . zrem ( 'reversi:matchAny' , user . id ) ;
221
+ await this . redisClient . zrem ( 'reversi:matchAny' , user . id , user . id + ':noIrregularRules' ) ;
208
222
}
209
223
210
224
@bindThis
@@ -266,7 +280,7 @@ export class ReversiService implements OnModuleInit {
266
280
}
267
281
268
282
@bindThis
269
- private async matched ( parentId : MiUser [ 'id' ] , childId : MiUser [ 'id' ] ) : Promise < MiReversiGame > {
283
+ private async matched ( parentId : MiUser [ 'id' ] , childId : MiUser [ 'id' ] , options : { noIrregularRules : boolean ; } ) : Promise < MiReversiGame > {
270
284
const game = await this . reversiGamesRepository . insert ( {
271
285
id : this . idService . gen ( ) ,
272
286
user1Id : parentId ,
@@ -279,6 +293,7 @@ export class ReversiService implements OnModuleInit {
279
293
map : Reversi . maps . eighteight . data ,
280
294
bw : 'random' ,
281
295
isLlotheo : false ,
296
+ noIrregularRules : options . noIrregularRules ,
282
297
} ) . then ( x => this . reversiGamesRepository . findOneOrFail ( {
283
298
where : { id : x . identifiers [ 0 ] . id } ,
284
299
relations : [ 'user1' , 'user2' ] ,
@@ -380,7 +395,7 @@ export class ReversiService implements OnModuleInit {
380
395
public async getInvitations ( user : MiUser ) : Promise < MiUser [ 'id' ] [ ] > {
381
396
const invitations = await this . redisClient . zrange (
382
397
`reversi:matchSpecific:${ user . id } ` ,
383
- Date . now ( ) - MATCHING_TIMEOUT_MS ,
398
+ Date . now ( ) - INVITATION_TIMEOUT_MS ,
384
399
'+inf' ,
385
400
'BYSCORE' ) ;
386
401
return invitations ;
0 commit comments