Skip to content

Commit

Permalink
Merge pull request #44 from versx/global-search
Browse files Browse the repository at this point in the history
Global Search
  • Loading branch information
versx authored Aug 17, 2020
2 parents 14e4356 + 303d83d commit 44bb572
Show file tree
Hide file tree
Showing 17 changed files with 380 additions and 14 deletions.
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"i18n": "^0.9.1",
"mustache-express": "^1.3.0",
"mysql": "^2.18.1",
"nodes2ts": "^2.0.0"
"nodes2ts": "^2.0.0",
"sanitizer": "^0.1.3"
}
}
3 changes: 2 additions & 1 deletion src/config.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -156,5 +156,6 @@
"enabled": false,
"url": "",
"maxScouts": 15
}
},
"searchMaxResults": 20
}
205 changes: 205 additions & 0 deletions src/data/map.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
/* global BigInt */
'use strict';

const i18n = require('i18n');
const S2 = require('nodes2ts');
const sanitizer = require('sanitizer');

const config = require('../config.json');
const MySQLConnector = require('../services/mysql.js');
const utils = require('../services/utils.js');

const db = new MySQLConnector(config.db.scanner);
const dbManual = new MySQLConnector(config.db.manualdb);

const masterfile = require('../../static/data/masterfile.json');


