2010-05-26 20:34:08 +00:00
|
|
|
<?php
|
2010-05-27 20:36:13 +00:00
|
|
|
// if the form was submitted we should
|
|
|
|
// 1. sanity check inputs
|
|
|
|
// 2. generate an ini file
|
|
|
|
// 3. start prediction running
|
|
|
|
// 4. start ajax server poller
|
|
|
|
// 5. display the prediction data when run is complete
|
|
|
|
// 6. make the ini and the csv/kml available for download
|
2010-05-28 23:04:59 +00:00
|
|
|
//
|
|
|
|
// get the time for populating the form
|
|
|
|
$time = time() + 3600;
|
2010-05-26 20:34:08 +00:00
|
|
|
?>
|
|
|
|
|
2010-05-27 20:36:13 +00:00
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<title>CUSF Landing Prediction 2 - GUI test</title>
|
|
|
|
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
|
2010-05-30 20:42:17 +00:00
|
|
|
<script type="text/javascript" src="http://www.google.com/jsapi?key=ABQIAAAAzpAeP4iTRyyvc3_y95bQZBSnyWegg1iFIOtWV3Ha3Qw-fH3UlBTg9lMAipYdJi6ac4b5hWAzBkkXgg"></script>
|
2010-05-27 20:36:13 +00:00
|
|
|
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
|
|
|
|
<link href="css/pred.css" type="text/css" rel="stylesheet">
|
2010-05-30 20:42:17 +00:00
|
|
|
<link href="css/cupertino/jquery-ui-1.8.1.custom.css" type="text/css" rel="stylesheet">
|
|
|
|
<script type="text/javascript">
|
|
|
|
google.load("jquery", "1.4.2");
|
|
|
|
google.load("jqueryui", "1.8.1");
|
|
|
|
</script>
|
2010-05-30 09:41:16 +00:00
|
|
|
<script src="js/jquery.form.js" type="text/javascript"></script>
|
2010-05-28 22:27:26 +00:00
|
|
|
<script src="js/pred.js" type="text/javascript"></script>
|
2010-05-26 20:34:08 +00:00
|
|
|
<script type="text/javascript">
|
2010-05-27 20:36:13 +00:00
|
|
|
|
2010-05-28 22:17:49 +00:00
|
|
|
var ajaxEventHandle;
|
2010-05-30 20:42:17 +00:00
|
|
|
var running_uuid = '<?php
|
|
|
|
if ( isset($_GET['uuid']) ) {
|
|
|
|
echo $_GET['uuid'];
|
|
|
|
} else {
|
|
|
|
echo "0";
|
|
|
|
}
|
|
|
|
?>';
|
2010-05-26 20:34:08 +00:00
|
|
|
|
2010-05-27 22:16:40 +00:00
|
|
|
function predSub() {
|
2010-05-28 21:11:33 +00:00
|
|
|
appendDebug(null, 1); // clear debug window
|
2010-05-30 22:45:08 +00:00
|
|
|
appendDebug("Sending data to server...");
|
2010-05-30 20:42:17 +00:00
|
|
|
// initialise progress bar
|
|
|
|
$("#prediction_progress").progressbar({ value: 0 });
|
|
|
|
$("#prediction_status").html("Sending data to server...");
|
|
|
|
$("#status_message").fadeIn(250);
|
2010-05-27 22:16:40 +00:00
|
|
|
}
|
|
|
|
|
2010-05-27 22:51:57 +00:00
|
|
|
function handlePred(pred_uuid) {
|
2010-05-30 22:45:08 +00:00
|
|
|
$("#prediction_status").html("Searching for wind data...");
|
2010-05-30 21:49:34 +00:00
|
|
|
$("#input_form").hide("slide", { direction: "down" }, 500);
|
|
|
|
$("#map_canvas").fadeTo(1000, 0.2);
|
2010-05-28 21:11:33 +00:00
|
|
|
// ajax to poll for progress
|
2010-05-30 20:42:17 +00:00
|
|
|
ajaxEventHandle = setInterval("getJSONProgress('"+pred_uuid+"')", 2000);
|
2010-05-28 22:17:49 +00:00
|
|
|
//getCSV(pred_uuid);
|
2010-05-27 22:51:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function getCSV(pred_uuid) {
|
|
|
|
$.get("ajax.php", { "action":"getCSV", "uuid":pred_uuid }, function(data) {
|
2010-05-27 23:13:16 +00:00
|
|
|
appendDebug("Got JSON response from server for flight path, parsing...");
|
|
|
|
if (parseCSV(data) ) {
|
2010-05-30 22:45:08 +00:00
|
|
|
appendDebug("Parsing function returned successfully.");
|
|
|
|
appendDebug("Done, AJAX functions quitting.");
|
2010-05-27 23:13:16 +00:00
|
|
|
} else {
|
2010-05-30 22:45:08 +00:00
|
|
|
appendDebug("The parsing function failed.");
|
2010-05-27 23:13:16 +00:00
|
|
|
}
|
2010-05-27 22:51:57 +00:00
|
|
|
}, 'json');
|
2010-05-27 21:37:12 +00:00
|
|
|
}
|
|
|
|
|
2010-05-28 22:17:49 +00:00
|
|
|
function getJSONProgress(pred_uuid) {
|
|
|
|
$.ajax({
|
2010-05-29 20:11:20 +00:00
|
|
|
url:"preds/"+pred_uuid+"/progress.json",
|
2010-05-28 22:17:49 +00:00
|
|
|
dataType:'json',
|
|
|
|
timeout: 500,
|
2010-05-29 20:11:20 +00:00
|
|
|
// complete: function(data, httpstatus) {
|
|
|
|
// appendDebug(httpstatus);
|
|
|
|
// },
|
|
|
|
success: processProgress
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function processProgress(progress) {
|
|
|
|
if ( progress['error'] ) {
|
|
|
|
clearInterval(ajaxEventHandle);
|
|
|
|
appendDebug("There was an error in running the prediction: "+progress['error']);
|
|
|
|
} else {
|
|
|
|
// get the progress of the wind data
|
|
|
|
if ( progress['gfs_complete'] == true ) {
|
|
|
|
if ( progress['pred_complete'] == true ) { // pred has finished
|
2010-05-30 20:42:17 +00:00
|
|
|
$("#prediction_status").html("Prediction finished.");
|
|
|
|
$("#status_message").fadeOut(500);
|
2010-05-30 20:53:16 +00:00
|
|
|
// now clear the status window
|
|
|
|
$("#prediction_status").html("");
|
|
|
|
$("#prediction_progress").progressbar("options", "value", 0);
|
|
|
|
$("#prediction_percent").html("");
|
2010-05-30 21:49:34 +00:00
|
|
|
// bring the input form back up
|
|
|
|
$("#input_form").show("slide", { direction: "down" }, 500);
|
|
|
|
// un-fade the map canvas
|
|
|
|
$("#map_canvas").fadeTo(1500, 1);
|
2010-05-30 22:45:08 +00:00
|
|
|
appendDebug("Server says: the predictor finished running.");
|
|
|
|
appendDebug("Attemping to retrieve flight path from server");
|
2010-05-30 20:53:16 +00:00
|
|
|
// stop polling for JSON
|
|
|
|
clearInterval(ajaxEventHandle);
|
|
|
|
// parse the data
|
2010-05-29 20:11:20 +00:00
|
|
|
getCSV(running_uuid);
|
|
|
|
} else if ( progress['pred_running'] != true ) {
|
2010-05-30 20:42:17 +00:00
|
|
|
$("#prediction_status").html("Waiting for predictor to run...");
|
2010-05-30 22:45:08 +00:00
|
|
|
appendDebug("Server says: predictor not yet running...");
|
2010-05-29 20:11:20 +00:00
|
|
|
} else if ( progress['pred_running'] == true ) {
|
2010-05-30 20:42:17 +00:00
|
|
|
$("#prediction_status").html("Predictor running...");
|
2010-05-30 22:45:08 +00:00
|
|
|
appendDebug("Server says: predictor currently running");
|
2010-05-28 22:17:49 +00:00
|
|
|
}
|
2010-05-29 20:11:20 +00:00
|
|
|
} else {
|
2010-05-30 22:45:08 +00:00
|
|
|
$("#prediction_status").html("Downloading wind data");
|
2010-05-30 20:42:17 +00:00
|
|
|
$("#prediction_progress").progressbar("option", "value",
|
|
|
|
progress['gfs_percent']);
|
|
|
|
$("#prediction_percent").html(progress['gfs_percent'] +
|
|
|
|
"% - Estimated time remaining: " + progress['gfs_timeremaining']);
|
2010-05-30 22:45:08 +00:00
|
|
|
appendDebug("Server says: downloaded " +
|
|
|
|
progress['gfs_percent'] + "% of GFS files");
|
2010-05-28 22:17:49 +00:00
|
|
|
}
|
2010-05-29 20:11:20 +00:00
|
|
|
}
|
|
|
|
return true;
|
2010-05-28 22:17:49 +00:00
|
|
|
}
|
|
|
|
|
2010-05-27 20:36:13 +00:00
|
|
|
var map;
|
2010-05-30 20:42:17 +00:00
|
|
|
var map_items = [];
|
2010-05-27 20:36:13 +00:00
|
|
|
var launch_img = "images/marker-sm-red.png";
|
|
|
|
var land_img = "images/marker-sm-red.png";
|
|
|
|
var burst_img = "images/pop-marker.png";
|
|
|
|
|
|
|
|
function initialize() {
|
|
|
|
// make the map and set center
|
|
|
|
var latlng = new google.maps.LatLng(52, 0);
|
|
|
|
var myOptions = {
|
|
|
|
zoom: 8,
|
|
|
|
center: latlng,
|
|
|
|
mapTypeId: google.maps.MapTypeId.ROADMAP
|
|
|
|
};
|
|
|
|
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
|
2010-05-30 09:41:16 +00:00
|
|
|
// submit the form here
|
|
|
|
$("#modelForm").ajaxForm({
|
|
|
|
url: 'ajax.php?action=submitForm',
|
|
|
|
type: 'POST',
|
|
|
|
success: function(data) {
|
2010-05-30 20:42:17 +00:00
|
|
|
predSub();
|
2010-05-30 10:06:23 +00:00
|
|
|
var data_split = data.split("|");
|
|
|
|
if ( data_split[0] == 0 ) {
|
2010-05-30 22:45:08 +00:00
|
|
|
appendDebug("The server rejected the submitted form data");
|
2010-05-30 10:06:23 +00:00
|
|
|
} else {
|
2010-05-30 22:45:08 +00:00
|
|
|
appendDebug("The server accepted the form data");
|
2010-05-30 10:06:23 +00:00
|
|
|
running_uuid = data_split[1];
|
2010-05-30 22:45:08 +00:00
|
|
|
appendDebug("The server gave us uuid:<br>" + running_uuid);
|
|
|
|
appendDebug("Starting to poll for progress JSON");
|
2010-05-30 10:06:23 +00:00
|
|
|
handlePred(running_uuid);
|
|
|
|
}
|
2010-05-30 09:41:16 +00:00
|
|
|
}
|
|
|
|
});
|
2010-05-30 21:49:34 +00:00
|
|
|
//$("#input_form").draggable({containment: '#map_canvas'});
|
2010-05-30 20:42:17 +00:00
|
|
|
// if ( running_uuid != 0 ) handlePred(running_uuid);
|
2010-05-30 22:20:26 +00:00
|
|
|
$("#debuginfo").hide();
|
|
|
|
$("#showHideDebug").click(function() {
|
|
|
|
// $("#debuginfo").show("slide", { direction: "down" }, 500);
|
|
|
|
toggleDebugWindow();
|
|
|
|
});
|
2010-05-27 20:36:13 +00:00
|
|
|
}
|
2010-05-26 20:34:08 +00:00
|
|
|
|
2010-05-30 09:41:16 +00:00
|
|
|
|
2010-05-27 22:51:57 +00:00
|
|
|
function parseCSV(lines) {
|
2010-05-29 20:11:20 +00:00
|
|
|
if(lines.length <= 0) {
|
|
|
|
appendDebug("The server returned an empty CSV file");
|
|
|
|
return false;
|
|
|
|
}
|
2010-05-27 23:13:16 +00:00
|
|
|
var path = [];
|
|
|
|
var max_height = -10; //just any -ve number
|
|
|
|
var max_point = null;
|
|
|
|
var launch_pt;
|
|
|
|
var land_pt;
|
|
|
|
$.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_pt = point;
|
2010-05-27 20:36:13 +00:00
|
|
|
}
|
|
|
|
|
2010-05-27 23:13:16 +00:00
|
|
|
// set on every iteration, last valid entry
|
|
|
|
// gives landing position
|
|
|
|
var land_lat = entry[1];
|
|
|
|
var land_lon = entry[2];
|
|
|
|
land_pt = point;
|
|
|
|
|
|
|
|
if(parseFloat(entry[3]) > max_height) {
|
|
|
|
max_height = parseFloat(entry[3]);
|
|
|
|
max_point = point;
|
|
|
|
}
|
|
|
|
path.push(point);
|
|
|
|
}
|
2010-05-27 20:36:13 +00:00
|
|
|
});
|
|
|
|
|
2010-05-27 23:13:16 +00:00
|
|
|
appendDebug("Flight data parsed, creating map plot...");
|
2010-05-30 20:42:17 +00:00
|
|
|
clearMapItems();
|
|
|
|
|
2010-05-27 23:13:16 +00:00
|
|
|
// make some nice icons
|
|
|
|
var launch_icon = new google.maps.MarkerImage(launch_img,
|
|
|
|
new google.maps.Size(16,16),
|
|
|
|
new google.maps.Point(0, 0),
|
|
|
|
new google.maps.Point(8, 8)
|
|
|
|
);
|
|
|
|
|
|
|
|
var land_icon = new google.maps.MarkerImage(land_img,
|
|
|
|
new google.maps.Size(16,16),
|
|
|
|
new google.maps.Point(0, 0),
|
|
|
|
new google.maps.Point(8, 8)
|
|
|
|
);
|
|
|
|
|
|
|
|
var launch_marker = new google.maps.Marker({
|
|
|
|
position: launch_pt,
|
|
|
|
map: map,
|
|
|
|
icon: launch_icon,
|
|
|
|
title: 'Balloon launch'
|
|
|
|
});
|
|
|
|
|
|
|
|
var land_marker = new google.maps.Marker({
|
|
|
|
position: land_pt,
|
|
|
|
map:map,
|
|
|
|
icon: land_icon,
|
|
|
|
title: 'Predicted Landing'
|
|
|
|
});
|
|
|
|
|
|
|
|
var path_polyline = new google.maps.Polyline({
|
|
|
|
path:path,
|
2010-05-30 20:42:17 +00:00
|
|
|
map: map,
|
2010-05-27 23:13:16 +00:00
|
|
|
strokeColor: '#000000',
|
|
|
|
strokeWeight: 3,
|
|
|
|
strokeOpacity: 0.75
|
|
|
|
});
|
|
|
|
|
|
|
|
var pop_marker = new google.maps.Marker({
|
|
|
|
position: max_point,
|
|
|
|
map: map,
|
|
|
|
icon: burst_img,
|
|
|
|
title: 'Balloon burst (max. altitude: ' + max_height + 'm)',
|
|
|
|
});
|
2010-05-27 20:36:13 +00:00
|
|
|
|
2010-05-30 20:42:17 +00:00
|
|
|
// 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);
|
|
|
|
|
2010-05-27 23:13:16 +00:00
|
|
|
return true;
|
2010-05-27 20:36:13 +00:00
|
|
|
|
|
|
|
}
|
2010-05-26 20:34:08 +00:00
|
|
|
|
2010-05-30 20:42:17 +00:00
|
|
|
function clearMapItems() {
|
|
|
|
appendDebug("Clearing previous map trace");
|
|
|
|
if(map_items) {
|
|
|
|
for(i in map_items) {
|
|
|
|
map_items[i].setMap(null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
map_items = [];
|
|
|
|
}
|
|
|
|
|
2010-05-26 20:34:08 +00:00
|
|
|
</script>
|
2010-05-27 20:36:13 +00:00
|
|
|
</head>
|
2010-05-30 21:49:34 +00:00
|
|
|
<body onload="initialize()" bgcolor="#000000">
|
2010-05-30 20:42:17 +00:00
|
|
|
|
|
|
|
<div id="map_canvas" style="width:100%; height:100%"></div>
|
|
|
|
|
2010-05-27 20:36:13 +00:00
|
|
|
<div id="scenario_template" class="box">
|
2010-05-30 22:20:26 +00:00
|
|
|
<h1>Debug Window -
|
|
|
|
<a href='#'><span id="showHideDebug">Show</span></a></span>
|
|
|
|
</h1>
|
2010-05-27 20:36:13 +00:00
|
|
|
<span id="debuginfo">No Messages</span>
|
|
|
|
</div>
|
|
|
|
|
2010-05-30 20:42:17 +00:00
|
|
|
<div id="status_message" class="box">
|
|
|
|
<div id="prediction_progress"></div>
|
|
|
|
<div id="prediction_percent"></div>
|
|
|
|
<br>
|
|
|
|
<div id="prediction_status"></div>
|
|
|
|
</div>
|
|
|
|
|
2010-05-27 20:36:13 +00:00
|
|
|
<div id="input_form" class="box">
|
2010-05-30 09:41:16 +00:00
|
|
|
<form action="" id="modelForm" name="modelForm">
|
2010-05-27 20:36:13 +00:00
|
|
|
<table>
|
|
|
|
<tr>
|
|
|
|
<td>Launch Site:</td>
|
|
|
|
<td>
|
|
|
|
<select id="site" name="launchsite" onchange="UpdateLaunchSite(this.selectedIndex)">
|
|
|
|
<option value="Churchill">Churchill</option>
|
|
|
|
<option value="EARS">EARS</option>
|
|
|
|
<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>
|
|
|
|
</select>
|
|
|
|
</td>
|
|
|
|
<tr>
|
|
|
|
<td>Latitude:</td>
|
|
|
|
<td><input id="lat" type="text" name="lat" value="52.2135" onKeyDown="SetSiteOther()"></td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>Longitude:</td>
|
|
|
|
<td><input id="lon" type="text" name="lon" value="0.0964" onKeyDown="SetSiteOther()"></td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>Launch altitude (m):</td>
|
2010-05-30 09:41:16 +00:00
|
|
|
<td><input id="initial_alt" type="text" name="initial_alt" value="0"></td>
|
2010-05-27 20:36:13 +00:00
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>Launch Time:</td>
|
|
|
|
<td>
|
2010-05-30 09:41:16 +00:00
|
|
|
<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>
|
2010-05-27 20:36:13 +00:00
|
|
|
<tr><td>Launch Date:</td><td>
|
2010-05-30 09:41:16 +00:00
|
|
|
<input id="day" type="text" name="day" value="<?php echo date("d", $time); ?>" maxlength="2" size="2">
|
|
|
|
<select id="month" name="month">
|
2010-05-29 20:11:20 +00:00
|
|
|
<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>
|
2010-05-27 20:36:13 +00:00
|
|
|
</select>
|
2010-05-30 09:41:16 +00:00
|
|
|
<input id="year" type="text" name="year" value="<?php echo date("Y", $time); ?>" maxlength="4" size="4">
|
2010-05-27 20:36:13 +00:00
|
|
|
</td>
|
|
|
|
<tr>
|
|
|
|
<td>Ascent Rate (m/s):</td>
|
2010-05-30 11:29:29 +00:00
|
|
|
<td><input id="ascent" type="text" name="ascent" value="5"></td>
|
2010-05-27 20:36:13 +00:00
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>Descent Rate (sea level m/s):</td>
|
2010-05-30 09:41:16 +00:00
|
|
|
<td><input id="drag" type="text" name="drag" value="5"></td>
|
2010-05-27 20:36:13 +00:00
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>Burst Altitude (m):</td>
|
2010-05-30 09:41:16 +00:00
|
|
|
<td><input id="burst" type="text" name="burst" value="30000"></td>
|
2010-05-27 20:36:13 +00:00
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>Float time at apogee (s):</td>
|
2010-05-30 09:41:16 +00:00
|
|
|
<td><input id="float" type="text" name="float_time" value="0"></td>
|
2010-05-27 20:36:13 +00:00
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<td>Landing prediction software: <td>
|
2010-05-30 09:41:16 +00:00
|
|
|
<select id="software" name="software">
|
2010-05-28 21:04:33 +00:00
|
|
|
<option value="gfs" selected="selected">GFS (faster, less accurate)</option>
|
|
|
|
<option value="gfs_hd">GFS HD (slower, more accurate)</option>
|
2010-05-27 20:36:13 +00:00
|
|
|
</select>
|
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
</td>
|
2010-05-30 09:41:16 +00:00
|
|
|
<td><input type="submit" name="submit" id="run_pred_btn" value="Run Prediction!"></td>
|
2010-05-27 20:36:13 +00:00
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
|
2010-05-26 20:34:08 +00:00
|
|
|
|
|
|
|
</body>
|
|
|
|
</html>
|