# MiroFish Simulator API Reference

## Quick Start

```python
from mirofish_simulator import AgenticOrchestrator

orchestrator = AgenticOrchestrator()

result = await orchestrator.simulate(
    question={"text": "...", "options": [...]},
    correct_answer="B",
    grade=8,
    archetype="average_student",
)

print(result.selected)        # "C"
print(result.is_correct)      # False
print(result.student_model.misconceptions)
```

---

## Core Classes

### AgenticOrchestrator

Main entry point for student simulation using misconception matching.

```python
class AgenticOrchestrator:
    def __init__(
        self,
        api_key: str = None,      # Uses OPENAI_API_KEY env var if not set
        base_url: str = None,     # Custom API endpoint
        model: str = "gpt-4o-mini",
    )
```

#### Methods

##### `simulate(question, correct_answer, grade, archetype) -> AgenticSimulationResult`

Simulate a single student answering a question.

**Parameters:**
- `question` (dict): Question with `text` and `options` keys
- `correct_answer` (str): The correct option letter ("A", "B", "C", or "D")
- `grade` (int): Student grade level (1-12)
- `archetype` (str): Student archetype (see Archetypes below)

**Returns:** `AgenticSimulationResult`

**Example:**
```python
result = await orchestrator.simulate(
    question={
        "text": "How many electoral votes are needed to win?",
        "options": ["218", "270", "300", "435"]
    },
    correct_answer="B",
    grade=5,
    archetype="class_clown",
)
```

##### `simulate_batch(question, correct_answer, students) -> List[AgenticSimulationResult]`

Simulate multiple students answering the same question efficiently.

**Parameters:**
- `question` (dict): Question with `text` and `options`
- `correct_answer` (str): Correct option letter
- `students` (list): List of `{"grade": int, "archetype": str}` dicts

**Returns:** List of `AgenticSimulationResult`

**Example:**
```python
results = await orchestrator.simulate_batch(
    question=question,
    correct_answer="B",
    students=[
        {"grade": 5, "archetype": "class_clown"},
        {"grade": 8, "archetype": "average_student"},
        {"grade": 11, "archetype": "honors_overachiever"},
    ]
)
```

---

### AgenticSimulationResult

Result from a student simulation.

```python
@dataclass
class AgenticSimulationResult:
    selected: str              # "A", "B", "C", "D"
    selected_text: str         # Full answer text
    is_correct: bool

    grade: int
    archetype: str
    question_id: Optional[str]

    distractor_analysis: DistractorAnalysis
    student_model: StudentModel
    selection_result: SelectionResult
```

#### Methods

- `to_dict()` - Returns full dictionary representation
- `summary()` - Returns human-readable summary string

---

### DistractorAgent

Analyzes what misconceptions lead to each wrong answer.

```python
agent = DistractorAgent()
analysis = await agent.analyze(question, correct_answer="B")

for mapping in analysis.mappings:
    print(f"{mapping.option}: {mapping.leads_from_misconception}")
```

#### DistractorAnalysis

```python
@dataclass
class DistractorAnalysis:
    question_text: str
    correct_option: str
    mappings: List[DistractorMapping]
    key_knowledge_required: str
```

#### DistractorMapping

```python
@dataclass
class DistractorMapping:
    option: str                    # "A", "B", "C", "D"
    option_text: str
    is_correct: bool
    leads_from_misconception: Optional[str]  # None if correct
    why_attractive: str
    grade_level_appeal: Dict[str, float]  # {"elementary": 0.8, ...}
```

---

### StudentModelAgent

Models what a student believes (including misconceptions).

```python
agent = StudentModelAgent()
student = await agent.model_student(question, grade=5, archetype="class_clown")

print(student.beliefs)
print(student.misconceptions)
print(student.topic_familiarity)
```

#### StudentModel

```python
@dataclass
class StudentModel:
    grade: int
    archetype: str

    beliefs: List[str]           # What they believe (may be wrong)
    misconceptions: List[str]    # Specifically wrong beliefs

    topic_familiarity: float     # 0-1
    confidence_level: str        # "confident", "uncertain", "guessing"

    guesses_when_unsure: bool
    uses_elimination: bool
    attracted_to_familiar_words: bool
    second_guesses_self: bool
```

---

### SelectorAgent

Matches student misconceptions to answers.

```python
agent = SelectorAgent()
selection = await agent.select(question, distractor_analysis, student_model)

print(selection.selected)
print(selection.misconception_matched)
```

#### SelectionResult

```python
@dataclass
class SelectionResult:
    selected: str
    selected_text: str
    is_correct: bool

    selection_reason: str
    misconception_matched: Optional[str]
    confidence: str

    consideration_process: str
    eliminated_options: Dict[str, str]
```

---

## Archetypes

| Archetype | Typical Familiarity | Behavior |
|-----------|---------------------|----------|
| `honors_overachiever` | 80%+ | Specific knowledge, confident, reads ahead |
| `average_student` | 60-70% | Knows what was taught, some gaps |
| `class_clown` | 40% | Minimal attention, guesses often |
| `esl_student` | 60-70% | Core concepts solid, vocabulary issues |
| `disengaged_but_smart` | Variable | Has ability but inconsistent |
| `quiet_thinker` | 60% | Thoughtful but second-guesses |
| `debate_club_kid` | High in interests | Good at arguments |

---

## Other APIs

### MisconceptionAnalyzer

Analyzes distractors and maps them to misconceptions with remediation suggestions.

```python
from mirofish_simulator import MisconceptionAnalyzer

analyzer = MisconceptionAnalyzer()
result = await analyzer.analyze({
    "text": "What is 1/2 + 1/4?",
    "options": ["2/6", "3/4", "1/6", "2/4"],
    "correct_answer": "B",
    "subject": "mathematics",
})
```

### ComparativeAnalyzer

Analyzes a set of questions for coverage, redundancy, and progression.

```python
from mirofish_simulator import ComparativeAnalyzer

analyzer = ComparativeAnalyzer()
result = await analyzer.analyze_quiz(questions, expected_standards)
```

### AccessibilityAnalyzer

Deterministic (no LLM) analysis of content accessibility.

```python
from mirofish_simulator import AccessibilityAnalyzer

analyzer = AccessibilityAnalyzer()
result = await analyzer.analyze(
    content={"text": "..."},
    target_grade=5,
)

print(result.reading_level.flesch_kincaid_grade)
print(result.vocabulary.issues)
```

---

## Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `OPENAI_API_KEY` | Yes (for simulation) | OpenAI API key |
| `OPENAI_BASE_URL` | No | Custom API endpoint |

---

## Error Handling

All agents have fallback behavior when API is unavailable:

```python
# Without API key, agents return fallback results
orchestrator = AgenticOrchestrator()  # No api_key
result = await orchestrator.simulate(...)

# result.selection_result.confidence will be "guessing"
# result.selection_result.selection_reason will indicate "Fallback"
```
