mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-25 02:56:41 +07:00
import: working solution
This commit is contained in:
parent
aa581b1a77
commit
fc5b6009cb
8 changed files with 257 additions and 13 deletions
|
@ -11,11 +11,12 @@ const RouteSchema = new Schema(
|
||||||
route: { type: Array, default: [] },
|
route: { type: Array, default: [] },
|
||||||
stickers: { type: Array, default: [] },
|
stickers: { type: Array, default: [] },
|
||||||
owner: { type: Schema.Types.ObjectId, ref: 'User' },
|
owner: { type: Schema.Types.ObjectId, ref: 'User' },
|
||||||
logo: { type: String, default: 'DEFAULT' },
|
|
||||||
distance: { type: Number, default: 0 },
|
distance: { type: Number, default: 0 },
|
||||||
public: { type: Boolean, default: true },
|
public: { type: Boolean, default: true },
|
||||||
created_at: { type: Date, default: Date.now() },
|
created_at: { type: Date, default: Date.now() },
|
||||||
updated_at: { type: Date, default: Date.now() },
|
updated_at: { type: Date, default: Date.now() },
|
||||||
|
logo: { type: String, default: 'DEFAULT' },
|
||||||
|
map_style: { type: String, default: 'DEFAULT' },
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
|
|
||||||
const { Schema } = mongoose;
|
const { Schema } = mongoose;
|
||||||
|
|
||||||
// Schemas
|
// Schemas
|
||||||
|
@ -17,6 +16,7 @@ const UserSchema = new Schema(
|
||||||
first_name: { type: String },
|
first_name: { type: String },
|
||||||
last_name: { type: String },
|
last_name: { type: String },
|
||||||
photo: { type: String },
|
photo: { type: String },
|
||||||
|
version: { type: Number, default: 2 },
|
||||||
routes: [{ type: Schema.Types.ObjectId, ref: 'Route' }]
|
routes: [{ type: Schema.Types.ObjectId, ref: 'Route' }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
181
backend/tools/import.js
Executable file
181
backend/tools/import.js
Executable 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();
|
||||||
|
|
44
backend/tools/stickersReplacement.js
Normal file
44
backend/tools/stickersReplacement.js
Normal 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',
|
||||||
|
};
|
32
package-lock.json
generated
32
package-lock.json
generated
|
@ -2764,6 +2764,11 @@
|
||||||
"integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==",
|
"integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"bignumber.js": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA=="
|
||||||
|
},
|
||||||
"binary-extensions": {
|
"binary-extensions": {
|
||||||
"version": "1.11.0",
|
"version": "1.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
|
||||||
|
@ -7658,8 +7663,7 @@
|
||||||
"isarray": {
|
"isarray": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
|
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"isbinaryfile": {
|
"isbinaryfile": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
|
@ -9308,6 +9312,17 @@
|
||||||
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
|
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"mysql": {
|
||||||
|
"version": "2.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mysql/-/mysql-2.16.0.tgz",
|
||||||
|
"integrity": "sha512-dPbN2LHonQp7D5ja5DJXNbCLe/HRdu+f3v61aguzNRQIrmZLOeRoymBYyeThrR6ug+FqzDL95Gc9maqZUJS+Gw==",
|
||||||
|
"requires": {
|
||||||
|
"bignumber.js": "4.1.0",
|
||||||
|
"readable-stream": "2.3.6",
|
||||||
|
"safe-buffer": "5.1.2",
|
||||||
|
"sqlstring": "2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nan": {
|
"nan": {
|
||||||
"version": "2.10.0",
|
"version": "2.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
|
||||||
|
@ -10725,8 +10740,7 @@
|
||||||
"process-nextick-args": {
|
"process-nextick-args": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
|
||||||
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
|
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"progress": {
|
"progress": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
|
@ -11257,7 +11271,6 @@
|
||||||
"version": "2.3.6",
|
"version": "2.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"core-util-is": "~1.0.0",
|
"core-util-is": "~1.0.0",
|
||||||
"inherits": "~2.0.3",
|
"inherits": "~2.0.3",
|
||||||
|
@ -12407,6 +12420,11 @@
|
||||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"sqlstring": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
|
||||||
|
"integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A="
|
||||||
|
},
|
||||||
"sshpk": {
|
"sshpk": {
|
||||||
"version": "1.14.2",
|
"version": "1.14.2",
|
||||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
|
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
|
||||||
|
@ -12541,7 +12559,6 @@
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
|
@ -13259,8 +13276,7 @@
|
||||||
"util-deprecate": {
|
"util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"util.promisify": {
|
"util.promisify": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
|
|
@ -71,6 +71,7 @@
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.10",
|
||||||
"mongoose": "^5.3.14",
|
"mongoose": "^5.3.14",
|
||||||
"morgan": "~1.9.0",
|
"morgan": "~1.9.0",
|
||||||
|
"mysql": "^2.16.0",
|
||||||
"pt-sans-cyrillic": "0.0.4",
|
"pt-sans-cyrillic": "0.0.4",
|
||||||
"pug": "2.0.0-beta11",
|
"pug": "2.0.0-beta11",
|
||||||
"raleway-cyrillic": "^4.0.2",
|
"raleway-cyrillic": "^4.0.2",
|
||||||
|
|
|
@ -5,8 +5,8 @@ export const LOGOS = {
|
||||||
jolly: ['Пин-Микс + JW', 'http://map.vault48.org/misc/jw.png', 'top-right'],
|
jolly: ['Пин-Микс + JW', 'http://map.vault48.org/misc/jw.png', 'top-right'],
|
||||||
pedals: ['Усталые Педальки', 'http://map.vault48.org/misc/pedals.png', 'bottom-right'],
|
pedals: ['Усталые Педальки', 'http://map.vault48.org/misc/pedals.png', 'bottom-right'],
|
||||||
rider: ['Райдер', 'http://map.vault48.org/misc/rider.png', 'bottom-right'],
|
rider: ['Райдер', 'http://map.vault48.org/misc/rider.png', 'bottom-right'],
|
||||||
// rider_evening: ['Вечерние городские', '/misc/rider_evening.png', 'top-right'],
|
rider_evening: ['Вечерние городские', '/misc/rider_evening.png', 'top-right'],
|
||||||
// fas: ['Алкоспорт', '/misc/fas.png', 'bottom-right'],
|
fas: ['Алкоспорт', '/misc/fas.png', 'bottom-right'],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DEFAULT_LOGO = 'nvs';
|
export const DEFAULT_LOGO = 'nvs';
|
||||||
|
|
|
@ -17,13 +17,14 @@ export const STICKERS = {
|
||||||
opera: { off: 11, title: 'Оперный', title_long: 'Оперный театр' },
|
opera: { off: 11, title: 'Оперный', title_long: 'Оперный театр' },
|
||||||
forest: { off: 1, title: 'Лес', title_long: 'Берёзовая роща' },
|
forest: { off: 1, title: 'Лес', title_long: 'Берёзовая роща' },
|
||||||
road: { off: 2, title: 'Трасса', title_long: 'Дорога' },
|
road: { off: 2, title: 'Трасса', title_long: 'Дорога' },
|
||||||
chicken1: { off: 3, title: 'Курочка', title_long: 'Курочка' },
|
chicken: { off: 3, title: 'Курочка', title_long: 'Курочка' },
|
||||||
camp: { off: 6, title: 'Палатка', title_long: 'Палаточный лагерь' },
|
camp: { off: 6, title: 'Палатка', title_long: 'Палаточный лагерь' },
|
||||||
rocks: { off: 14, title: 'Камни', title_long: 'Кааааммммуушшшки' },
|
rocks: { off: 14, title: 'Камни', title_long: 'Кааааммммуушшшки' },
|
||||||
crap: { off: 15, title: 'Щет', title_long: 'Полный щет' },
|
crap: { off: 15, title: 'Щет', title_long: 'Полный щет' },
|
||||||
pancake: { off: 13, title: 'Блинцы', title_long: 'Блинчики' },
|
pancake: { off: 13, title: 'Блинцы', title_long: 'Блинчики' },
|
||||||
fastfood: { off: 16, title: 'Фастфуд', title_long: 'Быстрая еда' },
|
fastfood: { off: 16, title: 'Фастфуд', title_long: 'Быстрая еда' },
|
||||||
beer: { off: 12, title: 'Пивко', title_long: 'Пивко' },
|
beer: { off: 12, title: 'Пивко', title_long: 'Пивко' },
|
||||||
|
empty: { off: 20, title: 'Пусто', title_long: 'Пусто' },
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
real: {
|
real: {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue