Skip to content

Commit

Permalink
faster technique
Browse files Browse the repository at this point in the history
  • Loading branch information
kavigupta committed Jan 18, 2025
1 parent e6054e8 commit 7675adc
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 56 deletions.
9 changes: 2 additions & 7 deletions react/src/quiz/quiz-result.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,7 @@ export function QuizResult(props: QuizResultProps): ReactNode {
: undefined
}
<div className="gap"></div>
{
// TODO stats for infinite quiz
props.quizDescriptor.kind === 'custom' || props.quizDescriptor.kind === 'infinite'
? undefined
: <QuizStatistics wholeHistory={props.wholeHistory} quiz={props.quizDescriptor} />
}
<QuizStatistics wholeHistory={props.wholeHistory} quiz={props.quizDescriptor} />
<div className="gap"></div>
<span className="serif quiz_summary">Details (spoilers, don&apos;t share!)</span>
<div className="gap_small"></div>
Expand Down Expand Up @@ -477,7 +472,7 @@ export function GenericQuizResultRow(props: GenericQuizResultRowProps): ReactNod
<td style={{ fontWeight: 400 }} className="serif quiz_result_value_left">
{props.getStat('a')}
</td>
<td className="serif quiz_result_symbol">
<td className="serif quiz_result_symbol quiz_result_comparison_symbol">
{comparison}
</td>
<td style={{ fontWeight: 400 }} className="serif quiz_result_value_right">
Expand Down
58 changes: 51 additions & 7 deletions react/src/quiz/quiz-statistics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,32 @@ import React, { ReactNode } from 'react'

import { useColors, useJuxtastatColors } from '../page_template/colors'

import { QuizDescriptorWithTime, QuizHistory } from './quiz'
import { parseTimeIdentifier } from './statistics'
import { QuizDescriptor, QuizDescriptorWithTime, QuizHistory } from './quiz'
import { getInfiniteQuizzes, parseTimeIdentifier } from './statistics'

