Add and use config file and example config file for DB.

This commit is contained in:
nearwood 2014-12-22 15:24:50 -05:00
commit ae5e8e43c7
62 changed files with 8947 additions and 0 deletions

2
.hgignore Normal file
View File

@ -0,0 +1,2 @@
.*.msq
^config.php$

2213
38.msq Normal file

File diff suppressed because it is too large Load Diff

5071
39.msq Normal file

File diff suppressed because it is too large Load Diff

57
README.md Normal file
View File

@ -0,0 +1,57 @@
# MSQur #
'Masker' for lack of better name.
MegaSquirt MSQ file sharing and viewing site.
Parses MSQ "XML" and displays it in a familiar format for viewing and comparison.
MSQ XML is pretty bad XML, it doesn't take advantage of many XML features.
# TODO #
1. Strip whitespace
1. Store gzipped?
1. Add Ads
1. Show extended info (warmup, etc.)
1. Searching MSQ comments?
1. Allow download
1. Allow export of just fuel/spark tables (msqpart, .table)
1. Sign-in?
1. Updating/Versioning/Differential MSQ info
# Done #
1. -Upload file-
1. -Store files in DB instead of FS-
1. -Re-encode as UTF-8 or degrees symbol breaks things.-
1. -Parse File, show basic info-
1. -Show Fuel Table-
1. -Show Timing Table-
Uploader (user)/Manager (admin)
Parser
Displayer
### How do I get set up? ###
* AMP Stack
* Create database user and tables
* Upload web files
* How to run tests
* Deployment instructions
### Contribution guidelines ###
* Writing tests
* Code review
* Other guidelines
### Who do I talk to? ###
* Repo owner or admin
* Other community or team contact
### Credits ###
Apache, PHP, MySQL
jQuery, jQuery UI
jquery.tablesorter http://tablesorter.com/docs/
Tango Icon Theme
Geany/Notepad++

7
admin.php Normal file
View File

@ -0,0 +1,7 @@
<?php
//total msqs
//total something
//total views
//most popular
//most viewed
?>

42
browse.php Normal file
View File

@ -0,0 +1,42 @@
<?php
require('db.php');
require('header.php');
?>
<div id='content'>
<div>
<form id="filter">
<fieldset>
<legend>Engine Filter</legend>
<div>Cylinders: <input type="number" min="0" value="6" max="99" style="width:3em;"/></div>
<div>Displacement (liters): <input type="number" min="0" step="0.01" value="3.0" style="width:4em;"/> +/- <span id="literMargin">0%<input type="number" min="0" step="1"></span></div>
<div>Compression (X:1) <input name="compression" type="number" min="0" step="0.1" value="9.0" style="width:4em;"/> +/- <span id="literMargin">0%<input type="number" min="0" step="1"></span></div>
<div>Aspiration:
<select>
<option value="na" title="AKA: Slow">Naturally Aspirated</option>
<option value="fi" title="The way God intended">Forced Induction</option>
</select>
</div>
<div>Firmware: X</div>
<div><button>Refresh</button></div>
</fieldset>
</form>
</div>
<?php
$results = getAll();
$numResults = count($results);
//echo '<div class="debug">'; var_export($results); echo '</div>';
echo '<div class="info">' . $numResults . ' results.</div>';
echo '<table>';
echo '<tr><th>ID</th><th>Cylinders</th><th>Liters</th><th>Compression</th><th>Turbo</th><th>Firmware/Version</th><th>Upload Date</th><th>Views</th></th>';
for ($c = 0; $c < $numResults; $c++)
{
echo '<tr><td><a href="index.php?msq=' . $results[$c]['id'] . '">' . $results[$c]['id'] . '</a></td><td>' . $results[$c]['numCylinders'] . '</td><td>' . $results[$c]['displacement'] . '</td><td>' . $results[$c]['compression'] . ':1</td><td>' . $results[$c]['induction'] . '</td><td>' . $results[$c]['firmware'] . '/' . $results[$c]['signature'] . '</td><td>' . $results[$c]['uploadDate'] . '</td><td></td></tr>';
}
echo '</table>';
?>
</div>
<?php require('footer.php'); ?>

7
config.php.dist Normal file
View File

@ -0,0 +1,7 @@
<?php
define('CONFIG_VERSION', "1");
define('DB_HOST', "localhost");
define('DB_USERNAME', "msqur");
define('DB_PASSWORD', "msqur123");
define('DB_NAME', "msqur");
?>

156
db.php Normal file
View File

