<commit_before>/*
 * KodeBlox Copyright 2017 Sayak Mukhopadhyay
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http: //www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

"use strict";

const _ = require('lodash');
const request = require('request');

const ebgsFactionsModel = require('../../../models/ebgs_factions');
const ebgsSystemsModel = require('../../../models/ebgs_systems');
const ebgsFactionsV3Model = require('../../../models/ebgs_factions_v3');
const ebgsSystemsV3Model = require('../../../models/ebgs_systems_v3');
const ebgsStationsV3Model = require('../../../models/ebgs_stations_v3');

module.exports = Journal;

function Journal() {
    this.schemaId = [
        // "http://schemas.elite-markets.net/eddn/journal/1",
        // "https://eddn.edcd.io/schemas/journal/1"
        "https://eddn.edcd.io/schemas/journal/1/test"
    ];

    this.trackSystem = function (message) {
        if (message.event === "FSDJump" || message.event === "Location") {
            if (message.Factions) {
                let systemObject = {
                    name: message.StarSystem,
                    name_lower: message.StarSystem.toLowerCase(),
                    x: message.StarPos[0],
                    y: message.StarPos[1],
                    z: message.StarPos[2],
                    government: message.SystemGovernment,
                    allegiance: message.SystemAllegiance,
                    state: message.FactionState,
                    security: message.SystemSecurity,
                    primary_economy: message.SystemEconomy,
                    updated_at: message.timestamp,
                    controlling_minor_faction: message.SystemFaction
                };

                if (message.Powers) {
                    systemObject.power = [];
                    message.Powers.forEach((power) => {
                        systemObject.power.push(power.toLowerCase());
                    });
                    systemObject.power_state = message.PowerplayState;
                }

                let factionArray = [];

                message.Factions.forEach((faction) => {
                    factionArray.push({
                        name: faction.Name,
                        name_lower: faction.Name.toLowerCase()
                    });

                    let historySubObject = {
                        updated_at: message.timestamp,
                        system: message.StarSystem,
                        system_lower: message.StarSystem.toLowerCase(),
                        state: faction.FactionState,
                        influence: faction.Influence
                    }

                    historySubObject.pending_states = [];
                    if (faction.PendingStates) {
                        faction.PendingStates.forEach(pendingState => {
                            let pendingStateObject = {
                                state: pendingState.State,
                                trend: pendingState.Trend
                            };
                            historySubObject.pending_states.push(pendingStateObject);
                        });
                    }
                    historySubObject.recovering_states = [];
                    if (faction.RecoveringStates) {
                        faction.RecoveringStates.forEach(recoveringState => {
                            let recoveringStateObject = {
                                state: recoveringState.State,
                                trend: recoveringState.Trend
                            };
                            historySubObject.recovering_states.push(recoveringStateObject);
                        });
                    };

                    let factionObject = {
                        name: faction.Name,
                        name_lower: faction.Name.toLowerCase(),
                        updated_at: message.timestamp,
                        government: faction.Government,
                        allegiance: faction.Allegiance,
                        $addToSet: {
                            faction_presence: {
                                system_name: message.StarSystem,
                                system_name_lower: message.StarSystem.toLowerCase()
                            },
                            history: historySubObject
                        }
                    };

                    ebgsFactionsModel
                        .then(model => {
                            model.findOneAndUpdate(
                                { name: faction.Name },
                                factionObject,
                                {
                                    upsert: true,
                                    runValidators: true
                                })
                                .exec()
                                .catch((err) => {
                                    console.log(err);
                                })
                        })
                        .catch(err => {
                            console.log(err);
                        });
                });
                systemObject.minor_faction_presences = factionArray;
                ebgsSystemsModel
                    .then(model => {
                        model.findOneAndUpdate(
                            { name: systemObject.name },
                            systemObject,
                            {
                                upsert: true,
                                runValidators: true
                            })
                            .exec()
                            .catch((err) => {
                                console.log(err);
                            })
                    })
                    .catch(err => {
                        console.log(err);
                    });
            }
        }
    }

    this.trackSystemV3 = function (message) {
        if (message.event === "FSDJump" || message.event === "Location") {
            if (message.Factions) {
                let factionArray = [];
                message.Factions.forEach(faction => {
                    let factionObject = {
                        name: faction.Name,
                        name_lower: faction.Name.toLowerCase()
                    };
                    factionArray.push(factionObject);
                });
                ebgsSystemsV3Model
                    .then(model => {
                        model.findOne(
                            {
                                name_lower: message.StarSystem.toLowerCase(),
                                x: this.correctCoordinates(message.StarPos[0]),
                                y: this.correctCoordinates(message.StarPos[1]),
                                z: this.correctCoordinates(message.StarPos[2])
                            },
                            { history: 0 }
                        ).lean().then(system => {
                            let hasEddbId = false;
                            let systemObject = {};
                            let historySubObject = {};
                            let eddbIdPromise;
                            if (system) {   // System exists in db
                                if (!system.eddb_id) {
                                    eddbIdPromise = this.getEDDBId(message.StarSystem);
                                } else {
                                    systemObject.eddb_id = system.eddb_id;
                                    hasEddbId = true;
                                }
                                if (system.government !== message.SystemGovernment.toLowerCase() ||
                                    system.allegiance !== message.SystemAllegiance.toLowerCase() ||
                                    system.state !== message.FactionState.toLowerCase() ||
                                    system.security !== message.SystemSecurity.toLowerCase() ||
                                    system.controlling_minor_faction !== message.SystemFaction.toLowerCase() ||
                                    !_.isEqual(_.sortBy(system.factions, ['name_lower']), _.sortBy(factionArray, ['name_lower']))) {

                                    systemObject.government = message.SystemGovernment;
                                    systemObject.allegiance = message.SystemAllegiance;
                                    systemObject.state = message.FactionState;
                                    systemObject.security = message.SystemSecurity;
                                    systemObject.controlling_minor_faction = message.SystemFaction;
                                    systemObject.factions = factionArray;
                                    systemObject.updated_at = message.timestamp;

                                    historySubObject.updated_at = message.timestamp;
                                    historySubObject.government = message.SystemGovernment;
                                    historySubObject.allegiance = message.SystemAllegiance;
                                    historySubObject.state = message.FactionState;
                                    historySubObject.security = message.SystemSecurity;
                                    historySubObject.controlling_minor_faction = message.SystemFaction;
                                    historySubObject.factions = factionArray;
                                } else {
                                    systemObject.updated_at = message.timestamp;
                                }
                            } else {
                                eddbIdPromise = this.getEDDBId(message.StarSystem);
                                systemObject = {
                                    name: message.StarSystem,
                                    name_lower: message.StarSystem.toLowerCase(),
                                    x: message.StarPos[0],
                                    y: message.StarPos[1],
                                    z: message.StarPos[2],
                                    government: message.SystemGovernment,
                                    allegiance: message.SystemAllegiance,
                                    state: message.FactionState,
                                    security: message.SystemSecurity,
                                    controlling_minor_faction: message.SystemFaction,
                                    factions: factionArray,
                                    updated_at: message.timestamp
                                };

                                historySubObject = {
                                    updated_at: message.timestamp,
                                    government: message.SystemGovernment,
                                    allegiance: message.SystemAllegiance,
                                    state: message.FactionState,
                                    security: message.SystemSecurity,
                                    controlling_minor_faction: message.SystemFaction,
                                    factions: factionArray
                                };
                            }
                            if (!_.isEmpty(historySubObject)) {
                                systemObject["$addToSet"] = {
                                    history: historySubObject
                                }
                            }
                            if (!_.isEmpty(systemObject)) {
                                if (hasEddbId) {
                                    model.findOneAndUpdate(
                                        {
                                            name_lower: message.StarSystem.toLowerCase(),
                                            x: this.correctCoordinates(message.StarPos[0]),
                                            y: this.correctCoordinates(message.StarPos[1]),
                                            z: this.correctCoordinates(message.StarPos[2])
                                        },
                                        systemObject,
                                        {
                                            upsert: true,
                                            runValidators: true
                                        })
                                        .exec()
                                        .catch((err) => {
                                            console.log(err);
                                        })
                                } else {
                                    eddbIdPromise.then(id => {
                                        systemObject.eddb_id = id;
                                        model.findOneAndUpdate(
                                            {
                                                name_lower: message.StarSystem.toLowerCase(),
                                                x: this.correctCoordinates(message.StarPos[0]),
                                                y: this.correctCoordinates(message.StarPos[1]),
                                                z: this.correctCoordinates(message.StarPos[2])
                                            },
                                            systemObject,
                                            {
                                                upsert: true,
                                                runValidators: true
                                            })
                                            .exec()
                                            .catch((err) => {
                                                console.log(err);
                                            })
                                    })
                                }
                            }
                        }).catch((err) => {
                            console.log(err);
                        })
                    })
                    .catch(err => {
                        console.log(err);
                    });
                ebgsFactionsV3Model
                    .then(model => {
                        // let factionsInSystem = new Promise((resolve, reject) => {
                        //     model.find(
                        //         {
                        //             faction_presence:
                        //             {
                        //                 $elemMatch:
                        //                 {
                        //                     name_lower: message.StarSystem.toLowerCase()
                        //                 }
                        //             }
                        //         },
                        //         { _id: 0, name: 1, name_lower: 1 }
                        //     ).lean().then(factions => {
                        //         resolve(factions);
                        //     }).catch(err => {
                        //         reject(err);
                        //     })
                        // });
                        model.find(
                            {
                                faction_presence:
                                {
                                    $elemMatch:
                                    {
                                        name_lower: message.StarSystem.toLowerCase()
                                    }
                                }
                            },
                            { _id: 0, name: 1, name_lower: 1 }
                        ).lean().then(factions => {
                            console.log(factionArray);
                            console.log(factions);

                            let messageFactionsLower = [];
                            message.Factions.forEach(faction => {
                                messageFactionsLower.push(faction.Name.toLowerCase());
                            });

                            model.find(
                                {
                                    name_lower: {
                                        $in: messageFactionsLower
                                    }
                                },
                                { history: 0 }
                            ).lean().then(factionsAllDetails => {
                                let dbFactionsLower = [];

                                factionsAllDetails.forEach(faction => {
                                    dbFactionsLower.push(faction.name_lower);
                                });

                                let notInDb = _.difference(messageFactionsLower, dbFactionsLower);
                                notInDb.forEach(factionNameLower => {
                                    message.Factions.forEach(messageFaction => {
                                        if (messageFaction.Name.toLowerCase() === factionNameLower) {
                                            let pendingStates = [];
                                            if (messageFaction.PendingStates) {
                                                messageFaction.PendingStates.forEach(pendingState => {
                                                    let pendingStateObject = {
                                                        state: pendingState.State,
                                                        trend: pendingState.Trend
                                                    };
                                                    pendingStates.push(pendingStateObject);
                                                });
                                            };
                                            let recoveringStates = [];
                                            if (messageFaction.RecoveringStates) {
                                                messageFaction.RecoveringStates.forEach(recoveringState => {
                                                    let recoveringStateObject = {
                                                        state: recoveringState.State,
                                                        trend: recoveringState.Trend
                                                    };
                                                    recoveringStates.push(recoveringStateObject);
                                                });
                                            };

                                            let factionObject = {
                                                name: messageFaction.Name,
                                                name_lower: messageFaction.Name.toLowerCase(),
                                                updated_at: message.timestamp,
                                                faction_presence: [{
                                                    system_name: message.StarSystem,
                                                    system_name_lower: message.StarSystem.toLowerCase(),
                                                    state: messageFaction.FactionState,
                                                    influence: messageFaction.Influence,
                                                    pending_states: pendingStates,
                                                    recovering_states: recoveringStates
                                                }],
                                                history: [{
                                                    updated_at: message.timestamp,
                                                    system_name: message.StarSystem,
                                                    system_name_lower: message.StarSystem.toLowerCase(),
                                                    state: messageFaction.FactionState,
                                                    influence: messageFaction.Influence,
                                                    pending_states: pendingStates,
                                                    recovering_states: recoveringStates,
                                                    systems: [{
                                                        name: message.StarSystem,
                                                        name_lower: message.StarSystem.toLowerCase()
                                                    }]
                                                }]
                                            };
                                            new model(factionObject).save()
                                                .then(saved => {
                                                    console.log("saved", saved);
                                                })
                                                .catch(err => {
                                                    console.log(err);
                                                })
                                        }
                                    })
                                })
                            })
                        }).catch(err => {
                            console.log(err);
                        })
                    })
                    .catch(err => {
                        console.log(err);
                    });
            }
        }
    }

    this.correctCoordinates = function (value) {
        let floatValue = Number.parseFloat(value);
        let intValue = Number.parseInt((floatValue * 32).toString().split('.')[0]);
        return intValue / 32;
    }

    this.getEDDBId = function (name) {
        return new Promise((resolve, reject) => {
            let requestOptions = {
                url: "http://elitebgs.kodeblox.com/api/eddb/v1/populatedsystems",
                method: "GET",
                auth: {
                    'user': 'guest',
                    'pass': 'secret',
                    'sendImmediately': true
                },
                qs: {
                    name: name.toLowerCase()
                }
            };
            request(requestOptions, (error, response, body) => {
                if (!error && response.statusCode == 200) {
                    let responseData = body;
                    if (responseData.length !== 2) {
                        let responseObject = JSON.parse(responseData);
                        resolve(responseObject[0].id);
                    } else {
                        reject();
                    }
                } else {
                    reject();
                }
            });
        })
    }
}
<commit_msg>Faction message all conditions check<commit_after>/*
 * KodeBlox Copyright 2017 Sayak Mukhopadhyay
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http: //www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

"use strict";

const _ = require('lodash');
const request = require('request');

const ebgsFactionsModel = require('../../../models/ebgs_factions');
const ebgsSystemsModel = require('../../../models/ebgs_systems');
const ebgsFactionsV3Model = require('../../../models/ebgs_factions_v3');
const ebgsSystemsV3Model = require('../../../models/ebgs_systems_v3');
const ebgsStationsV3Model = require('../../../models/ebgs_stations_v3');

module.exports = Journal;

function Journal() {
    this.schemaId = [
        // "http://schemas.elite-markets.net/eddn/journal/1",
        // "https://eddn.edcd.io/schemas/journal/1"
        "https://eddn.edcd.io/schemas/journal/1/test"
    ];

    this.trackSystem = function (message) {
        if (message.event === "FSDJump" || message.event === "Location") {
            if (message.Factions) {
                let systemObject = {
                    name: message.StarSystem,
                    name_lower: message.StarSystem.toLowerCase(),
                    x: message.StarPos[0],
                    y: message.StarPos[1],
                    z: message.StarPos[2],
                    government: message.SystemGovernment,
                    allegiance: message.SystemAllegiance,
                    state: message.FactionState,
                    security: message.SystemSecurity,
                    primary_economy: message.SystemEconomy,
                    updated_at: message.timestamp,
                    controlling_minor_faction: message.SystemFaction
                };

                if (message.Powers) {
                    systemObject.power = [];
                    message.Powers.forEach((power) => {
                        systemObject.power.push(power.toLowerCase());
                    });
                    systemObject.power_state = message.PowerplayState;
                }

                let factionArray = [];

                message.Factions.forEach((faction) => {
                    factionArray.push({
                        name: faction.Name,
                        name_lower: faction.Name.toLowerCase()
                    });

                    let historySubObject = {
                        updated_at: message.timestamp,
                        system: message.StarSystem,
                        system_lower: message.StarSystem.toLowerCase(),
                        state: faction.FactionState,
                        influence: faction.Influence
                    }

                    historySubObject.pending_states = [];
                    if (faction.PendingStates) {
                        faction.PendingStates.forEach(pendingState => {
                            let pendingStateObject = {
                                state: pendingState.State,
                                trend: pendingState.Trend
                            };
                            historySubObject.pending_states.push(pendingStateObject);
                        });
                    }
                    historySubObject.recovering_states = [];
                    if (faction.RecoveringStates) {
                        faction.RecoveringStates.forEach(recoveringState => {
                            let recoveringStateObject = {
                                state: recoveringState.State,
                                trend: recoveringState.Trend
                            };
                            historySubObject.recovering_states.push(recoveringStateObject);
                        });
                    };

                    let factionObject = {
                        name: faction.Name,
                        name_lower: faction.Name.toLowerCase(),
                        updated_at: message.timestamp,
                        government: faction.Government,
                        allegiance: faction.Allegiance,
                        $addToSet: {
                            faction_presence: {
                                system_name: message.StarSystem,
                                system_name_lower: message.StarSystem.toLowerCase()
                            },
                            history: historySubObject
                        }
                    };

                    ebgsFactionsModel
                        .then(model => {
                            model.findOneAndUpdate(
                                { name: faction.Name },
                                factionObject,
                                {
                                    upsert: true,
                                    runValidators: true
                                })
                                .exec()
                                .catch((err) => {
                                    console.log(err);
                                })
                        })
                        .catch(err => {
                            console.log(err);
                        });
                });
                systemObject.minor_faction_presences = factionArray;
                ebgsSystemsModel
                    .then(model => {
                        model.findOneAndUpdate(
                            { name: systemObject.name },
                            systemObject,
                            {
                                upsert: true,
                                runValidators: true
                            })
                            .exec()
                            .catch((err) => {
                                console.log(err);
                            })
                    })
                    .catch(err => {
                        console.log(err);
                    });
            }
        }
    }

    this.trackSystemV3 = function (message) {
        if (message.event === "FSDJump" || message.event === "Location") {
            if (message.Factions) {
                let factionArray = [];
                message.Factions.forEach(faction => {
                    let factionObject = {
                        name: faction.Name,
                        name_lower: faction.Name.toLowerCase()
                    };
                    factionArray.push(factionObject);
                });
                ebgsSystemsV3Model
                    .then(model => {
                        model.findOne(
                            {
                                name_lower: message.StarSystem.toLowerCase(),
                                x: this.correctCoordinates(message.StarPos[0]),
                                y: this.correctCoordinates(message.StarPos[1]),
                                z: this.correctCoordinates(message.StarPos[2])
                            },
                            { history: 0 }
                        ).lean().then(system => {
                            let hasEddbId = false;
                            let systemObject = {};
                            let historySubObject = {};
                            let eddbIdPromise;
                            if (system) {   // System exists in db
                                if (!system.eddb_id) {
                                    eddbIdPromise = this.getEDDBId(message.StarSystem);
                                } else {
                                    systemObject.eddb_id = system.eddb_id;
                                    hasEddbId = true;
                                }
                                if (system.government !== message.SystemGovernment.toLowerCase() ||
                                    system.allegiance !== message.SystemAllegiance.toLowerCase() ||
                                    system.state !== message.FactionState.toLowerCase() ||
                                    system.security !== message.SystemSecurity.toLowerCase() ||
                                    system.controlling_minor_faction !== message.SystemFaction.toLowerCase() ||
                                    !_.isEqual(_.sortBy(system.factions, ['name_lower']), _.sortBy(factionArray, ['name_lower']))) {

                                    systemObject.government = message.SystemGovernment;
                                    systemObject.allegiance = message.SystemAllegiance;
                                    systemObject.state = message.FactionState;
                                    systemObject.security = message.SystemSecurity;
                                    systemObject.controlling_minor_faction = message.SystemFaction;
                                    systemObject.factions = factionArray;
                                    systemObject.updated_at = message.timestamp;

                                    historySubObject.updated_at = message.timestamp;
                                    historySubObject.government = message.SystemGovernment;
                                    historySubObject.allegiance = message.SystemAllegiance;
                                    historySubObject.state = message.FactionState;
                                    historySubObject.security = message.SystemSecurity;
                                    historySubObject.controlling_minor_faction = message.SystemFaction;
                                    historySubObject.factions = factionArray;
                                } else {
                                    systemObject.updated_at = message.timestamp;
                                }
                            } else {
                                eddbIdPromise = this.getEDDBId(message.StarSystem);
                                systemObject = {
                                    name: message.StarSystem,
                                    name_lower: message.StarSystem.toLowerCase(),
                                    x: message.StarPos[0],
                                    y: message.StarPos[1],
                                    z: message.StarPos[2],
                                    government: message.SystemGovernment,
                                    allegiance: message.SystemAllegiance,
                                    state: message.FactionState,
                                    security: message.SystemSecurity,
                                    controlling_minor_faction: message.SystemFaction,
                                    factions: factionArray,
                                    updated_at: message.timestamp
                                };

                                historySubObject = {
                                    updated_at: message.timestamp,
                                    government: message.SystemGovernment,
                                    allegiance: message.SystemAllegiance,
                                    state: message.FactionState,
                                    security: message.SystemSecurity,
                                    controlling_minor_faction: message.SystemFaction,
                                    factions: factionArray
                                };
                            }
                            if (!_.isEmpty(historySubObject)) {
                                systemObject["$addToSet"] = {
                                    history: historySubObject
                                }
                            }
                            if (!_.isEmpty(systemObject)) {
                                if (hasEddbId) {
                                    model.findOneAndUpdate(
                                        {
                                            name_lower: message.StarSystem.toLowerCase(),
                                            x: this.correctCoordinates(message.StarPos[0]),
                                            y: this.correctCoordinates(message.StarPos[1]),
                                            z: this.correctCoordinates(message.StarPos[2])
                                        },
                                        systemObject,
                                        {
                                            upsert: true,
                                            runValidators: true
                                        })
                                        .exec()
                                        .catch((err) => {
                                            console.log(err);
                                        })
                                } else {
                                    eddbIdPromise.then(id => {
                                        systemObject.eddb_id = id;
                                        model.findOneAndUpdate(
                                            {
                                                name_lower: message.StarSystem.toLowerCase(),
                                                x: this.correctCoordinates(message.StarPos[0]),
                                                y: this.correctCoordinates(message.StarPos[1]),
                                                z: this.correctCoordinates(message.StarPos[2])
                                            },
                                            systemObject,
                                            {
                                                upsert: true,
                                                runValidators: true
                                            })
                                            .exec()
                                            .catch((err) => {
                                                console.log(err);
                                            })
                                    })
                                }
                            }
                        }).catch((err) => {
                            console.log(err);
                        })
                    })
                    .catch(err => {
                        console.log(err);
                    });
                ebgsFactionsV3Model
                    .then(model => {
                        let messageFactionsLower = [];
                        message.Factions.forEach(faction => {
                            messageFactionsLower.push(faction.Name.toLowerCase());
                        });

                        let allFactionsPresentInSystem = model.find(
                            {
                                faction_presence: {
                                    $elemMatch: { system_name_lower: message.StarSystem.toLowerCase() }
                                }
                            },
                            { history: 0 }
                        ).lean();

                        let allFactionsPresentInMessage = model.find(
                            {
                                name_lower: {
                                    $in: messageFactionsLower
                                }
                            },
                            { history: 0 }
                        ).lean();

                        Promise.all([allFactionsPresentInSystem, allFactionsPresentInMessage])
                            .then(values => {
                                let factionsPresentInSystemDB = values[0];
                                let factionsAllDetails = values[1];

                                let factionsNotInSystem = [];

                                factionsPresentInSystemDB.forEach(faction => {
                                    factionsNotInSystem.push(faction.name_lower);
                                });

                                let toRemove = _.difference(factionsNotInSystem, messageFactionsLower);

                                let dbFactionsLower = [];

                                factionsAllDetails.forEach(faction => {
                                    dbFactionsLower.push(faction.name_lower);
                                });
                                let notInDb = _.difference(messageFactionsLower, dbFactionsLower);
                                // To remove are those factions which are not present in this system anymore
                                // Such factions need to be updated too
                                toRemove.forEach(factionNameLower => {
                                    factionsPresentInSystemDB.forEach(faction => {
                                        if (factionNameLower === faction.name_lower) {
                                            let factionPresence = [];
                                            faction.faction_presence.forEach(system => {
                                                if (system.system_name_lower !== message.StarSystem.toLowerCase()) {
                                                    factionPresence.push(system);
                                                }
                                            });
                                            faction.faction_presence = factionPresence;
                                            faction.updated_at = message.timestamp;

                                            model.findOneAndUpdate(
                                                { name: faction.name },
                                                faction,
                                                {
                                                    upsert: true,
                                                    runValidators: true
                                                })
                                                .then(saved => {
                                                    // console.log("saved", saved);
                                                })
                                                .catch(err => {
                                                    console.log(err);
                                                })
                                        }
                                    })
                                })
                                // Not In DB means that the message contains a faction which is not present in the db yet
                                // So one must create a new record
                                notInDb.forEach(factionNameLower => {
                                    message.Factions.forEach(messageFaction => {
                                        if (messageFaction.Name.toLowerCase() === factionNameLower) {
                                            let pendingStates = [];
                                            if (messageFaction.PendingStates) {
                                                messageFaction.PendingStates.forEach(pendingState => {
                                                    let pendingStateObject = {
                                                        state: pendingState.State.toLowerCase(),
                                                        trend: pendingState.Trend
                                                    };
                                                    pendingStates.push(pendingStateObject);
                                                });
                                            };
                                            let recoveringStates = [];
                                            if (messageFaction.RecoveringStates) {
                                                messageFaction.RecoveringStates.forEach(recoveringState => {
                                                    let recoveringStateObject = {
                                                        state: recoveringState.State.toLowerCase(),
                                                        trend: recoveringState.Trend
                                                    };
                                                    recoveringStates.push(recoveringStateObject);
                                                });
                                            };

                                            let factionObject = {
                                                name: messageFaction.Name,
                                                name_lower: messageFaction.Name.toLowerCase(),
                                                updated_at: message.timestamp,
                                                faction_presence: [{
                                                    system_name: message.StarSystem,
                                                    system_name_lower: message.StarSystem.toLowerCase(),
                                                    state: messageFaction.FactionState,
                                                    influence: messageFaction.Influence,
                                                    pending_states: pendingStates,
                                                    recovering_states: recoveringStates
                                                }],
                                                history: [{
                                                    updated_at: message.timestamp,
                                                    system: message.StarSystem,
                                                    system_lower: message.StarSystem.toLowerCase(),
                                                    state: messageFaction.FactionState,
                                                    influence: messageFaction.Influence,
                                                    pending_states: pendingStates,
                                                    recovering_states: recoveringStates,
                                                    systems: [{
                                                        name: message.StarSystem,
                                                        name_lower: message.StarSystem.toLowerCase()
                                                    }]
                                                }]
                                            };
                                            new model(factionObject).save()
                                                .then(saved => {
                                                    // console.log("saved", saved);
                                                })
                                                .catch(err => {
                                                    console.log(err);
                                                })
                                        }
                                    })
                                })
                                // dbFactionsLower are the factions present in the db. So next we need to update them
                                // factionsAllDetails has all the factions details
                                factionsAllDetails.forEach(dbFaction => {
                                    message.Factions.forEach(messageFaction => {
                                        if (messageFaction.Name.toLowerCase() === dbFaction.name_lower) {
                                            let pendingStates = [];
                                            if (messageFaction.PendingStates) {
                                                messageFaction.PendingStates.forEach(pendingState => {
                                                    let pendingStateObject = {
                                                        state: pendingState.State.toLowerCase(),
                                                        trend: pendingState.Trend
                                                    };
                                                    pendingStates.push(pendingStateObject);
                                                });
                                            };
                                            let recoveringStates = [];
                                            if (messageFaction.RecoveringStates) {
                                                messageFaction.RecoveringStates.forEach(recoveringState => {
                                                    let recoveringStateObject = {
                                                        state: recoveringState.State.toLowerCase(),
                                                        trend: recoveringState.Trend
                                                    };
                                                    recoveringStates.push(recoveringStateObject);
                                                });
                                            };

                                            // Check if the incoming message has any different faction detail
                                            let doUpdate = true;
                                            dbFaction.faction_presence.forEach(faction => {
                                                if (faction.system_name_lower === message.StarSystem.toLowerCase() &&
                                                    faction.state === messageFaction.FactionState.toLowerCase() &&
                                                    faction.influence === messageFaction.Influence &&
                                                    _.isEqual(_.sortBy(faction.pending_states, ['state']), _.sortBy(pendingStates, ['state']))) {
                                                    doUpdate = false;
                                                }
                                            })
                                            if (doUpdate) {
                                                let factionPresentSystemObject = {};
                                                let factionPresence = dbFaction.faction_presence;

                                                factionPresence.forEach((factionPresenceObject, index, factionPresenceArray) => {
                                                    if (factionPresenceObject.system_name_lower === message.StarSystem.toLowerCase()) {
                                                        factionPresentSystemObject = {
                                                            system_name: message.StarSystem,
                                                            system_name_lower: message.StarSystem.toLowerCase(),
                                                            state: messageFaction.FactionState,
                                                            influence: messageFaction.Influence,
                                                            pending_states: pendingStates,
                                                            recovering_states: recoveringStates
                                                        };
                                                        factionPresenceArray[index] = factionPresentSystemObject;
                                                    }
                                                });

                                                if (_.isEmpty(factionPresentSystemObject)) {
                                                    // This system is not present as a presence system in db.
                                                    // Make a new array element
                                                    factionPresence.push({
                                                        system_name: message.StarSystem,
                                                        system_name_lower: message.StarSystem.toLowerCase(),
                                                        state: messageFaction.FactionState,
                                                        influence: messageFaction.Influence,
                                                        pending_states: pendingStates,
                                                        recovering_states: recoveringStates
                                                    });
                                                }

                                                let systemHistory = [];

                                                factionPresence.forEach((faction) => {
                                                    systemHistory.push({
                                                        name: faction.system_name,
                                                        name_lower: faction.system_name_lower
                                                    });
                                                });

                                                let factionObject = {
                                                    name: messageFaction.Name,
                                                    name_lower: messageFaction.Name.toLowerCase(),
                                                    updated_at: message.timestamp,
                                                    faction_presence: factionPresence,
                                                    $addToSet: {
                                                        history: {
                                                            updated_at: message.timestamp,
                                                            system: message.StarSystem,
                                                            system_lower: message.StarSystem.toLowerCase(),
                                                            state: messageFaction.FactionState,
                                                            influence: messageFaction.Influence,
                                                            pending_states: pendingStates,
                                                            recovering_states: recoveringStates,
                                                            systems: systemHistory
                                                        }
                                                    }
                                                };
                                                model.findOneAndUpdate(
                                                    { name: messageFaction.Name },
                                                    factionObject,
                                                    {
                                                        upsert: true,
                                                        runValidators: true
                                                    })
                                                    .then(saved => {
                                                        // console.log("saved", saved);
                                                    })
                                                    .catch(err => {
                                                        console.log(err);
                                                    })
                                            }
                                        }
                                    })
                                })
                            })
                    })
                    .catch(err => {
                        console.log(err);
                    });
            }
        }
    }

    this.correctCoordinates = function (value) {
        let floatValue = Number.parseFloat(value);
        let intValue = Number.parseInt((floatValue * 32).toString().split('.')[0]);
        return intValue / 32;
    }

    this.getEDDBId = function (name) {
        return new Promise((resolve, reject) => {
            let requestOptions = {
                url: "http://elitebgs.kodeblox.com/api/eddb/v1/populatedsystems",
                method: "GET",
                auth: {
                    'user': 'guest',
                    'pass': 'secret',
                    'sendImmediately': true
                },
                qs: {
                    name: name.toLowerCase()
                }
            };
            request(requestOptions, (error, response, body) => {
                if (!error && response.statusCode == 200) {
                    let responseData = body;
                    if (responseData.length !== 2) {
                        let responseObject = JSON.parse(responseData);
                        resolve(responseObject[0].id);
                    } else {
                        reject();
                    }
                } else {
                    reject();
                }
            });
        })
    }
}
<|endoftext|>


<commit_before>'use strict';

var GamesController = require('../Games');

module.exports = function () {

};

module.exports.prototype = GamesController.prototype.extend({
  name: 'sorting',

/**
 * GET - This Method is used for the index page
 *
 * @return title - the title of the game
 * @return route - url route
 */
  indexAction: function() {
    this.view.render({
      title: 'Sortierspiel',
      route: '/games/sorting'
    });
  },

/** GET - This renders the main game
 *
 * @return buildings - an array of buildings to display for the template
 */
  gameAction: function() {
    var _this = this,
        level = parseInt(this.request.param('level'),10),
        limit = parseInt(this.request.param('limit'),10);

    _this.renderGame(level, limit, function(err, buildings){
      _this.view.render({
        title: 'Sortierspiel',
        route: '/games/sorting',
        buildings: buildings
      });
    });
  },

/**
 * Gets the buildings from the database and returns it with a callback
 *
 * @param countLimit     - count limit of buildings
 * @param renderCallback - the callback to call after we got the buildings
 * @param game           - information about the current game
 */
  renderGame: function(level, countLimit, renderCallback) {
    var buildingLimit = countLimit || 7;
    if (level === 3) {

      // Only level 2 buildings
      this.mongodb
        .collection('sorting_buildings')
        .find({level: 2, _random: {$near: [Math.random(), 0]}})
        .limit(buildingLimit)
        .toArray(renderCallback);

    }else if (level === 2) {

      // Level 1 and level 2
      this.mongodb
        .collection('sorting_buildings')
        .find({_random: {$near: [Math.random(), 0]}})
        .limit(buildingLimit)
        .toArray(renderCallback);
    }
    else {

      // only level 1
      this.mongodb
        .collection('sorting_buildings')
        .find({level: 1, _random: {$near: [Math.random(), 0]}})
        .limit(buildingLimit)
        .toArray(renderCallback);
    }
  },

