예제 #1
0
        public void TestVACommodityEjectedEvent()
        {
            // Test a generated variable name from overlapping strings.
            // The prefix "EDDI ship fsd" should be merged with the formatted child key "fsd status" to yield "EDDI ship fsd status".
            CommodityEjectedEvent ev = new CommodityEjectedEvent(DateTime.UtcNow, CommodityDefinition.FromEDName("Water"), 5, null, true);

            var vars = new MetaVariables(ev.GetType(), ev).Results;

            var cottleVars = vars.AsCottleVariables();

            Assert.AreEqual(4, cottleVars.Count);
            Assert.AreEqual("Water", cottleVars.FirstOrDefault(k => k.key == "commodity").value);
            Assert.AreEqual(5, cottleVars.FirstOrDefault(k => k.key == "amount").value);
            Assert.IsNull(cottleVars.FirstOrDefault(k => k.key == "missionid").value);
            Assert.AreEqual(true, cottleVars.FirstOrDefault(k => k.key == "abandoned").value);

            var vaVars = vars.AsVoiceAttackVariables("EDDI", ev.type);

            foreach (var @var in vaVars)
            {
                @var.Set(vaProxy);
            }
            Assert.AreEqual(4, vaVars.Count);
            Assert.AreEqual("Water", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI commodity ejected commodity").Value);
            Assert.AreEqual(5, vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI commodity ejected amount").Value);
            Assert.IsNull(vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI commodity ejected missionid").Value);
            Assert.AreEqual(true, vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI commodity ejected abandoned").Value);
            foreach (VoiceAttackVariable variable in vaVars)
            {
                Assert.IsTrue(vaProxy.vaVars.ContainsKey(variable.key), "Unmatched key");
            }
        }
예제 #2
0
        public void TestMalformedCommodityName()
        {
            string malformedCommodityName = "I gotta quote\" and a backslash\\, I'm really bad.";
            var    badCommoditity         = CommodityDefinition.FromNameOrEDName(malformedCommodityName);

            Assert.AreEqual(malformedCommodityName.ToLowerInvariant(), badCommoditity.localizedName);
        }
예제 #3
0
        private void readInventory(CargoMonitorConfiguration configuration = null)
        {
            lock (inventoryLock)
            {
                // Obtain current cargo inventory from configuration
                configuration = configuration ?? CargoMonitorConfiguration.FromFile();
                cargoCarried  = configuration.cargocarried;
                updateDat     = configuration.updatedat;

                // Build a new inventory
                List <Cargo> newInventory = new List <Cargo>();

                // Start with the materials we have in the log
                foreach (Cargo cargo in configuration.cargo)
                {
                    if (cargo.commodityDef == null)
                    {
                        cargo.commodityDef = CommodityDefinition.FromEDName(cargo.edname);
                    }
                    cargo.CalculateNeed();
                    newInventory.Add(cargo);
                }

                // Now order the list by name
                newInventory = newInventory.OrderBy(c => c.invariantName).ToList();

                // Update the inventory
                inventory.Clear();
                foreach (Cargo cargo in newInventory)
                {
                    inventory.Add(cargo);
                }
            }
        }
예제 #4
0
 public CommodityPurchasedEvent(DateTime timestamp, long marketid, CommodityDefinition commodity, int amount, int price) : base(timestamp, NAME)
 {
     this.marketid            = marketid;
     this.amount              = amount;
     this.price               = price;
     this.commodityDefinition = commodity;
 }
예제 #5
0
 public AsteroidProspectedEvent(DateTime timestamp, List <CommodityPresence> commodities, AsteroidMaterialContent materialContent, decimal remaining, CommodityDefinition motherlodeCommodityDefinition) : base(timestamp, NAME)
 {
     this.commodities     = commodities;
     this.materialContent = materialContent;
     this.remaining       = remaining;
     this.motherlodeCommodityDefinition = motherlodeCommodityDefinition;
 }
예제 #6
0
        public void TestCommodityTea()
        {
            CommodityDefinition trinket = CommodityDefinition.FromEDName("Tea");

            Assert.AreEqual("Tea", trinket.edname);
            Assert.AreEqual("Tea", trinket.invariantName);
        }
예제 #7
0
 public CommodityEjectedEvent(DateTime timestamp, CommodityDefinition commodity, int amount, long?missionid, bool abandoned) : base(timestamp, NAME)
 {
     this.commodityDefinition = commodity;
     this.amount    = amount;
     this.missionid = missionid;
     this.abandoned = abandoned;
 }
예제 #8
0
        public void TestCommodityTrinketsOfFortune()
        {
            CommodityDefinition trinket = CommodityDefinition.FromEDName("TrinketsOfFortune");

            Assert.AreEqual("TrinketsOfFortune", trinket.edname);
            Assert.AreEqual("Trinkets Of Hidden Fortune", trinket.invariantName);
        }
예제 #9
0
        public void TestDataDefinitionReactiveArmour()
        {
            CommodityDefinition commodity = CommodityDefinition.FromEDName("$ReactiveArmour_Name;");

            Assert.AreEqual("Reactive Armour", commodity.invariantName);
            Assert.IsNotNull(commodity.EDDBID);
        }
예제 #10
0
 public SearchAndRescueEvent(DateTime timestamp, CommodityDefinition commodity, int?amount, long reward, long marketId) : base(timestamp, NAME)
 {
     this.amount    = amount;
     this.reward    = reward;
     this.commodity = commodity;
     this.marketId  = marketId;
 }
예제 #11
0
        public void TestDataDefinitionUnknownName()
        {
            CommodityDefinition commodity = CommodityDefinition.FromEDName("$MagicStuff_Name;");

            Assert.AreEqual("magicstuff", commodity.invariantName);
            Assert.IsNull(commodity.EDDBID);
        }
예제 #12
0
        public void TestCommodityDrones()
        {
            CommodityDefinition trinket = CommodityDefinition.FromEDName("Drones");

            Assert.AreEqual("Drones", trinket.edname);
            Assert.AreEqual("Limpet", trinket.invariantName);
            Assert.AreEqual("Non-marketable", trinket.category.invariantName);
        }
예제 #13
0
 public CargoWingUpdateEvent(DateTime timestamp, long?missionid, string updatetype, CommodityDefinition commodity, int?amount, int collected, int delivered, int totaltodeliver) : base(timestamp, NAME)
 {
     this.missionid           = missionid;
     this.updatetype          = updatetype;
     this.commodityDefinition = commodity;
     this.amount         = amount;
     this.collected      = collected;
     this.delivered      = delivered;
     this.totaltodeliver = totaltodeliver;
 }
예제 #14
0
 public CommoditySoldEvent(DateTime timestamp, long marketid, CommodityDefinition commodity, int amount, long price, long profit, bool illegal, bool stolen, bool blackmarket) : base(timestamp, NAME)
 {
     this.marketid            = marketid;
     this.amount              = amount;
     this.price               = price;
     this.profit              = profit;
     this.illegal             = illegal;
     this.stolen              = stolen;
     this.blackmarket         = blackmarket;
     this.commodityDefinition = commodity;
 }
예제 #15
0
 private void getContributedResourceDefinition()
 {
     if (contributiontype == "Commodity")
     {
         CommodityDefinition definition = commodityAmount?.commodityDefinition;
         contribution = definition?.localizedName;
         category     = definition?.category?.localizedName;
     }
     else if (contributiontype == "Material")
     {
         Material definition = Material.FromEDName(materialAmount?.edname);
         contribution = definition?.localizedName;
         category     = definition?.Category?.localizedName;
     }
 }
예제 #16
0
        public void TestCommodityMarketQuoteFromMarketJson()
        {
            var info = DeserializeJsonResource <MarketInfo>(Resources.market);
            var expectedMarketInfoItems = new List <MarketInfoItem>()
            {
                new MarketInfoItem(128668550, "$painite_name;", "$MARKET_category_minerals;", 0, 500096, 0, CommodityBracket.None, CommodityBracket.Medium, 0, 200),
                new MarketInfoItem(128673846, "$bromellite_name;", "$MARKET_category_minerals;", 0, 10009, 0, CommodityBracket.None, CommodityBracket.Medium, 0, 100),
                new MarketInfoItem(128673848, "$lowtemperaturediamond_name;", "$MARKET_category_minerals;", 0, 500553, 0, CommodityBracket.None, CommodityBracket.Medium, 0, 150),
                new MarketInfoItem(128924330, "$grandidierite_name;", "$MARKET_category_minerals;", 0, 424204, 0, CommodityBracket.None, CommodityBracket.Medium, 0, 100),
                new MarketInfoItem(128924331, "$alexandrite_name;", "$MARKET_category_minerals;", 0, 348192, 0, CommodityBracket.None, CommodityBracket.Medium, 0, 97),
                new MarketInfoItem(128924332, "$opal_name;", "$MARKET_category_minerals;", 0, 1014218, 0, CommodityBracket.None, CommodityBracket.Medium, 0, 300)
            };

            Assert.AreEqual(3702012928, info.MarketID);
            Assert.AreEqual("X9K-WTW", info.StationName);
            Assert.AreEqual("Gateway", info.StarSystem);
            Assert.AreEqual(expectedMarketInfoItems.Count, info.Items.Count);

            foreach (var item in info.Items)
            {
                // Test that all items match expected definitions
                if (!expectedMarketInfoItems.Exists(i => i.DeepEquals(item)))
                {
                    Assert.Fail();
                }
            }

            // Test that the MarketInfoItem can be sucessfully converted to a definition based CommodityMarketQuote
            var quote = info.Items[0].ToCommodityMarketQuote();

            Assert.AreEqual(128668550, quote.definition.EliteID);
            Assert.AreEqual("Painite", quote.definition.edname);
            Assert.AreEqual("Minerals", quote.definition.Category.invariantName);
            Assert.AreEqual(0, quote.buyprice);
            Assert.AreEqual(500096, quote.sellprice);
            Assert.AreEqual(CommodityDefinition.FromEDName("painite")?.avgprice, quote.avgprice); // Carriers always return an average price of zero. Verify this marches our commodity definition instead.
            Assert.AreEqual(CommodityBracket.None, quote.stockbracket);
            Assert.AreEqual(CommodityBracket.Medium, quote.demandbracket);
            Assert.AreEqual(0, quote.stock);
            Assert.AreEqual(200, quote.demand);
            Assert.AreEqual("Consumer", quote.StatusFlags.First());
        }
예제 #17
0
        public static List <CommodityMarketQuote> CommodityQuotesFromEDDP(JObject json)
        {
            var quotes = new List <CommodityMarketQuote>();

            if (json["commodities"] != null)
            {
                foreach (JObject commodity in json["commodities"])
                {
                    CommodityDefinition  commodityDefinition = CommodityDefinition.FromName((string)commodity["name"]);
                    CommodityMarketQuote quote = new CommodityMarketQuote(commodityDefinition);
                    // Annoyingly, these double-casts seem to be necessary because the boxed type is `long`. A direct cast to `int?` always returns null.
                    quote.buyprice  = (int?)(long?)commodity["buy_price"] ?? quote.buyprice;
                    quote.sellprice = (int?)(long?)commodity["sell_price"] ?? quote.sellprice;
                    quote.demand    = (int?)(long?)commodity["demand"] ?? quote.demand;
                    quote.stock     = (int?)(long?)commodity["supply"] ?? quote.stock;
                    quotes.Add(quote);
                }
            }
            return(quotes);
        }
예제 #18
0
 public MissionAcceptedEvent(DateTime timestamp, long?missionid, string name, string faction, string destinationsystem, string destinationstation, CommodityDefinition commodity, int?amount, string passengertype, bool?passengerswanted, string target, string targettype, string targetfaction, bool communal, DateTime?expiry, string influence, string reputation) : base(timestamp, NAME)
 {
     this.missionid           = missionid;
     this.name                = name;
     this.faction             = faction;
     this.destinationsystem   = destinationsystem;
     this.destinationstation  = destinationstation;
     this.commodity           = commodity?.localizedName;
     this.amount              = amount;
     this.passengertype       = passengertype;
     this.passengerswanted    = passengerswanted;
     this.target              = target;
     this.targettype          = targettype;
     this.targetfaction       = targetfaction;
     this.communal            = communal;
     this.expiry              = expiry;
     this.influence           = influence;
     this.reputation          = reputation;
     this.commodityDefinition = commodity;
 }
예제 #19
0
파일: CapiTests.cs 프로젝트: rodan123/EDDI
        public void TestProfileUpdateStation()
        {
            // Set up our original station
            var originalStation = new Station()
            {
                name      = "Libby Horizons",
                marketId  = 3228854528,
                updatedat = 0
            };

            // Set up our profile station
            var     profile         = new Profile();
            var     marketTimestamp = DateTime.UtcNow;
            JObject marketJson      = DeserializeJsonResource <JObject>(Resources.Libby_Horizons);

            profile.LastStation = CompanionAppService.ProfileStation(marketTimestamp, marketJson);

            var updatedStation = profile.LastStation.UpdateStation(DateTime.UtcNow, originalStation);

            Assert.IsTrue(updatedStation.economyShares.DeepEquals(new List <EconomyShare>()
            {
                new EconomyShare("Refinery", 0.88M),
                new EconomyShare("Industrial", 0.12M)
            }));
            Assert.IsTrue(updatedStation.stationServices.DeepEquals(new List <StationService>()
            {
                StationService.FromEDName("dock"),
                StationService.FromEDName("contacts"),
                StationService.FromEDName("exploration"),
                StationService.FromEDName("commodities"),
                StationService.FromEDName("refuel"),
                StationService.FromEDName("repair"),
                StationService.FromEDName("rearm"),
                StationService.FromEDName("outfitting"),
                StationService.FromEDName("shipyard"),
                StationService.FromEDName("crewlounge"),
                StationService.FromEDName("powerplay"),
                StationService.FromEDName("searchrescue"),
                StationService.FromEDName("materialtrader"),
                StationService.FromEDName("stationmenu"),
                StationService.FromEDName("shop"),
                StationService.FromEDName("engineer"),
            }));
            Assert.AreEqual(116, updatedStation.commodities.Count);
            Assert.IsTrue(new CommodityMarketQuote(CommodityDefinition.FromEDName("Tritium"))
            {
                buyprice      = 41179,
                sellprice     = 40693,
                demand        = 1,
                demandbracket = CommodityBracket.None,
                stock         = 10464,
                stockbracket  = CommodityBracket.Medium,
                StatusFlags   = new HashSet <string>()
                {
                    "Producer"
                }
            }.DeepEquals(updatedStation.commodities.FirstOrDefault(c => c.EliteID == 128961249)));
            Assert.AreEqual(42558, CommodityDefinition.FromEDName("Tritium").avgprice);
            Assert.AreEqual(6, updatedStation.prohibited.Count);
            Assert.IsTrue(CommodityDefinition.FromEDName("Tobacco").DeepEquals(updatedStation.prohibited.FirstOrDefault(p => p.EliteID == 128049213)));
            Assert.AreEqual(Dates.fromDateTimeToSeconds(marketTimestamp), updatedStation.commoditiesupdatedat);
        }
예제 #20
0
 public PowerCommodityObtainedEvent(DateTime timestamp, Power Power, CommodityDefinition commodity, int amount) : base(timestamp, NAME)
 {
     this.Power  = Power;
     this.amount = amount;
     this.commodityDefinition = commodity;
 }
예제 #21
0
 public MissionCompletedEvent(DateTime timestamp, long?missionid, string name, string faction, CommodityDefinition commodity, int?amount, bool communal, long reward, List <string> permitsawarded, List <CommodityAmount> commodityrewards, List <MaterialAmount> materialsrewards, long donation) : base(timestamp, NAME)
 {
     this.missionid           = missionid;
     this.name                = name;
     this.faction             = faction;
     this.commodityDefinition = commodity;
     this.amount              = amount;
     this.communal            = communal;
     this.reward              = reward;
     this.permitsawarded      = permitsawarded;
     this.commodityrewards    = commodityrewards ?? new List <CommodityAmount>();
     this.materialsrewards    = materialsrewards ?? new List <MaterialAmount>();
     this.donation            = donation;
     if (permitsawarded.Count > 0)
     {
         this.rewardPermit = permitsawarded[0];
     }
     if (this.commodityrewards.Count > 0)
     {
         this.rewardCommodity       = commodityrewards[0].commodity;
         this.rewardCommodityAmount = commodityrewards[0].amount;
     }
     if (materialsrewards.Count > 0)
     {
         this.rewardMaterial       = materialsrewards[0].material;
         this.rewardMaterialAmount = materialsrewards[0].amount;
     }
 }
예제 #22
0
 public CommodityAmount(CommodityDefinition commodity, int amount)
 {
     this.commodityDefinition = commodity;
     this.amount = amount;
 }
예제 #23
0
 public MissionCompletedEvent(DateTime timestamp, long?missionid, string name, string faction, CommodityDefinition commodity, int?amount, bool communal, long reward, List <CommodityAmount> commodityrewards, long donation) : base(timestamp, NAME)
 {
     this.missionid           = missionid;
     this.name                = name;
     this.faction             = faction;
     this.commodityDefinition = commodity;
     this.amount              = amount;
     this.communal            = communal;
     this.reward              = reward;
     this.commodityrewards    = commodityrewards ?? new List <CommodityAmount>();
     this.donation            = donation;
     if (this.commodityrewards.Count > 0)
     {
         this.rewardCommodity = commodityrewards[0].commodity;
         this.rewardAmount    = commodityrewards[0].amount;
     }
 }
예제 #24
0
 public PowerCommodityDeliveredEvent(DateTime timestamp, string power, CommodityDefinition commodity, int amount) : base(timestamp, NAME)
 {
     this.power  = power;
     this.amount = amount;
     this.commodityDefinition = commodity;
 }
예제 #25
0
 public CommodityRefinedEvent(DateTime timestamp, CommodityDefinition commodity) : base(timestamp, NAME)
 {
     this.commodityDefinition = commodity;
 }
예제 #26
0
        }                                  // Out of 100

        public CommodityPresence(CommodityDefinition commodity, decimal percentage)
        {
            this.commodityDefinition = commodity;
            this.percentage          = percentage;
        }
예제 #27
0
 public CommodityCollectedEvent(DateTime timestamp, CommodityDefinition commodity, long?missionid, bool stolen) : base(timestamp, NAME)
 {
     this.commodityDefinition = commodity;
     this.missionid           = missionid;
     this.stolen = stolen;
 }
예제 #28
0
        public Station UpdateStation(DateTime profileTimeStamp, Station station)
        {
            if (station.updatedat > Dates.fromDateTimeToSeconds(profileTimeStamp))
            {
                // The current station is already more up to date
                return(station);
            }
            if (station.marketId != marketId)
            {
                // The market IDs do not match, the stations are not the same
                return(station);
            }

            try
            {
                station.economyShares   = economyShares.Select(e => e.ToEconomyShare()).ToList();
                station.stationServices = stationServices.Select(s => StationService.FromEDName(s.Key)).ToList();
            }
            catch (Exception e)
            {
                var data = new Dictionary <string, object>()
                {
                    { "Exception", e },
                    { "Profile economy shares", economyShares },
                    { "Profile station services", stationServices },
                    { "Station", station }
                };
                Logging.Error("Failed to update station economy and services from profile.", data);
            }

            if (commoditiesupdatedat != null && (station.commoditiesupdatedat ?? 0) < commoditiesupdatedat)
            {
                try
                {
                    station.commodities          = eddnCommodityMarketQuotes.Select(c => c.ToCommodityMarketQuote()).ToList();
                    station.prohibited           = prohibitedCommodities.Select(p => CommodityDefinition.CommodityDefinitionFromEliteID(p.Key) ?? CommodityDefinition.FromEDName(p.Value)).ToList();
                    station.commoditiesupdatedat = commoditiesupdatedat;
                }
                catch (Exception e)
                {
                    var data = new Dictionary <string, object>()
                    {
                        { "Exception", e },
                        { "Profile commodity quotes", eddnCommodityMarketQuotes },
                        { "Profile prohibited commodities", prohibitedCommodities },
                        { "Station", station }
                    };
                    Logging.Error("Failed to update station market from profile.", data);
                }
            }
            if (outfittingupdatedat != null && (station.outfittingupdatedat ?? 0) < outfittingupdatedat)
            {
                try
                {
                    station.outfitting          = outfitting.Select(m => m.ToModule()).ToList();
                    station.outfittingupdatedat = outfittingupdatedat;
                }
                catch (Exception e)
                {
                    var data = new Dictionary <string, object>()
                    {
                        { "Exception", e },
                        { "Profile outiftting", outfitting },
                        { "Station", station }
                    };
                    Logging.Error("Failed to update station outfitting from profile.", data);
                }
            }
            if (shipyardupdatedat != null && (station.shipyardupdatedat ?? 0) < shipyardupdatedat)
            {
                try
                {
                    station.shipyard          = ships.Select(s => s.ToShip()).ToList();
                    station.shipyardupdatedat = shipyardupdatedat;
                }
                catch (Exception e)
                {
                    var data = new Dictionary <string, object>()
                    {
                        { "Exception", e },
                        { "Profile ships", ships },
                        { "Station", station }
                    };
                    Logging.Error("Failed to update station shipyard from profile.", data);
                }
            }
            station.updatedat = Dates.fromDateTimeToSeconds(profileTimeStamp);
            return(station);
        }
예제 #29
0
 public MissionCompletedEvent(DateTime timestamp, long?missionid, string name, string faction, MicroResource microResource, CommodityDefinition commodity, int?amount, bool communal, long reward, List <string> permitsawarded = null, List <CommodityAmount> commodityrewards = null, List <MaterialAmount> materialsrewards = null, List <MicroResourceAmount> microResourceRewards = null, List <MissionFactionEffect> factionEffects = null, long donation = 0) : base(timestamp, NAME)
 {
     this.missionid            = missionid;
     this.name                 = name;
     this.faction              = faction;
     this.commodityDefinition  = commodity;
     this.microResource        = microResource;
     this.amount               = amount;
     this.communal             = communal;
     this.reward               = reward;
     this.permitsawarded       = permitsawarded;
     this.commodityrewards     = commodityrewards;
     this.materialsrewards     = materialsrewards;
     this.microresourcerewards = microResourceRewards;
     this.factionEffects       = factionEffects;
     this.donation             = donation;
     if (permitsawarded?.Count > 0)
     {
         this.rewardPermit = permitsawarded[0];
     }
     if (this.commodityrewards?.Count > 0)
     {
         this.rewardCommodity       = commodityrewards[0].commodity;
         this.rewardCommodityAmount = commodityrewards[0].amount;
     }
     if (materialsrewards?.Count > 0)
     {
         this.rewardMaterial       = materialsrewards[0].material;
         this.rewardMaterialAmount = materialsrewards[0].amount;
     }
     if (microResourceRewards?.Count > 0)
     {
         this.rewardMicroResource       = microResourceRewards[0].microResource?.localizedName;
         this.rewardMicroResourceAmount = microResourceRewards[0].amount;
     }
 }
예제 #30
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);
        }