Find the game and the fisherman island 🏝️ [closed]

SO has a very specific way of evolving, and you really should spend a whole lot of time searching it before you post a question that has — especially if you’re a beginner — very likely already been answered. They’re very welcoming of novel, answerable questions, but they get really bored over there of flagging basic beginner questions as duplicates a million times in a row.

For most languages with any kind of user base there is at least one subreddit, and most languages at least try to be friendly to newcomers. Do a search on here for r/[LANG] and r/learn[LANG] and you’ve got a decent chance of finding a more language specific answer.

If it’s not really language specific you’re always welcome to ask here… different model from SO, but similarly it’s a good idea to spend some time searching and reading (especially in any given subreddit’s FAQ section) before asking anything that’s one-or-two quick Google searches away.

Upvote
22

Downvote

[deleted]
OP

3y ago
Thank you for that but what if one could really not get that point even he or she did multiple research abt it

Upvote
1

Downvote

[deleted]

3y ago
Then ask… and simultaneously learn to get better at researching. The simple fact is most questions a beginner might ask in any given language have an answer already out there. A beginner is not likely to ask a question that hasn’t been asked before, but it could happen. Always be prepared for the possibility that someone else seeming unfriendly to you might well be you asking a question you could have easily answered yourself.

Also, have patience; when you ask a question on either Reddit or SO it’s entirely possible the person with the answer you need is in a vastly different time zone than you.

Upvote
9

Downvote

[deleted]

3y ago
The thing is, that IF you did the research, your question will be very specific automatically. Stuff that gets harsh respones on SO usually falls into the category “general question without any context”.

Same goes for this subreddit: general questions will get ignored (or you’ll get asked for more context) or you will get asked for more context.

Asking bad / unanswerable questions will lead to unwanted reactions anywhere. On SO it’s kind of harsh reactions, here you will not get.

@ìr_Sign_#j1✨

Change label of Interactive Grid button without creating whole new button

I am a little stuck on working with javascript in Interactive Grid in Oracle Apex. I just want to change the label of one interactive Grid save button, but I am not able to do it. I am on APEX 23.2

This code is not working

function(config) {
var $ = apex.jQuery,
toolbarData = $.apex.interactiveGrid.copyDefaultToolbar(),  // Make a copy of the default toolbar
toolbarGroup = toolbarData.toolbarRemove("actions2");       // Remove the actions2 menu group

toolbarGroup.controls.push({
    type: "BUTTON",
    label: "test",
    action: "save",
    icon: "icon-ig-save",
    iconBeforeLabel: true,
    hot: true
});

// Assign new toolbar data back to toolbarData configuration property
config.toolbarData = toolbarData;

// Return the options
return config;

}

How to Programmatically Add and Draw Measurements from Mock Data in OHIF/Cornerstone.js?

I’m working on a project based on the OHIF Viewer. My goal is to load measurement data from a mock JSON file and have it automatically drawn on the corresponding image slice when the viewer loads.

When implementing measurement in the ViewerLayout component I use a useEffect hook that is bound to the activeViewportId and renderingEngineId. Inside this hook I do the following:

Read my mock measurement data.
Enrich it with the current study/series/instance UIDs.
Attempt to add it to the measurementService and annotationManager.

The Problem:
The measurement data successfully appears in the “Measurements” side panel, and measurementService.getMeasurements() shows the data correctly. However, the annotation (the actual PlanarFreehandROI drawing) is not rendered on the viewport’s SVG layer. There are no errors in the console.

It seems the data is tracked by the measurementService, but the rendering part is not being triggered correctly.

What is the correct, idiomatic way in OHIF/Cornerstone.js to programmatically add a measurement from data and ensure it gets rendered?
I’ve tried using measurementService.annotationToMeasurement and annotationManager.addAnnotation manually. Is this correct, or should measurementService.addMeasurement handle the rendering automatically through its mappings?
My current implementation uses a useEffect hook. Is there a more reliable event-based approach (e.g., listening for Enums.Events.IMAGE_RENDERED) to ensure the viewport is fully ready before I attempt to add the annotation?
Here are the relevant code snippets and my mock data structure. Any guidance would be greatly appreciated!

  const getViewportInfo = useCallback(() => {
    return cornerstoneViewportService.getViewportInfo(activeViewportId);
  }, [cornerstoneViewportService, activeViewportId]);
  const getCurrentImageId = useCallback(() => {
    if (!activeViewportId) return null;
    const viewportObj = cornerstoneViewportService.getCornerstoneViewport(activeViewportId);
    return viewportObj?.getCurrentImageId();
  }, [cornerstoneViewportService, activeViewportId]);

  if (!dataSource) {
    console.error('ViewerLayout: Invalid DataSource');
  } else {
    servicesManager.services.dataSource = dataSource;
    servicesManager.services.getImageIdsForDisplaySet = ds =>
      dataSource.getImageIdsForDisplaySet(ds);
  }

  const customToMeasurementSchema = useCallback(
    raw => {
      console.log('customToMeasurementSchema', raw);
      if (!dataSource?.getImageIdsForDisplaySet || !displaySetService.getDisplaySetByUID) {
        return null;
      }
      const ds = displaySetService.getDisplaySetByUID(raw.displaySetInstanceUID);

      if (!ds) {
        console.warn(`DisplaySet with UID ${raw.displaySetInstanceUID} not found.`);

        return null;
      }
      const imageIds = dataSource.getImageIdsForDisplaySet(ds) || [];
      const imageId = imageIds[raw.frameNumber - 1] || imageIds[0];
      const measurementSchema = {
        uid: raw.uid,
        SOPInstanceUID: raw.SOPInstanceUID,
        FrameOfReferenceUID: ds.FrameOfReferenceUID || raw.metadata?.FrameOfReferenceUID,
        referenceStudyUID: raw.referenceStudyUID || raw.studyInstanceUID,
        referenceSeriesUID: raw.seriesInstanceUID || ds.SeriesInstanceUID,
        frameNumber: raw.frameNumber || 1,
        displaySetInstanceUID: raw.displaySetInstanceUID,
        label: raw.label || '',
        displayText: raw.displayText || [],
        type: raw.type,
        points: raw.points || [],
        source: raw.source,
        toolName: raw.toolName,
        referencedImageId: imageId,
        metadata: {
          ...raw.metadata,
          FrameOfReferenceUID: ds.FrameOfReferenceUID || raw.metadata?.FrameOfReferenceUID,
          referencedImageId: imageId,
        },

        data: { [imageId]: raw.data },
        selected: raw.selected || false,
        textBox: raw.textBox,
      };
      console.log('customToMeasurementSchema Output:', measurementSchema);
      return measurementSchema;
    },
    [dataSource, displaySetService]
  );

  const toAnnotationSchema = useCallback((measurement, annotationType) => {
    const annotationObj = {
      annotationType,
      uid: measurement.uid,
      imageId: measurement.referencedImageId,
      frameNumber: measurement.frameNumber || 1,
      visible: true,
      handles: {
        points: measurement.points.map(([x, y, z]) => ({
          x,
          y,
          world: [x, y, z],
        })),
        textBox: {
          x: measurement.textBox?.worldPosition[0],
          y: measurement.textBox?.worldPosition[1],
        },
      },
      textBox: {
        x: measurement.textBox?.worldPosition[0],
        y: measurement.textBox?.worldPosition[1],
      },
      style: {
        color: 'rgb(0,255,0)',
        lineWidth: 3.5,
        fill: 'rgba(0,255,0,0.1)',
      },
      metadata: {
        ...(measurement.metadata || {}),
        FrameOfReferenceUID:
          measurement.metadata?.FrameOfReferenceUID || measurement.FrameOfReferenceUID || '',
      },
      data: measurement.data,
    };
    console.log('toAnnotationSchema Output:', annotationObj);
    return annotationObj;
  }, []);

  const injectMeasurements = useCallback(
    (currentImageId, displayUID, instance, viewportElement) => {
      console.log('Instance object in injectMeasurements:', instance);
      const renderingEngine = getRenderingEngine(renderingEngineId);
      if (!renderingEngine) {
        console.error('Rendering engine not found in injectMeasurements');
        return;
      }
      const viewport = renderingEngine.getViewport(activeViewportId);
      if (!viewport) {
        console.error('Viewport not found');
        return;
      }

      const { clientWidth, clientHeight } = viewport.element;
      const topLeftWorld = viewport.canvasToWorld([0, 0]);
      const bottomRightWorld = viewport.canvasToWorld([clientWidth, clientHeight]);
      const center = [
        (topLeftWorld[0] + bottomRightWorld[0]) / 2,
        (topLeftWorld[1] + bottomRightWorld[1]) / 2,
        (topLeftWorld[2] + bottomRightWorld[2]) / 2,
      ];

      const worldWidth = Math.abs(bottomRightWorld[0] - topLeftWorld[0]);
      const worldHeight = Math.abs(bottomRightWorld[1] - topLeftWorld[1]);
      const dynamicPoints = [
        [center[0] - worldWidth * 0.1, center[1] - worldHeight * 0.1, center[2]],
        [center[0] + worldWidth * 0.1, center[1] - worldHeight * 0.1, center[2]],
        [center[0] + worldWidth * 0.1, center[1] + worldHeight * 0.1, center[2]],
        [center[0] - worldWidth * 0.1, center[1] + worldHeight * 0.1, center[2]],
      ];
      console.log('Calculated dynamic points:', dynamicPoints);

      const commonProps = {
        displaySetInstanceUID: displayUID,
        StudyInstanceUID: instance.StudyInstanceUID,
        referenceStudyUID: instance.StudyInstanceUID,
        referenceSeriesUID: instance.SeriesInstanceUID,
        SOPInstanceUID: instance.SOPInstanceUID,
        metadata: {
          ...measurementsMock[0],
          FrameOfReferenceUID: instance.FrameOfReferenceUID,
          referencedImageId: currentImageId,
          data: measurementsMock[0].data,
          textBox: measurementsMock[0].textBox,
        },
        FrameOfReferenceUID: instance.FrameOfReferenceUID,
      };
      console.log('Common Props before raw assignment (with actual UIDs):', commonProps);

      const source = measurementService.getSource('Cornerstone3DTools', '0.1');
      const annotationManager = annotation.state.getAnnotationManager();

      if (!annotationManager || typeof annotationManager.addAnnotation !== 'function') {
        console.error(
          'Annotation Manager is not available or addAnnotation method is missing! Cannot inject measurements.'
        );
        return;
      }
      const rawTemplate = measurementsMock[0];

      measurementsMock.forEach(rawTemplate => {
        const raw = {
          ...rawTemplate,
          ...commonProps,
          points: dynamicPoints,
          metadata: {
            ...(rawTemplate.metadata || {}),
            ...(commonProps.metadata || {}),
          },

          referencedImageId: currentImageId,
          SOPInstanceUID: commonProps.SOPInstanceUID,
          FrameOfReferenceUID: commonProps.FrameOfReferenceUID,
          referenceSeriesUID: commonProps.referenceSeriesUID,
          referenceStudyUID: commonProps.referenceStudyUID,
        };
        console.log('Raw object for customToMeasurementSchema (after dynamic merge):', raw);

        measurementService.annotationToMeasurement(
          source,
          measurementService.VALUE_TYPES.POLYLINE,
          raw,
          false
        );

        let existingAnnotation = annotationManager.getAnnotation(raw.uid);

        if (!existingAnnotation) {
          console.log('Injecting measurement (no existing annotation found with this UID)');
          const annotationObj = toAnnotationSchema(raw, raw.toolName || 'PlanarFreehandROI');
          console.log('Eklenecek Annotation FoR:', annotationObj.metadata.FrameOfReferenceUID);

          annotationObj.imageId = currentImageId;
          console.log(
            'Final annotationObj before addAnnotation (full object):',
            JSON.stringify(annotationObj, null, 2)
          );

          const engine = getRenderingEngine(renderingEngineId);
          if (!engine) {
            console.error(`[ViewerLayout] Geçersiz renderingEngineId: ${renderingEngineId}`);
            return;
          }
          const groupKey = annotationObj.metadata.FrameOfReferenceUID;
          annotationManager.addAnnotation(annotationObj, groupKey);
          engine.render();
          const added = annotationManager.getAnnotation(raw.uid);

          if (!added) {
            console.error(`Annotation UID ${raw.uid} eklenemedi.`);
          }

          console.log(
            'Annotation retrieved from manager AFTER addAnnotation:',

            annotationManager.getAnnotation(raw.uid)
          );
        } else {
          console.log(
            `Annotation with UID ${raw.uid} already exists in manager. Skipping injection.`
          );
        }
      });
    },

    [measurementService, toAnnotationSchema, renderingEngineId, activeViewportId]
  );

  useEffect(() => {
    const source = measurementService.getSource('Cornerstone3DTools', '0.1');

    measurementService.addMapping(
      source,
      measurementService.VALUE_TYPES.POLYLINE,
      { points: measurementsMock[0].points.length },
      toAnnotationSchema,
      customToMeasurementSchema
    );
  }, [measurementService, toAnnotationSchema, customToMeasurementSchema]);

  useEffect(() => {
    const timeoutId = setTimeout(() => {
      const viewportInfo = getViewportInfo();

      if (viewportInfo?.renderingEngineId) {
        setRenderingEngineId(viewportInfo.renderingEngineId);

        console.log('[ViewerLayout] renderingEngineId set:', viewportInfo.renderingEngineId);
      }
    }, 5000);

    return () => clearTimeout(timeoutId);
  }, [getViewportInfo]);

  useEffect(() => {
    if (!renderingEngineId || !activeViewportId) return;

    const toolGroup = ToolGroupManager.getToolGroupForViewport(activeViewportId, renderingEngineId);

    if (!toolGroup) {
      console.error('ToolGroup not available, skipping tool configuration.');

      return;
    }

    toolGroup.setToolActive(PlanarFreehandROITool.toolName, {
      bindings: [{ mouseButton: Enums.MouseBindings.Primary }],
    });

    console.log('[ViewerLayout] Tool configured for:', toolGroup);
  }, [renderingEngineId, activeViewportId]);

  useEffect(() => {
    if (!activeViewportId || !viewports.has(activeViewportId) || !renderingEngineId) {
      return;
    }

    const renderingEngine = getRenderingEngine(renderingEngineId);

    if (!renderingEngine) {
      console.error('ViewerLayout: Invalid Rendering Engine');

      return;
    }

    const viewport = renderingEngine.getViewport(activeViewportId);

    if (!viewport) {
      console.error('ViewerLayout: Invalid Viewport');

      return;
    }

    const currentImageId = getCurrentImageId();

    console.log('Active Viewport currentImageId:', currentImageId);

    if (!currentImageId) {
      console.error('ViewerLayout: No current image ID');

      return;
    }

    if (showLoadingIndicator) {
      setShowLoadingIndicator(false);
    }

    const dsUIDs = viewports.get(activeViewportId).displaySetInstanceUIDs || [];

    if (!dsUIDs.length) return;

    const displayUID = dsUIDs[0];

    const ds = displaySetService.getDisplaySetByUID(displayUID);

    if (!ds?.instances?.length) return;

    const instance = ds.instances[0];

    const toolGroup = ToolGroupManager.getToolGroupForViewport(activeViewportId, renderingEngineId);

    if (toolGroup) {
      const viewportIdsInToolGroup = toolGroup.getViewportIds();

      console.log('Viewport IDs in ToolGroup:', viewportIdsInToolGroup);

      let isViewportAlreadyAdded = false;

      if (Array.isArray(viewportIdsInToolGroup)) {
        isViewportAlreadyAdded = viewportIdsInToolGroup.includes(activeViewportId);
      }

      if (!isViewportAlreadyAdded) {
        toolGroup.addViewport(activeViewportId, renderingEngineId);

        console.log(
          `[ViewerLayout] Added viewport ${activeViewportId} (engine: ${renderingEngineId}) to toolGroup ${toolGroup.id}`
        );
      }
    } else {
      console.error(`No toolGroup found for viewport ${activeViewportId}. Cannot add viewport.`);

      return;
    }

    injectMeasurements(currentImageId, displayUID, instance, viewport.element);

    viewport.render();

    console.log('[ViewerLayout] Measurements and annotations injected successfully');
  }, [
    activeViewportId,
    viewports,
    renderingEngineId,
    displaySetService,
    getCurrentImageId,
    injectMeasurements,
    showLoadingIndicator,
  ]);

Mock data is added to the measurement service, the annotation service is also triggered and data appears to have been added, but the relevant changes are not displayed in the svg layer, as a result, no drawing is visible on the image.

WebRTC auto-joins room and fails to establish remote connection

I’m building a WebRTC app where two users can join a video call using a signaling server (via WebSocket). I’m facing two main issues:

  1. Auto-joining: As soon as a room is created, it automatically connects — even if the second user has not clicked the “Join Room” button.

  2. No remote connection: When both users are present, the call does not complete — no remote video appears and ontrack does not fire for the second peer.

What I expect:

  • Only the first user (caller) should create a room.
  • The second user should click “Join Room” to enter.
  • Both users should see and hear each other.

What I tried:

  • Moving sendMessage({ type: "join_room" }) inside WebSocket.onopen
  • Removing room join logic from connectWebSocket()
  • Deferring ICE candidates until remoteDescription is set
  • Using remoteCandidatesQueue and flushing it after SDP negotiation

My current code:

How can I fix the automatic entry and ensure the peer connection succeeds?

Thank you in advance.

I need the call to begin only when the user who creates the room also joins it explicitly. I expected that by removing startCall() from the createRoom button and delaying sendMessage({ type: “join_room” }) until after WebSocket.onopen in the Join button, the caller would not join until ready. I also ensured signaling only begins after setupPeerConnection(), and candidates are queued until remoteDescription is set. Despite this, the caller still joins and the session starts automatically.

includeHTML() function not work in every browser (js and css effect miss) [duplicate]

i try to use includeHTML function via w3.js ,
cause i want to let main_menu.html as a block for another html include,
the menu problem is dropdown effect is not work in firefox,even sometime not work in chrome,
(actually i also try use sample code in my index.html like
https://www.w3schools.com/howto/howto_html_include.asp sample)

index.html (use sample code)
index_test_01.html (use w3.js)

(my project also put on my github https://github.com/hukluto7750/dev_h_life)

here is my demo video https://youtu.be/eZU11ymrQRY
the nav bar seems not 100% work in every browser ,
even chrome also not 100 % sure any time run work done.

but when i not use includeHTML funciton
(
mean main_menu.html part code merge in one index.html,not seperate in main_nenu.html
,that will run ok , not problem
)

<head>
  <script src="https://www.w3schools.com/lib/w3.js"></script>
</head>


<body>
  <!-- include 共用的 html  -->
  <div w3-include-html="main_menu.html"></div>
  <script>
    w3.includeHTML();
  </script>

How to prevent Enter from submitting while the user is still typing/composing (IME input mode) in JavaScript/React

When typing in Japanese,p ressing Enter often just confirms the conversion but not the submission. How can I achieve this?
I have an input field and upon pressing enter it will submit.

So I have this function

 const handleKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter' && searchQuery) {
      e.preventDefault();
      handleAddTag(searchQuery);
    }
  };

