public static void SetPlanetarySettlementData(StarSystem system, JObject response)
        {
            if (response["stations"] is JArray)
            {
                foreach (JObject Station in response["stations"])
                {
                    if ((bool)Station["has_docking"] is false)
                    {
                        Station settlement = new Station
                        {
                            name       = (string)Station["name"],
                            EDDBID     = (long)Station["id"],
                            systemname = system.name,
                            hasdocking = false,
                            Model      = StationModel.FromName((string)Station["type"]) ?? StationModel.None,
                            Economies  = new List <Economy> {
                                Economy.FromName((string)Station["primary_economy"]), Economy.None
                            },
                            Faction = new Faction
                            {
                                name         = (string)Station["controlling_faction"],
                                Allegiance   = Superpower.FromName((string)Station["allegiance"]) ?? Superpower.None,
                                Government   = Government.FromName((string)Station["government"]) ?? Government.None,
                                FactionState = FactionState.FromName((string)Station["state"]) ?? FactionState.None
                            },
                            distancefromstar = (long?)Station["distance_to_star"],
                            updatedat        = (long?)Station["updated_at"]
                        };

                        system.stations.Add(settlement);
                    }
                }
            }
        }
Exemple #2
0
        public void TestGovernmentKnownName()
        {
            Government govt = Government.FromName("Anarchy");

            Assert.AreEqual("Anarchy", govt.basename);
            Assert.AreEqual("Anarchy", govt.invariantName);
        }
Exemple #3
0
        private static StarSystem ParseStarMapSystem(JObject response, string system)
        {
            StarSystem starSystem = new StarSystem
            {
                name          = (string)response["name"],
                systemAddress = (long?)response["id64"],
                EDSMID        = (long?)response["id"]
            };

            if (response["coords"] is JObject)
            {
                var coords = response["coords"].ToObject <Dictionary <string, decimal?> >();
                starSystem.x = coords["x"];
                starSystem.y = coords["y"];
                starSystem.z = coords["z"];
            }

            if ((bool?)response["requirePermit"] is true)
            {
                starSystem.requirespermit = true;
                starSystem.permitname     = (string)response["permitName"];
            }

            if (response["information"] is JObject information)
            {
                starSystem.Reserve    = ReserveLevel.FromName((string)information["reserve"]) ?? ReserveLevel.None;
                starSystem.population = (long?)information["population"] ?? 0;

                // Populated system data
                if (starSystem.population > 0)
                {
                    Faction controllingFaction = new Faction
                    {
                        name       = (string)information["faction"],
                        Allegiance = Superpower.FromName((string)information["allegiance"]) ?? Superpower.None,
                        Government = Government.FromName((string)information["government"]) ?? Government.None,
                    };
                    controllingFaction.presences.Add(new FactionPresence()
                    {
                        systemName   = starSystem.name,
                        FactionState = FactionState.FromName((string)information["factionState"]) ?? FactionState.None,
                    });
                    starSystem.Faction = controllingFaction;

                    starSystem.securityLevel = SecurityLevel.FromName((string)information["security"]) ?? SecurityLevel.None;
                    starSystem.Economies     = new List <Economy>()
                    {
                        Economy.FromName((string)information["economy"]) ?? Economy.None,
                        Economy.FromName((string)information["secondEconomy"]) ?? Economy.None
                    };
                }
            }

            starSystem.lastupdated = DateTime.UtcNow;
            return(starSystem);
        }
Exemple #4
0
        private static StarSystem ParseEddbSystem(object response)
        {
            JObject    systemJson = ((JObject)response);
            StarSystem StarSystem = new StarSystem {
                name = (string)systemJson["name"]
            };

            if ((bool?)systemJson["is_populated"] != null)
            {
                // We have real data so populate the rest of the data

                // General data
                StarSystem.EDDBID  = (long?)systemJson["id"];
                StarSystem.EDSMID  = (long?)systemJson["edsm_id"];
                StarSystem.x       = (decimal?)systemJson["x"];
                StarSystem.y       = (decimal?)systemJson["y"];
                StarSystem.z       = (decimal?)systemJson["z"];
                StarSystem.Reserve = ReserveLevel.FromName((string)systemJson["reserve_type"]);

                // Populated system data
                StarSystem.population = (long?)systemJson["population"] == null ? 0 : (long?)systemJson["population"];
                // EDDB uses invariant / English localized economies
                StarSystem.Economies[0] = Economy.FromName((string)systemJson["primary_economy"]);
                // At present, EDDB does not provide any information about secondary economies.
                StarSystem.securityLevel = SecurityLevel.FromName((string)systemJson["security"]);

                // Controlling faction data
                if ((string)systemJson["controlling_minor_faction"] != null)
                {
                    Faction controllingFaction = new Faction()
                    {
                        EDDBID       = (long?)systemJson["controlling_minor_faction_id"],
                        name         = (string)systemJson["controlling_minor_faction"],
                        Government   = Government.FromName((string)systemJson["government"]),
                        Allegiance   = Superpower.FromName((string)systemJson["allegiance"]),
                        FactionState = FactionState.FromName((string)systemJson["state"])
                    };
                    StarSystem.Faction = controllingFaction;
                }

                // Powerplay details
                StarSystem.power      = (string)systemJson["power"] == "None" ? null : (string)systemJson["power"];
                StarSystem.powerstate = (string)systemJson["power_state"];

                StarSystem.updatedat = Dates.fromDateTimeStringToSeconds((string)systemJson["updated_at"]);
            }

            StarSystem.lastupdated = DateTime.UtcNow;

            return(StarSystem);
        }
Exemple #5
0
        private static Faction ParseStarMapFaction(JObject faction)
        {
            Faction Faction = new Faction
            {
                name         = (string)faction["name"],
                EDSMID       = (long?)faction["id"],
                Allegiance   = Superpower.FromName((string)faction["allegiance"]),
                Government   = Government.FromName((string)faction["government"]),
                isplayer     = (bool)faction["isPlayer"],
                influence    = (decimal?)faction["influence"] * 100, // Convert from a 0-1 range to a percentage
                FactionState = FactionState.FromName((string)faction["state"]),
                updatedAt    = (DateTime)Dates.fromTimestamp((long?)faction["lastUpdate"])
            };

            return(Faction);
        }
Exemple #6
0
        // Though not necessary at this time, it is possible to implement methods that query the data source
        // based on multiple criteria (e.g. state, government, etc.) by adding multiple criteria to the queryList.

        private static Faction ParseEddbFaction(object response)
        {
            JObject factionJson = ((JObject)response);
            Faction faction     = new Faction
            {
                EDDBID           = (long)factionJson["id"],
                name             = (string)factionJson["name"],
                updatedAt        = (DateTime)factionJson["updated_at"],
                Government       = Government.FromName((string)factionJson["government"]),
                Allegiance       = Superpower.FromName((string)factionJson["allegiance"]),
                FactionState     = FactionState.FromName((string)factionJson["state"]),
                homeSystemEddbId = (long?)factionJson["home_system_id"],
                isplayer         = (bool)factionJson["is_player_faction"]
            };

            return(faction);
        }
Exemple #7
0
        public Faction ParseFaction(object response)
        {
            try
            {
                IDictionary <string, object> factionJson = Deserializtion.DeserializeData(response.ToString());
                Faction faction = new Faction
                {
                    EDDBID     = (long)factionJson["eddb_id"],
                    name       = (string)factionJson["name"],
                    updatedAt  = (DateTime)factionJson["updated_at"],
                    Government = Government.FromName((string)factionJson["government"]),
                    Allegiance = Superpower.FromName((string)factionJson["allegiance"]),
                };

                foreach (object presence in (List <object>)factionJson["faction_presence"])
                {
                    IDictionary <string, object> presenceJson = (IDictionary <string, object>)presence;
                    FactionPresence factionPresence           = new FactionPresence()
                    {
                        systemName   = JsonParsing.getString(presenceJson, "system_name"),
                        influence    = (JsonParsing.getOptionalDecimal(presenceJson, "influence") ?? 0) * 100, // Convert from a 0-1 range to a percentage
                        FactionState = FactionState.FromEDName(JsonParsing.getString(presenceJson, "state")) ?? FactionState.None,
                    };

                    // These properties may not be present in the json, so we pass them after initializing our FactionPresence object.
                    factionPresence.Happiness = Happiness.FromEDName(JsonParsing.getString(presenceJson, "happiness")) ?? Happiness.None;
                    presenceJson.TryGetValue("updated_at", out object updatedVal);
                    factionPresence.updatedAt = (DateTime?)updatedVal ?? DateTime.MinValue;

                    // Active states
                    presenceJson.TryGetValue("active_states", out object activeStatesVal);
                    if (activeStatesVal != null)
                    {
                        var activeStatesList = (List <object>)activeStatesVal;
                        foreach (IDictionary <string, object> activeState in activeStatesList)
                        {
                            factionPresence.ActiveStates.Add(FactionState.FromEDName(JsonParsing.getString(activeState, "state")) ?? FactionState.None);
                        }
                    }

                    // Pending states
                    presenceJson.TryGetValue("pending_states", out object pendingStatesVal);
                    if (pendingStatesVal != null)
                    {
                        var pendingStatesList = (List <object>)pendingStatesVal;
                        foreach (IDictionary <string, object> pendingState in pendingStatesList)
                        {
                            FactionTrendingState pTrendingState = new FactionTrendingState(
                                FactionState.FromEDName(JsonParsing.getString(pendingState, "state")) ?? FactionState.None,
                                JsonParsing.getInt(pendingState, "trend")
                                );
                            factionPresence.PendingStates.Add(pTrendingState);
                        }
                    }

                    // Recovering states
                    presenceJson.TryGetValue("recovering_states", out object recoveringStatesVal);
                    if (recoveringStatesVal != null)
                    {
                        var recoveringStatesList = (List <object>)recoveringStatesVal;
                        foreach (IDictionary <string, object> recoveringState in recoveringStatesList)
                        {
                            FactionTrendingState rTrendingState = new FactionTrendingState(
                                FactionState.FromEDName(JsonParsing.getString(recoveringState, "state")) ?? FactionState.None,
                                JsonParsing.getInt(recoveringState, "trend")
                                );
                            factionPresence.RecoveringStates.Add(rTrendingState);
                        }
                    }

                    faction.presences.Add(factionPresence);
                }

                return(faction);
            }
            catch (Exception ex)
            {
                Dictionary <string, object> data = new Dictionary <string, object>()
                {
                    { "input", response },
                    { "exception", ex }
                };
                Logging.Error("Failed to parse BGS faction data.", data);
                return(null);
            }
        }
Exemple #8
0
        private static Station ParseStarMapStation(JObject station, string system)
        {
            Station Station = new Station
            {
                systemname       = system,
                name             = (string)station["name"],
                marketId         = (long?)station["marketId"],
                EDSMID           = (long?)station["id"],
                Model            = StationModel.FromName((string)station["type"]) ?? StationModel.None,
                distancefromstar = (decimal?)station["distanceToArrival"], // Light seconds
            };

            var faction = station["controllingFaction"]?.ToObject <Dictionary <string, object> >();

            Station.Faction = new Faction()
            {
                name       = (string)faction["name"],
                EDSMID     = (long?)faction["id"],
                Allegiance = Superpower.FromName((string)station["allegiance"]) ?? Superpower.None,
                Government = Government.FromName((string)station["government"]) ?? Government.None,
            };

            List <Economy> Economies = new List <Economy>()
            {
                Economy.FromName((string)station["economy"]) ?? Economy.None,
                Economy.FromName((string)station["secondEconomy"]) ?? Economy.None
            };

            Station.Economies = Economies;

            List <StationService> stationServices = new List <StationService>();

            if ((bool?)station["haveMarket"] is true)
            {
                stationServices.Add(StationService.FromEDName("Commodities"));
            }
            ;
            if ((bool?)station["haveShipyard"] is true)
            {
                stationServices.Add(StationService.FromEDName("Shipyard"));
            }
            ;
            if ((bool?)station["haveOutfitting"] is true)
            {
                stationServices.Add(StationService.FromEDName("Outfitting"));
            }
            ;
            var services = station["otherServices"].ToObject <List <string> >();

            foreach (string service in services)
            {
                stationServices.Add(StationService.FromName(service));
            }
            ;
            // Add always available services for dockable stations
            stationServices.Add(StationService.FromEDName("Dock"));
            stationServices.Add(StationService.FromEDName("AutoDock"));
            stationServices.Add(StationService.FromEDName("Exploration"));
            stationServices.Add(StationService.FromEDName("Workshop"));
            stationServices.Add(StationService.FromEDName("FlightController"));
            stationServices.Add(StationService.FromEDName("StationOperations"));
            stationServices.Add(StationService.FromEDName("Powerplay"));
            Station.stationServices = stationServices;

            var    updateTimes = station["updateTime"].ToObject <Dictionary <string, object> >();
            string datetime;

            datetime = JsonParsing.getString(updateTimes, "information");
            long?infoLastUpdated = Dates.fromDateTimeStringToSeconds(datetime);

            datetime = JsonParsing.getString(updateTimes, "market");
            long?marketLastUpdated = Dates.fromDateTimeStringToSeconds(datetime);

            datetime = JsonParsing.getString(updateTimes, "shipyard");
            long?shipyardLastUpdated = Dates.fromDateTimeStringToSeconds(datetime);

            datetime = JsonParsing.getString(updateTimes, "outfitting");
            long?        outfittingLastUpdated = Dates.fromDateTimeStringToSeconds(datetime);
            List <long?> updatedAt             = new List <long?>()
            {
                infoLastUpdated, marketLastUpdated, shipyardLastUpdated, outfittingLastUpdated
            };

            Station.updatedat            = updatedAt.Max();
            Station.outfittingupdatedat  = outfittingLastUpdated;
            Station.commoditiesupdatedat = marketLastUpdated;
            Station.shipyardupdatedat    = shipyardLastUpdated;

            return(Station);
        }
Exemple #9
0
        private void handleSystemDelta(JObject json)
        {
            // Fetch guaranteed information
            string  systemname = (string)json["systemname"];
            decimal x          = (decimal)(double)json["x"];
            decimal y          = (decimal)(double)json["y"];
            decimal z          = (decimal)(double)json["z"];

            // Fetch delta information
            string oldfaction = (string)json["oldfaction"];
            string newfaction = (string)json["newfaction"];

            FactionState oldstate = FactionState.FromName((string)json["oldstate"]);
            FactionState newstate = FactionState.FromName((string)json["newstate"]);

            string oldallegiance = (string)json["oldallegiance"];
            string newallegiance = (string)json["newallegiance"];

            string oldgovernment = (string)json["oldgovernment"];
            string newgovernment = (string)json["newgovernment"];

            string oldeconomy = (string)json["oldeconomy"];
            string neweconomy = (string)json["neweconomy"];

            // EDDP does not report currently changes to secondary economies.

            string oldsecurity = (string)json["oldsecurity"];
            string newsecurity = (string)json["newsecurity"];

            // See if this matches our parameters
            string matchname = match(systemname, null, x, y, z, oldfaction, newfaction, oldstate, newstate);

            if (matchname != null)
            {
                // Fetch the system from our local repository (but don't create it if it doesn't exist)
                StarSystem system = StarSystemSqLiteRepository.Instance.GetStarSystem(systemname);
                if (system != null)
                {
                    // Update our local copy of the system
                    if (system.Faction is null)
                    {
                        system.Faction = new Faction();
                    }
                    if (newfaction != null)
                    {
                        system.Faction.name = newfaction;
                    }
                    if (newallegiance != null)
                    {
                        system.Faction.Allegiance = Superpower.FromName(newallegiance);
                    }
                    if (newgovernment != null)
                    {
                        system.Faction.Government = Government.FromName(newgovernment);
                    }
                    if (newstate != null)
                    {
                        system.Faction.FactionState = newstate;
                    }
                    if (newsecurity != null)
                    {
                        system.securityLevel = SecurityLevel.FromName(newsecurity);
                    }
                    if (neweconomy != null)
                    {
                        // EDDP uses invariant English economy names and does not report changes to secondary economies.
                        system.Economies = new List <Economy>()
                        {
                            Economy.FromName(neweconomy), system.Economies[1]
                        };
                    }
                    system.lastupdated = DateTime.UtcNow;
                    StarSystemSqLiteRepository.Instance.SaveStarSystem(system);
                }

                // Send an appropriate event
                Event @event = null;
                if (newfaction != null)
                {
                    @event = new SystemFactionChangedEvent(DateTime.UtcNow, matchname, systemname, oldfaction, newfaction);
                }
                else if (newstate != null)
                {
                    @event = new SystemStateChangedEvent(DateTime.UtcNow, matchname, systemname, oldstate, newstate);
                }
                if (@event != null)
                {
                    EDDI.Instance.enqueueEvent(@event);
                }
            }
        }
Exemple #10
0
        private static Faction ParseStarMapFaction(JObject faction)
        {
            Faction Faction = new Faction
            {
                name         = (string)faction["name"],
                EDSMID       = (long?)faction["id"],
                Allegiance   = Superpower.FromName((string)faction["allegiance"]) ?? Superpower.None,
                Government   = Government.FromName((string)faction["government"]) ?? Government.None,
                isplayer     = (bool)faction["isPlayer"],
                influence    = (decimal?)faction["influence"] * 100, // Convert from a 0-1 range to a percentage
                FactionState = FactionState.FromName((string)faction["state"]) ?? FactionState.None,
                updatedAt    = (DateTime)Dates.fromTimestamp((long?)faction["lastUpdate"])
            };

            IDictionary <string, object> factionDetail = faction.ToObject <IDictionary <string, object> >();

            // Active states
            Faction.ActiveStates = new List <FactionState>();
            factionDetail.TryGetValue("ActiveStates", out object activeStatesVal);
            if (activeStatesVal != null)
            {
                var activeStatesList = (List <object>)activeStatesVal;
                foreach (IDictionary <string, object> activeState in activeStatesList)
                {
                    Faction.ActiveStates.Add(FactionState.FromEDName(JsonParsing.getString(activeState, "State") ?? "None"));
                }
            }

            // Pending states
            Faction.PendingStates = new List <FactionTrendingState>();
            factionDetail.TryGetValue("PendingStates", out object pendingStatesVal);
            if (pendingStatesVal != null)
            {
                var pendingStatesList = (List <object>)pendingStatesVal;
                foreach (IDictionary <string, object> pendingState in pendingStatesList)
                {
                    FactionTrendingState pTrendingState = new FactionTrendingState(
                        FactionState.FromEDName(JsonParsing.getString(pendingState, "State") ?? "None"),
                        JsonParsing.getInt(pendingState, "Trend")
                        );
                    Faction.PendingStates.Add(pTrendingState);
                }
            }

            // Recovering states
            Faction.RecoveringStates = new List <FactionTrendingState>();
            factionDetail.TryGetValue("RecoveringStates", out object recoveringStatesVal);
            if (recoveringStatesVal != null)
            {
                var recoveringStatesList = (List <object>)recoveringStatesVal;
                foreach (IDictionary <string, object> recoveringState in recoveringStatesList)
                {
                    FactionTrendingState rTrendingState = new FactionTrendingState(
                        FactionState.FromEDName(JsonParsing.getString(recoveringState, "State") ?? "None"),
                        JsonParsing.getInt(recoveringState, "Trend")
                        );
                    Faction.RecoveringStates.Add(rTrendingState);
                }
            }

            return(Faction);
        }
Exemple #11
0
        private Station ParseStarMapStation(JObject station, string system)
        {
            try
            {
                Station Station = new Station
                {
                    systemname       = system,
                    name             = (string)station["name"],
                    marketId         = (long?)station["marketId"],
                    EDSMID           = (long?)station["id"],
                    Model            = StationModel.FromName((string)station["type"]) ?? StationModel.None,
                    distancefromstar = (decimal?)station["distanceToArrival"], // Light seconds
                };

                var faction = station["controllingFaction"]?.ToObject <Dictionary <string, object> >();
                Station.Faction = new Faction()
                {
                    name       = (string)faction?["name"] ?? string.Empty,
                    EDSMID     = (long?)faction?["id"],
                    Allegiance = Superpower.FromName((string)station["allegiance"]) ?? Superpower.None,
                    Government = Government.FromName((string)station["government"]) ?? Government.None,
                };

                List <EconomyShare> economyShares = new List <EconomyShare>()
                {
                    { new EconomyShare(Economy.FromName((string)station["economy"]) ?? Economy.None, 0) },
                    { new EconomyShare(Economy.FromName((string)station["secondEconomy"]) ?? Economy.None, 0) }
                };
                Station.economyShares = economyShares;

                List <StationService> stationServices = new List <StationService>();
                if ((bool?)station["haveMarket"] is true)
                {
                    stationServices.Add(StationService.FromEDName("Commodities"));
                }
                ;
                if ((bool?)station["haveShipyard"] is true)
                {
                    stationServices.Add(StationService.FromEDName("Shipyard"));
                }
                ;
                if ((bool?)station["haveOutfitting"] is true)
                {
                    stationServices.Add(StationService.FromEDName("Outfitting"));
                }
                ;
                var services = station["otherServices"].ToObject <List <string> >();
                foreach (string service in services)
                {
                    stationServices.Add(StationService.FromName(service));
                }
                ;
                // Add always available services for dockable stations
                stationServices.Add(StationService.FromEDName("Dock"));
                stationServices.Add(StationService.FromEDName("AutoDock"));
                stationServices.Add(StationService.FromEDName("Exploration"));
                stationServices.Add(StationService.FromEDName("Workshop"));
                stationServices.Add(StationService.FromEDName("FlightController"));
                stationServices.Add(StationService.FromEDName("StationOperations"));
                stationServices.Add(StationService.FromEDName("Powerplay"));
                Station.stationServices = stationServices;

                var    updateTimes = station["updateTime"].ToObject <Dictionary <string, object> >();
                string datetime;
                datetime = JsonParsing.getString(updateTimes, "information");
                long?infoLastUpdated = Dates.fromDateTimeStringToSeconds(datetime);
                datetime = JsonParsing.getString(updateTimes, "market");
                long?marketLastUpdated = Dates.fromDateTimeStringToSeconds(datetime);
                datetime = JsonParsing.getString(updateTimes, "shipyard");
                long?shipyardLastUpdated = Dates.fromDateTimeStringToSeconds(datetime);
                datetime = JsonParsing.getString(updateTimes, "outfitting");
                long?        outfittingLastUpdated = Dates.fromDateTimeStringToSeconds(datetime);
                List <long?> updatedAt             = new List <long?>()
                {
                    infoLastUpdated, marketLastUpdated, shipyardLastUpdated, outfittingLastUpdated
                };
                Station.updatedat            = updatedAt.Max();
                Station.outfittingupdatedat  = outfittingLastUpdated;
                Station.commoditiesupdatedat = marketLastUpdated;
                Station.shipyardupdatedat    = shipyardLastUpdated;

                return(Station);
            }
            catch (Exception ex)
            {
                Dictionary <string, object> data = new Dictionary <string, object>
                {
                    { "station", JsonConvert.SerializeObject(station) },
                    { "exception", ex.Message },
                    { "stacktrace", ex.StackTrace }
                };
                Logging.Error("Error parsing EDSM station result.", data);
            }
            return(null);
        }
Exemple #12
0
        /// <summary>
        /// Build a store from a list of variables
        /// </summary>
        private BuiltinStore buildStore(Dictionary <string, Cottle.Value> vars)
        {
            BuiltinStore store = new BuiltinStore();

            // TODO fetch this from configuration
            bool useICAO = SpeechServiceConfiguration.FromFile().EnableIcao;

            // Function to call another script
            store["F"] = new NativeFunction((values) =>
            {
                return(new ScriptResolver(scripts).resolve(values[0].AsString, store, false));
            }, 1);

            // Translation functions
            store["P"] = new NativeFunction((values) =>
            {
                string val         = values[0].AsString;
                string translation = val;
                if (translation == val)
                {
                    translation = Translations.Body(val, useICAO);
                }
                if (translation == val)
                {
                    translation = Translations.StarSystem(val, useICAO);
                }
                if (translation == val)
                {
                    translation = Translations.Faction(val);
                }
                if (translation == val)
                {
                    translation = Translations.Power(val);
                }
                if (translation == val)
                {
                    Ship ship = ShipDefinitions.FromModel(val);
                    if (ship != null && ship.EDID > 0)
                    {
                        translation = ship.SpokenModel();
                    }
                }
                if (translation == val)
                {
                    Ship ship = ShipDefinitions.FromEDModel(val);
                    if (ship != null && ship.EDID > 0)
                    {
                        translation = ship.SpokenModel();
                    }
                }
                return(translation);
            }, 1);

            // Boolean constants
            store["true"]  = true;
            store["false"] = false;

            // Helper functions
            store["OneOf"] = new NativeFunction((values) =>
            {
                return(new ScriptResolver(scripts).resolveScript(values[random.Next(values.Count)].AsString, store, false));
            });

            store["Occasionally"] = new NativeFunction((values) =>
            {
                if (random.Next((int)values[0].AsNumber) == 0)
                {
                    return(new ScriptResolver(scripts).resolveScript(values[1].AsString, store, false));
                }
                else
                {
                    return("");
                }
            }, 2);

            store["Humanise"] = new NativeFunction((values) =>
            {
                return(Translations.Humanize(values[0].AsNumber));
            }, 1);

            store["List"] = new NativeFunction((values) =>
            {
                string output             = String.Empty;
                const string localisedAnd = "and";
                if (values.Count == 1)
                {
                    foreach (KeyValuePair <Cottle.Value, Cottle.Value> value in values[0].Fields)
                    {
                        string valueString = value.Value.ToString();
                        if (value.Key == 0)
                        {
                            output = valueString;
                        }
                        else if (value.Key < (values[0].Fields.Count - 1))
                        {
                            output = $"{output}, {valueString}";
                        }
                        else
                        {
                            output = $"{output}, {localisedAnd} {valueString}";
                        }
                    }
                }
                return(output);
            }, 1);

            store["Pause"] = new NativeFunction((values) =>
            {
                return(@"<break time=""" + values[0].AsNumber + @"ms"" />");
            }, 1);

            store["Play"] = new NativeFunction((values) =>
            {
                return(@"<audio src=""" + values[0].AsString + @""" />");
            }, 1);

            store["Spacialise"] = new NativeFunction((values) =>
            {
                string Entree = values[0].AsString;
                if (Entree == "")
                {
                    return("");
                }
                string Sortie      = "";
                string UpperSortie = "";
                foreach (char c in Entree)
                {
                    Sortie = Sortie + c + " ";
                }
                UpperSortie = Sortie.ToUpper();
                return(UpperSortie);
            }, 1);

            store["Emphasize"] = new NativeFunction((values) =>
            {
                if (values.Count == 1)
                {
                    return(@"<emphasis level =""strong"">" + values[0].AsString + @"</emphasis>");
                }
                else if (values.Count == 2)
                {
                    return(@"<emphasis level =""" + values[1].AsString + @""">" + values[0].AsString + @"</emphasis>");
                }
                else
                {
                    return("The Emphasize function is used improperly. Please review the documentation for correct usage.");
                }
            }, 1, 2);

            store["SpeechPitch"] = new NativeFunction((values) =>
            {
                string text  = values[0].AsString;
                string pitch = "default";
                if (values.Count == 1 || string.IsNullOrEmpty(values[1].AsString))
                {
                    return(text);
                }
                else if (values.Count == 2)
                {
                    pitch = values[1].AsString;
                    return(@"<prosody pitch=""" + pitch + @""">" + text + "</prosody>");
                }
                else
                {
                    return("The SpeechPitch function is used improperly. Please review the documentation for correct usage.");
                }
            }, 1, 2);

            store["SpeechRate"] = new NativeFunction((values) =>
            {
                string text = values[0].AsString;
                string rate = "default";
                if (values.Count == 1 || string.IsNullOrEmpty(values[1].AsString))
                {
                    return(text);
                }
                else if (values.Count == 2)
                {
                    rate = values[1].AsString;
                    return(@"<prosody rate=""" + rate + @""">" + text + "</prosody>");
                }
                else
                {
                    return("The SpeechRate function is used improperly. Please review the documentation for correct usage.");
                }
            }, 1, 2);

            store["SpeechVolume"] = new NativeFunction((values) =>
            {
                string text   = values[0].AsString;
                string volume = "default";
                if (values.Count == 1 || string.IsNullOrEmpty(values[1].AsString))
                {
                    return(text);
                }
                else if (values.Count == 2)
                {
                    volume = values[1].AsString;
                    return(@"<prosody volume=""" + volume + @""">" + text + "</prosody>");
                }
                else
                {
                    return("The SpeechVolume function is used improperly. Please review the documentation for correct usage.");
                }
            }, 1, 2);

            store["Transmit"] = new NativeFunction((values) =>
            {
                string text = values[0].AsString;
                if (values.Count == 1 || string.IsNullOrEmpty(values[1].AsString))
                {
                    return(@"<transmit>" + values[0].AsString + "</transmit>"); // This is a synthetic tag used to signal to the speech service that radio effects should be enabled.
                }
                else
                {
                    return("The Transmit function is used improperly. Please review the documentation for correct usage.");
                }
            }, 1);

            store["StartsWithVowel"] = new NativeFunction((values) =>
            {
                string Entree = values[0].AsString;
                if (Entree == "")
                {
                    return("");
                }

                char[] vowels       = { 'a', 'à', 'â', 'ä', 'e', 'ê', 'é', 'è', 'ë', 'i', 'î', 'ï', 'o', 'ô', 'ö', 'u', 'ù', 'û', 'ü', 'œ', 'y' };
                char firstCharacter = Entree.ToLower().ToCharArray().ElementAt(0);
                Boolean result      = vowels.Contains(firstCharacter);

                return(result);
            }, 1);

            store["Voice"] = new NativeFunction((values) =>
            {
                string text  = values[0].AsString;
                string voice = values[1].AsString;
                if (values.Count == 2)
                {
                    return(@"<voice name=""" + voice + @""">" + text + "</voice>");
                }
                else
                {
                    return("The Voice function is used improperly. Please review the documentation for correct usage.");
                }
            }, 1, 2);

            //
            // Commander-specific functions
            //
            store["ShipName"] = new NativeFunction((values) =>
            {
                int?localId   = (values.Count == 0 ? (int?)null : (int)values[0].AsNumber);
                string model  = (values.Count == 2 ? values[1].AsString : null);
                Ship ship     = findShip(localId, model);
                string result = (ship == null ? "your ship" : ship.SpokenName());
                return(result);
            }, 0, 2);

            store["ShipCallsign"] = new NativeFunction((values) =>
            {
                int?localId = (values.Count == 0 ? (int?)null : (int)values[0].AsNumber);
                Ship ship   = findShip(localId, null);

                string result;
                if (ship != null)
                {
                    if (EDDI.Instance.Cmdr != null && EDDI.Instance.Cmdr.name != null)
                    {
                        // Obtain the first three characters
                        string chars = new Regex("[^a-zA-Z0-9]").Replace(EDDI.Instance.Cmdr.name, "").ToUpperInvariant().Substring(0, 3);
                        result       = ship.SpokenManufacturer() + " " + Translations.ICAO(chars);
                    }
                    else
                    {
                        if (ship.SpokenManufacturer() == null)
                        {
                            result = "unidentified ship";
                        }
                        else
                        {
                            result = "unidentified " + ship.SpokenManufacturer() + " " + ship.SpokenModel();
                        }
                    }
                }
                else
                {
                    result = "unidentified ship";
                }
                return(result);
            }, 0, 1);

            //
            // Obtain definition objects for various items
            //

            store["SecondsSince"] = new NativeFunction((values) =>
            {
                long?date = (long?)values[0].AsNumber;
                if (date == null)
                {
                    return(null);
                }
                long?now = (long?)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc))).TotalSeconds;

                return(now - date);
            }, 1);

            store["ICAO"] = new NativeFunction((values) =>
            {
                // Turn a string in to an ICAO definition
                string value = values[0].AsString;
                if (value == null || value == "")
                {
                    return("");
                }

                // Remove anything that isn't alphanumeric
                Logging.Warn("value is " + value);
                value = value.ToUpperInvariant().Replace("[^A-Z0-9]", "");
                Logging.Warn("value is " + value);

                // Translate to ICAO
                return(Translations.ICAO(value));
            }, 1);

            store["ShipDetails"] = new NativeFunction((values) =>
            {
                Ship result = ShipDefinitions.FromModel(values[0].AsString);
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["CombatRatingDetails"] = new NativeFunction((values) =>
            {
                CombatRating result = CombatRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = CombatRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["TradeRatingDetails"] = new NativeFunction((values) =>
            {
                TradeRating result = TradeRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = TradeRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["ExplorationRatingDetails"] = new NativeFunction((values) =>
            {
                ExplorationRating result = ExplorationRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = ExplorationRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["EmpireRatingDetails"] = new NativeFunction((values) =>
            {
                EmpireRating result = EmpireRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = EmpireRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["FederationRatingDetails"] = new NativeFunction((values) =>
            {
                FederationRating result = FederationRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = FederationRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["SystemDetails"] = new NativeFunction((values) =>
            {
                StarSystem result = StarSystemSqLiteRepository.Instance.GetOrCreateStarSystem(values[0].AsString, true);
                setSystemDistanceFromHome(result);
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["BodyDetails"] = new NativeFunction((values) =>
            {
                StarSystem system;
                if (values.Count == 1 || string.IsNullOrEmpty(values[1].AsString))
                {
                    // Current system
                    system = EDDI.Instance.CurrentStarSystem;
                }
                else
                {
                    // Named system
                    system = StarSystemSqLiteRepository.Instance.GetOrCreateStarSystem(values[1].AsString, true);
                }
                Body result = system != null && system.bodies != null ? system.bodies.FirstOrDefault(v => v.name == values[0].AsString) : null;
                if (result != null && result.type == "Star" && result.chromaticity == null)
                {
                    // Need to set our internal extras for the star
                    result.setStellarExtras();
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1, 2);

            store["StationDetails"] = new NativeFunction((values) =>
            {
                if (values.Count == 0)
                {
                    return(null);
                }
                StarSystem system;
                if (values.Count == 1)
                {
                    // Current system
                    system = EDDI.Instance.CurrentStarSystem;
                }
                else
                {
                    // Named system
                    system = StarSystemSqLiteRepository.Instance.GetOrCreateStarSystem(values[1].AsString, true);
                }
                Station result = system != null && system.stations != null ? system.stations.FirstOrDefault(v => v.name == values[0].AsString) : null;
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1, 2);

            store["SuperpowerDetails"] = new NativeFunction((values) =>
            {
                Superpower result = Superpower.FromName(values[0].AsString);
                if (result == null)
                {
                    result = Superpower.From(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["StateDetails"] = new NativeFunction((values) =>
            {
                SystemState result = SystemState.FromName(values[0].AsString);
                if (result == null)
                {
                    result = SystemState.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["EconomyDetails"] = new NativeFunction((values) =>
            {
                Economy result = Economy.FromName(values[0].AsString);
                if (result == null)
                {
                    result = Economy.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["GovernmentDetails"] = new NativeFunction((values) =>
            {
                Government result = Government.FromName(values[0].AsString);
                if (result == null)
                {
                    result = Government.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["SecurityLevelDetails"] = new NativeFunction((values) =>
            {
                SecurityLevel result = SecurityLevel.FromName(values[0].AsString);
                if (result == null)
                {
                    result = SecurityLevel.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["MaterialDetails"] = new NativeFunction((values) =>
            {
                if (string.IsNullOrEmpty(values[0].AsString))
                {
                    return(new ReflectionValue(new object()));
                }

                Material result = Material.FromName(values[0].AsString);
                if (result == null)
                {
                    result = Material.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["CommodityMarketDetails"] = new NativeFunction((values) =>
            {
                CommodityMarketQuote result = null;
                CommodityMarketQuote CommodityDetails(string commodityLocalizedName, Station station)
                {
                    return(station?.commodities?.FirstOrDefault(c => c.localizedName == commodityLocalizedName));
                }

                if (values.Count == 1)
                {
                    // Named commodity, current station
                    Station station = EDDI.Instance.CurrentStation;
                    result          = CommodityDetails(values[0].AsString, station);
                }
                else if (values.Count == 2)
                {
                    // Named commodity, named station, current system
                    StarSystem system  = EDDI.Instance.CurrentStarSystem;
                    string stationName = values[1].AsString;
                    Station station    = system?.stations?.FirstOrDefault(v => v.name == stationName);
                    result             = CommodityDetails(values[0].AsString, station);
                }
                else if (values.Count == 3)
                {
                    // Named commodity, named station, named system
                    StarSystem system  = DataProviderService.GetSystemData(values[2].AsString, null, null, null);
                    string stationName = values[1].AsString;
                    Station station    = system?.stations?.FirstOrDefault(v => v.name == stationName);
                    result             = CommodityDetails(values[0].AsString, station);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 0, 3);

            store["CargoDetails"] = new NativeFunction((values) =>
            {
                Cottle.Value value = values[0];
                Cargo result       = null;
                string edname      = string.Empty;

                if (value.Type == Cottle.ValueContent.String)
                {
                    edname = CommodityDefinition.FromName(value.AsString).edname;
                    result = ((CargoMonitor)EDDI.Instance.ObtainMonitor("Cargo monitor")).GetCargoWithEDName(edname);
                }
                else if (value.Type == Cottle.ValueContent.Number)
                {
                    result = ((CargoMonitor)EDDI.Instance.ObtainMonitor("Cargo monitor")).GetCargoWithMissionId((long)value.AsNumber);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["HaulageDetails"] = new NativeFunction((values) =>
            {
                HaulageAmount result = null;
                result = ((CargoMonitor)EDDI.Instance.ObtainMonitor("Cargo monitor")).GetHaulageWithMissionId((long)values[0].AsNumber);
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["BlueprintDetails"] = new NativeFunction((values) =>
            {
                BlueprintMaterials result = BlueprintMaterials.FromName(values[0].AsString);
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["GalnetNewsArticle"] = new NativeFunction((values) =>
            {
                News result = GalnetSqLiteRepository.Instance.GetArticle(values[0].AsString);
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["GalnetNewsArticles"] = new NativeFunction((values) =>
            {
                List <News> results = null;
                if (values.Count == 0)
                {
                    // Obtain all unread articles
                    results = GalnetSqLiteRepository.Instance.GetArticles();
                }
                else if (values.Count == 1)
                {
                    // Obtain all unread news of a given category
                    results = GalnetSqLiteRepository.Instance.GetArticles(values[0].AsString);
                }
                else if (values.Count == 2)
                {
                    // Obtain all news of a given category
                    results = GalnetSqLiteRepository.Instance.GetArticles(values[0].AsString, values[1].AsBoolean);
                }
                return(results == null ? new ReflectionValue(new List <News>()) : new ReflectionValue(results));
            }, 0, 2);

            store["GalnetNewsMarkRead"] = new NativeFunction((values) =>
            {
                News result = GalnetSqLiteRepository.Instance.GetArticle(values[0].AsString);
                if (result != null)
                {
                    GalnetSqLiteRepository.Instance.MarkRead(result);
                }
                return("");
            }, 1);

            store["GalnetNewsMarkUnread"] = new NativeFunction((values) =>
            {
                News result = GalnetSqLiteRepository.Instance.GetArticle(values[0].AsString);
                if (result != null)
                {
                    GalnetSqLiteRepository.Instance.MarkUnread(result);
                }
                return("");
            }, 1);

            store["GalnetNewsDelete"] = new NativeFunction((values) =>
            {
                News result = GalnetSqLiteRepository.Instance.GetArticle(values[0].AsString);
                if (result != null)
                {
                    GalnetSqLiteRepository.Instance.DeleteNews(result);
                }
                return("");
            }, 1);

            store["Distance"] = new NativeFunction((values) =>
            {
                return((decimal)Math.Round(Math.Sqrt(Math.Pow((double)(values[0].AsNumber - values[3].AsNumber), 2)
                                                     + Math.Pow((double)(values[1].AsNumber - values[4].AsNumber), 2)
                                                     + Math.Pow((double)(values[2].AsNumber - values[5].AsNumber), 2)), 2));
            }, 6);

            store["Log"] = new NativeFunction((values) =>
            {
                Logging.Info(values[0].AsString);
                return("");
            }, 1);

            store["SetState"] = new NativeFunction((values) =>
            {
                string name        = values[0].AsString.ToLowerInvariant().Replace(" ", "_");
                Cottle.Value value = values[1];
                if (value.Type == Cottle.ValueContent.Boolean)
                {
                    EDDI.Instance.State[name] = value.AsBoolean;
                    store["state"]            = buildState();
                }
                else if (value.Type == Cottle.ValueContent.Number)
                {
                    EDDI.Instance.State[name] = value.AsNumber;
                    store["state"]            = buildState();
                }
                else if (value.Type == Cottle.ValueContent.String)
                {
                    EDDI.Instance.State[name] = value.AsString;
                    store["state"]            = buildState();
                }
                // Ignore other possibilities
                return("");
            }, 2);

            // Variables
            foreach (KeyValuePair <string, Cottle.Value> entry in vars)
            {
                store[entry.Key] = entry.Value;
            }

            return(store);
        }
        /// <summary>
        /// Build a store from a list of variables
        /// </summary>
        private BuiltinStore buildStore(Dictionary <string, Cottle.Value> vars)
        {
            BuiltinStore store = new BuiltinStore();

            // Function to call another script
            store["F"] = new NativeFunction((values) =>
            {
                return(new ScriptResolver(scripts).resolve(values[0].AsString, store));
            }, 1);

            // Translation functions
            store["P"] = new NativeFunction((values) =>
            {
                string val         = values[0].AsString;
                string translation = val;
                if (translation == val)
                {
                    translation = Translations.Faction(val);
                }
                if (translation == val)
                {
                    translation = Translations.Power(val);
                }
                if (translation == val)
                {
                    translation = Translations.StarSystem(val);
                }
                return(translation);
            }, 1);

            // Helper functions
            store["OneOf"] = new NativeFunction((values) =>
            {
                return(new ScriptResolver(scripts).resolveScript(values[random.Next(values.Count)].AsString, store));
            });

            store["Occasionally"] = new NativeFunction((values) =>
            {
                if (random.Next((int)values[0].AsNumber) == 0)
                {
                    return(new ScriptResolver(scripts).resolveScript(values[1].AsString, store));
                }
                else
                {
                    return("");
                }
            }, 2);

            store["Humanise"] = new NativeFunction((values) =>
            {
                return(Translations.Humanize(values[0].AsNumber));
            }, 1);

            store["Pause"] = new NativeFunction((values) =>
            {
                return(@"<break time =""" + values[0].AsNumber + @"ms"" />");
            }, 1);

            //
            // Commander-specific functions
            //
            store["ShipName"] = new NativeFunction((values) =>
            {
                int?localId   = (values.Count == 0 ? (int?)null : (int)values[0].AsNumber);
                string model  = (values.Count == 2 ? values[1].AsString : null);
                Ship ship     = findShip(localId, model);
                string result = (ship == null ? "your ship" : ship.SpokenName());
                return(result);
            }, 0, 2);

            store["ShipCallsign"] = new NativeFunction((values) =>
            {
                int?localId = (values.Count == 0 ? (int?)null : (int)values[0].AsNumber);
                Ship ship   = findShip(localId, null);

                string result;
                if (ship != null)
                {
                    if (EDDI.Instance.Cmdr != null && EDDI.Instance.Cmdr.name != null)
                    {
                        // Obtain the first three characters
                        string chars = new Regex("[^a-zA-Z0-9]").Replace(EDDI.Instance.Cmdr.name, "").ToUpperInvariant().Substring(0, 3);
                        result       = ship.SpokenManufacturer() + " " + Translations.CallSign(chars);
                    }
                    else
                    {
                        if (ship.SpokenManufacturer() == null)
                        {
                            result = "unidentified ship";
                        }
                        else
                        {
                            result = "unidentified " + ship.SpokenManufacturer() + " " + ship.SpokenModel();
                        }
                    }
                }
                else
                {
                    result = "unidentified ship";
                }
                return(result);
            }, 0, 1);

            //
            // Obtain definition objects for various items
            //

            store["ShipDetails"] = new NativeFunction((values) =>
            {
                int?localId = (values.Count == 0 ? (int?)null : (int)values[0].AsNumber);
                Ship result = findShip(localId, null);
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 0, 1);

            store["CombatRatingDetails"] = new NativeFunction((values) =>
            {
                CombatRating result = CombatRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = CombatRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["TradeRatingDetails"] = new NativeFunction((values) =>
            {
                TradeRating result = TradeRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = TradeRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["ExplorationRatingDetails"] = new NativeFunction((values) =>
            {
                ExplorationRating result = ExplorationRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = ExplorationRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["EmpireRatingDetails"] = new NativeFunction((values) =>
            {
                EmpireRating result = EmpireRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = EmpireRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["FederationRatingDetails"] = new NativeFunction((values) =>
            {
                FederationRating result = FederationRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = FederationRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["SystemDetails"] = new NativeFunction((values) =>
            {
                StarSystem result = StarSystemSqLiteRepository.Instance.GetOrCreateStarSystem(values[0].AsString, true);
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["StationDetails"] = new NativeFunction((values) =>
            {
                if (values.Count == 0)
                {
                    return(null);
                }
                StarSystem system;
                if (values.Count == 1)
                {
                    // Current system
                    system = EDDI.Instance.CurrentStarSystem;
                }
                else
                {
                    system = StarSystemSqLiteRepository.Instance.GetOrCreateStarSystem(values[1].AsString, true);
                }
                Station result = system != null && system.stations != null ? system.stations.FirstOrDefault(v => v.name == values[0].AsString) : null;
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1, 2);

            store["SuperpowerDetails"] = new NativeFunction((values) =>
            {
                Superpower result = Superpower.FromName(values[0].AsString);
                if (result == null)
                {
                    result = Superpower.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["StateDetails"] = new NativeFunction((values) =>
            {
                State result = State.FromName(values[0].AsString);
                if (result == null)
                {
                    result = State.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["EconomyDetails"] = new NativeFunction((values) =>
            {
                Economy result = Economy.FromName(values[0].AsString);
                if (result == null)
                {
                    result = Economy.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["GovernmentDetails"] = new NativeFunction((values) =>
            {
                Government result = Government.FromName(values[0].AsString);
                if (result == null)
                {
                    result = Government.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["SecurityLevelDetails"] = new NativeFunction((values) =>
            {
                SecurityLevel result = SecurityLevel.FromName(values[0].AsString);
                if (result == null)
                {
                    result = SecurityLevel.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["MaterialDetails"] = new NativeFunction((values) =>
            {
                Material result = Material.FromName(values[0].AsString);
                if (result == null)
                {
                    result = Material.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            // Variables
            foreach (KeyValuePair <string, Cottle.Value> entry in vars)
            {
                store[entry.Key] = entry.Value;
            }

            return(store);
        }
Exemple #14
0
        /// <summary>
        /// Build a store from a list of variables
        /// </summary>
        private BuiltinStore buildStore(Dictionary <string, Cottle.Value> vars)
        {
            BuiltinStore store = new BuiltinStore();

            // Function to call another script
            store["F"] = new NativeFunction((values) =>
            {
                return(new ScriptResolver(scripts).resolve(values[0].AsString, store, false));
            }, 1);

            // Translation functions
            store["P"] = new NativeFunction((values) =>
            {
                string val         = values[0].AsString;
                string translation = val;
                if (translation == val)
                {
                    translation = Translations.Faction(val);
                }
                if (translation == val)
                {
                    translation = Translations.Power(val);
                }
                if (translation == val)
                {
                    translation = Translations.StarSystem(val);
                }
                if (translation == val)
                {
                    Ship ship = ShipDefinitions.FromModel(val);
                    if (ship != null && ship.EDID > 0)
                    {
                        translation = ship.SpokenModel();
                    }
                }
                if (translation == val)
                {
                    Ship ship = ShipDefinitions.FromEDModel(val);
                    if (ship != null && ship.EDID > 0)
                    {
                        translation = ship.SpokenModel();
                    }
                }
                return(translation);
            }, 1);

            // Boolean constants
            store["true"]  = true;
            store["false"] = false;

            // Helper functions
            store["OneOf"] = new NativeFunction((values) =>
            {
                return(new ScriptResolver(scripts).resolveScript(values[random.Next(values.Count)].AsString, store, false));
            });

            store["Occasionally"] = new NativeFunction((values) =>
            {
                if (random.Next((int)values[0].AsNumber) == 0)
                {
                    return(new ScriptResolver(scripts).resolveScript(values[1].AsString, store, false));
                }
                else
                {
                    return("");
                }
            }, 2);

            store["Humanise"] = new NativeFunction((values) =>
            {
                return(Translations.Humanize(values[0].AsNumber));
            }, 1);

            store["Pause"] = new NativeFunction((values) =>
            {
                return(@"<break time =""" + values[0].AsNumber + @"ms"" />");
            }, 1);

            //
            // Commander-specific functions
            //
            store["ShipName"] = new NativeFunction((values) =>
            {
                int?localId   = (values.Count == 0 ? (int?)null : (int)values[0].AsNumber);
                string model  = (values.Count == 2 ? values[1].AsString : null);
                Ship ship     = findShip(localId, model);
                string result = (ship == null ? "your ship" : ship.SpokenName());
                return(result);
            }, 0, 2);

            store["ShipCallsign"] = new NativeFunction((values) =>
            {
                int?localId = (values.Count == 0 ? (int?)null : (int)values[0].AsNumber);
                Ship ship   = findShip(localId, null);

                string result;
                if (ship != null)
                {
                    if (EDDI.Instance.Cmdr != null && EDDI.Instance.Cmdr.name != null)
                    {
                        // Obtain the first three characters
                        string chars = new Regex("[^a-zA-Z0-9]").Replace(EDDI.Instance.Cmdr.name, "").ToUpperInvariant().Substring(0, 3);
                        result       = ship.SpokenManufacturer() + " " + Translations.CallSign(chars);
                    }
                    else
                    {
                        if (ship.SpokenManufacturer() == null)
                        {
                            result = "unidentified ship";
                        }
                        else
                        {
                            result = "unidentified " + ship.SpokenManufacturer() + " " + ship.SpokenModel();
                        }
                    }
                }
                else
                {
                    result = "unidentified ship";
                }
                return(result);
            }, 0, 1);

            //
            // Obtain definition objects for various items
            //

            store["SecondsSince"] = new NativeFunction((values) =>
            {
                long?date = (long?)values[0].AsNumber;
                if (date == null)
                {
                    return(null);
                }
                long now = (long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;

                return(now - date);
            }, 1);

            store["ShipDetails"] = new NativeFunction((values) =>
            {
                Ship result = ShipDefinitions.FromModel(values[0].AsString);
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["CombatRatingDetails"] = new NativeFunction((values) =>
            {
                CombatRating result = CombatRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = CombatRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["TradeRatingDetails"] = new NativeFunction((values) =>
            {
                TradeRating result = TradeRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = TradeRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["ExplorationRatingDetails"] = new NativeFunction((values) =>
            {
                ExplorationRating result = ExplorationRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = ExplorationRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["EmpireRatingDetails"] = new NativeFunction((values) =>
            {
                EmpireRating result = EmpireRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = EmpireRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["FederationRatingDetails"] = new NativeFunction((values) =>
            {
                FederationRating result = FederationRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = FederationRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["SystemDetails"] = new NativeFunction((values) =>
            {
                StarSystem result = StarSystemSqLiteRepository.Instance.GetOrCreateStarSystem(values[0].AsString, true);
                setSystemDistanceFromHome(result);
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["BodyDetails"] = new NativeFunction((values) =>
            {
                StarSystem system;
                if (values.Count == 1)
                {
                    // Current system
                    system = EDDI.Instance.CurrentStarSystem;
                }
                else
                {
                    // Named system
                    system = StarSystemSqLiteRepository.Instance.GetOrCreateStarSystem(values[1].AsString, true);
                }
                Body result = system != null && system.bodies != null ? system.bodies.FirstOrDefault(v => v.name == values[0].AsString) : null;
                if (result != null && result.type == "Star" && result.chromaticity == null)
                {
                    // Need to set our internal extras for the star
                    result.setStellarExtras();
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1, 2);

            store["StationDetails"] = new NativeFunction((values) =>
            {
                if (values.Count == 0)
                {
                    return(null);
                }
                StarSystem system;
                if (values.Count == 1)
                {
                    // Current system
                    system = EDDI.Instance.CurrentStarSystem;
                }
                else
                {
                    // Named system
                    system = StarSystemSqLiteRepository.Instance.GetOrCreateStarSystem(values[1].AsString, true);
                }
                Station result = system != null && system.stations != null ? system.stations.FirstOrDefault(v => v.name == values[0].AsString) : null;
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1, 2);

            store["SuperpowerDetails"] = new NativeFunction((values) =>
            {
                Superpower result = Superpower.FromName(values[0].AsString);
                if (result == null)
                {
                    result = Superpower.From(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["StateDetails"] = new NativeFunction((values) =>
            {
                State result = State.FromName(values[0].AsString);
                if (result == null)
                {
                    result = State.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["EconomyDetails"] = new NativeFunction((values) =>
            {
                Economy result = Economy.FromName(values[0].AsString);
                if (result == null)
                {
                    result = Economy.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["GovernmentDetails"] = new NativeFunction((values) =>
            {
                Government result = Government.FromName(values[0].AsString);
                if (result == null)
                {
                    result = Government.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["SecurityLevelDetails"] = new NativeFunction((values) =>
            {
                SecurityLevel result = SecurityLevel.FromName(values[0].AsString);
                if (result == null)
                {
                    result = SecurityLevel.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["MaterialDetails"] = new NativeFunction((values) =>
            {
                Material result = Material.FromName(values[0].AsString);
                if (result == null)
                {
                    result = Material.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["Distance"] = new NativeFunction((values) =>
            {
                return((decimal)Math.Round(Math.Sqrt(Math.Pow((double)(values[0].AsNumber - values[3].AsNumber), 2)
                                                     + Math.Pow((double)(values[1].AsNumber - values[4].AsNumber), 2)
                                                     + Math.Pow((double)(values[2].AsNumber - values[5].AsNumber), 2)), 2));
            }, 6);

            store["SetState"] = new NativeFunction((values) =>
            {
                string name        = values[0].AsString.ToLowerInvariant().Replace(" ", "_");
                Cottle.Value value = values[1];
                if (value.Type == Cottle.ValueContent.Boolean)
                {
                    EDDI.Instance.State[name] = value.AsBoolean;
                    store["state"]            = buildState();
                }
                else if (value.Type == Cottle.ValueContent.Number)
                {
                    EDDI.Instance.State[name] = value.AsNumber;
                    store["state"]            = buildState();
                }
                else if (value.Type == Cottle.ValueContent.String)
                {
                    EDDI.Instance.State[name] = value.AsString;
                    store["state"]            = buildState();
                }
                // Ignore other possibilities
                return("");
            }, 2);

            // Variables
            foreach (KeyValuePair <string, Cottle.Value> entry in vars)
            {
                store[entry.Key] = entry.Value;
            }

            return(store);
        }
Exemple #15
0
        private static Station ParseEddbStation(object response)
        {
            // Notes:
            // Whether a station is planetary is not given by the journal. Though EDDB provides this as a boolean,
            //   we will derive this from the station model instead of using the EDDB value to maximize consistency with journal data.
            // Economy share / proportion is not given from EDDB, so we cannot use the EconomyShare class
            //   to describe these economies and we fall back to strings.
            // CommodityMarketQuote data is not currently available from EDDB. Pilots will have to dock to retrieve this.

            JObject stationJson = ((JObject)response);

            Station Station = new Station
            {
                // General data
                EDDBID           = (long)stationJson["id"],
                name             = (string)stationJson["name"],
                bodyEDDBID       = (long?)stationJson["body_id"],
                distancefromstar = (decimal?)stationJson["distance_to_star"], // Light seconds

                // System name is not given directly, but we have an EDDB ID linking to the system
                // that we will be able to use for lookups once our system lookup is complete.
                // We will also need to use this lookup to find the reserve level associated with this system
                systemEDDBID = (long?)stationJson["system_id"]
            };

            /*
             * Station.systemname = systemName;
             */

            // Controlling faction data
            long?   factionEddbId = (long?)stationJson["controlling_minor_faction_id"];
            Faction controllingFaction;

            if (factionEddbId != null)
            {
                controllingFaction = Faction((long)factionEddbId);
            }
            else
            {
                controllingFaction = new Faction();
            };
            controllingFaction.Allegiance   = Superpower.FromName((string)stationJson["allegiance"]);
            controllingFaction.Government   = Government.FromName((string)stationJson["government"]);
            controllingFaction.FactionState = FactionState.FromName((string)stationJson["state"]);
            Station.Faction = controllingFaction;

            // Station facilities data
            Station.Model          = StationModel.FromName((string)stationJson["type"]);
            Station.hasblackmarket = (bool?)stationJson["has_blackmarket"];
            Station.hasdocking     = (bool?)stationJson["has_docking"];
            Station.hasmarket      = (bool?)stationJson["has_market"];
            Station.hasoutfitting  = (bool?)stationJson["has_outfitting"];
            Station.hasrefuel      = (bool?)stationJson["has_refuel"];
            Station.hasrepair      = (bool?)stationJson["has_repair"];
            Station.hasrearm       = (bool?)stationJson["has_rearm"];
            Station.hasshipyard    = (bool?)stationJson["has_shipyard"];
            if ((bool?)stationJson["has_docking"] is true)
            {
                // Add services which are always included when we can dock
                Station.stationServices.Add(StationService.FromEDName("Dock"));
                Station.stationServices.Add(StationService.FromEDName("AutoDock"));
                Station.stationServices.Add(StationService.FromEDName("Contacts"));
                Station.stationServices.Add(StationService.FromEDName("Exploration"));
                Station.stationServices.Add(StationService.FromEDName("Tuning"));
                Station.stationServices.Add(StationService.FromEDName("Workshop"));
                Station.stationServices.Add(StationService.FromEDName("FlightController"));
                Station.stationServices.Add(StationService.FromEDName("StationOperations"));
                Station.stationServices.Add(StationService.FromEDName("Powerplay"));
            }

            List <Economy> Economies = new List <Economy>();

            if (stationJson["economies"] != null)
            {
                foreach (JObject export in stationJson["economies"])
                {
                    Economy Economy = Economy.FromName((string)export["name"]);
                    if (Economy != null)
                    {
                        Economies.Add(Economy);
                    }
                }
            }
            Station.Economies = Economies;

            List <string> imports = new List <string>();

            if (stationJson["import_commodities"] != null)
            {
                foreach (JObject import in stationJson["import_commodities"])
                {
                    string name = (string)import["name"];
                    if (name != null)
                    {
                        imports.Add(name);
                    }
                }
            }
            Station.imported = imports;

            List <string> exports = new List <string>();

            if (stationJson["export_commodities"] != null)
            {
                foreach (JObject export in stationJson["export_commodities"])
                {
                    string name = (string)export["name"];
                    if (name != null)
                    {
                        exports.Add(name);
                    }
                }
            }
            Station.exported = exports;

            List <string> prohibited = new List <string>();

            if (stationJson["prohibited_commodities"] != null)
            {
                foreach (JObject export in stationJson["prohibited_commodities"])
                {
                    string name = (string)export["name"];
                    if (name != null)
                    {
                        prohibited.Add(name);
                    }
                }
            }
            Station.prohibited = prohibited;

            List <Ship> shipyard = new List <Ship>();

            if (stationJson["selling_ships"] != null)
            {
                foreach (JObject shipJson in stationJson["selling_ships"])
                {
                    Ship ship = ShipDefinitions.FromModel((string)shipJson["name"]);
                    if (ship != null)
                    {
                        shipyard.Add(ship);
                    }
                }
            }
            Station.shipyard = shipyard;

            List <Module> outfitting = new List <Module>();

            if (stationJson["selling_modules"] != null)
            {
                JArray modulesJArray = (JArray)stationJson["selling_modules"];
                foreach (JValue eddbIdValue in modulesJArray)
                {
                    Module module = Module.FromEddbID((long)eddbIdValue);
                    if (module != null)
                    {
                        outfitting.Add(module);
                    }
                }
            }
            Station.outfitting = outfitting;

            Station.outfittingupdatedat = Dates.fromDateTimeStringToSeconds((string)stationJson["outfitting_updated_at"]);
            Station.shipyardupdatedat   = Dates.fromDateTimeStringToSeconds((string)stationJson["shipyard_updated_at"]);
            Station.updatedat           = Dates.fromDateTimeStringToSeconds((string)stationJson["updated_at"]);

            return(Station);
        }
Exemple #16
0
        private static Faction ParseFaction(object response)
        {
            IDictionary <string, object> factionJson = Deserializtion.DeserializeData(response.ToString());
            Faction faction = new Faction
            {
                EDDBID     = (long)factionJson["eddb_id"],
                name       = (string)factionJson["name"],
                updatedAt  = (DateTime)factionJson["updated_at"],
                Government = Government.FromName((string)factionJson["government"]),
                Allegiance = Superpower.FromName((string)factionJson["allegiance"]),
            };

            foreach (object presence in (List <object>)factionJson["faction_presence"])
            {
                IDictionary <string, object> presenceJson = (IDictionary <string, object>)presence;
                FactionPresence factionPresence           = new FactionPresence()
                {
                    systemName   = (string)presenceJson["system_name"],
                    influence    = (decimal?)(double?)presenceJson["influence"] * 100, // Convert from a 0-1 range to a percentage
                    FactionState = FactionState.FromEDName((string)presenceJson["state"]) ?? FactionState.None,
                    Happiness    = Happiness.FromEDName((string)presenceJson["happiness"]) ?? Happiness.None,
                    updatedAt    = (DateTime)presenceJson["updated_at"],
                };

                // Active states
                presenceJson.TryGetValue("active_states", out object activeStatesVal);
                if (activeStatesVal != null)
                {
                    var activeStatesList = (List <object>)activeStatesVal;
                    foreach (IDictionary <string, object> activeState in activeStatesList)
                    {
                        factionPresence.ActiveStates.Add(FactionState.FromEDName(JsonParsing.getString(activeState, "state") ?? "None"));
                    }
                }

                // Pending states
                presenceJson.TryGetValue("pending_states", out object pendingStatesVal);
                if (pendingStatesVal != null)
                {
                    var pendingStatesList = (List <object>)pendingStatesVal;
                    foreach (IDictionary <string, object> pendingState in pendingStatesList)
                    {
                        FactionTrendingState pTrendingState = new FactionTrendingState(
                            FactionState.FromEDName(JsonParsing.getString(pendingState, "state") ?? "None"),
                            JsonParsing.getInt(pendingState, "trend")
                            );
                        factionPresence.PendingStates.Add(pTrendingState);
                    }
                }

                // Recovering states
                presenceJson.TryGetValue("recovering_states", out object recoveringStatesVal);
                if (recoveringStatesVal != null)
                {
                    var recoveringStatesList = (List <object>)recoveringStatesVal;
                    foreach (IDictionary <string, object> recoveringState in recoveringStatesList)
                    {
                        FactionTrendingState rTrendingState = new FactionTrendingState(
                            FactionState.FromEDName(JsonParsing.getString(recoveringState, "state") ?? "None"),
                            JsonParsing.getInt(recoveringState, "trend")
                            );
                        factionPresence.RecoveringStates.Add(rTrendingState);
                    }
                }

                faction.presences.Add(factionPresence);
            }

            return(faction);
        }
Exemple #17
0
        private Faction ParseStarMapFaction(JObject faction, string systemName)
        {
            try
            {
                if (faction is null)
                {
                    return(null);
                }
                Faction Faction = new Faction
                {
                    name       = (string)faction["name"],
                    EDSMID     = (long?)faction["id"],
                    Allegiance = Superpower.FromName((string)faction["allegiance"]) ?? Superpower.None,
                    Government = Government.FromName((string)faction["government"]) ?? Government.None,
                    isplayer   = (bool?)faction["isPlayer"],
                    updatedAt  = Dates.fromTimestamp((long?)faction["lastUpdate"]) ?? DateTime.MinValue
                };

                Faction.presences.Add(new FactionPresence()
                {
                    systemName   = systemName,
                    influence    = (decimal?)faction["influence"] * 100, // Convert from a 0-1 range to a percentage
                    FactionState = FactionState.FromName((string)faction["state"]) ?? FactionState.None,
                });

                IDictionary <string, object> factionDetail = faction.ToObject <IDictionary <string, object> >();

                // Active states
                factionDetail.TryGetValue("activeStates", out object activeStatesVal);
                if (activeStatesVal != null)
                {
                    var activeStatesList = (JArray)activeStatesVal;
                    foreach (var activeStateToken in activeStatesList)
                    {
                        var activeState = activeStateToken.ToObject <IDictionary <string, object> >();
                        Faction.presences.FirstOrDefault(p => p.systemName == systemName)?
                        .ActiveStates.Add(FactionState.FromName(JsonParsing.getString(activeState, "state")) ?? FactionState.None);
                    }
                }

                // Pending states
                factionDetail.TryGetValue("pendingStates", out object pendingStatesVal);
                if (pendingStatesVal != null)
                {
                    var pendingStatesList = ((JArray)pendingStatesVal).ToList();
                    foreach (var pendingStateToken in pendingStatesList)
                    {
                        var pendingState = pendingStateToken.ToObject <IDictionary <string, object> >();
                        FactionTrendingState pTrendingState = new FactionTrendingState(
                            FactionState.FromName(JsonParsing.getString(pendingState, "state")) ?? FactionState.None,
                            JsonParsing.getInt(pendingState, "trend")
                            );
                        Faction.presences.FirstOrDefault(p => p.systemName == systemName)?
                        .PendingStates.Add(pTrendingState);
                    }
                }

                // Recovering states
                factionDetail.TryGetValue("recoveringStates", out object recoveringStatesVal);
                if (recoveringStatesVal != null)
                {
                    var recoveringStatesList = (JArray)recoveringStatesVal;
                    foreach (var recoveringStateToken in recoveringStatesList)
                    {
                        var recoveringState = recoveringStateToken.ToObject <IDictionary <string, object> >();
                        FactionTrendingState rTrendingState = new FactionTrendingState(
                            FactionState.FromName(JsonParsing.getString(recoveringState, "state")) ?? FactionState.None,
                            JsonParsing.getInt(recoveringState, "trend")
                            );
                        Faction.presences.FirstOrDefault(p => p.systemName == systemName)?
                        .RecoveringStates.Add(rTrendingState);
                    }
                }

                return(Faction);
            }
            catch (Exception ex)
            {
                Dictionary <string, object> data = new Dictionary <string, object>
                {
                    { "faction", JsonConvert.SerializeObject(faction) },
                    { "exception", ex.Message },
                    { "stacktrace", ex.StackTrace }
                };
                Logging.Error("Error parsing EDSM faction result.", data);
            }
            return(null);
        }
        /// <summary>
        /// Build a store from a list of variables
        /// </summary>
        private BuiltinStore buildStore(Dictionary <string, Cottle.Value> vars)
        {
            BuiltinStore store = new BuiltinStore();

            // TODO fetch this from configuration
            bool useICAO = SpeechServiceConfiguration.FromFile().EnableIcao;

            // Function to call another script
            store["F"] = new NativeFunction((values) =>
            {
                return(new ScriptResolver(scripts).resolve(values[0].AsString, store, false));
            }, 1);

            // Translation functions
            store["P"] = new NativeFunction((values) =>
            {
                string val         = values[0].AsString;
                string translation = val;
                if (translation == val)
                {
                    translation = Translations.Body(val, useICAO);
                }
                if (translation == val)
                {
                    translation = Translations.StarSystem(val, useICAO);
                }
                if (translation == val)
                {
                    translation = Translations.Faction(val);
                }
                if (translation == val)
                {
                    translation = Translations.Power(val);
                }
                if (translation == val)
                {
                    Ship ship = ShipDefinitions.FromModel(val);
                    if (ship != null && ship.EDID > 0)
                    {
                        translation = ship.SpokenModel();
                    }
                }
                if (translation == val)
                {
                    Ship ship = ShipDefinitions.FromEDModel(val);
                    if (ship != null && ship.EDID > 0)
                    {
                        translation = ship.SpokenModel();
                    }
                }
                return(translation);
            }, 1);

            // Boolean constants
            store["true"]  = true;
            store["false"] = false;

            // Helper functions
            store["OneOf"] = new NativeFunction((values) =>
            {
                return(new ScriptResolver(scripts).resolveScript(values[random.Next(values.Count)].AsString, store, false));
            });

            store["Occasionally"] = new NativeFunction((values) =>
            {
                if (random.Next((int)values[0].AsNumber) == 0)
                {
                    return(new ScriptResolver(scripts).resolveScript(values[1].AsString, store, false));
                }
                else
                {
                    return("");
                }
            }, 2);

            store["Humanise"] = new NativeFunction((values) =>
            {
                return(Translations.Humanize(values[0].AsNumber));
            }, 1);

            store["Pause"] = new NativeFunction((values) =>
            {
                return(@"<break time=""" + values[0].AsNumber + @"ms"" />");
            }, 1);

            store["Play"] = new NativeFunction((values) =>
            {
                return(@"<audio src=""" + values[0].AsString + @""" />");
            }, 1);

            store["Spacialise"] = new NativeFunction((values) =>
            {
                string Entree = values[0].AsString;
                if (Entree == "")
                {
                    return("");
                }
                string Sortie      = "";
                string UpperSortie = "";
                foreach (char c in Entree)
                {
                    Sortie = Sortie + c + " ";
                }
                UpperSortie = Sortie.ToUpper();
                return(UpperSortie);
            }, 1);

            store["StartsWithVowel"] = new NativeFunction((values) =>
            {
                string Entree = values[0].AsString;
                if (Entree == "")
                {
                    return("");
                }

                char[] vowels       = { 'a', 'à', 'â', 'ä', 'e', 'ê', 'é', 'è', 'ë', 'i', 'î', 'ï', 'o', 'ô', 'ö', 'u', 'ù', 'û', 'ü', 'œ', 'y' };
                char firstCharacter = Entree.ToLower().ToCharArray().ElementAt(0);
                Boolean result      = vowels.Contains(firstCharacter);

                return(result);
            }, 1);

            //
            // Commander-specific functions
            //
            store["ShipName"] = new NativeFunction((values) =>
            {
                int?localId   = (values.Count == 0 ? (int?)null : (int)values[0].AsNumber);
                string model  = (values.Count == 2 ? values[1].AsString : null);
                Ship ship     = findShip(localId, model);
                string result = (ship == null ? "your ship" : ship.SpokenName());
                return(result);
            }, 0, 2);

            store["ShipCallsign"] = new NativeFunction((values) =>
            {
                int?localId = (values.Count == 0 ? (int?)null : (int)values[0].AsNumber);
                Ship ship   = findShip(localId, null);

                string result;
                if (ship != null)
                {
                    if (EDDI.Instance.Cmdr != null && EDDI.Instance.Cmdr.name != null)
                    {
                        // Obtain the first three characters
                        string chars = new Regex("[^a-zA-Z0-9]").Replace(EDDI.Instance.Cmdr.name, "").ToUpperInvariant().Substring(0, 3);
                        result       = ship.SpokenManufacturer() + " " + Translations.ICAO(chars);
                    }
                    else
                    {
                        if (ship.SpokenManufacturer() == null)
                        {
                            result = "unidentified ship";
                        }
                        else
                        {
                            result = "unidentified " + ship.SpokenManufacturer() + " " + ship.SpokenModel();
                        }
                    }
                }
                else
                {
                    result = "unidentified ship";
                }
                return(result);
            }, 0, 1);

            //
            // Obtain definition objects for various items
            //

            store["SecondsSince"] = new NativeFunction((values) =>
            {
                long?date = (long?)values[0].AsNumber;
                if (date == null)
                {
                    return(null);
                }
                long now = (long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;

                return(now - date);
            }, 1);

            store["ICAO"] = new NativeFunction((values) =>
            {
                // Turn a string in to an ICAO definition
                string value = values[0].AsString;
                if (value == null || value == "")
                {
                    return("");
                }

                // Remove anything that isn't alphanumeric
                Logging.Warn("value is " + value);
                value = value.ToUpperInvariant().Replace("[^A-Z0-9]", "");
                Logging.Warn("value is " + value);

                // Translate to ICAO
                return(Translations.ICAO(value));
            }, 1);

            store["ShipDetails"] = new NativeFunction((values) =>
            {
                Ship result = ShipDefinitions.FromModel(values[0].AsString);
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["CombatRatingDetails"] = new NativeFunction((values) =>
            {
                CombatRating result = CombatRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = CombatRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["TradeRatingDetails"] = new NativeFunction((values) =>
            {
                TradeRating result = TradeRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = TradeRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["ExplorationRatingDetails"] = new NativeFunction((values) =>
            {
                ExplorationRating result = ExplorationRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = ExplorationRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["EmpireRatingDetails"] = new NativeFunction((values) =>
            {
                EmpireRating result = EmpireRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = EmpireRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["FederationRatingDetails"] = new NativeFunction((values) =>
            {
                FederationRating result = FederationRating.FromName(values[0].AsString);
                if (result == null)
                {
                    result = FederationRating.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["SystemDetails"] = new NativeFunction((values) =>
            {
                StarSystem result = StarSystemSqLiteRepository.Instance.GetOrCreateStarSystem(values[0].AsString, true);
                setSystemDistanceFromHome(result);
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["BodyDetails"] = new NativeFunction((values) =>
            {
                StarSystem system;
                if (values.Count == 1 || string.IsNullOrEmpty(values[1].AsString))
                {
                    // Current system
                    system = EDDI.Instance.CurrentStarSystem;
                }
                else
                {
                    // Named system
                    system = StarSystemSqLiteRepository.Instance.GetOrCreateStarSystem(values[1].AsString, true);
                }
                Body result = system != null && system.bodies != null ? system.bodies.FirstOrDefault(v => v.name == values[0].AsString) : null;
                if (result != null && result.type == "Star" && result.chromaticity == null)
                {
                    // Need to set our internal extras for the star
                    result.setStellarExtras();
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1, 2);

            store["StationDetails"] = new NativeFunction((values) =>
            {
                if (values.Count == 0)
                {
                    return(null);
                }
                StarSystem system;
                if (values.Count == 1)
                {
                    // Current system
                    system = EDDI.Instance.CurrentStarSystem;
                }
                else
                {
                    // Named system
                    system = StarSystemSqLiteRepository.Instance.GetOrCreateStarSystem(values[1].AsString, true);
                }
                Station result = system != null && system.stations != null ? system.stations.FirstOrDefault(v => v.name == values[0].AsString) : null;
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1, 2);

            store["SuperpowerDetails"] = new NativeFunction((values) =>
            {
                Superpower result = Superpower.FromName(values[0].AsString);
                if (result == null)
                {
                    result = Superpower.From(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["StateDetails"] = new NativeFunction((values) =>
            {
                State result = State.FromName(values[0].AsString);
                if (result == null)
                {
                    result = State.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["EconomyDetails"] = new NativeFunction((values) =>
            {
                Economy result = Economy.FromName(values[0].AsString);
                if (result == null)
                {
                    result = Economy.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["GovernmentDetails"] = new NativeFunction((values) =>
            {
                Government result = Government.FromName(values[0].AsString);
                if (result == null)
                {
                    result = Government.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["SecurityLevelDetails"] = new NativeFunction((values) =>
            {
                SecurityLevel result = SecurityLevel.FromName(values[0].AsString);
                if (result == null)
                {
                    result = SecurityLevel.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["MaterialDetails"] = new NativeFunction((values) =>
            {
                if (string.IsNullOrEmpty(values[0].AsString))
                {
                    return(new ReflectionValue(new object()));
                }

                Material result = Material.FromName(values[0].AsString);
                if (result == null)
                {
                    result = Material.FromEDName(values[0].AsString);
                }
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["BlueprintDetails"] = new NativeFunction((values) =>
            {
                BlueprintMaterials result = BlueprintMaterials.FromName(values[0].AsString);
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["GalnetNewsArticle"] = new NativeFunction((values) =>
            {
                News result = GalnetSqLiteRepository.Instance.GetArticle(values[0].AsString);
                return(result == null ? new ReflectionValue(new object()) : new ReflectionValue(result));
            }, 1);

            store["GalnetNewsArticles"] = new NativeFunction((values) =>
            {
                List <News> results = null;
                if (values.Count == 0)
                {
                    // Obtain all unread articles
                    results = GalnetSqLiteRepository.Instance.GetArticles();
                }
                else if (values.Count == 1)
                {
                    // Obtain all unread news of a given category
                    results = GalnetSqLiteRepository.Instance.GetArticles(values[0].AsString);
                }
                else if (values.Count == 2)
                {
                    // Obtain all news of a given category
                    results = GalnetSqLiteRepository.Instance.GetArticles(values[0].AsString, false);
                }
                return(results == null ? new ReflectionValue(new List <News>()) : new ReflectionValue(results));
            }, 0, 2);

            store["GalnetNewsMarkRead"] = new NativeFunction((values) =>
            {
                News result = GalnetSqLiteRepository.Instance.GetArticle(values[0].AsString);
                if (result != null)
                {
                    GalnetSqLiteRepository.Instance.MarkRead(result);
                }
                return("");
            }, 1);

            store["GalnetNewsMarkUnread"] = new NativeFunction((values) =>
            {
                News result = GalnetSqLiteRepository.Instance.GetArticle(values[0].AsString);
                if (result != null)
                {
                    GalnetSqLiteRepository.Instance.MarkUnread(result);
                }
                return("");
            }, 1);

            store["Distance"] = new NativeFunction((values) =>
            {
                return((decimal)Math.Round(Math.Sqrt(Math.Pow((double)(values[0].AsNumber - values[3].AsNumber), 2)
                                                     + Math.Pow((double)(values[1].AsNumber - values[4].AsNumber), 2)
                                                     + Math.Pow((double)(values[2].AsNumber - values[5].AsNumber), 2)), 2));
            }, 6);

            store["Log"] = new NativeFunction((values) =>
            {
                Logging.Info(values[0].AsString);
                return("");
            }, 1);

            store["SetState"] = new NativeFunction((values) =>
            {
                string name        = values[0].AsString.ToLowerInvariant().Replace(" ", "_");
                Cottle.Value value = values[1];
                if (value.Type == Cottle.ValueContent.Boolean)
                {
                    EDDI.Instance.State[name] = value.AsBoolean;
                    store["state"]            = buildState();
                }
                else if (value.Type == Cottle.ValueContent.Number)
                {
                    EDDI.Instance.State[name] = value.AsNumber;
                    store["state"]            = buildState();
                }
                else if (value.Type == Cottle.ValueContent.String)
                {
                    EDDI.Instance.State[name] = value.AsString;
                    store["state"]            = buildState();
                }
                // Ignore other possibilities
                return("");
            }, 2);

            // Variables
            foreach (KeyValuePair <string, Cottle.Value> entry in vars)
            {
                store[entry.Key] = entry.Value;
            }

            return(store);
        }