Skip to content

Instantly share code, notes, and snippets.

@wahidustoz
Last active July 5, 2025 03:13
Show Gist options
  • Select an option

  • Save wahidustoz/78b7077d5aa3ea24c5fb144c316828d9 to your computer and use it in GitHub Desktop.

Select an option

Save wahidustoz/78b7077d5aa3ea24c5fb144c316828d9 to your computer and use it in GitHub Desktop.
Quiz Engine | C# Project

📚 Quiz engine

Build a two‑mode console app—Teacher and Student—that creates, manages, and runs quizzes, using Spectre.Console for all user interaction.

New in this version

  • Teacher Mode can disable / enable or delete existing quizzes.
  • Optional time‑limited questions feature worth +50 bonus points.

🗂 Table of Contents

  1. Objective
  2. Functional Requirements
  3. Non‑Functional Requirements
  4. Folder Structure
  5. Data Model (Mermaid)
  6. Sample Quiz JSON
  7. Console I/O Samples
  8. Edge Cases
  9. Spectre.Console Usage Requirements
  10. Task Breakdown
  11. Evaluation Rubric
  12. Sequence Diagrams

🎯 1 Objective

Create a console application that lets:

  • Teachers

    1. Build quizzes (MCQ, True/False, Short Answer).
    2. Enable/disable quizzes (disabled quizzes are hidden from students).
    3. Delete quizzes with confirmation.
  • Students

    1. Load an active quiz.
    2. Answer questions via SelectionPrompt / TextPrompt.
    3. Receive an auto‑graded report, with optional half‑score logic for questions answered after their time limit.

✅ 2 Functional Requirements

👩‍🏫 Teacher Mode

Requirement Detail
Main menu SelectionPrompt: Create Quiz, Manage Quizzes, Exit.
Create quiz Enter title & description via TextPrompt.
Add questions MCQ, True/False, Short Answer; repeat until done.
MCQ format Options must be dictionary: "A": "int", etc. Answer stores the key (e.g., "A").
Time‑limited (optional) Teacher may set TimeLimitSeconds (≥ 5 s). Omit for unlimited.
Validation Reject empty prompts, duplicate option keys, invalid time limits.
Summary & save Show a Table; confirm via ConfirmationPrompt before writing JSON.
Manage quizzes List all JSON files via SelectionPrompt. After selection: Enable/Disable, Delete, View Summary.
Delete Requires two confirmations.

👦 Student Mode

Requirement Detail
Quiz list Show only enabled .json files via SelectionPrompt.
Load & header Display in a Panel.
Question flow MCQ / True‑False: SelectionPrompt (arrow keys + Enter).
Short Answer: TextPrompt.
Time‑limited logic (bonus) If a question has TimeLimitSeconds, start a countdown.
• Correct within limit → full point.
• Correct after limit → ½ point.
• No answer or wrong answer → 0.
Scoring Auto‑update points (1, 0.5, 0).
Report Table with ✔/✖ and ⏱ icons; overall % and pass/fail (70 % threshold).

🚫 3 Non‑Functional Requirements

  • 100 % Spectre.Console for input/output—no Console.ReadLine/WriteLine.
  • Robust error handling with custom exceptions where appropriate.
  • Disabled quizzes must not appear in Student Mode.

🗂 4 Folder Structure

QuizApp/
│
├── Program.cs
├── Models/
│   ├── Question.cs
│   ├── McqQuestion.cs
│   ├── TrueFalseQuestion.cs
│   ├── ShortAnswerQuestion.cs
│   └── QuizMeta.cs          <-- holds Title, Description, IsActive
│
├── Services/
│   ├── QuizBuilder.cs
│   ├── QuizManager.cs       <-- enable/disable/delete logic
│   ├── QuizRunner.cs
│   └── QuizStorage.cs
│
├── Utilities/
│   └── InputHelper.cs
│
└── Data/
    └── quizzes/

🏗 5 Data Model

classDiagram
    direction TB
    class QuizMeta {
        +string Title
        +string Description
        +bool IsActive
        +List~Question~ Questions
    }

    class Question {
        +string Prompt
        +int? TimeLimitSeconds
        +abstract double CheckAnswer(string answer, double elapsedSec)
    }

    class McqQuestion {
        +Dictionary~string,string~ Options
        +string AnswerKey
    }

    class TrueFalseQuestion {
        +bool CorrectAnswer
    }

    class ShortAnswerQuestion {
        +string CorrectAnswer
    }

    QuizMeta *-- Question
    Question <|-- McqQuestion
    Question <|-- TrueFalseQuestion
    Question <|-- ShortAnswerQuestion
Loading

📑 6 Sample Quiz JSON (time‑limit demo)

{
  "Title": "C# Basics",
  "Description": "Covers primitive types and control flow.",
  "IsActive": true,
  "Questions": [
    {
      "Type": "MCQ",
      "Prompt": "Which is a value type in C#?",
      "Options": {
        "A": "string",
        "B": "int",
        "C": "object",
        "D": "dynamic"
      },
      "Answer": "B",
      "TimeLimitSeconds": 20   // answer in 20 s for full credit
    },
    {
      "Type": "TrueFalse",
      "Prompt": "The 'var' keyword implies dynamic typing.",
      "CorrectAnswer": false
    },
    {
      "Type": "ShortAnswer",
      "Prompt": "What keyword defines a constant?",
      "CorrectAnswer": "const",
      "TimeLimitSeconds": 15
    }
  ]
}

💻 7 Console I/O Samples

Teacher Mode – Manage Quizzes

[ Manage Existing Quizzes ]
❯ C# Basics   (active)
  OOP Review   (disabled)
Actions for **C# Basics**
❯ Disable Quiz
  Delete Quiz
  View Summary
  Back

Student Mode – Time‑Limited Question

[ Question 1 of 3 ]  ⏱ 20s
Which is a value type in C#?

❯ A: string
  B: int
  C: object
  D: dynamic

(timer counts down; answer after 22 s but correct)
⚠ Time exceeded. Half credit awarded.


⚠ 8 Edge Cases

  • Attempting to start Student Mode when no active quizzes exist.
  • Deleting a quiz that is currently disabled.
  • Teacher disabling an already disabled quiz.
  • Time limit ≤ 0 or < 5 seconds (reject).
  • Student presses Esc or closes prompt before answering (treat as wrong).
  • Half‑credit rounding (0.5 increments).

🖼 9 Spectre.Console Usage Requirements

Purpose API
Main & sub‑menus SelectionPrompt<string>()
Confirmations ConfirmationPrompt()
Text input TextPrompt<string>()
Timer display LiveDisplay, Status(), or custom markup refresh
Tables Table()
Panels / headings Panel(), Rule()
Color feedback Markup()

⏱ 10 Task Breakdown (≈ 16 hrs core + 2‑3 hrs bonus)

Task Hours
Design models & interfaces 2
Implement Teacher Mode (create) 3
Implement Teacher Mode (manage) 1
Implement Student Mode 4
JSON save/load layer 2
Spectre polishing 2
Edge case handling & tests 2
Bonus: time‑limit engine +2–3

🧾 11 Evaluation Rubric /150

Area Points
OOP design & readability 15
Teacher Mode – create 15
Teacher Mode – manage 10
Student Mode 15
JSON persistence reliability 15
Full Spectre.Console usage 15
Error/edge handling 15
All mandatory edge cases met 15
Bonus: time‑limit questions +50

(Max = 150; graders scale to 100 % for final grade.)


🔄 12 Sequence Diagrams

12.1 Teacher Mode (Create / Manage)

sequenceDiagram
    participant T as Teacher
    participant App as ConsoleApp
    participant FS as FileSystem

    T->>App: Launch Teacher Mode
    App-->>T: Main menu (Create / Manage)
    alt Create Quiz
        App-->>T: Prompt meta
        loop Add Qs
            App-->>T: Select q‑type
            T-->>App: Provide details
        end
        App-->>T: Show summary -> confirm save
        T-->>App: Confirm
        App->>FS: Write JSON
        FS-->>App: OK
    else Manage Quiz
        App->>FS: List quizzes
        FS-->>App: File list
        App-->>T: Select quiz
        T-->>App: Choose Disable/Delete/View
        alt Disable
            App->>FS: Toggle IsActive
        else Delete
            App-->>T: Confirm x2
            T-->>App: Confirm
            App->>FS: Delete file
        end
    end
    App-->>T: Result message
Loading

12.2 Student Mode (with Time Limit)

sequenceDiagram
    participant S as Student
    participant App as ConsoleApp
    participant FS as FileSystem
    S->>App: Launch Student Mode
    App->>FS: List active quizzes
    FS-->>App: Quiz list
    App-->>S: Select quiz
    S-->>App: Choose
    App->>FS: Read JSON
    FS-->>App: Quiz data
    loop Each question
        App-->>S: Show prompt (+timer if set)
        App-->>S: SelectionPrompt/TextPrompt
        S-->>App: Answer (and elapsed time)
        App-->>S: Evaluate ✔ / ✖ / ⏱½
    end
    App-->>S: Display final report
Loading

13  End‑to‑End I/O Examples

The following transcripts demonstrate every realistic branch the user can take in Teacher and Student modes, including success paths, validation errors, confirmation prompts, disabled quizzes, time‑limited questions, half credit, and “no active quiz” handling.
All prompts are powered by Spectre.Console components (shown in bold).

13.1 Teacher Mode – Full Cycle

A. Create a New Quiz (happy path)
──────────────  TEACHER MODE  ──────────────
❯ Create Quiz
  Manage Quizzes
  Exit
─────────────────────────────────────────────

[ Title of new quiz ]           (TextPrompt)
> C# Basics

[ Short description ]           (TextPrompt)
> Covers primitive types and control flow.

─────────────────────────────────────────────
Add questions to “C# Basics”
❯ Add MCQ
  Add True/False
  Add Short Answer
  Finish Quiz
─────────────────────────────────────────────

(After choosing Add MCQ)

[ Question prompt ]             (TextPrompt)
> Which is a value type in C#?

[ Option A ]                    (TextPrompt)
> string
[ Option B ]
> int
[ Option C ]
> object
[ Option D ]
> dynamic

[ Correct option key ]          (SelectionPrompt) 
❯ A
  B
  C
  D
(Teacher moves to B)  Enter

[ Time limit in seconds (ENTER for none) ]   (TextPrompt)
> 20

✔ MCQ added.

(Add True/False, Add Short Answer …)

─────────────────────────────────────────────
All questions entered.  Summary:
┌─────┬────────────────────────────────────────────┬─────────┐
│ #   │ Type            │ Prompt                               │
├─────┼─────────────────┼───────────────────────────────────────┤
│ 1   │ MCQ (20 s)      │ Which is a value type in C#?          │
│ 2   │ True/False      │ 'var' implies dynamic typing.         │
│ 3   │ Short Answer    │ Keyword that defines a constant?      │
└─────┴─────────────────┴───────────────────────────────────────┘
Save quiz?                     (ConfirmationPrompt)  [y/N]
> y

🗂 Writing file “C# Basics.json” … done.
[green]Quiz created successfully![/]
B. Validation Error — Duplicate MCQ Option Key
Add MCQ
[ Option A ]
> int
[ Option A ]  (again by mistake)
> integer
[red]Duplicate option key “A”. Option keys must be unique (A‑Z).[/]
C. Overwrite Existing Quiz — Decline
Quiz titled “C# Basics” already exists.
Overwrite?  (ConfirmationPrompt) [y/N]
> n
[grey]File not overwritten. Returning to main menu…[/]
D. Manage Quizzes — Disable, Enable, Delete
──────────  MANAGE QUIZZES  ──────────
❯ C# Basics         (active)
  OOP Review        (disabled)
  Back
───────────────────────────────────────

