diff --git a/dvd_bounce_brute_force.js b/dvd_bounce_brute_force.js index 55dc71a..c208e01 100644 --- a/dvd_bounce_brute_force.js +++ b/dvd_bounce_brute_force.js @@ -1,15 +1,22 @@ 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 * 7; -const framesMax = 30 * 60; +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; @@ -18,43 +25,110 @@ let angle = 45; let angles = [ 45, 45 + 90, 45 + 180, 45 + 270]; -let searchHit = 1; +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 (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; + if (y < 0.0) y = 0.0; } return { x, y, angle } } -function simulateAll () { +function simulateAll (xStart, yStart, xLimit, yLimit) { let res; let attempts = 0; let startTime; let duration; let secondsLeft; - for (let x = buffer; x < xMax-buffer; x++ ) { - for (let y = buffer; y < yMax-buffer; y++) { + 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 < 4; a++) { + //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++) { + 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) { + 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}`); @@ -63,24 +137,47 @@ function simulateAll () { 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}`) + //console.timeEnd(`${x},${y}`) duration = ((+new Date()) - startTime); - secondsLeft = (duration / 1000) * (x - (xMax - buffer)) * (y - (yMax - buffer)); - console.log(`Minutes Left: ${Math.round(secondsLeft / 60)}`); + 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(); + 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() } }