Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // NTSL Telescience Calculator!
- //
- // Does all the Telescience work for you,
- // without any external program accusations.
- // Bruteforces through everything, so is
- // guaranteed to be 100% accurate.
- //
- // Change $opfreq to whatever frequency you
- // want to use it on.
- //
- // Commands:
- //
- // "reset"
- //
- // Resets the calibration data for
- // this run. This is called the first time
- // the program is run.
- //
- // "help"
- //
- // Displays (more concise) usage information
- // on these commands.
- //
- // "calibrate <bearing> <elevation> <power>
- // <result_x> <result_y> <source_x> <source_y"
- //
- // Calibrates on the given data. Will report
- // on the currently achievable accuracy when
- // finished. Result X and Y are where the GPS
- // device ended up, and Source X and Y are the
- // coordinates of the Telepad.
- //
- // Because NTSL only accepts a certain amount
- // of function calls per run, calibrating will
- // require several runs at the start. Just trigger
- // it by saying anything to have it continue.
- //
- // "target <dest_x> <dest_y> <power> <source_x>
- // <source_y>"
- //
- // Computes the Telescience settings needed
- // to reach (dest_x, dest_y) with the given
- // power, and the given telepad location.
- // Will report if unreachable.
- //
- // "apply <power_offset> <bearing_offset>"
- //
- // Takes the given offsets as truth and applies
- // them. Interoperability!
- //
- // "get"
- //
- // Gets the determined offsets. Only works if
- // it's calibrated properly!
- //
- // Be sure to use appropiate precision! This
- // means limiting the Elevation to one digit
- // after the period, and Bearing to two digits
- // after the period.
- //
- // Made by Braincake, pretty much a direct
- // port of the existing C# calculator.
- $opfreq = 1449;
- // Don't change this unless they change the NTSL
- // function call restrictions
- $max_calcs = 30;
- // Degrees to radians
- def toRadian($angle) {
- return $angle * (PI/180);
- }
- // Radians to degrees
- def toDegree($angle) {
- return $angle * (180/PI);
- }
- // Tangent function, in radians
- def tan($angle) {
- return sin($angle) / cos($angle);
- }
- // Inverse tangent function, in radians
- def atan($angle) {
- return toRadian(asin($angle / sqrt($angle^2 + 1)));
- }
- // Atan2
- def atan2($y, $x) {
- if ($x > 0) {
- return atan($y / $x);
- }
- if ($y >= 0 && $x < 0) {
- return atan($y / $x) + PI;
- }
- if ($y < 0 && $x < 0) {
- return atan($y / $x) - PI;
- }
- if ($y > 0 && $x == 0) {
- return PI/2;
- }
- if ($y < 0 && $x == 0) {
- return 0-PI/2;
- }
- }
- // Modulus function, $a % $b
- def mod($a, $b) {
- return $a - $b * floor($a / $b);
- }
- // BYOND degree to scientific degree
- def toScientific($angle) {
- return mod(360 - $angle + 90, 360);
- }
- // Scientific degree to BYOND degree
- def fromScientific($angle) {
- return mod(360 - $angle + 90, 360);
- }
- // Sends a message
- def send($message) {
- broadcast($message, $opfreq, "Telescience", "Calculator");
- }
- // Clear and create the initial offsets
- def reset() {
- // Boundaries
- $pow_min = -4;
- $pow_max = 0;
- $ha_min = -10;
- $ha_max = 10;
- // Keep track
- $pow_offsets = vector();
- $ha_offsets = vector();
- $pow = $pow_min;
- // Fill them
- while ($pow <= $pow_max) {
- $ha = $ha_min;
- while ($ha <= $ha_max) {
- push_back($pow_offsets, $pow);
- push_back($ha_offsets, $ha);
- $ha += 1;
- }
- $pow += 1;
- }
- // Store them, overwrite existing
- mem("pow_offsets", $pow_offsets);
- mem("ha_offsets", $ha_offsets);
- mem("total_offsets", 105);
- // Done, report
- send("Offsets initialized!");
- }
- // Apply specified calibration settings
- def calibrate($bearing, $elevation, $power, $result_x, $result_y, $source_x, $source_y) {
- // Retrieve remaining offsets
- $old_pow_offsets = mem("pow_offsets");
- $old_ha_offsets = mem("ha_offsets");
- $old_total_offsets = mem("total_offsets");
- // Keep track of the new stuff
- $new_pow_offsets = vector();
- $new_ha_offsets = vector();
- $new_total_offsets = 0;
- $index = 1;
- $count = 1;
- // Do we need to continue a computation?
- if (mem("continue")) {
- $new_pow_offsets = mem("temp_pow_offsets");
- $new_ha_offsets = mem("temp_ha_offsets");
- $new_total_offsets = mem("temp_total_offsets");
- $index = mem("temp_index");
- }
- // Bruteforce through them
- while ($index <= $old_total_offsets) {
- // Are we at the quota yet?
- if ($count > $max_calcs) {
- // Store the temporary information, then break
- mem("temp_pow_offsets", $new_pow_offsets);
- mem("temp_ha_offsets", $new_ha_offsets);
- mem("temp_total_offsets", $new_total_offsets);
- mem("temp_index", $index);
- mem("continue", 1);
- break;
- }
- // Get some information
- $current_pow_offset = at($old_pow_offsets, $index);
- $current_ha_offset = at($old_ha_offsets, $index);
- // Assume that this offset is true, then run the numbers
- // Get the actual bearing
- $actual_bearing = mod($bearing + $current_ha_offset, 360);
- // Convert it to scientific radians
- $actual_ha = toRadian(toScientific($actual_bearing));
- // Convert the elevation to scientific radians
- $actual_va = toRadian($elevation);
- // Get the actual velocity
- $actual_vel = $power + $current_pow_offset;
- // Compute the range, G = 10
- $range = $actual_vel^2 * sin(toDegree(2 * $actual_va)) / 10;
- // Compute delta X and Y
- $delta_x = $range * cos(toDegree($actual_ha));
- $delta_y = $range * sin(toDegree($actual_ha));
- // Compute destination X and Y
- $dest_x = round($source_x + $delta_x);
- $dest_y = round($source_y + $delta_y);
- // Check if this matches the provided coordinates
- if ($dest_x == $result_x && $dest_y == $result_y) {
- // We got a match! Add it
- push_back($new_pow_offsets, $current_pow_offset);
- push_back($new_ha_offsets, $current_ha_offset);
- $new_total_offsets += 1;
- }
- // Next iteration
- $index += 1;
- $count += 1;
- }
- // If we're really done, store everything and report
- if ($index > $old_total_offsets) {
- mem("pow_offsets", $new_pow_offsets);
- mem("ha_offsets", $new_ha_offsets);
- mem("total_offsets", $new_total_offsets);
- mem("continue", 0);
- // Report
- $report = tostring($new_total_offsets) + " offsets left! ";
- if ($new_total_offsets == 0) {
- $report += "Impossible, please reset!";
- mem("reset", 0);
- }
- if ($new_total_offsets == 1) {
- $report += "Perfectly accurate!";
- }
- if ($new_total_offsets > 1) {
- $report += "Not quite accurate yet!";
- }
- send($report);
- }
- }
- // Computes the bearing and elevation required for the given destination
- def target($dest_x, $dest_y, $power, $source_x, $source_y) {
- // Retrieve the best offsets
- $pow_offsets = mem("pow_offsets");
- $ha_offsets = mem("ha_offsets");
- $pow_offset = at($pow_offsets, 1);
- $ha_offset = at($ha_offsets, 1);
- // Compute delta X and Y
- $delta_x = $dest_x - $source_x;
- $delta_y = $dest_y - $source_y;
- // Compute the distance we need
- $dist = sqrt($delta_x^2 + $delta_y^2);
- // Get the actual power
- $actual_pow = $power + $pow_offset;
- // Get the maximum distance achievable
- $max_range = $actual_pow^2 * sin(2 * 45) / 10;
- // Check
- if ($dist > $max_range) {
- send("That target is out of range!");
- } else {
- // Compute the bearing we need
- $atan2_result = atan2($delta_y, $delta_x);
- $bearing = mod(toDegree($atan2_result), 360);
- // Convert it
- $bearing = fromScientific($bearing);
- // Modify it with the offset
- $bearing -= $ha_offset;
- // Round it to two decimals
- $bearing = round($bearing * 100) / 100;
- // Compute the vertical angle we need
- $elevation = 0.5 * asin(10 * $dist / $actual_pow^2);
- // Round it as well
- $elevation = round($elevation * 10) / 10;
- // All done! Report it
- $report = "Bearing = " + tostring($bearing) + " , Elevation = " + tostring($elevation);
- send($report);
- }
- }
- // Applies a given power and bearing offset
- def apply($pow_offset, $ha_offset) {
- $pow_offsets = vector($pow_offset);
- $ha_offsets = vector($ha_offset);
- $total_offsets = 1;
- mem("reset", 1);
- mem("pow_offsets", $pow_offsets);
- mem("ha_offsets", $ha_offsets);
- mem("total_offsets", $total_offsets);
- send("Applied given offsets! Assuming they were accurate, you can now target!");
- }
- // Gets the offsets and displays them
- def get() {
- $total_offsets = mem("total_offsets");
- if ($total_offsets == 1) {
- $pow_offsets = mem("pow_offsets");
- $ha_offsets = mem("ha_offsets");
- $pow_offset = at($pow_offsets, 1);
- $ha_offset = at($ha_offsets, 1);
- $report = "Power offset: " + tostring($pow_offset) + " , Bearing offset: " + tostring($ha_offset);
- send($report);
- } else {
- send("We're not accurate enough to have proper offsets!");
- }
- }
- // Turn a list of <command, num1, num2, ...> into a number vector
- def tonums($command_vec) {
- $index = 2;
- $total = length($command_vec);
- $result = vector();
- while ($index <= $total) {
- $textv = at($command_vec, $index);
- $numv = tonum($textv);
- push_back($result, $numv);
- $index += 1;
- }
- return $result;
- }
- // Initialisation
- if (!mem("init")) {
- mem("continue", 0);
- mem("reset", 0);
- mem("init", 1);
- }
- // Command processing
- if ($freq == $opfreq) {
- // If we're still computing, make a nice progress report, then continue
- if (mem("continue")) {
- $report = "Still computing, currently at ";
- $total = mem("total_offsets");
- $current = mem("temp_index");
- $percent = round($current / $total * 100);
- $report += tostring($percent) + "%!";
- send($report);
- $params = mem("calibrate_params");
- $bearing = at($params, 1);
- $elevation = at($params, 2);
- $power = at($params, 3);
- $result_x = at($params, 4);
- $result_y = at($params, 5);
- $source_x = at($params, 6);
- $source_y = at($params, 7);
- calibrate($bearing, $elevation, $power, $result_x, $result_y, $source_x, $source_y);
- } else {
- // Check for commands
- $commanded = 0;
- $words = explode($content, " ");
- $first = at($words, 1);
- $first = lower($first);
- if ($first == "reset") {
- reset();
- mem("reset", 1);
- $commanded = 1;
- }
- if ($first == "help") {
- send("NTSL Telescience Calculator! To view this line, use 'help'. To reset the calibration, use 'reset'. To calibrate, use 'calibrate bearing elevation power result_x result_y source_x source_y'. To compute, use 'target dest_x dest_y power source_x source_y'. To transfer, use 'apply power_offset bearing_offset'. Have fun!");
- $commanded = 1;
- }
- if ($first == "calibrate") {
- if (mem("reset")) {
- send("Calibrating!");
- $params = tonums($words);
- mem("calibrate_params", $params);
- $bearing = at($params, 1);
- $elevation = at($params, 2);
- $power = at($params, 3);
- $result_x = at($params, 4);
- $result_y = at($params, 5);
- $source_x = at($params, 6);
- $source_y = at($params, 7);
- calibrate($bearing, $elevation, $power, $result_x, $result_y, $source_x, $source_y);
- } else {
- send("You should reset before calibrating!");
- }
- $commanded = 1;
- }
- if ($first == "target") {
- if (mem("reset")) {
- $params = tonums($words);
- $dest_x = at($params, 1);
- $dest_y = at($params, 2);
- $power = at($params, 3);
- $source_x = at($params, 4);
- $source_y = at($params, 5);
- target($dest_x, $dest_y, $power, $source_x, $source_y);
- } else {
- send("You should calibrate properly first!");
- }
- $commanded = 1;
- }
- if ($first == "apply") {
- $params = tonums($words);
- $pow_offset = at($params, 1);
- $ha_offset = at($params, 2);
- apply($dest_x, $dest_y, $power, $source_x, $source_y);
- $commanded = 1;
- }
- if ($first == "get") {
- if (mem("reset")) {
- get();
- } else {
- send("You should initialize first!");
- }
- $commanded = 1;
- }
- // Display generic help if the command is unknown
- if (!$commanded) {
- send("Unknown command! Use 'help' for a list of commands and their usage!");
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement