UNPKG

@empirica/core

Version:
298 lines (296 loc) 7.42 kB
import { Scope, Scopes, Steps } from "./chunk-IJG2YOZB.js"; import { Attributes } from "./chunk-RXGVZSIF.js"; import { Globals } from "./chunk-2TT3WJZY.js"; // src/player/classic/classic.ts import { BehaviorSubject, Subject } from "rxjs"; var endedStatuses = ["ended", "terminated", "failed"]; var Game = class extends Scope { get hasEnded() { return endedStatuses.includes(this.get("status")); } get stage() { return this.scopeByKey("stageID"); } get round() { return this.stage?.round; } }; var Player = class extends Scope { get game() { const { game } = this.ctx; if (!game) { return; } const key = `playerGameID-${game.id}`; return this.scopeByKey(key); } get round() { const { stage } = this.ctx; if (!stage) { return; } const { round } = stage; if (!round) { return; } const key = `playerRoundID-${round.id}`; return this.scopeByKey(key); } get stage() { const { stage } = this.ctx; if (!stage) { return; } const key = `playerStageID-${stage.id}`; return this.scopeByKey(key); } hasUpdated() { if (super.hasUpdated()) { return true; } return Boolean( this.round?.hasUpdated() || this.stage?.hasUpdated() || this.game?.hasUpdated() ); } }; var PlayerGame = class extends Scope { }; var PlayerRound = class extends Scope { }; var PlayerStage = class extends Scope { }; var Round = class extends Scope { }; var Stage = class extends Scope { get round() { return this.scopeByKey("roundID"); } get timer() { return this.tickerByKey("timerID"); } }; var Context = class { }; var kinds = { game: Game, player: Player, playerGame: PlayerGame, playerRound: PlayerRound, playerStage: PlayerStage, round: Round, stage: Stage }; function EmpiricaClassic(participantID, provider) { const attributesDones = new Subject(); const scopesDones = new Subject(); const ctx = new Context(); const attributes = new Attributes( provider.attributes, attributesDones, provider.setAttributes ); const steps = new Steps( provider.steps, provider.dones ); const scopes = new Scopes( provider.scopes, scopesDones, ctx, kinds, attributes, steps ); const participantIDs = /* @__PURE__ */ new Set(); const glob = new Globals(provider.globals); const ret = { game: new BehaviorSubject(void 0), player: new BehaviorSubject(void 0), players: new BehaviorSubject(void 0), round: new BehaviorSubject(void 0), stage: new BehaviorSubject(void 0), globals: glob.self }; provider.participants.subscribe({ next: ({ participant, removed }) => { if (removed) { if (participantIDs.has(participant.id)) { participantIDs.delete(participant.id); } } else { if (!participantIDs.has(participant.id)) { participantIDs.add(participant.id); } } } }); let scopesUpdated = /* @__PURE__ */ new Set(); provider.attributes.subscribe({ next: (attr) => { const nodeID = attr.attribute.node?.id || attr.attribute.nodeID; if (!nodeID) { return; } scopesUpdated.add(nodeID); } }); provider.dones.subscribe({ next: () => { const current = getCurrent(ret); const updated = getMainObjects(participantID, scopes, attributes); ctx.game = updated.game; ctx.stage = updated.stage; if (scopeChanged(current.game, updated.game)) { ret.game.next(updated.game); } if (scopeChanged(current.player, updated.player)) { ret.player.next(updated.player); } if (scopeChanged(current.round, updated.round)) { ret.round.next(updated.round); } if (scopeChanged(current.stage, updated.stage) || steps.hadUpdates()) { ret.stage.next(updated.stage); } let playersChanged = false; const players = []; for (let i = 0; i < (updated.players || []).length; i++) { let p = updated.players[i]; if (p) { const partID = attributes.nextAttributeValue( p.id, "participantID" ); if (!participantIDs.has(partID)) { p = void 0; } } if (!playersChanged && scopeChanged(p, (current.players || [])[i])) { playersChanged = true; } if (!playersChanged && scopeChanged(p?.stage, (current.players || [])[i]?.stage)) { playersChanged = true; } if (!playersChanged && scopeChanged(p?.round, (current.players || [])[i]?.round)) { playersChanged = true; } if (!playersChanged && scopeChanged(p?.game, (current.players || [])[i]?.game)) { playersChanged = true; } if (p) { players.push(p); } } if (playersChanged) { ret.players.next(players); } const scopeIDs = Array.from(scopesUpdated); scopesDones.next(scopeIDs); attributesDones.next(scopeIDs); scopesUpdated.clear(); } }); return ret; } function scopeChanged(current, updated) { if (!current && !updated) { if (current === void 0 && updated === null) { return true; } return false; } if (!current || !updated) { return true; } return current.id !== updated.id || updated.hasUpdated(); } function getCurrent(ctx) { return { game: ctx.game.getValue(), player: ctx.player.getValue(), round: ctx.round.getValue(), stage: ctx.stage.getValue(), players: ctx.players.getValue() }; } function getMainObjects(participantID, scopes, attributes) { const players = Array.from(scopes.byKind("player").values()); players.sort(); const res = { players, game: null, player: null, round: null, stage: null }; if (players.length === 0) { return res; } res.player = players.find((p) => { const pID = attributes.nextAttributeValue(p.id, "participantID"); return pID === participantID; }); if (!res.player) { return res; } res.game = nextScopeByKey(scopes, attributes, res.player, "gameID"); if (!res.game) { return res; } for (const player of players || []) { const key = `playerGameID-${res.game.id}`; if (!nextScopeByKey(scopes, attributes, player, key)) { return res; } } res.stage = nextScopeByKey(scopes, attributes, res.game, "stageID"); if (!res.stage) { return res; } for (const player of players || []) { const key = `playerStageID-${res.stage.id}`; if (!nextScopeByKey(scopes, attributes, player, key)) { delete res.stage; return res; } } res.round = nextScopeByKey(scopes, attributes, res.stage, "roundID"); if (!res.round) { return res; } for (const player of players || []) { const key = `playerRoundID-${res.round.id}`; if (!nextScopeByKey(scopes, attributes, player, key)) { delete res.stage; delete res.round; return res; } } return res; } function nextScopeByKey(scopes, attributes, scope, key) { const id = attributes.nextAttributeValue(scope.id, key); if (!id || typeof id !== "string") { return null; } return scopes.scope(id) || null; } export { Game, Player, PlayerGame, PlayerRound, PlayerStage, Round, Stage, EmpiricaClassic }; //# sourceMappingURL=chunk-KV4C4Q27.js.map