"use strict"; const DATASET_URL = "https://huggingface.co/datasets/Max00035/ml-systems-interview-bench/resolve/main/data/questions.jsonl"; const ALL = "All"; const COMPARISON_MARKERS = ["tradeoff", "trade off", "however", "whereas", "depends on", "compared with", "compared to", "on the other hand", "rather than", "versus"]; const TRADEOFF_DOMAIN_SIGNALS = ["cost", "latency", "throughput", "risk", "complexity", "reliability", "accuracy", "memory"]; const STRUCTURE_SIGNALS = ["first", "second", "finally", "because", "for example", "for instance", "therefore", "then"]; const REQUIRED_FIELDS = ["question", "domain", "difficulty", "question_type", "expected_concepts", "reference_answer", "evaluation_rubric", "answer_dimensions", "max_score", "follow_up_questions"]; const state = { questions: [], selectedQuestion: null }; const elements = { status: document.querySelector("#status"), domain: document.querySelector("#domain-filter"), difficulty: document.querySelector("#difficulty-filter"), questionType: document.querySelector("#type-filter"), randomButton: document.querySelector("#random-button"), questionCard: document.querySelector("#question-card"), answer: document.querySelector("#answer-input"), evaluateButton: document.querySelector("#evaluate-button"), clearButton: document.querySelector("#clear-button"), evaluationStatus: document.querySelector("#evaluation-status"), scoreCard: document.querySelector("#score-card"), reviewCard: document.querySelector("#review-card"), referenceAnswer: document.querySelector("#reference-answer"), rubricExcellent: document.querySelector("#rubric-excellent"), rubricAcceptable: document.querySelector("#rubric-acceptable"), rubricWeak: document.querySelector("#rubric-weak"), followUps: document.querySelector("#follow-ups"), }; function normalize(text) { return String(text).toLowerCase().replace(/[-/]/g, " ").match(/[a-z0-9]+/g)?.join(" ") || ""; } function containsSignal(normalizedAnswer, signal) { return ` ${normalizedAnswer} `.includes(` ${normalize(signal)} `); } function conceptIsDetected(concept, normalizedAnswer) { const normalizedConcept = normalize(concept); if (!normalizedConcept) return false; if (containsSignal(normalizedAnswer, normalizedConcept)) return true; const answerTokens = new Set(normalizedAnswer.split(" ")); const meaningfulTokens = normalizedConcept.split(" ").filter((token) => token.length > 2); return meaningfulTokens.length > 1 && meaningfulTokens.every((token) => answerTokens.has(token)); } function isValidQuestion(record) { const rubric = record?.evaluation_rubric; return record && REQUIRED_FIELDS.every((field) => Object.hasOwn(record, field)) && Array.isArray(record.expected_concepts) && Array.isArray(record.answer_dimensions) && Array.isArray(record.follow_up_questions) && record.follow_up_questions.length >= 2 && rubric && typeof rubric === "object" && ["excellent", "acceptable", "weak"].every((key) => Object.hasOwn(rubric, key)); } async function loadQuestions() { try { const response = await fetch(DATASET_URL, { headers: { Accept: "application/jsonl, application/json" } }); if (!response.ok) throw new Error(`Dataset request returned HTTP ${response.status}.`); const lines = (await response.text()).split(/\r?\n/).filter((line) => line.trim()); const records = lines.map((line) => JSON.parse(line)); if (!records.length || !records.every(isValidQuestion)) throw new Error("The dataset is empty or does not match the expected schema."); state.questions = records; populateSelect(elements.domain, uniqueValues(records, "domain"), ALL); updateDependentFilters(); [elements.domain, elements.difficulty, elements.questionType, elements.randomButton].forEach((element) => { element.disabled = false; }); elements.status.className = "status"; elements.status.textContent = `${records.length} questions ready. Choose filters and select a random question.`; } catch (error) { elements.status.className = "status error"; elements.status.textContent = `Dataset unavailable. The public question bank could not be loaded. Please refresh in a moment. ${error.message}`; } } function uniqueValues(records, field) { return [...new Set(records.map((record) => String(record[field])))].sort(); } function populateSelect(select, values, preferredValue) { const nextValue = values.includes(preferredValue) ? preferredValue : ALL; select.replaceChildren(); [ALL, ...values].forEach((value) => { const option = document.createElement("option"); option.value = value; option.textContent = displayValue(value); select.append(option); }); select.value = nextValue; } function displayValue(value) { if (value === ALL) return value; return value.replaceAll("_", " ").replaceAll("-", " ").replace(/\b\w/g, (letter) => letter.toUpperCase()); } function updateDependentFilters() { const domainValue = elements.domain.value || ALL; const domainMatches = state.questions.filter((question) => domainValue === ALL || question.domain === domainValue); populateSelect(elements.difficulty, uniqueValues(domainMatches, "difficulty"), elements.difficulty.value); updateQuestionTypes(); } function updateQuestionTypes() { const matches = state.questions.filter((question) => (elements.domain.value === ALL || question.domain === elements.domain.value) && (elements.difficulty.value === ALL || question.difficulty === elements.difficulty.value)); populateSelect(elements.questionType, uniqueValues(matches, "question_type"), elements.questionType.value); } function matchingQuestions() { return state.questions.filter((question) => (elements.domain.value === ALL || question.domain === elements.domain.value) && (elements.difficulty.value === ALL || question.difficulty === elements.difficulty.value) && (elements.questionType.value === ALL || question.question_type === elements.questionType.value)); } function resetEvaluation() { elements.answer.value = ""; elements.evaluationStatus.textContent = ""; elements.evaluationStatus.className = "inline-status"; elements.scoreCard.hidden = true; elements.scoreCard.replaceChildren(); elements.reviewCard.hidden = true; elements.referenceAnswer.textContent = ""; elements.rubricExcellent.textContent = ""; elements.rubricAcceptable.textContent = ""; elements.rubricWeak.textContent = ""; elements.followUps.replaceChildren(); } function selectRandomQuestion() { const matches = matchingQuestions(); resetEvaluation(); if (!matches.length) { state.selectedQuestion = null; elements.evaluateButton.disabled = true; elements.questionCard.replaceChildren(createElement("p", "No questions match these filters. Try a broader selection.", "muted")); elements.evaluationStatus.textContent = "No questions match these filters."; return; } state.selectedQuestion = matches[Math.floor(Math.random() * matches.length)]; elements.evaluateButton.disabled = false; renderQuestion(state.selectedQuestion); elements.answer.focus(); } function renderQuestion(question) { const badges = createElement("div", "", "badges"); [question.domain, question.difficulty, question.question_type].forEach((value) => badges.append(createElement("span", displayValue(String(value)), "badge"))); elements.questionCard.replaceChildren(badges, createElement("h2", question.question)); } function evaluateAnswer() { const question = state.selectedQuestion; if (!question) return showEvaluationError("Select a question first."); const normalizedAnswer = normalize(elements.answer.value); const words = normalizedAnswer ? normalizedAnswer.split(" ") : []; if (words.length < 12) return showEvaluationError("Please give a fuller interview answer (at least 12 words) before evaluating."); const detected = question.expected_concepts.filter((concept) => conceptIsDetected(concept, normalizedAnswer)); const missing = question.expected_concepts.filter((concept) => !detected.includes(concept)); const coverage = question.expected_concepts.length ? detected.length / question.expected_concepts.length : 0; const dimensions = new Set(question.answer_dimensions); const conceptCoverage = dimensions.has("correctness") ? 4 * coverage : 0; const lengthFactor = Math.min(1, words.length / 90); const completeness = dimensions.has("completeness") ? 2.5 * ((0.8 * coverage) + (0.2 * lengthFactor)) : 0; const hasComparison = COMPARISON_MARKERS.some((marker) => containsSignal(normalizedAnswer, marker)); const domainSignalCount = TRADEOFF_DOMAIN_SIGNALS.filter((signal) => containsSignal(normalizedAnswer, signal)).length; const tradeoffs = dimensions.has("tradeoffs") && hasComparison ? Math.min(2, 1 + (0.5 * Math.min(2, domainSignalCount))) : 0; const sentenceCount = elements.answer.value.split(/[.!?]+/).filter((part) => part.trim()).length; const structureHits = STRUCTURE_SIGNALS.filter((signal) => containsSignal(normalizedAnswer, signal)).length; const communicationFactor = (0.45 * Math.min(1, sentenceCount / 3)) + (0.35 * Math.min(1, structureHits / 2)) + (0.20 * (words.length >= 35 && words.length <= 300 ? 1 : 0.5)); const communication = dimensions.has("communication") ? 1.5 * communicationFactor : 0; const rawTotal = conceptCoverage + completeness + tradeoffs + communication; const parsedMaximum = Number(question.max_score); const maximum = Number.isFinite(parsedMaximum) && parsedMaximum > 0 ? parsedMaximum : 10; const total = Math.min(maximum, rawTotal * maximum / 10); renderScore({ total, maximum, conceptCoverage, completeness, tradeoffs, communication, detected, missing }); revealReview(question); elements.evaluationStatus.textContent = "Evaluation complete. Reference material is now available below."; elements.evaluationStatus.className = "inline-status"; } function showEvaluationError(message) { elements.evaluationStatus.textContent = message; elements.evaluationStatus.className = "inline-status error"; elements.scoreCard.hidden = true; elements.reviewCard.hidden = true; } function renderScore(scores) { const { total, maximum, conceptCoverage, completeness, tradeoffs, communication, detected, missing } = scores; const anchor = total >= 8 ? "excellent" : total >= 5 ? "acceptable" : "weak"; const improvement = missing.length ? `Add explicit evidence for: ${missing.slice(0, 3).join(", ")}.` : "All listed concepts had literal evidence; sharpen examples and trade-off reasoning."; const warning = createElement("p", "", "heuristic-warning"); warning.append(createElement("strong", "This is a heuristic baseline, not an AI judge. "), document.createTextNode("It checks literal concept evidence and basic answer structure; it does not understand meaning.")); const metricGrid = createElement("div", "", "score-grid"); metricGrid.append(metric("Concept coverage", conceptCoverage, 4, "Heuristic proxy for correctness"), metric("Completeness", completeness, 2.5), metric("Trade-offs", tradeoffs, 2), metric("Communication", communication, 1.5)); const concepts = createElement("div", "", "concept-grid"); concepts.append(conceptList("Concepts detected", detected), conceptList("Concepts not detected", missing)); const feedback = createElement("p", "", "feedback"); feedback.append(createElement("strong", "Feedback: "), document.createTextNode(`The heuristic result is closest to the dataset's ${anchor} anchor. ${improvement}`)); const title = createElement("h2", `${total.toFixed(1)} / ${formatMaximum(maximum)}`); title.id = "score-title"; elements.scoreCard.replaceChildren(createElement("p", "Heuristic result", "eyebrow"), title, warning, metricGrid, concepts, feedback); elements.scoreCard.hidden = false; } function metric(label, value, maximum, note = "") { const container = createElement("div", "", "metric"); container.append(createElement("span", label), createElement("strong", `${value.toFixed(1)} / ${maximum}`)); if (note) container.append(createElement("small", note)); return container; } function conceptList(title, items) { const container = document.createElement("div"); const list = document.createElement("ul"); (items.length ? items : ["None"]).forEach((item) => list.append(createElement("li", item))); container.append(createElement("h3", title), list); return container; } function revealReview(question) { elements.referenceAnswer.textContent = question.reference_answer; elements.rubricExcellent.textContent = question.evaluation_rubric.excellent; elements.rubricAcceptable.textContent = question.evaluation_rubric.acceptable; elements.rubricWeak.textContent = question.evaluation_rubric.weak; elements.followUps.replaceChildren(); question.follow_up_questions.slice(0, 2).forEach((followUp) => elements.followUps.append(createElement("li", followUp))); elements.reviewCard.hidden = false; } function createElement(tag, text = "", className = "") { const element = document.createElement(tag); element.textContent = text; if (className) element.className = className; return element; } function formatMaximum(maximum) { return Number.isInteger(maximum) ? String(maximum) : maximum.toFixed(1); } elements.domain.addEventListener("change", updateDependentFilters); elements.difficulty.addEventListener("change", updateQuestionTypes); elements.randomButton.addEventListener("click", selectRandomQuestion); elements.evaluateButton.addEventListener("click", evaluateAnswer); elements.clearButton.addEventListener("click", () => { elements.answer.value = ""; elements.answer.focus(); }); loadQuestions();