Merge remote branch 'origin/master'

pull/73/head
Adam Greig 2010-06-07 21:39:39 +01:00
commit ffb1238b02
10 zmienionych plików z 532 dodań i 112 usunięć

Wyświetl plik

@ -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'])) {

Wyświetl plik

@ -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

Wyświetl plik

@ -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";
?>

Wyświetl plik

@ -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;
}
}
?>

Wyświetl plik

@ -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>&nbsp;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>

Wyświetl plik

@ -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);
}
}