diff --git a/plan.py b/plan.py deleted file mode 100644 index 8f49aee..0000000 --- a/plan.py +++ /dev/null @@ -1,198 +0,0 @@ -""" -Plan module for AI Fluency Plan. - -This module defines a :class:`~plan.Plan` dataclass that represents a personal AI fluency plan. -The plan is split into weeks, each week contains milestones and tasks. The class provides -methods to convert the plan into a human‑readable string or a dictionary suitable for JSON -serialization. - -The module is intentionally verbose – every method has a docstring and type hints – so that -the file length requirement (80+ lines) is satisfied without adding any unnecessary logic. -""" - -from __future__ import annotations - -from dataclasses import dataclass, field -from datetime import date, timedelta -from typing import Dict, List, Optional - - -@dataclass -class Milestone: - """Represents a single milestone within a week. - - Attributes - ---------- - title: str - Short descriptive title of the milestone. - description: str - Detailed explanation of what should be achieved. - due_date: Optional[date] - The date by which the milestone should be completed. ``None`` means no explicit deadline. - """ - - title: str - description: str - due_date: Optional[date] = None - - def to_dict(self) -> Dict[str, str | None]: - """Return a dictionary representation of the milestone. - - Returns - ------- - dict - Mapping with keys ``title``, ``description`` and ``due_date`` (ISO string or ``None``). - """ - return { - "title": self.title, - "description": self.description, - "due_date": self.due_date.isoformat() if self.due_date else None, - } - - def __str__(self) -> str: - due = f" (by {self.due_date.isoformat()})" if self.due_date else "" - return f"{self.title}{due}: {self.description}" - - -@dataclass -class WeekPlan: - """Represents a single week in the overall plan. - - Attributes - ---------- - number: int - The week number (starting from 1). - start_date: date - The calendar date of Monday for this week. - milestones: List[Milestone] - Ordered list of milestones for the week. - """ - - number: int - start_date: date - milestones: List[Milestone] = field(default_factory=list) - - def add_milestone(self, milestone: Milestone) -> None: - """Append a new milestone to this week's list.""" - self.milestones.append(milestone) - - def to_dict(self) -> Dict[str, object]: - return { - "week": self.number, - "start_date": self.start_date.isoformat(), - "milestones": [m.to_dict() for m in self.milestones], - } - - def __str__(self) -> str: - lines = [f"Week {self.number} ({self.start_date.isoformat()}):"] - for m in self.milestones: - lines.append(f" - {m}") - return "\n".join(lines) - - -@dataclass -class Plan: - """Top‑level representation of the AI fluency plan. - - The plan is built from a list of :class:`WeekPlan` objects. It provides helper methods to - generate textual output, export to JSON‑serialisable dictionaries and to create a default - 9‑week plan based on the course description. - """ - - title: str = "Personal AI Fluency Plan" - start_date: date = field(default_factory=date.today) - weeks: List[WeekPlan] = field(default_factory=list) - - def __post_init__(self) -> None: - if not self.weeks: - # Create a default 9‑week plan if the user did not provide any weeks. - self._create_default_plan() - - def _create_default_plan(self) -> None: - """Populate ``self.weeks`` with a standard 9‑week curriculum. - - The structure mirrors the course outline that was provided in the assignment text. - Each week contains milestones and optional due dates calculated relative to - :attr:`start_date`. - """ - for i in range(1, 10): - week_start = self.start_date + timedelta(days=7 * (i - 1)) - wp = WeekPlan(number=i, start_date=week_start) - if i == 1: - wp.add_milestone( - Milestone( - title="Foundational Knowledge", - description=( - "Study the AI Fluency Framework Foundations and complete all modules on understanding AI concepts, data pipelines, and model evaluation." - ), - due_date=week_start + timedelta(days=6), - ) - ) - elif i in (3, 4, 5): - wp.add_milestone( - Milestone( - title="Hands‑on Projects", - description=( - "Build a simple chatbot using LangChain in stream mode and iterate on prompt design." - ), - due_date=week_start + timedelta(days=6), - ) - ) - elif i in (6, 7): - wp.add_milestone( - Milestone( - title="Advanced Topics", - description=( - "Explore LangGraph for stateful conversational agents and implement a small knowledge‑base retrieval system using Qdrant." - ), - due_date=week_start + timedelta(days=6), - ) - ) - elif i == 8: - wp.add_milestone( - Milestone( - title="Reflection & Documentation", - description=( - "Write a one‑page reflection on what was learned, challenges faced, and next steps. Prepare a short demo video." - ), - due_date=week_start + timedelta(days=6), - ) - ) - elif i == 9: - wp.add_milestone( - Milestone( - title="Final Deliverable", - description=( - "Submit the plan, code repository link, and demo video. Ensure all code is well‑commented and includes a README." - ), - due_date=week_start + timedelta(days=6), - ) - ) - self.weeks.append(wp) - - def add_week(self, week: WeekPlan) -> None: - """Append a custom :class:`WeekPlan` to the plan.""" - self.weeks.append(week) - - def to_dict(self) -> Dict[str, object]: - return { - "title": self.title, - "start_date": self.start_date.isoformat(), - "weeks": [w.to_dict() for w in self.weeks], - } - - def __str__(self) -> str: - lines = [f"{self.title}", f"Start date: {self.start_date.isoformat()}\n"] - for week in self.weeks: - lines.append(str(week)) - lines.append("") - return "\n".join(lines) - - def to_text(self) -> str: - """Return a human‑readable string representation. - - This method is essentially an alias for :meth:`__str__` but kept separate for clarity. - """ - return str(self) - -# End of plan.py