# HVAC Blueprint Analyzer - Output Generator & GUI Guide **Date**: June 19, 2026 **Component**: Output Generation & User Interface --- ## πŸ“Š OUTPUT GENERATOR OVERVIEW ### Purpose Convert analyzed HVAC data into multiple formats: - CSV files for spreadsheet analysis - PDF reports with visual summaries - JSON for API consumption - HTML reports for web viewing - Excel workbooks with multiple sheets --- ## 🎯 PHASE A: CSV OUTPUT GENERATION ### CSV Output 1: Floor & Units Summary **File**: `hvac_analysis_floors_units.csv` ```csv Floor,Unit_ID,Unit_Type,Quantity,Capacity_BTU,Capacity_kW,Status,Notes 1,AC-A,Ceiling Concealed Ducted,1,36000,10.5,Detected,Located near kitchen 1,AC-B,Wall Mounted,1,24000,7.0,Detected,Bedroom unit 2,AC-C,Ceiling Concealed Ducted,1,36000,10.5,Detected,Master bedroom 2,AC-D,Wall Mounted,2,12000,3.5,Detected,Living areas 3,AC-E,Ceiling Concealed Ducted,1,48000,14.0,Detected,Commercial zone 3,AC-F,Wall Mounted,1,24000,7.0,Detected,Office area ``` **Columns to Include:** - [ ] Floor number (1, 2, 3, B for basement) - [ ] Unit ID/Tag (AC-A, AC-B, etc.) - [ ] Unit Type (Ceiling Concealed Ducted, Wall Mounted, Ductless, etc.) - [ ] Quantity (number of units) - [ ] Capacity in BTU - [ ] Capacity in kW - [ ] Detection Status (Detected, Manual Entry, Inferred) - [ ] Notes/Comments - [ ] Location within floor (optional) - [ ] Equipment Schedule reference (optional) **Implementation**: ```python def export_floors_units_csv(analysis_data, output_path): """ Export floor-by-floor unit breakdown to CSV Args: analysis_data: Dict with floors and units output_path: Path to save CSV Returns: Path to saved CSV file """ import pandas as pd rows = [] for floor in analysis_data['floors']: floor_num = floor['number'] for unit in floor['units']: rows.append({ 'Floor': floor_num, 'Unit_ID': unit['tag'], 'Unit_Type': unit['type'], 'Quantity': unit['quantity'], 'Capacity_BTU': unit.get('capacity_btu', ''), 'Capacity_kW': unit.get('capacity_kw', ''), 'Status': unit.get('detection_status', 'Detected'), 'Notes': unit.get('notes', ''), 'Location': unit.get('location', ''), }) df = pd.DataFrame(rows) df.to_csv(output_path, index=False) return output_path ``` ### CSV Output 2: Equipment Schedule **File**: `hvac_equipment_schedule.csv` ```csv Equipment_ID,Manufacturer,Model,Type,Capacity_BTU,Voltage,Phase,Frequency_Hz,Quantity,Floor,Unit_Tag,Remarks 1,Carrier,25HNE024A03,Ceiling Cassette,24000,208-230,1,60,1,2,AC-B,Installed Jan 2023 2,Daikin,FCAG71B,Ceiling Concealed,36000,208-230,3,60,2,1,AC-A,New equipment 3,LG,ASNQ48LNZA0,Wall Mounted,48000,208-230,1,60,1,3,AC-E,High efficiency model ``` **Columns to Include:** - [ ] Equipment ID (from schedule) - [ ] Manufacturer - [ ] Model number - [ ] Equipment Type - [ ] Capacity (BTU) - [ ] Voltage - [ ] Phase (1 or 3) - [ ] Frequency (Hz) - [ ] Quantity - [ ] Floor number - [ ] Associated Unit Tag (AC-A, AC-B, etc.) - [ ] Remarks/Notes ### CSV Output 3: Reconciliation Report **File**: `hvac_reconciliation_report.csv` ```csv Issue_Type,Severity,Floor,Unit_ID,Detected_in_Plan,Found_in_Schedule,Details,Recommended_Action Missing_Unit,High,2,AC-B,No,Yes,Unit found in schedule but not detected in floor plan,Review floor plan markup Extra_Unit,Medium,1,AC-A,Yes,No,Unit detected in plan but not listed in schedule,Add to equipment schedule Capacity_Mismatch,Medium,3,AC-E,36000,48000,Plan shows 36kBTU but schedule lists 48kBTU,Verify actual installed capacity Floor_Mismatch,High,NULL,AC-C,3,2,Unit AC-C listed on floor 2 but appears in floor 3 plan,Correct schedule or floor plan ``` **Columns to Include:** - [ ] Issue Type (Missing Unit, Extra Unit, Capacity Mismatch, Floor Mismatch, etc.) - [ ] Severity (Low, Medium, High) - [ ] Floor number - [ ] Unit ID - [ ] Detected in floor plan (Yes/No) - [ ] Found in schedule (Yes/No) - [ ] Details/Description - [ ] Recommended Action - [ ] Confidence Score (0-100%) --- ## πŸ–₯️ PHASE B: GUI - USER INTERFACE ### Technology Stack (Recommended) - [ ] **Frontend Framework**: Streamlit (easiest for quick demo) OR React - [ ] **Styling**: Tailwind CSS (if React) OR Streamlit theme - [ ] **Charting**: Plotly or Chart.js (for visualizations) - [ ] **Forms**: Built-in Streamlit components OR React Hook Form ### GUI Features Checklist #### 1. **File Upload Section** ```python # Streamlit example import streamlit as st st.title("🏒 HVAC Blueprint Analyzer") uploaded_file = st.file_uploader("Upload Mechanical Blueprint (PDF)", type="pdf") if uploaded_file: st.info(f"πŸ“„ File: {uploaded_file.name} ({uploaded_file.size / 1024:.2f} KB)") col1, col2 = st.columns(2) with col1: model_choice = st.radio("Choose AI Model:", ["Gemini", "OpenAI"]) with col2: schedule_mode = st.radio("Schedule Mode:", ["Auto-Detect", "Upload Schedule"]) if st.button("πŸš€ Analyze Blueprint"): with st.spinner("Analyzing..."): results = analyze_blueprint(uploaded_file, model_choice, schedule_mode) st.success("Analysis complete!") ``` **Checklist:** - [ ] PDF upload widget - [ ] File validation (size, format) - [ ] Progress indicator during upload - [ ] File preview/info display - [ ] Multiple file upload support (batch processing) - [ ] Drag-and-drop file upload #### 2. **Configuration Section** - [ ] Model selection (Gemini vs OpenAI toggle) - [ ] Schedule mode selection (Auto vs Manual) - [ ] Output format selection (CSV, PDF, JSON) - [ ] Advanced options (OCR threshold, confidence limits) - [ ] Cost calculator (estimate before processing) #### 3. **Analysis Results Display** **Tab 1: Floors & Units Summary** ```python st.header("πŸ“Š Analysis Results") tab1, tab2, tab3, tab4 = st.tabs([ "Floors & Units", "Equipment Schedule", "Reconciliation", "Downloads" ]) with tab1: st.subheader("HVAC Units by Floor") # Interactive table st.dataframe( floors_units_df, use_container_width=True, column_config={ "Floor": st.column_config.TextColumn("Floor"), "Unit_ID": st.column_config.TextColumn("Unit ID", width="medium"), "Unit_Type": st.column_config.TextColumn("Type", width="medium"), "Quantity": st.column_config.NumberColumn("Qty"), "Capacity_BTU": st.column_config.NumberColumn("BTU"), } ) # Summary statistics col1, col2, col3, col4 = st.columns(4) with col1: st.metric("Total Floors", len(analysis_data['floors'])) with col2: st.metric("Total Units", sum([u['quantity'] for f in analysis_data['floors'] for u in f['units']])) with col3: st.metric("Total Capacity", f"{total_btu:,.0f} BTU") with col4: st.metric("Cost (Gemini)", f"${cost:.2f}") ``` **Tab 2: Equipment Schedule Table** - [ ] Sortable table with equipment details - [ ] Filter by floor, manufacturer, type - [ ] Search functionality - [ ] Edit capability (for manual corrections) - [ ] Export to CSV **Tab 3: Reconciliation Report** - [ ] Visual summary of issues (count by severity) - [ ] Detailed issue list - [ ] Severity indicators (color-coded) - [ ] Recommended actions - [ ] Mark issues as resolved **Tab 4: Downloads** - [ ] Download CSV files (Floors & Units, Schedule, Reconciliation) - [ ] Download PDF report - [ ] Download JSON data - [ ] Zip all outputs together #### 4. **Visualization Components** **Floor Plan Overview** ```python import plotly.graph_objects as go fig = go.Figure() # Add floor layers for floor in analysis_data['floors']: fig.add_trace(go.Scatter( x=floor['units_x'], y=floor['units_y'], mode='markers+text', text=floor['units_tags'], marker=dict(size=15, color='blue'), name=f"Floor {floor['number']}" )) st.plotly_chart(fig, use_container_width=True) ``` **Capacity Distribution Chart** - [ ] Stacked bar chart showing capacity by floor - [ ] Unit type distribution pie chart - [ ] Comparison chart (Detected vs Schedule) **Cost Breakdown** - [ ] API cost per model comparison - [ ] Cost per unit analyzed - [ ] Total project cost estimate #### 5. **Schedule Upload Section** (if auto-detect fails) ```python with st.expander("πŸ“‹ Manual Schedule Upload"): schedule_source = st.radio( "How would you like to provide the schedule?", ["Upload CSV", "Upload Excel", "Paste Data", "Use Previous Schedule"] ) if schedule_source == "Upload CSV": schedule_file = st.file_uploader("Upload CSV with schedule", type="csv") if schedule_file: schedule_df = pd.read_csv(schedule_file) st.dataframe(schedule_df) elif schedule_source == "Paste Data": schedule_text = st.text_area("Paste schedule data (CSV format)") if schedule_text: schedule_df = pd.read_csv(StringIO(schedule_text)) st.dataframe(schedule_df) ``` **Checklist:** - [ ] CSV upload - [ ] Excel upload (.xlsx, .xls) - [ ] Copy/paste data - [ ] Data validation - [ ] Preview of uploaded data - [ ] Confirm & save schedule #### 6. **A/B Testing Comparison View** ```python col1, col2 = st.columns(2) with col1: st.subheader("πŸ”΅ Gemini Results") st.write(f"Time: {gemini_time:.2f}s") st.write(f"Cost: ${gemini_cost:.4f}") st.write(f"Units Found: {gemini_units}") st.dataframe(gemini_results) with col2: st.subheader("🟠 OpenAI Results") st.write(f"Time: {openai_time:.2f}s") st.write(f"Cost: ${openai_cost:.4f}") st.write(f"Units Found: {openai_units}") st.dataframe(openai_results) # Comparison metrics st.subheader("πŸ“Š Comparison") comparison_data = { 'Metric': ['Speed (seconds)', 'Cost ($)', 'Units Detected', 'Accuracy (%)'], 'Gemini': [gemini_time, gemini_cost, gemini_units, gemini_accuracy], 'OpenAI': [openai_time, openai_cost, openai_units, openai_accuracy] } comparison_df = pd.DataFrame(comparison_data) st.dataframe(comparison_df, use_container_width=True) ``` --- ## πŸ“ PHASE C: PDF REPORT GENERATION ### Report Sections - [ ] **Cover Page** - [ ] Project name - [ ] Analysis date - [ ] Number of blueprints analyzed - [ ] Model used (Gemini/OpenAI) - [ ] **Executive Summary** - [ ] Total units found - [ ] Total capacity - [ ] Number of floors - [ ] Key findings - [ ] **Floor-by-Floor Summary** - [ ] Table of units per floor - [ ] Visual breakdown - [ ] **Equipment Schedule** - [ ] Full equipment table - [ ] Specifications - [ ] **Reconciliation Issues** - [ ] List of discrepancies - [ ] Severity indicators - [ ] Recommended actions - [ ] **Appendix** - [ ] Analysis parameters - [ ] Processing time - [ ] Cost breakdown ### PDF Generation Library ```python from reportlab.lib.pagesizes import letter, A4 from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph import pandas as pd def generate_pdf_report(analysis_data, output_path): """Generate comprehensive PDF report""" from reportlab.lib import colors from reportlab.lib.units import inch doc = SimpleDocTemplate(output_path, pagesize=letter) elements = [] # Title title = Paragraph( "HVAC Blueprint Analysis Report", style=ParagraphStyle(alignment=1) # Center aligned ) elements.append(title) elements.append(Spacer(1, 0.5*inch)) # Summary table summary_data = [ ['Total Floors', str(len(analysis_data['floors']))], ['Total Units', str(sum_units(analysis_data))], ['Total Capacity', f"{total_btu(analysis_data):,} BTU"], ] summary_table = Table(summary_data) summary_table.setStyle(TableStyle([ ('BACKGROUND', (0, 0), (-1, 0), colors.grey), ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke), ('ALIGN', (0, 0), (-1, -1), 'CENTER'), ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'), ('FONTSIZE', (0, 0), (-1, 0), 14), ('BOTTOMPADDING', (0, 0), (-1, 0), 12), ('GRID', (0, 0), (-1, -1), 1, colors.black) ])) elements.append(summary_table) # Build PDF doc.build(elements) return output_path ``` **Checklist:** - [ ] ReportLab setup - [ ] Cover page generation - [ ] Table formatting - [ ] Chart embedding - [ ] Multi-page support - [ ] Table of contents - [ ] Page numbering --- ## πŸ“Š PHASE D: JSON OUTPUT ### JSON Structure ```json { "metadata": { "analysis_date": "2026-06-19T10:30:00Z", "blueprint_file": "353_E_86th_St.pdf", "model_used": "gemini-2.5-pro", "processing_time_seconds": 25.3, "cost_usd": 0.08 }, "summary": { "total_floors": 3, "total_units": 8, "total_capacity_btu": 256000, "total_capacity_kw": 75.0 }, "floors": [ { "floor_number": 1, "floor_type": "residential", "units": [ { "id": "AC-A", "type": "Ceiling Concealed Ducted", "quantity": 1, "capacity_btu": 36000, "capacity_kw": 10.5, "manufacturer": "Carrier", "model": "25HNE024A03", "location": "Living area", "detection_confidence": 0.95 } ] } ], "equipment_schedule": [ { "id": 1, "manufacturer": "Carrier", "model": "25HNE024A03", "type": "Ceiling Cassette", "capacity_btu": 24000, "voltage": "208-230V", "phase": 1, "frequency_hz": 60, "quantity": 1, "floor": 2, "unit_tag": "AC-B" } ], "reconciliation": { "issues_found": 2, "high_severity": 0, "medium_severity": 2, "low_severity": 0, "issues": [ { "type": "capacity_mismatch", "floor": 3, "unit_id": "AC-E", "plan_capacity": 36000, "schedule_capacity": 48000, "severity": "medium", "recommendation": "Verify actual installed capacity" } ] } } ``` **Checklist:** - [ ] Metadata section - [ ] Summary statistics - [ ] Detailed floor data - [ ] Equipment schedule - [ ] Reconciliation issues - [ ] Confidence scores - [ ] Timestamps --- ## πŸ–₯️ PHASE E: GUI IMPLEMENTATION OPTIONS ### Option 1: Streamlit (Recommended for Quick Demo) **Pros:** - Fastest to build - No frontend experience needed - Built-in data visualization - Free hosting on Streamlit Cloud **Cons:** - Limited customization - Not suitable for production UIs - Slower for large datasets **Setup:** ```bash pip install streamlit plotly pandas openpyxl streamlit run app.py ``` ### Option 2: React + FastAPI **Pros:** - Full customization - Production-quality UI - Better performance - Responsive design **Cons:** - Takes longer to build - Requires frontend/backend skills - More complex deployment **Setup:** ```bash # Backend pip install fastapi uvicorn pydantic # Frontend npm create vite@latest hvac-ui -- --template react npm install axios react-query ``` ### Option 3: Simple HTML + jQuery **Pros:** - Minimal dependencies - Fast to build - Easy to deploy - No build step needed **Cons:** - Limited functionality - Not modern - Harder to maintain --- ## πŸ“‹ CSV EXPORT IMPLEMENTATION CHECKLIST ### Code Structure ```python # outputs/csv_exporter.py import pandas as pd from typing import Dict, List from pathlib import Path class HVACCSVExporter: """Export HVAC analysis data to CSV formats""" def __init__(self, output_dir: str = "./outputs"): self.output_dir = Path(output_dir) self.output_dir.mkdir(exist_ok=True) def export_all(self, analysis_data: Dict) -> Dict[str, Path]: """Export all CSV files and return paths""" return { 'floors_units': self.export_floors_units(analysis_data), 'equipment_schedule': self.export_equipment_schedule(analysis_data), 'reconciliation': self.export_reconciliation(analysis_data), 'summary': self.export_summary(analysis_data), } def export_floors_units(self, data: Dict) -> Path: """Export floor and unit breakdown""" rows = [] for floor in data['floors']: for unit in floor['units']: rows.append({ 'Floor': floor['number'], 'Unit_ID': unit['tag'], 'Unit_Type': unit['type'], 'Quantity': unit['quantity'], 'Capacity_BTU': unit.get('capacity_btu'), 'Capacity_kW': unit.get('capacity_kw'), 'Status': unit.get('detection_status', 'Detected'), 'Location': unit.get('location', ''), 'Notes': unit.get('notes', ''), }) df = pd.DataFrame(rows) path = self.output_dir / "hvac_floors_units.csv" df.to_csv(path, index=False) return path def export_equipment_schedule(self, data: Dict) -> Path: """Export equipment schedule""" df = pd.DataFrame(data.get('equipment_schedule', [])) path = self.output_dir / "hvac_equipment_schedule.csv" df.to_csv(path, index=False) return path def export_reconciliation(self, data: Dict) -> Path: """Export reconciliation report""" issues = data.get('reconciliation', {}).get('issues', []) df = pd.DataFrame(issues) path = self.output_dir / "hvac_reconciliation.csv" df.to_csv(path, index=False) return path def export_summary(self, data: Dict) -> Path: """Export summary statistics""" summary = data.get('summary', {}) summary_df = pd.DataFrame([summary]) path = self.output_dir / "hvac_summary.csv" summary_df.to_csv(path, index=False) return path # Usage exporter = HVACCSVExporter() csv_files = exporter.export_all(analysis_data) print(f"Exported to: {csv_files}") ``` **Checklist:** - [ ] CSV exporter class created - [ ] floors_units.csv export working - [ ] equipment_schedule.csv export working - [ ] reconciliation.csv export working - [ ] summary.csv export working - [ ] Error handling for missing data - [ ] File encoding (UTF-8) - [ ] Column ordering consistent --- ## 🎨 GUI MOCKUP LAYOUT ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ 🏒 HVAC Blueprint Analyzer β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ πŸ“€ Upload Blueprint β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Drag & drop PDF here or click to browse β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ βš™οΈ Configuration β”‚ β”‚ Model: [Gemini ●] [OpenAI β—‹] β”‚ β”‚ Schedule: [Auto-Detect ●] [Upload β—‹] β”‚ β”‚ Output Format: [CSV βœ“] [PDF βœ“] [JSON βœ“] β”‚ β”‚ β”‚ β”‚ [πŸš€ Analyze Blueprint] [πŸ’Ύ Save Config]β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ πŸ“Š Results (Tabs) β”‚ β”‚ [Floors & Units] [Equipment] [Reconciliation] [Downloads] β”‚ β”‚ β”‚ β”‚ β”Œβ”€ Floors & Units ──────────────────────────┐ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Summary Statistics: β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ β”‚ Floors β”‚ Units β”‚ Capacity β”‚ Cost β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ 3 β”‚ 8 β”‚256kBTU β”‚$0.08 β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Detailed Table: β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚ β”‚ β”‚ β”‚ β”‚Floorβ”‚Unit IDβ”‚Type β”‚Qtyβ”‚BTU β”‚β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”‚ β”‚ β”‚ β”‚ β”‚ 1 β”‚ AC-A β”‚Ceiling Duct β”‚ 1 β”‚36000 β”‚β”‚ β”‚ β”‚ β”‚ β”‚ 1 β”‚ AC-B β”‚Wall Mount β”‚ 1 β”‚24000 β”‚β”‚ β”‚ β”‚ β”‚ β”‚ 2 β”‚ AC-C β”‚Ceiling Duct β”‚ 1 β”‚36000 β”‚β”‚ β”‚ β”‚ β”‚ β”‚ 2 β”‚ AC-D β”‚Wall Mount β”‚ 2 β”‚24000 β”‚β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ [πŸ“Š Chart View] [πŸ“‹ Table View] [πŸ”„ Refresh]β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”Œβ”€ Downloads ────────────────────────────────┐ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Available Outputs: β”‚ β”‚ β”‚ β”‚ β˜‘ Floors & Units (CSV) [⬇ Download] β”‚ β”‚ β”‚ β”‚ β˜‘ Equipment Schedule (CSV) [⬇ Download] β”‚ β”‚ β”‚ β”‚ β˜‘ Reconciliation (CSV) [⬇ Download] β”‚ β”‚ β”‚ β”‚ β˜‘ Analysis Report (PDF) [⬇ Download] β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ [πŸ“¦ Download All as ZIP] β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- ## πŸš€ IMPLEMENTATION ORDER ### Week 1: CSV Output & Basic GUI 1. [ ] Create CSV exporter (all 3 CSV types) 2. [ ] Test CSV output with sample data 3. [ ] Build basic Streamlit app with file upload 4. [ ] Add results display table ### Week 2: Full GUI & Visualizations 5. [ ] Add charts and visualizations 6. [ ] Implement tabs (Floors, Schedule, Reconciliation) 7. [ ] Add schedule upload functionality 8. [ ] Create downloads section ### Week 3: Polish & Deployment 9. [ ] PDF report generation 10. [ ] A/B testing comparison view 11. [ ] Error handling and validation 12. [ ] Deploy to Streamlit Cloud or cloud provider --- ## πŸ“‹ SUCCESS CRITERIA **CSV Output:** - βœ… All three CSVs generated successfully - βœ… Data is accurate and complete - βœ… Columns are properly labeled - βœ… No missing values (or clearly marked) **GUI:** - βœ… File upload works smoothly - βœ… Results display in <2 seconds - βœ… All tabs functional - βœ… Download buttons work - βœ… Mobile-responsive (if web) **Integration:** - βœ… FastAPI endpoint returns CSVs - βœ… GUI calls API correctly - βœ… Error messages are clear - βœ… No hardcoded paths --- ## πŸ”— INTEGRATION WITH FASTAPI ```python # main.py - FastAPI app with CSV export from fastapi import FastAPI, UploadFile, File from fastapi.responses import FileResponse, StreamingResponse from outputs.csv_exporter import HVACCSVExporter import zipfile from io import BytesIO app = FastAPI() exporter = HVACCSVExporter() @app.post("/analyze") async def analyze_blueprint(file: UploadFile = File(...)): """Analyze blueprint and return results""" analysis_data = await process_blueprint(file) # Generate CSVs csv_files = exporter.export_all(analysis_data) return { "status": "success", "analysis": analysis_data, "csv_files": {name: str(path) for name, path in csv_files.items()} } @app.get("/download/csv/{csv_type}") async def download_csv(csv_type: str, task_id: str): """Download specific CSV file""" file_path = f"./outputs/{task_id}_{csv_type}.csv" return FileResponse(file_path, filename=f"hvac_{csv_type}.csv") @app.get("/download/all/{task_id}") async def download_all(task_id: str): """Download all outputs as ZIP""" zip_buffer = BytesIO() with zipfile.ZipFile(zip_buffer, 'w') as zf: zf.write(f"./outputs/{task_id}_floors_units.csv") zf.write(f"./outputs/{task_id}_equipment_schedule.csv") zf.write(f"./outputs/{task_id}_reconciliation.csv") zf.write(f"./outputs/{task_id}_report.pdf") zip_buffer.seek(0) return StreamingResponse( iter([zip_buffer.getvalue()]), media_type="application/zip", headers={"Content-Disposition": "attachment; filename=hvac_analysis.zip"} ) ``` **Checklist:** - [ ] /analyze endpoint returns CSV file paths - [ ] /download/csv/{type} serves files - [ ] /download/all/{task_id} creates ZIP - [ ] Content-Type headers correct - [ ] Filenames are descriptive - [ ] Error handling for missing files