Advertisement
Guest User

kOS Capacitor management script for Near Future Electric.

a guest
Sep 27th, 2015
741
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.48 KB | None | 0 0
  1. clearscreen.
  2.  
  3. // Create a list of all parts with capacitators.
  4. SET capacitors TO list().
  5. PRINT "Found capacitors:".
  6. FOR part IN SHIP:PARTS {
  7. FOR resource in part:RESOURCES {
  8. IF resource:NAME = "StoredCharge" {
  9. capacitors:ADD(part).
  10. print " - " + part:NAME.
  11. }
  12. }
  13. }
  14.  
  15. // Create a reference to the total/global value of ec and sc
  16. LIST RESOURCES IN RESLIST.
  17. FOR resource IN RESLIST {
  18. IF resource:NAME = "ElectricCharge" {
  19. set EC to resource.
  20. } ELSE IF resource:NAME = "StoredCharge" {
  21. set SC to resource.
  22. }
  23. }
  24.  
  25. WAIT 3.
  26. clearscreen.
  27.  
  28. // log "-- start --" to "dischargelog.log".
  29.  
  30. print "CAPACITOR MANAGER".
  31.  
  32. set lastEC to EC:AMOUNT.
  33. set lastTC to EC:AMOUNT + SC:AMOUNT.
  34. set lastT to TIME:SECONDS.
  35. set charging to FALSE.
  36. set lastPrint to 7.
  37. UNTIL False {
  38. WAIT 0.25.
  39. // Figure out at what rates EC and SC is currently changing.
  40. set dT to TIME:SECONDS - lastT.
  41. set lastT to TIME:SECONDS.
  42. set dEC to (EC:AMOUNT - lastEC) / dT.
  43. set lastEC to EC:AMOUNT.
  44. set dTC to (EC:AMOUNT + SC:AMOUNT - lastTC) / dT.
  45. set lastTC to EC:AMOUNT + SC:AMOUNT.
  46.  
  47. // We only care about managing capacitators if we are currently losing more
  48. // energy than we are gaining.
  49. IF dTC < 0 {
  50. // Try to keep our EC amount at around half, and change it faster towards
  51. // that value the further out it currently is. By keeping it around half we
  52. // keep a decent amount of leeway in both directions. Upwards leeway avoids accidentally
  53. // wasting charge by running capacitators when we are at max, downwards avoids the system
  54. // shutting down (engines burning out, kOS computer restarting, SAS stopping).
  55. set targetEC to (EC:CAPACITY * 0.5 - EC:AMOUNT) / 2.0.
  56.  
  57. // log "Rebalance session. tEC " + targetEC + ". dEC " + dEC + ". Current " + EC:AMOUNT to "dischargelog.log".
  58.  
  59. // In this initial step, we look capacitators currently firing, and adjust them until
  60. // the rate of change of the EC is (close to) equal to our target.
  61. if abs(dEC - targetEC) > 10 {
  62. for capacitor in capacitors {
  63. set module to capacitor:GETMODULE("DischargeCapacitor").
  64. if module:GETFIELD("status") <> "Ready" and module:GETFIELD("status") <> "Discharged!" {
  65. set currentDischargeRate to module:GETFIELD("adjusted discharge rate").
  66. set maxdischargerate to 100 * currentDischargeRate / module:GETFIELD("percent power").
  67. // setting targetRate like this may cause it to be over 100% or under 50%, but that's fine
  68. // since the setfield will just cap it back to a valid value, and we then use the actual
  69. // value to adjust dEC.
  70. set targetRate to 100 * (targetEC - (dEC - currentDischargeRate)) / maxdischargerate.
  71. module:SETFIELD("percent power", targetRate).
  72. // log "Adjusting. Current: " + currentDischargeRate
  73. // + ". Max: " + maxdischargerate
  74. // + ". Target: " + targetRate
  75. // + ". Result: " + module:GETFIELD("percent power") to "dischargelog.log".
  76.  
  77. set dEC to dEC - currentDischargeRate + maxdischargerate * module:GETFIELD("percent power") / 100.
  78.  
  79. if abs(dEC - targetEC) < 10 { break. }
  80. }
  81. }
  82. // log "after " + dEC to "dischargelog.log".
  83. }
  84.  
  85. // After the currently discharging capacitors have been adjusted, if we are still losing
  86. // EC, it means that we need to trigger another one. We then simply trigger capacitors until
  87. // our EC is again flowing up (we could follow this up with another balancing, but we just leave
  88. // that for the next iteration).
  89. // This logic is not ideal in all cases. For instance, we have a series of smaller capacitors
  90. // that need to be fired in parallel, and some big capacitors that have to be fired alone
  91. // not to overflow, this logic will still trigger the big capacitor in conjunction with the
  92. // smaller ones.
  93. if dEC + 10 < targetEC {
  94. FOR capacitor in capacitors {
  95. set module to capacitor:GETMODULE("DischargeCapacitor").
  96. IF module:GETFIELD("status") = "Ready" {
  97. set max_rate to 100 * module:GETFIELD("adjusted discharge rate") / module:GETFIELD("percent power").
  98. // Firing at 100% power means that we reach targetEC in as few capacitors as possible.
  99. module:SETFIELD("percent power", 100).
  100. module:DOEVENT("discharge capacitor").
  101. set dEC to dEC + max_rate.
  102. // log "Discharging capacitor. Current rate " + dEC to "dischargelog.log".
  103. if dEC > targetEC { break. }
  104. }
  105. }
  106. }
  107. }
  108.  
  109. // Print a list of all currently discharging capacitor. At this build of kOS, string
  110. // manipulation is not in, so we have to check for "not ready" and "not discharged" because
  111. // the status string indicating discharging isn't static, and is postfixed by the amount
  112. // it's discharging with. Unfortunately, the string for recharging also has that postfix
  113. // which makes the code for checking "Is this capacitator discharging" inelegant.
  114. set i to 7.
  115. for capacitor in capacitors {
  116. set module to capacitor:GETMODULE("DischargeCapacitor").
  117. if module:GETFIELD("status") <> "Ready" AND module:GETFIELD("status") <> "Discharged!" AND not charging {
  118. print module:GETFIELD("status")
  119. + ". Store: " + round(capacitor:RESOURCES[0]:AMOUNT)
  120. + ". Time left: " + round(capacitor:RESOURCES[0]:AMOUNT / module:GETFIELD("adjusted discharge rate"), 2)
  121. + " seconds." at (5, i).
  122. set i to i + 1.
  123. }
  124. }
  125. set iterationLastPrint to i.
  126. until i >= lastPrint {
  127. print " " at (5, i).
  128. set i to i + 1.
  129. }
  130. set lastPrint to iterationLastPrint.
  131.  
  132. // We globally recharge all capacitors if we are either currently gaining more EC than
  133. // we are using (engines off typically). We also set them to charge if we are at full
  134. // capacity (because then we technically can't verify that we are gaining more than
  135. // we are using). Because the charging may use more power than we are generating, and
  136. // that could cause systems to shut down, we stop charging if we have less than 50% EC.
  137. if (EC:AMOUNT = EC:CAPACITY OR dTC > 0) AND EC:AMOUNT > EC:CAPACITY*0.5 AND charging = FALSE {
  138. FOR capacitor in capacitors {
  139. capacitor:GETMODULE("DischargeCapacitor"):DOACTION("enable charging", TRUE).
  140. }
  141. set charging to TRUE.
  142. } ELSE IF dTC < 0 and charging = TRUE {
  143. FOR capacitor in capacitors {
  144. capacitor:GETMODULE("DischargeCapacitor"):DOACTION("disable charging", TRUE).
  145. }
  146. set charging to FALSE.
  147. }
  148.  
  149. // Printing the status display
  150. print "Electric Charge: " + ROUND(EC:AMOUNT) + " / " + EC:CAPACITY + "(" + ROUND(100*EC:AMOUNT/EC:CAPACITY) + "%) [" + round(dEC) + "] " AT (3, 2).
  151. print "Stored Charge: " + ROUND(SC:AMOUNT) + " / " + SC:CAPACITY + "(" + ROUND(100*SC:AMOUNT/SC:CAPACITY) + "%) [" + round(dTC) + "] " at (3, 3).
  152. IF dTC < 0 {
  153. print "Time until empty at current rate: " + ROUND(-(SC:AMOUNT+EC:AMOUNT)/dTC) + " seconds " AT (3, 4).
  154. } ELSE IF dTC > 0 {
  155. print "Time until recharged at current rate: " + ROUND((SC:CAPACITY+EC:CAPACITY-SC:AMOUNT-EC:AMOUNT)/dTC) + " seconds " AT (3, 4).
  156. } ELSE {
  157. print " " AT (3, 4).
  158. }
  159. if charging = TRUE {
  160. print "Charging enabled " at (3, 5).
  161. } ELSE {
  162. print "Charging disabled" at (3, 5).
  163. }
  164. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement