Doughnut ChartJs shrink when hover

I’m using doughnut chart from chartJS for my project. For some reason, it become smaller when I hover into center area of the chart. Below i have a link to the video how its looks like. I want to find what is the cause and how to fix it.

https://imgur.com/0v9FKzl

options: {
interaction: {
    mode: 'nearest',
    intersect: false
},
responsive: true,
maintainAspectRatio: false,
plugins: {
    tooltip: {
        enabled: true
    }
},
elements: {
    arc: {
        hoverOffset: 0
    }
}

Any ideas would be appreciated! Thank you.

Why does using the `lazy` attribute of `el-image` inside `el-carousel` cause several blank pages when flipping to the right?

Why does using the lazy attribute of el-image inside el-carousel cause several blank pages when flipping to the right?

Online Demo

Element Plus Playground 1

Example Code

<script setup lang="ts">

</script>

<template>
   <div>
<div style="width: 100%; height: 2000px; display: block">lazy load header</div>
<el-carousel height="2000px">
  <el-carousel-item>
    <el-row>
      <el-col :span="24">
        <el-image
          src="https://dummyimage.com/2000x2000/aaa/fff&text=2000x2000"
          lazy
        />
      </el-col>
    </el-row>
  </el-carousel-item>
  <el-carousel-item>
    <el-row>
      <el-col :span="24">
        <el-image
          src="https://dummyimage.com/2000x2000/bbb/fff&text=2000x2000"
          lazy
        />
      </el-col>
    </el-row>
  </el-carousel-item>
  <el-carousel-item>
    <el-row>
      <el-col :span="24">
        <el-image
          src="https://dummyimage.com/2000x2000/ccc/fff&text=2000x2000"
          lazy
        />
      </el-col>
    </el-row>
  </el-carousel-item>
  <el-carousel-item>
    <el-row>
      <el-col :span="24">
        <el-image
          src="https://dummyimage.com/2000x2000/ddd/fff&text=2000x2000"
          lazy
        />
      </el-col>
    </el-row>
  </el-carousel-item>
  <el-carousel-item>
    <el-row>
      <el-col :span="24">
        <el-image
          src="https://dummyimage.com/2000x2000/eee/fff&text=2000x2000"
          lazy
        />
      </el-col>
    </el-row>
  </el-carousel-item>
</el-carousel>
  </div>
</template>

<style>

Currently, I’m not sure how to make an attempt. The expected result is that when using the lazy attribute of el-image inside el-carousel, there won’t be any blank pages when flipping to the right.

Circular Progress and Graph

I’ve been trying to create this design using HTML, CSS and JS (particularly chart.io). I am wondering if there is a better way to do this without relying much on JS. The reason for this is that, this particular screenshot below is for a report. So I need to make sure that the design renders graciously with all browsers. And if a user decides to save it as PDF, the report should not have any problem rendering on different PDF viewers. I’m worried about having too much JS as I’ve had issues before where the designs break in iOS and Acrobat.

For starters, I’ll use 12 o’clock as the top most part of the progress.

  • If the progress bar is exactly 12 o’clock, it has a blue gradient.
  • If it less than 12 oclock, it has a faint green gradient and not filling up the whole progress.
  • But if it goes beyond 12 o’clock, it’s replaced by a purple gradient with the end having darker gradient and a curved end. The endings of the bar is also determined by how far it is from 12’oclock.

enter image description here

This is what I currently have at the moment.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Age Progress and Graph</title>
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2"></script>
  <style>
    body {
      font-family: sans-serif;
      display: flex;
      align-items: center;
      justify-content: space-between;
      background: #fff;
      margin: 0;
      padding: 2rem;
      width: 700px;
    }

    .progress-container {
      position: relative;
      width: 160px;
      height: 160px;
      margin-bottom: 2rem;
    }

    .progress-container svg {
      transform: rotate(-90deg);
    }

    .progress-text {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      text-align: center;
    }

    .progress-text h2 {
      margin: 0;
      font-size: 2rem;
    }

    .chart-container {
      width: 440px;
      height: 150px;
    }
  </style>
</head>
<body>
  <div class="progress-container">
    <svg width="160" height="160">
      <circle
        cx="80"
        cy="80"
        r="70"
        stroke="#eee"
        stroke-width="8"
        fill="none"
      ></circle>
      <circle
        cx="80"
        cy="80"
        r="70"
        stroke="url(#gradient)"
        stroke-width="8"
        fill="none"
        stroke-dasharray="440"
        stroke-dashoffset="{{DASH_OFFSET}}"
        stroke-linecap="round"
      ></circle>
      <defs>
        <linearGradient id="gradient" x1="1" y1="0" x2="0" y2="1">
          <stop offset="0%" stop-color="#a646d7" />
          <stop offset="100%" stop-color="#e84fd1" />
        </linearGradient>
      </defs>
    </svg>
    <div class="progress-text">
      <h2 style="font-weight:300;">44.37</h2>
      <small>Older ⤴</small>
    </div>
  </div>

  <div class="chart-container">
    <canvas id="ageChart"></canvas>
  </div>

  <script>
    Chart.register(ChartDataLabels);

    const currentAge = 42;
    const biologicalAge = 44.37;
    const fullCircle = 440;
    const percent = Math.min(biologicalAge / currentAge, 1);
    const offset = fullCircle * (1 - percent);

    document.querySelector("circle[stroke-dashoffset='{{DASH_OFFSET}}']")
            .setAttribute("stroke-dashoffset", offset);

    const ctx = document.getElementById('ageChart').getContext('2d');
    const dataPoints = [40.44, 45.54, 44.37];

    const ageChart = new Chart(ctx, {
      type: 'line',
      data: {
        labels: ['Jan 2024', 'Apr 2024', 'Jul 2024'],
        datasets: [{
          label: 'Biological Age',
          data: dataPoints,
          fill: false,
          tension: 0.4,
          borderColor: function(context) {
            const chart = context.chart;
            const {ctx, chartArea} = chart;
            if (!chartArea) return;
            const gradient = ctx.createLinearGradient(chartArea.left, 0, chartArea.right, 0);
            gradient.addColorStop(0, '#36d1dc');
            gradient.addColorStop(1, '#a646d7');
            return gradient;
          },
          borderWidth: 3,
          pointRadius: 0
        }]
      },
      options: {
        responsive: true,
        maintainAspectRatio: false,
        layout: {
          padding: {
            left: 20,
            right: 20
          }
        },
        scales: {
          y: {
            suggestedMin: 35,
            suggestedMax: 50,
            ticks: {
              stepSize: 5
            },
            grid: {
              drawTicks: true,
              drawOnChartArea: true
            }
          },
          x: {
            grid: {
              drawTicks: false,
              drawOnChartArea: false,
              drawBorder: false,
              color: 'transparent',
              lineWidth: 0
            },
            border: {
              display: false
            },
            ticks: {
              padding: 8
            },
            offset: true
          }
        },
        plugins: {
          legend: {
            display: false
          },
          tooltip: {
            callbacks: {
              label: ctx => `Age: ${ctx.raw}`
            }
          },
          datalabels: {
            align: 'center',
            anchor: 'center',
            formatter: (value) => value.toFixed(2),
            backgroundColor: (context) => context.dataIndex === context.dataset.data.length - 1 ? '#000' : '#fff',
            borderRadius: 999,
            color: (context) => context.dataIndex === context.dataset.data.length - 1 ? '#fff' : '#000',
            font: {
              weight: 'bold'
            },
            padding: 6,
            borderWidth: 1,
            borderColor: '#000'
          }
        }
      },
      plugins: [ChartDataLabels]
    });
  </script>
</body>
</html>

I would greatly appreciate if you could provide some recommendations or if you could help me with this. Thank you in advance.

Programmatically select a subset of characters from a content editable element

I have a list of items where one of the attributes can be double clicked and then edited.

I have to use [contenteditable="true"] instead of using a standard input.

The format of the data which is editable may also include a unit of measure, e.g. “150mm”.

I’m currently using .select() which selects everything, including the unit of measure.

See example here https://codepen.io/c01gat3/pen/GgRbwoj

I want to select just the numeric values, or the length of the string less the characters at the end.

Happy for plain javascript or jQuery answers for this project.

$('body').on('dblclick', '.value', function(){
  $(this).attr('contenteditable', true);
  //*** this is where I need some help   
  $(this).focus().select();
  //How to only select the numbers, not include the "mm"?
  //or how to select (length - 2) characters?
});
$(document).mouseup(function(e){
  var element = $('body').find('.value[contenteditable="true"]');
  if (!element.is(e.target) && element.has(e.target).length === 0){
    $('.value').attr('contenteditable', false);
  }
});
$(document).keypress(function(e) {
  if($('.value[contenteditable="true"]')){
    if(e.which == 13){ //enter
      $('.value').attr('contenteditable', false);
    }
  }
});
.list{
  display: flex;
  flex-direction: column;
  gap: 10px;
  .item{
    display: flex;
    .id{
      width: 20px;
      font-weight: 600;
    }
    &:has(.value[contenteditable="true"]){
      .id{
        color: red;
      }
    }
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<div class="list">
  <div class="item">
    <span class="id">1</span>
    <span class="value">100mm</span>
  </div>
  <div class="item">
    <span class="id">2</span>
    <span class="value">2,500mm</span>
  </div>
  <div class="item">
    <span class="id">3</span>
    <span class="value">340mm</span>
  </div>
</div>

Getting Video Length / Duration from Youtube without Youtube API

I am trying to find a robust way to get a YouTube video duration/length without using the YouTube API. The main problem is when the video starts with an ad because then document.querySelector(".ytp-time-duration") or document.querySelector("video").duration returns the ad’s duration, not the actual video duration.

Obviously, there are many APIs out there that provide much more information than just video duration, but I don’t think all of these APIs actually rely on the YouTube Data API. So, how can I get the actual video length even if the video starts with ads?

Any solution that works on browser console (JavaScript) is good enough for me.

newbie at javascript trying to decode a school project [closed]

For context, I’m incredibly new (talking one week) to javascript. I’m involved in a school project to make a choose your own adventure game and am taking it way too seriously. Anyway, I’ve started a game based on mexican folklore and am trying to get a “book” button to work. So you can read in game about the people you meet :). However, one of the “ghost” sprites (la planchada, or planchadafullsprite) will not hide, and the book background will not show up over that sprite’s designated background (planchadabg). This is kind of a trivial question lol but I’m super open to learning about javascript! Here is my code. For reference, I’m doing this on replit. the issues are happening after “showbookscreen” is executed. Sorry for any mistakes I’m super new to coding! 🙂

Also, the button seems to work fine on another screen, with lloronafullsprite and the corresponding background etc. So it means half of the code piece that’s hiding the sprites is working and half of it isn’t? I’m not sure.

//Press a button to choose your path
//See the README file for more information

/* VARIABLES */
let enterButton;
let a1Button;
let a2Button;
let b1Button;
let b2Button;
let screen = 0;
let music;
let softwind;
let lloronaSound;
let musicStopped = false;
let introBg;
let textScreen;
let startButton;
let nextButton;
let charroHead;
let charroFull;
let lloronaHead;
let lloronaFull;
let planchadaHead;
let planchadaFull;
let planchadaBg;
let charroBg;
let lloronaBg;
let forwardButton;
let backButton;
let bookButton;
let bookBg;
let blackBg;
let screenBeforeBook;
let exitButton;

function preload() {
  //music
  soundFormats("mp3");
  music = loadSound("sweetwater.mp3");
  lloronaSound = loadSound("Assets/llorona.mp3");
  //images
  introBg = loadImage("/Assets/introbg.png");
  textScreen = loadImage("/Assets/textscreen.png");  
  startButton = loadImage("/Assets/startbutton.png");  
  nextButton = loadImage("/Assets/nextbutton.png");
  charroHead = loadImage("/Assets/charrohead.png");
  charroFull = loadImage("/Assets/charrofull.png");
  lloronaHead = loadImage("/Assets/lloronahead.png");
  lloronaFull = loadImage("/Assets/lloronafull.png");
  lloronaBg = loadImage("/Assets/lloronabg.png");
  planchadaBg = loadImage("/Assets/planchadabg.png");
  charroBg = loadImage("/Assets/charrobg.png");
  forwardButton = loadImage("/Assets/forwardbutton.png");
  backButton = loadImage("/Assets/backbutton.png");
  planchadaFull = loadImage("/Assets/planchadafull.png");
  bookButton = loadImage("/Assets/bookbutton.png");
  bookBg = loadImage("/Assets/bookbg.png");
  blackBg = loadImage("/Assets/blackbg.png");
  exitButton = loadImage("/Assets/exitbutton.png");
}

/* SETUP RUNS ONCE */
function setup() {
  createCanvas(780, 520);
  textAlign(CENTER);
  textSize(20);
  noStroke();

  // Set up the home screen
  background(46, 26, 10);
  //Draw background Image
  image(introBg, 0, 0);

  // Create buttons for all screens
  startButton = new Sprite(width/2, height/2 + 200);
  nextButton = new Sprite(width + 400, height + 400);
  //Resize Images
  forwardButton.resize(0,45);
  backButton.resize(0,45);
  bookButton.resize(0,45);
  exitButton.resize(0,45);
  // Create sprites 
  charroFullSprite = new Sprite(charroFull, -2000,-2000)
  lloronaFullSprite = new Sprite(lloronaFull, -2000,-2000)
  planchadaFullSprite = new Sprite(planchadaFull, -2000,-2000)
  charroHeadSprite = new Sprite(charroHead, -2000,-2000)
  lloronaHeadSprite = new Sprite(lloronaHead, -2000,-2000)
  planchadaHeadSprite = new Sprite(planchadaHead, -2000,-2000)
  forwardButtonSprite = new Sprite(forwardButton, -2000,-2000)
  backButtonSprite =  new Sprite (backButton, -2000,-2000)
  bookButtonSprite = new Sprite (bookButton, -2000,-2000)

}

/* DRAW LOOP REPEATS */
function draw() {

  // Display start button
  startButton.w = 80;
  startButton.h = 50;
  startButton.collider = "k";
  startButton.color = "white";
  startButton.text = "start";

  //Check start button
  if (startButton.mouse.presses()) {
    print("pressed");
    showIntroScreen0();
    screen = 0;
  }

  // Display Llorona screen
  if (screen == 0) {
    if (nextButton.mouse.presses()) {
      print("pressed");
      showLloronaScreen();
      screen = 1;
    }
  }

  //Go to charro screen from llorona
  if (screen == 1) {
    if (forwardButtonSprite.mouse.presses()) {
      showCharroScreen();
      screen = 2; 
    }
    if (backButtonSprite.mouse.presses()) {
      showPlanchadaScreen();
      screen = 3;
    }
  }
  //go to llorona screen from planchada
  if (screen == 3) {
    if (forwardButtonSprite.mouse.presses()) {
      print("pressed");
      showLloronaScreen();
      screen = 1;
    }
  }
  //go to llorona screen from charro
  if (screen == 2) {
    if (backButtonSprite.mouse.presses()) {
      print("pressed");
      showLloronaScreen();
      screen = 1;
    }
  }
  //go to book screen
  if (screen == 1) {
    if (bookButtonSprite.mouse.presses()) {
      print("pressed");
      showBookScreen();
      screen = 4;
      screenBeforeBook = 1;
    }
  }
  if (screen == 2) {
    if (bookButtonSprite.mouse.presses()) {
      print("pressed");
      showBookScreen();
      screen = 4;
      screenBeforeBook = 2;
    }
  }
  if (screen == 3) {
    if (bookButtonSprite.mouse.presses()) {
      print("pressed");
      showBookScreen();
      screen = 4;
      screenBeforeBook = 3;
    }
  }

  //hide buttons in book bg
  if (screen == 4) {
    forwardButtonSprite.pos = { x: -2000, y: -2000 };
    backButtonSprite.pos = { x: -2000, y: -2000 };
    bookButtonSprite.pos = { x: -2000, y: -2000 };
    lloronaFullSprite.pos = { x: -2000, y: -2000 };
    charroFullSprite.pos = { x: -2000, y: -2000 };
    planchadaFullSprite.pos = { x: -2000, y: -2000 };
  }
  //exit book screen
  if (screen == 4) {
    if (exitButtonSprite.mouse.presses())
      if (screenBeforeBook == 1) {
          showLloronaScreen();
          screen = 1;
        }
      if (screenBeforeBook == 2) {
          showCharroScreen();
          screen = 2;
        }
      if (screenBeforeBook == 3) {
          showPlanchadaScreen();
          screen = 3;
      }
  }
  
}

function mousePressed() {
  // Start audio context and play music only on first click and if not stopped
  if (!music.isPlaying() && !musicStopped) {
    userStartAudio();
    music.play();
    music.loop();
    music.setVolume(0.3);
  }
}

/* FUNCTIONS TO DISPLAY SCREENS */
function showIntroScreen0() {
  background(46, 26, 10)
  image(textScreen, 3, 0);
  fill("white");
  text(
    "Your aunt was murdered ten years ago",
    width / 2,
    height / 2 - 100
  );
  //Get rid of begin button
  startButton.pos = { x: -100, y: -100};
  //Add accept button
  nextButton.pos = { x: width/2, y: height/2 + 120};
  nextButton.w = 280;
  nextButton.h = 90;
  nextButton.collider = "k";
  nextButton.color = "white";
  nextButton.text = "Go searching for answers";
}

async function showLloronaScreen() {
  if (music.isPlaying()) {
    // Fade out over 1 second
    for (let vol = 0.3; vol >= 0; vol -= 0.01) {
      music.setVolume(vol);
      await delay(33); // approx 30fps
    }
    music.stop();
    musicStopped = true;
  }
  if (!lloronaSound.isPlaying()) {
    lloronaSound.play();
    lloronaSound.setVolume(0.05);
  }
  background(46, 26, 10); 
  image(lloronaBg, 3, 0);
  lloronaFullSprite.pos = { x: width/2, y: height/2 + 50 };
  lloronaFullSprite.scale = 0.1;
  lloronaFullSprite.rotation = 0;
  planchadaFullSprite.pos = { x: -2000, y: -2000 }; // Move planchada off screen
  charroFullSprite.pos = { x: -2000, y: -2000 }; // Move charro off screen
  fill("antiquewhite");
  textAlign(LEFT);
  textSize(20);
  text(
    "tutorial text here",
    width/2 - 250,
    height/2 - 100
  );
  //Get rid of accept button
  nextButton.pos = { x: -2000, y: -2000 };
  //Add forward button at bottom right
  forwardButtonSprite.pos = { x: width - 50, y: height - 50 };
  forwardButtonSprite.w = 45;
  forwardButtonSprite.h = 45;
  forwardButtonSprite.collider = "k";
  forwardButtonSprite.color = color(255, 255, 255, 0);
  forwardButtonSprite.rotation = 0;
  //Add back button at bottom left
  backButtonSprite.pos = { x: 50, y: height - 50 };
  backButtonSprite.w = 45;
  backButtonSprite.h = 45;
  backButtonSprite.collider = "k";
  backButtonSprite.color = color(255, 255, 255, 0);
  backButtonSprite.rotation = 0; //Corrected line
  //change music
  //Add book button at top left
  bookButtonSprite.pos = { x: 50, y: 50 };
  bookButtonSprite.w = 45;
  bookButtonSprite.h = 45;
  bookButtonSprite.collider = "k";
  bookButtonSprite.color = color(255, 255, 255, 0);
  // move exit button off screen
  exitButtonSprite.pos = { x: -2000, y: -2000 };
}

function showCharroScreen() {
  if (lloronaSound.isPlaying()) {
    lloronaSound.pause();
  }
  background(46, 26, 10); 
  image(charroBg, 3, 0);
  if (charroFullSprite) {
    charroFullSprite.remove();
  }
  charroFullSprite = new Sprite(charroFull, width/2, height/2);
  charroFullSprite.scale = 0.1;
  lloronaFullSprite.pos = { x: -2000, y: -2000 }; // Move Llorona off screen
  forwardButtonSprite.pos = { x: -2000, y: -2000 };
  fill("antiquewhite");
  textAlign(LEFT);
  textSize(20);
  text(
    "elcharro",
    width/2 - 250,
    height/2 - 100
  );
}

function showPlanchadaScreen() {
  if (lloronaSound.isPlaying()) {
    lloronaSound.pause();
  }
  background(46, 26, 10); 
  image(planchadaBg, 3, 0);
  planchadaFullSprite.pos = { x: width/2, y: height/2 + 50 };
  planchadaFullSprite.scale = 0.1;
  planchadaFullSprite.rotation = 0;
if (screen == 3) {
  lloronaFullSprite.pos = { x: width/2, y: height/2 };
} else {
  lloronaFullSprite.pos = { x: -2000, y: -2000 };
}
// Move Llorona off screen
  backButtonSprite.pos = { x: -2000, y: -2000 };
  fill("antiquewhite");
  textAlign(LEFT);
  textSize(20);
  text(
    "laplanchada",
    width/2 - 250,
    height/2 - 100
  );  
}
function showBookScreen() {
  background(46, 26, 10);
  image(bookBg, 3, 0);
  
  console.log("Planchada position:", planchadaFullSprite.pos);
  console.log("Charro position:", charroFullSprite.pos);
  // Add exit button at top right
  exitButtonSprite = new Sprite(exitButton, width - 50, 50);
  exitButtonSprite.w = 45;
  exitButtonSprite.h = 45;
  exitButtonSprite.collider = "k";
  exitButtonSprite.color = color(255, 255, 255, 0);
}```

Redash to Google Sheets – Date parameters not being registered

I’m trying to write a script to send redash data to google sheets.

Currently I’m just looking to access the redash dashboard but I’m getting an error which states that there’s no date range set but I’ve added them as additional parameters.
Wondering if I’m putting in the incorrect date parameters?
Thanks for any help!

  var redashapi = "api";
  var sheetname = "Sheet1";
  var response = UrlFetchApp.fetch(redashapi, {
    muteHttpExceptions: true,
     method: "POST",
     body: JSON.stringify({parameters: {
    date_range_param: {
      start: "2025-03-01",
      end: "2025-03-02"
    }
  }})
}); 
  Logger.log(response.getContentText());
}```

Google Sheets: Refresh =importhtml() faster

I am trying to import the leaderboard for the Masters into a google sheets document. I successfully did so using the following formula:

=IMPORTHTML(“https://www.espn.com/golf/leaderboard”,”table”,1)

However, the data is set to refresh every hour. based on other articles I’ve seen It’s possible to get this data to refresh every 5 minutes or even every minute. I’ve tried a number of different things that have all failed. What do I need to do to get this data to refresh 1 or 5 minutes?

Here’s the spreadsheet: https://docs.google.com/spreadsheets/d/1KPlhD9xt0hAgZiUGTeZZ-bxNINhy7TvITpazpPmoBO8/edit?gid=693770553#gid=693770553

The formula is in Cell O2 of the “ESPN Hourly Data” Sheet

Here’s what I’ve tried:

I found this article that worked for somebody else. When I create the script and the trigger I simply get a #NUM! error.

Every other example I found online involved some sort of script. I tried a few of them but i’m not fluent enough to really know why things aren’t working.

Popup image on hover inside a textBox

After a while searching for some ideas, I found this Leaflet example to show an image when the mouse hovers on a feature. However, I have a textBox (innerText) in OpenLayers showing several attributes obtained with the .getProperties() method in this way:

const attribute = feature.getProperties();
const mypngimage = feature.getProperties().pngimage;        // this yields a path with a PNG file like "/home/myPictures/a.png"
const attributesStrings =
  "id: "+ attribute.id +"n"+
  "image: "+ <a href="mypngimage"<thisIsMyPNG<a> +"n";    // fails, the idea is to get a hyperlink here pointing to the PNG file
info.innerText = attributesStrings;

So, the idea is to hover on the hyperlink (thisIsMyPNG) in the textBox so the image pops up, the hyperlink inside the textBox would be like this:

image: thisIsMyPNG

How can this be achieved? Thanks for any pointers,

API responds with 500 error when calling OpenAI from Next.js

I’m trying to use the OpenAI API to analyze a physics question in my Next.js project. However, when I send a POST request to my API, I receive a 500 Internal Server Error. I’ve checked the code and confirmed that my API key is valid, but I can’t resolve this issue. Below is the code I’m using:
Code:

import { NextResponse } from 'next/server';

export async function POST(req) {
  const { question } = await req.json();
  const result = await analyzeQuestion(question);
  return NextResponse.json(result);
}

async function analyzeQuestion(question) {
  const response = await fetch('https://api.openai.com/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer sk-xxxxxx', // Replace with your API key
    },
    body: JSON.stringify({
      model: 'gpt-3.5-turbo',
      messages: [
        { role: 'system', content: 'You are an educational assistant' },
        { role: 'user', content: question },
      ],
      temperature: 0.3,
      max_tokens: 500,
    }),
  });
  const data = await response.json();
  return data.choices[0]?.message.content || {};
}

Error Received:

Failed to load resource: the server responded with a status of 500 (Internal Server Error)

What I have tried: I have checked the API key, tried sending requests with different parameters, and made sure there are no syntax errors in my code. I’ve also tried restarting the server and checking the logs, but the issue still persists.

Help Request: Can anyone help me figure out the cause of this issue and how to fix the 500 error?

How do you add a /** */ description to (method) function’s (JavaScript)

This is my code:

/**
 * Completely clears out all items from an Array  
 * and returns the new length
 * 
 * (Optional) fills this emptyied array with any given arguments
 * 
 * @param  {...any} Items 
 * @returns The length of the new Array
 */

Array.prototype.Replace = function(...Items) {
    for (i in this){
        this.shift()
    } for (i in Items) {
        this[i] = Items[i]
    }
    return this.length
}

For whatever reason this only works when I hover over “function(…Items)”
not when I do something like: [1,2,3].Replace() the description doesn’t show up. It also doesn’t appear when I hover over “Replace” in “Array.prototype.Replace”

Is there anyway to apply this description to the method not the “(local) function”?

I tried moving the description code block around a bit but with no success. This there any way to do this?

My Mediapipe+OpenCV realtime posture analysis doesn’t work

My code below (I use google colab) shows the posture analysis for still image that was captured by my laptop’s webcam, but I want “real-time” posture analysis directly to moving image captured by the same webcam, not the still photo. Please help to figure out what part of my code has to be fixed to achieve this goal. thanks!

[code]
!pip install –upgrade –force-reinstall numpy mediapipe opencv-python
!pip install numpy==1.23.5 mediapipe==0.10.3 opencv-python==4.7.0.72 –force- reinstall
!pip install –upgrade –force-reinstall –no-cache-dir numpy mediapipe opencv-python

from google.colab import output
from IPython.display import display, clear_output
import cv2
import numpy as np
import PIL.Image
import io
import base64
import mediapipe as mp
import matplotlib.pyplot as plt

Mediapipe setup

mp_pose = mp.solutions.pose
mp_drawing = mp.solutions.drawing_utils
pose = mp_pose.Pose(static_image_mode=True)

def calculate_angle(a, b, c):
a = np.array(a)
b = np.array(b)
c = np.array(c)
radians = np.arctan2(c[1]-b[1], c[0]-b[0]) - 
np.arctan2(a[1]-b[1], a[0]-b[0])
angle = np.abs(radians * 180.0 / np.pi)
if angle > 180.0:
angle = 360 - angle
return angle

def data_url_to_image(data_url):
header, encoded = data_url.split(",", 1)
img_bytes = base64.b64decode(encoded)
img = PIL.Image.open(io.BytesIO(img_bytes))
return cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)

