JavaScript works on laptop, not on phone [closed]

I have some code on my website that does lookups of state information using the state name abbreviation (e.g., ‘AL’) as the key into a JavaScript Map. The Map is populated with the set() function, like stateTaxMap.set(‘AL’, 0.075). Creating the Map works on both my windows laptop and my phone, and the lookup works on the laptop, but fails on a phone. Can anybody at least point me to somewhere to look? Thanks very much.

i am new to react and facing this problem [closed]

react-dom-client.development.js:4442 Uncaught Error: A React Element from an older version of React was rendered. This is not supported. It can happen if:

  • Multiple copies of the “react” package is used.
  • A library pre-bundled an old copy of “react” or “react/jsx-runtime”.
  • A compiler tries to “inline” JSX instead of using the runtime.

Open Android app with browser if app is installed else open playstore

I don’t have much knowledge of javascript.
What I need to do is replace Firebase DeepLink

From a web page (html), open an android app if it exists, passing a parameter (This works in the app)

<a href='app://com.mycompany.myapp?jq=e44759b5-088b-41ea-9b81-faabcc0c7fe6'>Open myapp if it exists and send a parameter --> OK</a>

If the app is NOT installed, it should be redirected to google playstore and send the referrer (This works in the app)

<a id="market" href="market://details?id=com.mycompany.myapp&referrer=jq%e44759b5-088b-41ea-9b81-faabcc0c7fe6">Goto google play with referrer Ok</a>

Everything works great, if you touch the hrefs.

I implemented in $(document).ready that when navigator.userAgent is Android it executes the Android(); function.

  • In Chrome 133 0 6943 137, it works fine, except that when it redirects to Google Play to install the app, a sign appears “Do you want to continue to Google Play?”.
  • In Firefox 135 0 1, it works fine, except that when it redirects to Google Play to install the app, a sign appears “Do you want to continue to Google Play?”.
  • In Chrome 133 0 6943 138, it does not redirect to Google Play.
  • In Opera 87 6 4607 83252, it does not redirect to Google Play.

What I need is for it to navigate directly to Google Play, just like Firebase DeepLink does. (@Google give me the solution, since you are deprecating the service in August 2025)

function Android() {

    const appURL = 'app://com.mycompany.myapp?jq=e44759b5-088b-41ea-9b81-faabcc0c7fe6';
    const playStoreURL = 'https://play.google.com/store/apps/details?id=com.mycompany.myapp&referrer=jq%e44759b5-088b-41ea-9b81-faabcc0c7fe6';

    // Intenta abrir la app
    window.location.href = appURL;

    // Si la app no está instalada, redirige directamente al Store después de un tiempo
    setTimeout(() => {
        if (!document.hidden) {
            market.click(); // Simula un clic en el enlace
        }
    }, 1500); // Espera 1500ms antes de redirigir

    // Verifica si la página se oculta (indica que la app se abrió)
    document.addEventListener('visibilitychange', () => {
        if (document.hidden) {
            console.log('La app se abrió correctamente.');
        }
    });
}

On the other hand, in browsers that do not redirect to Google Play, I tap the first href (id=”market”) and it navigates perfectly. I really don’t understand

FabricJS when adding path to Eraser, it doesnt show

In FabricJS with erase, I want to create like an interactive whiteboard thats the same between users. I do this using websockets. When I draw a line, everything goes well, but when I try to send a new Erased line, it adds in the object, but it doesn’t show.

The code in the websocket:

let drawingObject = paintCanvas._objects.find(
        (obj) => obj.id === drawingId
      );
      console.log(drawingObject);
      let pathArray = [];
      for (let erasePath of data.path) {
        let pathArr = [];
        pathArr.push(erasePath[0]);
        for (let i = 1; i < erasePath.length; i++) {
          if (i % 2 === 0) {
            pathArr.push(erasePath[i] * width);
          } else {
            pathArr.push(erasePath[i] * height);
          }
        }
        pathArray.push(pathArr);
      }
      console.log(pathArray);
      let pathObject = new fabric.Path(pathArray, {
        angle: 0,
        backgroundColor: "",
        erasable: true,
        fill: null,
        fillRule: "nonzero",
        flipX: false,
        flipY: false,
        globalCompositeOperation: "destination-out",
        height: data.transform.height * height,
        left: data.transform.x * width,
        name: "done",
        opacity: 1,
        originX: "left",
        originY: "top",
        paintFirst: "fill",
        pathOffset: {
          x: data.transform.pathOffsetX * width,
          y: data.transform.pathOffsetY * height,
        },
        scaleX: 1,
        scaleY: 1,
        shadow: null,
        skewX: 0,
        skewY: 0,
        stroke: "black",
        strokeDashArray: null,
        strokeDashOffset: 0,
        strokeLineCap: "round",
        strokeLineJoin: "round",
        strokeMiterLimit: 10,
        strokeUniform: false,
        strokeWidth: data.transform.strokeWidth,
        top: data.transform.y * height,
        type: "path",
        version: "5.2.1",
        visible: true,
        width: data.transform.width * width,
      });
      console.log(pathObject);
      console.log(drawingObject.eraser);
      if (drawingObject.eraser) {
        drawingObject.eraser._objects.push(pathObject);
        drawingObject.eraser.eraseChildren++;
      } else {
        let eraser = new fabric.Eraser([pathObject], {
          selectable: false,
          angle: 0,
          scaleX: 1,
          scaleY: 1,
          zoomX: 2,
          zoomY: 2,
          skewX: 0,
          skewY: 0,
          flipX: false,
          flipY: false,
          eraseChildren: 1,
        });
        drawingObject.set("eraser", eraser);
      }
      console.log(drawingObject.eraser);
      paintCanvas.renderAll();
    }

this is the code i use. When I look at the object data when it tries to add the new path through the websocket, it is the same as when I refresh the page and get the same data out of the database.
The width, height and other points get calculated based on the width and height of the canvas. This works fine with for example the drawing because the canvas is always 16:9

If you look at my code for adding the paths to an Eraser object at loading, it is almost identical. The only difference is I do see it when loading, but not through the websocket

The code at the start:

let drawings = data.drawings;
        // console.log(drawings);
        // if (drawings.length === 0) {
        //   return;
        // }
        for (let drawing of drawings) {
          let newPathArray = drawing.path;
          let pathArray = [];
          for (let path of newPathArray) {
            let pathArr = [];
            pathArr.push(path[0]);
            for (let i = 1; i < path.length; i++) {
              if (i % 2 === 0) {
                pathArr.push(path[i] * width);
              } else {
                pathArr.push(path[i] * height);
              }
            }
            pathArray.push(pathArr);
          }
          console.log({
            x: drawing.transform.x * width,
            y: drawing.transform.y * height,
            strokeWidth: drawing.transform.strokeWidth,
            color: drawing.transform.color,
            width: drawing.transform.width * width,
            height: drawing.transform.height * height,
            pathOffsetX: drawing.transform.pathOffsetX * width,
            pathOffsetY: drawing.transform.pathOffsetY * height,
          });
          let transform = drawing.transform;
          let drawingObject = new fabric.Path(pathArray, {
            id: drawing.id,
            fill: null,
            stroke: transform.color,
            strokeWidth: transform.strokeWidth,
            strokeDashArray: null,
            strokeLineCap: "round",
            strokeLineJoin: "round",
            strokeMiterLimit: 10,
            left: transform.x * width,
            top: transform.y * height,
            scaleX: transform.width,
            scaleY: transform.height,
            selectable: false,
            width: transform.width * width,
            height: transform.height * height,
            pathOffset: {
              x: transform.pathOffsetX * width,
              y: transform.pathOffsetY * height,
            },
            scaleX: 1,
            scaleY: 1,
            zoomX: 2,
            zoomY: 2,
            eraser: false,
          });
          let eraser = drawing.eraser;
          eraser = JSON.parse(eraser);
          // let eraser = [];
          if (eraser.length === 0) {
          } else {
            console.log(eraser);
            let eraserPaths = [];
            for (let erase of eraser) {
              console.log(erase);
              let pathArray = [];
              for (let erasePath of erase.path) {
                let pathArr = [];
                pathArr.push(erasePath[0]);
                for (let i = 1; i < erasePath.length; i++) {
                  if (i % 2 === 0) {
                    pathArr.push(erasePath[i] * width);
                  } else {
                    pathArr.push(erasePath[i] * height);
                  }
                }
                pathArray.push(pathArr);
              }
              let pathObject = new fabric.Path(pathArray, {
                ownCaching: false,
                angle: 0,
                backgroundColor: "",
                erasable: true,
                fill: null,
                fillRule: "nonzero",
                flipX: false,
                flipY: false,
                globalCompositeOperation: "destination-out",
                height: erase.transform.height * height,
                left: erase.transform.x * width,
                name: "done",
                opacity: 1,
                originX: "left",
                originY: "top",
                paintFirst: "fill",
                path: pathArray,
                pathOffset: {
                  x: erase.transform.pathOffsetX * width,
                  y: erase.transform.pathOffsetY * height,
                },
                scaleX: 1,
                scaleY: 1,
                shadow: null,
                skewX: 0,
                skewY: 0,
                stroke: "black",
                strokeDashArray: null,
                strokeDashOffset: 0,
                strokeLineCap: "round",
                strokeLineJoin: "round",
                strokeMiterLimit: 10,
                strokeUniform: false,
                strokeWidth: erase.transform.strokeWidth,
                top: erase.transform.y * height,

                visible: true,
                width: erase.transform.width * width,
              });

              eraserPaths.push(pathObject);
            }

            let eraserObject = new fabric.Eraser(eraserPaths, {
              ownCaching: false,
              angle: 0,
              selectable: false,
              scaleX: 1,
              scaleY: 1,
              zoomX: 1,
              zoomY: 1,
              skewX: 0,
              skewY: 0,
              flipX: false,
              flipY: false,
              eraseChildren: eraserPaths.length,
            });
            // drawingObject.set("eraser", eraserPaths);

            // console.log(eraserObject);
            drawingObject.set("eraser", eraserObject);
            drawingObject.set("zoomX", 1);
            drawingObject.set("zoomY", 1);
          }
          paintCanvas.add(drawingObject);
        }

As you can probably see, I added a lot of properties. These come from looking at working paths, but removing them doesnt change anything visually. How can I make the erase lines sync through the websocket?

Handle disconnects in multiplayer JavaScript game

I am creating an online multiplayer game in JavaScript (JS), think Lichess or Chess.com but for another game. I now want to detect if a user disconnects but having trouble figuring out how to do this reliably. It doesn’t matter if user closes the tab, the window, or loses internet connection. I need to know if any of the events happen. However, they should be allowed to switch tabs, windows or similar, as long as they don’t close the game.

I use socket.io for websocket communication.

Problems and what I have tried

So far I have tried some different solutions:

  1. Handle it in sockets disconnect event: socket.on('disconnect', () => { console.log('User disconnected) }); But this is not reliable and doesn’t always fire.

  2. Using a ping/pong system where client sends a signal to server to let it know it is alive. But if I switch tab or window it seems that JS starts throttling, or even stops completely.

    socket.on("connect", () => {     
        if (!heartbeatInterval) {
            heartbeatInterval = setInterval(() => {
                socket.emit("pong");
            }, 4000);
        }
    });
    
  3. To get around the problem in point 2 I tried using a Web Worker. The problem with that is that even if I closes a tab or window it keeps going. I tried stopping it in window.addEventListener("beforeunload", () => {... but it doesn’t always fire, so basically opposit problem to point 2.

     heartbeatWorker = new Worker('/heartbeatWorker.js');
     heartbeatWorker.onmessage = () => {
         socket.emit("pong");
     };
     heartbeatWorker.postMessage('start');
    

Question

How can I create a reliable disconnect system similar to Lichess or Chess.com with above requirements?

All the services return as a undefined in Global Interceptor in NEST JS

I am trying to create a global interceptor in NestJS and call a service inside it. I have followed all the documented steps, but all the services used within the interceptor are still returning as undefined.

import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from "@nestjs/common";
import { Observable } from "rxjs";
import { tap } from "rxjs/operators";
import { SerialLoggerService } from "@/core/logging/seri-logger.service";
import { DeviceService } from "@/modules/device/device.service";

@Injectable()
export class HistoryTrackingInterceptor implements NestInterceptor {
  constructor(
    private logger: SerialLoggerService,
    private readonly deviceService: DeviceService,
  ) {}

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    try {
      const request = context.switchToHttp().getRequest();
      const method = request.method;

      console.log("Logger Init: ", this.logger);
      this.logger?.log(`Request Method: ${method}`);
      console.log("Device Service Init: ", this.deviceService);

      return next.handle().pipe(
        tap(() => {
          console.log('Request processing completed');
        })
      );
    } catch (error) {
      console.log(error);
      return next.handle();
    }
  }
}

I have used the correct @Inject decorator for the services, and all the services work perfectly elsewhere. This issue only occurs with the interceptor.

  providers: [
    AppService,
    {
      provide: APP_INTERCEPTOR,
      useClass: HistoryTrackingInterceptor,
    },
   ]

Can anyone help me to understand what went wrong?

Bundled React application doesn’t render in WebKit despite support for modern JavaScript features?

Problem

I’ve been developing a React application that works fine in Chrome and Firefox, but fails to render in WebKit-based browsers. The WebKit instance is running in C++ as an overlay atop a Gstreamer video stream using GTK for window handling. The strange part is that WebKit supports all the modern JavaScript features React requires from what I can tell.

What Doesn’t Work

  • Bundled React application (created with npm build) doesn’t render in WebKit
  • No console errors are displayed, the app simply doesn’t render anything.
  • I can verify webkit is running, it is even hosting a HTML overlay / page. Normal HTML and javascript will run. It is the react elements that will not load.
  • This is despite the fact that WebKit supports all modern JavaScript features React needs

Key Findings

  1. WebKit environment (WebKit/605.1.15) supports all modern JavaScript features
  2. The issue is specific to how bundled React applications are loaded in WebKit
  3. Loading React directly from CDN works perfectly in the same browser
  4. Using React.createElement() instead of JSX syntax avoids compatibility issues

Current Workaround

I’m currently using a CDN-based approach that:

  • Loads React directly from unpkg.com
  • Uses vanilla JavaScript with React.createElement() instead of JSX
  • Implements the functionality without a build step
  • Works reliably in WebKit

Environment Details
React: v18.3.1
React DOM: v18.3.1
Webpack: v5.98.0
Babel: v7.26.x with @babel/core v7.26.9
React Scripts: v5.0.1
Using babel-loader (v10.0.0)

Question

While my workaround is functional, I’d prefer to use my build system for consistency across environments. What could be causing bundled React to fail in WebKit despite the browser supporting all necessary JavaScript features? How can I modify my build process to be WebKit-compatible?

Any insights would be greatly appreciated!

How to Implement Text Summarization in a Chrome Extension Using OpenAI API?

I am currently working on a Chrome extension called Summarizer. The extension allows users to highlight a paragraph and summarize it. I am using the OpenAI API for summarization, but I am facing issues with the API integration and its cost. I need help fixing my code to ensure that the summarization works correctly.

Here’s how my extension works:

The user highlights a paragraph.

A “Summarize It?” button appears near the highlighted text.

When clicked, the button sends the highlighted text to the OpenAI API for summarization.

The summarized text is displayed in an alert and saved in the sidebar history.

I have already implemented most of the features, but I am stuck on the summarization logic. Here are my files:

background.js

chrome.runtime.onInstalled.addListener(() => {
    chrome.sidePanel
        .setPanelBehavior({ openPanelOnActionClick: true })
        .catch((error) => console.error("Side Panel Error:", error));
});

content.js

document.addEventListener("mouseup", function (event) {
    let selectedText = window.getSelection().toString().trim();
    let existingButton = document.getElementById("summarize-btn");
    
    // Remove existing button if text is deselected
    if (!selectedText) {
        if (existingButton) existingButton.remove();
        return;
    }
    
    // If the button already exists, reposition it
    if (!existingButton) {
        existingButton = document.createElement("button");
        existingButton.id = "summarize-btn";
        existingButton.innerText = "Summarize It?";
        existingButton.style.position = "absolute";
        existingButton.style.zIndex = "1000";
        existingButton.style.background = "#ff5722";
        existingButton.style.color = "white";
        existingButton.style.border = "none";
        existingButton.style.padding = "8px";
        existingButton.style.cursor = "pointer";
        existingButton.style.borderRadius = "5px";
        existingButton.style.boxShadow = "2px 2px 5px rgba(0,0,0,0.2)";
        document.body.appendChild(existingButton);
    }
    
    // Position the button near the highlighted text
    let rect = window.getSelection().getRangeAt(0).getBoundingClientRect();
    existingButton.style.top = `${rect.bottom + window.scrollY + 5}px`;
    existingButton.style.left = `${rect.left + window.scrollX}px`;

    // Add click event to summarize text
    existingButton.onclick = async function () {
        existingButton.innerText = "Summarizing...";
        let summary = await summarizeText(selectedText);
        alert("Summary:n" + summary);
        existingButton.remove();
    };

    // Hide the button when clicking elsewhere
    document.addEventListener("click", function removeBtn(event) {
        if (!summarizeBtn.contains(event.target)) {
            summarizeBtn.remove();
            document.removeEventListener("click", removeBtn);
        }
    });
});

async function summarizeText(text) {
    const apiKey = "The api key"; // Replace with your actual API key
    const url = "https://api.openai.com/v1/chat/completions";

    try {
        const response = await fetch(url, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "Authorization": `Bearer ${apiKey}`
            },
            body: JSON.stringify({
                model: "gpt-3.5-turbo",
                messages: [{ role: "user", content: `Summarize this: ${text}` }],
                max_tokens: 100
            })
        });

        if (!response.ok) {
            let errorMsg = await response.text(); // Get error details
            console.error("API Error:", errorMsg);
            throw new Error("API Request Failed: " + errorMsg);
        }

        const data = await response.json();
        return data.choices?.[0]?.message?.content || "Error summarizing text.";
    } catch (error) {
        console.error("Summarization error:", error);
        return "Error summarizing text.";
    }
}

manifest.json

{
    "manifest_version": 3,
    "name": "Summarizer",
    "version": "1.0",
    "description": "Quickly summarize and save important text.",
    "permissions": ["storage", "sidePanel"],
    "action": {
        "default_icon": {
            "48": "icons/icon48.png",
            "128": "icons/icon128.png"
        }
    },
    "side_panel": {
        "default_path": "sidebar.html"
    },
    "background": {
        "service_worker": "background.js"
    },
    "content_scripts": [
        {
            "matches": ["<all_urls>"],
            "js": ["content.js"],
            "run_at": "document_end"
        }
    ]
}

sidebar.html

<!DOCTYPE html>
<html>
<head>
    <title>Summary History</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            padding: 10px;
            width: 300px;
        }
        .summary-item {
            border-bottom: 1px solid #ddd;
            padding: 10px;
            margin-bottom: 10px;
        }
        button {
            background-color: #f44336;
            color: white;
            border: none;
            padding: 5px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <h2>Summary History</h2>
    <div id="summary-list"></div>
    <script src="sidebar.js"></script>
</body>
</html>

sidebar.js

document.addEventListener("DOMContentLoaded", function () {
    const summaryList = document.getElementById("summary-list");

    function loadSummaries() {
        chrome.storage.local.get(["summaries"], function (result) {
            summaryList.innerHTML = ""; // Clear the list before reloading
            const summaries = result.summaries || [];
            summaries.forEach((summary, index) => {
                displaySummary(summary, index);
            });
        });
    }

    function displaySummary(summary, index) {
        const summaryItem = document.createElement("div");
        summaryItem.classList.add("summary-item");
        summaryItem.innerHTML = `
            <p>${summary}</p>
            <button data-index="${index}">Delete</button>
        `;

        summaryItem.querySelector("button").addEventListener("click", function () {
            deleteSummary(index);
        });

        summaryList.appendChild(summaryItem);
    }

    function deleteSummary(index) {
        chrome.storage.local.get(["summaries"], function (result) {
            let summaries = result.summaries || [];
            summaries.splice(index, 1);

            chrome.storage.local.set({ summaries: summaries }, function () {
                loadSummaries(); // Update UI instead of reloading page
            });
        });
    }

    loadSummaries(); // Load summaries when sidebar opens
});

How can I get all token information in my Solana wallet?

I tried to get all token information in my wallet using solana/web3 but I can’t get it.

I need token address, token amount, token price, token name, token symbol at least.

How can I get this data?

This is my current code that gets the token mint address and amount.

const getTokenFromTokenAccount = async (tokenAccount) => {
  const Ta = new PublicKey(tokenAccount);
  const AccInfo = await connection.getParsedAccountInfo(Ta, {
    commitment: "confirmed",
  });

  const splData = AccInfo.value?.data;
  let splToken = "";
  if (splData && "parsed" in splData) {
    const parsed = splData.parsed;
    splToken = parsed.info.mint;
    amount = parsed.info.tokenAmount.uiAmount;

    return { mint: splToken, amount: amount };
  }
};

const getAllTokenInfo = async () => {
  const wallet = new PublicKey("pkrQznmnts6q3vDfbDwuaj5JPqGmjiC6gJfx4xcAv5n");
  const tokenProgramId = new PublicKey(
    "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" // SPL TOKEN - TOKEN_PROGRAM_ID
  );
  const token2022ProgramId = new PublicKey(
    "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" // TOKEN 2022 - TOKEN_PROGRAM_ID
  );

  let tokenAccounts = [];

  const splTokenAccounts = await connection.getTokenAccountsByOwner(wallet, {
    programId: tokenProgramId,
  });
  const token2022Accounts = await connection.getTokenAccountsByOwner(wallet, {
    programId: token2022ProgramId,
  });

  tokenAccounts = [...splTokenAccounts.value, ...token2022Accounts.value];

  let tokenInfoArray = [];
  for (let i = 0; i < tokenAccounts.length; i++) {
    const tokenInfo = await getTokenFromTokenAccount(
      tokenAccounts[i].pubkey.toBase58()
    );
    tokenInfoArray.push(tokenInfo);
  }
  return tokenInfoArray;
};

Promise: {Pending} [duplicate]

Currently I am enrolled in a Full-Stack Enginner course and, in order to test Express.js, I have written the following file:

const express = require ('express');

const bodyParser = require('body-parser');

const app = express();

const db = [
    {
        author: "J.R.R. Tolkien",
        title: "The Lord of the Rings"
    }
]

app.use(bodyParser.json());

app.get('/', (req, res) => {
    res.send(db)
});

const PORT = process.env.PORT || 4001;

app.listen(PORT, () => {
    console.log(`Listening on ${PORT}`)
});

To verify that this “server” is working correctly, I tested it with Postman. Additionally, following the approach used when building other APIs, I have written the following function to fetch data from the “server”:

const x = async () => {
    try {
        const response = await fetch('http://localhost:4001/', {method: 'GET'});
        if (response.ok) {
            const result = await response.json();
            return result;
        }
    } catch (error) {
        console.log(error)
    }
};

With Postman, I get the expected result (the db), so the “server” appears to be functioning properly. However, whenever I try to assign the returned value of the function to a variable [e.g., let y = x();], I do not get the expected result. Instead, the log shows “Promise { }”.
I have researched this issue and found that due to the asynchronous nature of the function, it returns a promise. Therefore, if I add a .then block, I can log the expected result [e.g., x().then(result => console.log(result));]. However, using this approach, I cannot assign the promise’s resolved value to a variable outside the .then block, at least as far as I have tested.
I do not understand why, in the case of the other APIs built during the course, I was able to assign the returned value of an asynchronous function to a variable and work with it, whereas in this case, I receive a “Promise { }”.
Kind regards, and thanks in advance for your help and answers.

Using TensorFlow.js to Correct Sentences Based on Training Data

I’m working on a Node.js project that uses TensorFlow.js to correct sentences based on a training dataset. The dataset consists of example sentences, and I want the machine learning model to learn from these examples and be able to correct input sentences.

Here is what I’ve tried so far:

What I’m trying to do:

I have an array of training sentences like:

let sentences = [
    "Distribution of radiotracer is unremarkable",
    "Distribution of radiotracer is homogeneous",
    "Distribution of radiotracer is heterogeneous",
    "Distribution of PSMA is unremarkable",
    "Distribution of tracer is unremarkable",
    "Distribution of FDG is unremarkable",
    "Avidity of radiotracer is unremarkable"
];

I want to feed input sentences to the model, for example:

“Distribution of radio tracer is on remarkable” → should be corrected
to
→ “Distribution of radiotracer is unremarkable”

I’m using TensorFlow.js to train a model that processes the relationships between words in the sentences and can detect and correct mistakes in new input sentences.

The code I have written so far: To be honest I don’t know what exactly I did here !)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sentence Correction with TensorFlow.js</title>
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
</head>
<body>
    <h2>Sentence Correction with TensorFlow.js</h2>
    <p id="output"></p>

    <script>
        // Sample sentence to correct
        const sentenceToCorrect = "Distribution of radiotracer is onremarkable";

        // Training data
        const sentences = [
            "Distribution of radiotracer is unremarkable",
            "Distribution of radiotracer is homogeneous",
            "Distribution of radiotracer is heterogeneous",
            "Distribution of PSMA is unremarkable",
            "Distribution of tracer is unremarkable",
            "Distribution of FDG is unremarkable",
            "Avidity of radiotracer is unremarkable"
        ];

        let wordEmbeddings = {};

        // 1. Generate word embeddings from sentences
        function generateWordEmbeddings(sentences) {
            let allWords = new Set();

            sentences.forEach(sentence => {
                sentence.split(" ").forEach(word => {
                    allWords.add(word);
                });
            });

            allWords.forEach(word => {
                wordEmbeddings[word] = Array.from({ length: 5 }, () => Math.random());
            });

            console.log("Generated word embeddings:", wordEmbeddings);
        }

        // 2. Tokenizer to convert sentences to numerical vectors
        function tokenize(sentence) {
            return sentence.split(" ").map(word => wordEmbeddings[word] || Array(5).fill(0));
        }

        // 3. Preprocess sentences
        function preprocessSentences(sentences) {
            return sentences.map(tokenize);
        }

        let inputTensors = preprocessSentences(sentences);

        // 4. Build LSTM model
        async function createModel() {
            const model = tf.sequential();
            model.add(tf.layers.lstm({ units: 16, inputShape: [5, 5], returnSequences: true }));
            model.add(tf.layers.dense({ units: 5, activation: "softmax" }));

            model.compile({
                loss: "categoricalCrossentropy",
                optimizer: "adam",
                metrics: ["accuracy"]
            });

            return model;
        }

        let model;

        // 5. Train the model
        async function trainModel() {
            if (Object.keys(wordEmbeddings).length === 0) {
                alert("Please generate word embeddings first.");
                return;
            }
            model = await createModel();
            const inputTensor = tf.tensor3d(inputTensors);
            const outputTensor = inputTensor;

            console.log("Training model...");
            await model.fit(inputTensor, outputTensor, { epochs: 100 });

            console.log("Model trained!");
            alert("Model trained!");
            correctSentence(); // Correct the sentence after training
        }

        // 6. Beam Search for sentence correction
        function beamSearch(predictions, beamWidth = 3) {
            const sequences = [[]];
            for (let t = 0; t < predictions.length; t++) {
                let allCandidates = [];
                for (let seq of sequences) {
                    for (let i = 0; i < predictions[t].length; i++) {
                        let candidate = [...seq, i];
                        let score = candidate.reduce((a, b) => a + predictions[t][b], 0);
                        allCandidates.push({ sequence: candidate, score });
                    }
                }
                allCandidates.sort((a, b) => b.score - a.score);
                sequences.length = 0;
                for (let i = 0; i < beamWidth; i++) {
                    sequences.push(allCandidates[i].sequence);
                }
            }
            return sequences[0];
        }

        // 7. Correct the input sentence
        async function correctSentence() {
            if (!model) {
                alert("Please train the model first!");
                return;
            }

            const inputTensor = tf.tensor3d([tokenize(sentenceToCorrect)]);

            const prediction = model.predict(inputTensor);
            const outputData = await prediction.array();
            console.log("Prediction output:", outputData);

            const bestSequence = beamSearch(outputData[0]);
            console.log("Best sequence:", bestSequence);

            const correctedWords = bestSequence.map(i => Object.keys(wordEmbeddings)[i] || "?").join(" ");
            console.log("Corrected sentence:", correctedWords);

            document.getElementById("output").innerText = "Corrected sentence: " + correctedWords;
        }

        // Generate word embeddings based on sentences
        generateWordEmbeddings(sentences);

        // Train the model after page load
        window.onload = trainModel;
    </script>
</body>
</html>

As you see the issue is my code doesn’t return the correct sentence:(

How would you do this?

I appreciate any guidance or suggestions. Thanks in advance!

New Lines in JavaScript Regular Expression

I use a regular expression defined in JavaScript to search function definitions for specific symbols:

var fieldName = 'ExportImportLicenseAuthorization';

var funcDef = 'ƒ () { return self.ExportImportLicenseAuthorization() === tsrDetVM.ExportImportLicenseTypes()[0].Id;    // "NLR" }';

new RegExp(`^(.*[(.]\s*)*${fieldName}\s*[() ]+.*$`).test(funcDef)

If funcDef contains carriage returns & new lines rn, which most of them do, the RegExp.test returns false when I need it to allow for these and return true.

I have tried inserting r*n* in several places in the regular expression, sometimes in repetition, but I can’t seem to get it to allow for carriage returns & new lines. How can I successfully modify the regular expression so it does?

(rn placed immediately before & after the return statement line in funcDef.)

Trying to load a module via require() but get an error

I have this 3rd party program which allows scripting via the use of js and it uses Duktape JavaScript engine. I am attempting to load a module (dll) through duktape In order to Call upon certain functions the dll brings that duktape doesn’t have. I’m attempting to load ultralight.

const ultralight = require("Ultralight.dll");

ultralight.init();

// Initialize Ultralight UI
const app = new ultralight.App();
const window = app.createWindow(800, 600, {
    title: "Tracker",
    transparent: true,
    resizable: true,
    alwaysOnTop: true
});
const view = window.createView(800, 600);
view.loadURL("file:///usr/interface.html"); // Update with the actual UI file
window.setRootView(view);
app.run();

Everything looks like it would be fine but this is the error I keep getting:

   Error: failed to load native module ("Ultralight.dll")
   at [anon] (UserInterfaceDebuggerScriptAPIScriptAPI.cpp:648) internal
   at [anon] () native strict preventsyield
   at require () native strict preventsyield
   at global (trackerv2.js:31) strict preventsyield

Would anyone be able to tell me why this is happening? Is it because I cannot use ultralight with duktape?

Using pgBouncer on DigitalOcean with Node.js pg Pool and Kysely – Can They Coexist?

I’m running a Node.js application that connects to my PostgreSQL database using Kysely and the pg Pool. Here’s the snippet of my current DB connection logic.
I have deployed my database on DigitalOcean, and I’ve also set up pgBouncer to manage connection pooling at the database level. Can the application-level connection pool (via pg) and pgBouncer coexist without causing issues?

I’m particularly interested in learning about:

  • Potential conflicts or issues between these two pooling layers.
  • Best practices for configuration, especially regarding pooling modes (like transaction pooling) and handling prepared statements or session state.
import type { DB } from '../types/db';
import { Pool } from 'pg';
import { Kysely, PostgresDialect } from 'kysely';

const pool = new Pool({
  database: process.env.DB_NAME,
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  port: Number(process.env.DB_PORT),
  max: 20,
});

pool.on('error', (err) => {
  console.error('Unexpected error on idle client', err);
});

const dialect = new PostgresDialect({
  pool,
});

export const db = new Kysely<DB>({
  dialect,
  log(event) {
    if (event.level === 'error') {
      console.error(event.error);
    }
  },
});

D3js: Bar charts with dynamic width labels

I am completely new to d3js and I have a problem with the labels, especially on the y-axis on a horizontal bar chart, but in general the labels are also a problem.

If I use longer labels, they are cut off and not displayed correctly. I am aware that this could be solved by using a larger marginLeft, for example, but a permanently large marginLeft is not a solution, as the labels can change dynamically and should only ever take up as much space as the longest label. How can I achieve this? It should also be responsive, i.e. it should also look good on smaller displays, which can be a problem, for example if the longest label is 170px wide, the bar chart would no longer look good in mobile.

A current example from me (sorry working code snipped didnt work):

 init() {
document.addEventListener('readystatechange', () => {
  if (document.readyState === 'complete') {
    const data = [
            {
              "category": "Test long test Test long test",
              "value": 26,
              "color": "#1e2a78"
            },
            {
              "category": "Test long test sd sds d",
              "value": 15,
              "color": "#1e2a78"
            },
            {
              "category": "Test long test Test aaa",
              "value": 12,
              "color": "#1e2a78"
            },
            { "category": "Test", "value": 10, "color": "#1e2a78" },
            { "category": "Test long testss", "value": 9, "color": "#1e2a78" },
            {
              "category": "Test long test",
              "value": 7,
              "color": "#1e2a78"
            }
          ];
    const margin = { top: 50, right: 30, bottom: 30, left: 40 };
    const width = this.element.clientWidth - margin.left - margin.right;
    const height = this.height - margin.top - margin.bottom;

    const svg = select(this.element)
    .classed('svg-container', true)
    .append('div')
    .classed('svg-container', true)
      .append('svg')
         .classed('svg-content-responsive', true)
        .attr('viewBox', `0 0 ${width + margin.left + margin.right} ${height + margin.top + margin.bottom}`)
        .attr('preserveAspectRatio', 'xMidYMid meet')
        .append('g')
        .attr('transform', `translate(${margin.left},${margin.top})`);


    const x = this.horizontal ?
        scaleLinear().domain([0, max(data, d => d.value)]).range([0, width]) :
        scaleBand().domain(data.map(d => d.category)).range([0, width]).padding(0.2);

    const y = this.horizontal ?
        scaleBand().domain(data.map(d => d.category)).range([0, height]).padding(0.2) :
        scaleLinear().domain([0, max(data, d => d.value)]).range([height, 0]);


    if (this.horizontal) {
      svg.append('g').call(axisLeft(y)).selectAll('text').style('font-size', '14px');
      svg.append('g').attr('transform', `translate(0,${height})`).call(axisBottom(x)).selectAll('text')
      .style('font-size', '14px');
    } else {
      svg.append('g').attr('transform', `translate(0,${height})`).call(axisBottom(x)).selectAll('text')
      .style('font-size', '14px');
      svg.append('g').call(axisLeft(y)).selectAll('text').style('font-size', '14px');
    }

           // Balken erstellen
    svg.selectAll('.bar')
           .data(data)
           .enter()
           .append('rect')
           .attr('class', 'bar')
           .attr(this.horizontal ? 'y' : 'x', d => (this.horizontal ? y(d.category) : x(d.category)))
           .attr(this.horizontal ? 'x' : 'y', this.horizontal ? 0 : height)
           .attr(this.horizontal ? 'height' : 'width', this.horizontal ? y.bandwidth() : x.bandwidth())
           .attr(this.horizontal ? 'width' : 'height', 0) 
           .attr('fill', d => d.color);


    const animateBars = () => {
      // eslint-disable-next-line no-underscore-dangle
      // console.log('bars ', bars._groups[0][0]);
      const rects = svg.selectAll('rect');

      rects
        .transition()
        .duration(1000) // Dauer der Animation
        // Übergang starten
      .attr(this.horizontal ? 'width' : 'height', d => (this.horizontal ? x(d.value) : height - y(d.value)))
      .attr(this.horizontal ? 'x' : 'y', d => (this.horizontal ? 0 : y(d.value)));
    };

    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {


            animateBars();

            observer.disconnect(); 
          }
        });
      },
      { threshold: 1 },
    ); 


    observer.observe(this.element);
  }
});

}

How it looks like (you can see all the category labels are cutted and not fully visible):
enter image description here