progress
This commit is contained in:
parent
34ed6355c9
commit
e5d9ced955
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,3 +4,5 @@ node_modules
|
|||||||
.env
|
.env
|
||||||
.env.local
|
.env.local
|
||||||
.env.*.local
|
.env.*.local
|
||||||
|
testData/
|
||||||
|
.notes
|
||||||
|
50
app/controllers/adminController.js
Normal file
50
app/controllers/adminController.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
const moment = require('moment');
|
||||||
|
const { insertSessions, insertSessionTracks } = require("../db/mongo/mongoSessions");
|
||||||
|
const { getHistoricalSessions, getIvaoSessionTracks } = require("../requests/ivao/session");
|
||||||
|
|
||||||
|
async function initSessionsData(opts) {
|
||||||
|
const { callsign, userId, from, clear = false } = opts;
|
||||||
|
let to = opts.to;
|
||||||
|
if (!to) {
|
||||||
|
to = moment().utc().subtract(1, 'day').endOf('day').format();
|
||||||
|
}
|
||||||
|
const data = await getHistoricalSessions({
|
||||||
|
callsign,
|
||||||
|
userId,
|
||||||
|
from,
|
||||||
|
to
|
||||||
|
});
|
||||||
|
await insertSessions(data, clear);
|
||||||
|
|
||||||
|
console.log(`${data.length} sessions inserted.`);
|
||||||
|
await initSessionsTracks(data.map(d => d.id), clear);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function initSessionsTracks(sessions, clear) {
|
||||||
|
const array = [];
|
||||||
|
const batchSize = 50;
|
||||||
|
|
||||||
|
for (let index = 0; index < sessions.length; index++) {
|
||||||
|
const sessionId = sessions[index];
|
||||||
|
const tracks = await getIvaoSessionTracks(sessionId);
|
||||||
|
array.push({
|
||||||
|
sessionId,
|
||||||
|
tracks,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (index < sessions.length - 1 && (index + 1) % batchSize === 0) {
|
||||||
|
await pause(5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await insertSessionTracks(array, clear);
|
||||||
|
|
||||||
|
console.log(`${array.length} tracks inserted.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function pause(millis) {
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, millis));
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
initSessionsData,
|
||||||
|
}
|
@ -1,8 +1,9 @@
|
|||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
const { getUserFromReferenceTable } = require('../db/mongo/mongoPilots');
|
const { getUserFromReferenceTable } = require('../db/mongo/mongoPilots');
|
||||||
const { getSessions } = require('../db/mongo/mongoSessions');
|
const { getSessions, getSessionTracks, updateSessionTracks, insertOneSessionTracks } = require('../db/mongo/mongoSessions');
|
||||||
const { RedisClient } = require('../db/redis/redis');
|
const { RedisClient } = require('../db/redis/redis');
|
||||||
const { getHistoricalSessions } = require('../requests/ivao/session');
|
const { getHistoricalSessions, getIvaoSessionTracks, getIvaoPilotsNow, getIvaoLatestSessionFlightPlan, getIvaoSessionLatestTrack } = require('../requests/ivao/session');
|
||||||
|
const { getAirTime } = require('./trackerAnalizer');
|
||||||
|
|
||||||
async function getTodaySessionsFromIvao(callsign, incompletes) {
|
async function getTodaySessionsFromIvao(callsign, incompletes) {
|
||||||
const from = moment().utc().startOf('day').format();
|
const from = moment().utc().startOf('day').format();
|
||||||
@ -50,43 +51,64 @@ async function getWhitelist() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getSessionCalculatedTime(sessionId) {
|
||||||
|
let tracks = await getSessionTracks(sessionId);
|
||||||
|
if (tracks && !Number.isInteger(tracks.calculatedTime)) {
|
||||||
|
tracks.calculatedTime = getAirTime(tracks);
|
||||||
|
await updateSessionTracks(tracks);
|
||||||
|
} else if (!tracks) {
|
||||||
|
const t = await getIvaoSessionTracks(sessionId);
|
||||||
|
tracks = {
|
||||||
|
sessionId,
|
||||||
|
tracks: t,
|
||||||
|
calculatedTime: getAirTime(t)
|
||||||
|
};
|
||||||
|
await insertOneSessionTracks(tracks);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tracks.calculatedTime;
|
||||||
|
}
|
||||||
|
|
||||||
async function getList(callsign) {
|
async function getList(callsign) {
|
||||||
const from = moment().utc().startOf('month');
|
const from = moment().startOf('month').format('YYYY-MM-DD');
|
||||||
const to = moment().subtract(1, 'day').utc().endOf('day');
|
const to = moment().subtract(1, 'day').endOf('day').format('YYYY-MM-DD');
|
||||||
const todayData = await getTodaySessionsFromIvao(callsign);
|
const todayData = await getTodaySessionsFromIvao(callsign);
|
||||||
const monthData = await getSessions(from, to);
|
const monthData = await getSessions(from, to);
|
||||||
const allData = [...todayData, ...monthData];
|
const allData = [...todayData, ...monthData];
|
||||||
const redisUsers = await RedisClient.getPair('users');
|
const redisUsers = await RedisClient.getPair('users');
|
||||||
|
|
||||||
const totalsByUserId = allData.reduce((acc, d) => {
|
const totalsByUserId = {};
|
||||||
const userId = d.userId;
|
|
||||||
const flightPlan = d.flightPlans[d.flightPlans.length - 1];
|
|
||||||
const date = moment(d.completedAt);
|
|
||||||
// console.log(date);
|
|
||||||
|
|
||||||
if (!acc[userId]) {
|
for (let index = 0; index < allData.length; index++) {
|
||||||
acc[userId] = {
|
const session = allData[index];
|
||||||
|
const userId = session.userId;
|
||||||
|
const flightPlan = session.flightPlans[session.flightPlans.length - 1];
|
||||||
|
const date = moment(session.completedAt);
|
||||||
|
const calculated = await getSessionCalculatedTime(session.id);
|
||||||
|
if (!totalsByUserId[userId]) {
|
||||||
|
totalsByUserId[userId] = {
|
||||||
time: 0,
|
time: 0,
|
||||||
flights: 0
|
flights: 0,
|
||||||
|
sessionsTime: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
acc[userId].time += d.time;
|
totalsByUserId[userId].time += calculated;
|
||||||
acc[userId].flights++;
|
totalsByUserId[userId].sessionsTime += session.time || 0;
|
||||||
|
totalsByUserId[userId].flights++;
|
||||||
|
|
||||||
if (!acc[userId].lastFlight || date.isAfter(acc[userId].lastFlightDate)) {
|
if (!totalsByUserId[userId].lastFlight || date.isAfter(totalsByUserId[userId].lastFlightDate)) {
|
||||||
acc[userId].lastFlight = {...flightPlan };
|
totalsByUserId[userId].lastFlight = {...flightPlan };
|
||||||
acc[userId].lastFlightDate = date;
|
totalsByUserId[userId].lastFlightDate = date;
|
||||||
acc[userId].lastCallsign = d.callsign;
|
totalsByUserId[userId].lastCallsign = session.callsign;
|
||||||
|
|
||||||
delete acc[userId].lastFlight.id;
|
delete totalsByUserId[userId].lastFlight.id;
|
||||||
if (d.user.firstName) {
|
if (session.user.firstName) {
|
||||||
acc[userId].name = `${d.user.firstName} ${d.user.lastName || ''}`;
|
totalsByUserId[userId].name = `${session.user.firstName} ${session.user.lastName || ''}`;
|
||||||
}
|
}
|
||||||
acc[userId].division = d.user.divisionId;
|
totalsByUserId[userId].division = session.user.divisionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
}
|
||||||
}, {});
|
|
||||||
|
|
||||||
const array = [];
|
const array = [];
|
||||||
for (const key in totalsByUserId) {
|
for (const key in totalsByUserId) {
|
||||||
@ -96,11 +118,40 @@ async function getList(callsign) {
|
|||||||
array.push(user);
|
array.push(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return array.filter(d => d.time > 0);
|
||||||
|
}
|
||||||
|
|
||||||
return array;
|
async function getLatestSessions() {
|
||||||
|
return await getIvaoPilotsNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getLatestsFlightPlans() {
|
||||||
|
const sessionsNow = await getLatestSessions();
|
||||||
|
const response = [];
|
||||||
|
for (let index = 0; index < sessionsNow.length; index++) {
|
||||||
|
const session = sessionsNow[index];
|
||||||
|
const sessionFlightplan = await getIvaoLatestSessionFlightPlan(session.id);
|
||||||
|
const track = await getIvaoSessionLatestTrack(session.id);
|
||||||
|
const fplan = {};
|
||||||
|
fplan.sessionId = session.id;
|
||||||
|
fplan.callsign = session.callsign;
|
||||||
|
fplan.arrival = sessionFlightplan.arrival;
|
||||||
|
fplan.departure = sessionFlightplan.departure;
|
||||||
|
fplan.departureTime = sessionFlightplan.departureTime;
|
||||||
|
fplan.eet = sessionFlightplan.eet;
|
||||||
|
fplan.eta = track.groundSpeed === 0 ? 0 : Math.round((track.arrivalDistance / track.groundSpeed) * 3600);
|
||||||
|
fplan.arrivalDistance = track.arrivalDistance;
|
||||||
|
fplan.groundSpeed = track.groundSpeed;
|
||||||
|
|
||||||
|
response.push(fplan);
|
||||||
|
|
||||||
|
}
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getList,
|
getList,
|
||||||
getWhitelist,
|
getWhitelist,
|
||||||
|
getLatestSessions,
|
||||||
|
getLatestsFlightPlans,
|
||||||
};
|
};
|
184
app/controllers/trackerAnalizer.js
Normal file
184
app/controllers/trackerAnalizer.js
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
//50135458, 50949601
|
||||||
|
|
||||||
|
function getAirTime(tracks) {
|
||||||
|
let accumTime = 0;
|
||||||
|
if (tracks && tracks.length > 0) {
|
||||||
|
let prev = tracks[0];
|
||||||
|
let initialTime;
|
||||||
|
let track;
|
||||||
|
|
||||||
|
if (tracks.length === 1) {
|
||||||
|
return (prev.onGround === false) ? prev.time : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev.onGround === false) {
|
||||||
|
initialTime = 0;
|
||||||
|
// console.log('initialTime', initialTime, prev.time);
|
||||||
|
}
|
||||||
|
for (let index = 1; index < tracks.length; index++) {
|
||||||
|
track = tracks[index];
|
||||||
|
if (prev.onGround !== track.onGround) {
|
||||||
|
if (isInitialTimeSet(initialTime)) {
|
||||||
|
accumTime += Math.round((prev.time + track.time) / 2) - initialTime;
|
||||||
|
|
||||||
|
// console.log('accumTime', accumTime, prev.time, track.time);
|
||||||
|
initialTime = undefined;
|
||||||
|
} else {
|
||||||
|
initialTime = Math.round((prev.time + track.time) / 2);
|
||||||
|
// console.log('initialTime', initialTime, prev.time, track.time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev = track;
|
||||||
|
}
|
||||||
|
if (!track.onGround && isInitialTimeSet(initialTime)) {
|
||||||
|
accumTime += track.time - initialTime;
|
||||||
|
// console.log('accumTime', accumTime, track.time);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return accumTime;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function isInitialTimeSet(num) {
|
||||||
|
return Number.isInteger(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateTime(tracks) {
|
||||||
|
// const states = getShortStates(tracks);
|
||||||
|
// const depTime = getDepartingTime(states);
|
||||||
|
// const arrTime = getOnBlocksTime(states);
|
||||||
|
// console.log((arrTime - depTime));
|
||||||
|
// const time = ((arrTime - depTime));
|
||||||
|
// console.log('time :>> ', `${Math.trunc(time / 60 / 60)}h ${Math.round((time % 1) * 60)}m`, );
|
||||||
|
// return time;
|
||||||
|
return getAirTime(tracks);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getShortStates(tracks) {
|
||||||
|
let short = [];
|
||||||
|
if (tracks && tracks.length > 0) {
|
||||||
|
let track;
|
||||||
|
let prev = tracks[0];
|
||||||
|
short.push(getTrace(prev));
|
||||||
|
let index = 1;
|
||||||
|
for (; index < tracks.length - 1; index++) {
|
||||||
|
track = tracks[index];
|
||||||
|
if (prev.onGround !== track.onGround || prev.state !== track.state) {
|
||||||
|
short.push(getTrace(track))
|
||||||
|
}
|
||||||
|
prev = track;
|
||||||
|
}
|
||||||
|
|
||||||
|
short.push(getTrace(tracks[index]))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return short;
|
||||||
|
|
||||||
|
// if (!tracks || tracks.length === 0) {
|
||||||
|
// return [];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// while (tracks[0] && tracks[0].state === 'En Route') {
|
||||||
|
// tracks.shift();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (tracks.length === 0) {
|
||||||
|
// return [];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let lastState = '';
|
||||||
|
// let lastOnGround;
|
||||||
|
// let short = [];
|
||||||
|
// let states = [];
|
||||||
|
// let lastPushed = -1;
|
||||||
|
// let index = 0;
|
||||||
|
// let prevTrack;
|
||||||
|
|
||||||
|
// for (; index < tracks.length; index++) {
|
||||||
|
// const track = tracks[index];
|
||||||
|
// if (index > 0) {
|
||||||
|
// prevTrack = tracks[index - 1];
|
||||||
|
// }
|
||||||
|
// if (track.state !== lastState || track.onGround !== lastOnGround) {
|
||||||
|
// console.log(index, lastPushed);
|
||||||
|
// if (index > 0 && index > lastPushed - 1) {
|
||||||
|
// states.push(getTrace(prevTrack));
|
||||||
|
// }
|
||||||
|
// short.push(track);
|
||||||
|
// states.push(getTrace(track));
|
||||||
|
// lastPushed = index;
|
||||||
|
// lastState = track.state;
|
||||||
|
// lastOnGround = track.onGround;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (index > 0 && index > lastPushed) {
|
||||||
|
// states.push(getTrace(tracks[index - 1]));
|
||||||
|
// }
|
||||||
|
// return states;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTrace(track) {
|
||||||
|
const {
|
||||||
|
state,
|
||||||
|
time,
|
||||||
|
onGround,
|
||||||
|
groundSpeed,
|
||||||
|
altitude,
|
||||||
|
arrivalDistance,
|
||||||
|
departureDistance,
|
||||||
|
latitude,
|
||||||
|
longitude,
|
||||||
|
pitch,
|
||||||
|
} = track;
|
||||||
|
return {
|
||||||
|
state,
|
||||||
|
time,
|
||||||
|
onGround,
|
||||||
|
groundSpeed,
|
||||||
|
altitude,
|
||||||
|
arrivalDistance,
|
||||||
|
departureDistance,
|
||||||
|
latitude,
|
||||||
|
longitude,
|
||||||
|
pitch,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDepartingTime(states) {
|
||||||
|
const prevState = 'Boarding';
|
||||||
|
const nextState = 'Departing';
|
||||||
|
|
||||||
|
for (let index = 1; index < states.length; index++) {
|
||||||
|
const prev = states[index - 1];
|
||||||
|
const state = states[index];
|
||||||
|
if (prev.state === prevState && state.state === nextState) {
|
||||||
|
return Math.round((state.time + prev.time) / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOnBlocksTime(states) {
|
||||||
|
const STATE = 'On Blocks';
|
||||||
|
const PREV_STATE = 'Landed';
|
||||||
|
let time = -1;
|
||||||
|
|
||||||
|
for (let index = 1; index < states.length; index++) {
|
||||||
|
const state = states[index];
|
||||||
|
const prev = states[index - 1];
|
||||||
|
if (prev.state === PREV_STATE && state.state === STATE) {
|
||||||
|
time = Math.round((state.time + prev.time) / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
calculateTime,
|
||||||
|
getShortStates,
|
||||||
|
getDepartingTime,
|
||||||
|
getOnBlocksTime,
|
||||||
|
getAirTime,
|
||||||
|
};
|
@ -9,13 +9,34 @@ const {
|
|||||||
|
|
||||||
const uri = `mongodb://${MONGO_USER}:${MONGO_PASS}@${MONGO_HOST}:${MONGO_PORT}/?maxPoolSize=20`;
|
const uri = `mongodb://${MONGO_USER}:${MONGO_PASS}@${MONGO_HOST}:${MONGO_PORT}/?maxPoolSize=20`;
|
||||||
|
|
||||||
module.exports = {
|
const getMongoConnection = async() => {
|
||||||
getMongoConnection: async() => {
|
const client = new MongoClient(uri);
|
||||||
const client = new MongoClient(uri);
|
return await client.connect();
|
||||||
return await client.connect();
|
};
|
||||||
},
|
|
||||||
getMongoDatabase: (client, db) => {
|
const getMongoDatabase = (client, db) => {
|
||||||
const DB = db || MONGO_DB || 'lsa_leaderboard';
|
const DB = db || MONGO_DB;
|
||||||
return client.db(DB);
|
return client.db(DB);
|
||||||
|
};
|
||||||
|
|
||||||
|
const mongoExecute = async(fn, dbName = MONGO_DB) => {
|
||||||
|
let conn;
|
||||||
|
try {
|
||||||
|
conn = await getMongoConnection();
|
||||||
|
const db = conn.db(dbName);
|
||||||
|
const result = await fn(db, conn);
|
||||||
|
return result;
|
||||||
|
} catch (err) {
|
||||||
|
console.log('MOMGODB ERROR:', err.message);
|
||||||
|
} finally {
|
||||||
|
if (conn) {
|
||||||
|
await conn.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mongoExecute,
|
||||||
|
getMongoConnection,
|
||||||
|
getMongoDatabase,
|
||||||
};
|
};
|
@ -1,15 +1,7 @@
|
|||||||
const moment = require("moment/moment");
|
const { mongoExecute } = require("./mongoDBPool");
|
||||||
const { getMongoConnection } = require("./mongoDBPool");
|
|
||||||
const {
|
|
||||||
MONGO_DB,
|
|
||||||
} = process.env;
|
|
||||||
|
|
||||||
const DB = MONGO_DB || 'lts';
|
|
||||||
|
|
||||||
async function insertSessions(sessions, clear) {
|
async function insertSessions(sessions, clear) {
|
||||||
const conn = await getMongoConnection();
|
return mongoExecute(async(db) => {
|
||||||
try {
|
|
||||||
const db = conn.db(DB);
|
|
||||||
const sessionsCollection = db.collection('sessions');
|
const sessionsCollection = db.collection('sessions');
|
||||||
|
|
||||||
if (clear) {
|
if (clear) {
|
||||||
@ -18,21 +10,36 @@ async function insertSessions(sessions, clear) {
|
|||||||
|
|
||||||
await sessionsCollection.insertMany(sessions);
|
await sessionsCollection.insertMany(sessions);
|
||||||
|
|
||||||
} catch (err) {
|
});
|
||||||
console.error(err);
|
}
|
||||||
} finally {
|
|
||||||
await conn.close();
|
|
||||||
}
|
|
||||||
|
async function insertOneSessionTracks(sessionTracks) {
|
||||||
|
return mongoExecute(async(db) => {
|
||||||
|
const sessionsCollection = db.collection('sessionTracks');
|
||||||
|
|
||||||
|
await sessionsCollection.insertOne(sessionTracks);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function insertSessionTracks(sessionTracks, clear) {
|
||||||
|
return mongoExecute(async(db) => {
|
||||||
|
const sessionsCollection = db.collection('sessionTracks');
|
||||||
|
|
||||||
|
if (clear) {
|
||||||
|
sessionsCollection.deleteMany({});
|
||||||
|
}
|
||||||
|
|
||||||
|
await sessionsCollection.insertMany(sessionTracks);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getSessions(start, end) {
|
async function getSessions(start, end) {
|
||||||
const conn = await getMongoConnection();
|
return mongoExecute(async(db) => {
|
||||||
try {
|
|
||||||
const db = conn.db(DB);
|
|
||||||
const sessionsCollection = db.collection('sessions');
|
const sessionsCollection = db.collection('sessions');
|
||||||
|
const startDate = start + 'T00:00:00.000Z';
|
||||||
const startDate = moment(start).utc().startOf('day').toDate();
|
const endDate = end + 'T23:59:59.999Z';
|
||||||
const endDate = moment(end).utc().endOf('day').toDate();
|
|
||||||
const result = await sessionsCollection.aggregate([{
|
const result = await sessionsCollection.aggregate([{
|
||||||
$addFields: {
|
$addFields: {
|
||||||
completedDate: {
|
completedDate: {
|
||||||
@ -54,22 +61,39 @@ async function getSessions(start, end) {
|
|||||||
}, {
|
}, {
|
||||||
$match: {
|
$match: {
|
||||||
createdDate: {
|
createdDate: {
|
||||||
$gt: startDate,
|
$gt: new Date(startDate),
|
||||||
$lte: endDate
|
$lte: new Date(endDate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}]).toArray();
|
}]).toArray();
|
||||||
return result;
|
return result;
|
||||||
} catch (err) {
|
});
|
||||||
console.error(err);
|
}
|
||||||
} finally {
|
|
||||||
await conn.close();
|
async function getSessionTracks(sessionId) {
|
||||||
}
|
return mongoExecute(
|
||||||
|
async(db) => {
|
||||||
|
const tracksCollection = db.collection('sessionTracks');
|
||||||
|
const tracks = await tracksCollection.findOne({ sessionId });
|
||||||
|
return tracks;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateSessionTracks(tracks) {
|
||||||
|
return mongoExecute(async(db) => {
|
||||||
|
const tracksCollection = db.collection('sessionTracks');
|
||||||
|
await tracksCollection.updateOne({ _id: tracks._id }, { $set: { calculatedTime: tracks.calculatedTime } });
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
insertSessions,
|
insertSessions,
|
||||||
|
insertSessionTracks,
|
||||||
|
insertOneSessionTracks,
|
||||||
getSessions,
|
getSessions,
|
||||||
|
getSessionTracks,
|
||||||
|
updateSessionTracks,
|
||||||
};
|
};
|
||||||
|
|
||||||
//http://localhost:3001/api/v1/ivao/init-sessions?callsign=LTS&from=2023-01-05T00:00:00&to=2023-01-05T23:59:59
|
//http://localhost:3001/api/v1/ivao/init-sessions?callsign=LTS&from=2023-01-05T00:00:00&to=2023-01-05T23:59:59
|
@ -27,7 +27,7 @@ async function getMysqlPool() {
|
|||||||
}
|
}
|
||||||
return pool;
|
return pool;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log('error', err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ const query = async(sql) => {
|
|||||||
const pool = await getMysqlPool();
|
const pool = await getMysqlPool();
|
||||||
return pool.query(sql);
|
return pool.query(sql);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log('error', err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
const { RedisClient } = require('../../db/redis/redis');
|
||||||
const { request } = require('../request');
|
const { request } = require('../request');
|
||||||
|
|
||||||
const getHistoricalSessions = async({ callsign, userId, from, to }) => {
|
const getHistoricalSessions = async({ callsign, userId, from, to }) => {
|
||||||
@ -41,6 +42,58 @@ async function _requestHistoricalRecursive(data, url, options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getIvaoSessionTracks(idSession) {
|
||||||
|
const url = `https://api.ivao.aero/v2/tracker/sessions/${idSession}/tracks`;
|
||||||
|
const options = {
|
||||||
|
headers: {
|
||||||
|
apiKey: process.env.IVAO_APIKEY,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const tracks = await request(url, options);
|
||||||
|
return tracks;
|
||||||
|
}
|
||||||
|
async function getIvaoSessionLatestTrack(idSession) {
|
||||||
|
const url = `https://api.ivao.aero/v2/tracker/sessions/${idSession}/tracks/latest`;
|
||||||
|
const options = {
|
||||||
|
headers: {
|
||||||
|
apiKey: process.env.IVAO_APIKEY,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const tracks = await request(url, options);
|
||||||
|
return tracks;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function getIvaoPilotsNow(all = false) {
|
||||||
|
const url = `https://api.ivao.aero/v2/tracker/now/pilots`;
|
||||||
|
const options = {
|
||||||
|
headers: {
|
||||||
|
apiKey: process.env.IVAO_APIKEY,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const redisUsers = await RedisClient.getPair('users');
|
||||||
|
const pilots = await request(url, options);
|
||||||
|
// console.log('redisUsers :>> ', redisUsers);
|
||||||
|
|
||||||
|
return all ? pilots : pilots.filter(d => d.callsign.startsWith('LTS'));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getIvaoLatestSessionFlightPlan(sessionId) {
|
||||||
|
const url = `https://api.ivao.aero/v2/tracker/sessions/${sessionId}/flightPlans/latest`;
|
||||||
|
const options = {
|
||||||
|
headers: {
|
||||||
|
apiKey: process.env.IVAO_APIKEY,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const fp = await request(url, options);
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getHistoricalSessions,
|
getHistoricalSessions,
|
||||||
|
getIvaoSessionTracks,
|
||||||
|
getIvaoPilotsNow,
|
||||||
|
getIvaoLatestSessionFlightPlan,
|
||||||
|
getIvaoSessionLatestTrack,
|
||||||
}
|
}
|
16
app/routes/admin.js
Normal file
16
app/routes/admin.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const { initSessionsData } = require('../controllers/adminController');
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
router.get('/init-sessions', async(req, res) => {
|
||||||
|
try {
|
||||||
|
await initSessionsData(req.query);
|
||||||
|
res.status(200);
|
||||||
|
} catch (err) {
|
||||||
|
console.log('error', err.response);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
@ -1,7 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { getList, getWhitelist } = require('../controllers/sessionsController');
|
const { getList, getWhitelist, getLatestsFlightPlans, getLatestSessions } = require('../controllers/sessionsController');
|
||||||
const { insertSessions, getSessions } = require('../db/mongo/mongoSessions');
|
const { getSessions } = require('../db/mongo/mongoSessions');
|
||||||
const { getHistoricalSessions } = require('../requests/ivao/session');
|
const { getIvaoPilotsNow } = require('../requests/ivao/session');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
const { getIvaoWazzup } = require('../requests/ivao/wazzup');
|
const { getIvaoWazzup } = require('../requests/ivao/wazzup');
|
||||||
@ -24,6 +24,34 @@ router.get('/sessions', async(req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.get('/sessions/now', async(req, res) => {
|
||||||
|
try {
|
||||||
|
const data = await getIvaoPilotsNow();
|
||||||
|
res.status(200).json(data);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/sessions/all/now', async(req, res) => {
|
||||||
|
try {
|
||||||
|
const data = await getLatestSessions();
|
||||||
|
res.status(200).json(data);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/flightplans/latest', async(req, res) => {
|
||||||
|
console.log('object :>> ', '/flightplans/latest');
|
||||||
|
try {
|
||||||
|
const data = await getLatestsFlightPlans();
|
||||||
|
res.status(200).json(data);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
router.get('/list/today', async(req, res) => {
|
router.get('/list/today', async(req, res) => {
|
||||||
try {
|
try {
|
||||||
const data = await getList('LTS');
|
const data = await getList('LTS');
|
||||||
@ -40,17 +68,6 @@ router.get('/whitelist', async(req, res) => {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
router.get('/init-sessions', async(req, res) => {
|
|
||||||
try {
|
|
||||||
const data = await getHistoricalSessions(req.query);
|
|
||||||
await insertSessions(data);
|
|
||||||
console.log(`${data.length} sessions inserted.`);
|
|
||||||
res.status(200);
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
36
app/routes/lts.js
Normal file
36
app/routes/lts.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
const { getList, getWhitelist } = require('../controllers/sessionsController');
|
||||||
|
const { getSessions } = require('../db/mongo/mongoSessions');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
router.get('/sessions', async(req, res) => {
|
||||||
|
try {
|
||||||
|
const data = await getSessions(req.query);
|
||||||
|
res.status(200).json(data);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/list/today', async(req, res) => {
|
||||||
|
try {
|
||||||
|
const data = await getList('LTS');
|
||||||
|
res.status(200).json(data);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.get('/whitelist', async(req, res) => {
|
||||||
|
try {
|
||||||
|
const data = await getWhitelist();
|
||||||
|
res.status(200).json(data);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = router;
|
@ -3,20 +3,53 @@ const moment = require('moment');
|
|||||||
|
|
||||||
const { getUsersWhitelist, getUsers } = require('../db/mysql/lsaUsers');
|
const { getUsersWhitelist, getUsers } = require('../db/mysql/lsaUsers');
|
||||||
const { RedisClient } = require('../db/redis/redis');
|
const { RedisClient } = require('../db/redis/redis');
|
||||||
|
const { getHistoricalSessions } = require('../requests/ivao/session');
|
||||||
|
const { insertSessions } = require('../db/mongo/mongoSessions');
|
||||||
|
|
||||||
async function task() {
|
const canRunTasks = process.env.EXECUTE_TASKS_ON_START !== 'false';
|
||||||
|
|
||||||
|
async function taskSyncLSAUsers() {
|
||||||
console.log('Running task', moment().format('HH:mm:ss'));
|
console.log('Running task', moment().format('HH:mm:ss'));
|
||||||
const users = await getUsers();
|
try {
|
||||||
const whitelist = await getUsersWhitelist();
|
const users = await getUsers();
|
||||||
RedisClient.setCollection([
|
const whitelist = await getUsersWhitelist();
|
||||||
['users', users],
|
RedisClient.setCollection([
|
||||||
['users_whitelist', whitelist],
|
['users', users],
|
||||||
]);
|
['users_whitelist', whitelist],
|
||||||
|
]);
|
||||||
|
} catch (err) {
|
||||||
|
console.log('ERR executing taskSyncLSAUsers');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function taskSyncPrevioudDaySessions(callsign) {
|
||||||
|
try {
|
||||||
|
const from = moment().utc().subtract(1, 'day').startOf('day').format();
|
||||||
|
const to = moment().utc().subtract(1, 'day').endOf('day').format();
|
||||||
|
console.log(moment().format('DD HH:mm:ss'), 'taskSyncPrevioudDaySessions', from, to);
|
||||||
|
const params = {
|
||||||
|
callsign,
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
};
|
||||||
|
const data = await getHistoricalSessions(params);
|
||||||
|
insertSessions(data);
|
||||||
|
} catch (err) {
|
||||||
|
console.log('ERR executing taskSyncPrevioudDaySessions');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function() {
|
module.exports = function() {
|
||||||
task();
|
if (canRunTasks) {
|
||||||
cron.schedule('*/15 * * * *', async() => {
|
cron.schedule(process.env.SYNC_TASK_SCHEDULE, () => {
|
||||||
task();
|
taskSyncPrevioudDaySessions('LTS');
|
||||||
});
|
});
|
||||||
|
cron.schedule(process.env.USERS_TASK_SCHEDULE, async() => {
|
||||||
|
taskSyncLSAUsers();
|
||||||
|
});
|
||||||
|
console.log('Tasks started.');
|
||||||
|
} else {
|
||||||
|
console.log('Tasks skipped.');
|
||||||
|
}
|
||||||
}
|
}
|
30
index.js
30
index.js
@ -5,12 +5,15 @@ require('./app/tasks/sync')();
|
|||||||
const express = require("express");
|
const express = require("express");
|
||||||
const bodyParser = require("body-parser");
|
const bodyParser = require("body-parser");
|
||||||
const cors = require("cors");
|
const cors = require("cors");
|
||||||
|
const helmet = require("helmet");
|
||||||
|
|
||||||
const ivaoRoutes = require('./app/routes/ivao');
|
const ivaoRoutes = require('./app/routes/ivao');
|
||||||
|
const ltsRoutes = require('./app/routes/lts');
|
||||||
|
const adminRoutes = require('./app/routes/admin');
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
const whitelist = process.env.HOSTS_WHITELIST ? process.env.HOSTS_WHITELIST.split(',') : [];
|
// const whitelist = process.env.HOSTS_WHITELIST ? process.env.HOSTS_WHITELIST.split(',') : [];
|
||||||
|
|
||||||
// parse application/json
|
// parse application/json
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
@ -18,21 +21,26 @@ app.use(bodyParser.json());
|
|||||||
// parse application/x-www-form-urlencoded
|
// parse application/x-www-form-urlencoded
|
||||||
app.use(bodyParser.urlencoded({ extended: true }));
|
app.use(bodyParser.urlencoded({ extended: true }));
|
||||||
|
|
||||||
var corsOptions = {
|
// var corsOptions = {
|
||||||
origin: function(origin, callback) {
|
// origin: function(origin, callback) {
|
||||||
if (whitelist.indexOf(origin) !== -1) {
|
// if (whitelist.indexOf(origin) !== -1) {
|
||||||
callback(null, true)
|
// callback(null, true)
|
||||||
} else {
|
// } else {
|
||||||
callback(new Error('Not allowed by CORS'))
|
// callback(new Error('Not allowed by CORS'))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
// use cors options
|
// use cors options
|
||||||
app.use(cors(corsOptions));
|
app.use(cors());
|
||||||
|
app.use(helmet.referrerPolicy({
|
||||||
|
policy: ["origin", "unsafe-url"],
|
||||||
|
}));
|
||||||
app.use(express.static('assets'));
|
app.use(express.static('assets'));
|
||||||
|
|
||||||
// routes
|
// routes
|
||||||
app.use('/api/v1/ivao', ivaoRoutes);
|
app.use('/api/v1/ivao', ivaoRoutes);
|
||||||
|
app.use('/api/v1', ltsRoutes);
|
||||||
|
app.use('/api/v1/admin', adminRoutes);
|
||||||
|
|
||||||
// listening port
|
// listening port
|
||||||
const PORT = process.env.PORT || 3000;
|
const PORT = process.env.PORT || 3000;
|
||||||
|
14
package-lock.json
generated
14
package-lock.json
generated
@ -14,6 +14,7 @@
|
|||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
"helmet": "^6.0.1",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"mongodb": "^4.13.0",
|
"mongodb": "^4.13.0",
|
||||||
"node": "^19.3.0",
|
"node": "^19.3.0",
|
||||||
@ -2397,6 +2398,14 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/helmet": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/helmet/-/helmet-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-8wo+VdQhTMVBMCITYZaGTbE4lvlthelPYSvoyNvk4RECTmrVjMerp9RfUOQXZWLvCcAn1pKj7ZRxK4lI9Alrcw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/http-errors": {
|
"node_modules/http-errors": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||||
@ -5577,6 +5586,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||||
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
|
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
|
||||||
},
|
},
|
||||||
|
"helmet": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/helmet/-/helmet-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-8wo+VdQhTMVBMCITYZaGTbE4lvlthelPYSvoyNvk4RECTmrVjMerp9RfUOQXZWLvCcAn1pKj7ZRxK4lI9Alrcw=="
|
||||||
|
},
|
||||||
"http-errors": {
|
"http-errors": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"docker-build": "docker build -t arhuako/ltsapi .",
|
||||||
"dev": "nodemon ./index.js"
|
"dev": "nodemon ./index.js"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
@ -15,6 +16,7 @@
|
|||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
"helmet": "^6.0.1",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"mongodb": "^4.13.0",
|
"mongodb": "^4.13.0",
|
||||||
"node": "^19.3.0",
|
"node": "^19.3.0",
|
||||||
@ -26,4 +28,4 @@
|
|||||||
"eslint": "^8.31.0",
|
"eslint": "^8.31.0",
|
||||||
"nodemon": "^2.0.20"
|
"nodemon": "^2.0.20"
|
||||||
}
|
}
|
||||||
}
|
}
|
57
test.js
57
test.js
@ -1,17 +1,54 @@
|
|||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
|
|
||||||
const { getUsers } = require('./app/db/mysql/lsaUsers');
|
const data = require('./testData/short.json');
|
||||||
const { RedisClient } = require('./app/db/redis/redis');
|
|
||||||
|
|
||||||
async function f() {
|
|
||||||
const users = await getUsers();
|
|
||||||
const redis = new RedisClient(process.env.REDIS_HOST);
|
|
||||||
|
|
||||||
await redis.connect()
|
const { analize, getShortStates, getAirTime } = require('./app/controllers/trackerAnalizer');
|
||||||
await redis.set('users', JSON.stringify(users))
|
const { getSessions, getSessionTracks, updateSessionTracks } = require('./app/db/mongo/mongoSessions');
|
||||||
await redis.disconnect();
|
const { getIvaoPilotsNow } = require('./app/requests/ivao/session');
|
||||||
|
// const { getHistoricalSessions, getSessionTracks } = require('./app/requests/ivao/session');
|
||||||
|
|
||||||
|
|
||||||
|
// const { getUsers } = require('./app/db/mysql/lsaUsers');
|
||||||
|
// const { RedisClient } = require('./app/db/redis/redis');
|
||||||
|
|
||||||
|
async function recalculateTime() {
|
||||||
|
// console.log(await getShortStates(data.tracks).map(d => ({ time: d.time, state: d.state, onGround: d.onGround })));
|
||||||
|
// console.log(await getAirTime(data.tracks));
|
||||||
|
|
||||||
|
|
||||||
|
const sessions = await getSessions('2022-01-01', '2023-11-01');
|
||||||
|
console.log('sessions.length :>> ', sessions.length);
|
||||||
|
let errs = [];
|
||||||
|
for (let index = 0; index < sessions.length; index++) {
|
||||||
|
let session;
|
||||||
|
try {
|
||||||
|
session = sessions[index];
|
||||||
|
const tracks = await getSessionTracks(session.id);
|
||||||
|
if (tracks) {
|
||||||
|
const newCalculatedTime = getAirTime(tracks.tracks);
|
||||||
|
// console.log(session.id, tracks.calculatedTime, newCalculatedTime);
|
||||||
|
tracks.calculatedTime = newCalculatedTime;
|
||||||
|
await updateSessionTracks(tracks);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(session.id);
|
||||||
|
errs.push(session.id, err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!errs.length) {
|
||||||
|
console.log('process ended OK');
|
||||||
|
} else {
|
||||||
|
console.log(errs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// f();
|
async function f() {
|
||||||
|
console.log((await getIvaoPilotsNow(true)).length);
|
||||||
|
}
|
||||||
|
|
||||||
require('./app/tasks/sync')();
|
f();
|
||||||
|
|
||||||
|
|
||||||
|
// require('./app/tasks/sync')();
|
Loading…
x
Reference in New Issue
Block a user