/**
 * POST request to check the solution
 * the parameters are from the <form> element
 *
 * @param gameid    - the id of the game
 * @param sortings  - an array of ids, shows how the images were sorted
 */
  checkSortingAction: function() {
    var _this = this;

    // get the era attribute with correct sorting of eras
    _this.mongodb
      .collection('attributes')
      .find({name: 'era'})
      .nextObject(function(err, attribute) {

        var eras = attribute.values,
            sortIds = _this.request.param('sortings'),
            sortedBuildings = {};

        // we have to cast the mongo ids for the db-request
        for (var i = 0; i < sortIds.length; i++) {
          sortIds[i] = _this.mongo.ObjectID(sortIds[i]);
          sortedBuildings[sortIds[i]] = null;
        }

        _this.mongodb.collection('sorting_buildings')
          .find({_id: {$in: sortIds}})
          .toArray(function(err, buildings) {

            // got all requested buildings, now calculate if sorting is right
            var lastEraIndex = 0,
              lastCorrectBuilding = -1,
              correct = true;

            // TODO:
            // gameparam: show last right
            // gameparam: show right solution
            // gameparam: show only correct or false
            // gameparam: num of possible tries

            for (var i = 0; i < buildings.length; i++) {
              sortedBuildings[''+buildings[i]._id] = buildings[i];
            }

            var buildingIndex = 0;
            for (var _id in sortedBuildings) {
              if (!sortedBuildings[_id]){ continue; }

              // go through all buildings and check index of era in era-array
              var buildingEraIndex = eras.indexOf(sortedBuildings[_id].era);

              if (buildingEraIndex < lastEraIndex) {
                correct = false;
                break;
              }
              lastEraIndex = buildingEraIndex;
              lastCorrectBuilding = buildingIndex;
              buildingIndex++;
            }

            // response with a json object
            _this.response.json({
              correct: correct,
              lastCorrectBuilding: lastCorrectBuilding
            });
          });
      });
  }
});
<commit_msg>sorting: returns error if elements are empty<commit_after>'use strict';

var GamesController = require('../Games');

module.exports = function () {

};

module.exports.prototype = GamesController.prototype.extend({
  name: 'sorting',

/**
 * GET - This Method is used for the index page
 *
 * @return title - the title of the game
 * @return route - url route
 */
  indexAction: function() {
    this.view.render({
      title: 'Sortierspiel',
      route: '/games/sorting'
    });
  },

/** GET - This renders the main game
 *
 * @return buildings - an array of buildings to display for the template
 */
  gameAction: function() {
    var _this = this,
        level = parseInt(this.request.param('level'),10),
        limit = parseInt(this.request.param('limit'),10);

    _this.renderGame(level, limit, function(err, buildings){
      _this.view.render({
        title: 'Sortierspiel',
        route: '/games/sorting',
        buildings: buildings
      });
    });
  },

/**
 * Gets the buildings from the database and returns it with a callback
 *
 * @param countLimit     - count limit of buildings
 * @param renderCallback - the callback to call after we got the buildings
 * @param game           - information about the current game
 */
  renderGame: function(level, countLimit, renderCallback) {
    var buildingLimit = countLimit || 7;
    if (level === 3) {

      // Only level 2 buildings
      this.mongodb
        .collection('sorting_buildings')
        .find({level: 2, _random: {$near: [Math.random(), 0]}})
        .limit(buildingLimit)
        .toArray(renderCallback);

    }else if (level === 2) {

      // Level 1 and level 2
      this.mongodb
        .collection('sorting_buildings')
        .find({_random: {$near: [Math.random(), 0]}})
        .limit(buildingLimit)
        .toArray(renderCallback);
    }
    else {

      // only level 1
      this.mongodb
        .collection('sorting_buildings')
        .find({level: 1, _random: {$near: [Math.random(), 0]}})
        .limit(buildingLimit)
        .toArray(renderCallback);
    }
  },

/**
 * POST request to check the solution
 * the parameters are from the <form> element
 *
 * @param sortings  - an array of ids, shows how the images were sorted
 */
  checkSortingAction: function() {
    var _this = this;

    // get the era attribute with correct sorting of eras
    _this.mongodb
      .collection('attributes')
      .find({name: 'era'})
      .nextObject(function(err, attribute) {

        var eras = attribute.values,
            sortIds = _this.request.param('sortings'),
            sortedBuildings = {};
        if(sortIds === undefined){
          _this.response.json({
            error: 'Irgendwas ist schiefgelaufen!'
          });
        }
        // we have to cast the mongo ids for the db-request
        for (var i = 0; i < sortIds.length; i++) {
          sortIds[i] = _this.mongo.ObjectID(sortIds[i]);
          sortedBuildings[sortIds[i]] = null;
        }

        _this.mongodb.collection('sorting_buildings')
          .find({_id: {$in: sortIds}})
          .toArray(function(err, buildings) {

            // got all requested buildings, now calculate if sorting is right
            var lastEraIndex = 0,
              lastCorrectBuilding = -1,
              correct = true;

            // TODO:
            // gameparam: show last right
            // gameparam: show right solution
            // gameparam: show only correct or false
            // gameparam: num of possible tries

            for (var i = 0; i < buildings.length; i++) {
              sortedBuildings[''+buildings[i]._id] = buildings[i];
            }

            var buildingIndex = 0;
            for (var _id in sortedBuildings) {
              if (!sortedBuildings[_id]){ continue; }

              // go through all buildings and check index of era in era-array
              var buildingEraIndex = eras.indexOf(sortedBuildings[_id].era);

              if (buildingEraIndex < lastEraIndex) {
                correct = false;
                break;
              }
              lastEraIndex = buildingEraIndex;
              lastCorrectBuilding = buildingIndex;
              buildingIndex++;
            }

            // response with a json object
            _this.response.json({
              correct: correct,
              lastCorrectBuilding: lastCorrectBuilding
            });
          });
      });
  }
});
<|endoftext|>


<commit_before>Hull.component({
  templates: ['main'],

  datasources : {
    quizzes : {
      path: 'app/achievements',
      params: { where: { _type: 'Quiz'} }
    }
  },

  beforeRender: function(data) {
    var _ = this.sandbox.util._;

    var fields = ['user_id', ['name', 'Name'], ['email', 'Email']];

    if (_.isArray(data.app.extra.profile_fields)) {
      _.each(data.app.extra.profile_fields, function(f) {
        if (f.name == null || f.label == null) return;

        key = ['apps', data.app.id, 'profile', f.name].join('.');
        value = f.label + ' (registration form)';

        fields.push([key, value]);
      });
    }

    _.each(data.quizzes, function(q) {
      _.each([
        ['best_score', 'Score'],
        ['timing', 'Timing'],
        ['stats.attempts', 'Attempts']
      ], function(k) {
        key = ['apps', data.app.id, 'badges', q.id, k[0]].join('.');
        value = k[1] + ' (quiz: ' + q.name + ')';

        fields.push([key, value]);
      });
    });

    this.fields = fields;
  },

  actions: {
    extract: function(event, action) {
      var email = this.$('input[type="email"]').val();

      this.api('app/user_reports/extracts', 'post', {
        email: email,
        fields: this.fields
      }).always(function(r) {
        alert(r.message);
      });
    }
  }
});
<commit_msg>Change key for timing<commit_after>Hull.component({
  templates: ['main'],

  datasources : {
    quizzes : {
      path: 'app/achievements',
      params: { where: { _type: 'Quiz'} }
    }
  },

  beforeRender: function(data) {
    var _ = this.sandbox.util._;

    var fields = ['user_id', ['name', 'Name'], ['email', 'Email']];

    if (_.isArray(data.app.extra.profile_fields)) {
      _.each(data.app.extra.profile_fields, function(f) {
        if (f.name == null || f.label == null) return;

        key = ['apps', data.app.id, 'profile', f.name].join('.');
        value = f.label + ' (registration form)';

        fields.push([key, value]);
      });
    }

    _.each(data.quizzes, function(q) {
      _.each([
        ['best_score', 'Score'],
        ['data.timing', 'Timing'],
        ['stats.attempts', 'Attempts']
      ], function(k) {
        key = ['apps', data.app.id, 'badges', q.id, k[0]].join('.');
        value = k[1] + ' (quiz: ' + q.name + ')';

        fields.push([key, value]);
      });
    });

    this.fields = fields;
  },

  actions: {
    extract: function(event, action) {
      var email = this.$('input[type="email"]').val();

      this.api('app/user_reports/extracts', 'post', {
        email: email,
        fields: this.fields
      }).always(function(r) {
        alert(r.message);
      });
    }
  }
});
<|endoftext|>


<commit_before>'use strict';
/*
 * Copyright 2014 Next Century Corporation
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// Defaulting the Neon SERVER_URL to be under the neon context on the same host machine.
// Used by neon core server.  Don't delete this or you will probably break everything!
neon.SERVER_URL = "/neon";

/**
 * Utility that calls the given function in an $apply if the given $scope is not in the apply/digest phase or just calls the given function normally otherwise.
 * @param {Object} $scope The $scope of an angular directive.
 * @param {Fucntion} func The function to call.
 * @method safeApply
 */
neon.safeApply = function($scope, func) {
    if(!$scope || !func || typeof func !== "function") {
        return;
    }

    var phase = $scope.$root.$$phase;
    if(phase === "$apply" || phase === "$digest") {
        func();
    } else {
        $scope.$apply(func);
    }
};

var neonDemo = angular.module('neonDemo', [
    'neonDemo.controllers',
    'neonDemo.services',
    'neonDemo.directives',
    'neonDemo.filters',
    'gridster',
    'ngDraggable',
    'ngRoute',
    'ui.bootstrap.datetimepicker',

    'gantt',
    'gantt.tooltips',
    'gantt.tree',
    'gantt.groups'
]);

neonDemo.config(function($routeProvider, $locationProvider) {
    $routeProvider.when('/', {
        templateUrl: 'index.html',
        controller: 'neonDemoController'
    });
    $locationProvider.html5Mode({
        enabled: true,
        requireBase: false
    });
});

// AngularJS filter for reversing the order of an array.
// http://stackoverflow.com/questions/15266671/angular-ng-repeat-in-reverse
neonDemo.filter("reverse", function() {
    return function(items) {
        return items.slice().reverse();
    };
});

angular.module('neonDemo.directives', []);
angular.module('neonDemo.controllers', []);
angular.module('neonDemo.services', []);

angular.module('neonDemo.filters', [])
.filter('numberShort', function() {
    return function(number) {
        if(typeof number !== undefined) {
            var abs = Math.abs(number);
            if(abs >= Math.pow(10, 12)) {
                number = (number / Math.pow(10, 12)).toFixed(1) + "T";
            } else if(abs < Math.pow(10, 12) && abs >= Math.pow(10, 9)) {
                number = (number / Math.pow(10, 9)).toFixed(1) + "B";
            } else if(abs < Math.pow(10, 9) && abs >= Math.pow(10, 6)) {
                number = (number / Math.pow(10, 6)).toFixed(1) + "M";
            } else if(abs < Math.pow(10, 6) && abs >= Math.pow(10, 3)) {
                number = (number / Math.pow(10, 3)).toFixed(1) + "K";
            } else {
                number = Math.round(number * 100) / 100;
            }
        }
        return number;
    };
});

var XDATA = {};

// Start angular once all of the configuration variables have been read from the JSON file(s) and set in the module.
var startAngular = function() {
    angular.bootstrap(document, ['neonDemo']);
};

var saveUserAle = function(config) {
    // Configure the user-ale logger.
    var aleConfig = (config.user_ale || {
        loggingUrl: "http://192.168.1.100",
        toolName: "Neon Dashboard",
        elementGroups: [
            "top",
            "map_group",
            "table_group",
            "chart_group",
            "query_group",
            "graph_group"
        ],
        workerUrl: "lib/user-ale/js/userale-worker.js",
        debug: false,
        sendLogs: false
    });
    XDATA.userALE = new userale(aleConfig);
    XDATA.userALE.register();
};

var saveOpenCpu = function(config) {
    var opencpuConfig = (config.opencpu || {
        enableOpenCpu: false
    });
    if(opencpuConfig.enableOpenCpu) {
        ocpu.enableLogging = opencpuConfig.enableLogging;
        ocpu.useAlerts = opencpuConfig.useAlerts;
        ocpu.seturl(opencpuConfig.url);
        ocpu.connected = true;
    }
    neonDemo.constant('opencpu', opencpuConfig);
};

var saveDashboards = function(config) {
    var helpConfig = (config.help || {
        guide: undefined,
        video: undefined
    });
    var dashboardConfig = config.dashboard || {
        hideNavbarItems: false,
        hideAddVisualizationsButton: false,
        hideAdvancedOptions: false,
        hideErrorNotifications: false,
        hideHeader: false,
        showImport: false,
        showExport: true
    };
    dashboardConfig.gridsterColumns = dashboardConfig.gridsterColumns || 8;
    dashboardConfig.gridsterMargins = dashboardConfig.gridsterMargins || 10;
    // Most visualizations should have a minimum size of about 300px square to have space for their UI elements.
    // TODO Use the browser width to determine the minimum size for visualizations and update it on browser resize.
    dashboardConfig.gridsterDefaultMinSizeX = Math.floor(dashboardConfig.gridsterColumns / 4);
    dashboardConfig.gridsterDefaultMinSizeY = Math.floor(dashboardConfig.gridsterColumns / 6);
    dashboardConfig.help = helpConfig;
    dashboardConfig.showExport = (dashboardConfig.showExport === undefined || dashboardConfig.showExport) ? true : false;
    neonDemo.constant('config', dashboardConfig);

    // Keep the autoplay video code here because when it was in the neonDemoController the dashboard would start playing the video whenever the dataset was changed.
    if(dashboardConfig.showVideoOnLoad && dashboardConfig.help.video) {
        neon.ready(function() {
            $("#videoModal").modal("show");
            $("#helpVideo").attr("autoplay", "");
        });
    }
};

var saveVisualizations = function(config) {
    var visualizations = (config.visualizations || []);
    neonDemo.constant('visualizations', visualizations);
};

var createExternalService = function(args, argsMappings) {
    var service = {
        apps: {},
        args: []
    };

    args.forEach(function(argName) {
        service.args.push({
            variable: argName,
            mappings: argsMappings[argName]
        });
    });

    return service;
};

var saveExternal = function(services) {
    neonDemo.constant('external', {
        active: Object.keys(services).length,
        services: services
    });
};

/**
 * @example of external.services
 *  {
 *      user: {
 *          apps: {
 *              App1: {
 *                  image: file_path,
 *                  url: app/{{userVariable}}
 *              }
 *          },
 *          args: [{
 *              variable: userVariable,
 *              mappings: neonUserMapping
 *          }]
 *      },
 *      bounds: {
 *          apps: {
 *              App2: {
 *                  image: file_path,
 *                  url: app/?bounds={{boundsVariable.min_lat}},{{boundsVariable.min_lon}},{{boundsVariable.max_lat}},{{boundsVariable.max_lon}}
 *              }
 *          },
 *          args: [{
 *              variable: boundsVariable,
 *              mappings: {
 *                  min_lat: neonMinLatMapping,
 *                  min_lon: neonMinLonMapping,
 *                  max_lat: neonMaxLatMapping,
 *                  max_lat: neonMaxLonMapping
 *              }
 *          }]
 *      }
 *  }
 */
var readAndSaveExternalServices = function(config, callback) {
    var saveExternalServicesAndRunCallback = function(services) {
        saveExternal(services);
        if(callback) {
            callback();
        }
    };

    if(!(config.configList && config.configList.length && config.servicesMappings && config.argsMappings)) {
        saveExternalServicesAndRunCallback({});
        return;
    }

    var services = {};
    var urlProperty = (config.fileProperties ? config.fileProperties.url : undefined) || "url";
    var nameProperty = (config.fileProperties ? config.fileProperties.name : undefined) || "name";
    var imageProperty = (config.fileProperties ? config.fileProperties.image : undefined) || "image";
    var servicesProperty = (config.fileProperties ? config.fileProperties.services : undefined) || "services";

    var readConfigCallback = function(configList) {
        if(configList.length) {
            readConfig(configList);
        } else {
            saveExternalServicesAndRunCallback(services);
        }
    };

    var readConfig = function(configList) {
        $.ajax({
            url: configList.shift(),
            success: function(json) {
                var data = _.isString(json) ? $.parseJSON(json) : json;
                Object.keys(data).forEach(function(appType) {
                    Object.keys(data[appType][servicesProperty]).forEach(function(serviceType) {
                        var neonServiceMappings = Object.keys(config.servicesMappings).filter(function(neonServiceMapping) {
                            return config.servicesMappings[neonServiceMapping] === serviceType;
                        });

                        neonServiceMappings.forEach(function(neonServiceMapping) {
                            services[neonServiceMapping] = services[neonServiceMapping] || createExternalService(serviceType.split(","), config.argsMappings[neonServiceMapping]);

                            services[neonServiceMapping].apps[data[appType][nameProperty]] = {
                                image: (config.imageDirectory || ".") + "/" + data[appType][imageProperty],
                                url: data[appType][urlProperty] + "/" + data[appType][servicesProperty][serviceType]
                            };
                        });
                    });
                });
                readConfigCallback(configList);
            },
            error: function() {
                readConfigCallback(configList);
            }
        });
    };

    readConfig(config.configList);
};

var saveLayouts = function(layouts) {
    neonDemo.constant('layouts', layouts);
};

var readLayoutFilesAndSaveLayouts = function($http, layouts, layoutFiles, callback) {
    if(layoutFiles.length) {
        var layoutFile = layoutFiles.shift();
        $http.get(layoutFile).then(function(response) {
            var layoutConfig = layoutFile.substring(layoutFile.length - 4) === "yaml" ? jsyaml.load(response.data) : response.data;
            if(layoutConfig.name && layoutConfig.layout) {
                layouts[layoutConfig.name] = layoutConfig.layout;
            }
            readLayoutFilesAndSaveLayouts($http, layouts, layoutFiles, callback);
        }, function(response) {
            readLayoutFilesAndSaveLayouts($http, layouts, layoutFiles, callback);
        });
    } else {
        saveLayouts(layouts);
        if(callback) {
            callback();
        }
    }
};

var saveDatasets = function(datasets) {
    neonDemo.value('datasets', datasets);
};

var readDatasetFilesAndSaveDatasets = function($http, datasets, datasetFiles, callback) {
    if(datasetFiles.length) {
        var datasetFile = datasetFiles.shift();
        $http.get(datasetFile).then(function(response) {
            var datasetConfig = datasetFile.substring(datasetFile.length - 4) === "yaml" ? jsyaml.load(response.data) : response.data;
            if(datasetConfig.dataset) {
                datasets.push(datasetConfig.dataset);
            }
            readDatasetFilesAndSaveDatasets($http, datasets, datasetFiles, callback);
        }, function(response) {
            readDatasetFilesAndSaveDatasets($http, datasets, datasetFiles, callback);
        });
    } else {
        saveDatasets(datasets);
        if(callback) {
            callback();
        }
    }
};

var saveNeonConfig = function($http, config) {
    saveUserAle(config);
    saveOpenCpu(config);
    saveDashboards(config);
    saveVisualizations(config);

    var files = (config.files || []);
    var layouts = (config.layouts || {});
    if(!(layouts.default)) {
        layouts.default = [];
    }
    var datasets = (config.datasets || []);

    // Read the external application services config file and create the services, then read each layout config file and add the layouts,
    // then read each dataset config file and add the datasets, then start angular.
    readAndSaveExternalServices((config.externalServices || {}), function() {
        readLayoutFilesAndSaveLayouts($http, layouts, (files.layouts || []), function() {
            readDatasetFilesAndSaveDatasets($http, datasets, (files.datasets || []), startAngular);
        });
    });
};

angular.element(document).ready(function() {
    var $http = angular.injector(['ng']).get('$http');
    $http.get("./config/config.yaml").then(function(response) {
        saveNeonConfig($http, jsyaml.load(response.data));
    }, function() {
        $http.get("./config/config.json").then(function(response) {
            saveNeonConfig($http, response.data);
        });
    });
});
<commit_msg>Neon now ignores itself in the external services configuration.<commit_after>'use strict';
/*
 * Copyright 2014 Next Century Corporation
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// Defaulting the Neon SERVER_URL to be under the neon context on the same host machine.
// Used by neon core server.  Don't delete this or you will probably break everything!
neon.SERVER_URL = "/neon";

/**
 * Utility that calls the given function in an $apply if the given $scope is not in the apply/digest phase or just calls the given function normally otherwise.
 * @param {Object} $scope The $scope of an angular directive.
 * @param {Fucntion} func The function to call.
 * @method safeApply
 */
neon.safeApply = function($scope, func) {
    if(!$scope || !func || typeof func !== "function") {
        return;
    }

    var phase = $scope.$root.$$phase;
    if(phase === "$apply" || phase === "$digest") {
        func();
    } else {
        $scope.$apply(func);
    }
};

var neonDemo = angular.module('neonDemo', [
    'neonDemo.controllers',
    'neonDemo.services',
    'neonDemo.directives',
    'neonDemo.filters',
    'gridster',
    'ngDraggable',
    'ngRoute',
    'ui.bootstrap.datetimepicker',

    'gantt',
    'gantt.tooltips',
    'gantt.tree',
    'gantt.groups'
]);

neonDemo.config(function($routeProvider, $locationProvider) {
    $routeProvider.when('/', {
        templateUrl: 'index.html',
        controller: 'neonDemoController'
    });
    $locationProvider.html5Mode({
        enabled: true,
        requireBase: false
    });
});

// AngularJS filter for reversing the order of an array.
// http://stackoverflow.com/questions/15266671/angular-ng-repeat-in-reverse
neonDemo.filter("reverse", function() {
    return function(items) {
        return items.slice().reverse();
    };
});

angular.module('neonDemo.directives', []);
angular.module('neonDemo.controllers', []);
angular.module('neonDemo.services', []);

angular.module('neonDemo.filters', [])
.filter('numberShort', function() {
    return function(number) {
        if(typeof number !== undefined) {
            var abs = Math.abs(number);
            if(abs >= Math.pow(10, 12)) {
                number = (number / Math.pow(10, 12)).toFixed(1) + "T";
            } else if(abs < Math.pow(10, 12) && abs >= Math.pow(10, 9)) {
                number = (number / Math.pow(10, 9)).toFixed(1) + "B";
            } else if(abs < Math.pow(10, 9) && abs >= Math.pow(10, 6)) {
                number = (number / Math.pow(10, 6)).toFixed(1) + "M";
            } else if(abs < Math.pow(10, 6) && abs >= Math.pow(10, 3)) {
                number = (number / Math.pow(10, 3)).toFixed(1) + "K";
            } else {
                number = Math.round(number * 100) / 100;
            }
        }
        return number;
    };
});

var XDATA = {};

// Start angular once all of the configuration variables have been read from the JSON file(s) and set in the module.
var startAngular = function() {
    angular.bootstrap(document, ['neonDemo']);
};

var saveUserAle = function(config) {
    // Configure the user-ale logger.
    var aleConfig = (config.user_ale || {
        loggingUrl: "http://192.168.1.100",
        toolName: "Neon Dashboard",
        elementGroups: [
            "top",
            "map_group",
            "table_group",
            "chart_group",
            "query_group",
            "graph_group"
        ],
        workerUrl: "lib/user-ale/js/userale-worker.js",
        debug: false,
        sendLogs: false
    });
    XDATA.userALE = new userale(aleConfig);
    XDATA.userALE.register();
};

var saveOpenCpu = function(config) {
    var opencpuConfig = (config.opencpu || {
        enableOpenCpu: false
    });
    if(opencpuConfig.enableOpenCpu) {
        ocpu.enableLogging = opencpuConfig.enableLogging;
        ocpu.useAlerts = opencpuConfig.useAlerts;
        ocpu.seturl(opencpuConfig.url);
        ocpu.connected = true;
    }
    neonDemo.constant('opencpu', opencpuConfig);
};

var saveDashboards = function(config) {
    var helpConfig = (config.help || {
        guide: undefined,
        video: undefined
    });
    var dashboardConfig = config.dashboard || {
        hideNavbarItems: false,
        hideAddVisualizationsButton: false,
        hideAdvancedOptions: false,
        hideErrorNotifications: false,
        hideHeader: false,
        showImport: false,
        showExport: true
    };
    dashboardConfig.gridsterColumns = dashboardConfig.gridsterColumns || 8;
    dashboardConfig.gridsterMargins = dashboardConfig.gridsterMargins || 10;
    // Most visualizations should have a minimum size of about 300px square to have space for their UI elements.
    // TODO Use the browser width to determine the minimum size for visualizations and update it on browser resize.
    dashboardConfig.gridsterDefaultMinSizeX = Math.floor(dashboardConfig.gridsterColumns / 4);
    dashboardConfig.gridsterDefaultMinSizeY = Math.floor(dashboardConfig.gridsterColumns / 6);
    dashboardConfig.help = helpConfig;
    dashboardConfig.showExport = (dashboardConfig.showExport === undefined || dashboardConfig.showExport) ? true : false;
    neonDemo.constant('config', dashboardConfig);

    // Keep the autoplay video code here because when it was in the neonDemoController the dashboard would start playing the video whenever the dataset was changed.
    if(dashboardConfig.showVideoOnLoad && dashboardConfig.help.video) {
        neon.ready(function() {
            $("#videoModal").modal("show");
            $("#helpVideo").attr("autoplay", "");
        });
    }
};

var saveVisualizations = function(config) {
    var visualizations = (config.visualizations || []);
    neonDemo.constant('visualizations', visualizations);
};

var createExternalService = function(args, argsMappings) {
    var service = {
        apps: {},
        args: []
    };

    args.forEach(function(argName) {
        service.args.push({
            variable: argName,
            mappings: argsMappings[argName]
        });
    });

    return service;
};

var saveExternal = function(services) {
    neonDemo.constant('external', {
        active: Object.keys(services).length,
        services: services
    });
};

/**
 * @example of external.services
 *  {
 *      user: {
 *          apps: {
 *              App1: {
 *                  image: file_path,
 *                  url: app/{{userVariable}}
 *              }
 *          },
 *          args: [{
 *              variable: userVariable,
 *              mappings: neonUserMapping
 *          }]
 *      },
 *      bounds: {
 *          apps: {
 *              App2: {
 *                  image: file_path,
 *                  url: app/?bounds={{boundsVariable.min_lat}},{{boundsVariable.min_lon}},{{boundsVariable.max_lat}},{{boundsVariable.max_lon}}
 *              }
 *          },
 *          args: [{
 *              variable: boundsVariable,
 *              mappings: {
 *                  min_lat: neonMinLatMapping,
 *                  min_lon: neonMinLonMapping,
 *                  max_lat: neonMaxLatMapping,
 *                  max_lat: neonMaxLonMapping
 *              }
 *          }]
 *      }
 *  }
 */
var readAndSaveExternalServices = function(config, callback) {
    var saveExternalServicesAndRunCallback = function(services) {
        saveExternal(services);
        if(callback) {
            callback();
        }
    };

    if(!(config.configList && config.configList.length && config.servicesMappings && config.argsMappings)) {
        saveExternalServicesAndRunCallback({});
        return;
    }

    var services = {};
    var urlProperty = (config.fileProperties ? config.fileProperties.url : undefined) || "url";
    var nameProperty = (config.fileProperties ? config.fileProperties.name : undefined) || "name";
    var imageProperty = (config.fileProperties ? config.fileProperties.image : undefined) || "image";
    var servicesProperty = (config.fileProperties ? config.fileProperties.services : undefined) || "services";

    var readConfigCallback = function(configList) {
        if(configList.length) {
            readConfig(configList);
        } else {
            saveExternalServicesAndRunCallback(services);
        }
    };

    var readConfig = function(configList) {
        $.ajax({
            url: configList.shift(),
            success: function(json) {
                var data = _.isString(json) ? $.parseJSON(json) : json;
                Object.keys(data).forEach(function(appType) {
                    Object.keys(data[appType][servicesProperty]).forEach(function(serviceType) {
                        var neonServiceMappings = Object.keys(config.servicesMappings).filter(function(neonServiceMapping) {
                            return config.servicesMappings[neonServiceMapping] === serviceType;
                        });

                        var appName = data[appType][nameProperty];

                        // Ignore linking to the Neon Dashboard itself.
                        if(!(appName.toLowerCase().indexOf("neon") === 0)) {
                            neonServiceMappings.forEach(function(neonServiceMapping) {
                                services[neonServiceMapping] = services[neonServiceMapping] || createExternalService(serviceType.split(","), config.argsMappings[neonServiceMapping]);

                                services[neonServiceMapping].apps[appName] = {
                                    image: (config.imageDirectory || ".") + "/" + data[appType][imageProperty],
                                    url: data[appType][urlProperty] + "/" + data[appType][servicesProperty][serviceType]
                                };
                            });
                        }
                    });
                });
                readConfigCallback(configList);
            },
            error: function() {
                readConfigCallback(configList);
            }
        });
    };

    readConfig(config.configList);
};

var saveLayouts = function(layouts) {
    neonDemo.constant('layouts', layouts);
};

var readLayoutFilesAndSaveLayouts = function($http, layouts, layoutFiles, callback) {
    if(layoutFiles.length) {
        var layoutFile = layoutFiles.shift();
        $http.get(layoutFile).then(function(response) {
            var layoutConfig = layoutFile.substring(layoutFile.length - 4) === "yaml" ? jsyaml.load(response.data) : response.data;
            if(layoutConfig.name && layoutConfig.layout) {
                layouts[layoutConfig.name] = layoutConfig.layout;
            }
            readLayoutFilesAndSaveLayouts($http, layouts, layoutFiles, callback);
        }, function(response) {
            readLayoutFilesAndSaveLayouts($http, layouts, layoutFiles, callback);
        });
    } else {
        saveLayouts(layouts);
        if(callback) {
            callback();
        }
    }
};

var saveDatasets = function(datasets) {
    neonDemo.value('datasets', datasets);
};

var readDatasetFilesAndSaveDatasets = function($http, datasets, datasetFiles, callback) {
    if(datasetFiles.length) {
        var datasetFile = datasetFiles.shift();
        $http.get(datasetFile).then(function(response) {
            var datasetConfig = datasetFile.substring(datasetFile.length - 4) === "yaml" ? jsyaml.load(response.data) : response.data;
            if(datasetConfig.dataset) {
                datasets.push(datasetConfig.dataset);
            }
            readDatasetFilesAndSaveDatasets($http, datasets, datasetFiles, callback);
        }, function(response) {
            readDatasetFilesAndSaveDatasets($http, datasets, datasetFiles, callback);
        });
    } else {
        saveDatasets(datasets);
        if(callback) {
            callback();
        }
    }
};

var saveNeonConfig = function($http, config) {
    saveUserAle(config);
    saveOpenCpu(config);
    saveDashboards(config);
    saveVisualizations(config);

    var files = (config.files || []);
    var layouts = (config.layouts || {});
    if(!(layouts.default)) {
        layouts.default = [];
    }
    var datasets = (config.datasets || []);

    // Read the external application services config file and create the services, then read each layout config file and add the layouts,
    // then read each dataset config file and add the datasets, then start angular.
    readAndSaveExternalServices((config.externalServices || {}), function() {
        readLayoutFilesAndSaveLayouts($http, layouts, (files.layouts || []), function() {
            readDatasetFilesAndSaveDatasets($http, datasets, (files.datasets || []), startAngular);
        });
    });
};

angular.element(document).ready(function() {
    var $http = angular.injector(['ng']).get('$http');
    $http.get("./config/config.yaml").then(function(response) {
        saveNeonConfig($http, jsyaml.load(response.data));
    }, function() {
        $http.get("./config/config.json").then(function(response) {
            saveNeonConfig($http, response.data);
        });
    });
});
<|endoftext|>