Algorithm-TimelinePacking

 view release on metacpan or  search on metacpan

examples/conference.html  view on Meta::CPAN

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>TinfoilConf 2024 - Timeline Demo</title>
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <style>
        * { box-sizing: border-box; }
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            margin: 0; padding: 20px; background: #f8f9fa; color: #333;
        }
        h1 { margin-top: 0; color: #2c3e50; }
        .subtitle { color: #666; margin-bottom: 20px; }
        .container { max-width: 1200px; margin: 0 auto; }
        #chart {
            background: white; border-radius: 8px; padding: 20px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1); overflow-x: auto;
        }
        svg { overflow: visible; }
        .talk rect { cursor: pointer; transition: opacity 0.2s; }
        .talk:hover rect { opacity: 0.85; }
        .talk text { font-size: 11px; fill: white; pointer-events: none; }
        .room-label { font-size: 13px; font-weight: bold; fill: #555; }
        .time-label { font-size: 12px; fill: #666; }
        .legend { display: flex; gap: 20px; margin-top: 20px; flex-wrap: wrap; }
        .legend-item { display: flex; align-items: center; gap: 6px; font-size: 13px; }
        .legend-color { width: 16px; height: 16px; border-radius: 3px; }
        .tooltip {
            position: absolute; background: rgba(0,0,0,0.9); color: #fff;
            padding: 12px; border-radius: 6px; font-size: 13px;
            pointer-events: none; z-index: 1000; max-width: 280px; line-height: 1.4;
            display: none;
        }
        .tooltip-title { font-weight: bold; font-size: 14px; margin-bottom: 6px; }
        .tooltip-time { color: #aaa; margin-bottom: 4px; }
        .stats { margin-top: 15px; font-size: 13px; color: #666; }
    </style>
</head>
<body>
    <div class="container">
        <h1>TinfoilConf 2024</h1>
        <p class="subtitle">The premier conference for developers who do their own research. Wake up, sheeple! Hover over sessions for details.</p>
        <div id="chart"></div>
        <div class="legend" id="legend"></div>
        <div class="stats" id="stats"></div>
    </div>
    <div class="tooltip" id="tooltip">
        <div class="tooltip-title" id="tooltip-title"></div>
        <div class="tooltip-time" id="tooltip-time"></div>
        <div id="tooltip-speaker"></div>
        <div id="tooltip-track"></div>
    </div>

<script>
// =============================================================================
// INPUT: Raw conference data (sent to server)
// Each talk: [start_minutes, end_minutes, title, speaker, track]
// =============================================================================
var INPUT = [
    [540, 570, "Registration & Colloidal Silver Reception", "", "break"],
    [570, 615, "Opening Keynote: Why Facts Have a Liberal Bias", "George Sorostein", "keynote"],
    [615, 660, "Flat Earth Arrays: Why Your Data Won't Round", "Kyrie Irvington", "beginner"],
    [615, 660, "5G Mind Control: A Networking Deep Dive", "Karen McWiFi", "advanced"],
    [615, 705, "Workshop: Space Lasers and Serverless Architecture", "Margarine Trailer Queen", "workshop"],
    [660, 705, "Birds Aren't Real: An Introduction to Mocking", "Peter McAfee", "beginner"],
    [660, 705, "The Deep State Design Pattern", "Q. Anon Watkins", "advanced"],
    [705, 750, "Vaccine Microchips: A Hardware Deep Dive", "Bill Gatekeeping", "advanced"],
    [705, 750, "Ivermectin-Driven Development", "Dr. Demon Sperm", "beginner"],
    [705, 795, "Workshop: Chemtrails as Code Comments", "Alex Jonestein", "workshop"],
    [750, 810, "Lunch (Raw Milk & Ivermectin Bar)", "", "break"],
    [810, 855, "Election Security: Why Math is a Hoax", "Sidney Kraken", "advanced"],
    [810, 855, "The Great Reset: Migrating from COBOL", "Klaus Schwabernetes", "beginner"],
    [810, 900, "Workshop: Crisis Actors in Your Test Suite", "Sandy Hookwinked", "workshop"],
    [855, 900, "JFK Jr Returns: Zombie Process Management", "Dallas Grassy Knoll", "advanced"],
    [855, 900, "Plandemic: Error Handling for Lab Leaks", "Dr. Judy Mikovits-Clone", "beginner"],
    [900, 930, "Lightning Talks: Things I Learned on YouTube", "Various Patriots", "community"],
    [930, 975, "Closing Keynote: Doing Your Own Research", "Tucker Carlsplaining", "keynote"],
    [975, 1080, "Conference Social & Adrenochrome Tasting", "", "break"]
];

// =============================================================================
// OUTPUT: Pre-computed by Algorithm::TimelinePacking (returned from server)
// Times normalized to start at 0, arranged into non-overlapping lines
// =============================================================================
var EARLIEST = 540;  // Original start time (9:00 AM)
var LATEST = 540;    // Duration in minutes (until 6:00 PM)

var lines = [
    [[0,30,"Registration & Colloidal Silver Reception","","break"],[30,75,"Opening Keynote: Why Facts Have a Liberal Bias","George Sorostein","keynote"],[75,120,"Flat Earth Arrays: Why Your Data Won't Round","Kyrie Irvington","beginner"],[120,165,"Bi...
    [[75,120,"5G Mind Control: A Networking Deep Dive","Karen McWiFi","advanced"],[120,165,"The Deep State Design Pattern","Q. Anon Watkins","advanced"],[165,210,"Ivermectin-Driven Development","Dr. Demon Sperm","beginner"],[270,315,"Election Securit...
    [[75,165,"Workshop: Space Lasers and Serverless Architecture","Margarine Trailer Queen","workshop"],[165,255,"Workshop: Chemtrails as Code Comments","Alex Jonestein","workshop"],[270,315,"The Great Reset: Migrating from COBOL","Klaus Schwabernete...
];

// =============================================================================
// RENDERING: Display the pre-computed layout using D3.js
// =============================================================================
var COLORS = { keynote: '#e74c3c', beginner: '#3498db', advanced: '#9b59b6', workshop: '#27ae60', community: '#f39c12', break: '#95a5a6' };
var LABELS = { keynote: 'Keynote', beginner: 'Beginner Track', advanced: 'Advanced Track', workshop: 'Workshop', community: 'Community', break: 'Break' };

var LINE_HEIGHT = 40;
var BAR_HEIGHT = 30;
var MARGIN_LEFT = 80;
var SCALE = 900 / LATEST;

examples/conference.html  view on Meta::CPAN

for (var h = 9; h <= 19; h++) {
    svg.append("text")
        .attr("class", "time-label")
        .attr("x", MARGIN_LEFT + (h - 9) * 60 * SCALE)
        .attr("y", 15)
        .text(h + ":00");
}

// Rooms
lines.forEach(function(line, idx) {
    var y = 30 + idx * LINE_HEIGHT;

    svg.append("text")
        .attr("class", "room-label")
        .attr("x", 0)
        .attr("y", y + 20)
        .text("Room " + (idx + 1));

    var talks = svg.selectAll(".talk-" + idx)
        .data(line)
        .enter()
        .append("g")
        .attr("class", "talk");

    talks.append("rect")
        .attr("x", function(d) { return MARGIN_LEFT + d[0] * SCALE; })
        .attr("y", y + 2)
        .attr("width", function(d) { return Math.max(30, (d[1] - d[0]) * SCALE - 3); })
        .attr("height", BAR_HEIGHT)
        .attr("rx", 4)
        .attr("fill", function(d) { return COLORS[d[4]] || '#666'; });

    talks.append("text")
        .attr("x", function(d) { return MARGIN_LEFT + d[0] * SCALE + 6; })
        .attr("y", y + 22)
        .text(function(d) {
            var w = Math.max(30, (d[1] - d[0]) * SCALE);
            var maxChars = Math.floor(w / 7);
            return d[2].length > maxChars ? d[2].substring(0, maxChars - 1) + '...' : d[2];
        });

    talks.on("mouseover", function(event, d) {
            d3.select("#tooltip-title").text(d[2]);
            d3.select("#tooltip-time").text(fmt(d[0] + EARLIEST) + ' - ' + fmt(d[1] + EARLIEST));
            d3.select("#tooltip-speaker").text(d[3] ? 'Speaker: ' + d[3] : '');
            d3.select("#tooltip-track").text('Track: ' + LABELS[d[4]]);
            tooltip.style("display", "block")
                .style("left", (event.pageX + 10) + "px")
                .style("top", (event.pageY - 10) + "px");
        })
        .on("mousemove", function(event) {
            tooltip.style("left", (event.pageX + 10) + "px")
                .style("top", (event.pageY - 10) + "px");
        })
        .on("mouseout", function() {
            tooltip.style("display", "none");
        });
});

// Legend
var legend = d3.select("#legend");
Object.keys(COLORS).forEach(function(track) {
    var item = legend.append("div").attr("class", "legend-item");
    item.append("div").attr("class", "legend-color").style("background", COLORS[track]);
    item.append("span").text(LABELS[track]);
});

// Stats
d3.select("#stats").text(INPUT.length + ' sessions arranged in ' + lines.length + ' rooms | Conference runs ' + fmt(EARLIEST) + ' - ' + fmt(EARLIEST + LATEST));
</script>
</body>
</html>



( run in 1.933 second using v1.01-cache-2.11-cpan-acebb50784d )