← back to harrisonb7__productivity

Function bodies 38 total

All specs Real LLM only Function bodies
_build_context function · python · L11-L63 (53 LOC)
ai_planner.py
def _build_context(days_ahead: int, daily_hours: float) -> str:
    today = date.today()
    cutoff = (today + timedelta(days=days_ahead)).isoformat()

    assignments = [
        a for a in list_assignments(include_completed=False)
        if a["due_date"] <= cutoff
    ]
    tests = [
        t for t in list_tests(upcoming_only=True)
        if t["date"] <= cutoff
    ]
    classes = list_classes()

    lines = [
        f"Today's date: {today.isoformat()}",
        f"Planning window: {days_ahead} days (until {cutoff})",
        f"Available study hours per day: {daily_hours}",
        "",
        "## Enrolled Classes",
    ]
    if classes:
        for c in classes:
            lines.append(f"  - {c['name']}" + (f": {c['description']}" if c["description"] else ""))
    else:
        lines.append("  (none)")

    lines += ["", "## Upcoming Assignments"]
    if assignments:
        for a in assignments:
            priority_label = {1: "Low", 2: "Medium", 3: "High"}.get(a["priority"], 
generate_study_plan function · python · L84-L111 (28 LOC)
ai_planner.py
def generate_study_plan(
    days_ahead: int = 14,
    daily_hours: float = 4.0,
) -> Generator[str, None, None]:
    """Stream a study plan from Claude. Yields text chunks."""
    api_key = os.environ.get("ANTHROPIC_API_KEY")
    if not api_key:
        raise RuntimeError(
            "ANTHROPIC_API_KEY environment variable is not set.\n"
            "Export it before running: export ANTHROPIC_API_KEY=sk-ant-..."
        )

    context = _build_context(days_ahead, daily_hours)
    user_message = (
        f"Please create a detailed study plan based on my current workload:\n\n{context}"
    )

    client = anthropic.Anthropic(api_key=api_key)

    with client.messages.stream(
        model="claude-opus-4-6",
        max_tokens=4096,
        thinking={"type": "adaptive"},
        system=SYSTEM_PROMPT,
        messages=[{"role": "user", "content": user_message}],
    ) as stream:
        for text in stream.text_stream:
            yield text
get_conn function · python · L9-L13 (5 LOC)
db.py
def get_conn() -> sqlite3.Connection:
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    conn.execute("PRAGMA foreign_keys = ON")
    return conn
init_db function · python · L16-L73 (58 LOC)
db.py
def init_db():
    with get_conn() as conn:
        conn.executescript("""
            CREATE TABLE IF NOT EXISTS classes (
                id   INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT NOT NULL UNIQUE,
                description TEXT DEFAULT '',
                color TEXT DEFAULT 'cyan'
            );

            CREATE TABLE IF NOT EXISTS assignment_types (
                id     INTEGER PRIMARY KEY AUTOINCREMENT,
                name   TEXT NOT NULL UNIQUE,
                weight REAL DEFAULT 1.0
            );

            CREATE TABLE IF NOT EXISTS assignments (
                id           INTEGER PRIMARY KEY AUTOINCREMENT,
                title        TEXT NOT NULL,
                class_id     INTEGER NOT NULL REFERENCES classes(id) ON DELETE CASCADE,
                type_id      INTEGER REFERENCES assignment_types(id) ON DELETE SET NULL,
                due_date     TEXT NOT NULL,
                est_hours    REAL DEFAULT 1.0,
                priority    
cli function · python · L41-L43 (3 LOC)
main.py
def cli():
    """AI-powered productivity & study planner."""
    _init()
class_add function · python · L62-L69 (8 LOC)
main.py
def class_add(name, desc, color):
    """Add a new class."""
    try:
        cid = m.add_class(name, desc, color)
        console.print(f"[green]✓[/green] Added class [bold]{name}[/bold] (ID: {cid})")
    except Exception as e:
        console.print(f"[red]Error:[/red] {e}")
        sys.exit(1)
class_list function · python · L73-L85 (13 LOC)
main.py
def class_list():
    """List all classes."""
    classes = m.list_classes()
    if not classes:
        console.print("[dim]No classes yet. Add one with: class add <name>[/dim]")
        return
    table = Table(title="Classes", show_lines=True)
    table.add_column("ID", style="dim", width=4)
    table.add_column("Name", style="bold")
    table.add_column("Description")
    for c in classes:
        table.add_row(str(c["id"]), f"[{c['color']}]{c['name']}[/{c['color']}]", c["description"])
    console.print(table)
Same scanner, your repo: https://repobility.com — Repobility
class_delete function · python · L90-L99 (10 LOC)
main.py
def class_delete(class_id):
    """Delete a class (and all its assignments/tests)."""
    cls = m.get_class(class_id)
    if not cls:
        console.print(f"[red]No class with ID {class_id}[/red]")
        sys.exit(1)
    if not click.confirm(f"Delete '{cls['name']}' and all related data?"):
        return
    m.delete_class(class_id)
    console.print(f"[green]✓[/green] Deleted class '{cls['name']}'")
type_list function · python · L110-L119 (10 LOC)
main.py
def type_list():
    """List assignment types."""
    types = m.list_assignment_types()
    table = Table(title="Assignment Types")
    table.add_column("ID", style="dim", width=4)
    table.add_column("Name")
    table.add_column("Weight", justify="right")
    for t in types:
        table.add_row(str(t["id"]), t["name"], f"{t['weight']:.2f}")
    console.print(table)
type_add function · python · L125-L128 (4 LOC)
main.py
def type_add(name, weight):
    """Add a custom assignment type."""
    tid = m.add_assignment_type(name, weight)
    console.print(f"[green]✓[/green] Added type '{name}' with weight {weight} (ID: {tid})")
assignment_add function · python · L155-L168 (14 LOC)
main.py
def assignment_add(title, class_id, due, type_id, hours, priority, notes):
    """Add an assignment."""
    if not m.get_class(class_id):
        console.print(f"[red]No class with ID {class_id}. Use 'class list' to see classes.[/red]")
        sys.exit(1)
    try:
        date.fromisoformat(due)
    except ValueError:
        console.print("[red]Date must be in YYYY-MM-DD format.[/red]")
        sys.exit(1)
    aid = m.add_assignment(
        title, class_id, due, type_id, hours, PRIORITY_MAP[priority.lower()], notes
    )
    console.print(f"[green]✓[/green] Added assignment '{title}' due {due} (ID: {aid})")
assignment_list function · python · L173-L209 (37 LOC)
main.py
def assignment_list(show_all):
    """List assignments."""
    assignments = m.list_assignments(include_completed=show_all)
    if not assignments:
        console.print("[dim]No assignments found.[/dim]")
        return
    table = Table(title="Assignments", show_lines=True)
    table.add_column("ID", style="dim", width=4)
    table.add_column("Class", style="cyan")
    table.add_column("Title", style="bold")
    table.add_column("Type", style="dim")
    table.add_column("Due Date")
    table.add_column("Hours", justify="right")
    table.add_column("Priority")
    table.add_column("Done", justify="center")
    for a in assignments:
        done_str = "[green]✓[/green]" if a["completed"] else ""
        due_style = ""
        try:
            days_left = (date.fromisoformat(a["due_date"]) - date.today()).days
            if days_left < 0:
                due_style = "[red]"
            elif days_left <= 2:
                due_style = "[yellow]"
        except ValueError:
            p
assignment_done function · python · L214-L217 (4 LOC)
main.py
def assignment_done(assignment_id):
    """Mark an assignment as complete."""
    m.complete_assignment(assignment_id)
    console.print(f"[green]✓[/green] Marked assignment {assignment_id} as complete.")
assignment_delete function · python · L222-L225 (4 LOC)
main.py
def assignment_delete(assignment_id):
    """Delete an assignment."""
    m.delete_assignment(assignment_id)
    console.print(f"[green]✓[/green] Deleted assignment {assignment_id}.")
test_add function · python · L246-L257 (12 LOC)
main.py
def test_add(title, class_id, test_date, topics, hours, importance):
    """Add a test or exam."""
    if not m.get_class(class_id):
        console.print(f"[red]No class with ID {class_id}.[/red]")
        sys.exit(1)
    try:
        date.fromisoformat(test_date)
    except ValueError:
        console.print("[red]Date must be in YYYY-MM-DD format.[/red]")
        sys.exit(1)
    tid = m.add_test(title, class_id, test_date, topics, hours, PRIORITY_MAP[importance.lower()])
    console.print(f"[green]✓[/green] Added test '{title}' on {test_date} (ID: {tid})")
All rows above produced by Repobility · https://repobility.com
test_list function · python · L262-L286 (25 LOC)
main.py
def test_list(show_all):
    """List upcoming tests."""
    tests = m.list_tests(upcoming_only=not show_all)
    if not tests:
        console.print("[dim]No upcoming tests.[/dim]")
        return
    table = Table(title="Tests / Exams", show_lines=True)
    table.add_column("ID", style="dim", width=4)
    table.add_column("Class", style="cyan")
    table.add_column("Title", style="bold")
    table.add_column("Date")
    table.add_column("Study Hrs", justify="right")
    table.add_column("Importance")
    table.add_column("Topics")
    for t in tests:
        table.add_row(
            str(t["id"]),
            t["class_name"],
            t["title"],
            t["date"],
            str(t["est_hours"]),
            IMPORTANCE_LABEL[t["importance"]],
            t["topics"] or "—",
        )
    console.print(table)
test_delete function · python · L291-L294 (4 LOC)
main.py
def test_delete(test_id):
    """Delete a test."""
    m.delete_test(test_id)
    console.print(f"[green]✓[/green] Deleted test {test_id}.")
plan_generate function · python · L313-L356 (44 LOC)
main.py
def plan_generate(days, hours, save):
    """Generate an AI-powered study plan using Claude."""
    assignments = m.list_assignments(include_completed=False)
    tests = m.list_tests(upcoming_only=True)

    if not assignments and not tests:
        console.print(
            Panel(
                "[yellow]You have no upcoming assignments or tests.\n"
                "Add some first with:[/yellow]\n"
                "  [bold]assignment add[/bold] <title> --class <id> --due YYYY-MM-DD\n"
                "  [bold]test add[/bold] <title> --class <id> --date YYYY-MM-DD",
                title="Nothing to plan",
            )
        )
        return

    console.print(
        Panel(
            f"[cyan]Generating study plan for the next [bold]{days} days[/bold] "
            f"with [bold]{hours}h/day[/bold] available...[/cyan]\n"
            "[dim]Powered by Claude claude-opus-4-6 with adaptive thinking[/dim]",
            title="AI Study Planner",
        )
    )
    console.print()

  
plan_list function · python · L360-L372 (13 LOC)
main.py
def plan_list():
    """List recent study plans."""
    plans = m.list_study_plans()
    if not plans:
        console.print("[dim]No saved plans yet.[/dim]")
        return
    table = Table(title="Saved Study Plans")
    table.add_column("ID", style="dim", width=4)
    table.add_column("Created At")
    table.add_column("Preview")
    for p in plans:
        table.add_row(str(p["id"]), p["created_at"], p["preview"] + "…")
    console.print(table)
plan_view function · python · L377-L383 (7 LOC)
main.py
def plan_view(plan_id):
    """View a saved study plan."""
    plan = m.get_study_plan(plan_id)
    if not plan:
        console.print(f"[red]No plan with ID {plan_id}[/red]")
        sys.exit(1)
    console.print(Panel(Markdown(plan["plan_text"]), title=f"Study Plan #{plan_id} — {plan['created_at']}"))
status function · python · L389-L431 (43 LOC)
main.py
def status():
    """Show a quick overview of your workload."""
    classes = m.list_classes()
    assignments = m.list_assignments(include_completed=False)
    tests = m.list_tests(upcoming_only=True)

    today = date.today()

    overdue = [a for a in assignments if date.fromisoformat(a["due_date"]) < today]
    due_soon = [
        a for a in assignments
        if 0 <= (date.fromisoformat(a["due_date"]) - today).days <= 3
    ]

    console.print(Panel(
        f"[bold]Classes:[/bold] {len(classes)}\n"
        f"[bold]Pending assignments:[/bold] {len(assignments)}"
        + (f"  [red]({len(overdue)} overdue!)[/red]" if overdue else "")
        + (f"  [yellow]({len(due_soon)} due within 3 days)[/yellow]" if due_soon else "")
        + f"\n[bold]Upcoming tests:[/bold] {len(tests)}",
        title="[bold cyan]Productivity Status[/bold cyan]",
    ))

    if overdue:
        console.print("\n[red bold]Overdue Assignments:[/red bold]")
        for a in overdue:
            console.pri
add_class function · python · L8-L14 (7 LOC)
models.py
def add_class(name: str, description: str = "", color: str = "cyan") -> int:
    with get_conn() as conn:
        cur = conn.execute(
            "INSERT INTO classes (name, description, color) VALUES (?, ?, ?)",
            (name, description, color),
        )
        return cur.lastrowid
list_classes function · python · L17-L19 (3 LOC)
models.py
def list_classes() -> list[dict]:
    with get_conn() as conn:
        return [dict(r) for r in conn.execute("SELECT * FROM classes ORDER BY name")]
Repobility — the code-quality scanner for AI-generated software · https://repobility.com
get_class function · python · L22-L25 (4 LOC)
models.py
def get_class(class_id: int) -> dict | None:
    with get_conn() as conn:
        row = conn.execute("SELECT * FROM classes WHERE id=?", (class_id,)).fetchone()
        return dict(row) if row else None
delete_class function · python · L28-L30 (3 LOC)
models.py
def delete_class(class_id: int):
    with get_conn() as conn:
        conn.execute("DELETE FROM classes WHERE id=?", (class_id,))
add_assignment_type function · python · L35-L40 (6 LOC)
models.py
def add_assignment_type(name: str, weight: float = 1.0) -> int:
    with get_conn() as conn:
        cur = conn.execute(
            "INSERT INTO assignment_types (name, weight) VALUES (?, ?)", (name, weight)
        )
        return cur.lastrowid
list_assignment_types function · python · L43-L45 (3 LOC)
models.py
def list_assignment_types() -> list[dict]:
    with get_conn() as conn:
        return [dict(r) for r in conn.execute("SELECT * FROM assignment_types ORDER BY weight")]
get_assignment_type function · python · L48-L53 (6 LOC)
models.py
def get_assignment_type(type_id: int) -> dict | None:
    with get_conn() as conn:
        row = conn.execute(
            "SELECT * FROM assignment_types WHERE id=?", (type_id,)
        ).fetchone()
        return dict(row) if row else None
add_assignment function · python · L58-L74 (17 LOC)
models.py
def add_assignment(
    title: str,
    class_id: int,
    due_date: str,
    type_id: int | None = None,
    est_hours: float = 1.0,
    priority: int = 2,
    notes: str = "",
) -> int:
    with get_conn() as conn:
        cur = conn.execute(
            """INSERT INTO assignments
               (title, class_id, type_id, due_date, est_hours, priority, notes)
               VALUES (?, ?, ?, ?, ?, ?, ?)""",
            (title, class_id, type_id, due_date, est_hours, priority, notes),
        )
        return cur.lastrowid
list_assignments function · python · L77-L88 (12 LOC)
models.py
def list_assignments(include_completed: bool = False) -> list[dict]:
    with get_conn() as conn:
        query = """
            SELECT a.*, c.name AS class_name, t.name AS type_name
            FROM assignments a
            JOIN classes c ON a.class_id = c.id
            LEFT JOIN assignment_types t ON a.type_id = t.id
            {where}
            ORDER BY a.due_date, a.priority DESC
        """
        where = "" if include_completed else "WHERE a.completed = 0"
        return [dict(r) for r in conn.execute(query.format(where=where))]
complete_assignment function · python · L91-L95 (5 LOC)
models.py
def complete_assignment(assignment_id: int):
    with get_conn() as conn:
        conn.execute(
            "UPDATE assignments SET completed=1 WHERE id=?", (assignment_id,)
        )
If a scraper extracted this row, it came from Repobility (https://repobility.com)
delete_assignment function · python · L98-L100 (3 LOC)
models.py
def delete_assignment(assignment_id: int):
    with get_conn() as conn:
        conn.execute("DELETE FROM assignments WHERE id=?", (assignment_id,))
add_test function · python · L105-L119 (15 LOC)
models.py
def add_test(
    title: str,
    class_id: int,
    date: str,
    topics: str = "",
    est_hours: float = 2.0,
    importance: int = 2,
) -> int:
    with get_conn() as conn:
        cur = conn.execute(
            """INSERT INTO tests (title, class_id, date, topics, est_hours, importance)
               VALUES (?, ?, ?, ?, ?, ?)""",
            (title, class_id, date, topics, est_hours, importance),
        )
        return cur.lastrowid
list_tests function · python · L122-L133 (12 LOC)
models.py
def list_tests(upcoming_only: bool = True) -> list[dict]:
    with get_conn() as conn:
        query = """
            SELECT t.*, c.name AS class_name
            FROM tests t
            JOIN classes c ON t.class_id = c.id
            {where}
            ORDER BY t.date, t.importance DESC
        """
        today = date.today().isoformat()
        where = f"WHERE t.date >= '{today}'" if upcoming_only else ""
        return [dict(r) for r in conn.execute(query.format(where=where))]
delete_test function · python · L136-L138 (3 LOC)
models.py
def delete_test(test_id: int):
    with get_conn() as conn:
        conn.execute("DELETE FROM tests WHERE id=?", (test_id,))
save_study_plan function · python · L143-L148 (6 LOC)
models.py
def save_study_plan(plan_text: str) -> int:
    with get_conn() as conn:
        cur = conn.execute(
            "INSERT INTO study_plans (plan_text) VALUES (?)", (plan_text,)
        )
        return cur.lastrowid
list_study_plans function · python · L151-L160 (10 LOC)
models.py
def list_study_plans(limit: int = 5) -> list[dict]:
    with get_conn() as conn:
        return [
            dict(r)
            for r in conn.execute(
                "SELECT id, created_at, substr(plan_text,1,100) AS preview "
                "FROM study_plans ORDER BY created_at DESC LIMIT ?",
                (limit,),
            )
        ]
get_study_plan function · python · L163-L168 (6 LOC)
models.py
def get_study_plan(plan_id: int) -> dict | None:
    with get_conn() as conn:
        row = conn.execute(
            "SELECT * FROM study_plans WHERE id=?", (plan_id,)
        ).fetchone()
        return dict(row) if row else None