diff --git a/main.js b/main.js index a857374..1cc31fb 100644 --- a/main.js +++ b/main.js @@ -3228,11 +3228,20 @@ var MCQModal = class extends import_obsidian8.Modal { let totalScore = 0; this.session.answers.forEach((answer) => { let questionScore = 0; - if (answer.correct && answer.selectedAnswerIndex !== -1) { - if (answer.attempts === 1) + if (this.plugin.settings.mcqDeductFullMarkOnFirstFailure) { + if (answer.attempts === 1 && answer.correct) { questionScore = 1; - else if (answer.attempts === 2) - questionScore = 0.5; + } else { + questionScore = 0; + } + } else { + if (answer.correct && answer.selectedAnswerIndex !== -1) { + if (answer.attempts === 1) { + questionScore = 1; + } else if (answer.attempts === 2) { + questionScore = 0.5; + } + } } if (questionScore > 0 && answer.timeToAnswer > this.plugin.settings.mcqTimeDeductionSeconds) { questionScore -= this.plugin.settings.mcqTimeDeductionAmount; @@ -6465,6 +6474,7 @@ var DEFAULT_SETTINGS = { mcqTimeDeductionAmount: 0.5, mcqTimeDeductionSeconds: 90, mcqDifficulty: "advanced" /* Advanced */, + mcqDeductFullMarkOnFirstFailure: false, mcqBasicSystemPrompt: "You are a tutor who creates clear, straightforward multiple-choice questions to test basic understanding of the given content. Focus on key concepts and important facts. Make questions simple and direct, with one clearly correct answer. Always mark the correct answer with [CORRECT] at the end of the line.", mcqAdvancedSystemPrompt: "You are an expert tutor who creates challenging but fair multiple-choice questions to test deep understanding of the given content. Generate questions that assess comprehension, application, and analysis, not just memorization. Make incorrect choices plausible to encourage critical thinking. Always mark the correct answer with [CORRECT] at the end of the line.", // Pomodoro Timer Defaults @@ -7031,6 +7041,10 @@ var SpaceforgeSettingTab = class extends import_obsidian17.PluginSettingTab { this.plugin.settings.mcqTimeDeductionSeconds = value; await this.plugin.savePluginData(); })); + new import_obsidian17.Setting(mcqSection).setName("Deduct full mark on first failure").setDesc("If enabled, the score for a question will be 0 if the first attempt is incorrect.").addToggle((toggle) => toggle.setValue(this.plugin.settings.mcqDeductFullMarkOnFirstFailure).onChange(async (value) => { + this.plugin.settings.mcqDeductFullMarkOnFirstFailure = value; + await this.plugin.savePluginData(); + })); const systemPromptsContainer = mcqSection.createEl("details", { cls: "sf-system-prompts-container" }); systemPromptsContainer.createEl("summary", { text: "System Prompts (Advanced)", cls: "sf-settings-subsection" }); systemPromptsContainer.createEl("div", { text: "Basic Difficulty Prompt", cls: "sf-prompt-label" }); diff --git a/models/settings.ts b/models/settings.ts index 4d75702..c058de8 100644 --- a/models/settings.ts +++ b/models/settings.ts @@ -179,6 +179,12 @@ export interface SpaceforgeSettings { */ mcqDifficulty: MCQDifficulty; + /** + * Deduct full mark for a question if the first attempt is a failure. + * Default: false + */ + mcqDeductFullMarkOnFirstFailure: boolean; + /** * API Provider for MCQ generation * Default: 'openrouter' @@ -351,6 +357,7 @@ export const DEFAULT_SETTINGS: SpaceforgeSettings = { mcqTimeDeductionAmount: 0.5, mcqTimeDeductionSeconds: 90, mcqDifficulty: MCQDifficulty.Advanced, + mcqDeductFullMarkOnFirstFailure: true, mcqBasicSystemPrompt: 'You are a tutor who creates clear, straightforward multiple-choice questions to test basic understanding of the given content. Focus on key concepts and important facts. Make questions simple and direct, with one clearly correct answer. Always mark the correct answer with [CORRECT] at the end of the line.', mcqAdvancedSystemPrompt: 'You are an expert tutor who creates challenging but fair multiple-choice questions to test deep understanding of the given content. Generate questions that assess comprehension, application, and analysis, not just memorization. Make incorrect choices plausible to encourage critical thinking. Always mark the correct answer with [CORRECT] at the end of the line.', diff --git a/styles.css b/styles.css index 9669bf2..d547b6a 100644 --- a/styles.css +++ b/styles.css @@ -1494,8 +1494,6 @@ button.disabled:hover { border-radius: var(--radius-m, 8px); box-shadow: var(--sf-shadow-md); } -.is-collapsed .calendar-container-wrapper { -} .is-collapsed .calendar-container { padding: var(--sf-space-sm); } @@ -2369,6 +2367,10 @@ button.disabled:hover { color: var(--sf-danger); font-weight: 500; } +.mcq-result-final-correct { + color: var(--sf-warning); + font-weight: 500; +} .mcq-result-attempts, .mcq-result-time { font-size: 0.9em; @@ -2709,35 +2711,6 @@ button.disabled:hover { padding: 2px 6px !important; border-radius: 4px !important; } -.review-time-short, -.review-time-medium, -.review-time-long, -.sm2-info, -.sm2-ratings-title, -.sm2-ratings-desc, -.sm2-ratings-table, -.sm2-ratings-table th, -.sm2-ratings-table td, -.prompt-setting, -.prompt-textarea, -.sf-settings-section, -.sf-settings-section-header, -.sf-settings-icon, -.sf-settings-section-header h3, -.sf-settings-collapse-indicator, -.sf-settings-section-content, -.sf-settings-subsection, -.sf-setting-explain, -.sf-setting-highlight, -.sf-setting-grid, -.sf-settings-actions, -.sf-info-box, -.sf-prompt-label, -.sf-system-prompts-container, -.sf-danger-zone, -.mcq-shortcut-hint, -.hidden { -} .mcq-choice-selected { border-color: var(--interactive-accent) !important; box-shadow: 0 0 0 2px rgba(var(--interactive-accent-rgb), 0.5), 0 1px 3px rgba(0, 0, 0, 0.1); @@ -2817,8 +2790,6 @@ button.disabled:hover { font-weight: 500; color: var(--text-faint); } -.mcq-breakdown-item .user-answer-text { -} .mcq-breakdown-item .correctness-indicator { font-weight: bold; } @@ -3005,8 +2976,6 @@ button.disabled:hover { .pomodoro-quick-save-btn { display: none; } -.pomodoro-quick-save-btn:hover { -} .pomodoro-quick-calculate-btn { background-color: var(--background-modifier-border); color: var(--text-normal); diff --git a/styles/mcq.css b/styles/mcq.css index 9255a0d..0d3b383 100644 --- a/styles/mcq.css +++ b/styles/mcq.css @@ -486,6 +486,10 @@ color: var(--sf-danger); font-weight: 500; } +.mcq-result-final-correct { + color: var(--sf-warning); + font-weight: 500; +} .mcq-result-attempts, .mcq-result-time { @@ -889,14 +893,6 @@ } /* Preserve legacy class function while improving appearance */ -.review-time-short, .review-time-medium, .review-time-long, -.sm2-info, .sm2-ratings-title, .sm2-ratings-desc, .sm2-ratings-table, .sm2-ratings-table th, .sm2-ratings-table td, -.prompt-setting, .prompt-textarea, .sf-settings-section, .sf-settings-section-header, .sf-settings-icon, -.sf-settings-section-header h3, .sf-settings-collapse-indicator, .sf-settings-section-content, .sf-settings-subsection, -.sf-setting-explain, .sf-setting-highlight, .sf-setting-grid, .sf-settings-actions, .sf-info-box, .sf-prompt-label, -.sf-system-prompts-container, .sf-danger-zone, .mcq-shortcut-hint, .hidden { - /* Preserve the classes for compatibility */ -} /* Style for the selected answer using keyboard navigation */ .mcq-choice-selected { @@ -999,9 +995,6 @@ } /* Specific styling for the user's answer text and correctness indicator */ -.mcq-breakdown-item .user-answer-text { /* Class to be added in JS if needed for more specific targeting */ - /* (color is set dynamically in JS) */ -} .mcq-breakdown-item .correctness-indicator { /* Class to be added in JS */ font-weight: bold; diff --git a/ui/mcq-modal.ts b/ui/mcq-modal.ts index f9d93dd..a7d2bf7 100644 --- a/ui/mcq-modal.ts +++ b/ui/mcq-modal.ts @@ -456,10 +456,26 @@ export class MCQModal extends Modal { let totalScore = 0; this.session.answers.forEach(answer => { let questionScore = 0; - if (answer.correct && answer.selectedAnswerIndex !== -1) { - if (answer.attempts === 1) questionScore = 1.0; - else if (answer.attempts === 2) questionScore = 0.5; + + if (this.plugin.settings.mcqDeductFullMarkOnFirstFailure) { + // With this setting, you only get points if you're correct on the first try. + if (answer.attempts === 1 && answer.correct) { + questionScore = 1.0; + } else { + questionScore = 0; // 0 for multiple attempts or for a single incorrect attempt. + } + } else { + // Original scoring logic + if (answer.correct && answer.selectedAnswerIndex !== -1) { + if (answer.attempts === 1) { + questionScore = 1.0; + } else if (answer.attempts === 2) { + questionScore = 0.5; + } + } } + + // Apply time deduction only if points were scored. if (questionScore > 0 && answer.timeToAnswer > this.plugin.settings.mcqTimeDeductionSeconds) { questionScore -= this.plugin.settings.mcqTimeDeductionAmount; questionScore = Math.max(0, questionScore); diff --git a/ui/settings-tab.ts b/ui/settings-tab.ts index 83a4fa0..8afbf48 100644 --- a/ui/settings-tab.ts +++ b/ui/settings-tab.ts @@ -937,6 +937,16 @@ export class SpaceforgeSettingTab extends PluginSettingTab { this.plugin.settings.mcqTimeDeductionSeconds = value; await this.plugin.savePluginData(); })); + + new Setting(mcqSection) + .setName('Deduct full mark on first failure') + .setDesc('If enabled, the score for a question will be 0 if the first attempt is incorrect.') + .addToggle(toggle => toggle + .setValue(this.plugin.settings.mcqDeductFullMarkOnFirstFailure) + .onChange(async (value: boolean) => { + this.plugin.settings.mcqDeductFullMarkOnFirstFailure = value; + await this.plugin.savePluginData(); + })); // Add collapsible section for system prompts const systemPromptsContainer = mcqSection.createEl('details', { cls: 'sf-system-prompts-container' });