From b30542130bf4b12959a808f063c3bbbac64756df Mon Sep 17 00:00:00 2001 From: T'kael Date: Sun, 23 Jun 2024 00:02:38 -0700 Subject: [PATCH 01/36] Initial commit to update Cottle to latest version. Some objects are not being parsed correctly still. --- SpeechResponder/ConfigurationWindow.xaml.cs | 2 +- .../CustomFunctions/BlueprintDetails.cs | 15 +- .../CustomFunctions/BodyDetails.cs | 10 +- .../CustomFunctions/CargoDetails.cs | 19 ++- .../CustomFunctions/CombatRatingDetails.cs | 15 +- .../CustomFunctions/CommanderName.cs | 4 +- .../CustomFunctions/CommodityMarketDetails.cs | 22 +-- SpeechResponder/CustomFunctions/Distance.cs | 30 ++-- .../CustomFunctions/EconomyDetails.cs | 14 +- SpeechResponder/CustomFunctions/Emphasize.cs | 4 +- .../CustomFunctions/EmpireRatingDetails.cs | 15 +- .../CustomFunctions/EngineerDetails.cs | 12 +- .../ExplorationRatingDetails.cs | 15 +- SpeechResponder/CustomFunctions/F.cs | 22 +-- .../CustomFunctions/FactionDetails.cs | 8 +- .../FederationRatingDetails.cs | 15 +- .../CustomFunctions/GalnetNewsArticle.cs | 12 +- .../CustomFunctions/GalnetNewsArticles.cs | 8 +- .../CustomFunctions/GalnetNewsDelete.cs | 9 +- .../CustomFunctions/GalnetNewsMarkRead.cs | 9 +- .../CustomFunctions/GalnetNewsMarkUnread.cs | 9 +- SpeechResponder/CustomFunctions/GetState.cs | 27 ++++ .../CustomFunctions/GovernmentDetails.cs | 14 +- .../CustomFunctions/HaulageDetails.cs | 14 +- SpeechResponder/CustomFunctions/Humanise.cs | 7 +- SpeechResponder/CustomFunctions/ICAO.cs | 23 +-- .../CustomFunctions/InaraDetails.cs | 20 ++- .../CustomFunctions/JumpDetails.cs | 18 +-- SpeechResponder/CustomFunctions/List.cs | 37 ++--- SpeechResponder/CustomFunctions/Log.cs | 8 +- .../CustomFunctions/MaterialDetails.cs | 14 +- .../CustomFunctions/MissionDetails.cs | 12 +- .../CustomFunctions/Occasionally.cs | 36 +++-- SpeechResponder/CustomFunctions/OneOf.cs | 36 +++-- .../CustomFunctions/OrbitalVelocity.cs | 12 +- SpeechResponder/CustomFunctions/P.cs | 10 +- SpeechResponder/CustomFunctions/Pause.cs | 7 +- SpeechResponder/CustomFunctions/Play.cs | 10 +- .../CustomFunctions/RefreshProfile.cs | 6 +- .../CustomFunctions/RouteDetails.cs | 24 +-- .../CustomFunctions/SecondsSince.cs | 13 +- .../CustomFunctions/SecurityLevelDetails.cs | 13 +- .../CustomFunctions/SetClipboard.cs | 8 +- SpeechResponder/CustomFunctions/SetState.cs | 29 ++-- .../CustomFunctions/ShipCallsign.cs | 7 +- .../CustomFunctions/ShipDetails.cs | 12 +- SpeechResponder/CustomFunctions/ShipName.cs | 4 +- SpeechResponder/CustomFunctions/Spacialise.cs | 12 +- .../CustomFunctions/SpeechPitch.cs | 6 +- SpeechResponder/CustomFunctions/SpeechRate.cs | 6 +- .../CustomFunctions/SpeechVolume.cs | 8 +- .../CustomFunctions/StartsWithVowel.cs | 17 +- .../CustomFunctions/StateDetails.cs | 14 +- .../CustomFunctions/StationDetails.cs | 8 +- .../CustomFunctions/SuperpowerDetails.cs | 12 +- .../CustomFunctions/SystemDetails.cs | 26 +-- .../CustomFunctions/TradeRatingDetails.cs | 15 +- .../CustomFunctions/TrafficDetails.cs | 10 +- SpeechResponder/CustomFunctions/Transmit.cs | 21 +-- SpeechResponder/CustomFunctions/Voice.cs | 6 +- .../CustomFunctions/VoiceDetails.cs | 25 +-- SpeechResponder/EddiSpeechResponder.csproj | 13 +- SpeechResponder/EditScriptWindow.xaml.cs | 2 +- .../CustomFunctions.Untranslated.Designer.cs | 20 ++- .../CustomFunctions.Untranslated.resx | 33 ++-- .../ScriptResolverService/ICustomFunction.cs | 37 ++--- .../ScriptResolverService/ScriptResolver.cs | 151 +++++++++--------- Tests/CustomFunctions.cs | 2 +- Tests/GeneratorTests.cs | 21 +-- Tests/ScriptResolverTest.cs | 70 ++++---- Tests/Tests.csproj | 2 +- 71 files changed, 623 insertions(+), 604 deletions(-) create mode 100644 SpeechResponder/CustomFunctions/GetState.cs diff --git a/SpeechResponder/ConfigurationWindow.xaml.cs b/SpeechResponder/ConfigurationWindow.xaml.cs index f8d8e0e87d..ae74a5791e 100644 --- a/SpeechResponder/ConfigurationWindow.xaml.cs +++ b/SpeechResponder/ConfigurationWindow.xaml.cs @@ -85,7 +85,7 @@ public ConfigurationWindow(SpeechResponder speechResponder) { if (speechResponder is null) { return; } this.speechResponder = speechResponder; - customFunctionNames = speechResponder.ScriptResolver.GetCustomFunctions().Select(f => f.name); + customFunctionNames = ScriptResolver.GetCustomFunctions().Select( f => f.name ); Task.Run( GetStandardVariables ); InitializeComponent(); diff --git a/SpeechResponder/CustomFunctions/BlueprintDetails.cs b/SpeechResponder/CustomFunctions/BlueprintDetails.cs index 7b37554540..d72f4e6cc3 100644 --- a/SpeechResponder/CustomFunctions/BlueprintDetails.cs +++ b/SpeechResponder/CustomFunctions/BlueprintDetails.cs @@ -1,9 +1,9 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -14,12 +14,11 @@ public class BlueprintDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.BlueprintDetails; public Type ReturnType => typeof(Blueprint); - public NativeFunction function => new NativeFunction((values) => + + public IFunction function => Function.CreateNative2( ( runtime, blueprintName, blueprintGrade, writer ) => { - string blueprintName = values[0].AsString; - int blueprintGrade = Convert.ToInt32(values[1].AsNumber); - Blueprint result = Blueprint.FromNameAndGrade(blueprintName, blueprintGrade); - return new ReflectionValue(result ?? new object()); - }, 2); + var result = Blueprint.FromNameAndGrade( blueprintName.AsString, Convert.ToInt32(blueprintGrade.AsNumber) ); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + } ); } } diff --git a/SpeechResponder/CustomFunctions/BodyDetails.cs b/SpeechResponder/CustomFunctions/BodyDetails.cs index 6d4386a058..46bb3337f5 100644 --- a/SpeechResponder/CustomFunctions/BodyDetails.cs +++ b/SpeechResponder/CustomFunctions/BodyDetails.cs @@ -1,11 +1,11 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiCore; using EddiDataDefinitions; using EddiDataProviderService; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -16,7 +16,7 @@ public class BodyDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.BodyDetails; public Type ReturnType => typeof( Body ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { StarSystem system; if (values.Count == 0) @@ -32,8 +32,8 @@ public class BodyDetails : ICustomFunction // Named system system = StarSystemSqLiteRepository.Instance.GetOrFetchStarSystem(values[1].AsString, true); } - Body result = system?.bodies?.Find(v => v.bodyname?.ToLowerInvariant() == values[0].AsString?.ToLowerInvariant()); - return new ReflectionValue(result ?? new object()); + var result = system?.bodies?.Find(v => v.bodyname?.ToLowerInvariant() == values[0].AsString?.ToLowerInvariant()); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); }, 1, 2); } } diff --git a/SpeechResponder/CustomFunctions/CargoDetails.cs b/SpeechResponder/CustomFunctions/CargoDetails.cs index f3e502e351..8ebaa2b6b3 100644 --- a/SpeechResponder/CustomFunctions/CargoDetails.cs +++ b/SpeechResponder/CustomFunctions/CargoDetails.cs @@ -1,11 +1,11 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiConfigService; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; using System.Linq; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -16,22 +16,21 @@ public class CargoDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.CargoDetails; public Type ReturnType => typeof( Cargo ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, input, writer ) => { var cargoInventory = ConfigService.Instance.cargoMonitorConfiguration?.cargo; - Cottle.Value value = values[0]; Cargo result = null; - if (value.Type == Cottle.ValueContent.String) + if (input.Type == ValueContent.String) { - var edname = CommodityDefinition.FromNameOrEDName(value.AsString)?.edname; + var edname = CommodityDefinition.FromNameOrEDName(input.AsString)?.edname; result = cargoInventory?.FirstOrDefault(c=> c.edname == edname) ?? new Cargo(edname); } - else if (value.Type == Cottle.ValueContent.Number) + else if (input.Type == ValueContent.Number) { - result = cargoInventory?.FirstOrDefault(c => c.haulageData.FirstOrDefault(h => h.missionid == (long)value.AsNumber) != null); + result = cargoInventory?.FirstOrDefault(c => c.haulageData.FirstOrDefault(h => h.missionid == Convert.ToInt64(input.AsNumber)) != null); } - return new ReflectionValue(result ?? new object()); - }, 1); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/CombatRatingDetails.cs b/SpeechResponder/CustomFunctions/CombatRatingDetails.cs index 7b26f324f6..4025f4f191 100644 --- a/SpeechResponder/CustomFunctions/CombatRatingDetails.cs +++ b/SpeechResponder/CustomFunctions/CombatRatingDetails.cs @@ -1,9 +1,9 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -14,11 +14,12 @@ public class CombatRatingDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.CombatRatingDetails; public Type ReturnType => typeof( CombatRating ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, combatRank, writer ) => { - var result = CombatRating.FromName(values[0].AsString) ?? - CombatRating.FromEDName(values[0].AsString); - return new ReflectionValue(result ?? new object()); - }, 1); + var result = combatRank.Type == ValueContent.Number + ? CombatRating.FromRank( Convert.ToInt32( combatRank.AsNumber) ) + : CombatRating.FromName(combatRank.AsString) ?? CombatRating.FromEDName(combatRank.AsString); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/CommanderName.cs b/SpeechResponder/CustomFunctions/CommanderName.cs index 9a4fce9afb..861ecf4392 100644 --- a/SpeechResponder/CustomFunctions/CommanderName.cs +++ b/SpeechResponder/CustomFunctions/CommanderName.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiCore; using EddiSpeechResponder.Service; using JetBrains.Annotations; @@ -13,6 +13,6 @@ public class CommanderName : ICustomFunction public FunctionCategory Category => FunctionCategory.Phonetic; public string description => Properties.CustomFunctions_Untranslated.CommanderName; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => EDDI.Instance.Cmdr?.SpokenName(), 0, 0); + public IFunction function => Function.CreateNative0( ( runtime, writer ) => EDDI.Instance.Cmdr?.SpokenName() ); } } diff --git a/SpeechResponder/CustomFunctions/CommodityMarketDetails.cs b/SpeechResponder/CustomFunctions/CommodityMarketDetails.cs index 69063422a9..89764a1fe6 100644 --- a/SpeechResponder/CustomFunctions/CommodityMarketDetails.cs +++ b/SpeechResponder/CustomFunctions/CommodityMarketDetails.cs @@ -1,5 +1,4 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiCore; using EddiDataDefinitions; using EddiDataProviderService; @@ -7,6 +6,7 @@ using JetBrains.Annotations; using System; using System.Linq; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -17,7 +17,7 @@ public class CommodityMarketDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.CommodityMarketDetails; public Type ReturnType => typeof( CommodityMarketQuote ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { CommodityMarketQuote result = null; CommodityMarketQuote CommodityDetails(string commodityLocalizedName, Station station) @@ -29,26 +29,26 @@ CommodityMarketQuote CommodityDetails(string commodityLocalizedName, Station sta if (values.Count == 1) { // Named commodity, current station - Station station = EDDI.Instance.CurrentStation; + var 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); + var system = EDDI.Instance.CurrentStarSystem; + var stationName = values[1].AsString; + var 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 = StarSystemSqLiteRepository.Instance.GetOrFetchStarSystem(values[2].AsString); - string stationName = values[1].AsString; - Station station = system?.stations?.FirstOrDefault(v => v.name == stationName); + var system = StarSystemSqLiteRepository.Instance.GetOrFetchStarSystem(values[2].AsString); + var stationName = values[1].AsString; + var station = system?.stations?.FirstOrDefault(v => v.name == stationName); result = CommodityDetails(values[0].AsString, station); } - return new ReflectionValue(result ?? new object()); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); }, 0, 3); } } diff --git a/SpeechResponder/CustomFunctions/Distance.cs b/SpeechResponder/CustomFunctions/Distance.cs index fd882d7118..0b19b2ad5f 100644 --- a/SpeechResponder/CustomFunctions/Distance.cs +++ b/SpeechResponder/CustomFunctions/Distance.cs @@ -1,11 +1,11 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiCore; using EddiDataDefinitions; using EddiDataProviderService; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; using Utilities; namespace EddiSpeechResponder.CustomFunctions @@ -17,10 +17,10 @@ public class Distance : ICustomFunction public FunctionCategory Category => FunctionCategory.Utility; public string description => Properties.CustomFunctions_Untranslated.Distance; public Type ReturnType => typeof( decimal? ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeVariadic( ( runtime, values, writer ) => { - bool numVal = values[0].Type == Cottle.ValueContent.Number; - bool stringVal = values[0].Type == Cottle.ValueContent.String; + var numVal = values[0].Type == ValueContent.Number; + var stringVal = values[0].Type == ValueContent.String; StarSystem curr = null; StarSystem dest = null; @@ -41,23 +41,23 @@ public class Distance : ICustomFunction { return $"Unable to calculate distance between {curr.systemname} and {dest.systemname}. Could not obtain system coordinates."; } - return new ReflectionValue(result); + return Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); } else if (values.Count == 6 && numVal) { - var x1 = values[0].AsNumber; - var y1 = values[1].AsNumber; - var z1 = values[2].AsNumber; - var x2 = values[3].AsNumber; - var y2 = values[4].AsNumber; - var z2 = values[5].AsNumber; - var result = Functions.StellarDistanceLy(x1, y1, z1, x2, y2, z2); - return new ReflectionValue(result); + var x1 = Convert.ToDecimal( values[ 0 ].AsNumber ); + var y1 = Convert.ToDecimal( values[ 1 ].AsNumber ); + var z1 = Convert.ToDecimal( values[ 2 ].AsNumber ); + var x2 = Convert.ToDecimal( values[ 3 ].AsNumber ); + var y2 = Convert.ToDecimal( values[ 4 ].AsNumber ); + var z2 = Convert.ToDecimal( values[ 5 ].AsNumber ); + var result = Functions.StellarDistanceLy( x1, y1, z1, x2, y2, z2 ); + return Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); } else { return "The Distance function is used improperly. Please review the documentation for correct usage."; } - }, 1, 6); + }); } } diff --git a/SpeechResponder/CustomFunctions/EconomyDetails.cs b/SpeechResponder/CustomFunctions/EconomyDetails.cs index 72558d4055..6dd5ab256f 100644 --- a/SpeechResponder/CustomFunctions/EconomyDetails.cs +++ b/SpeechResponder/CustomFunctions/EconomyDetails.cs @@ -1,9 +1,9 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -14,11 +14,11 @@ public class EconomyDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.EconomyDetails; public Type ReturnType => typeof( Economy ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, economy, writer ) => { - var result = Economy.FromName(values[0].AsString) ?? - Economy.FromEDName(values[0].AsString); - return new ReflectionValue(result ?? new object()); - }, 1); + var result = Economy.FromName(economy.AsString) ?? + Economy.FromEDName(economy.AsString); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/Emphasize.cs b/SpeechResponder/CustomFunctions/Emphasize.cs index 3fb1232ec4..a1481458b0 100644 --- a/SpeechResponder/CustomFunctions/Emphasize.cs +++ b/SpeechResponder/CustomFunctions/Emphasize.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; @@ -12,7 +12,7 @@ public class Emphasize : ICustomFunction public FunctionCategory Category => FunctionCategory.Phonetic; public string description => Properties.CustomFunctions_Untranslated.Emphasize; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { // We use prosody rather than emphasis so that we can tune the output. // Prosody also seems to be better supported by languages than emphasis. diff --git a/SpeechResponder/CustomFunctions/EmpireRatingDetails.cs b/SpeechResponder/CustomFunctions/EmpireRatingDetails.cs index 2e5d00264f..a80582f6a2 100644 --- a/SpeechResponder/CustomFunctions/EmpireRatingDetails.cs +++ b/SpeechResponder/CustomFunctions/EmpireRatingDetails.cs @@ -1,9 +1,9 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -14,11 +14,12 @@ public class EmpireRatingDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.EmpireRatingDetails; public Type ReturnType => typeof( EmpireRating ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, input, writer ) => { - var result = EmpireRating.FromName(values[0].AsString) ?? - EmpireRating.FromEDName(values[0].AsString); - return new ReflectionValue(result ?? new object()); - }, 1); + var result = input.Type == ValueContent.Number + ? EmpireRating.FromRank(Convert.ToInt32(input.AsNumber)) + : EmpireRating.FromName(input.AsString) ?? EmpireRating.FromEDName(input.AsString); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/EngineerDetails.cs b/SpeechResponder/CustomFunctions/EngineerDetails.cs index 110263718c..f61e12de99 100644 --- a/SpeechResponder/CustomFunctions/EngineerDetails.cs +++ b/SpeechResponder/CustomFunctions/EngineerDetails.cs @@ -1,9 +1,9 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -14,10 +14,10 @@ public class EngineerDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.EngineerDetails; public Type ReturnType => typeof( Engineer ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, input, writer ) => { - Engineer result = Engineer.FromName(values[0].AsString) ?? Engineer.FromSystemName(values[0].AsString); - return new ReflectionValue(result ?? new object()); - }, 1); + Engineer result = Engineer.FromName(input.AsString) ?? Engineer.FromSystemName(input.AsString); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/ExplorationRatingDetails.cs b/SpeechResponder/CustomFunctions/ExplorationRatingDetails.cs index 15c229c54e..3aa3637887 100644 --- a/SpeechResponder/CustomFunctions/ExplorationRatingDetails.cs +++ b/SpeechResponder/CustomFunctions/ExplorationRatingDetails.cs @@ -1,9 +1,9 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -14,11 +14,12 @@ public class ExplorationRatingDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.ExplorationRatingDetails; public Type ReturnType => typeof( ExplorationRating ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, input, writer ) => { - var result = ExplorationRating.FromName(values[0].AsString) ?? - ExplorationRating.FromEDName(values[0].AsString); - return new ReflectionValue(result ?? new object()); - }, 1); + var result = input.Type == ValueContent.Number + ? ExplorationRating.FromRank( Convert.ToInt32( input.AsNumber ) ) + : ExplorationRating.FromName( input.AsString ) ?? ExplorationRating.FromEDName( input.AsString ); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/F.cs b/SpeechResponder/CustomFunctions/F.cs index f74b6967b9..f46ca1009c 100644 --- a/SpeechResponder/CustomFunctions/F.cs +++ b/SpeechResponder/CustomFunctions/F.cs @@ -1,25 +1,29 @@ -using Cottle.Functions; -using Cottle.Stores; +using Cottle; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Collections.Generic; +using System.Linq; namespace EddiSpeechResponder.CustomFunctions { [UsedImplicitly] - public class F : ResolverInstance, ICustomFunction + public class F : RecursiveFunction, ICustomFunction { public string name => "F"; public FunctionCategory Category => FunctionCategory.Utility; public string description => Properties.CustomFunctions_Untranslated.F; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, scriptName, writer ) => { - return resolver.resolveFromName(values[0].AsString, store, false)?.Trim(); - }, 1); - - // Implement nesting - public F(ScriptResolver resolver, BuiltinStore store) : base(resolver, store) + // Use a cascading context consisting of variables set in the current document and variables set prior to resolving + var context = Cottle.Context.CreateCascade(Cottle.Context.CreateCustom(runtime.Globals.ToDictionary(g => g.Key, g => g.Value)), Context ); + var result = scriptName.AsString; + return ScriptResolver.resolveFromName( result, Scripts, context, false )?.Trim(); + }); + + [UsedImplicitly] + public F ( IContext context, Dictionary scripts ) : base( context, scripts ) { } } } diff --git a/SpeechResponder/CustomFunctions/FactionDetails.cs b/SpeechResponder/CustomFunctions/FactionDetails.cs index f0fa8bfa12..42839ecd73 100644 --- a/SpeechResponder/CustomFunctions/FactionDetails.cs +++ b/SpeechResponder/CustomFunctions/FactionDetails.cs @@ -1,11 +1,11 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiBgsService; using EddiCore; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -19,7 +19,7 @@ public class FactionDetails : ICustomFunction private static readonly BgsService bgsService = new BgsService(); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { Faction result; if (values.Count == 0) @@ -34,7 +34,7 @@ public class FactionDetails : ICustomFunction { result = bgsService.GetFactionByName(values[0].AsString, values[1].AsString); } - return new ReflectionValue(result ?? new object()); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); }, 1, 2); } } diff --git a/SpeechResponder/CustomFunctions/FederationRatingDetails.cs b/SpeechResponder/CustomFunctions/FederationRatingDetails.cs index 708f3925d5..fb79899cd5 100644 --- a/SpeechResponder/CustomFunctions/FederationRatingDetails.cs +++ b/SpeechResponder/CustomFunctions/FederationRatingDetails.cs @@ -1,9 +1,9 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -14,11 +14,12 @@ public class FederationRatingDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.FederationRatingDetails; public Type ReturnType => typeof( FederationRating ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, input, writer ) => { - var result = FederationRating.FromName(values[0].AsString) ?? - FederationRating.FromEDName(values[0].AsString); - return new ReflectionValue(result ?? new object()); - }, 1); + var result = input.Type == ValueContent.Number + ? FederationRating.FromRank( Convert.ToInt32( input.AsNumber ) ) + : FederationRating.FromName( input.AsString ) ?? FederationRating.FromEDName( input.AsString ); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/GalnetNewsArticle.cs b/SpeechResponder/CustomFunctions/GalnetNewsArticle.cs index dcf8c9ac3f..5cf489cdb6 100644 --- a/SpeechResponder/CustomFunctions/GalnetNewsArticle.cs +++ b/SpeechResponder/CustomFunctions/GalnetNewsArticle.cs @@ -1,10 +1,10 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiGalnetMonitor; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -15,10 +15,10 @@ public class GalnetNewsArticle : ICustomFunction public FunctionCategory Category => FunctionCategory.Galnet; public string description => Properties.CustomFunctions_Untranslated.GalnetNewsArticle; public Type ReturnType => typeof( News ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreatePure1( ( runtime, uuid ) => { - var result = GalnetSqLiteRepository.Instance.GetArticle(values[0].AsString); - return new ReflectionValue(result ?? new object()); - }, 1); + var result = GalnetSqLiteRepository.Instance.GetArticle(uuid.AsString); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/GalnetNewsArticles.cs b/SpeechResponder/CustomFunctions/GalnetNewsArticles.cs index 8328403197..68dfcb764d 100644 --- a/SpeechResponder/CustomFunctions/GalnetNewsArticles.cs +++ b/SpeechResponder/CustomFunctions/GalnetNewsArticles.cs @@ -1,11 +1,11 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiGalnetMonitor; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; using System.Collections.Generic; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -16,7 +16,7 @@ internal class GalnetNewsArticles : ICustomFunction public FunctionCategory Category => FunctionCategory.Galnet; public string description => Properties.CustomFunctions_Untranslated.GalnetNewsArticles; public Type ReturnType => typeof( List ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { List results = null; if (values.Count == 0) @@ -34,7 +34,7 @@ internal class GalnetNewsArticles : ICustomFunction // Obtain all news of a given category results = GalnetSqLiteRepository.Instance.GetArticles(values[0].AsString, values[1].AsBoolean); } - return new ReflectionValue(results ?? new List()); + return results is null ? Value.EmptyMap : Value.FromReflection( results, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); }, 0, 2); } } diff --git a/SpeechResponder/CustomFunctions/GalnetNewsDelete.cs b/SpeechResponder/CustomFunctions/GalnetNewsDelete.cs index 745914406b..a07cad43ef 100644 --- a/SpeechResponder/CustomFunctions/GalnetNewsDelete.cs +++ b/SpeechResponder/CustomFunctions/GalnetNewsDelete.cs @@ -1,5 +1,4 @@ -using Cottle.Functions; -using EddiDataDefinitions; +using Cottle; using EddiGalnetMonitor; using EddiSpeechResponder.Service; using JetBrains.Annotations; @@ -14,14 +13,14 @@ public class GalnetNewsDelete : ICustomFunction public FunctionCategory Category => FunctionCategory.Galnet; public string description => Properties.CustomFunctions_Untranslated.GalnetNewsDelete; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreatePure1( ( runtime, uuid ) => { - News result = GalnetSqLiteRepository.Instance.GetArticle(values[0].AsString); + var result = GalnetSqLiteRepository.Instance.GetArticle(uuid.AsString); if (result != null) { GalnetSqLiteRepository.Instance.DeleteNews(result); } return ""; - }, 1); + }); } } diff --git a/SpeechResponder/CustomFunctions/GalnetNewsMarkRead.cs b/SpeechResponder/CustomFunctions/GalnetNewsMarkRead.cs index 817ef3c091..4ba3129882 100644 --- a/SpeechResponder/CustomFunctions/GalnetNewsMarkRead.cs +++ b/SpeechResponder/CustomFunctions/GalnetNewsMarkRead.cs @@ -1,5 +1,4 @@ -using Cottle.Functions; -using EddiDataDefinitions; +using Cottle; using EddiGalnetMonitor; using EddiSpeechResponder.Service; using JetBrains.Annotations; @@ -14,14 +13,14 @@ public class GalnetNewsMarkRead : ICustomFunction public FunctionCategory Category => FunctionCategory.Galnet; public string description => Properties.CustomFunctions_Untranslated.GalnetNewsMarkRead; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreatePure1( ( runtime, uuid ) => { - News result = GalnetSqLiteRepository.Instance.GetArticle(values[0].AsString); + var result = GalnetSqLiteRepository.Instance.GetArticle(uuid.AsString); if (result != null) { GalnetSqLiteRepository.Instance.MarkRead(result); } return ""; - }, 1); + }); } } diff --git a/SpeechResponder/CustomFunctions/GalnetNewsMarkUnread.cs b/SpeechResponder/CustomFunctions/GalnetNewsMarkUnread.cs index b46e1299f4..72e4f6885e 100644 --- a/SpeechResponder/CustomFunctions/GalnetNewsMarkUnread.cs +++ b/SpeechResponder/CustomFunctions/GalnetNewsMarkUnread.cs @@ -1,5 +1,4 @@ -using Cottle.Functions; -using EddiDataDefinitions; +using Cottle; using EddiGalnetMonitor; using EddiSpeechResponder.Service; using JetBrains.Annotations; @@ -14,14 +13,14 @@ public class GalnetNewsMarkUnread : ICustomFunction public FunctionCategory Category => FunctionCategory.Galnet; public string description => Properties.CustomFunctions_Untranslated.GalnetNewsMarkUnread; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreatePure1( ( runtime, uuid ) => { - News result = GalnetSqLiteRepository.Instance.GetArticle(values[0].AsString); + var result = GalnetSqLiteRepository.Instance.GetArticle(uuid.AsString); if (result != null) { GalnetSqLiteRepository.Instance.MarkUnread(result); } return ""; - }, 1); + }); } } diff --git a/SpeechResponder/CustomFunctions/GetState.cs b/SpeechResponder/CustomFunctions/GetState.cs new file mode 100644 index 0000000000..d001d2546c --- /dev/null +++ b/SpeechResponder/CustomFunctions/GetState.cs @@ -0,0 +1,27 @@ +using Cottle; +using EddiCore; +using EddiSpeechResponder.Service; +using JetBrains.Annotations; +using System; +using System.Reflection; + +namespace EddiSpeechResponder.CustomFunctions +{ + [UsedImplicitly] + public class GetState : ICustomFunction + { + public string name => "GetState"; + public FunctionCategory Category => FunctionCategory.Utility; + public string description => Properties.CustomFunctions_Untranslated.GetState; + public Type ReturnType => typeof( Value ); + public IFunction function => Function.CreateNative1((runtime, variableName, writer) => + { + var varName = variableName.AsString.ToLowerInvariant().Replace(" ", "_"); + if ( EDDI.Instance.State.TryGetValue( varName, out var result ) ) + { + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + } + return ""; + }); + } +} diff --git a/SpeechResponder/CustomFunctions/GovernmentDetails.cs b/SpeechResponder/CustomFunctions/GovernmentDetails.cs index 628417ba8e..e6eb9b4684 100644 --- a/SpeechResponder/CustomFunctions/GovernmentDetails.cs +++ b/SpeechResponder/CustomFunctions/GovernmentDetails.cs @@ -1,9 +1,9 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -14,11 +14,11 @@ public class GovernmentDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.GovernmentDetails; public Type ReturnType => typeof( Government ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, government, writer ) => { - var result = Government.FromName(values[0].AsString) ?? - Government.FromEDName(values[0].AsString); - return new ReflectionValue(result ?? new object()); - }, 1); + var result = Government.FromName(government.AsString) ?? + Government.FromEDName(government.AsString); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/HaulageDetails.cs b/SpeechResponder/CustomFunctions/HaulageDetails.cs index b66b14cf9d..d452643fa0 100644 --- a/SpeechResponder/CustomFunctions/HaulageDetails.cs +++ b/SpeechResponder/CustomFunctions/HaulageDetails.cs @@ -1,5 +1,4 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiConfigService; using EddiDataDefinitions; using EddiSpeechResponder.Service; @@ -7,6 +6,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -17,11 +17,13 @@ public class HaulageDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.HaulageDetails; public Type ReturnType => typeof( List ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, missionID, writer ) => { var cargo = ConfigService.Instance.cargoMonitorConfiguration?.cargo; - var result = cargo?.FirstOrDefault(c => c.haulageData.FirstOrDefault(h => h.missionid == (long)values[0].AsNumber) != null)?.haulageData; - return new ReflectionValue(result ?? new object()); - }, 1); + var result = cargo + ?.FirstOrDefault( c => c.haulageData.Any( h => h.missionid == Convert.ToInt64( missionID.AsNumber ) ) ) + ?.haulageData; + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/Humanise.cs b/SpeechResponder/CustomFunctions/Humanise.cs index 4cddc57f7e..dc14fa7d03 100644 --- a/SpeechResponder/CustomFunctions/Humanise.cs +++ b/SpeechResponder/CustomFunctions/Humanise.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiSpeechResponder.Service; using EddiSpeechService; using JetBrains.Annotations; @@ -13,9 +13,6 @@ public class Humanise : ICustomFunction public FunctionCategory Category => FunctionCategory.Utility; public string description => Properties.CustomFunctions_Untranslated.Humanise; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => - { - return Translations.Humanize(values[0].AsNumber); - }, 1); + public IFunction function => Function.CreateNative1( ( runtime, input, writer ) => Translations.Humanize( (decimal?)Convert.ToDecimal( input.AsNumber ) ) ); } } diff --git a/SpeechResponder/CustomFunctions/ICAO.cs b/SpeechResponder/CustomFunctions/ICAO.cs index b9f1f16a75..ceeb9159a0 100644 --- a/SpeechResponder/CustomFunctions/ICAO.cs +++ b/SpeechResponder/CustomFunctions/ICAO.cs @@ -1,9 +1,8 @@ -using Cottle.Functions; +using Cottle; using EddiSpeechResponder.Service; using EddiSpeechService; using JetBrains.Annotations; using System; -using Utilities; namespace EddiSpeechResponder.CustomFunctions { @@ -14,22 +13,14 @@ public class ICAO : ICustomFunction public FunctionCategory Category => FunctionCategory.Phonetic; public string description => Properties.CustomFunctions_Untranslated.ICAO; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, input, writer ) => { // Turn a string in to an ICAO definition - string value = values[0].AsString; - if (string.IsNullOrEmpty(value)) - { - return ""; - } + var value = input.AsString; + if (string.IsNullOrEmpty(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); + // Translate to ICAO, removing anything that isn't alphanumeric + return Translations.ICAO( value.ToUpperInvariant().Replace( "[^A-Z0-9]", "" ) ); + }); } } diff --git a/SpeechResponder/CustomFunctions/InaraDetails.cs b/SpeechResponder/CustomFunctions/InaraDetails.cs index f5cd2e0925..5a2131bf21 100644 --- a/SpeechResponder/CustomFunctions/InaraDetails.cs +++ b/SpeechResponder/CustomFunctions/InaraDetails.cs @@ -1,9 +1,9 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiInaraService; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -14,18 +14,16 @@ public class InaraDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.InaraDetails; public Type ReturnType => typeof( InaraCmdr ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, cmdrName, writer ) => { - if (values[0].AsString is string commanderName) + var commanderName = cmdrName.AsString; + if ( !string.IsNullOrWhiteSpace( commanderName ) ) { - if (!string.IsNullOrWhiteSpace(commanderName)) - { - EddiInaraService.IInaraService inaraService = new EddiInaraService.InaraService(); - var result = inaraService.GetCommanderProfile(commanderName); - return new ReflectionValue(result ?? new object()); - } + IInaraService inaraService = new InaraService(); + var result = inaraService.GetCommanderProfile(commanderName); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); } return ""; - }, 1); + }); } } diff --git a/SpeechResponder/CustomFunctions/JumpDetails.cs b/SpeechResponder/CustomFunctions/JumpDetails.cs index 2f293912ec..97d8a33a8a 100644 --- a/SpeechResponder/CustomFunctions/JumpDetails.cs +++ b/SpeechResponder/CustomFunctions/JumpDetails.cs @@ -1,10 +1,10 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiCore; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -15,15 +15,11 @@ public class JumpDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.JumpDetails; public Type ReturnType => typeof( JumpDetail ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, input, writer ) => { - string value = values[0].AsString; - if (string.IsNullOrEmpty(value)) - { - return null; - } - var result = EDDI.Instance.CurrentShip?.JumpDetails(value); - return new ReflectionValue(result ?? new object()); - }, 1); + if (string.IsNullOrEmpty( input.AsString ) ) { return Value.EmptyMap; } + var result = EDDI.Instance.CurrentShip?.JumpDetails( input.AsString ); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/List.cs b/SpeechResponder/CustomFunctions/List.cs index 45ae388594..59568309a4 100644 --- a/SpeechResponder/CustomFunctions/List.cs +++ b/SpeechResponder/CustomFunctions/List.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; @@ -14,30 +14,27 @@ public class List : ICustomFunction public FunctionCategory Category => FunctionCategory.Utility; public string description => Properties.CustomFunctions_Untranslated.List; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, values, writer ) => { - string output = string.Empty; - string localisedAnd = Properties.SpeechResponder.localizedAnd; - if (values.Count == 1) + var output = string.Empty; + var localisedAnd = Properties.SpeechResponder.localizedAnd; + foreach ( var value in values.Fields ) { - foreach (KeyValuePair value in values[0].Fields) + var valueString = value.Value.AsString; + if ( value.Key == 0 ) { - string valueString = value.Value.AsString; - if (value.Key == 0) - { - output = valueString; - } - else if (value.Key < (values[0].Fields.Count - 1)) - { - output = $"{output}, {valueString}"; - } - else - { - output = $"{output}{(values[0].Fields.Count() > 2 ? "," : "")} {localisedAnd} {valueString}"; - } + output = valueString; + } + else if ( value.Key < ( values.Fields.Count - 1 ) ) + { + output = $"{output}, {valueString}"; + } + else + { + output = $"{output}{( values.Fields.Count() > 2 ? "," : "" )} {localisedAnd} {valueString}"; } } return output; - }, 1); + }); } } diff --git a/SpeechResponder/CustomFunctions/Log.cs b/SpeechResponder/CustomFunctions/Log.cs index 494cb81141..b704f0f56b 100644 --- a/SpeechResponder/CustomFunctions/Log.cs +++ b/SpeechResponder/CustomFunctions/Log.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; @@ -13,10 +13,10 @@ public class Log : ICustomFunction public FunctionCategory Category => FunctionCategory.Utility; public string description => Properties.CustomFunctions_Untranslated.Log; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreatePure1( ( runtime, input ) => { - Logging.Info(values[0].AsString); + Logging.Info( input.AsString ); return ""; - }, 1); + }); } } diff --git a/SpeechResponder/CustomFunctions/MaterialDetails.cs b/SpeechResponder/CustomFunctions/MaterialDetails.cs index 038d10e405..ef5ce35714 100644 --- a/SpeechResponder/CustomFunctions/MaterialDetails.cs +++ b/SpeechResponder/CustomFunctions/MaterialDetails.cs @@ -1,10 +1,10 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiDataProviderService; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -15,20 +15,20 @@ public class MaterialDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.MaterialDetails; public Type ReturnType => typeof( Material ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { - Material result = Material.FromName(values[0].AsString); + var result = Material.FromName(values[0].AsString); if (result?.edname != null && values.Count == 2) { - StarSystem starSystem = StarSystemSqLiteRepository.Instance.GetOrFetchStarSystem(values[1].AsString, true); + var starSystem = StarSystemSqLiteRepository.Instance.GetOrFetchStarSystem(values[1].AsString, true); if (starSystem != null) { - Body body = Material.highestPercentBody(result.edname, starSystem.bodies); + var body = Material.highestPercentBody(result.edname, starSystem.bodies); result.bodyname = body?.bodyname; result.bodyshortname = body?.shortname; } } - return new ReflectionValue(result ?? new object()); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); }, 1, 2); } } diff --git a/SpeechResponder/CustomFunctions/MissionDetails.cs b/SpeechResponder/CustomFunctions/MissionDetails.cs index 3f576ef106..ef79606fbb 100644 --- a/SpeechResponder/CustomFunctions/MissionDetails.cs +++ b/SpeechResponder/CustomFunctions/MissionDetails.cs @@ -1,11 +1,11 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiConfigService; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; using System.Linq; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -16,11 +16,11 @@ public class MissionDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.MissionDetails; public Type ReturnType => typeof( Mission ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, missionID, writer ) => { var missions = ConfigService.Instance.missionMonitorConfiguration?.missions.ToList(); - var result = missions?.FirstOrDefault(v => v.missionid == values[0].AsNumber); - return new ReflectionValue(result ?? new object()); - }, 1); + var result = missions?.FirstOrDefault(v => v.missionid == Convert.ToInt64( missionID.AsNumber ) ); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/Occasionally.cs b/SpeechResponder/CustomFunctions/Occasionally.cs index ee85844821..654e1c7aeb 100644 --- a/SpeechResponder/CustomFunctions/Occasionally.cs +++ b/SpeechResponder/CustomFunctions/Occasionally.cs @@ -1,38 +1,40 @@ -using Cottle.Functions; -using Cottle.Stores; +using Cottle; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Collections.Generic; +using System.Linq; namespace EddiSpeechResponder.CustomFunctions { [UsedImplicitly] - public class Occasionally : ResolverInstance, ICustomFunction + public class Occasionally : RecursiveFunction, ICustomFunction { public string name => "Occasionally"; public FunctionCategory Category => FunctionCategory.Dynamic; public string description => Properties.CustomFunctions_Untranslated.Occasionally; public Type ReturnType => typeof( string ); - private static readonly Random random = new Random(); + private static readonly Random random = + new Random( new { n = nameof(Occasionally), dt = DateTime.UtcNow }.GetHashCode() ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative2( ( runtime, n, input, writer ) => { - lock ( random ) + Value result; + if ( random.Next( Convert.ToInt32( n.AsNumber) ) == 0 ) { - if ( random.Next( (int)values[ 0 ].AsNumber ) == 0 ) - { - return resolver?.resolveFromValue( values[ 1 ].AsString, store, false ); - } - else - { - return ""; - } + result = input.AsString; } - }, 2); + else + { + result = ""; + } + var context = Cottle.Context.CreateCascade(Cottle.Context.CreateCustom(runtime.Globals.ToDictionary(g => g.Key, g => g.Value)), Context ); + return ScriptResolver.resolveFromValue( result.AsString, context, false ); + }); - // Implement nesting - public Occasionally(ScriptResolver resolver, BuiltinStore store) : base(resolver, store) + [UsedImplicitly] + public Occasionally ( IContext context, Dictionary scripts ) : base( context, scripts ) { } } } diff --git a/SpeechResponder/CustomFunctions/OneOf.cs b/SpeechResponder/CustomFunctions/OneOf.cs index 77f5117e2f..50a3c459f2 100644 --- a/SpeechResponder/CustomFunctions/OneOf.cs +++ b/SpeechResponder/CustomFunctions/OneOf.cs @@ -1,39 +1,41 @@ using Cottle; -using Cottle.Functions; -using Cottle.Stores; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Collections.Generic; +using System.Linq; namespace EddiSpeechResponder.CustomFunctions { [UsedImplicitly] - public class OneOf : ResolverInstance, ICustomFunction + public class OneOf : RecursiveFunction, ICustomFunction { public string name => "OneOf"; public FunctionCategory Category => FunctionCategory.Dynamic; public string description => Properties.CustomFunctions_Untranslated.OneOf; public Type ReturnType => typeof( string ); - private static readonly Random random = new Random(); - public NativeFunction function => new NativeFunction( ( values ) => + private static readonly Random random = + new Random( new { n = nameof(OneOf), dt = DateTime.UtcNow }.GetHashCode() ); + + public IFunction function => Function.CreateNativeVariadic( ( runtime, values, writer ) => { - lock ( random ) + Value result; + if ( values.Count == 1 && values[ 0 ].Type == ValueContent.Map ) + { + values[ 0 ].Fields.TryGet( random.Next( values[ 0 ].Fields.Count ), out result ); + } + else { - if ( values.Count == 1 && values[ 0 ].Type == ValueContent.Map ) - { - values[ 0 ].Fields.TryGet( random.Next( values[ 0 ].Fields.Count ), out var result ); - return resolver?.resolveFromValue( result?.AsString, store, false ); - } - else - { - return resolver?.resolveFromValue( values[ random.Next( values.Count ) ]?.AsString, store, false ); - } + var rand = random.Next( values.Count ); + result = values[ rand ]; } + var context = Cottle.Context.CreateCascade(Cottle.Context.CreateCustom(runtime.Globals.ToDictionary(g => g.Key, g => g.Value)), Context ); + return ScriptResolver.resolveFromValue( result.AsString, context, false ); } ); - // Implement nesting - public OneOf(ScriptResolver resolver, BuiltinStore store) : base(resolver, store) + [UsedImplicitly] + public OneOf ( IContext context, Dictionary scripts ) : base( context, scripts ) { } } } diff --git a/SpeechResponder/CustomFunctions/OrbitalVelocity.cs b/SpeechResponder/CustomFunctions/OrbitalVelocity.cs index 387dd52c0f..c094178e2c 100644 --- a/SpeechResponder/CustomFunctions/OrbitalVelocity.cs +++ b/SpeechResponder/CustomFunctions/OrbitalVelocity.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiCore; using EddiDataDefinitions; using EddiDataProviderService; @@ -17,7 +17,7 @@ public class OrbitalVelocity : ICustomFunction public string description => Properties.CustomFunctions_Untranslated.OrbitalVelocity; public Type ReturnType => typeof( decimal? ); public static decimal? currentAltitudeMeters = null; - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { Body body; if (values.Count == 0) @@ -26,18 +26,18 @@ public class OrbitalVelocity : ICustomFunction } else if (values.Count == 1 && values[0].AsNumber >= 0) { - currentAltitudeMeters = values[0].AsNumber; + currentAltitudeMeters = Convert.ToDecimal(values[0].AsNumber); body = EDDI.Instance.CurrentStellarBody; } else if (values.Count == 2 && values[0].AsNumber >= 0 && !string.IsNullOrEmpty(values[1].AsString)) { - currentAltitudeMeters = values[0].AsNumber; + currentAltitudeMeters = Convert.ToDecimal(values[0].AsNumber); body = EDDI.Instance.CurrentStarSystem?.bodies? .FirstOrDefault(b => b.bodyname == values[1].AsString); } else if (values.Count == 3 && values[0].AsNumber >= 0 && !string.IsNullOrEmpty(values[1].AsString) && !string.IsNullOrEmpty(values[2].AsString)) { - currentAltitudeMeters = values[0].AsNumber; + currentAltitudeMeters = Convert.ToDecimal(values[0].AsNumber); body = StarSystemSqLiteRepository.Instance.GetOrFetchStarSystem(values[2].AsString)?.bodies? .FirstOrDefault(b => b.bodyname == values[1].AsString); } @@ -53,7 +53,7 @@ public class OrbitalVelocity : ICustomFunction { return "Body not found."; } - return body.GetOrbitalVelocityMetersPerSecond( currentAltitudeMeters ) ?? 0; + return body.GetOrbitalVelocityMetersPerSecond(currentAltitudeMeters) ?? 0; }, 0, 3); } } diff --git a/SpeechResponder/CustomFunctions/P.cs b/SpeechResponder/CustomFunctions/P.cs index 2b53903f5f..dc88d8c49f 100644 --- a/SpeechResponder/CustomFunctions/P.cs +++ b/SpeechResponder/CustomFunctions/P.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiSpeechResponder.Service; using EddiSpeechService; using JetBrains.Annotations; @@ -13,11 +13,11 @@ public class P : ICustomFunction public FunctionCategory Category => FunctionCategory.Phonetic; public string description => Properties.CustomFunctions_Untranslated.P; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer) => { - string val = values[0].AsString; - string type = values.Count > 1 ? values[1].AsString : null; - bool useICAO = SpeechServiceConfiguration.FromFile().EnableIcao; + var val = values[0].AsString; + var type = values.Count > 1 ? values[1].AsString : null; + var useICAO = SpeechServiceConfiguration.FromFile().EnableIcao; return Translations.GetTranslation(val, useICAO, type); }, 1, 2); } diff --git a/SpeechResponder/CustomFunctions/Pause.cs b/SpeechResponder/CustomFunctions/Pause.cs index 6538e61ffe..9704a3e22d 100644 --- a/SpeechResponder/CustomFunctions/Pause.cs +++ b/SpeechResponder/CustomFunctions/Pause.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; @@ -12,9 +12,6 @@ public class Pause : ICustomFunction public FunctionCategory Category => FunctionCategory.Tempo; public string description => Properties.CustomFunctions_Untranslated.Pause; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => - { - return @""; - }, 1); + public IFunction function => Function.CreateNative1( ( runtime, milliseconds, writer ) => @"" ); } } diff --git a/SpeechResponder/CustomFunctions/Play.cs b/SpeechResponder/CustomFunctions/Play.cs index 1110a6cc27..4b80210dfc 100644 --- a/SpeechResponder/CustomFunctions/Play.cs +++ b/SpeechResponder/CustomFunctions/Play.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; @@ -12,20 +12,20 @@ public class Play : ICustomFunction public FunctionCategory Category => FunctionCategory.Utility; public string description => Properties.CustomFunctions_Untranslated.Play; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { // The file to play - string fileName = values[0].AsString; + var fileName = values[0].AsString; // Whether the audio should be played asynchronously - bool async = false; + var async = false; if (values.Count > 1) { async = values[1].AsBoolean; } // The volume override (where 100 is normal max volume) - decimal? volumeOverride = null; + double? volumeOverride = null; if (values.Count > 2) { volumeOverride = values[2].AsNumber; diff --git a/SpeechResponder/CustomFunctions/RefreshProfile.cs b/SpeechResponder/CustomFunctions/RefreshProfile.cs index ecf286e7f5..5ae570a2a8 100644 --- a/SpeechResponder/CustomFunctions/RefreshProfile.cs +++ b/SpeechResponder/CustomFunctions/RefreshProfile.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiCore; using EddiSpeechResponder.Service; using JetBrains.Annotations; @@ -14,9 +14,9 @@ public class RefreshProfile : ICustomFunction public FunctionCategory Category => FunctionCategory.Hidden; public string description => Properties.CustomFunctions_Untranslated.RefreshProfile; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreatePureMinMax( ( runtime, values ) => { - bool stationRefresh = (values.Count != 0 && values[0].AsBoolean); + var stationRefresh = (values.Count != 0 && values[0].AsBoolean); EDDI.Instance.refreshProfile(stationRefresh); return ""; }, 0, 1); diff --git a/SpeechResponder/CustomFunctions/RouteDetails.cs b/SpeechResponder/CustomFunctions/RouteDetails.cs index f1134ebe11..ce545f2dd6 100644 --- a/SpeechResponder/CustomFunctions/RouteDetails.cs +++ b/SpeechResponder/CustomFunctions/RouteDetails.cs @@ -1,11 +1,11 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiCore; using EddiNavigationService; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; using System.Linq; +using System.Reflection; using Utilities; namespace EddiSpeechResponder.CustomFunctions @@ -17,23 +17,24 @@ public class RouteDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.RouteDetails; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { try { - Logging.Debug($"RouteDetails() invoked, arguments: ", values); + Logging.Debug("RouteDetails() invoked, arguments: ", values); + + var query = values?.FirstOrDefault().AsString; - string query = values?.FirstOrDefault()?.AsString; - string result = null; if (string.IsNullOrEmpty(query)) { - return new ReflectionValue(new object()); + return Value.EmptyMap; } if (!Enum.TryParse(query, true, out QueryType queryType)) { Logging.Warn($"The search query '{query}' is unrecognized."); - return new ReflectionValue(new object()); + return Value.EmptyMap; } + // Special case any queries which allow optional arguments string stringArg0 = null; string stringArg1 = null; @@ -120,17 +121,18 @@ public class RouteDetails : ICustomFunction // Execute var @event = NavigationService.Instance?.NavQuery(queryType, stringArg0, stringArg1, numericArg); - if (@event != null) + string result = null; + if ( @event != null) { EDDI.Instance?.enqueueEvent(@event); result = @event.system; } - return new ReflectionValue(result ?? new object()); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); } catch (Exception e) { Logging.Error("Unable to resolve RouteDetails() request", e); - return new ReflectionValue(new object()); + return Value.EmptyMap; } }, 1, 4); } diff --git a/SpeechResponder/CustomFunctions/SecondsSince.cs b/SpeechResponder/CustomFunctions/SecondsSince.cs index 2f1d56e302..b96e127fae 100644 --- a/SpeechResponder/CustomFunctions/SecondsSince.cs +++ b/SpeechResponder/CustomFunctions/SecondsSince.cs @@ -1,5 +1,4 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; @@ -14,14 +13,14 @@ public class SecondsSince : ICustomFunction public FunctionCategory Category => FunctionCategory.Utility; public string description => Properties.CustomFunctions_Untranslated.SecondsSince; public Type ReturnType => typeof( long? ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreatePureMinMax( ( runtime, values ) => { - long? date = values.Count == 1 - ? (long?)values[0].AsNumber + var date = values.Count == 1 + ? (long)values[0].AsNumber : 0; - long? now = Dates.fromDateTimeToSeconds(DateTime.UtcNow); + var now = Dates.fromDateTimeToSeconds(DateTime.UtcNow); - return new ReflectionValue(now - date); + return Value.FromNumber( now - date ); }, 0, 1); } } diff --git a/SpeechResponder/CustomFunctions/SecurityLevelDetails.cs b/SpeechResponder/CustomFunctions/SecurityLevelDetails.cs index fa2293051a..988029063b 100644 --- a/SpeechResponder/CustomFunctions/SecurityLevelDetails.cs +++ b/SpeechResponder/CustomFunctions/SecurityLevelDetails.cs @@ -1,9 +1,9 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -14,11 +14,10 @@ public class SecurityLevelDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.SecurityLevelDetails; public Type ReturnType => typeof( SecurityLevel ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( state, input, writer ) => { - var result = SecurityLevel.FromName(values[0].AsString) ?? - SecurityLevel.FromEDName(values[0].AsString); - return new ReflectionValue(result ?? new object()); - }, 1); + var result = SecurityLevel.FromName(input.AsString) ?? SecurityLevel.FromEDName(input.AsString); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/SetClipboard.cs b/SpeechResponder/CustomFunctions/SetClipboard.cs index f91ca242f8..64b7459604 100644 --- a/SpeechResponder/CustomFunctions/SetClipboard.cs +++ b/SpeechResponder/CustomFunctions/SetClipboard.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; @@ -15,9 +15,9 @@ public class SetClipboard : ICustomFunction public FunctionCategory Category => FunctionCategory.Utility; public string description => Properties.CustomFunctions_Untranslated.SetClipboard; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction( ( values ) => + public IFunction function => Function.CreatePure1( ( runtime, input ) => { - var text = values[0].AsString; + var text = input.AsString; if ( !string.IsNullOrEmpty( text ) ) { var clipboardThread = new Thread( () => @@ -40,6 +40,6 @@ public class SetClipboard : ICustomFunction { return "The SetClipboard function is used improperly. Please review the documentation for correct usage."; } - }, 1 ); + } ); } } \ No newline at end of file diff --git a/SpeechResponder/CustomFunctions/SetState.cs b/SpeechResponder/CustomFunctions/SetState.cs index 61ab8091f7..f5e15cef87 100644 --- a/SpeechResponder/CustomFunctions/SetState.cs +++ b/SpeechResponder/CustomFunctions/SetState.cs @@ -1,5 +1,4 @@ -using Cottle.Functions; -using Cottle.Stores; +using Cottle; using EddiCore; using EddiSpeechResponder.Service; using JetBrains.Annotations; @@ -8,42 +7,34 @@ namespace EddiSpeechResponder.CustomFunctions { [UsedImplicitly] - public class SetState : ResolverInstance, ICustomFunction + public class SetState : ICustomFunction { public string name => "SetState"; public FunctionCategory Category => FunctionCategory.Utility; public string description => Properties.CustomFunctions_Untranslated.SetState; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative2((runtime, variableName, variableValue, writer) => { - string varName = values[0].AsString.ToLowerInvariant().Replace(" ", "_"); - Cottle.Value value = values[1]; - if (value.Type == Cottle.ValueContent.Boolean) + var varName = variableName.AsString.ToLowerInvariant().Replace(" ", "_"); + var value = variableValue; + if (value.Type == ValueContent.Boolean) { EDDI.Instance.State[varName] = value.AsBoolean; - store["state"] = ScriptResolver.buildState(); } - else if (value.Type == Cottle.ValueContent.Number) + else if (value.Type == ValueContent.Number) { EDDI.Instance.State[varName] = value.AsNumber; - store["state"] = ScriptResolver.buildState(); } - else if (value.Type == Cottle.ValueContent.String) + else if (value.Type == ValueContent.String) { EDDI.Instance.State[varName] = value.AsString; - store["state"] = ScriptResolver.buildState(); } - else if (value.Type == Cottle.ValueContent.Void) + else if (value.Type == ValueContent.Void) { EDDI.Instance.State[varName] = null; - store["state"] = ScriptResolver.buildState(); } // Ignore other possibilities return ""; - }, 2); - - // Implement nesting - public SetState(ScriptResolver resolver, BuiltinStore store) : base(resolver, store) - { } + }); } } diff --git a/SpeechResponder/CustomFunctions/ShipCallsign.cs b/SpeechResponder/CustomFunctions/ShipCallsign.cs index a1bfcd1690..4564153a9b 100644 --- a/SpeechResponder/CustomFunctions/ShipCallsign.cs +++ b/SpeechResponder/CustomFunctions/ShipCallsign.cs @@ -1,5 +1,4 @@ using Cottle; -using Cottle.Functions; using EddiConfigService; using EddiCore; using EddiDataDefinitions; @@ -21,17 +20,17 @@ public class ShipCallsign : ICustomFunction public FunctionCategory Category => FunctionCategory.Phonetic; public string description => Properties.CustomFunctions_Untranslated.ShipCallsign; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { // The game provides three options for callsigns used by in-game ATC: // (1) CommanderName (default): ship manufacturer name (sometimes partial) + first 3 alphanumeric characters of commander name // (2) ShipName: ship manufacturer name (sometimes partial) + first 3 alphanumeric characters of ship name // (3) ShipID: ship manufacturer name (sometimes partial) + first 3 alphanumeric characters of ship identifier - int? localId = (values.Count < 0 && values[0].Type != ValueContent.Void + var localId = (values.Count < 0 && values[0].Type != ValueContent.Void ? (int)values[0].AsNumber : (int?)null); - int? callsignType = (values.Count > 1 && values[1].Type != ValueContent.Void + var callsignType = (values.Count > 1 && values[1].Type != ValueContent.Void ? (int)values[1].AsNumber : (int?)null); diff --git a/SpeechResponder/CustomFunctions/ShipDetails.cs b/SpeechResponder/CustomFunctions/ShipDetails.cs index eabae5eb39..8156b2cf4c 100644 --- a/SpeechResponder/CustomFunctions/ShipDetails.cs +++ b/SpeechResponder/CustomFunctions/ShipDetails.cs @@ -1,9 +1,9 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; using System.Text.RegularExpressions; namespace EddiSpeechResponder.CustomFunctions @@ -15,11 +15,11 @@ public class ShipDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.ShipDetails; public Type ReturnType => typeof( Ship ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, shipModel, writer ) => { // The inputs to this function might include phonetic SSML tags // (to improve phonetic pronunciations). We'll need to strip those. - var tidiedModel = Regex.Replace(values[0].AsString, @"", string.Empty); + var tidiedModel = Regex.Replace(shipModel.AsString, @"", string.Empty); tidiedModel = Regex.Replace(tidiedModel, @"<\/phoneme>", string.Empty); tidiedModel = tidiedModel // Ship models with mark numbers need to be reverted to abbreviated forms .Replace(" Mark 1", " Mk. I") @@ -30,7 +30,7 @@ public class ShipDetails : ICustomFunction tidiedModel = tidiedModel.Trim(); var result = ShipDefinitions.FromModel(tidiedModel); - return new ReflectionValue(result ?? new object()); - }, 1); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/ShipName.cs b/SpeechResponder/CustomFunctions/ShipName.cs index 06b2f6633d..b964f03780 100644 --- a/SpeechResponder/CustomFunctions/ShipName.cs +++ b/SpeechResponder/CustomFunctions/ShipName.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiConfigService; using EddiCore; using EddiDataDefinitions; @@ -17,7 +17,7 @@ public class ShipName : ICustomFunction public FunctionCategory Category => FunctionCategory.Phonetic; public string description => Properties.CustomFunctions_Untranslated.ShipName; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { int? localId = (values.Count == 0 ? (int?) null : (int) values[0].AsNumber); string model = (values.Count == 2 ? values[1].AsString : null); diff --git a/SpeechResponder/CustomFunctions/Spacialise.cs b/SpeechResponder/CustomFunctions/Spacialise.cs index 184064365e..e534880d58 100644 --- a/SpeechResponder/CustomFunctions/Spacialise.cs +++ b/SpeechResponder/CustomFunctions/Spacialise.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiSpeechResponder.Service; using EddiSpeechService; using JetBrains.Annotations; @@ -13,11 +13,11 @@ public class Spacialise : ICustomFunction public FunctionCategory Category => FunctionCategory.Utility; public string description => Properties.CustomFunctions_Untranslated.Spacialise; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, input, writer ) => { - if (values[0].AsString == null) { return ""; } - bool useICAO = SpeechServiceConfiguration.FromFile().EnableIcao; - return Translations.sayAsLettersOrNumbers(values[0].AsString, false, useICAO); - }, 1); + if ( string.IsNullOrEmpty( input.AsString ) ) { return ""; } + var useICAO = SpeechServiceConfiguration.FromFile().EnableIcao; + return Translations.sayAsLettersOrNumbers( input.AsString, false, useICAO ); + }); } } diff --git a/SpeechResponder/CustomFunctions/SpeechPitch.cs b/SpeechResponder/CustomFunctions/SpeechPitch.cs index 2581846b68..3fecef76e3 100644 --- a/SpeechResponder/CustomFunctions/SpeechPitch.cs +++ b/SpeechResponder/CustomFunctions/SpeechPitch.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; @@ -12,7 +12,7 @@ public class SpeechPitch : ICustomFunction public FunctionCategory Category => FunctionCategory.Voice; public string description => Properties.CustomFunctions_Untranslated.SpeechPitch; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { string text = values[0].AsString; if (values.Count == 1 || string.IsNullOrEmpty(values[1].AsString)) @@ -21,7 +21,7 @@ public class SpeechPitch : ICustomFunction } if (values.Count == 2) { - string pitch = values[1].AsString ?? "default"; + string pitch = values[1].AsString; return @"" + text + ""; } return "The SpeechPitch function is used improperly. Please review the documentation for correct usage."; diff --git a/SpeechResponder/CustomFunctions/SpeechRate.cs b/SpeechResponder/CustomFunctions/SpeechRate.cs index ee4106e605..d723a02350 100644 --- a/SpeechResponder/CustomFunctions/SpeechRate.cs +++ b/SpeechResponder/CustomFunctions/SpeechRate.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; @@ -12,7 +12,7 @@ public class SpeechRate : ICustomFunction public FunctionCategory Category => FunctionCategory.Tempo; public string description => Properties.CustomFunctions_Untranslated.SpeechRate; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { string text = values[0].AsString; if (values.Count == 1 || string.IsNullOrEmpty(values[1].AsString)) @@ -21,7 +21,7 @@ public class SpeechRate : ICustomFunction } if (values.Count == 2) { - string rate = values[1].AsString ?? "default"; + string rate = values[1].AsString; return @"" + text + ""; } return "The SpeechRate function is used improperly. Please review the documentation for correct usage."; diff --git a/SpeechResponder/CustomFunctions/SpeechVolume.cs b/SpeechResponder/CustomFunctions/SpeechVolume.cs index e3e3b09bbe..8ff55138ec 100644 --- a/SpeechResponder/CustomFunctions/SpeechVolume.cs +++ b/SpeechResponder/CustomFunctions/SpeechVolume.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; @@ -12,16 +12,16 @@ public class SpeechVolume : ICustomFunction public FunctionCategory Category => FunctionCategory.Voice; public string description => Properties.CustomFunctions_Untranslated.SpeechVolume; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { - string text = values[0].AsString; + var text = values[0].AsString; if (values.Count == 1 || string.IsNullOrEmpty(values[1].AsString)) { return text; } if (values.Count == 2) { - string volume = values[1].AsString ?? "default"; + var volume = values[1].AsString; return @"" + text + ""; } return "The SpeechVolume function is used improperly. Please review the documentation for correct usage."; diff --git a/SpeechResponder/CustomFunctions/StartsWithVowel.cs b/SpeechResponder/CustomFunctions/StartsWithVowel.cs index 5930ad3d4d..7a85218396 100644 --- a/SpeechResponder/CustomFunctions/StartsWithVowel.cs +++ b/SpeechResponder/CustomFunctions/StartsWithVowel.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; @@ -13,18 +13,13 @@ public class StartsWithVowel : ICustomFunction public FunctionCategory Category => FunctionCategory.Utility; public string description => Properties.CustomFunctions_Untranslated.StartsWithVowel; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreatePure1( ( runtime, input) => { - string Entree = values[0].AsString; - if (Entree == "") - { return ""; } + if (string.IsNullOrEmpty( input.AsString )) { return ""; } char[] vowels = { 'a', 'à', 'â', 'ä', 'e', 'ê', 'é', 'è', 'ë', 'i', 'î', 'ï', 'o', 'ô', 'ö', 'u', 'ù', 'û', 'ü', 'œ' }; - char firstCharacter = Entree.ToLower().ToCharArray().ElementAt(0); - bool result = vowels.Contains(firstCharacter); - - return result; - - }, 1); + var firstCharacter = input.AsString.ToLower().ToCharArray().ElementAt(0); + return vowels.Contains( firstCharacter ); + }); } } diff --git a/SpeechResponder/CustomFunctions/StateDetails.cs b/SpeechResponder/CustomFunctions/StateDetails.cs index eff01e93ce..22a97adf58 100644 --- a/SpeechResponder/CustomFunctions/StateDetails.cs +++ b/SpeechResponder/CustomFunctions/StateDetails.cs @@ -1,9 +1,9 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -14,11 +14,11 @@ public class StateDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.StateDetails; public Type ReturnType => typeof( FactionState ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, factionState, writer ) => { - var result = FactionState.FromName(values[0].AsString) ?? - FactionState.FromEDName(values[0].AsString); - return new ReflectionValue(result ?? new object()); - }, 1); + var result = FactionState.FromName(factionState.AsString) ?? + FactionState.FromEDName(factionState.AsString); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/StationDetails.cs b/SpeechResponder/CustomFunctions/StationDetails.cs index 92068eb114..ae64047c9f 100644 --- a/SpeechResponder/CustomFunctions/StationDetails.cs +++ b/SpeechResponder/CustomFunctions/StationDetails.cs @@ -1,5 +1,4 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiCore; using EddiDataDefinitions; using EddiDataProviderService; @@ -7,6 +6,7 @@ using JetBrains.Annotations; using System; using System.Linq; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -17,7 +17,7 @@ public class StationDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.StationDetails; public Type ReturnType => typeof( Station ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { Station result; if (values.Count == 0 || (values.Count > 0 && values[0].AsString?.ToLowerInvariant() == EDDI.Instance.CurrentStation?.name?.ToLowerInvariant())) @@ -39,7 +39,7 @@ public class StationDetails : ICustomFunction } result = system != null && system.stations != null ? system.stations.FirstOrDefault(v => v.name?.ToLowerInvariant() == values[0].AsString.ToLowerInvariant()) : null; } - return new ReflectionValue(result ?? new object()); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); }, 1, 2); } } diff --git a/SpeechResponder/CustomFunctions/SuperpowerDetails.cs b/SpeechResponder/CustomFunctions/SuperpowerDetails.cs index 0c1e6f7480..d7a0f62ecf 100644 --- a/SpeechResponder/CustomFunctions/SuperpowerDetails.cs +++ b/SpeechResponder/CustomFunctions/SuperpowerDetails.cs @@ -1,9 +1,9 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -14,10 +14,10 @@ public class SuperpowerDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.SuperpowerDetails; public Type ReturnType => typeof( Superpower ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, superpower, writer ) => { - var result = Superpower.FromNameOrEdName(values[0].AsString) ?? Superpower.None; - return new ReflectionValue(result ?? new object()); - }, 1); + var result = Superpower.FromNameOrEdName(superpower.AsString) ?? Superpower.None; + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/SystemDetails.cs b/SpeechResponder/CustomFunctions/SystemDetails.cs index 8693d39b43..e8df444e05 100644 --- a/SpeechResponder/CustomFunctions/SystemDetails.cs +++ b/SpeechResponder/CustomFunctions/SystemDetails.cs @@ -1,11 +1,11 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiCore; using EddiDataDefinitions; using EddiDataProviderService; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; using Utilities; namespace EddiSpeechResponder.CustomFunctions @@ -17,23 +17,13 @@ public class SystemDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.SystemDetails; public Type ReturnType => typeof( StarSystem ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { try { - StarSystem result; - if (values.Count == 0) - { - result = EDDI.Instance.CurrentStarSystem; - } - else if (values.Count > 0 && values[0].AsString?.ToLowerInvariant() == EDDI.Instance.CurrentStarSystem?.systemname?.ToLowerInvariant()) - { - result = EDDI.Instance.CurrentStarSystem; - } - else - { - result = StarSystemSqLiteRepository.Instance.GetOrFetchStarSystem(values[0].AsString, true); - } + var result = values.Count == 0 + ? EDDI.Instance.CurrentStarSystem + : StarSystemSqLiteRepository.Instance.GetOrFetchStarSystem(values[0].AsString, true); var distanceFromHome = result?.DistanceFromStarSystem(EDDI.Instance.HomeStarSystem); if (distanceFromHome != null) @@ -42,12 +32,12 @@ public class SystemDetails : ICustomFunction result.distancefromhome = distanceFromHome; } - return new ReflectionValue(result ?? new object()); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); } catch (Exception e) { return $"The SystemDetails function is used incorrectly. {e.Message}."; } - }, 1); + }, 0, 1); } } diff --git a/SpeechResponder/CustomFunctions/TradeRatingDetails.cs b/SpeechResponder/CustomFunctions/TradeRatingDetails.cs index fe63c56400..5e4085cb8a 100644 --- a/SpeechResponder/CustomFunctions/TradeRatingDetails.cs +++ b/SpeechResponder/CustomFunctions/TradeRatingDetails.cs @@ -1,9 +1,9 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -14,11 +14,12 @@ public class TradeRatingDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.TradeRatingDetails; public Type ReturnType => typeof( TradeRating ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, tradeRating, writer ) => { - var result = TradeRating.FromName(values[0].AsString) ?? - TradeRating.FromEDName(values[0].AsString); - return new ReflectionValue(result ?? new object()); - }, 1); + var result = tradeRating.Type == ValueContent.Number + ? TradeRating.FromRank(Convert.ToInt32(tradeRating.AsNumber)) + : TradeRating.FromName(tradeRating.AsString) ?? TradeRating.FromEDName(tradeRating.AsString); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + }); } } diff --git a/SpeechResponder/CustomFunctions/TrafficDetails.cs b/SpeechResponder/CustomFunctions/TrafficDetails.cs index cf707e50db..e35ace73f0 100644 --- a/SpeechResponder/CustomFunctions/TrafficDetails.cs +++ b/SpeechResponder/CustomFunctions/TrafficDetails.cs @@ -1,10 +1,10 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiDataDefinitions; using EddiDataProviderService; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -18,10 +18,10 @@ public class TrafficDetails : ICustomFunction private static readonly DataProviderService dataProviderService = new DataProviderService(); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { Traffic result = null; - string systemName = values[0].AsString; + var systemName = values[0].AsString; if (!string.IsNullOrEmpty(systemName)) { if (values.Count == 2) @@ -44,7 +44,7 @@ public class TrafficDetails : ICustomFunction result = dataProviderService.GetSystemTraffic(systemName); } } - return new ReflectionValue(result ?? new object()); + return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); }, 1, 2); } } diff --git a/SpeechResponder/CustomFunctions/Transmit.cs b/SpeechResponder/CustomFunctions/Transmit.cs index aae5cfded1..8c12f8aa17 100644 --- a/SpeechResponder/CustomFunctions/Transmit.cs +++ b/SpeechResponder/CustomFunctions/Transmit.cs @@ -1,29 +1,32 @@ -using Cottle.Functions; -using Cottle.Stores; +using Cottle; using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; +using System.Collections.Generic; +using System.Linq; namespace EddiSpeechResponder.CustomFunctions { [UsedImplicitly] - public class Transmit : ResolverInstance, ICustomFunction + public class Transmit : RecursiveFunction, ICustomFunction { public string name => "Transmit"; public FunctionCategory Category => FunctionCategory.Phonetic; public string description => Properties.CustomFunctions_Untranslated.Transmit; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNative1( ( runtime, input, writer ) => { - if (values.Count == 1) + if (!string.IsNullOrEmpty( input.AsString) ) { - return resolver.resolveFromValue(@"" + values[0].AsString + "", store, false); + var result = @"" + input.AsString + ""; + var context = Cottle.Context.CreateCascade(Cottle.Context.CreateCustom(runtime.Globals.ToDictionary(g => g.Key, g => g.Value)), Context ); + return ScriptResolver.resolveFromValue( result, context, false ); } return "The Transmit function is used improperly. Please review the documentation for correct usage."; - }, 1); + }); - // Implement nesting - public Transmit(ScriptResolver resolver, BuiltinStore store) : base(resolver, store) + [UsedImplicitly] + public Transmit ( IContext context, Dictionary scripts ) : base( context, scripts ) { } } } diff --git a/SpeechResponder/CustomFunctions/Voice.cs b/SpeechResponder/CustomFunctions/Voice.cs index f9b0472604..e1d18a0352 100644 --- a/SpeechResponder/CustomFunctions/Voice.cs +++ b/SpeechResponder/CustomFunctions/Voice.cs @@ -1,4 +1,4 @@ -using Cottle.Functions; +using Cottle; using EddiSpeechResponder.Service; using EddiSpeechService; using JetBrains.Annotations; @@ -14,9 +14,9 @@ public class Voice : ICustomFunction public FunctionCategory Category => FunctionCategory.Voice; public string description => Properties.CustomFunctions_Untranslated.Voice; public Type ReturnType => typeof( string ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { - string text = values[0].AsString ?? string.Empty; + string text = values[0].AsString; var voice = SpeechService.Instance.allVoices?.SingleOrDefault(v => string.Equals(v.name, values[1].AsString ?? string.Empty, StringComparison.InvariantCultureIgnoreCase)); if (voice != null && values.Count == 2) { diff --git a/SpeechResponder/CustomFunctions/VoiceDetails.cs b/SpeechResponder/CustomFunctions/VoiceDetails.cs index d9b8356a65..f6e6ff1a3f 100644 --- a/SpeechResponder/CustomFunctions/VoiceDetails.cs +++ b/SpeechResponder/CustomFunctions/VoiceDetails.cs @@ -1,9 +1,9 @@ -using Cottle.Functions; -using Cottle.Values; +using Cottle; using EddiSpeechResponder.Service; using EddiSpeechService; using System; using System.Linq; +using System.Reflection; namespace EddiSpeechResponder.CustomFunctions { @@ -14,15 +14,17 @@ public class VoiceDetails : ICustomFunction public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.VoiceDetails; public Type ReturnType => typeof( VoiceDetails ); - public NativeFunction function => new NativeFunction((values) => + public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { if (values.Count == 0) { if (SpeechService.Instance?.allVoices != null) { - return new ReflectionValue( - SpeechService.Instance.allVoices.FirstOrDefault(v => - v.name == SpeechService.Instance.Configuration.StandardVoice) ?? new object()); + var result = SpeechService.Instance.allVoices.FirstOrDefault( v => + v.name == SpeechService.Instance.Configuration.StandardVoice ); + return result is null + ? Value.EmptyMap + : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); } } @@ -31,17 +33,18 @@ public class VoiceDetails : ICustomFunction if (int.TryParse(values[0].AsString, out var seed) && SpeechService.Instance?.allVoices != null) { var fromSeed = new System.Random(seed); - return new ReflectionValue(SpeechService.Instance.allVoices - .OrderBy(o => fromSeed.Next()).ToList()); + var result = SpeechService.Instance.allVoices + .OrderBy( o => fromSeed.Next() ).ToList(); + return Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); } if (!string.IsNullOrEmpty(values[0].AsString) && SpeechService.Instance?.allVoices != null) { - foreach (var vc in SpeechService.Instance.allVoices) + foreach (var result in SpeechService.Instance.allVoices) { - if (vc.name.ToLowerInvariant().Contains(values[0].AsString.ToLowerInvariant())) + if (result.name.ToLowerInvariant().Contains(values[0].AsString.ToLowerInvariant())) { - return new ReflectionValue(vc); + return Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); } } diff --git a/SpeechResponder/EddiSpeechResponder.csproj b/SpeechResponder/EddiSpeechResponder.csproj index 557c72291a..91d66efedd 100644 --- a/SpeechResponder/EddiSpeechResponder.csproj +++ b/SpeechResponder/EddiSpeechResponder.csproj @@ -73,6 +73,10 @@ Always + + SettingsSingleFileGenerator + Settings.Designer.cs + PreserveNewest @@ -88,7 +92,7 @@ 0.15.1 - 1.4.0.4 + 2.1.0-experimental1 2023.3.0 @@ -121,6 +125,13 @@ + + + True + True + Settings.settings + + 7.0 diff --git a/SpeechResponder/EditScriptWindow.xaml.cs b/SpeechResponder/EditScriptWindow.xaml.cs index 2b0bccd953..ea2d1bd60c 100644 --- a/SpeechResponder/EditScriptWindow.xaml.cs +++ b/SpeechResponder/EditScriptWindow.xaml.cs @@ -50,7 +50,7 @@ public EditScriptWindow ( ScriptResolver scriptResolver, Script script, Dictiona InitializeComponent(); DataContext = this; - this.customFunctions = scriptResolver.GetCustomFunctions(); + this.customFunctions = ScriptResolver.GetCustomFunctions(); this.isNewOrRecoveredScript = isNewOrRecoveredScript; _scripts = scripts; this.script = script; diff --git a/SpeechResponder/Properties/CustomFunctions.Untranslated.Designer.cs b/SpeechResponder/Properties/CustomFunctions.Untranslated.Designer.cs index 6f9eaea7a7..3232b28ea1 100644 --- a/SpeechResponder/Properties/CustomFunctions.Untranslated.Designer.cs +++ b/SpeechResponder/Properties/CustomFunctions.Untranslated.Designer.cs @@ -350,7 +350,25 @@ public static string GalnetNewsMarkUnread { return ResourceManager.GetString("GalnetNewsMarkUnread", resourceCulture); } } - + + /// + /// Looks up a localized string similar to This function will retrieve a session state value. + /// + /// GetState takes one argument: the name of the state value to retrieve. The name of the state value shall be converted to lower-case with spaces changed to underscores. + /// + /// Common usage of this is to retrieve cumulative or persistent information stored using `SetState` during a session, for example: + /// + /// {SetState("distance_travelled_today", state.distance_travelled_today + event.distance)} + /// {set distance to GetState("distance_travelled_today")}. + /// + public static string GetState + { + get + { + return ResourceManager.GetString( "GetState", resourceCulture ); + } + } + /// /// Looks up a localized string similar to This function will provide full information for a government given its name. /// diff --git a/SpeechResponder/Properties/CustomFunctions.Untranslated.resx b/SpeechResponder/Properties/CustomFunctions.Untranslated.resx index 5dd8969280..707ec71453 100644 --- a/SpeechResponder/Properties/CustomFunctions.Untranslated.resx +++ b/SpeechResponder/Properties/CustomFunctions.Untranslated.resx @@ -184,8 +184,9 @@ Common usage of this is to provide further information about a commodity, for ex This function will provide the distance (in light years) between two systems. -Distance() takes either two or six arguments. -- Two argurments, the names of the two systems. +Distance() takes either one, two, or six arguments. +- One argument, the name of the target system (distance calculated relative to the current system) +- Two arguments, the names of the two systems. - Six arguments, the x, y, z coordinates of the two systems. Examples of each usage: @@ -198,7 +199,7 @@ Examples of each usage: EconomyDetails() takes a single argument of the economy for which you want more information. -At current this does not have a lot of use as the economy object only contains its name, but expect it to be expanded in future. +At current this does not have a lot of use as the economy object only contains its name, but this may be expanded in future. This function allows you to give emphasis to specific words (to the extent supported by the voice you are using - your mileage may vary). This function uses SSML tags. @@ -302,7 +303,7 @@ It takes a single mandatory argument, the article uuid to mark as unread. +At current this does not have a lot of use as the government object only contains its name but this may be expanded in future. This function will provide 'haulage' information for a mission-related cargo. See the 'haulage' object for variable details. @@ -534,12 +535,12 @@ Common usage of this is to check how long it has been since a given time, for ex SecurityLevelDetails() takes a single argument of the security level for which you want more information. -At current this does not have a lot of use as the security level object only contains its name, but expect it to be expanded in future. +At current this does not have a lot of use as the security level object only contains its name, but this may be expanded in future. - This function will set a session state value. The value will be available as a property of the 'state' object in future templates within the same EDDI session. + This function will set a session state value. The stored value may be retrieved using the `GetState()` function. -SetState takes two arguments: the name of the state value to set, and its value. The name of the state value will be converted to lower-case and spaces changed to underscores. The value must be either a boolean, a number, or a string; other values will be ignored. +SetState takes two arguments: the name of the state value to set, and its value. The name of the state value will be converted to lower-case and spaces changed to underscores. The value must be either a boolean, a number, a string, or a null / void value; other values will be ignored. Common usage of this is to keep track of the cumulative or persistent information within a session, for example: @@ -629,11 +630,11 @@ Common usage of this is to select the word that should proceed the string (e.g. {if StartsWithVowel(event.name): an |else: a } {event.name} - This function will provide full information for a state given its name. + This function will provide full information for a faction state given its name. -StateDetails() takes a single argument of the state for which you want more information. +StateDetails() takes a single argument of the faction state for which you want more information. -At current this does not have a lot of use as the state object only contains its name, but expect it to be expanded in future. +At current this does not have a lot of use as the state object only contains its name but this may be expanded in future. This function will provide full information for a station given its name and optional system. @@ -650,7 +651,7 @@ Common usage of this is to provide further information about a station, for exam SuperpowerDetails() takes a single argument of the superpower for which you want more information. -At current this does not have a lot of use as the superpower object only contains its name, but expect it to be expanded in future. +At current this does not have a lot of use as the superpower object only contains its name but this may be expanded in future. This function will provide full information for a star system given its name. @@ -765,4 +766,14 @@ Common usage of this is to allow a text string to be pasted outside of EDDI, for {SetClipboard("Shinrarta Dezhra")} + + This function will retrieve a session state value. + +SetState takes one argument: the name of the state value to retrieve. The name of the state value shall be converted to lower-case with spaces changed to underscores. + +Common usage of this is to retrieve cumulative or persistent information stored using `SetState` during a session, for example: + + {SetState("distance_travelled_today", state.distance_travelled_today + event.distance)} + {set distance to GetState("distance_travelled_today")} + \ No newline at end of file diff --git a/SpeechResponder/ScriptResolverService/ICustomFunction.cs b/SpeechResponder/ScriptResolverService/ICustomFunction.cs index a969681bc2..a301782c8f 100644 --- a/SpeechResponder/ScriptResolverService/ICustomFunction.cs +++ b/SpeechResponder/ScriptResolverService/ICustomFunction.cs @@ -1,6 +1,6 @@ -using Cottle.Functions; -using Cottle.Stores; +using Cottle; using System; +using System.Collections.Generic; namespace EddiSpeechResponder.Service { @@ -10,7 +10,20 @@ public interface ICustomFunction FunctionCategory Category { get; } string description { get; } Type ReturnType { get; } - NativeFunction function { get; } + IFunction function { get; } + } + + public class RecursiveFunction + { + public IContext Context { get; } + + public Dictionary Scripts { get; } + + public RecursiveFunction ( IContext context, Dictionary< string, Script > scripts ) + { + this.Context = context; + this.Scripts = scripts; + } } public enum FunctionCategory @@ -24,22 +37,4 @@ public enum FunctionCategory Utility, Voice } - - public abstract class ResolverInstance - { - protected ScriptResolver resolver { get; } - protected BuiltinStore store { get; } - - protected ResolverInstance(T1 parameter1, T2 parameter2) - { - if (parameter1 is ScriptResolver resolverParameter) - { - resolver = resolverParameter; - } - if (parameter2 is BuiltinStore storeParameter) - { - store = storeParameter; - } - } - } } diff --git a/SpeechResponder/ScriptResolverService/ScriptResolver.cs b/SpeechResponder/ScriptResolverService/ScriptResolver.cs index d64f721d61..61325f1e02 100644 --- a/SpeechResponder/ScriptResolverService/ScriptResolver.cs +++ b/SpeechResponder/ScriptResolverService/ScriptResolver.cs @@ -1,10 +1,5 @@ using Cottle; -using Cottle.Builtins; -using Cottle.Documents; using Cottle.Exceptions; -using Cottle.Settings; -using Cottle.Stores; -using Cottle.Values; using Eddi; using EddiCompanionAppService; using EddiCore; @@ -24,38 +19,37 @@ namespace EddiSpeechResponder.Service { public class ScriptResolver { - private readonly Dictionary scripts; - private readonly CustomSetting setting; + public readonly Dictionary Scripts; + public static readonly DocumentConfiguration documentConfiguration = new DocumentConfiguration + { + Trimmer = DocumentConfiguration.TrimRepeatedWhitespaces, NbCycleMax = 10000 + }; // The file to log speech [UsedImplicitly] public static readonly string LogFile = Constants.DATA_DIR + @"\speechresponder.out"; - public ScriptResolver(Dictionary scripts) + public ScriptResolver(Dictionary scripts = null) { - this.scripts = scripts ?? new Dictionary(); - setting = new CustomSetting - { - Trimmer = BuiltinTrimmers.CollapseBlankCharacters - }; + this.Scripts = scripts ?? new Dictionary(); } public int priority(string name) { - scripts.TryGetValue(name, out Script script); + Scripts.TryGetValue(name, out var script); return script?.Priority ?? 3; } - /// From a custom dictionary of variable values in the default store + /// From a custom dictionary of variable values in the default context public string resolveFromName(string name, Dictionary> vars, bool isTopLevelScript) { - BuiltinStore store = buildStore(vars); - return resolveFromName(name, store, isTopLevelScript); + var context = buildContext(vars, Scripts); + return resolveFromName(name, Scripts, context, isTopLevelScript); } - /// From a custom store - public string resolveFromName(string name, BuiltinStore store, bool isTopLevelScript) + /// From a custom context + public static string resolveFromName(string name, IDictionary scripts, IContext context, bool isTopLevelScript) { - if (!scripts.TryGetValue(name, out Script script) || + if (!scripts.TryGetValue(name, out var script) || script?.Value is null) { Logging.Debug($"No {name} script found"); @@ -67,23 +61,23 @@ public string resolveFromName(string name, BuiltinStore store, bool isTopLevelSc return null; } - return resolveFromValue(script.Value, store, isTopLevelScript, script); + return resolveFromValue(script.Value, context, isTopLevelScript, script); } - /// From the default dictionary of variable values in the default store + /// From the default dictionary of variable values in the default context public string resolveFromValue(string scriptValue, bool isTopLevelScript) { var vars = CompileVariables(); - BuiltinStore store = buildStore(vars); - return resolveFromValue(scriptValue, store, isTopLevelScript); + var context = buildContext(vars); + return resolveFromValue(scriptValue, context, isTopLevelScript); } - /// From a custom store - public string resolveFromValue(string script, BuiltinStore store, bool isTopLevelScript, Script scriptObject = null) + /// From a custom context + public static string resolveFromValue(string script, IContext context, bool isTopLevelScript, Script scriptObject = null) { try { - Logging.Debug( $"Resolving {( isTopLevelScript ? "top level " : "" )}script {scriptObject?.Name}: {script}", store ); + Logging.Debug( $"Resolving {( isTopLevelScript ? "top level " : "" )}script {scriptObject?.Name}: {script}", context ); //If this is not a top level script then we need to preserve escape sequence characters (\). if ( !isTopLevelScript ) @@ -91,8 +85,25 @@ public string resolveFromValue(string script, BuiltinStore store, bool isTopLeve script = Regex.Replace( script, @"\\", @"\\\\" ); } - var document = new SimpleDocument( script, setting ); - var result = document.Render( store ); + var documentResult = Document.CreateDefault( script, documentConfiguration ); + if ( !documentResult.Success ) + { + foreach ( var report in documentResult.Reports ) + { + // Errors will be handled through the ParseException class so we're only concerned with warnings and notices here. + if ( report.Severity is DocumentSeverity.Warning ) + { + Logging.Warn( @"Cottle Parser Warning", report ); + } + if ( report.Severity is DocumentSeverity.Notice ) + { + Logging.Debug( @"Cottle Parser Suggestion", report ); + } + } + } + var document = documentResult.DocumentOrThrow; + + var result = document.Render( context ); // Tidy up the output script if ( isTopLevelScript ) @@ -189,72 +200,72 @@ protected internal Dictionary> CompileVariables(Event // Standard objects if ( EDDI.Instance.Cmdr != null ) { - dict[ "cmdr" ] = new Tuple( typeof( Commander ), new ReflectionValue( EDDI.Instance.Cmdr ) ); + dict[ "cmdr" ] = new Tuple( typeof( Commander ), Value.FromReflection( EDDI.Instance.Cmdr, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } if ( EDDI.Instance.HomeStarSystem != null ) { - dict[ "homesystem" ] = new Tuple( typeof( StarSystem ), new ReflectionValue( EDDI.Instance.HomeStarSystem ) ); + dict[ "homesystem" ] = new Tuple( typeof( StarSystem ), Value.FromReflection(EDDI.Instance.HomeStarSystem, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } if ( EDDI.Instance.HomeStation != null ) { - dict[ "homestation" ] = new Tuple( typeof( Station ), new ReflectionValue( EDDI.Instance.HomeStation ) ); + dict[ "homestation" ] = new Tuple( typeof( Station ), Value.FromReflection(EDDI.Instance.HomeStation, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } if ( EDDI.Instance.SquadronStarSystem != null ) { - dict[ "squadronsystem" ] = new Tuple( typeof( StarSystem ), new ReflectionValue( EDDI.Instance.SquadronStarSystem ) ); + dict[ "squadronsystem" ] = new Tuple( typeof( StarSystem ), Value.FromReflection(EDDI.Instance.SquadronStarSystem, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } if ( EDDI.Instance.CurrentStarSystem != null ) { - dict[ "system" ] = new Tuple( typeof( StarSystem ), new ReflectionValue( EDDI.Instance.CurrentStarSystem ) ); + dict[ "system" ] = new Tuple( typeof( StarSystem ), Value.FromReflection(EDDI.Instance.CurrentStarSystem, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } if ( EDDI.Instance.LastStarSystem != null ) { - dict[ "lastsystem" ] = new Tuple( typeof( StarSystem ), new ReflectionValue( EDDI.Instance.LastStarSystem ) ); + dict[ "lastsystem" ] = new Tuple( typeof( StarSystem ), Value.FromReflection(EDDI.Instance.LastStarSystem, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } if ( EDDI.Instance.NextStarSystem != null ) { - dict[ "nextsystem" ] = new Tuple( typeof( StarSystem ), new ReflectionValue( EDDI.Instance.NextStarSystem ) ); + dict[ "nextsystem" ] = new Tuple( typeof( StarSystem ), Value.FromReflection(EDDI.Instance.NextStarSystem, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } if ( EDDI.Instance.DestinationStarSystem != null ) { - dict[ "destinationsystem" ] = new Tuple( typeof( StarSystem ), new ReflectionValue( EDDI.Instance.DestinationStarSystem ) ); + dict[ "destinationsystem" ] = new Tuple( typeof( StarSystem ), Value.FromReflection(EDDI.Instance.DestinationStarSystem, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } if ( NavigationService.Instance.SearchStarSystem != null ) { - dict[ "searchsystem" ] = new Tuple( typeof( StarSystem ), new ReflectionValue( NavigationService.Instance.SearchStarSystem ) ); + dict[ "searchsystem" ] = new Tuple( typeof( StarSystem ), Value.FromReflection(NavigationService.Instance.SearchStarSystem, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } if ( NavigationService.Instance.SearchStation != null ) { - dict[ "searchstation" ] = new Tuple( typeof( Station ), new ReflectionValue( NavigationService.Instance.SearchStation ) ); + dict[ "searchstation" ] = new Tuple( typeof( Station ), Value.FromReflection(NavigationService.Instance.SearchStation, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } if ( EDDI.Instance.CurrentStation != null ) { - dict[ "station" ] = new Tuple( typeof( Station ), new ReflectionValue( EDDI.Instance.CurrentStation ) ); + dict[ "station" ] = new Tuple( typeof( Station ), Value.FromReflection(EDDI.Instance.CurrentStation, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } if ( EDDI.Instance.CurrentStellarBody != null ) { - dict[ "body" ] = new Tuple( typeof( Body ), new ReflectionValue( EDDI.Instance.CurrentStellarBody ) ); + dict[ "body" ] = new Tuple( typeof( Body ), Value.FromReflection(EDDI.Instance.CurrentStellarBody, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } if ( EDDI.Instance.FleetCarrier != null ) { - dict[ "carrier" ] = new Tuple( typeof( FleetCarrier ), new ReflectionValue( EDDI.Instance.FleetCarrier ) ); + dict[ "carrier" ] = new Tuple( typeof( FleetCarrier ), Value.FromReflection(EDDI.Instance.FleetCarrier, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } if ( theEvent != null ) { - dict[ "event" ] = new Tuple( typeof( Event ), new ReflectionValue( theEvent ) ); + dict[ "event" ] = new Tuple( typeof( Event ), Value.FromReflection( theEvent, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } if ( EDDI.Instance.State != null ) @@ -262,14 +273,14 @@ protected internal Dictionary> CompileVariables(Event dict[ "state" ] = new Tuple( typeof( IDictionary), buildState() ); Logging.Debug( "State is: ", EDDI.Instance.State ); } - + // Obtain additional variables from each monitor - foreach ( IEddiMonitor monitor in EDDI.Instance.monitors ) + foreach ( var monitor in EDDI.Instance.monitors ) { var monitorVariables = monitor.GetVariables(); if ( monitorVariables != null ) { - foreach ( string key in monitorVariables.Keys ) + foreach ( var key in monitorVariables.Keys ) { if ( monitorVariables[ key ].Item2 == null ) { @@ -277,7 +288,7 @@ protected internal Dictionary> CompileVariables(Event } else { - dict[ key ] = new Tuple( monitorVariables[ key ].Item1, new ReflectionValue( monitorVariables[ key ]?.Item2 ) ); + dict[ key ] = new Tuple( monitorVariables[ key ].Item1, Value.FromReflection(monitorVariables[key]?.Item2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } } } @@ -287,37 +298,28 @@ protected internal Dictionary> CompileVariables(Event } /// - /// Build a store from a list of variables + /// Build a context from a list of variables /// - public BuiltinStore buildStore(Dictionary> vars = null) + public static IContext buildContext (Dictionary> vars = null, IDictionary scripts = null ) { - BuiltinStore store = new BuiltinStore(); - - // Loop through our custom functions and add them to the store. - foreach (var type in Assembly.GetExecutingAssembly().GetTypes() - .Where(t => t.IsClass && t.GetInterface(nameof(ICustomFunction)) != null)) - { - // Create an instance of the function and add it to the store, - // either with no .ctor or passing data to a .ctor as required (for classes implementing `ResolverInstance`). - var function = (ICustomFunction)(type.GetConstructor(Type.EmptyTypes) != null - ? Activator.CreateInstance(type) : - Activator.CreateInstance(type, this, store)); - if ( function != null ) - { - store.Set( function.name, function.function, StoreMode.Global ); - } - } + var context = new Dictionary(); // Variables if (vars != null) { foreach (var entry in vars) { - store[ entry.Key ] = entry.Value.Item2; + context[ entry.Key ] = entry.Value.Item2; } } - return store; + // Loop through our custom functions and add them to the context. + foreach ( var function in GetCustomFunctions( context, scripts ) ) + { + context[ function.name ] = Value.FromFunction( function.function ); + } + + return Context.CreateBuiltin( context ); } public static Dictionary buildState() @@ -357,18 +359,23 @@ public static Dictionary buildState() return state; } - internal List GetCustomFunctions () + public static List GetCustomFunctions ( Dictionary dict, IDictionary scripts = null ) + { + return GetCustomFunctions( Context.CreateBuiltin( dict ), scripts ); + } + + public static List GetCustomFunctions ( IContext context = null, IDictionary scripts = null ) { var functionsList = new List(); - var assy = Assembly.GetAssembly(typeof(ScriptResolver)); + var assy = Assembly.GetAssembly( typeof(ScriptResolver) ); if ( assy != null ) { foreach ( var type in assy.GetTypes() - .Where( t => t.IsClass && t.GetInterface( nameof( ICustomFunction ) ) != null ) ) + .Where( t => t.IsClass && t.GetInterface( nameof(ICustomFunction) ) != null ) ) { var function = (ICustomFunction)( type.GetConstructor( Type.EmptyTypes ) != null - ? Activator.CreateInstance( type ) - : Activator.CreateInstance( type, this, buildStore() ) ); + ? Activator.CreateInstance( type ) + : Activator.CreateInstance( type, context ?? Context.Empty, scripts ?? new Dictionary() ) ); if ( function != null ) { diff --git a/Tests/CustomFunctions.cs b/Tests/CustomFunctions.cs index 0abac67573..3f68eff911 100644 --- a/Tests/CustomFunctions.cs +++ b/Tests/CustomFunctions.cs @@ -22,7 +22,7 @@ public void start() private string ResolveScript(string script, Dictionary> vars = null) { - return resolver.resolveFromValue(script, resolver.buildStore(vars), true); + return ScriptResolver.resolveFromValue(script, ScriptResolver.buildContext(vars), true); } [DataTestMethod] diff --git a/Tests/GeneratorTests.cs b/Tests/GeneratorTests.cs index 1b64021bfc..74b61a3613 100644 --- a/Tests/GeneratorTests.cs +++ b/Tests/GeneratorTests.cs @@ -1,12 +1,10 @@ -using Cottle.Stores; -using EddiEvents; +using EddiEvents; using EddiSpeechResponder.Service; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Reflection; using Utilities; namespace GeneratorTests @@ -178,22 +176,7 @@ public void TestGenerateEventVariables() public void TestGenerateFunctionsHelp() { // Prepare our functions - var functionsList = new List(); - var resolver = new ScriptResolver(null); - var store = new BuiltinStore(); - var assy = Assembly.GetAssembly(typeof(ScriptResolver)); - foreach (var type in assy.GetTypes() - .Where(t => t.IsClass && t.GetInterface(nameof(ICustomFunction)) != null)) - { - var function = (ICustomFunction)(type.GetConstructor(Type.EmptyTypes) != null - ? Activator.CreateInstance(type) : - Activator.CreateInstance(type, resolver, store)); - - if (function != null) - { - functionsList.Add(function); - } - } + var functionsList = ScriptResolver.GetCustomFunctions(); // Organize functions in alphabetical order (except exclude functions that we've flagged as hidden) functionsList = functionsList diff --git a/Tests/ScriptResolverTest.cs b/Tests/ScriptResolverTest.cs index f855716175..3f41991f0f 100644 --- a/Tests/ScriptResolverTest.cs +++ b/Tests/ScriptResolverTest.cs @@ -1,13 +1,10 @@ using Cottle; -using Cottle.Documents; -using Cottle.Functions; -using Cottle.Stores; using EddiSpeechResponder; using EddiSpeechResponder.Service; -using EddiSpeechService; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; +using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Windows; @@ -23,60 +20,63 @@ public void start() MakeSafe(); } + private string Render ( string template, Dictionary vars ) + { + var document = Document.CreateDefault( template ).DocumentOrThrow; + var store = Context.CreateBuiltin( vars ); + return document.Render(store); + } + [TestMethod] public void TestTemplateSimple() { - var document = new SimpleDocument(@"Hello {name}!"); - var store = new BuiltinStore(); - store["name"] = "world"; - var result = document.Render(store); + var template = @"Hello {name}!"; + var vars = new Dictionary { [ "name" ] = "world" }; + + var result = Render(template, vars); Assert.AreEqual("Hello world!", result); } [TestMethod] public void TestTemplateFunctional() { - var document = new SimpleDocument(@"You are entering the {P(system)} system."); - var store = new BuiltinStore(); - store["P"] = new NativeFunction((values) => + var template = @"You are entering the {P(system)} system."; + var vars = new Dictionary { - return Translations.GetTranslation(values[0].AsString); - }, 1); - store["system"] = "Alrai"; - var result = document.Render(store); + ["system"] = "Alrai", + ["P"] = Value.FromFunction(ScriptResolver.GetCustomFunctions().FirstOrDefault(f => f.name == "P")?.function) + }; + + var result = Render( template, vars ); Assert.AreEqual("You are entering the Alrai system.", result); } [TestMethod] public void TestTemplateConditional() { - var document = new SimpleDocument("{if value = 1:foo|else:{if value = 2:bar|else:baz}}"); - var store = new BuiltinStore(); - store["value"] = 1; - var result = document.Render(store); - Assert.AreEqual("foo", result); - store["value"] = 2; - result = document.Render(store); - Assert.AreEqual("bar", result); - store["value"] = 3; - result = document.Render(store); - Assert.AreEqual("baz", result); + var template = @"{if value = 1:foo|else:{if value = 2:bar|else:baz}}"; + var vars = new Dictionary { [ "value" ] = 1 }; + Assert.AreEqual("foo", Render( template, vars ) ); + vars[ "value" ] = 2; + Assert.AreEqual("bar", Render( template, vars ) ); + vars[ "value" ] = 3; + Assert.AreEqual("baz", Render( template, vars ) ); } [TestMethod] public void TestTemplateOneOf() { - Random random = new Random(); - var document = new SimpleDocument("{set result to OneOf(\"a\", \"b\", \"c\", \"d\", null)} The letter is {OneOf(result)}."); - var store = new BuiltinStore(); - store["OneOf"] = new NativeFunction((values) => + var template = "{set result to OneOf(\"a\", \"b\", \"c\", \"d\", null)} The letter is {OneOf(result)}."; + var vars = new Dictionary { - return values[random.Next(values.Count)]; - }); + ["system"] = "Alrai", + ["OneOf"] = Value.FromFunction(ScriptResolver.GetCustomFunctions().FirstOrDefault(f => f.name == "OneOf")?.function) + }; + List results = new List(); for (int i = 0; i < 1000; i++) { - results.Add(document.Render(store).Trim()); + results.Add(Render(template, vars).Trim()); } Assert.IsTrue(results.Contains(@"The letter is a.")); results.RemoveAll(result => result == @"The letter is a."); @@ -107,12 +107,12 @@ public void TestResolverSimple() [TestMethod] public void TestResolverFunctions() { - Dictionary scripts = new Dictionary + var scripts = new Dictionary { {"func", new Script("func", null, false, "Hello {name}")}, {"test", new Script("test", null, false, "Well {F(\"func\")}")} }; - ScriptResolver resolver = new ScriptResolver(scripts); + var resolver = new ScriptResolver(scripts); var dict = new Dictionary> { ["name"] = new Tuple(typeof(string), "world") }; string result = resolver.resolveFromName("test", dict, true); Assert.AreEqual("Well Hello world", result); diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 7d142aa3af..06c58f86e5 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -48,7 +48,7 @@ - 1.4.0.4 + 2.1.0-experimental1 1.2.1.2 From bda012a2ac5a6ced7d71510e23a77d5fb1b14364 Mon Sep 17 00:00:00 2001 From: T'kael Date: Sun, 23 Jun 2024 11:14:52 -0700 Subject: [PATCH 02/36] Fix event object values being reflected using their base type only. --- SpeechResponder/CustomFunctions/List.cs | 1 - SpeechResponder/ScriptResolverService/ScriptResolver.cs | 7 +++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/SpeechResponder/CustomFunctions/List.cs b/SpeechResponder/CustomFunctions/List.cs index 59568309a4..92d2dfbb0e 100644 --- a/SpeechResponder/CustomFunctions/List.cs +++ b/SpeechResponder/CustomFunctions/List.cs @@ -2,7 +2,6 @@ using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; -using System.Collections.Generic; using System.Linq; namespace EddiSpeechResponder.CustomFunctions diff --git a/SpeechResponder/ScriptResolverService/ScriptResolver.cs b/SpeechResponder/ScriptResolverService/ScriptResolver.cs index 61325f1e02..bca6d548ed 100644 --- a/SpeechResponder/ScriptResolverService/ScriptResolver.cs +++ b/SpeechResponder/ScriptResolverService/ScriptResolver.cs @@ -4,7 +4,6 @@ using EddiCompanionAppService; using EddiCore; using EddiDataDefinitions; -using EddiEvents; using EddiNavigationService; using EddiSpeechService; using JetBrains.Annotations; @@ -175,7 +174,7 @@ private static string errorTranslation(string msg) } // Compile variables from the EDDI information - protected internal Dictionary> CompileVariables(Event theEvent = null) + protected internal Dictionary> CompileVariables(dynamic theEvent = null) { var dict = new Dictionary> { @@ -263,9 +262,9 @@ protected internal Dictionary> CompileVariables(Event dict[ "carrier" ] = new Tuple( typeof( FleetCarrier ), Value.FromReflection(EDDI.Instance.FleetCarrier, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } - if ( theEvent != null ) + if ( theEvent != null ) // A dynamic type is used so that Value.FromReflection { - dict[ "event" ] = new Tuple( typeof( Event ), Value.FromReflection( theEvent, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); + dict[ "event" ] = new Tuple( theEvent.GetType(), Value.FromReflection( theEvent, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } if ( EDDI.Instance.State != null ) From a9b5ce950496352e126327e891b35ccae06d87e1 Mon Sep 17 00:00:00 2001 From: T'kael Date: Sun, 23 Jun 2024 11:31:48 -0700 Subject: [PATCH 03/36] Allow `state` to be updated in invoked functions. Values set with `SetState` are now retrievable except in the specific script where `SetState` was invoked. `GetState` may be used to retrieve the variable in that instance if needed. --- SpeechResponder/CustomFunctions/F.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/SpeechResponder/CustomFunctions/F.cs b/SpeechResponder/CustomFunctions/F.cs index f46ca1009c..954f4dfb9f 100644 --- a/SpeechResponder/CustomFunctions/F.cs +++ b/SpeechResponder/CustomFunctions/F.cs @@ -17,9 +17,16 @@ public class F : RecursiveFunction, ICustomFunction public IFunction function => Function.CreateNative1( ( runtime, scriptName, writer ) => { // Use a cascading context consisting of variables set in the current document and variables set prior to resolving - var context = Cottle.Context.CreateCascade(Cottle.Context.CreateCustom(runtime.Globals.ToDictionary(g => g.Key, g => g.Value)), Context ); + var latestGlobalsContext = + Cottle.Context.CreateCustom( runtime.Globals.ToDictionary( g => g.Key, g => g.Value ) ); + var latestStateContext = + Cottle.Context.CreateBuiltin( + new Dictionary { [ "state" ] = ScriptResolver.buildState() } ); + var originalContext = Context; + var joinedContexts = Cottle.Context.CreateCascade(latestGlobalsContext, Cottle.Context.CreateCascade(latestStateContext, originalContext)); + var result = scriptName.AsString; - return ScriptResolver.resolveFromName( result, Scripts, context, false )?.Trim(); + return ScriptResolver.resolveFromName( result, Scripts, joinedContexts, false )?.Trim(); }); [UsedImplicitly] From cf77534a26073cd0f1106dd46d002c2c4a6e2c9a Mon Sep 17 00:00:00 2001 From: T'kael Date: Sun, 23 Jun 2024 11:48:28 -0700 Subject: [PATCH 04/36] Update our function descriptions for `SetState` and `GetState` --- SpeechResponder/Properties/CustomFunctions.Untranslated.resx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SpeechResponder/Properties/CustomFunctions.Untranslated.resx b/SpeechResponder/Properties/CustomFunctions.Untranslated.resx index 707ec71453..17f02a717d 100644 --- a/SpeechResponder/Properties/CustomFunctions.Untranslated.resx +++ b/SpeechResponder/Properties/CustomFunctions.Untranslated.resx @@ -538,7 +538,7 @@ SecurityLevelDetails() takes a single argument of the security level for which y At current this does not have a lot of use as the security level object only contains its name, but this may be expanded in future. - This function will set a session state value. The stored value may be retrieved using the `GetState()` function. + This function will set a session state value. The value will be available in future scripts or child scripts throughout the remainder of the EDDI session as a property of the persistent 'state' object. If you wish to refer to the stored value in the same script where it was stored then please retrieve the value using the 'GetState' function. SetState takes two arguments: the name of the state value to set, and its value. The name of the state value will be converted to lower-case and spaces changed to underscores. The value must be either a boolean, a number, a string, or a null / void value; other values will be ignored. @@ -769,7 +769,7 @@ Common usage of this is to allow a text string to be pasted outside of EDDI, for This function will retrieve a session state value. -SetState takes one argument: the name of the state value to retrieve. The name of the state value shall be converted to lower-case with spaces changed to underscores. +GetState takes one argument: the name of the state value to retrieve. The name of the state value shall be converted to lower-case with spaces changed to underscores. Common usage of this is to retrieve cumulative or persistent information stored using `SetState` during a session, for example: From e3b746df25de089186b1de724e09b2eab8599eff Mon Sep 17 00:00:00 2001 From: Tkael Date: Sun, 23 Jun 2024 21:07:28 -0700 Subject: [PATCH 05/36] Use generic types in GetState rather than using reflection. Use decimal rather than double to store numeric values (for VoiceAttack compatibility) --- SpeechResponder/CustomFunctions/GetState.cs | 26 ++++++++++++++++--- SpeechResponder/CustomFunctions/SetState.cs | 2 +- .../Properties/Settings.Designer.cs | 4 +-- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/SpeechResponder/CustomFunctions/GetState.cs b/SpeechResponder/CustomFunctions/GetState.cs index d001d2546c..f2def4afc0 100644 --- a/SpeechResponder/CustomFunctions/GetState.cs +++ b/SpeechResponder/CustomFunctions/GetState.cs @@ -3,7 +3,7 @@ using EddiSpeechResponder.Service; using JetBrains.Annotations; using System; -using System.Reflection; + namespace EddiSpeechResponder.CustomFunctions { @@ -17,9 +17,29 @@ public class GetState : ICustomFunction public IFunction function => Function.CreateNative1((runtime, variableName, writer) => { var varName = variableName.AsString.ToLowerInvariant().Replace(" ", "_"); - if ( EDDI.Instance.State.TryGetValue( varName, out var result ) ) + if ( EDDI.Instance.State.TryGetValue( varName, out var @value ) ) + { + if ( value is null ) + { + return ""; + } + + if ( @value is bool b ) + { + return b; + } + + if ( @value is decimal d ) + { + return d; + } + + if ( @value is string s ) { - return result is null ? Value.EmptyMap : Value.FromReflection( result, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); + return s; + } + + return $"State variable {varName} does not match any expected type."; } return ""; }); diff --git a/SpeechResponder/CustomFunctions/SetState.cs b/SpeechResponder/CustomFunctions/SetState.cs index f5e15cef87..1c2bd39e2a 100644 --- a/SpeechResponder/CustomFunctions/SetState.cs +++ b/SpeechResponder/CustomFunctions/SetState.cs @@ -23,7 +23,7 @@ public class SetState : ICustomFunction } else if (value.Type == ValueContent.Number) { - EDDI.Instance.State[varName] = value.AsNumber; + EDDI.Instance.State[varName] = Convert.ToDecimal( value.AsNumber ); } else if (value.Type == ValueContent.String) { diff --git a/SpeechResponder/Properties/Settings.Designer.cs b/SpeechResponder/Properties/Settings.Designer.cs index c1c3f411cf..7f6446509f 100644 --- a/SpeechResponder/Properties/Settings.Designer.cs +++ b/SpeechResponder/Properties/Settings.Designer.cs @@ -12,8 +12,8 @@ namespace EddiSpeechResponder.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")] - public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.10.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); From 24f2990f47e6035435315518ec8f3b871d145e11 Mon Sep 17 00:00:00 2001 From: T'kael Date: Sun, 23 Jun 2024 21:27:48 -0700 Subject: [PATCH 06/36] Trim when matching FromName or FromEDName. --- DataDefinitions/ResourceBasedLocalizedEDName.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/DataDefinitions/ResourceBasedLocalizedEDName.cs b/DataDefinitions/ResourceBasedLocalizedEDName.cs index 1122c00ef4..8374c17a66 100644 --- a/DataDefinitions/ResourceBasedLocalizedEDName.cs +++ b/DataDefinitions/ResourceBasedLocalizedEDName.cs @@ -167,14 +167,14 @@ public static T FromName(string from) return null; } - from = from.ToLowerInvariant(); + from = from.ToLowerInvariant().Trim(); T result; lock (resourceLock) { result = allOfThem.FirstOrDefault( v => - v.localizedName.ToLowerInvariant() == from - || v.invariantName.ToLowerInvariant() == from); + v.localizedName.ToLowerInvariant().Trim() == from + || v.invariantName.ToLowerInvariant().Trim() == from); } return result; } @@ -187,14 +187,14 @@ public static T FromEDName(string from) return null; } - string tidiedFrom = from?.Replace(";", "").Replace(" ", "").ToLowerInvariant(); + string tidiedFrom = from?.Replace(";", "").Replace(" ", "").ToLowerInvariant().Trim(); T result; lock (resourceLock) { result = allOfThem.FirstOrDefault( v => v.edname .ToLowerInvariant() - .Replace(";", "") == tidiedFrom); + .Replace(";", "").Trim() == tidiedFrom); } if (result == null) { From 77c47772135ea9e1473032801c7608ba2a47706e Mon Sep 17 00:00:00 2001 From: T'kael Date: Sun, 23 Jun 2024 21:50:52 -0700 Subject: [PATCH 07/36] Cast to dynamic for correct reflection values. --- SpeechResponder/ScriptResolverService/ScriptResolver.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpeechResponder/ScriptResolverService/ScriptResolver.cs b/SpeechResponder/ScriptResolverService/ScriptResolver.cs index bca6d548ed..2dd285e10f 100644 --- a/SpeechResponder/ScriptResolverService/ScriptResolver.cs +++ b/SpeechResponder/ScriptResolverService/ScriptResolver.cs @@ -287,7 +287,7 @@ protected internal Dictionary> CompileVariables(dynam } else { - dict[ key ] = new Tuple( monitorVariables[ key ].Item1, Value.FromReflection(monitorVariables[key]?.Item2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); + dict[ key ] = new Tuple( monitorVariables[ key ].Item1, Value.FromReflection((dynamic)monitorVariables[key]?.Item2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ) ); } } } From cb0417649518ed7ff99f33378ea43911f34e18a4 Mon Sep 17 00:00:00 2001 From: T'kael Date: Sun, 23 Jun 2024 22:36:40 -0700 Subject: [PATCH 08/36] Support integers, provided they can be converted from double within the tolerance we specify --- SpeechResponder/CustomFunctions/GetState.cs | 5 +++++ SpeechResponder/CustomFunctions/SetState.cs | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/SpeechResponder/CustomFunctions/GetState.cs b/SpeechResponder/CustomFunctions/GetState.cs index f2def4afc0..b985d57fd1 100644 --- a/SpeechResponder/CustomFunctions/GetState.cs +++ b/SpeechResponder/CustomFunctions/GetState.cs @@ -34,6 +34,11 @@ public class GetState : ICustomFunction return d; } + if ( @value is int i ) + { + return i; + } + if ( @value is string s ) { return s; diff --git a/SpeechResponder/CustomFunctions/SetState.cs b/SpeechResponder/CustomFunctions/SetState.cs index 1c2bd39e2a..99b65d8331 100644 --- a/SpeechResponder/CustomFunctions/SetState.cs +++ b/SpeechResponder/CustomFunctions/SetState.cs @@ -23,7 +23,14 @@ public class SetState : ICustomFunction } else if (value.Type == ValueContent.Number) { - EDDI.Instance.State[varName] = Convert.ToDecimal( value.AsNumber ); + if ( Math.Abs(value.AsNumber - Convert.ToInt32(value.AsNumber)) < .000000001 ) + { + EDDI.Instance.State[ varName ] = Convert.ToInt32( value.AsNumber ); + } + else + { + EDDI.Instance.State[ varName ] = Convert.ToDecimal( value.AsNumber ); + } } else if (value.Type == ValueContent.String) { From cbdf95c835f37cfdd7793b49edb16946114d7db7 Mon Sep 17 00:00:00 2001 From: Tkael Date: Sun, 23 Jun 2024 22:31:46 -0700 Subject: [PATCH 09/36] `Blueprint make report` script updated to use `GetState` function. --- SpeechResponder/eddi.cs.json | 2 +- SpeechResponder/eddi.de.json | 2 +- SpeechResponder/eddi.hu.json | 2 +- SpeechResponder/eddi.it.json | 2 +- SpeechResponder/eddi.ja.json | 2 +- SpeechResponder/eddi.json | 2 +- SpeechResponder/eddi.ru.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index fec83d4bab..d642f1b275 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch from context / state _}\r\n{set blueprintname to state.blueprint}\r\n{set blueprintgrade to state.blueprintgrade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if !blueprint:\r\n {_ Fetch from context }\r\n {set blueprint to BlueprintDetails(state.eddi_context_blueprint_name, state.eddi_context_blueprint_grade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to _inventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to GetState('eddi_context_blueprint_name')}\r\n{set blueprintgrade to GetState('eddi_context_blueprint_grade')}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index 33b77d1a2d..2cceddb13f 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch from context / state _}\r\n{set blueprintname to state.blueprint}\r\n{set blueprintgrade to state.blueprintgrade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if !blueprint:\r\n {_ Fetch from context }\r\n {set blueprint to BlueprintDetails(state.eddi_context_blueprint_name, state.eddi_context_blueprint_grade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to _inventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to GetState('eddi_context_blueprint_name')}\r\n{set blueprintgrade to GetState('eddi_context_blueprint_grade')}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index a8666c7572..0296a1ad79 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch from context / state _}\r\n{set blueprintname to state.blueprint}\r\n{set blueprintgrade to state.blueprintgrade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if !blueprint:\r\n {_ Fetch from context }\r\n {set blueprint to BlueprintDetails(state.eddi_context_blueprint_name, state.eddi_context_blueprint_grade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to _inventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to GetState('eddi_context_blueprint_name')}\r\n{set blueprintgrade to GetState('eddi_context_blueprint_grade')}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index a8666c7572..0296a1ad79 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch from context / state _}\r\n{set blueprintname to state.blueprint}\r\n{set blueprintgrade to state.blueprintgrade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if !blueprint:\r\n {_ Fetch from context }\r\n {set blueprint to BlueprintDetails(state.eddi_context_blueprint_name, state.eddi_context_blueprint_grade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to _inventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to GetState('eddi_context_blueprint_name')}\r\n{set blueprintgrade to GetState('eddi_context_blueprint_grade')}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index a8666c7572..0296a1ad79 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch from context / state _}\r\n{set blueprintname to state.blueprint}\r\n{set blueprintgrade to state.blueprintgrade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if !blueprint:\r\n {_ Fetch from context }\r\n {set blueprint to BlueprintDetails(state.eddi_context_blueprint_name, state.eddi_context_blueprint_grade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to _inventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to GetState('eddi_context_blueprint_name')}\r\n{set blueprintgrade to GetState('eddi_context_blueprint_grade')}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index 764eff0f39..74ef13e321 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch from context / state _}\r\n{set blueprintname to state.blueprint}\r\n{set blueprintgrade to state.blueprintgrade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if !blueprint:\r\n {_ Fetch from context }\r\n {set blueprint to BlueprintDetails(state.eddi_context_blueprint_name, state.eddi_context_blueprint_grade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to _inventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to GetState('eddi_context_blueprint_name')}\r\n{set blueprintgrade to GetState('eddi_context_blueprint_grade')}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index a8666c7572..0296a1ad79 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch from context / state _}\r\n{set blueprintname to state.blueprint}\r\n{set blueprintgrade to state.blueprintgrade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if !blueprint:\r\n {_ Fetch from context }\r\n {set blueprint to BlueprintDetails(state.eddi_context_blueprint_name, state.eddi_context_blueprint_grade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to _inventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to GetState('eddi_context_blueprint_name')}\r\n{set blueprintgrade to GetState('eddi_context_blueprint_grade')}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" From 1aadaea4cda42b6b90c5fa6550fb2a68b951ac06 Mon Sep 17 00:00:00 2001 From: T'kael Date: Sun, 23 Jun 2024 23:06:27 -0700 Subject: [PATCH 10/36] Update `Blueprint make report` and `Blueprint materials report` - GetState is not required. --- SpeechResponder/eddi.cs.json | 4 ++-- SpeechResponder/eddi.de.json | 4 ++-- SpeechResponder/eddi.hu.json | 4 ++-- SpeechResponder/eddi.it.json | 4 ++-- SpeechResponder/eddi.ja.json | 4 ++-- SpeechResponder/eddi.json | 4 ++-- SpeechResponder/eddi.ru.json | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index d642f1b275..7322df10ff 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to GetState('eddi_context_blueprint_name')}\r\n{set blueprintgrade to GetState('eddi_context_blueprint_grade')}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" @@ -60,7 +60,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch from context / state _}\r\n{set blueprintname to state.blueprint}\r\n{set blueprintgrade to state.blueprintgrade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if blueprintname:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if !blueprint || !blueprintgrade:\r\n {_ Fetch from context }\r\n {set blueprint to BlueprintDetails(state.eddi_context_blueprint_name, state.eddi_context_blueprint_grade)}\r\n}\r\n\r\n{if blueprint && blueprintgrade:\r\n {set materials to len(blueprint.materials)}\r\n {blueprintname} grade {blueprintgrade} requires \r\n {if materials = 1:\r\n {blueprint.materials[0].material}\r\n |elif materials = 2:\r\n {blueprint.materials[0].material} and {blueprint.materials[1].material}\r\n |else:\r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {if cur = 0:\r\n {blueprint.materials[cur].material}\r\n |elif cur < len(blueprint.materials) - 1:\r\n , {blueprint.materials[cur].material}\r\n |else:\r\n , and {blueprint.materials[cur].material}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint material report", "description": "Report on the material requirements for a blueprint" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index 2cceddb13f..0ae48511cf 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to GetState('eddi_context_blueprint_name')}\r\n{set blueprintgrade to GetState('eddi_context_blueprint_grade')}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" @@ -60,7 +60,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch from context / state _}\r\n{set blueprintname to state.blueprint}\r\n{set blueprintgrade to state.blueprintgrade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if blueprintname:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if !blueprint || !blueprintgrade:\r\n {_ Fetch from context }\r\n {set blueprint to BlueprintDetails(state.eddi_context_blueprint_name, state.eddi_context_blueprint_grade)}\r\n}\r\n\r\n{if blueprint && blueprintgrade:\r\n {set materials to len(blueprint.materials)}\r\n {blueprintname} grade {blueprintgrade} requires \r\n {if materials = 1:\r\n {blueprint.materials[0].material}\r\n |elif materials = 2:\r\n {blueprint.materials[0].material} and {blueprint.materials[1].material}\r\n |else:\r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {if cur = 0:\r\n {blueprint.materials[cur].material}\r\n |elif cur < len(blueprint.materials) - 1:\r\n , {blueprint.materials[cur].material}\r\n |else:\r\n , and {blueprint.materials[cur].material}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint material report", "description": "Report on the material requirements for a blueprint" diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index 0296a1ad79..91d5c5db63 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to GetState('eddi_context_blueprint_name')}\r\n{set blueprintgrade to GetState('eddi_context_blueprint_grade')}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" @@ -60,7 +60,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch from context / state _}\r\n{set blueprintname to state.blueprint}\r\n{set blueprintgrade to state.blueprintgrade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if blueprintname:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if !blueprint || !blueprintgrade:\r\n {_ Fetch from context }\r\n {set blueprint to BlueprintDetails(state.eddi_context_blueprint_name, state.eddi_context_blueprint_grade)}\r\n}\r\n\r\n{if blueprint && blueprintgrade:\r\n {set materials to len(blueprint.materials)}\r\n {blueprintname} grade {blueprintgrade} requires \r\n {if materials = 1:\r\n {blueprint.materials[0].material}\r\n |elif materials = 2:\r\n {blueprint.materials[0].material} and {blueprint.materials[1].material}\r\n |else:\r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {if cur = 0:\r\n {blueprint.materials[cur].material}\r\n |elif cur < len(blueprint.materials) - 1:\r\n , {blueprint.materials[cur].material}\r\n |else:\r\n , and {blueprint.materials[cur].material}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint material report", "description": "Report on the material requirements for a blueprint" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index 0296a1ad79..91d5c5db63 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to GetState('eddi_context_blueprint_name')}\r\n{set blueprintgrade to GetState('eddi_context_blueprint_grade')}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" @@ -60,7 +60,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch from context / state _}\r\n{set blueprintname to state.blueprint}\r\n{set blueprintgrade to state.blueprintgrade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if blueprintname:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if !blueprint || !blueprintgrade:\r\n {_ Fetch from context }\r\n {set blueprint to BlueprintDetails(state.eddi_context_blueprint_name, state.eddi_context_blueprint_grade)}\r\n}\r\n\r\n{if blueprint && blueprintgrade:\r\n {set materials to len(blueprint.materials)}\r\n {blueprintname} grade {blueprintgrade} requires \r\n {if materials = 1:\r\n {blueprint.materials[0].material}\r\n |elif materials = 2:\r\n {blueprint.materials[0].material} and {blueprint.materials[1].material}\r\n |else:\r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {if cur = 0:\r\n {blueprint.materials[cur].material}\r\n |elif cur < len(blueprint.materials) - 1:\r\n , {blueprint.materials[cur].material}\r\n |else:\r\n , and {blueprint.materials[cur].material}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint material report", "description": "Report on the material requirements for a blueprint" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index 0296a1ad79..91d5c5db63 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to GetState('eddi_context_blueprint_name')}\r\n{set blueprintgrade to GetState('eddi_context_blueprint_grade')}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" @@ -60,7 +60,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch from context / state _}\r\n{set blueprintname to state.blueprint}\r\n{set blueprintgrade to state.blueprintgrade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if blueprintname:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if !blueprint || !blueprintgrade:\r\n {_ Fetch from context }\r\n {set blueprint to BlueprintDetails(state.eddi_context_blueprint_name, state.eddi_context_blueprint_grade)}\r\n}\r\n\r\n{if blueprint && blueprintgrade:\r\n {set materials to len(blueprint.materials)}\r\n {blueprintname} grade {blueprintgrade} requires \r\n {if materials = 1:\r\n {blueprint.materials[0].material}\r\n |elif materials = 2:\r\n {blueprint.materials[0].material} and {blueprint.materials[1].material}\r\n |else:\r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {if cur = 0:\r\n {blueprint.materials[cur].material}\r\n |elif cur < len(blueprint.materials) - 1:\r\n , {blueprint.materials[cur].material}\r\n |else:\r\n , and {blueprint.materials[cur].material}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint material report", "description": "Report on the material requirements for a blueprint" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index 74ef13e321..ecefe47098 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to GetState('eddi_context_blueprint_name')}\r\n{set blueprintgrade to GetState('eddi_context_blueprint_grade')}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" @@ -60,7 +60,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch from context / state _}\r\n{set blueprintname to state.blueprint}\r\n{set blueprintgrade to state.blueprintgrade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if blueprintname:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if !blueprint || !blueprintgrade:\r\n {_ Fetch from context }\r\n {set blueprint to BlueprintDetails(state.eddi_context_blueprint_name, state.eddi_context_blueprint_grade)}\r\n}\r\n\r\n{if blueprint && blueprintgrade:\r\n {set materials to len(blueprint.materials)}\r\n {blueprintname} grade {blueprintgrade} requires \r\n {if materials = 1:\r\n {blueprint.materials[0].material}\r\n |elif materials = 2:\r\n {blueprint.materials[0].material} and {blueprint.materials[1].material}\r\n |else:\r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {if cur = 0:\r\n {blueprint.materials[cur].material}\r\n |elif cur < len(blueprint.materials) - 1:\r\n , {blueprint.materials[cur].material}\r\n |else:\r\n , and {blueprint.materials[cur].material}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint material report", "description": "Report on the material requirements for a blueprint" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index 0296a1ad79..91d5c5db63 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to GetState('eddi_context_blueprint_name')}\r\n{set blueprintgrade to GetState('eddi_context_blueprint_grade')}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" @@ -60,7 +60,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch from context / state _}\r\n{set blueprintname to state.blueprint}\r\n{set blueprintgrade to state.blueprintgrade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if blueprintname:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'blueprint')}\r\n {SetState('eddi_context_blueprint_name', blueprintname)}\r\n {SetState('eddi_context_blueprint_grade', blueprintgrade)}\r\n}\r\n\r\n{if !blueprint || !blueprintgrade:\r\n {_ Fetch from context }\r\n {set blueprint to BlueprintDetails(state.eddi_context_blueprint_name, state.eddi_context_blueprint_grade)}\r\n}\r\n\r\n{if blueprint && blueprintgrade:\r\n {set materials to len(blueprint.materials)}\r\n {blueprintname} grade {blueprintgrade} requires \r\n {if materials = 1:\r\n {blueprint.materials[0].material}\r\n |elif materials = 2:\r\n {blueprint.materials[0].material} and {blueprint.materials[1].material}\r\n |else:\r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {if cur = 0:\r\n {blueprint.materials[cur].material}\r\n |elif cur < len(blueprint.materials) - 1:\r\n , {blueprint.materials[cur].material}\r\n |else:\r\n , and {blueprint.materials[cur].material}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint material report", "description": "Report on the material requirements for a blueprint" From 724ba919816c81c1330fb31895fdbf1e6ad622f4 Mon Sep 17 00:00:00 2001 From: T'kael Date: Sun, 23 Jun 2024 23:27:12 -0700 Subject: [PATCH 11/36] `Galnet news` script updated to simplify state retrieval. --- SpeechResponder/eddi.cs.json | 2 +- SpeechResponder/eddi.de.json | 2 +- SpeechResponder/eddi.hu.json | 2 +- SpeechResponder/eddi.it.json | 2 +- SpeechResponder/eddi.ja.json | 2 +- SpeechResponder/eddi.json | 2 +- SpeechResponder/eddi.ru.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index 7322df10ff..2a57088d38 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -1090,7 +1090,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch article from state }\r\n{set articleid to state.articleid}\r\n{if articleid:\r\n {set article to GalnetNews(articleid)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'news')}\r\n {SetState('eddi_context_galnet_news_id', articleid)}\r\n}\r\n\r\n{if !article:\r\n {_ Fetch from context }\r\n {set article to GalnetNews(state.eddi_context_galnet_news_id)}\r\n}\r\n\r\n{if article:\r\n {article.title}: {article.content}\r\n {GalnetNewsMarkRead(article.id)}\r\n|else:\r\n I don't have any information about that article\r\n}.", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'news')}\r\n\r\n{_ Fetch from context }\r\n{set articleid to state.eddi_context_galnet_news_id}\r\n{if articleid:\r\n {set article to GalnetNews(state.eddi_context_galnet_news_id)}\r\n}\r\n\r\n{if article:\r\n {article.title}: {article.content}\r\n {GalnetNewsMarkRead(article.id)}\r\n|else:\r\n I don't have any information about that article\r\n}.", "default": true, "name": "Galnet news", "description": "Read a particular news article" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index 0ae48511cf..0e5c825f85 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -1090,7 +1090,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch article from state }\r\n{set articleid to state.articleid}\r\n{if articleid:\r\n {set article to GalnetNews(articleid)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'news')}\r\n {SetState('eddi_context_galnet_news_id', articleid)}\r\n}\r\n\r\n{if !article:\r\n {_ Fetch from context }\r\n {set article to GalnetNews(state.eddi_context_galnet_news_id)}\r\n}\r\n\r\n{if article:\r\n {article.title}: {article.content}\r\n {GalnetNewsMarkRead(article.id)}\r\n|else:\r\n I don't have any information about that article\r\n}.", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'news')}\r\n\r\n{_ Fetch from context }\r\n{set articleid to state.eddi_context_galnet_news_id}\r\n{if articleid:\r\n {set article to GalnetNews(state.eddi_context_galnet_news_id)}\r\n}\r\n\r\n{if article:\r\n {article.title}: {article.content}\r\n {GalnetNewsMarkRead(article.id)}\r\n|else:\r\n I don't have any information about that article\r\n}.", "default": true, "name": "Galnet news", "description": "Read a particular news article" diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index 91d5c5db63..91fe73a16f 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -1090,7 +1090,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch article from state }\r\n{set articleid to state.articleid}\r\n{if articleid:\r\n {set article to GalnetNews(articleid)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'news')}\r\n {SetState('eddi_context_galnet_news_id', articleid)}\r\n}\r\n\r\n{if !article:\r\n {_ Fetch from context }\r\n {set article to GalnetNews(state.eddi_context_galnet_news_id)}\r\n}\r\n\r\n{if article:\r\n {article.title}: {article.content}\r\n {GalnetNewsMarkRead(article.id)}\r\n|else:\r\n I don't have any information about that article\r\n}.", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'news')}\r\n\r\n{_ Fetch from context }\r\n{set articleid to state.eddi_context_galnet_news_id}\r\n{if articleid:\r\n {set article to GalnetNews(state.eddi_context_galnet_news_id)}\r\n}\r\n\r\n{if article:\r\n {article.title}: {article.content}\r\n {GalnetNewsMarkRead(article.id)}\r\n|else:\r\n I don't have any information about that article\r\n}.", "default": true, "name": "Galnet news", "description": "Read a particular news article" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index 91d5c5db63..91fe73a16f 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -1090,7 +1090,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch article from state }\r\n{set articleid to state.articleid}\r\n{if articleid:\r\n {set article to GalnetNews(articleid)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'news')}\r\n {SetState('eddi_context_galnet_news_id', articleid)}\r\n}\r\n\r\n{if !article:\r\n {_ Fetch from context }\r\n {set article to GalnetNews(state.eddi_context_galnet_news_id)}\r\n}\r\n\r\n{if article:\r\n {article.title}: {article.content}\r\n {GalnetNewsMarkRead(article.id)}\r\n|else:\r\n I don't have any information about that article\r\n}.", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'news')}\r\n\r\n{_ Fetch from context }\r\n{set articleid to state.eddi_context_galnet_news_id}\r\n{if articleid:\r\n {set article to GalnetNews(state.eddi_context_galnet_news_id)}\r\n}\r\n\r\n{if article:\r\n {article.title}: {article.content}\r\n {GalnetNewsMarkRead(article.id)}\r\n|else:\r\n I don't have any information about that article\r\n}.", "default": true, "name": "Galnet news", "description": "Read a particular news article" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index 91d5c5db63..91fe73a16f 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -1090,7 +1090,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch article from state }\r\n{set articleid to state.articleid}\r\n{if articleid:\r\n {set article to GalnetNews(articleid)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'news')}\r\n {SetState('eddi_context_galnet_news_id', articleid)}\r\n}\r\n\r\n{if !article:\r\n {_ Fetch from context }\r\n {set article to GalnetNews(state.eddi_context_galnet_news_id)}\r\n}\r\n\r\n{if article:\r\n {article.title}: {article.content}\r\n {GalnetNewsMarkRead(article.id)}\r\n|else:\r\n I don't have any information about that article\r\n}.", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'news')}\r\n\r\n{_ Fetch from context }\r\n{set articleid to state.eddi_context_galnet_news_id}\r\n{if articleid:\r\n {set article to GalnetNews(state.eddi_context_galnet_news_id)}\r\n}\r\n\r\n{if article:\r\n {article.title}: {article.content}\r\n {GalnetNewsMarkRead(article.id)}\r\n|else:\r\n I don't have any information about that article\r\n}.", "default": true, "name": "Galnet news", "description": "Read a particular news article" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index ecefe47098..4e350a2568 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -1090,7 +1090,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch article from state }\r\n{set articleid to state.articleid}\r\n{if articleid:\r\n {set article to GalnetNews(articleid)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'news')}\r\n {SetState('eddi_context_galnet_news_id', articleid)}\r\n}\r\n\r\n{if !article:\r\n {_ Fetch from context }\r\n {set article to GalnetNews(state.eddi_context_galnet_news_id)}\r\n}\r\n\r\n{if article:\r\n {article.title}: {article.content}\r\n {GalnetNewsMarkRead(article.id)}\r\n|else:\r\n I don't have any information about that article\r\n}.", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'news')}\r\n\r\n{_ Fetch from context }\r\n{set articleid to state.eddi_context_galnet_news_id}\r\n{if articleid:\r\n {set article to GalnetNews(state.eddi_context_galnet_news_id)}\r\n}\r\n\r\n{if article:\r\n {article.title}: {article.content}\r\n {GalnetNewsMarkRead(article.id)}\r\n|else:\r\n I don't have any information about that article\r\n}.", "default": true, "name": "Galnet news", "description": "Read a particular news article" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index 91d5c5db63..91fe73a16f 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -1090,7 +1090,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch article from state }\r\n{set articleid to state.articleid}\r\n{if articleid:\r\n {set article to GalnetNews(articleid)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'news')}\r\n {SetState('eddi_context_galnet_news_id', articleid)}\r\n}\r\n\r\n{if !article:\r\n {_ Fetch from context }\r\n {set article to GalnetNews(state.eddi_context_galnet_news_id)}\r\n}\r\n\r\n{if article:\r\n {article.title}: {article.content}\r\n {GalnetNewsMarkRead(article.id)}\r\n|else:\r\n I don't have any information about that article\r\n}.", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'news')}\r\n\r\n{_ Fetch from context }\r\n{set articleid to state.eddi_context_galnet_news_id}\r\n{if articleid:\r\n {set article to GalnetNews(state.eddi_context_galnet_news_id)}\r\n}\r\n\r\n{if article:\r\n {article.title}: {article.content}\r\n {GalnetNewsMarkRead(article.id)}\r\n|else:\r\n I don't have any information about that article\r\n}.", "default": true, "name": "Galnet news", "description": "Read a particular news article" From 618d2f6b4b0e3e76ce84d4b9f9a2aa71e2e2b2b8 Mon Sep 17 00:00:00 2001 From: T'kael Date: Tue, 25 Jun 2024 21:57:18 -0700 Subject: [PATCH 12/36] `Material discard report` and `Material inventory report` updated to simplify state retrieval. --- SpeechResponder/eddi.cs.json | 4 ++-- SpeechResponder/eddi.de.json | 4 ++-- SpeechResponder/eddi.hu.json | 4 ++-- SpeechResponder/eddi.it.json | 4 ++-- SpeechResponder/eddi.ja.json | 4 ++-- SpeechResponder/eddi.json | 4 ++-- SpeechResponder/eddi.ru.json | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index 2a57088d38..8c2cfd0029 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -1351,7 +1351,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n\r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", "default": true, "name": "Material discard report", "description": "Report on how many of a material can be discarded" @@ -1396,7 +1396,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n \r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_last_subject', 'inventory')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", "default": true, "name": "Material inventory report", "description": "Report on how many of a material are on-board" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index 0e5c825f85..8f605cef62 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -1351,7 +1351,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n\r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", "default": true, "name": "Material discard report", "description": "Report on how many of a material can be discarded" @@ -1396,7 +1396,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n \r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_last_subject', 'inventory')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", "default": true, "name": "Material inventory report", "description": "Report on how many of a material are on-board" diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index 91fe73a16f..c82523cb29 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -1351,7 +1351,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n\r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", "default": true, "name": "Material discard report", "description": "Report on how many of a material can be discarded" @@ -1396,7 +1396,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n \r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_last_subject', 'inventory')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", "default": true, "name": "Material inventory report", "description": "Report on how many of a material are on-board" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index 91fe73a16f..c82523cb29 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -1351,7 +1351,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n\r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", "default": true, "name": "Material discard report", "description": "Report on how many of a material can be discarded" @@ -1396,7 +1396,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n \r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_last_subject', 'inventory')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", "default": true, "name": "Material inventory report", "description": "Report on how many of a material are on-board" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index 91fe73a16f..c82523cb29 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -1351,7 +1351,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n\r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", "default": true, "name": "Material discard report", "description": "Report on how many of a material can be discarded" @@ -1396,7 +1396,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n \r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_last_subject', 'inventory')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", "default": true, "name": "Material inventory report", "description": "Report on how many of a material are on-board" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index 4e350a2568..287602f7ec 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -1351,7 +1351,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n\r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", "default": true, "name": "Material discard report", "description": "Report on how many of a material can be discarded" @@ -1396,7 +1396,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n \r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_last_subject', 'inventory')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", "default": true, "name": "Material inventory report", "description": "Report on how many of a material are on-board" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index 91fe73a16f..c82523cb29 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -1351,7 +1351,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n\r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", "default": true, "name": "Material discard report", "description": "Report on how many of a material can be discarded" @@ -1396,7 +1396,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n \r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_last_subject', 'inventory')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", "default": true, "name": "Material inventory report", "description": "Report on how many of a material are on-board" From db6a5688a7b8849e3788415dc2fb8deb65582648 Mon Sep 17 00:00:00 2001 From: T'kael Date: Tue, 25 Jun 2024 22:05:23 -0700 Subject: [PATCH 13/36] `Material required report` script updated to simplify state retrieval. --- SpeechResponder/eddi.cs.json | 2 +- SpeechResponder/eddi.de.json | 2 +- SpeechResponder/eddi.hu.json | 2 +- SpeechResponder/eddi.it.json | 2 +- SpeechResponder/eddi.ja.json | 2 +- SpeechResponder/eddi.json | 2 +- SpeechResponder/eddi.ru.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index 8c2cfd0029..30a322673d 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -1414,7 +1414,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n\r\n{if materialInventory:\r\n {if materialInventory.minimum && materialInventory.minimum > materialInventory.amount:\r\n {set under to materialInventory.minimum - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your minimum level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your minimum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired > materialInventory.amount:\r\n {set under to materialInventory.desired - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your desired level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are above your desired level for {materialInventory.material}.\r\n |elif materialInventory.minimum :\r\n You are above your minimum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'required')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.minimum && materialInventory.minimum > materialInventory.amount:\r\n {set under to materialInventory.minimum - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your minimum level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your minimum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired > materialInventory.amount:\r\n {set under to materialInventory.desired - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your desired level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are above your desired level for {materialInventory.material}.\r\n |elif materialInventory.minimum :\r\n You are above your minimum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}", "default": true, "name": "Material required report", "description": "Report on how many of a material are required to reach 'desired' level" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index 8f605cef62..86ed6b0e53 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -1414,7 +1414,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n\r\n{if materialInventory:\r\n {if materialInventory.minimum && materialInventory.minimum > materialInventory.amount:\r\n {set under to materialInventory.minimum - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your minimum level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your minimum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired > materialInventory.amount:\r\n {set under to materialInventory.desired - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your desired level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are above your desired level for {materialInventory.material}.\r\n |elif materialInventory.minimum :\r\n You are above your minimum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'required')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.minimum && materialInventory.minimum > materialInventory.amount:\r\n {set under to materialInventory.minimum - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your minimum level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your minimum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired > materialInventory.amount:\r\n {set under to materialInventory.desired - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your desired level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are above your desired level for {materialInventory.material}.\r\n |elif materialInventory.minimum :\r\n You are above your minimum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}", "default": true, "name": "Material required report", "description": "Report on how many of a material are required to reach 'desired' level" diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index c82523cb29..3e6bcae899 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -1414,7 +1414,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n\r\n{if materialInventory:\r\n {if materialInventory.minimum && materialInventory.minimum > materialInventory.amount:\r\n {set under to materialInventory.minimum - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your minimum level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your minimum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired > materialInventory.amount:\r\n {set under to materialInventory.desired - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your desired level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are above your desired level for {materialInventory.material}.\r\n |elif materialInventory.minimum :\r\n You are above your minimum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'required')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.minimum && materialInventory.minimum > materialInventory.amount:\r\n {set under to materialInventory.minimum - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your minimum level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your minimum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired > materialInventory.amount:\r\n {set under to materialInventory.desired - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your desired level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are above your desired level for {materialInventory.material}.\r\n |elif materialInventory.minimum :\r\n You are above your minimum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}", "default": true, "name": "Material required report", "description": "Report on how many of a material are required to reach 'desired' level" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index c82523cb29..3e6bcae899 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -1414,7 +1414,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n\r\n{if materialInventory:\r\n {if materialInventory.minimum && materialInventory.minimum > materialInventory.amount:\r\n {set under to materialInventory.minimum - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your minimum level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your minimum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired > materialInventory.amount:\r\n {set under to materialInventory.desired - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your desired level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are above your desired level for {materialInventory.material}.\r\n |elif materialInventory.minimum :\r\n You are above your minimum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'required')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.minimum && materialInventory.minimum > materialInventory.amount:\r\n {set under to materialInventory.minimum - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your minimum level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your minimum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired > materialInventory.amount:\r\n {set under to materialInventory.desired - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your desired level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are above your desired level for {materialInventory.material}.\r\n |elif materialInventory.minimum :\r\n You are above your minimum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}", "default": true, "name": "Material required report", "description": "Report on how many of a material are required to reach 'desired' level" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index c82523cb29..3e6bcae899 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -1414,7 +1414,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n\r\n{if materialInventory:\r\n {if materialInventory.minimum && materialInventory.minimum > materialInventory.amount:\r\n {set under to materialInventory.minimum - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your minimum level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your minimum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired > materialInventory.amount:\r\n {set under to materialInventory.desired - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your desired level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are above your desired level for {materialInventory.material}.\r\n |elif materialInventory.minimum :\r\n You are above your minimum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'required')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.minimum && materialInventory.minimum > materialInventory.amount:\r\n {set under to materialInventory.minimum - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your minimum level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your minimum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired > materialInventory.amount:\r\n {set under to materialInventory.desired - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your desired level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are above your desired level for {materialInventory.material}.\r\n |elif materialInventory.minimum :\r\n You are above your minimum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}", "default": true, "name": "Material required report", "description": "Report on how many of a material are required to reach 'desired' level" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index 287602f7ec..4f742747f6 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -1414,7 +1414,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n\r\n{if materialInventory:\r\n {if materialInventory.minimum && materialInventory.minimum > materialInventory.amount:\r\n {set under to materialInventory.minimum - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your minimum level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your minimum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired > materialInventory.amount:\r\n {set under to materialInventory.desired - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your desired level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are above your desired level for {materialInventory.material}.\r\n |elif materialInventory.minimum :\r\n You are above your minimum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'required')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.minimum && materialInventory.minimum > materialInventory.amount:\r\n {set under to materialInventory.minimum - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your minimum level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your minimum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired > materialInventory.amount:\r\n {set under to materialInventory.desired - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your desired level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are above your desired level for {materialInventory.material}.\r\n |elif materialInventory.minimum :\r\n You are above your minimum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}", "default": true, "name": "Material required report", "description": "Report on how many of a material are required to reach 'desired' level" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index c82523cb29..3e6bcae899 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -1414,7 +1414,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Function to obtain a material from inventory}\r\n{set _inventory(required) to:\r\n {for material in materials:\r\n {if material.material = required:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{set materialInventory to _inventory(material.name)}\r\n\r\n\r\n{if materialInventory:\r\n {if materialInventory.minimum && materialInventory.minimum > materialInventory.amount:\r\n {set under to materialInventory.minimum - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your minimum level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your minimum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired > materialInventory.amount:\r\n {set under to materialInventory.desired - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your desired level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are above your desired level for {materialInventory.material}.\r\n |elif materialInventory.minimum :\r\n You are above your minimum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'required')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.minimum && materialInventory.minimum > materialInventory.amount:\r\n {set under to materialInventory.minimum - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your minimum level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your minimum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired > materialInventory.amount:\r\n {set under to materialInventory.desired - materialInventory.amount}\r\n {if under > 1:\r\n You require {under} units of {materialInventory.material} to reach your desired level.\r\n |elif under = 1:\r\n You require 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are above your desired level for {materialInventory.material}.\r\n |elif materialInventory.minimum :\r\n You are above your minimum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}", "default": true, "name": "Material required report", "description": "Report on how many of a material are required to reach 'desired' level" From 346f78b2610cbc74673976996b5771d29d5b4d49 Mon Sep 17 00:00:00 2001 From: T'kael Date: Tue, 25 Jun 2024 22:08:16 -0700 Subject: [PATCH 14/36] `Material location report` script updated to simplify state retrieval. --- SpeechResponder/eddi.cs.json | 2 +- SpeechResponder/eddi.de.json | 2 +- SpeechResponder/eddi.hu.json | 2 +- SpeechResponder/eddi.it.json | 2 +- SpeechResponder/eddi.ja.json | 2 +- SpeechResponder/eddi.json | 2 +- SpeechResponder/eddi.ru.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index 30a322673d..e7a2fa08c3 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -1405,7 +1405,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{if material.name:\r\n {if material.location:\r\n {material.name} can be {material.location}\r\n |else:\r\n No information available on where to find {material.name}\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'location')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{if material.name:\r\n {if material.location:\r\n {material.name} can be {material.location}\r\n |else:\r\n No information available on where to find {material.name}\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.\r\n", "default": true, "name": "Material location report", "description": "Report on the where to obtain a particular material" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index 86ed6b0e53..6023434443 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -1405,7 +1405,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{if material.name:\r\n {if material.location:\r\n {material.name} can be {material.location}\r\n |else:\r\n No information available on where to find {material.name}\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'location')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{if material.name:\r\n {if material.location:\r\n {material.name} can be {material.location}\r\n |else:\r\n No information available on where to find {material.name}\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.\r\n", "default": true, "name": "Material location report", "description": "Report on the where to obtain a particular material" diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index 3e6bcae899..fad28c8470 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -1405,7 +1405,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{if material.name:\r\n {if material.location:\r\n {material.name} can be {material.location}\r\n |else:\r\n No information available on where to find {material.name}\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'location')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{if material.name:\r\n {if material.location:\r\n {material.name} can be {material.location}\r\n |else:\r\n No information available on where to find {material.name}\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.\r\n", "default": true, "name": "Material location report", "description": "Report on the where to obtain a particular material" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index 3e6bcae899..fad28c8470 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -1405,7 +1405,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{if material.name:\r\n {if material.location:\r\n {material.name} can be {material.location}\r\n |else:\r\n No information available on where to find {material.name}\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'location')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{if material.name:\r\n {if material.location:\r\n {material.name} can be {material.location}\r\n |else:\r\n No information available on where to find {material.name}\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.\r\n", "default": true, "name": "Material location report", "description": "Report on the where to obtain a particular material" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index 3e6bcae899..fad28c8470 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -1405,7 +1405,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{if material.name:\r\n {if material.location:\r\n {material.name} can be {material.location}\r\n |else:\r\n No information available on where to find {material.name}\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'location')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{if material.name:\r\n {if material.location:\r\n {material.name} can be {material.location}\r\n |else:\r\n No information available on where to find {material.name}\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.\r\n", "default": true, "name": "Material location report", "description": "Report on the where to obtain a particular material" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index 4f742747f6..9b3e11c859 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -1405,7 +1405,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{if material.name:\r\n {if material.location:\r\n {material.name} can be {material.location}\r\n |else:\r\n No information available on where to find {material.name}\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'location')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{if material.name:\r\n {if material.location:\r\n {material.name} can be {material.location}\r\n |else:\r\n No information available on where to find {material.name}\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.\r\n", "default": true, "name": "Material location report", "description": "Report on the where to obtain a particular material" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index 3e6bcae899..fad28c8470 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -1405,7 +1405,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n}\r\n\r\n{if material.name:\r\n {if material.location:\r\n {material.name} can be {material.location}\r\n |else:\r\n No information available on where to find {material.name}\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'location')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{if material.name:\r\n {if material.location:\r\n {material.name} can be {material.location}\r\n |else:\r\n No information available on where to find {material.name}\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.\r\n", "default": true, "name": "Material location report", "description": "Report on the where to obtain a particular material" From 374f6eb5fd1f74532cc4c1a90f0f95cf692ef1af Mon Sep 17 00:00:00 2001 From: T'kael Date: Tue, 25 Jun 2024 22:13:40 -0700 Subject: [PATCH 15/36] `Material use report` script updated to simplify state retrieval. --- SpeechResponder/eddi.cs.json | 2 +- SpeechResponder/eddi.de.json | 2 +- SpeechResponder/eddi.hu.json | 2 +- SpeechResponder/eddi.it.json | 2 +- SpeechResponder/eddi.ja.json | 2 +- SpeechResponder/eddi.json | 2 +- SpeechResponder/eddi.ru.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index e7a2fa08c3..f5dbafca4d 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -1441,7 +1441,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {if len(state.eddi_context_material_name) > 0:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n }\r\n}\r\n\r\n{if material && material.name:\r\n {set uses to len(material.blueprints)}\r\n {if slice(material.name, len(material.name)-1) = 's':\r\n {set plural to 'are'}\r\n |else:\r\n {set plural to 'is'}\r\n }\r\n {if uses = 0:\r\n {material.name} {plural} not required for any blueprints\r\n |elif uses = 1:\r\n {set name to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {material.name} {plural} used for the {name} blueprint\r\n |elif uses = 2:\r\n {set name0 to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {set name1 to cat(material.blueprints[1].name, material.blueprints[1].modulename, ' grade ', material.blueprints[1].grade)}\r\n {material.name} {plural} used for the {name0} and {name1} blueprints\r\n |else:\r\n {material.name} {plural} used for {len(material.blueprints)} blueprints. These are\r\n {set cur to 0}\r\n {while cur < len(material.blueprints):\r\n {set name to cat(material.blueprints[cur].name, material.blueprints[cur].modulename, ' grade ', material.blueprints[cur].grade)}\r\n {if cur = 0:\r\n {name}\r\n |elif cur < len(material.blueprints) - 1:\r\n , {name}\r\n |else:\r\n , and {name}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'use')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{if material && material.name:\r\n {set uses to len(material.blueprints)}\r\n {if slice(material.name, len(material.name)-1) = 's':\r\n {set plural to 'are'}\r\n |else:\r\n {set plural to 'is'}\r\n }\r\n {if uses = 0:\r\n {material.name} {plural} not required for any blueprints\r\n |elif uses = 1:\r\n {set name to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {material.name} {plural} used for the {name} blueprint\r\n |elif uses = 2:\r\n {set name0 to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {set name1 to cat(material.blueprints[1].name, material.blueprints[1].modulename, ' grade ', material.blueprints[1].grade)}\r\n {material.name} {plural} used for the {name0} and {name1} blueprints\r\n |else:\r\n {material.name} {plural} used for {len(material.blueprints)} blueprints. These are\r\n {set cur to 0}\r\n {while cur < len(material.blueprints):\r\n {set name to cat(material.blueprints[cur].name, material.blueprints[cur].modulename, ' grade ', material.blueprints[cur].grade)}\r\n {if cur = 0:\r\n {name}\r\n |elif cur < len(material.blueprints) - 1:\r\n , {name}\r\n |else:\r\n , and {name}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.", "default": true, "name": "Material use report", "description": "Report on the use of a material" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index 6023434443..332c1871bf 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -1441,7 +1441,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {if len(state.eddi_context_material_name) > 0:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n }\r\n}\r\n\r\n{if material && material.name:\r\n {set uses to len(material.blueprints)}\r\n {if slice(material.name, len(material.name)-1) = 's':\r\n {set plural to 'are'}\r\n |else:\r\n {set plural to 'is'}\r\n }\r\n {if uses = 0:\r\n {material.name} {plural} not required for any blueprints\r\n |elif uses = 1:\r\n {set name to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {material.name} {plural} used for the {name} blueprint\r\n |elif uses = 2:\r\n {set name0 to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {set name1 to cat(material.blueprints[1].name, material.blueprints[1].modulename, ' grade ', material.blueprints[1].grade)}\r\n {material.name} {plural} used for the {name0} and {name1} blueprints\r\n |else:\r\n {material.name} {plural} used for {len(material.blueprints)} blueprints. These are\r\n {set cur to 0}\r\n {while cur < len(material.blueprints):\r\n {set name to cat(material.blueprints[cur].name, material.blueprints[cur].modulename, ' grade ', material.blueprints[cur].grade)}\r\n {if cur = 0:\r\n {name}\r\n |elif cur < len(material.blueprints) - 1:\r\n , {name}\r\n |else:\r\n , and {name}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'use')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{if material && material.name:\r\n {set uses to len(material.blueprints)}\r\n {if slice(material.name, len(material.name)-1) = 's':\r\n {set plural to 'are'}\r\n |else:\r\n {set plural to 'is'}\r\n }\r\n {if uses = 0:\r\n {material.name} {plural} not required for any blueprints\r\n |elif uses = 1:\r\n {set name to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {material.name} {plural} used for the {name} blueprint\r\n |elif uses = 2:\r\n {set name0 to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {set name1 to cat(material.blueprints[1].name, material.blueprints[1].modulename, ' grade ', material.blueprints[1].grade)}\r\n {material.name} {plural} used for the {name0} and {name1} blueprints\r\n |else:\r\n {material.name} {plural} used for {len(material.blueprints)} blueprints. These are\r\n {set cur to 0}\r\n {while cur < len(material.blueprints):\r\n {set name to cat(material.blueprints[cur].name, material.blueprints[cur].modulename, ' grade ', material.blueprints[cur].grade)}\r\n {if cur = 0:\r\n {name}\r\n |elif cur < len(material.blueprints) - 1:\r\n , {name}\r\n |else:\r\n , and {name}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.", "default": true, "name": "Material use report", "description": "Report on the use of a material" diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index fad28c8470..61ae529f45 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -1441,7 +1441,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {if len(state.eddi_context_material_name) > 0:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n }\r\n}\r\n\r\n{if material && material.name:\r\n {set uses to len(material.blueprints)}\r\n {if slice(material.name, len(material.name)-1) = 's':\r\n {set plural to 'are'}\r\n |else:\r\n {set plural to 'is'}\r\n }\r\n {if uses = 0:\r\n {material.name} {plural} not required for any blueprints\r\n |elif uses = 1:\r\n {set name to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {material.name} {plural} used for the {name} blueprint\r\n |elif uses = 2:\r\n {set name0 to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {set name1 to cat(material.blueprints[1].name, material.blueprints[1].modulename, ' grade ', material.blueprints[1].grade)}\r\n {material.name} {plural} used for the {name0} and {name1} blueprints\r\n |else:\r\n {material.name} {plural} used for {len(material.blueprints)} blueprints. These are\r\n {set cur to 0}\r\n {while cur < len(material.blueprints):\r\n {set name to cat(material.blueprints[cur].name, material.blueprints[cur].modulename, ' grade ', material.blueprints[cur].grade)}\r\n {if cur = 0:\r\n {name}\r\n |elif cur < len(material.blueprints) - 1:\r\n , {name}\r\n |else:\r\n , and {name}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'use')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{if material && material.name:\r\n {set uses to len(material.blueprints)}\r\n {if slice(material.name, len(material.name)-1) = 's':\r\n {set plural to 'are'}\r\n |else:\r\n {set plural to 'is'}\r\n }\r\n {if uses = 0:\r\n {material.name} {plural} not required for any blueprints\r\n |elif uses = 1:\r\n {set name to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {material.name} {plural} used for the {name} blueprint\r\n |elif uses = 2:\r\n {set name0 to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {set name1 to cat(material.blueprints[1].name, material.blueprints[1].modulename, ' grade ', material.blueprints[1].grade)}\r\n {material.name} {plural} used for the {name0} and {name1} blueprints\r\n |else:\r\n {material.name} {plural} used for {len(material.blueprints)} blueprints. These are\r\n {set cur to 0}\r\n {while cur < len(material.blueprints):\r\n {set name to cat(material.blueprints[cur].name, material.blueprints[cur].modulename, ' grade ', material.blueprints[cur].grade)}\r\n {if cur = 0:\r\n {name}\r\n |elif cur < len(material.blueprints) - 1:\r\n , {name}\r\n |else:\r\n , and {name}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.", "default": true, "name": "Material use report", "description": "Report on the use of a material" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index fad28c8470..61ae529f45 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -1441,7 +1441,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {if len(state.eddi_context_material_name) > 0:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n }\r\n}\r\n\r\n{if material && material.name:\r\n {set uses to len(material.blueprints)}\r\n {if slice(material.name, len(material.name)-1) = 's':\r\n {set plural to 'are'}\r\n |else:\r\n {set plural to 'is'}\r\n }\r\n {if uses = 0:\r\n {material.name} {plural} not required for any blueprints\r\n |elif uses = 1:\r\n {set name to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {material.name} {plural} used for the {name} blueprint\r\n |elif uses = 2:\r\n {set name0 to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {set name1 to cat(material.blueprints[1].name, material.blueprints[1].modulename, ' grade ', material.blueprints[1].grade)}\r\n {material.name} {plural} used for the {name0} and {name1} blueprints\r\n |else:\r\n {material.name} {plural} used for {len(material.blueprints)} blueprints. These are\r\n {set cur to 0}\r\n {while cur < len(material.blueprints):\r\n {set name to cat(material.blueprints[cur].name, material.blueprints[cur].modulename, ' grade ', material.blueprints[cur].grade)}\r\n {if cur = 0:\r\n {name}\r\n |elif cur < len(material.blueprints) - 1:\r\n , {name}\r\n |else:\r\n , and {name}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'use')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{if material && material.name:\r\n {set uses to len(material.blueprints)}\r\n {if slice(material.name, len(material.name)-1) = 's':\r\n {set plural to 'are'}\r\n |else:\r\n {set plural to 'is'}\r\n }\r\n {if uses = 0:\r\n {material.name} {plural} not required for any blueprints\r\n |elif uses = 1:\r\n {set name to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {material.name} {plural} used for the {name} blueprint\r\n |elif uses = 2:\r\n {set name0 to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {set name1 to cat(material.blueprints[1].name, material.blueprints[1].modulename, ' grade ', material.blueprints[1].grade)}\r\n {material.name} {plural} used for the {name0} and {name1} blueprints\r\n |else:\r\n {material.name} {plural} used for {len(material.blueprints)} blueprints. These are\r\n {set cur to 0}\r\n {while cur < len(material.blueprints):\r\n {set name to cat(material.blueprints[cur].name, material.blueprints[cur].modulename, ' grade ', material.blueprints[cur].grade)}\r\n {if cur = 0:\r\n {name}\r\n |elif cur < len(material.blueprints) - 1:\r\n , {name}\r\n |else:\r\n , and {name}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.", "default": true, "name": "Material use report", "description": "Report on the use of a material" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index fad28c8470..61ae529f45 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -1441,7 +1441,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {if len(state.eddi_context_material_name) > 0:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n }\r\n}\r\n\r\n{if material && material.name:\r\n {set uses to len(material.blueprints)}\r\n {if slice(material.name, len(material.name)-1) = 's':\r\n {set plural to 'are'}\r\n |else:\r\n {set plural to 'is'}\r\n }\r\n {if uses = 0:\r\n {material.name} {plural} not required for any blueprints\r\n |elif uses = 1:\r\n {set name to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {material.name} {plural} used for the {name} blueprint\r\n |elif uses = 2:\r\n {set name0 to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {set name1 to cat(material.blueprints[1].name, material.blueprints[1].modulename, ' grade ', material.blueprints[1].grade)}\r\n {material.name} {plural} used for the {name0} and {name1} blueprints\r\n |else:\r\n {material.name} {plural} used for {len(material.blueprints)} blueprints. These are\r\n {set cur to 0}\r\n {while cur < len(material.blueprints):\r\n {set name to cat(material.blueprints[cur].name, material.blueprints[cur].modulename, ' grade ', material.blueprints[cur].grade)}\r\n {if cur = 0:\r\n {name}\r\n |elif cur < len(material.blueprints) - 1:\r\n , {name}\r\n |else:\r\n , and {name}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'use')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{if material && material.name:\r\n {set uses to len(material.blueprints)}\r\n {if slice(material.name, len(material.name)-1) = 's':\r\n {set plural to 'are'}\r\n |else:\r\n {set plural to 'is'}\r\n }\r\n {if uses = 0:\r\n {material.name} {plural} not required for any blueprints\r\n |elif uses = 1:\r\n {set name to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {material.name} {plural} used for the {name} blueprint\r\n |elif uses = 2:\r\n {set name0 to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {set name1 to cat(material.blueprints[1].name, material.blueprints[1].modulename, ' grade ', material.blueprints[1].grade)}\r\n {material.name} {plural} used for the {name0} and {name1} blueprints\r\n |else:\r\n {material.name} {plural} used for {len(material.blueprints)} blueprints. These are\r\n {set cur to 0}\r\n {while cur < len(material.blueprints):\r\n {set name to cat(material.blueprints[cur].name, material.blueprints[cur].modulename, ' grade ', material.blueprints[cur].grade)}\r\n {if cur = 0:\r\n {name}\r\n |elif cur < len(material.blueprints) - 1:\r\n , {name}\r\n |else:\r\n , and {name}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.", "default": true, "name": "Material use report", "description": "Report on the use of a material" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index 9b3e11c859..4e041a7be1 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -1441,7 +1441,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {if len(state.eddi_context_material_name) > 0:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n }\r\n}\r\n\r\n{if material && material.name:\r\n {set uses to len(material.blueprints)}\r\n {if slice(material.name, len(material.name)-1) = 's':\r\n {set plural to 'are'}\r\n |else:\r\n {set plural to 'is'}\r\n }\r\n {if uses = 0:\r\n {material.name} {plural} not required for any blueprints\r\n |elif uses = 1:\r\n {set name to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {material.name} {plural} used for the {name} blueprint\r\n |elif uses = 2:\r\n {set name0 to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {set name1 to cat(material.blueprints[1].name, material.blueprints[1].modulename, ' grade ', material.blueprints[1].grade)}\r\n {material.name} {plural} used for the {name0} and {name1} blueprints\r\n |else:\r\n {material.name} {plural} used for {len(material.blueprints)} blueprints. These are\r\n {set cur to 0}\r\n {while cur < len(material.blueprints):\r\n {set name to cat(material.blueprints[cur].name, material.blueprints[cur].modulename, ' grade ', material.blueprints[cur].grade)}\r\n {if cur = 0:\r\n {name}\r\n |elif cur < len(material.blueprints) - 1:\r\n , {name}\r\n |else:\r\n , and {name}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'use')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{if material && material.name:\r\n {set uses to len(material.blueprints)}\r\n {if slice(material.name, len(material.name)-1) = 's':\r\n {set plural to 'are'}\r\n |else:\r\n {set plural to 'is'}\r\n }\r\n {if uses = 0:\r\n {material.name} {plural} not required for any blueprints\r\n |elif uses = 1:\r\n {set name to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {material.name} {plural} used for the {name} blueprint\r\n |elif uses = 2:\r\n {set name0 to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {set name1 to cat(material.blueprints[1].name, material.blueprints[1].modulename, ' grade ', material.blueprints[1].grade)}\r\n {material.name} {plural} used for the {name0} and {name1} blueprints\r\n |else:\r\n {material.name} {plural} used for {len(material.blueprints)} blueprints. These are\r\n {set cur to 0}\r\n {while cur < len(material.blueprints):\r\n {set name to cat(material.blueprints[cur].name, material.blueprints[cur].modulename, ' grade ', material.blueprints[cur].grade)}\r\n {if cur = 0:\r\n {name}\r\n |elif cur < len(material.blueprints) - 1:\r\n , {name}\r\n |else:\r\n , and {name}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.", "default": true, "name": "Material use report", "description": "Report on the use of a material" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index fad28c8470..61ae529f45 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -1441,7 +1441,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Fetch material from state }\r\n{set material to state.material}\r\n{if material:\r\n {_ Fetch full material details }\r\n {set material to MaterialDetails(material)}\r\n\r\n {_ Context }\r\n {SetState('eddi_context_last_subject', 'material')}\r\n {SetState('eddi_context_material_name', material.name)}\r\n}\r\n\r\n{if !material:\r\n {if len(state.eddi_context_material_name) > 0:\r\n {_ Fetch from context }\r\n {set material to MaterialDetails(state.eddi_context_material_name)}\r\n }\r\n}\r\n\r\n{if material && material.name:\r\n {set uses to len(material.blueprints)}\r\n {if slice(material.name, len(material.name)-1) = 's':\r\n {set plural to 'are'}\r\n |else:\r\n {set plural to 'is'}\r\n }\r\n {if uses = 0:\r\n {material.name} {plural} not required for any blueprints\r\n |elif uses = 1:\r\n {set name to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {material.name} {plural} used for the {name} blueprint\r\n |elif uses = 2:\r\n {set name0 to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {set name1 to cat(material.blueprints[1].name, material.blueprints[1].modulename, ' grade ', material.blueprints[1].grade)}\r\n {material.name} {plural} used for the {name0} and {name1} blueprints\r\n |else:\r\n {material.name} {plural} used for {len(material.blueprints)} blueprints. These are\r\n {set cur to 0}\r\n {while cur < len(material.blueprints):\r\n {set name to cat(material.blueprints[cur].name, material.blueprints[cur].modulename, ' grade ', material.blueprints[cur].grade)}\r\n {if cur = 0:\r\n {name}\r\n |elif cur < len(material.blueprints) - 1:\r\n , {name}\r\n |else:\r\n , and {name}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'use')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{if material && material.name:\r\n {set uses to len(material.blueprints)}\r\n {if slice(material.name, len(material.name)-1) = 's':\r\n {set plural to 'are'}\r\n |else:\r\n {set plural to 'is'}\r\n }\r\n {if uses = 0:\r\n {material.name} {plural} not required for any blueprints\r\n |elif uses = 1:\r\n {set name to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {material.name} {plural} used for the {name} blueprint\r\n |elif uses = 2:\r\n {set name0 to cat(material.blueprints[0].name, material.blueprints[0].modulename, ' grade ', material.blueprints[0].grade)}\r\n {set name1 to cat(material.blueprints[1].name, material.blueprints[1].modulename, ' grade ', material.blueprints[1].grade)}\r\n {material.name} {plural} used for the {name0} and {name1} blueprints\r\n |else:\r\n {material.name} {plural} used for {len(material.blueprints)} blueprints. These are\r\n {set cur to 0}\r\n {while cur < len(material.blueprints):\r\n {set name to cat(material.blueprints[cur].name, material.blueprints[cur].modulename, ' grade ', material.blueprints[cur].grade)}\r\n {if cur = 0:\r\n {name}\r\n |elif cur < len(material.blueprints) - 1:\r\n , {name}\r\n |else:\r\n , and {name}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n }\r\n|else:\r\n I don't have any information about that material\r\n}.", "default": true, "name": "Material use report", "description": "Report on the use of a material" From 075234a124e3ee65d8999c1b067b324db28b5dfc Mon Sep 17 00:00:00 2001 From: T'kael Date: Tue, 25 Jun 2024 22:26:47 -0700 Subject: [PATCH 16/36] `System materials report` script updated to use `factionState` variable name rather than (ideally) reserved `state` variable name. --- SpeechResponder/eddi.cs.json | 2 +- SpeechResponder/eddi.de.json | 2 +- SpeechResponder/eddi.hu.json | 2 +- SpeechResponder/eddi.it.json | 2 +- SpeechResponder/eddi.ja.json | 2 +- SpeechResponder/eddi.json | 2 +- SpeechResponder/eddi.ru.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index f5dbafca4d..da80a30043 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for state in factionPresence.ActiveStates:\r\n {if state.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif state.invariantName = \"Civil War\" || state.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif state.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif state.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index 332c1871bf..9e775ad69e 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for state in factionPresence.ActiveStates:\r\n {if state.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif state.invariantName = \"Civil War\" || state.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif state.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif state.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index 61ae529f45..4afcf74e9f 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for state in factionPresence.ActiveStates:\r\n {if state.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif state.invariantName = \"Civil War\" || state.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif state.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif state.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index 61ae529f45..4afcf74e9f 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for state in factionPresence.ActiveStates:\r\n {if state.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif state.invariantName = \"Civil War\" || state.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif state.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif state.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index 61ae529f45..4afcf74e9f 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for state in factionPresence.ActiveStates:\r\n {if state.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif state.invariantName = \"Civil War\" || state.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif state.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif state.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index 4e041a7be1..0ba078cd3f 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for state in factionPresence.ActiveStates:\r\n {if state.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif state.invariantName = \"Civil War\" || state.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif state.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif state.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index 61ae529f45..4afcf74e9f 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for state in factionPresence.ActiveStates:\r\n {if state.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif state.invariantName = \"Civil War\" || state.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif state.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif state.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" From 6b7811da3912b7726642896e7fd2104a0eb5bf35 Mon Sep 17 00:00:00 2001 From: T'kael Date: Tue, 25 Jun 2024 22:30:34 -0700 Subject: [PATCH 17/36] Update EDDI.vap to synchronize state variable names with updated scripts --- VoiceAttackResponder/EDDI.vap | Bin 51959 -> 52931 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/VoiceAttackResponder/EDDI.vap b/VoiceAttackResponder/EDDI.vap index 2d67520ea1c2b8df7ec43dba11a23317359be6e3..aebfe464daf84199132451020ca721ffadf60d8f 100644 GIT binary patch literal 52931 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%0AUCSyz(DZQa|eykH;xQU6_#*U{p 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 Date: Tue, 25 Jun 2024 22:30:53 -0700 Subject: [PATCH 18/36] Change log. --- ChangeLog.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index 74372655e2..f7a20cc979 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -5,6 +5,23 @@ Full details of the variables available for each noted event, and VoiceAttack in ## 4.1.0-a1 * Events * `Cargo Transfer` added. (#2621) + * Speech Responder + * Update Cottle to latest available experimental version. + * Custom Functions + * `SetState` no longer is able to retrieve a state variable from from the same script / context where it was set. + * `GetState` has been added to allow retrieval of state variables in the same script / context where it was set. + * Scripts + * `Blueprint make report` updated to simplify state retrieval. + * `Blueprint material report` updated to simplify state retrieval. + * `Galnet news` updated to simplify state retrieval. + * `Material discard report` updated to simplify state retrieval. + * `Material inventory report` updated to simplify state retrieval. + * `Material required report` updated to simplify state retrieval. + * `Material location report` updated to simplify state retrieval. + * `Material use report` updated to simplify state retrieval. + * `System materials report` updated to use `factionState` variable name rather than reserved `state` variable name. + * VoiceAttack + * EDDI.vap commands updated to synchronize state variable names with updated scripts. ## 4.0.4 * Core From a0de66296768fbd95662aa0692067031092092d4 Mon Sep 17 00:00:00 2001 From: Tkael Date: Sat, 29 Jun 2024 13:29:46 -0700 Subject: [PATCH 19/36] Move `XMLSchemaSet` and `CultureInfo` properties out of the `VoiceDetails` type to prevent parsing errors with Value.FromReflection(). --- SpeechResponder/CustomFunctions/GetState.cs | 2 +- .../CustomFunctions/VoiceDetails.cs | 2 +- .../SpeechPreparation/SpeechFormatter.cs | 108 ++++++++++++++- SpeechService/SpeechService.cs | 124 ++---------------- 4 files changed, 120 insertions(+), 116 deletions(-) diff --git a/SpeechResponder/CustomFunctions/GetState.cs b/SpeechResponder/CustomFunctions/GetState.cs index b985d57fd1..07a1b368a3 100644 --- a/SpeechResponder/CustomFunctions/GetState.cs +++ b/SpeechResponder/CustomFunctions/GetState.cs @@ -40,7 +40,7 @@ public class GetState : ICustomFunction } if ( @value is string s ) - { + { return s; } diff --git a/SpeechResponder/CustomFunctions/VoiceDetails.cs b/SpeechResponder/CustomFunctions/VoiceDetails.cs index f6e6ff1a3f..e608809bb6 100644 --- a/SpeechResponder/CustomFunctions/VoiceDetails.cs +++ b/SpeechResponder/CustomFunctions/VoiceDetails.cs @@ -13,7 +13,7 @@ public class VoiceDetails : ICustomFunction public string name => "VoiceDetails"; public FunctionCategory Category => FunctionCategory.Details; public string description => Properties.CustomFunctions_Untranslated.VoiceDetails; - public Type ReturnType => typeof( VoiceDetails ); + public Type ReturnType => typeof( EddiSpeechService.VoiceDetails ); public IFunction function => Function.CreateNativeMinMax( ( runtime, values, writer ) => { if (values.Count == 0) diff --git a/SpeechService/SpeechPreparation/SpeechFormatter.cs b/SpeechService/SpeechPreparation/SpeechFormatter.cs index b9aa547165..0ab6586513 100644 --- a/SpeechService/SpeechPreparation/SpeechFormatter.cs +++ b/SpeechService/SpeechPreparation/SpeechFormatter.cs @@ -1,8 +1,12 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.IO; using System.Linq; using System.Security; using System.Text.RegularExpressions; using System.Xml; +using System.Xml.Linq; +using System.Xml.Schema; using Utilities; namespace EddiSpeechService.SpeechPreparation @@ -38,7 +42,7 @@ public static string TrimSpeech(string s) internal static void PrepareSpeech(VoiceDetails voice, ref string speech, out bool useSSML) { - var lexicons = voice.GetLexicons(); + var lexicons = GetLexicons(voice); if (speech.Contains("<") || lexicons.Any()) { // Keep XML version at 1.0. Version 1.1 is not recommended for general use. https://en.wikipedia.org/wiki/XML#Versions @@ -227,5 +231,105 @@ public static string DisableIPA(string speech) speech = Regex.Replace(speech, @"<\/phoneme>", string.Empty); return speech; } + + #region Lexicons + + private static HashSet GetLexicons ( VoiceDetails voice ) + { + var result = new HashSet(); + HashSet GetLexiconsFromDirectory ( string directory, bool createIfMissing = false ) + { + // When multiple lexicons are referenced, their precedence goes from lower to higher with document order. + // Precedence means that a token is first looked up in the lexicon with highest precedence. + // Only if not found in that lexicon, the next lexicon is searched and so on until a first match or until all lexicons have been used for lookup. (https://www.w3.org/TR/2004/REC-speech-synthesis-20040907/#S3.1.4). + + if ( string.IsNullOrEmpty( directory ) || string.IsNullOrEmpty( voice.culturecode ) ) + { return null; } + DirectoryInfo dir = new DirectoryInfo(directory); + if ( dir.Exists ) + { + // Find two letter language code lexicons (these will have lower precedence than any full language code lexicons) + foreach ( var file in dir.GetFiles( "*.pls", SearchOption.AllDirectories ) + .Where( f => $"{f.Name.ToLowerInvariant()}" == $"{voice.cultureTwoLetterISOLanguageName.ToLowerInvariant()}.pls" ) ) + { + CheckAndAdd( file ); + } + // Find full language code lexicons + foreach ( var file in dir.GetFiles( "*.pls", SearchOption.AllDirectories ) + .Where( f => $"{f.Name.ToLowerInvariant()}" == $"{voice.cultureIetfLanguageTag.ToLowerInvariant()}.pls" ) ) + { + CheckAndAdd( file ); + } + } + else if ( createIfMissing ) + { + dir.Create(); + } + return result; + } + + void CheckAndAdd ( FileInfo file ) + { + if ( IsValidXML( file.FullName, out _ ) ) + { + result.Add( file.FullName ); + } + else + { + file.MoveTo( $"{file.FullName}.malformed" ); + } + } + + // When multiple lexicons are referenced, their precedence goes from lower to higher with document order (https://www.w3.org/TR/2004/REC-speech-synthesis-20040907/#S3.1.4) + + // Add lexicons from our installation directory + result.UnionWith( GetLexiconsFromDirectory( new FileInfo( System.Reflection.Assembly.GetExecutingAssembly().Location ).DirectoryName + @"\lexicons" ) ); + + // Add lexicons from our user configuration (allowing these to overwrite any prior lexeme values) + result.UnionWith( GetLexiconsFromDirectory( Constants.DATA_DIR + @"\lexicons" ) ); + + return result; + } + + private static bool IsValidXML ( string filename, out XDocument xml ) + { + // Check whether the file is valid .xml (.pls is an xml-based format) + xml = null; + try + { + // Try to load the file as xml + xml = XDocument.Load( filename ); + + // Validate the lexicon xml against the schema + xml.Validate( SpeechService.Instance.lexiconSchemas, ( o, e ) => + { + if ( e.Severity == XmlSeverityType.Warning || e.Severity == XmlSeverityType.Error ) + { + throw new XmlSchemaValidationException( e.Message, e.Exception ); + } + } ); + var reader = xml.CreateReader(); + var lastNodeName = string.Empty; + while ( reader.Read() ) + { + if ( reader.HasValue && + reader.NodeType is XmlNodeType.Text && + lastNodeName == "phoneme" && + !IPA.IsValid( reader.Value ) ) + { + throw new ArgumentException( $"Invalid phoneme found in lexicon file: {reader.Value}" ); + } + lastNodeName = reader.Name; + } + return true; + } + catch ( Exception ex ) + { + Logging.Warn( $"Could not load lexicon file '{filename}', please review.", ex ); + return false; + } + } + + #endregion } } diff --git a/SpeechService/SpeechService.cs b/SpeechService/SpeechService.cs index 5fc26ce58f..b6fd3dc7a0 100644 --- a/SpeechService/SpeechService.cs +++ b/SpeechService/SpeechService.cs @@ -22,8 +22,6 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; -using System.Xml; -using System.Xml.Linq; using System.Xml.Schema; using Utilities; @@ -57,7 +55,7 @@ public SpeechServiceConfiguration Configuration .Select(v => v.name) .ToList(); - private readonly XmlSchemaSet lexiconSchemas = new XmlSchemaSet(); + internal readonly XmlSchemaSet lexiconSchemas = new XmlSchemaSet(); private static readonly object activeAudioLock = new object(); private static readonly object activeSpeechLock = new object(); @@ -787,128 +785,30 @@ public class VoiceDetails : IEquatable public string synthType { get; } [Utilities.PublicAPI] - public string cultureinvariantname => Culture.EnglishName; + public string cultureinvariantname { get; } [Utilities.PublicAPI] - public string culturename => Culture.NativeName; - - public CultureInfo Culture { get; } + public string culturename { get; } public bool hideVoice { get; set; } + internal string cultureTwoLetterISOLanguageName; + internal string cultureIetfLanguageTag; + internal VoiceDetails( string displayName, string gender, CultureInfo Culture, string synthType, XmlSchemaSet lexiconSchemas ) { this.name = displayName; this.gender = gender; - this.Culture = Culture; + this.cultureinvariantname = Culture.EnglishName; + this.culturename = Culture.NativeName; + this.cultureTwoLetterISOLanguageName = Culture.TwoLetterISOLanguageName; + this.cultureIetfLanguageTag = Culture.IetfLanguageTag; this.synthType = synthType; - culturecode = BestGuessCulture(); - this.lexiconSchemas = lexiconSchemas; - } - - #region Lexicons - - private XmlSchemaSet lexiconSchemas; - - public HashSet GetLexicons() - { - var result = new HashSet(); - HashSet GetLexiconsFromDirectory(string directory, bool createIfMissing = false) - { - // When multiple lexicons are referenced, their precedence goes from lower to higher with document order. - // Precedence means that a token is first looked up in the lexicon with highest precedence. - // Only if not found in that lexicon, the next lexicon is searched and so on until a first match or until all lexicons have been used for lookup. (https://www.w3.org/TR/2004/REC-speech-synthesis-20040907/#S3.1.4). - - if (string.IsNullOrEmpty(directory) || string.IsNullOrEmpty(culturecode)) { return null; } - DirectoryInfo dir = new DirectoryInfo(directory); - if (dir.Exists) - { - // Find two letter language code lexicons (these will have lower precedence than any full language code lexicons) - foreach (var file in dir.GetFiles("*.pls", SearchOption.AllDirectories) - .Where(f => $"{f.Name.ToLowerInvariant()}" == $"{Culture.TwoLetterISOLanguageName.ToLowerInvariant()}.pls")) - { - CheckAndAdd(file); - } - // Find full language code lexicons - foreach (var file in dir.GetFiles("*.pls", SearchOption.AllDirectories) - .Where(f => $"{f.Name.ToLowerInvariant()}" == $"{Culture.IetfLanguageTag.ToLowerInvariant()}.pls")) - { - CheckAndAdd(file); - } - } - else if (createIfMissing) - { - dir.Create(); - } - return result; - } - - void CheckAndAdd(FileInfo file) - { - if (IsValidXML(file.FullName, out _)) - { - result.Add(file.FullName); - } - else - { - file.MoveTo($"{file.FullName}.malformed"); - } - } - - // When multiple lexicons are referenced, their precedence goes from lower to higher with document order (https://www.w3.org/TR/2004/REC-speech-synthesis-20040907/#S3.1.4) - - // Add lexicons from our installation directory - result.UnionWith(GetLexiconsFromDirectory(new FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).DirectoryName + @"\lexicons")); - - // Add lexicons from our user configuration (allowing these to overwrite any prior lexeme values) - result.UnionWith(GetLexiconsFromDirectory(Constants.DATA_DIR + @"\lexicons")); - - return result; - } - - private bool IsValidXML(string filename, out XDocument xml) - { - // Check whether the file is valid .xml (.pls is an xml-based format) - xml = null; - try - { - // Try to load the file as xml - xml = XDocument.Load(filename); - - // Validate the lexicon xml against the schema - xml.Validate(lexiconSchemas, ( o, e ) => - { - if ( e.Severity == XmlSeverityType.Warning || e.Severity == XmlSeverityType.Error ) - { - throw new XmlSchemaValidationException( e.Message, e.Exception ); - } - } ); - var reader = xml.CreateReader(); - var lastNodeName = string.Empty; - while ( reader.Read() ) - { - if ( reader.HasValue && - reader.NodeType is XmlNodeType.Text && - lastNodeName == "phoneme" && - !IPA.IsValid( reader.Value ) ) - { - throw new ArgumentException( $"Invalid phoneme found in lexicon file: {reader.Value}" ); - } - lastNodeName = reader.Name; - } - return true; - } - catch (Exception ex) - { - Logging.Warn($"Could not load lexicon file '{filename}', please review.", ex); - return false; - } + culturecode = BestGuessCulture(Culture); } - #endregion - - private string BestGuessCulture() + private string BestGuessCulture(CultureInfo Culture) { string guess; if (name.Contains("CereVoice")) From 151a00f511e901304dd8200cd2f00223113e64ab Mon Sep 17 00:00:00 2001 From: T'kael Date: Mon, 1 Jul 2024 12:23:27 -0700 Subject: [PATCH 20/36] To 4.1.0-a2 --- ChangeLog.md | 2 ++ Installer.iss | 2 +- Utilities/Constants.cs | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index f7a20cc979..633bc084e8 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -2,6 +2,8 @@ Full details of the variables available for each noted event, and VoiceAttack integrations, are available in the individual [event pages](https://github.com/EDCD/EDDI/wiki/Events). +## 4.1.0-a2 + ## 4.1.0-a1 * Events * `Cargo Transfer` added. (#2621) diff --git a/Installer.iss b/Installer.iss index a21fc5015c..78bcf4b52c 100644 --- a/Installer.iss +++ b/Installer.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "EDDI" -#define MyAppVersion "4.1.0-a1" +#define MyAppVersion "4.1.0-a2" #define MyAppPublisher "Elite Dangerous Community Developers (EDCD)" #define MyAppURL "https://github.com/EDCD/EDDI/" #define MyAppExeName "EDDI.exe" diff --git a/Utilities/Constants.cs b/Utilities/Constants.cs index bd8ce38840..58afab64fa 100644 --- a/Utilities/Constants.cs +++ b/Utilities/Constants.cs @@ -9,7 +9,7 @@ public class Constants { public const string EDDI_NAME = "EDDI"; public const string EDDI_URL_PROTOCOL = "eddi"; - public static Version EDDI_VERSION = new Version(4, 1, 0, Version.TestPhase.a, 1); + public static Version EDDI_VERSION = new Version(4, 1, 0, Version.TestPhase.a, 2); public const string EDDI_SERVER_URL = "https://edcd.github.io/EDDP/"; public static readonly string EDDI_SYSTEM_MUTEX_NAME = $"{EDDI_SERVER_URL}/{EDDI_NAME}/{Environment.GetEnvironmentVariable("UserName")}"; From e06997f3904191b44c7320abf90f6189973a339a Mon Sep 17 00:00:00 2001 From: T'kael Date: Mon, 1 Jul 2024 12:25:13 -0700 Subject: [PATCH 21/36] Increased the render cycle limit from 10,0000 to 100,000. Revise the `System materials report` script to more efficiently identify volcanic bodies. Resolves #2628 --- ChangeLog.md | 8 ++++++-- SpeechResponder/ScriptResolverService/ScriptResolver.cs | 2 +- SpeechResponder/eddi.cs.json | 2 +- SpeechResponder/eddi.de.json | 2 +- SpeechResponder/eddi.hu.json | 2 +- SpeechResponder/eddi.it.json | 2 +- SpeechResponder/eddi.ja.json | 2 +- SpeechResponder/eddi.json | 2 +- SpeechResponder/eddi.ru.json | 2 +- 9 files changed, 14 insertions(+), 10 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 633bc084e8..0876bcf831 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -3,14 +3,18 @@ Full details of the variables available for each noted event, and VoiceAttack integrations, are available in the individual [event pages](https://github.com/EDCD/EDDI/wiki/Events). ## 4.1.0-a2 + * Speech Responder + * Increased the render cycle limit () from 10,0000 to 100,000. + * Scripts + * `System materials report` updated to more efficiently identify volcanic bodies. ## 4.1.0-a1 * Events * `Cargo Transfer` added. (#2621) * Speech Responder - * Update Cottle to latest available experimental version. + * Update Cottle to latest available experimental version. Variables which are set in a script are now being stored in an immutable context. While these variables can still be passed to a child script / context, variables in a child script / context cannot be set and passed back to a parent script / context. * Custom Functions - * `SetState` no longer is able to retrieve a state variable from from the same script / context where it was set. + * A variable set with `SetState` can no longer be retrieved using `state` from the same script / context where it was set. * `GetState` has been added to allow retrieval of state variables in the same script / context where it was set. * Scripts * `Blueprint make report` updated to simplify state retrieval. diff --git a/SpeechResponder/ScriptResolverService/ScriptResolver.cs b/SpeechResponder/ScriptResolverService/ScriptResolver.cs index 2dd285e10f..b9b255afcc 100644 --- a/SpeechResponder/ScriptResolverService/ScriptResolver.cs +++ b/SpeechResponder/ScriptResolverService/ScriptResolver.cs @@ -21,7 +21,7 @@ public class ScriptResolver public readonly Dictionary Scripts; public static readonly DocumentConfiguration documentConfiguration = new DocumentConfiguration { - Trimmer = DocumentConfiguration.TrimRepeatedWhitespaces, NbCycleMax = 10000 + Trimmer = DocumentConfiguration.TrimRepeatedWhitespaces, NbCycleMax = 100000 }; // The file to log speech diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index da80a30043..89765fcb8f 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index 9e775ad69e..da79dcc5ca 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index 4afcf74e9f..b872e99b26 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index 4afcf74e9f..b872e99b26 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index 4afcf74e9f..b872e99b26 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index 0ba078cd3f..52c237aa5e 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index 4afcf74e9f..b872e99b26 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n\r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && isVolcanic(bodyName, reportSystem):\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isVolcanic(bodyName, reportSystem) to:\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.name = bodyName:\r\n {return reportBody.volcanism}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats),\r\n \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname, reportSystem):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats, cmp(a, b)):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" From f0138cf584d1cd8ad9e76ccc36e09531e66fc99b Mon Sep 17 00:00:00 2001 From: T'kael Date: Fri, 5 Jul 2024 17:03:34 -0700 Subject: [PATCH 22/36] Upgrade Cottle to 2.1.0. --- SpeechResponder/EddiSpeechResponder.csproj | 2 +- Tests/Tests.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SpeechResponder/EddiSpeechResponder.csproj b/SpeechResponder/EddiSpeechResponder.csproj index 91d66efedd..812c00e64e 100644 --- a/SpeechResponder/EddiSpeechResponder.csproj +++ b/SpeechResponder/EddiSpeechResponder.csproj @@ -92,7 +92,7 @@ 0.15.1 - 2.1.0-experimental1 + 2.1.0 2023.3.0 diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 06c58f86e5..827c34444f 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -48,7 +48,7 @@ - 2.1.0-experimental1 + 2.1.0 1.2.1.2 From 32c58762b9ddc5580db204169af328e9187e1da5 Mon Sep 17 00:00:00 2001 From: T'kael Date: Sat, 6 Jul 2024 13:54:20 -0700 Subject: [PATCH 23/36] Further refine `Mission check system` script. --- SpeechResponder/eddi.cs.json | 4 ++-- SpeechResponder/eddi.de.json | 4 ++-- SpeechResponder/eddi.hu.json | 4 ++-- SpeechResponder/eddi.it.json | 4 ++-- SpeechResponder/eddi.ja.json | 4 ++-- SpeechResponder/eddi.json | 4 ++-- SpeechResponder/eddi.ru.json | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index 89765fcb8f..46c203f319 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -1513,7 +1513,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Mission check galaxy }\r\n{_ Check what systems you have missions in }\r\n\r\n\r\n{_ Setup allmissions function _}\r\n{set allmissions(system) to:\r\n {set here to find(systems, system)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [system])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", + "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", "default": true, "name": "Mission check galaxy", "description": "Check what systems you have missions in" @@ -1531,7 +1531,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Mission check system }\r\n{_ Check what missions you have for the current system }\r\n\r\n{_ Setup addstation function }\r\n{set addstation(station) to:\r\n {set missions_here to missions_here + 1}\r\n {set station_based to station_based + 1}\r\n {set here to find(stations_here, station)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\":\r\n {set active to stations_active[here] + 1}\r\n {set stations_active to union(stations_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to stations_claim[here] + 1}\r\n {set stations_claim to union(stations_claim, [here:claim])}\r\n }\r\n |else:\r\n {set stations_here to cat(stations_here, [station])}\r\n {if mission.statusEDName = \"Active\":\r\n {set stations_active to cat(stations_active, [1])}\r\n {set stations_claim to cat(stations_claim , [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set stations_active to cat(stations_active, [0])}\r\n {set stations_claim to cat(stations_claim , [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set missions_here to 0}\r\n {set station_based to 0}\r\n {set stations_active to []}\r\n {set stations_claim to []}\r\n {set stations_here to []}\r\n {set non_stations to []}\r\n\r\n {_ Find all missions in the current system and identify all the stations }\r\n {for mission in missions:\r\n {if mission.status != \"Failed\":\r\n {if mission.destinationsystems:\r\n {for destination in mission.destinationsystems:\r\n {if destination.name = system.name && !destination.visited:\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.destinationsystem = system.name:\r\n {if mission.destinationstation && mission.destinationstation != \"\":\r\n {addstation(mission.destinationstation)}\r\n |else:\r\n {if mission.status = \"Active\":\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.originsystem = system.name && find(mission.invariantTags, \"Delivery\") > -1:\r\n {if mission.originstation && mission.originstation != \"\":\r\n {addstation(mission.originstation)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {if missions_here > 0:\r\n {set missionSummaries to []}\r\n {set cur to 0}\r\n {for station in stations_here:\r\n {set station to StationDetails(station)}\r\n {set active to stations_active[cur]}\r\n {set claim to stations_claim[cur]}\r\n {set depot to stations_depot[cur]}\r\n\r\n {set summaries to []}\r\n {if active > 0:\r\n {set activeSummary to: \r\n {active} {OneOf(\"active\", \"pending\")} {if active = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [activeSummary])}\r\n }\r\n {if claim > 0:\r\n {set claimSummary to: \r\n {claim} claimable {if claim = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [claimSummary])}\r\n }\r\n {if len(summaries) > 0:\r\n {set stationSummary to:\r\n {List(summaries)} at \r\n {Occasionally(2, \"the {P(station.model, 'station')}, \")}\r\n {station.name}\r\n }\r\n {set missionSummaries to cat(missionSummaries, [stationSummary])}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n \r\n {set remaining to missions_here - station_based}\r\n {if remaining > 0:\r\n {set otherMissions to:\r\n {remaining} {if len(missionSummaries) > 0: other}\r\n {if remaining > 1: missions |else: mission}\r\n }\r\n {set missionSummaries to cat(missionSummaries, [otherMissions])}\r\n }\r\n\r\n {if len(missionSummaries) > 0:\r\n {Pause(500)}\r\n You have\r\n {List(missionSummaries)}\r\n {OneOf(\"here\", \"in this system\")}.\r\n }\r\n }\r\n}", + "script": "{_ Setup addstation function }\r\n{set addstation(stationName, mission) to:\r\n {set missions_here to missions_here + 1}\r\n {set station_based to station_based + 1}\r\n {set here to find(stations_here, stationName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\":\r\n {set active to stations_active[here] + 1}\r\n {set stations_active to union(stations_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to stations_claim[here] + 1}\r\n {set stations_claim to union(stations_claim, [here:claim])}\r\n }\r\n |else:\r\n {set stations_here to cat(stations_here, [stationName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set stations_active to cat(stations_active, [1])}\r\n {set stations_claim to cat(stations_claim , [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set stations_active to cat(stations_active, [0])}\r\n {set stations_claim to cat(stations_claim , [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set missions_here to 0}\r\n {set station_based to 0}\r\n {set stations_active to []}\r\n {set stations_claim to []}\r\n {set stations_here to []}\r\n {set non_stations to []}\r\n\r\n {_ Find all missions in the current system and identify all the stations }\r\n {for mission in missions:\r\n {if mission.status != \"Failed\":\r\n {if mission.destinationsystems:\r\n {for destination in mission.destinationsystems:\r\n {if destination.name = system.name && !destination.visited:\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.destinationsystem = system.name:\r\n {if mission.destinationstation && mission.destinationstation != \"\":\r\n {addstation(mission.destinationstation, mission)}\r\n |else:\r\n {if mission.status = \"Active\":\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.originsystem = system.name && find(mission.invariantTags, \"Delivery\") > -1:\r\n {if mission.originstation && mission.originstation != \"\":\r\n {addstation(mission.originstation, mission)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {if missions_here > 0:\r\n {set missionSummaries to []}\r\n {set cur to 0}\r\n {for station in stations_here:\r\n {set station to StationDetails(station)}\r\n {set active to stations_active[cur]}\r\n {set claim to stations_claim[cur]}\r\n {set depot to stations_depot[cur]}\r\n\r\n {set summaries to []}\r\n {if active > 0:\r\n {set activeSummary to: \r\n {active} {OneOf(\"active\", \"pending\")} {if active = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [activeSummary])}\r\n }\r\n {if claim > 0:\r\n {set claimSummary to: \r\n {claim} claimable {if claim = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [claimSummary])}\r\n }\r\n {if len(summaries) > 0:\r\n {set summary to:\r\n {List(summaries)} here\r\n {if station:\r\n at \r\n {set stationModel to P(station.model, 'station')}\r\n {if stationModel: {Occasionally(2, \"the {stationModel}, \")} }\r\n {station.name}\r\n }\r\n }\r\n {set missionSummaries to cat(missionSummaries, [summary])}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n \r\n {set remaining to missions_here - station_based}\r\n {if remaining > 0:\r\n {set otherMissions to:\r\n {remaining} {if len(missionSummaries) > 0: other}\r\n {if remaining > 1: missions |else: mission}\r\n here\r\n }\r\n {set missionSummaries to cat(missionSummaries, [otherMissions])}\r\n }\r\n\r\n {if len(missionSummaries) > 0:\r\n {Pause(500)}\r\n You have\r\n {List(missionSummaries)}.\r\n }\r\n }\r\n}", "default": true, "name": "Mission check system", "description": "Check what missions you have for the current system" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index da79dcc5ca..5981ea9697 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -1513,7 +1513,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Mission check galaxy }\r\n{_ Check what systems you have missions in }\r\n\r\n\r\n{_ Setup allmissions function _}\r\n{set allmissions(system) to:\r\n {set here to find(systems, system)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [system])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", + "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", "default": true, "name": "Mission check galaxy", "description": "Check what systems you have missions in" @@ -1531,7 +1531,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Mission check system }\r\n{_ Check what missions you have for the current system }\r\n\r\n{_ Setup addstation function }\r\n{set addstation(station) to:\r\n {set missions_here to missions_here + 1}\r\n {set station_based to station_based + 1}\r\n {set here to find(stations_here, station)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\":\r\n {set active to stations_active[here] + 1}\r\n {set stations_active to union(stations_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to stations_claim[here] + 1}\r\n {set stations_claim to union(stations_claim, [here:claim])}\r\n }\r\n |else:\r\n {set stations_here to cat(stations_here, [station])}\r\n {if mission.statusEDName = \"Active\":\r\n {set stations_active to cat(stations_active, [1])}\r\n {set stations_claim to cat(stations_claim , [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set stations_active to cat(stations_active, [0])}\r\n {set stations_claim to cat(stations_claim , [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set missions_here to 0}\r\n {set station_based to 0}\r\n {set stations_active to []}\r\n {set stations_claim to []}\r\n {set stations_here to []}\r\n {set non_stations to []}\r\n\r\n {_ Find all missions in the current system and identify all the stations }\r\n {for mission in missions:\r\n {if mission.status != \"Failed\":\r\n {if mission.destinationsystems:\r\n {for destination in mission.destinationsystems:\r\n {if destination.name = system.name && !destination.visited:\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.destinationsystem = system.name:\r\n {if mission.destinationstation && mission.destinationstation != \"\":\r\n {addstation(mission.destinationstation)}\r\n |else:\r\n {if mission.status = \"Active\":\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.originsystem = system.name && find(mission.invariantTags, \"Delivery\") > -1:\r\n {if mission.originstation && mission.originstation != \"\":\r\n {addstation(mission.originstation)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {if missions_here > 0:\r\n {set missionSummaries to []}\r\n {set cur to 0}\r\n {for station in stations_here:\r\n {set station to StationDetails(station)}\r\n {set active to stations_active[cur]}\r\n {set claim to stations_claim[cur]}\r\n {set depot to stations_depot[cur]}\r\n\r\n {set summaries to []}\r\n {if active > 0:\r\n {set activeSummary to: \r\n {active} {OneOf(\"active\", \"pending\")} {if active = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [activeSummary])}\r\n }\r\n {if claim > 0:\r\n {set claimSummary to: \r\n {claim} claimable {if claim = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [claimSummary])}\r\n }\r\n {if len(summaries) > 0:\r\n {set stationSummary to:\r\n {List(summaries)} at \r\n {Occasionally(2, \"the {P(station.model, 'station')}, \")}\r\n {station.name}\r\n }\r\n {set missionSummaries to cat(missionSummaries, [stationSummary])}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n \r\n {set remaining to missions_here - station_based}\r\n {if remaining > 0:\r\n {set otherMissions to:\r\n {remaining} {if len(missionSummaries) > 0: other}\r\n {if remaining > 1: missions |else: mission}\r\n }\r\n {set missionSummaries to cat(missionSummaries, [otherMissions])}\r\n }\r\n\r\n {if len(missionSummaries) > 0:\r\n {Pause(500)}\r\n You have\r\n {List(missionSummaries)}\r\n {OneOf(\"here\", \"in this system\")}.\r\n }\r\n }\r\n}", + "script": "{_ Setup addstation function }\r\n{set addstation(stationName, mission) to:\r\n {set missions_here to missions_here + 1}\r\n {set station_based to station_based + 1}\r\n {set here to find(stations_here, stationName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\":\r\n {set active to stations_active[here] + 1}\r\n {set stations_active to union(stations_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to stations_claim[here] + 1}\r\n {set stations_claim to union(stations_claim, [here:claim])}\r\n }\r\n |else:\r\n {set stations_here to cat(stations_here, [stationName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set stations_active to cat(stations_active, [1])}\r\n {set stations_claim to cat(stations_claim , [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set stations_active to cat(stations_active, [0])}\r\n {set stations_claim to cat(stations_claim , [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set missions_here to 0}\r\n {set station_based to 0}\r\n {set stations_active to []}\r\n {set stations_claim to []}\r\n {set stations_here to []}\r\n {set non_stations to []}\r\n\r\n {_ Find all missions in the current system and identify all the stations }\r\n {for mission in missions:\r\n {if mission.status != \"Failed\":\r\n {if mission.destinationsystems:\r\n {for destination in mission.destinationsystems:\r\n {if destination.name = system.name && !destination.visited:\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.destinationsystem = system.name:\r\n {if mission.destinationstation && mission.destinationstation != \"\":\r\n {addstation(mission.destinationstation, mission)}\r\n |else:\r\n {if mission.status = \"Active\":\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.originsystem = system.name && find(mission.invariantTags, \"Delivery\") > -1:\r\n {if mission.originstation && mission.originstation != \"\":\r\n {addstation(mission.originstation, mission)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {if missions_here > 0:\r\n {set missionSummaries to []}\r\n {set cur to 0}\r\n {for station in stations_here:\r\n {set station to StationDetails(station)}\r\n {set active to stations_active[cur]}\r\n {set claim to stations_claim[cur]}\r\n {set depot to stations_depot[cur]}\r\n\r\n {set summaries to []}\r\n {if active > 0:\r\n {set activeSummary to: \r\n {active} {OneOf(\"active\", \"pending\")} {if active = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [activeSummary])}\r\n }\r\n {if claim > 0:\r\n {set claimSummary to: \r\n {claim} claimable {if claim = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [claimSummary])}\r\n }\r\n {if len(summaries) > 0:\r\n {set summary to:\r\n {List(summaries)} here\r\n {if station:\r\n at \r\n {set stationModel to P(station.model, 'station')}\r\n {if stationModel: {Occasionally(2, \"the {stationModel}, \")} }\r\n {station.name}\r\n }\r\n }\r\n {set missionSummaries to cat(missionSummaries, [summary])}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n \r\n {set remaining to missions_here - station_based}\r\n {if remaining > 0:\r\n {set otherMissions to:\r\n {remaining} {if len(missionSummaries) > 0: other}\r\n {if remaining > 1: missions |else: mission}\r\n here\r\n }\r\n {set missionSummaries to cat(missionSummaries, [otherMissions])}\r\n }\r\n\r\n {if len(missionSummaries) > 0:\r\n {Pause(500)}\r\n You have\r\n {List(missionSummaries)}.\r\n }\r\n }\r\n}", "default": true, "name": "Mission check system", "description": "Check what missions you have for the current system" diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index b872e99b26..1c762147dc 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -1513,7 +1513,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Mission check galaxy }\r\n{_ Check what systems you have missions in }\r\n\r\n\r\n{_ Setup allmissions function _}\r\n{set allmissions(system) to:\r\n {set here to find(systems, system)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [system])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", + "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", "default": true, "name": "Mission check galaxy", "description": "Check what systems you have missions in" @@ -1531,7 +1531,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Mission check system }\r\n{_ Check what missions you have for the current system }\r\n\r\n{_ Setup addstation function }\r\n{set addstation(station) to:\r\n {set missions_here to missions_here + 1}\r\n {set station_based to station_based + 1}\r\n {set here to find(stations_here, station)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\":\r\n {set active to stations_active[here] + 1}\r\n {set stations_active to union(stations_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to stations_claim[here] + 1}\r\n {set stations_claim to union(stations_claim, [here:claim])}\r\n }\r\n |else:\r\n {set stations_here to cat(stations_here, [station])}\r\n {if mission.statusEDName = \"Active\":\r\n {set stations_active to cat(stations_active, [1])}\r\n {set stations_claim to cat(stations_claim , [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set stations_active to cat(stations_active, [0])}\r\n {set stations_claim to cat(stations_claim , [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set missions_here to 0}\r\n {set station_based to 0}\r\n {set stations_active to []}\r\n {set stations_claim to []}\r\n {set stations_here to []}\r\n {set non_stations to []}\r\n\r\n {_ Find all missions in the current system and identify all the stations }\r\n {for mission in missions:\r\n {if mission.status != \"Failed\":\r\n {if mission.destinationsystems:\r\n {for destination in mission.destinationsystems:\r\n {if destination.name = system.name && !destination.visited:\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.destinationsystem = system.name:\r\n {if mission.destinationstation && mission.destinationstation != \"\":\r\n {addstation(mission.destinationstation)}\r\n |else:\r\n {if mission.status = \"Active\":\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.originsystem = system.name && find(mission.invariantTags, \"Delivery\") > -1:\r\n {if mission.originstation && mission.originstation != \"\":\r\n {addstation(mission.originstation)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {if missions_here > 0:\r\n {set missionSummaries to []}\r\n {set cur to 0}\r\n {for station in stations_here:\r\n {set station to StationDetails(station)}\r\n {set active to stations_active[cur]}\r\n {set claim to stations_claim[cur]}\r\n {set depot to stations_depot[cur]}\r\n\r\n {set summaries to []}\r\n {if active > 0:\r\n {set activeSummary to: \r\n {active} {OneOf(\"active\", \"pending\")} {if active = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [activeSummary])}\r\n }\r\n {if claim > 0:\r\n {set claimSummary to: \r\n {claim} claimable {if claim = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [claimSummary])}\r\n }\r\n {if len(summaries) > 0:\r\n {set stationSummary to:\r\n {List(summaries)} at \r\n {Occasionally(2, \"the {P(station.model, 'station')}, \")}\r\n {station.name}\r\n }\r\n {set missionSummaries to cat(missionSummaries, [stationSummary])}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n \r\n {set remaining to missions_here - station_based}\r\n {if remaining > 0:\r\n {set otherMissions to:\r\n {remaining} {if len(missionSummaries) > 0: other}\r\n {if remaining > 1: missions |else: mission}\r\n }\r\n {set missionSummaries to cat(missionSummaries, [otherMissions])}\r\n }\r\n\r\n {if len(missionSummaries) > 0:\r\n {Pause(500)}\r\n You have\r\n {List(missionSummaries)}\r\n {OneOf(\"here\", \"in this system\")}.\r\n }\r\n }\r\n}", + "script": "{_ Setup addstation function }\r\n{set addstation(stationName, mission) to:\r\n {set missions_here to missions_here + 1}\r\n {set station_based to station_based + 1}\r\n {set here to find(stations_here, stationName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\":\r\n {set active to stations_active[here] + 1}\r\n {set stations_active to union(stations_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to stations_claim[here] + 1}\r\n {set stations_claim to union(stations_claim, [here:claim])}\r\n }\r\n |else:\r\n {set stations_here to cat(stations_here, [stationName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set stations_active to cat(stations_active, [1])}\r\n {set stations_claim to cat(stations_claim , [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set stations_active to cat(stations_active, [0])}\r\n {set stations_claim to cat(stations_claim , [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set missions_here to 0}\r\n {set station_based to 0}\r\n {set stations_active to []}\r\n {set stations_claim to []}\r\n {set stations_here to []}\r\n {set non_stations to []}\r\n\r\n {_ Find all missions in the current system and identify all the stations }\r\n {for mission in missions:\r\n {if mission.status != \"Failed\":\r\n {if mission.destinationsystems:\r\n {for destination in mission.destinationsystems:\r\n {if destination.name = system.name && !destination.visited:\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.destinationsystem = system.name:\r\n {if mission.destinationstation && mission.destinationstation != \"\":\r\n {addstation(mission.destinationstation, mission)}\r\n |else:\r\n {if mission.status = \"Active\":\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.originsystem = system.name && find(mission.invariantTags, \"Delivery\") > -1:\r\n {if mission.originstation && mission.originstation != \"\":\r\n {addstation(mission.originstation, mission)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {if missions_here > 0:\r\n {set missionSummaries to []}\r\n {set cur to 0}\r\n {for station in stations_here:\r\n {set station to StationDetails(station)}\r\n {set active to stations_active[cur]}\r\n {set claim to stations_claim[cur]}\r\n {set depot to stations_depot[cur]}\r\n\r\n {set summaries to []}\r\n {if active > 0:\r\n {set activeSummary to: \r\n {active} {OneOf(\"active\", \"pending\")} {if active = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [activeSummary])}\r\n }\r\n {if claim > 0:\r\n {set claimSummary to: \r\n {claim} claimable {if claim = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [claimSummary])}\r\n }\r\n {if len(summaries) > 0:\r\n {set summary to:\r\n {List(summaries)} here\r\n {if station:\r\n at \r\n {set stationModel to P(station.model, 'station')}\r\n {if stationModel: {Occasionally(2, \"the {stationModel}, \")} }\r\n {station.name}\r\n }\r\n }\r\n {set missionSummaries to cat(missionSummaries, [summary])}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n \r\n {set remaining to missions_here - station_based}\r\n {if remaining > 0:\r\n {set otherMissions to:\r\n {remaining} {if len(missionSummaries) > 0: other}\r\n {if remaining > 1: missions |else: mission}\r\n here\r\n }\r\n {set missionSummaries to cat(missionSummaries, [otherMissions])}\r\n }\r\n\r\n {if len(missionSummaries) > 0:\r\n {Pause(500)}\r\n You have\r\n {List(missionSummaries)}.\r\n }\r\n }\r\n}", "default": true, "name": "Mission check system", "description": "Check what missions you have for the current system" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index b872e99b26..1c762147dc 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -1513,7 +1513,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Mission check galaxy }\r\n{_ Check what systems you have missions in }\r\n\r\n\r\n{_ Setup allmissions function _}\r\n{set allmissions(system) to:\r\n {set here to find(systems, system)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [system])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", + "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", "default": true, "name": "Mission check galaxy", "description": "Check what systems you have missions in" @@ -1531,7 +1531,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Mission check system }\r\n{_ Check what missions you have for the current system }\r\n\r\n{_ Setup addstation function }\r\n{set addstation(station) to:\r\n {set missions_here to missions_here + 1}\r\n {set station_based to station_based + 1}\r\n {set here to find(stations_here, station)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\":\r\n {set active to stations_active[here] + 1}\r\n {set stations_active to union(stations_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to stations_claim[here] + 1}\r\n {set stations_claim to union(stations_claim, [here:claim])}\r\n }\r\n |else:\r\n {set stations_here to cat(stations_here, [station])}\r\n {if mission.statusEDName = \"Active\":\r\n {set stations_active to cat(stations_active, [1])}\r\n {set stations_claim to cat(stations_claim , [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set stations_active to cat(stations_active, [0])}\r\n {set stations_claim to cat(stations_claim , [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set missions_here to 0}\r\n {set station_based to 0}\r\n {set stations_active to []}\r\n {set stations_claim to []}\r\n {set stations_here to []}\r\n {set non_stations to []}\r\n\r\n {_ Find all missions in the current system and identify all the stations }\r\n {for mission in missions:\r\n {if mission.status != \"Failed\":\r\n {if mission.destinationsystems:\r\n {for destination in mission.destinationsystems:\r\n {if destination.name = system.name && !destination.visited:\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.destinationsystem = system.name:\r\n {if mission.destinationstation && mission.destinationstation != \"\":\r\n {addstation(mission.destinationstation)}\r\n |else:\r\n {if mission.status = \"Active\":\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.originsystem = system.name && find(mission.invariantTags, \"Delivery\") > -1:\r\n {if mission.originstation && mission.originstation != \"\":\r\n {addstation(mission.originstation)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {if missions_here > 0:\r\n {set missionSummaries to []}\r\n {set cur to 0}\r\n {for station in stations_here:\r\n {set station to StationDetails(station)}\r\n {set active to stations_active[cur]}\r\n {set claim to stations_claim[cur]}\r\n {set depot to stations_depot[cur]}\r\n\r\n {set summaries to []}\r\n {if active > 0:\r\n {set activeSummary to: \r\n {active} {OneOf(\"active\", \"pending\")} {if active = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [activeSummary])}\r\n }\r\n {if claim > 0:\r\n {set claimSummary to: \r\n {claim} claimable {if claim = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [claimSummary])}\r\n }\r\n {if len(summaries) > 0:\r\n {set stationSummary to:\r\n {List(summaries)} at \r\n {Occasionally(2, \"the {P(station.model, 'station')}, \")}\r\n {station.name}\r\n }\r\n {set missionSummaries to cat(missionSummaries, [stationSummary])}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n \r\n {set remaining to missions_here - station_based}\r\n {if remaining > 0:\r\n {set otherMissions to:\r\n {remaining} {if len(missionSummaries) > 0: other}\r\n {if remaining > 1: missions |else: mission}\r\n }\r\n {set missionSummaries to cat(missionSummaries, [otherMissions])}\r\n }\r\n\r\n {if len(missionSummaries) > 0:\r\n {Pause(500)}\r\n You have\r\n {List(missionSummaries)}\r\n {OneOf(\"here\", \"in this system\")}.\r\n }\r\n }\r\n}", + "script": "{_ Setup addstation function }\r\n{set addstation(stationName, mission) to:\r\n {set missions_here to missions_here + 1}\r\n {set station_based to station_based + 1}\r\n {set here to find(stations_here, stationName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\":\r\n {set active to stations_active[here] + 1}\r\n {set stations_active to union(stations_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to stations_claim[here] + 1}\r\n {set stations_claim to union(stations_claim, [here:claim])}\r\n }\r\n |else:\r\n {set stations_here to cat(stations_here, [stationName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set stations_active to cat(stations_active, [1])}\r\n {set stations_claim to cat(stations_claim , [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set stations_active to cat(stations_active, [0])}\r\n {set stations_claim to cat(stations_claim , [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set missions_here to 0}\r\n {set station_based to 0}\r\n {set stations_active to []}\r\n {set stations_claim to []}\r\n {set stations_here to []}\r\n {set non_stations to []}\r\n\r\n {_ Find all missions in the current system and identify all the stations }\r\n {for mission in missions:\r\n {if mission.status != \"Failed\":\r\n {if mission.destinationsystems:\r\n {for destination in mission.destinationsystems:\r\n {if destination.name = system.name && !destination.visited:\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.destinationsystem = system.name:\r\n {if mission.destinationstation && mission.destinationstation != \"\":\r\n {addstation(mission.destinationstation, mission)}\r\n |else:\r\n {if mission.status = \"Active\":\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.originsystem = system.name && find(mission.invariantTags, \"Delivery\") > -1:\r\n {if mission.originstation && mission.originstation != \"\":\r\n {addstation(mission.originstation, mission)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {if missions_here > 0:\r\n {set missionSummaries to []}\r\n {set cur to 0}\r\n {for station in stations_here:\r\n {set station to StationDetails(station)}\r\n {set active to stations_active[cur]}\r\n {set claim to stations_claim[cur]}\r\n {set depot to stations_depot[cur]}\r\n\r\n {set summaries to []}\r\n {if active > 0:\r\n {set activeSummary to: \r\n {active} {OneOf(\"active\", \"pending\")} {if active = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [activeSummary])}\r\n }\r\n {if claim > 0:\r\n {set claimSummary to: \r\n {claim} claimable {if claim = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [claimSummary])}\r\n }\r\n {if len(summaries) > 0:\r\n {set summary to:\r\n {List(summaries)} here\r\n {if station:\r\n at \r\n {set stationModel to P(station.model, 'station')}\r\n {if stationModel: {Occasionally(2, \"the {stationModel}, \")} }\r\n {station.name}\r\n }\r\n }\r\n {set missionSummaries to cat(missionSummaries, [summary])}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n \r\n {set remaining to missions_here - station_based}\r\n {if remaining > 0:\r\n {set otherMissions to:\r\n {remaining} {if len(missionSummaries) > 0: other}\r\n {if remaining > 1: missions |else: mission}\r\n here\r\n }\r\n {set missionSummaries to cat(missionSummaries, [otherMissions])}\r\n }\r\n\r\n {if len(missionSummaries) > 0:\r\n {Pause(500)}\r\n You have\r\n {List(missionSummaries)}.\r\n }\r\n }\r\n}", "default": true, "name": "Mission check system", "description": "Check what missions you have for the current system" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index b872e99b26..1c762147dc 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -1513,7 +1513,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Mission check galaxy }\r\n{_ Check what systems you have missions in }\r\n\r\n\r\n{_ Setup allmissions function _}\r\n{set allmissions(system) to:\r\n {set here to find(systems, system)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [system])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", + "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", "default": true, "name": "Mission check galaxy", "description": "Check what systems you have missions in" @@ -1531,7 +1531,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Mission check system }\r\n{_ Check what missions you have for the current system }\r\n\r\n{_ Setup addstation function }\r\n{set addstation(station) to:\r\n {set missions_here to missions_here + 1}\r\n {set station_based to station_based + 1}\r\n {set here to find(stations_here, station)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\":\r\n {set active to stations_active[here] + 1}\r\n {set stations_active to union(stations_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to stations_claim[here] + 1}\r\n {set stations_claim to union(stations_claim, [here:claim])}\r\n }\r\n |else:\r\n {set stations_here to cat(stations_here, [station])}\r\n {if mission.statusEDName = \"Active\":\r\n {set stations_active to cat(stations_active, [1])}\r\n {set stations_claim to cat(stations_claim , [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set stations_active to cat(stations_active, [0])}\r\n {set stations_claim to cat(stations_claim , [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set missions_here to 0}\r\n {set station_based to 0}\r\n {set stations_active to []}\r\n {set stations_claim to []}\r\n {set stations_here to []}\r\n {set non_stations to []}\r\n\r\n {_ Find all missions in the current system and identify all the stations }\r\n {for mission in missions:\r\n {if mission.status != \"Failed\":\r\n {if mission.destinationsystems:\r\n {for destination in mission.destinationsystems:\r\n {if destination.name = system.name && !destination.visited:\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.destinationsystem = system.name:\r\n {if mission.destinationstation && mission.destinationstation != \"\":\r\n {addstation(mission.destinationstation)}\r\n |else:\r\n {if mission.status = \"Active\":\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.originsystem = system.name && find(mission.invariantTags, \"Delivery\") > -1:\r\n {if mission.originstation && mission.originstation != \"\":\r\n {addstation(mission.originstation)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {if missions_here > 0:\r\n {set missionSummaries to []}\r\n {set cur to 0}\r\n {for station in stations_here:\r\n {set station to StationDetails(station)}\r\n {set active to stations_active[cur]}\r\n {set claim to stations_claim[cur]}\r\n {set depot to stations_depot[cur]}\r\n\r\n {set summaries to []}\r\n {if active > 0:\r\n {set activeSummary to: \r\n {active} {OneOf(\"active\", \"pending\")} {if active = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [activeSummary])}\r\n }\r\n {if claim > 0:\r\n {set claimSummary to: \r\n {claim} claimable {if claim = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [claimSummary])}\r\n }\r\n {if len(summaries) > 0:\r\n {set stationSummary to:\r\n {List(summaries)} at \r\n {Occasionally(2, \"the {P(station.model, 'station')}, \")}\r\n {station.name}\r\n }\r\n {set missionSummaries to cat(missionSummaries, [stationSummary])}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n \r\n {set remaining to missions_here - station_based}\r\n {if remaining > 0:\r\n {set otherMissions to:\r\n {remaining} {if len(missionSummaries) > 0: other}\r\n {if remaining > 1: missions |else: mission}\r\n }\r\n {set missionSummaries to cat(missionSummaries, [otherMissions])}\r\n }\r\n\r\n {if len(missionSummaries) > 0:\r\n {Pause(500)}\r\n You have\r\n {List(missionSummaries)}\r\n {OneOf(\"here\", \"in this system\")}.\r\n }\r\n }\r\n}", + "script": "{_ Setup addstation function }\r\n{set addstation(stationName, mission) to:\r\n {set missions_here to missions_here + 1}\r\n {set station_based to station_based + 1}\r\n {set here to find(stations_here, stationName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\":\r\n {set active to stations_active[here] + 1}\r\n {set stations_active to union(stations_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to stations_claim[here] + 1}\r\n {set stations_claim to union(stations_claim, [here:claim])}\r\n }\r\n |else:\r\n {set stations_here to cat(stations_here, [stationName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set stations_active to cat(stations_active, [1])}\r\n {set stations_claim to cat(stations_claim , [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set stations_active to cat(stations_active, [0])}\r\n {set stations_claim to cat(stations_claim , [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set missions_here to 0}\r\n {set station_based to 0}\r\n {set stations_active to []}\r\n {set stations_claim to []}\r\n {set stations_here to []}\r\n {set non_stations to []}\r\n\r\n {_ Find all missions in the current system and identify all the stations }\r\n {for mission in missions:\r\n {if mission.status != \"Failed\":\r\n {if mission.destinationsystems:\r\n {for destination in mission.destinationsystems:\r\n {if destination.name = system.name && !destination.visited:\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.destinationsystem = system.name:\r\n {if mission.destinationstation && mission.destinationstation != \"\":\r\n {addstation(mission.destinationstation, mission)}\r\n |else:\r\n {if mission.status = \"Active\":\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.originsystem = system.name && find(mission.invariantTags, \"Delivery\") > -1:\r\n {if mission.originstation && mission.originstation != \"\":\r\n {addstation(mission.originstation, mission)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {if missions_here > 0:\r\n {set missionSummaries to []}\r\n {set cur to 0}\r\n {for station in stations_here:\r\n {set station to StationDetails(station)}\r\n {set active to stations_active[cur]}\r\n {set claim to stations_claim[cur]}\r\n {set depot to stations_depot[cur]}\r\n\r\n {set summaries to []}\r\n {if active > 0:\r\n {set activeSummary to: \r\n {active} {OneOf(\"active\", \"pending\")} {if active = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [activeSummary])}\r\n }\r\n {if claim > 0:\r\n {set claimSummary to: \r\n {claim} claimable {if claim = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [claimSummary])}\r\n }\r\n {if len(summaries) > 0:\r\n {set summary to:\r\n {List(summaries)} here\r\n {if station:\r\n at \r\n {set stationModel to P(station.model, 'station')}\r\n {if stationModel: {Occasionally(2, \"the {stationModel}, \")} }\r\n {station.name}\r\n }\r\n }\r\n {set missionSummaries to cat(missionSummaries, [summary])}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n \r\n {set remaining to missions_here - station_based}\r\n {if remaining > 0:\r\n {set otherMissions to:\r\n {remaining} {if len(missionSummaries) > 0: other}\r\n {if remaining > 1: missions |else: mission}\r\n here\r\n }\r\n {set missionSummaries to cat(missionSummaries, [otherMissions])}\r\n }\r\n\r\n {if len(missionSummaries) > 0:\r\n {Pause(500)}\r\n You have\r\n {List(missionSummaries)}.\r\n }\r\n }\r\n}", "default": true, "name": "Mission check system", "description": "Check what missions you have for the current system" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index 52c237aa5e..9633c847c7 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -1513,7 +1513,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Mission check galaxy }\r\n{_ Check what systems you have missions in }\r\n\r\n\r\n{_ Setup allmissions function _}\r\n{set allmissions(system) to:\r\n {set here to find(systems, system)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [system])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", + "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", "default": true, "name": "Mission check galaxy", "description": "Check what systems you have missions in" @@ -1531,7 +1531,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Mission check system }\r\n{_ Check what missions you have for the current system }\r\n\r\n{_ Setup addstation function }\r\n{set addstation(station) to:\r\n {set missions_here to missions_here + 1}\r\n {set station_based to station_based + 1}\r\n {set here to find(stations_here, station)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\":\r\n {set active to stations_active[here] + 1}\r\n {set stations_active to union(stations_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to stations_claim[here] + 1}\r\n {set stations_claim to union(stations_claim, [here:claim])}\r\n }\r\n |else:\r\n {set stations_here to cat(stations_here, [station])}\r\n {if mission.statusEDName = \"Active\":\r\n {set stations_active to cat(stations_active, [1])}\r\n {set stations_claim to cat(stations_claim , [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set stations_active to cat(stations_active, [0])}\r\n {set stations_claim to cat(stations_claim , [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set missions_here to 0}\r\n {set station_based to 0}\r\n {set stations_active to []}\r\n {set stations_claim to []}\r\n {set stations_here to []}\r\n {set non_stations to []}\r\n\r\n {_ Find all missions in the current system and identify all the stations }\r\n {for mission in missions:\r\n {if mission.status != \"Failed\":\r\n {if mission.destinationsystems:\r\n {for destination in mission.destinationsystems:\r\n {if destination.name = system.name && !destination.visited:\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.destinationsystem = system.name:\r\n {if mission.destinationstation && mission.destinationstation != \"\":\r\n {addstation(mission.destinationstation)}\r\n |else:\r\n {if mission.status = \"Active\":\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.originsystem = system.name && find(mission.invariantTags, \"Delivery\") > -1:\r\n {if mission.originstation && mission.originstation != \"\":\r\n {addstation(mission.originstation)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {if missions_here > 0:\r\n {set missionSummaries to []}\r\n {set cur to 0}\r\n {for station in stations_here:\r\n {set station to StationDetails(station)}\r\n {set active to stations_active[cur]}\r\n {set claim to stations_claim[cur]}\r\n {set depot to stations_depot[cur]}\r\n\r\n {set summaries to []}\r\n {if active > 0:\r\n {set activeSummary to: \r\n {active} {OneOf(\"active\", \"pending\")} {if active = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [activeSummary])}\r\n }\r\n {if claim > 0:\r\n {set claimSummary to: \r\n {claim} claimable {if claim = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [claimSummary])}\r\n }\r\n {if len(summaries) > 0:\r\n {set summary to:\r\n {List(summaries)} here\r\n {if station:\r\n at \r\n {Occasionally(2, \"the {P(station.model, 'station')}, \")}\r\n {station.name}\r\n }\r\n }\r\n {set missionSummaries to cat(missionSummaries, [summary])}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n \r\n {set remaining to missions_here - station_based}\r\n {if remaining > 0:\r\n {set otherMissions to:\r\n {remaining} {if len(missionSummaries) > 0: other}\r\n {if remaining > 1: missions |else: mission}\r\n here\r\n }\r\n {set missionSummaries to cat(missionSummaries, [otherMissions])}\r\n }\r\n\r\n {if len(missionSummaries) > 0:\r\n {Pause(500)}\r\n You have\r\n {List(missionSummaries)}.\r\n }\r\n }\r\n}", + "script": "{_ Setup addstation function }\r\n{set addstation(stationName, mission) to:\r\n {set missions_here to missions_here + 1}\r\n {set station_based to station_based + 1}\r\n {set here to find(stations_here, stationName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\":\r\n {set active to stations_active[here] + 1}\r\n {set stations_active to union(stations_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to stations_claim[here] + 1}\r\n {set stations_claim to union(stations_claim, [here:claim])}\r\n }\r\n |else:\r\n {set stations_here to cat(stations_here, [stationName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set stations_active to cat(stations_active, [1])}\r\n {set stations_claim to cat(stations_claim , [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set stations_active to cat(stations_active, [0])}\r\n {set stations_claim to cat(stations_claim , [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set missions_here to 0}\r\n {set station_based to 0}\r\n {set stations_active to []}\r\n {set stations_claim to []}\r\n {set stations_here to []}\r\n {set non_stations to []}\r\n\r\n {_ Find all missions in the current system and identify all the stations }\r\n {for mission in missions:\r\n {if mission.status != \"Failed\":\r\n {if mission.destinationsystems:\r\n {for destination in mission.destinationsystems:\r\n {if destination.name = system.name && !destination.visited:\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.destinationsystem = system.name:\r\n {if mission.destinationstation && mission.destinationstation != \"\":\r\n {addstation(mission.destinationstation, mission)}\r\n |else:\r\n {if mission.status = \"Active\":\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.originsystem = system.name && find(mission.invariantTags, \"Delivery\") > -1:\r\n {if mission.originstation && mission.originstation != \"\":\r\n {addstation(mission.originstation, mission)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {if missions_here > 0:\r\n {set missionSummaries to []}\r\n {set cur to 0}\r\n {for station in stations_here:\r\n {set station to StationDetails(station)}\r\n {set active to stations_active[cur]}\r\n {set claim to stations_claim[cur]}\r\n {set depot to stations_depot[cur]}\r\n\r\n {set summaries to []}\r\n {if active > 0:\r\n {set activeSummary to: \r\n {active} {OneOf(\"active\", \"pending\")} {if active = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [activeSummary])}\r\n }\r\n {if claim > 0:\r\n {set claimSummary to: \r\n {claim} claimable {if claim = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [claimSummary])}\r\n }\r\n {if len(summaries) > 0:\r\n {set summary to:\r\n {List(summaries)} here\r\n {if station:\r\n at \r\n {set stationModel to P(station.model, 'station')}\r\n {if stationModel: {Occasionally(2, \"the {stationModel}, \")} }\r\n {station.name}\r\n }\r\n }\r\n {set missionSummaries to cat(missionSummaries, [summary])}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n \r\n {set remaining to missions_here - station_based}\r\n {if remaining > 0:\r\n {set otherMissions to:\r\n {remaining} {if len(missionSummaries) > 0: other}\r\n {if remaining > 1: missions |else: mission}\r\n here\r\n }\r\n {set missionSummaries to cat(missionSummaries, [otherMissions])}\r\n }\r\n\r\n {if len(missionSummaries) > 0:\r\n {Pause(500)}\r\n You have\r\n {List(missionSummaries)}.\r\n }\r\n }\r\n}", "default": true, "name": "Mission check system", "description": "Check what missions you have for the current system" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index b872e99b26..1c762147dc 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -1513,7 +1513,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Mission check galaxy }\r\n{_ Check what systems you have missions in }\r\n\r\n\r\n{_ Setup allmissions function _}\r\n{set allmissions(system) to:\r\n {set here to find(systems, system)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [system])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", + "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", "default": true, "name": "Mission check galaxy", "description": "Check what systems you have missions in" @@ -1531,7 +1531,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Mission check system }\r\n{_ Check what missions you have for the current system }\r\n\r\n{_ Setup addstation function }\r\n{set addstation(station) to:\r\n {set missions_here to missions_here + 1}\r\n {set station_based to station_based + 1}\r\n {set here to find(stations_here, station)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\":\r\n {set active to stations_active[here] + 1}\r\n {set stations_active to union(stations_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to stations_claim[here] + 1}\r\n {set stations_claim to union(stations_claim, [here:claim])}\r\n }\r\n |else:\r\n {set stations_here to cat(stations_here, [station])}\r\n {if mission.statusEDName = \"Active\":\r\n {set stations_active to cat(stations_active, [1])}\r\n {set stations_claim to cat(stations_claim , [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set stations_active to cat(stations_active, [0])}\r\n {set stations_claim to cat(stations_claim , [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set missions_here to 0}\r\n {set station_based to 0}\r\n {set stations_active to []}\r\n {set stations_claim to []}\r\n {set stations_here to []}\r\n {set non_stations to []}\r\n\r\n {_ Find all missions in the current system and identify all the stations }\r\n {for mission in missions:\r\n {if mission.status != \"Failed\":\r\n {if mission.destinationsystems:\r\n {for destination in mission.destinationsystems:\r\n {if destination.name = system.name && !destination.visited:\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.destinationsystem = system.name:\r\n {if mission.destinationstation && mission.destinationstation != \"\":\r\n {addstation(mission.destinationstation)}\r\n |else:\r\n {if mission.status = \"Active\":\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.originsystem = system.name && find(mission.invariantTags, \"Delivery\") > -1:\r\n {if mission.originstation && mission.originstation != \"\":\r\n {addstation(mission.originstation)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {if missions_here > 0:\r\n {set missionSummaries to []}\r\n {set cur to 0}\r\n {for station in stations_here:\r\n {set station to StationDetails(station)}\r\n {set active to stations_active[cur]}\r\n {set claim to stations_claim[cur]}\r\n {set depot to stations_depot[cur]}\r\n\r\n {set summaries to []}\r\n {if active > 0:\r\n {set activeSummary to: \r\n {active} {OneOf(\"active\", \"pending\")} {if active = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [activeSummary])}\r\n }\r\n {if claim > 0:\r\n {set claimSummary to: \r\n {claim} claimable {if claim = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [claimSummary])}\r\n }\r\n {if len(summaries) > 0:\r\n {set stationSummary to:\r\n {List(summaries)} at \r\n {Occasionally(2, \"the {P(station.model, 'station')}, \")}\r\n {station.name}\r\n }\r\n {set missionSummaries to cat(missionSummaries, [stationSummary])}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n \r\n {set remaining to missions_here - station_based}\r\n {if remaining > 0:\r\n {set otherMissions to:\r\n {remaining} {if len(missionSummaries) > 0: other}\r\n {if remaining > 1: missions |else: mission}\r\n }\r\n {set missionSummaries to cat(missionSummaries, [otherMissions])}\r\n }\r\n\r\n {if len(missionSummaries) > 0:\r\n {Pause(500)}\r\n You have\r\n {List(missionSummaries)}\r\n {OneOf(\"here\", \"in this system\")}.\r\n }\r\n }\r\n}", + "script": "{_ Setup addstation function }\r\n{set addstation(stationName, mission) to:\r\n {set missions_here to missions_here + 1}\r\n {set station_based to station_based + 1}\r\n {set here to find(stations_here, stationName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\":\r\n {set active to stations_active[here] + 1}\r\n {set stations_active to union(stations_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to stations_claim[here] + 1}\r\n {set stations_claim to union(stations_claim, [here:claim])}\r\n }\r\n |else:\r\n {set stations_here to cat(stations_here, [stationName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set stations_active to cat(stations_active, [1])}\r\n {set stations_claim to cat(stations_claim , [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set stations_active to cat(stations_active, [0])}\r\n {set stations_claim to cat(stations_claim , [1])}\r\n }\r\n }\r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set missions_here to 0}\r\n {set station_based to 0}\r\n {set stations_active to []}\r\n {set stations_claim to []}\r\n {set stations_here to []}\r\n {set non_stations to []}\r\n\r\n {_ Find all missions in the current system and identify all the stations }\r\n {for mission in missions:\r\n {if mission.status != \"Failed\":\r\n {if mission.destinationsystems:\r\n {for destination in mission.destinationsystems:\r\n {if destination.name = system.name && !destination.visited:\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.destinationsystem = system.name:\r\n {if mission.destinationstation && mission.destinationstation != \"\":\r\n {addstation(mission.destinationstation, mission)}\r\n |else:\r\n {if mission.status = \"Active\":\r\n {set missions_here to missions_here + 1}\r\n {if find(mission.invariantTags, \"Transport\") > -1:\r\n {set type to \"Transport \"}\r\n {set type to cat(type, mission.passengertype)}\r\n |else:\r\n {set type to mission.tags[0]}\r\n }\r\n {if find(non_stations, type) = -1:\r\n {set non_stations to cat(non_stations, [type])}\r\n }\r\n }\r\n }\r\n |elif mission.originsystem = system.name && find(mission.invariantTags, \"Delivery\") > -1:\r\n {if mission.originstation && mission.originstation != \"\":\r\n {addstation(mission.originstation, mission)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {if missions_here > 0:\r\n {set missionSummaries to []}\r\n {set cur to 0}\r\n {for station in stations_here:\r\n {set station to StationDetails(station)}\r\n {set active to stations_active[cur]}\r\n {set claim to stations_claim[cur]}\r\n {set depot to stations_depot[cur]}\r\n\r\n {set summaries to []}\r\n {if active > 0:\r\n {set activeSummary to: \r\n {active} {OneOf(\"active\", \"pending\")} {if active = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [activeSummary])}\r\n }\r\n {if claim > 0:\r\n {set claimSummary to: \r\n {claim} claimable {if claim = 1: mission |else: missions}\r\n }\r\n {set summaries to cat(summaries, [claimSummary])}\r\n }\r\n {if len(summaries) > 0:\r\n {set summary to:\r\n {List(summaries)} here\r\n {if station:\r\n at \r\n {set stationModel to P(station.model, 'station')}\r\n {if stationModel: {Occasionally(2, \"the {stationModel}, \")} }\r\n {station.name}\r\n }\r\n }\r\n {set missionSummaries to cat(missionSummaries, [summary])}\r\n }\r\n {set cur to cur + 1}\r\n }\r\n \r\n {set remaining to missions_here - station_based}\r\n {if remaining > 0:\r\n {set otherMissions to:\r\n {remaining} {if len(missionSummaries) > 0: other}\r\n {if remaining > 1: missions |else: mission}\r\n here\r\n }\r\n {set missionSummaries to cat(missionSummaries, [otherMissions])}\r\n }\r\n\r\n {if len(missionSummaries) > 0:\r\n {Pause(500)}\r\n You have\r\n {List(missionSummaries)}.\r\n }\r\n }\r\n}", "default": true, "name": "Mission check system", "description": "Check what missions you have for the current system" From 4bbfb87d9bf22d52e832cbfaf6dfc0fe4d3ee635 Mon Sep 17 00:00:00 2001 From: T'kael Date: Sat, 6 Jul 2024 14:00:35 -0700 Subject: [PATCH 24/36] Refine `Mission check galaxy` script to better handle systems with only claimable missions. --- SpeechResponder/eddi.cs.json | 2 +- SpeechResponder/eddi.de.json | 2 +- SpeechResponder/eddi.hu.json | 2 +- SpeechResponder/eddi.it.json | 2 +- SpeechResponder/eddi.ja.json | 2 +- SpeechResponder/eddi.json | 2 +- SpeechResponder/eddi.ru.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index 46c203f319..1b9231c9b6 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -1513,7 +1513,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", + "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n |elif claim > 0:\r\n {claim} claimable {if claim = 1: mission |else: missions }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", "default": true, "name": "Mission check galaxy", "description": "Check what systems you have missions in" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index 5981ea9697..b5243316b1 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -1513,7 +1513,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", + "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n |elif claim > 0:\r\n {claim} claimable {if claim = 1: mission |else: missions }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", "default": true, "name": "Mission check galaxy", "description": "Check what systems you have missions in" diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index 1c762147dc..077d3df103 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -1513,7 +1513,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", + "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n |elif claim > 0:\r\n {claim} claimable {if claim = 1: mission |else: missions }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", "default": true, "name": "Mission check galaxy", "description": "Check what systems you have missions in" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index 1c762147dc..077d3df103 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -1513,7 +1513,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", + "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n |elif claim > 0:\r\n {claim} claimable {if claim = 1: mission |else: missions }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", "default": true, "name": "Mission check galaxy", "description": "Check what systems you have missions in" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index 1c762147dc..077d3df103 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -1513,7 +1513,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", + "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n |elif claim > 0:\r\n {claim} claimable {if claim = 1: mission |else: missions }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", "default": true, "name": "Mission check galaxy", "description": "Check what systems you have missions in" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index 9633c847c7..9523a00995 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -1513,7 +1513,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", + "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n |elif claim > 0:\r\n {claim} claimable {if claim = 1: mission |else: missions }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", "default": true, "name": "Mission check galaxy", "description": "Check what systems you have missions in" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index 1c762147dc..077d3df103 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -1513,7 +1513,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", + "script": "{_ Setup allmissions function _}\r\n{set allmissions(systemName, mission) to:\r\n {set here to find(systems, systemName)}\r\n {if here > -1:\r\n {if mission.statusEDName = \"Active\": \r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set claim to systems_claim[here] + 1}\r\n {set systems_claim to union(systems_claim, [here:claim])}\r\n {set active to systems_active[here] + 1}\r\n {set systems_active to union(systems_active, [here:active])}\r\n }\r\n |else:\r\n {set systems to cat(systems, [systemName])}\r\n {if mission.statusEDName = \"Active\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [0])}\r\n |elif mission.statusEDName = \"Claim\":\r\n {set systems_active to cat(systems_active, [1])}\r\n {set systems_claim to cat(systems_claim, [1])}\r\n }\r\n } \r\n}\r\n\r\n{if missionsCount + goalsCount > 0:\r\n {set failed to 0}\r\n {set multi to 0}\r\n {set pending to 0}\r\n {set systems to []}\r\n {set systems_active to []}\r\n {set systems_claim to []}\r\n\r\n {for mission in missions:\r\n {if mission.statusEDName = \"Failed\":\r\n {set failed to failed + 1}\r\n |else:\r\n {set pending to pending + 1}\r\n {if mission.destinationsystems:\r\n {set multi to multi + 1}\r\n {for destination in mission.destinationsystems:\r\n {allmissions(destination.name, mission)}\r\n }\r\n |elif mission.destinationsystem && mission.destinationsystem != \"\":\r\n {allmissions(mission.destinationsystem, mission)}\r\n }\r\n }\r\n }\r\n {set systemsCount to len(systems)}\r\n\r\n You have\r\n {if failed > 0:\r\n {failed} failed\r\n {if pending > 0:\r\n and\r\n |elif missionsCount + goalsCount = 1:\r\n mission.\r\n |else:\r\n missions.\r\n }\r\n }\r\n\r\n {if pending > 0:\r\n {if mission_report && systemsCount > 0:\r\n {set cur to 0}\r\n {while cur < systemsCount:\r\n {set active to systems_active[cur]}\r\n {set claim to systems_claim[cur]}\r\n\r\n {if active > 0 && active > claim:\r\n {active} pending {if active = 1: mission |else: missions }\r\n {if claim > 0:, including {claim} claimable {if claim = 1: mission |else: missions} }\r\n |elif claim > 0:\r\n {claim} claimable {if claim = 1: mission |else: missions }\r\n }\r\n {OneOf(\"at\",\"in\")} {P(systems[cur], \"starsystem\")}\r\n {set cur to cur + 1}\r\n {if cur = systemsCount - 1: and |elif cur < systemsCount: , }\r\n }.\r\n |else:\r\n {pending} pending {if missionsCount + goalsCount = 1: mission |else: missions} \r\n {if systemsCount = 0:\r\n with no designated target {if missionsCount + goalsCount = 1: system |else: systems }\r\n |elif systemsCount = 1:\r\n in {if systems[0] = system.name: this |else: one } system\r\n |else:\r\n in {systemsCount} {Occasionally(2,\"star\")} systems\r\n }.\r\n {if multi > 0:\r\n {if multi = pending: All |else: {multi} } of these {if multi = 1: is a |else: are }\r\n multi-destination {if multi = 1: mission |else: missions }.\r\n } \r\n }\r\n }\r\n}", "default": true, "name": "Mission check galaxy", "description": "Check what systems you have missions in" From 9d5bc3e3da5156bc9cdec0e2993507e3d3769126 Mon Sep 17 00:00:00 2001 From: T'kael Date: Sun, 7 Jul 2024 12:37:27 -0700 Subject: [PATCH 25/36] `System materials report` script updated to fix an error with the `isSeleniumSpecialCase` helper function. --- SpeechResponder/eddi.cs.json | 2 +- SpeechResponder/eddi.de.json | 2 +- SpeechResponder/eddi.hu.json | 2 +- SpeechResponder/eddi.it.json | 2 +- SpeechResponder/eddi.ja.json | 2 +- SpeechResponder/eddi.json | 2 +- SpeechResponder/eddi.ru.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index 1b9231c9b6..1c8d031c46 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in volcanicBodies[bodyName].materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index b5243316b1..81dae24568 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in volcanicBodies[bodyName].materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index 077d3df103..351a0c0849 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in volcanicBodies[bodyName].materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index 077d3df103..351a0c0849 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in volcanicBodies[bodyName].materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index 077d3df103..351a0c0849 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in volcanicBodies[bodyName].materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index 9523a00995..ca04389d58 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in volcanicBodies[bodyName].materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index 077d3df103..351a0c0849 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -2440,7 +2440,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName, reportSystem) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in reportbody.materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", + "script": "{_ Preferences _}\r\n{set reportMats to 1} {_ Set to 0 to hear about materials below your minimum inventory level _}\r\n {_ Set to 1 to hear about materials below your desired inventory level _}\r\n {_ Set to 2 to hear about all materials irrespective of inventory levels _}\r\n\r\n{set reportMatConc to 1} {_ Set to 0 if you only want to hear about great material concentrations _}\r\n {_ Set to 1 if you want to hear about good and great material concentrations _}\r\n {_ Set to 2 if you want to hear about all material concentrations _}\r\n\r\n{_ Fetch from context _}\r\n{if state.eddi_context_system_name:\r\n {set reportSystem to SystemDetails(state.eddi_context_system_name)}\r\n|else:\r\n {set reportSystem to SystemDetails(system.systemname)}\r\n}\r\n\r\n{set bodyMaterials to []}\r\n{set signalMaterials to []}\r\n{set bodyDescriptions to []}\r\n{set signalDescriptions to []}\r\n{set volcanicBodies to []}\r\n \r\n{_ Define various functions to help with this script _}\r\n{set addBodyMaterial(details, bodyName) to:\r\n {set bodyName to:\r\n {if details.bodyname != details.bodyshortname: body} {details.bodyshortname}\r\n }\r\n {if has(bodyMaterials, bodyName):\r\n {if find(bodyMaterials[bodyName], details.localizedName) = -1:\r\n {set newMats to cat(bodyMaterials[bodyName], [details.localizedName])} \r\n {set bodyMaterials to union(bodyMaterials, [bodyName: newMats])}\r\n }\r\n |else:\r\n {set bodyMaterials to union(bodyMaterials, [bodyName: [details.localizedName]])}\r\n }\r\n}\r\n\r\n{set addSignalMaterial(materialName, signalSourceType) to:\r\n {if has(signalMaterials, materialName):\r\n {if find(signalMaterials[materialName], signalSourceType) = -1:\r\n {set locations to cat(signalMaterials[materialName], [signalSourceType])}\r\n {set signalMaterials to union(signalMaterials, [materialName:locations])}\r\n }\r\n |else:\r\n {set signalMaterials to union(signalMaterials, [materialName: [signalSourceType]])}\r\n }\r\n}\r\n\r\n{set isConcentrated(materialPresence) to:\r\n {if (reportMatConc >= 0 && materialPresence.percentage >= materialPresence.definition.greatpctbody)\r\n || (reportMatConc >= 1 && materialPresence.percentage >= materialPresence.definition.goodpctbody)\r\n || (reportMatConc >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isSeleniumSpecialCase(materialPresence, bodyName) to:\r\n {_ Special case Selenium, which is bugged to appear in crystalline fragments _}\r\n {_ (i.e. with common elements) rather than crystalline shards (i.e. with rare elements) _}\r\n {_ when surface prospecting geological sites _}\r\n {if materialPresence.name = \"Selenium\" && volcanicBodies[bodyName]:\r\n {set commonMaterialPercentages to 0}\r\n {for m in volcanicBodies[bodyName].materials:\r\n {_ Sum up the percentages of common elements so that we can _}\r\n {_ calculate the relative chance of Selenium being present _}\r\n {if m.definition.Rarity.invariantName = \"common\":\r\n {set commonMaterialPercentages to commonMaterialPercentages + m.percentage}\r\n }\r\n }\r\n {if reportMatConc >= 0 && materialPresence.percentage > commonMaterialPercentages:\r\n {_ More than a 50% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n |elif reportMatConc >= 1\r\n && materialPresence.percentage > commonMaterialPercentages / 2:\r\n {_ More than a 33% chance to drop Selenium from crystalline fragments _}\r\n {return 1} \r\n }\r\n }\r\n {return 0}\r\n}\r\n\r\n{set isNeeded(invMaterial) to:\r\n {if (reportMats >= 0 && invMaterial.minimum && invMaterial.amount < invMaterial.minimum)\r\n || (reportMats >= 1 && invMaterial.desired && invMaterial.amount < invMaterial.desired)\r\n || (reportMats >= 2):\r\n {return 1}\r\n }\r\n {return 0}\r\n}\r\n\r\n{set materialInventory(materialName) to:\r\n {for material in materials:\r\n {if material.material = materialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set getMaterialPresence(materialName, bodyName, reportSystem) to:\r\n {for body in reportSystem.bodies:\r\n {for materialPresence in body.materials:\r\n {if body.name = bodyName && material.material = materialName: \r\n {return materialPresence}\r\n }\r\n }\r\n }\r\n}\r\n\r\n{_ Get information about populated system signal sources _}\r\n{if reportSystem.population > 0:\r\n {set sigMaterials to []}\r\n {set signalsType to [\"Encoded Emissions\", \"High Grade Emissions\"]}\r\n\r\n {for sigType in signalsType:\r\n {if sigType = \"Encoded Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n }\r\n |elif sigType = \"High Grade Emissions\":\r\n {if reportSystem.Faction.Allegiance.invariantName = \"Federation\":\r\n {set sigMaterials to cat(sigMaterials, [\"Core Dynamics Composites\"])}\r\n {set sigMaterials to cat(sigMaterials, [\"Proprietary Composites\"])}\r\n |elif reportSystem.Faction.Allegiance.invariantName = \"Empire\":\r\n {set sigMaterials to cat(sigMaterials, [\"Imperial Shielding\"])}\r\n }\r\n {for faction in reportSystem.factions:\r\n {for factionPresence in faction.presences:\r\n {if reportSystem.systemname = factionPresence.systemName && factionPresence.influence >= 25:\r\n {for factionState in factionPresence.ActiveStates:\r\n {if factionState.invariantName = \"Civil Unrest\":\r\n {set sigMaterials to cat(sigMaterials, [\"Improvised Components\"])}\r\n |elif factionState.invariantName = \"Civil War\" || factionState.invariantName = \"War\":\r\n {set sigMaterials to cat(sigMaterials, [\"Military Grade Alloys\", \r\n \"Military Supercapacitors\"])}\r\n |elif factionState.invariantName = \"Outbreak\":\r\n {set sigMaterials to cat(sigMaterials, [\"Pharmaceutical Isolators\"])}\r\n |elif factionState.invariantName = \"Boom\":\r\n {set sigMaterials to cat(sigMaterials, [\"Proto Heat Radiators\",\r\n \"Proto Light Alloys\",\r\n \"Proto Radiolic Alloys\"])}\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n \r\n {_ Add material if it is 'needed' and the signal type is not already added for it _}\r\n {for invariantMaterial in sigMaterials:\r\n {set details to MaterialDetails(invariantMaterial)}\r\n {if isNeeded(materialInventory(details.localizedName)):\r\n {if !has(signalMaterials[details.localizedName], sigType):\r\n {addSignalMaterial(details.localizedName, sigType)}\r\n }\r\n }\r\n }\r\n {_ Reset sigMaterials array _}\r\n {set sigMaterials to []}\r\n }\r\n\r\n {_ Reorganise signals array -> 'material':'sources' _}\r\n {set signalsOrganised to []}\r\n {for mat, sig in signalMaterials:\r\n {set sig to List(sig)}\r\n {set matList to []}\r\n {if has(signalsOrganised, sig):\r\n {set matList to cat(signalsOrganised[sig], [mat])}\r\n {set signalsOrganised to union(signalsOrganised, [sig:matList])}\r\n |else:\r\n {set signalsOrganised to union(signalsOrganised, [sig:[mat]])}\r\n }\r\n }\r\n {set signalMaterials to signalsOrganised}\r\n\r\n {_ Sort materials into alphabetical order _}\r\n {for signalType, mats in signalMaterials:\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set signalDescriptions to cat(signalDescriptions, [cat(List(sortMats), \" may be found in \", signalType, \" signal sources\")])}\r\n }\r\n}\r\n\r\n{for compartment in ship.compartments:\r\n {if compartment.module.invariantName = \"Planetary Vehicle Hangar\":\r\n {set hasSRV to true}\r\n }\r\n}\r\n\r\n{if hasSRV:\r\n\r\n {_ Get information about volcanic bodies in the system }\r\n {for reportbody in reportSystem.bodies:\r\n {if reportbody.volcanism:\r\n {set volcanicBodies to cat(volcanicBodies, [reportbody.name:[reportbody.volcanism]])}\r\n }\r\n }\r\n\r\n {_ Get information about body surface prospecting materials _}\r\n {for material in reportSystem.surfaceelements:\r\n {set detail to MaterialDetails(material, reportSystem.systemname)}\r\n {if detail.bodyname:\r\n {if isNeeded(materialInventory(detail.localizedName)):\r\n {set materialPresence to getMaterialPresence(material.name, detail.bodyname, reportSystem)}\r\n {if isConcentrated(materialPresence)\r\n || isSeleniumSpecialCase(materialPresence, detail.bodyname):\r\n {addBodyMaterial(detail)}\r\n }\r\n }\r\n }\r\n }\r\n\r\n {for bodyName, mats in bodyMaterials:\r\n {_ Sort materials into alphanumerical order _}\r\n {set sortMats to []}\r\n {for item in sort(mats):\r\n {set sortMats to cat(sortMats, [item])}\r\n }\r\n {set bodyDescriptions to cat(bodyDescriptions, [\r\n cat(List(sortMats),\r\n when(len(sortMats) > 1, \" are \", \" is \"),\r\n when(len(mats) > 1, OneOf(\"most prevalent\", \"most abundant\"), \"found\"), \r\n \" on \" P(bodyName, 'body')\r\n )])}\r\n }\r\n\r\n {_ Sort bodies into alphanumerical order _}\r\n {declare check(a, b) as:\r\n {set body1 to token(a, \" on \", 1)}\r\n {set body2 to token(b, \" on \", 1)}\r\n {return cmp(body1, body2)}\r\n }\r\n {set sortDesc to []}\r\n {for item in sort(bodyDescriptions, check):\r\n {set sortDesc to cat(sortDesc, [item])}\r\n }\r\n {set bodyDescriptions to cat(sortDesc)}\r\n}\r\n\r\n{if len(signalMaterials) > 0 && len(bodyMaterials) > 0:\r\n {set break to OneOf(\". \", \". Additionally, \")}\r\n}\r\n\r\n{set descriptions to cat(List(signalDescriptions), break, List(bodyDescriptions))}\r\n{if len(descriptions) > 0:\r\n {descriptions} in this system.\r\n}", "default": true, "name": "System materials report", "description": "Report on the materials available from the contextual system" From e023146585612af14f8a36ac7828b4b65bf5e385 Mon Sep 17 00:00:00 2001 From: T'kael Date: Sun, 7 Jul 2024 14:28:53 -0700 Subject: [PATCH 26/36] `Blueprint make report` script updated to fix a typo (stray letter) --- SpeechResponder/eddi.cs.json | 2 +- SpeechResponder/eddi.de.json | 2 +- SpeechResponder/eddi.hu.json | 2 +- SpeechResponder/eddi.it.json | 2 +- SpeechResponder/eddi.ja.json | 2 +- SpeechResponder/eddi.json | 2 +- SpeechResponder/eddi.ru.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index 1c8d031c46..b3731702b4 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index 81dae24568..ac1cf36c91 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index 351a0c0849..58bc2fd552 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index 351a0c0849..58bc2fd552 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index 351a0c0849..58bc2fd552 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index ca04389d58..b279c07d15 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index 351a0c0849..58bc2fd552 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -51,7 +51,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{_ Function to obtain current inventory of a material}\r\n{set GetMaterialFromInventory(requiredMaterialName) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterialName:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set canbemade to 999}\r\n\r\n{if blueprint:\r\n {_ Find the smallest number of this blueprint that can be made }\r\n \r\n {set cur to 0}\r\n {while cur < len(blueprint.materials):\r\n {set materialInventory to GetMaterialFromInventory(blueprint.materials[cur].material)}\r\n {if !materialInventory:\r\n {set canbemade to 0}\r\n |else:\r\n {if materialInventory.amount < canbemade:\r\n {set canbemade to materialInventory.amount}\r\n }\r\n }\r\n {set cur to cur + 1}\r\n }\r\n\r\n {if canbemade = 0:\r\n You cannot make any {blueprintname} grade {blueprintgrade}\r\n |elif canbemade = 1:\r\n You can make one {blueprintname} grade {blueprintgrade}\r\n |else:\r\n You can make {blueprintname} grade {blueprintgrade} {Humanise(canbemade)} times.\r\n }\r\n \r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint make report", "description": "Report on how many of a particular blueprint we can make" From 8f0cf3c439f5cb5cc8f52b6a0f11bc5da09669c8 Mon Sep 17 00:00:00 2001 From: T'kael Date: Sun, 7 Jul 2024 14:32:36 -0700 Subject: [PATCH 27/36] `Material discard report` updated to tidy context. --- SpeechResponder/eddi.cs.json | 2 +- SpeechResponder/eddi.de.json | 2 +- SpeechResponder/eddi.hu.json | 2 +- SpeechResponder/eddi.it.json | 2 +- SpeechResponder/eddi.ja.json | 2 +- SpeechResponder/eddi.json | 2 +- SpeechResponder/eddi.ru.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index b3731702b4..c1b291d049 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -1351,7 +1351,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n\r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", "default": true, "name": "Material discard report", "description": "Report on how many of a material can be discarded" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index ac1cf36c91..7dcbafa46b 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -1351,7 +1351,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n\r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", "default": true, "name": "Material discard report", "description": "Report on how many of a material can be discarded" diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index 58bc2fd552..3727238281 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -1351,7 +1351,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n\r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", "default": true, "name": "Material discard report", "description": "Report on how many of a material can be discarded" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index 58bc2fd552..3727238281 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -1351,7 +1351,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n\r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", "default": true, "name": "Material discard report", "description": "Report on how many of a material can be discarded" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index 58bc2fd552..3727238281 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -1351,7 +1351,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n\r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", "default": true, "name": "Material discard report", "description": "Report on how many of a material can be discarded" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index b279c07d15..af57e4d27c 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -1351,7 +1351,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n\r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", "default": true, "name": "Material discard report", "description": "Report on how many of a material can be discarded" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index 58bc2fd552..3727238281 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -1351,7 +1351,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n\r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory:\r\n {if materialInventory.maximum && materialInventory.maximum < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.maximum}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your maximum level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your maximum level.\r\n }\r\n |elif materialInventory.desired && materialInventory.desired < materialInventory.amount:\r\n {set over to materialInventory.amount - materialInventory.desired}\r\n {if over > 1:\r\n You can discard {over} units of {materialInventory.material} to reach your desired level.\r\n |elif over = 1:\r\n You can discard 1 unit of {materialInventory.material} to reach your desired level.\r\n }\r\n |elif materialInventory.desired:\r\n You are below your desired level for {materialInventory.material}.\r\n |elif materialInventory.maximum:\r\n You are below your maximum level for {materialInventory.material}.\r\n |else:\r\n You have not set any levels for {materialInventory.material}.\r\n }\r\n}\r\n", "default": true, "name": "Material discard report", "description": "Report on how many of a material can be discarded" From 9a9ded958de8eb0169fb0b875af710d5fafd64a5 Mon Sep 17 00:00:00 2001 From: T'kael Date: Sun, 7 Jul 2024 14:33:28 -0700 Subject: [PATCH 28/36] `Material inventory report` updated to tidy context. --- SpeechResponder/eddi.cs.json | 2 +- SpeechResponder/eddi.de.json | 2 +- SpeechResponder/eddi.hu.json | 2 +- SpeechResponder/eddi.it.json | 2 +- SpeechResponder/eddi.ja.json | 2 +- SpeechResponder/eddi.json | 2 +- SpeechResponder/eddi.ru.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index c1b291d049..6bbe129cdc 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -1396,7 +1396,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'inventory')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", "default": true, "name": "Material inventory report", "description": "Report on how many of a material are on-board" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index 7dcbafa46b..46230e897b 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -1396,7 +1396,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'inventory')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", "default": true, "name": "Material inventory report", "description": "Report on how many of a material are on-board" diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index 3727238281..4dcd9bac23 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -1396,7 +1396,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'inventory')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", "default": true, "name": "Material inventory report", "description": "Report on how many of a material are on-board" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index 3727238281..4dcd9bac23 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -1396,7 +1396,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'inventory')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", "default": true, "name": "Material inventory report", "description": "Report on how many of a material are on-board" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index 3727238281..4dcd9bac23 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -1396,7 +1396,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'inventory')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", "default": true, "name": "Material inventory report", "description": "Report on how many of a material are on-board" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index af57e4d27c..43dd05b50f 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -1396,7 +1396,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'inventory')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", "default": true, "name": "Material inventory report", "description": "Report on how many of a material are on-board" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index 3727238281..4dcd9bac23 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -1396,7 +1396,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'discard')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'material')}\r\n{SetState('eddi_context_last_subject_action', 'inventory')}\r\n \r\n{_ Fetch from context }\r\n{set material to MaterialDetails(state.eddi_context_material_name)}\r\n\r\n{_ Function to obtain a material from inventory}\r\n{set GetInventory(requiredMaterial) to:\r\n {for material in materials:\r\n {if material.material = requiredMaterial:\r\n {return material}\r\n }\r\n }\r\n}\r\n\r\n{set materialInventory to GetInventory(material.name)}\r\n\r\n{if materialInventory && materialInventory.amount > 0:\r\n {if materialInventory.amount = 1:\r\n You have {materialInventory.amount} unit of {materialInventory.material} on board.\r\n |else:\r\n You have {materialInventory.amount} units of {materialInventory.material} on board.\r\n }\r\n|else:\r\n You have no {materialInventory.material} on board.\r\n}\r\n", "default": true, "name": "Material inventory report", "description": "Report on how many of a material are on-board" From 3d79e652cca1d3a61b471380cea946657c1b0df7 Mon Sep 17 00:00:00 2001 From: Tkael Date: Tue, 9 Jul 2024 22:12:30 -0700 Subject: [PATCH 29/36] `Star scanned` script updated to fix a typo (missing comma). --- SpeechResponder/eddi.cs.json | 2 +- SpeechResponder/eddi.de.json | 2 +- SpeechResponder/eddi.es.json | 2 +- SpeechResponder/eddi.hu.json | 2 +- SpeechResponder/eddi.it.json | 2 +- SpeechResponder/eddi.ja.json | 2 +- SpeechResponder/eddi.json | 2 +- SpeechResponder/eddi.ru.json | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index 6bbe129cdc..8944f68cfa 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -2332,7 +2332,7 @@ "enabled": true, "priority": 3, "responder": true, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'star')}\r\n{SetState('eddi_context_last_action', 'scan')}\r\n{SetState('eddi_context_star_system', system.name)}\r\n{SetState('eddi_context_star_star', event.name)}\r\n{SetState('eddi_context_last_scan_estimated_value', event.estimatedvalue)}\r\n\r\n{if ship.Role.edname = \"Exploration\" || ship.Role.edname = \"Multipurpose\":\r\n {F(\"Star report\")}\r\n}", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'star')}\r\n{SetState('eddi_context_last_action', 'scan')}\r\n{SetState('eddi_context_star_system', system.name)}\r\n{SetState('eddi_context_star_star', event.name)}\r\n{SetState('eddi_context_last_scan_estimated_value', event.estimatedvalue)}\r\n\r\n{if ship.Role.edname = \"Exploration\" || ship.Role.edname = \"Multipurpose\":\r\n\r\n {if event.mainstar && !event.alreadydiscovered && event.scantype = \"AutoScan\":\r\n This system \r\n {OneOf(\r\n \"is not {Occasionally(2, 'yet')} registered\",\r\n \"isn't registered\",\r\n \"has yet to be logged\",\r\n \"hasn't been logged\"\r\n )}\r\n with Universal Cartographics.\r\n {Pause(500)}\r\n }\r\n\r\n {F(\"Star report\")}\r\n}", "default": true, "name": "Star scanned", "description": "Triggered when you complete a scan of a stellar body" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index 46230e897b..abad7e5ad0 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -2332,7 +2332,7 @@ "enabled": true, "priority": 3, "responder": true, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'star')}\r\n{SetState('eddi_context_last_action', 'scan')}\r\n{SetState('eddi_context_star_system', system.name)}\r\n{SetState('eddi_context_star_star', event.name)}\r\n{SetState('eddi_context_last_scan_estimated_value', event.estimatedvalue)}\r\n\r\n{if ship.Role.edname = \"Exploration\" || ship.Role.edname = \"Multipurpose\":\r\n {F(\"Star report\")}\r\n}", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'star')}\r\n{SetState('eddi_context_last_action', 'scan')}\r\n{SetState('eddi_context_star_system', system.name)}\r\n{SetState('eddi_context_star_star', event.name)}\r\n{SetState('eddi_context_last_scan_estimated_value', event.estimatedvalue)}\r\n\r\n{if ship.Role.edname = \"Exploration\" || ship.Role.edname = \"Multipurpose\":\r\n\r\n {if event.mainstar && !event.alreadydiscovered && event.scantype = \"AutoScan\":\r\n This system \r\n {OneOf(\r\n \"is not {Occasionally(2, 'yet')} registered\",\r\n \"isn't registered\",\r\n \"has yet to be logged\",\r\n \"hasn't been logged\"\r\n )}\r\n with Universal Cartographics.\r\n {Pause(500)}\r\n }\r\n\r\n {F(\"Star report\")}\r\n}", "default": true, "name": "Star scanned", "description": "Triggered when you complete a scan of a stellar body" diff --git a/SpeechResponder/eddi.es.json b/SpeechResponder/eddi.es.json index 4124f4c6b6..1fe6b518f8 100644 --- a/SpeechResponder/eddi.es.json +++ b/SpeechResponder/eddi.es.json @@ -2346,7 +2346,7 @@ "enabled": true, "priority": 3, "responder": true, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'star')}\r\n{SetState('eddi_context_last_action', 'scan')}\r\n{SetState('eddi_context_star_system', system.name)}\r\n{SetState('eddi_context_star_star', event.name)}\r\n{SetState('eddi_context_last_scan_estimated_value', event.estimatedvalue)}\r\n\r\n{if ship.Role.edname = \"Exploration\" || ship.Role.edname = \"Multipurpose\":\r\n {F(\"Star report\")}\r\n}", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'star')}\r\n{SetState('eddi_context_last_action', 'scan')}\r\n{SetState('eddi_context_star_system', system.name)}\r\n{SetState('eddi_context_star_star', event.name)}\r\n{SetState('eddi_context_last_scan_estimated_value', event.estimatedvalue)}\r\n\r\n{if ship.Role.edname = \"Exploration\" || ship.Role.edname = \"Multipurpose\":\r\n\r\n {if event.mainstar && !event.alreadydiscovered && event.scantype = \"AutoScan\":\r\n This system \r\n {OneOf(\r\n \"is not {Occasionally(2, 'yet')} registered\",\r\n \"isn't registered\",\r\n \"has yet to be logged\",\r\n \"hasn't been logged\"\r\n )}\r\n with Universal Cartographics.\r\n {Pause(500)}\r\n }\r\n\r\n {F(\"Star report\")}\r\n}", "name": "Star scanned", "description": "Se activa cuando completa un escaneo de un cuerpo estelar (TEST)" }, diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index 4dcd9bac23..121ffe338a 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -2332,7 +2332,7 @@ "enabled": true, "priority": 3, "responder": true, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'star')}\r\n{SetState('eddi_context_last_action', 'scan')}\r\n{SetState('eddi_context_star_system', system.name)}\r\n{SetState('eddi_context_star_star', event.name)}\r\n{SetState('eddi_context_last_scan_estimated_value', event.estimatedvalue)}\r\n\r\n{if ship.Role.edname = \"Exploration\" || ship.Role.edname = \"Multipurpose\":\r\n {F(\"Star report\")}\r\n}", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'star')}\r\n{SetState('eddi_context_last_action', 'scan')}\r\n{SetState('eddi_context_star_system', system.name)}\r\n{SetState('eddi_context_star_star', event.name)}\r\n{SetState('eddi_context_last_scan_estimated_value', event.estimatedvalue)}\r\n\r\n{if ship.Role.edname = \"Exploration\" || ship.Role.edname = \"Multipurpose\":\r\n\r\n {if event.mainstar && !event.alreadydiscovered && event.scantype = \"AutoScan\":\r\n This system \r\n {OneOf(\r\n \"is not {Occasionally(2, 'yet')} registered\",\r\n \"isn't registered\",\r\n \"has yet to be logged\",\r\n \"hasn't been logged\"\r\n )}\r\n with Universal Cartographics.\r\n {Pause(500)}\r\n }\r\n\r\n {F(\"Star report\")}\r\n}", "default": true, "name": "Star scanned", "description": "Triggered when you complete a scan of a stellar body" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index 4dcd9bac23..121ffe338a 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -2332,7 +2332,7 @@ "enabled": true, "priority": 3, "responder": true, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'star')}\r\n{SetState('eddi_context_last_action', 'scan')}\r\n{SetState('eddi_context_star_system', system.name)}\r\n{SetState('eddi_context_star_star', event.name)}\r\n{SetState('eddi_context_last_scan_estimated_value', event.estimatedvalue)}\r\n\r\n{if ship.Role.edname = \"Exploration\" || ship.Role.edname = \"Multipurpose\":\r\n {F(\"Star report\")}\r\n}", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'star')}\r\n{SetState('eddi_context_last_action', 'scan')}\r\n{SetState('eddi_context_star_system', system.name)}\r\n{SetState('eddi_context_star_star', event.name)}\r\n{SetState('eddi_context_last_scan_estimated_value', event.estimatedvalue)}\r\n\r\n{if ship.Role.edname = \"Exploration\" || ship.Role.edname = \"Multipurpose\":\r\n\r\n {if event.mainstar && !event.alreadydiscovered && event.scantype = \"AutoScan\":\r\n This system \r\n {OneOf(\r\n \"is not {Occasionally(2, 'yet')} registered\",\r\n \"isn't registered\",\r\n \"has yet to be logged\",\r\n \"hasn't been logged\"\r\n )}\r\n with Universal Cartographics.\r\n {Pause(500)}\r\n }\r\n\r\n {F(\"Star report\")}\r\n}", "default": true, "name": "Star scanned", "description": "Triggered when you complete a scan of a stellar body" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index 4dcd9bac23..121ffe338a 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -2332,7 +2332,7 @@ "enabled": true, "priority": 3, "responder": true, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'star')}\r\n{SetState('eddi_context_last_action', 'scan')}\r\n{SetState('eddi_context_star_system', system.name)}\r\n{SetState('eddi_context_star_star', event.name)}\r\n{SetState('eddi_context_last_scan_estimated_value', event.estimatedvalue)}\r\n\r\n{if ship.Role.edname = \"Exploration\" || ship.Role.edname = \"Multipurpose\":\r\n {F(\"Star report\")}\r\n}", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'star')}\r\n{SetState('eddi_context_last_action', 'scan')}\r\n{SetState('eddi_context_star_system', system.name)}\r\n{SetState('eddi_context_star_star', event.name)}\r\n{SetState('eddi_context_last_scan_estimated_value', event.estimatedvalue)}\r\n\r\n{if ship.Role.edname = \"Exploration\" || ship.Role.edname = \"Multipurpose\":\r\n\r\n {if event.mainstar && !event.alreadydiscovered && event.scantype = \"AutoScan\":\r\n This system \r\n {OneOf(\r\n \"is not {Occasionally(2, 'yet')} registered\",\r\n \"isn't registered\",\r\n \"has yet to be logged\",\r\n \"hasn't been logged\"\r\n )}\r\n with Universal Cartographics.\r\n {Pause(500)}\r\n }\r\n\r\n {F(\"Star report\")}\r\n}", "default": true, "name": "Star scanned", "description": "Triggered when you complete a scan of a stellar body" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index 43dd05b50f..ec01e779b2 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -2332,7 +2332,7 @@ "enabled": true, "priority": 3, "responder": true, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'star')}\r\n{SetState('eddi_context_last_action', 'scan')}\r\n{SetState('eddi_context_star_system', system.name)}\r\n{SetState('eddi_context_star_star', event.name)}\r\n{SetState('eddi_context_last_scan_estimated_value', event.estimatedvalue)}\r\n\r\n{if ship.Role.edname = \"Exploration\" || ship.Role.edname = \"Multipurpose\":\r\n\r\n {if event.mainstar && !event.alreadydiscovered && event.scantype = \"AutoScan\":\r\n This system \r\n {OneOf(\r\n \"is not {Occasionally(2, 'yet')} registered\",\r\n \"isn't registered\"\r\n \"has yet to be logged\",\r\n \"hasn't been logged\"\r\n )}\r\n with Universal Cartographics.\r\n {Pause(500)}\r\n }\r\n\r\n {F(\"Star report\")}\r\n}", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'star')}\r\n{SetState('eddi_context_last_action', 'scan')}\r\n{SetState('eddi_context_star_system', system.name)}\r\n{SetState('eddi_context_star_star', event.name)}\r\n{SetState('eddi_context_last_scan_estimated_value', event.estimatedvalue)}\r\n\r\n{if ship.Role.edname = \"Exploration\" || ship.Role.edname = \"Multipurpose\":\r\n\r\n {if event.mainstar && !event.alreadydiscovered && event.scantype = \"AutoScan\":\r\n This system \r\n {OneOf(\r\n \"is not {Occasionally(2, 'yet')} registered\",\r\n \"isn't registered\",\r\n \"has yet to be logged\",\r\n \"hasn't been logged\"\r\n )}\r\n with Universal Cartographics.\r\n {Pause(500)}\r\n }\r\n\r\n {F(\"Star report\")}\r\n}", "default": true, "name": "Star scanned", "description": "Triggered when you complete a scan of a stellar body" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index 4dcd9bac23..121ffe338a 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -2332,7 +2332,7 @@ "enabled": true, "priority": 3, "responder": true, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'star')}\r\n{SetState('eddi_context_last_action', 'scan')}\r\n{SetState('eddi_context_star_system', system.name)}\r\n{SetState('eddi_context_star_star', event.name)}\r\n{SetState('eddi_context_last_scan_estimated_value', event.estimatedvalue)}\r\n\r\n{if ship.Role.edname = \"Exploration\" || ship.Role.edname = \"Multipurpose\":\r\n {F(\"Star report\")}\r\n}", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'star')}\r\n{SetState('eddi_context_last_action', 'scan')}\r\n{SetState('eddi_context_star_system', system.name)}\r\n{SetState('eddi_context_star_star', event.name)}\r\n{SetState('eddi_context_last_scan_estimated_value', event.estimatedvalue)}\r\n\r\n{if ship.Role.edname = \"Exploration\" || ship.Role.edname = \"Multipurpose\":\r\n\r\n {if event.mainstar && !event.alreadydiscovered && event.scantype = \"AutoScan\":\r\n This system \r\n {OneOf(\r\n \"is not {Occasionally(2, 'yet')} registered\",\r\n \"isn't registered\",\r\n \"has yet to be logged\",\r\n \"hasn't been logged\"\r\n )}\r\n with Universal Cartographics.\r\n {Pause(500)}\r\n }\r\n\r\n {F(\"Star report\")}\r\n}", "default": true, "name": "Star scanned", "description": "Triggered when you complete a scan of a stellar body" From a912d43391f349add38c9b23e3a03a0f07b36865 Mon Sep 17 00:00:00 2001 From: T'kael Date: Sat, 13 Jul 2024 15:40:12 -0700 Subject: [PATCH 30/36] Variables set with SetState are now set to as types as possible (e.g. TXT, DEC, INT, SMALL, BOOL) in VoiceAttack. --- ChangeLog.md | 4 + SpeechResponder/CustomFunctions/SetState.cs | 9 +- Tests/VoiceAttackPluginTests.cs | 333 ++++++++++++------ VoiceAttack-Integration.md | 2 + VoiceAttackResponder/VoiceAttackPlugin.cs | 7 + .../VoiceAttackStandardVariables.cs | 78 ++-- 6 files changed, 282 insertions(+), 151 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 0876bcf831..a50104fe03 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -2,6 +2,10 @@ Full details of the variables available for each noted event, and VoiceAttack integrations, are available in the individual [event pages](https://github.com/EDCD/EDDI/wiki/Events). +## 4.1.0-b1 + * VoiceAttack + * Variables set with SetState are now set to as types as possible (e.g. TXT, DEC, INT, SMALL, BOOL) in VoiceAttack. + ## 4.1.0-a2 * Speech Responder * Increased the render cycle limit () from 10,0000 to 100,000. diff --git a/SpeechResponder/CustomFunctions/SetState.cs b/SpeechResponder/CustomFunctions/SetState.cs index 99b65d8331..0a79584744 100644 --- a/SpeechResponder/CustomFunctions/SetState.cs +++ b/SpeechResponder/CustomFunctions/SetState.cs @@ -23,14 +23,7 @@ public class SetState : ICustomFunction } else if (value.Type == ValueContent.Number) { - if ( Math.Abs(value.AsNumber - Convert.ToInt32(value.AsNumber)) < .000000001 ) - { - EDDI.Instance.State[ varName ] = Convert.ToInt32( value.AsNumber ); - } - else - { - EDDI.Instance.State[ varName ] = Convert.ToDecimal( value.AsNumber ); - } + EDDI.Instance.State[ varName ] = Convert.ToDecimal( value.AsNumber ); } else if (value.Type == ValueContent.String) { diff --git a/Tests/VoiceAttackPluginTests.cs b/Tests/VoiceAttackPluginTests.cs index 2b96c1bda2..1ee6a06c16 100644 --- a/Tests/VoiceAttackPluginTests.cs +++ b/Tests/VoiceAttackPluginTests.cs @@ -15,44 +15,102 @@ namespace UnitTests { public class MockVAProxy { - [UsedImplicitly] public List> vaLog = new List>(); + [ UsedImplicitly ] public List> vaLog = new List>(); - public Dictionary vaVars = new Dictionary(); + private readonly Dictionary vaStrings = new Dictionary(); + private readonly Dictionary vaDecimals = new Dictionary(); + private readonly Dictionary vaIntegers = new Dictionary(); + private readonly Dictionary vaShorts = new Dictionary(); + private readonly Dictionary vaBooleans = new Dictionary(); + private readonly Dictionary vaDates = new Dictionary(); - [UsedImplicitly] - public void WriteToLog(string msg, string color = null) + [ UsedImplicitly ] + public void WriteToLog ( string msg, string color = null ) { - vaLog.Add(new KeyValuePair(msg, color)); + vaLog.Add( new KeyValuePair( msg, color ) ); } - [UsedImplicitly] - public void SetText(string varName, string value) + [ UsedImplicitly ] + public string GetText ( string varName ) { - vaVars[ varName ] = value; + return vaStrings.TryGetValue( varName, out var s ) ? s : null; } - [UsedImplicitly] - public void SetInt(string varName, int? value) + [ UsedImplicitly ] + public void SetText ( string varName, object value ) { - vaVars[ varName ] = value; + vaStrings[ varName ] = value?.ToString(); } - [UsedImplicitly] - public void SetBoolean(string varName, bool? value) + [ UsedImplicitly ] + public int? GetInt ( string varName ) { - vaVars[ varName ] = value; + return vaIntegers.TryGetValue(varName, out var i) ? i : null; } - [UsedImplicitly] - public void SetDecimal(string varName, decimal? value) + [ UsedImplicitly ] + public void SetInt ( string varName, int? value ) { - vaVars[ varName ] = value; + vaIntegers[ varName ] = value; } - [UsedImplicitly] - public void SetDate(string varName, DateTime? value) + [ UsedImplicitly ] + public short? GetSmallInt ( string varName ) { - vaVars[ varName ] = value; + return vaShorts.TryGetValue( varName, out var sh ) ? sh : null; + } + + [ UsedImplicitly ] + public void SetSmallInt ( string varName, short? value ) + { + vaShorts[ varName ] = value; + } + + [ UsedImplicitly ] + public bool? GetBoolean ( string varName ) + { + return vaBooleans.TryGetValue( varName, out var b ) ? b : null; + } + + [ UsedImplicitly ] + public void SetBoolean ( string varName, bool? value ) + { + vaBooleans[ varName ] = value; + } + + [ UsedImplicitly ] + public decimal? GetDecimal ( string varName ) + { + return vaDecimals.TryGetValue( varName, out var d ) ? d : null; + } + + [ UsedImplicitly ] + public void SetDecimal ( string varName, decimal? value ) + { + vaDecimals[ varName ] = value; + } + + [ UsedImplicitly ] + public DateTime? GetDate ( string varName ) + { + return vaDates.TryGetValue( varName, out var dt ) ? dt : null; + } + + [ UsedImplicitly ] + public void SetDate ( string varName, DateTime? value ) + { + vaDates[ varName ] = value; + } + + [ UsedImplicitly ] + public bool ContainsKey ( string varName ) + { + return vaStrings.ContainsKey( varName ) || + vaDecimals.ContainsKey( varName ) || + vaIntegers.ContainsKey( varName ) || + vaShorts.ContainsKey( varName ) || + vaBooleans.ContainsKey( varName ) || + vaDates.ContainsKey(varName); } } @@ -65,11 +123,58 @@ public void start() MakeSafe(); } - private readonly MockVAProxy vaProxy = new MockVAProxy(); + [DataTestMethod] + [DataRow( "1", "1", "1", "1", "true" )] // Value is a string. Numeric results are set to 1 and bool is true. + [DataRow( "2", "123.45", "123", "123", "true" )] // Value is decimal. Integer and short values are rounded. Value exists so bool is true. + [DataRow( "3", "1234567.89", "1234568", null, "true" )] // Value is a decimal. Integer value is rounded, value is too large for short and thus is null. Value exists so bool is true. + [DataRow( "4", "12345", "12345", "12345", "true" )] // Value is a short and qualifies for all numeric types. Value exists so bool is true. + [DataRow( "5", "1", "1", "1", "true" )] // Value is boolean, numeric values are set to 1. + [DataRow( "6", "1", "1", "1", "true" )] // Value is boolean, numeric values are set to 1. + [DataRow( "7", null, null, null, null )] // Value is null, no values. + [DataRow( "8", "0", "0", "0", "false" )] // Value is zero in all numeric types and false as a boolean. + [DataRow( "9", "0", "0", "0", "false" )] // Value is zero in all numeric types and false as a boolean. + [DataRow( "10", "0", "0", "0", "false" )] // Value is zero in all numeric types and false as a boolean. + public void TestSetState ( string varName, string decimalResult, string integerResult, string shortresult, string booleanResult ) + { + // Define values using dynamic types for each varName. Expected returns are defined above. + var dict = new Dictionary + { + [ "1" ] = "test", + [ "2" ] = "123.45", + [ "3" ] = 1234567.89M, + [ "4" ] = 12345, + [ "5" ] = 1, + [ "6" ] = true, + [ "7" ] = null, + [ "8" ] = 0, + [ "9" ] = "false", + [ "10" ] = string.Empty, + }; + + dynamic vaProxy = new MockVAProxy(); + var mockVAProxy = (MockVAProxy)vaProxy; + VoiceAttackVariables.setDictionaryValues( dict, "state", ref vaProxy ); + Assert.AreEqual( dict.FirstOrDefault(kv => kv.Key == varName).Value? + .ToString(), mockVAProxy.GetText( "EDDI state " + varName ) ); + Assert.AreEqual( decimalResult is null + ? null + : (decimal?)decimal.Parse(decimalResult), mockVAProxy.GetDecimal( "EDDI state " + varName ) ); + Assert.AreEqual( integerResult is null + ? null + : (int?)int.Parse(integerResult), mockVAProxy.GetInt( "EDDI state " + varName ) ); + Assert.AreEqual( shortresult is null + ? null + : (short?)short.Parse(shortresult), mockVAProxy.GetSmallInt( "EDDI state " + varName ) ); + Assert.AreEqual( booleanResult is null + ? null + : (bool?)bool.Parse(booleanResult), mockVAProxy.GetBoolean( "EDDI state " + varName ) ); + } [TestMethod] public void TestVAExplorationDataSoldEvent() { + dynamic vaProxy = new MockVAProxy(); + var mockVAProxy = (MockVAProxy)vaProxy; string line = @"{ ""timestamp"":""2016-09-23T18:57:55Z"", ""event"":""SellExplorationData"", ""Systems"":[ ""Gamma Tucanae"", ""Rho Capricorni"", ""Dain"", ""Col 285 Sector BR-S b18-0"", ""LP 571-80"", ""Kawilocidi"", ""Irulachan"", ""Alrai Sector MC-M a7-0"", ""Col 285 Sector FX-Q b19-5"", ""Col 285 Sector EX-Q b19-7"", ""Alrai Sector FB-O a6-3"" ], ""Discovered"":[ ""Irulachan"" ], ""BaseValue"":63573, ""Bonus"":1445, ""TotalEarnings"":65018 }"; List events = JournalMonitor.ParseJournalEntry(line); Assert.IsTrue(events.Count == 1); @@ -82,30 +187,32 @@ public void TestVAExplorationDataSoldEvent() var vaVars = vars.AsVoiceAttackVariables("EDDI", ev.type); foreach (var @var in vaVars) { @var.Set(vaProxy); } Assert.AreEqual(15, vaVars.Count); - Assert.AreEqual("Gamma Tucanae", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI exploration data sold systems 1").Value); - Assert.AreEqual("Rho Capricorni", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI exploration data sold systems 2").Value); - Assert.AreEqual("Dain", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI exploration data sold systems 3").Value); - Assert.AreEqual("Col 285 Sector BR-S b18-0", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI exploration data sold systems 4").Value); - Assert.AreEqual("LP 571-80", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI exploration data sold systems 5").Value); - Assert.AreEqual("Kawilocidi", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI exploration data sold systems 6").Value); - Assert.AreEqual("Irulachan", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI exploration data sold systems 7").Value); - Assert.AreEqual("Alrai Sector MC-M a7-0", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI exploration data sold systems 8").Value); - Assert.AreEqual("Col 285 Sector FX-Q b19-5", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI exploration data sold systems 9").Value); - Assert.AreEqual("Col 285 Sector EX-Q b19-7", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI exploration data sold systems 10").Value); - Assert.AreEqual("Alrai Sector FB-O a6-3", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI exploration data sold systems 11").Value); - Assert.AreEqual(11, vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI exploration data sold systems").Value); - Assert.AreEqual(63573M, vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI exploration data sold reward").Value); - Assert.AreEqual(1445M, vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI exploration data sold bonus").Value); - Assert.AreEqual(65018M, vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI exploration data sold total").Value); - foreach (VoiceAttackVariable variable in vaVars) + Assert.AreEqual("Gamma Tucanae", mockVAProxy.GetText("EDDI exploration data sold systems 1")); + Assert.AreEqual("Rho Capricorni", mockVAProxy.GetText("EDDI exploration data sold systems 2")); + Assert.AreEqual("Dain", mockVAProxy.GetText("EDDI exploration data sold systems 3")); + Assert.AreEqual("Col 285 Sector BR-S b18-0", mockVAProxy.GetText("EDDI exploration data sold systems 4")); + Assert.AreEqual("LP 571-80", mockVAProxy.GetText("EDDI exploration data sold systems 5")); + Assert.AreEqual("Kawilocidi", mockVAProxy.GetText("EDDI exploration data sold systems 6")); + Assert.AreEqual("Irulachan", mockVAProxy.GetText("EDDI exploration data sold systems 7")); + Assert.AreEqual("Alrai Sector MC-M a7-0", mockVAProxy.GetText("EDDI exploration data sold systems 8")); + Assert.AreEqual("Col 285 Sector FX-Q b19-5", mockVAProxy.GetText("EDDI exploration data sold systems 9")); + Assert.AreEqual("Col 285 Sector EX-Q b19-7", mockVAProxy.GetText("EDDI exploration data sold systems 10")); + Assert.AreEqual("Alrai Sector FB-O a6-3", mockVAProxy.GetText("EDDI exploration data sold systems 11")); + Assert.AreEqual(11, mockVAProxy.GetInt("EDDI exploration data sold systems")); + Assert.AreEqual(63573M, mockVAProxy.GetDecimal( "EDDI exploration data sold reward" ) ); + Assert.AreEqual(1445M, mockVAProxy.GetDecimal("EDDI exploration data sold bonus")); + Assert.AreEqual(65018M, mockVAProxy.GetDecimal("EDDI exploration data sold total")); + foreach (var variable in vaVars) { - Assert.IsTrue(vaProxy.vaVars.ContainsKey(variable.key), "Unmatched key"); + Assert.IsTrue(mockVAProxy.ContainsKey(variable.key), "Unmatched key"); } } [TestMethod] public void TestVADiscoveryScanEvent() { + dynamic vaProxy = new MockVAProxy(); + var mockVAProxy = (MockVAProxy)vaProxy; string line = @"{ ""timestamp"":""2019-10-26T02:15:49Z"", ""event"":""FSSDiscoveryScan"", ""Progress"":0.439435, ""BodyCount"":7, ""NonBodyCount"":3, ""SystemName"":""Outotz WO-A d1"", ""SystemAddress"":44870715523 }"; List events = JournalMonitor.ParseJournalEntry(line); Assert.IsTrue(events.Count == 1); @@ -122,18 +229,20 @@ public void TestVADiscoveryScanEvent() var vaVars = vars.AsVoiceAttackVariables("EDDI", ev.type); foreach (var @var in vaVars) { @var.Set(vaProxy); } Assert.AreEqual(2, vaVars.Count); - Assert.AreEqual(7, vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI discovery scan totalbodies").Value); - Assert.AreEqual(3, vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI discovery scan nonbodies").Value); - Assert.IsNull(vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI discovery scan progress").Value); + Assert.AreEqual(7, mockVAProxy.GetInt( "EDDI discovery scan totalbodies")); + Assert.AreEqual(3, mockVAProxy.GetInt("EDDI discovery scan nonbodies")); + Assert.IsNull(mockVAProxy.GetInt("EDDI discovery scan progress")); foreach (VoiceAttackVariable variable in vaVars) { - Assert.IsTrue(vaProxy.vaVars.ContainsKey(variable.key), "Unmatched key"); + Assert.IsTrue(mockVAProxy.ContainsKey(variable.key), "Unmatched key"); } } [TestMethod] public void TestVAAsteroidProspectedEvent() { + dynamic vaProxy = new MockVAProxy(); + var mockVAProxy = (MockVAProxy)vaProxy; string line = "{ \"timestamp\":\"2020-04-10T02:32:21Z\", \"event\":\"ProspectedAsteroid\", \"Materials\":[ { \"Name\":\"LowTemperatureDiamond\", \"Name_Localised\":\"Low Temperature Diamonds\", \"Proportion\":26.078022 }, { \"Name\":\"HydrogenPeroxide\", \"Name_Localised\":\"Hydrogen Peroxide\", \"Proportion\":10.189009 } ], \"MotherlodeMaterial\":\"Alexandrite\", \"Content\":\"$AsteroidMaterialContent_Low;\", \"Content_Localised\":\"Material Content: Low\", \"Remaining\":90.000000 }"; List events = JournalMonitor.ParseJournalEntry(line); Assert.IsTrue(events.Count == 1); @@ -146,23 +255,25 @@ public void TestVAAsteroidProspectedEvent() var vaVars = vars.AsVoiceAttackVariables("EDDI", ev.type); foreach (var @var in vaVars) { @var.Set(vaProxy); } Assert.AreEqual(8, vaVars.Count); - Assert.AreEqual(90M, vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI asteroid prospected remaining").Value); - Assert.AreEqual("Alexandrite", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI asteroid prospected motherlode").Value); - Assert.AreEqual("Low Temperature Diamonds", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI asteroid prospected commodities 1 commodity").Value); - Assert.AreEqual(26.078022M, vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI asteroid prospected commodities 1 percentage").Value); - Assert.AreEqual("Hydrogen Peroxide", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI asteroid prospected commodities 2 commodity").Value); - Assert.AreEqual(10.189009M, vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI asteroid prospected commodities 2 percentage").Value); - Assert.AreEqual(2, vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI asteroid prospected commodities").Value); - Assert.AreEqual("Low", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI asteroid prospected materialcontent").Value); + Assert.AreEqual(90M, mockVAProxy.GetDecimal("EDDI asteroid prospected remaining")); + Assert.AreEqual("Alexandrite", mockVAProxy.GetText("EDDI asteroid prospected motherlode")); + Assert.AreEqual("Low Temperature Diamonds", mockVAProxy.GetText("EDDI asteroid prospected commodities 1 commodity")); + Assert.AreEqual(26.078022M, mockVAProxy.GetDecimal("EDDI asteroid prospected commodities 1 percentage")); + Assert.AreEqual("Hydrogen Peroxide", mockVAProxy.GetText("EDDI asteroid prospected commodities 2 commodity")); + Assert.AreEqual(10.189009M, mockVAProxy.GetDecimal("EDDI asteroid prospected commodities 2 percentage")); + Assert.AreEqual(2, mockVAProxy.GetInt("EDDI asteroid prospected commodities")); + Assert.AreEqual("Low", mockVAProxy.GetText("EDDI asteroid prospected materialcontent")); foreach (VoiceAttackVariable variable in vaVars) { - Assert.IsTrue(vaProxy.vaVars.ContainsKey(variable.key), "Unmatched key"); + Assert.IsTrue(mockVAProxy.ContainsKey(variable.key), "Unmatched key"); } } [TestMethod] public void TestVAShipFSDEvent() { + dynamic vaProxy = new MockVAProxy(); + var mockVAProxy = (MockVAProxy)vaProxy; // 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". ShipFsdEvent ev = new ShipFsdEvent (DateTime.UtcNow, "ready"); @@ -171,16 +282,18 @@ public void TestVAShipFSDEvent() var vaVars = vars.AsVoiceAttackVariables("EDDI", ev.type); foreach (var @var in vaVars) { @var.Set(vaProxy); } Assert.AreEqual(2, vaVars.Count); - Assert.AreEqual("ready", vaProxy.vaVars.FirstOrDefault(k => k.Key == "EDDI ship fsd status").Value); + Assert.AreEqual("ready", mockVAProxy.GetText("EDDI ship fsd status")); foreach (VoiceAttackVariable variable in vaVars) { - Assert.IsTrue(vaProxy.vaVars.ContainsKey(variable.key), "Unmatched key"); + Assert.IsTrue(mockVAProxy.ContainsKey(variable.key), "Unmatched key"); } } [TestMethod] public void TestVACommodityEjectedEvent() { + dynamic vaProxy = new MockVAProxy(); + var mockVAProxy = (MockVAProxy)vaProxy; // 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); @@ -198,19 +311,22 @@ public void TestVACommodityEjectedEvent() 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); + Assert.AreEqual("Water", mockVAProxy.GetText("EDDI commodity ejected commodity")); + Assert.AreEqual(5, mockVAProxy.GetInt("EDDI commodity ejected amount")); + Assert.IsNull(mockVAProxy.GetDecimal("EDDI commodity ejected missionid")); + Assert.AreEqual(true, mockVAProxy.GetBoolean("EDDI commodity ejected abandoned")); foreach (VoiceAttackVariable variable in vaVars) { - Assert.IsTrue(vaProxy.vaVars.ContainsKey(variable.key), "Unmatched key"); + Assert.IsTrue(mockVAProxy.ContainsKey(variable.key), "Unmatched key"); } } [ TestMethod ] public void TestVAShip () { + dynamic vaProxy = new MockVAProxy(); + var mockVAProxy = (MockVAProxy)vaProxy; + // Read from our test item "shipMonitor.json" var configuration = new ShipMonitorConfiguration(); try @@ -223,63 +339,60 @@ public void TestVAShip () Assert.Fail(); } - dynamic mockVaProxy = new MockVAProxy(); - var varVars = ( (MockVAProxy)mockVaProxy ).vaVars; - var krait = configuration.shipyard.FirstOrDefault( s => s.LocalId == 81 ); var cobraMk3 = configuration.shipyard.FirstOrDefault( s => s.LocalId == 0 ); Assert.IsNotNull( krait ); Assert.IsNotNull( cobraMk3 ); - VoiceAttackVariables.setShipValues( krait, "Ship", ref mockVaProxy ); - Assert.AreEqual( "Krait Mk. II", (string)varVars[ "Ship model" ] ); - Assert.AreEqual( "The Impact Kraiter", (string)varVars[ "Ship name" ] ); - Assert.AreEqual( "TK-29K", (string)varVars[ "Ship ident" ] ); - Assert.AreEqual( "Combat", (string)varVars[ "Ship role" ] ); - Assert.AreEqual( 201065994, (decimal?)varVars[ "Ship value" ] ); - Assert.AreEqual( 10053299, (decimal?)varVars[ "Ship rebuy" ] ); - Assert.AreEqual( 100M, (decimal?)varVars[ "Ship health" ] ); - Assert.AreEqual( 16, (int?)varVars[ "Ship cargo capacity" ] ); - Assert.AreEqual( 8, (int?)varVars[ "Ship compartments" ] ); - Assert.AreEqual( 6, (int?)varVars[ "Ship compartment 1 size" ] ); - Assert.AreEqual( true, (bool?)varVars[ "Ship compartment 1 occupied" ] ); - Assert.AreEqual( 6, (int?)varVars[ "Ship compartment 1 module class" ] ); - Assert.AreEqual( "C", (string)varVars[ "Ship compartment 1 module grade" ] ); - Assert.AreEqual( 100M, (decimal?)varVars[ "Ship compartment 1 module health" ] ); - Assert.AreEqual( 2234799, (decimal?)varVars[ "Ship compartment 1 module cost" ] ); - Assert.AreEqual( 2696600, (decimal?)varVars[ "Ship compartment 1 module value" ] ); - Assert.AreEqual( 9, (int?)varVars[ "Ship hardpoints" ] ); - Assert.AreEqual( true, (bool?)varVars[ "Ship large hardpoint 1 occupied" ] ); - Assert.AreEqual( 2, (int?)varVars[ "Ship large hardpoint 1 module class" ] ); - Assert.AreEqual( "B", (string)varVars[ "Ship large hardpoint 1 module grade" ] ); - Assert.AreEqual( 100M, (decimal?)varVars[ "Ship large hardpoint 1 module health" ] ); - Assert.AreEqual( 310425, (decimal?)varVars[ "Ship large hardpoint 1 module cost" ] ); - Assert.AreEqual( 344916, (decimal?)varVars[ "Ship large hardpoint 1 module value" ] ); - - VoiceAttackVariables.setShipValues( cobraMk3, "Ship", ref mockVaProxy ); - Assert.AreEqual( "Cobra Mk. III", (string)varVars[ "Ship model" ] ); - Assert.AreEqual( "The Dynamo", (string)varVars[ "Ship name" ] ); - Assert.AreEqual( "TK-20C", (string)varVars[ "Ship ident" ] ); - Assert.AreEqual( "Multipurpose", (string)varVars[ "Ship role" ] ); - Assert.AreEqual( 8605684, (decimal?)varVars[ "Ship value" ] ); - Assert.AreEqual( 0, (decimal?)varVars[ "Ship rebuy" ] ); - Assert.AreEqual( 100M, (decimal?)varVars[ "Ship health" ] ); - Assert.AreEqual( 0, (int?)varVars[ "Ship cargo capacity" ] ); - Assert.AreEqual( 0, (int?)varVars[ "Ship compartments" ] ); - Assert.AreEqual( null, (int?)varVars[ "Ship compartment 1 size" ] ); - Assert.AreEqual( false, (bool?)varVars[ "Ship compartment 1 occupied" ] ); - Assert.AreEqual( null, (int?)varVars[ "Ship compartment 1 module class" ] ); - Assert.AreEqual( null, (string)varVars[ "Ship compartment 1 module grade" ] ); - Assert.AreEqual( null, (decimal?)varVars[ "Ship compartment 1 module health" ] ); - Assert.AreEqual( null, (decimal?)varVars[ "Ship compartment 1 module cost" ] ); - Assert.AreEqual( null, (decimal?)varVars[ "Ship compartment 1 module value" ] ); - Assert.AreEqual( 0, (int?)varVars[ "Ship hardpoints" ] ); - Assert.AreEqual( false, (bool?)varVars[ "Ship large hardpoint 1 occupied" ] ); - Assert.AreEqual( null, (int?)varVars[ "Ship large hardpoint 1 module class" ] ); - Assert.AreEqual( null, (string)varVars[ "Ship large hardpoint 1 module grade" ] ); - Assert.AreEqual( null, (decimal?)varVars[ "Ship large hardpoint 1 module health" ] ); - Assert.AreEqual( null, (decimal?)varVars[ "Ship large hardpoint 1 module cost" ] ); - Assert.AreEqual( null, (decimal?)varVars[ "Ship large hardpoint 1 module value" ] ); + VoiceAttackVariables.setShipValues( krait, "Ship", ref vaProxy ); + Assert.AreEqual( "Krait Mk. II", mockVAProxy.GetText( "Ship model" ) ); + Assert.AreEqual( "The Impact Kraiter", mockVAProxy.GetText("Ship name") ); + Assert.AreEqual( "TK-29K", mockVAProxy.GetText("Ship ident") ); + Assert.AreEqual( "Combat", mockVAProxy.GetText("Ship role") ); + Assert.AreEqual( 201065994, mockVAProxy.GetDecimal( "Ship value" ) ); + Assert.AreEqual( 10053299, mockVAProxy.GetDecimal("Ship rebuy") ); + Assert.AreEqual( 100M, mockVAProxy.GetDecimal("Ship health") ); + Assert.AreEqual( 16, mockVAProxy.GetInt( "Ship cargo capacity" ) ); + Assert.AreEqual( 8, mockVAProxy.GetInt("Ship compartments") ); + Assert.AreEqual( 6, mockVAProxy.GetInt("Ship compartment 1 size") ); + Assert.AreEqual( true, mockVAProxy.GetBoolean( "Ship compartment 1 occupied" ) ); + Assert.AreEqual( 6, mockVAProxy.GetInt("Ship compartment 1 module class") ); + Assert.AreEqual( "C", mockVAProxy.GetText("Ship compartment 1 module grade") ); + Assert.AreEqual( 100M, mockVAProxy.GetDecimal("Ship compartment 1 module health") ); + Assert.AreEqual( 2234799, mockVAProxy.GetDecimal("Ship compartment 1 module cost") ); + Assert.AreEqual( 2696600, mockVAProxy.GetDecimal("Ship compartment 1 module value") ); + Assert.AreEqual( 9, mockVAProxy.GetInt("Ship hardpoints") ); + Assert.AreEqual( true, mockVAProxy.GetBoolean( "Ship large hardpoint 1 occupied" ) ); + Assert.AreEqual( 2, mockVAProxy.GetInt("Ship large hardpoint 1 module class") ); + Assert.AreEqual( "B", mockVAProxy.GetText("Ship large hardpoint 1 module grade") ); + Assert.AreEqual( 100M, mockVAProxy.GetDecimal("Ship large hardpoint 1 module health") ); + Assert.AreEqual( 310425, mockVAProxy.GetDecimal("Ship large hardpoint 1 module cost") ); + Assert.AreEqual( 344916, mockVAProxy.GetDecimal("Ship large hardpoint 1 module value") ); + + VoiceAttackVariables.setShipValues( cobraMk3, "Ship", ref vaProxy ); + Assert.AreEqual( "Cobra Mk. III", mockVAProxy.GetText("Ship model") ); + Assert.AreEqual( "The Dynamo", mockVAProxy.GetText("Ship name") ); + Assert.AreEqual( "TK-20C", mockVAProxy.GetText("Ship ident") ); + Assert.AreEqual( "Multipurpose", mockVAProxy.GetText("Ship role") ); + Assert.AreEqual( 8605684, mockVAProxy.GetDecimal("Ship value") ); + Assert.AreEqual( 0, mockVAProxy.GetDecimal("Ship rebuy") ); + Assert.AreEqual( 100M, mockVAProxy.GetDecimal("Ship health") ); + Assert.AreEqual( 0, mockVAProxy.GetInt("Ship cargo capacity") ); + Assert.AreEqual( 0, mockVAProxy.GetInt("Ship compartments") ); + Assert.AreEqual( null, mockVAProxy.GetInt("Ship compartment 1 size") ); + Assert.AreEqual( false, mockVAProxy.GetBoolean("Ship compartment 1 occupied") ); + Assert.AreEqual( null, mockVAProxy.GetInt("Ship compartment 1 module class") ); + Assert.AreEqual( null, mockVAProxy.GetText("Ship compartment 1 module grade") ); + Assert.AreEqual( null, mockVAProxy.GetDecimal("Ship compartment 1 module health") ); + Assert.AreEqual( null, mockVAProxy.GetDecimal("Ship compartment 1 module cost") ); + Assert.AreEqual( null, mockVAProxy.GetDecimal("Ship compartment 1 module value") ); + Assert.AreEqual( 0, mockVAProxy.GetInt("Ship hardpoints") ); + Assert.AreEqual( false, mockVAProxy.GetBoolean("Ship large hardpoint 1 occupied") ); + Assert.AreEqual( null, mockVAProxy.GetInt("Ship large hardpoint 1 module class") ); + Assert.AreEqual( null, mockVAProxy.GetText("Ship large hardpoint 1 module grade") ); + Assert.AreEqual( null, mockVAProxy.GetDecimal("Ship large hardpoint 1 module health") ); + Assert.AreEqual( null, mockVAProxy.GetDecimal("Ship large hardpoint 1 module cost") ); + Assert.AreEqual( null, mockVAProxy.GetDecimal("Ship large hardpoint 1 module value") ); } } } diff --git a/VoiceAttack-Integration.md b/VoiceAttack-Integration.md index 68646859d6..8c49468a02 100644 --- a/VoiceAttack-Integration.md +++ b/VoiceAttack-Integration.md @@ -562,6 +562,8 @@ This function only supports integers, booleans, decimals and strings as state va State variables are made available in VoiceAttack with the prefix 'EDDI state'. For example, to access the text variable stored in the last paragraph you would use '\{TXT:EDDI state my_variable\}'. +Variables shall be set to as many variable types as possible, e.g. 'TXT', 'DEC', 'INT', 'SMALL', and 'BOOL' as applicable. Decimal values shall be set to their rounded values in 'INT' and 'SMALL' variable types. Non-zero numeric values and non-empty string values shall be set to 'True' in the BOOL variable type. + To access the same variable from within EDDI's Speech Responder, you would call '\{state.my_variable\}'. Please note that state is transient, and is purposefully not persisted beyond the running instance of EDDI. This means that every time you start VoiceAttack the state will be empty. Also, because EDDI responders run asynchronously and concurrently there is no guarantee that, for example, the speech responder for an event will finish before the VoiceAttack responder for an event starts (or vice versa). diff --git a/VoiceAttackResponder/VoiceAttackPlugin.cs b/VoiceAttackResponder/VoiceAttackPlugin.cs index a91c241446..9d03eb7572 100644 --- a/VoiceAttackResponder/VoiceAttackPlugin.cs +++ b/VoiceAttackResponder/VoiceAttackPlugin.cs @@ -770,6 +770,13 @@ public static void InvokeSetState(ref dynamic vaProxy) return; } + int? shortValue = vaProxy.GetSmallInt(name); + if ( shortValue != null ) + { + EDDI.Instance.State[ stateVariableName ] = shortValue; + return; + } + int? intValue = vaProxy.GetInt(name); if (intValue != null) { diff --git a/VoiceAttackResponder/VoiceAttackStandardVariables.cs b/VoiceAttackResponder/VoiceAttackStandardVariables.cs index 4c89316efe..7665ebd8e0 100644 --- a/VoiceAttackResponder/VoiceAttackStandardVariables.cs +++ b/VoiceAttackResponder/VoiceAttackStandardVariables.cs @@ -99,54 +99,66 @@ protected static void initializeStandardValues() } // Set values from a dictionary - protected static void setDictionaryValues(IDictionary dict, string prefix, ref dynamic vaProxy) + public static void setDictionaryValues ( IDictionary dict, string prefix, ref dynamic vaProxy ) { - foreach (var key in dict.Keys) + foreach ( var key in dict.Keys ) { var varname = "EDDI " + prefix + " " + key; - var value = dict[key]; - if (value == null) - { - // No idea what it might have been so reset everything - vaProxy.SetText(varname, null); - vaProxy.SetInt(varname, null); - vaProxy.SetDecimal(varname, null); - vaProxy.SetBoolean(varname, null); - continue; - } - var valueType = value.GetType(); - if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Nullable<>)) - { - valueType = Nullable.GetUnderlyingType(valueType); - } - if (valueType == typeof(string)) - { - vaProxy.SetText(varname, (string)value); - } - else if (valueType == typeof(int)) + vaProxy.SetText( varname, null ); + vaProxy.SetInt( varname, null ); + vaProxy.SetSmallInt( varname, null ); + vaProxy.SetDecimal( varname, null ); + vaProxy.SetBoolean( varname, null ); + + var value = dict[ key ]; + if ( value is null ) { continue; } + + var s = value.ToString(); + vaProxy.SetText( varname, s ); + if ( value is decimal d || decimal.TryParse( s, out d ) ) { - vaProxy.SetInt(varname, (int)value); + vaProxy.SetDecimal( varname, d ); + vaProxy.SetBoolean( varname, d != 0 ); + if ( d <= int.MaxValue ) + { + vaProxy.SetInt( varname, Convert.ToInt32( Math.Round( d, MidpointRounding.AwayFromZero ) ) ); + } + + if ( d <= short.MaxValue ) + { + vaProxy.SetSmallInt( varname, Convert.ToInt16( Math.Round( d, MidpointRounding.AwayFromZero ) ) ); + } } - else if (valueType == typeof(bool)) + else { - vaProxy.SetBoolean(varname, (bool?)value); + vaProxy.SetDecimal( varname, null ); } - else if (valueType == typeof(decimal)) + + if ( value is int i || int.TryParse( s, out i ) ) { - vaProxy.SetDecimal(varname, (decimal?)value); + vaProxy.SetInt( varname, i ); } - else if (valueType == typeof(double)) + + if ( value is short sh || short.TryParse( s, out sh ) ) { - vaProxy.SetDecimal(varname, (decimal?)(double?)value); + vaProxy.SetSmallInt( varname, sh ); } - else if (valueType == typeof(long)) + + if ( value is bool b || bool.TryParse( s, out b ) ) { - vaProxy.SetDecimal(varname, (decimal?)(long?)value); + vaProxy.SetBoolean( varname, b ); + vaProxy.SetDecimal( varname, (decimal?)( b ? 1 : 0 ) ); + vaProxy.SetInt( varname, (int?)( b ? 1 : 0 ) ); + vaProxy.SetSmallInt( varname, (short?)( b ? 1 : 0 ) ); } - else + else if ( !decimal.TryParse( s, out _ ) ) { - Logging.Debug("Not handling state value type " + valueType); + b = !string.IsNullOrEmpty( s ); + vaProxy.SetBoolean( varname, b ); + vaProxy.SetDecimal( varname, (decimal?)(b ? 1 : 0) ); + vaProxy.SetInt( varname, (int?)(b ? 1 : 0) ); + vaProxy.SetSmallInt( varname, (short?)(b ? 1 : 0) ); } } } From 0c4afcaadcb748c565460506f8123e69cdc29a78 Mon Sep 17 00:00:00 2001 From: T'kael Date: Sat, 13 Jul 2024 15:44:15 -0700 Subject: [PATCH 31/36] Fix typo in `Blueprint material report` --- SpeechResponder/eddi.cs.json | 2 +- SpeechResponder/eddi.de.json | 2 +- SpeechResponder/eddi.hu.json | 2 +- SpeechResponder/eddi.it.json | 2 +- SpeechResponder/eddi.ja.json | 2 +- SpeechResponder/eddi.json | 2 +- SpeechResponder/eddi.ru.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/SpeechResponder/eddi.cs.json b/SpeechResponder/eddi.cs.json index 8944f68cfa..87cecd1076 100644 --- a/SpeechResponder/eddi.cs.json +++ b/SpeechResponder/eddi.cs.json @@ -60,7 +60,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint material report", "description": "Report on the material requirements for a blueprint" diff --git a/SpeechResponder/eddi.de.json b/SpeechResponder/eddi.de.json index abad7e5ad0..5bd3b7b3fd 100644 --- a/SpeechResponder/eddi.de.json +++ b/SpeechResponder/eddi.de.json @@ -60,7 +60,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint material report", "description": "Report on the material requirements for a blueprint" diff --git a/SpeechResponder/eddi.hu.json b/SpeechResponder/eddi.hu.json index 121ffe338a..76318ff59f 100644 --- a/SpeechResponder/eddi.hu.json +++ b/SpeechResponder/eddi.hu.json @@ -60,7 +60,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint material report", "description": "Report on the material requirements for a blueprint" diff --git a/SpeechResponder/eddi.it.json b/SpeechResponder/eddi.it.json index 121ffe338a..76318ff59f 100644 --- a/SpeechResponder/eddi.it.json +++ b/SpeechResponder/eddi.it.json @@ -60,7 +60,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint material report", "description": "Report on the material requirements for a blueprint" diff --git a/SpeechResponder/eddi.ja.json b/SpeechResponder/eddi.ja.json index 121ffe338a..76318ff59f 100644 --- a/SpeechResponder/eddi.ja.json +++ b/SpeechResponder/eddi.ja.json @@ -60,7 +60,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint material report", "description": "Report on the material requirements for a blueprint" diff --git a/SpeechResponder/eddi.json b/SpeechResponder/eddi.json index ec01e779b2..1066c643c3 100644 --- a/SpeechResponder/eddi.json +++ b/SpeechResponder/eddi.json @@ -60,7 +60,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint material report", "description": "Report on the material requirements for a blueprint" diff --git a/SpeechResponder/eddi.ru.json b/SpeechResponder/eddi.ru.json index 121ffe338a..76318ff59f 100644 --- a/SpeechResponder/eddi.ru.json +++ b/SpeechResponder/eddi.ru.json @@ -60,7 +60,7 @@ "enabled": true, "priority": 3, "responder": false, - "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\nr\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", + "script": "{_ Context }\r\n{SetState('eddi_context_last_subject', 'blueprint')}\r\n \r\n{_ Fetch from context / state _}\r\n{set blueprintname to state.eddi_context_blueprint_name}\r\n{set blueprintgrade to state.eddi_context_blueprint_grade}\r\n\r\n{if blueprintname && blueprintgrade:\r\n {_ Fetch full blueprint details }\r\n {set blueprint to BlueprintDetails(blueprintname, blueprintgrade)}\r\n}\r\n\r\n{if blueprint:\r\n {set blueprintMaterials to []}\r\n {for material in blueprint.materials:\r\n {set blueprintMaterials to cat(blueprintMaterials, [material.material])}\r\n }\r\n {blueprintname} grade {blueprintgrade} requires \r\n {List(blueprintMaterials)}.\r\n|else:\r\n No information available on materials required for {blueprintname} grade {blueprintgrade}\r\n}.\r\n", "default": true, "name": "Blueprint material report", "description": "Report on the material requirements for a blueprint" From 2a47e22a3e1dd797c2b0d58e3d93f860dbe5b233 Mon Sep 17 00:00:00 2001 From: T'kael Date: Sat, 13 Jul 2024 15:45:12 -0700 Subject: [PATCH 32/36] Change log - updated scripts --- ChangeLog.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index a50104fe03..bf5217a5a1 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -3,6 +3,15 @@ Full details of the variables available for each noted event, and VoiceAttack integrations, are available in the individual [event pages](https://github.com/EDCD/EDDI/wiki/Events). ## 4.1.0-b1 + * Speech Responder + * Scripts + * `Blueprint make report` updated to fix a typo (stray letter). + * `Material discard report` updated to tidy context. + * `Material inventory report` updated to tidy context. + * `Mission check galaxy` updated to make `allmissions()` function pure. + * `Mission check system` updated to make `addstation()` function pure. + * `Star scanned` updated to fix a typo (missing comma). + * `System materials report` updated to fix an error with the `isSeleniumSpecialCase` helper function. * VoiceAttack * Variables set with SetState are now set to as types as possible (e.g. TXT, DEC, INT, SMALL, BOOL) in VoiceAttack. @@ -32,6 +41,7 @@ Full details of the variables available for each noted event, and VoiceAttack in * `System materials report` updated to use `factionState` variable name rather than reserved `state` variable name. * VoiceAttack * EDDI.vap commands updated to synchronize state variable names with updated scripts. + * Whole number variables set with SetState are now set as INT values rather than DEC values in VoiceAttack. ## 4.0.4 * Core From ff1c8dd0cd3d782b0bcd7c3594b57d4edfd4cd9c Mon Sep 17 00:00:00 2001 From: Tkael Date: Sat, 13 Jul 2024 21:38:13 -0700 Subject: [PATCH 33/36] Refactor `MissionType` and `Mission` definitions --- DataDefinitions/Mission.cs | 579 +++++++----------- DataDefinitions/MissionType.cs | 322 +++++++--- .../Properties/MissionType.Designer.cs | 162 ++--- .../Properties/MissionType.de.resx | 33 +- .../Properties/MissionType.es.resx | 26 +- .../Properties/MissionType.fr.resx | 26 +- .../Properties/MissionType.hu.resx | 4 +- .../Properties/MissionType.it.resx | 33 +- .../Properties/MissionType.ja.resx | 6 - .../Properties/MissionType.pt-BR.resx | 33 +- DataDefinitions/Properties/MissionType.resx | 56 +- .../Properties/MissionType.ru.resx | 31 +- .../Properties/MissionType.zh-CN.resx | 33 +- MissionMonitor/MissionMonitor.cs | 2 +- Tests/MissionMonitorTests.cs | 7 +- 15 files changed, 567 insertions(+), 786 deletions(-) diff --git a/DataDefinitions/Mission.cs b/DataDefinitions/Mission.cs index 5ae412f6dc..22e4c28803 100644 --- a/DataDefinitions/Mission.cs +++ b/DataDefinitions/Mission.cs @@ -10,55 +10,6 @@ namespace EddiDataDefinitions { public class Mission : INotifyPropertyChanged { - private static readonly Dictionary CHAINED = new Dictionary() - { - {"clearingthepath", "delivery"}, - {"drawthegeneralout", "assassinate"}, - {"findthepiratelord", "assassinate"}, - {"helpfinishtheorder", "delivery"}, - {"helpwithpreventionmeasures", "massacre"}, - {"miningtoorder", "mining"}, - {"piracyfraud", "delivery"}, - {"planetaryincursions", "scan"}, - {"rampantleadership", "assassinate"}, - {"regainfooting", "assassinate"}, - {"rescuefromthetwins", "salvage"}, - {"rescuethewares", "salvage"}, - {"safetravelling", "passengervip"}, - {"salvagejustice", "assassinate"}, - {"securingmyposition", "passengervip"}, - {"seekingasylum", "assassinate"}, - {"thedead", "special"}, - {"wrongtarget", "assassinate"}, - }; - - public static readonly List ORGRETURN = new List() - { - "altruism", - "altruismcredits", - "assassinate", - "assassinatewing", - "collect", - "collectwing", - "deliverywing", - "disable", - "disablewing", - "genericpermit1", - "hack", - "longdistanceexpedition", - "massacre", - "massacrethargoid", - "massacrewing", - "mining", - "miningwing", - "onfoot", - "piracy", - "rescue", - "salvage", - "scan", - "sightseeing" - }; - // The mission ID [Utilities.PublicAPI] public long missionid { get; private set; } @@ -71,18 +22,13 @@ public string name set { _name = value; - SetFactionState(); - SetTypes(); + OnPropertyChanged(); } } - [JsonIgnore] private string _name; // The localised name of the mission - [JsonIgnore] - private string _localisedname; - [Utilities.PublicAPI] public string localisedname { @@ -90,34 +36,50 @@ public string localisedname set { _localisedname = value; - GetDestinationStation(); - GetTargetFaction(); + destinationstation = !string.IsNullOrEmpty( destinationstation ) + ? destinationstation + : FallbackGetDestinationStation( value ); + targetfaction = !string.IsNullOrEmpty(targetfaction) + ? targetfaction + : FallbackGetTargetFaction( value ); OnPropertyChanged(); } } + [JsonIgnore] + private string _localisedname; - // The type of mission + #region Expiration Data - [JsonIgnore] - public List tagsList { get; set; } = new List(); + [Utilities.PublicAPI] + public DateTime? expiry { get; set; } [Utilities.PublicAPI, JsonIgnore] - public List invariantTags => tagsList.Select(t => t.invariantName ?? "Unknown").ToList(); + public long? expiryseconds => expiry != null ? (long?)Utilities.Dates.fromDateTimeToSeconds( (DateTime)expiry ) : null; [JsonIgnore] - public List localizedTags => tagsList.Select(t => t.localizedName ?? "Unknown").ToList(); - - [JsonIgnore, UsedImplicitly] - public string localizedTagsString => string.Join(", ", localizedTags); + public bool expiring { get; set; } + // The mission time remaining [JsonIgnore] - public List edTags => tagsList.Select(t => t.edname ?? "Unknown").ToList(); + public TimeSpan? timeRemaining => expiry != null ? TimeSpanNearestSecond( expiry - DateTime.UtcNow ) : null; - [Utilities.PublicAPI, JsonIgnore] - public List tags => localizedTags; + private TimeSpan? TimeSpanNearestSecond ( TimeSpan? utcNow ) + { + if ( utcNow is null ) + { return null; } + return new TimeSpan( utcNow.Value.Days, utcNow.Value.Hours, utcNow.Value.Minutes, utcNow.Value.Seconds ); + } - [Utilities.PublicAPI("Obsolete: `type` has been deprecated in favor of tags"), JsonIgnore, Obsolete("`type` has been deprecated in favor of tags")] - public string type => localizedTags[0]; + // While we track the time remaining constantly, we loop through each mission + // and update the displayed time remaining at intervals defined by the Mission Monitor. + public void UpdateTimeRemaining () + { + OnPropertyChanged( nameof( timeRemaining ) ); + } + + #endregion + + #region Mission Status // Status of the mission public string statusEDName @@ -125,13 +87,11 @@ public string statusEDName get => statusDef?.edname; set { - MissionStatus sDef = MissionStatus.FromEDName(value); + var sDef = MissionStatus.FromEDName(value); this.statusDef = sDef; } } - [JsonIgnore] - private MissionStatus _statusDef; [JsonIgnore] public MissionStatus statusDef { @@ -139,82 +99,82 @@ public MissionStatus statusDef set { _statusDef = value; - UpdateExpiry(); - OnPropertyChanged("localizedStatus"); + if ( value != MissionStatus.Active && !onfoot ) + { + // Missions are time constrained when active, and on-foot missions + // continue to be time constrained even after they are claimable. + expiry = null; + } + OnPropertyChanged( nameof( localizedStatus ) ); } } + [JsonIgnore] + private MissionStatus _statusDef; [JsonIgnore] public string localizedStatus => statusDef?.localizedName ?? "Unknown"; - [Utilities.PublicAPI, JsonIgnore, Obsolete("Please use localizedName or invariantName")] + [Utilities.PublicAPI, JsonIgnore, Obsolete( "Please use localizedName or invariantName" )] public string status => localizedStatus; - // The system in which the mission was accepted [Utilities.PublicAPI] - public string originsystem { get; set; } + public bool shared { get; set; } - // The station in which the mission was accepted - [Utilities.PublicAPI] - public string originstation { get; set; } + #endregion - // Mission returns to origin - [Utilities.PublicAPI] - public bool originreturn => edTags - .Any(t => ORGRETURN.Contains(t, StringComparer.InvariantCultureIgnoreCase)); + #region Mission Tags / MetaData - [Utilities.PublicAPI] - public string faction { get; set; } + [ JsonIgnore ] + public List tagsList => MissionTypes.FromMissionName( name ); + + [Utilities.PublicAPI, JsonIgnore] + public List invariantTags => tagsList.Select(t => t.invariantName ?? "Unknown").ToList(); + + [JsonIgnore, UsedImplicitly] + public string localizedTagsString => string.Join(", ", tags ); - // The state of the minor faction - [JsonProperty("factionstate")] - public string factionstate - { - get => FactionState?.localizedName ?? FactionState.None.localizedName; - set - { - FactionState fsDef = FactionState.FromName(value); - this.FactionState = fsDef; - } - } - [JsonIgnore] - private FactionState _FactionState = FactionState.None; [JsonIgnore] - public FactionState FactionState - { - get { return _FactionState; } - set { _FactionState = value; } - } + public List edTags => tagsList.Select(t => t.edname ?? "Unknown").ToList(); - [Utilities.PublicAPI] - public string influence { get; set; } + [Utilities.PublicAPI, JsonIgnore] + public List tags => tagsList.Select( t => t.localizedName ?? "Unknown" ).ToList(); - [Utilities.PublicAPI] - public string reputation { get; set; } + [Utilities.PublicAPI("Obsolete: `type` has been deprecated in favor of tags"), JsonIgnore, Obsolete("`type` has been deprecated in favor of tags")] + public string type => tags[0]; - public bool chained => name.ToLowerInvariant().Contains("chained"); + [JsonIgnore] + public bool chained => tagsList.Contains( MissionType.Chained ); - public bool onfoot => name.ToLowerInvariant().Contains("onfoot"); + [JsonIgnore] + public bool onfoot => tagsList.Contains( MissionType.OnFoot ); [Utilities.PublicAPI] public bool communal { get; set; } - [Utilities.PublicAPI] - public bool legal => !name.ToLowerInvariant().Contains("hack") - && !name.ToLowerInvariant().Contains("illegal") - && !name.ToLowerInvariant().Contains("piracy") - && !name.ToLowerInvariant().Contains("smuggle"); + [Utilities.PublicAPI, JsonIgnore] + public bool legal => !tagsList.Any( t => + t == MissionType.Hack || + t == MissionType.Illegal || + t == MissionType.Piracy || + t == MissionType.Smuggle ); - [Utilities.PublicAPI] - public bool shared { get; set; } + [Utilities.PublicAPI, JsonIgnore] + public bool wing => tagsList.Contains( MissionType.Wing ) || onfoot; + + #endregion + + #region Mission Rewards [Utilities.PublicAPI] - public bool wing => name.ToLowerInvariant().Contains("wing") || onfoot; + public string influence { get; set; } [Utilities.PublicAPI] + public string reputation { get; set; } + + [Utilities.PublicAPI("Credits awarded upon successful completion")] public long? reward { get; set; } - [Utilities.PublicAPI, JsonProperty("commodity")] + [Utilities.PublicAPI, JsonProperty( "commodity" )] public string commodity { get => CommodityDefinition?.localizedName; @@ -227,7 +187,7 @@ public string commodity [JsonIgnore] public CommodityDefinition CommodityDefinition { get; set; } - [Utilities.PublicAPI, JsonProperty("microresource")] + [Utilities.PublicAPI, JsonProperty( "microresource" )] public string microresource { get => MicroResourceDefinition?.localizedName; @@ -243,230 +203,100 @@ public string microresource [Utilities.PublicAPI] public int? amount { get; set; } - // THe destination system of the mission - private string _destinationsystem; - - [Utilities.PublicAPI] - public string destinationsystem - { - get - { - return _destinationsystem; - } - set - { - if (_destinationsystem != value) - { - _destinationsystem = value; - OnPropertyChanged(); - } - } - } - - // The destination station of the mission - private string _destinationstation; - - [Utilities.PublicAPI] - public string destinationstation - { - get - { - return _destinationstation; - } - set - { - if (_destinationstation != value) - { - _destinationstation = value; - OnPropertyChanged(); - } - } - } - - // Destination systems for chained missions - - [Utilities.PublicAPI] - public List destinationsystems { get; set; } - - // Community goal details, if applicable - public int communalPercentileBand { get; set; } - - public int communalTier { get; set; } - - // The mission time remaining - [JsonIgnore] - public TimeSpan? timeRemaining => expiry != null ? TimeSpanNearestSecond(expiry - DateTime.UtcNow) : null; - - private TimeSpan? TimeSpanNearestSecond(TimeSpan? utcNow) - { - if (utcNow is null) { return null; } - return new TimeSpan(utcNow.Value.Days, utcNow.Value.Hours, utcNow.Value.Minutes, utcNow.Value.Seconds); - } + #endregion - public string passengertypeEDName { get; set; } - - [Utilities.PublicAPI, JsonIgnore] - public string passengertype => PassengerType.FromEDName(passengertypeEDName)?.localizedName; - - [Utilities.PublicAPI] - public bool? passengerwanted { get; set; } + #region Mission Origin and Origin Faction + // The system in which the mission was accepted [Utilities.PublicAPI] - public bool? passengervips { get; set; } + public string originsystem { get; set; } + // The station in which the mission was accepted [Utilities.PublicAPI] - public string target { get; set; } + public string originstation { get; set; } + // Mission returns to origin [Utilities.PublicAPI] - public string targetfaction { get; set; } - - public string targetTypeEDName; - - [Utilities.PublicAPI, JsonIgnore] - public string targettype => TargetType.FromEDName(targetTypeEDName)?.localizedName; + public bool originreturn => tagsList.Any(t => t.ClaimAtOrigin); [Utilities.PublicAPI] - public DateTime? expiry { get; set; } - - [Utilities.PublicAPI, JsonIgnore] - public long? expiryseconds => expiry != null ? (long?)Utilities.Dates.fromDateTimeToSeconds((DateTime)expiry) : null; - - [JsonIgnore] - public bool expiring { get; set; } - - // Default Constructor - public Mission() { } - - [JsonConstructor] - // Main Constructor - public Mission(long MissionId, string Name, DateTime? expiry, MissionStatus Status, bool Shared = false) - { - this.missionid = MissionId; - this.name = Name; - this.expiry = expiry?.ToUniversalTime(); - this.statusDef = Status; - this.shared = Shared; - this.expiring = false; - destinationsystems = new List(); - } - - public void UpdateTimeRemaining() - { - OnPropertyChanged(nameof(timeRemaining)); - } - - public event PropertyChangedEventHandler PropertyChanged; + public string faction { get; set; } - [NotifyPropertyChangedInvocator] - protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } + // The state of the minor faction + [ JsonIgnore ] public FactionState FactionState => GetFactionState( name ); - private void SetFactionState() + private FactionState GetFactionState ( string missionName ) { - if (string.IsNullOrEmpty(name)) { return; } + if ( string.IsNullOrEmpty( missionName ) ) + { return null; } // Get the faction state (Boom, Bust, Civil War, etc), if available - for (int i = 2; i < name.Split('_').Count(); i++) + var elements = missionName.Split( '_' ); + for ( var i = 2; i < elements.Length; i++ ) { - string element = name.Split('_') + var element = elements .ElementAtOrDefault(i)? .ToLowerInvariant(); - // Might be a faction state - FactionState factionState = FactionState + // Return faction state when present + var factionState = FactionState .AllOfThem - .Find(s => s.edname.ToLowerInvariant() == element); - if (factionState != null) - { - factionstate = factionState.localizedName; - break; - } + .FirstOrDefault(s => s.edname.ToLowerInvariant() == element); + if ( factionState != null ) + { return factionState; } } - } - private void SetTypes() - { - if (string.IsNullOrEmpty(name)) { return; } - - var tidiedName = name.ToLowerInvariant() - .Replace("agriculture", "agri") // to match the `agri` economy definition - .Replace("altruismcredits", "altruism_credits") - .Replace("elections", "election") // to match the `election` faction state definition - .Replace("assassinationillegal", "assassinate_illegal") - .Replace("massacreillegal", "massacre_illegal") - .Replace("onslaughtillegal", "onslaught_illegal") - .Replace("salvageillegal", "salvage_illegal") - ; + return null; + } - var elements = tidiedName.Split('_').ToList(); - - // Skip various obscure mission type elements that we don't need or that we're representing some other way - elements.RemoveAll(t => - t == "mission" || - t == "arriving" || - t == "leaving" || - t == "plural" || - t == "name" || - t == "bs" || - t == "ds" || - t == "rs" || - t == "mb" - ); - - // Some elements should not be removed but should be moved to the end of the list. - // Do that here. - foreach (var elementToMove in new[] { "tw" }) - { - if (elements.FirstOrDefault() == elementToMove) - { - elements.Remove(elementToMove); - elements.Add(elementToMove); - } - } + #endregion - // Skip passenger elements (we'll fill these using the `Passengers` event) - elements.RemoveAll(t => PassengerType - .AllOfThem - .Select(s => s.edname) - .Contains(t, StringComparer.InvariantCultureIgnoreCase)); + #region Mission Destination - // Tidy up any government name embedded in the elements - for (var index = 0; index < elements.Count; index++) + // The destination system of the mission + [ Utilities.PublicAPI ] + public string destinationsystem + { + get => _destinationsystem; + set { - var gov = Government.AllOfThem - .FirstOrDefault(e => e.edname.ToLowerInvariant() == $"$government_{elements[index]};"); - if (gov != null) + if (_destinationsystem != value) { - elements[index] = gov.edname; + _destinationsystem = value; + OnPropertyChanged(); } } + } + [JsonIgnore] + private string _destinationsystem; - // Skip numeric elements - elements.RemoveAll(t => int.TryParse(t, out _)); - - // Replace chained mission types with conventional equivalents - elements.ForEach(e => - { - if (CHAINED.TryGetValue(e, out var value)) { e = value; } - }); - - foreach (var element in elements) + // The destination station of the mission + [Utilities.PublicAPI] + public string destinationstation + { + get => _destinationstation; + set { - var typeDef = MissionType.FromEDName(element); - if (typeDef != null) + if (_destinationstation != value) { - tagsList.Add(typeDef); + _destinationstation = value; + OnPropertyChanged(); } } } + [JsonIgnore] + private string _destinationstation; - private void GetDestinationStation() + // Destination systems for chained missions + [Utilities.PublicAPI] + public List destinationsystems { get; set; } + + private static string FallbackGetDestinationStation ( string localisedName ) { - if (string.IsNullOrEmpty(localisedname) || !string.IsNullOrEmpty(destinationstation)) { return; } + if ( string.IsNullOrEmpty( localisedName ) ) + { return string.Empty; } - var tidiedName = localisedname + var tidiedName = localisedName .Replace("Covert ", "") .Replace("Nonviolent ", "") .Replace("Digital Infiltration: ", "") @@ -494,43 +324,88 @@ private void GetDestinationStation() Tuple.Create("Turn on power at ", "") }; - string settlementName = null; - foreach (var prefixSuffix in prefixesSuffixes) + foreach ( var prefixSuffix in prefixesSuffixes ) { - if (tidiedName.StartsWith(prefixSuffix.Item1, StringComparison.InvariantCultureIgnoreCase) - && tidiedName.EndsWith(prefixSuffix.Item2, StringComparison.InvariantCultureIgnoreCase)) + if ( tidiedName.StartsWith( prefixSuffix.Item1, StringComparison.InvariantCultureIgnoreCase ) + && tidiedName.EndsWith( prefixSuffix.Item2, StringComparison.InvariantCultureIgnoreCase ) ) { - if (prefixSuffix.Item1.Length > 0) + if ( prefixSuffix.Item1.Length > 0 ) { tidiedName = tidiedName - .Replace(prefixSuffix.Item1, ""); + .Replace( prefixSuffix.Item1, "" ); } - if (prefixSuffix.Item2.Length > 0) + if ( prefixSuffix.Item2.Length > 0 ) { tidiedName = tidiedName - .Replace(prefixSuffix.Item2, ""); + .Replace( prefixSuffix.Item2, "" ); } - settlementName = tidiedName; break; } } + return tidiedName; + } + + #endregion + + #region Community Goal Info + + // Community goal details, if applicable + public int communalPercentileBand { get; set; } + + public int communalTier { get; set; } + + #endregion + + #region Passenger Data + + public string passengertypeEDName { get; set; } + + [Utilities.PublicAPI, JsonIgnore] + public string passengertype => PassengerType.FromEDName( passengertypeEDName )?.localizedName; + + [Utilities.PublicAPI] + public bool? passengerwanted { get; set; } + + [Utilities.PublicAPI] + public bool? passengervips { get; set; } - if (!string.IsNullOrEmpty(settlementName)) + #endregion + + #region Mission Target + + [Utilities.PublicAPI] + public string target { get; set; } + + [Utilities.PublicAPI] + public string targetfaction + { + get => _targetfaction; + set { - destinationstation = settlementName; - OnPropertyChanged(nameof(destinationstation)); + if ( _targetfaction != value ) + { + _targetfaction = value; + OnPropertyChanged(); + } } } + private string _targetfaction; + + public string targetTypeEDName; - private void GetTargetFaction() + [Utilities.PublicAPI, JsonIgnore] + public string targettype => TargetType.FromEDName( targetTypeEDName )?.localizedName; + + private string FallbackGetTargetFaction ( string localisedName ) { - if (string.IsNullOrEmpty(localisedname) || !string.IsNullOrEmpty(targetfaction)) { return; } + if ( string.IsNullOrEmpty( localisedName ) ) + { return string.Empty; } - var tidiedName = localisedname - .Replace("Settlement ", "") - .Replace("Massacre: ", "") - .Replace("Raid: ", "") - ; + var tidiedName = localisedName + .Replace("Settlement ", "") + .Replace("Massacre: ", "") + .Replace("Raid: ", "") + ; var prefixesSuffixes = new List> { @@ -538,40 +413,52 @@ private void GetTargetFaction() Tuple.Create("Take out ", " personnel"), }; - string factionName = null; - foreach (var prefixSuffix in prefixesSuffixes) + foreach ( var prefixSuffix in prefixesSuffixes ) { - if (tidiedName.StartsWith(prefixSuffix.Item1, StringComparison.InvariantCultureIgnoreCase) - && tidiedName.EndsWith(prefixSuffix.Item2, StringComparison.InvariantCultureIgnoreCase)) + if ( tidiedName.StartsWith( prefixSuffix.Item1, StringComparison.InvariantCultureIgnoreCase ) + && tidiedName.EndsWith( prefixSuffix.Item2, StringComparison.InvariantCultureIgnoreCase ) ) { - if (prefixSuffix.Item1.Length > 0) + if ( prefixSuffix.Item1.Length > 0 ) { tidiedName = tidiedName - .Replace(prefixSuffix.Item1, ""); + .Replace( prefixSuffix.Item1, "" ); } - if (prefixSuffix.Item2.Length > 0) + if ( prefixSuffix.Item2.Length > 0 ) { tidiedName = tidiedName - .Replace(prefixSuffix.Item2, ""); + .Replace( prefixSuffix.Item2, "" ); } - factionName = tidiedName; break; } } - if (!string.IsNullOrEmpty(factionName)) - { - targetfaction = factionName; - OnPropertyChanged(nameof(targetfaction)); - } + return tidiedName; } - private void UpdateExpiry() + #endregion + + // Default Constructor + public Mission() { } + + [JsonConstructor] + // Main Constructor + public Mission(long MissionId, string Name, DateTime? expiry, MissionStatus Status, bool Shared = false) { - if (statusDef != MissionStatus.Active && !onfoot) - { - expiry = null; - } + this.missionid = MissionId; + this.name = Name; + this.expiry = expiry?.ToUniversalTime(); + this.statusDef = Status; + this.shared = Shared; + this.expiring = false; + destinationsystems = new List(); + } + + public event PropertyChangedEventHandler PropertyChanged; + + [NotifyPropertyChangedInvocator] + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } } diff --git a/DataDefinitions/MissionType.cs b/DataDefinitions/MissionType.cs index f0b453aafe..fcf1195d3b 100644 --- a/DataDefinitions/MissionType.cs +++ b/DataDefinitions/MissionType.cs @@ -1,124 +1,250 @@ -namespace EddiDataDefinitions +using System; +using System.Collections.Generic; +using System.Linq; + +namespace EddiDataDefinitions { ///

/// Mission types /// public class MissionType : ResourceBasedLocalizedEDName { - static MissionType() + static MissionType () { resourceManager = Properties.MissionType.ResourceManager; resourceManager.IgnoreCase = true; - missingEDNameHandler = (edname) => new MissionType(edname); - - _ = new MissionType("Alert"); - _ = new MissionType("Altruism"); - _ = new MissionType("Assassination", true); - _ = new MissionType("Assassinate", true); - _ = new MissionType("AssassinateWing", true); - _ = new MissionType("BlOps", true); - _ = new MissionType("Collect", true); - _ = new MissionType("CollectWing", true); - _ = new MissionType("CommunityGoal"); - _ = new MissionType("Courier", true); - _ = new MissionType("Credits"); // Donation type: credits - _ = new MissionType("Delivery", true); - _ = new MissionType("DeliveryWing", true); - _ = new MissionType("Disable", true); - _ = new MissionType("DisableMegaship", true); - _ = new MissionType("DisableWing", true); - _ = new MissionType("Founder"); - _ = new MissionType("Hack", true); - _ = new MissionType("HackMegaship", true); - _ = new MissionType("LongDistanceExpedition"); - _ = new MissionType("Massacre", true); - _ = new MissionType("MassacreThargoid", true); - _ = new MissionType("MassacreWing", true); - _ = new MissionType("Mining", true); - _ = new MissionType("MiningWing", true); - _ = new MissionType("OnFoot", true); - _ = new MissionType("Onslaught", true); - _ = new MissionType("PassengerBulk", true); - _ = new MissionType("PassengerEvacuation", true); - _ = new MissionType("PassengerVIP", true); - _ = new MissionType("Piracy", true); - _ = new MissionType("Planet", true); - _ = new MissionType("Planetary", true); - _ = new MissionType("POI", true); - _ = new MissionType("Rescue", true); - _ = new MissionType("Sabotage", true); - _ = new MissionType("Salvage", true); - _ = new MissionType("Scan", true); - _ = new MissionType("Sightseeing", true); - _ = new MissionType("Smuggle", true); - - // Hack types - _ = new MissionType("Download", true); - _ = new MissionType("Upload", true); - - // Heist types - _ = new MissionType("Heist", true); - _ = new MissionType("ProductionHeist", true); - - // Massacre target types - _ = new MissionType( "Scout", true ); - _ = new MissionType( "Skimmer", true ); - _ = new MissionType( "Conflict", true ); - - // Mission difficulty types - _ = new MissionType("Covert"); - _ = new MissionType("Hard"); - _ = new MissionType("Illegal"); - _ = new MissionType("Legal"); - _ = new MissionType("NCD"); - - // Mission special types - _ = new MissionType("Chain"); - _ = new MissionType("GenericPermit1"); - _ = new MissionType("RankEmp"); - _ = new MissionType("RankFed"); - _ = new MissionType("Special"); - _ = new MissionType("StartZone"); - _ = new MissionType("Welcome"); - _ = new MissionType("TheDead"); // Ram-Tah special mission investigating Guardian ruins - _ = new MissionType("TW"); // Thargoid War - - // Station states - _ = new MissionType("Burning"); - - // Odyssey settlement states - _ = new MissionType("Offline", true); - _ = new MissionType("Reboot", true); - _ = new MissionType("RebootRestore", true); - - // Sabotage types - _ = new MissionType("Power", true); - _ = new MissionType("Production", true); + missingEDNameHandler = ( edname ) => new MissionType( edname ); + + // Include tags derived from economies, faction states, and government types + foreach ( var economy in Economy.AllOfThem ) + { + _ = new MissionType( economy.edname ) + { + fallbackLocalizedName = economy.localizedName, fallbackInvariantName = economy.invariantName + }; + } + + foreach ( var factionState in FactionState.AllOfThem ) + { + _ = new MissionType( factionState.edname ) + { + fallbackLocalizedName = factionState.localizedName, + fallbackInvariantName = factionState.invariantName + }; + } + + foreach ( var government in Government.AllOfThem ) + { + _ = new MissionType( government.edname ) + { + fallbackLocalizedName = government.localizedName, + fallbackInvariantName = government.invariantName + }; + } } + // PRIMARY mission types (typically listed first in mission name) + + public static MissionType Altruism = new MissionType( "Altruism", true, true ); + public static MissionType Assassinate = new MissionType( "Assassinate", true, true ); + public static MissionType Collect = new MissionType( "Collect", true, true ); + public static MissionType CommunityGoal = new MissionType( "CommunityGoal", true ); + public static MissionType Courier = new MissionType( "Courier", false, true ); + public static MissionType Delivery = new MissionType( "Delivery", true, true ); + public static MissionType Disable = new MissionType( "Disable", true, true ); + public static MissionType Hack = new MissionType( "Hack", true, true ); + public static MissionType LongDistanceExpedition = new MissionType( "LongDistanceExpedition", true, true ); + public static MissionType Massacre = new MissionType( "Massacre", true, true ); + public static MissionType Mining = new MissionType( "Mining", true, true ); + public static MissionType OnFoot = new MissionType( "OnFoot", true, true ); + public static MissionType Passenger = new MissionType( "Passenger", false, true ); + public static MissionType Piracy = new MissionType( "Piracy", true, true ); + public static MissionType Rescue = new MissionType( "Rescue", true, true ); // Horizons / surface salvage missions + public static MissionType Salvage = new MissionType( "Salvage", true, true ); + public static MissionType Scan = new MissionType( "Scan", true, true ); // Surface scan + public static MissionType SightSeeing = new MissionType( "Sightseeing", true, true ); + public static MissionType Smuggle = new MissionType( "Smuggle", false, true ); + + // SECONDARY mission types + + public static MissionType Alert = new MissionType( "Alert" ); + public static MissionType Assassination = new MissionType( "Assassination" ); // On-Foot missions to assassinate individual persons + public static MissionType BlOps = new MissionType( "BlOps" ); // Black ops + public static MissionType Bulk = new MissionType( "Bulk" ); // Bulk passenger missions + public static MissionType Burning = new MissionType( "Burning" ); // Burning station + public static MissionType Chained = new MissionType( "Chain" ); // Chained missions + public static MissionType Conflict = new MissionType( "Conflict" ); // Conflict zone massacre missions + public static MissionType Contact = new MissionType( "Contact" ); // On-foot missions assigned by an on-foot contact + public static MissionType Covert = new MissionType( "Covert" ); // On-foot covert missions + public static MissionType Credits = new MissionType( "Credits" ); // Altruism missions delivering credits + public static MissionType Download = new MissionType( "Download" ); // On-foot hack missions + public static MissionType Evacuation = new MissionType( "Evacuation" ); // Evacuation passenger missions + public static MissionType Founder = new MissionType( "Founder" ); // Founder missions (seen on delivery missions) + public static MissionType GenericPermit1 = new MissionType( "GenericPermit1" ); // This is a special type which seems to be awarded / completed immediately. + public static MissionType Hard = new MissionType( "Hard" ); // Hard missions + public static MissionType Heist = new MissionType( "Heist" ); // On-foot heist missions + public static MissionType Illegal = new MissionType( "Illegal" ); // Illegal missions + public static MissionType Legal = new MissionType( "Legal" ); // Legal missions + public static MissionType Megaship = new MissionType( "Megaship" ); // Missions interacting with a megaship + public static MissionType NCD = new MissionType( "NCD" ); // On-foot nonviolent missions + public static MissionType Offline = new MissionType( "Offline" ); // On-foot settlement state + public static MissionType Onslaught = new MissionType( "Onslaught" ); // On-foot massacre of settlement personnel + public static MissionType Planet = new MissionType( "Planet" ); // Horizons rescue and salvage missions + public static MissionType Planetary = new MissionType( "Planetary" ); // Horizons assassinate missions + public static MissionType POI = new MissionType( "POI" ); // On-foot POI heist missions, e.g. 'Seize the Hush from a hidden cache' + public static MissionType PoliticalPrisoners = new MissionType( "PolPrisoner" ); // Political prisoners passenger mission + public static MissionType Power = new MissionType( "Power" ); // On-foot mission sabotage target + public static MissionType Production = new MissionType( "Production" ); // On-foot mission sabotage target + public static MissionType ProductionHeist = new MissionType( "ProductionHeist" ); // On-foot heist missions, e.g. 'Acquire a (chemical) sample from Gough's Works' + public static MissionType RankEmp = new MissionType( "RankEmp" ); // Imperial rank missions + public static MissionType RankFed = new MissionType( "RankFed" ); // Federation rank missions + public static MissionType Reboot = new MissionType( "Reboot" ); // On-foot settlement mission objective + public static MissionType RebootRestore = new MissionType( "RebootRestore" ); // On-foot settlement mission objective + public static MissionType Sabotage = new MissionType( "Sabotage" ); // On-foot settlement sabotage missions + public static MissionType Scout = new MissionType( "Scout" ); // Thargoid war massacre scout missions + public static MissionType Skimmer = new MissionType( "Skimmer" ); // Horizons massacre planetary skimmer missions + public static MissionType Special = new MissionType( "Special" ); // Special missions + public static MissionType StartZone = new MissionType( "StartZone" ); // Start zone missions + public static MissionType Thargoid = new MissionType( "Thargoid" ); // Thargoid war massacre missions + public static MissionType TheDead = new MissionType( "TheDead" ); // Ram-Tah special mission investigating Guardian ruins + public static MissionType ThargoidWar = new MissionType( "TW" ); // Thargoid War + public static MissionType Upload = new MissionType( "Upload" ); // On-foot hack missions + public static MissionType VIP = new MissionType( "VIP" ); // VIP passenger missions + public static MissionType Welcome = new MissionType( "Welcome" ); // Welcome missions + public static MissionType Wing = new MissionType( "Wing" ); // Wing missions + public bool IncludeInMissionRouting { get; set; } + public bool ClaimAtOrigin { get; set; } + // dummy used to ensure that the static constructor has run - public MissionType() : this("") + public MissionType () : this( "" ) + { } + + private MissionType ( string edname, bool claimAtOrigin = false, bool includeInMissionRouting = false ) : base( + edname, edname ) { - // Include tags derived from economies, faction states, and government types - foreach (var economy in Economy.AllOfThem) + ClaimAtOrigin = claimAtOrigin; + IncludeInMissionRouting = includeInMissionRouting; + } + } + + public class MissionTypes + { + public static List FromMissionName ( string name ) + { + var tagsList = new List(); + if ( string.IsNullOrEmpty( name ) ) { return tagsList; } + + var tidiedName = name.ToLowerInvariant() + .Replace("agriculture", "agri") // to match the `agri` economy definition + .Replace("altruismcredits", "altruism_credits") + .Replace("assassinatewing", "assassinate_wing") + .Replace("assassinationillegal", "assassinate_illegal") + .Replace("collectwing", "collect_wing") + .Replace("deliverywing", "delivery_wing") + .Replace("disablemegaship", "disable_megaship") + .Replace("disablewing", "disable_wing") + .Replace("elections", "election") // to match the `election` faction state definition + .Replace("hackmegaship", "hack_megaship") + .Replace("massacreillegal", "massacre_illegal") + .Replace("massacrethargoid", "massacre_thargoid") + .Replace("massacrewing", "massacre_wing") + .Replace("miningwing", "mining_wing") + .Replace("onslaughtillegal", "onslaught_illegal") + .Replace("passengerbulk", "passenger_bulk") + .Replace("passengerevacuation", "passenger_evacuation") + .Replace("passengervip", "passenger_vip") + .Replace("salvageillegal", "salvage_illegal") + ; + + var elements = tidiedName.Split('_').ToList(); + + // Skip various obscure mission type elements that we don't need or that we're representing some other way + elements.RemoveAll( t => + t == "mission" || + t == "arriving" || + t == "leaving" || + t == "plural" || + t == "name" || + t == "bs" || + t == "ds" || + t == "rs" || + t == "mb" + ); + + // Some elements should not be removed but should be moved to the end of the list. + // Do that here. + foreach ( var elementToMove in new[] { "tw" } ) { - _ = new MissionType(economy.edname) { fallbackLocalizedName = economy.localizedName, fallbackInvariantName = economy.invariantName }; + if ( elements.FirstOrDefault() == elementToMove ) + { + elements.Remove( elementToMove ); + elements.Add( elementToMove ); + } } - foreach (var factionState in FactionState.AllOfThem) + + // Skip passenger elements (we'll fill these using the `Passengers` event) + elements.RemoveAll( t => PassengerType + .AllOfThem + .Select( s => s.edname ) + .Contains( t, StringComparer.InvariantCultureIgnoreCase ) ); + + // Tidy up any government name embedded in the elements + for ( var index = 0; index < elements.Count; index++ ) { - _ = new MissionType(factionState.edname) { fallbackLocalizedName = factionState.localizedName, fallbackInvariantName = factionState.invariantName }; + var gov = Government.AllOfThem + .FirstOrDefault(e => e.edname.ToLowerInvariant() == $"$government_{elements[index]};"); + if ( gov != null ) + { + elements[ index ] = gov.edname; + } } - foreach (var government in Government.AllOfThem) + + // Skip numeric elements + elements.RemoveAll( t => int.TryParse( t, out _ ) ); + + // Replace chained mission types with conventional equivalents + foreach ( var chainedElement in CHAINED ) { - _ = new MissionType(government.edname) { fallbackLocalizedName = government.localizedName, fallbackInvariantName = government.invariantName }; + if ( elements.Remove( chainedElement.Key ) ) + { + elements = elements.Prepend( chainedElement.Value ).ToList(); + } } + + foreach ( var element in elements ) + { + var typeDef = MissionType.FromEDName(element); + if ( typeDef != null ) + { + tagsList.Add( typeDef ); + } + } + + return tagsList; } - private MissionType(string edname, bool includeInMissionRouting = false) : base(edname, edname) + private static readonly Dictionary CHAINED = new Dictionary() { - IncludeInMissionRouting = includeInMissionRouting; - } + {"clearingthepath", "delivery"}, + {"drawthegeneralout", "assassinate"}, + {"findthepiratelord", "assassinate"}, + {"helpfinishtheorder", "delivery"}, + {"helpwithpreventionmeasures", "massacre"}, + {"miningtoorder", "mining"}, + {"piracyfraud", "delivery"}, + {"planetaryincursions", "scan"}, + {"rampantleadership", "assassinate"}, + {"regainfooting", "assassinate"}, + {"rescuefromthetwins", "salvage"}, + {"rescuethewares", "salvage"}, + {"safetravelling", "passengervip"}, + {"salvagejustice", "assassinate"}, + {"securingmyposition", "passengervip"}, + {"seekingasylum", "assassinate"}, + {"thedead", "special"}, + {"wrongtarget", "assassinate"}, + }; } } diff --git a/DataDefinitions/Properties/MissionType.Designer.cs b/DataDefinitions/Properties/MissionType.Designer.cs index 865d84f35b..ebac14d37e 100644 --- a/DataDefinitions/Properties/MissionType.Designer.cs +++ b/DataDefinitions/Properties/MissionType.Designer.cs @@ -87,15 +87,6 @@ internal static string Assassinate { } } - /// - /// Looks up a localized string similar to Wing Assassination. - /// - internal static string AssassinateWing { - get { - return ResourceManager.GetString("AssassinateWing", resourceCulture); - } - } - /// /// Looks up a localized string similar to Assassination. /// @@ -114,6 +105,15 @@ internal static string BlOps { } } + /// + /// Looks up a localized string similar to Bulk Transport. + /// + internal static string Bulk { + get { + return ResourceManager.GetString("Bulk", resourceCulture); + } + } + /// /// Looks up a localized string similar to On Fire. /// @@ -141,15 +141,6 @@ internal static string Collect { } } - /// - /// Looks up a localized string similar to Wing Collection. - /// - internal static string CollectWing { - get { - return ResourceManager.GetString("CollectWing", resourceCulture); - } - } - /// /// Looks up a localized string similar to Community Goal. /// @@ -168,6 +159,15 @@ internal static string Conflict { } } + /// + /// Looks up a localized string similar to Contact. + /// + internal static string Contact { + get { + return ResourceManager.GetString("Contact", resourceCulture); + } + } + /// /// Looks up a localized string similar to Data Courier. /// @@ -204,15 +204,6 @@ internal static string Delivery { } } - /// - /// Looks up a localized string similar to Wing Delivery. - /// - internal static string DeliveryWing { - get { - return ResourceManager.GetString("DeliveryWing", resourceCulture); - } - } - /// /// Looks up a localized string similar to Disable Surface Installation. /// @@ -223,29 +214,20 @@ internal static string Disable { } /// - /// Looks up a localized string similar to Disable Megaship. + /// Looks up a localized string similar to Download. /// - internal static string DisableMegaship { + internal static string Download { get { - return ResourceManager.GetString("DisableMegaship", resourceCulture); + return ResourceManager.GetString("Download", resourceCulture); } } /// - /// Looks up a localized string similar to Wing Disable. + /// Looks up a localized string similar to Evacuation. /// - internal static string DisableWing { + internal static string Evacuation { get { - return ResourceManager.GetString("DisableWing", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Download. - /// - internal static string Download { - get { - return ResourceManager.GetString("Download", resourceCulture); + return ResourceManager.GetString("Evacuation", resourceCulture); } } @@ -276,15 +258,6 @@ internal static string Hack { } } - /// - /// Looks up a localized string similar to Hack Megaship. - /// - internal static string HackMegaship { - get { - return ResourceManager.GetString("HackMegaship", resourceCulture); - } - } - /// /// Looks up a localized string similar to Hard. /// @@ -340,20 +313,11 @@ internal static string Massacre { } /// - /// Looks up a localized string similar to Thargoid Massacre. - /// - internal static string MassacreThargoid { - get { - return ResourceManager.GetString("MassacreThargoid", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Wing Massacre. + /// Looks up a localized string similar to Megaship. /// - internal static string MassacreWing { + internal static string Megaship { get { - return ResourceManager.GetString("MassacreWing", resourceCulture); + return ResourceManager.GetString("Megaship", resourceCulture); } } @@ -366,15 +330,6 @@ internal static string Mining { } } - /// - /// Looks up a localized string similar to Wing Mining. - /// - internal static string MiningWing { - get { - return ResourceManager.GetString("MiningWing", resourceCulture); - } - } - /// /// Looks up a localized string similar to Nonviolent. /// @@ -411,33 +366,6 @@ internal static string Onslaught { } } - /// - /// Looks up a localized string similar to Transport. - /// - internal static string PassengerBulk { - get { - return ResourceManager.GetString("PassengerBulk", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Passenger Evacuation. - /// - internal static string PassengerEvacuation { - get { - return ResourceManager.GetString("PassengerEvacuation", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Transport. - /// - internal static string PassengerVIP { - get { - return ResourceManager.GetString("PassengerVIP", resourceCulture); - } - } - /// /// Looks up a localized string similar to Piracy. /// @@ -555,6 +483,15 @@ internal static string Rescue { } } + /// + /// Looks up a localized string similar to Sabotage. + /// + internal static string Sabotage { + get { + return ResourceManager.GetString("Sabotage", resourceCulture); + } + } + /// /// Looks up a localized string similar to Salvage. /// @@ -627,6 +564,15 @@ internal static string StartZone { } } + /// + /// Looks up a localized string similar to Thargoid. + /// + internal static string Thargoid { + get { + return ResourceManager.GetString("Thargoid", resourceCulture); + } + } + /// /// Looks up a localized string similar to The Dead. /// @@ -654,6 +600,15 @@ internal static string Upload { } } + /// + /// Looks up a localized string similar to Transport VIP. + /// + internal static string VIP { + get { + return ResourceManager.GetString("VIP", resourceCulture); + } + } + /// /// Looks up a localized string similar to Welcome. /// @@ -662,5 +617,14 @@ internal static string Welcome { return ResourceManager.GetString("Welcome", resourceCulture); } } + + /// + /// Looks up a localized string similar to Wing. + /// + internal static string Wing { + get { + return ResourceManager.GetString("Wing", resourceCulture); + } + } } } diff --git a/DataDefinitions/Properties/MissionType.de.resx b/DataDefinitions/Properties/MissionType.de.resx index b8aff3ae64..18320a9931 100644 --- a/DataDefinitions/Properties/MissionType.de.resx +++ b/DataDefinitions/Properties/MissionType.de.resx @@ -126,15 +126,9 @@ Mordauftrag - - Mordauftrag im Wing - Beschaffungsmission - - Beschaffung im Wing - Gemeinschaftsziel @@ -144,15 +138,9 @@ Liefermission - - Lieferung im Wing - Oberflächeneinrichtung abschalten - - Abschalten im Wing - Einreisegenehmigung @@ -165,22 +153,13 @@ Massakermission - - Thargoiden Massakermission - - - Massakermission im Wing - Bergbaumission - - Bergbau im Wing - - + Passagiertransport - + VIP-Transport @@ -235,15 +214,9 @@ Imperiale Aufstiegsmission - - Megaschiff ausschalten - Gründermission - - Megaschiff hacken - Skimmer zerstören Massacre type @@ -324,7 +297,7 @@ In Flammen e.g. rescue from a burning station - + Passagier-Evakuierung diff --git a/DataDefinitions/Properties/MissionType.es.resx b/DataDefinitions/Properties/MissionType.es.resx index 26fb836883..e90bcfebd3 100644 --- a/DataDefinitions/Properties/MissionType.es.resx +++ b/DataDefinitions/Properties/MissionType.es.resx @@ -124,15 +124,9 @@ Asesinato - - Asesinato de escuadrón - Recaudación - - Recaudación de escuadrón - Objetivos de la comunidad @@ -142,16 +136,9 @@ Entrega - - Entrega de Escuadrón - Deshabilitar instalación de superficie - - Deshabilitar escuadrón - - Hackeo @@ -161,22 +148,13 @@ Masacre - - Masacre Thargoide - - - Masacre de Escuadrón - Minería - - Escuadrón minero - - + Transporte - + Transporte diff --git a/DataDefinitions/Properties/MissionType.fr.resx b/DataDefinitions/Properties/MissionType.fr.resx index 07dc83355e..ceafef6571 100644 --- a/DataDefinitions/Properties/MissionType.fr.resx +++ b/DataDefinitions/Properties/MissionType.fr.resx @@ -124,15 +124,9 @@ Assassinat - - Assassinat d'Escadrille - Collection - - Collection d'Escadrille - Objectif communautaire @@ -142,16 +136,9 @@ Livraison - - Livraison d'Escadrille - Désactiver installation de surface - - Désactiver Escadrille - - Piratage @@ -161,22 +148,13 @@ Massacre - - Massacre Thargoïd - - - Massacre d'Escadrille - Minage - - Escadrille minière - - + Transport - + Transport diff --git a/DataDefinitions/Properties/MissionType.hu.resx b/DataDefinitions/Properties/MissionType.hu.resx index 608f7c3298..75a62911f8 100644 --- a/DataDefinitions/Properties/MissionType.hu.resx +++ b/DataDefinitions/Properties/MissionType.hu.resx @@ -143,10 +143,10 @@ Bányászat - + Szállítás - + Szállítás diff --git a/DataDefinitions/Properties/MissionType.it.resx b/DataDefinitions/Properties/MissionType.it.resx index b5443360aa..fd44f99fb7 100644 --- a/DataDefinitions/Properties/MissionType.it.resx +++ b/DataDefinitions/Properties/MissionType.it.resx @@ -126,15 +126,9 @@ Assassinio - - Assassinio di gruppo - Raccolta - - Raccolta di gruppo - Obiettivo Comunitario @@ -144,15 +138,9 @@ Consegna - - Consegna di gruppo - Disabilitazione Installazione di Superficie - - Disabilitazione di Gruppo - Occasione per il Lasciapassare @@ -165,22 +153,13 @@ Massacro - - Massacra Thargoid - - - Massacro di Gruppo - Estrazione di Minerali - - Estrazione di Minerali in Gruppo - - + Trasporta - + Trasporta @@ -235,15 +214,9 @@ Contratto per la Marina Imperiale - - Disabilita Mega nave - Fondatore - - Vìola Mega nave - Obiettivi Skimmer Massacre type @@ -324,7 +297,7 @@ A fuoco e.g. rescue from a burning station - + Evacuazione dei Passeggeri diff --git a/DataDefinitions/Properties/MissionType.ja.resx b/DataDefinitions/Properties/MissionType.ja.resx index 6ce1afb92a..3146b71f2e 100644 --- a/DataDefinitions/Properties/MissionType.ja.resx +++ b/DataDefinitions/Properties/MissionType.ja.resx @@ -177,15 +177,9 @@ 帝国海軍の契約 - - メガシップの無効化 - ファウンダー - - メガシップのハッキング - 標的のスキマー Massacre type diff --git a/DataDefinitions/Properties/MissionType.pt-BR.resx b/DataDefinitions/Properties/MissionType.pt-BR.resx index df81f1c614..5b7d30d9f5 100644 --- a/DataDefinitions/Properties/MissionType.pt-BR.resx +++ b/DataDefinitions/Properties/MissionType.pt-BR.resx @@ -126,15 +126,9 @@ Assassinato - - Assassinato em Esquadrão - Coleta - - Coleta em Esquadrão - Objetivo da Comunidade @@ -144,15 +138,9 @@ Entrega - - Entrega em Esquadrão - Desabilitar Instalação em Superfície - - Desabilitar em Esquadrão - Oportunidade de Aquisição de Permissão @@ -165,22 +153,13 @@ Massacre - - Massacre de Thargoid - - - Massacre em Esquadrão - Mineração - - Mineração em Esquadrão - - + Transporte - + Transporte @@ -235,15 +214,9 @@ Contrato da Marinha Imperial - - Desabilitar Meganave - Fundador - - Hackear Meganave - Alvos Skimmer Massacre type @@ -324,7 +297,7 @@ Em Chamas e.g. rescue from a burning station - + Evacuação de Passageiro diff --git a/DataDefinitions/Properties/MissionType.resx b/DataDefinitions/Properties/MissionType.resx index 77f95c3144..1247c6168c 100644 --- a/DataDefinitions/Properties/MissionType.resx +++ b/DataDefinitions/Properties/MissionType.resx @@ -126,15 +126,12 @@ Assassination - - Wing Assassination + + Wing Collection - - Wing Collection - Community Goal @@ -144,15 +141,9 @@ Delivery - - Wing Delivery - Disable Surface Installation - - Wing Disable - Permit Acquisition Opportunity @@ -165,23 +156,17 @@ Massacre - - Thargoid Massacre - - - Wing Massacre + + Thargoide.g. massacre of thargoid targets Mining - - Wing Mining + + Bulk Transporte.g. of passengers - - Transport - - - Transport + + Transport VIPe.g. VIP passenger Piracy @@ -235,15 +220,12 @@ Imperial Navy Contract - - Disable Megaship + + Megashipe.g. hack or disable missions targeting a megaship Founder - - Hack Megaship - Skimmer Targets Massacre type @@ -256,12 +238,12 @@ Covert - Download - Hack type + Download + On-foot hack type - Upload - Hack type + Upload + On-foot hack type Offline Settlement @@ -324,8 +306,8 @@ On Fire e.g. rescue from a burning station - - Passenger Evacuation + + Evacuatione.g. of passengers Alert @@ -334,4 +316,10 @@ Thargoid Scout Targets Massacre type + + Contacte.g. mission assigned by an on-foot contact + + + Sabotagee.g. on-foot settlement sabotage mission + \ No newline at end of file diff --git a/DataDefinitions/Properties/MissionType.ru.resx b/DataDefinitions/Properties/MissionType.ru.resx index f94ebc8244..de1e2c2320 100644 --- a/DataDefinitions/Properties/MissionType.ru.resx +++ b/DataDefinitions/Properties/MissionType.ru.resx @@ -126,15 +126,9 @@ Заказное убийство - - Заказное убийство для крыла - Поиск товаров - - Поиск товаров для крыла - Общественные Цели @@ -144,15 +138,9 @@ Доставка товара - - Доставка товара для крыла - Уничтожение беспилотников - - Wing Disable - Возможность получения разрешений @@ -165,22 +153,13 @@ Резня - - Уничтожение Таргоидов - - - Уничтожение целей длля крыла - Шахтерские - - Шахтерские для крыла - - + Транспорт - + Транспорт @@ -233,15 +212,9 @@ Контракт Империи - - Обесточить Мегакорабль - Основатель - - Взлом Мегакоробля - Цели беспелотники Massacre type diff --git a/DataDefinitions/Properties/MissionType.zh-CN.resx b/DataDefinitions/Properties/MissionType.zh-CN.resx index d87585d9a5..7a89decc9b 100644 --- a/DataDefinitions/Properties/MissionType.zh-CN.resx +++ b/DataDefinitions/Properties/MissionType.zh-CN.resx @@ -126,15 +126,9 @@ 刺杀 - - 组队刺杀 - 搜集 - - 组队搜集 - 社区目标 @@ -144,15 +138,9 @@ 投递 - - 组队投递 - 禁用地面站 - - 禁用组队 - Permit Aquisition @@ -165,22 +153,13 @@ 屠戮 - - 八角屠戮 - - - 组队屠戮 - 采矿 - - 组队采矿 - - + 运输 - + 运输 @@ -235,15 +214,9 @@ 帝国海军合同 - - 禁用巨舰 - 创始人 - - 骇入巨舰 - Skimmer 目标 Massacre type @@ -324,7 +297,7 @@ 失火 e.g. rescue from a burning station - + 疏散乘客 diff --git a/MissionMonitor/MissionMonitor.cs b/MissionMonitor/MissionMonitor.cs index 86fbc1b6a0..5482c6d21b 100644 --- a/MissionMonitor/MissionMonitor.cs +++ b/MissionMonitor/MissionMonitor.cs @@ -952,7 +952,7 @@ public bool UpdateRedirectStatus(Mission mission) if (mission.originreturn && mission.originsystem == mission.destinationsystem && mission.originstation == mission.destinationstation) { - if (mission.edTags.Any(t => Mission.ORGRETURN.Contains(t, StringComparer.InvariantCultureIgnoreCase))) + if (mission.tagsList.Any(t => t.ClaimAtOrigin)) { if (mission.statusDef != MissionStatus.Claim) { diff --git a/Tests/MissionMonitorTests.cs b/Tests/MissionMonitorTests.cs index 007d071ff2..476d1ea972 100644 --- a/Tests/MissionMonitorTests.cs +++ b/Tests/MissionMonitorTests.cs @@ -169,7 +169,7 @@ public void TestMissionEventsScenario() Assert.IsTrue(events.Count == 1); missionMonitor._handleMissionsEvent((MissionsEvent)events[0]); Assert.AreEqual(3, missionMonitor.missions.Count); - Assert.AreEqual(3, missionMonitor.missions.Where(m => m.statusEDName == "Active").Count()); + Assert.AreEqual(3, missionMonitor.missions.Count( m => m.statusEDName == "Active" )); //CargoDepotEvent - 'Shared' line = @"{ ""timestamp"":""2018-08-26T02:55:10Z"", ""event"":""CargoDepot"", ""MissionID"":413748365, ""UpdateType"":""WingUpdate"", ""CargoType"":""Gold"", ""Count"":20, ""StartMarketID"":0, ""EndMarketID"":3224777216, ""ItemsCollected"":0, ""ItemsDelivered"":20, ""TotalItemsToDeliver"":54, ""Progress"":0.000000 }"; @@ -179,7 +179,8 @@ public void TestMissionEventsScenario() var mission = missionMonitor.missions.ToList().FirstOrDefault(m => m.missionid == 413748365); Assert.AreEqual(4, missionMonitor.missions.Count); Assert.IsNotNull(mission); - Assert.IsTrue(mission.edTags.Contains("CollectWing")); + Assert.IsTrue( mission.edTags.Contains( "Collect" ) ); + Assert.IsTrue( mission.edTags.Contains( "Wing" ) ); Assert.AreEqual("Active", mission.statusEDName); Assert.IsTrue(mission.originreturn); Assert.IsTrue(mission.wing); @@ -225,7 +226,7 @@ public void TestMissionEventsScenario() events = JournalMonitor.ParseJournalEntry(line); Assert.IsTrue(events.Count == 1); missionMonitor._handleMissionAcceptedEvent((MissionAcceptedEvent)events[0]); - Assert.AreEqual(1, missionMonitor.missions.ToList().Where(m => m.missionid == 413748324).Count()); + Assert.AreEqual(1, missionMonitor.missions.Count( m => m.missionid == 413748324 )); Assert.AreEqual(4, missionMonitor.missions.Count); //CargoDepotEvent - 'Collect' From 213d0783b228adfae9877960a23cba9ed863c4be Mon Sep 17 00:00:00 2001 From: T'kael Date: Sun, 14 Jul 2024 01:11:47 -0700 Subject: [PATCH 34/36] Fix a bug causing mission `expiry` to be unduly null. --- DataDefinitions/Mission.cs | 2 +- MissionMonitor/MissionMonitor.cs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/DataDefinitions/Mission.cs b/DataDefinitions/Mission.cs index 22e4c28803..eeb7723bf5 100644 --- a/DataDefinitions/Mission.cs +++ b/DataDefinitions/Mission.cs @@ -99,7 +99,7 @@ public MissionStatus statusDef set { _statusDef = value; - if ( value != MissionStatus.Active && !onfoot ) + if ( value != null && value != MissionStatus.Active && !onfoot ) { // Missions are time constrained when active, and on-foot missions // continue to be time constrained even after they are claimable. diff --git a/MissionMonitor/MissionMonitor.cs b/MissionMonitor/MissionMonitor.cs index 5482c6d21b..813d4ecad7 100644 --- a/MissionMonitor/MissionMonitor.cs +++ b/MissionMonitor/MissionMonitor.cs @@ -339,8 +339,9 @@ public bool _handleMissionsEvent(MissionsEvent @event) } else if (missionEntry.statusDef == MissionStatus.Active) { - // Update status on a missed 'redirect' - update = UpdateRedirectStatus(missionEntry); + missionEntry.expiry = mission.expiry; + UpdateRedirectStatus(missionEntry); + update = true; } } break; From edf353942f4bedb77bd0c217b8e2a563b1c1631d Mon Sep 17 00:00:00 2001 From: T'kael Date: Fri, 19 Jul 2024 15:54:45 -0700 Subject: [PATCH 35/36] Refactor context handling and fix a bug where context might not be preserved. --- SpeechResponder/CustomFunctions/F.cs | 12 +------- .../CustomFunctions/Occasionally.cs | 4 +-- SpeechResponder/CustomFunctions/OneOf.cs | 4 +-- SpeechResponder/CustomFunctions/Transmit.cs | 4 +-- .../ScriptResolverService/ICustomFunction.cs | 29 ++++++++++++++++--- 5 files changed, 29 insertions(+), 24 deletions(-) diff --git a/SpeechResponder/CustomFunctions/F.cs b/SpeechResponder/CustomFunctions/F.cs index 954f4dfb9f..8556babdaf 100644 --- a/SpeechResponder/CustomFunctions/F.cs +++ b/SpeechResponder/CustomFunctions/F.cs @@ -3,7 +3,6 @@ using JetBrains.Annotations; using System; using System.Collections.Generic; -using System.Linq; namespace EddiSpeechResponder.CustomFunctions { @@ -16,17 +15,8 @@ public class F : RecursiveFunction, ICustomFunction public Type ReturnType => typeof( string ); public IFunction function => Function.CreateNative1( ( runtime, scriptName, writer ) => { - // Use a cascading context consisting of variables set in the current document and variables set prior to resolving - var latestGlobalsContext = - Cottle.Context.CreateCustom( runtime.Globals.ToDictionary( g => g.Key, g => g.Value ) ); - var latestStateContext = - Cottle.Context.CreateBuiltin( - new Dictionary { [ "state" ] = ScriptResolver.buildState() } ); - var originalContext = Context; - var joinedContexts = Cottle.Context.CreateCascade(latestGlobalsContext, Cottle.Context.CreateCascade(latestStateContext, originalContext)); - var result = scriptName.AsString; - return ScriptResolver.resolveFromName( result, Scripts, joinedContexts, false )?.Trim(); + return ScriptResolver.resolveFromName( result, Scripts, GetContext( runtime.Globals ), false )?.Trim(); }); [UsedImplicitly] diff --git a/SpeechResponder/CustomFunctions/Occasionally.cs b/SpeechResponder/CustomFunctions/Occasionally.cs index 654e1c7aeb..b2356b81e7 100644 --- a/SpeechResponder/CustomFunctions/Occasionally.cs +++ b/SpeechResponder/CustomFunctions/Occasionally.cs @@ -3,7 +3,6 @@ using JetBrains.Annotations; using System; using System.Collections.Generic; -using System.Linq; namespace EddiSpeechResponder.CustomFunctions { @@ -29,8 +28,7 @@ public class Occasionally : RecursiveFunction, ICustomFunction { result = ""; } - var context = Cottle.Context.CreateCascade(Cottle.Context.CreateCustom(runtime.Globals.ToDictionary(g => g.Key, g => g.Value)), Context ); - return ScriptResolver.resolveFromValue( result.AsString, context, false ); + return ScriptResolver.resolveFromValue( result.AsString, GetContext( runtime.Globals ), false ); }); [UsedImplicitly] diff --git a/SpeechResponder/CustomFunctions/OneOf.cs b/SpeechResponder/CustomFunctions/OneOf.cs index 50a3c459f2..81975bc4c8 100644 --- a/SpeechResponder/CustomFunctions/OneOf.cs +++ b/SpeechResponder/CustomFunctions/OneOf.cs @@ -3,7 +3,6 @@ using JetBrains.Annotations; using System; using System.Collections.Generic; -using System.Linq; namespace EddiSpeechResponder.CustomFunctions { @@ -30,8 +29,7 @@ public class OneOf : RecursiveFunction, ICustomFunction var rand = random.Next( values.Count ); result = values[ rand ]; } - var context = Cottle.Context.CreateCascade(Cottle.Context.CreateCustom(runtime.Globals.ToDictionary(g => g.Key, g => g.Value)), Context ); - return ScriptResolver.resolveFromValue( result.AsString, context, false ); + return ScriptResolver.resolveFromValue( result.AsString, GetContext( runtime.Globals ), false ); } ); [UsedImplicitly] diff --git a/SpeechResponder/CustomFunctions/Transmit.cs b/SpeechResponder/CustomFunctions/Transmit.cs index 8c12f8aa17..f7a46ed859 100644 --- a/SpeechResponder/CustomFunctions/Transmit.cs +++ b/SpeechResponder/CustomFunctions/Transmit.cs @@ -3,7 +3,6 @@ using JetBrains.Annotations; using System; using System.Collections.Generic; -using System.Linq; namespace EddiSpeechResponder.CustomFunctions { @@ -19,8 +18,7 @@ public class Transmit : RecursiveFunction, ICustomFunction if (!string.IsNullOrEmpty( input.AsString) ) { var result = @"" + input.AsString + ""; - var context = Cottle.Context.CreateCascade(Cottle.Context.CreateCustom(runtime.Globals.ToDictionary(g => g.Key, g => g.Value)), Context ); - return ScriptResolver.resolveFromValue( result, context, false ); + return ScriptResolver.resolveFromValue( result, GetContext( runtime.Globals ), false ); } return "The Transmit function is used improperly. Please review the documentation for correct usage."; }); diff --git a/SpeechResponder/ScriptResolverService/ICustomFunction.cs b/SpeechResponder/ScriptResolverService/ICustomFunction.cs index a301782c8f..2187d9075e 100644 --- a/SpeechResponder/ScriptResolverService/ICustomFunction.cs +++ b/SpeechResponder/ScriptResolverService/ICustomFunction.cs @@ -1,6 +1,7 @@ using Cottle; using System; using System.Collections.Generic; +using System.Linq; namespace EddiSpeechResponder.Service { @@ -15,14 +16,34 @@ public interface ICustomFunction public class RecursiveFunction { - public IContext Context { get; } + private IContext TopLevelContext { get; } - public Dictionary Scripts { get; } + private static Dictionary RuntimeGlobals { get; set; } = new Dictionary(); - public RecursiveFunction ( IContext context, Dictionary< string, Script > scripts ) + protected Dictionary Scripts { get; } + + protected RecursiveFunction ( IContext context, Dictionary< string, Script > scripts ) { - this.Context = context; + this.TopLevelContext = context; this.Scripts = scripts; + RuntimeGlobals.Clear(); + } + + protected IContext GetContext ( IMap globals ) + { + RuntimeGlobals = new[] + { + globals.ToDictionary( g => g.Key, g => g.Value ), + RuntimeGlobals.Where( g => !globals.Contains( g.Key ) ) + } + .SelectMany( dict => dict ) + .ToDictionary( pair => pair.Key, pair => pair.Value ); + var runtimeState = new Dictionary { [ "state" ] = ScriptResolver.buildState() } + .Where( pair => !RuntimeGlobals.ContainsKey( pair.Key ) ); + var latestContext = Context.CreateBuiltin( new[] { RuntimeGlobals, runtimeState } + .SelectMany( dict => dict ) + .ToDictionary( pair => pair.Key, pair => pair.Value ) ); + return Context.CreateCascade( latestContext, TopLevelContext ); } } From e22a55973b58e7723f94e4840ae0294cb4920c95 Mon Sep 17 00:00:00 2001 From: T'kael Date: Sat, 27 Jul 2024 23:48:28 -0700 Subject: [PATCH 36/36] Roll EDDI version, note fix to nested contexts. --- ChangeLog.md | 5 +++-- Installer.iss | 2 +- Utilities/Constants.cs | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index bf5217a5a1..a3eb85ff18 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -4,12 +4,13 @@ Full details of the variables available for each noted event, and VoiceAttack in ## 4.1.0-b1 * Speech Responder + * Fixed a bug that could prevent variables set with `set` from being available in some contexts. * Scripts * `Blueprint make report` updated to fix a typo (stray letter). * `Material discard report` updated to tidy context. * `Material inventory report` updated to tidy context. - * `Mission check galaxy` updated to make `allmissions()` function pure. - * `Mission check system` updated to make `addstation()` function pure. + * `Mission check galaxy` updated to make `allmissions()` internal function pure. + * `Mission check system` updated to make `addstation()` internal function pure. * `Star scanned` updated to fix a typo (missing comma). * `System materials report` updated to fix an error with the `isSeleniumSpecialCase` helper function. * VoiceAttack diff --git a/Installer.iss b/Installer.iss index 78bcf4b52c..24982a2f36 100644 --- a/Installer.iss +++ b/Installer.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "EDDI" -#define MyAppVersion "4.1.0-a2" +#define MyAppVersion "4.1.0-b1" #define MyAppPublisher "Elite Dangerous Community Developers (EDCD)" #define MyAppURL "https://github.com/EDCD/EDDI/" #define MyAppExeName "EDDI.exe" diff --git a/Utilities/Constants.cs b/Utilities/Constants.cs index 58afab64fa..ae63134f7f 100644 --- a/Utilities/Constants.cs +++ b/Utilities/Constants.cs @@ -9,7 +9,7 @@ public class Constants { public const string EDDI_NAME = "EDDI"; public const string EDDI_URL_PROTOCOL = "eddi"; - public static Version EDDI_VERSION = new Version(4, 1, 0, Version.TestPhase.a, 2); + public static Version EDDI_VERSION = new Version(4, 1, 0, Version.TestPhase.b, 1); public const string EDDI_SERVER_URL = "https://edcd.github.io/EDDP/"; public static readonly string EDDI_SYSTEM_MUTEX_NAME = $"{EDDI_SERVER_URL}/{EDDI_NAME}/{Environment.GetEnvironmentVariable("UserName")}";