@@ -447,7 +447,7 @@ async function verifyAndCorrectCountWithData(metaGame: string, countType: "curre
447447 }
448448
449449 const details = countsData . Item as MetaGameCounts ;
450-
450+
451451 // Check if the metaGame nested attribute exists at all
452452 if ( ! details [ metaGame ] ) {
453453 console . log ( `No nested attribute for ${ metaGame } in METAGAMES COUNTS, initializing...` ) ;
@@ -461,7 +461,7 @@ async function verifyAndCorrectCountWithData(metaGame: string, countType: "curre
461461 console . log ( `Initialized ${ countType } for new game ${ metaGame } to ${ actualCount } ` ) ;
462462 return ;
463463 }
464-
464+
465465 const storedCount = details [ metaGame ] [ countType ] || 0 ;
466466
467467 if ( storedCount !== actualCount ) {
@@ -2944,22 +2944,22 @@ async function updateStandingChallengeCount(metaGame: any, diff: number) {
29442944 ExpressionAttributeValues : { ":n" : diff , ":zero" : 0 } ,
29452945 UpdateExpression : "set #g.standingchallenges = if_not_exists(#g.standingchallenges, :zero) + :n" ,
29462946 } ) ;
2947-
2947+
29482948 try {
29492949 return await ddbDocClient . send ( updateCommand ) ;
29502950 } catch ( error : any ) {
29512951 if ( error . name === 'ValidationException' ) {
29522952 console . log ( `ValidationException updating METAGAMES/COUNTS standing challenges for new game ${ metaGame } . Initializing nested attribute...` ) ;
2953-
2953+
29542954 // Fetch current METAGAMES/COUNTS record
29552955 const countsData = await ddbDocClient . send ( new GetCommand ( {
29562956 TableName : process . env . ABSTRACT_PLAY_TABLE ,
29572957 Key : { "pk" : "METAGAMES" , "sk" : "COUNTS" }
29582958 } ) ) ;
2959-
2959+
29602960 // Initialize the nested attribute for this game
29612961 await verifyAndCorrectCountWithData ( metaGame , "standingchallenges" , 0 , countsData ) ;
2962-
2962+
29632963 // Retry the original update
29642964 return await ddbDocClient . send ( updateCommand ) ;
29652965 }
@@ -3257,21 +3257,21 @@ async function addToGameLists(type: string, game: Game, now: number, keepgame: b
32573257 ExpressionAttributeValues : { ":n" : 1 , ":zero" : 0 } ,
32583258 UpdateExpression : "set #g.currentgames = if_not_exists(#g.currentgames, :zero) + :n"
32593259 } ) ;
3260-
3260+
32613261 work . push (
32623262 sendCommandWithRetry ( updateCommand ) . catch ( async ( error ) => {
32633263 if ( error . name === 'ValidationException' ) {
32643264 console . log ( `ValidationException updating METAGAMES/COUNTS for new game ${ game . metaGame } . Initializing nested attribute...` ) ;
3265-
3265+
32663266 // Fetch current METAGAMES/COUNTS record
32673267 const countsData = await ddbDocClient . send ( new GetCommand ( {
32683268 TableName : process . env . ABSTRACT_PLAY_TABLE ,
32693269 Key : { "pk" : "METAGAMES" , "sk" : "COUNTS" }
32703270 } ) ) ;
3271-
3271+
32723272 // Initialize the nested attribute for this game
32733273 await verifyAndCorrectCountWithData ( game . metaGame , "currentgames" , 0 , countsData ) ;
3274-
3274+
32753275 // Retry the original update
32763276 return sendCommandWithRetry ( updateCommand ) ;
32773277 }
@@ -4375,7 +4375,7 @@ function applyMove(
43754375 } ) ) ) ;
43764376 }
43774377 }
4378-
4378+
43794379 game . state = engine . serialize ( ) ;
43804380 if ( engine . gameover ) {
43814381 game . toMove = "" ;
@@ -4396,10 +4396,10 @@ function isInterestingComment(comment: string): boolean {
43964396 }
43974397 // Normalize the comment
43984398 const normalized = comment . toLowerCase ( ) . trim ( ) ;
4399-
4399+
44004400 // Remove punctuation for comparison
44014401 const withoutPunctuation = normalized . replace ( / [ ^ \w \s ] / g, '' ) ;
4402-
4402+
44034403 // Common boring phrases (exact matches)
44044404 const boringPhrases = new Set ( [
44054405 'gg' , 'glhf' , 'gl' , 'hf' , 'tagg' , 'hi' , 'hello' , 'hey' ,
@@ -4410,48 +4410,48 @@ function isInterestingComment(comment: string): boolean {
44104410 'thanks for playing' , 'thanks for the game!' , 'gg thanks' ,
44114411 'yoyo' , 'yoyo gl' , 'yoyo gl hf'
44124412 ] ) ;
4413-
4413+
44144414 // Check for exact matches (with or without punctuation)
44154415 if ( boringPhrases . has ( normalized ) || boringPhrases . has ( withoutPunctuation ) ) {
44164416 return false ;
44174417 }
4418-
4418+
44194419 // Split into words for further analysis
44204420 const words = withoutPunctuation . split ( / \s + / ) . filter ( w => w . length > 0 ) ;
4421-
4421+
44224422 // Very short comments with only common game words are boring
44234423 const commonWords = new Set ( [
44244424 'gg' , 'gl' , 'hf' , 'tagg' , 'hi' , 'hello' , 'yoyo' ,
44254425 'thanks' , 'thx' , 'ty' , 'wp' , 'move' , 'pie' , 'invoked' ,
44264426 'good' , 'game' , 'luck' , 'fun' , 'for' , 'the' , 'a' , 'to' ,
44274427 'have' , 'sir' , 'well' , 'played' , 'you' , 'too'
44284428 ] ) ;
4429-
4429+
44304430 if ( words . length <= 3 && words . every ( w => commonWords . has ( w ) ) ) {
44314431 return false ;
44324432 }
4433-
4433+
44344434 // If we got here, the comment is interesting
44354435 return true ;
44364436}
44374437
44384438// Helper function to update lastChat and seen for all players of a game
44394439// Used by both submitComment (for in-game chats) and saveExploration (for completed game comments)
44404440async function updateLastChatForPlayers (
4441- gameId : string ,
4441+ gameId : string ,
44424442 metaGame : string ,
44434443 players : { [ k : string ] : any ; id : string } [ ] ,
44444444 currentUserId : string ,
44454445 allowReAdd : boolean = false // Only true for completed games via saveExploration
44464446) {
44474447 console . log ( `Updating lastChat for all players of game ${ gameId } ` ) ;
4448-
4448+
44494449 // Lazy-loaded only if needed (when a player doesn't have the game in their list)
44504450 let fullGame : FullGame | undefined ;
44514451 let gameEngine : any | undefined ;
4452-
4452+
44534453 const now = Date . now ( ) ;
4454-
4454+
44554455 for ( const pid of players . map ( p => p . id ) ) {
44564456 let data : any ;
44574457 let user : FullUser | undefined ;
@@ -4473,14 +4473,14 @@ async function updateLastChatForPlayers(
44734473 console . log ( `Unable to get user data for user ${ pid } when updating lastChat` ) ;
44744474 continue ; // Don't fail the whole operation
44754475 }
4476-
4476+
44774477 if ( user === undefined ) {
44784478 console . log ( `Unable to get user data for user ${ pid } when updating lastChat` ) ;
44794479 continue ; // Don't fail the whole operation
44804480 }
4481-
4481+
44824482 const game = user . games ?. find ( g => g . id === gameId ) ;
4483-
4483+
44844484 if ( game !== undefined ) {
44854485 game . lastChat = now ;
44864486 // if this is the user who added the comment/exploration, also update their `seen`
@@ -4493,7 +4493,7 @@ async function updateLastChatForPlayers(
44934493 } else if ( allowReAdd ) {
44944494 // Only try to re-add for completed games (when allowReAdd is true)
44954495 console . log ( `User ${ user . name } does not have a game entry for ${ gameId } , re-adding it` ) ;
4496-
4496+
44974497 // Fetch the full game only once (lazy loading)
44984498 if ( fullGame === undefined ) {
44994499 try {
@@ -4518,7 +4518,7 @@ async function updateLastChatForPlayers(
45184518 console . log ( `Failed to get completed game ${ gameId } for re-adding to user's list:` , err ) ;
45194519 }
45204520 }
4521-
4521+
45224522 if ( fullGame !== undefined && gameEngine !== undefined ) {
45234523 const newGame : Game = {
45244524 id : gameId ,
@@ -4533,7 +4533,7 @@ async function updateLastChatForPlayers(
45334533 lastChat : now ,
45344534 seen : pid === currentUserId ? now + 10 : undefined ,
45354535 } ;
4536-
4536+
45374537 if ( ! user . games ) {
45384538 user . games = [ ] ;
45394539 }
@@ -4593,19 +4593,19 @@ async function submitComment(userid: string, pars: { id: string; players?: {[k:
45934593 "comments" : comments
45944594 }
45954595 } ) ) ;
4596-
4596+
45974597 // Check if the new comment is interesting
45984598 const newCommentIsInteresting = isInterestingComment ( comment . comment ) ;
4599-
4599+
46004600 // If we didn't have interesting comments before but the new one is interesting,
46014601 // update the GAME record to set commented = 1
46024602 if ( pars . metaGame && ! hadInterestingCommentBefore && newCommentIsInteresting ) {
46034603 try {
46044604 await ddbDocClient . send ( new UpdateCommand ( {
46054605 TableName : process . env . ABSTRACT_PLAY_TABLE ,
4606- Key : {
4607- "pk" : "GAME" ,
4608- "sk" : pars . metaGame + "#0#" + pars . id
4606+ Key : {
4607+ "pk" : "GAME" ,
4608+ "sk" : pars . metaGame + "#0#" + pars . id
46094609 } ,
46104610 ExpressionAttributeValues : { ":c" : 1 } ,
46114611 UpdateExpression : "set commented = :c" ,
@@ -4618,7 +4618,7 @@ async function submitComment(userid: string, pars: { id: string; players?: {[k:
46184618 }
46194619 }
46204620 }
4621-
4621+
46224622 // Update lastChat for all players when a comment is added to an in-game chat
46234623 // Note: For completed games, comments go through the exploration system (saveExploration)
46244624 if ( pars . players && pars . metaGame ) {
@@ -4639,8 +4639,8 @@ async function saveExploration(userid: string, pars: { public: boolean, game: st
46394639 try {
46404640 await ddbDocClient . send ( new UpdateCommand ( {
46414641 TableName : process . env . ABSTRACT_PLAY_TABLE ,
4642- Key : {
4643- "pk" : "COMPLETEDGAMES#" + pars . metaGame ,
4642+ Key : {
4643+ "pk" : "COMPLETEDGAMES#" + pars . metaGame ,
46444644 "sk" : pars . gameEnded + "#" + pars . game
46454645 } ,
46464646 ExpressionAttributeValues : { ":c" : pars . updateCommentedFlag } ,
@@ -4653,7 +4653,7 @@ async function saveExploration(userid: string, pars: { public: boolean, game: st
46534653 // Don't fail the whole operation just because of the flag update
46544654 }
46554655 }
4656-
4656+
46574657 // If we need to update lastChat and seen for all players (completed games only)
46584658 if ( pars . updateLastChat && pars . public && pars . players ) {
46594659 await updateLastChatForPlayers (
@@ -4664,7 +4664,7 @@ async function saveExploration(userid: string, pars: { public: boolean, game: st
46644664 true // Allow re-adding game to list for completed games
46654665 ) ;
46664666 }
4667-
4667+
46684668 if ( ! pars . public ) {
46694669 await ddbDocClient . send ( new PutCommand ( {
46704670 TableName : process . env . ABSTRACT_PLAY_TABLE ,
@@ -7866,8 +7866,8 @@ async function updateCommented(userId: string, pars: {id: string; metaGame: stri
78667866 // For completed games, update COMPLETEDGAMES table
78677867 await ddbDocClient . send ( new UpdateCommand ( {
78687868 TableName : process . env . ABSTRACT_PLAY_TABLE ,
7869- Key : {
7870- "pk" : "COMPLETEDGAMES#" + pars . metaGame ,
7869+ Key : {
7870+ "pk" : "COMPLETEDGAMES#" + pars . metaGame ,
78717871 "sk" : pars . gameEnded + "#" + pars . id
78727872 } ,
78737873 ExpressionAttributeValues : { ":c" : pars . commented } ,
@@ -7879,17 +7879,17 @@ async function updateCommented(userId: string, pars: {id: string; metaGame: stri
78797879 // For current games, update GAME table
78807880 await ddbDocClient . send ( new UpdateCommand ( {
78817881 TableName : process . env . ABSTRACT_PLAY_TABLE ,
7882- Key : {
7883- "pk" : "GAME" ,
7884- "sk" : pars . metaGame + "#0#" + pars . id
7882+ Key : {
7883+ "pk" : "GAME" ,
7884+ "sk" : pars . metaGame + "#0#" + pars . id
78857885 } ,
78867886 ExpressionAttributeValues : { ":c" : pars . commented } ,
78877887 UpdateExpression : "set commented = :c" ,
78887888 ConditionExpression : "attribute_exists(pk) AND attribute_exists(sk)"
78897889 } ) ) ;
78907890 console . log ( `Successfully updated commented flag in GAME for game ${ pars . id } to ${ pars . commented } ` ) ;
78917891 }
7892-
7892+
78937893 return {
78947894 statusCode : 200 ,
78957895 body : JSON . stringify ( { success : true } ) ,
0 commit comments