interface QuizStatisticsProps {
// this kind of statistic only really applies to daily/weekly quizzes
quiz: QuizDescriptorWithTime
wholeHistory: QuizHistory
export function QuizStatistics(
props: {
quiz: QuizDescriptor
wholeHistory: QuizHistory
},
): ReactNode | undefined {
switch (props.quiz.kind) {
case 'juxtastat':
case 'retrostat':
return <QuizStatisticsForTimedStatistics quiz={props.quiz} wholeHistory={props.wholeHistory} />
case 'infinite':
return <QuizStatisticsForInfinite quiz={props.quiz} wholeHistory={props.wholeHistory} />
case 'custom':
return undefined
}
}

export function QuizStatistics(props: QuizStatisticsProps): ReactNode {
export function QuizStatisticsForTimedStatistics(
props: {
quiz: QuizDescriptorWithTime
wholeHistory: QuizHistory
},
): ReactNode {
const colors = useColors()
const history = (i: number): QuizHistory[string] | undefined => {
switch (props.quiz.kind) {
Expand Down Expand Up @@ -153,3 +169,31 @@ export function DisplayedStat({ number, name, additionalClass, color }: { number
</div>
)
}

export function QuizStatisticsForInfinite(
props: {
quiz: QuizDescriptor & { kind: 'infinite' }
wholeHistory: QuizHistory
},
): ReactNode | undefined {
const [seedVersions, keys] = getInfiniteQuizzes(props.wholeHistory)
const numCorrects = keys.map(
key => props.wholeHistory[key].correct_pattern.reduce((partialSum: number, a) => partialSum + (a ? 1 : 0), 0),
)

// sort indices by numCorrects
let sortedIndices = Array.from(Array(numCorrects.length).keys())
sortedIndices.sort((a, b) => numCorrects[a] - numCorrects[b])
// take first 5
sortedIndices = sortedIndices.slice(0, 5)
if (sortedIndices.length === 0) {
return undefined
}

const sortedSeedVersions = sortedIndices.map(i => seedVersions[i])
const sortedNumCorrects = sortedIndices.map(i => numCorrects[i])

console.log(sortedSeedVersions)

Check failure on line 196 in react/src/quiz/quiz-statistics.tsx

View workflow job for this annotation

GitHub Actions / lint

Unexpected console statement
console.log(sortedNumCorrects)

Check failure on line 197 in react/src/quiz/quiz-statistics.tsx

View workflow job for this annotation

GitHub Actions / lint

Unexpected console statement
return undefined
}
2 changes: 1 addition & 1 deletion react/src/quiz/statistics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ async function reportToServerGeneric(wholeHistory: QuizHistory, endpointLatest:
return false
}

function getInfiniteQuizzes(wholeHistory: QuizHistory): [[string, number][], string[]] {
export function getInfiniteQuizzes(wholeHistory: QuizHistory): [[string, number][], string[]] {
const seedVersions: [string, number][] = []
const keys: string[] = []
for (const day of Object.keys(wholeHistory)) {
Expand Down
137 changes: 96 additions & 41 deletions react/test/quiz_infinite_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,44 +33,94 @@ async function correctIncorrect(t: TestController): Promise<boolean[]> {

const localStorageDefault = { persistent_id: '000000000000007', secure_id: '00000003' }

async function completeCorrectAnswerSequence(t: TestController, alreadyKnownAnswers: string[]): Promise<string[]> {
const seedStr = 'deadbeef00'

// async function completeCorrectAnswerSequence(t: TestController, alreadyKnownAnswers: string[]): Promise<string[]> {
// // console.log(await sampleRandomQuestion(seedStr, 0))
// await t.eval(() => {
// localStorage.clear()
// for (const key of Object.keys(localStorageDefault)) {
// localStorage.setItem(key, localStorageDefault[key])
// }
// }, { dependencies: { localStorageDefault } })
// await t.wait(100)
// await safeReload(t)
// await waitForQuizLoading(t)
// await clickButtons(t, alreadyKnownAnswers)
// while (await isQuestionPage(t)) {
// await clickButton(t, 'a')
// await t.wait(500)
// }
// // check that the first n characters match the already known answers
// const text = await correctIncorrect(t)
// for (let i = 0; i < alreadyKnownAnswers.length; i++) {
// if (!text[i]) {
// throw new Error('alreadyKnownAnswers is incorrect')
// }
// }
// const correctAnswers: string[] = [...alreadyKnownAnswers]
// for (let i = alreadyKnownAnswers.length; i < text.length; i++) {
// if (text[i]) {
// correctAnswers.push('a')
// }
// else {
// correctAnswers.push('b')
// }
// }
// // check that the prefixes match

// return correctAnswers
// }

const correctAnswerSequences = new Map<string, string[]>()

quizFixture(
'collect correct answers',
`${target}/quiz.html`,
localStorageDefault,
``,
'desktop',
)

const version = 0

test('collect correct answers', async (t) => {
const seed = 'deadbeef00'
// set localStorage such that I_{seedStr}_{version} has had 30 questions answered
await t.eval(() => {
localStorage.clear()
for (const key of Object.keys(localStorageDefault)) {
localStorage.setItem(key, localStorageDefault[key])
}
}, { dependencies: { localStorageDefault } })
await t.wait(100)
localStorage.quiz_history = JSON.stringify({
[`I_${seed}_${version}`]: {
// false so the quiz ends
correct_pattern: Array(30).fill(false),
choices: Array(30).fill('a'),
},
})
}, { dependencies: { seed, version } })
await t.navigateTo(`${target}/quiz.html#mode=infinite&seed=${seed}&v=${version}`)
await safeReload(t)
await waitForQuizLoading(t)
await clickButtons(t, alreadyKnownAnswers)
while (await isQuestionPage(t)) {
await clickButton(t, 'a')
await t.wait(500)
}
// check that the first n characters match the already known answers
const text = await correctIncorrect(t)
for (let i = 0; i < alreadyKnownAnswers.length; i++) {
if (!text[i]) {
throw new Error('alreadyKnownAnswers is incorrect')
}
}
const correctAnswers: string[] = [...alreadyKnownAnswers]
for (let i = alreadyKnownAnswers.length; i < text.length; i++) {
if (text[i]) {
// Get all quiz_result_symbol elements and the text therein
const symbols = Selector('.quiz_result_comparison_symbol')
const symbolsCount = await symbols.count
const correctAnswers: string[] = []
for (let i = 0; i < symbolsCount; i++) {
const symbol = symbols.nth(i)
const text = await symbol.innerText
console.log(text)

Check failure on line 108 in react/test/quiz_infinite_test.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected console statement
if (text === '>') {
correctAnswers.push('a')
}
else {
else if (text === '<') {
correctAnswers.push('b')
}
else {
throw new Error(`unexpected text ${text} in ${await symbol.textContent}`)
}
}
// check that the prefixes match

return correctAnswers
}
correctAnswerSequences.set(seed, correctAnswers)
})

const seed = 0xdeadbeef00
const param = '#mode=infinite&seed=deadbeef00&v=0'
const param = `#mode=infinite&seed=${seedStr}&v=${version}`
quizFixture(
'generate link',
`${target}/quiz.html${param}`,
Expand All @@ -79,21 +129,22 @@ quizFixture(
'desktop',
)

let correctAnswerSequence: string[]
// let correctAnswerSequence: string[]

test('formulates correct sequence', async (t) => {
// returns if quiztext exists as a class
let alreadyKnownAnswers: string[] = []
while (true) {
alreadyKnownAnswers = await completeCorrectAnswerSequence(t, alreadyKnownAnswers)
if (alreadyKnownAnswers.length >= 30) {
break
}
}
correctAnswerSequence = alreadyKnownAnswers
})
// test('formulates correct sequence', async (t) => {
// // returns if quiztext exists as a class
// let alreadyKnownAnswers: string[] = []
// while (true) {
// alreadyKnownAnswers = await completeCorrectAnswerSequence(t, alreadyKnownAnswers)
// if (alreadyKnownAnswers.length >= 30) {
// break
// }
// }
// correctAnswerSequence = alreadyKnownAnswers
// })

async function provideAnswers(t: TestController, start: number, isCorrect: boolean[]): Promise<void> {
const correctAnswerSequence = correctAnswerSequences.get(seedStr)!
for (let i = start; i < start + isCorrect.length; i++) {
await clickButton(t, isCorrect[i - start] === (correctAnswerSequence[i] === 'a') ? 'a' : 'b')
await t.wait(500)
Expand Down Expand Up @@ -184,3 +235,7 @@ test('19-correct', async (t) => {
// low bit order first: 1111,1111 1111,1111 1111,0000 000[0,0000] This becomes FF FF 0F 00
await t.expect(await juxtastatInfiniteTable()).eql(`7|${seed}|FFFF0F00|20|27\n`)
})

// test('do-not-report-partial', async (t) => {
// await provideAnswers(t, 0, [false, true, true, true, true])
// await t.navigateTo(`${target}/quiz.html#mode=infinite&seed=deadbeef01&v=0`)

0 comments on commit 7675adc

Please sign in to comment.