#![allow(clippy::expect_used)]
use jugar_probar::brick::{Brick, BrickAssertion, BrickBudget, BrickVerification};
use jugar_probar::brick_house::BrickHouseBuilder;
use std::sync::Arc;
use std::time::Duration;
struct StatusBrick {
message: String,
is_visible: bool,
}
impl StatusBrick {
fn new(message: impl Into<String>) -> Self {
Self {
message: message.into(),
is_visible: true,
}
}
}
impl Brick for StatusBrick {
fn brick_name(&self) -> &'static str {
"StatusBrick"
}
fn assertions(&self) -> &[BrickAssertion] {
&[
BrickAssertion::TextVisible,
BrickAssertion::ContrastRatio(4.5),
]
}
fn budget(&self) -> BrickBudget {
BrickBudget::uniform(50)
}
fn verify(&self) -> BrickVerification {
let mut passed = Vec::new();
let mut failed = Vec::new();
if self.is_visible && !self.message.is_empty() {
passed.push(BrickAssertion::TextVisible);
} else {
failed.push((BrickAssertion::TextVisible, "Text not visible".into()));
}
passed.push(BrickAssertion::ContrastRatio(4.5));
BrickVerification {
passed,
failed,
verification_time: Duration::from_micros(50),
}
}
fn to_html(&self) -> String {
format!(
r#"<div class="status-brick" role="status">{}</div>"#,
self.message
)
}
fn to_css(&self) -> String {
r#".status-brick {
padding: 8px 16px;
background: #1a1a2e;
color: #eaeaea;
border-radius: 4px;
font-size: 14px;
}"#
.into()
}
}
struct WaveformBrick {
samples: Vec<f32>,
is_active: bool,
}
impl WaveformBrick {
fn new(samples: Vec<f32>) -> Self {
Self {
samples,
is_active: true,
}
}
}
static WAVEFORM_ASSERTIONS: [BrickAssertion; 1] = [BrickAssertion::MaxLatencyMs(100)];
impl Brick for WaveformBrick {
fn brick_name(&self) -> &'static str {
"WaveformBrick"
}
fn assertions(&self) -> &[BrickAssertion] {
&WAVEFORM_ASSERTIONS
}
fn budget(&self) -> BrickBudget {
BrickBudget::uniform(100)
}
fn verify(&self) -> BrickVerification {
let mut passed = Vec::new();
let mut failed = Vec::new();
if self.is_active {
passed.push(BrickAssertion::MaxLatencyMs(100));
} else {
failed.push((
BrickAssertion::MaxLatencyMs(100),
"Waveform not active".into(),
));
}
BrickVerification {
passed,
failed,
verification_time: Duration::from_micros(100),
}
}
fn to_html(&self) -> String {
format!(
r#"<canvas class="waveform" width="400" height="100" data-samples="{}"></canvas>"#,
self.samples.len()
)
}
fn to_css(&self) -> String {
r#".waveform {
background: #0f0f23;
border: 1px solid #333;
}"#
.into()
}
}
struct TranscriptionBrick {
text: String,
is_final: bool,
}
impl TranscriptionBrick {
fn new(text: impl Into<String>, is_final: bool) -> Self {
Self {
text: text.into(),
is_final,
}
}
}
impl Brick for TranscriptionBrick {
fn brick_name(&self) -> &'static str {
"TranscriptionBrick"
}
fn assertions(&self) -> &[BrickAssertion] {
&[
BrickAssertion::TextVisible,
BrickAssertion::Focusable, ]
}
fn budget(&self) -> BrickBudget {
BrickBudget::uniform(600)
}
fn verify(&self) -> BrickVerification {
let mut passed = Vec::new();
let failed = Vec::new();
passed.push(BrickAssertion::TextVisible);
passed.push(BrickAssertion::Focusable);
BrickVerification {
passed,
failed,
verification_time: Duration::from_micros(200),
}
}
fn to_html(&self) -> String {
let class = if self.is_final { "final" } else { "interim" };
format!(
r#"<p class="transcription {}" tabindex="0">{}</p>"#,
class, self.text
)
}
fn to_css(&self) -> String {
r#".transcription {
font-size: 18px;
line-height: 1.6;
padding: 16px;
}
.transcription.final { color: #fff; }
.transcription.interim { color: #888; font-style: italic; }"#
.into()
}
}
fn main() {
println!("=== Brick Architecture Demo ===\n");
println!("1. Individual Brick Verification");
println!(" -----------------------------");
let status = StatusBrick::new("Recording...");
let verification = status.verify();
println!(
" StatusBrick: {} (score: {:.0}%)",
if verification.is_valid() {
"VALID"
} else {
"INVALID"
},
verification.score() * 100.0
);
let waveform = WaveformBrick::new(vec![0.1, 0.5, 0.3, 0.8, 0.2]);
let verification = waveform.verify();
println!(
" WaveformBrick: {} (score: {:.0}%)",
if verification.is_valid() {
"VALID"
} else {
"INVALID"
},
verification.score() * 100.0
);
let transcription = TranscriptionBrick::new("Hello, this is a test transcription.", true);
let verification = transcription.verify();
println!(
" TranscriptionBrick: {} (score: {:.0}%)\n",
if verification.is_valid() {
"VALID"
} else {
"INVALID"
},
verification.score() * 100.0
);
println!("2. BrickHouse Composition");
println!(" -----------------------");
let status_brick = Arc::new(StatusBrick::new("Listening..."));
let waveform_brick = Arc::new(WaveformBrick::new(vec![0.2, 0.6, 0.4, 0.9, 0.1]));
let transcription_brick = Arc::new(TranscriptionBrick::new(
"Testing speech recognition...",
false,
));
let mut house = BrickHouseBuilder::new("whisper-app")
.budget_ms(1000) .brick(status_brick, 50) .brick(waveform_brick, 100) .brick(transcription_brick, 600) .build()
.expect("Failed to build brick house");
println!(" House: {}", house.name());
println!(" Total budget: {}ms", house.budget().total_ms);
println!(" Brick count: {}", house.brick_count());
println!(" Remaining budget: {}ms\n", house.remaining_budget_ms());
println!("3. House-wide Verification");
println!(" ------------------------");
let verifications = house.verify_all();
for (name, verification) in &verifications {
println!(
" {}: {} assertions passed, {} failed",
name,
verification.passed.len(),
verification.failed.len()
);
}
println!(" Can render: {}\n", house.can_render());
println!("4. Render with Budget Tracking");
println!(" ----------------------------");
match house.render() {
Ok(html) => {
println!(" Render SUCCESS");
println!(" HTML length: {} chars", html.len());
if let Some(report) = house.last_report() {
println!(" Budget utilization: {:.1}%", report.utilization());
println!(" Total used: {}ms", report.total_used_ms);
println!(" Within budget: {}", report.within_budget());
}
}
Err(e) => {
println!(" Render FAILED: {}", e);
}
}
println!("\n5. Combined CSS Output");
println!(" --------------------");
let css = house.to_css();
println!(" CSS length: {} chars", css.len());
println!(" First 100 chars: {}...", &css[..css.len().min(100)]);
println!("\n=== Demo Complete ===");
}