Pwa implementation in Yii2 PHP framework

I need to implement PWA for a project in Yii 2 framework in php. I have added the manifest.json file which is working as I checked in devtools. Also I added a service-worker file that registered successfull upon loading the browser. But the popup to install the app is not triggering in any device. I am stuck and need help.

sw.js

var staticCacheName = 'pwa-v' + new Date().getTime()

var filesToCache = [
        'css/bootstrap.css',
        'css/select2.min.css',
        'css/select2-bootstrap.css',
        'css/anno.css',
        'css/jquery.mThumbnailScroller.css',
        'css/jquery-ui.css',
        'css/bootstrap-theme.css',
        'css/fm.selectator.jquery.css',
        'css/lightgallery.min.css',
        'css/magnific-popup.css',
        'css/jquery.mCustomScrollbar.css',
        'css/bootstrap-datetimepicker.css',
        'css/croppie.css',
        'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.11.2/css/bootstrap-select.min.css',
        'css/developer.css',
        'css/empwin.css?v=2.37',
    'js/bootstrap.js?v=0.01',
        'js/fm.selectator.jquery.js?v=0.01',
        'js/lightgallery-all.min.js?v=0.01',
        'js/jquery.magnific-popup.min.js?v=0.01',
        'js/jquery.mThumbnailScroller.js?v=0.01',
        'js/moment.js?v=0.01',
        'js/bootstrap-datetimepicker.min.js?v=0.01',
        'js/highlight.min.js?v=0.01',
        'js/jquery-ui.js?v=0.01',
        'js/bootstrap-transition.js?v=0.01',
        'js/jquery.geocomplete.min.js?v=0.01',
        'js/croppie.js?v=0.01',
        'js/webcam.js?v=0.01',
        'js/anchorme.min.js?v=0.01',
        'js/anno.js?v=0.01',
        'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.11.2/js/bootstrap-select.min.js',
        'https://cdnjs.cloudflare.com/ajax/libs/jquery.lazyload/1.9.1/jquery.lazyload.min.js',
        'js/jquery.ui.core.min.js?v=0.01',
        'js/jquery.ui.timepicker.js?v=0.01',
        'js/jquery.pinBox.min.js?v=0.01',
        'js/propeller.min.js?v=0.01',
        'js/select2.full.js?v=0.01',
        'js/video.js?v=0.01',
        'js/jquery.mCustomScrollbar.concat.min.js?v=0.01',
        'js/custom.js?v=3.49',
        'js/custom1.js?v=0.02',
        'js/blur.js?v=0.01',
        'js/exif.js?v=0.02',
        'js/browser-deeplink.min.js',



]

// Cache on install
self.addEventListener("install", event => {
    this.skipWaiting();
    event.waitUntil(
        caches.open(staticCacheName)
            .then(cache => {
                return cache.addAll(filesToCache);
            })
    )
});

// Clear cache on activate
self.addEventListener('activate', event => {
    event.waitUntil(
        caches.keys().then(cacheNames => {
            return Promise.all(
                cacheNames
                    .filter(cacheName => (cacheName.startsWith("pwa-")))
                    .filter(cacheName => (cacheName !== staticCacheName))
                    .map(cacheName => caches.delete(cacheName))
            );
        })
    );
});

//Serve from Cache
self.addEventListener("fetch", event => {
    event.respondWith(
        caches.match(event.request)
            .then(response => {
                return response || fetch(event.request);
            })
            .catch(() => {
                return caches.match('offline');
            })
    )
});

manifest.json

{
    "theme_color": "#175795",
    "background_color": "#175795",
    "display": "standalone",
    "orientation": "portrait",
    "scope": "xxx",
    "start_url": "xxx",
    "name": "win",
    "icons": [
    {
      "src": "images/icons/icon-72x72.png",
      "sizes": "72x72",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-96x96.png",
      "sizes": "96x96",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-128x128.png",
      "sizes": "128x128",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-144x144.png",
      "sizes": "144x144",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-152x152.png",
      "sizes": "152x152",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-384x384.png",
      "sizes": "384x384",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
  
}

upload and process a potree file using threejs?

I’m currently exploring options for uploading and processing a Potree file using Three.js. I attempted to use the solution provided in the GitHub repository
https://github.com/pnext/three-loader?tab=readme-ov-file)
but unfortunately, it didn’t work out for me.

I was wondering if there is any alternative methods or resources that could help achieve this task? My objective is to enable the viewing of the Potree file directly within a web browser using Three.js. so i can process it……..

When creating an invoice on xero I get the error: TypeError: Converting circular structure to JSON

I am creating invoices on Xero but a couple of times (maybe 3 or 4 in about 1000 calls) i get the error: TypeError: Converting circular structure to JSON.

NOTE – the invoice is still being created

Here’s the code where im getting the error:

    const invoices = {
      invoices: [invoice],
    };

    let invoiceData: { body: Invoices } | undefined;
    try {
      invoiceData = await this.xero?.accountingApi.createInvoices(
        this.getTenantId(),
        invoices,
        true,
        4,
      );
    } catch (error: any) {
      const errors = error?.response?.body?.Elements?.[0]?.ValidationErrors;
      throw errors;
    }

    const invoiceNumber = invoiceData?.body?.invoices?.[0]?.invoiceNumber;

How to make the ball act more realisticly in my pong game?

i dont seem to make the ball react well..the ball only seems to go up when collides with the box…im programming with p5Play.js…https://github.com/simo8el8attar/MyPonggame.git

let box1;
let box2;
let ball;
let gameFloor1;
let gameFloor2;
let gameFloor3;
let gameFloor4;
function setup() {
    new Canvas(1270, 500);
  gameFloor1 =new Sprite(5, 245, 10, 500, 'static');
  gameFloor2 =new Sprite(1265, 245, 10, 500, 'static');
  gameFloor3 =new Sprite(0, 5, 2550, 10, 'static');
  gameFloor4 =new Sprite(0, 495, 2550, 10, 'static');
  
  box1 = new Sprite(25, 60, 20, 90, 'static');
  box2 = new Sprite(1240,160,20,90,'static');
  ball = new Sprite(800,300,30)
  ball.direction = 187;
  ball.speed = 6;
}

function draw() {
    background('black');
  box1.y = mouse.y
  box2.y = mouse.y
  
  if (box1.collides(ball)) {
        ball.direction = -400;
    ball.speed = 8;
    }
  if (box2.collides(ball)) {
        ball.direction = 187;
    ball.speed = 8;
    }
  if (gameFloor3.collides(ball)) {
    ball.speed = 8;
    }
  if (gameFloor4.collides(ball)) {
    ball.speed = 8;
    }
}

Problem sending file to server when in OneDrive

When the Excel file is synchronized via OneDrive and is open in the Excel application, when you try to select the file, the message “The file is in use” appears and this is correct. However, when I drag and drop the file, no message appears, but when sending the file to the server, the file is not sent.

Is there any way to check if a file is being used by another process? To be able to display the message yourself.

2d HTML5 game: How to dynamically add collision shapes to individual tiles?

I’m trying to write a multiplayer shooter game in HTML5 with Canvas. I have a function that loads 50 x 50 px map tiles like this in game.js:

const rotationKeys = {0: 0, 1: 90, 2: 180, 3: 270}

const tilemap = "0C0003 0W1003 0W0003 0W2003 0W3003 0W4003 0W0003".split(" "); // example

let tiles = {};

let collisionData = {}

function loadTiles() {
    for (const tileIndex in tilemap) {
        const rawTile = tilemap[tileIndex].substring(0, 3);
        const tileImg = new Image();
        tileImg.src = `sprites/maps/tiles/${rawTile}.png`;
        tiles[rawTile] = tileImg;
    }
}

function drawMap() {
    const tileSize = 50;
    gameSettings.mapWidth = 35;
    gameSettings.mapHeight = 24;

    const startX = Math.max(0, Math.floor(camera.x / (tileSize * scaleFactor)));
    const startY = Math.max(0, Math.floor(camera.y / (tileSize * scaleFactor)));

    const endX = Math.min(gameSettings.mapWidth, startX + Math.ceil(canvas.width / (tileSize * scaleFactor)) + 1);
    const endY = Math.min(gameSettings.mapHeight, startY + Math.ceil(canvas.height / (tileSize * scaleFactor)) + 1);
  
    for (let y = startY; y < endY; y++) {
      for (let x = startX; x < endX; x++) {
        const index = y * gameSettings.mapWidth + x;
        const tile = tilemap[index];
        const rotation = tile[3]; // Get rotation type for this tile
        const flip = tile[4]; // Get flip type for this tile
        const collision = parseInt(tile[5]); // Get collision type for this tile
  
        // Apply rotation transformation
        ctx.save(); // Save the current canvas state
        ctx.translate((x + 0.5) * tileSize * scaleFactor, (y + 0.5) * tileSize * scaleFactor); // Translate to the center of the tile
        ctx.rotate(rotationKeys[rotation] * Math.PI / 180); // Rotate by the specified angle (converted to radians)
  
        // Apply flip transformation
        var xScale = 1;
        var yScale = 1;
        if (flip == 1 || flip == 3) {
          xScale = -1;
        }
        if (flip == 2 || flip == 3) {
          yScale = -1;
        }
        ctx.scale(xScale, yScale);
  
        try {
            ctx.drawImage(tiles[tile.substring(0, 3)], -0.5 * tileSize * scaleFactor, -0.5 * tileSize * scaleFactor, tileSize * scaleFactor, tileSize * scaleFactor); // Draw the rotated image
        } catch (error) {
            console.error(`Failed to draw tile at (${x}, ${y}):`, error);
            console.log("Responsible tile:", tile);
        }
        ctx.restore(); // Restore the saved canvas state to undo the rotation transformation
      }
    }
}

There are 9 types of collision, where 0, 1 and 2 means the entire tile can be walked on. Where 3, 4 means that the entire tile is an obstacle (a wall for example). And the rest are basic rectangle shapes that are applied to the top of the 50×50 tile. The width of some shapes is 52, which exceed the tile size itself, resulting in extra edges. There is one shape that is a mixture of a rectangle and square.

Naturally, the collisions also need to go through the flip and rotation transformations, just like the tiles do.

My question is how can I do this? We should be able to detect that collision and not allow the player to go any further. He may continue to walk against the collision, it just shouldn’t let it walk on it.

I’ve tried something like this, but that didnt work as expected (misplacement and rotations/flips didnt work):

function generateCollisions(tileName, rotation, flip, collision) {
  // Check if collision data for this tile name already exists
  if (!(tileName in collisionData)) {

    // Determine collision shape based on collision type
    let collisionShape = null;

    switch (collision) {
      case 0:
      case 1:
      case 2:
        // The entire tile is walkable
        collisionShape = null; // No need to define a collision shape for walkable tiles
        break;
      case 3:
      case 4:
        // The entire tile is an obstacle
        collisionShape = { x: -1, y: -1, width: 52, height: 52 };
        break;
      case 5:
        collisionShape = { x: -1, y: 0, width: 52, height: 38 };
        break;
      case 6:
        collisionShape = { x: -1, y: 0, width: 52, height: 26 };
        break;
      case 7:
        collisionShape = { x: -1, y: 0, width: 52, height: 13 };
        break;
      case 8:
        collisionShape = { x: 0, y: 0, width: 26, height: 26 };
        break;
      case 9:
        collisionShape = { x: 24, y: 24, width: 26, height: 26 }; // this is a more complicated shape, should actually be a mix of rectangle of longer height and squre on top
        break;
    }

    if (collisionShape !== null && typeof collisionShape === 'object') {
      // Apply rotation and flip transformations to the collision shape
      const angleInRadians = rotationKeys[rotation] * Math.PI / 180;

      // Apply flip transformations
      if (flip === 1 || flip === 3) {
        collisionShape.x = 50 - collisionShape.x - collisionShape.width;
      }
      if (flip === 2 || flip === 3) {
        collisionShape.y = 50 - collisionShape.y - collisionShape.height;
      }

      // Apply rotation transformations
      const rotatedX = collisionShape.x * Math.cos(angleInRadians) - collisionShape.y * Math.sin(angleInRadians);
      const rotatedY = collisionShape.x * Math.sin(angleInRadians) + collisionShape.y * Math.cos(angleInRadians);

      // Update the collision shape with the transformed coordinates
      collisionShape.x = rotatedX;
      collisionShape.y = rotatedY;
    }

    collisionData[tileName] = collisionShape;
  }
}

NodeJS: Is it possible to pass modules to an isolate in isolated-vm?

I am trying to execute a script code inside isolated-vm‘s isolate. Script code needs some third party packages as dependencies like lodash, node-xlsx, etc.,. Is it possible to pass the dependent modules to an isolate?

Getting the following error while trying to pass module to an isolate:
TypeError: [object Module] could not be cloned.

Code:

import ivm from 'isolated-vm'
import _ from 'lodash-es'

(async function() {
        try{
                let code = `
                        async function setup() {
                                log('setup called!!');
                                log('config -> ', config);
                        }
                        setup();
                `;
                const isolate = new ivm.Isolate({ memoryLimit: 128 })
                const context = isolate.createContextSync()

                const jail = context.global
                jail.setSync('global', jail.derefInto());

                const config = {
                        id: 1234,
                        name: 'test'
                }
                jail.setSync('config', new ivm.ExternalCopy(config).copyInto());

                jail.setSync('libraries', new ivm.ExternalCopy(_).copyInto());

                jail.setSync('log', function(...args) {
                        console.log(...args);
                })

                const hostile = isolate.compileScriptSync(code)
                hostile.run(context).catch(err => console.error(err));

                        
        } catch(e) {
                console.log('err->', e)
        }
        
}) ()

Expected: Need to access libraries (lodash module) inside setup() function

How to change the icon of leaflet-routing-machine

Here is the usage of “new L.Routing.Control()“:

Leaflet Routing Machine – Usage of options

I copied the code and then modify it by adding two “routingControl_1” and “routingControl_2“:

var routingControl_1 = new L.Routing.Control({
    waypoints: [
        L.latLng(57.74, 11.94),
        L.latLng(57.6792, 11.949)
    ],
    show: false
}).addTo(map);

var routingControl_2 = new L.Routing.Control({
    waypoints: [
        L.latLng(57.74, 11.94),
        L.latLng(57.6792, 11.949)
    ],
    show: false
}).addTo(map);

But the two “L.Routing.Control()“s have the same icon “leaflet.routing.icons.png” in the UI.

Here is the source code related to “leaflet.routing.icons.png”:
(I downloaded this project and then search all files contains the keyword “leaflet.routing.icons.png“)

https://github.com/perliedman/leaflet-routing-machine/blob/master/dist/leaflet-routing-machine.css

.leaflet-routing-icon {
  background-image: url('leaflet.routing.icons.png');
  -webkit-background-size: 240px 20px;
  background-size: 240px 20px;
  background-repeat: no-repeat;
  margin: 0;
  content: '';
  display: inline-block;
  vertical-align: top;
  width: 20px;
  height: 20px;
}

https://github.com/perliedman/leaflet-routing-machine/blob/master/src/itinerary-builder.js

createStep: function(text, distance, icon, steps) {
  var row = L.DomUtil.create('tr', '', steps),
    span,
    td;
  td = L.DomUtil.create('td', '', row);
  span = L.DomUtil.create('span', 'leaflet-routing-icon leaflet-routing-icon-'+icon, td);
  td.appendChild(span);
  td = L.DomUtil.create('td', '', row);
  td.appendChild(document.createTextNode(text));
  td = L.DomUtil.create('td', '', row);
  td.appendChild(document.createTextNode(distance));
  return row;
}

The “createStep: function(text, distance, icon, steps)” has an icon argument, but I don’t know how to set it when creating the “new L.Routing.Control()“.

# Here is the dummy code.

var routingControl_1 = new L.Routing.Control({
    waypoints: [
        L.latLng(57.74, 11.94),
        L.latLng(57.6792, 11.949)
    ],
    show: false,
    custom_icon: /path/to/my_icon_1.png
}).addTo(map);

var routingControl_2 = new L.Routing.Control({
    waypoints: [
        L.latLng(57.74, 11.94),
        L.latLng(57.6792, 11.949)
    ],
    show: false,
    custom_icon: /path/to/my_icon_2.png
}).addTo(map);

How to set the custom icon for L.Routing.Control?

Ensuring H1 is within defined width when content is changed programmatically

There are two headings defined as below:

<h1>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. At risus viverra adipiscing at in tellus integer feugiat. Eu lobortis elementum nibh tellus molestie nunc. Sagittis purus sit amet volutpat. Facilisis leo vel fringilla est. Luctus venenatis lectus magna fringilla urna. Faucibus pulvinar elementum integer enim neque volutpat ac tincidunt vitae. Amet consectetur adipiscing elit ut aliquam. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Gravida cum sociis natoque penatibus et magnis dis. Sit amet venenatis urna cursus eget nunc scelerisque. Mollis aliquam ut porttitor leo a diam. Vestibulum mattis ullamcorper velit sed. Tellus rutrum tellus pellentesque eu tincidunt.</h1>
<h1>{text}</h1>

First one respects defined width as aqua:
enter image description here

Second one doesn’t respect defined width and destroys the whole layout:
enter image description here

text is updated by JavaScript after both of headlines are rendered. At render time the length of h1 content is zero (text = '') and heading renders correctly. I assume after JS starts to change it the h1 doesn’t know the actual length of content and it can’t compute the wrap correctly.

I tried to give width and max-width properties to the second h1. There were no changes in behaviour but I confirmed it goes out of width as red:
enter image description here

What should be the correct approach that second headline respects the width?

Function strings evaluation in script injection in chrome extensions

I am trying to improve the script injection in chrome extension. As per the previous implementation written using manifest version 2, a function string was coming in the response of an API call and then the function string is again wrapped inside another function string and then passed to the executeScript function to do it’s task.

For Ex:
Let say API call send the below function string in the response:

function() {perform_login(doc)};

Now, it is again processed and converted to the below function string

const script = “function() {” + execTag + “n perform_login(document); }”;

Where execTag is the variable holding the value of API response function string. And the inject function is called as below

chrome.tabs.executeScript(tabId, {code, run_at: “document_end”}, executeCallback);

where

code = “(” + someWrapperFn + “)” + “(” + script + “)”;

and executeCallback is some other function that will execute during the process.

Now, as per the manifest version 3 executeScript docs – The format of executeScript is changed and now there is no code object.

How can I change the current implementation so that it injects scripts properly. How can I convert the function strings to normal functions.

P.S. I tried using the eval() to convert the string to normal function but chrome extension is not allowing it stating content security policy violation.

how do i use brevo api to send whatsapp messages?

following these docs https://mukulsib.readme.io/reference/sendwhatsappmessage

i wrote this code:

import axios from 'axios';

const API_KEY = '/i got api key from brevo SMTP & API page/';

export default async function handler(req, res) {
  if (req.method === 'POST') {
    const { phoneNumbers, Message } = req.body;

    for (const phone of phoneNumbers) {
        const options = {
            method: 'POST',
            headers: {
              accept: 'application/json',
              'content-type': 'application/json',
              'api-key': API_KEY,
            },
            body: JSON.stringify({
                senderNumber: '123456789', 
                text: Message, 
                contactNumbers: [phone,]
            })
        };

            try {
                const response = await axios.request(options);
                console.log(`Message sent successfully to ${phone}`);
                console.log('Response data:', response.data);
            } catch (error) {
                console.error(`Error sending message to ${phone}:`, error.message);
            }
        }
    
            res.status(200).json({ message: 'Messages sent' });
        } else {
            res.status(405).json({ error: 'Method not allowed' });
        }
    }

and when i try it on the docs page i get this error:
{“code”: “permission_denied”, “message”: “Your account is not registered”}

boxBufferGeometry doesn’t show up in React three Fiber

This is the App.jsx file

import { Canvas } from "@react-three/fiber"
import Experience from "./components/Experience"
function App() {
  return (
    <Canvas>
      <Experience />
    </Canvas>
  )
}

export default App

This is Experience.jsx file I add boxBufferGeometry and it is not workink

const Experience = () => {
    return (
        <mesh>
            <boxBufferGeometry />
            <meshNormalMaterial />
        </mesh>
    )
}

export default Experience

How can I make the value of the second option vary depending on the value of the first option?

We are currently modifying the code that changes the amount according to each option.

However, I would like to modify the ‘value’ of option 2 and ‘value’ of option 3 to change according to option 1.

For example, if option 1-1 is selected, the amount of 2-2 is -1, but if option 1-2 is selected, the amount of 2-2 is -2.

I would like the amount of the final TOTAL to be revised according to the revised value value.

$('.form-item input').on('change', function() {
  // addition and subtraction here
  var $this;
  var sum = 0;

  $('.form-item input').each(function() {
    $this = $(this);

    if ($this[0].checked == true) {
      sum += parseInt($this.val());
    }

    $('.total span').html(sum.toLocaleString('en-US'));
  })
});
.form-wrap {
  display: block;
  margin: 0 auto;
  width: 480px;
}

.form-text {
  text-align: left;
  font-size: 20px;
  font-weight: 400;
  line-height: 1.3;
  margin-bottom: 15px;
  color: #bbb;
  padding: 0 5px;
}

#fm-title {
  color: #444;
  font-weight: 600;
}

#op-title {
  font-weight: 600;
  font-size: 20px;
  color: #444;
}

.form-item {
  margin-bottom: 5px;
}

.form-item input[type=radio] {
  display: none;
}

.form-type-radio {
  text-align: center;
  margin-bottom: 35px;
}

.form-item input[type=radio]+label {
  display: inline-block;
  cursor: pointer;
  height: 115px;
  width: 480px;
  border: 2px solid #ddd;
  line-height: 1.5;
  text-align: left;
  font-weight: 400;
  font-size: 16px;
  padding: 26px 45px;
  border-radius: 20px;
}

.form-item input[type=radio]+label {
  background-color: #fff;
  color: #bbb;
  font-weight: 400;
}

.form-item input[type=radio]:checked+label {
  background-color: #fff;
  color: #bbb;
  border-color: #444;
}

.total {
  font-size: 22px;
  font-weight: 600;
  height: 65px;
  padding: 15px 15px;
  text-align: center;
  color: #555;
}

#bm-text {
  font-size: 18px;
  width: 100%;
  font-weight: 400;
  color: #555;
  padding: 0 5px;
  margin-bottom: 40px;
}

#bm-text p {
  margin-bottom: 20px;
}

@media (max-width: 991px) {
  .form-wrap {
    width: 100%;
  }
  .form-item input[type=radio]+label {
    width: 100%;
    height: 70px;
    line-height: 1.4;
    padding: 17px 25px;
    font-size: 12px;
    border: 1px solid #ddd;
  }
  .form-text {
    font-size: 14px;
    margin-bottom: 10px;
  }
  #op-title {
    font-size: 13px;
  }
  .form-item {
    margin-bottom: 1px;
  }
  .form-type-radio {
    margin-bottom: 20px;
  }
  .total {
    font-size: 17px;
    font-weight: 500;
    padding: 10px 10px;
    color: #444;
  }
  #bm-text {
    font-size: 12px;
    margin-bottom: 20px;
  }
  #bm-text p {
    margin-bottom: 15px;
  }
}
<div class="form-wrap">
  <div class="form-type-radio">
    <div class="form-text">OPTION 1</div>
    <div class="form-item">
      <input type="radio" id="radio-1" name="samename" value="1800000" class="form-radio" checked="checked">
      <label class="option" for="radio-1"><span id="op-title">1-1</span></label>
    </div>

    <div class="form-item">
      <input type="radio" id="radio-2" name="samename" value="2500000" class="form-radio">
      <label class="option" for="radio-2"><span id="op-title">1-2</span></label>
    </div>

    <div class="form-item">
      <input type="radio" id="radio-3" name="samename" value="6000000" class="form-radio">
      <label class="option" for="radio-3"><span id="op-title">1-3</span></label>
    </div>
  </div>

  <div class="form-type-radio">
    <div class="form-text">OPTION 2</div>
    <div class="form-item">
      <input type="radio" id="radio-4" name="samename1" value="0" class="form-radio" checked="checked">
      <label class="option" for="radio-4"><span id="op-title">2-1</span></label>
    </div>

    <div class="form-item">
      <input type="radio" id="radio-5" name="samename1" value="-700000" class="form-radio">
      <label class="option" for="radio-5"><span id="op-title">2-2</span></label>
    </div>
  </div>
  <div class="form-type-radio">
    <div class="form-text">OPTION 3</div>
    <div class="form-item">
      <input type="radio" id="radio-6" name="samename2" value="0" class="form-radio" checked="checked">
      <label class="option" for="radio-6"><span id="op-title">3-1</span></label>
    </div>

    <div class="form-item">
      <input type="radio" id="radio-7" name="samename2" value="2000000" class="form-radio">
      <label class="option" for="radio-7"><span id="op-title">3-2</span></label>
    </div>

    <div class="form-item">
      <input type="radio" id="radio-8" name="samename2" value="-1300000" class="form-radio">
      <label class="option" for="radio-8"><span id="op-title">3-3</span></label>
    </div>

    <div class="form-item">
      <input type="radio" id="radio-9" name="samename2" value="-600000" class="form-radio">
      <label class="option" for="radio-9"><span id="op-title">3-4</span></label>
    </div>
  </div>

  <div class="form-type-radio">
    <div class="form-text">OPTION 4</div>
    <div class="form-item">
      <input type="radio" id="radio-10" name="samename3" value="0" class="form-radio" checked="checked">
      <label class="option" for="radio-10"><span id="op-title">4-1</span></label>
    </div>

    <div class="form-item">
      <input type="radio" id="radio-11" name="samename3" value="100000" class="form-radio">
      <label class="option" for="radio-11"><span id="op-title">4-2</span></label>
    </div>

    <div class="form-item">
      <input type="radio" id="radio-12" name="samename3" value="300000" class="form-radio">
      <label class="option" for="radio-12"><span id="op-title">4-3</span></label>
    </div>
  </div>

  <div class="form-type-radio">
    <div class="form-text">OPTION 5</div>
    <div class="form-item">
      <input type="radio" id="radio-13" name="samename4" value="0" class="form-radio" checked="checked">
      <label class="option" for="radio-13"><span id="op-title">5-1</span></label>
    </div>

    <div class="form-item">
      <input type="radio" id="radio-14" name="samename4" value="300000" class="form-radio">
      <label class="option" for="radio-14"><span id="op-title">5-2</span></label>
    </div>
  </div>
  <div class="total">TOTAL <span>0</span></div>
</div>