webpage_quality_analyzer 1.0.2

High-performance webpage quality analyzer with 115 comprehensive metrics - Rust library with WASM, C++, and Python bindings
Documentation
//! # Phase 3: Threshold Customization Example
//!
//! This example demonstrates how to customize metric thresholds to tune scoring
//! behavior for specific content types and quality expectations.
//!
//! ## What are Thresholds?
//!
//! Thresholds define the scoring boundaries for each metric using 4 values:
//! - **min**: Below this, score is 0
//! - **optimal_min**: Start of 100% score range
//! - **optimal_max**: End of 100% score range
//! - **max**: Above this, no additional score improvement
//!
//! ## Use Cases
//!
//! - **Short-form content**: Lower thresholds for word count, paragraph count
//! - **Technical documentation**: Higher thresholds for code examples, internal links
//! - **News articles**: Stricter requirements for timeliness, citation quality
//! - **E-commerce**: Product-specific thresholds (images, descriptions, reviews)

use webpage_quality_analyzer::{async_runtime::DefaultRuntime, Analyzer};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Phase 3: Threshold Customization Demo ===\n");

    // Example 1: Blog post with default thresholds
    println!("1️⃣  Blog Post Analysis (Default Thresholds)");
    println!("   Using built-in blog profile with standard thresholds");

    let blog_html = r#"
    <!DOCTYPE html>
    <html>
    <head><title>10 Tips for Better Code Reviews</title></head>
    <body>
        <article>
            <h1>10 Tips for Better Code Reviews</h1>
            <p>Code reviews are essential for maintaining code quality. Here are 10 practical tips...</p>
            <h2>1. Review Small Changes</h2>
            <p>Breaking changes into smaller pieces makes reviews more effective and less time-consuming.</p>
            <h2>2. Focus on the Important Stuff</h2>
            <p>Don't nitpick style issues - use automated tools for that. Focus on logic and design.</p>
            <h2>3. Be Constructive</h2>
            <p>Frame feedback positively and explain the "why" behind your suggestions.</p>
        </article>
    </body>
    </html>
    "#;

    let analyzer_default: Analyzer = Analyzer::builder().with_profile_name("blog")?.build()?;

    let report_default = analyzer_default
        .run("https://example.com/blog/code-reviews", Some(blog_html))
        .await?;

    println!("   Score: {:.2}", report_default.score);
    println!(
        "   Word count: {}",
        report_default.metrics.html_analysis.content.word_count
    );
    println!("   Verdict: {:?}\n", report_default.verdict);

    // Example 2: Same content with custom thresholds for short-form blog
    println!("2️⃣  Blog Post Analysis (Custom Thresholds for Short-Form)");
    println!("   Lowering word count and paragraph thresholds for quick reads");

    let analyzer_custom: Analyzer = Analyzer::builder()
        .with_profile_name("blog")?
        // Lower word count requirements for short-form content
        .set_metric_threshold(
            "word_count",
            50.0,   // min: At least 50 words
            100.0,  // optimal_min: 100 words is good
            500.0,  // optimal_max: 500 words is ideal
            2000.0, // max: Beyond 2000 words, no score boost
        )?
        // Adjust paragraph expectations
        .set_simple_threshold(
            "paragraph_count",
            2.0,  // min: At least 2 paragraphs
            5.0,  // optimal: 5 paragraphs is ideal
            20.0, // max: 20 paragraphs
        )?
        .build()?;

    let report_custom = analyzer_custom
        .run("https://example.com/blog/code-reviews", Some(blog_html))
        .await?;

    println!("   Score: {:.2}", report_custom.score);
    println!(
        "   Word count: {}",
        report_custom.metrics.html_analysis.content.word_count
    );
    println!("   Verdict: {:?}", report_custom.verdict);
    println!(
        "   Score improvement: {:.2} points\n",
        report_custom.score - report_default.score
    );

    // Example 3: Technical documentation with strict requirements
    println!("3️⃣  Technical Documentation (High Standards)");
    println!("   Raising thresholds for comprehensive technical content");

    let tech_doc_html = r#"
    <!DOCTYPE html>
    <html>
    <head><title>API Authentication Guide</title></head>
    <body>
        <article>
            <h1>API Authentication Guide</h1>
            <p>This guide explains how to authenticate requests to our API using OAuth 2.0.</p>
            <h2>Prerequisites</h2>
            <p>Before you begin, ensure you have:</p>
            <ul>
                <li>A valid API key from the developer portal</li>
                <li>Understanding of OAuth 2.0 flow</li>
            </ul>
            <h2>Step 1: Register Your Application</h2>
            <p>Navigate to the developer portal and register your application...</p>
            <pre><code>
            curl -X POST https://api.example.com/oauth/token \
              -d "grant_type=client_credentials" \
              -d "client_id=YOUR_CLIENT_ID"
            </code></pre>
        </article>
    </body>
    </html>
    "#;

    let analyzer_technical: Analyzer = Analyzer::builder()
        .with_profile_name("content_article")?
        .set_thresholds(vec![
            // Comprehensive content expected
            ("word_count", 300.0, 800.0, 2000.0, 5000.0),
            // Many structured sections
            ("paragraph_count", 5.0, 10.0, 25.0, 50.0),
            // Detailed headings required
            ("heading_count", 3.0, 5.0, 10.0, 20.0),
            // Code examples or visual aids
            ("image_count", 1.0, 3.0, 8.0, 15.0),
        ])?
        .build()?;

    let report_technical = analyzer_technical
        .run("https://docs.example.com/api/auth", Some(tech_doc_html))
        .await?;

    println!("   Score: {:.2}", report_technical.score);
    println!(
        "   Word count: {}",
        report_technical.metrics.html_analysis.content.word_count
    );
    println!(
        "   Heading count: {}",
        report_technical
            .metrics
            .html_analysis
            .structure
            .headings_count
    );
    println!("   Verdict: {:?}\n", report_technical.verdict);

    // Example 4: Product page with e-commerce expectations
    println!("4️⃣  Product Page (E-commerce Optimized)");
    println!("   Emphasizing images, structure, and concise descriptions");

    let product_html = r#"
    <!DOCTYPE html>
    <html>
    <head><title>Wireless Bluetooth Headphones - Premium Sound</title></head>
    <body>
        <div class="product">
            <h1>Wireless Bluetooth Headphones</h1>
            <img src="headphones-main.jpg" alt="Black wireless headphones">
            <img src="headphones-side.jpg" alt="Side view">
            <img src="headphones-case.jpg" alt="Carrying case">
            
            <p>Experience premium audio quality with our latest wireless headphones. 
            Featuring active noise cancellation, 30-hour battery life, and premium comfort.</p>
            
            <h2>Key Features</h2>
            <ul>
                <li>Active noise cancellation</li>
                <li>30-hour battery life</li>
                <li>Premium leather cushions</li>
                <li>Bluetooth 5.0</li>
            </ul>
            
            <h2>What's in the Box</h2>
            <ul>
                <li>Headphones</li>
                <li>Carrying case</li>
                <li>USB-C charging cable</li>
            </ul>
        </div>
    </body>
    </html>
    "#;

    let analyzer_product: Analyzer = Analyzer::builder()
        .with_profile_name("ecommerce")?
        // Product pages are concise
        .set_metric_threshold("word_count", 50.0, 100.0, 300.0, 800.0)?
        // But need many images
        .set_metric_threshold("image_count", 2.0, 3.0, 8.0, 15.0)?
        // Structured with lists
        .set_metric_threshold("list_item_count", 3.0, 5.0, 15.0, 30.0)?
        .build()?;

    let report_product = analyzer_product
        .run(
            "https://shop.example.com/products/headphones",
            Some(product_html),
        )
        .await?;

    println!("   Score: {:.2}", report_product.score);
    println!(
        "   Word count: {}",
        report_product.metrics.html_analysis.content.word_count
    );
    println!(
        "   Image count: {}",
        report_product.metrics.html_analysis.media.images_count
    );
    println!(
        "   List items: {}",
        report_product
            .metrics
            .html_analysis
            .structure
            .headings_count
    );
    println!("   Verdict: {:?}\n", report_product.verdict);

    // Example 5: Validation - What happens with invalid thresholds?
    println!("5️⃣  Validation Example");
    println!("   Attempting invalid threshold configuration...");

    let result = Analyzer::<DefaultRuntime>::builder()
        .with_profile_name("blog")?
        // ERROR: min > optimal_min
        .set_metric_threshold("word_count", 500.0, 100.0, 800.0, 2000.0);

    match result {
        Ok(_) => println!("   ❌ Should have failed!"),
        Err(e) => println!("   ✅ Correctly rejected: {}\n", e),
    }

    // Summary
    println!("=== Summary ===");
    println!("✅ Threshold customization allows fine-tuning scoring for:");
    println!("   • Different content types (blog, docs, product pages)");
    println!("   • Content length expectations (short-form vs long-form)");
    println!("   • Quality standards (strict vs lenient)");
    println!("   • Domain-specific requirements");
    println!("\n✅ Validation ensures:");
    println!("   • min < optimal_min ≤ optimal_max < max");
    println!("   • All values finite and non-negative");
    println!("   • Clear error messages for configuration mistakes");

    Ok(())
}