Skip to content

Commit

Permalink
using compound keys for users to identify same user under different e…
Browse files Browse the repository at this point in the history
…xperiments
  • Loading branch information
recap committed Apr 6, 2024
1 parent 06446ba commit 6f19ae1
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 15 deletions.
4 changes: 3 additions & 1 deletion UserDb.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ class UserDb extends Map {
user.oTreeId = u.oTreeId
user.tokenParams = u.tokenParams
user.state = (u.redirectedUrl) ? u.state : user.state
this.set(user.userId, user)
const compoundKey = `${user.userId}:${user.experimentId}`
this.set(compoundKey, user)
})
}).catch((err) => {
console.error(`[WARNING] UserDb file ${this.file} file not found will be recreated!`)
Expand All @@ -35,6 +36,7 @@ class UserDb extends Map {

const dump = JSON.stringify(data)
const h = murmurhash(dump, this.seed)
console.log(`${h}:${this.lastHash}:${dump}`)
if (this.lastHash !== h) {
fs.writeFile(this.file, dump).then(() => {
this.lastHash = h
Expand Down
37 changes: 23 additions & 14 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,8 @@ async function getExperimentUrls(experiments) {
// starting the game.
function agreeGame(users, uuid, agreement, usersDb) {
for (let i = 0; i < users.length; i++) {
const userId = users[i]
const user = usersDb.get(userId)
const compoundKey = users[i]
const user = usersDb.get(compoundKey)
const sock = user.webSocket
if (!sock) {
console.error(`User ${userId} has not socket!`)
Expand Down Expand Up @@ -256,7 +256,7 @@ function startReadyGames(experiments, agreementIds, usersDb) {
// waits for all users to 'agree' and
// proceed to the game together
const uuid = crypto.randomUUID()
const gameUsersIds = conditionObject.users.map((u) => u.userId)
const gameUsersIds = conditionObject.users.map((u) => `${u.userId}:${u.experimentId}`)
const agreement = new Agreement(
uuid,
experimentId,
Expand All @@ -279,11 +279,13 @@ function startReadyGames(experiments, agreementIds, usersDb) {
agreement.server,
)
agreedUsersIds.forEach((userId) => {
const user = usersDb.get(userId)
const compoundKey = `${userId}:${agreement.experimentId}`
const user = usersDb.get(compoundKey)
user.changeState("queued")
})
nonAgreedUsersIds.forEach((userId) => {
const user = usersDb.get(userId)
const compoundKey = `${userId}:${agreement.experimentId}`
const user = usersDb.get(compoundKey)
user.reset()
})
}
Expand Down Expand Up @@ -504,9 +506,10 @@ async function main() {
res.status(404).sendFile(__dirname + "/webpage_templates/404.html")
return
}
const user = usersDb.get(userId) || new User(userId, params.experimentId)
const compoundKey = `${userId}:${params.experimentId}`
const user = usersDb.get(compoundKey) || new User(userId, params.experimentId)
user.tokenParams = params
usersDb.set(userId, user)
usersDb.set(compoundKey, user)
console.log(`Token params: ${JSON.stringify(user.tokenParams)}`)
if (
fs.existsSync(
Expand All @@ -526,7 +529,8 @@ async function main() {
socket.on("landingPage", async (msg) => {
const userId = msg.userId
const experimentId = msg.experimentId
const user = usersDb.get(userId) || new User(userId, experimentId)
const compoundKey = `${userId}:${experimentId}`
const user = usersDb.get(compoundKey) || new User(userId, experimentId)
user.webSocket = socket
// If user is queued and refreshes page then re-trigger
// queued events.
Expand All @@ -543,15 +547,17 @@ async function main() {
default:
user.changeState("startedPage")
user.reset()
usersDb.set(userId, user)
usersDb.set(compoundKey, user)
console.log(
`User ${userId} connected for experiment ${experimentId}.`,
)
}
})
socket.on("newUser", async (msg) => {
let userId = msg.userId
let user = usersDb.get(userId)
const experimentId = msg.experimentId
const compoundKey = `${userId}:${experimentId}`
let user = usersDb.get(compoundKey)

if (!user) {
console.error(`No user ${userId} found!`)
Expand Down Expand Up @@ -597,17 +603,19 @@ async function main() {
console.log("[SOCKET][userAgreed] ", data)
const userId = data.userId
const uuid = data.uuid
const experimentId = data.experimentId
const compoundKey = `${userId}:${experimentId}`

const agreement = agreementIds[uuid]
if (!agreement) {
console.log(`[ERROR] no agreement ${uuid}`)
return
}
usersDb.get(userId).changeState("agreed")
usersDb.get(compoundKey).changeState("agreed")
// If everyone agrees, start game
if (agreement.agree(userId)) {
console.log("Start Game!")
startGame(agreement.agreedUsers, agreement.urls)
startGame(agreement.agreedUsers, agreement.urls, agreement.experimentId)
}
})

Expand All @@ -623,11 +631,12 @@ async function main() {
* @param users {string[]}
* @param urls {string[]}
*/
function startGame(users, urls) {
function startGame(users, urls, experimentId) {
console.log(`Starting game with users: ${users} and urls ${urls}.`)
for (let i = 0; i < users.length; i++) {
const userId = users[i]
const user = usersDb.get(userId)
const compoundKey = `${userId}:${experimentId}`
const user = usersDb.get(compoundKey)
user.changeState("redirected")
const expUrl = new URL(urls[i])
userMapping[userId] = expUrl
Expand Down

0 comments on commit 6f19ae1

Please sign in to comment.