const getPokemon = async (minLat, maxLat, minLon, maxLon, showPVP, showIV, updated, pokemonFilterExclude = null, pokemonFilterIV = null, pokemonFilterPVP = null) => {
const excludePokemonIds = [];
const excludeFormIds = [];
Expand Down Expand Up @@ -1041,6 +1046,155 @@ const getNests = async (minLat, maxLat, minLon, maxLon, nestFilterExclude = null
return null;
};

const getSearchData = async (lat, lon, id, value) => {
let sql = '';
let args = [lat, lon, lat];
let useManualDb = false;
let conditions = [];
let sanitizedValue = sanitizer.sanitize(value);
switch (id) {
case 'search-reward':
let pokemonIds = getPokemonIdsByName(sanitizedValue);
let pokemonRewardSQL = '';
if (pokemonIds.length > 0) {
// TODO: Search by form
pokemonRewardSQL = 'quest_pokemon_id IN (';
for (let i = 0; i < pokemonIds.length; i++) {
const pokemonId = pokemonIds[i];
pokemonRewardSQL += '?';
if (i !== pokemonIds.length - 1) {
pokemonRewardSQL += ',';
}
args.push(pokemonId);
}
pokemonRewardSQL += ')';
conditions.push(pokemonRewardSQL);
}
let itemIds = getItemIdsByName(sanitizedValue);
let itemsSQL = '';
if (itemIds.length > 0) {
itemsSQL = 'quest_item_id IN (';
for (let i = 0; i < itemIds.length; i++) {
const id = itemIds[i];
itemsSQL += '?';
if (i !== itemIds.length - 1) {
itemsSQL += ',';
}
args.push(id);
}
itemsSQL += ')';
conditions.push(itemsSQL);
}
let questTypes = getQuestTypesByName(sanitizedValue);
let questTypesSQL = '';
if (questTypes.length > 0) {
questTypesSQL = 'quest_type IN (';
for (let i = 0; i < questTypes.length; i++) {
const id = questTypes[i];
questTypesSQL += '?';
if (i !== questTypes.length - 1) {
questTypesSQL += ',';
}
args.push(id);
}
questTypesSQL += ')';
conditions.push(questTypesSQL);
}
let questRewardTypes = getQuestRewardTypesByName(sanitizedValue);
let questRewardTypesSQL = '';
if (questRewardTypes.length > 0) {
questRewardTypesSQL = 'quest_reward_type IN (';
for (let i = 0; i < questRewardTypes.length; i++) {
const id = questRewardTypes[i];
questRewardTypesSQL += '?';
if (i !== questRewardTypes.length - 1) {
questRewardTypesSQL += ',';
}
args.push(id);
}
questRewardTypesSQL += ')';
conditions.push(questRewardTypesSQL);
}
sql = `
SELECT id, name, lat, lon, url, quest_type, quest_pokemon_id, quest_item_id, quest_reward_type,
json_extract(json_extract('quest_rewards','$[*].info.form_id'),'$[0]') AS quest_pokemon_form_id,
ROUND(( 3959 * acos( cos( radians(?) ) * cos( radians( lat ) ) * cos( radians( lon ) - radians(?) ) + sin( radians(?) ) * sin( radians( lat ) ) ) ),2) AS distance
FROM pokestop
WHERE ${conditions.join(' OR ') || 'FALSE'}
`;
break;
case 'search-nest':
let ids = getPokemonIdsByName(sanitizedValue);
let pokemonSQL = '';
if (ids.length > 0) {
pokemonSQL = 'OR pokemon_id IN (';
for (let i = 0; i < ids.length; i++) {
const nestPokemonId = ids[i];
pokemonSQL += '?';
if (i !== ids.length - 1) {
pokemonSQL += ',';
}
args.push(nestPokemonId);
}
pokemonSQL += ')';
}
sql = `
SELECT name, lat, lon, pokemon_id,
ROUND(( 3959 * acos( cos( radians(?) ) * cos( radians( lat ) ) * cos( radians( lon ) - radians(?) ) + sin( radians(?) ) * sin( radians( lat ) ) ) ),2) AS distance
FROM nests
WHERE LOWER(name) LIKE '%${sanitizedValue}%' ${pokemonSQL}
`;
useManualDb = true;
break;
case 'search-gym':
sql = `
SELECT id, name, lat, lon, url,
ROUND(( 3959 * acos( cos( radians(?) ) * cos( radians( lat ) ) * cos( radians( lon ) - radians(?) ) + sin( radians(?) ) * sin( radians( lat ) ) ) ),2) AS distance
FROM gym
WHERE LOWER(name) LIKE '%${sanitizedValue}%'
`;
break;
case 'search-pokestop':
sql = `
SELECT id, name, lat, lon, url,
ROUND(( 3959 * acos( cos( radians(?) ) * cos( radians( lat ) ) * cos( radians( lon ) - radians(?) ) + sin( radians(?) ) * sin( radians( lat ) ) ) ),2) AS distance
FROM pokestop
WHERE LOWER(name) LIKE '%${sanitizedValue}%'
`;
break;
}
sql += ` ORDER BY distance LIMIT ${config.searchMaxResults || 20}`;
let results = useManualDb
? await dbManual.query(sql, args)
: await db.query(sql, args);
if (results && results.length > 0) {
switch (id) {
case 'search-reward':
for (let i = 0; i < results.length; i++) {
let result = results[i];
// TODO: Check quest types
if (result.quest_item_id > 0) {
result.url2 = config.icons['Default'/* TODO: Add icon style */] + `/item/${result.quest_item_id}.png`;
} else if (result.quest_pokemon_id > 0) {
const formId = result.quest_pokemon_form_id ? result.quest_pokemon_form_id : '00';
result.url2 = config.icons['Default'/* TODO: Add icon style */] + `/pokemon/pokemon_icon_${utils.zeroPad(result.quest_pokemon_id, 3)}_${formId}.png`;
} else if (result.quest_reward_type === 3) {
result.url2 = config.icons['Default'/* TODO: Add icon style */] + '/item/-1.png';
}
}
break;
case 'search-nest':
for (let i = 0; i < results.length; i++) {
let result = results[i];
result.url = config.icons['Default'/* TODO: Add icon style */] + `/pokemon/pokemon_icon_${utils.zeroPad(result.pokemon_id, 3)}_00.png`;
}
break;
}
return results;
}
return null;
};

const getPolygon = (s2cellId) => {
let s2cell = new S2.S2Cell(new S2.S2CellId(BigInt(s2cellId).toString()));
let polygon = [];
Expand Down Expand Up @@ -1160,6 +1314,56 @@ const getAvailableNestPokemon = async () => {
return result;
};

const getPokemonIdsByName = (search) => {
const pokemon = masterfile.pokemon;
const keys = Object.keys(pokemon);
const filtered = keys.filter(x => {
if (x !== 0) {
const name = i18n.__('poke_' + x) || '';
if (name.toLowerCase().includes(search)) {
return x;
}
}
});
return filtered;
};

const getItemIdsByName = (search) => {
const items = masterfile.items;
const keys = Object.keys(items);
const filtered = keys.filter(x => {
const name = i18n.__('item_' + x) || '';
if (name.toLowerCase().includes(search)) {
return x;
}
});
return filtered;
};

const getQuestTypesByName = (search) => {
const questTypes = masterfile.quest_types;
const keys = Object.keys(questTypes);
const filtered = keys.filter(x => {
const name = i18n.__('quest_' + x) || '';
if (name.toLowerCase().includes(search)) {
return x;
}
});
return filtered;
};

const getQuestRewardTypesByName = (search) => {
const questRewardTypes = masterfile.quest_reward_types;
const keys = Object.keys(questRewardTypes);
const filtered = keys.filter(x => {
const name = i18n.__('quest_reward_' + x) || '';
if (name.toLowerCase().includes(search)) {
return x;
}
});
return filtered;
};

class Ring {
constructor(lat, lon, radius) {
this.id = `${lat}-${lon}-${radius}`;
Expand All @@ -1180,6 +1384,7 @@ module.exports = {
getSubmissionTypeCells,
getWeather,
getNests,
getSearchData,
getAvailableRaidBosses,
getAvailableQuests,
getAvailableNestPokemon
Expand Down
11 changes: 11 additions & 0 deletions src/routes/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ router.post('/get_data', async (req, res) => {
res.json({ data: data });
});

router.get('/search', async (req, res) => {
const data = await getSearch(req.query);
res.json({ data: data });
});


const getData = async (perms, filter) => {
//console.log('Filter:', filter);
const minLat = parseFloat(filter.min_lat);
Expand Down Expand Up @@ -618,6 +624,11 @@ const getData = async (perms, filter) => {
return data;
};

const getSearch = async (filter) => {
const searchData = await map.getSearchData(filter.lat, filter.lon, filter.id, filter.value);
return searchData;
};

const generateShowHideButtons = (id, type, ivLabel = '') => {
const hideString = i18n.__('filter_hide');
const showString = i18n.__('filter_show');
Expand Down
2 changes: 1 addition & 1 deletion src/views/header.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<link rel="stylesheet" type="text/css" href="/css/all.css" />

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha256-VsEqElsCHSGmnmHXGQzvoWjWwoznFSZc6hs7ARLRacQ=" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.js" integrity="sha256-tfcLorv/GWSrbbsn6NVgflWp1YOmTjyJ8HWtfXaOaJc=" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdn.datatables.net/v/bs4/dt-1.10.18/r-2.2.2/rg-1.1.0/sc-1.5.0/datatables.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/bundle.min.js"></script>
Expand Down
Loading

0 comments on commit 44bb572

Please sign in to comment.