@@ -194,7 +194,7 @@ type Game = {
194194 lastMoveTime : number ;
195195 clockHard : boolean ;
196196 noExplore ?: boolean ;
197- toMove : string | boolean [ ] ;
197+ toMove ? : string | boolean [ ] ;
198198 note ?: string ;
199199 seen ?: number ;
200200 winner ?: number [ ] ;
@@ -203,6 +203,7 @@ type Game = {
203203 gameEnded ?: number ;
204204 lastChat ?: number ;
205205 variants ?: string [ ] ;
206+ commented ?: number ; // 0 or missing: no comments or post game variations, 1: has in-game comments, 2: has post game variations, 3: has post game comments. Only used in main COMPLETEDGAMES list.
206207}
207208
208209type FullGame = {
@@ -235,6 +236,7 @@ type FullGame = {
235236 event ?: string ;
236237 division ?: number ;
237238 noExplore ?: boolean ;
239+ commented ?: number ; // 0 or missing: no comments or post game variations, 1: has in-game comments (note this does NOT get updated for post-game comments/variations)
238240}
239241
240242type Playground = {
@@ -649,6 +651,8 @@ module.exports.authQuery = async (event: { body: { query: any; pars: any; }; cog
649651 return await invokePie ( event . cognitoPoolClaims . sub , pars ) ;
650652 case "update_note" :
651653 return await updateNote ( event . cognitoPoolClaims . sub , pars ) ;
654+ case "update_commented" :
655+ return await updateCommented ( event . cognitoPoolClaims . sub , pars ) ;
652656 case "set_lastSeen" :
653657 return await setLastSeen ( event . cognitoPoolClaims . sub , pars ) ;
654658 case "submit_comment" :
@@ -1652,7 +1656,7 @@ async function me(claim: PartialClaims, pars: { size: string, vars: string, upda
16521656
16531657 console . log ( `Checking for out-of-time games` ) ;
16541658 for ( const game of games ) {
1655- if ( game . clockHard && game . toMove !== '' ) {
1659+ if ( game . clockHard && game . toMove && game . toMove !== '' ) {
16561660 if ( Array . isArray ( game . toMove ) ) {
16571661 let minTime = 0 ;
16581662 let minIndex = - 1 ;
@@ -3349,36 +3353,20 @@ async function submitMove(userid: string, pars: { id: string, move: string, draw
33493353 "players" : game . players ,
33503354 "clockHard" : game . clockHard ,
33513355 "noExplore" : game . noExplore || false ,
3352- "toMove" : game . toMove ,
3353- "lastMoveTime" : timestamp ,
3354- "numMoves" : engine . stack . length - 1 ,
3355- "gameStarted" : new Date ( engine . stack [ 0 ] . _timestamp ) . getTime ( ) ,
3356- "variants" : engine . variants ,
3357- } as Game ;
3358- const myGame = {
3359- "id" : game . id ,
3360- "metaGame" : game . metaGame ,
3361- "players" : game . players ,
3362- "clockHard" : game . clockHard ,
3363- "noExplore" : game . noExplore || false ,
3364- "toMove" : game . toMove ,
33653356 "lastMoveTime" : timestamp ,
33663357 "numMoves" : engine . stack . length - 1 ,
33673358 "gameStarted" : new Date ( engine . stack [ 0 ] . _timestamp ) . getTime ( ) ,
3368- "variants" : engine . variants ,
3359+ "variants" : engine . variants
33693360 } as Game ;
33703361 if ( engine . gameover ) {
33713362 playerGame . gameEnded = new Date ( engine . stack [ engine . stack . length - 1 ] . _timestamp ) . getTime ( ) ;
33723363 playerGame . winner = engine . winner ;
3373- myGame . gameEnded = new Date ( engine . stack [ engine . stack . length - 1 ] . _timestamp ) . getTime ( ) ;
3374- myGame . winner = engine . winner ;
33753364 }
33763365 const list : Promise < any > [ ] = [ ] ;
33773366 let newRatings : { [ metaGame : string ] : Rating } [ ] | null = null ;
33783367 if ( ( game . toMove === "" || game . toMove === null ) ) {
33793368 newRatings = updateRatings ( game , players ) ;
3380- myGame . seen = Date . now ( ) ;
3381- list . push ( addToGameLists ( "COMPLETEDGAMES" , playerGame , timestamp , game . numMoves !== undefined && game . numMoves > game . numPlayers ) ) ;
3369+ list . push ( addToGameLists ( "COMPLETEDGAMES" , { ...playerGame , commented : game . commented } , timestamp , game . numMoves !== undefined && game . numMoves > game . numPlayers ) ) ;
33823370 // delete at old sk
33833371 list . push ( ddbDocClient . send (
33843372 new DeleteCommand ( {
@@ -3446,12 +3434,18 @@ async function submitMove(userid: string, pars: { id: string, move: string, draw
34463434 players . forEach ( ( player , ind ) => {
34473435 const games : Game [ ] = [ ] ;
34483436 const updatedGames : string [ ] = [ ] ;
3437+ playerGame . toMove = game . toMove ;
34493438 player . games . forEach ( g => {
34503439 if ( g . id === playerGame . id ) {
3451- if ( player . id === userid )
3452- games . push ( myGame ) ;
3453- else
3440+ if ( player . id === userid ) {
3441+ if ( game . toMove === "" || game . toMove === null )
3442+ games . push ( { ...playerGame , seen : Date . now ( ) } ) ;
3443+ else
3444+ games . push ( playerGame ) ;
3445+ }
3446+ else {
34543447 games . push ( playerGame ) ;
3448+ }
34553449 updatedGames . push ( g . id ) ;
34563450 }
34573451 else
@@ -4174,7 +4168,7 @@ function applyMove(userid: string, move: string, engine: GameBase, game: FullGam
41744168 return moveForced ;
41754169}
41764170
4177- async function submitComment ( userid : string , pars : { id : string ; players ?: { [ k : string ] : any ; id : string } [ ] ; metaGame ?: string , comment : string ; moveNumber : number ; } ) {
4171+ async function submitComment ( userid : string , pars : { id : string ; players ?: { [ k : string ] : any ; id : string } [ ] ; metaGame ?: string , comment : string ; moveNumber : number ; updateCommented ?: number ; } ) {
41784172 // reject empty comments
41794173 if ( ( pars . comment . length === 0 ) || ( / ^ \s * $ / . test ( pars . comment ) ) ) {
41804174 return formatReturnError ( `Refusing to accept blank comment.` ) ;
@@ -4215,6 +4209,25 @@ async function submitComment(userid: string, pars: { id: string; players?: {[k:
42154209 }
42164210 } ) ) ;
42174211 }
4212+
4213+ // Update the commented flag for ongoing games if requested
4214+ if ( pars . updateCommented !== undefined && pars . updateCommented === 1 && pars . metaGame ) {
4215+ try {
4216+ await ddbDocClient . send ( new UpdateCommand ( {
4217+ TableName : process . env . ABSTRACT_PLAY_TABLE ,
4218+ Key : {
4219+ "pk" : "GAME" ,
4220+ "sk" : pars . metaGame + "#0#" + pars . id
4221+ } ,
4222+ ExpressionAttributeValues : { ":c" : 1 } ,
4223+ UpdateExpression : "set commented = :c" ,
4224+ } ) ) ;
4225+ console . log ( `Updated commented flag to 1 for game ${ pars . id } ` ) ;
4226+ } catch ( error ) {
4227+ console . log ( `Failed to update commented flag for game ${ pars . id } :` , error ) ;
4228+ // Don't fail the whole operation just because of the flag update
4229+ }
4230+ }
42184231
42194232 // if game is completed, `players` will be passed
42204233 // pull each user's record and update `lastChat`
@@ -4311,7 +4324,23 @@ async function submitComment(userid: string, pars: { id: string; players?: {[k:
43114324 }
43124325}
43134326
4314- async function saveExploration ( userid : string , pars : { public : boolean , game : string ; move : number ; version : number ; tree : Exploration ; } ) {
4327+ async function saveExploration ( userid : string , pars : { public : boolean , game : string ; metaGame : string ; move : number ; version : number ; tree : Exploration ; updateCommentedFlag ?: number ; gameEnded ?: number ; } ) {
4328+ // If we need to update the commented flag for a completed game
4329+ if ( pars . updateCommentedFlag !== undefined && pars . public && pars . gameEnded !== undefined ) {
4330+ // Update the commented flag in COMPLETEDGAMES
4331+ await ddbDocClient . send ( new UpdateCommand ( {
4332+ TableName : process . env . ABSTRACT_PLAY_TABLE ,
4333+ Key : {
4334+ "pk" : "COMPLETEDGAMES#" + pars . metaGame ,
4335+ "sk" : pars . game + "#" + pars . gameEnded
4336+ } ,
4337+ ExpressionAttributeValues : { ":c" : pars . updateCommentedFlag } ,
4338+ UpdateExpression : "set commented = :c" ,
4339+ } ) ) ;
4340+
4341+ console . log ( `Updated commented flag for completed game ${ pars . game } to ${ pars . updateCommentedFlag } ` ) ;
4342+ }
4343+
43154344 if ( ! pars . public ) {
43164345 await ddbDocClient . send ( new PutCommand ( {
43174346 TableName : process . env . ABSTRACT_PLAY_TABLE ,
@@ -7531,6 +7560,33 @@ async function updateNote(userId: string, pars: {gameId: string; note?: string;}
75317560 } ;
75327561}
75337562
7563+ async function updateCommented ( userId : string , pars : { id : string ; metaGame : string ; cbit : number ; commented : number ; } ) {
7564+ console . log ( `Updating commented flag for game ${ pars . id } to ${ pars . commented } ` ) ;
7565+ try {
7566+ // Directly update the commented flag without checking if game exists
7567+ // This is a non-critical flag, so we can save the DB lookup
7568+ await ddbDocClient . send ( new UpdateCommand ( {
7569+ TableName : process . env . ABSTRACT_PLAY_TABLE ,
7570+ Key : {
7571+ "pk" : "GAME" ,
7572+ "sk" : pars . metaGame + "#" + pars . cbit + "#" + pars . id
7573+ } ,
7574+ ExpressionAttributeValues : { ":c" : pars . commented } ,
7575+ UpdateExpression : "set commented = :c" ,
7576+ } ) ) ;
7577+
7578+ console . log ( `Successfully updated commented flag for game ${ pars . id } to ${ pars . commented } ` ) ;
7579+ return {
7580+ statusCode : 200 ,
7581+ body : JSON . stringify ( { success : true } ) ,
7582+ headers
7583+ } ;
7584+ } catch ( err ) {
7585+ logGetItemError ( err ) ;
7586+ return formatReturnError ( `Unable to update commented flag for game ${ pars . id } : ${ err } ` ) ;
7587+ }
7588+ }
7589+
75347590async function setLastSeen ( userId : string , pars : { gameId : string ; interval ?: number ; } ) {
75357591 // get USER rec
75367592 let user : FullUser | undefined ;
@@ -7618,13 +7674,13 @@ async function botManageChallenges() {
76187674 // the overall meta must be supported
76197675 const info = gameinfo . get ( challenge . metaGame ) ;
76207676 if ( info ?. flags . includes ( "aiai" ) ) {
7621- accepted = true ;
7677+ accepted = true ;
76227678 }
76237679 // add any variant exceptions here too
76247680 if ( challenge . metaGame === "tumbleweed" ) {
7625- if ( challenge . variants . includes ( "free-neutral" ) || challenge . variants . includes ( "capture-delay" ) ) {
7626- accepted = false ;
7627- }
7681+ if ( challenge . variants . includes ( "free-neutral" ) || challenge . variants . includes ( "capture-delay" ) ) {
7682+ accepted = false ;
7683+ }
76287684 }
76297685
76307686 // accept/reject challenge
@@ -7640,41 +7696,44 @@ async function botManageChallenges() {
76407696 // have to refetch, sadly!
76417697 // but check for bot's turn early to avoid unnecessary refetches
76427698 try {
7643- console . log ( `Getting USER record` ) ;
7644- const userData = await ddbDocClient . send (
7645- new GetCommand ( {
7646- TableName : process . env . ABSTRACT_PLAY_TABLE ,
7647- Key : {
7648- "pk" : "USER" ,
7649- "sk" : userId
7650- } ,
7651- } ) ) ;
7652- if ( userData . Item === undefined ) {
7653- throw new Error ( "Could not find a USER record for the AiAi bot" ) ;
7654- }
7655- const user = userData . Item as FullUser ;
7656- let games : Game [ ] = user . games ;
7657- if ( games === undefined )
7658- games = [ ] ;
7659-
7660- for ( const game of games ) {
7661- const info = gameinfo . get ( game . metaGame ) ;
7662- if ( game . toMove !== null && game . toMove !== "" ) {
7663- const ids : string [ ] = [ ] ;
7664- if ( info . flags . includes ( "simultaneous" ) ) {
7665- for ( let i = 0 ; i < ( game . toMove as boolean [ ] ) . length ; i ++ ) {
7666- if ( game . toMove [ i ] ) {
7667- ids . push ( game . players [ i ] . id ) ;
7668- }
7669- }
7670- } else {
7671- ids . push ( game . players [ parseInt ( game . toMove as string , 10 ) ] . id ) ;
7672- }
7673- if ( ids . includes ( process . env . AIAI_USERID ! ) ) {
7674- await realPingBot ( game . metaGame , game . id ) ;
7699+ console . log ( `Getting USER record` ) ;
7700+ const userData = await ddbDocClient . send (
7701+ new GetCommand ( {
7702+ TableName : process . env . ABSTRACT_PLAY_TABLE ,
7703+ Key : {
7704+ "pk" : "USER" ,
7705+ "sk" : userId
7706+ } ,
7707+ } ) ) ;
7708+ if ( userData . Item === undefined ) {
7709+ throw new Error ( "Could not find a USER record for the AiAi bot" ) ;
7710+ }
7711+ const user = userData . Item as FullUser ;
7712+ let games : Game [ ] = user . games ;
7713+ if ( games === undefined )
7714+ games = [ ] ;
7715+
7716+ for ( const game of games ) {
7717+ const info = gameinfo . get ( game . metaGame ) ;
7718+ if ( game . toMove !== null && game . toMove !== "" ) {
7719+ const ids : string [ ] = [ ] ;
7720+ if ( info . flags . includes ( "simultaneous" ) ) {
7721+ const toMove = game . toMove as boolean [ ] ;
7722+ if ( toMove ) {
7723+ for ( let i = 0 ; i < toMove . length ; i ++ ) {
7724+ if ( toMove [ i ] ) {
7725+ ids . push ( game . players [ i ] . id ) ;
76757726 }
7727+ }
76767728 }
7729+ } else {
7730+ ids . push ( game . players [ parseInt ( game . toMove as string , 10 ) ] . id ) ;
7731+ }
7732+ if ( ids . includes ( process . env . AIAI_USERID ! ) ) {
7733+ await realPingBot ( game . metaGame , game . id ) ;
7734+ }
76777735 }
7736+ }
76787737 } catch ( err ) {
76797738 logGetItemError ( err ) ;
76807739 return formatReturnError ( `Unable to manage bot challenges: ${ err } ` ) ;
0 commit comments