import type { db as Db } from "../db"; import type { Question, QuizState } from "../party-types"; import { buildMemberOptions, buildMemberPairOptions, buildQuestionWindow, getCurrentLeader, getMostDiverseMember, getTopClusterTracks, getTopTrackListener, hasClearLeader, type PartyAnalytics, type PartyQuestionMember, pickQuestionCandidate, pickRandom, type QuestionCandidate, resolveQuestionSong, } from "./question-utils"; export async function buildSocialQuestion( dbClient: typeof Db, quizState: QuizState, analytics: PartyAnalytics, members: PartyQuestionMember[], index: number, ): Promise { type ChoiceQuestion = Extract; const questions: Array< QuestionCandidate> > = []; const topSong = await resolveQuestionSong(dbClient, analytics); const hasMultipleMembers = members.length >= 2; if (hasMultipleMembers && hasClearLeader(quizState)) { const leader = getCurrentLeader(quizState, members); const options = buildMemberOptions(leader, members); if (options) { questions.push({ key: "social:leader", subjectKey: `member:${leader.userId}`, question: { type: "choice", text: "Who is leading the quiz right now?", options, correct: 0, points: 10, song: topSong ?? undefined, }, }); } } if (hasMultipleMembers) { const diverse = getMostDiverseMember(analytics, members); if (diverse) { const options = buildMemberOptions(diverse, members); if (options) { questions.push({ key: "social:diverse", subjectKey: `member:${diverse.userId}`, question: { type: "choice", text: "Who looks like the most diverse listener in the party?", options, correct: 0, points: 10, song: topSong ?? undefined, }, }); } } } const topTracks = getTopClusterTracks(analytics); const randomTrack = pickRandom(topTracks); if (randomTrack && hasMultipleMembers) { const topListener = getTopTrackListener(randomTrack, members); if (topListener) { const randomTrackSong = await resolveQuestionSong(dbClient, analytics, { trackName: randomTrack.name, artistNames: randomTrack.artists?.map((artist) => artist.name), albumName: randomTrack.albumName, }); const options = buildMemberOptions(topListener, members); if (options) { questions.push({ key: `social:track-listener:${randomTrack.name}`, subjectKey: `track:${randomTrack.name}`, question: { type: "choice", text: `Who listens the most to "${randomTrack.name}"?`, options, correct: 0, points: 10, song: randomTrackSong ?? topSong ?? undefined, }, }); } } } if (members.length >= 3 && analytics?.groupSummary?.mostAlignedPair) { const topPair = analytics.groupSummary.mostAlignedPair; const memberA = members.find((m) => m.userId === topPair.userIdA); const memberB = members.find((m) => m.userId === topPair.userIdB); if (memberA && memberB) { const correctPair = `${memberA.name} & ${memberB.name}`; const pairOptions = buildMemberPairOptions(members, correctPair); if (pairOptions) { questions.push({ key: `social:pair:${memberA.userId}:${memberB.userId}`, subjectKey: `pair:${[memberA.userId, memberB.userId].sort().join("|")}`, question: { type: "choice", text: "Which two players share the most musical taste?", options: pairOptions, correct: 0, points: 10, song: topSong ?? undefined, }, }); } } } if (questions.length === 0) { return null; } const question = pickQuestionCandidate(questions, quizState.history, index); if (!question) return null; return buildQuestionWindow(question); }