@ -0,0 +1,156 @@
<?php
require "config.php";
function connect()
{
$db = null;
try
{
//echo "mysql:dbname=" . DB_NAME . ";host=" . DB_HOST . "," . DB_USERNAME . "," . DB_PASSWORD;
$db = new PDO("mysql:dbname=" . DB_NAME . ";host=" . DB_HOST, DB_USERNAME, DB_PASSWORD);
}
catch(PDOException $e)
{
echo '<div class="error">Error connecting to database.</div>'; echo $e->getMessage();
$db = null; //Redundant.
}
return $db;
}
function addEngine($displacement, $cylinders, $compression, $turbo)
{
if (!is_numeric($displacement) || !is_numeric($cylinders) || !is_numeric($compression))
echo '<div class="error">Invalid engine configuration.</div>';
else
{
$db = connect();
if ($db == null) return null;
try
{
//TODO use any existing one before creating
$st = $db->prepare("INSERT INTO engines (displacement, numCylinders, compression, induction) VALUES (:displacement, :cylinders, :compression, :induction)");
$st->bindParam(":displacement", $displacement);
$st->bindParam(":cylinders", $cylinders);
$st->bindParam(":compression", $compression);
if ($turbo == "na")
$t = 0;
else
$t = 1;
$st->bindParam(":induction", $t);
$st->execute();
$id = $db->lastInsertId();
}
catch(PDOException $e)
{
echo '<div class="error">Error adding to the database.</div>'; echo $e->getMessage();
}
return $id;
}
return null;
}
function addFiles($files, $engineid)
{
$db = connect();
if ($db == null) return null;
$fileList = array();
foreach ($files as $file)
{
//echo 'Adding ' . $file['tmp_name'];
$fileList[] = addFile($file, $engineid);
}
return $fileList;
}
function addFile($file, $engineid, $db = null)
{
if ($db == null)
{
$db = connect();
if ($db == null) return null;
}
try
{
//TODO Compress?
$st = $db->prepare("INSERT INTO msqs (xml) VALUES (:xml)");
$xml = file_get_contents($file['tmp_name']);
//Convert encoding to UTF-8
$xml = mb_convert_encoding($xml, "UTF-8");
//Strip out invalid xmlns
$xml = preg_replace('/xmlns=".*?"/', '', $xml);
$st->bindParam(":xml", $xml);
$st->execute();
$id = $db->lastInsertId();
$st = $db->prepare("INSERT INTO metadata (url,msq,engine,fileFormat,signature,uploadDate) VALUES (:url, :id, :engine, '4.0', 'unknown', :uploaded)");
$st->bindParam(":url", $id); //could do hash but for now, just the id
$st->bindParam(":id", $id);
if (!is_numeric($engineid)) $engineid = null;
$st->bindParam(":engine", $engineid);
//TODO Make sure it's an int
$dt = new DateTime();
$dt = $dt->format('Y-m-d H:i:s');
$st->bindParam(":uploaded", $dt);
$st->execute();
$id = $db->lastInsertId();
}
catch(PDOException $e)
{
echo '<div class="error">Error adding to the database.</div>'; echo $e->getMessage();
}
return $id;
}
function getMSQ($id)
{
$db = connect();
if ($db == null) return null;
try
{
$st = $db->prepare("SELECT msqs.xml FROM msqs INNER JOIN metadata ON metadata.msq = msqs.id WHERE metadata.id = :id");
$st->bindParam(":id", $id);
$st->execute();
$result = $st->fetch(PDO::FETCH_ASSOC);
}
catch(PDOException $e)
{
echo '<div class="error">Error executing database query.</div>'; echo $e->getMessage();
}
if (!$result) return null;
else return $result['xml'];
}
//TODO Rename?
//TODO Pagination
function getAll()
{
$db = connect();
if ($db == null) return null;
try
{
$st = $db->prepare("SELECT * FROM metadata INNER JOIN engines ON metadata.engine = engines.id");
$st->execute();
$result = $st->fetchAll(PDO::FETCH_ASSOC);
}
catch(PDOException $e)
{
echo '<div class="error">Error executing database query: </div>'; echo $e->getMessage();
}
if (!$result) return null;
else return $result;
}
?>

5
footer.php Normal file
View File

@ -0,0 +1,5 @@
<div class="footer">
v0.2a (DB 0) <a href="http://httpd.apache.org/">Apache</a> <a href="http://php.net/">PHP</a> <a href="http://jquery.com/">jQuery</a>
</div>
</body>
</html>

46
header.php Normal file
View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<title>MSQur</title>
<meta name="description" content="Megasquirt tune file sharing site">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="msqur.css" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/themes/smoothness/jquery-ui.css" />
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js"></script>
<script src="lib/tablesorter/jquery.tablesorter.min.js"></script>
<script src="msqur.js"></script>
</head>
<body>
<div id="navigation"><span><button id="btnUpload">Upload</button></span><span><a href="browse.php">Browse</a></span><span><a href="search.php">Search</a></span><span><a href="stats.php">Stats</a></span><span id="aboutLink">About</span></div>
<div id="upload" style="display:none;">
<form action="index.php" method="post" enctype="multipart/form-data">
<div id="fileDropZone">Drop files here
<input type="file" id="fileSelect" name="files[]" multiple />
</div>
<output id="fileList"></output>
<div id="engineForm">
<fieldset>
<legend>Engine Information</legend>
<div>Cylinders: <input name="cylinders" type="number" min="0" value="6" max="99" style="width:3em;"/></div>
<div>Displacement (liters): <input name="displacement" type="number" min="0" step="0.01" value="3.0" style="width:4em;"/></div>
<div>Compression (X:1) <input name="compression" type="number" min="0" step="0.1" value="9.0" style="width:4em;"/></div>
<div>Aspiration:
<select name="aspiration">
<option value="na" title="AKA: Slow">Naturally Aspirated</option>
<option value="fi" title="The way God intended">Forced Induction</option>
</select>
</div>
</fieldset>
</div>
<input type="hidden" name="upload" value="upload" style="display:none;">
</form>
</div>
<div id="settings">
<img id="settingsIcon" src="img/settings3.png"/>
<div id="settingsPanel" style="display:none;">
<label><input type="checkbox" checked />Colorize</label>
<label><input type="checkbox" checked />Normalize Axis</label>
<label><input type="checkbox" disabled />Normalize Data</label>
</div>
</div>

BIN
img/error.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
img/important.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
img/settings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
img/settings2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
img/settings3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
img/unreadable.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
img/warning.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

95
index.php Normal file
View File

@ -0,0 +1,95 @@
<?php
error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('html_errors', false);
require('db.php');
require('msq.php');
function fixFileArray(&$file_post)
{//From php.net anonymous comment
$file_ary = array();
$file_count = count($file_post['name']);
$file_keys = array_keys($file_post);
for ($i=0; $i<$file_count; $i++)
{
foreach ($file_keys as $key)
{
$file_ary[$i][$key] = $file_post[$key][$i];
}
}
return $file_ary;
}
function checkUploads($files)
{//Expects fixed array instead of $_FILES array
foreach ($files as $index => $file)
{
//Discard any with errors
if ($file['error'] != UPLOAD_ERR_OK)
{
unset($files[$index]);
continue;
}
//Check sizes against 1MiB
if ($file['size'] > 1048576)
{
unset($files[$index]);
continue;
}
//Get and check mime types (ignoring provided ones)
$finfo = new finfo(FILEINFO_MIME_TYPE);
if ($finfo->file($file['tmp_name']) != "application/xml")
{
unset($files[$index]);
continue;
}
}
return $files;
}
require('header.php');
?>
<div id='content'>
<?php
if (isset($_GET['msq'])) {
$msq = getMSQ($_GET['msq']);
parseMSQ($msq);
} else if (isset($_POST['upload']) && isset($_FILES)) {
//var_dump($_POST);
//var_dump($_FILES);
?>
<div class="info">Upload successful</div>
<?php
$files = checkUploads(fixFileArray($_FILES['files']));
if (count($files) == 0)
{
//No files made it past the check
echo '<div class="error">Your files have asploded.</div>';
}
else
{
if (count($files) == 1)
echo '<div class="info">' . count($files) . ' file was uploaded:</div>';
else
echo '<div class="info">' . count($files) . ' files were uploaded:</div>';
//$motor = $validate($_POST['cylinders'])
$engineid = addEngine($_POST['displacement'], $_POST['cylinders'], $_POST['compression'], $_POST['aspiration']);
$fileList = addFiles($files, $engineid);
echo '<div class="info"><ul id="fileList">';
foreach ($fileList as $f)
{
echo '<li><a href="' . $_SERVER['REQUEST_URI'] . '?msq=' . $f . '">' . $f . '</a></li>';
}
echo '</div></ul>';
}
}
?>
</div>
<?php require('footer.php'); ?>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,5 @@
K 25
svn:wc:ra_dav:version-url
V 28
/svn/!svn/ver/3/trunk/themes
END

View File

@ -0,0 +1,34 @@
10
dir
5
https://tablesorter.googlecode.com/svn/trunk/themes
https://tablesorter.googlecode.com/svn
2009-10-02T08:54:38.707056Z
3
christian.bach
svn:special svn:externals svn:needs-lock
dbe5111a-81cf-11de-b558-27974e103503
blue
dir
green
dir

View File

@ -0,0 +1,35 @@
K 25
svn:wc:ra_dav:version-url
V 33
/svn/!svn/ver/3/trunk/themes/blue
END
style.css
K 25
svn:wc:ra_dav:version-url
V 43
/svn/!svn/ver/3/trunk/themes/blue/style.css
END
desc.gif
K 25
svn:wc:ra_dav:version-url
V 42
/svn/!svn/ver/3/trunk/themes/blue/desc.gif
END
asc.gif
K 25
svn:wc:ra_dav:version-url
V 41
/svn/!svn/ver/3/trunk/themes/blue/asc.gif
END
bg.gif
K 25
svn:wc:ra_dav:version-url
V 40
/svn/!svn/ver/3/trunk/themes/blue/bg.gif
END
blue.zip
K 25
svn:wc:ra_dav:version-url
V 42
/svn/!svn/ver/3/trunk/themes/blue/blue.zip
END

View File

@ -0,0 +1,198 @@
10
dir
5
https://tablesorter.googlecode.com/svn/trunk/themes/blue
https://tablesorter.googlecode.com/svn
2009-10-02T08:54:38.707056Z
3
christian.bach
svn:special svn:externals svn:needs-lock
dbe5111a-81cf-11de-b558-27974e103503
asc.gif
file
2010-10-15T09:18:19.000000Z
f8a1940c9cf44ab8870319169f3a14ff
2009-10-02T08:54:38.707056Z
3
christian.bach
has-props
54
bg.gif
file
2010-10-15T09:18:19.000000Z
c01ad2e7c59d1a20a433cb873c21bd88
2009-10-02T08:54:38.707056Z
3
christian.bach
has-props
64
blue.zip
file
2010-10-15T09:18:19.000000Z
898afbfe9f54e586eb483bc9e91fd01d
2009-10-02T08:54:38.707056Z
3
christian.bach
has-props
885
desc.gif
file
2010-10-15T09:18:19.000000Z
a54846803de3cc786eec3d69f9ac2d38
2009-10-02T08:54:38.707056Z
3
christian.bach
has-props
54
style.css
file
2010-10-15T09:18:19.000000Z
5b98d0810fb7dbb9fcbc2362655f0dd7
2009-10-02T08:54:38.707056Z
3
christian.bach
has-props
912

View File

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 24
application/octet-stream
END

View File

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 24
application/octet-stream
END

View File

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 24
application/octet-stream
END

View File

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 24
application/octet-stream
END

View File

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 10
text/plain
END

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 B

View File

@ -0,0 +1,39 @@
/* tables */
table.tablesorter {
font-family:arial;
background-color: #CDCDCD;
margin:10px 0pt 15px;
font-size: 8pt;
width: 100%;
text-align: left;
}
table.tablesorter thead tr th, table.tablesorter tfoot tr th {
background-color: #e6EEEE;
border: 1px solid #FFF;
font-size: 8pt;
padding: 4px;
}
table.tablesorter thead tr .header {
background-image: url(bg.gif);
background-repeat: no-repeat;
background-position: center right;
cursor: pointer;
}
table.tablesorter tbody td {
color: #3D3D3D;
padding: 4px;
background-color: #FFF;
vertical-align: top;
}
table.tablesorter tbody tr.odd td {
background-color:#F0F0F6;
}
table.tablesorter thead tr .headerSortUp {
background-image: url(asc.gif);
}
table.tablesorter thead tr .headerSortDown {
background-image: url(desc.gif);
}
table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp {
background-color: #8dbdd8;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 B

View File

@ -0,0 +1,39 @@
/* tables */
table.tablesorter {
font-family:arial;
background-color: #CDCDCD;
margin:10px 0pt 15px;
font-size: 8pt;
width: 100%;
text-align: left;
}
table.tablesorter thead tr th, table.tablesorter tfoot tr th {
background-color: #e6EEEE;
border: 1px solid #FFF;
font-size: 8pt;
padding: 4px;
}
table.tablesorter thead tr .header {
background-image: url(bg.gif);
background-repeat: no-repeat;
background-position: center right;
cursor: pointer;
}
table.tablesorter tbody td {
color: #3D3D3D;
padding: 4px;
background-color: #FFF;
vertical-align: top;
}
table.tablesorter tbody tr.odd td {
background-color:#F0F0F6;
}
table.tablesorter thead tr .headerSortUp {
background-image: url(asc.gif);
}
table.tablesorter thead tr .headerSortDown {
background-image: url(desc.gif);
}
table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp {
background-color: #8dbdd8;
}

View File

@ -0,0 +1,35 @@
K 25
svn:wc:ra_dav:version-url
V 34
/svn/!svn/ver/3/trunk/themes/green
END
bg.png
K 25
svn:wc:ra_dav:version-url
V 41
/svn/!svn/ver/3/trunk/themes/green/bg.png
END
green.zip
K 25
svn:wc:ra_dav:version-url
V 44
/svn/!svn/ver/3/trunk/themes/green/green.zip
END
style.css
K 25
svn:wc:ra_dav:version-url
V 44
/svn/!svn/ver/3/trunk/themes/green/style.css
END
desc.png
K 25
svn:wc:ra_dav:version-url
V 43
/svn/!svn/ver/3/trunk/themes/green/desc.png
END
asc.png
K 25
svn:wc:ra_dav:version-url
V 42
/svn/!svn/ver/3/trunk/themes/green/asc.png
END

View File

@ -0,0 +1,198 @@
10
dir
5
https://tablesorter.googlecode.com/svn/trunk/themes/green
https://tablesorter.googlecode.com/svn
2009-10-02T08:54:38.707056Z
3
christian.bach
svn:special svn:externals svn:needs-lock
dbe5111a-81cf-11de-b558-27974e103503
asc.png
file
2010-10-15T09:18:19.000000Z
47d431b1524d523eae100b66b09babdc
2009-10-02T08:54:38.707056Z
3
christian.bach
has-props
2665
bg.png
file
2010-10-15T09:18:19.000000Z
7b0a5fe32e94b1595e48810a3df45648
2009-10-02T08:54:38.707056Z
3
christian.bach
has-props
2655
desc.png
file
2010-10-15T09:18:19.000000Z
0f7f4fd46fe145ed6ed4c81c3b26a93f
2009-10-02T08:54:38.707056Z
3
christian.bach
has-props
2662
green.zip
file
2010-10-15T09:18:19.000000Z
9c8b5235a0a9864b292b97e783541c08
2009-10-02T08:54:38.707056Z
3
christian.bach
has-props
8464
style.css
file
2010-10-15T09:18:19.000000Z
8c047013d96b74708da195dac43980b7
2009-10-02T08:54:38.707056Z
3
christian.bach
has-props
801

View File

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 24
application/octet-stream
END

View File

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 24
application/octet-stream
END

View File

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 24
application/octet-stream
END

View File

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 24
application/octet-stream
END

View File

@ -0,0 +1,5 @@
K 13
svn:mime-type
V 10
text/plain
END

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,39 @@
table.tablesorter {
font-size: 12px;
background-color: #4D4D4D;
width: 1024px;
border: 1px solid #000;
}
table.tablesorter th {
text-align: left;
padding: 5px;
background-color: #6E6E6E;
}
table.tablesorter td {
color: #FFF;
padding: 5px;
}
table.tablesorter .even {
background-color: #3D3D3D;
}
table.tablesorter .odd {
background-color: #6E6E6E;
}
table.tablesorter .header {
background-image: url(bg.png);
background-repeat: no-repeat;
border-left: 1px solid #FFF;
border-right: 1px solid #000;
border-top: 1px solid #FFF;
padding-left: 30px;
padding-top: 8px;
height: auto;
}
table.tablesorter .headerSortUp {
background-image: url(asc.png);
background-repeat: no-repeat;
}
table.tablesorter .headerSortDown {
background-image: url(desc.png);
background-repeat: no-repeat;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

View File

@ -0,0 +1,39 @@
table.tablesorter {
font-size: 12px;
background-color: #4D4D4D;
width: 1024px;
border: 1px solid #000;
}
table.tablesorter th {
text-align: left;
padding: 5px;
background-color: #6E6E6E;
}
table.tablesorter td {
color: #FFF;
padding: 5px;
}
table.tablesorter .even {
background-color: #3D3D3D;
}
table.tablesorter .odd {
background-color: #6E6E6E;
}
table.tablesorter .header {
background-image: url(bg.png);
background-repeat: no-repeat;
border-left: 1px solid #FFF;
border-right: 1px solid #000;
border-top: 1px solid #FFF;
padding-left: 30px;
padding-top: 8px;
height: auto;
}
table.tablesorter .headerSortUp {
background-image: url(asc.png);
background-repeat: no-repeat;
}
table.tablesorter .headerSortDown {
background-image: url(desc.png);
background-repeat: no-repeat;
}

8
msq.format4.json Normal file
View File

@ -0,0 +1,8 @@
{
constants: [{name: "O2 Sensor Type", id: 'egoType'}],
tables: [
{name: "VE Table", data: 'veTable1', units: "%", x: 'frpm_table1', y: 'fmap_table1'},
{name: "Timing Advance", data: 'advanceTable1', units: "degrees", x: 'arpm_table1', y: 'amap_table1'},
{name: "AFR Targets", data: 'afrTable1', units: "AFR", x: 'arpm_table1', y: 'amap_table1'}
]
};

128
msq.php Normal file
View File

@ -0,0 +1,128 @@
<?php
//TODO Find better name
define("LARGE_HOT", 0x1);
define("LARGE_COLD", 0x2);
function msqAxis($el)
{
//Why the fuck does this flag bork here on not on the table data?
//And why don't I have to trim the table data either?
return preg_split("/\s+/", trim($el));//, PREG_SPLIT_NO_EMPTY);
}
function msqTable($name, $data, $x, $y, $hot)
{
$rows = count($y);
$cols = count($x);
//echo "ROWS: $rows, $cols";
//var_dump($x, "YYYYYYYYY", $y);
if ($rows * $cols != count($data))
{
echo '<div class="error">' . $name . ' column/row count mismatched with data count.</div>';
return;
}
echo '<table class="msq tablesorter" hot="' . $hot . '">';
echo "<caption>$name</caption>";
echo "<thead><tr><th></th>";
for ($c = 0; $c < $cols; $c++)
{
//TODO: This is not triggering tablesorter
echo '<th class="{sorter: false}">' . $x[$c] . "</th>";
}
echo "</tr></thead>";
for ($r = 0; $r < $rows; $r++)
{
echo "<tr><th>" . $y[$r] . "</th>";
for ($c = 0; $c < $cols; $c++)
{
//if ($r == 0) echo "<td>" . $data[$c] . "</td>";
//else
echo "<td>" . $data[$r * $rows + $c] . "</td>";
//echo "</tr>($c, $r) ";
}
}
echo "</tr>";
echo "</table>";
}
function parseMSQ($xml)
{
//This should be json and stored somewhere else
$msqMap = array(//xmlName => pretty name, [xAxisXmlName, yAxisXmlName]
'veTable1' => array('name' => 'VE Table 1', 'x' => 'frpm_table1', 'y' => 'fmap_table1', 'units' => '%', 'hot' => 'descending'),
'advanceTable1' => array('name' => 'Timing Advance', 'x' => 'frpm_table1', 'y' => 'fmap_table1', 'units' => 'degrees', 'hot' => 'ascending'),
'afrTable1' => array('name' => 'AFR Targets', 'x' => 'arpm_table1', 'y' => 'amap_table1', 'hot' => 'ascending'),
'egoType' => array('name' => 'O2 Sensor Type')
);
$msq = simplexml_load_string($xml);
if ($msq)
{
/*
* <bibliography author="TunerStudio MS 2.0.6 - EFI Analytics, Inc." tuneComment=" &lt;br&gt;&#13; &lt;br&gt;&#13; &lt;br&gt;&#13; &lt;br&gt;&#13; &lt;br&gt;&#13; &lt;br&gt;&#13; " writeDate="Mon Jul 15 09:16:28 EDT 2013"/>
* <versionInfo fileFormat="4.0" firmwareInfo="" nPages="15" signature="MS3 Format 0262.09 "/>
*/
//var_dump($msq);
echo '<div class="msqInfo">';
echo "<span>Format Version: " . $msq->versionInfo['fileFormat'] . "</span>";
echo "<span>MS Signature: " . $msq->versionInfo['signature'] . "</span>";
echo "<span>Tuning SW: " . $msq->bibliography['author'] . "</span>";
echo "<span>Date: " . $msq->bibliography['writeDate'] . "</span>";
echo '</div>';
//if cols and rows exist it's a table (maybe 1xR)
//otherwise it's a single value
//looks like cols=1 is typical for single dimension
//still need lookup table of axis
//wtf is digits?
//foreach ($msq->page as $page)
//foreach ($page->constant as $constant)
// //constant[@name="veTable1"]
foreach ($msqMap as $key => $value)
{
$constant = $msq->xpath('//constant[@name="' . $key . '"]')[0];
if (isset($constant['cols'])) //and >= 1?
{//We have a table
//See if this is one we know how to handle
if (isset($value['x'])) //and y hopefully
{
$numCols = (int)$constant['cols'];
$numRows = (int)$constant['rows'];
$x = msqAxis($msq->xpath('//constant[@name="' . $value['x'] . '"]')[0]);
$y = msqAxis($msq->xpath('//constant[@name="' . $value['y'] . '"]')[0]);
if ((count($x) == $numCols) && (count($y) == $numRows))
{
$tableData = preg_split("/\s+/", trim($constant));//, PREG_SPLIT_NO_EMPTY); //, $limit);
msqTable($value['name'], $tableData, $x, $y, $value['hot']);
}
else
{
echo '<div class="error">' . $value['name'] . ' axis count mismatched with data count.</div>';
echo '<div class="debug">' . count($x) . ", " . count($y) . " vs $numCols, $numRows</div>";
}
}
}
}
//foreach ($movies->xpath('//settings/setting') as $setting) {
// echo $setting->name, 'value: ', $setting->value, PHP_EOL;
//}
}
else
{
echo '<div class="error">No such tune dude.</div>';
}
}
?>

118
msqur.css Normal file
View File

@ -0,0 +1,118 @@
* {
font-family: "Verdana", sans-serif;
}
div.error {
color: red;
}
div.warning {
color: orange;
}
div.info {
color: green;
}
div.debug {
font-family: monospace !important;
color: dark-gray;
}
div#navigation {
background: #333;
color: white;
padding: 8px 24px 8px 24px;
}
div#navigation span {
font-weight: bold;
padding: 0px 8px 0px 8px;
}
div#navigation a:link {
color: green;
}
div#navigation a:hover {
color: white;
}
div#navigation a:active {
color: white;
}
div#navigation a:visited {
color: red;
}
div.footer {
font-size: 0.66em;
text-align: right;
color: light-gray;
position: fixed;
bottom: 4px;
right: 8px;
z-index: -999
}
div#settings {
position: absolute;
margin-top: 4px;
right: 8px;
}
#fileDropZone {
border: 2px dashed #bbb;
border-radius: 5px;
padding: 25px;
text-align: center;
font: 20pt bold 'Vollkorn';
color: #bbb;
}
table {
border-collapse: collapse;
border: 1px solid #CCC;
/*width: 100%;*/
}
table caption {
caption-side: top;
font-size: 2em;
font-style: bold;
text-align: left;
padding: 0.2em;
}
table.msq td:hover {
background-color: magenta !important;
}
table th, table td {
padding: 4px;
border: 1px dotted #333;
font-size: smaller;
text-align: center;
}
/* eh, need to switch top/bottom border dep. on where the header is */
table th[scope=col] {
border-top: 2px solid #333;
border-right: 2px solid #333;
}
/* inbetween headers but not ends */
table th+th[scope=col] {
border-right: 1px dotted #666;
}
table th[scope=row] {
border-right: 2px solid #333;
}
/* Hidden features */
span#literMargin input{
display: none;
}
form#filter {
display: none;
}

142
msqur.js Normal file
View File

@ -0,0 +1,142 @@
$(function() {
//TODO Move this somewhere else
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-5743113-10', 'auto');
ga('send', 'pageview');
$('div#upload').dialog({
modal: true,
autoOpen: false,
title: "Upload Tune Files",
width: "450px",
buttons: {
Upload: upload,
Cancel: function() { $(this).dialog('close'); }
}
});
$('#btnUpload').click(function(e) {
if (window.File && window.FileReader && window.FileList && window.Blob)
{
$('div#upload').dialog('open');
} else {
alert('The File APIs are not fully supported in this browser.');
//TODO no ajax file upload
}
});
$('#settingsIcon').click(function(e) {
$('#settingsPanel').toggle();
});
function colorTable(table, reverseColor)
{//reverseColor could be an override, value passed in is currently ignored
var colors = new Array();
var min = Number.MAX_SAFE_INTEGER;
var max = Number.MIN_SAFE_INTEGER;
//Find min and max
table.find('td').each(function(i) {
var v = parseFloat(this.textContent);
if (v < min) min = v;
else if (v > max) max = v;
});
if (table.attr('hot') == 'ascending')
reverseColor = true;
if (table.attr('hot') == 'descending')
reverseColor = false;
var range = (max - min);
console.debug("Range: " + range);
var r = 0, g = 0, b = 0, percent = 0, intensity = 0.6;
table.find('td').each(function(i) {
var v = parseFloat(this.textContent);
percent = (v - min) / range;
if (reverseColor)
percent = 1.0 - percent;
if (percent < 0.33)
{
r = 1.0;
g = Math.min(1.0, (percent * 3));
b = 0.0;
}
else if (percent < 0.66)
{
r = Math.min(1.0, ((0.66 - percent) * 3));
g = 1.0;
b = 0.0;
}
else
{
r = 0.0;
g = Math.min(1.0, ((1.0 - percent) * 3));
b = 1.0 - g;
}
r = Math.round((r * intensity + (1.0 - intensity)) * 255);
g = Math.round((g * intensity + (1.0 - intensity)) * 255);
b = Math.round((b * intensity + (1.0 - intensity)) * 255);
//this.css('background-color', 'rgb(' + r + ',' + g + ',' + b + ')');
this.style.backgroundColor = 'rgb(' + r + ',' + g + ',' + b + ')';
});
return colors;
}
//FIXME Hack for tablesorter bug
var hdrObj = {};
for (var i = 1; i < 32; ++i)
hdrObj[i] = {sorter: false};
$('table').tablesorter({
headers: hdrObj,
sortList: [[0, 1]]
});
$('table.msq').each(function(i) { colorTable($(this)); });
function uploadAdd(e)
{
e.stopPropagation();
e.preventDefault();
var files = e.target.files || e.dataTransfer.files
//TODO type check
var output = [];
for (var i = 0, f; f = files[i]; ++i)
{
output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',
f.size, ' bytes, last modified: ',
f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a',
'</li>');
}
$('output#fileList').html('<ul>' + output.join('') + '</ul>');
}
function uploadDragOver(e)
{
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
}
function upload()
{
//TODO Check files
$('div#upload form').submit();
}
$('input#fileSelect').change(uploadAdd);
var dropZone = document.getElementById('fileDropZone');
dropZone.addEventListener('dragover', uploadDragOver);
dropZone.addEventListener('drop', uploadAdd);
});

110
msqur.sql Normal file
View File

@ -0,0 +1,110 @@
-- phpMyAdmin SQL Dump
-- version 4.3.3
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Dec 22, 2014 at 02:49 PM
-- Server version: 10.0.15-MariaDB-log
-- PHP Version: 5.6.3
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET NAMES utf8 */;
--
-- Database: `msqur`
--
CREATE DATABASE IF NOT EXISTS `msqur` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `msqur`;
-- --------------------------------------------------------
--
-- Table structure for table `engines`
--
DROP TABLE IF EXISTS `engines`;
CREATE TABLE IF NOT EXISTS `engines` (
`id` int(11) NOT NULL,
`displacement` decimal(4,2) NOT NULL,
`numCylinders` tinyint(2) NOT NULL,
`compression` decimal(4,2) NOT NULL,
`induction` int(11) NOT NULL,
`injectorSize` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `metadata`
--
DROP TABLE IF EXISTS `metadata`;
CREATE TABLE IF NOT EXISTS `metadata` (
`id` int(11) NOT NULL,
`msq` int(11) NOT NULL,
`engine` int(11) DEFAULT NULL,
`url` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`fileFormat` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`signature` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`firmware` varchar(255) NOT NULL,
`author` varchar(255) NOT NULL,
`writeDate` datetime NOT NULL,
`uploadDate` datetime NOT NULL,
`tuneComment` text NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `msqs`
--
DROP TABLE IF EXISTS `msqs`;
CREATE TABLE IF NOT EXISTS `msqs` (
`id` int(11) NOT NULL,
`xml` mediumtext CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `engines`
--
ALTER TABLE `engines`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `metadata`
--
ALTER TABLE `metadata`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `msqs`
--
ALTER TABLE `msqs`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `engines`
--
ALTER TABLE `engines`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3;
--
-- AUTO_INCREMENT for table `metadata`
--
ALTER TABLE `metadata`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3;
--
-- AUTO_INCREMENT for table `msqs`
--
ALTER TABLE `msqs`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3;

13
search.php Normal file
View File

@ -0,0 +1,13 @@
<?php
require('db.php');
require('header.php');
?>
<div id='content'>
<div class="info">Coming soon...</div>
<form id="search">
<input type="text"/>
</form>
</div>
<?php require('footer.php'); ?>

12
stats.php Normal file
View File

@ -0,0 +1,12 @@
<?php
//trim/concentrate/whatever engines (remove dupes)
//remove all msqs/metadata/engines (fresh slate)
//find metada and engines (browse)
SELECT * FROM `metadata` JOIN `engines` ON engines.id = metadata.engine
//DELETE ALL DATA
TRUNCATE metadata
TRUNCATE engines
TRUNCATE msqs
?>