Guest User

Solar Panel Alignment Script FIX

a guest
Aug 10th, 2016
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 23.36 KB | None | 0 0
  1. // =================================[ START OF CONFIGURATION ]=================================  
  2. static class Configuration {
  3.     // Target average maximum power output to reach (in kW)
  4.     // Default (Vanilla): 119.5f for large ship/station, 29.5f for small ship
  5.     // Allowed values: 0f - 999999999f
  6.     public const float TargetAveragePowerOutput = 119.5f;
  7.  
  8.     // Delay between executions while aligning (in seconds)
  9.     // Default: 2.0f  
  10.     // Recommended values: 1.5f - 2.5f  
  11.     public const float WorkDelay = 2.0f;
  12.  
  13.     // Delay between executions while idling (in seconds)  
  14.     // Default: 10.0f  
  15.     // Recommended values: 2.5f - 10.0f  
  16.     public const float IdleDelay = 10.0f;
  17.  
  18.     // Delay between executions while aligning in hibernation mode (in seconds)
  19.     // Default: 1.5f
  20.     // Recommended values: 1.5f - 5f;
  21.     public const float HibernationWorkDelay = 1.5f;
  22.  
  23.     // Delay between executions while idling in hibernation mode (in seconds)
  24.     // Default: 10.0f
  25.     // Recommended values: 2.5f - 10.0f
  26.     public const float HibernationIdleDelay = 10.0f;
  27.  
  28.     // Maximum deviation when comparing angles (in degrees)
  29.     // Default: 1.0f;
  30.     // Recommended values: 0.0001f - 1.0f
  31.     public const float MaxAngleDeviation = 1.0f;
  32.  
  33.     // Speed of all rotors that are used to align the solar panels (in RPM)
  34.     // Lower values mean higher accuracy but also higher alignment time.  
  35.     // Default: 0.1f  
  36.     // Recommended values: 0.05f - 0.5f  
  37.     public const float RotorSpeed = 0.1f;
  38.  
  39.     // Name of the solar panel that should be used for optimization
  40.     // The name has to be EXACTLY THE SAME as in the terminal overview.  
  41.     // Default: "Solar Panel (optimized)"  
  42.     public const string SolarPanelName = "Solar Panel (SPAS)";
  43.  
  44.     // Determines if the name that was provided for SolarPanelName should be used as group name (true) or block name (false).  
  45.     // Default: false  
  46.     // Allowed values: true, false  
  47.     public const bool SolarPanelName_IsGroup = false;
  48.  
  49.     // Name of the timer block that should be used for looping
  50.     // The name has to be EXACTLY THE SAME as in the terminal overview.  
  51.     // Default: "Loop Timer"  
  52.     public const string TimerName = "Timer Block (SPAS)";
  53.  
  54.     // Names of all rotors that are connected to the solar panels that should be optimized
  55.     // Each name has to be EXACTLY THE SAME as the corresponding rotor's name in the terminal overview.  
  56.     // Default: { "Advanced Rotor" }  
  57.     // Allowed values: comma-separated list of strings  
  58.     public static readonly string[] RotorNames = { "Advanced Rotor (SPAS)" };
  59.  
  60.     // Determines for each element of RotorNames if the name provided should be used as group name (true) or block name (false).  
  61.     // If this does not have the same amount of elements as RotorNames, each remaining element of RotorNames is treated as block, not as group.
  62.     // Default: { false }  
  63.     // Allowed values: comma-separated list of true and false  
  64.     public static readonly bool[] RotorNames_IsGroup = {};
  65.  
  66.     // Suffix which can be applied to a rotor in a group to make it rotate in the opposite direction.  
  67.     // Use this in combination with rotor groups to set up more than one rotor in one axis.  
  68.     // Default: "[inv]"  
  69.     public const string InvertedRotorSuffix = "[inv]";
  70.  
  71.     // Configure features like the Energy Saver feature inside this class.  
  72.     public static class Features {
  73.         public static class EnergySaver {
  74.             // Enables the energy saver feature. This will cause rotors to move faster if the power output is low or make them do nothing if the power output is too low.  
  75.             // Default: true  
  76.             // Allowed values: true, false  
  77.             public const bool Enabled = true;
  78.  
  79.             // Maximum power output at which the script will stay in idle mode (in kW).  
  80.             // Default (Vanilla): 20 for large ship/station, 5 for small ship  
  81.             // Allowed values: 0 - 999999999  
  82.             public const int HibernatePowerOutput = 20;
  83.  
  84.             // Maximum power output at which the rotors will be accelerated by the panic speed multiplier (in kW).  
  85.             // Default (Vanilla): 60 for large ship/station, 15 for small ship  
  86.             // Allowed values: 0 - 999999999  
  87.             public const int PanicPowerOutput = 60;
  88.  
  89.             // Value by which the default rotor speed will be multiplied while in panic mode.
  90.             // Default: 2.0f  
  91.             // Recommended values: 1.0f - 5.0f  
  92.             public const float PanicSpeedMultiplier = 2.0f;
  93.         }
  94.  
  95.         public static class MaintenanceMode {
  96.             // Enables the maintenance mode feature. Use it to shut this script down temporarily, e.g. for repairs.
  97.             // Default: true
  98.             // Allowed values: true, false
  99.             public const bool Enabled = true;
  100.  
  101.             // Determines if the script should reinitialize after resuming from maintenance mode. This is needed if you add blocks to a group.
  102.             // Default: true
  103.             // Allowed values: true, false
  104.             public const bool Reinitialize = true;
  105.  
  106.             // Delay between executions while in maintenance mode (in seconds).
  107.             // Default: 30.0f
  108.             public const float MaintenanceDelay = 30.0f;
  109.  
  110.             // Suffix which should be used to mark a programmable block as in maintenance mode.
  111.             // Default: " [MAINTENANCE]"
  112.             public const string MaintenanceSuffix = " [MAINTENANCE]";
  113.         }
  114.     }
  115.  
  116.     // Configure your language by editing the values inside this class to the texts that are displayed inside your game.  
  117.     public static class Localization {
  118.         // Text that is located before the maximum power output value in the detailed description of the solar panel, including whitespaces.  
  119.         // English: "Max Output: "  
  120.         public const string MaxOutput = "Max Output: ";
  121.  
  122.         // Text that is located before the current power output value in the detailed description of the solar panel, including whitespaces.  
  123.         // English: "Current Output: "  
  124.         public const string CurrentOutput = "Current Output: ";
  125.     }
  126. }
  127. // =================================[ END OF CONFIGURATION ]=================================  
  128.  
  129. static class Status { public const int HIBERNATING = -1, IDLING = 0, UPDATING = 1, TESTING = 2, ALIGNING = 3; }
  130.  
  131. int CurrentStatus {
  132.     get { return currentStatus; }
  133.     set {
  134.         if (value == Status.HIBERNATING) Echo("Hibernating...");
  135.         else if (value == Status.IDLING) Echo("Idling...");
  136.         else if (value == Status.UPDATING) Echo("Updating...");
  137.         else if (value == Status.TESTING) Echo("Testing...");
  138.         else if (value == Status.ALIGNING) Echo("Aligning...");
  139.         currentStatus = value;
  140.     }
  141. }
  142.  
  143. float currentPower = 0.0f;
  144. int currentRotorIndex = 0;
  145. int currentDirection = 1;
  146. int currentStatus = Status.UPDATING;
  147. IMyTimerBlock timer = null;
  148. List<IMyMotorStator> currentRotors = new List<IMyMotorStator>();
  149. List<IMySolarPanel> solarPanels = new List<IMySolarPanel>();
  150. List<List<IMyMotorStator>> rotors = new List<List<IMyMotorStator>>();
  151.  
  152. void Main(string argument) {
  153.     // toggle maintenance mode
  154.     if (Configuration.Features.MaintenanceMode.Enabled && (argument + " ").Contains("maintenance ")) {
  155.         if (Me.CustomName.EndsWith(Configuration.Features.MaintenanceMode.MaintenanceSuffix)) {
  156.             Me.SetCustomName(Me.CustomName.Substring(0, Me.CustomName.Length - Configuration.Features.MaintenanceMode.MaintenanceSuffix.Length));
  157.             Echo("This programmable block is no longer in maintenance mode.");
  158.  
  159.             InitializeSolarPanels(Configuration.Features.MaintenanceMode.Reinitialize);
  160.             InitializeRotors(Configuration.Features.MaintenanceMode.Reinitialize);
  161.             InitializeTimer(Configuration.Features.MaintenanceMode.Reinitialize);
  162.         } else {
  163.             Me.SetCustomName(Me.CustomName + Configuration.Features.MaintenanceMode.MaintenanceSuffix);
  164.             Echo("This programmable block is now in maintenance mode.");
  165.             return;
  166.         }
  167.     } else {
  168.         // initialize the solar panels  
  169.         InitializeSolarPanels();
  170.  
  171.         // initialize the rotors  
  172.         InitializeRotors();
  173.  
  174.         // initialize the timer  
  175.         InitializeTimer();
  176.     }
  177.  
  178.     // maintenance mode
  179.     if (Me.CustomName.EndsWith(Configuration.Features.MaintenanceMode.MaintenanceSuffix)) {
  180.         Echo("MAINTENANCE MODE");
  181.         Utilities.Trigger(timer, Configuration.Features.MaintenanceMode.MaintenanceDelay);
  182.         return;
  183.     }
  184.  
  185.     // get current power output  
  186.     if (!Utilities.AverageMaxOutput(solarPanels, out currentPower)) throw new Exception(" Main(): failed to read average maximum power from solar panels\n\nDid you configure this script correctly?");
  187.     if (currentPower == float.NaN) throw new Exception(" Main(): failed to read average maximum power from solar panels - power output too high (>= 1 PW)");
  188.  
  189.     Echo("current average output: " + currentPower + " kW");
  190.  
  191.     // check if the energy saver feature has been enabled  
  192.     if (Configuration.Features.EnergySaver.Enabled) {
  193.         // check if the current power output is too low to make rotating effective but allow direction testing
  194.         if (currentPower <= Configuration.Features.EnergySaver.HibernatePowerOutput && CurrentStatus != Status.TESTING) {
  195.             Hibernate();
  196.             return;
  197.         }
  198.     }
  199.  
  200.     // check if the target output has been reached  
  201.     if (currentPower >= Configuration.TargetAveragePowerOutput) {
  202.         Idle();
  203.         return;
  204.     }
  205.  
  206.     // update the rotor and check which direction yields the higher power output  
  207.     if (CurrentStatus == Status.UPDATING || CurrentStatus == Status.IDLING || CurrentStatus == Status.HIBERNATING) {
  208.         currentRotors = rotors[currentRotorIndex];
  209.         UpdateNames();
  210.         Utilities.SetSpeed(currentRotors, GetRotorSpeed());
  211.         Utilities.ToggleOn(currentRotors);
  212.         CurrentStatus = Status.TESTING;
  213.         Utilities.Trigger(timer, Configuration.WorkDelay);
  214.         return;
  215.     }
  216.  
  217.     // set the rotation direction towards the higher power output  
  218.     if (CurrentStatus == Status.TESTING) {
  219.         Utilities.SetSpeed(currentRotors, GetRotorSpeed());
  220.         Utilities.ToggleOff(currentRotors);
  221.  
  222.         float oldPower;
  223.         UpdateNames(out oldPower);
  224.         if (currentPower < oldPower) {
  225.             currentDirection = -currentDirection;
  226.             Utilities.SetSpeed(currentRotors, GetRotorSpeed());
  227.         }
  228.  
  229.         CurrentStatus = Status.ALIGNING;
  230.     }
  231.  
  232.     // rotate towards the local maximum output  
  233.     if (CurrentStatus == Status.ALIGNING) {
  234.         Utilities.SetSpeed(currentRotors, GetRotorSpeed());
  235.         Utilities.ToggleOn(currentRotors);
  236.  
  237.         float oldPower;
  238.         UpdateNames(out oldPower);
  239.         if (currentPower < oldPower) {
  240.             if (rotors.Count > 1) {
  241.                 Utilities.ToggleOff(currentRotors);
  242.                 CurrentStatus = Status.UPDATING;
  243.                 currentRotorIndex = (currentRotorIndex + 1) % rotors.Count;
  244.             } else {
  245.                 currentDirection = -currentDirection;
  246.                 Utilities.SetSpeed(currentRotors, GetRotorSpeed());
  247.             }
  248.         }
  249.  
  250.         Utilities.Trigger(timer, Configuration.WorkDelay);
  251.         return;
  252.     }
  253. }
  254.  
  255. void InitializeSolarPanels(bool forced = false) {
  256.     // exit this method if the solar panels have already been initialized  
  257.     if (solarPanels.Count > 0 && !forced) return;
  258.  
  259.     if (Configuration.SolarPanelName_IsGroup) {
  260.         InitializeSolarPanelGroup();
  261.     } else {
  262.         InitializeSolarPanel();
  263.     }
  264.  
  265.     Echo("initialized solar panels");
  266. }
  267.  
  268. void InitializeSolarPanelGroup() {
  269.     // get a list of all block groups  
  270.     List<IMyTerminalBlock> group = GetBlockGroupsWithName(Configuration.SolarPanelName);
  271.      
  272.     // add all solar panels in that group  
  273.     for (int j = 0; j < group.Count; j++) {
  274.         IMySolarPanel solarPanel = group[j] as IMySolarPanel;
  275.         if (solarPanel != null) {
  276.             solarPanels.Add(solarPanel);
  277.         }
  278.     }
  279.  
  280.     if (solarPanels.Count <= 0) throw new Exception(" InitializeSolarPanelGroup(): failed to find any solar panels in the group \"" + Configuration.SolarPanelName + "\"");
  281. }
  282.  
  283. void InitializeSolarPanel() {
  284.     // get a list of all solar panels  
  285.     List<IMyTerminalBlock> panels = new List<IMyTerminalBlock>();
  286.     GridTerminalSystem.GetBlocksOfType<IMySolarPanel>(panels);
  287.  
  288.     // search all solar panels for one which starts with the provided name  
  289.     for (int i = 0; i < panels.Count; i++) {
  290.         IMySolarPanel solarPanel = panels[i] as IMySolarPanel;
  291.         if (solarPanel != null && solarPanel.CustomName.StartsWith(Configuration.SolarPanelName)) {
  292.             solarPanels.Add(solarPanel);
  293.             break;
  294.         }
  295.     }
  296.  
  297.     if (solarPanels.Count <= 0) throw new Exception(" InitializeSolarPanels(): failed to find solar panel with name \"" + Configuration.SolarPanelName + "\"");
  298. }
  299.  
  300. void InitializeRotors(bool forced = false) {
  301.     // exit this method if the rotors have already been initialized  
  302.     if (rotors.Count > 0 && !forced) return;
  303.  
  304.     for (int i = 0; i < Configuration.RotorNames.Length; i++) {
  305.         List<IMyMotorStator> axis = new List<IMyMotorStator>();
  306.         string name = Configuration.RotorNames[i];
  307.         bool isGroup = i >= Configuration.RotorNames_IsGroup.Length? false : Configuration.RotorNames_IsGroup[i];
  308.  
  309.         if (isGroup) {
  310.             InitializeRotorGroup(axis, name);
  311.         } else {
  312.             InitializeRotor(axis, name);
  313.         }
  314.  
  315.         rotors.Add(axis);
  316.     }
  317.  
  318.     Echo("initialized rotors");
  319. }
  320.  
  321. void InitializeRotorGroup(List<IMyMotorStator> axis, string groupName) {
  322.     // get a list of all block groups  
  323.     List<IMyTerminalBlock> group =GetBlockGroupsWithName(groupName);
  324.  
  325.     // add all rotors in that group  
  326.     for (int k = 0; k < group.Count; k++) {
  327.         IMyMotorStator rotor = group[k] as IMyMotorStator;
  328.         if (rotor != null) {
  329.             axis.Add(rotor);
  330.             Utilities.ToggleOff(rotor);
  331.         }
  332.     }
  333.            
  334.     if (axis.Count <= 0) throw new Exception(" InitializeRotors(): failed to find any rotors in the group \"" + groupName + "\"");
  335. }
  336.  
  337. void InitializeRotor(List<IMyMotorStator> axis, string rotorName) {
  338.     IMyMotorStator rotor = GridTerminalSystem.GetBlockWithName(rotorName) as IMyMotorStator;
  339.     if (rotor == null) {
  340.         string message = " InitializeRotor(): failed to find rotor with name \"" + rotorName + "\"";
  341.         if (rotorName.Contains(",")) {
  342.             message += "\n\nDid you want to write\nRotorNames = { [...]\"";
  343.             string[] split = rotorName.Split(',');
  344.             for (int k = 0; k < split.Length; k++) {
  345.                 message += split[k];
  346.                 if (k < split.Length - 1) message += "\", \"";
  347.             }
  348.             message += "\" [...] };\ninstead?";
  349.         }
  350.         throw new Exception(message);
  351.     }
  352.     axis.Add(rotor);
  353.     Utilities.ToggleOff(rotor);
  354. }
  355.  
  356. void InitializeTimer(bool forced = false) {
  357.     // exit this method if the timer has already been initialized  
  358.     if (timer != null && !forced) return;
  359.  
  360.     timer = GridTerminalSystem.GetBlockWithName(Configuration.TimerName) as IMyTimerBlock;
  361.     if (timer == null) throw new Exception("InitializeTimer(): failed to find timer block with name \"" + Configuration.TimerName + "\"");
  362.  
  363.     Echo("initialized timer");
  364. }
  365.  
  366. void Idle() {
  367.     for (int i = 0; i < rotors.Count; i++) {
  368.         Utilities.ToggleOff(rotors[i]);
  369.     }
  370.     UpdateNames();
  371.     CurrentStatus = Status.IDLING;
  372.     Utilities.Trigger(timer, Configuration.IdleDelay);
  373. }
  374.  
  375. void Hibernate() {
  376.     bool idle = true;
  377.     float speed = GetRotorSpeed();
  378.     for (int i = 0; i < rotors.Count; i++) {
  379.         List<IMyMotorStator> axis = rotors[i];
  380.         for (int j = 0; j < axis.Count; j++) {
  381.             IMyMotorStator rotor = axis[j];
  382.             if (Utilities.ReachedLowerLimit(rotor) || Utilities.ReachedUpperLimit(rotor)) {
  383.                 Utilities.ToggleOff(rotor);
  384.             } else {
  385.                 float distanceFromUpperLimit = rotor.UpperLimit - rotor.Angle;
  386.                 float distanceFromLowerLimit = rotor.Angle - rotor.LowerLimit;
  387.  
  388.                 Utilities.ToggleOn(rotor);
  389.                 if (distanceFromLowerLimit < distanceFromUpperLimit) Utilities.RotateTowards(rotor, Utilities.ToDegrees(rotor.UpperLimit), speed);
  390.                 else Utilities.RotateTowards(rotor, Utilities.ToDegrees(rotor.LowerLimit), speed);
  391.  
  392.                 idle = false;
  393.             }
  394.         }
  395.     }
  396.     UpdateNames();
  397.     CurrentStatus = Status.HIBERNATING;
  398.     Utilities.Trigger(timer, idle ? Configuration.HibernationIdleDelay : Configuration.HibernationWorkDelay);
  399. }
  400.  
  401. void UpdateNames() {
  402.     float __ignored;
  403.     UpdateNames(out __ignored);
  404. }
  405.  
  406. void UpdateNames(out float oldPower) {
  407.     oldPower = 0.0f;
  408.     for (int i = 0; i < solarPanels.Count; i++) {
  409.         IMySolarPanel panel = solarPanels[i];
  410.  
  411.         float panelOutput;
  412.         if (!Utilities.MaxOutput(panel, out panelOutput)) continue;
  413.  
  414.         string[] split = panel.CustomName.Split('~');
  415.         if (split.Length <= 1) {
  416.             panel.SetCustomName(panel.CustomName + "~" + panelOutput);
  417.             continue;
  418.         }
  419.  
  420.         float panelOldOutput;
  421.         float.TryParse(split[split.Length - 1], out panelOldOutput);
  422.  
  423.         string name = "";
  424.         for (int k = 0; k < split.Length - 1; k++) {
  425.             name += split[k];
  426.         }
  427.         name += "~" + panelOutput;
  428.         panel.SetCustomName(name);
  429.  
  430.         if (oldPower == 0) oldPower = panelOldOutput;
  431.         else oldPower = (oldPower + panelOldOutput) / 2;
  432.     }
  433. }
  434.  
  435. float GetRotorSpeed() {
  436.     float speed = Configuration.RotorSpeed;
  437.     if (Configuration.Features.EnergySaver.Enabled && currentPower <= Configuration.Features.EnergySaver.PanicPowerOutput) {
  438.         speed *= Configuration.Features.EnergySaver.PanicSpeedMultiplier;
  439.         Echo("Panicking...");
  440.     }
  441.     return speed * currentDirection;
  442. }
  443.  
  444. static class Utilities {
  445.     public static void ToggleOn(IMyFunctionalBlock block) {
  446.         block.GetActionWithName("OnOff_On").Apply(block);
  447.     }
  448.  
  449.     public static void ToggleOn(List<IMyMotorStator> blocks) {
  450.         for (int i = 0; i < blocks.Count; i++) {
  451.             ToggleOn(blocks[i]);
  452.         }
  453.     }
  454.  
  455.     public static void ToggleOff(IMyFunctionalBlock block) {
  456.         block.GetActionWithName("OnOff_Off").Apply(block);
  457.     }
  458.  
  459.     public static void ToggleOff(List<IMyMotorStator> blocks) {
  460.         for (int i = 0; i < blocks.Count; i++) {
  461.             ToggleOff(blocks[i]);
  462.         }
  463.     }
  464.  
  465.     public static void Trigger(IMyTimerBlock timer, float delay) {
  466.         timer.SetValue("TriggerDelay", delay);
  467.         timer.GetActionWithName("Start").Apply(timer);
  468.     }
  469.  
  470.     public static void SetSpeed(IMyMotorStator rotor, float speed) {
  471.         if (rotor.CustomName.EndsWith(Configuration.InvertedRotorSuffix)) speed = -speed;
  472.         rotor.SetValue("Velocity", speed);
  473.     }
  474.  
  475.     public static void SetSpeed(List<IMyMotorStator> rotors, float speed) {
  476.         for (int i = 0; i < rotors.Count; i++) {
  477.             SetSpeed(rotors[i], speed);
  478.         }
  479.     }
  480.  
  481.     public static void RotateTowards(IMyMotorStator rotor, float target, float speed) {
  482.         float angle = ToDegrees(rotor.Angle);
  483.         if (RotationEquals(angle, target)) SetSpeed(rotor, 0);
  484.         float posrot = (target + 360 - angle) % 360;
  485.         float negrot = (angle + 360 - target) % 360;
  486.         if (posrot < negrot) {
  487.             if (HasUpperLimit(rotor) && rotor.UpperLimit <= target) SetSpeed(rotor, -speed);
  488.             else SetSpeed(rotor, speed);
  489.         } else {
  490.             if (HasLowerLimit(rotor) && rotor.LowerLimit >= target) SetSpeed(rotor, speed);
  491.             else SetSpeed(rotor, -speed);
  492.         }
  493.     }
  494.  
  495.     public static bool RotationEquals(float a, float b) {
  496.         return Math.Abs(a - b) <= Configuration.MaxAngleDeviation;
  497.     }
  498.  
  499.     public static bool HasLowerLimit(IMyMotorStator rotor) {
  500.         return !float.IsInfinity(rotor.LowerLimit);
  501.     }
  502.  
  503.     public static bool HasUpperLimit(IMyMotorStator rotor) {
  504.         return !float.IsInfinity(rotor.UpperLimit);
  505.     }
  506.  
  507.     public static bool ReachedLowerLimit(IMyMotorStator rotor) {
  508.         return !HasLowerLimit(rotor) || (HasLowerLimit(rotor) && RotationEquals(ToDegrees(rotor.Angle), ToDegrees(rotor.LowerLimit)));
  509.     }
  510.  
  511.     public static bool ReachedUpperLimit(IMyMotorStator rotor) {
  512.         return !HasUpperLimit(rotor) || (HasUpperLimit(rotor) && RotationEquals(ToDegrees(rotor.Angle), ToDegrees(rotor.UpperLimit)));
  513.     }
  514.  
  515.     public static float ToDegrees(float radians) {
  516.         return (float)(radians / Math.PI) * 180;
  517.     }
  518.  
  519.     public static bool MaxOutput(IMySolarPanel panel, out float power) {
  520.         power = 0.0f;
  521.         int start = panel.DetailedInfo.IndexOf(Configuration.Localization.MaxOutput);
  522.         int end = panel.DetailedInfo.IndexOf(Configuration.Localization.CurrentOutput);
  523.         if (start < 0 || end < 0 || end < start) return false;
  524.         start += Configuration.Localization.MaxOutput.Length;
  525.  
  526.         string maxOutput = panel.DetailedInfo.Substring(start, end - start);
  527.         if (float.TryParse(System.Text.RegularExpressions.Regex.Replace(maxOutput, @"[^0-9.]", ""), out power)) {
  528.             float factor = 0.0f;
  529.             if (maxOutput.Contains(" W")) factor = 0.001f;
  530.             else if (maxOutput.Contains(" kW")) factor = 1.0f;
  531.             else if (maxOutput.Contains(" MW")) factor = 1000.0f;
  532.             else if (maxOutput.Contains(" GW")) factor = 1000000.0f;
  533.             else if (maxOutput.Contains(" TW")) factor = 1000000000.0f;
  534.             else {
  535.                 power = float.NaN;
  536.                 return true;
  537.             }
  538.  
  539.             power *= factor;
  540.             return true;
  541.         }
  542.  
  543.         return false;
  544.     }
  545.  
  546.     public static bool AverageMaxOutput(List<IMySolarPanel> panels, out float power) {
  547.         power = 0.0f;
  548.         for (int i = 0; i < panels.Count; i++) {
  549.             float maxOutput;
  550.             IMySolarPanel panel = panels[i];
  551.             if (!MaxOutput(panel, out maxOutput)) return false;
  552.  
  553.             if (power == 0) power = maxOutput;
  554.             else power = (power + maxOutput) / 2;
  555.         }
  556.         return true;
  557.     }
  558. }
  559.  
  560. List<IMyTerminalBlock> GetBlockGroupsWithName(string strGroupName) {  
  561.     List<IMyBlockGroup> allGroups = new List<IMyBlockGroup>();
  562.     GridTerminalSystem.GetBlockGroups(allGroups);  
  563.      
  564.     var blockGroup = allGroups.Find(g => g.Name.Equals(strGroupName));
  565.     List<IMyTerminalBlock> blocks = new List<IMyTerminalBlock>();
  566.  
  567.     if (blockGroup != null){
  568.         blockGroup.GetBlocks(blocks);
  569.         return blocks;
  570.     }
  571.     throw new Exception(" " + strGroupName + " Not Found");        
  572.     return null;
  573. }
Advertisement
Add Comment
Please, Sign In to add comment