selfware 0.6.1

Your personal AI workshop — software you own, software that lasts
//! L5: Visual Mockup to TUI Layout (Extreme)
//!
//! Input: Hand-drawn or ASCII mockup of a TUI layout.
//! Tasks: Generate ratatui Rust code, identify widget types, specify constraints.
//! Scoring: Widget type identification, layout constraint accuracy, code compilability.
//! Pass threshold: 40% structural accuracy.

use async_trait::async_trait;
use std::path::PathBuf;

use crate::vlm_bench::scoring::{self, LevelScore, Rating};
use crate::vlm_bench::{BenchScenario, Difficulty, ExpectedAnswer, VlmBenchLevel};

const PASS_THRESHOLD: f64 = 0.40;

/// Level 5: Visual Mockup to TUI Layout.
pub struct L5Layout {
    fixtures_dir: PathBuf,
}

impl Default for L5Layout {
    fn default() -> Self {
        Self::new()
    }
}

impl L5Layout {
    pub fn new() -> Self {
        Self {
            fixtures_dir: PathBuf::from("vlm_fixtures/l5_layout"),
        }
    }
}

#[async_trait]
impl VlmBenchLevel for L5Layout {
    fn name(&self) -> &str {
        "L5 Layout"
    }

    fn difficulty(&self) -> Difficulty {
        Difficulty::Extreme
    }

    fn description(&self) -> &str {
        "Visual mockup to code translation: identify widget types from ASCII/visual mockups, \
         generate ratatui layout code, specify correct constraint percentages."
    }

    fn scenarios(&self) -> Vec<BenchScenario> {
        vec![
            BenchScenario {
                id: "l5_simple_split".into(),
                description: "Translate a simple horizontal split layout to ratatui code".into(),
                image_path: self.fixtures_dir.join("simple_split.png"),
                prompt: "This mockup shows a terminal UI with a horizontal split layout. \
                         Identify the widget types and generate the ratatui layout code. \
                         Respond with JSON: {\"widgets\": [{\"type\": \"<widget type>\", \
                         \"position\": \"<left|right|top|bottom>\", \
                         \"constraint\": \"<Percentage(N) or Min(N)>\"}], \
                         \"layout_direction\": \"<Horizontal|Vertical>\", \
                         \"code_snippet\": \"<ratatui layout code>\"}"
                    .into(),
                expected: ExpectedAnswer::Keywords(vec![
                    "layout".into(),
                    "horizontal".into(),
                    "constraint".into(),
                    "percentage".into(),
                ]),
            },
            BenchScenario {
                id: "l5_dashboard_grid".into(),
                description: "Translate a grid-based dashboard mockup to code".into(),
                image_path: self.fixtures_dir.join("dashboard_grid.png"),
                prompt: "This mockup shows a dashboard with a grid layout: \
                         header bar at top, sidebar on left, main content area, \
                         and status bar at bottom. Describe the layout hierarchy \
                         and widget types. Respond with JSON: \
                         {\"layout_tree\": {\"direction\": \"Vertical\", \
                         \"children\": [...]}, \
                         \"widget_types\": [\"<type>\", ...]}"
                    .into(),
                expected: ExpectedAnswer::Keywords(vec![
                    "vertical".into(),
                    "horizontal".into(),
                    "header".into(),
                    "sidebar".into(),
                ]),
            },
            BenchScenario {
                id: "l5_complex_nested".into(),
                description: "Translate a complex nested layout with multiple widget types".into(),
                image_path: self.fixtures_dir.join("complex_nested.png"),
                prompt: "This mockup shows a complex TUI with nested layouts: \
                         tab bar, split panes with different widget types (list, chart, text), \
                         and a floating popup. Describe the full layout structure and \
                         identify all widget types. Respond with JSON: \
                         {\"widgets\": [{\"type\": \"<type>\", \"name\": \"<name>\"}], \
                         \"nesting_depth\": <N>, \"has_popup\": true/false, \
                         \"code_outline\": \"<pseudocode or ratatui code>\"}"
                    .into(),
                expected: ExpectedAnswer::Keywords(vec![
                    "tab".into(),
                    "list".into(),
                    "chart".into(),
                    "popup".into(),
                    "nested".into(),
                ]),
            },
        ]
    }

    fn evaluate(&self, scenario: &BenchScenario, response: &str) -> LevelScore {
        crate::vlm_bench::score_response(scenario, response, PASS_THRESHOLD)
    }
}

#[cfg(test)]
#[path = "../../../tests/unit/vlm_bench/levels/l5_layout/l5_layout_test.rs"]
mod tests;