Skip to main content Senior Full Stack Web Developer - Ossi Jalonen

An AI Companion: a short-ish intro before a longer post or series

Published: 2024-03-15
Updated: 2024-03-15

Ok, I know it’s been a while and I’m not done with the Full Stack series, or detours. But as things stand, I think it’s worth making a little note here, to record the state of AI. I know all you coders out there, already having used all sorts of copilots and extensions for years, it’s old news. But it’s still very much in the news for most people. These next couple of posts, we’re (mostly) using AI in ‘ChatGPT’ style - just logging in and asking a question or two and hoping for the best. We’re going to get in touch mainly with Claude 3 Sonnet, but to start with…

Let’s say hello to Gemini

So there was some news about Gemini Pro 1.5 or something. And it’s probably some big news. Check it out. But it just made me go check out Google’s Gemini. Not really concerned what version the free one is, I started typing away.

A bit of Maths and JavaScript

So I asked Gemini: Write a javascript function that finds the intersection of two lines in 2d space

And back it came, with two options.

gemini response 1

What I have noticed in past is that these AI helpers really need to work on reliability and they tend to get things wrong with code if you try to do too much at once. And we’re talking about these general types like ChatGPT, not specifically code oriented AI.

I then asked for a HTML page where this line intersection functionality is tested. A single html file, with javascript and all in one file. So it’s easy to test. And also easy to see that it does not work. A few prompts down the line, I wasn’t sure anymore how to get Gemini to fix issues, as it wasn’t quite working.

So I tried something else: Can you explain to me what the following function does and how it might help with the intersection issue:

function lerp(a, b, t) {
    //points on the line Ax + (Bx - Ax)t & Ay + (By - Ay)t
    //where 0 <= t <= 1 (ie. between A and B)
    return a + (b - a) * t;
}

Now if you showed me this function, I’d have to at least have a little think before answering. But Gemini has no problem.

gemini response 2

I was happy with that. Next I asked Gemini to put together a working page, but I realised the lerp function alone wasn’t enough help. So I double checked Gemini’s understanding of code by giving it one more piece of the puzzle. I also have another function that uses the lerp function. Can you explain how this works:

function getIntersection(A,B,C,D) {

    const tTop = (D.x - C.x) * (A.y - C.y) - (D.y - C.y) * (A.x - C.x);
    const uTop = (C.y - A.y) * (A.x - B.x) - (C.x - A.x) * (A.y - B.y);
    const bottom = (D.y - C.y) * (B.x - A.x) - (D.x - C.x) * (B.y - A.y);
    
    if(bottom != 0) {
        const t = tTop / bottom;
        const u = uTop / bottom;
        if(t >= 0 && t <= 1 && u >= 0 && u <= 1) {
            return {
                x: lerp(A.x, B.x, t),
                y: lerp(A.y, B.y, t),
                bottom: bottom,
                offset: t
            };
        }
    }
    return null;
}

And sure enough, it’s definitely figured it out, and it’s interpreting code I’ve given, surely it has a very high level of understanding?

gemini response 3

We had all the necessary parts now, so here we go: can you adapt your checkLineIntersection(line1, line2) function to utilise the two functions I've given

After a few tries, Gemini almost got it right! At this point it was so close, so I tried to get it to figure out and find the problem.

Please point out the errors in your checkLineIntersection function

No luck…

function getIntersection(A,B,C,D) { //...

Considering what I've just asked, can you check what you're passing to the getIntersection function, and what is the getIntersection function expecting as parameters?

Again - no luck, a long and very generic reply. So I asked why it is not answering in relation to the code we’ve discussed earlier. Turns out it’s forgotten the early section of the conversation completely!

Gemini: Please share the entire checkLineIntersection function you're currently using, including the call to the getIntersection function. This will allow me to see exactly what parameters are being passed and how the results are being handled.

After sharing the function code again, and another generic type of answer (felt like I was talking to a different AI), I noted:

yesterday you correctly analysed the getIntersection like this:
"This function, getIntersection, calculates the intersection point of two line segments defined by points A, B and C, D"
Can you modify the call inside the checkLineIntersection to reflect this knowledge

gemini response 4

Me: How many parameters does getIntersection accept?

Gemini: The getIntersection function you provided accepts 8 parameters ... etc

Me: But this is the function:

function getIntersection(A,B,C,D) {
   ...
}

Where do you get 8?

Gemini: You're absolutely right, I apologize for the mistake. I misread the provided getIntersection function and confused it with another version from our earlier discussion. It's clear that the provided function indeed only accepts 4 parameters: A, B, C, and D, representing the coordinates of the two points defining the line segment... etc

Me: Now you're only passing in individual coordinates of the two endpoints of line1 and disregarding line 2

Gemini: You're absolutely correct. I apologize for the mistake in the previous code snippet. My understanding of the getIntersection function and the desired behavior was inaccurate... etc

Me: now you're passing 8 arguments again

Gemini: You're absolutely right, I made another mistake in my previous response. The correct number of arguments to pass to the getIntersection function is 4, not 8... etc

So this had now formed a loop - Gemini went back to the earlier suggestion, undoubtedly ready to keep going as long as I wanted. So I gave up. Haven’t had another conversation with Gemini since.

Gemini and the rest of the AI’s do point out you should Use code with caution. But the html below is probably not going to end up in any real production. It is purely an example of AI-generated html with some javascript, with minimal human-help to get it up and running.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Random Line Intersection</title>
  <style>
    body { margin: 0; }
    canvas { width: 100vw; height: 100vh; }
  </style>
</head>
<body>
  <canvas id="myCanvas"></canvas>
  <script>
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');

    // Set canvas size to be the viewport dimensions
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

    function getRandomColor() {
      // Generate random hex color for lines
      return '#' + Math.floor(Math.random()*16777215).toString(16).padStart(6, '0');
    }

    function getRandomLine() {
      // Generate random start and end points, angle, and length for a line within canvas bounds
      const startX = Math.floor(Math.random() * canvas.width);
      const startY = Math.floor(Math.random() * canvas.height);
      const angle = Math.random() * Math.PI * 2; // 0 to 2π radians
      const length = Math.floor(Math.random() * (Math.min(canvas.width, canvas.height) / 2) + 50); // Min length 50

      const endX = startX + length * Math.cos(angle);
      const endY = startY + length * Math.sin(angle);

      return {
        startX,
        startY,
        endX,
        endY
      };
    }

    function checkLineIntersection(line1, line2) {
        const intersection = getIntersection({x: line1.startX, y: line1.startY}, {x: line1.endX, y: line1.endY},
                                            {x: line2.startX, y: line2.startY}, {x:line2.endX, y:line2.endY});

        if (!intersection) {
            return false; // No intersection found
        }
        return true;
    }

    let lines = []; // Array to store latest pair of lines

    function drawLines() {
      ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear canvas

      // Generate new lines if no intersection found, otherwise stop
      if (!lines.length || !checkLineIntersection(lines[0], lines[1])) {
        const line1 = getRandomLine();
        const line2 = getRandomLine();
        lines = [line1, line2];
      }
      else {
        clearInterval(intval);
      }

      // Draw both lines
      for (const line of lines) {
        ctx.beginPath();
        ctx.strokeStyle = getRandomColor();
        ctx.lineWidth = 2;
        ctx.moveTo(line.startX, line.startY);
        ctx.lineTo(line.endX, line.endY);
        ctx.stroke();
      }
    }

    intval = setInterval(drawLines, 100); // Draw lines every second

    function getIntersection(A,B,C,D) {
        const tTop = (D.x - C.x) * (A.y - C.y) - (D.y - C.y) * (A.x - C.x);
        const uTop = (C.y - A.y) * (A.x - B.x) - (C.x - A.x) * (A.y - B.y);
        const bottom = (D.y - C.y) * (B.x - A.x) - (D.x - C.x) * (B.y - A.y);
        
        const eps = 0.001;
        // if(bottom != 0) { //causes floating point issues
        if(Math.abs(bottom) > eps) {
            const t = tTop / bottom;
            const u = uTop / bottom;
            if(t >= 0 && t <= 1 && u >= 0 && u <= 1) {
                return {
                    x: lerp(A.x, B.x, t),
                    y: lerp(A.y, B.y, t),
                    bottom: bottom,
                    offset: t
                };
            }
        }
        return null;
    }

    function lerp(a, b, t) {
        //points on the line Ax + (Bx - Ax)t & Ay + (By - Ay)t
        //where 0 <= t <= 1 (ie. between A and B)
        return a + (b - a) * t;
    }
  </script>
</body>
</html>

Coming up

There’s a long conversation I had with Claude this week. It might need to be broken into a few separate posts.