Last active
July 17, 2023 18:06
-
-
Save CyberShadow/930bb7b89aa4073159955c5410d71154 to your computer and use it in GitHub Desktop.
Subnautica Cyclops energy efficiency Fandom table generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ae.utils.text; | |
import std.algorithm.comparison; | |
import std.algorithm.iteration; | |
import std.range; | |
import std.stdio; | |
/* | |
Old values: | |
|style="text-align: center; width: 25%;"|Ahead Slow | |
|style="text-align: center; width: 25%;"|9 ⚡/min | |
|style="text-align: center; width: 25%;"|7 m/sec | |
|style="text-align: center; width: 25%;"|45 m/⚡ | |
|- | |
|style="text-align: center; width: 25%;"|Ahead Standard | |
|style="text-align: center; width: 25%;"|20 ⚡/min | |
|style="text-align: center; width: 25%;"|9 m/sec | |
|style="text-align: center; width: 25%;"|27 m/⚡ | |
|- | |
|style="text-align: center; width: 25%;"|Ahead Flank | |
|style="text-align: center; width: 25%;"|40 ⚡/min | |
|style="text-align: center; width: 25%;"|12 m/sec | |
|style="text-align: center; width: 25%;"|16 m/⚡ | |
*/ | |
static immutable motorModeNoiseValues = [55, 70, 100]; | |
static immutable motorModeSpeeds = [4.68, 6.27, 7.3]; | |
static immutable motorModePowerConsumption = [0.075, 0.165, 0.33]; | |
// Measured empirically | |
static immutable double[3] speeds = [ | |
(1098-698)/60., | |
8.9 /*(1005-578)/60.*/, | |
(866-242)/60., | |
]; | |
enum sonarPowerCost = 10f; | |
enum pingIterationDuration = 5f; | |
enum silentRunningPowerCost = 5f; | |
enum silentRunningIteration = 5f; | |
enum shieldPowerCost = 50f; | |
enum shieldRunningIteration = 5f; | |
enum maxNoiseRange = 150f; // AttackCyclops::UpdateAggression() | |
void main() | |
{ | |
union Flags | |
{ | |
struct | |
{ | |
bool withSilentRunning; | |
bool withEfficiencyModule; | |
bool withSonar; | |
bool withShield; | |
} | |
bool[4] flags; | |
} | |
Flags flags; | |
static immutable string[] flagNames = [ | |
"Silent Running", | |
"Engine Efficiency Module", | |
"Sonar", | |
"Shield Generator", | |
]; | |
void iterateFlags(void delegate() cb, size_t index = 0) | |
{ | |
if (index == flags.flags.length) | |
cb(); | |
else | |
{ | |
// writeln(`{{Clear}}`); | |
if (index == 0) | |
writeln(`<div class="MainPageBox"><div class="lostRiverTabber"><tabber>`); | |
else | |
writeln(`{{#tag:tabber|`); | |
foreach (value; [false, true]) | |
{ | |
flags.flags[index] = value; | |
writefln("%s %s=", ["Without", "With"][value], flagNames[index]); | |
iterateFlags(cb, index + 1); | |
if (value == false) | |
{ | |
if (index == 0) | |
writeln("|-|"); | |
else | |
writeln("{{!}}-{{!}}"); | |
} | |
} | |
if (index == 0) | |
writeln(`</tabber></div></div>`); | |
else | |
writeln(`}}`); | |
} | |
} | |
writeln("<!-- Generated using https://gist.github.com/CyberShadow/930bb7b89aa4073159955c5410d71154 -->"); | |
iterateFlags({ | |
write(q"EOF | |
<table style="width: 100%;" class="article-table" cellspacing="1" cellpadding="1" border="1" align="center"> | |
<tr> | |
<th scope="col" style="text-align: center; width: 25%;">'''Speed Setting'''</th> | |
<th scope="col" style="text-align: center; width: 25%;">'''Energy Consumption Rate (⚡/Min)'''</th> | |
<th scope="col" style="text-align: center; width: 25%;">'''Acceleration (Meters/Sec²)'''</th> | |
<th scope="col" style="text-align: center; width: 25%;">'''Top speed (Meters/Sec)'''</th> | |
<th scope="col" style="text-align: center; width: 25%;">'''Efficiency (Meters/⚡)'''</th> | |
<th scope="col" style="text-align: center; width: 25%;">'''Noise reach (Meters)'''</th> | |
</tr> | |
EOF"); | |
struct Result | |
{ | |
double energyConsumption; | |
double acceleration; | |
double topSpeed; | |
double noise; | |
double noiseRange; | |
double efficiency; | |
} | |
Result calculate(Flags flags, size_t motorMode) | |
{ | |
Result result; | |
result.energyConsumption = motorModePowerConsumption[motorMode]; | |
result.acceleration = motorModeSpeeds[motorMode]; | |
result.topSpeed = speeds[motorMode]; | |
result.noise = motorModeNoiseValues[motorMode]; | |
if (flags.withSilentRunning) | |
{ | |
result.energyConsumption += silentRunningPowerCost / silentRunningIteration; | |
result.noise /= 2; | |
} | |
if (flags.withEfficiencyModule) | |
result.energyConsumption /= 3; | |
if (flags.withSonar) | |
result.energyConsumption += (sonarPowerCost / pingIterationDuration); | |
if (flags.withShield) | |
result.energyConsumption += (shieldPowerCost / shieldRunningIteration); | |
result.efficiency = result.topSpeed / result.energyConsumption; | |
result.noiseRange = result.noise / 100 * maxNoiseRange; | |
return result; | |
} | |
Result[3] results = 3.iota.map!(motorMode => calculate(flags, motorMode)).array; | |
auto bestEfficiency = results[].map!(result => result.efficiency).reduce!max; | |
foreach (motorMode, result; results) | |
{ | |
writef(q"EOF | |
<tr> | |
<td style="text-align: center; width: 25%%;">%s</td> | |
<td style="text-align: center; width: 25%%;">%1.1f ⚡/min</td> | |
<td style="text-align: center; width: 25%%;">%1.1f m/s²</td> | |
<td style="text-align: center; width: 25%%;">%1.1f m/s</td> | |
<td style="text-align: center; width: 25%%;">%s%1.1f m/⚡%s</td> | |
<td style="text-align: center; width: 25%%;">%s m</td> | |
</tr> | |
EOF", | |
["Ahead Slow", "Ahead Standard", "Ahead Flank"][motorMode], | |
result.energyConsumption * 60, | |
result.acceleration, | |
result.topSpeed, | |
result.efficiency == bestEfficiency ? "'''" : "", result.efficiency, result.efficiency == bestEfficiency ? "'''" : "", | |
result.noiseRange.doubleToString, | |
); | |
} | |
writeln("</table>"); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment