Advertisement
Guest User

Isy's Solar Alignment

a guest
May 25th, 2019
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 46.29 KB | None | 0 0
  1.  
  2. // Isy's Solar Alignment Script
  3. // ============================
  4. // Version: 4.2.1
  5. // Date: 2019-04-08
  6.  
  7. // =======================================================================================
  8. // --- Configuration ---
  9. // =======================================================================================
  10.  
  11. // --- Essential Configuration ---
  12. // =======================================================================================
  13.  
  14. // Name of the group with all the solar related rotors (not needed in gyro mode)
  15. string rotorGroupName = "Solar Rotors";
  16.  
  17. // By enabling gyro mode, the script will no longer use rotors but all gyroscopes on the grid instead.
  18. // This mode only makes sense when used on a SHIP in SPACE. Gyro mode deactivates the following
  19. // features: night mode, rotate to sunrise, time calculation and triggering external timer blocks.
  20. bool useGyroMode = false;
  21.  
  22. // Name of the reference group for gyro mode. Put your main cockpit, flight seat or remote control in this group!
  23. string referenceGroupName = "Solar Reference";
  24.  
  25.  
  26. // --- Rotate to sunrise ---
  27. // =======================================================================================
  28.  
  29. // Rotate the panels towards the sunrise during the night? (Possible values: true | false, default: true)
  30. // The angle is figured out automatically based on the first lock of the day.
  31. // If you want to set the angles yourself, set manualAngle to true and adjust the angles to your likings.
  32. bool rotateToSunrise = true;
  33. bool manualAngle = false;
  34. int manualAngleVertical = 0;
  35. int manualAngleHorizontal = 0;
  36.  
  37.  
  38. // --- Power fallback ---
  39. // =======================================================================================
  40.  
  41. // With this option, you can enable your reactors and hydrogen engines as a safety fallback, if not enough power is available
  42. // to power all your machines or if the battery charge gets low. By default, all reactors and hydrogen engines
  43. // on the same grid will be used. If you only want to use specific ones, put their names or group in the list.
  44. // Example: string[] fallbackDevices = { "Small Reactor 1", "Base reactor group", "Hydrogen Engine" };
  45. bool useReactorFallback = false;
  46. bool useHydrogenEngineFallback = false;
  47. string[] fallbackDevices = { };
  48.  
  49. // Activation order
  50. // By default, the hydrogen engine will be turned on first and the reactors after that if still not enough power is available.
  51. // Set this value to false, and the reactors will be used first.
  52. bool activateHydrogenEngineFirst = true;
  53.  
  54. // Activation on low battery?
  55. // The fallback devices will be active until 'turnOffAtPercent' of the max battery charge after it was turned on at 'turnOnAtPercent'.
  56. bool activateOnLowBattery = true;
  57. double turnOnAtPercent = 10;
  58. double turnOffAtPercent = 15;
  59.  
  60. // Activate on overload?
  61. // If the combined output of batteries, solar panels and wind turbines is more than 'overloadPercentage' of their max output, the fallback devices will be turned on.
  62. bool activateOnOverload = true;
  63. double overloadPercentage = 90;
  64.  
  65.  
  66. // --- Base Light Management ---
  67. // =======================================================================================
  68.  
  69. // Enable base light management? (Possible values: true | false, default: false)
  70. // Lights will be turned on/off based on daytime.
  71. bool baseLightManagement = false;
  72.  
  73. // Simple mode: toggle lights based on max. solar output (percentage). Time based toggle will be deactivated.
  74. bool simpleMode = false;
  75. int simpleThreshold = 50;
  76.  
  77. // Define the times when your lights should be turned on or off. If simple mode is active, this does nothing.
  78. int lightOffHour = 8;
  79. int lightOnHour = 18;
  80.  
  81. // To only toggle specific lights, declare groups for them.
  82. // Example: string[] baseLightGroups = { "Interior Lights", "Spotlights", "Hangar Lights" };
  83. string[] baseLightGroups = { };
  84.  
  85.  
  86. // --- LCD panels ---
  87. // =======================================================================================
  88.  
  89. // Add the following keyword to any LCD panel to show the script's informations.
  90. // Edit the LCD's custom data to change the information that is shown there.
  91. // When using the keyword on corner LCDs, put one of these keywords in their custom data:
  92. // time, battery, oxygen
  93. string lcdKeyword = "!SAS";
  94.  
  95.  
  96. // --- Terminal statistics ---
  97. // =======================================================================================
  98.  
  99. // The script can display informations in the names of the used blocks. The shown information is a percentage of
  100. // the current efficiency (solar panels and oxygen farms) or the fill level (batteries and tanks).
  101. // You can enable or disable single statistics or disable all using the master switch below.
  102. bool enableTerminalStatistics = true;
  103.  
  104. bool showSolarStats = true;
  105. bool showWindTurbineStats = true;
  106. bool showBatteryStats = true;
  107. bool showOxygenFarmStats = true;
  108. bool showOxygenTankStats = true;
  109.  
  110.  
  111. // --- External timer blocks ---
  112. // =======================================================================================
  113.  
  114. // Trigger external timer blocks at specific events? (action "Start" will be applied which takes the delay into account)
  115. // Events can be: "sunrise", "sunset", a time like "15:00" or a number for every X seconds
  116. // Every event needs a timer block name in the exact same order as the events.
  117. // Calling the same timer block with multiple events requires it's name multiple times in the timers list!
  118. // Example:
  119. // string[] events = { "sunrise", "sunset", "15:00", "30" };
  120. // string[] timers = { "Timer 1", "Timer 1", "Timer 2", "Timer 3" };
  121. // This will trigger "Timer 1" at sunrise and sunset, "Timer 2" at 15:00 and "Timer 3" every 30 seconds.
  122. bool triggerTimerBlock = false;
  123. string[] events = { };
  124. string[] timers = { };
  125.  
  126.  
  127. // --- Settings for enthusiasts ---
  128. // =======================================================================================
  129.  
  130. // Change percentage of the last locked output where the script should realign for a new best output (default: 2, gyro: 5)
  131. double realginPercentageRotor = 2;
  132. double realignPercentageGyro = 5;
  133.  
  134. // Percentage of the max detected output where the script starts night mode (default: 10)
  135. double nightPercentage = 10;
  136.  
  137. // Percentage of the max detected output where the script detects night for time calculation (default: 50)
  138. double nightTimePercentage = 50;
  139.  
  140. // Rotor speeds (speeds are automatically scaled between these values based on the output)
  141. const float rotorMinSpeed = 0.1f;
  142. const float rotorMaxSpeed = 1.0f;
  143.  
  144. // Rotor options
  145. float rotorTorqueLarge = 33600000f;
  146. float rotorTorqueSmall = 448000f;
  147. bool setInertiaTensor = true;
  148. bool setRotorLockWhenStopped = false;
  149.  
  150. // Min gyro RPM, max gyro RPM and gyro power for gyro mode
  151. const double minGyroRPM = 0.1;
  152. const double maxGyroRPM = 1;
  153. const float gyroPower = 1f;
  154.  
  155. // Debugging
  156. string debugLcd = "LCD Solar Alignment Debugging";
  157. bool showPerformance = true;
  158. bool showBlockCounts = true;
  159.  
  160.  
  161. // =======================================================================================
  162. // --- End of Configuration ---
  163. // Don't change anything beyond this point!
  164. // =======================================================================================
  165.  
  166.  
  167. double ǀ=0;double ǁ=0;double ǂ=0;double ǃ=0;double DŽ=0;double ƿ=0;List<IMyMotorStator>Ʈ=new List<IMyMotorStator>();List<
  168. IMyMotorStator>Ƶ=new List<IMyMotorStator>();List<IMyMotorStator>Ư=new List<IMyMotorStator>();List<IMyGyro>ư=new List<IMyGyro>();List<
  169. IMyTextPanel>Ʊ=new List<IMyTextPanel>();List<IMyTextPanel>Ʋ=new List<IMyTextPanel>();List<IMyInteriorLight>Ƴ=new List<
  170. IMyInteriorLight>();List<IMyReflectorLight>ƴ=new List<IMyReflectorLight>();List<IMyPowerProducer>ƶ=new List<IMyPowerProducer>();List<
  171. IMySolarPanel>ƽ=new List<IMySolarPanel>();int Ʒ=0;bool Ƹ=false;bool ƹ=false;int ƺ=30;int ƻ=90;bool Ƽ=true;List<string>ƾ=new List<
  172. string>{"output=0","outputLast=0","outputLocked=0","outputMax=0","outputMaxAngle=0","outputMaxDayBefore=0","outputBestPanel=0"
  173. ,"direction=1","directionChanged=0","directionTimer=0","allowRotation=1","rotationDone=1","timeSinceRotation=0",
  174. "firstLockOfDay=0","sunriseAngle=0"};List<IMyShipController>ƭ=new List<IMyShipController>();double Ƭ=0;double Ŵ=0;double ŷ=0;double Ÿ=1;
  175. double Ź=1;double ź=1;bool Ż=false;bool ż=false;bool Ž=false;double ž=0;double ſ=0;double ƀ=0;bool Ɓ=true;bool Ƃ=true;bool ƃ=
  176. true;double Ƅ=0;double ƅ=0;double Ƈ=0;List<IMyBatteryBlock>ŵ=new List<IMyBatteryBlock>();double Ť=0;double ū=0;double ť=0;
  177. double Ŧ=0;double ŧ=0;double Ũ=0;List<IMyOxygenFarm>ũ=new List<IMyOxygenFarm>();List<IMyGasTank>Ū=new List<IMyGasTank>();
  178. double Ŭ=0;double ų=0;double ŭ=0;int Ů=0;List<IMyPowerProducer>ů=new List<IMyPowerProducer>();double Ű=0;double ű=0;string Ų=
  179. "0 kW";string Ɔ="0 kW";string ƈ="0 kW";string ƪ="0 kW";string ƚ="0 kW";string ƛ="0 kW";string Ɯ="0 kW";string Ɲ="0 kW";string
  180. ƞ="0 kW";string Ɵ="0 kW";string Ơ="0 kW";string ơ="0 L";string Ƣ="0 L";string ƣ="Checking setup...";string Ƥ;string ƥ;
  181. string[]Ʀ={"/","-","\\","|"};int Ƨ=0;int ƨ=0;int Ʃ=270;const int ƫ=7200;int ƙ=ƫ;const int Ɖ=ƫ/2;int Ɛ=Ɖ;List<string>Ɗ=new List
  182. <string>{"showCurrentOperation=true","showSolarStats=true","showTurbineStats=true","showBatteryStats=true",
  183. "showOxygenStats=true","showLocationTime=true"};bool Ƌ=false;bool ƌ=false;bool ƍ=false;int Ǝ=0;int Ə=0;double Ƒ=0;string Ƙ="";string ƒ,Ɠ;int Ɣ
  184. =0;int ƕ=0;string Ɩ="align";int Ɨ=3;bool Ŷ=false;string Dž="both";bool Ǐ=false;double Ǥ=0;double ǥ=0;int Ǧ=0;int ǧ=15;int
  185. Ǩ=1;bool ǩ=true;bool Ǫ=true;bool ǫ=true;string[]Ǭ={"","Get Output","Time Calculation","Rotation Logic","Reactor Fallback"
  186. };Program(){IJ();realginPercentageRotor=(realginPercentageRotor%100)/100;realignPercentageGyro=(realignPercentageGyro%100)
  187. /100;nightPercentage=(nightPercentage%100)/100;nightTimePercentage=(nightTimePercentage%100)/100;Runtime.UpdateFrequency=
  188. UpdateFrequency.Update1;}void Main(string ǭ){try{ŗ("",true);if(ǭ!=""){Ɩ=ǭ.ToLower();Ǩ=3;}if(ǩ){Ǯ();Ò(false);Į();ǩ=false;}if(Ǧ<ǧ){Ǧ++;
  189. return;}else{if(Ǫ){Ǯ();Ǫ=false;return;}if(ǫ){K();Ç();Ê();ǫ=false;return;}Ƨ=Ƨ>=3?0:Ƨ+1;Ǧ=0;ǫ=true;Ǫ=true;}if(Ǩ==1&&ƒ==null){dž()
  190. ;}if(Ǩ==2&&!useGyroMode&&ƒ==null){Ë();if(baseLightManagement)ĺ();if(triggerTimerBlock)Ŀ();}if(Ǩ==3&&ƒ==null){if(!DZ(Ɩ)){if
  191. (useGyroMode){lj();}else{Ǚ();}}}if(Ǩ==4&&ƒ==null){if(useReactorFallback||useHydrogenEngineFallback)Â();foreach(var d in Ʈ)
  192. {double í=Ƿ(d,"output");ǐ(d,"outputLast",í);}ǃ=ǂ;Save();}Echo(e(true));ŗ(Ǭ[Ǩ]);if(Ǩ>=4){Ǩ=1;if(Ɣ==0)ƒ=null;if(ƕ==0)Ɠ=null
  193. ;Ɣ=0;ƕ=0;ƥ=Ƥ;Ƥ="";}else{Ǩ++;}}catch(Exception e){Ò();string D=e+" \n\n";D+=
  194. "The error occured while executing the following script step:\n"+Ǭ[Ǩ]+" (ID: "+Ǩ+")";K(D);throw new Exception(D);}}void Ǯ(){if(Ā==null){ā(Me.CubeGrid);}GridTerminalSystem.
  195. GetBlocksOfType<IMyTextPanel>(Ʊ,ǣ=>ǣ.CustomName.Contains(lcdKeyword)&&!ǣ.BlockDefinition.SubtypeId.Contains("Corner"));
  196. GridTerminalSystem.GetBlocksOfType<IMyTextPanel>(Ʋ,ǣ=>ǣ.CustomName.Contains(lcdKeyword)&&ǣ.BlockDefinition.SubtypeId.Contains("Corner"));
  197. if(!useGyroMode){var ǚ=GridTerminalSystem.GetBlockGroupWithName(rotorGroupName);if(ǚ!=null){ǚ.GetBlocksOfType<
  198. IMyMotorStator>(Ʈ);if(Ʈ.Count==0){ń("There are no rotors in the rotor group:\n'"+rotorGroupName+"'");return;}}else{ń(
  199. "Rotor group not found:\n'"+rotorGroupName+"'");return;}HashSet<IMyCubeGrid>Ǟ=new HashSet<IMyCubeGrid>();foreach(var d in Ʈ){if(!d.IsFunctional)ņ(
  200. "'"+d.CustomName+"' is broken!\nRepair it to use it for aligning!");if(!d.Enabled)ņ("'"+d.CustomName+
  201. "' is turned off!\nTurn it on to use it for aligning!");if(!d.IsAttached)ņ("'"+d.CustomName+"' has no rotor head!\nAdd one to use it for aligning!");Ǟ.Add(d.CubeGrid);if(d.
  202. CubeGrid.GridSize==0.5){d.Torque=rotorTorqueSmall;}else{d.Torque=rotorTorqueLarge;}if(d.GetOwnerFactionTag()!=Me.
  203. GetOwnerFactionTag()){ņ("'"+d.CustomName+"' has a different owner / faction!\nAll blocks should have the same owner / faction!");}}Ƶ.Clear
  204. ();Ư.Clear();foreach(var d in Ʈ){if(Ǟ.Contains(d.TopGrid)){Ƶ.Add(d);}else{Ư.Add(d);if(d.CubeGrid!=Ā&&setInertiaTensor){
  205. try{d.SetValueBool("ShareInertiaTensor",true);}catch(Exception){}}}}List<IMyMotorStator>Ǜ=new List<IMyMotorStator>();Ǜ.
  206. AddRange(Ư);Ư.Clear();bool ǜ;foreach(var ǝ in Ǜ){ǜ=true;foreach(var d in Ư){if(d.TopGrid==ǝ.TopGrid){ǝ.RotorLock=false;ǝ.
  207. TargetVelocityRPM=0f;ǝ.Torque=0f;ǝ.BrakingTorque=0f;ǜ=false;break;}}if(ǜ)Ư.Add(ǝ);}ƽ.Clear();ũ.Clear();foreach(var Þ in Ư){ǀ=0;ǁ=0;Ĥ(Þ.
  208. TopGrid,true);var Ǣ=new List<IMySolarPanel>();GridTerminalSystem.GetBlocksOfType<IMySolarPanel>(Ǣ,ǟ=>ī.Contains(ǟ.CubeGrid)&&ǟ.
  209. IsWorking);var Ǡ=new List<IMyOxygenFarm>();GridTerminalSystem.GetBlocksOfType<IMyOxygenFarm>(Ǡ,ǡ=>ī.Contains(ǡ.CubeGrid)&&ǡ.
  210. IsWorking);foreach(var Ĵ in Ǣ){ƽ.Add(Ĵ);ǀ+=Ĵ.MaxOutput;if(Ĵ.MaxOutput>ǁ)ǁ=Ĵ.MaxOutput;}foreach(var İ in Ǡ){ũ.Add(İ);ǀ+=İ.
  211. GetOutput();if(İ.GetOutput()>ǁ)ǁ=İ.GetOutput();}if(Ǣ.Count==0&&Ǡ.Count==0){ņ("'"+Þ.CustomName+
  212. "' can't see the sun!\nAdd a solar panel or oxygen farm to it!");}ǐ(Þ,"output",ǀ);ǐ(Þ,"outputBestPanel",ǁ);if(ǀ>Ƿ(Þ,"outputMax")){ǐ(Þ,"outputMax",ǀ);ǐ(Þ,"outputMaxAngle",c(Þ));}}
  213. foreach(var Ü in Ƶ){double è=0;ǁ=double.MaxValue;foreach(var Þ in Ư){if(Þ.CubeGrid==Ü.TopGrid){è+=Ƿ(Þ,"output");if(Ƿ(Þ,
  214. "outputBestPanel")<ǁ)ǁ=Ƿ(Þ,"outputBestPanel");}}ǐ(Ü,"output",è);ǐ(Ü,"outputBestPanel",ǁ);if(è>Ƿ(Ü,"outputMax")){ǐ(Ü,"outputMax",è);ǐ(Ü,
  215. "outputMaxAngle",c(Ü));}}}Ĥ(Ā,true);if(useGyroMode){if(Me.CubeGrid.IsStatic){ń(
  216. "The grid is stationary!\nConvert it to a ship in the Info tab!");return;}var Ȁ=GridTerminalSystem.GetBlockGroupWithName(referenceGroupName);if(Ȁ!=null){Ȁ.GetBlocksOfType<
  217. IMyShipController>(ƭ);if(ƭ.Count==0){ń("There are no cockpits, flight seats or remote controls in the reference group:\n'"+
  218. referenceGroupName+"'");return;}}else{ń(
  219. "Reference group not found!\nPut your main cockpit, flight seat or remote control in a group called '"+referenceGroupName+"'!");return;}GridTerminalSystem.GetBlocksOfType<IMyGyro>(ư,Ǻ=>Ǻ.CubeGrid==Ā&&Ǻ.IsWorking);if(ư.
  220. Count==0){ń("No gyroscopes found!\nAre they enabled and completely built?");return;}GridTerminalSystem.GetBlocksOfType<
  221. IMySolarPanel>(ƽ,ǟ=>ī.Contains(ǟ.CubeGrid)&&ǟ.IsWorking);GridTerminalSystem.GetBlocksOfType<IMyOxygenFarm>(ũ,ǡ=>ī.Contains(ǡ.CubeGrid
  222. )&&ǡ.IsWorking);}if(Ʒ!=ƽ.Count||Ů!=ũ.Count){foreach(var d in Ʈ){ǐ(d,"outputMax",0);}DŽ=0;Ʒ=ƽ.Count;Ů=ũ.Count;ń(
  223. "Amount of solar panels or oxygen farms changed!\nRestarting..");return;}if(ƽ.Count==0&&ũ.Count==0){ń("No solar panels or oxygen farms found!\nHow should I see the sun now?");return;}
  224. ŵ.Clear();GridTerminalSystem.GetBlocksOfType<IMyBatteryBlock>(ŵ,ǻ=>ī.Contains(ǻ.CubeGrid)&&ǻ.IsWorking);if(ŵ.Count==0){ņ(
  225. "No batteries found!\nDon't you want to store your Power?");}ů.Clear();GridTerminalSystem.GetBlocksOfType<IMyPowerProducer>(ů,Ǽ=>Ǽ.BlockDefinition.TypeIdString.Contains(
  226. "WindTurbine")&&ī.Contains(Ǽ.CubeGrid)&&Ǽ.IsWorking);Ū.Clear();GridTerminalSystem.GetBlocksOfType<IMyGasTank>(Ū,Ǽ=>!Ǽ.BlockDefinition
  227. .SubtypeId.Contains("Hydrogen")&&ī.Contains(Ǽ.CubeGrid)&&Ǽ.IsWorking);if(useReactorFallback||useHydrogenEngineFallback){ƶ
  228. .Clear();foreach(var ł in fallbackDevices){var ǽ=GridTerminalSystem.GetBlockGroupWithName(ł);if(ǽ!=null){var Ǿ=new List<
  229. IMyPowerProducer>();ǽ.GetBlocksOfType<IMyPowerProducer>(Ǿ,Ǻ=>Ǻ.BlockDefinition.TypeIdString.Contains("Reactor")||Ǻ.BlockDefinition.
  230. TypeIdString.Contains("HydrogenEngine"));ƶ.AddRange(Ǿ);}else{IMyPowerProducer ǿ=GridTerminalSystem.GetBlockWithName(ł)as
  231. IMyPowerProducer;if(ǿ!=null){ƶ.Add(ǿ);}else{ņ("Power fallback device not found:\n'"+ł+"'");}}}if(ƶ.Count==0){GridTerminalSystem.
  232. GetBlocksOfType<IMyPowerProducer>(ƶ,Ǻ=>(Ǻ.BlockDefinition.TypeIdString.Contains("Reactor")||Ǻ.BlockDefinition.TypeIdString.Contains(
  233. "HydrogenEngine"))&&ī.Contains(Ǻ.CubeGrid)&&Ǻ.IsFunctional);}if(!useReactorFallback)ƶ.RemoveAll(Ǻ=>Ǻ.BlockDefinition.TypeIdString.
  234. Contains("Reactor"));if(!useHydrogenEngineFallback)ƶ.RemoveAll(Ǻ=>Ǻ.BlockDefinition.TypeIdString.Contains("HydrogenEngine"));Ǝ=ƶ
  235. .Count(Ǻ=>Ǻ.BlockDefinition.TypeIdString.Contains("Reactor"));Ə=ƶ.Count(Ǻ=>Ǻ.BlockDefinition.TypeIdString.Contains(
  236. "HydrogenEngine"));}if(baseLightManagement){Ƴ.Clear();ƴ.Clear();if(baseLightGroups.Length>0){var ǹ=new List<IMyInteriorLight>();var ǯ=
  237. new List<IMyReflectorLight>();foreach(var Ǵ in baseLightGroups){var ǰ=GridTerminalSystem.GetBlockGroupWithName(Ǵ);if(ǰ!=
  238. null){ǰ.GetBlocksOfType<IMyInteriorLight>(ǹ);Ƴ.AddRange(ǹ);ǰ.GetBlocksOfType<IMyReflectorLight>(ǯ);ƴ.AddRange(ǯ);}else{ņ(
  239. "Light group not found:\n'"+Ǵ+"'");}}}else{GridTerminalSystem.GetBlocksOfType<IMyInteriorLight>(Ƴ,ǣ=>ī.Contains(ǣ.CubeGrid));GridTerminalSystem.
  240. GetBlocksOfType<IMyReflectorLight>(ƴ,ǣ=>ī.Contains(ǣ.CubeGrid));}}}bool DZ(string Dz){bool dz=true;if(Dz=="pause"){Ò();if(Ŷ){Ɩ="align";Ŷ=
  241. false;return false;}else{Ɩ="paused";Ŷ=true;}ƣ="Automatic alignment paused.\n";ƣ+="Run 'pause' again to continue..";}else if(Dz
  242. =="paused"){ƣ="Automatic alignment paused.\n";ƣ+="Run 'pause' again to continue..";}else if(Dz=="realign"&&!useGyroMode){õ(
  243. );ƣ="Forced realign by user.\n";ƣ+="Searching highest output for "+ƻ+" more seconds.";if(ƻ==0){Ɩ="";ƻ=90;}else{ƻ-=1;}}
  244. else if(Dz=="reset"&&!useGyroMode){ƨ=0;Ʃ=270;Ɛ=Ɖ;ƙ=ƫ;ƣ="Calculated time resetted.\n";ƣ+="Continuing in "+Ɨ+" seconds.";if(Ɨ==
  245. 0){Ɩ="";Ɨ=3;}else{Ɨ-=1;}}else if(Dz.Contains("rotate")&&!useGyroMode){String[]ǵ=Dz.Split(' ');bool Ǹ=false;Dž="both";Ǐ=false
  246. ;if(ǵ[0].Contains("pause"))Ǐ=true;if(ǵ.Length==2){if(ǵ[1].Contains("h")){Ǹ=Double.TryParse(ǵ[1].Replace("h",""),out Ǥ);Dž=
  247. "horizontalOnly";}else if(ǵ[1].Contains("v")){Ǹ=Double.TryParse(ǵ[1].Replace("v",""),out ǥ);Dž="verticalOnly";}if(Ǹ){ƣ=
  248. "Checking rotation parameters...";Ɩ="rotNormal";}else{Ò();ņ("Wrong format!\n\nShould be (e.g. 90 degrees):\nrotate h90 OR\nrotate v90");}}else if(ǵ.
  249. Length==3){string Ƕ="rotNormal";if(ǵ[1].Contains("v")){Ǹ=Double.TryParse(ǵ[1].Replace("v",""),out ǥ);if(Ǹ)Ǹ=Double.TryParse(ǵ[
  250. 2].Replace("h",""),out Ǥ);Ƕ="rotVH1";}else{Ǹ=Double.TryParse(ǵ[1].Replace("h",""),out Ǥ);if(Ǹ)Ǹ=Double.TryParse(ǵ[2].
  251. Replace("v",""),out ǥ);}if(Ǹ){ƣ="Checking rotation parameters...";Ɩ=Ƕ;}else{Ò();ņ(
  252. "Wrong format!\n\nShould be (e.g. 90 degrees):\nrotate h90 v90 OR\nrotate v90 h90");}}else{Ò();ņ("Not enough parameters!\n\nShould be 2 or 3:\nrotate h90 OR\nrotate h90 v90");}}else if(Dz=="rotNormal"){ƣ
  253. ="Rotating to user defined values...";bool Î=ö(Dž,Ǥ,ǥ);if(Î&&Ǐ){Ɩ="paused";}else if(Î&&!Ǐ){Ɩ="resume";}}else if(Dz==
  254. "rotVH1"){ƣ="Rotating to user defined values...";bool Î=ö("verticalOnly",Ǥ,ǥ);if(Î)Ɩ="rotVH2";}else if(Dz=="rotVH2"){ƣ=
  255. "Rotating to user defined values...";bool Î=ö("horizontalOnly",Ǥ,ǥ);if(Î&&Ǐ){Ɩ="paused";}else if(Î&&!Ǐ){Ɩ="resume";}}else{dz=false;}return dz;}double Ƿ(
  256. IMyTerminalBlock U,string Ǒ){Ǔ(U);var È=U.CustomData.Split('\n').ToList();int ǒ=È.FindIndex(ĸ=>ĸ.Contains(Ǒ+"="));if(ǒ>-1){return
  257. Convert.ToDouble(È[ǒ].Replace(Ǒ+"=",""));}return 0;}void ǐ(IMyTerminalBlock U,string Ǒ,double Û){Ǔ(U);var È=U.CustomData.Split(
  258. '\n').ToList();int ǒ=È.FindIndex(ĸ=>ĸ.Contains(Ǒ+"="));if(ǒ>-1){È[ǒ]=Ǒ+"="+Û;U.CustomData=String.Join("\n",È);}}void Ǔ(
  259. IMyTerminalBlock U){var È=U.CustomData.Split('\n').ToList();if(È.Count!=ƾ.Count){U.CustomData=String.Join("\n",ƾ);}}bool ǔ(IMyTextPanel
  260. M,string Ǒ){ǎ(M);var È=M.CustomData.Split('\n').ToList();int ǒ=È.FindIndex(ĸ=>ĸ.Contains(Ǒ+"="));if(ǒ>-1){try{return
  261. Convert.ToBoolean(È[ǒ].Replace(Ǒ+"=",""));}catch{return true;}}return true;}void ǎ(IMyTextPanel M){var È=M.CustomData.Split(
  262. '\n').ToList();if(È.Count!=Ɗ.Count){M.CustomData=String.Join("\n",Ɗ);M.FontSize=0.5f;}}void dž(){ǂ=0;ƿ=0;foreach(var Ĵ in ƽ){
  263. ǂ+=Ĵ.MaxOutput;ƿ+=Ĵ.CurrentOutput;if(showSolarStats&&enableTerminalStatistics){double LJ=0;double.TryParse(Ĵ.CustomData,
  264. out LJ);if(LJ<Ĵ.MaxOutput){LJ=Ĵ.MaxOutput;Ĵ.CustomData=LJ.ToString();}T(Ĵ,true,"",Ĵ.MaxOutput,LJ);}}foreach(var İ in ũ){ǂ+=İ.
  265. GetOutput()/1000000;}if(ǂ>DŽ){DŽ=ǂ;}Ų=ǂ.ğ();ƈ=ƿ.ğ();Ɔ=DŽ.ğ();Ť=0;ū=0;ť=0;Ŧ=0;ŧ=0;Ũ=0;foreach(var į in ŵ){Ť+=į.CurrentInput;ū+=į.
  266. MaxInput;ť+=į.CurrentOutput;Ŧ+=į.MaxOutput;ŧ+=į.CurrentStoredPower;Ũ+=į.MaxStoredPower;if(showBatteryStats&&
  267. enableTerminalStatistics){string W="";if(į.CurrentStoredPower<į.MaxStoredPower*0.99){W="Draining";if(į.CurrentInput>į.CurrentOutput)W=
  268. "Recharging";}T(į,true,W,į.CurrentStoredPower,į.MaxStoredPower);}}ƪ=Ť.ğ();ƚ=ū.ğ();ƛ=ť.ğ();Ɯ=Ŧ.ğ();Ɲ=ŧ.ğ(true);ƞ=Ũ.ğ(true);Ű=0;ű=0;
  269. foreach(var Lj in ů){Ű+=Lj.CurrentOutput;ű+=Lj.MaxOutput;if(showWindTurbineStats&&enableTerminalStatistics){T(Lj,true,"",Lj.
  270. CurrentOutput,Lj.MaxOutput);}}Ɵ=Ű.ğ();Ơ=ű.ğ();Ŭ=0;ų=0;ŭ=0;foreach(var İ in ũ){Ŭ+=İ.GetOutput();if(showOxygenFarmStats&&
  271. enableTerminalStatistics){T(İ,true,"",İ.GetOutput(),1);}}Ŭ=Math.Round(Ŭ/ũ.Count*100,2);foreach(var ı in Ū){ų+=ı.Capacity;ŭ+=ı.Capacity*ı.
  272. FilledRatio;if(showOxygenTankStats&&enableTerminalStatistics){T(ı,true,"",ı.FilledRatio,1);}}ơ=ų.Ģ();Ƣ=ŭ.Ģ();}void lj(){if(ư.Count==
  273. 0)return;if(ƭ[0].IsUnderControl){Ò();ƣ="Automatic alignment paused.\n";ƣ+="Ship is currently controlled by a player.";
  274. return;}int NJ=10;bool Nj=false;bool nj=false;bool Ǎ=false;string à="";double è=ǂ;double é=DŽ;double í=ǃ;double á=maxGyroRPM-(
  275. maxGyroRPM-minGyroRPM)*(è/é);á=á/(Math.PI*3);if(!è.Ħ(Ƭ-Ƭ*realignPercentageGyro,Ƭ+Ƭ*realignPercentageGyro)&&Ɓ&&Ƅ>=NJ){Ƃ=false;ƃ=
  276. false;Ƭ=0;if(è<í&&ž==3&&!Ż){Ÿ=-Ÿ;ž=0;Ż=true;}â((float)(Ÿ*á),0,0);if(Ÿ==-1){à="down";}else{à="up";}if(è<í&&ž>=4){Ï();Ƃ=true;ƃ=
  277. true;Ƭ=è;Ż=false;ž=0;Ƅ=0;}else{Nj=true;ž++;}}else if(Ɓ){Ï();Ƃ=true;ƃ=true;Ż=false;ž=0;Ƅ++;}else{Ƅ++;}if(!è.Ħ(Ŵ-Ŵ*
  278. realignPercentageGyro,Ŵ+Ŵ*realignPercentageGyro)&&Ƃ&&ƅ>=NJ){Ɓ=false;ƃ=false;Ŵ=0;if(è<í&&ſ==3&&!ż){Ź=-Ź;ſ=0;ż=true;}â(0,(float)(Ź*á),0);if(Ź==-
  279. 1){à="left";}else{à="right";}if(è<í&&ſ>=4){Ï();Ɓ=true;ƃ=true;Ŵ=è;ż=false;ſ=0;ƅ=0;}else{nj=true;ſ++;}}else if(Ƃ){Ï();Ɓ=true
  280. ;ƃ=true;ż=false;ſ=0;ƅ++;}else{ƅ++;}if(!è.Ħ(ŷ-ŷ*realignPercentageGyro,ŷ+ŷ*realignPercentageGyro)&&ƃ&&Ƈ>=NJ){Ɓ=false;Ƃ=false
  281. ;ŷ=0;if(è<í&&ƀ==3&&!Ž){ź=-ź;ƀ=0;Ž=true;}â(0,0,(float)(ź*á));if(ź==-1){à="left";}else{à="right";}if(è<í&&ƀ>=4){Ï();Ɓ=true;
  282. Ƃ=true;ŷ=è;Ž=false;ƀ=0;Ƈ=0;}else{Ǎ=true;ƀ++;}}else if(ƃ){Ï();Ɓ=true;Ƃ=true;Ž=false;ƀ=0;Ƈ++;}else{Ƈ++;}if(!Nj&&!nj&&!Ǎ){ƣ=
  283. "Aligned.";}else if(Nj){ƣ="Aligning by pitching the ship "+à+"..";}else if(nj){ƣ="Aligning by yawing the ship "+à+"..";}else if(Ǎ){ƣ
  284. ="Aligning by rolling the ship "+à+"..";}}void Ǚ(){if(ǂ<DŽ*nightPercentage&&ƺ>=30){ƣ="Night Mode.";Ƹ=true;if(
  285. rotateToSunrise&&!ƹ){if(manualAngle){ƹ=ö("both",manualAngleHorizontal,manualAngleVertical);}else{ƹ=ö("sunrise");}if(ƹ){foreach(var d in
  286. Ʈ){ǐ(d,"firstLockOfDay",1);ǐ(d,"rotationDone",0);}}}else{Ò();}}else{if(Ƹ){Ƹ=false;ƺ=0;foreach(var d in Ʈ){ǐ(d,
  287. "outputMaxDayBefore",Ƿ(d,"outputMax"));ǐ(d,"outputMax",0);}}else if(ƺ>172800){ƺ=0;}else{ƺ++;}ƹ=false;Ƽ=true;int NJ=10;if(ǂ<DŽ*0.5){NJ=30;}int ó
  288. =0;int ô=0;foreach(var Ü in Ƶ){double è=Ƿ(Ü,"output");double í=Ƿ(Ü,"outputLast");double ǖ=Ƿ(Ü,"outputLocked");double é=Ƿ(
  289. Ü,"outputMax");double à=Ƿ(Ü,"direction");double ë=Ƿ(Ü,"directionChanged");double Ú=Ƿ(Ü,"directionTimer");double Ǘ=Ƿ(Ü,
  290. "allowRotation");double ǘ=Ƿ(Ü,"timeSinceRotation");bool Ǖ=false;if(Ǘ==0||ǘ<NJ){Ó(Ü);ǐ(Ü,"allowRotation",1);ǐ(Ü,"timeSinceRotation",ǘ+1);
  291. continue;}if(!è.Ħ(ǖ-ǖ*realginPercentageRotor,ǖ+ǖ*realginPercentageRotor)){Ý(Ü,false);ǖ=0;if(è<í&&Ú==3&&ë==0){à=-à;Ú=0;ë=1;}if((Ü
  292. .LowerLimitDeg!=float.MinValue||Ü.UpperLimitDeg!=float.MaxValue)&&Ú>=5){double Ì=c(Ü);float Q=(float)Math.Round(Ü.
  293. LowerLimitDeg);float S=(float)Math.Round(Ü.UpperLimitDeg);if(Ì==Q||Ì==360+Q||Ì==S||Ì==360+S){if(è<í&&ë==0){à=-à;Ú=0;ë=1;}else{Ǖ=true;
  294. }}}ß(Ü,à,(float)(rotorMaxSpeed-rotorMaxSpeed*(è/é)+rotorMinSpeed));if(è<í&&Ú>=4||è==0||Ǖ){Ó(Ü);if(Ƿ(Ü,"firstLockOfDay")==
  295. 1){if(è>Ƿ(Ü,"outputMaxDayBefore")*0.9){ǐ(Ü,"firstLockOfDay",0);ǐ(Ü,"sunriseAngle",c(Ü));}}ǖ=è;ë=0;Ú=0;ǘ=0;}else{ó++;Ú++;}
  296. ǐ(Ü,"outputLocked",ǖ);ǐ(Ü,"direction",à);ǐ(Ü,"directionChanged",ë);ǐ(Ü,"directionTimer",Ú);ǐ(Ü,"timeSinceRotation",ǘ);}
  297. else{Ó(Ü);ǐ(Ü,"directionChanged",ë);ǐ(Ü,"directionTimer",Ú);}}foreach(var Þ in Ư){double è=Ƿ(Þ,"output");double í=Ƿ(Þ,
  298. "outputLast");double ǖ=Ƿ(Þ,"outputLocked");double é=Ƿ(Þ,"outputMax");double à=Ƿ(Þ,"direction");double ë=Ƿ(Þ,"directionChanged");
  299. double Ú=Ƿ(Þ,"directionTimer");double Ǘ=Ƿ(Þ,"allowRotation");double ǘ=Ƿ(Þ,"timeSinceRotation");bool Ǖ=false;if(Ǘ==0||ǘ<NJ){Ó(Þ)
  300. ;ǐ(Þ,"allowRotation",1);ǐ(Þ,"timeSinceRotation",ǘ+1);continue;}if(!è.Ħ(ǖ-ǖ*realginPercentageRotor,ǖ+ǖ*
  301. realginPercentageRotor)){ţ(Þ,false);ǖ=0;if(è<í&&Ú==3&&ë==0){à=-à;Ú=0;ë=1;}if((Þ.LowerLimitDeg!=float.MinValue||Þ.UpperLimitDeg!=float.MaxValue
  302. )&&Ú>=5){double ì=c(Þ);float î=(float)Math.Round(Þ.LowerLimitDeg);float ï=(float)Math.Round(Þ.UpperLimitDeg);if(ì==î||ì==
  303. 360+î||ì==ï||ì==360+ï){if(è<í&&ë==0){à=-à;Ú=0;ë=1;}else{Ǖ=true;}}}ß(Þ,à,(float)(rotorMaxSpeed-rotorMaxSpeed*(è/é)+
  304. rotorMinSpeed));if(è<í&&Ú>=4||è==0||Ǖ){Ó(Þ);if(Ƿ(Þ,"firstLockOfDay")==1){if(è>Ƿ(Þ,"outputMaxDayBefore")*0.9){ǐ(Þ,"firstLockOfDay",0);
  305. ǐ(Þ,"sunriseAngle",c(Þ));}}ǖ=è;ë=0;Ú=0;ǘ=0;}else{ô++;Ú++;}ǐ(Þ,"outputLocked",ǖ);ǐ(Þ,"direction",à);ǐ(Þ,"directionChanged"
  306. ,ë);ǐ(Þ,"directionTimer",Ú);ǐ(Þ,"timeSinceRotation",ǘ);}else{Ó(Þ);ǐ(Þ,"directionChanged",0);ǐ(Þ,"directionTimer",0);}}if(
  307. ó==0&&ô==0){ƣ="Aligned.";}else if(ó==0){ƣ="Aligning "+ô+" horizontal rotors..";}else if(ô==0){ƣ="Aligning "+ó+
  308. " vertical rotors..";}else{ƣ="Aligning "+ô+" horizontal and "+ó+" vertical rotors..";}}}void ţ(IMyMotorStator d,bool Û){foreach(var Ü in Ƶ){
  309. if(d.CubeGrid==Ü.TopGrid){if(Û){ǐ(Ü,"allowRotation",1);}else{Ó(Ü);ǐ(Ü,"allowRotation",0);}}}}void Ý(IMyMotorStator d,bool
  310. Û){foreach(var Þ in Ư){if(d.TopGrid==Þ.CubeGrid){if(Û){ǐ(Þ,"allowRotation",1);}else{Ó(Þ);ǐ(Þ,"allowRotation",0);}}}}void
  311. ß(IMyMotorStator d,double à,float á=rotorMinSpeed){d.RotorLock=false;d.TargetVelocityRPM=á*(float)à;}void â(double ã,
  312. double ä,double å){Vector3D æ=new Vector3D(-ã,ä,å);Vector3D ç=Vector3D.TransformNormal(æ,ƭ[0].WorldMatrix);foreach(var Ñ in ư)
  313. {Vector3D Í=Vector3D.TransformNormal(ç,Matrix.Transpose(Ñ.WorldMatrix));Ñ.GyroOverride=true;Ñ.GyroPower=gyroPower;Ñ.Pitch
  314. =(float)Í.X;Ñ.Yaw=(float)Í.Y;Ñ.Roll=(float)Í.Z;}}void Ó(IMyMotorStator d,bool Î=true){d.TargetVelocityRPM=0f;if(Î){ǐ(d,
  315. "rotationDone",1);}else{ǐ(d,"rotationDone",0);}if(setRotorLockWhenStopped){d.RotorLock=true;}}void Ï(bool Ð=false){foreach(var Ñ in ư)
  316. {Ñ.Pitch=0;Ñ.Yaw=0;Ñ.Roll=0;if(Ð)Ñ.GyroOverride=false;}}void Ò(bool Î=true){foreach(var d in Ʈ){Ó(d,Î);ǐ(d,
  317. "timeSinceRotation",0);}Ï(true);Ƅ=0;ƅ=0;Ƈ=0;}bool Ô(IMyMotorStator d,double Õ,bool Ö=true){double Ø=c(d);bool Ù=false;if(Ö){if(d.CustomName
  318. .IndexOf("[90]")>=0){Õ+=90;}else if(d.CustomName.IndexOf("[180]")>=0){Õ+=180;}else if(d.CustomName.IndexOf("[270]")>=0){Õ
  319. +=270;}if(Õ>=360)Õ-=360;if(d.Orientation.Up.ToString()=="Down"){Ù=true;}else if(d.Orientation.Up.ToString()=="Backward"){Ù
  320. =true;}else if(d.Orientation.Up.ToString()=="Left"){Ù=true;}}if(d.LowerLimitDeg!=float.MinValue||d.UpperLimitDeg!=float.
  321. MaxValue){if(Ù)Õ=-Õ;if(Õ>d.UpperLimitDeg){Õ=Math.Floor(d.UpperLimitDeg);}if(Õ<d.LowerLimitDeg){Õ=Math.Ceiling(d.LowerLimitDeg);}
  322. }else{if(Ù)Õ=360-Õ;}if(Ø.Ħ(Õ-1,Õ+1)||Ø.Ħ(360+Õ-1,360+Õ+1)){Ó(d);return true;}else{int à=Ø<Õ?1:-1;if(Ø<=90&&Õ>=270){à=-1;}
  323. if(Ø>=270&&Õ<=90){à=1;}Single á=Math.Abs(Ø-Õ)>15?rotorMaxSpeed:rotorMinSpeed;if(Math.Abs(Ø-Õ)<3)á=0.1f;ß(d,à,á);return
  324. false;}}bool ö(string ð,double ñ=0,double ò=0){bool Î=true;int ó=0;int ô=0;if(Ƽ){Ƽ=false;Ò(false);}if(ð!="verticalOnly"){
  325. foreach(var Þ in Ư){if(Ƿ(Þ,"rotationDone")==1)continue;bool Ö=true;double Õ=ñ;if(ð=="sunrise"){Õ=Ƿ(Þ,"sunriseAngle");Ö=false;}
  326. if(!Ô(Þ,Õ,Ö)){Î=false;ô++;Ƥ=ô+" horizontal rotors are set to "+ñ+"°";if(ð=="sunrise")Ƥ=ô+
  327. " horizontal rotors are set to sunrise position";}}}if(!Î)return false;if(ð!="horizontalOnly"){foreach(var Ü in Ƶ){if(Ƿ(Ü,"rotationDone")==1)continue;bool Ö=true;double
  328. Õ=ò;if(ð=="sunrise"){Õ=Ƿ(Ü,"sunriseAngle");Ö=false;}if(!Ô(Ü,Õ,Ö)){Î=false;ó++;Ƥ=ó+" vertical rotors are set to "+ò+"°";if
  329. (ð=="sunrise")Ƥ=ó+" vertical rotors are set to sunrise position";}}}if(Î)Ƽ=true;return Î;}void õ(){int ô=0;int ó=0;if(ƻ==
  330. 90){foreach(var d in Ʈ){Ó(d,false);double ø=1;if(d.Orientation.Up.ToString()=="Up"){ø=-1;}else if(d.Orientation.Up.
  331. ToString()=="Forward"){ø=-1;}else if(d.Orientation.Up.ToString()=="Right"){ø=-1;}ǐ(d,"outputMax",Ƿ(d,"output"));ǐ(d,"direction",
  332. ø);ǐ(d,"directionChanged",0);ǐ(d,"directionTimer",0);DŽ=0;}}foreach(var Þ in Ư){if(Ƿ(Þ,"rotationDone")==1)continue;double
  333. è=Ƿ(Þ,"output");double í=Ƿ(Þ,"outputLast");double é=Ƿ(Þ,"outputMax");double ê=Ƿ(Þ,"outputMaxAngle");double à=Ƿ(Þ,
  334. "direction");double ë=Ƿ(Þ,"directionChanged");double Ú=Ƿ(Þ,"directionTimer");if(é==0)é=1;if(ë!=2){ô++;if(è<í&&Ú>=7&&ë==0){ǐ(Þ,
  335. "direction",-à);ǐ(Þ,"directionChanged",1);Ú=0;}if((Þ.LowerLimitDeg!=float.MinValue||Þ.UpperLimitDeg!=float.MaxValue)&&Ú>=3&&ë==0){
  336. double ì=c(Þ);float î=(float)Math.Round(Þ.LowerLimitDeg);float ï=(float)Math.Round(Þ.UpperLimitDeg);if(ì==î||ì==360+î||ì==ï||ì
  337. ==360+ï){ǐ(Þ,"direction",-à);ǐ(Þ,"directionChanged",1);Ú=0;}}ß(Þ,à,(float)(2.75-(è/é)*2));if(è<í&&Ú>=7&&ë==1){Ó(Þ,false);ǐ
  338. (Þ,"directionChanged",2);}else{ǐ(Þ,"directionTimer",Ú+1);}}else{if(!Ô(Þ,ê,false))ô++;}}if(ô!=0)return;foreach(var Ü in Ƶ)
  339. {if(Ƿ(Ü,"rotationDone")==1)continue;double è=Ƿ(Ü,"output");double í=Ƿ(Ü,"outputLast");double é=Ƿ(Ü,"outputMax");double ê=
  340. Ƿ(Ü,"outputMaxAngle");double à=Ƿ(Ü,"direction");double ë=Ƿ(Ü,"directionChanged");double Ú=Ƿ(Ü,"directionTimer");if(é==0)é
  341. =1;if(ë!=2){ó++;if(è<í&&Ú>=7&&ë==0){ǐ(Ü,"direction",-à);ǐ(Ü,"directionChanged",1);Ú=0;}if((Ü.LowerLimitDeg!=float.
  342. MinValue||Ü.UpperLimitDeg!=float.MaxValue)&&Ú>=3&&ë==0){double Ì=c(Ü);float Q=(float)Math.Round(Ü.LowerLimitDeg);float S=(float)
  343. Math.Round(Ü.UpperLimitDeg);if(Ì==Q||Ì==360+Q||Ì==S||Ì==360+S){ǐ(Ü,"direction",-à);ǐ(Ü,"directionChanged",1);Ú=0;}}ß(Ü,à,(
  344. float)(2.75-(è/é)*2));if(è<í&&Ú>=7&&ë==1){Ó(Ü,false);ǐ(Ü,"directionChanged",2);}else{ǐ(Ü,"directionTimer",Ú+1);}}else{if(!Ô(Ü
  345. ,ê,false))ó++;}}if(ô==0&&ó==0){ƻ=0;}}void T(IMyTerminalBlock U,bool V=true,string W="",double X=0,double Y=0){string Z=U.
  346. CustomName;string a=System.Text.RegularExpressions.Regex.Match(U.CustomName,@" *\(\d+\.*\d*%.*\)").Value;if(a!=String.Empty){Z=U.
  347. CustomName.Replace(a,"");}if(V){Z+=" ("+X.Ě(Y);if(W!=""){Z+=", "+W;}Z+=")";}if(Z!=U.CustomName){U.CustomName=Z;}}double c(
  348. IMyMotorStator d){return Math.Round(d.Angle*180/Math.PI);}string e(bool f=false,float h=0.65f,int j=26,bool N=true,bool O=true,bool A=
  349. true,bool H=true,bool B=true,bool C=true){string D="";bool E=false;D="Isy's Solar Alignment Script "+Ʀ[Ƨ]+"\n";D+=
  350. "=======================";if(!f)D+="=======";D+="\n\n";if(ƒ!=null){D+="Error!\n";D+=ƒ+"\n\n";D+="Script stopped!\n\n";return D;}if(Ɠ!=null){D+=
  351. "Warning!\n";D+=Ɠ+"\n\n";E=true;}if(N){string F=ƣ+"\n"+ƥ;D+=F;D+='\n'.ĝ(3-F.Count(G=>G=='\n'));E=true;}if(O){D+="Statistics for "+ƽ.
  352. Count+" Solar Panels:\n";D+=Ķ(h,j,"Efficiency",ǂ,DŽ,Ų,Ɔ);D+=Ķ(h,j,"Output",ƿ,ǂ,ƈ,Ų)+"\n\n";E=true;}if(A&&ů.Count>0){D+=
  353. "Statistics for "+ů.Count+" Wind Turbines:\n";D+=Ķ(h,j,"Output",Ű,ű,Ɵ,Ơ)+"\n\n";E=true;}if(H&&ŵ.Count>0){D+="Statistics for "+ŵ.Count+
  354. " Batteries:\n";D+=Ķ(h,j,"Input",Ť,ū,ƪ,ƚ);D+=Ķ(h,j,"Output",ť,Ŧ,ƛ,Ɯ);D+=Ķ(h,j,"Charge",ŧ,Ũ,Ɲ,ƞ)+"\n\n";E=true;}if(B&&(ũ.Count>0||Ū.
  355. Count>0)){D+="Statistics for Oxygen:\n";if(ũ.Count>0){D+=Ķ(h,j,ũ.Count+" Farms",Ŭ,100);}if(Ū.Count>0){D+=Ķ(h,j,Ū.Count+
  356. " Tanks",ŭ,ų,Ƣ,ơ);}D+="\n\n";E=true;}if(C&&!useGyroMode){string I="";string P="";string J="";if(ƙ<ƨ){P=" inaccurate";I="*";}else
  357. if(ƙ==ƫ||Ɛ==Ɖ){P=" inaccurate, still calculating";I="*";}if(ƨ<Ɛ&&I==""){J=" / Dusk in: "+µ(Ɛ-ƨ);}else if(ƨ>Ɛ&&I==""){J=
  358. " / Dawn in: "+µ(ƙ-ƨ);}D+="Time of your location:\n";D+="Time: "+k(ƨ)+J+I+"\n";D+="Dawn: "+k(ƙ)+" / Daylength: "+µ(Ɛ)+I+"\n";D+=
  359. "Dusk: "+k(Ɛ)+" / Nightlength: "+µ(ƙ-Ɛ)+I+"\n";if(I!=""){D+=I+P;}E=true;}if(!E){D+="-- No informations to show --";}return D;}
  360. void K(string L=null){if(Ʊ.Count==0)return;foreach(var M in Ʊ){bool N=ǔ(M,"showCurrentOperation");bool O=ǔ(M,
  361. "showSolarStats");bool A=ǔ(M,"showTurbineStats");bool H=ǔ(M,"showBatteryStats");bool B=ǔ(M,"showOxygenStats");bool C=ǔ(M,
  362. "showLocationTime");float h=M.FontSize;int Å=26;if(M.BlockDefinition.SubtypeName.Contains("Wide"))Å=52;string D="";if(L!=null){D=L;}else{D
  363. =e(false,h,Å,N,O,A,H,B,C);}string Æ=Ċ(h,D,M);M.WritePublicTitle("Isy's Solar Alignment Script");M.WriteText(Æ,false);M.
  364. Font="Monospace";M.TextPadding=0;M.ContentType=VRage.Game.GUI.TextPanel.ContentType.TEXT_AND_IMAGE;}}void Ç(){if(Ʋ.Count==0)
  365. return;foreach(var M in Ʋ){string È=M.CustomData.ToLower().Replace(" ","").TrimEnd('\n');if(È=="time"||È=="realtime"){if(M.
  366. Font=="Monospace")M.Font="Debug";M.FontSize=2.5f;}else{M.Font="Monospace";M.FontSize=0.5f;}float h=M.FontSize;int j=26;int É
  367. =(int)(j/h);string L="";if(È=="time"){L=k(ƨ);}else if(È=="realtime"){L=DateTime.Now.ToString(@"HH:mm:ss");}else if(È==
  368. "solar"){L="Statistics for "+ƽ.Count+" Solar Panels:\n";L+=Ķ(h,j,"Efficiency",ǂ,DŽ,Ų,Ɔ,Ś:true);L+=Ķ(h,j,"Output ",ƿ,ǂ,ƈ,Ų,Ś:
  369. true);}else if(È=="battery"){L="Statistics for "+ŵ.Count+" Batteries:\n";L+=Ķ(h,j,"Input ",Ť,ū,ƪ,ƚ,Ś:true);L+=Ķ(h,j,"Output"
  370. ,ť,Ŧ,ƛ,Ɯ,Ś:true);L+=Ķ(h,j,"Charge",ŧ,Ũ,Ɲ,ƞ,Ś:true);}else if(È=="oxygen"){if(ũ.Count>0){L+="Statistics for "+ũ.Count+
  371. " Oxygen Farms:\n";L+=Ķ(h,j,"Efficiency",Ŭ,100,Ś:true)+"\n";}if(Ū.Count>0){L+="Statistics for "+Ū.Count+" Oxygen Tanks:\n";L+=Ķ(h,j,
  372. "Fill Level",ŭ,ų,Ƣ,ơ,Ś:true);}}else{L=
  373. "Keyword required!\n\nPlease edit the custom data of this LCD\nto set, what should be shown here!";È="In order to show informations on this LCD, delete this text and leave\none of the following keywords behind:\n\n";È
  374. +="solar\nbattery\noxygen\ntime\nrealtime\n\n";È+=
  375. "If you didn't specify a valid or no keyword, this message will reappear.";M.CustomData=È;}M.WriteText(L,false);M.WritePublicTitle("Please edit Custom Data!");M.SetValue<Int64>("alignment",2);M.
  376. TextPadding=0;M.ContentType=VRage.Game.GUI.TextPanel.ContentType.TEXT_AND_IMAGE;}}void Ê(){IMyTextPanel M=GridTerminalSystem.
  377. GetBlockWithName(debugLcd)as IMyTextPanel;if(M==null)return;if(M.GetText()=="")M.FontSize=0.5f;float h=M.FontSize;string L=
  378. "Solar Alignment Debug\n=====================\n\n";L+="Task: "+Ǭ[Ǩ]+"\n";L+="Script step: "+Ǩ+" / "+(Ǭ.Length-1)+"\n\n";if(showPerformance)L+=ŏ;if(showBlockCounts){L+=
  379. "Main Grid: "+Ā.CustomName+"\n";if(ī.Count>0)L+="Connected Grids: "+ī.Count+"\n";if(Ʈ.Count>0)L+="Rotors: "+Ʈ.Count+"\n";if(ư.Count>0
  380. )L+="Gyros: "+ư.Count+"\n";if(ƽ.Count>0)L+="Solar Panels: "+ƽ.Count+"\n";if(ů.Count>0)L+="Wind Turbines: "+ů.Count+"\n";
  381. if(ũ.Count>0)L+="Oxygen Farms: "+ũ.Count+"\n";if(Ū.Count>0)L+="Oxygen Tanks: "+Ū.Count+"\n";if(ŵ.Count>0)L+="Batteries: "+
  382. ŵ.Count+"\n";if(Ǝ>0)L+="Reactors: "+Ǝ+"\n";if(Ə>0)L+="Hydrogen Engines: "+Ə+"\n";if(Ʊ.Count>0)L+="LCDs: "+Ʊ.Count+"\n";if
  383. (Ʋ.Count>0)L+="Corner LCDs: "+Ʋ.Count+"\n";if(Ƴ.Count>0)L+="Lights: "+Ƴ.Count+"\n";if(ƴ.Count>0)L+="Spotlights: "+ƴ.Count
  384. +"\n";if(timers.Length>0)L+="Timer Blocks: "+timers.Length+"\n";}M.WritePublicTitle("Solar Alignment Debug");M.WriteText(
  385. Ċ(h,L,M),false);M.Font="Monospace";M.TextPadding=0;M.ContentType=VRage.Game.GUI.TextPanel.ContentType.TEXT_AND_IMAGE;}
  386. void Ë(){ƨ+=1;Ʃ+=1;if(ƨ>172800){ƨ=0;Ʃ=0;}double Ä=DŽ*nightTimePercentage;if(ǂ<Ä&&ǃ>=Ä&&Ʃ>300){Ɛ=ƨ;Ʃ=0;}if(ǂ>Ä&&ǃ<=Ä&&Ʃ>300){
  387. if(Ɛ!=Ɖ){ƙ=ƨ;}ƨ=0;Ʃ=0;}if(Ɛ>ƙ){ƙ=Ɛ*2;}}string k(double y,bool m=false){string q="";y=y%ƙ;double u=Ɛ+(ƙ-Ɛ)/2D;double v=ƙ/
  388. 24D;double w;if(y<u){w=(y+(ƙ-u))/v;}else{w=(y-u)/v;}double x=Math.Floor(w);double z=Math.Floor((w%1*100)*0.6);string Ã=x.
  389. ToString("00");string ª=z.ToString("00");q=Ã+":"+ª;if(m){return x.ToString();}else{return q;}}string µ(int º){string À="";
  390. TimeSpan Á=TimeSpan.FromSeconds(º);À=Á.ToString(@"hh\:mm\:ss");return À;}void Â(){if(ƶ.Count==0)return;double R=turnOnAtPercent%
  391. 100/100;double ù=turnOffAtPercent%100/100;double ĉ=overloadPercentage%100/100;if(Ƙ=="lowBat"||Ƙ==""){if(
  392. activateOnLowBattery&&ŧ<Ũ*R){Ƌ=true;Ƙ="lowBat";}else if(activateOnLowBattery&&ŧ>Ũ*ù){Ƌ=false;Ƙ="";}}if(Ƙ=="overload"||Ƙ==""){if(
  393. activateOnOverload&&ť+ƿ+Ű>(Ŧ+ǂ+ű)*ĉ){Ƌ=true;Ƙ="overload";}else{Ƌ=false;Ƙ="";}}if(ŧ<Ƒ||(Ƌ&&ƌ&&ƍ)){ƌ=true;ƍ=true;}else{if(
  394. activateHydrogenEngineFirst&&Ə>0){ƍ=true;ƌ=false;}else if(!activateHydrogenEngineFirst&&Ǝ>0){ƍ=false;ƌ=true;}else{ƍ=true;ƌ=true;}}Ƒ=ŧ;foreach(var Ĺ
  395. in ƶ){if(Ƌ){if(ƌ&&Ĺ.BlockDefinition.TypeIdString.Contains("Reactor")){Ĺ.Enabled=true;}else if(ƍ&&Ĺ.BlockDefinition.
  396. TypeIdString.Contains("HydrogenEngine")){Ĺ.Enabled=true;}else{Ĺ.Enabled=false;}}else{Ĺ.Enabled=false;}}if(Ƙ=="lowBat")Ƥ=
  397. "Power fallback active: Low battery charge!";if(Ƙ=="overload")Ƥ="Power fallback active: Overload!";}void ĺ(){if(Ƴ.Count==0&&ƴ.Count==0)return;int Ļ=0;int.TryParse(k
  398. (ƨ,true),out Ļ);bool ļ=true;if(!simpleMode){if(ƨ!=ƙ&&Ļ>=lightOffHour&&Ļ<lightOnHour){ļ=false;}else if(ƨ==ƙ&&ǂ>DŽ*
  399. nightTimePercentage){ļ=false;}}else{if(ǂ>DŽ*(simpleThreshold%100)/100)ļ=false;}foreach(var Ľ in Ƴ){Ľ.Enabled=ļ;}foreach(var ľ in ƴ){ľ.
  400. Enabled=ļ;}}void Ŀ(){if(events.Length==0){ņ("No events for triggering specified!");}else if(timers.Length==0){ņ(
  401. "No timers for triggering specified!");}else if(events.Length!=timers.Length){ņ("Every event needs a timer block name!\nFound "+events.Length+" events and "+
  402. timers.Length+" timers.");}else{int ŀ=-1;string Ł="";int º;for(int ĸ=0;ĸ<=events.Length-1;ĸ++){if(events[ĸ]=="sunrise"&&ƨ==0){
  403. ŀ=ĸ;Ł="sunrise";}else if(events[ĸ]=="sunset"&&ƨ==Ɛ){ŀ=ĸ;Ł="sunset";}else if(int.TryParse(events[ĸ],out º)==true&&ƨ%º==0){
  404. ŀ=ĸ;Ł=º+" seconds";}else if(k(ƨ)==events[ĸ]){ŀ=ĸ;Ł=events[ĸ];}}foreach(var ł in timers){var Ń=GridTerminalSystem.
  405. GetBlockWithName(ł)as IMyTimerBlock;if(Ń==null){ņ("External timer block not found:\n'"+Ń.CustomName+"'");}else{if(Ń.GetOwnerFactionTag()
  406. !=Me.GetOwnerFactionTag()){ņ("'"+Ń.CustomName+
  407. "' has a different owner / faction!\nAll blocks should have the same owner / faction!");}if(Ń.Enabled==false){ņ("'"+Ń.CustomName+"' is turned off!\nTurn it on in order to be used by the script!");}}}if(ŀ>=0
  408. ){var Ń=GridTerminalSystem.GetBlockWithName(timers[ŀ])as IMyTimerBlock;if(Ń!=null){Ń.ApplyAction("Start");ƣ=
  409. "External timer triggered! Reason: "+Ł;}}}}void ń(string L){Ò();if(ƒ==null){ƒ=L;Ɣ++;}}void ņ(string L){if(Ɠ==null){Ɠ=L;ƕ++;}}void Į(){foreach(var Ĵ in ƽ){Ĵ.
  410. CustomData="";T(Ĵ,false);}foreach(var į in ŵ){T(į,false);}foreach(var İ in ũ){T(İ,false);}foreach(var ı in Ū){T(ı,false);}}void IJ(
  411. ){if(Me.CustomData.Length>0){var ij=Me.CustomData.Split('\n');foreach(var ú in ij){var ĵ=ú.Split('=');if(ĵ.Length!=2)
  412. continue;if(ĵ[0]=="dayTimer"){int.TryParse(ĵ[1],out ƨ);}else if(ĵ[0]=="dayLength"){int.TryParse(ĵ[1],out ƙ);}else if(ĵ[0]==
  413. "sunSet"){int.TryParse(ĵ[1],out Ɛ);}else if(ĵ[0]=="outputLast"){double.TryParse(ĵ[1],out ǃ);}else if(ĵ[0]=="maxDetectedOutput"){
  414. double.TryParse(ĵ[1],out DŽ);}else if(ĵ[0]=="solarPanelsCount"){int.TryParse(ĵ[1],out Ʒ);}else if(ĵ[0]=="oxygenFarmsCount"){int
  415. .TryParse(ĵ[1],out Ů);}else if(ĵ[0]=="action"){Ɩ=ĵ[1];}}if(Ɩ=="paused")Ŷ=true;}}void Save(){string È="";È+="dayTimer="+ƨ+
  416. "\n";È+="dayLength="+ƙ+"\n";È+="sunSet="+Ɛ+"\n";È+="outputLast="+ǃ+"\n";È+="maxDetectedOutput="+DŽ+"\n";È+=
  417. "solarPanelsCount="+ƽ.Count+"\n";È+="oxygenFarmsCount="+ũ.Count+"\n";È+="action="+Ɩ;Me.CustomData=È;}string Ķ(double h,int j,string ķ,
  418. double Û,double Ņ,string Ň=null,string Ţ=null,bool ř=false,bool Ś=false){string ś=Û.ToString();string Ĩ=Ņ.ToString();if(Ň!=
  419. null){ś=Ň;}if(Ţ!=null){Ĩ=Ţ;}string Ŝ=Û.Ě(Ņ);Ŝ=' '.ĝ(6-Ŝ.Length)+Ŝ;string ŝ=ś+" / "+Ĩ;int É=(int)(j/h);double Ş=0;if(Ņ>0)Ş=Û/
  420. Ņ>=1?1:Û/Ņ;StringBuilder ş=new StringBuilder(ķ+" ");StringBuilder Š=new StringBuilder();if(Ś){if(h<=0.5||(h<=1&&j==52)){ş
  421. .Append(' '.ĝ(9-ś.Length)+ś);ş.Append(" / "+Ĩ+' '.ĝ(9-Ĩ.Length));int š=ş.Length+1;int Ř=É-ş.Length-Ŝ.Length-2;int ň=(int)
  422. Math.Ceiling(Ř*Ş);ş.Append("["+'I'.ĝ(ň)+'.'.ĝ(Ř-ň)+"]");ş.Append(Ŝ+"\n");}else{int Ř=É-ş.Length-Ŝ.Length-2;int ň=(int)Math.
  423. Ceiling(Ř*Ş);ş.Append("["+'I'.ĝ(ň)+'.'.ĝ(Ř-ň)+"]");ş.Append(Ŝ+"\n");}return ş.ToString();}else{if(h<=0.6||(h<=1&&j==52)){ş.
  424. Append(' '.ĝ(É/2-(ş.Length+ś.Length)));ş.Append(ś+" / "+Ĩ);ş.Append(' '.ĝ(É-(ş.Length+Ŝ.Length)));ş.Append(Ŝ+"\n");if(!ř){int
  425. Ř=É-2;int ň=(int)Math.Ceiling(Ř*Ş);Š=new StringBuilder("["+'I'.ĝ(ň)+'.'.ĝ(Ř-ň)+"]\n");}}else{ş.Append(' '.ĝ(É-(ş.Length+ŝ
  426. .Length)));ş.Append(ŝ+"\n");if(!ř){int Ř=É-Ŝ.Length-2;int ň=(int)Math.Ceiling(Ř*Ş);Š=new StringBuilder("["+'I'.ĝ(ň)+'.'.ĝ
  427. (Ř-ň)+"]");Š.Append(Ŝ+"\n");}}return ş.Append(Š).ToString();}}string ŏ="Performance information is generated..";
  428. Dictionary<string,int>ʼn=new Dictionary<string,int>();List<int>Ŋ=new List<int>(new int[100]);List<double>ŋ=new List<double>(new
  429. double[100]);double Ō,ō;int Ŏ=0;DateTime Ő;void ŗ(string ő,bool Œ=false){if(Œ){Ő=DateTime.Now;return;}Ŏ=Ŏ>=99?0:Ŏ+1;ŏ="";int œ
  430. =Runtime.CurrentInstructionCount;if(œ>Ō)Ō=œ;Ŋ[Ŏ]=œ;double Ŕ=Ŋ.Sum()/Ŋ.Count;ŏ+="Instructions: "+œ+" / "+Runtime.
  431. MaxInstructionCount+"\n";ŏ+="Max. Instructions: "+Ō+" / "+Runtime.MaxInstructionCount+"\n";ŏ+="Avg. Instructions: "+Math.Floor(Ŕ)+" / "+
  432. Runtime.MaxInstructionCount+"\n\n";double ŕ=(DateTime.Now-Ő).TotalMilliseconds;if(ŕ>ō)ō=ŕ;ŋ[Ŏ]=ŕ;double Ŗ=ŋ.Sum()/ŋ.Count;ŏ+=
  433. "Last runtime: "+Math.Round(ŕ,4)+" ms\n";ŏ+="Max. runtime: "+Math.Round(ō,4)+" ms\n";ŏ+="Avg. runtime: "+Math.Round(Ŗ,4)+" ms\n\n";ŏ+=
  434. "Instructions per Method:\n";ʼn[ő]=œ;foreach(var ł in ʼn.OrderByDescending(ĸ=>ĸ.Value)){ŏ+="- "+ł.Key+": "+ł.Value+"\n";}ŏ+="\n";}DateTime ĭ=DateTime.
  435. Now;Dictionary<long,List<int>>Ĉ=new Dictionary<long,List<int>>();string Ċ(float h,string L,IMyTextPanel M,int ċ=3,bool Č=
  436. true,int č=1){long Ď=M.EntityId;if(!Ĉ.ContainsKey(Ď)){Ĉ[Ď]=new List<int>{1,3,ċ,0};}int ď=Ĉ[Ď][0];int Đ=Ĉ[Ď][1];int đ=Ĉ[Ď][2]
  437. ;int Ē=Ĉ[Ď][3];var ē=L.TrimEnd('\n').Split('\n');List<string>Ĕ=new List<string>();int ĕ=(int)Math.Ceiling(17/h*č);int É=(
  438. int)(26/h);string Æ="";if(M.BlockDefinition.SubtypeName.Contains("Corner")){if(M.CubeGrid.GridSize==0.5){ĕ=(int)Math.Floor(
  439. 5/h);}else{ĕ=(int)Math.Floor(3/h);}}if(M.BlockDefinition.SubtypeName.Contains("Wide")){É=(int)(52/h);}foreach(var ú in ē)
  440. {if(ú.Length<=É){Ĕ.Add(ú);}else{try{string ÿ="";var û=ú.Split(' ');string ü=System.Text.RegularExpressions.Regex.Match(ú,
  441. @".+(\.|\:)\ ").Value;string ý=' '.ĝ(ü.Length);foreach(var þ in û){if((ÿ+" "+þ).Length>É){Ĕ.Add(ÿ);ÿ=ý+þ+" ";}else{ÿ+=þ+" ";}}Ĕ.Add(ÿ)
  442. ;}catch{Ĕ.Add(ú);}}}if(Č){if(Ĕ.Count>ĕ){if(DateTime.Now.Second!=Ē){Ē=DateTime.Now.Second;if(Đ>0)Đ--;if(Đ<=0)đ+=ď;if(đ+ĕ-ċ
  443. >=Ĕ.Count&&Đ<=0){ď=-1;Đ=3;}if(đ<=ċ&&Đ<=0){ď=1;Đ=3;}}}else{đ=ċ;ď=1;Đ=3;}Ĉ[Ď][0]=ď;Ĉ[Ď][1]=Đ;Ĉ[Ď][2]=đ;Ĉ[Ď][3]=Ē;}else{đ=ċ;}
  444. for(var ú=0;ú<ċ;ú++){Æ+=Ĕ[ú]+"\n";}for(var ú=đ;ú<Ĕ.Count;ú++){Æ+=Ĕ[ú]+"\n";}return Æ;}IMyCubeGrid Ā=null;HashSet<
  445. IMyCubeGrid>ć=new HashSet<IMyCubeGrid>();void ā(IMyCubeGrid Ă){ć.Add(Ă);List<IMyMotorStator>ă=new List<IMyMotorStator>();List<
  446. IMyPistonBase>Ą=new List<IMyPistonBase>();GridTerminalSystem.GetBlocksOfType<IMyMotorStator>(ă,ą=>ą.IsAttached&&ą.TopGrid==Ă&&!ć.
  447. Contains(ą.CubeGrid));GridTerminalSystem.GetBlocksOfType<IMyPistonBase>(Ą,Ć=>Ć.IsAttached&&Ć.TopGrid==Ă&&!ć.Contains(Ć.CubeGrid)
  448. );if(ă.Count==0&&Ą.Count==0){Ā=Ă;return;}else{foreach(var d in ă){ā(d.CubeGrid);}foreach(var Ė in Ą){ā(Ė.CubeGrid);}}}
  449. HashSet<IMyCubeGrid>ī=new HashSet<IMyCubeGrid>();void Ĥ(IMyCubeGrid Ă,bool ĥ=false){if(ĥ)ī.Clear();ī.Add(Ă);List<IMyMotorStator
  450. >ă=new List<IMyMotorStator>();List<IMyPistonBase>Ą=new List<IMyPistonBase>();GridTerminalSystem.GetBlocksOfType<
  451. IMyMotorStator>(ă,ą=>ą.CubeGrid==Ă&&ą.IsAttached&&!ī.Contains(ą.TopGrid));GridTerminalSystem.GetBlocksOfType<IMyPistonBase>(Ą,Ć=>Ć.
  452. CubeGrid==Ă&&Ć.IsAttached&&!ī.Contains(Ć.TopGrid));foreach(var d in ă){Ĥ(d.TopGrid);}foreach(var Ė in Ą){Ĥ(Ė.TopGrid);}}
  453. }static partial class ė{public static bool Ħ(this double Û,double ħ,double Ĩ,bool ĩ=false,bool Ī=false){bool Ĭ=Û>=ħ;bool
  454. ģ=Û<=Ĩ;if(Ī)Ĭ=Û>ħ;if(ĩ)ģ=Û<Ĩ;return Ĭ&&ģ;}}static partial class ė{public static string ĝ(this char Ę,int ę){if(ę<=0){
  455. return"";}return new string(Ę,ę);}}static partial class ė{public static string Ě(this double ě,double Ĝ){double Ğ=Math.Round(ě
  456. /Ĝ*100,1);if(Ĝ==0){return"0%";}else{return Ğ+"%";}}}static partial class ė{public static string ğ(this double Û,bool Ġ=
  457. false){string ġ="MW";if(Û<1){Û*=1000;ġ="kW";}else if(Û>=1000&&Û<1000000){Û/=1000;ġ="GW";}else if(Û>=1000000&&Û<1000000000){Û
  458. /=1000000;ġ="TW";}else if(Û>=1000000000){Û/=1000000000;ġ="PW";}if(Ġ)ġ+="h";return Math.Round(Û,1)+" "+ġ;}}static partial
  459. class ė{public static string Ģ(this double Û){string ġ="L";if(Û>=1000&&Û<1000000){Û/=1000;ġ="KL";}else if(Û>=1000000&&Û<
  460. 1000000000){Û/=1000000;ġ="ML";}else if(Û>=1000000000&&Û<1000000000000){Û/=1000000000;ġ="BL";}else if(Û>=1000000000000){Û/=
  461. 1000000000000;ġ="TL";}return Math.Round(Û,1)+" "+ġ;}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement