import: working solution

This commit is contained in:
muerwre 2018-12-06 18:36:28 +07:00
parent aa581b1a77
commit fc5b6009cb
8 changed files with 257 additions and 13 deletions

View file

@ -11,11 +11,12 @@ const RouteSchema = new Schema(
route: { type: Array, default: [] },
stickers: { type: Array, default: [] },
owner: { type: Schema.Types.ObjectId, ref: 'User' },
logo: { type: String, default: 'DEFAULT' },
distance: { type: Number, default: 0 },
public: { type: Boolean, default: true },
created_at: { type: Date, default: Date.now() },
updated_at: { type: Date, default: Date.now() },
logo: { type: String, default: 'DEFAULT' },
map_style: { type: String, default: 'DEFAULT' },
},
);

View file

@ -1,5 +1,4 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
// Schemas
@ -17,6 +16,7 @@ const UserSchema = new Schema(
first_name: { type: String },
last_name: { type: String },
photo: { type: String },
version: { type: Number, default: 2 },
routes: [{ type: Schema.Types.ObjectId, ref: 'Route' }]
},
{

181
backend/tools/import.js Executable file
View file

@ -0,0 +1,181 @@
#!/usr/bin/env node
const mysql = require('mysql');
const { REPLACEMENT, MAPS } = require('./stickersReplacement');
const db = require('../config/db');
let total_dist = 0;
const { User, Route } = require('../models');
const con = mysql.createConnection({
host: 'vault48.org',
user: 'macos_exporter',
password: 'password',
});
const tryJSON = data => {
try {
return JSON.parse(data);
} catch (e) {
return {};
}
};
function deg2rad(deg) {
return (deg * Math.PI) / 180;
}
const findDistance = (t1, n1, t2, n2) => {
// convert coordinates to radians
const lat1 = deg2rad(t1);
const lon1 = deg2rad(n1);
const lat2 = deg2rad(t2);
const lon2 = deg2rad(n2);
// find the differences between the coordinates
const dlat = lat2 - lat1;
const dlon = lon2 - lon1;
// here's the heavy lifting
const a = (Math.sin(dlat / 2) ** 2) +
(Math.cos(lat1) * Math.cos(lat2) * (Math.sin(dlon / 2) ** 2));
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); // great circle distance in radians
// const dm = c * 3961; // great circle distance in miles
const dk = c * 6373; // great circle distance in km
// round the results down to the nearest 1/1000
// const mi = round(dm);
return (Math.round(dk * 1000) / 1000);
};
const calcPolyDistance = route => {
let summ = 0;
for (let i = 1; i < route.length; i += 1) {
summ += findDistance(route[i - 1].lat, route[i - 1].lng, route[i].lat, route[i].lng);
}
total_dist += summ;
return parseFloat(Number(summ).toFixed(2));
};
const stickerAngleParser = angle => parseFloat((Number(angle) - Math.PI).toFixed(2));
const stickerStyleParser = style => (REPLACEMENT[style]
? { ...REPLACEMENT[style] }
: { set: 'base', sticker: 'chicken' });
const stickersParser = stickers => (
stickers.map(({
ang, latlng, style, text
}) => ({
angle: stickerAngleParser(ang), // todo: change it!
latlng,
text,
...stickerStyleParser(style),
}))
);
const pointParser = points => (
points.map(({ latlngs, text }) => ({
text,
latlng: latlngs[0],
set: 'base',
sticker: 'empty',
angle: 2.2,
}))
);
const mapStyleParser = style => (MAPS[style]
? MAPS[style]
: 'DEFAULT'
);
const run = async () => {
await con.connect(err => { if (err) throw err; });
await con.query('use neu_map');
const users = await new Promise(resolve => con.query('SELECT * from tokens where role = "vk"', (err, rows) => {
resolve(rows.map(({
login, token, created, role, data
}) => {
const info = tryJSON(data);
const created_at = new Date(created * 1000);
return {
_id: login,
token,
created_at,
updated_at: created_at,
name: info.name,
first_name: (info.name && info.name.split(' ')[0]) || '',
last_name: (info.name && info.name.split(' ')[1]) || '',
role,
photo: info.photo,
version: 1,
};
}));
}));
const routes = await new Promise(resolve => con.query('SELECT routes.*, tokens.login as login from routes LEFT JOIN tokens ON tokens.id = routes.id WHERE tokens.login IS NOT NULL AND tokens.role="vk"', (err, rows) => {
if (err) console.log('error', err);
resolve(rows.map(({
data, created, name, login
}) => {
const {
map_style, route, stickers, points, logo
} = tryJSON(data);
const created_at = new Date(created * 1000);
return {
_id: name,
owner: { _id: login },
created_at,
updated_at: created_at,
map_style: mapStyleParser(map_style),
route,
stickers: [
...stickersParser(stickers),
...pointParser(points)
],
logo,
title: '',
version: 1,
distance: calcPolyDistance(route),
};
}));
}));
console.log('ended, got users:', users.length);
console.log('ended, got routes:', routes.length);
const deletedUsers = await User.deleteMany({
// version: 1
});
const deletedRoutes = await Route.deleteMany({
// version: 1
});
console.log("dropped users", deletedUsers);
console.log("dropped routes", deletedRoutes);
console.log('inserting users');
const addedUsers = (await Promise.all(users.map(user => User.create(user))))
.reduce((obj, user) => ({ ...obj, [user._id]: user }), {});
console.log('inserting routes');
const addedRoutes = await (await Promise.all(routes.map(route => Route.create({
...route,
owner: addedUsers[route.owner._id],
}))));
await Promise.all(addedRoutes.map(async (route) => {
await addedUsers[route.owner._id].routes.push(route);
}));
await Promise.all(addedRoutes.map(route => new Promise(resolve => (
addedUsers[route.owner._id].save(() => resolve())
))));
console.log('ok');
};
run();

View file

@ -0,0 +1,44 @@
module.exports.REPLACEMENT = {
0: { set: 'base', sticker: 'men' },
1: { set: 'base', sticker: 'square' },
2: { set: 'base', sticker: 'bridge' },
3: { set: 'base', sticker: 'ikea' },
4: { set: 'base', sticker: 'bugr' },
5: { set: 'base', sticker: 'monum' },
6: { set: 'base', sticker: 'opera' },
7: { set: 'base', sticker: 'forest' },
8: { set: 'base', sticker: 'empty' },
9: { set: 'base', sticker: 'empty' },
10: { set: 'base', sticker: 'road' },
11: { set: 'base', sticker: 'chicken' },
12: { set: 'base', sticker: 'camp' },
13: { set: 'base', sticker: 'fastfood' },
14: { set: 'base', sticker: 'beer' },
15: { set: 'base', sticker: 'pancake' },
16: { set: 'base', sticker: 'rocks' },
17: { set: 'real', sticker: 'swamp' },
18: { set: 'real', sticker: 'skull' },
19: { set: 'base', sticker: 'crap' },
20: { set: 'pin', sticker: 'start' },
21: { set: 'pin', sticker: 'p1' },
22: { set: 'pin', sticker: 'p2' },
23: { set: 'pin', sticker: 'p3' },
24: { set: 'pin', sticker: 'p4' },
25: { set: 'pin', sticker: 'p5' },
26: { set: 'pin', sticker: 'p6' },
27: { set: 'pin', sticker: 'finish' },
29: { set: 'pin', sticker: 'danger' },
30: { set: 'pin', sticker: 'question' },
};
module.exports.MAPS = {
'watercolor': 'BLANK',
'darq': 'BLANK',
'default': 'DGIS',
'osm': 'DEFAULT',
'hot': 'HOT',
'blank': 'BLANK',
'sat': 'DEFAULT',
'ymap': 'DEFAULT',
'ysat': 'DEFAULT',
};