The Fresh Start Fallacy
About This Sketch
Algorithm
This sketch visualizes the compounding difference between starting immediately versus waiting for a "fresh start" temporal landmark (like New Year's Day).
Two groups of progress dots are created:
- "Start Now" group begins accumulating immediately
- "Wait for Fresh Start" group delays until a predetermined landmark
As time progresses, dots "activate" and float upward to represent accumulated progress. The sketch tracks and displays the growing gap between immediate action and delayed action.
A timeline shows the current moment and the future "fresh start" landmark. Progress bars quantify the cumulative difference, demonstrating that starting now—even imperfectly—builds more real progress than waiting for ideal conditions.
Pseudocode
SETUP:
Initialize canvas (400x300)
Create 30 "start now" dots with immediate, staggered activation times
Create 30 "wait for fresh start" dots with delayed activation (after landmark)
Set fresh start landmark at frame 120
DRAW (every frame):
Get current theme colors
Clear background
Increment time counter
Draw timeline with:
- Current time marker (moving)
- Fresh start landmark (fixed, until reached)
For each dot group:
Update activation status based on current time
If activated, move upward (accumulate progress)
Display with theme colors and glow effect
Count active dots
Display labels and progress metrics:
- Group names ("Start Now" vs "Wait for Fresh Start")
- Active dot counts
- Progress bars showing cumulative difference
- Dynamic insight when gap becomes significant
Show how immediate action compounds while waiting postpones
Source Code
let sketch = function(p) {
// Visualization of starting now vs waiting for fresh start
// Two groups of progress bars:
// "Start now" bars begin immediately and accumulate
// "Wait for fresh start" bars wait for landmark, then start
let time = 0;
let freshStartTime = 120; // The "fresh start" moment
let maxTime = 400;
// Progress trackers
let startNowProgress = 0;
let waitForStartProgress = 0;
// Visual elements
let startNowDots = [];
let waitForStartDots = [];
class ProgressDot {
constructor(x, baseY, delay) {
this.x = x;
this.baseY = baseY;
this.y = baseY;
this.delay = delay;
this.born = false;
this.age = 0;
this.size = 4;
this.targetY = baseY - 80;
}
update(currentTime) {
if (currentTime >= this.delay && !this.born) {
this.born = true;
}
if (this.born) {
this.age++;
// Float upward (representing progress/accumulation)
if (this.y > this.targetY) {
this.y -= 0.5;
}
}
}
display(colors, color) {
if (this.born) {
let opacity = p.map(this.age, 0, 100, 100, 200);
opacity = p.min(opacity, 200);
p.fill(...colors[color], opacity);
p.noStroke();
p.circle(this.x, this.y, this.size);
// Subtle glow
p.fill(...colors[color], opacity * 0.3);
p.circle(this.x, this.y, this.size * 1.5);
}
}
}
p.setup = function() {
p.createCanvas(400, 300);
// Create dots for "start now" - begin immediately
let startNowX = 100;
let startNowY = 200;
for (let i = 0; i < 30; i++) {
startNowDots.push(new ProgressDot(
startNowX + p.random(-20, 20),
startNowY,
i * 8 // Start immediately, spaced out
));
}
// Create dots for "wait for fresh start" - delay until landmark
let waitX = 300;
let waitY = 200;
for (let i = 0; i < 30; i++) {
waitForStartDots.push(new ProgressDot(
waitX + p.random(-20, 20),
waitY,
freshStartTime + (i * 8) // Wait until fresh start
));
}
};
p.draw = function() {
const colors = getThemeColors();
p.background(...colors.bg);
time++;
// Title
p.fill(...colors.accent3);
p.noStroke();
p.textAlign(p.CENTER);
p.textSize(12);
p.text('The Fresh Start Fallacy', 200, 20);
// Subtitle
p.textSize(7);
p.fill(...colors.accent3, 180);
p.text('Starting now accumulates. Waiting for fresh starts postpones.', 200, 32);
// Timeline marker
let timelineY = 240;
p.stroke(...colors.accent3, 100);
p.strokeWeight(1);
p.line(50, timelineY, 350, timelineY);
// Current time marker
let timeX = p.map(time, 0, maxTime, 50, 350);
timeX = p.min(timeX, 350);
p.stroke(...colors.accent3, 200);
p.strokeWeight(2);
p.line(timeX, timelineY - 5, timeX, timelineY + 5);
// Fresh start landmark
if (time < freshStartTime) {
let landmarkX = p.map(freshStartTime, 0, maxTime, 50, 350);
p.stroke(...colors.accent2, 150);
p.strokeWeight(1);
p.line(landmarkX, timelineY - 10, landmarkX, timelineY + 10);
p.noStroke();
p.fill(...colors.accent2, 180);
p.textSize(7);
p.text('Fresh Start', landmarkX, timelineY + 18);
}
// Update and display "start now" dots
let startNowActive = 0;
for (let dot of startNowDots) {
dot.update(time);
dot.display(colors, 'accent1');
if (dot.born) startNowActive++;
}
// Update and display "wait for start" dots
let waitActive = 0;
for (let dot of waitForStartDots) {
dot.update(time);
dot.display(colors, 'accent2');
if (dot.born) waitActive++;
}
// Labels
p.textAlign(p.CENTER);
p.textSize(8);
// Start now label
p.fill(...colors.accent1, 200);
p.text('Start Now', 100, 215);
p.textSize(6);
p.fill(...colors.accent3, 150);
p.text(`Progress: ${startNowActive}`, 100, 224);
// Wait for start label
p.fill(...colors.accent2, 200);
p.textSize(8);
p.text('Wait for Fresh Start', 300, 215);
p.textSize(6);
p.fill(...colors.accent3, 150);
if (time < freshStartTime) {
p.text('Waiting...', 300, 224);
} else {
p.text(`Progress: ${waitActive}`, 300, 224);
}
// Progress bars
let barY = 260;
let barWidth = 100;
let barHeight = 8;
// Start now bar
let startNowFill = p.map(startNowActive, 0, 30, 0, barWidth);
p.fill(...colors.accent3, 80);
p.noStroke();
p.rect(50, barY, barWidth, barHeight, 4);
p.fill(...colors.accent1, 200);
p.rect(50, barY, startNowFill, barHeight, 4);
// Wait for start bar
let waitFill = p.map(waitActive, 0, 30, 0, barWidth);
p.fill(...colors.accent3, 80);
p.rect(250, barY, barWidth, barHeight, 4);
p.fill(...colors.accent2, 200);
p.rect(250, barY, waitFill, barHeight, 4);
// Dynamic insight
if (time > 250) {
let progressDiff = startNowActive - waitActive;
if (progressDiff > 8) {
p.fill(...colors.accent1, 200);
p.textAlign(p.CENTER);
p.textSize(7);
p.text(`Starting immediately built ${progressDiff} more progress`, 200, 50);
}
}
// "Now" marker
p.fill(...colors.accent3);
p.textSize(6);
p.textAlign(p.CENTER);
p.text('Now', timeX, timelineY - 10);
};
};