and this input field

<TextInput
  placeholder='タグを検索'
  value={searchQuery}
  onChange={(e) => setSearchQuery(e.currentTarget.value)}
  onKeyDown={handleKeyPress}
  className='h-9 text-sm w-full box-border'
  leftSection={<IconTag size={16} className='text-gray-400' />}
/>

What can I do?
It is a React app.

Why does this JavaScript comma operator example return different results?

I was testing JavaScript’s comma operator and got confused by the following behavior:

function A() {
    return '1','2' == '1';
}
function B() {
    return '1','2' == '2';
}

console.log(A() && B());  // Output: false

const x = ('1','2' == '1' && '1','2' == '2');
console.log(x);  // Output: true

I expected both expressions to behave similarly, but:

  • A() && B() returns false.

  • The expression assigned to x returns true.

Why does this happen?
I know that the comma operator evaluates both expressions and returns the last one, but I’m not sure how it interacts with the == operator in these cases.
Is it about operator precedence or evaluation order?

GA4 custom event parameter not available after 96+ hours (despite working setup)

I’m using GA4 in a production web app and sending a custom event using this code:

gtag('event', 'Email sent', {
  email_sent_count: 1,
  email_template: emailTemplate,
})

emailTemplate is a simple string like ‘welcome_email’, ‘reminder’, etc.

The event Email sent shows up in the GA4 Events report

Both parameters (email_sent_count and email_template) appear in DebugView

I’ve tried creating a custom dimension/metric manually in GA4 (Admin > Custom Definitions), but the parameters are not listed even after 96+ hours

Additional context:

I already track 34 other events in GA4, all with custom parameters, and they propagate fine

  • I’ve kept email_template values clean and predictable — no spaces, special characters, or dynamic variations like “Unknown (id)”

  • Property limits are not exceeded (I’m under 50 custom dimensions/metrics)

When I click the “Create custom dimension” button, the email_template parameter from the Email sent event does not appear in the list.

Is there any reason why this specific parameter is delayed or silently dropped?
Has anyone encountered a situation where GA4 delays propagation of new event parameters despite correct setup?

Any help or insights appreciated.

Preconnect/dns-prefetch Firebase Auth

I’m looking into optimizing Firebase Auth.

The web SDK does cache login state, but (unlike the native iOS and Android versions of the SDK) always performs at least one request to check authentication. This causes calls to FB Database (and I assume Firestore) to be delayed until auth has settled. On a good connection, the request(s, preflights included) can take up to 1 second, which isn’t ideal to begin with, but on bad/spotty connections, it’s a lot worse.

So I figured I’d use preconnect and (and dns-prefetch for optionals), but I can’t get it to work.

I’m seeing requests to the following domains:

[1] Performs preflight request
[2] Only requested when security token is no longer valid?

It looks like these are cross origin requests, so the html snippets should end up looking like this:

<link rel="preconnect" href="https://identitytoolkit.googleapis.com" crossorigin>
<link rel="preconnect" href="https://securetoken.googleapis.com" crossorigin>

But this doesn’t seem to work. What am I doing wrong?

Bonus question:

For Firebase Database, is there a way to dns-prefetch the domain for the websocket connection? (I know preconnect doesn’t work for websocket), e.g.:

<link rel="dns-prefetch" href="https://my-app.firebaseio.com">

Should that work?

Outlook Add-In 3rd party authorization

I develop Outlook add-in that should be able to send data to my server. To do this I added authorization flow using Auth0 (same as I do in frontend app)

I am not sure if this approach will pass add-in review for publishing on the marketplace

  1. Is it ok to store access-token in localstorage? If not, what approach to use?
  2. Where to store subscription key I use for Auth0?

I would be grateful for any code examples or links to documentation that demonstrate a secure, third-party authentication flow (specifically with Auth0) for an Office Add-in that would be compliant with AppSource policies.

How to check if an array has consecutive values in any order ? for example in a roll of 41423, we have 1234

I want to build an algorithm that checks if an array has four consecutive values in any order to do something. And when all the elements in that array have consecutive values in any order to do something else.

When the first condition is true I want to leave the order condition disabled.
Here is an example of what I have already done, but, I still can not get the required result.

function checkForStraights(arr) {
  const newArr = arr.toSorted((a, b) => a - b)

  for(let i = 1; i < newArr.slice(0, 4).length; i++){
    if(newArr[i] - newArr[i-1] === 1){
      updateRadioOption(3, 30);
      scoreInputs[4].disabled = false;
    }
    updateRadioOption(5, 0);
  }
  
  for(let i = 1; i< newArr.length; i++){
    if(newArr[i] - newArr[i-1] === 1){
      updateRadioOption(4, 40);
    }
    updateRadioOption(5, 0);
  }
}

How can I use Cypress to retrieve an array of elements, then run a test against each of those elements?

I have a large menu on my site. I want to create a test that test’s each link individually in it’s own it function.

I imagined doing it in the following way:

let linkArr = [];
describe('I am on desktop view of a page to check the main menu links', () => {
    before(() => {
        cy.visit(pageUrl);
        cy.get('.main-header a').each(($link) => {
            linkArr.push($link);
        })
    });

    linkArr.forEach(link => {
        it(`Ensures the link works`, () => {
            checkLink(link);
            const linkText = (link.prop('text').replace("/n", "")).trim();
            stepReportNotes(reportObj, testName, `${link.prop('href')} on '${linkText}' returns 200 or 301`);
        });
    });
});

But its doesn’t. The forEach loop seems to run at the same time as the before() function so the linkArr is empty.

It does kind of work if I wrap the forEach within the it eg:

it(`Ensures each link works`, () => {
    linkArr.forEach(link => {
        checkLink(link);
        const linkText = (link.prop('text').replace("/n", "")).trim();
        stepReportNotes(reportObj, testName, `${link.prop('href')} on '${linkText}' returns 200 or 301`);
    });
});

but then I’m really only running one step and if one link fails that entire step fails.

I’ve tried a few things like creating 2 tests (one to get the array, one to run the test) and moving the loop into a function but with no success.

Would anyone know how to achieve this?

What is causing this CSS cube to “clip” when rotated three-dimensionally?

I have a three dimensional cube that I created in HTML and CSS and can rotate with javascript. It works just about how I expected and I’m pretty happy with it but there’s one problem I just don’t understand: each side of the cube is its own div, and some of them seem to “clip” when rotated in a certain way. Here’s a codepen that shows how it works – you rotate the cube using the arrow keys (it rotates up and down around the x-axis using the up and down keys and left and right around the y-axis using the left and right keys – each keypress advances it 45 degrees in the given direction. Hitting the “R” key will reset it to its original position):

https://codepen.io/shaundgrey/pen/azOjYxx

I removed the initial code snippet because when embedded in the post the issue doesn’t replicate. You’ll have to use the codepen link, I’m sorry. The other two snippets are still embedded below, however.

The easiest way to replicate the problem is to just hit the down key once – you should be able to see that the top and bottom faces (red and green, respectively) seem to “recede” by almost a quarter of their length and the inside of the cube gets exposed.

At first I thought this was a problem with just like, my computer not being fast enough and some of the faces not applying their transformations quickly enough but it doesn’t matter how slow it goes, or even if it stops, the problem is still apparent.

Then I thought maybe it was something to do with the code having a bug in it, since I had basically pasted it together from several different sources and I didn’t fully understand how it worked, but I went through line-by-line and simplified it down to its barest essence and the problem remains unchanged – I learned a lot about the code at least, although exactly what the matrix transformation is doing is still beyond me.

I eventually started removing faces in order to just isolate the problem and that actually got me somewhere – if I just set the visibility of every face except for the top and bottom to “hidden” and hit the down key once, the problem disappears!

https://codepen.io/shaundgrey/pen/NPqLNaV

//the cube and its six faces for easy refernce
var cube = document.querySelector(".cube");
var frontFace = document.querySelector(".cube-face-front");
var backFace = document.querySelector(".cube-face-back");
var leftFace = document.querySelector(".cube-face-left");
var rightFace = document.querySelector(".cube-face-right");
var topFace = document.querySelector(".cube-face-top");
var bottomFace = document.querySelector(".cube-face-bottom");

//this is the rotation matrix in which we can save the current state of the cube
var resetMatrix = new DOMMatrix();
var matrix = new DOMMatrix();

//takes a vector (rotation axis) and angle (rotation direction) as input and rotates the cube accordingly
function applyRotation(x, y, z, angle) {
  var newMatrix = new DOMMatrix().rotateAxisAngle(x, y, z, angle).multiply(matrix);
  cube.style.transform = newMatrix;
  matrix = newMatrix;
}

