Merge remote branch 'origin/master'
commit
ffb1238b02
|
@ -1,12 +1,17 @@
|
|||
<?php
|
||||
require_once("includes/functions.inc.php");
|
||||
require_once("includes/config.inc.php");
|
||||
|
||||
$action = $_GET['action'];
|
||||
|
||||
$software_available = array("gfs", "gfs_hd");
|
||||
|
||||
switch($action) {
|
||||
case "getCSV":
|
||||
$uuid = $_GET['uuid'];
|
||||
$fh = fopen("preds/".$uuid."/flight_path.csv", "r");
|
||||
$tryfile = $c_preds_path.$uuid."/".$c_flight_csv;
|
||||
if(!file_exists($tryfile)) return false;
|
||||
$fh = fopen($tryfile, "r");
|
||||
$data = array();
|
||||
while (!feof($fh)) {
|
||||
$line = trim(fgets($fh));
|
||||
|
@ -18,16 +23,34 @@ case "getCSV":
|
|||
|
||||
case "JSONexists":
|
||||
$uuid = $_GET['uuid'];
|
||||
if(file_exists("preds/$uuid/progress.json")) {
|
||||
if(file_exists($c_preds_path.$uuid."/".$c_progress_json)) {
|
||||
echo true;
|
||||
} else {
|
||||
echo false;
|
||||
}
|
||||
break;
|
||||
|
||||
case "submitForm":
|
||||
$software_available = array("gfs", "gfs_hd");
|
||||
case "getModelByUUID":
|
||||
$uuid = ( isset($_GET['uuid']) ? $_GET['uuid'] : false );
|
||||
if( !uuid ) die ("No uuid given to getModelByUUID");
|
||||
// make a new model
|
||||
$pred_model = array();
|
||||
if ( !file_exists($c_preds_path.$uuid."/".$c_scenario_file) ) {
|
||||
$pred_model['valid'] = false;
|
||||
} else {
|
||||
// populate the array, JSON encode it and return
|
||||
$pred_model = parse_ini_file($c_preds_path.$uuid."/".$c_scenario_file);
|
||||
if ( verifyModel($pred_model, $software_available) ){
|
||||
$pred_model['valid'] = true;
|
||||
} else {
|
||||
$pred_model['valid'] = false;
|
||||
}
|
||||
$pred_model['uuid'] = $uuid;
|
||||
}
|
||||
echo json_encode($pred_model);
|
||||
break;
|
||||
|
||||
case "submitForm":
|
||||
$pred_model = array();
|
||||
|
||||
if ( isset($_POST['submit'])) {
|
||||
|
|
|
@ -8,13 +8,13 @@ body {
|
|||
margin: 0; padding: 0;
|
||||
}
|
||||
|
||||
a:link { text-decoration: underline; color: #333 }
|
||||
a:active { text-decoration: underline; color: #333; }
|
||||
a:hover { text-decoration: underline; color: #333; }
|
||||
a:visited { text-decoration: underline; color: #333; }
|
||||
a { text-decoration: underline; color: #333; cursor: pointer; }
|
||||
|
||||
/* The whoppping map in the centre */
|
||||
#map_canvas { width: 100%; height: 100%; }
|
||||
#map_canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#status_message{
|
||||
position: absolute;
|
||||
|
@ -29,6 +29,30 @@ a:visited { text-decoration: underline; color: #333; }
|
|||
display: none;
|
||||
}
|
||||
|
||||
#error_window {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 400px;
|
||||
margin-left: -200px;
|
||||
margin-top: -50px;
|
||||
padding: 1em;
|
||||
text-align: center;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#about_window {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 500px;
|
||||
margin-left: -250px;
|
||||
margin-top: -120px;
|
||||
padding: 1em;
|
||||
text-align: center;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.box {
|
||||
position: absolute;
|
||||
background-color: white;
|
||||
|
@ -72,16 +96,30 @@ a:visited { text-decoration: underline; color: #333; }
|
|||
left: 0; bottom: 0;
|
||||
border-left: none;
|
||||
border-bottom: none;
|
||||
max-height: 400px;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
#input_form {
|
||||
right: 0; bottom: 0;
|
||||
border-right: none;
|
||||
border-bottom: none;
|
||||
height:370px;
|
||||
width: 400px;
|
||||
height:350px;
|
||||
padding: 5px;
|
||||
bottom: 0; right: 0;
|
||||
}
|
||||
|
||||
#scenario_info {
|
||||
position: absolute;
|
||||
top: 25px;
|
||||
right: 0px;
|
||||
border-right: none;
|
||||
width: 400px;
|
||||
text-align:center;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
|
||||
td.right-td {
|
||||
text-align: right;
|
||||
}
|
||||
|
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 575 B |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 432 B |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 521 B |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 557 B |
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
$c_preds_path = "preds/";
|
||||
|
||||
$c_scenario_file = "scenario.ini";
|
||||
$c_flight_csv = "flight_path.csv";
|
||||
$c_progress_json = "progress.json";
|
||||
|
||||
?>
|
|
@ -9,13 +9,13 @@ function createModel($post_array) {
|
|||
$pred_model = array();
|
||||
|
||||
// first, populate the prediction model
|
||||
$pred_model['hour'] = $post_array['hour'] + 1; //adjust for GMT
|
||||
$pred_model['min'] = $post_array['min'];
|
||||
$pred_model['sec'] = $post_array['sec'];
|
||||
$pred_model['hour'] = (int)$post_array['hour']; //adjust for GMT
|
||||
$pred_model['min'] = (int)$post_array['min'];
|
||||
$pred_model['sec'] = (int)$post_array['sec'];
|
||||
|
||||
$pred_model['month'] = $post_array['month'];
|
||||
$pred_model['day'] = $post_array['day'];
|
||||
$pred_model['year'] = $post_array['year'];
|
||||
$pred_model['month'] = (int)$post_array['month'];
|
||||
$pred_model['day'] = (int)$post_array['day'];
|
||||
$pred_model['year'] = (int)$post_array['year'];
|
||||
|
||||
$pred_model['lat'] = $post_array['lat'];
|
||||
$pred_model['lon'] = $post_array['lon'];
|
||||
|
@ -23,7 +23,9 @@ function createModel($post_array) {
|
|||
$pred_model['alt'] = $post_array['initial_alt'];
|
||||
$pred_model['des'] = $post_array['drag'];
|
||||
$pred_model['burst'] = $post_array['burst'];
|
||||
$pred_model['float'] = $post_array['float_time'];
|
||||
|
||||
$pred_model['delta_lat'] = $post_array['delta_lat'];
|
||||
$pred_model['delta_lon'] = $post_array['delta_lon'];
|
||||
|
||||
$pred_model['wind_error'] = 0;
|
||||
|
||||
|
@ -55,10 +57,10 @@ function verifyModel($pred_model, $software_available) {
|
|||
foreach($pred_model as $idx => $value) {
|
||||
if ($idx == "software") {
|
||||
if (!in_array($value, $software_available)) return false;
|
||||
} else {
|
||||
if (!is_numeric($value)) {
|
||||
return false;
|
||||
}
|
||||
} else if ($idx == "delta_lat" || $idx == "delta_lon") {
|
||||
if ( $value < 1 || $value > 10 ) return false;
|
||||
} else if (!is_numeric($value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -77,7 +79,11 @@ function runPred($pred_model) {
|
|||
|
||||
// use `at` to automatically background the task
|
||||
$ph = popen("at now", "w");
|
||||
fwrite($ph, "cd /var/www/hab/predict/ && ./predict.py -v --latdelta=3 --londelta=3 -p1 -f5 -t ".$pred_model['timestamp']." --lat=".$predictor_lat." --lon=".$predictor_lon." " . $use_hd . $pred_model['uuid']);
|
||||
fwrite($ph, "cd /var/www/hab/predict/ && ./predict.py -v --latdelta="
|
||||
.$pred_model['delta_lat']." --londelta=".$pred_model['delta_lon']
|
||||
." -p1 -f5 -t ".$pred_model['timestamp']
|
||||
." --lat=".$predictor_lat." --lon=".$predictor_lon." " . $use_hd
|
||||
. $pred_model['uuid']);
|
||||
fclose($ph);
|
||||
|
||||
}
|
||||
|
@ -97,10 +103,22 @@ function makeINI($pred_model) { // makes an ini file
|
|||
$w_string .= "month = " . $pred_model['month'] . "\nsecond = " . $pred_model['sec'] . "\n";
|
||||
$w_string .= "year = " . $pred_model['year'] . "\nday = " . $pred_model['day'] . "\nminute = ";
|
||||
$w_string .= $pred_model['min'] . "\n";
|
||||
// add our predictor stuff
|
||||
$w_string .= "[predictor]\nlat-delta = " . $pred_model['delta_lat'] . "\n";
|
||||
$w_string .= "lon-delta = " . $pred_model['delta_lon'] . "\nsoftware = ";
|
||||
$w_string .= $pred_model['software'] . "\n";
|
||||
|
||||
fwrite($fh, $w_string);
|
||||
fclose($fh);
|
||||
}
|
||||
|
||||
function getModelByUUID($uuid) {
|
||||
if ( file_exists("preds/".$uuid."/scenario.ini") ) {
|
||||
$pred_model = parse_ini_file("preds/".$uuid."/scenario.ini");
|
||||
return $pred_model;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
<?php
|
||||
require_once("includes/functions.inc.php");
|
||||
// get the time for pre-populating the form
|
||||
$time = time() + 3600;
|
||||
$current_uuid = ( isset($_GET['uuid'])? $_GET['uuid'] : "0" );
|
||||
// if we were given a UUID, try and construct its model
|
||||
if ( $current_uuid != 0 ) {
|
||||
if ( $pred_model = getModelByUUID($current_uuid) ) {
|
||||
} else {
|
||||
// assume we weren't given a UUID (bad FIXME)
|
||||
$current_uuid = 0;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<html>
|
||||
|
@ -21,47 +31,98 @@ google.load("jqueryui", "1.8.1");
|
|||
<script type="text/javascript">
|
||||
|
||||
var ajaxEventHandle;
|
||||
var running_uuid = '<?php echo ( isset($_GET['uuid'])? $_GET['uuid'] : "0" ); ?>';
|
||||
var current_uuid = '<?php echo $current_uuid ?>';
|
||||
|
||||
var map;
|
||||
var map_items = [];
|
||||
var launch_img = "images/marker-sm-red.png";
|
||||
var land_img = "images/marker-sm-red.png";
|
||||
var launch_img = "images/target-1-sm.png";
|
||||
var land_img = "images/target-8-sm.png";
|
||||
var burst_img = "images/pop-marker.png";
|
||||
var clickListener;
|
||||
var clickMarker;
|
||||
|
||||
function initialize() {
|
||||
if(window.location.hash != "") {
|
||||
var ln = window.location.hash.split("=");
|
||||
current_uuid = ln[1];
|
||||
}
|
||||
// make the map and set center
|
||||
var latlng = new google.maps.LatLng(52, 0);
|
||||
var myOptions = {
|
||||
zoom: 8,
|
||||
scaleControl: true,
|
||||
scaleControlOptions: { position: google.maps.ControlPosition.BOTTOM_LEFT } ,
|
||||
mapTypeId: google.maps.MapTypeId.TERRAIN,
|
||||
center: latlng,
|
||||
mapTypeId: google.maps.MapTypeId.ROADMAP
|
||||
};
|
||||
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
|
||||
// submit the form here
|
||||
// attach form submit event handler to launch card
|
||||
$("#modelForm").ajaxForm({
|
||||
url: 'ajax.php?action=submitForm',
|
||||
type: 'POST',
|
||||
success: function(data) {
|
||||
predSub();
|
||||
var data_split = data.split("|");
|
||||
if ( data_split[0] == 0 ) {
|
||||
appendDebug("The server rejected the submitted form data");
|
||||
throwError("The server rejected the submitted form data");
|
||||
resetGUI();
|
||||
} else {
|
||||
predSub();
|
||||
appendDebug("The server accepted the form data");
|
||||
running_uuid = data_split[1];
|
||||
appendDebug("The server gave us uuid:<br>" + running_uuid);
|
||||
// update the global current_uuid variable
|
||||
current_uuid = data_split[1];
|
||||
appendDebug("The server gave us uuid:<br>" + current_uuid);
|
||||
appendDebug("Starting to poll for progress JSON");
|
||||
handlePred(running_uuid);
|
||||
handlePred(current_uuid);
|
||||
}
|
||||
}
|
||||
});
|
||||
//$("#input_form").draggable({containment: '#map_canvas'});
|
||||
// if ( running_uuid != 0 ) handlePred(running_uuid);
|
||||
$("#debuginfo").hide();
|
||||
// activate the "Set with Map" link
|
||||
$("#setWithClick").click(function() {
|
||||
setLatLonByClick(true);
|
||||
});
|
||||
// attach onchange handlers to the lat/long boxes
|
||||
$("#lat").change(function() {
|
||||
plotClick();
|
||||
});
|
||||
$("#lon").change(function() {
|
||||
plotClick();
|
||||
});
|
||||
$("#site").change(function() {
|
||||
plotClick();
|
||||
});
|
||||
$("#input_form").draggable({containment: '#map_canvas'});
|
||||
if ( current_uuid != '0' ) {
|
||||
appendDebug("Got an old UUID to plot:<br>" + current_uuid);
|
||||
appendDebug("Trying to populate form with scenario data");
|
||||
populateFormByUUID(current_uuid);
|
||||
appendDebug("Trying to get flight path from server...");
|
||||
getCSV(current_uuid);
|
||||
}
|
||||
$("#scenario_template").hide();
|
||||
$("#showHideDebug").click(function() {
|
||||
// $("#debuginfo").show("slide", { direction: "down" }, 500);
|
||||
toggleDebugWindow();
|
||||
toggleWindow("scenario_template", "showHideDebug", "Show Debug", "Hide Debug");
|
||||
});
|
||||
$("#showHideDebug_status").click(function() {
|
||||
toggleWindow("scenario_template", "showHideDebug", "Show Debug", "Hide Debug");
|
||||
});
|
||||
$("#showHideForm").click(function() {
|
||||
toggleWindow("input_form", "showHideForm", "Show Launch Card",
|
||||
"Hide Launch Card");
|
||||
});
|
||||
$("#closeErrorWindow").click(function() {
|
||||
$("#error_window").fadeOut();
|
||||
});
|
||||
$("#about_window_close").click(function() {
|
||||
$("#about_window").fadeOut();
|
||||
});
|
||||
$("#about_window_show").click(function() {
|
||||
$("#about_window").fadeIn();
|
||||
});
|
||||
// plot the initial launch location
|
||||
plotClick();
|
||||
google.maps.event.addListener(map, 'mousemove', function(event) {
|
||||
showMousePos(event.latLng);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -74,9 +135,7 @@ function initialize() {
|
|||
<div id="map_canvas" style="width:100%; height:100%"></div>
|
||||
|
||||
<div id="scenario_template" class="box">
|
||||
<h1>Debug Window -
|
||||
<a href='#'><span id="showHideDebug">Show</span></a></span>
|
||||
</h1>
|
||||
<h1>Debug Window</h1>
|
||||
<span id="debuginfo">No Messages</span>
|
||||
</div>
|
||||
|
||||
|
@ -84,7 +143,48 @@ function initialize() {
|
|||
<div id="prediction_progress"></div>
|
||||
<div id="prediction_percent"></div>
|
||||
<br>
|
||||
<div id="prediction_status"></div>
|
||||
<span id="prediction_status"></span><br>
|
||||
<a><span id="showHideDebug_status">Toggle Debug</span></a></span>
|
||||
</div>
|
||||
|
||||
<div id="error_window" class="box">
|
||||
<span id="error_message">Nothing here!</span>
|
||||
<br /><br />
|
||||
<a id="closeErrorWindow">Close</a>
|
||||
</div>
|
||||
|
||||
<!-- scenario info -->
|
||||
<div id="scenario_info" class="box">
|
||||
<h1>Scenario Information</h1>
|
||||
<span id="cursor_info">Current mouse position:
|
||||
Lat: <span id="cursor_lat">?</span>
|
||||
Lon: <span id="cursor_lon">?</span>
|
||||
</span><br />
|
||||
<span id="cursor_pred" style="display:none">
|
||||
Range: <span id="cursor_pred_range"></span>km,
|
||||
Flight Time: <span id="cursor_pred_time"></span><br />
|
||||
Cursor range from launch: <span id="cursor_pred_launchrange">?</span>km,
|
||||
land: <span id="cursor_pred_landrange">?</span>km
|
||||
</span>
|
||||
<br />
|
||||
<a><span id="showHideDebug">Show Debug</span></a></span> |
|
||||
<a><span id="showHideForm">Hide Launch Card</span></a></span>
|
||||
<br />
|
||||
<a style="font-size: 10px" id="about_window_show">About this software</a>
|
||||
</div>
|
||||
|
||||
<!-- the about window -->
|
||||
<div id="about_window" class="box">
|
||||
<b>Cambridge University Spaceflight Landing Predictor</b>
|
||||
<br /><br />
|
||||
A tool to predict the flight path and landing location of latex sounding balloons based on wind data from the NOAA.
|
||||
<br /><br />
|
||||
Written by <a href="http://github.com/jonsowman" target="_blank">Jon Sowman</a> and <a href="http://github.com/randomskk" target="_blank">Adam Greig</a> for <a href="http://www.cuspaceflight.co.uk" target="_blank">CUSF</a>.
|
||||
Credit also to <a href="http://github.com/rjw57" target="_blank">Rich Wareham</a> for work on the predictor. Some parts of code taken from old landing prediction software, credit to Rob Anderson, Fergus Noble and Ed Moore.
|
||||
<br /><br />
|
||||
No guarantee is given for the accuracy, precision or reliability of the data produced by this softare, and you use it at your own risk.
|
||||
<br /><br />
|
||||
<a id="about_window_close">Close</a>
|
||||
</div>
|
||||
|
||||
<div id="input_form" class="box">
|
||||
|
@ -99,67 +199,101 @@ function initialize() {
|
|||
<option value="Glenrothes">Glenrothes</option>
|
||||
<option value="Bujaraloz, Monegros">Bujaraloz, Monegros</option>
|
||||
<option value="Adelaide Airport">Adelaide Airport</option>
|
||||
<option id="other" value="other">Other</option>
|
||||
<option id="other" value="other"<?php
|
||||
if ($current_uuid !=0) echo " selected=\"selected\"";
|
||||
?>>Other</option>
|
||||
</select>
|
||||
</td>
|
||||
<tr>
|
||||
<td>Latitude:</td>
|
||||
<td><input id="lat" type="text" name="lat" value="52.2135" onKeyDown="SetSiteOther()"></td>
|
||||
<td><input id="lat" type="text" name="lat" value="<?php
|
||||
echo ($current_uuid!=0 ? $pred_model['latitude'] : "52.2135");
|
||||
?>" onKeyDown="SetSiteOther()"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Longitude:</td>
|
||||
<td><input id="lon" type="text" name="lon" value="0.0964" onKeyDown="SetSiteOther()"></td>
|
||||
<td><input id="lon" type="text" name="lon" value="<?php
|
||||
echo ($current_uuid!=0 ? $pred_model['longitude'] : "0.0964");
|
||||
?>" onKeyDown="SetSiteOther()"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="setWithClick">Set with map</a></td>
|
||||
<td><a id="requestLocationSave">Request to save</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Launch altitude (m):</td>
|
||||
<td><input id="initial_alt" type="text" name="initial_alt" value="0"></td>
|
||||
<td><input id="initial_alt" type="text" name="initial_alt" value="<?php
|
||||
echo ($current_uuid!=0 ? $pred_model['altitude'] : "0");?>"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Launch Time:</td>
|
||||
<td>
|
||||
<input id="hour" type="text" name="hour" value="<?php echo date("H", $time); ?>" maxlength="2" size="2"> :
|
||||
<input id="min" type="text" name="min" value="<?php echo date("i", $time); ?>" maxlength="2" size="2">
|
||||
<input id="sec" type="hidden" name="sec" value="0"></td></tr>
|
||||
<input id="hour" type="text" name="hour" value="<?php
|
||||
echo ($current_uuid!=0 ? $pred_model['hour'] : date("H", $time));
|
||||
?>" maxlength="2" size="2"> :
|
||||
<input id="min" type="text" name="min" value="<?php
|
||||
echo ($current_uuid!=0 ? $pred_model['minute'] : date("i", $time));
|
||||
?>" maxlength="2" size="2">
|
||||
<input id="sec" type="hidden" name="second" value="0"></td></tr>
|
||||
<tr><td>Launch Date:</td><td>
|
||||
<input id="day" type="text" name="day" value="<?php echo date("d", $time); ?>" maxlength="2" size="2">
|
||||
<select id="month" name="month">
|
||||
<option value="1"<?php if (date("n", $time) == 1) echo " selected"; ?>>Jan</option>
|
||||
<option value="2"<?php if (date("n", $time) == 2) echo " selected"; ?>>Feb</option>
|
||||
<option value="3"<?php if (date("n", $time) == 3) echo " selected"; ?>>Mar</option>
|
||||
<option value="4"<?php if (date("n", $time) == 4) echo " selected"; ?>>Apr</option>
|
||||
<option value="5"<?php if (date("n", $time) == 5) echo " selected"; ?>>May</option>
|
||||
<option value="6"<?php if (date("n", $time) == 6) echo " selected"; ?>>Jun</option>
|
||||
<option value="7"<?php if (date("n", $time) == 7) echo " selected"; ?>>Jul</option>
|
||||
<option value="8"<?php if (date("n", $time) == 8) echo " selected"; ?>>Aug</option>
|
||||
<option value="9"<?php if (date("n", $time) == 9) echo " selected"; ?>>Sep</option>
|
||||
<option value="10"<?php if (date("n", $time) == 10) echo " selected"; ?>>Oct</option>
|
||||
<option value="11"<?php if (date("n", $time) == 11) echo " selected"; ?>>Nov</option>
|
||||
<option value="12"<?php if (date("n", $time) == 12) echo " selected"; ?>>Dec</option>
|
||||
</select>
|
||||
<input id="year" type="text" name="year" value="<?php echo date("Y", $time); ?>" maxlength="4" size="4">
|
||||
<input id="day" type="text" name="day" value="<?php
|
||||
echo ($current_uuid!=0 ? $pred_model['day'] : date("d", $time));
|
||||
?>" maxlength="2" size="2">
|
||||
<select id="month" name="month"><?php
|
||||
// php enumeration
|
||||
for($i=1;$i<=12;$i++) {
|
||||
echo "<option value=\"" . $i . "\"";
|
||||
if ($i == date("n", $time) && $current_uuid==0 ) {
|
||||
echo " selected=\"selected\"";
|
||||
} else if ($current_uuid != 0 && $i == $pred_model['month']) {
|
||||
echo " selected=\"selected\"";
|
||||
}
|
||||
echo ">".date("M", mktime(0,0,0,$i,11,1978))."</option>\n";
|
||||
}
|
||||
|
||||
?></select>
|
||||
<input id="year" type="text" name="year" value="<?php
|
||||
echo ($current_uuid!=0 ? $pred_model['year'] : date("Y", $time));
|
||||
?>" maxlength="4" size="4">
|
||||
</td>
|
||||
<tr>
|
||||
<td>Ascent Rate (m/s):</td>
|
||||
<td><input id="ascent" type="text" name="ascent" value="5"></td>
|
||||
<td><input id="ascent" type="text" name="ascent" value="<?php
|
||||
echo ($current_uuid!=0 ? $pred_model['ascent-rate'] : "5");
|
||||
?>"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Descent Rate (sea level m/s):</td>
|
||||
<td><input id="drag" type="text" name="drag" value="5"></td>
|
||||
<td><input id="drag" type="text" name="drag" value="<?php
|
||||
echo ($current_uuid!=0 ? $pred_model['descent-rate'] : "5");
|
||||
?>"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Burst Altitude (m):</td>
|
||||
<td><input id="burst" type="text" name="burst" value="30000"></td>
|
||||
<td><input id="burst" type="text" name="burst" value="<?php
|
||||
echo ($current_uuid!=0 ? $pred_model['burst-altitude'] : "30000");
|
||||
?>"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Float time at apogee (s):</td>
|
||||
<td><input id="float" type="text" name="float_time" value="0"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Landing prediction software: <td>
|
||||
<td>Landing prediction software: </td><td>
|
||||
<select id="software" name="software">
|
||||
<option value="gfs" selected="selected">GFS (faster, less accurate)</option>
|
||||
<option value="gfs_hd">GFS HD (slower, more accurate)</option>
|
||||
<option value="gfs" selected="selected">GFS</option>
|
||||
<option value="gfs_hd">GFS HD</option>
|
||||
</select></td></tr>
|
||||
<tr><td>Lat/Lon Deltas: </td>
|
||||
<td>Lat:
|
||||
<select id="delta_lat" name="delta_lat">
|
||||
<option value="3" selected="selected">3</option>
|
||||
<option value="5">5</option>
|
||||
<option value="10">10</option>
|
||||
</select> Lon:
|
||||
<select id="delta_lon" name="delta_lon">
|
||||
<option value="3" selected="selected">3</option>
|
||||
<option value="5">5</option>
|
||||
<option value="10">10</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
</td>
|
||||
|
@ -169,6 +303,5 @@ function initialize() {
|
|||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -21,24 +21,70 @@ function predSub() {
|
|||
$("#status_message").fadeIn(250);
|
||||
}
|
||||
|
||||
function populateFormByUUID(pred_uuid) {
|
||||
$.get("ajax.php", { "action":"getModelByUUID", "uuid":pred_uuid }, function(data) {
|
||||
if ( !data.valid ) {
|
||||
appendDebug("Populating form by UUID failed");
|
||||
appendDebug("The server said the model it made was invalid");
|
||||
} else {
|
||||
// we're good to go, populate the form
|
||||
}
|
||||
}, 'json');
|
||||
}
|
||||
|
||||
function addHashLink(link) {
|
||||
var ln = "#!/" + link;
|
||||
window.location = ln;
|
||||
}
|
||||
|
||||
function showMousePos(GLatLng) {
|
||||
var curr_lat = GLatLng.lat().toFixed(4);
|
||||
var curr_lon = GLatLng.lng().toFixed(4);
|
||||
$("#cursor_lat").html(curr_lat);
|
||||
$("#cursor_lon").html(curr_lon);
|
||||
// if we have a prediction displayed
|
||||
// show range from launch and land:
|
||||
if ( current_uuid != 0 && map_items['launch_marker'] != null ) {
|
||||
var launch_pt = map_items['launch_marker'].position;
|
||||
var land_pt = map_items['land_marker'].position;
|
||||
var range_launch = distHaversine(launch_pt, GLatLng, 1);
|
||||
var range_land = distHaversine(land_pt, GLatLng, 1);
|
||||
$("#cursor_pred_launchrange").html(range_launch);
|
||||
$("#cursor_pred_landrange").html(range_land);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function throwError(data) {
|
||||
$("#error_message").html(data);
|
||||
$("#error_window").fadeIn();
|
||||
}
|
||||
|
||||
function handlePred(pred_uuid) {
|
||||
$("#prediction_status").html("Searching for wind data...");
|
||||
$("#input_form").hide("slide", { direction: "down" }, 500);
|
||||
$("#scenario_info").hide("slide", { direction: "up" }, 500);
|
||||
// disable user control of the map canvas
|
||||
$("#map_canvas").fadeTo(1000, 0.2);
|
||||
// ajax to poll for progress
|
||||
ajaxEventHandle = setInterval("getJSONProgress('"+pred_uuid+"')", 2000);
|
||||
//getCSV(pred_uuid);
|
||||
}
|
||||
|
||||
function getCSV(pred_uuid) {
|
||||
$.get("ajax.php", { "action":"getCSV", "uuid":pred_uuid }, function(data) {
|
||||
appendDebug("Got JSON response from server for flight path, parsing...");
|
||||
if (parseCSV(data) ) {
|
||||
appendDebug("Parsing function returned successfully.");
|
||||
appendDebug("Done, AJAX functions quitting.");
|
||||
} else {
|
||||
appendDebug("The parsing function failed.");
|
||||
}
|
||||
if(data != null) {
|
||||
appendDebug("Got JSON response from server for flight path, parsing...");
|
||||
if (parseCSV(data) ) {
|
||||
appendDebug("Parsing function returned successfully.");
|
||||
appendDebug("Done, AJAX functions quitting.");
|
||||
} else {
|
||||
appendDebug("The parsing function failed.");
|
||||
}
|
||||
} else {
|
||||
appendDebug("Server couldn't find a CSV for that UUID");
|
||||
throwError("Sorry, we couldn't find the data for that UUID. "+
|
||||
"Please run another prediction.");
|
||||
}
|
||||
}, 'json');
|
||||
}
|
||||
|
||||
|
@ -54,6 +100,21 @@ function getJSONProgress(pred_uuid) {
|
|||
});
|
||||
}
|
||||
|
||||
function resetGUI() {
|
||||
$("#status_message").fadeOut(500);
|
||||
// now clear the status window
|
||||
$("#prediction_status").html("");
|
||||
$("#prediction_progress").progressbar("options", "value", 0);
|
||||
$("#prediction_percent").html("");
|
||||
$("#cursor_pred").hide();
|
||||
// bring the input form back up
|
||||
toggleWindow("input_form", null, null, null, "show");
|
||||
toggleWindow("scenario_info", null, null, null, "show");
|
||||
// un-fade the map canvas
|
||||
$("#map_canvas").fadeTo(1500, 1);
|
||||
}
|
||||
|
||||
|
||||
function processProgress(progress) {
|
||||
if ( progress['error'] ) {
|
||||
clearInterval(ajaxEventHandle);
|
||||
|
@ -63,21 +124,15 @@ function processProgress(progress) {
|
|||
if ( progress['gfs_complete'] == true ) {
|
||||
if ( progress['pred_complete'] == true ) { // pred has finished
|
||||
$("#prediction_status").html("Prediction finished.");
|
||||
$("#status_message").fadeOut(500);
|
||||
// now clear the status window
|
||||
$("#prediction_status").html("");
|
||||
$("#prediction_progress").progressbar("options", "value", 0);
|
||||
$("#prediction_percent").html("");
|
||||
// bring the input form back up
|
||||
$("#input_form").show("slide", { direction: "down" }, 500);
|
||||
// un-fade the map canvas
|
||||
$("#map_canvas").fadeTo(1500, 1);
|
||||
appendDebug("Server says: the predictor finished running.");
|
||||
appendDebug("Attemping to retrieve flight path from server");
|
||||
// reset the GUI
|
||||
resetGUI();
|
||||
// stop polling for JSON
|
||||
clearInterval(ajaxEventHandle);
|
||||
// parse the data
|
||||
getCSV(running_uuid);
|
||||
getCSV(current_uuid);
|
||||
addHashLink("uuid="+current_uuid);
|
||||
} else if ( progress['pred_running'] != true ) {
|
||||
$("#prediction_status").html("Waiting for predictor to run...");
|
||||
appendDebug("Server says: predictor not yet running...");
|
||||
|
@ -106,22 +161,30 @@ function parseCSV(lines) {
|
|||
var path = [];
|
||||
var max_height = -10; //just any -ve number
|
||||
var max_point = null;
|
||||
var launch_lat;
|
||||
var launch_lon;
|
||||
var land_lat;
|
||||
var land_lon;
|
||||
var launch_pt;
|
||||
var land_pt;
|
||||
var launch_time;
|
||||
var land_time;
|
||||
$.each(lines, function(idx, line) {
|
||||
entry = line.split(',');
|
||||
if(entry.length >= 4) { // check valid entry length
|
||||
var point = new google.maps.LatLng( parseFloat(entry[1]), parseFloat(entry[2]) );
|
||||
if ( idx == 0 ) { // get the launch lat/long for marker
|
||||
var launch_lat = entry[1];
|
||||
var launch_lon = entry[2];
|
||||
launch_lat = entry[1];
|
||||
launch_lon = entry[2];
|
||||
launch_time = entry[0];
|
||||
launch_pt = point;
|
||||
}
|
||||
|
||||
// set on every iteration, last valid entry
|
||||
// gives landing position
|
||||
var land_lat = entry[1];
|
||||
var land_lon = entry[2];
|
||||
land_lat = entry[1];
|
||||
land_lon = entry[2];
|
||||
land_time = entry[0];
|
||||
land_pt = point;
|
||||
|
||||
if(parseFloat(entry[3]) > max_height) {
|
||||
|
@ -135,6 +198,16 @@ function parseCSV(lines) {
|
|||
appendDebug("Flight data parsed, creating map plot...");
|
||||
clearMapItems();
|
||||
|
||||
// calculate range and time of flight
|
||||
var range = distHaversine(launch_pt, land_pt, 1);
|
||||
var flighttime = land_time - launch_time;
|
||||
var f_hours = Math.floor((flighttime % 86400) / 3600);
|
||||
var f_minutes = Math.floor(((flighttime % 86400) % 3600) / 60);
|
||||
flighttime = f_hours + "hr" + f_minutes;
|
||||
$("#cursor_pred_range").html(range);
|
||||
$("#cursor_pred_time").html(flighttime);
|
||||
$("#cursor_pred").show();
|
||||
|
||||
// make some nice icons
|
||||
var launch_icon = new google.maps.MarkerImage(launch_img,
|
||||
new google.maps.Size(16,16),
|
||||
|
@ -152,14 +225,14 @@ function parseCSV(lines) {
|
|||
position: launch_pt,
|
||||
map: map,
|
||||
icon: launch_icon,
|
||||
title: 'Balloon launch'
|
||||
title: 'Balloon launch ('+launch_lat+', '+launch_lon+') at ' + POSIXtoHM(launch_time)
|
||||
});
|
||||
|
||||
var land_marker = new google.maps.Marker({
|
||||
position: land_pt,
|
||||
map:map,
|
||||
icon: land_icon,
|
||||
title: 'Predicted Landing'
|
||||
title: 'Predicted Landing ('+land_lat+', '+land_lon+') at ' + POSIXtoHM(land_time)
|
||||
});
|
||||
|
||||
var path_polyline = new google.maps.Polyline({
|
||||
|
@ -178,18 +251,92 @@ function parseCSV(lines) {
|
|||
});
|
||||
|
||||
// now add the launch/land markers to map
|
||||
map_items.push(launch_marker);
|
||||
map_items.push(land_marker);
|
||||
map_items.push(pop_marker);
|
||||
map_items.push(path_polyline);
|
||||
// we might need these later, so push them
|
||||
// associatively
|
||||
map_items['launch_marker'] = launch_marker;
|
||||
map_items['land_marker'] = land_marker;
|
||||
map_items['pop_marker'] = pop_marker;
|
||||
map_items['path_polyline'] = path_polyline;
|
||||
|
||||
// pan to the new position
|
||||
map.panTo(launch_pt);
|
||||
map.setZoom(8);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function plotClick() {
|
||||
// clear the old marker
|
||||
clearMapItems();
|
||||
// get the new values from the form
|
||||
click_lat = parseFloat($("#lat").val());
|
||||
click_lon = parseFloat($("#lon").val());
|
||||
var click_pt = new google.maps.LatLng(click_lat, click_lon);
|
||||
clickMarker = new google.maps.Marker({
|
||||
position: click_pt,
|
||||
map: map,
|
||||
icon: 'images/target-1-sm.png',
|
||||
title: 'Currently selected launch location ('+click_lat+', '+click_lon+')'
|
||||
});
|
||||
map_items['clickMarker'] = clickMarker;
|
||||
map.panTo(click_pt);
|
||||
map.setZoom(8);
|
||||
}
|
||||
|
||||
|
||||
function setFormLatLon(GLatLng) {
|
||||
$("#lat").val(GLatLng.lat().toFixed(4));
|
||||
$("#lon").val(GLatLng.lng().toFixed(4));
|
||||
// remove the event handler so another click doesn't register
|
||||
setLatLonByClick(false);
|
||||
// change the dropdown to read "other"
|
||||
SetSiteOther();
|
||||
// plot the new marker for launch location
|
||||
plotClick();
|
||||
}
|
||||
|
||||
function setLatLonByClick(state) {
|
||||
if ( state == true ) {
|
||||
// check this listener doesn't already exist
|
||||
if (!clickListener) {
|
||||
clickListener = google.maps.event.addListener(map,
|
||||
'click', function(event) {
|
||||
$("#error_window").fadeOut();
|
||||
setFormLatLon(event.latLng);
|
||||
});
|
||||
}
|
||||
// tell the user what to do next
|
||||
throwError("Now click your desired launch location on the map");
|
||||
} else if ( state == false ) {
|
||||
google.maps.event.removeListener(clickListener);
|
||||
clickListener = null;
|
||||
} else {
|
||||
appendDebug("Unrecognised state for setLatLonByClick");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function enableMap(map, state) {
|
||||
if ( state != false && state != true) {
|
||||
appendDebug("Unrecognised map state");
|
||||
} else if (state == false) {
|
||||
map.draggable = false;
|
||||
map.disableDoubleClickZoom = true;
|
||||
map.scrollwheel = false;
|
||||
map.navigationControl = false;
|
||||
} else if (state == true ) {
|
||||
map.draggable = true;
|
||||
map.disableDoubleClickZoom = false;
|
||||
map.scrollwheel = false;
|
||||
map.navigationControl = true;
|
||||
}
|
||||
}
|
||||
|
||||
function clearMapItems() {
|
||||
$("#cursor_pred").hide();
|
||||
if(getAssocSize(map_items) > 0) {
|
||||
appendDebug("Clearing previous map trace");
|
||||
if(map_items) {
|
||||
for(i in map_items) {
|
||||
map_items[i].setMap(null);
|
||||
}
|
||||
|
@ -197,6 +344,14 @@ function clearMapItems() {
|
|||
map_items = [];
|
||||
}
|
||||
|
||||
function getAssocSize(arr) {
|
||||
var i = 0;
|
||||
for ( j in arr ) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
function appendDebug(appendage, clear) {
|
||||
if ( clear == null ){
|
||||
var curr = $("#debuginfo").html();
|
||||
|
@ -205,16 +360,44 @@ function appendDebug(appendage, clear) {
|
|||
} else {
|
||||
$("#debuginfo").html("");
|
||||
}
|
||||
// keep the debug window scrolled to bottom
|
||||
scrollToBottom("scenario_template");
|
||||
}
|
||||
|
||||
function scrollToBottom(div_id) {
|
||||
$("#"+div_id).animate({scrollTop: $("#"+div_id)[0].scrollHeight});
|
||||
}
|
||||
|
||||
function toggleDebugWindow() {
|
||||
if( $("#debuginfo").css('display') != "none" ){
|
||||
$("#debuginfo").hide("slide", { direction: "down" }, 500);
|
||||
$("#showHideDebug").html("Show");
|
||||
function toggleWindow(window_name, linker, onhide, onshow, force) {
|
||||
if ( force == null ) {
|
||||
if( $("#"+window_name).css('display') != "none" ){
|
||||
$("#"+window_name+"").hide("slide", { direction: "down" }, 500);
|
||||
$("#"+linker).html(onhide);
|
||||
} else {
|
||||
$("#debuginfo").show("slide", { direction: "down" }, 500);
|
||||
$("#showHideDebug").html("Hide");
|
||||
$("#"+window_name).show("slide", { direction: "down" }, 500);
|
||||
$("#"+linker).html(onshow);
|
||||
}
|
||||
} else if ( force == "hide" ) {
|
||||
if( $("#"+window_name).css('display') != "none" ){
|
||||
$("#"+window_name+"").hide("slide", { direction: "down" }, 500);
|
||||
$("#"+linker).html(onhide);
|
||||
}
|
||||
} else if ( force == "show") {
|
||||
if( $("#"+window_name).css('display') == "none" ){
|
||||
$("#"+window_name).show("slide", { direction: "down" }, 500);
|
||||
$("#"+linker).html(onshow);
|
||||
}
|
||||
} else {
|
||||
appendDebug("toggleWindow force parameter unrecognised");
|
||||
}
|
||||
}
|
||||
|
||||
function POSIXtoHM(timestamp) {
|
||||
var ts = new Date();
|
||||
ts.setTime(timestamp*1000);
|
||||
var adjHours = ts.getHours() + (ts.getTimezoneOffset()/60);
|
||||
var str = adjHours + ":" + ts.getMinutes();
|
||||
return str;
|
||||
}
|
||||
|
||||
// launch site dropdown switcher
|
||||
|
@ -247,8 +430,24 @@ function UpdateLaunchSite(id) {
|
|||
|
||||
function SetSiteOther() {
|
||||
optOther = document.getElementById("other");
|
||||
//cmbSite = document.getElementById("site");
|
||||
//cmbSite.selectedIndex = 1;
|
||||
optOther.selected = true;
|
||||
}
|
||||
|
||||
rad = function(x) {return x*Math.PI/180;}
|
||||
|
||||
distHaversine = function(p1, p2, precision) {
|
||||
var R = 6371; // earth's mean radius in km
|
||||
var dLat = rad(p2.lat() - p1.lat());
|
||||
var dLong = rad(p2.lng() - p1.lng());
|
||||
|
||||
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
|
||||
Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) * Math.sin(dLong/2) * Math.sin(dLong/2);
|
||||
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
|
||||
var d = R * c;
|
||||
if ( precision == null ) {
|
||||
return d.toFixed(3);
|
||||
} else {
|
||||
return d.toFixed(precision);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue