11<template >
22 <div class =" backdrop d-flex flex-column justify-content-center align-items-center" >
3+ <button @click =" leaveAll" >leave all</button >
4+ <p v-if =" reconnectTimeout && !isTransitioning" >Connection lost. Attempting to reconnect...</p >
35 <b-alert v-if =" started" variant =" warning" show dismissible >
46 <small >
57 <p >
1719 <p >{{ joinFailureReason }}</p >
1820 </div >
1921 <div
20- v-if =" !started && lobbyRoom"
22+ v-else- if =" !started && lobbyRoom"
2123 class =" mt-5 text-center p-5"
2224 style =" max-width : 30rem ; margin : auto "
2325 >
3032 other participants to join. If 5 minutes passes since the last player joined the lobby,
3133 you will be redirected back to Prolific and compensated for your time.
3234 </p >
33- <p >Please <b >do not</b > refresh this page</p >
35+ <p >Please <b >do not</b > refresh this page as this will reset the timer </p >
3436 </small >
3537 </div >
3638
@@ -143,7 +145,7 @@ export default class ProlificMultiplayerStudy extends Vue {
143145 }
144146
145147 get gameOverText() {
146- return this .isSecondGame
148+ return this .isStudyComplete || this . isSecondGame
147149 ? " You have completed the study. Thank you for your participation!"
148150 : " You will be advanced to the next game in a few seconds.." ;
149151 }
@@ -168,16 +170,7 @@ export default class ProlificMultiplayerStudy extends Vue {
168170 async created() {
169171 await this .fetchParticipantStatus ();
170172 if (this .participantStatus .status === " not-started" ) {
171- try {
172- await this .joinLobby ();
173- } catch (error ) {
174- console .error (" Failed to join lobby:" , error );
175- if (error instanceof Error ) {
176- this .joinFailureReason = error .message ;
177- } else {
178- this .joinFailureReason = " Failed to join lobby. Please try refreshing the page." ;
179- }
180- }
173+ await this .joinLobby ();
181174 } else if (this .participantStatus .status === " in-progress" ) {
182175 if (this .participantStatus .activeRoomId ) {
183176 // try to re-join active game
@@ -186,24 +179,81 @@ export default class ProlificMultiplayerStudy extends Vue {
186179 }
187180 }
188181
189- private async joinLobby() {
190- this .lobbyRoom = await this .$client .joinOrCreate (LITE_LOBBY_NAME , { type: " prolificBaseline" });
191- applyLiteLobbyResponses (this .lobbyRoom , this );
192- this .lobbyApi .connect (this .lobbyRoom );
182+ private async onLobbyLeave() {
183+ this .lobbyRoom = null ;
184+ this .scheduleReconnect ();
185+ }
186+
187+ private async onGameLeave() {
188+ this .gameRoom = null ;
189+ this .scheduleReconnect ();
190+ }
191+
192+ private reconnectTimeout: number | null = null ;
193+ private isTransitioning = false ;
193194
194- // intercept lobby -> game messages
195- this .lobbyRoom .onMessage (" removed-client-from-lobby" , () => this .transitionToGame ());
196- this .lobbyRoom .onMessage (" join-existing-game" , () => this .transitionToGame ());
195+ private async scheduleReconnect() {
196+ if (this .reconnectTimeout ) {
197+ clearTimeout (this .reconnectTimeout );
198+ }
199+ this .reconnectTimeout = setTimeout (async () => {
200+ this .reconnectTimeout = null ;
201+ this .attemptReconnect ();
202+ }, 10000 );
203+ }
204+
205+ private async attemptReconnect() {
206+ // abort if we're already connected
207+ if (this .lobbyRoom || this .gameRoom ) return ;
208+ await this .fetchParticipantStatus ();
209+ if (this .participantStatus .status === " in-progress" && this .participantStatus .activeRoomId ) {
210+ await this .joinGame (this .participantStatus .activeRoomId );
211+ } else if (this .participantStatus .status === " not-started" ) {
212+ await this .joinLobby ();
213+ }
214+ }
215+
216+ private async joinLobby() {
217+ try {
218+ this .lobbyRoom = await this .$client .joinOrCreate (LITE_LOBBY_NAME , {
219+ type: " prolificBaseline" ,
220+ });
221+ applyLiteLobbyResponses (this .lobbyRoom , this );
222+ this .lobbyApi .connect (this .lobbyRoom );
223+ // intercept lobby -> game messages
224+ this .lobbyRoom .onMessage (" removed-client-from-lobby" , () => this .transitionToGame ());
225+ this .lobbyRoom .onMessage (" join-existing-game" , () => this .transitionToGame ());
226+ this .lobbyRoom .onLeave (() => this .onLobbyLeave ());
227+ } catch (error ) {
228+ console .error (" Failed to join lobby:" , error );
229+ this .joinFailureReason =
230+ " Failed to join lobby. Please try refreshing the page. If the problem persists, please contact the researcher with error details and you will be compensated for your time." ;
231+ if (error instanceof Error ) {
232+ this .joinFailureReason += ` Error details: ${error .message } ` ;
233+ }
234+ }
197235 }
198236
199237 private async joinGame(roomId : string ) {
200- this .gameRoom = await this .$client .joinById (roomId );
201- applyMultiplayerGameServerResponses (this .gameRoom , this , this .$tstore .state .user );
202- this .api .connect (this .gameRoom );
203- this .started = true ;
238+ try {
239+ this .gameRoom = await this .$client .joinById (roomId );
240+ applyMultiplayerGameServerResponses (this .gameRoom , this , this .$tstore .state .user );
241+ this .api .connect (this .gameRoom );
242+ this .started = true ;
243+ this .gameRoom .onLeave (() => this .onGameLeave ());
244+ } catch (error ) {
245+ console .error (" Failed to join game:" , error );
246+ this .joinFailureReason =
247+ " Failed to join game. Please try refreshing the page. If the problem persists, please contact the researcher with error details and you will be compensated for your time." ;
248+ if (error instanceof Error ) {
249+ this .joinFailureReason += ` Error details: ${error .message } ` ;
250+ }
251+ }
204252 }
205253
206254 private async transitionToGame() {
255+ this .isTransitioning = true ;
256+ console .log (this .isTransitioning );
207257 // leave lobby and join the real game room
208258 await this .lobbyRoom ! .leave ();
209259 this .lobbyApi .leave ();
@@ -212,6 +262,12 @@ export default class ProlificMultiplayerStudy extends Vue {
212262 return console .error (" Missing roomId" );
213263 }
214264 await this .joinGame (roomId );
265+ // clear timeout
266+ if (this .reconnectTimeout ) {
267+ clearTimeout (this .reconnectTimeout );
268+ this .reconnectTimeout = null ;
269+ }
270+ this .isTransitioning = false ;
215271 }
216272
217273 async handleContinue() {
0 commit comments