fix(StartPracticeModal): responsive improvements + integrated tutorial CTA
- Full-screen mode at ≤700px height for iPhone SE support - Two-column grid layout for settings in landscape mode - Integrated tutorial CTA: combines unlock banner + start button - Fixed collapsed mode clipping of target skills section - Made "focusing on weak skills" visible on all screen sizes - Fixed duplicate CSS media query breakpoints - BKT: changed computeBktFromHistory to accept Partial<BktComputeExtendedOptions> 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
5735ff0810
commit
56742c511d
File diff suppressed because it is too large
Load Diff
|
|
@ -75,8 +75,10 @@ function applyTimeDecay(
|
||||||
*/
|
*/
|
||||||
export function computeBktFromHistory(
|
export function computeBktFromHistory(
|
||||||
results: ProblemResultWithContext[],
|
results: ProblemResultWithContext[],
|
||||||
options: BktComputeExtendedOptions = DEFAULT_BKT_OPTIONS
|
options: Partial<BktComputeExtendedOptions> = {}
|
||||||
): BktComputeResult {
|
): BktComputeResult {
|
||||||
|
// Merge with defaults so callers can override just what they need
|
||||||
|
const opts: BktComputeExtendedOptions = { ...DEFAULT_BKT_OPTIONS, ...options }
|
||||||
// Sort by timestamp to replay in chronological order
|
// Sort by timestamp to replay in chronological order
|
||||||
// Note: timestamp may be a Date or a string (from JSON serialization)
|
// Note: timestamp may be a Date or a string (from JSON serialization)
|
||||||
const sorted = [...results].sort((a, b) => {
|
const sorted = [...results].sort((a, b) => {
|
||||||
|
|
@ -126,7 +128,7 @@ export function computeBktFromHistory(
|
||||||
const evidenceWeight = helpWeight * rtWeight
|
const evidenceWeight = helpWeight * rtWeight
|
||||||
|
|
||||||
// Compute BKT updates (conjunctive model)
|
// Compute BKT updates (conjunctive model)
|
||||||
const blameMethod = options.blameMethod ?? 'heuristic'
|
const blameMethod = opts.blameMethod ?? 'heuristic'
|
||||||
const updates = result.isCorrect
|
const updates = result.isCorrect
|
||||||
? updateOnCorrect(skillRecords)
|
? updateOnCorrect(skillRecords)
|
||||||
: updateOnIncorrectWithMethod(skillRecords, blameMethod)
|
: updateOnIncorrectWithMethod(skillRecords, blameMethod)
|
||||||
|
|
@ -158,13 +160,13 @@ export function computeBktFromHistory(
|
||||||
|
|
||||||
// Apply decay if enabled
|
// Apply decay if enabled
|
||||||
let finalPKnown = state.pKnown
|
let finalPKnown = state.pKnown
|
||||||
if (options.applyDecay && state.lastPracticedAt) {
|
if (opts.applyDecay && state.lastPracticedAt) {
|
||||||
const daysSinceLastPractice =
|
const daysSinceLastPractice =
|
||||||
(now.getTime() - state.lastPracticedAt.getTime()) / (1000 * 60 * 60 * 24)
|
(now.getTime() - state.lastPracticedAt.getTime()) / (1000 * 60 * 60 * 24)
|
||||||
finalPKnown = applyTimeDecay(
|
finalPKnown = applyTimeDecay(
|
||||||
state.pKnown,
|
state.pKnown,
|
||||||
daysSinceLastPractice,
|
daysSinceLastPractice,
|
||||||
options.decayHalfLifeDays,
|
opts.decayHalfLifeDays,
|
||||||
state.params.pInit
|
state.params.pInit
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -175,7 +177,7 @@ export function computeBktFromHistory(
|
||||||
const masteryClassification = classifyMastery(
|
const masteryClassification = classifyMastery(
|
||||||
finalPKnown,
|
finalPKnown,
|
||||||
confidence,
|
confidence,
|
||||||
options.confidenceThreshold
|
opts.confidenceThreshold
|
||||||
)
|
)
|
||||||
|
|
||||||
skills.push({
|
skills.push({
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue