Page MenuHomeCode

No OneTemporary

This document is not UTF8. It was detected as ISO-8859-1 (Latin 1) and converted to UTF8 for display.
diff --git a/api.php b/api.php
--- a/api.php
+++ b/api.php
@@ -1,320 +1,319 @@
<?php
/**
* API entry point
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* @package Zed
* @subpackage EntryPoints
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @copyright 2010 Sébastien Santoro aka Dereckson
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @version 0.1
* @link http://scherzo.dereckson.be/doc/zed
* @link http://zed.dereckson.be/
* @filesource
* @todo Consider to output documentation on / and /ship queries
* @todo /app/getdata
*/
//API Preferences
define('URL', 'http://' . $_SERVER['HTTP_HOST'] . '/index.php');
//Pluton library
require_once('includes/core.php');
require_once('includes/config.php');
//API libs
require_once('includes/api/api_helpers.php');
require_once('includes/api/cerbere.php');
//Use our URL controller method if you want to mod_rewrite the API
$url = explode('/', substr($_SERVER['PATH_INFO'], 1));
switch ($module = $url[0]) {
/* -------------------------------------------------------------
Site API
/time
/location
- /perso (disabled)
+ /coordinates
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case '':
//Nothing to do
//TODO: offer documentation instead
die();
case 'time':
//Hypership time
api_output(get_hypership_time(), "time");
break;
case 'location':
//Checks creditentials
cerbere();
//Gets location info
require_once("includes/geo/location.php");
$location = new GeoLocation($url[1], $url[2]);
api_output($location, "location");
break;
+
+ case 'coordinates':
+ //Checks creditentials
+ cerbere();
+ //Get coordiantes
+ api_output(GeoGalaxy::get_coordinates(), 'galaxy', 'object');
+ break;
- //case 'perso':
- // //Checks creditentials
- // cerbere();
- // //Gets perso info
- // require_once("includes/objects/perso.php");
- // $perso = new Perso($url[1]);
- // api_output($perso, "perso");
- // break;
/* -------------------------------------------------------------
Ship API
/authenticate
/appauthenticate
/appauthenticated
/move
/land
/flyout
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case 'ship':
//Ship API
//Gets ship from Ship API key (distinct of regular API keys)
require_once('includes/objects/ship.php');
$ship = Ship::from_api_key($_REQUEST['key']) or cerbere_die("Invalid ship API key");
switch ($command = $url[1]) {
case '':
//Nothing to do
//TODO: offer documentation instead
die();
case 'authenticate':
//TODO: web authenticate
break;
case 'appauthenticate':
//Allows desktop application to authenticate an user
$tmp_session_id = $url[2] or cerbere_die("/appauthenticate/ must be followed by any session identifier");
if ($_REQUEST['name']) {
//Perso will be offered auth invite at next login.
//Handy for devices like PDA, where it's not easy to auth.
$perso = new Perso($_REQUEST['name']);
if ($perso->lastError) {
cerbere_die($perso->lastError);
}
if (!$ship->is_perso_authenticated($perso->id)) {
$ship->request_perso_authenticate($perso->id);
}
$ship->request_perso_confirm_session($tmp_session_id, $perso->id);
} else {
//Delivers an URL. App have to redirects user to this URL
//launching a browser or printing the link.
$ship_code = $ship->get_code();
registry_set("api.ship.session.$ship_code.$tmp_session_id", -1);
$url = get_server_url() . get_url() . "?action=api.ship.appauthenticate&session_id=" . $tmp_session_id;
api_output($url, "URL");
}
break;
case 'appauthenticated':
//Checks the user authentication
$tmp_session_id = $url[2] or cerbere_die("/appauthenticated/ must be followed by any session identifier you used in /appauthenticate");
$perso_id = $ship->get_perso_from_session($tmp_session_id);
if (!$isPersoAuth = $ship->is_perso_authenticated($perso_id)) {
//Global auth not ok/revoked.
$auth->status = -1;
} else {
$perso = Perso::get($perso_id);
$auth->status = 1;
$auth->perso->id = $perso->id;
$auth->perso->nickname = $perso->nickname;
$auth->perso->name = $perso->name;
//$auth->perso->location = $perso->location;
//Is the perso on board? Yes if its global location is S...
$auth->perso->onBoard = (
$perso->location_global[0] == 'S' &&
substr($perso->location_global, 1, 5) == $ship->id
);
if ($auth->perso->onBoard) {
//If so, give local location
$auth->perso->location_local = $perso->location_local;
}
}
api_output($auth, "auth");
break;
case 'move':
//Moves the ship to a new location, given absolute coordinates
//TODO: handle relative moves
if (count($url) < 2) cerbere_die("/move/ must be followed by a location expression");
//Gets location class
//It's allow: (1) to normalize locations between formats
// (2) to ensure the syntax
//==> if the ship want to communicate free forms coordinates, must be added on GeoLocation a free format
try {
$location = new GeoLocation($url[2]);
} catch (Exception $ex) {
$reply->success = 0;
$reply->error = $ex->getMessage();
api_output($reply, "move");
break;
}
$ship->location_global = $location->global;
$ship->save_to_database();
$reply->success = 1;
$reply->location = $ship->location;
api_output($reply, "move");
break;
case 'land':
case 'flyin':
//Flies in
try {
$location = new GeoLocation($location);
} catch (Exception $ex) {
$reply->success = 0;
$reply->error = $ex->getMessage();
api_output($reply, "land");
break;
}
break;
case 'flyout':
//Flies out
break;
}
break;
/* -------------------------------------------------------------
Application API
/checkuserkey
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case 'app':
//Application API
require_once("includes/objects/application.php");
$app = Application::from_api_key($_REQUEST['key']) or cerbere_die("Invalid application API key");
switch ($command = $url[1]) {
case '':
//Nothing to do
//TODO: offer documentation instead
die();
case 'checkuserkey':
if (count($url) < 2) cerbere_die("/checkuserkey/ must be followed by an user key");
$reply = (boolean)$app->get_perso_id($url[2]);
api_output($reply, "check");
break;
case 'pushuserdata':
if (count($url) < 3) cerbere_die("/pushuserdata/ must be followed by an user key");
$perso_id = $app->get_perso_id($url[2]) or cerbere_die("Invalid application user key");
//then, falls to 'pushdata'
case 'pushdata':
$data_id = $_REQUEST['data'] ? $_REQUEST['data'] : new_guid();
//Gets data
switch ($mode = $_REQUEST['mode']) {
case '':
cerbere_die("Add in your data posted or in the URL mode=file to read data from the file posted (one file per api call) or mode=request to read data from \$_REQUEST['data'].");
case 'request':
$data = $_REQUEST['data'];
$format = "raw";
break;
case 'file':
$file = $_FILES['datafile']['tmp_name'] or cerbere_die("File is missing");
if (!is_uploaded_file($file)) cerbere_die("Invalid form request");
$data = "";
if (preg_match('/\.tar$/', $file)) {
$format = "tar";
$data = file_get_contents($file);
} elseif (preg_match('/\.tar\.bz2$/', $file)) {
$format = "tar";
} elseif (preg_match('/\.bz2$/', $file)) {
$format = "raw";
} else {
$format = "raw";
$data = file_get_contents($file);
}
if ($data === "") {
//.bz2
$bz = bzopen($file, "r") or cerbere_die("Couldn't open $file");
while (!feof($bz)) {
$data .= bzread($bz, BUFFER_SIZE);
}
bzclose($bz);
}
unlink($file);
break;
default:
cerbere_die("Invalid mode. Expected: file, request");
}
//Saves data
global $db;
$data_id = $db->sql_escape($data_id);
$data = $db->sql_escape($data);
$perso_id = $perso_id ? $perso_id : 'NULL';
$sql = "REPLACE INTO applications_data (application_id, data_id, data_content, data_format, perso_id) VALUES ('$app->id', '$data_id', '$data', '$format', $perso_id)";
if (!$db->sql_query($sql))
message_die(SQL_ERROR, "Can't save data", '', __LINE__, __FILE__, $sql);
//cerbere_die("Can't save data");
//Returns
api_output($data_id);
break;
case 'getuserdata':
// /api.php/getuserdata/data_id/perso_key
// /api.php/getdata/data_id
if (count($url) < 3) cerbere_die("/getuserdata/ must be followed by an user key");
$perso_id = $app->get_perso_id($url[2]) or cerbere_die("Invalid application user key");
//then, falls to 'getdata'
case 'getdata':
if (count($url) < 2) cerbere_die('/' + $url[0] + '/ must be followed by the data ID');
if (!$perso_id) $perso_id = 'NULL';
$data_id = $db->sql_escape($url[1]);
$sql = "SELECT data_content FROM applications_data WHERE application_id = '$app->id' AND data_id = '$data_id' AND perso_id = $perso_id";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Unable to query the table", '', __LINE__, __FILE__, $sql);
}
while ($row = $db->sql_fetchrow($result)) {
}
break;
default:
echo "Unknown module:";
dprint_r($url);
break;
}
break;
default:
echo "Unknown module:";
dprint_r($url);
break;
}
?>
diff --git a/dev/objects_viewer.html b/dev/objects_viewer.html
new file mode 100644
--- /dev/null
+++ b/dev/objects_viewer.html
@@ -0,0 +1,219 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" >
+<head>
+ <title>Zed galaxy :: objects representation</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <link rel="Stylesheet" href="../css/zed/theme.css" type="text/css" />
+ <style type="text/css">
+ @import "/js/dojo/dojo/resources/dojo.css";
+ @import "/js/dojo/dijit/tests/css/dijitTests.css";
+ @import "/js/dojo/dijit/themes/tundra/tundra.css";
+
+ body {
+ margin-left: auto;
+ margin-right: auto;
+ }
+
+ .viewscreen {
+ width: 500px; height: 500px;
+ background-color: black;
+ background-image: url('http://www.formandfunction.com/wraptures/datum-TILE/Astronomy/Cluster_Virgo.jpg');
+ }
+ </style>
+ <script type="text/javascript" src="/js/misc.js" djConfig="isDebug: false"></script>
+ <script type="text/javascript" src="/js/dojo/dojo/dojo.js" djConfig="isDebug: false"></script>
+ <script type="text/javascript" src="/js/dojo/dojox/gfx3d/object.js"></script>
+ <script type="text/javascript" src="/js/dojo/dojox/gfx3d/scheduler.js"></script>
+
+ <script type="text/javascript">
+ dojo.require("dojox.gfx3d");
+
+ viewer = {
+ angles: {x: 30, y: 30, z: 0},
+ view: null,
+ objects: null,
+
+ getObjects: function() {
+ var url = 'http://zed51.dereckson.be/api.php/coordinates?key=303392c7-97c6-11df-a1e9-000c2923380c&format=json';
+
+ dojo.xhrGet({
+ handleAs: "json",
+ url: url,
+ preventCache: true,
+ handle: function (response, ioArgs) {
+ viewer.objects = response;
+ viewer.drawObjects();
+ }
+ });
+ },
+
+ initialize: function() {
+ viewer.getObjects();
+ },
+
+ drawObjects: function () {
+ viewer.makeObjects();
+
+ //Some cones to help understand the axis rotation
+ //(thanks Alphos for the tip)
+ var coneZ = [
+ {x: 0, y: 0, z: 15},
+ {x: 5, y: 0, z: 0},
+ {x: 0, y: 5, z: 0},
+ {x: -5, y: 0, z: 0},
+ {x: 0, y: -5, z: 0}
+ ];
+
+ var coneX = [
+ {x: 15, y: 0, z: 0},
+ {x: 0, y: 5, z: 0},
+ {x: 0, y: 0, z: 5},
+ {x: 0, y: -5, z: 0},
+ {x: 0, y: 0, z: -5}
+ ];
+
+ var coneY = [
+ {x: 0, y: 15, z: 0},
+ {x: 0, y: 0, z: 5},
+ {x: 5, y: 0, z: 0},
+ {x: 0, y: 0, z: -5},
+ {x: -5, y: 0, z: 0}
+ ];
+
+ view.createTriangles(coneZ, "fan")
+ .setStroke({color: "blue", width: 1})
+ .setFill("blue")
+ .applyTransform(dojox.gfx3d.matrix.translate({x: 0, y: 0, z: 200}));
+
+ view.createTriangles(coneX, "fan")
+ .setStroke({color: "red", width: 1})
+ .setFill("red")
+ .applyTransform(dojox.gfx3d.matrix.translate({x: 200, y: 0, z: 0}));
+
+ view.createTriangles(coneY, "fan")
+ .setStroke({color: "green", width: 1})
+ .setFill("green")
+ .applyTransform(dojox.gfx3d.matrix.translate({x: 0, y: 200, z: 0}));
+
+ //Zed objects
+ for (i = 0 ; i < this.objects.length ; i++) {
+ var object = this.objects[i];
+ switch (object[1]) {
+ case 'ship':
+ //Spaceship -> blue cube
+ var c = {bottom: object[2], top: {x: object[2].x + 10, y: object[2].y + 10, z: object[2].z + 10}};
+ view.createCube(c).setFill({ type: "plastic", finish: "dull", color: "blue" });
+ break;
+
+ case 'hypership':
+ //Hypership -> Yellow cylinder
+ var c = {center: object[2], height: 15, radius: 8}
+ view.createCylinder(c)
+ .setStroke("black")
+ .setFill({type: "plastic", finish: "dull", color: "yellow"});
+ break;
+
+ case 'asteroid':
+ //Asteroid -> Red orbit
+ var o = {center: object[2], radius: 8}
+ view.createOrbit(o)
+ .setStroke({color: "red", width: 1});
+ break;
+
+ default:
+ alert('Not handled object type: ' + object[1]);
+
+ }
+ }
+ },
+
+ rotate: function() {
+ var m = dojox.gfx3d.matrix;
+
+ if(dojo.byId('rx').checked){
+ viewer.angles.x += 1;
+ }
+ if(dojo.byId('ry').checked){
+ viewer.angles.y += 1;
+ }
+ if(dojo.byId('rz').checked){
+ viewer.angles.z += 1;
+ }
+ var t = m.normalize([
+ m.cameraTranslate(-300, -200, 0),
+ m.cameraRotateXg(viewer.angles.x),
+ m.cameraRotateYg(viewer.angles.y),
+ m.cameraRotateZg(viewer.angles.z)
+ ]);
+ // console.debug(t);
+ view.setCameraTransform(t);
+ view.render();
+ },
+
+ makeObjects: function(){
+ var surface = dojox.gfx.createSurface("test", 500, 500);
+ view = surface.createViewport();
+
+ view.setLights([
+ { direction: { x: -10, y: -5, z: 5 }, color: "white"}
+ ],
+ { color:"white", intensity: 2 },
+ "white"
+ );
+
+ var xaxis = [{x: 0, y: 0, z: 0}, {x: 200, y: 0, z: 0}];
+ var yaxis = [{x: 0, y: 0, z: 0}, {x: 0, y: 200, z: 0}];
+ var zaxis = [{x: 0, y: 0, z: 0}, {x: 0, y: 0, z: 200}];
+
+ var m = dojox.gfx3d.matrix;
+
+ view.createEdges(xaxis).setStroke({color: "red", width: 1});
+ view.createEdges(yaxis).setStroke({color: "green", width: 1});
+ view.createEdges(zaxis).setStroke({color: "blue", width: 1});
+
+ var camera = dojox.gfx3d.matrix.normalize([
+ m.cameraTranslate(-300, -200, 0),
+ m.cameraRotateXg(this.angles.x),
+ m.cameraRotateYg(this.angles.y),
+ m.cameraRotateZg(this.angles.z)
+ ]);
+
+ view.applyCameraTransform(camera);
+ view.render();
+ setInterval(viewer.rotate, 50);
+ }
+ };
+
+ dojo.addOnLoad(viewer.initialize);
+ </script>
+</head>
+<body class="tundra">
+<div style="width: 960px; margin: auto; margin-top: 1em;" class="container_16">
+ <div style="float: right; width: 400px;">
+ <h1>Zed objects viewer</h1>
+ <h2>Objects viewer</h2>
+ <p>This page shows the different objects in the Zed galaxy.</p>
+ <p>This is based on the camera rotate <a href="http://archive.dojotoolkit.org/nightly/dojotoolkit/dojox/gfx3d/tests/test_camerarotate_shaded.html">dojox.gfx3d demo</a>.
+ <br />The background is a <a href="http://www.formandfunction.com/wraptures/LINX/w_astronomy.html">Cluster Virgo</a> from Jonathan Gibson, under CC-BY-SA license.</p>
+ <h2>Controls</h2>
+ <form>
+ <input id="rx" type="checkbox" name="rotateX" checked="true" value="on"/>
+ <label for="rx"> Rotate around X-axis (red)</label> <br/>
+ <input id="ry" type="checkbox" name="rotateY" checked="false" value="off"/>
+ <label for="ry"> Rotate around Y-axis (green)</label> <br/>
+ <input id="rz" type="checkbox" name="rotateZ" checked="false" value="off"/>
+ <label for="rz"> Rotate around Z-axis (blue)</label> <br/>
+ </form>
+ <h2>Legend</h2>
+ <ul>
+ <li>Blue cube: ship</li>
+ <li>Yellow cylinder: hypership</li>
+ <li>Red orbit: asteroid</li>
+ </ul>
+ </div>
+
+
+ <div id="test" class="viewscreen"></div>
+
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/dev/quux.php b/dev/quux.php
--- a/dev/quux.php
+++ b/dev/quux.php
@@ -1,87 +1,105 @@
<?php
require_once('includes/objects/ship.php');
require_once('includes/objects/port.php');
require_once('includes/objects/application.php');
require_once('includes/objects/content.php');
require_once('includes/objects/message.php');
require_once('includes/objects/invite.php');
require_once('includes/cache/cache.php');
include('controllers/header.php');
- $case = 'travel';
+ $case = 'spherical';
switch ($case) {
+ case 'spherical':
+ require_once('includes/geo/galaxy.php');
+ echo '<H2>Spherical coordinates test</H2>';
+ echo '<table cellpadding=8>';
+ echo "<tr><th>Name</th><th>Type</th><th>Cartesian coords</th><th>Spherical I</th><th>Spherical II</th><th>Pencil coordinates</th></tr>";
+ $objects = GeoGalaxy::get_coordinates();
+ foreach ($objects as $row) {
+ echo "<tr><th style='text-align: left'>$row[0]</th><td>$row[1]</td><td>$row[2]</td>";
+ $pt = $row[2];
+ echo '<td>(', implode(', ', $pt->to_spherical()), ')</td>';
+ echo '<td>(', implode(', ', $pt->to_spherical2()), ')</td>';
+ $pt->translate(500, 300, 200, 2);
+ echo '<td>', $pt, '</td>';
+ echo '</tr>';
+ }
+ echo '</table>';
+ break;
+
case 'travel':
require_once('includes/travel/travel.php');
require_once('includes/travel/place.php');
$cache = Cache::load();
$travel = $cache->get('zed_travel');
if ($travel == '') {
$travel_nocached = new Travel();
$travel_nocached->load_xml("content/travel.xml");
$cache->set('zed_travel', serialize($travel_nocached));
} else {
$travel = unserialize($travel);
}
dieprint_r($travel);
break;
case 'perso.create.notify':
$testperso = Perso::get(4733);
$message = new Message();
$message->from = 0;
$message->to = invite::who_invited(4733);
$url = get_server_url() . get_url('who', $testperso->nickname);
$message->text = sprintf(lang_get('InvitePersoCreated'), $testperso->name, $url);
$message->send();
dieprint_r($message);
break;
case 'pushdata';
echo '
<h2>/api.php/app/pushdata</h2>
<form method="post" action="/api.php/app/pushdata?mode=file&key=37d839ba-f9fc-42ca-a3e8-28053e979b90" enctype="multipart/form-data">
<input type="file" name="datafile" /><br />
<input type="submit" value="Send file" />
</form>
';
break;
case 'thumbnail':
$content = new Content(1);
dprint_r($content);
$content->generate_thumbnail();
break;
case 'port':
echo '<h2>Port::from_location test</h2>';
$locations = array("B00002", "B00002123", "B00001001", "xyz: [800, 42, 220]");
foreach ($locations as $location) {
dprint_r(Port::from_location($location));
}
break;
case 'ext':
$file = 'dev/foo.tar';
echo "<h2>$file</h2>";
echo "<h3>.tar.bz2</h3>";
echo ereg('\.tar\.bz2$', $file);
echo "<h3>.tar</h3>";
echo ereg('\.tar$', $file);
break;
case 'app':
echo Application::from_api_key("37d839ba-f9fc-42ca-a3e8-28053e979b90")->generate_userkey();
break;
case '':
dieprint_r("No case currently selected.");
break;
}
include('controllers/footer.php');
?>
\ No newline at end of file
diff --git a/dev/schema-mysql.sql b/dev/schema-mysql.sql
--- a/dev/schema-mysql.sql
+++ b/dev/schema-mysql.sql
@@ -1,633 +1,641 @@
-- phpMyAdmin SQL Dump
-- version 3.3.3
-- http://www.phpmyadmin.net
--
-- Serveur: localhost
-- Généré le : Sam 17 Juillet 2010 à 19:37
-- Version du serveur: 5.5.4
-- Version de PHP: 5.3.2
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
--
-- Base de données: `zed`
--
-- --------------------------------------------------------
--
-- Structure de la table `api_keys`
--
CREATE TABLE IF NOT EXISTS `api_keys` (
`key_guid` varchar(36) NOT NULL,
`key_active` tinyint(1) unsigned NOT NULL DEFAULT '1',
`key_description` tinytext,
`key_hits` bigint(20) NOT NULL DEFAULT '0',
`key_lastcall` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`key_guid`),
KEY `key_active` (`key_active`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Contenu de la table `api_keys`
--
-- --------------------------------------------------------
--
-- Doublure de structure pour la vue `content`
--
CREATE TABLE IF NOT EXISTS `content` (
`content_id` mediumint(8) unsigned
,`location_global` varchar(9)
,`location_local` varchar(255)
,`location_k` smallint(5) unsigned
,`content_path` varchar(255)
,`user_id` smallint(5)
,`perso_id` smallint(5)
,`content_title` varchar(255)
);
-- --------------------------------------------------------
--
-- Structure de la table `content_files`
--
CREATE TABLE IF NOT EXISTS `content_files` (
`content_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`content_path` varchar(255) NOT NULL,
`user_id` smallint(5) NOT NULL,
`perso_id` smallint(5) NOT NULL,
`content_title` varchar(255) NOT NULL,
PRIMARY KEY (`content_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
--
-- Contenu de la table `content_files`
--
-- --------------------------------------------------------
--
-- Structure de la table `content_locations`
--
CREATE TABLE IF NOT EXISTS `content_locations` (
`location_global` varchar(9) NOT NULL,
`location_local` varchar(255) NOT NULL,
`location_k` smallint(5) unsigned NOT NULL,
`content_id` mediumint(8) unsigned NOT NULL,
PRIMARY KEY (`location_global`,`location_local`,`location_k`),
KEY `content_id` (`content_id`),
KEY `location_global` (`location_global`,`location_local`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Contenu de la table `content_locations`
--
-- --------------------------------------------------------
--
-- Structure de la table `geo_bodies`
--
CREATE TABLE IF NOT EXISTS `geo_bodies` (
`body_code` mediumint(5) unsigned zerofill NOT NULL AUTO_INCREMENT,
`body_name` varchar(31) NOT NULL,
`body_status` set('hypership','asteroid','moon','planet','star','orbital','hidden') DEFAULT NULL,
`body_location` varchar(15) DEFAULT NULL,
`body_description` text,
PRIMARY KEY (`body_code`),
KEY `body_status` (`body_status`),
FULLTEXT KEY `text` (`body_name`,`body_description`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
--
-- Contenu de la table `geo_bodies`
--
INSERT INTO `geo_bodies` (`body_code`, `body_name`, `body_status`, `body_location`, `body_description`) VALUES
(00001, 'Hypership', 'hypership', NULL, NULL),
(00002, 'Xen', 'asteroid', NULL, NULL),
(00003, 'Kaos', 'asteroid', NULL, NULL);
-- --------------------------------------------------------
--
-- Doublure de structure pour la vue `geo_locations`
--
CREATE TABLE IF NOT EXISTS `geo_locations` (
`location_code` varchar(9)
,`location_name` varchar(255)
);
-- --------------------------------------------------------
--
-- Structure de la table `geo_places`
--
CREATE TABLE IF NOT EXISTS `geo_places` (
`place_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`body_code` mediumint(5) unsigned zerofill NOT NULL,
`place_code` smallint(3) unsigned zerofill NOT NULL,
`place_name` varchar(255) NOT NULL,
`place_description` longtext NOT NULL,
`place_status` set('start','hidden') DEFAULT NULL,
PRIMARY KEY (`place_id`),
UNIQUE KEY `body_id` (`body_code`,`place_code`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;
--
-- Contenu de la table `geo_places`
--
INSERT INTO `geo_places` (`place_id`, `body_code`, `place_code`, `place_name`, `place_description`, `place_status`) VALUES
(1, 00001, 001, 'Tour', 'Tour circulaire, surplombant l''hypership, offrant une vue circulaire sur l''espace (ou l''ultraespace, ou l''hyperespace) et une rotonde aux derniers étages.\r\n\r\n== Toponymie numérique ==\r\nChaque niveau (correspondant à un secteur, identifié par la lettre T suivi du niveau, en partant du haut) est divisé en 6 couloirs d''approximativement 60°.', NULL),
(2, 00001, 002, 'Core', 'Le c.ur de l''hypership, son centre de gravité et les 8 cubes l''entourant.\r\n\r\n== Toponymie numérique ==\r\nLe core est divisé en 9 secteurs : C0 pour le centre de gravité, C1 à C4 pour les cubes de la couche inférieure, C5 à C8 pour les cubes de la couche supérieure.', NULL),
(3, 00002, 001, 'Algir', '', NULL),
(4, 00003, 001, 'Zeta', '', 'start'),
(5, 00001, 003, 'Bays', 'Baies permettant d''accueillir divers vaisseaux au sein de l''hypership.', NULL);
-- --------------------------------------------------------
--
-- Structure de la table `log_smartline`
--
CREATE TABLE IF NOT EXISTS `log_smartline` (
`command_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`perso_id` smallint(5) unsigned DEFAULT NULL,
`command_time` int(10) DEFAULT NULL,
`command_text` varchar(255) DEFAULT NULL,
`isError` tinyint(1) DEFAULT '0',
PRIMARY KEY (`command_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
--
-- Contenu de la table `log_smartline`
--
-- --------------------------------------------------------
--
-- Structure de la table `messages`
--
CREATE TABLE IF NOT EXISTS `messages` (
`message_id` mediumint(9) NOT NULL AUTO_INCREMENT,
`message_date` int(11) NOT NULL DEFAULT '0',
`message_from` varchar(4) NOT NULL DEFAULT '0',
`message_to` varchar(4) NOT NULL DEFAULT '0',
`message_text` longtext NOT NULL,
`message_flag` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`message_id`),
KEY `message_to` (`message_to`),
KEY `message_flag` (`message_flag`),
KEY `message_date` (`message_date`),
KEY `inbox` (`message_to`,`message_flag`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
--
-- Contenu de la table `messages`
--
-- --------------------------------------------------------
--
-- Structure de la table `motd`
--
CREATE TABLE IF NOT EXISTS `motd` (
`motd_id` int(11) NOT NULL AUTO_INCREMENT,
`perso_id` int(11) NOT NULL,
`motd_text` varchar(255) NOT NULL,
`motd_date` int(10) NOT NULL,
PRIMARY KEY (`motd_id`),
KEY `perso_id` (`perso_id`),
KEY `motd_date` (`motd_date`),
FULLTEXT KEY `motd_text` (`motd_text`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=25 ;
--
-- Contenu de la table `motd`
--
INSERT INTO `motd` (`motd_id`, `perso_id`, `motd_text`, `motd_date`) VALUES
(24, 4960, 'You''re on the *DEVELOPMENT AND TESTING server (database zed, using the repo hg)*', 1279161701);
-- --------------------------------------------------------
--
-- Structure de la table `pages`
--
CREATE TABLE IF NOT EXISTS `pages` (
`page_id` int(11) NOT NULL AUTO_INCREMENT,
`page_code` varchar(31) NOT NULL,
`page_title` varchar(255) NOT NULL,
`page_content` longtext NOT NULL,
PRIMARY KEY (`page_id`),
UNIQUE KEY `page_code` (`page_code`),
FULLTEXT KEY `page_text` (`page_code`,`page_title`,`page_content`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
--
-- Contenu de la table `pages`
--
INSERT INTO `pages` (`page_id`, `page_code`, `page_title`, `page_content`) VALUES
(3, 'ArtworkCredits', 'Artwork credits', '<h2>Login screen</h2>\r\n<p>Wires and blocks use following tutorials:</p>\r\n<ul>\r\n <li><a href="http://www.tutorio.com/tutorial/futuristic-decay-interface">Futuristic Decay Interface</a></li>\r\n <li><a href="http://www.tutorio.com/tutorial/photoshop-wire-tutorial">Photoshop Wire Tutorial</a></li>\r\n</ul>\r\n<h2>Hypership</h2>\r\n<h3>Gallery tower</h3>\r\n<p>Technical schemas Dereckson. In the future, some could contain technical shapes Photoshop brushes, by <a href="http://scully7491.deviantart.com/">scully7491</a>.</p>\r\n<p>Portholes structure (c) Richard Carpenter, Six Revisions.<br />\r\nA <a href="http://sixrevisions.com/tutorials/photoshop-tutorials/how-to-design-a-space-futuristic-gallery-layout-in-photoshop/">tutorial is available here</a>.</p>\r\n<p>When the hypership is in hyperspace mode, portholes prints a colored background by <a href="http://www.sxc.hu/profile/ilco">ilco</a>.<br />\r\nWhen reaching a system, it prints a scene excerpt.</p>\r\n<h3>Core cancelled sector</h3>\r\n<p>Photographies: J&eacute;r&ocirc;me<br />\r\nEditing: Dereckson</p>\r\n<h2>Scenes</h2>\r\n<h3>Xen and Kaos</h3>\r\n<p>Scene composed from 2 wallpapers from Interfacelift, n&deg; 587 and 781.</p>\r\n<h2>Future sources</h2>\r\n<h3>Fasticon</h3>\r\n<p>It''s possible in the future some http://www.fasticon.com/ icons are added.</p>\r\n<h4>Comic Tiger</h4>\r\n<p>(c) <a href="mailto:dirceu@fasticon.com">Dirceu Veiga</a> - FastIcon Studio.<br />\r\n<strong>License:</strong> All Icons on the Fast Icon &quot;Download&quot; page are are FREEWARE, but to use our Icons in your software, web site, in a theme or other project, <a href="mailto:contact@fasticon.com">you need our permission first</a>. You don''t need permission for personal use our Icons on your computer.</p>');
-- --------------------------------------------------------
--
-- Structure de la table `pages_edits`
--
CREATE TABLE IF NOT EXISTS `pages_edits` (
`page_edit_id` int(11) NOT NULL AUTO_INCREMENT,
`page_code` varchar(255) DEFAULT NULL,
`page_version` smallint(6) NOT NULL DEFAULT '0',
`page_title` varchar(255) NOT NULL DEFAULT '',
`page_content` longtext,
`page_edit_reason` varchar(255) DEFAULT NULL,
`page_edit_user_id` smallint(4) unsigned DEFAULT NULL,
`page_edit_time` int(10) DEFAULT NULL,
PRIMARY KEY (`page_edit_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
--
-- Contenu de la table `pages_edits`
--
-- --------------------------------------------------------
--
-- Structure de la table `persos`
--
CREATE TABLE IF NOT EXISTS `persos` (
`user_id` smallint(4) DEFAULT NULL,
`perso_id` smallint(4) NOT NULL DEFAULT '0',
`perso_name` varchar(255) NOT NULL DEFAULT '',
`perso_nickname` varchar(31) NOT NULL DEFAULT '',
`perso_race` varchar(31) NOT NULL DEFAULT '',
`perso_sex` enum('M','F','N','2') NOT NULL DEFAULT 'M',
`perso_avatar` varchar(255) DEFAULT NULL,
`location_global` varchar(9) DEFAULT 'B00001001',
`location_local` varchar(255) DEFAULT NULL,
PRIMARY KEY (`perso_id`),
UNIQUE KEY `nickname` (`perso_nickname`),
KEY `race` (`perso_race`),
KEY `user_id` (`user_id`),
KEY `location_global` (`location_global`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Contenu de la table `persos`
--
INSERT INTO `persos` (`user_id`, `perso_id`, `perso_name`, `perso_nickname`, `perso_race`, `perso_sex`, `perso_avatar`, `location_global`, `location_local`) VALUES
(2600, 4960, 'Lorem Ipsum', 'demo', 'humanoid', 'M', '', 'B00003001', '1');
-- --------------------------------------------------------
--
-- Structure de la table `persos_flags`
--
CREATE TABLE IF NOT EXISTS `persos_flags` (
`flag_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`perso_id` smallint(6) NOT NULL DEFAULT '0',
`flag_key` varchar(255) NOT NULL,
`flag_value` varchar(512) NOT NULL,
PRIMARY KEY (`flag_id`),
UNIQUE KEY `persoflag` (`perso_id`,`flag_key`),
KEY `perso_id` (`perso_id`),
KEY `flag_key` (`flag_key`),
KEY `flag` (`flag_key`(127),`flag_value`(199))
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=459 ;
-- --------------------------------------------------------
--
-- Structure de la table `persos_notes`
--
CREATE TABLE IF NOT EXISTS `persos_notes` (
`perso_id` smallint(4) NOT NULL,
`note_code` varchar(63) NOT NULL,
`note_text` longtext NOT NULL,
PRIMARY KEY (`perso_id`,`note_code`),
KEY `perso_id` (`perso_id`),
KEY `note_code` (`note_code`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Contenu de la table `persos_notes`
--
-- --------------------------------------------------------
--
-- Structure de la table `ports`
--
CREATE TABLE IF NOT EXISTS `ports` (
`port_id` smallint(6) NOT NULL AUTO_INCREMENT,
`location_global` char(9) NOT NULL,
`location_local` varchar(255) NOT NULL,
`port_name` varchar(63) NOT NULL,
`port_status` set('hidden','requiresPTA') NOT NULL,
PRIMARY KEY (`port_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
--
-- Contenu de la table `ports`
--
INSERT INTO `ports` (`port_id`, `location_global`, `location_local`, `port_name`, `port_status`) VALUES
(1, 'B00003001', '3', 'Le Dôme de Thétys', ''),
(2, 'B00001003', '', 'Hypership''s general bays', '');
-- --------------------------------------------------------
--
-- Structure de la table `profiles`
--
CREATE TABLE IF NOT EXISTS `profiles` (
`perso_id` int(11) NOT NULL,
`profile_text` longtext NOT NULL,
`profile_updated` int(10) NOT NULL,
`profile_fixedwidth` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`perso_id`),
KEY `profile_fixedwidth` (`profile_fixedwidth`),
KEY `profile_updated` (`profile_updated`),
FULLTEXT KEY `profile` (`profile_text`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Contenu de la table `profiles`
--
-- --------------------------------------------------------
--
-- Structure de la table `profiles_comments`
--
CREATE TABLE IF NOT EXISTS `profiles_comments` (
`comment_id` mediumint(9) NOT NULL AUTO_INCREMENT,
`perso_id` smallint(5) unsigned NOT NULL,
`comment_author` smallint(5) unsigned NOT NULL,
`comment_date` int(10) NOT NULL,
`comment_text` text NOT NULL,
PRIMARY KEY (`comment_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
--
-- Contenu de la table `profiles_comments`
--
-- --------------------------------------------------------
--
-- Structure de la table `profiles_photos`
--
CREATE TABLE IF NOT EXISTS `profiles_photos` (
`photo_id` int(11) NOT NULL AUTO_INCREMENT,
`perso_id` smallint(6) NOT NULL,
`photo_name` varchar(63) NOT NULL,
`photo_description` varchar(63) NOT NULL,
`photo_avatar` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`photo_id`),
UNIQUE KEY `photo_name` (`photo_name`),
KEY `user_id` (`perso_id`),
KEY `photo_avatar` (`photo_avatar`),
KEY `user_avatar` (`perso_id`,`photo_avatar`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
--
-- Contenu de la table `profiles_photos`
--
-- --------------------------------------------------------
--
-- Structure de la table `profiles_tags`
--
CREATE TABLE IF NOT EXISTS `profiles_tags` (
`perso_id` int(11) NOT NULL,
`tag_code` varchar(31) NOT NULL,
`tag_class` varchar(15) NOT NULL DEFAULT 'music',
PRIMARY KEY (`perso_id`,`tag_code`),
KEY `tag_code` (`tag_code`),
KEY `tag_class` (`tag_class`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Contenu de la table `profiles_tags`
--
-- --------------------------------------------------------
--
-- Structure de la table `registry`
--
CREATE TABLE IF NOT EXISTS `registry` (
`registry_key` varchar(63) NOT NULL,
`registry_value` longtext NOT NULL,
`registry_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`registry_key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Contenu de la table `registry`
--
INSERT INTO `registry` (`registry_key`, `registry_value`, `registry_updated`) VALUES
('api.ship.session.S00001.Demios0001', '1148', '2010-07-04 15:18:04');
-- --------------------------------------------------------
--
-- Structure de la table `sessions`
--
CREATE TABLE IF NOT EXISTS `sessions` (
`session_id` varchar(32) NOT NULL DEFAULT '',
`Where` tinyint(4) NOT NULL DEFAULT '1',
`IP` varchar(8) NOT NULL DEFAULT '',
`user_id` smallint(5) NOT NULL DEFAULT '-1',
`perso_id` smallint(6) DEFAULT NULL,
`Skin` varchar(31) NOT NULL DEFAULT 'zed',
`Skin_accent` varchar(31) NOT NULL DEFAULT '',
`online` tinyint(4) NOT NULL DEFAULT '1',
`HeureLimite` varchar(15) NOT NULL DEFAULT '',
`SessionLimite` varchar(15) NOT NULL DEFAULT '',
PRIMARY KEY (`session_id`),
KEY `Where` (`Where`),
KEY `HeureLimite` (`HeureLimite`)
) ENGINE=MEMORY DEFAULT CHARSET=latin1 COMMENT='Sessions @ Pluton';
--
-- Contenu de la table `sessions`
--
INSERT INTO `sessions` (`session_id`, `Where`, `IP`, `user_id`, `perso_id`, `Skin`, `Skin_accent`, `online`, `HeureLimite`, `SessionLimite`) VALUES
('11o5p5fpacnoutbc2pgvh03ih1', 21, '0a000004', -1, NULL, 'zed', '', 1, '1279392190', '1279399090'),
('74ue7g6k02e6k7bfirqudmhgi7', 21, '0a000004', -1, NULL, 'zed', '', 1, '1279392191', '1279399091'),
('tu8otohbqlhknmt0atiuk850r6', 21, '0a000004', 2600, 4960, 'zed', '', 1, '1279392446', '1279399346'),
('395f7o7pme0dkt32df8h8reo66', 21, '0a000004', -1, NULL, 'zed', '', 1, '1279392191', '1279399091'),
('klss5iti1bf6vja6a6ibd48j02', 21, '0a000004', -1, NULL, 'zed', '', 1, '1279392193', '1279399093'),
('ai71qqkde5hbbjc14sh4dj87o1', 21, '0a000004', -1, NULL, 'zed', '', 1, '1279392194', '1279399094');
-- --------------------------------------------------------
--
-- Structure de la table `ships`
--
CREATE TABLE IF NOT EXISTS `ships` (
`ship_id` mediumint(5) unsigned zerofill NOT NULL AUTO_INCREMENT,
`ship_name` varchar(63) NOT NULL,
`location_global` char(9) DEFAULT NULL,
`location_local` varchar(255) NOT NULL,
`api_key` varchar(36) NOT NULL,
`ship_description` text NOT NULL,
PRIMARY KEY (`ship_id`),
UNIQUE KEY `ship_name` (`ship_name`),
KEY `location` (`location_global`),
KEY `api_key` (`api_key`),
FULLTEXT KEY `ship_name_2` (`ship_name`,`ship_description`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
--
-- Contenu de la table `ships`
--
-- --------------------------------------------------------
--
-- Doublure de structure pour la vue `ships_sessions`
--
CREATE TABLE IF NOT EXISTS `ships_sessions` (
`ship_id` varchar(5)
,`session_id` varchar(165)
,`perso_id` longtext
,`session_updated` bigint(10)
);
-- --------------------------------------------------------
--
-- Structure de la table `users`
--
CREATE TABLE IF NOT EXISTS `users` (
`user_id` smallint(4) NOT NULL DEFAULT '0',
`username` varchar(11) NOT NULL DEFAULT '',
`user_password` varchar(32) NOT NULL DEFAULT '',
`user_active` tinyint(1) NOT NULL DEFAULT '0',
`user_actkey` varchar(11) DEFAULT NULL,
`user_email` varchar(63) NOT NULL DEFAULT '',
`user_regdate` int(10) NOT NULL DEFAULT '0',
PRIMARY KEY (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Contenu de la table `users`
--
-- Adds a default account with demo/demo as login/password
--
INSERT INTO `users` (`user_id`, `username`, `user_password`, `user_active`, `user_actkey`, `user_email`, `user_regdate`) VALUES
(2600, 'demo', 'fe01ce2a7fbac8fafaed7c982a04e229', 1, NULL, 'lorem@ipsum.dol', 1279161321);
-- --------------------------------------------------------
--
-- Structure de la table `users_invites`
--
CREATE TABLE IF NOT EXISTS `users_invites` (
`invite_code` char(6) NOT NULL,
`invite_date` int(10) NOT NULL,
`invite_from_user_id` smallint(5) NOT NULL,
`invite_from_perso_id` smallint(5) NOT NULL,
`invite_to_user_id` smallint(5) DEFAULT NULL,
PRIMARY KEY (`invite_code`),
KEY `invite_to_user_id` (`invite_to_user_id`),
KEY `invite_from_user_id` (`invite_from_user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Contenu de la table `users_invites`
--
-- --------------------------------------------------------
--
-- Structure de la table `users_openid`
--
CREATE TABLE IF NOT EXISTS `users_openid` (
`openid_id` mediumint(9) NOT NULL AUTO_INCREMENT,
`openid_url` varchar(255) NOT NULL,
`user_id` mediumint(9) NOT NULL,
PRIMARY KEY (`openid_id`),
UNIQUE KEY `openid_url` (`openid_url`),
KEY `user_id` (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
--
-- Contenu de la table `users_openid`
--
-- --------------------------------------------------------
--
-- Structure de la vue `content`
--
DROP TABLE IF EXISTS `content`;
CREATE VIEW `content` AS select `cl`.`content_id` AS `content_id`,`cl`.`location_global` AS `location_global`,`cl`.`location_local` AS `location_local`,`cl`.`location_k` AS `location_k`,`cf`.`content_path` AS `content_path`,`cf`.`user_id` AS `user_id`,`cf`.`perso_id` AS `perso_id`,`cf`.`content_title` AS `content_title` from (`content_locations` `cl` join `content_files` `cf`) where (`cf`.`content_id` = `cl`.`content_id`);
-- --------------------------------------------------------
--
-- Structure de la vue `geo_locations`
--
DROP TABLE IF EXISTS `geo_locations`;
CREATE VIEW `geo_locations` AS select concat(_utf8'B',convert(`geo_bodies`.`body_code` using utf8)) AS `location_code`,`geo_bodies`.`body_name` AS `location_name` from `geo_bodies` union select concat(_utf8'B',convert(`geo_places`.`body_code` using utf8),convert(`geo_places`.`place_code` using utf8)) AS `code`,`geo_places`.`place_name` AS `NAME` from `geo_places` union select concat(_utf8'S',convert(`ships`.`ship_id` using utf8)) AS `location_code`,`ships`.`ship_name` AS `location_name` from `ships`;
-- --------------------------------------------------------
--
-- Structure de la vue `ships_sessions`
--
DROP TABLE IF EXISTS `ships_sessions`;
CREATE VIEW `ships_sessions` AS select substr(`registry`.`registry_key`,19,5) AS `ship_id`,substr(`registry`.`registry_key`,25) AS `session_id`,`registry`.`registry_value` AS `perso_id`,unix_timestamp(`registry`.`registry_updated`) AS `session_updated` from `registry` where (left(`registry`.`registry_key`,17) = _utf8'api.ship.session.');
+-- --------------------------------------------------------
+
+--
+-- Structure de la vue `geo_coordinates`
+--
+CREATE VIEW geo_coordinates AS (SELECT body_name as object_name, body_status as object_type, body_location as object_location FROM geo_bodies)
+UNION
+(SELECT ship_name as object_name, 'ship' as object_type, location_global as object_location FROM ships WHERE LEFT(location_global, 3) = 'xyz') ORDER BY object_name
\ No newline at end of file
diff --git a/dev/tests/GeoGalaxyTest.php b/dev/tests/GeoGalaxyTest.php
new file mode 100644
--- /dev/null
+++ b/dev/tests/GeoGalaxyTest.php
@@ -0,0 +1,3 @@
+<?php
+
+?>
\ No newline at end of file
diff --git a/includes/geo/galaxy.php b/includes/geo/galaxy.php
--- a/includes/geo/galaxy.php
+++ b/includes/geo/galaxy.php
@@ -1,85 +1,119 @@
<?php
/**
* Geo galaxy class.
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* A 3D grid of objects
*
- * 0.1 2010-02-08 14:02 DcK
- *
+ * 0.1 2010-02-08 14:02 Initial version [DcK]
+ * 0.2 2010-07-25 9:20 Spherical conversion, get objects
+ *
* @package Zed
* @subpackage Geo
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @copyright 2010 Sébastien Santoro aka Dereckson
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @version 0.1
* @link http://scherzo.dereckson.be/doc/zed
* @link http://zed.dereckson.be/
* @filesource
*/
/**
* Geo galaxy class
*
* This class provides methods to convert coordinate polars.
*
- * @todo add a cartesian_to_polar method
- * @todo add a static method to get a grid of all the galaxy objects, with their x y z representation ; that will be useful to add in API, for a javascript galaxy viewer.
- *
* @todo create a unit testing file dev/tests/GeoGalaxyTest.php
* @todo add unit testing for the normalize_angle method in dev/tests/GeoGalaxyTest.php
- * @todo add unit testing for the polar_to_cartesian method
*/
class GeoGalaxy {
+ /*
+ * ----------------------------------------------------------------------- *
+ * Objects fetchers
+ * ----------------------------------------------------------------------- *
+ */
+
+ /**
+ * Gets all the coordinates of the objects in the galaxy.
+ *
+ * @return array An array of array. Each item is [string object_name, string object_type, GeoPoint3D coordinates]
+ */
+ static function get_coordinates () {
+ global $db;
+ $sql = "SELECT * FROM geo_coordinates";
+ if (!$result = $db->sql_query($sql)) message_die(SQL_ERROR, "Can't query geo_coordinates view.", '', __LINE__, __FILE__, $sql);
+
+ $objects = array();
+ while ($row = $db->sql_fetchrow($result)) {
+ //Demios ship xyz: [-50, 30, 40]
+ //Kaos asteroid xyz: [150, -129, 10]
+ $objects[] = array($row[0], $row[1], GeoPoint3D::fromString($row[2]));
+ }
+ return $objects;
+ }
/*
* ----------------------------------------------------------------------- *
* Helper methods - math
* ----------------------------------------------------------------------- *
*/
/**
* Normalizes an angle, so 0 =< angle < 2 PI
*
* @param float $angle angle in radians (use deg2rad() if you've degrees)
* @return an angle in the 0 =< angle < 2 PI interval
*/
static function normalize_angle ($angle) {
while ($angle < 0) {
$angle += 2 * M_PI;
}
while ($angle >= 2 * M_PI) {
$angle -= 2 * M_PI;
}
return $angle;
}
-
- /*
- * Converts polar coordinates in cartesian x y coordinates
- * @param float $angle angle in radians (use deg2rad() if you've degrees)
- * @param float $height height
- * @return array an array of 2 float items: x, y
+
+ /**
+ * Converts (x, y, z) cartesian to (ρ, φ, θ) spherical coordinates
+ *
+ * The algo used is from http://fr.wikipedia.org/wiki/Coordonn%C3%A9es_sph%C3%A9riques#Relation_avec_les_autres_syst.C3.A8mes_de_coordonn.C3.A9es_usuels
+ *
+ * @param int $x the x coordinate
+ * @param int $y the y coordinate
+ * @param int $z the z coordinate
+ * @return array an array of 3 floats number, representing the (ρ, φ, θ) spherical coordinates
*/
- static function polar_to_cartesian ($angle, $height) {
- //A story of numbers
- if ($height < 0) {
- //Adds 180° and gets absolute value
- $height *= -1;
- $angle + M_PI;
- }
- $x = abs(sin($angle)) . $height;
- $y = abs(cos($angle)) . $height;
+ static function cartesian_to_spherical ($x, $y, $z) {
+ $rho = sqrt($x * $x + $y * $y + $z * $z); //ρ = sqrt(x² + y² + z²)
+ $theta= acos($z / $rho); //φ = acos z/φ
+ $phi = acos($x / sqrt($x * $x + $y * $y)); //θ = acos x / sqrt(x² + y²)
+ if (y < 0) $phi = 2 * M_PI - $phi; //∀ y < 0 θ = 2π - θ
- //And now, the sign
-
-
- //Returns our coordinates
- return array($x, $y);
+ return array(round($rho, 2), round(rad2deg($theta), 2), round(rad2deg($phi), 2));
}
+ /**
+ * Converts (x, y, z) cartesian to (ρ, φ, θ) spherical coordinates
+ *
+ * The algo used is from http://www.phy225.dept.shef.ac.uk/mediawiki/index.php/Cartesian_to_polar_conversion
+ *
+ * @param int $x the x coordinate
+ * @param int $y the y coordinate
+ * @param int $z the z coordinate
+ * @return array an array of 3 floats number, representing the (ρ, φ, θ) spherical coordinates
+ */
+ static function cartesian_to_spherical2 ($x, $y, $z) {
+ $rho = sqrt($x * $x + $y * $y + $z * $z); //ρ = sqrt(x² + y² + z²)
+ $theta= atan2($y, $x); //φ = atan2 $y $x
+ $phi = acos($z / $rho); //θ = acos z/φ
+
+ return array(round($rho, 2), round(rad2deg($theta), 2), round(rad2deg($phi), 2));
+ }
}
\ No newline at end of file
diff --git a/includes/geo/point3D.php b/includes/geo/point3D.php
--- a/includes/geo/point3D.php
+++ b/includes/geo/point3D.php
@@ -1,118 +1,208 @@
<?php
/**
* Geo point 3D class.
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* 0.1 2010-02-23 14:14 DcK
*
* @package Zed
* @subpackage Geo
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @copyright 2010 Sébastien Santoro aka Dereckson
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @version 0.1
* @link http://scherzo.dereckson.be/doc/zed
* @link http://zed.dereckson.be/
* @filesource
*/
/**
* Geo point 3D class.
*
* This class represents a x, y, z point.
*
* It implements IteratorAggregate to allow the foreach instruction
* on a GeoPoint3D object:
*
* <code>
* $point = new GeoPoint3D(17, 24, -6);
* foreach ($point as $axis => $coordinate) {
* echo "\n\t$axis = $coordinate";
* }
* //This will output:
* // x = 17
* // y = 24
* // z = -6
* </code>
*
* The point 3D representation is xyz: [x, y, z] ; you can print it as a string
* and get this format:
*
* <code>
* $point = new GeoPoint3D(17, 24, -6);
* echo (string)$point; //will output xyz: [17, 24, -6]
* </code>
*
*/
class GeoPoint3D implements IteratorAggregate {
//
// x, y, z public properties
//
/**
* the x coordinate
*
* @var integer
*/
public $x;
/**
* the y coordinate
*
* @var integer
*/
public $y;
/**
* the z coordinate
*
* @var integer
*/
public $z;
//
// constructor / toString
//
/**
* Initializes a new instance of GeoPoint3D class
*
* @param int $x the x coordinate
* @param int $y the y coordinate
* @param int $z the z coordinate
*/
function __construct ($x, $y, $z) {
- $this->x = $x;
- $this->y = $y;
- $this->z = $z;
+ $this->x = (int)$x;
+ $this->y = (int)$y;
+ $this->z = (int)$z;
}
/**
- * Returns a xyz: [x, y, z] string representation of the point coordinates
+ * Parses a xyz: [x, y, z] string expression ang gets a GeoPoint3D object
+ *
+ * @param string $expression the expression to parse
+ * @return GeoPoint3D If the specified expression could be parsed, a GeoPoint3D instance ; otherwise, null.
+ */
+ static function fromString ($expression) {
+ if (string_starts_with($expression, 'xyz:', false)) {
+ $pos1 = strpos($expression, '[', 4) + 1;
+ $pos2 = strpos($expression, ']', $pos1);
+ if ($pos1 > -1 && $pos2 > -1) {
+ $expression = substr($expression, $pos1, $pos2 - $pos1);
+ $xyz = explode(',', $expression, 3);
+ return new GeoPoint3D($xyz[0], $xyz[1], $xyz[2]);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns a xyz: [x, y, z] string representation of the point coordinates.
*
* @return string a xyz: [x, y, z] string representation of the coordinates
*/
function __toString () {
return sprintf("xyz: [%d, %d, %d]", $this->x, $this->y, $this->z);
}
+ /**
+ * Determines if this point is equal to the specified point.
+ *
+ * @param GeoPoint3D $point The point to compare
+ * @return bool true if the two points are equal ; otherwise, false.
+ */
+ function equals ($point) {
+ return ($this->x == $point->x) && ($this->y == $point->y) && ($this->z == $point->z);
+ }
+
+ //
+ // Math
+ //
+
+ /**
+ * Gets the (ρ, φ, θ) spherical coordinates from the current x, y, z cartesian point
+ *
+ * The algo used is from http://fr.wikipedia.org/wiki/Coordonn%C3%A9es_sph%C3%A9riques#Relation_avec_les_autres_syst.C3.A8mes_de_coordonn.C3.A9es_usuels
+ *
+ * @return array an array of 3 floats number, representing the (ρ, φ, θ) spherical coordinates
+ */
+ function to_spherical () {
+ return GeoGalaxy::cartesian_to_spherical($this->x, $this->y, $this->z);
+ }
+
+ /**
+ * Gets the (ρ, φ, θ) spherical coordinates from the current x, y, z cartesian point
+ *
+ * The algo used is from http://www.phy225.dept.shef.ac.uk/mediawiki/index.php/Cartesian_to_polar_conversion
+ *
+ * @return array an array of 3 floats number, representing the (ρ, φ, θ) spherical coordinates
+ */
+ function to_spherical2 () {
+ return GeoGalaxy::cartesian_to_spherical2($this->x, $this->y, $this->z);
+ }
+
+ /**
+ * Translates the center and rescales.
+ *
+ * This method allow to help to represent coordinate in a new system
+ *
+ * This method is used to represent Zed objects in dojo with the following
+ * parameters:
+ * <code>
+ * $pointKaos = GeoPoint3D(800, 42, 220);
+ * $pointKaos->translate(500, 300, 200, 2);
+ * </code>
+ *
+ * @param int $dx the difference between the old x and new x (ie the value of x = 0 in the new system)
+ * @param int $dy the difference between the old y and new y (ie the value of y = 0 in the new system)
+ * @param int $dz the difference between the old y and new z (ie the value of z = 0 in the new system)
+ * @scale float $scale if specified, divides each coordinate by this value (optional)
+ */
+ function translate ($dx, $dy, $dz, $scale = 1) {
+ if ($scale == 1) {
+ $this->x += $dx;
+ $this->y += $dy;
+ $this->z += $dz;
+ } elseif ($scale == 0) {
+ $this->x = 0;
+ $this->y = 0;
+ $this->z = 0;
+ } else {
+ $this->x = $this->x * $scale + $dx;
+ $this->y = $this->y * $scale + $dy;
+ $this->z = $this->z * $scale + $dz;
+ }
+ }
+
//
// Implementing IteratorAggregate
//
/**
* Retrieves class iterator. It traverses x, y and z.
*
* @return Traversable the iterator
*/
function getIterator () {
return new ArrayIterator($this);
}
+
+
}
?>
\ No newline at end of file
diff --git a/includes/story/hook_spatioport.php b/includes/story/hook_spatioport.php
--- a/includes/story/hook_spatioport.php
+++ b/includes/story/hook_spatioport.php
@@ -1,130 +1,132 @@
<?php
/**
* Story hook class :: spatioport
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* This class allows to hook spatioport content to a story.
*
* It lists the ship inside the spatioport and in the surrounding space.
*
* @package Zed
* @subpackage Story
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @copyright 2010 Sébastien Santoro aka Dereckson
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @version 0.1
* @link http://scherzo.dereckson.be/doc/zed
* @link http://zed.dereckson.be/
* @filesource
*
* @todo Adds spatioport services, like ship repair & co
* @todo Adds a map of the sky, with ship around
* @todo Consider to use the Port class instead and to move get_ships methods there.
*/
require_once('includes/objects/ship.php');
require_once('includes/geo/location.php');
+$class = 'SpatioportStoryHook';
+
/**
* Spatioport story hook class
*/
class SpatioportStoryHook extends StoryHook {
/**
* The spatioport location
*
* @var GeoLocation
*/
public $location;
/**
* The spatioport global location
*
* @var string
*/
public $location_global;
/**
* The spatioport local location
*
* @var string
*/
public $location_local;
/**
* Updates and gets the current section choices
*
* @param Array $links The story links
*/
function get_choices_links (&$links) {
//$links[] = array('Examiner les vaisseaux', get_url('port','ships'));
}
/**
* Initializes instance location properties
*/
function initialize () {
$this->location_global = $this->perso->location_global;
$this->location_local = $this->section->location_local;
$this->location = new GeoLocation($this->location_global, $this->location_local);
}
/**
* Appends ship list to the story description
*/
function add_content () {
$ships = $this->get_ships();
if (count($ships)) {
echo "\n<h2>Ships</h2>";
echo "<p>Amongst the ships are at the spatioport:</p>";
echo "\n<ul>";
foreach ($ships as $ship) {
$url = get_url('ship', $ship);
echo "\n\t<li><a href=\"$url\">$ship->name</a></li>";
}
echo "\n</ul>";
}
$ships = $this->get_ships_in_space();
if (count($ships)) {
echo "\n<h2>In orbit</h2>";
$place = (string)$this->location->body;
echo "<p>Those ships are in space around $place:</p>";
echo "\n<ul>";
foreach ($ships as $ship) {
$url = get_url('ship', $ship);
echo "\n\t<li><a href=\"$url\">$ship->name</a></li>";
}
echo "\n</ul>";
}
}
/**
* Get ships in the spatioports
*
* @param string $location_global global location
* @param string $location_local local location
* @return array The ships in the spatioport
*/
private function get_ships () {
return Ship::get_ships_at($this->location_global, $this->location_local);
}
/**
* Get ships in the space surrounding the spatioport
*
* @param string $location_global global location
* @param string $location_local local location
* @return array The ships in the space around the spatioport
*/
private function get_ships_in_space () {
return Ship::get_ships_at($this->location_global, null);
}
}
-?>
\ No newline at end of file
+?>
diff --git a/includes/story/story.php b/includes/story/story.php
--- a/includes/story/story.php
+++ b/includes/story/story.php
@@ -1,133 +1,135 @@
<?php
/**
* Story class
*
* Zed. The immensity of stars. The HyperShip. The people.
*
* (c) 2010, Dereckson, some rights reserved.
* Released under BSD license.
*
* @package Zed
* @subpackage Story
* @author Sébastien Santoro aka Dereckson <dereckson@espace-win.org>
* @copyright 2010 Sébastien Santoro aka Dereckson
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* @version 0.1
* @link http://scherzo.dereckson.be/doc/zed
* @link http://zed.dereckson.be/
* @filesource
*/
+require_once('section.php');
+
/**
* Story class
*
* This class is a PHP mapping from the Story XML format.
*
* This class also provides a collection of helper methods to explore the story.
*/
class Story {
/**
* The file path
*
* @var string
*/
public $file;
/**
* The story title
*
* @var string
*/
public $title;
/**
* An array of StorySection elements
*
* @var Array
*/
public $sections = array();
/**
* The SimpleXML parser
*
* @var SimpleXMLElement
*/
private $xml;
/**
* The index of start section in sections array
*
* @var string
*/
private $startSection = null;
/**
* An array of StorySection elements, indexed by location
*
* @var Array
*/
private $sectionsByLocation = array();
function __construct ($file) {
//Opens .xml
if (!file_exists($file)) {
message_die(GENERAL_ERROR, "$file not found.", "Story loading error");
}
$this->file = $file;
$this->parse();
}
/**
* Gets start section
*
* @return StorySection the section where the story starts, or null if not defined
*/
function get_start_section () {
return ($this->startSection != null) ? $this->sections[$this->startSection] : null;
}
/**
* Gets section from local location
*
* @return StorySection the default section at this location, or null if not defined
*/
function get_section_from_location ($location) {
return array_key_exists($location, $this->sectionsByLocation) ? $this->sectionsByLocation[$location] : null;
}
/**
* Parses XML file
*/
function parse () {
//Parses it
$this->xml = simplexml_load_file($this->file);
$this->title = (string)$this->xml->title;
foreach ($this->xml->section as $section) {
//Gets section
$section = StorySection::from_xml($section, $this);
//Have we a start section?
if ($section->start) {
//Ensures we've only one start section
if ($this->startSection != null) {
message_die(GENERAL_ERROR, "Two sections have start=\"true\": $section->id and $this->startSection.", "Story error");
}
$this->startSection = $section->id;
}
//By location
if ($section->location_local) {
$this->sectionsByLocation[$section->location_local] = $section;
}
//Adds to sections array
$this->sections[$section->id] = $section;
}
}
}
-?>
\ No newline at end of file
+?>

File Metadata

Mime Type
text/x-diff
Expires
Sun, Nov 3, 22:34 (3 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
21154
Default Alt Text
(68 KB)

Event Timeline