//takes a keyboard arrow input and creates a vector (rotation axis) and angle (rotation direction) in response, then feeds that vector and angle to applyRotation
function keyboardTurn(event) {
  switch (event.key) {
    case "ArrowRight":
      applyRotation(0, 1, 0, 45);
      break;
    case "ArrowLeft":
      applyRotation(0, 1, 0, -45);
      break;
    case "ArrowUp":
      applyRotation(1, 0, 0, 45);
      break;
    case "ArrowDown":
      applyRotation(1, 0, 0, -45);
      break;
    case "r":
      cube.style.transform = resetMatrix;
      matrix = resetMatrix;
      break;
    default:
      break;
  }
}
body {
  margin: 0;
  box-sizing: border-box;
  height: 100vh;
  width: 100vw;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  overflow: hidden;
}

.perspective-container {
  perspective: 500vmin;
  width: 96vmin;
  height: 96vmin;
}

.z-translation-container {
  position: relative;
  transform: translateZ(-48vmin);
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
}

.cube {
  width: 100%;
  height: 100%;
  position: relative;
  transform-style: preserve-3d;
  transition: transform 2s;
}

.cube-face {
  box-sizing: border-box;
  position: absolute;
  width: 96vmin;
  height: 96vmin;
  border: 0.5vmin solid black;
  opacity: 0.55;
}

.cube-face-front {
  transform: rotateY(0deg) translateZ(48vmin);
  background-color: blue;
  visibility: hidden;
}

.cube-face-back {
  transform: rotateY(180deg) translateZ(48vmin);
  background-color: orange;
  visibility: hidden;
}

.cube-face-left {
  transform: rotateY(-90deg) translateZ(48vmin);
  background-color: yellow;
  visibility: hidden;
}

.cube-face-right {
  transform: rotateY(90deg) translateZ(48vmin);
  background-color: purple;
  visibility: hidden;
}

.cube-face-top {
  transform: rotateX(90deg) translateZ(48vmin);
  background-color: red;
}

.cube-face-bottom {
  transform: rotateX(-90deg) translateZ(48vmin);
  background-color: green;
}
<html>
  <body class='user' onkeydown='keyboardTurn(event)'>
    <div class='perspective-container'>
      <div class='z-translation-container'>
        <div class='cube'>
          <div class='cube-face cube-face-front'></div>
          <div class='cube-face cube-face-back'></div>
          <div class='cube-face cube-face-left'></div>
          <div class='cube-face cube-face-right'></div>
          <div class='cube-face cube-face-top'></div>
          <div class='cube-face cube-face-bottom'></div>
        </div>
      </div>
    </div>
  </body>
</html>

So it appears that maybe the problem is that the faces are interfering with each other in some way, but I can’t imagine how.

Another “fix” for the problem is to shrink the cube’s container and the size of each face by half (from 96vmin to 48vmin) and that seems to clear it up as well – the problem is that it’s important to me that the cube be 96vmin on each side. Here’s an example in action:

https://codepen.io/shaundgrey/pen/ByNOKYb

//the cube and its six faces for easy refernce
var cube = document.querySelector(".cube");
var frontFace = document.querySelector(".cube-face-front");
var backFace = document.querySelector(".cube-face-back");
var leftFace = document.querySelector(".cube-face-left");
var rightFace = document.querySelector(".cube-face-right");
var topFace = document.querySelector(".cube-face-top");
var bottomFace = document.querySelector(".cube-face-bottom");

//this is the rotation matrix in which we can save the current state of the cube
var resetMatrix = new DOMMatrix();
var matrix = new DOMMatrix();

//takes a vector (rotation axis) and angle (rotation direction) as input and rotates the cube accordingly
function applyRotation(x, y, z, angle) {
  var newMatrix = new DOMMatrix().rotateAxisAngle(x, y, z, angle).multiply(matrix);
  cube.style.transform = newMatrix;
  matrix = newMatrix;
}

//takes a keyboard arrow input and creates a vector (rotation axis) and angle (rotation direction) in response, then feeds that vector and angle to applyRotation
function keyboardTurn(event) {
  switch (event.key) {
    case "ArrowRight":
      applyRotation(0, 1, 0, 45);
      break;
    case "ArrowLeft":
      applyRotation(0, 1, 0, -45);
      break;
    case "ArrowUp":
      applyRotation(1, 0, 0, 45);
      break;
    case "ArrowDown":
      applyRotation(1, 0, 0, -45);
      break;
    case "r":
      cube.style.transform = resetMatrix;
      matrix = resetMatrix;
      break;
    default:
      break;
  }
}
body {
  margin: 0;
  box-sizing: border-box;
  height: 100vh;
  width: 100vw;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  overflow: hidden;
}

.perspective-container {
  perspective: 500vmin;
  width: 48vmin;
  height: 48vmin;
}

.z-translation-container {
  position: relative;
  transform: translateZ(-48vmin);
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
}

.cube {
  width: 100%;
  height: 100%;
  position: relative;
  transform-style: preserve-3d;
  transition: transform 2s;
}

.cube-face {
  box-sizing: border-box;
  position: absolute;
  width: 48vmin;
  height: 48vmin;
  border: 0.5vmin solid black;
  opacity: 0.55;
}

.cube-face-front {
  transform: rotateY(0deg) translateZ(24vmin);
  background-color: blue;
}

.cube-face-back {
  transform: rotateY(180deg) translateZ(24vmin);
  background-color: orange;
}

.cube-face-left {
  transform: rotateY(-90deg) translateZ(24vmin);
  background-color: yellow;
}

.cube-face-right {
  transform: rotateY(90deg) translateZ(24vmin);
  background-color: purple;
}

.cube-face-top {
  transform: rotateX(90deg) translateZ(24vmin);
  background-color: red;
}

.cube-face-bottom {
  transform: rotateX(-90deg) translateZ(24vmin);
  background-color: green;
}
<html>
  <body class='user' onkeydown='keyboardTurn(event)'>
    <div class='perspective-container'>
      <div class='z-translation-container'>
        <div class='cube'>
          <div class='cube-face cube-face-front'></div>
          <div class='cube-face cube-face-back'></div>
          <div class='cube-face cube-face-left'></div>
          <div class='cube-face cube-face-right'></div>
          <div class='cube-face cube-face-top'></div>
          <div class='cube-face cube-face-bottom'></div>
        </div>
      </div>
    </div>
  </body>
</html>

Does anyone have any idea what could be going on here? I’ve been beating my head against it for a few days now and feel completely stumped! Thank you!

Assistance Needed: Tasker + OpenAI Integration – %reply Always Outputting “=%reply” Instead of Parsed Value

What I’m trying to do: Build a Tasker profile that:

Sends a prompt to OpenAI via HTTP Request

Receives the JSON response

Parses the assistant’s reply into %reply

Displays %reply in a Flash and uses Say (TTS) to speak it aloud

Looking for help with:

Why %reply isn’t resolving even though JavaScriptlet is setting it.

Whether setLocal is working properly inside JavaScriptlets.

Whether global() is retrieving the correct content from Tasker variables.

Any Tasker best practices for scoping variables between JavaScriptlet and Tasker actions.

Ways to log/debug silent JS parsing failures (no errors shown).

Any quirks in Tasker that could cause %reply to be used before it’s actually set.

Device/Environment:

Android with Tasker installed

TTS Engine: default Google

Internet and API key are working — valid JSON is received in %gptresponse_http_data

If anyone with Tasker scripting or advanced JavaScriptlet experience has ideas, I’d really appreciate it. I’ve hit a wall. Thanks!

What I’ve tried:

Verified that %gptresponse_http_data contains valid JSON (confirmed via Flash/debug).

Switched between setGlobal() and setLocal() for the reply variable.

Rearranged task actions so Flash and Say come after the JavaScriptlet.

Checked that HTTP request output variables are named gptresponse and that I’m referencing gptresponse_http_data properly.

Hardcoded test values work every time — the issue only appears when referencing the actual HTTP response.

Confirmed that the %reply variable exists and is evaluated, but it never resolves to the JSON content unless it’s hardcoded.

Task Order:

  1. HTTP Request

URL: https://api.openai.com/v1/chat/completions

Headers:

 Authorization: Bearer sk-...

 Content-Type: application/json

Body:

{

 "model": "gpt-3.5-turbo",

 "messages": [

   {

     "role": "system",

     "content": "You are GhostCore, a    tactical AI..."

   },
   {

     "role": "user",
    "content": "%avcomm"
   }
  ]
 }

Output variable: gptresponse

  1. JavaScriptlet:

     var raw
     global("gptresponse_http_data");
     var json = JSON.parse(raw);
     setLocal("reply")
     json.choices[0].message.content);
    
  2. Flash: %reply

  3. Say: %reply

Still, %reply is output as a literal string: =%reply

What works:

The HTTP POST request to https://api.openai.com/v1/chat/completions is successful.

I correctly get data in %gptresponse_http_data (raw JSON).

When I hardcode a JSON response in a JavaScriptlet, parsing works and %reply gets set correctly.

Example of working hardcoded test:

  var raw = '{"choices":[{"message":       {"content":"This is a test."}}]}';
  var json = JSON.parse(raw);
   setLocal("reply",    json.choices[0].message.content);

Also, this basic test works fine:

setGlobal(“reply”, “JS is working”);

But here’s the issue: When I try to use the actual response data, like this:

   var raw =    global("gptresponse_http_data");
   var json = JSON.parse(raw);
   setLocal("reply",   json.choices[0].message.content);

…the Flash and Say actions both output “=%reply” instead of the actual content.