const { writeFileSync } = require('fs'); function generateRandomIntegerInRange(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } const xMax = 1080.0; const yMax = 1920.0; const framesMin = 30 * 5; const framesMax = 30 * 60 * 3; const distanceMax = 30.0; const buffer = 50; const xRandStart = generateRandomIntegerInRange(buffer, xMax - buffer); const yRandStart = generateRandomIntegerInRange(buffer, yMax - buffer); let xStart = 0; let yStart = 0; let frames = framesMin; let distance = 15.0; let angle = 45; let angles = [ 45, 45 + 90, 45 + 180, 45 + 270]; let searchHit = 100; let iterator = 10; function addCommas (num) { let nums = (num + '').split(''); let output = ''; nums.reverse(); output += nums[0]; for (let i = 1; i < nums.length; i++) { if (i % 3 === 0) output += ','; output += nums[i]; } return output.split('').reverse().join(''); } function millisecondsToStr (milliseconds) { // TIP: to find current time in milliseconds, use: // var current_time_milliseconds = new Date().getTime(); function numberEnding (number) { return (number > 1) ? 's' : ''; } var temp = Math.floor(milliseconds / 1000); var years = Math.floor(temp / 31536000); if (years) { return years + ' year' + numberEnding(years); } //TODO: Months! Maybe weeks? var days = Math.floor((temp %= 31536000) / 86400); if (days) { return days + ' day' + numberEnding(days); } var hours = Math.floor((temp %= 86400) / 3600); if (hours) { return hours + ' hour' + numberEnding(hours); } var minutes = Math.floor((temp %= 3600) / 60); if (minutes) { return minutes + ' minute' + numberEnding(minutes); } var seconds = temp % 60; if (seconds) { return seconds + ' second' + numberEnding(seconds); } return 'less than a second'; //'just now' //or other string you like; } let currentDisplay = ''; let currentUpdate = 0; function displayTimeLeft (msLeft, percent) { const timeStr = `Time Left: ~${millisecondsToStr(msLeft)}`; const now = +new Date(); const rateLimit = msLeft < 60 * 1000 ? (now - currentUpdate > 1000) : (now - currentUpdate > 60 * 1000) ; if (timeStr != currentDisplay && !rateLimit) { currentDisplay = timeStr; currentUpdate = now; console.log(timeStr + ` @ ${Math.round(percent * 10) / 10}%`); } } function simulate (x, y, frames, angle, distance) { for (let i = 0; i < frames; i++) { x = x + distance * Math.cos(angle * Math.PI / 180.0); y = y + distance * Math.sin(angle * Math.PI / 180.0); if (x >= 1080.0 || x <= 0.0) { angle = 180 - angle; } if (x >= 1080.0) x = 1080.0; if (x < 0.0) x = 0.0; if (y >= 1920.0 || y <= 0.0) { angle = 360 - angle; } if (y >= 1920.0) y = 1920.0; if (y < 0.0) y = 0.0; } return { x, y, angle } } function simulateAll (xStart, yStart, xLimit, yLimit) { let res; let attempts = 0; let startTime; let duration; let secondsLeft; let pointsTotal = Math.ceil((xLimit - xStart) / iterator) * Math.ceil((yLimit - yStart) / iterator); let searchesTotal = (pointsTotal * angles.length * 10 * Math.ceil( (framesMax - framesMin) / iterator) ); let pointsCounter = 0; let rollingAvgDuration = null; console.log(`Simulating ${addCommas(searchesTotal)} possible candidates...`); console.log(``) for (let x = xStart; x < xLimit; x+=iterator ) { for (let y = yStart; y < yLimit; y+=iterator) { startTime = +new Date(); //console.time(`${x},${y}`) for (let a = 0; a < angles.length; a++) { for (let d = 0; d < 10; d++) { for (let frames = framesMin; frames < framesMax + 1; frames+=iterator) { angle = angles[a]; res = simulate(x, y, frames, angle, distance + d); attempts++; if (Math.abs(res.x - x) < searchHit && Math.abs(res.y - y) < searchHit && ((res.angle == angle) ) ) { console.log(`#${attempts}`); console.log(`startx = ${x} endx = ${res.x}`); console.log(`starty = ${y} endy = ${res.y}`); console.log(`startangle = ${angle}`); console.log(`frames = ${frames}`); console.log(`distance = ${distance + d}`); console.log(`searchHit = ${searchHit}`); console.log("++++++++++++++++++++++++++++++++++++++++"); writeFileSync('candidate.json', JSON.stringify({ startx : x, starty : y, startangle : angle, startframes : frames, distance : distance + d }) , 'utf-8') return res; } } } } //console.timeEnd(`${x},${y}`) duration = ((+new Date()) - startTime); if (rollingAvgDuration === null) { rollingAvgDuration = duration; } else { rollingAvgDuration = (rollingAvgDuration + duration) / 2; } msLeft = duration * (pointsTotal - pointsCounter); displayTimeLeft(msLeft, attempts / searchesTotal); pointsCounter++; } } } function main () { let res; let xLimit = xMax - buffer; let yLimit = yMax - buffer; xStart = xRandStart; yStart = yRandStart; for (let i = 0; i < 7; i++) { res = simulateAll(xStart, yStart, xLimit, yLimit); xStart = res.x - searchHit; yStart = res.y - searchHit; xLimit = res.x + searchHit; yLimit = res.y + searchHit; searchHit = Math.floor(searchHit / 2.0); iterator = Math.floor(iterator / 2.0); if (iterator === 0) iterator = 1; if (searchHit === 0) process.exit() } } main();