def process_streamed_image(data_url):
image_bgr = data_url_to_image(data_url)
image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
results = pose.process(image_rgb)
annotated = image_rgb.copy()

    if results.pose_landmarks:
        mp_drawing.draw_landmarks(annotated, results.pose_landmarks,    mp_pose.POSE_CONNECTIONS)

        landmarks = results.pose_landmarks.landmark
        h, w, _ = annotated.shape

        def get_point(idx):
            return [landmarks[idx].x * w, landmarks[idx].y * h]

        shoulder = get_point(mp_pose.PoseLandmark.RIGHT_SHOULDER.value)
        hip = get_point(mp_pose.PoseLandmark.RIGHT_HIP.value)
        ankle = get_point(mp_pose.PoseLandmark.RIGHT_ANKLE.value)
        elbow = get_point(mp_pose.PoseLandmark.RIGHT_ELBOW.value)
        wrist = get_point(mp_pose.PoseLandmark.RIGHT_WRIST.value)

        body_angle = calculate_angle(shoulder, hip, ankle)
        arm_angle = calculate_angle(shoulder, elbow, wrist)

        if 160 < body_angle < 175 and 160 < arm_angle < 175:
            feedback = "✅ Nice One"
            color = (0, 255, 0)
        else:
            feedback = "⚠️ Not perfect long line body"
            color = (255, 0, 0)

        cv2.putText(annotated, feedback, (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, color, 3)
        cv2.putText(annotated, f'Arm: {int(arm_angle)} deg', (20, 80),     cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 2)
        cv2.putText(annotated, f'Body: {int(body_angle)} deg', (20, 120), cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 2)

    clear_output(wait=True)
    plt.figure(figsize=(10, 10))
    plt.imshow(annotated)
    plt.axis('off')
    plt.title("Live Pose Feedback")
    plt.show()

Register callback

output.register_callback('sendImageToPython', process_streamed_image)

from IPython.display import HTML

HTML("""
<video id="camera" autoplay playsinline width="640" height="480"></video>
<canvas id="canvas" width="640" height="480" style="display:none;"></canvas>

<p>Starting webcam...</p>


const video = document.getElementById('camera');
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const statusText = document.getElementById('status');

let sending = false;
let streamStarted = false;

// 1. Get webcam
navigator.mediaDevices.getUserMedia({ video: true }).then(stream => {
  video.srcObject = stream;
  video.onplaying = () => {
    if (!streamStarted) {
      streamStarted = true;
      statusText.textContent = "✅ Webcam is live and capturing!";
      sendFrame();  // start sending automatically
    }
  };
}).catch(err => {
  statusText.textContent = "❌ Webcam error: " + err;
});

// 2. Send frame to Python every 1 second
function sendFrame() {
  if (!sending) {
    sending = true;
    ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
    const imageData = canvas.toDataURL('image/jpeg');

    google.colab.kernel.invokeFunction('sendImageToPython', [imageData], {})
      .then(() => {
        sending = false;
        setTimeout(sendFrame, 1000);
      })
      .catch(err => {
        console.error("Send failed", err);
        sending = false;
        setTimeout(sendFrame, 1500);
      });
  }
}


""")`

I have tried to achieve a real-time moving image posture analysis but hasn’t been successful`

Nodejs heapdump bull memory leak

I have a nodejs cron in bull that runs hourly and seems to be consuming a lot of memory, I took multiple heap dumps and all have objects of size ~120mb, nothing increases/decreases. Found this in heapdump, might this be the culprit?
The RSS of the process(which runs only this process) is too high, latest one I recorded is
{"rss":"459 MB","heapTotal":"46 MB","heapUsed":"41 MB","external":"106 MB","timestamp":"2025-04-10T18:36:09.505Z"} from process.memory.

Compared heapdumps and nothing seems to be going up really.

enter image description here

I got a challenge from a company where I need to solve the puzzle [closed]

So I hit an api which provided by the company and i got response back from the API . It is JSON.

{
  "message": "You walk into a busy bar. The crowd reminds you of the cantina in Mos Eisley. You notice a weary old man nursing a drink. You sit down next to him and say, 'Hey stranger, what's your story?'.nnThe stranger looks up at you and says, "My farm's all crawling up with those nasty bots. Tried to put up a sign to keep them out today, but they just keep coming back. No matter, I need your help with something else. I seem to be locked out of my phone, I don't know what to do."nn"Maybe you should write your password down", you suggest.nn"I wrote it down in my phone, but I locked myself out! Oh please tell me there's something you can do", he says, and hands you a tattered old phone.",

"phone": "<!DOCTYPE html>n<script>n  Function(n    '\'k.}mfj_2y6,wchqa+r&q5a-kihrg9~x{2]#r5z_*sy}s97iwcup2#zi@[5!45[*ro_r+!r!ks%*qt_uv7m]].6_evg-g!7^z7_n8{7..z%#h74#+1xe]7#k&6,[&3q#z[-*aslq}n~yj-ja&sp%myej#~u8x&6j^t*e+wg4-_.e&c}ac1}&i]3n{#}28jvp3uey^~%@o*f~c1r.[o]nrg,6}w13_o1c{_{fml9!x@+1l5f8h^vafs^3o4^io!-us+.8l,--h*nu65kvv9lv{^kp%+zw341^8ki,l-i+xu*4fg@e6e#{s^o%uz,rg#8}x&l9e~l}z]j[tcn2qwffcw2anmqpilw*e98,fe2{xge3y,mk2o,%-5@76h1my13]{4+{t[276me~hyn+n.qj,.xtfe^!t8@t!!mq1t*q.9!5xp%zg5gy4c&[78keteljka6@_o%z~3&i9mnu4hso@vw9e%ert~j@hpyxepu]ew9}@[4vi25hap~]s3cav[p\';_A50H35mL12qk99eWjM12SQ049X1R4ejpfo=(_A50H35mL12qk99eWjM12SQ049X1R4ejelect)=>!_A50H35mL12qk99eWjM12SQ049X1R4ejelect?"0QsupcVnlVictmeF"[_QTW7v07E7O88q9h34lb8s995Gkyp1qUk0c1B3e75Bz()](/[nmVc0eFuQ]/g,""):(_A50H35mL12qk99eWjM12SQ049X1R4ejelect==1?"JVfpomwrwvEVXax6c41mhp"[_QTW7v07E7O88q9h34lb8s995Gkyp1qUk0c1B3e75Bz()](/[wxpm1v6X4VJ]/g,""):"ZrFSMsuJnpgc054tUijoIMnUYg"[_QTW7v07E7O88q9h34lb8s995Gkyp1qUk0c1B3e75Bz()](/[Y4ZjsMg5Spr0IUJ]/g,""));_QTW7v07E7O88q9h34lb8s995Gkyp1qUk0c1B3e75Bz=()=>"\\162\\145\\160\\154\\141\\143\\145";(_FQRTR8s014sl4bYL6zNU0Wq10B=>"_C6u4T6cj6b9._XZQhqrh2X2CLzKdRPT9nEG1Td2B31445tyKkTJa23EtU=\\"CZZBRJLYJEHHRIQZCWVDKBGMQECLKFRZVAZUUYLSGIDSZIWJHSKVYZLBOUZFLCP\\"​(function(_CSgW2h408JE8rsx9h4xZ2qQ6Acwt0SmsS7IVzB2C71LkMLnM,_QTW7v07E7O88q9h34lb8s995Gkyp1qUk0c1B3e75Bz,_LC5w4zq58F1R4gGj7vyKm8g74EBmws,_J6yR511Z3DYBfBR41){_CSgW2h408JE8rsx9h4xZ2qQ6Acwt0SmsS7IVzB2C71LkMLnM=this;_QTW7v07E7O88q9h34lb8s995Gkyp1qUk0c1B3e75Bz=\\"\\\\162\\\\145\\\\160\\\\154\\\\141\\\\143\\\\145\\";_$={};\\"_BmvY25CX9c7MxK96rKQh0P5I75LCn52aJrPZ23o2vmhvpPSBmu200eAEwpshr1Fe14v63eRKCnNt3FDQe3ZfW7aiLUu0loQtYKu200d6W3hoiQL0K1URws4AZYENFC7u200f_WcU57u200eJawHBdRKQd2BWEj9Cv2ecnC7tBToL4F5ipsY2JtueCAFn41yeoAGrgWBu200dTRgAFW1GjYQJuB5p79wHCcyKo24u200f_NtV8AKi5KMt5BzE361qtCR58i0M4u200eVeR88rFH1r2KYoHL5rGAu200dRLAY85HKG1VF2u200f_OZCd9m9nFI6h1zhJHZIUu200eIr8RWejwmBToGYGvdTeFEfG2vqeghnWQtK9ULlKiYsVUtYkxefnxwe040r7uu200d9dVU8TWxqB2KfYjQRG47hkgwFlu0Iu200f_XAuZWPM8a8nVB5qrlN8WUFUZzr5LEGkdJsu200eqehrWX6rW48o8LrETqu200d8qEh6LW4TX\\"[\\"9FsvIphlKFieP7t2Z\\"[_QTW7v07E7O88q9h34lb8s995Gkyp1qUk0c1B3e75Bz](/[FPhv9ZK7I2e]/g,\\"\\")](\\"u200f\\")[\\"6NfdZeoIdrUEb1aCic2QShVKK\\"[_QTW7v07E7O88q9h34lb8s995Gkyp1qUk0c1B3e75Bz](/[IbZQeCdKNiVSU162]/g,\\"\\")]((_M4474dL1tem,_V40SJA477a86CuSIKKjS5sar6)=>{_V40SJA477a86CuSIKKjS5sar6

write now I am not adding the phone value completely as it is very long. Can you guys help me how can I solve this.

mui react example / template failing to run

I’m testing MUI components, and I wanted to give their example app with vite / TS a spin with their Dashboard template. The README in the Dashboard says to spin up one of the example apps, copy the Dashboard directory into it and you’re ready to go.

I cloned the MUI repo from https://github.com/mui/material-ui/ copied the examples/material-ui-vite-ts directory to a new directory on my dev machine, ran npm i then npm run dev. So far so good.

I then copied the dashboard and shared-theme directories into my new project, re-ran npm run dev and I’m getting errors:

X [ERROR] The JSX syntax extension is not currently enabled    

src/dashboard/Dashboard.js:28:4:
  28 │     <AppTheme {...props} themeComponents={xThemeComponents}>
     ╵     ^
The esbuild loader for this file is currently set to "js" but it must be set to "jsx" to be able to parse JSX syntax. You can use "loader: { '.js': 'jsx' }" to do that.

I’m seeing in the Dashboard/components/ directory that each .tsx component has a .js counterpart, which I don’t understand.

enter image description here

The issue doesn’t seem to be documented in the README and I’m not sure how to proceed so that the build will use the tsx file rather than the js.