(Select “C# Basics”)

Actions:                      (SelectionPrompt)
❯ Disable Quiz
  Delete Quiz
  View Summary
  Back

> Disable Quiz
Confirm disable “C# Basics”?  (ConfirmationPrompt) [y/N]
> y
[green]Quiz disabled.[/]

──────────  MANAGE QUIZZES  ──────────
  C# Basics         (disabled)
❯ OOP Review        (disabled)
  Back

(Select “OOP Review”)

Actions:
❯ Enable Quiz
  Delete Quiz
  View Summary
  Back

> Enable Quiz
[green]Quiz enabled.[/]

(Delete flow)

Actions:
  Enable/Disable
❯ Delete Quiz

Danger! This will permanently delete “C# Basics”.
Type DELETE to confirm →  
> del
[red]Incorrect confirmation string. Delete aborted.[/]

Type DELETE to confirm →  
> DELETE
Are you absolutely sure?  (ConfirmationPrompt) [y/N]
> y
File removed.

13.2 Student Mode – Full Cycle

E. No Active Quizzes
──────────────  STUDENT MODE  ──────────────
(no active quizzes found)
Ask your teacher to enable at least one quiz.
─────────────────────────────────────────────
F. Take Quiz – Mixed Results + Time Limit Scenarios
──────────────  STUDENT MODE  ──────────────
Select a quiz:                (SelectionPrompt)
❯ C# Basics
  OOP Review
─────────────────────────────────────────────

╭────────────────────────────────────────────╮
│  C# Basics                                │
│  Covers primitive types and control flow. │
╰────────────────────────────────────────────╯
Press ENTER to begin…

[ Question 1 / 3 | ⏱ 20 s ]
Which is a value type in C#?
❯ A: string
  B: int
  C: object
  D: dynamic
(Answer chosen within 12 s → B)  
[green]✔ Correct![/]

[ Question 2 / 3 ]
'var' implies dynamic typing.
❯ True
  False
(Selected “True”)  
[red]✖ Incorrect.[/]

[ Question 3 / 3 | ⏱ 15 s ]
Keyword that defines a constant?
(15‑second countdown shown with Status spinner)
> const
(Time taken: 19 s)  
[yellow]⚠ Time exceeded. Half credit awarded.[/]

─────────────────  RESULTS  ─────────────────
┌─────┬──────────────────────────────────┬─────────┐
│ #   │ Question                         │ Score   │
├─────┼──────────────────────────────────┼─────────┤
│ 1   │ value type in C#?                │ [green]1.0[/] │
│ 2   │ 'var' implies dynamic typing.    │ [red]0.0[/]  │
│ 3   │ keyword for constant             │ [yellow]0.5[/]│
└─────┴──────────────────────────────────┴─────────┘
Total: 1.5 / 3  (50 %) → [red]Fail[/]
G. Invalid Selection Key (Prevented by UI)

Because MCQ and True/False use SelectionPrompt, the user cannot enter an invalid key—arrow keys restrict the choice set.
If they press Esc or CTRL‑C, you should catch the OperationCanceledException and treat the answer as wrong (0 pts).

[ Question 1 / 3 ]
Which is a value type in C#?
(ESC pressed)
[grey]No answer selected. Marked as incorrect.[/]

These exhaustive transcripts cover all paths that must be handled in code.
Good luck, and happy coding! 🚀

@wahidustoz
Copy link
Author

🧰 InputHelper — What It's Used For

The InputHelper class is a utility helper that centralizes and simplifies user input logic, especially when using Spectre.Console.


✅ What Does It Help With?

Purpose What It Does
AskText(string prompt) Shows a TextPrompt<string> with validation for non-empty values
AskNumber(string prompt, int min…) Prompts user for a number within a range
AskConfirmation(string message) Asks yes/no with ConfirmationPrompt
AskSelection(string title, List<T>) Uses SelectionPrompt with a given list of choices
AskOptionDictionary() Asks for multiple options (e.g., A–D) and returns a Dictionary<string,string>
AskWithOptionalTimeout() Lets teacher optionally set a time limit (used for bonus feature)

💡 Why Is It Useful?

  • Cleaner code – All input code stays in one place.
  • 🔁 No repetition – Reuse prompt logic throughout your app.
  • 🛡 Centralized validation – Like empty-checks or number limits.
  • 🎨 Easy updates – Want to style prompts differently later? Change it once here.

📦 Example Usage in Code

string title = InputHelper.AskText("Enter quiz title:");
int timeLimit = InputHelper.AskNumber("Time limit in seconds:", 5, 300);
bool confirm = InputHelper.AskConfirmation("Do you want to save?");

🧠 Pro Tip

Good developers extract repeated logic into helpers like this.
It makes your code easier to read, maintain, and scale.


@wahidustoz
Copy link
Author

📚 Quiz Engine — SPEC v3

(Adds full class‑diagrams for all classes, clarifies mode selection
startup flow, and makes the question/option‑creation procedure strict and
user‑friendly. All earlier content is preserved or tightened.)


0  Startup Flow — Mode Selection

Immediately after launching the application the user sees:

────────────  QUIZ APP  ────────────
❯ Teacher Mode
  Student Mode
  Exit
────────────────────────────────────

A SelectionPrompt lets them choose:

  • Teacher ModeQuizBuilder / QuizManager
  • Student ModeQuizRunner
  • ExitEnvironment.Exit(0)

This entry point lives in Program.cs:

var choice = InputHelper.AskSelection(
    "Select application mode:",
    new [] { "Teacher Mode", "Student Mode", "Exit" });

switch (choice)
{
    case "Teacher Mode": new QuizBuilder().Run(); break;
    case "Student Mode": new QuizRunner().Run(); break;
    default: return;
}

1  Objective (unchanged)

2  Functional Requirements (unchanged except tighter creation rules below)

👩‍🏫 Strict Question‑Creation Workflow

  1. Select question type via SelectionPrompt.
  2. Enter prompt text — must be 10–200 chars (validated).
  3. MCQ only:
    1. Number of options: teacher picks 2 – 6.
    2. App autogenerates keys A, B, C….
    3. Loop asking non‑empty text for each key.
    4. After all options are entered, a SelectionPrompt shows the finished
      list so the teacher can pick the correct option.
  4. True/False: no options needed; app shows fixed True / False choice
    for the correct answer.
  5. Short Answer: teacher enters the exact correct answer
    (auto‑trimmed, case‑insensitive when grading).
  6. Time limit prompt:
    • “Add a time limit?” (ConfirmationPrompt)
    • If Yes, numeric TextPrompt<int> with min = 5 s, max = 600 s.
  7. Question is appended to quiz; summary table updates in real time.

Invalid inputs loop until they meet constraints.


3–12 (identical to previous version; omitted for brevity)


5  Complete Class Diagram

classDiagram
    direction LR

    %% ==== Models ====
    class QuizMeta {
        +string Title
        +string Description
        +bool IsActive
        +List~Question~ Questions
        +void ToggleActive()
    }

    class Question {
        +string Prompt
        +int? TimeLimitSeconds
        +abstract double CheckAnswer(string answer, double elapsedSec)
    }

    class McqQuestion {
        +Dictionary~string,string~ Options
        +string AnswerKey
    }

    class TrueFalseQuestion {
        +bool CorrectAnswer
    }

    class ShortAnswerQuestion {
        +string CorrectAnswer
    }

    %% ==== Services ====
    class QuizBuilder {
        +void Run()
        -void CreateQuiz()
        -void AddQuestionLoop()
    }

    class QuizManager {
        +void Run()
        -void ManageLoop()
        -void ToggleActive()
        -void DeleteQuiz()
    }

    class QuizRunner {
        +void Run()
        -void AskQuestions()
        -void ShowReport()
    }

    class QuizStorage {
        +IEnumerable~QuizMeta~ ListAll()
        +QuizMeta Load(string file)
        +void Save(QuizMeta quiz)
        +void Delete(string file)
    }

    %% ==== Helper ====
    class InputHelper {
        <<static>>
        +string AskText(...)
        +int AskNumber(...)
        +bool AskConfirmation(...)
        +T AskSelection~T~(...)
    }

    %% ==== Relationships ====
    QuizMeta *-- Question
    Question <|-- McqQuestion
    Question <|-- TrueFalseQuestion
    Question <|-- ShortAnswerQuestion

    Program ..> QuizBuilder
    Program ..> QuizRunner
    Program ..> QuizManager

    QuizBuilder --> QuizStorage
    QuizManager --> QuizStorage
    QuizRunner  --> QuizStorage

    QuizBuilder ..> InputHelper
    QuizManager ..> InputHelper
    QuizRunner  ..> InputHelper
Loading

Legend: solid arrow = composition/implementation, dotted arrow = usage.


13  End‑to‑End I/O Examples (unchanged, still exhaustive)

(See previous version for the full transcripts A – G.)


Happy coding — now with crystal‑clear flow and fully‑mapped classes! 🚀

@wahidustoz
Copy link
Author

wahidustoz commented Jul 5, 2025

👩‍🏫 Teacher Mode — How QuizBuilder and QuizManager Work


🚪 Entry Point

When the user selects "Teacher Mode" from the main menu:

new QuizBuilder().Run();

🧩 Role of QuizBuilder

QuizBuilder acts as the controller for Teacher Mode.
It routes the teacher to either creating or managing quizzes.

🧭 Main Menu Prompt

public void Run()
{
    while (true)
    {
        var choice = InputHelper.AskSelection("Teacher Menu", new[]
        {
            "➕ Create New Quiz",
            "🛠 Manage Existing Quizzes",
            "🔙 Back to Main Menu"
        });

        switch (choice)
        {
            case "➕ Create New Quiz":
                CreateQuiz(); // Handles new quiz creation
                break;

            case "🛠 Manage Existing Quizzes":
                new QuizManager().Run(); // Delegates to QuizManager
                break;

            case "🔙 Back to Main Menu":
                return;
        }
    }
}

🏗️ What CreateQuiz() Does

Inside QuizBuilder, the CreateQuiz() method:

  • Prompts for:
    • ✅ Quiz Title (TextPrompt)
    • ✅ Description (TextPrompt)
  • Creates an empty QuizMeta object
  • Starts a loop to add questions:
    • MCQ
    • True/False
    • Short Answer
  • Validates all entries
  • Offers optional time limits
  • Renders a Table summary
  • Confirms saving via ConfirmationPrompt
  • Calls QuizStorage.Save() to write JSON

🔧 What QuizManager.Run() Does

Once the teacher selects "Manage Existing Quizzes",
control is passed to QuizManager:

Responsibilities:

  • List all quizzes from Data/quizzes/
  • Let the user:
    • Enable/Disable selected quiz
    • Delete a quiz (with 2 confirmations)
    • 📄 View Summary in a table
  • Update the quiz metadata (IsActive flag)
  • Remove file if deleted

🔁 Diagram — Teacher Mode Lifecycle

flowchart TD
    A[Start: Teacher Mode Selected]
    B[QuizBuilder.Run]
    C[Main Menu: SelectionPrompt]
    D[CreateQuiz]
    E[QuizManager.Run]
    F[Return to Main Menu]

    A --> B --> C
    C --> D
    C --> E
    C --> F

    D --> D1[Prompt for title + description]
    D1 --> D2[Loop: Add Questions]
    D2 --> D3[Show summary table]
    D3 --> D4[Confirm and Save as JSON]

    E --> E1[List all quizzes]
    E1 --> E2[Select quiz to manage]
    E2 --> E3[Action: Enable/Disable/Delete/View]
    E3 --> E4[Perform selected action]
    E3 --> F

Loading

🎯 Why Split the Logic?

Class Responsibility
QuizBuilder Create new quizzes from scratch
QuizManager Manage existing quizzes

✅ Benefits:

  • Clear separation of concerns (SRP)
  • Better readability and maintenance
  • Easier to test independently

Let me know if you'd like this shown as a Mermaid diagram too!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment