[object Object]

← back to Model Arena

auto-save: 2026-08-01T07:34:56 (3 files) — data/challenges.json yolo/daily-log.jsonl data/artifacts/2723444f5049/

de1ead58fc8e0d55c03fd53f1a90865a432f0ecf · 2026-08-01 07:35:07 -0700 · Steve Abrams

Files touched

Diff

commit de1ead58fc8e0d55c03fd53f1a90865a432f0ecf
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sat Aug 1 07:35:07 2026 -0700

    auto-save: 2026-08-01T07:34:56 (3 files) — data/challenges.json yolo/daily-log.jsonl data/artifacts/2723444f5049/
---
 data/artifacts/2723444f5049/gemma3-12b.html | 111 ++++++++++++++++++++++
 data/artifacts/2723444f5049/gemma3-12b.png  | Bin 0 -> 13961 bytes
 data/artifacts/2723444f5049/hermes3-8b.html | 137 ++++++++++++++++++++++++++++
 data/artifacts/2723444f5049/hermes3-8b.png  | Bin 0 -> 5753 bytes
 data/artifacts/2723444f5049/qwen25-7b.html  |  96 +++++++++++++++++++
 data/artifacts/2723444f5049/qwen25-7b.png   | Bin 0 -> 4534 bytes
 data/artifacts/2723444f5049/qwen3-14b.html  | 135 +++++++++++++++++++++++++++
 data/artifacts/2723444f5049/qwen3-14b.png   | Bin 0 -> 107399 bytes
 data/challenges.json                        |  90 ++++++++++++++++++
 yolo/daily-log.jsonl                        |   1 +
 10 files changed, 570 insertions(+)

diff --git a/data/artifacts/2723444f5049/gemma3-12b.html b/data/artifacts/2723444f5049/gemma3-12b.html
new file mode 100644
index 0000000..8bdf24e
--- /dev/null
+++ b/data/artifacts/2723444f5049/gemma3-12b.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Bouncing Balls</title>
+<style>
+body { margin: 0; overflow: hidden; }
+canvas { background-color: #f0f0f0; display: block; }
+#gravitySliderContainer { width: 100%; height: 40px; bottom: 0; left: 0; position: absolute; padding: 5px; box-sizing: border-box; background-color: rgba(255, 255, 255, 0.8); }
+#gravitySlider { width: 100%; height: 30px; margin: auto; }
+</style>
+</head>
+<body>
+
+<div id="gravitySliderContainer">
+  <input type="range" id="gravitySlider" min="0.1" max="2.0" value="1.0" step="0.01"/>
+</div>
+
+<canvas id="myCanvas"></canvas>
+
+<script>
+const canvas = document.getElementById("myCanvas");
+const ctx = canvas.getContext("2d");
+
+canvas.width = window.innerWidth;
+canvas.height = window.innerHeight;
+
+let balls = [];
+let gravity = 1.0;
+
+function init() {
+  for (let i = 0; i < 20; i++) {
+    balls.push({
+      x: Math.random() * canvas.width,
+      y: Math.random() * canvas.height,
+      radius: Math.random() * 10 + 5,
+      vx: (Math.random() - 0.5) * 4,
+      vy: (Math.random() - 0.5) * 4,
+      trailLength: Math.floor(Math.random() * 5) + 3,
+      trailColor: `rgba(${Math.random()*255}, ${Math.random()*255}, ${Math.random()*255}, 0.7)`
+    });
+  }
+
+  const slider = document.getElementById("gravitySlider");
+  slider.addEventListener("input", function() {
+     gravity = parseFloat(this.value);
+  });
+}
+
+
+function drawBall(ball) {
+  ctx.beginPath();
+  ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
+  ctx.fillStyle = ball.trailColor;
+  ctx.fill();
+
+  // Draw trail
+  ctx.beginPath();
+  ctx.moveTo(ball.x, ball.y);
+  for (let i = 0; i < ball.trailLength; i++) {
+    const x = ball.x - ball.vx * (i + 1) / ball.trailLength;
+    const y = ball.y - ball.vy * (i + 1) / ball.trailLength;
+    ctx.lineTo(x, y);
+
+  }
+  ctx.strokeStyle = ball.trailColor;
+  ctx.lineWidth = ball.radius/2;
+  ctx.stroke();
+}
+
+
+function update() {
+  ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+  for (let i = 0; i < balls.length; i++) {
+    const ball = balls[i];
+
+    ball.vx += 0; // No horizontal acceleration
+    ball.vy += gravity;
+
+
+    ball.x += ball.vx;
+    ball.y += ball.vy;
+
+    if (ball.x + ball.radius > canvas.width || ball.x - ball.radius < 0) {
+      ball.vx = -ball.vx;
+    }
+    if (ball.y + ball.radius > canvas.height || ball.y - ball.radius < 0) {
+      ball.vy = -ball.vy;
+    }
+
+    drawBall(ball);
+  }
+
+
+  requestAnimationFrame(update);
+}
+
+
+
+init();
+update();
+
+window.addEventListener('resize', () => {
+    canvas.width = window.innerWidth;
+    canvas.height = window.innerHeight;
+});
+
+</script>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/2723444f5049/gemma3-12b.png b/data/artifacts/2723444f5049/gemma3-12b.png
new file mode 100644
index 0000000..aeffc28
Binary files /dev/null and b/data/artifacts/2723444f5049/gemma3-12b.png differ
diff --git a/data/artifacts/2723444f5049/hermes3-8b.html b/data/artifacts/2723444f5049/hermes3-8b.html
new file mode 100644
index 0000000..e78a0e4
--- /dev/null
+++ b/data/artifacts/2723444f5049/hermes3-8b.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>Bouncing Balls</title>
+  <style>
+    body {
+      margin: 0;
+      padding: 10px;
+      font-family: Arial, sans-serif;
+    }
+    canvas {
+      border: 1px solid black;
+    }
+    #gravitySlider {
+      margin-top: 10px;
+    }
+  </style>
+</head>
+<body>
+  <label for="gravitySlider">Gravity:</label>
+  <input type="range" id="gravitySlider" min="50" max="1000" value="300" step="1">
+  <canvas id="myCanvas"></canvas>
+
+  <script>
+    const canvas = document.getElementById('myCanvas');
+    const ctx = canvas.getContext('2d');
+
+    let balls = [];
+    let gravity;
+    const gravitySlider = document.getElementById('gravitySlider');
+    const maxBalls = 20;
+
+    function Ball(x, y, radius) {
+      this.x = x;
+      this.y = y;
+      this.radius = radius;
+      this.speedX = 0;
+      this.speedY = 0;
+      this.trailLength = 30;
+      this.trails = [];
+    }
+
+    Ball.prototype.updateTrail = function() {
+      if (this.trails.length >= this.trailLength) {
+        this.trails.shift();
+      }
+      this.trails.push({ x: this.x, y: this.y });
+    };
+
+    Ball.prototype.draw = function() {
+      ctx.beginPath();
+      ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
+      ctx.fillStyle = 'black';
+      ctx.fill();
+
+      ctx.strokeStyle = 'white';
+      ctx.lineWidth = 1;
+      for (let i = 0; i < this.trails.length; i++) {
+        const trailX = this.trails[i].x;
+        const trailY = this.trails[i].y;
+        ctx.moveTo(trailX, trailY);
+        ctx.lineTo(this.x, this.y);
+      }
+      ctx.stroke();
+    };
+
+    function createBalls() {
+      for (let i = 0; i < maxBalls; i++) {
+        let x = Math.random() * canvas.width;
+        let y = Math.random() * canvas.height - 100;
+        let radius = Math.random() * 10 + 5;
+
+        balls.push(new Ball(x, y, radius));
+      }
+    }
+
+    function updateGravity(value) {
+      gravity = value;
+    }
+
+    function updateBalls() {
+      for (let i = 0; i < balls.length; i++) {
+        balls[i].speedY += gravity * Math.random() / 50;
+
+        balls[i].x += balls[i].speedX;
+        balls[i].y += balls[i].speedY;
+
+        if (balls[i].y + balls[i].radius > canvas.height) {
+          balls[i].y = canvas.height - balls[i].radius;
+          balls[i].speedY *= -0.8;
+        }
+
+        for (let j = i + 1; j < balls.length; j++) {
+          const dx = balls[j].x - balls[i].x;
+          const dy = balls[j].y - balls[i].y;
+          const distance = Math.sqrt(dx * dx + dy * dy);
+
+          if (distance < balls[i].radius + balls[j].radius) {
+            const angle = Math.atan2(dy, dx);
+            balls[i].speedX += Math.cos(angle) * 15;
+            balls[i].speedY += Math.sin(angle) * 15;
+            balls[j].speedX -= Math.cos(angle) * 15;
+            balls[j].speedY -= Math.sin(angle) * 15;
+          }
+        }
+
+        balls[i].updateTrail();
+      }
+    }
+
+    function drawBalls() {
+      ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+      for (let i = 0; i < balls.length; i++) {
+        balls[i].draw();
+      }
+    }
+
+    function loop() {
+      updateGravity(gravitySlider.value);
+      updateBalls();
+      drawBalls();
+
+      setTimeout(loop, 20);
+    }
+
+    gravitySlider.addEventListener('input', () => {
+      updateGravity(gravitySlider.value);
+    });
+
+    createBalls();
+    loop();
+  </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/2723444f5049/hermes3-8b.png b/data/artifacts/2723444f5049/hermes3-8b.png
new file mode 100644
index 0000000..7c8819f
Binary files /dev/null and b/data/artifacts/2723444f5049/hermes3-8b.png differ
diff --git a/data/artifacts/2723444f5049/qwen25-7b.html b/data/artifacts/2723444f5049/qwen25-7b.html
new file mode 100644
index 0000000..c064237
--- /dev/null
+++ b/data/artifacts/2723444f5049/qwen25-7b.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Bouncing Balls</title>
+    <style>
+        body { margin: 0; overflow: hidden; background-color: #1e1e1e; }
+        canvas { display: block; width: 100%; height: 100vh; cursor: none; }
+    </style>
+</head>
+<body>
+<canvas id="canvas"></canvas>
+<script>
+const canvas = document.getElementById('canvas');
+const ctx = canvas.getContext('2d');
+
+canvas.width = window.innerWidth;
+canvas.height = window.innerHeight;
+
+class Ball {
+    constructor(x, y, radius, speed) {
+        this.x = x; 
+        this.y = y; 
+        this.radius = radius; 
+        this.speed = speed || 10;
+        this.trail = [];
+    }
+
+    draw() {
+        ctx.beginPath();
+        ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
+        ctx.stroke();
+        this.trail.push({x: this.x, y: this.y});
+        if (this.trail.length > 5) this.trail.shift();
+    }
+
+    update() {
+        const gravity = 0.3;
+        const bounce = -0.8;
+
+        this.y += this.speed;
+        this.speed += gravity;
+
+        for (let i = balls.length - 2; i >= 0; --i) {
+            if (this !== balls[i] && Math.hypot(this.x - balls[i].x, this.y - balls[i].y) < this.radius + balls[i].radius) {
+                const dx = this.x - balls[i].x;
+                const dy = this.y - balls[i].y;
+                const angle = Math.atan2(dy, dx);
+                const dist = (this.speed * 0.5) / (1 + 0.5);
+
+                this.x += dx * bounce * dist;
+                this.y += dy * bounce * dist;
+
+                balls[i].x -= dx * bounce * dist;
+                balls[i].y -= dy * bounce * dist;
+
+                this.speed = Math.sqrt((this.speed * -0.8) ** 2 + (balls[i].speed * 0.3) ** 2);
+                balls[i].speed = Math.sqrt((balls[i].speed * -0.8) ** 2 + (this.speed * 0.3) ** 2);
+            }
+        }
+
+        this.draw();
+    }
+}
+
+const balls = [];
+for (let i = 0; i < 20; ++i) {
+    const x = Math.random() * canvas.width;
+    const y = -10 + Math.random() * 150;
+    balls.push(new Ball(x, y, 10 + Math.random() * 10));
+}
+
+function animate() {
+    ctx.clearRect(0, 0, canvas.width, canvas.height);
+    for (let ball of balls) ball.update();
+    requestAnimationFrame(animate);
+}
+animate();
+
+document.body.style.cursor = 'none';
+
+const gravitySlider = document.createElement('input');
+gravitySlider.type = 'range';
+gravitySlider.min = 0;
+gravitySlider.max = 1;
+gravitySlider.step = 0.1;
+gravitySlider.value = 0.3;
+
+gravitySlider.oninput = function() {
+    for (let ball of balls) ball.speed += (this.value - gravity);
+};
+
+document.body.appendChild(gravitySlider);
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/2723444f5049/qwen25-7b.png b/data/artifacts/2723444f5049/qwen25-7b.png
new file mode 100644
index 0000000..2ca092c
Binary files /dev/null and b/data/artifacts/2723444f5049/qwen25-7b.png differ
diff --git a/data/artifacts/2723444f5049/qwen3-14b.html b/data/artifacts/2723444f5049/qwen3-14b.html
new file mode 100644
index 0000000..3993170
--- /dev/null
+++ b/data/artifacts/2723444f5049/qwen3-14b.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="UTF-8">
+  <title>Bouncing Balls with Gravity</title>
+  <style>
+    html, body {
+      margin: 0;
+      padding: 0;
+      overflow: hidden;
+      background: #111;
+      font-family: sans-serif;
+    }
+    canvas {
+      display: block;
+    }
+    #controls {
+      position: absolute;
+      top: 10px;
+      left: 10px;
+      color: white;
+      font-size: 14px;
+    }
+  </style>
+</head>
+<body>
+<canvas id="canvas"></canvas>
+<div id="controls">
+  Gravity: <input type="range" id="gravitySlider" min="0.01" max="0.5" step="0.001" value="0.1">
+</div>
+<script>
+  const canvas = document.getElementById("canvas");
+  const ctx = canvas.getContext("2d");
+  let width = canvas.width = window.innerWidth;
+  let height = canvas.height = window.innerHeight;
+
+  window.addEventListener("resize", () => {
+    width = canvas.width = window.innerWidth;
+    height = canvas.height = window.innerHeight;
+  });
+
+  const gravitySlider = document.getElementById("gravitySlider");
+  let gravity = parseFloat(gravitySlider.value);
+  gravitySlider.addEventListener("input", () => {
+    gravity = parseFloat(gravitySlider.value);
+  });
+
+  const balls = [];
+  const numBalls = 20;
+  const trails = [];
+
+  function createBall() {
+    return {
+      x: Math.random() * width,
+      y: Math.random() * height,
+      vx: (Math.random() - 0.5) * 6,
+      vy: (Math.random() - 0.5) * 6,
+      radius: 12 + Math.random() * 8,
+      color: `hsl(${Math.random() * 360}, 70%, 60%)`,
+      trail: []
+    };
+  }
+
+  for (let i = 0; i < numBalls; i++) {
+    balls.push(createBall());
+  }
+
+  function drawBall(ball) {
+    ctx.beginPath();
+    ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
+    ctx.fillStyle = ball.color;
+    ctx.fill();
+    ctx.strokeStyle = ball.color;
+    ctx.stroke();
+  }
+
+  function updateBall(ball) {
+    // Apply gravity
+    ball.vy += gravity;
+
+    // Move the ball
+    ball.x += ball.vx;
+    ball.y += ball.vy;
+
+    // Bounce off walls
+    if (ball.x - ball.radius < 0 || ball.x + ball.radius > width) {
+      ball.vx *= -1;
+    }
+    if (ball.y - ball.radius < 0) {
+      ball.vy *= -1;
+      ball.y = ball.radius;
+    } else if (ball.y + ball.radius > height) {
+      ball.vy *= -1;
+      ball.y = height - ball.radius;
+    }
+
+    // Add trail point
+    ball.trail.push({ x: ball.x, y: ball.y });
+    if (ball.trail.length > 20) {
+      ball.trail.shift();
+    }
+  }
+
+  function drawTrails(ball) {
+    ctx.strokeStyle = ball.color;
+    ctx.lineWidth = 1;
+    ctx.beginPath();
+    for (let i = 0; i < ball.trail.length; i++) {
+      const point = ball.trail[i];
+      if (i === 0) {
+        ctx.moveTo(point.x, point.y);
+      } else {
+        ctx.lineTo(point.x, point.y);
+      }
+    }
+    ctx.stroke();
+  }
+
+  function animate() {
+    ctx.fillStyle = "rgba(0, 0, 0, 0.1)";
+    ctx.fillRect(0, 0, width, height);
+
+    balls.forEach(ball => {
+      updateBall(ball);
+      drawTrails(ball);
+      drawBall(ball);
+    });
+
+    requestAnimationFrame(animate);
+  }
+
+  animate();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/2723444f5049/qwen3-14b.png b/data/artifacts/2723444f5049/qwen3-14b.png
new file mode 100644
index 0000000..e4487ed
Binary files /dev/null and b/data/artifacts/2723444f5049/qwen3-14b.png differ
diff --git a/data/challenges.json b/data/challenges.json
index 08b15af..abeac57 100644
--- a/data/challenges.json
+++ b/data/challenges.json
@@ -31095,5 +31095,95 @@
     "judging": false,
     "aiPick": "qwen3-14b",
     "judged_at": "2026-07-31T14:19:31.505Z"
+  },
+  {
+    "id": "2723444f5049",
+    "title": "Daily: Bouncing Balls",
+    "prompt": "Single-file HTML canvas with 20 balls bouncing under gravity with collisions and trails; a slider controls gravity.",
+    "category": "Custom",
+    "designTools": false,
+    "created_at": "2026-08-01T14:15:02.519Z",
+    "winner": null,
+    "runs": [
+      {
+        "model": "qwen3-14b",
+        "status": "done",
+        "error": null,
+        "seconds": 43,
+        "cost": 0,
+        "started_at": "2026-08-01T14:15:02.551Z",
+        "finished_at": "2026-08-01T14:15:45.376Z",
+        "queued_at": "2026-08-01T14:15:02.528Z",
+        "bytes": 3043,
+        "thumb": true,
+        "aiScore": 7.5,
+        "aiReason": "The model fulfills the challenge requirements and has good visual quality.",
+        "aiScores": {
+          "qwen2.5vl:7b": 9,
+          "minicpm-v:latest": 6
+        },
+        "aiSpread": 3
+      },
+      {
+        "model": "gemma3-12b",
+        "status": "done",
+        "error": null,
+        "seconds": 50,
+        "cost": 0,
+        "started_at": "2026-08-01T14:15:45.385Z",
+        "finished_at": "2026-08-01T14:16:35.883Z",
+        "queued_at": "2026-08-01T14:15:02.534Z",
+        "bytes": 2585,
+        "thumb": true,
+        "aiScore": 6.5,
+        "aiReason": "The model successfully implements the challenge requirements but lacks some visual polish and detail.",
+        "aiScores": {
+          "qwen2.5vl:7b": 7,
+          "minicpm-v:latest": 6
+        },
+        "aiSpread": 1
+      },
+      {
+        "model": "hermes3-8b",
+        "status": "done",
+        "error": null,
+        "seconds": 44,
+        "cost": 0,
+        "started_at": "2026-08-01T14:16:35.894Z",
+        "finished_at": "2026-08-01T14:17:19.583Z",
+        "queued_at": "2026-08-01T14:15:02.540Z",
+        "bytes": 3456,
+        "thumb": true,
+        "aiScore": 6.3,
+        "aiReason": "The model shows basic functionality but lacks visual appeal and detail.",
+        "aiScores": {
+          "qwen2.5vl:7b": 6,
+          "minicpm-v:latest": 6.5
+        },
+        "aiSpread": 0.5
+      },
+      {
+        "model": "qwen25-7b",
+        "status": "done",
+        "error": null,
+        "seconds": 19,
+        "cost": 0,
+        "started_at": "2026-08-01T14:15:02.567Z",
+        "finished_at": "2026-08-01T14:15:21.772Z",
+        "queued_at": "2026-08-01T14:15:02.545Z",
+        "bytes": 2640,
+        "thumb": true,
+        "aiScore": 4,
+        "aiReason": "The image is nearly black and does not show any balls or gravity effect.",
+        "aiScores": {
+          "qwen2.5vl:7b": 2,
+          "minicpm-v:latest": 6
+        },
+        "aiSpread": 4
+      }
+    ],
+    "judging": false,
+    "aiPick": "qwen3-14b",
+    "judged_at": "2026-08-01T14:18:08.519Z"
   }
 ]
\ No newline at end of file
diff --git a/yolo/daily-log.jsonl b/yolo/daily-log.jsonl
index 63c014b..c221371 100644
--- a/yolo/daily-log.jsonl
+++ b/yolo/daily-log.jsonl
@@ -4,3 +4,4 @@
 {"ts":"2026-07-29T14:17:29.433Z","id":"b697e7a2f3e5","title":"Daily: Conway Life","done":4,"aiPick":"qwen25-7b"}
 {"ts":"2026-07-30T14:16:48.177Z","id":"40d4661c01ff","title":"Daily: Particle Fireworks","done":4,"aiPick":"qwen25-7b"}
 {"ts":"2026-07-31T14:19:37.271Z","id":"6067924bfe58","title":"Daily: Sortable Catalog","done":4,"aiPick":"qwen3-14b"}
+{"ts":"2026-08-01T14:18:14.630Z","id":"2723444f5049","title":"Daily: Bouncing Balls","done":4,"aiPick":"qwen3-14b"}

← 5416fd4 auto-save: 2026-07-31T08:25:30 (2 files) — data/challenges.j  ·  back to Model Arena  ·  auto-save: 2026-08-02T07:43:26 (3 files) — data/challenges.j 7000ba2 →