Where ideas percolate and thoughts brew

The Right Decision Myth

About This Sketch

Visualizing the right decision myth Left: Multiple decision paths being analyzed endlessly (stuck at crossroads) Right: One path chosen with full commitment showing growth/progress Shows contrast between decision paralysis vs. committed execution

This sketch accompanies the blog post "The Right Decision Myth" and visualizes its core concepts through generative art.

Algorithm

Visualizing the right decision myth Left: Multiple decision paths being analyzed endlessly (stuck at crossroads) Right: One path chosen with full commitment showing growth/progress Shows contrast between decision paralysis vs. committed execution This sketch was originally created as a visual companion to the blog post "The Right Decision Myth" and explores its themes through generative art.

Pseudocode

SETUP:
  Initialize canvas (400x300)
  Set up drawing parameters

DRAW (every frame):
  Get current theme colors
  Clear background
  Draw generative visualization
  Update animation state

Source Code

let sketch = function(p) {

    // Visualizing the right decision myth
    // Left: Multiple decision paths being analyzed endlessly (stuck at crossroads)
    // Right: One path chosen with full commitment showing growth/progress
    // Shows contrast between decision paralysis vs. committed execution

    let time = 0;
    let decisionPaths = [];
    let committedPath = null;
    let analysisParticles = [];

    class DecisionPath {
        constructor(x, y, angle, index) {
            this.x = x;
            this.y = y;
            this.angle = angle;
            this.length = 0;
            this.maxLength = 60;
            this.index = index;
            this.weight = 2;
            this.analyzing = true;
        }

        update() {
            // Paths grow tentatively then retract - never committing
            if (this.analyzing) {
                let growth = p.sin(time * 0.02 + this.index * 0.5);
                this.length = p.map(growth, -1, 1, 10, this.maxLength);
                this.weight = p.map(growth, -1, 1, 1, 3);
            }
        }

        display(colors) {
            p.push();
            p.translate(this.x, this.y);
            p.rotate(this.angle);

            // Tentative, wavering line
            p.stroke(...colors.accent3, 140);
            p.strokeWeight(this.weight);
            p.noFill();

            p.beginShape();
            for (let i = 0; i <= this.length; i += 3) {
                // Wavy, uncertain path
                let yOffset = p.sin(i * 0.1 + time * 0.05) * 2;
                p.vertex(i, yOffset);
            }
            p.endShape();

            // Question marks at the end
            if (time % 90 > 45) {
                let qAlpha = p.map(time % 45, 0, 45, 0, 180);
                p.noStroke();
                p.fill(...colors.accent3, qAlpha);
                p.textAlign(p.CENTER, p.CENTER);
                p.textSize(10);
                p.text("?", this.length, 0);
            }

            p.pop();
        }
    }

    class CommittedPath {
        constructor(x, y) {
            this.x = x;
            this.y = y;
            this.length = 0;
            this.maxLength = 120;
            this.width = 6;
            this.growing = true;
            this.milestones = [];
            this.growth = 0;
        }

        update() {
            // Steady, consistent growth
            if (this.growing && this.length < this.maxLength) {
                this.length += 0.5;
                this.growth += 0.5;

                // Add milestones periodically
                if (this.length > 20 && this.length % 25 < 0.5) {
                    this.milestones.push({
                        pos: this.length,
                        time: time,
                        size: 0
                    });
                }
            }

            // Update milestones
            for (let m of this.milestones) {
                if (m.size < 10) m.size += 0.3;
            }
        }

        display(colors) {
            p.push();
            p.translate(this.x, this.y);

            // Strong, committed line going forward
            p.stroke(...colors.accent1, 200);
            p.strokeWeight(this.width);
            p.noFill();

            // Main path
            p.beginShape();
            for (let i = 0; i <= this.length; i += 2) {
                // Mostly straight with slight natural variation
                let yOffset = p.sin(i * 0.05) * 1;
                p.vertex(i, yOffset);
            }
            p.endShape();

            // Growth glow at the tip
            if (this.length < this.maxLength) {
                p.noStroke();
                for (let r = 20; r > 0; r -= 4) {
                    let alpha = p.map(r, 0, 20, 0, 80);
                    p.fill(...colors.accent1, alpha);
                    p.circle(this.length, 0, r);
                }
            }

            // Milestones - achievements along the way
            for (let m of this.milestones) {
                p.noStroke();
                p.fill(...colors.accent2, 180);
                p.circle(m.pos, 0, m.size);

                // Checkmark inside
                if (m.size > 8) {
                    p.stroke(...colors.bg, 200);
                    p.strokeWeight(1.5);
                    p.noFill();
                    p.beginShape();
                    let cx = m.pos;
                    p.vertex(cx - 3, 0);
                    p.vertex(cx - 1, 2);
                    p.vertex(cx + 3, -3);
                    p.endShape();
                }
            }

            p.pop();
        }
    }

    class AnalysisParticle {
        constructor(x, y) {
            this.x = x;
            this.y = y;
            this.vx = p.random(-0.5, 0.5);
            this.vy = p.random(-0.5, 0.5);
            this.life = 255;
            this.size = p.random(2, 4);
        }

        update() {
            this.x += this.vx;
            this.y += this.vy;
            this.life -= 2;

            // Circular motion - going in circles
            this.vx += p.random(-0.1, 0.1);
            this.vy += p.random(-0.1, 0.1);

            // Keep near center
            let dx = 80 - this.x;
            let dy = 150 - this.y;
            this.vx += dx * 0.001;
            this.vy += dy * 0.001;
        }

        display(colors) {
            p.noStroke();
            p.fill(...colors.accent3, this.life * 0.6);
            p.circle(this.x, this.y, this.size);
        }

        isDead() {
            return this.life <= 0;
        }
    }

    p.setup = function() {
        p.createCanvas(400, 300);
        p.colorMode(p.RGB);

        // Create multiple decision paths radiating from center (left side)
        let centerX = 80;
        let centerY = 150;
        for (let i = 0; i < 6; i++) {
            let angle = p.map(i, 0, 6, -p.PI * 0.6, p.PI * 0.6);
            decisionPaths.push(new DecisionPath(centerX, centerY, angle, i));
        }

        // Committed path (right side) - starts later
        committedPath = new CommittedPath(240, 150);
    };

    p.draw = function() {
        const colors = getThemeColors();
        p.background(...colors.bg);

        // Title
        p.noStroke();
        p.fill(...colors.accent3, 180);
        p.textAlign(p.CENTER, p.TOP);
        p.textSize(11);
        p.text("The Right Decision Myth", 200, 15);

        // Section labels
        p.textSize(8);
        p.fill(...colors.accent3, 160);
        p.textAlign(p.CENTER, p.TOP);
        p.text("Analyzing options", 80, 35);
        p.text("Committing to one", 300, 35);

        // Dividing line
        p.stroke(...colors.accent3, 60);
        p.strokeWeight(1);
        p.line(200, 60, 200, 240);

        // Left side: Decision paralysis
        // Add analysis particles
        if (p.random() < 0.3) {
            analysisParticles.push(new AnalysisParticle(
                80 + p.random(-20, 20),
                150 + p.random(-20, 20)
            ));
        }

        // Update and display particles
        for (let i = analysisParticles.length - 1; i >= 0; i--) {
            analysisParticles[i].update();
            analysisParticles[i].display(colors);
            if (analysisParticles[i].isDead()) {
                analysisParticles.splice(i, 1);
            }
        }

        // Display decision paths - wavering, uncertain
        for (let path of decisionPaths) {
            path.update();
            path.display(colors);
        }

        // Center point - stuck at crossroads
        p.noStroke();
        p.fill(...colors.accent3, 160);
        p.circle(80, 150, 8);

        // Right side: Committed path
        if (time > 60) {
            committedPath.update();
            committedPath.display(colors);

            // Starting point
            p.noStroke();
            p.fill(...colors.accent1, 180);
            p.circle(240, 150, 8);
        }

        // Labels and comparisons
        if (time > 120) {
            let labelAlpha = Math.min((time - 120) * 2, 160);

            p.textAlign(p.CENTER, p.TOP);
            p.textSize(7);
            p.noStroke();
            p.fill(...colors.accent3, labelAlpha);
            p.text("\"Which path is right?\"", 80, 210);
            p.text("6 months analyzing", 80, 222);

            if (time > 180) {
                p.fill(...colors.accent1, labelAlpha);
                p.text("\"This one. Let's go.\"", 300, 210);
                p.text("6 months building", 300, 222);
            }
        }

        // Show progress comparison
        if (time > 300) {
            let compAlpha = Math.min((time - 300) * 1.5, 180);

            p.textAlign(p.CENTER, p.BOTTOM);
            p.textSize(8);

            p.fill(...colors.accent3, compAlpha);
            p.text("Progress: None", 80, 270);

            p.fill(...colors.accent1, compAlpha);
            let progress = Math.floor(committedPath.growth / 2);
            p.text(`Progress: ${progress}`, 300, 270);
        }

        // Core insight
        if (time > 420) {
            let insightAlpha = Math.min((time - 420) * 2, 170);

            p.textAlign(p.CENTER, p.BOTTOM);
            p.textSize(8);
            p.fill(...colors.accent2, insightAlpha);
            p.text("The commitment matters more than the choice", 200, 290);
        }

        // Show the trap
        if (time > 240 && time < 360) {
            let trapAlpha = p.map(p.sin((time - 240) / 40), -1, 1, 100, 180);

            // "WHICH?" over decision paths
            p.push();
            p.textAlign(p.CENTER, p.CENTER);
            p.textSize(14);
            p.fill(...colors.accent3, trapAlpha);
            p.text("WHICH?", 80, 90);
            p.pop();

            // Arrow showing movement on committed side
            p.push();
            p.stroke(...colors.accent1, trapAlpha);
            p.strokeWeight(2);
            p.fill(...colors.accent1, trapAlpha);
            let arrowX = 260 + committedPath.length * 0.3;
            p.line(arrowX - 10, 180, arrowX, 180);
            p.triangle(arrowX, 180, arrowX - 6, 177, arrowX - 6, 183);
            p.pop();
        }

        // Satisfaction comparison over time
        if (time > 540) {
            let satAlpha = Math.min((time - 540) * 2, 150);

            p.push();
            p.textAlign(p.LEFT, p.TOP);
            p.textSize(7);
            p.noStroke();

            // Left side - anxiety
            p.fill(...colors.accent3, satAlpha);
            p.text("Anxiety: ↑↑↑", 25, 250);
            p.text("Results: →", 25, 262);

            // Right side - progress
            p.fill(...colors.accent1, satAlpha);
            p.text("Clarity: ↑", 230, 250);
            p.text("Results: ↑↑", 230, 262);

            p.pop();
        }

        time++;

        // Loop
        if (time > 720) {
            time = 0;
            // Reset committed path to show cycle again
            committedPath = new CommittedPath(240, 150);
        }
    };
};