Skip to content

Instantly share code, notes, and snippets.

@devNoiseConsulting
Last active December 13, 2018 01:39
Show Gist options
  • Save devNoiseConsulting/4c8e181c09d3c55f6b53c52fd9cfc59a to your computer and use it in GitHub Desktop.
Save devNoiseConsulting/4c8e181c09d3c55f6b53c52fd9cfc59a to your computer and use it in GitHub Desktop.
RDM Raid Circle minimizer
// Goal: Trying to minimize the number of raid circles looked at.
//
// 1. Setup up a raid circle instance that covers your desired raid area
// 2. Run the UI-Controller, so that the database can be populated with your gym data
// 2b. Update your gym data so that the gyms have name.
// 3. Run the sql statement to a list of gyms that are good candidates for a raid circle.
// SELECT
// g1.lat,
// g1.lon,
// g1.name,
// count(*) AS gyms,
// sum(g2.ex_raid_eligible) AS ex_gyms
// FROM
// gym AS g1, gym AS g2
// WHERE
// st_distance_sphere(
// point(g1.lon, g1.lat),
// point(g2.lon, g2.lat)
// )
// < 550
// AND (g1.id != g2.id OR g1.ex_raid_eligible = 1)
// GROUP BY
// g1.lat, g1.lon, g1.name
// ORDER BY
// 5 DESC, 4 DESC, 1, 2;
//
// mysql -urdmuser -p rdmdb -N -e"SELECT g1.lat, g1.lon, g1.name, count(*) AS gyms, sum(g2.ex_raid_eligible) AS ex_gyms FROM gym AS g1, gym AS g2 WHERE st_distance_sphere( point(g1.lon, g1.lat), point(g2.lon, g2.lat) ) < 550 AND (g1.id != g2.id OR g1.ex_raid_eligible = 1) GROUP BY g1.lat, g1.lon, g1.name ORDER BY 5 DESC, 4 DESC, 1, 2;" > /tmp/raid-circles.csv
//
// 4. Install the great-circle node package.
// npm install great-circle
//
// 5. Run this script on the
// node index.js /tmp/raid-circles.csv > optmized-circles.csv
//
// 6. You may still have to many points. Try to determine the best points for your area.
// Try to target 30 locations per phone for raids.
// 7. Create a new instance on RealDeviceMap and paste in the contents of optmized-circles.csv
// 8. Set a device to the new instance.
const GreatCircle = require('great-circle');
const fs = require('fs');
const path = require('path');
const pathName = process.argv[2];
if (pathName) {
poi = readFile(pathName);
poi = formatPoints(poi);
gyms = filterCloseGyms(poi);
console.log(`lat,lon,name,gyms,ex_gyms`);
gyms.sort(compareExGyms).forEach(p => {
console.log(`${p.lat},${p.lon},"${p.name}",${p.gyms},${p.exgyms}`);
});
// console.log(gyms.length);
} else {
var node = path.basename(process.argv[0]);
var script = path.basename(process.argv[1]);
console.log('Usage: ' + node + ' ' + script + ' <filename> <gymsFile.csv>');
}
function readFile(fileName) {
let poi;
try {
let text = fs.readFileSync(fileName, 'utf8');
poi = text.split('\n').map(point => point.split('\t'));
} catch (e) {
console.log('ERROR 1: file: ' + fileName + ' error: ' + e.message);
return false;
}
return poi;
}
function formatPoints(points) {
return points.map(p => { return { lat: p[0], lon: p[1], gyms: parseInt(p[3]), exgyms: parseInt(p[4]), name: p[2] }; });
}
function filterCloseGyms(points) {
let gyms = points;
let index = 0;
while (index < gyms.length) {
let filteredGyms = gyms.slice(0, index + 1);
let circleGym = gyms[index];
gyms.slice(index).forEach(g => {
let distance = GreatCircle.distance(circleGym.lat, circleGym.lon, g.lat, g.lon, 'M');
if ((distance > 550) && (g.exgyms > 0 || g.gyms > 1)) {
filteredGyms.push(g);
}
});
gyms = filteredGyms.slice();
index++;
}
return gyms;
}
function compareExGyms(a, b) {
if (b.exgyms < a.exgyms) {
return -1;
}
if (b.exgyms > a.exgyms) {
return 1;
}
return b.gyms - a.gyms
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment