* Accelerometer class to access the device accelerometer
*
* @author Rikhard Kuutti <rikhard.kuutti@fudeco.com>
- * @author Kai Rasilainen
+ * @author Kai Rasilainen <kai.rasilainen@fudeco.com>
* @copyright (c) 2010 Speed Freak team
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/
#define ACCELEROMETER_H
#include <QObject>
-#include <QTime>
-#include <QTimer>
-#include <QFile>
#include "calculate.h"
peakPower = 0;
currentPower = 0;
currentSpeed = 0;
+ maxSpeed = 0;
distanceTraveled = 0;
lastAcceleration = 0;
lastDistance = 0;
lastSpeed = 0;
numOfIterations = 0;
totalTime = 0;
- //count = 0;
+ count = 0;
speedCheckPoints.append(10);
speedCheckPoints.append(20);
// First integration of acceleration provides speed
currentSpeed = (lastSpeed + (((currentAcceleration + lastAcceleration) * seconds) / 2));
+ // Update maximum speed
+ if (currentSpeed > maxSpeed)
+ maxSpeed = currentSpeed;
+
// Second integration: distance.
distanceTraveled = (lastDistance + (((currentSpeed + lastSpeed) * seconds) / 2));
}
// Check for movement
- //accelStoppedCheck(currentAcceleration);
+ accelStoppedCheck(currentAcceleration);
lastSpeed = currentSpeed;
lastAcceleration = currentAcceleration;
* a short period of time. Velocity is set to zero to avoid
* distance errors.
*/
-/*
void Calculate::accelStoppedCheck(double currentAcceleration)
{
-
// counting number of acceleration samples that equals zero
if (currentAcceleration==0) {
count++;
count = 0;
}
- // if count exceeds 15, we assume that velocity is zero
- if (count >= 15)
+ // if count exceeds 25, we assume that velocity is zero
+ if (count >= 25)
{
currentSpeed=0;
}
}
-*/
+
// Getters and setters
double Calculate::getAverageSpeed()
averagePower = value;
}
+double Calculate::getMaxSpeed()
+{
+ return maxSpeed;
+}
+
+void Calculate::setMaxSpeed(double value)
+{
+ maxSpeed = value;
+}
void reset();
void calculateParameters(double currentAcceleration, double seconds);
- //void accelStoppedCheck(double currentAcceleration);
+ void accelStoppedCheck(double currentAcceleration);
double getAverageSpeed();
void setAverageSpeed(double value);
double getAveragePower();
void setAveragePower(double value);
+ double getMaxSpeed();
+ void setMaxSpeed(double value);
+
private:
double averageSpeed;
double currentSpeed;
+ double maxSpeed;
double distanceTraveled;
double lastAcceleration;
double lastCheckpoint;
double lastSpeed;
long numOfIterations;
double totalTime;
- //int count;
+ int count;
double peakPower;
double currentPower;
double averagePower;
initListViewStartTabAccelerationCategories();
myLogin = new LoginWindow(this);
- categorylist = new CategoryList();
+ myCategorylist = new CategoryList();
myHttpClient = new HttpClient(this);
myRegistration = new Registration(this);
connect(myRegistration,SIGNAL(sendregistration()),this,SLOT(regUserToServer()));
connect(myLogin,SIGNAL(userNameChanged()),this,SLOT(userLogin()));
+ connect(myHttpClient->myXmlreader, SIGNAL(receivedCategoryList()), this, SLOT(setCategoryCompoBox()));
+ connect(myHttpClient->myXmlreader, SIGNAL(receivedTop10List()), this, SLOT(showTop10()));
myRoute = new RouteDialog( this);
//GPS
connect(location,SIGNAL(agnss()),this,SLOT(gpsStatus()));
gpsTime = new QDateTime();
- time = 0;
- speed = 0;
+ this->time = 0;
+ this->speed = 0;
+ counterForSaveResults = 0;
timer = new QTimer();
// Accelerometer
stopTime = 0;
accelerationStartThreshold = 0.02;
- QTimer *accelerometerTimer = new QTimer(this);
+ accelerometerTimer = new QTimer(this);
connect(accelerometerTimer, SIGNAL(timeout()), this, SLOT(readAccelerometerData()));
- accelerometerTimer->start(kAccelerometerSampleRate);
+ //accelerometerTimer->start(kAccelerometerSampleRate);
// Calculate
calculate = new Calculate();
- //connect(calculate, SIGNAL(checkPointReached()), this, SLOT(handleCheckPoint()));
+ connect(calculate, SIGNAL(checkPointReached()), this, SLOT(handleCheckPoint()));
resetAccelerometerMeasurements();
measures = new Measures();
this->initializeMeasures();
- timer->setInterval(300);
+ this->timer->setInterval(300);
connect(this->timer, SIGNAL(timeout()), this, SLOT(after_timeout()));
connect(myLogin, SIGNAL( userNameChanged()), this, SLOT(updateUserName()));
ui->labelMeasureTabResult->hide();
+ ui->pushButtonShowResultDialog->setEnabled(false);
this->setWindowTitle("Speed Freak");
ui = NULL;
//delete result;
//delete measure;
- delete categorylist;
- categorylist = NULL;
+ delete myCategorylist;
+ myCategorylist = NULL;
delete welcomeDialog;
welcomeDialog = NULL;
delete myRoute;
*/
void CarMainWindow::on_autoStartButton_clicked()
{
+ initializeMeasures();
+ resetAccelerometerMeasurements();
+ ui->pushButtonSendResult->setEnabled(false);
+ ui->pushButtonShowResultDialog->setEnabled(false);
choice = ui->listViewStartTabAccelerationCategories->currentIndex();
choiceInt = choice.row();
qDebug() << choiceInt;
result->setDiagramGapStem(37.5);
}
ui->labelMeasureTabResult->setText("");
- //delete measure;
- //measure = NULL;
- //measure = new MeasureDialog();
- // connect(measure, SIGNAL(speedAchieved()), this, SLOT(openResultView()));
- timer->start();
- // Show measure dialog.
- //measure->show();
-
- // TODO: Move next if else to the function which is called when target speed
- // has reached.
- if (choiceInt == 0)
- {
- if (floor(this->measures->getTime40kmh()) <= 5)
- {
- result->setDiagramGapHorizontal(80);
- }
-
- else if (floor(this->measures->getTime40kmh()) <= 10)
- {
- result->setDiagramGapHorizontal(40);
- }
-
- else
- {
- result->setDiagramGapHorizontal(20);
- }
- }
-
- else
- {
- if (floor(this->measures->getTime40kmh()) <= 5)
- {
- result->setDiagramGapHorizontal(80);
- }
-
- else if (floor(this->measures->getTime40kmh()) <= 10)
- {
- result->setDiagramGapHorizontal(40);
- }
-
- else
- {
- result->setDiagramGapHorizontal(20);
- }
- }
+ this->accelerometerTimer->start(kAccelerometerSampleRate);
+ this->timer->start();
+ this->time = 0;
+ this->speed = 0;
ui->tabWidget->setCurrentWidget(this->ui->tabMeasureResult);
}
*/
void CarMainWindow::setCategoryCompoBox()
{
- ui->comboBoxTopCategory->addItems(categorylist->getCategoryList());
+ qDebug() << "_setCategoryCompoBox";
+ ui->comboBoxTopCategory->addItems(myHttpClient->myXmlreader->myCategoryList->getCategoryList());
+}
+
+/**
+ *This function prcesses UI updating after a new top10List has been received.
+ *@todo Check where limitNr is taken, fixed or user input, see on_comboBoxTopCategory_currentIndexChanged.
+ */
+void CarMainWindow::showTop10()
+{
+ int limitNr = 5;
+ setListViewTopList(recentCategory, limitNr);
}
/**
*This function is used to set items to labelTopList. Top-tab view.
- *@param QString category
+ *@param Category
+ *@param Size, number of results.
*/
void CarMainWindow::setListViewTopList(QString category, int size)
{
+ qDebug() << "_setListViewTopList";
QString topList;
- topList.append( categorylist->getTopList(category, size));
+ topList.append(myHttpClient->myXmlreader->myCategoryList->getTopList(category, size));
ui->labelTopList->setText(topList);
}
*/
void CarMainWindow::openResultView()
{
- //result->saveMeasuresToArray(measure->measures);
- // Show result dialog.
- //result->show();
- ui->pushButtonSendResult->setEnabled(true);
- QString timeInteger;
- if (choiceInt == 0)
- {
- if (floor(this->measures->getTime40kmh()) <= 5)
- {
- result->setDiagramGapHorizontal(80);
- }
-
- else if (floor(this->measures->getTime40kmh()) <= 10)
- {
- result->setDiagramGapHorizontal(40);
- }
- else
- {
- result->setDiagramGapHorizontal(20);
- }
- }
-
- else
- {
- if (floor(this->measures->getTime40kmh()) <= 5)
- {
- result->setDiagramGapHorizontal(80);
- }
-
- else if (floor(this->measures->getTime40kmh()) <= 10)
- {
- result->setDiagramGapHorizontal(40);
- }
-
- else
- {
- result->setDiagramGapHorizontal(20);
- }
- }
- timeInteger.setNum(this->measures->getTime40kmh());
- //time = "0 - 40 km/h: ";
- //time.append(timeInteger);
- //ui->labelResult40kmh->setText(time);
- ui->labelMeasureTabResult->show();
- ui->labelMeasureTabResult->setText(timeInteger);
- //ui->tabWidget->setCurrentWidget(this->ui->tabMeasureResult);
}
/**
void CarMainWindow::on_buttonTopRefresh_clicked()
{
myHttpClient->requestCategories();
- setCategoryCompoBox();
}
/**
*This slot function is called when ever category combobox current index changed. Top-tab view.
- *@param QString category
- *@todo Check where limitNr is taken.
+ *@param QString category.
+ *@todo Check where limitNr is taken, fixed or user input, see showTop10.
*/
void CarMainWindow::on_comboBoxTopCategory_currentIndexChanged(QString category)
{
- int limitNr = 5; //replace with real value?
+ qDebug() << "_on_comboBoxTopCategory_currentIndexChanged: " << category;
+ recentCategory = category; //for showTop10()
+ int limitNr = 5;
QString limit = QString::number(limitNr);
- category = "acceleration-0-100"; //replace with real value from category list/top window
myHttpClient->requestTopList(category, limit);
- setListViewTopList(category,10);
-}
-
-/**
- *This slot function is called when ever category combobox activated. Top-tab view.
- *@param QString category
- */
-void CarMainWindow::on_comboBoxTopCategory_activated(QString category)
-{
- setListViewTopList(category,10);
}
/**
void CarMainWindow::after_timeout()
{
QString timeString, speedString;
- time++;
- speed = speed +10;
-
- if (floor(speed) == 10)
- {
- measures->setTime10kmh(time);
- }
-
- else if (floor(speed) == 20)
- {
- measures->setTime20kmh(time);
- }
-
- else if (floor(speed) == 30)
- {
- measures->setTime30kmh(time);
- }
-
- else if (floor(speed) == 40)
- {
- measures->setTime40kmh(time);
- }
-
- else if (floor(speed) == 50)
- {
- measures->setTime50kmh(time);
- }
-
- else if (floor(speed) == 60)
- {
- measures->setTime60kmh(time);
- }
-
- else if (floor(speed) == 70)
- {
- measures->setTime70kmh(time);
- }
-
- else if (floor(speed) == 80)
- {
- measures->setTime80kmh(time);
- }
-
- else if (floor(speed) == 90)
- {
- measures->setTime90kmh(time);
- }
-
- else if (floor(speed) == 100)
- {
- measures->setTime100kmh(time);
- }
-
- else
- {
-
- }
-
- // If speed is over 40 km/h emits speedAchieved() signal and close this dialog.
- if (speed >= 40.0)
- {
- timer->stop();
- time = 0;
- speed = 0;
- //emit this->speedAchieved();
- this->openResultView();
- //this->close();
-
- }
-
- // Updates speed and time.
- else
- {
- timeString.setNum(time);
- speedString.setNum(speed);
- ui->labelMeasureTabTime->setText(timeString);
- ui->labelMeasureTabSpeed->setText(speedString);
-
- timer->start();
- }
+ //time++;
+ //speed = speed +10;
+ timeString.setNum(time);
+ speedString.setNum(speed);
+ ui->labelMeasureTabTime->setText(timeString);
+ ui->labelMeasureTabSpeed->setText(speedString);
+ //handleCheckPoint(time, speed);
}
/**
*/
void CarMainWindow::on_pushButtonMeasureTabAbort_clicked()
{
+ ui->pushButtonSendResult->setEnabled(false);
+ ui->pushButtonShowResultDialog->setEnabled(false);
+ ui->labelMeasureTabResult->hide();
+ ui->labelMeasureTabTime->setText("");
+ ui->labelMeasureTabSpeed->setText("");
measures->setTime10kmh(0);
measures->setTime20kmh(0);
measures->setTime30kmh(0);
measures->setTime80kmh(0);
measures->setTime90kmh(0);
measures->setTime100kmh(0);
- timer->stop();
- time = 0;
- speed = 0;
+ this->accelerometerTimer->stop();
+ this->timer->stop();
+ this->time = 0;
+ this->speed = 0;
ui->tabWidget->setCurrentWidget(this->ui->StartTab);
//this->close();
}
+/**
+ *This slot function is called when pushButtonSendResult is clicked.
+ *@todo Use real category value.
+ */
void CarMainWindow::on_pushButtonSendResult_clicked()
{
- myHttpClient->sendResultXml();
+ myHttpClient->sendResultXml("acceleration-0-100");
ui->pushButtonSendResult->setEnabled(false);
}
if (newUserName.length())
{
ui->setUserPushButton->setText( "Change User");
- this->setWindowTitle("Speed freak - " + newUserName);
+ this->setWindowTitle("Speed Freak - " + newUserName);
}
else
{
ui->setUserPushButton->setText( "Set User");
- this->setWindowTitle("Speed freak");
+ this->setWindowTitle("Speed Freak");
}
}
*/
void CarMainWindow::on_pushButtonShowResultDialog_clicked()
{
- Measures meas;
- meas.setTime10kmh(1.3);
- meas.setTime20kmh(2.5);
- meas.setTime30kmh(3.6);
- meas.setTime40kmh(6.7);
- meas.setTime50kmh(7.3);
- meas.setTime60kmh(7.5);
- meas.setTime70kmh(8.6);
- meas.setTime80kmh(8.7);
- meas.setTime90kmh(9.6);
- meas.setTime100kmh(9.9);
- result->setDiagramGapHorizontal(40);
- result->saveMeasuresToArray(&meas);
+ result->saveMeasuresToArray(measures);
this->result->show();
}
*/
void CarMainWindow::handleCheckPoint(double totalTime, double currentSpeed)
{
- // TODO
- //totalTime;
- //currentSpeed;
- return;
+ switch (counterForSaveResults)
+ {
+ case 0:
+ measures->setTime10kmh(totalTime);
+ break;
+
+ case 1:
+ measures->setTime20kmh(totalTime);
+ break;
+
+ case 2:
+ measures->setTime30kmh(totalTime);
+ break;
+
+ case 3:
+ measures->setTime40kmh(totalTime);
+ break;
+
+ case 4:
+ measures->setTime50kmh(totalTime);
+ break;
+
+ case 5:
+ measures->setTime60kmh(totalTime);
+ break;
+
+ case 6:
+ measures->setTime70kmh(totalTime);
+ break;
+
+ case 7:
+ measures->setTime80kmh(totalTime);
+ break;
+
+ case 8:
+ measures->setTime90kmh(totalTime);
+ break;
+
+ case 9:
+ measures->setTime100kmh(totalTime);
+ break;
+
+ default:
+ break;
+ }
+ counterForSaveResults++;
+
+ if (choiceInt == 0 && measures->getTime40kmh() != 0)
+ {
+ setTimeAxisGapAndShowResult(measures->getTime40kmh());
+ this->timer->stop();
+ this->accelerometerTimer->stop();
+ this->time = 0;
+ this->speed = 0;
+ counterForSaveResults = 0;
+ }
+
+ else if (choiceInt == 1 && measures->getTime100kmh() != 0)
+ {
+ setTimeAxisGapAndShowResult(measures->getTime100kmh());
+ this->timer->stop();
+ this->accelerometerTimer->stop();
+ this->time = 0;
+ this->speed = 0;
+ counterForSaveResults = 0;
+
+ }
+
+ else if (choiceInt != 1 && choiceInt != 0 && measures->getTime80kmh() != 0)
+ {
+ setTimeAxisGapAndShowResult(measures->getTime80kmh());
+ this->timer->stop();
+ this->accelerometerTimer->stop();
+ this->time = 0;
+ this->speed = 0;
+ counterForSaveResults = 0;
+ }
+
+ else
+ {
+
+ }
}
/**
currentAcceleration = sqrt(x*x + y*y + z*z);
changeInAcceleration = (currentAcceleration - firstAcceleration); // firstAcceleration only gets set once
- if (((abs(changeInAcceleration) <= accelerationStartThreshold)
+ if (((fabs(changeInAcceleration) <= accelerationStartThreshold)
&& !vehicleStartedMoving))
{
return;
if ((changeInAcceleration <= 0))
{
// actually increasing here...
- changeInAcceleration = abs(changeInAcceleration);
+ changeInAcceleration = fabs(changeInAcceleration);
}
else
{
{
// we started to move backwards first time through
reverseAccelerationFlag = true;
- changeInAcceleration = abs(changeInAcceleration);
+ changeInAcceleration = fabs(changeInAcceleration);
}
vehicleStartedMoving = true;
ui->labelRouteTabRecStatus->setText("Recording stopped");
gpsData->stopRouteRecording(ui->labelRouteTabGPSTime->text());
}
+
+/**
+ *Sets time axis right way in result dialog and shows target speed result.
+ *@param double pTime is the target speed result time which is shown to the user.
+ */
+void CarMainWindow::setTimeAxisGapAndShowResult(double pTime)
+{
+ ui->pushButtonShowResultDialog->setEnabled(true);
+ ui->pushButtonSendResult->setEnabled(true);
+ QString timeInteger;
+ timeInteger.setNum(pTime);
+ ui->labelMeasureTabResult->show();
+ ui->labelMeasureTabResult->setText(timeInteger);
+
+ if (floor(pTime) <= 5)
+ {
+ result->setDiagramGapHorizontal(80);
+ }
+
+ else if (floor(pTime) <= 10)
+ {
+ result->setDiagramGapHorizontal(40);
+ }
+
+ else
+ {
+ result->setDiagramGapHorizontal(20);
+ }
+}
CarMainWindow(QWidget *parent = 0);
~CarMainWindow();
Registration *myRegistration; //Check if this should be public or private
-
+ LoginWindow *myLogin;
void setComboBoxStartTabUnits(QStringList units); //Start-tab view
void setListViewStartTabAccelerationCategories(QStringList numbers); //Start-tab view
- void setListViewTopList(QString category, int size); //Top-tab view
- void setCategoryCompoBox(); //Top-tab
protected:
void changeEvent(QEvent *e);
ResultDialog *result;
//MeasureDialog *measure;
WelcomeDialog *welcomeDialog;
- CategoryList *categorylist;
+ CategoryList *myCategorylist;
HttpClient *myHttpClient;
- LoginWindow *myLogin;
RouteDialog *myRoute;
GPSData *gpsData;
Maemo5Location *location;
void initComboBoxStartTabUnits(); //Start-tab view
void initListViewStartTabAccelerationCategories(); //Start-tab view
void initializeMeasures();
+ void setListViewTopList(QString category, int size); //Top-tab view
void resetAccelerometerMeasurements();
void calibrateAccelerometer();
+ void setTimeAxisGapAndShowResult(double pTime);
private:
QStringList accelerationCategoriesStartTab; //Start-tab view
QStringList units; //Start-tab view
- QStringList categories; //Top-tab view
+ QString recentCategory;
QTimer *timer;
Accelerometer *accelerometer;
QDateTime *gpsTime;
+ int counterForSaveResults;
+
signals:
void speedAchieved();
void userNameChanged();
void on_manualStartButton_clicked();
void on_setUserPushButton_clicked();
void on_registratePushButton_clicked();
- void on_comboBoxTopCategory_activated(QString );
- //void on_pushButton_clicked();
void on_comboBoxTopCategory_currentIndexChanged(QString category); //Top-tab view
void on_listViewStartTabAccelerationCategories_clicked(QModelIndex index); //Start-tab view
void updateComboBoxStartTabUnits(QString unit); //Start-tab view
void userLogin();
void readAccelerometerData();
void handleCheckPoint(double totalTime, double currentSpeed);
+ void setCategoryCompoBox(); //Top-tab
+ void showTop10();
+
};
#endif // CARMAINWINDOW_H
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/
+#include <QDebug>
#include "categorylist.h"
/**
*/
CategoryList::CategoryList()
{
- categoryList << "Speed" << "acceleration-0-40" << "acceleration-0-100" << "G-force"; // OLPU
- //top10AccelerationList << "acc-tulos1\nacc-tulos2\nacc-tulos3\nacc-tulos4\nacc-tulos5\nacc-tulos6\nacc-tulos7\nacc-tulos8\nacc-tulos9\nacc-tulos10";
+
}
/**
/**
*This is return function.
- *@todo Read real top 10 category list
*@return QStringList categoryList
*/
QStringList CategoryList::getCategoryList()
{
+ qDebug() << "_getCategoryList" ;
return categoryList;
}
/**
+ *Append an item in the end of the categorylist.
+ */
+void CategoryList::appendCategoryList(QString item)
+{
+ categoryList.append(item);
+}
+
+/**
+ *Input an item into the categorylist.
+ */
+void CategoryList::fillCategoryList(int index, QString item)
+{
+ categoryList.insert(index, item);
+}
+
+/**
+ *Show an item of the categorylist.
+ */
+QString CategoryList::itemOfCategoryList(int index)
+{
+ return categoryList.at(index);
+}
+
+/**
+ *Clear categorylist.
+ */
+void CategoryList::clearCategoryList()
+{
+ categoryList.clear();
+ qDebug() << "_clearCategoryList" ;
+}
+
+/**
+ *Read size of categorylist.
+ */
+int CategoryList::sizeOfCategoryList()
+{
+ return categoryList.size();
+}
+
+/**
*This function is used to get items to top list of current category.
*@param QString category
*@param int size
*/
QString CategoryList::getTopList( QString category, int size)
{
- if (category == "acceleration-0-100")
- {
- //topList.append(xmlreader->getTop10AccelerationList());
- //return top10AccelerationList;
- return "acc-tulos1\nacc-tulos2\nacc-tulos3\nacc-tulos4\nacc-tulos5\nacc-tulos6\nacc-tulos7\nacc-tulos8\nacc-tulos9\nacc-tulos10";
-
- }
- else if (category == "acceleration-0-40")
- {
- //topList.append(xmlreader->getTop10AccelerationList());
- //return top10AccelerationList;
- return "acc-40-tulos1\nacc-40-tulos2\nacc-40-tulos3\nacc-40-tulos4\nacc-40-tulos5\nacc-40-tulos6\nacc-40-tulos7\nacc-40-tulos8\nacc-40-tulos9\nacc-40-tulos10";
+ qDebug() << "_getTopList";
- }
- else if (category == "Speed")
+ if(!(top10List.isEmpty()))
{
- //topList.append(xmlreader->getTop10SpeedList());
- //return top10SpeedList;
- return "speed-tulos1\nspeed-tulos2\nspeed-tulos3\nspeed-tulos4\nspeed-tulos5\nspeed-tulos6\nspeed-tulos7\nspeed-tulos8\nspeed-tulos9\nspeed-tulos10";
+ return top10List;
}
- else if (category == "G-force")
+ else
{
- //topList.append(xmlreader->getTop10GforceList());
- //return top10GforceList;
- return "g-tulos1\ng-tulos2\ng-tulos3\ng-tulos4\ng-tulos5\ng-tulos6\ng-tulos7\ng-tulos8\ng-tulos9\ng-tulos10";
-
+ QString emptyStr("");
+ qDebug() << "_getTopList: Category not found";
+ return emptyStr;
}
}
public:
CategoryList();
~CategoryList();
+ QString top10List;
+
QStringList getCategoryList();
+ void fillCategoryList(int index, QString item);
+ void appendCategoryList(QString item);
+ QString itemOfCategoryList(int index);
QString getTopList( QString category, int size);
+ void clearCategoryList();
+ int sizeOfCategoryList();
private:
QStringList categoryList;
- QString top10AccelerationList;
- QString top10SpeedList;
- QString top10GforceList;
+
};
#endif // CATEGORYLIST_H
#include "httpclient.h"
#include "carmainwindow.h"
+
/**
*@brief Constructor, connects object to GUI
*@param Pointer to carmainwindow, which is temporarily used during development
*Send authentication information in the header.
*@todo Read category elsewhere.
*/
-void HttpClient::sendResultXml()
+void HttpClient::sendResultXml(QString category)
{
qDebug() << "_sendResultXml";
QBuffer *xmlbuffer = new QBuffer();
- QString category_name = "acceleration-0-100"; //replace with real value from category list
- QUrl qurl("http://api.speedfreak-app.com/api/update/" + category_name);
+ QUrl qurl("http://api.speedfreak-app.com/api/update/" + category);
qDebug() << qurl.toString();
QNetworkRequest request(qurl);
QNetworkReply *currentDownload;
myXmlwriter->writeResult(xmlbuffer);
qDebug() << "carmainwindow: xmlbuffer->data(): " << xmlbuffer->data();
- QString credentials = myMainw->myRegistration->getUserName() + ":" + myMainw->myRegistration->getPassword();
+ QString credentials = myMainw->myLogin->getUserName() + ":" + myMainw->myLogin->getPassword();
credentials = "Basic " + credentials.toAscii().toBase64();
request.setRawHeader(QByteArray("Authorization"),credentials.toAscii());
QNetworkRequest request(qurl);
QNetworkReply *currentDownload;
- QString credentials = myMainw->myRegistration->getUserName() + ":" + myMainw->myRegistration->getPassword();
+ QString credentials = myMainw->myLogin->getUserName() + ":" + myMainw->myLogin->getPassword();
credentials = "Basic " + credentials.toAscii().toBase64();
request.setRawHeader(QByteArray("Authorization"),credentials.toAscii());
QNetworkRequest request(qurl);
QNetworkReply *currentDownload;
- QString credentials = myMainw->myRegistration->getUserName() + ":" + myMainw->myRegistration->getPassword();
+ QString credentials = myMainw->myLogin->getUserName() + ":" + myMainw->myLogin->getPassword();
credentials = "Basic " + credentials.toAscii().toBase64();
request.setRawHeader(QByteArray("Authorization"),credentials.toAscii());
QNetworkRequest request(qurl);
QNetworkReply *currentDownload;
- QString credentials = myMainw->myRegistration->getUserName() + ":" + myMainw->myRegistration->getPassword();
+ QString credentials = myMainw->myLogin->getUserName() + ":" + myMainw->myLogin->getPassword();
credentials = "Basic " + credentials.toAscii().toBase64();
request.setRawHeader(QByteArray("Authorization"),credentials.toAscii());
}
else {
qDebug() << "errorcode:" << errorcode << reply->errorString();
- qDebug() << reply->readAll();
+ QMessageBox::about(myMainw, "Server reply to result sending", "Result received " + reply->readAll());
}
}
}
else {
qDebug() << "errorcode:" << errorcode << reply->errorString();
- qDebug() << reply->readAll();
+ QMessageBox::about(myMainw, "Server reply to requesting categories ", "OK");
}
}
qDebug() << "_ackOffLogin";
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
- myXmlreader->xmlReadTop10Results(reply);
QNetworkReply::NetworkError errorcode;
errorcode = reply->error();
}
else {
qDebug() << "errorcode:" << errorcode << reply->errorString();
- qDebug() << reply->readAll();
+ QMessageBox::about(myMainw, "Server reply to requesting top 10 list", "OK " + reply->readAll());
}
}
-class HttpClient : public QObject
-{
+class HttpClient : public QObject {
Q_OBJECT
public:
HttpClient(CarMainWindow *myCarw);
private:
CarMainWindow *myMainw;
QNetworkAccessManager *netManager;
- //XmlWriter *myXmlwriter;
- //XmlReader *myXmlreader;
public slots:
void requestRegistration();
void checkLogin();
- void sendResultXml();
+ void sendResultXml(QString category);
void requestTopList(QString category, QString limit);
void requestCategories();
void ackOfResult();
ui(new Ui::ResultDialog)
{
ui->setupUi(this);
+ timeAxelLength = 10;
speedList << "0" << "10" << "20" << "30" << "40" << "50" << "60" << "70" << "80" << "90" << "100" ;
timeList << "0" << "1" << "2" << "3" << "4" << "5" << "6" << "7" << "8" << "9" << "10" << "11"
<< "12" << "13" << "14" << "15" << "16" << "17" << "18" << "19" << "20";
*/
void ResultDialog::paintEvent(QPaintEvent *)
{
- QPainter painter(this);
+ QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setPen(QPen((Qt::red),2));
if (this->diagramGapStem == DIAGRAMGAP100KMH)
{
speedAsPixels = DIAGRAM_HEIGHT*aSpeed/100;
- timeAsPixels = DIAGRAM_WIDTH*aTime/10;
+ timeAsPixels = DIAGRAM_WIDTH*aTime/timeAxelLength;
}
else if (this->diagramGapStem == DIAGRAMGAP80KMH)
{
speedAsPixels = DIAGRAM_HEIGHT*aSpeed/80;
- timeAsPixels = DIAGRAM_WIDTH*aTime/10;
+ timeAsPixels = DIAGRAM_WIDTH*aTime/timeAxelLength;
}
else if (this->diagramGapStem == DIAGRAMGAP60KMH)
{
speedAsPixels = DIAGRAM_HEIGHT*aSpeed/60;
- timeAsPixels = DIAGRAM_WIDTH*aTime/10;
+ timeAsPixels = DIAGRAM_WIDTH*aTime/timeAxelLength;
}
else if (this->diagramGapStem == DIAGRAMGAP50KMH)
{
speedAsPixels = DIAGRAM_HEIGHT*aSpeed/50;
- timeAsPixels = DIAGRAM_WIDTH*aTime/10;
+ timeAsPixels = DIAGRAM_WIDTH*aTime/timeAxelLength;
}
else
{
speedAsPixels = DIAGRAM_HEIGHT*aSpeed/40;
- timeAsPixels = DIAGRAM_WIDTH*aTime/10;
+ timeAsPixels = DIAGRAM_WIDTH*aTime/timeAxelLength;
}
point.setY(diagramStemStart.y()-speedAsPixels);
point.setX(diagramStemStart.x()+timeAsPixels);
timeArray[9] = pMeasures->getTime90kmh();
timeArray[10] = pMeasures->getTime100kmh();
+ setTimeAxelLength();
+
for (int i = 0; i < 11; i++)
{
points[i] = changeMeasuresToDiagramPoint(speedArray[i], timeArray[i]);
ui->labelResult100kmh->hide();
}
+ else if (this->diagramGapStem == DIAGRAMGAP80KMH)
+ {
+ ui->labelResult50kmh->show();
+ ui->labelResult60kmh->show();
+ ui->labelResult70kmh->show();
+ ui->labelResult80kmh->show();
+ ui->labelResult90kmh->hide();
+ ui->labelResult100kmh->hide();
+ }
+
else
{
ui->labelResult50kmh->show();
ui->labelResult100kmh->show();
}
}
+
+/**
+ * Sets right timeAxelLength value depending the time which
+ * has spent to reach target speed.
+ */
+void ResultDialog::setTimeAxelLength()
+{
+ if (this->diagramGapStem == DIAGRAMGAP40KMH)
+ {
+ if (timeArray[4] <= 5)
+ {
+ timeAxelLength = 5;
+ }
+
+ else if (timeArray[4] <= 10)
+ {
+ timeAxelLength = 10;
+ }
+
+ else if (timeArray[4] <= 15)
+ {
+ timeAxelLength = 15;
+ }
+
+ else
+ {
+ timeAxelLength = 20;
+ }
+ }
+
+ else if (this->diagramGapStem == DIAGRAMGAP80KMH)
+ {
+ if (timeArray[8] <= 5)
+ {
+ timeAxelLength = 5;
+ }
+
+ else if (timeArray[8] <= 10)
+ {
+ timeAxelLength = 10;
+ }
+
+ else if (timeArray[8] <= 15)
+ {
+ timeAxelLength = 15;
+ }
+
+ else
+ {
+ timeAxelLength = 20;
+ }
+ }
+
+ else
+ {
+ if (timeArray[10] <= 5)
+ {
+ timeAxelLength = 5;
+ }
+
+ else if (timeArray[10] <= 10)
+ {
+ timeAxelLength = 10;
+ }
+
+ else if (timeArray[10] <= 15)
+ {
+ timeAxelLength = 15;
+ }
+
+ else
+ {
+ timeAxelLength = 20;
+ }
+ }
+}
private:
QPoint changeMeasuresToDiagramPoint(int aSpeed, qreal aTime);
void setTimesIntoLabels();
+ void setTimeAxelLength();
private:
Ui::ResultDialog *ui;
double diagramGapHorizontal;
QStringList speedList;
QStringList timeList;
+ int timeAxelLength;
private slots:
void on_pushButtonSend_clicked();
#include <cmath>
#include <QPainter>
#include <QList>
-//#include <QVector3D>
-//#include <QDebug>
-//#include <stdio.h>
-#include <QMessageBox>
+//#include <QMessageBox>
-typedef struct
+/*
+ * Vector class
+ */
+class Vector
{
qreal x, y, z;
-} VECTOR;
+public:
+ Vector() { x=0.; y=0. ; z=0.; };
+ Vector( qreal initX, qreal initY, qreal initZ) { x = initX, y = initY; z = initZ; };
+ void setX( qreal newX) { x = newX; };
+ void setY( qreal newY) { y = newY; };
+ void setZ( qreal newZ) { z = newZ; };
+ qreal getX() { return x; };
+ qreal getY() { return y; };
+ qreal getZ() { return z; };
+ qreal length() { return sqrt(x*x+y*y+z*z); };
+ Vector operator+(Vector v)
+ {
+ x = x + v.x; y = y + v.y; z = z + v.z;
+ return *this;
+ };
+ Vector operator-(Vector v)
+ {
+ x = x - v.x; y = y - v.y; z = z - v.z;
+ return *this;
+ };
+ Vector operator/(qreal c)
+ {
+ x = x/c; y = y/c; z = z/c;
+ return *this;
+ };
+ Vector crossProduct( Vector a, Vector b)
+ {
+ x = a.y*b.z - a.z*b.y;
+ y = a.z*b.x - a.x*b.z;
+ z = a.x*b.y - a.y*b.x;
+ return *this;
+ };
+};
-int left, top, right, bottom; // Limits in screen coordinates
-qreal xmax, xmin, ymin, ymax; // Limits in world coordinates
+int left, top, right, bottom; // Limits in screen coordinates
+qreal xmax, xmin, ymin, ymax; // Limits in world coordinates
-//QList<QVector3D> vertexList; // Vertecies of route
-QList<VECTOR> vertexList;
+QList<Vector> vertexList; // Vertecies of route
-//QVector3D atPoint, fromPoint, up;
-//QVector3D a1, a2, a3;
-VECTOR atPoint, fromPoint, up, a1, a2, a3;
-// QVector3D dist;
+Vector atPoint, fromPoint, up, a1, a2, a3;
qreal offsx, offsy, offsz;
qreal objxmin, objxmax, objymin, objymax, objzmin, objzmax;
-qreal t_from;
qreal angle;
qreal a, b,c,d, dval;
#define WIDTH 1.8
int length = 24;
-int connection[24] = { 1, 5, 8, -4,
- 5, 6, 7, -8,
- 6, 2, 3, -7,
- 1, 4, 3, -2,
- 8, 7, 3, -4,
- 6, 5, 1, -2 };
-/*QVector3D pa[8] = { {1.,1.,1.},{1.,1.,0.},
- {1.,0.,0.},{1.,0.,1.},
- {0.,1.,1.},{0.,1.,0.},
- {0.,0.,0.},{0.,0.,1.}};*/
-//QVector3D pa[8];
-VECTOR pa[8];
+int connection[30];
void setAtPoint();
void setFromPoint();
ui(new Ui::RouteDialog)
{
ui->setupUi(this);
- left = 50;
- top = 50;
- right = 350;
- bottom = 200;
+ //left = 50; top = 50; right = 350; bottom = 200;
+ left = 5; top = 5; right = 395; bottom = 295;
xmin =0.0; xmax=100.0; ymin = 0.0; ymax = 20.0;
+ // Ruudun koko 400 x 300
/*vertexList.append(QVector3D(40.02, 10.02, 10.02));
vertexList.append(QVector3D(50.01, 5.01, 10));
vertexList.append(QVector3D(49.99, 14.97, 10));
vertexList.append(QVector3D(40.01, 10.01, 10.02));
*/
- /*pa[0] = QVector3D(1.,1.,1.);
- pa[1] = QVector3D(1.,1.,0.);
- pa[2] = QVector3D(1.,0.,0.);
- pa[3] = QVector3D(1.,0.,1.);
- pa[4] = QVector3D(0.,1.,1.);
- pa[5] = QVector3D(0.,1.,0.);
- pa[6] = QVector3D(0.,0.,0.);
- pa[7] = QVector3D(0.,0.,1.);
- */
-
- pa[0].x = 1.; pa[0].y = 1.; pa[0].z =1.;
- pa[1].x = 1.; pa[1].y = 1.; pa[1].z = 0.;
- pa[2].x = 1.; pa[2].y = 0.; pa[2].z = 0.;
- pa[3].x = 1.; pa[3].y = 0.; pa[3].z = 1.;
- pa[4].x = 0.; pa[4].y = 1.; pa[4].z = 1.;
- pa[5].x = 0.; pa[5].y = 1.; pa[5].y = 0.;
- pa[6].x = 0.; pa[6].y = 0.; pa[6].z = 0.;
- pa[7].x = 0.; pa[7].y = 0.; pa[7].z = 1.;
-
- fromPoint.x = 1.0; fromPoint.y = 0.0; fromPoint.z = 0.0;
- atPoint.x = 0.0; atPoint.y = 0.0; atPoint.z = 0.0;
- up.x = 0.0; up.y = 0.0; up.z = 1.0;
-
- a = 350/2;
+ vertexList.append(Vector(0.0, 0.0, 0.0));
+ vertexList.append(Vector(1.0, 1.0, 1.0));
+ vertexList.append(Vector(1.0, 1.0, 0.0));
+
+ vertexList.append(Vector(1.0, 0.0, 0.0));
+ vertexList.append(Vector(1.0, 0.0, 1.0));
+ vertexList.append(Vector(0.0, 1.0, 1.0));
+
+ vertexList.append(Vector(0.0, 1.0, 0.0));
+ vertexList.append(Vector(0.0, 0.0, 0.0));
+ vertexList.append(Vector(0.0, 0.0, 1.0));
+
+ connection[0] = 0;
+ connection[1] = 1; connection[2] = 5; connection[3] = 8; connection[4] = -4;
+ connection[5] = 5; connection[6] = 6; connection[7] = 7; connection[8] = -8;
+ connection[9] = 6; connection[10] = 2; connection[11] = 3; connection[12] = -7;
+ connection[13] = 1; connection[14] = 4; connection[15] = 3; connection[16] = -2;
+ connection[17] = 8; connection[18] = 7; connection[19] = 3; connection[20] = -4;
+ connection[21] = 6; connection[22] = 5; connection[23] = 1; connection[24] = -2;
+
+ fromPoint.setX( 1.0); fromPoint.setY( 0.0); fromPoint.setZ( 0.0);
+ atPoint.setX( 0.0); atPoint.setY( 0.0); atPoint.setZ( 0.0);
+ up.setX( 0.0); up.setY( 0.0); up.setZ(1.0);
+
+ a = 400/2.;
b = 1 - a*(-1);
- c = 200/2;
- d = 200 - c*(-1);
+ c = -300/2.;
+ d = 300 - c*(-1);
angle = toradians(60);
- t_from = 1.0;
setAtPoint();
setFromPoint();
{
int i, maxi;
qreal x,y,z;
+ Vector temp;
- objxmax = objxmin = pa[0].x; //vertexList.at(0).x();
- objymax = objymin = pa[0].y; //vertexList.at(0).y();
- objzmax = objzmin = pa[0].z; //vertexList.at(0).z();
+ temp = vertexList.at(0);
+ objxmax = objxmin = temp.getX();
+ objymax = objymin = temp.getY();
+ objzmax = objzmin = temp.getZ();
- //maxi = vertexList.size();
- maxi = 8;
+ maxi = vertexList.size();
+ //maxi = 9;
for (i=1; i<maxi; i++)
{
- x = pa[i].x; // vertexList.at(i).x();
- y = pa[i].y; //vertexList.at(i).y();
- z = pa[i].z; //vertexList.at(i).z();
+ temp = vertexList.at(i);
+ x = temp.getX();
+ y = temp.getY();
+ z = temp.getZ();
if (x < objxmin)
{
objzmax = z;
}
}
- //qDebug() << "ojbxmin";
- //fprintf(stdout,"objxmin");
//QString jono = QString("ojxmin %1 objxmax %2").arg(objxmin).arg(objxmax);
//QString jono = QString("ojymin %1 objymax %2").arg(objymin).arg(objymax);
//QString jono = QString("ojzmin %1 objzmax %2").arg(objzmin).arg(objzmax);
void setAtPoint()
{
dataMinMax();
- /*atPoint.setX((objxmax+objxmin)/2.0);
+ atPoint.setX((objxmax+objxmin)/2.0);
atPoint.setY((objymax+objymin)/2.0);
atPoint.setZ((objzmax+objzmin)/2.0);
- */
- atPoint.x = (objxmax+objxmin)/2.0;
- atPoint.y = (objymax+objymin)/2.0;
- atPoint.z = (objzmax+objzmin)/2.0;
//QString jono = QString("AtX %1 Aty %2 AtZ %3").arg(atPoint.x()).arg(atPoint.y()).arg(atPoint.z());
+ //QString jono = QString("AtX %1 Aty %2 AtZ %3").arg(atPoint.x).arg(atPoint.y).arg(atPoint.z);
//QMessageBox::about(0,"At point", jono);
}
void setFromPoint()
{
- /*fromPoint.setX( atPoint.x() + (objxmax-objxmin)/2.0 + WIDTH*maxof((objzmax-objzmin)/2.0,(objymax-objymin)/2.0));
- fromPoint.setY( atPoint.y());
- fromPoint.setZ( atPoint.z());
- */
- fromPoint.x = ( atPoint.x + (objxmax-objxmin)/2.0 + WIDTH*maxof((objzmax-objzmin)/2.0,(objymax-objymin)/2.0));
- fromPoint.y = atPoint.y;
- fromPoint.z = atPoint.z;
-
+ //fromPoint.setX( atPoint.getX() + (objxmax-objxmin)/2.0 + WIDTH*maxof((objzmax-objzmin)/2.0,(objymax-objymin)/2.0));
+ fromPoint.setX(3.0);
+ fromPoint.setY( atPoint.getY());
+ fromPoint.setZ( atPoint.getZ());
//QString jono = QString("FromX %1 FromY %2 FromZ %3").arg(fromPoint.x()).arg(fromPoint.y()).arg(fromPoint.z());
- //QMessageBox::about(0,"From point", jono); // (1.9,
-}
-
-VECTOR CrossProduct( VECTOR a, VECTOR b)
-{
- VECTOR c;
-
- c.x = a.y*b.z - a.z*b.y;
- c.y = a.z*b.x - a.x*b.z;
- c.z = a.x*b.y - a.y*b.x;
-
- return c;
+ //QString jono = QString("FromX %1 FromY %2 FromZ %3").arg(fromPoint.x).arg(fromPoint.y).arg(fromPoint.z);
+ //QMessageBox::about(0,"From point", jono); // (1.9, 0.5, 0.5)
}
void setEye()
{
double amarkmag, tempmag;
- //QVector3D temp;
- //QVector3D dist;
- VECTOR temp, dist;
+ Vector temp, dist;
dval = cos(angle/2.0)/sin(angle/2.0);
- //dist = atPoint-fromPoint;
- dist.x = atPoint.x - fromPoint.x;
- dist.y = atPoint.y - fromPoint.y;
- dist.z = atPoint.z - fromPoint.z;
- //amarkmag = dist.length();
- amarkmag = sqrt( dist.x*dist.x + dist.y*dist.y + dist.z*dist.z);
- //QString jono = QString("amarkmag %1").arg(amarkmag);
- //QMessageBox::about(0,"amarkmag", jono); // 1.4
- //a3 = dist.operator /=(amarkmag);
- a3.x = dist.x/amarkmag;
- a3.y = dist.y/amarkmag;
- a3.z = dist.z/amarkmag;
-
- //temp.crossProduct( dist, up);
- temp = CrossProduct( dist, up);
- //tempmag = temp.length();
- tempmag = sqrt( temp.x*temp.x + temp.y*temp.y + temp.z*temp.z);
- //a1 = temp.operator /=(tempmag);
- a1.x = temp.x/tempmag;
- a1.y = temp.y/tempmag;
- a1.z = temp.z/tempmag;
-
- //temp.crossProduct( a1, a3);
- temp = CrossProduct( a1, a3);
- //tempmag = temp.length();
- tempmag = sqrt( temp.x*temp.x + temp.y*temp.y + temp.z*temp.z);
- //a2 = temp.operator /=(tempmag);
- a2.x = temp.x/tempmag;
- a2.y = temp.y/tempmag;
- a2.z = temp.z/tempmag;
-
- /*offsx = -a1.x()*fromPoint.x() - a1.y()*fromPoint.y() - a1.z()*fromPoint.z();
- offsy = -a2.x()*fromPoint.x() - a2.y()*fromPoint.y() - a2.z()*fromPoint.z();
- offsz = -a3.x()*fromPoint.x() - a3.y()*fromPoint.y() - a3.z()*fromPoint.z();
-*/
- offsx = -a1.x*fromPoint.x - a1.y*fromPoint.y - a1.z*fromPoint.z;
- offsy = -a2.x*fromPoint.x - a2.y*fromPoint.y - a2.z*fromPoint.z;
- offsz = -a3.x*fromPoint.x - a3.y*fromPoint.y - a3.z*fromPoint.z;
+ dist = atPoint-fromPoint;
+ amarkmag = dist.length();
+ a3 = dist/amarkmag;
+
+ temp.crossProduct( dist, up);
+ tempmag = temp.length();
+ a1 = temp/tempmag;
+
+ temp.crossProduct( a1, a3);
+ tempmag = temp.length();
+ a2 = temp/tempmag;
+ offsx = -a1.getX()*fromPoint.getX() - a1.getY()*fromPoint.getY() - a1.getZ()*fromPoint.getZ();
+ offsy = -a2.getX()*fromPoint.getX() - a2.getY()*fromPoint.getY() - a2.getZ()*fromPoint.getZ();
+ offsz = -a3.getX()*fromPoint.getX() - a3.getY()*fromPoint.getY() - a3.getZ()*fromPoint.getZ();
//QString jono2 = QString("offsx %1 offsy %2 offsz %3").arg(offsx).arg(offsy).arg(offsz);
//QMessageBox::about(0,"offs x y z", jono2);
}
#define RIGHTEDGE 0x02
#define BOTTOMEDGE 0x04
#define TOPEDGE 0x08
-
+/*
+ * Returns a code specifying which edge in the viewing pyramid was crossed.
+ * There may be more than one.
+ */
int code( qreal x, qreal y, qreal z)
{
int c;
return c;
}
-
-void WORLDtoSCREEN( qreal xw, qreal yw, int *xpc, int *ypc)
+/*
+ * Converts clipped world coordinates to screen coordinates.
+ */
+void WORLDtoSCREEN( qreal xWorld, qreal yWorld, int *xScreen, int *yScreen)
{
- *xpc = (int) (a+xw+b);
- *ypc = (int) (c+yw+d);
+ *xScreen = (int) (a*xWorld+b);
+ *yScreen = (int) (c*yWorld+d);
}
-
-void clip3d( qreal x1, qreal y1, qreal z1, qreal x2, qreal y2, qreal z2, int *xpc1, int *ypc1, int *xpc2, int *ypc2)
+/*
+ * Clips the line segment in three-dimensional coordinates to the
+ * viewing pyramid.
+ */
+void clip3d( qreal x1, qreal y1, qreal z1, qreal x2, qreal y2, qreal z2, int *xscreen1, int *yscreen1, int *xscreen2, int *yscreen2)
{
- int c,c1,c2; //, xpc1, ypc1, xpc2, ypc2;
+ int c,c1,c2;
qreal x,y,z,t;
c1 = code(x1,y1,z1);
else if ((c&RIGHTEDGE) == RIGHTEDGE)
{
// Crosses right edge
- t = (z1-x1)/((x2-x2)-(z2-z1));
+ t = (z1-x1)/((x2-x1)-(z2-z1));
z = t*(z2-z1)+z1;
x = z;
y = t*(y2-y1)+y1;
}
else if ((c&BOTTOMEDGE) == BOTTOMEDGE)
{
- // Crosses left edge
+ // Crosses bottom edge
t = (z1+y1)/((y1-y2)-(z2-z1));
z = t*(z2-z1)+z1;
x = t*(x2-x1)+x1;
}
else if ((c&TOPEDGE) == TOPEDGE)
{
- // Crosses left edge
+ // Crosses top edge
t = (z1-y1)/((y2-y1)-(z2-z1));
z = t*(z2-z1)+z1;
x = t*(x2-x1)+x1;
if (z1 != 0)
{
- WORLDtoSCREEN(x1/z1,y1/z1,xpc1, ypc1);
- WORLDtoSCREEN(x2/z2,y2/z2,xpc2, ypc2);
+ WORLDtoSCREEN(x1/z1,y1/z1,xscreen1, yscreen1);
+ WORLDtoSCREEN(x2/z2,y2/z2,xscreen2, yscreen2);
}
else
{
- WORLDtoSCREEN(x1,y1,xpc1, ypc1);
- WORLDtoSCREEN(x2,y2,xpc2, ypc2);
+ WORLDtoSCREEN(x1,y1,xscreen1, yscreen1);
+ WORLDtoSCREEN(x2,y2,xscreen2, yscreen2);
}
- //line( xpc1, ypc1, xpc2, ypc2);
- //painter.drawLine(xpc1, ypc1, xpc2, ypc2);
+ //line( xscreen1, yscreen1, xscreen2, yscreen2);
}
-//void transformseg( QVector3D *v1, QVector3D *v2, int *xpc1, int *ypc1, int *xpc2, int *ypc2 )
-void transformseg( VECTOR *v1, VECTOR *v2, int *xpc1, int *ypc1, int *xpc2, int *ypc2 )
+/*
+ * Transform the segment connecting the two vectors into the viewing plane.
+ * clip3d() clips the line if needed.
+ */
+void transformseg( Vector *v1, Vector *v2, int *xscreen1, int *yscreen1, int *xscreen2, int *yscreen2 )
+
{
qreal x1, y1, z1, x2, y2, z2;
- /*x1 = (a1.x()*v1->x() + a1.y()*v1->y() + a1.z()*v1->z() + offsx)*dval;
- y1 = (a2.x()*v1->x() + a2.y()*v1->y() + a2.z()*v1->z() + offsy)*dval;
- z1 = a3.x()*v1->x() + a3.y()*v1->y() + a3.z()*v1->z() + offsz;*/
- x1 = (a1.x*v1->x + a1.y*v1->y + a1.z*v1->z + offsx)*dval;
- y1 = (a2.x*v1->x + a2.y*v1->y + a2.z*v1->z + offsy)*dval;
- z1 = a3.x*v1->x + a3.y*v1->y + a3.z*v1->z + offsz;
-
- /*x2 = (a1.x()*v2->x() + a1.y()*v2->y() + a1.z()*v2->z() + offsx)*dval;
- y2 = (a2.x()*v2->x() + a2.y()*v2->y() + a2.z()*v2->z() + offsy)*dval;
- z2 = a3.x()*v2->x() + a3.y()*v2->y() + a3.z()*v2->z() + offsz;*/
- x2 = (a1.x*v2->x + a1.y*v2->y + a1.z*v2->z + offsx)*dval;
- y2 = (a2.x*v2->x + a2.y*v2->y + a2.z*v2->z + offsy)*dval;
- z2 = a3.x*v2->x + a3.y*v2->y + a3.z*v2->z + offsz;
-
- clip3d(x1,y1,z1,x2,y2,z2, xpc1, ypc1, xpc2, ypc2 );
+ x1 = (a1.getX()*v1->getX() + a1.getY()*v1->getY() + a1.getZ()*v1->getZ() + offsx)*dval;
+ y1 = (a2.getX()*v1->getX() + a2.getY()*v1->getY() + a2.getZ()*v1->getZ() + offsy)*dval;
+ z1 = a3.getX()*v1->getX() + a3.getY()*v1->getY() + a3.getZ()*v1->getZ() + offsz;
+
+ x2 = (a1.getX()*v2->getX() + a1.getY()*v2->getY() + a1.getZ()*v2->getZ() + offsx)*dval;
+ y2 = (a2.getX()*v2->getX() + a2.getY()*v2->getY() + a2.getZ()*v2->getZ() + offsy)*dval;
+ z2 = a3.getX()*v2->getX() + a3.getY()*v2->getY() + a3.getZ()*v2->getZ() + offsz;
+
+ clip3d(x1,y1,z1,x2,y2,z2, xscreen1, yscreen1, xscreen2, yscreen2 );
}
void RouteDialog::paintEvent(QPaintEvent *)
{
- //int i, maxi;
int i, startofside;
qreal x1, y1, x2, y2;
int scx1, scy1, scx2, scy2;
int xpc1, ypc1, xpc2, ypc2;
+ Vector temp1, temp2;
QPainter painter(this);
painter.setBrush(QBrush((Qt::yellow), Qt::SolidPattern));
// Draw route window frsme
- painter.drawLine(left,top,right,top);
- painter.drawLine(right,top,right,bottom);
- painter.drawLine(left,top,left,bottom);
- painter.drawLine(left,bottom,right,bottom);
-
-//void view( void)
-//{
- //int i, startofside;
+ //painter.drawLine(left,top,right,top);
+ //painter.drawLine(right,top,right,bottom);
+ //painter.drawLine(left,top,left,bottom);
+ //painter.drawLine(left,bottom,right,bottom);
+
i=1;
while(i<length)
{
i++;
while (connection[i] > 0)
{
- transformseg( &pa[connection[i-1]],&pa[connection[i]], &xpc1, &ypc1, &xpc2, &ypc2);
+ //transformseg( &pa[connection[i-1]],&pa[connection[i]], &xpc1, &ypc1, &xpc2, &ypc2);
+ temp1 = vertexList.at(connection[i-1]);
+ temp2 = vertexList.at(connection[i]);
+ transformseg( &temp1,&temp2, &xpc1, &ypc1, &xpc2, &ypc2);
+
painter.drawLine(xpc1, ypc1, xpc2, ypc2);
i++;
}
- transformseg( &pa[connection[i-1]],&pa[-connection[i]],&xpc1, &ypc1, &xpc2, &ypc2);
+ // to last segment
+ //transformseg( &pa[connection[i-1]],&pa[-connection[i]],&xpc1, &ypc1, &xpc2, &ypc2);
+ temp1 = vertexList.at(connection[i-1]);
+ temp2 = vertexList.at(-connection[i]);
+ transformseg( &temp1,&temp2, &xpc1, &ypc1, &xpc2, &ypc2);
painter.drawLine(xpc1, ypc1, xpc2, ypc2);
- transformseg( &pa[-connection[i]],&pa[connection[startofside]],&xpc1, &ypc1, &xpc2, &ypc2);
+ // from last segemt to start
+ //transformseg( &pa[-connection[i]],&pa[connection[startofside]],&xpc1, &ypc1, &xpc2, &ypc2);
+ temp1 = vertexList.at(-connection[i]);
+ temp2 = vertexList.at(connection[startofside]);
+ transformseg( &temp1,&temp2, &xpc1, &ypc1, &xpc2, &ypc2);
painter.drawLine(xpc1, ypc1, xpc2, ypc2);
i++;
}
*/
XmlReader::XmlReader()
{
- xmlShow();
+ myCategoryList = new CategoryList();
}
/**
{
category = "";
unit = "";
- description = "";
position = "";
user = "";
value = "";
+ delete myCategoryList;
}
/**
- *This function is used to parsing xml file.
+ *This function is used to parse top 10 results of a certain category.
*/
void XmlReader::xmlReadTop10Results(QNetworkReply *device)
{
qDebug() << "_xmlReadTop10Results";
- xmlreader.addData(device->readAll());
+ int i = 0;
+ int receivedFlag = 0;
+
+ xmlreader.clear();
+ QByteArray array = device->readAll();
+ qDebug() << "array: " << array;
+ xmlreader.addData(array);
+ //xmlreader.addData(device->readAll());
+
+ if(!(myCategoryList->top10List.isEmpty())) {
+ myCategoryList->top10List.clear();
+ }
//Go trough the xml document
while(!xmlreader.atEnd())
if(xmlreader.name() == "results")
{
qDebug() << xmlreader.name();
- attr = xmlreader.attributes();
-
- category = attr.value("category").toString();
- unit = attr.value("unit").toString();
- description = attr.value("description").toString();
-
- top10List << category;
- qDebug() << top10List << unit << description;
}
-
if(xmlreader.name() == "result")
{
qDebug() << "result";
attr = xmlreader.attributes();
+ user = attr.value("username").toString();
position = attr.value("position").toString();
- user = attr.value("user").toString();
+ date = attr.value("date").toString();
+ unit = attr.value("unit").toString();
value = attr.value("value").toString();
- if (category == "acceleration-0-100")
- {
- top10AccelerationList.append(position + "\t" +
+ myCategoryList->top10List.append(position + "\t" +
user + "\t" +
- value +
+ value + " " +
unit + "\t" +
- description + "\n");
- }
-
- if(category == "top10speed")
- {
- top10SpeedList.append(position + "\t" +
- user + "\t" +
- value +
- unit + "\t" +
- description + "\n");
- }
-
- if(category == "top10gforce")
- {
- top10GforceList.append(position + "\t" +
- user + "\t" +
- value +
- unit + "\t" +
- description + "\n");
- }
- qDebug() << position << user << value << unit;
+ date + "\n");
+
+ qDebug() << position << user << value << unit << date;
+ i++;
+ receivedFlag = 1;
}
}
}
+ //Only change labelTopList if a new top10List has been received
+ if(receivedFlag)
+ {
+ qDebug() << "receivedTop10List() emitted";
+ emit receivedTop10List();
+ }
}
void XmlReader::xmlReadCategories(QNetworkReply *device)
qDebug() << "_xmlReadCategories";
int i = 0;
+ int receivedFlag = 0;
+ xmlreader.clear();
QByteArray array = device->readAll();
- qDebug() << array;
+ qDebug() << "array: " << array;
xmlreader.addData(array);
+ //xmlreader.addData(device->readAll());
+
+ if(myCategoryList->sizeOfCategoryList() != 0) {
+ myCategoryList->clearCategoryList();
+ }
+ //qDebug() << "sizeOfCategoryList(): " << myCategoryList->sizeOfCategoryList();
//Go trough the xml document
while(!xmlreader.atEnd())
if(xmlreader.name() == "category")
{
qDebug() << xmlreader.name();
- categoryList.insert(i, xmlreader.readElementText());
- qDebug() << "i=" << i << categoryList.at(i);
+ myCategoryList->appendCategoryList(xmlreader.readElementText());
+ qDebug() << "i=" << i << myCategoryList->itemOfCategoryList(i);
i++;
+ receivedFlag = 1;
}
}
}
+ //Only change comboBoxTopCategory if a new list has been received
+ if(receivedFlag)
+ {
+ qDebug() << "receivedCategoryList() emitted";
+ emit receivedCategoryList();
+ }
}
/**
#include <QXmlStreamReader>
#include <QStringList>
#include <QNetworkReply>
+#include "categorylist.h"
-class XmlReader : public QObject
-{
+class XmlReader : public QObject {
+ Q_OBJECT
public:
XmlReader();
~XmlReader();
+ CategoryList *myCategoryList;
private:
QXmlStreamReader xmlreader;
- QStringList top10List; // Next 4 to be removed. Categorylist now in own class.
- QStringList categoryList;
- QString top10AccelerationList;
- QString top10SpeedList;
- QString top10GforceList;
QXmlStreamAttributes attr;
QString category;
QString unit;
- QString description;
+ QString date;
QString position;
QString user;
QString value;
+signals:
+ void receivedCategoryList();
+ void receivedTop10List();
+
public slots:
void xmlReadTop10Results(QNetworkReply *device);
void xmlReadCategories(QNetworkReply *device);
*/
XmlWriter::XmlWriter()
{
- tmpvalue = 10;
+ tmpvalue = 110;
+ trackInd = 0;
}
/**
tmpvalue++;
qDebug() << tmpvalue;
xmlwriter.writeAttribute("value", QString::number(tmpvalue));
- xmlwriter.writeAttribute("unit", "seconds");
- xmlwriter.writeAttribute("date", QDateTime::currentDateTime().toString());
xmlwriter.writeEndElement();
xmlwriter.writeEndDocument();
}
/**
+ *@brief Write track to server.
+ *@param Starting index of gps results table.
+ *@param Ending index of gps results table.
+ *@todo Connect to real values.
+ *@todo Decide suitable parameters.
+ */
+void XmlWriter::writeGpsTrack(int startInd, int stopInd)
+{
+ qDebug() << "_writeGpsTrack";
+ analyzeGpsData();
+
+ int i = 0;
+
+ xmlwriter.writeStartElement("gpx");
+ xmlwriter.writeAttribute("someattribute", "abc");
+ xmlwriter.writeAttribute("otherattribute", "cde");
+
+ xmlwriter.writeStartElement("metadata");
+ xmlwriter.writeStartElement("link");
+ xmlwriter.writeAttribute("href", "http://api.speedfreak-app.com/api/track");
+ xmlwriter.writeCharacters("Speed Freak");
+ xmlwriter.writeEndElement();
+ xmlwriter.writeStartElement("time");
+ xmlwriter.writeCharacters(QDateTime::currentDateTime().toString());
+ xmlwriter.writeEndElement();
+ xmlwriter.writeEndElement(); //metadata
+
+ xmlwriter.writeStartElement("trk");
+ xmlwriter.writeStartElement("name");
+ xmlwriter.writeCharacters("Example Track");
+ xmlwriter.writeEndElement();
+ xmlwriter.writeStartElement("trkseg");
+ for(i = startInd; i < (stopInd - startInd); i++) {
+ xmlwriter.writeStartElement("trkpt");
+ xmlwriter.writeAttribute("lat", QString::number(trackTable[i].latitude));
+ xmlwriter.writeAttribute("lon", QString::number(trackTable[i].longitude));
+ xmlwriter.writeStartElement("ele");
+ xmlwriter.writeCharacters(QString::number(trackTable[i].altitude));
+ xmlwriter.writeEndElement();
+ xmlwriter.writeStartElement("time");
+ xmlwriter.writeCharacters(QString::number(trackTable[i].time));
+ xmlwriter.writeEndElement();
+ xmlwriter.writeStartElement("speed");
+ xmlwriter.writeCharacters(QString::number(trackTable[i].speed));
+ xmlwriter.writeEndElement();
+ xmlwriter.writeStartElement("track");
+ xmlwriter.writeCharacters(QString::number(trackTable[i].track));
+ xmlwriter.writeEndElement();
+ xmlwriter.writeEndElement(); //trkpt
+ }
+ xmlwriter.writeEndElement(); //trkseg
+ xmlwriter.writeEndElement(); //trk
+ xmlwriter.writeEndElement(); //gpx
+}
+
+
+/**
*@brief Opens and closes a file, when xml information is written into a file,
*and passes file to writeXmlFile()
*@param usr for user name.
{
xmlwriter.setDevice(device);
xmlwriter.writeStartDocument();
- writeItems();
+ //writeItems();
//serverWritesXml();
+ writeGpsTrack(0, 16);
xmlwriter.writeEndDocument();
return true;
xmlwriter.writeEndElement();
xmlwriter.writeStartElement("category");
- xmlwriter.writeCharacters("acceleration-0-60");
+ xmlwriter.writeCharacters("acceleration-0-40");
xmlwriter.writeEndElement();
xmlwriter.writeStartElement("category");
xmlwriter.writeEndElement();
}
+
+
+/**
+ *@brief A temp function during development, used to create data for drawing route and for server.
+ */
+void XmlWriter::analyzeGpsData()
+{
+ qDebug() << "_analyzeGpsData";
+
+ double startTime;
+ int tableSize = 0;
+
+ qDebug() << "sizeof(analyzeTable)" << sizeof(analyzeTable);
+ tableSize = 16;
+
+ for(int i = 1; i < tableSize; i++)
+ {
+ //example of one feature whose consequent values are compared and saved if they differentiate too much
+ if(analyzeTable[i].speed < (analyzeTable[i-1].speed - 1) ||
+ analyzeTable[i].speed > (analyzeTable[i-1].speed + 1) )
+ {
+ trackTable[trackInd] = analyzeTable[i];
+ trackInd++;
+ qDebug() << "trackTable[trackInd].speed" << trackTable[trackInd].speed;
+ }
+ }
+}
+
+void XmlWriter::initPointTable(gpsPoint *table, int count, double add1, int add2, int add3)
+{
+ qDebug() << "_initPointTable";
+
+ int i = 1;
+ int j = 0;
+
+ table[0].latitude = 67.00;
+ table[0].longitude = 27.50;
+ table[0].altitude = 7.00;
+ table[0].speed = 0;
+ table[0].time = 0;
+
+ for(j = 0; j < count; j++)
+ {
+ table[i].latitude = table[i-1].latitude + add1;
+ //table[i].longitude = table[i-1].longitude + add1;
+ table[i].altitude = table[i-1].altitude + add1;
+ table[i].speed = table[i-1].speed + add2;
+ table[i].track = table[i-1].track + 1;
+ table[i].time = table[i-1].time + add3;
+ i++;
+ }
+ for(j = 0; j < count; j++)
+ {
+ //table[i].latitude = table[i-1].latitude + add1;
+ table[i].longitude = table[i-1].longitude + add1;
+ table[i].altitude = table[i-1].altitude -add1;
+ table[i].speed = table[i-1].speed + add2;
+ table[i].track = table[i-1].track + 1;
+ table[i].time = table[i-1].time + add3;
+ i++;
+ }
+ for(j = 0; j < count; j++)
+ {
+ table[i].latitude = table[i-1].latitude - add1;
+ //table[i].longitude = table[i-1].longitude + add1;
+ table[i].altitude = table[i-1].altitude + add1;
+ table[i].speed = table[i-1].speed - add2;
+ table[i].track = table[i-1].track - 1;
+ table[i].time = table[i-1].time + add3;
+ i++;
+ }
+ for(j = 0; j < count; j++)
+ {
+ //table[i].latitude = table[i-1].latitude + add1;
+ table[i].longitude = table[i-1].longitude - add1;
+ table[i].altitude = table[i-1].altitude - add1;
+ table[i].speed = table[i-1].speed - add2;
+ table[i].track = table[i-1].track - 1;
+ table[i].time = table[i-1].time + add3;
+ i++;
+ }
+}
+
+
#include <QApplication>
-class XmlWriter : public QObject
-{
+class XmlWriter : public QObject {
+ Q_OBJECT
public:
XmlWriter();
~XmlWriter();
int tmpvalue;
+ typedef struct {
+ double time;
+ double latitude;
+ double longitude;
+ double altitude;
+ double speed;
+ double track;
+ } gpsPoint;
+ gpsPoint trackTable[100];
+ gpsPoint analyzeTable[100];
+ int trackInd;
private:
QXmlStreamWriter xmlwriter;
void writeXml();
void writeItems();
void serverWritesXml();
-
+ void writeGpsTrack(int startInd, int stopInd);
+ void initPointTable(gpsPoint *table, int count, double add1, int add2, int add3);
+ void analyzeGpsData();
};
#endif // XMLWRITER_H
+
*/
public function categories(){
if ($this->is_authorized()){
- $xml = new View('api/categories');
+ $view = new View('api/categories');
$cat = new Category_Model();
- $xml->categories=$cat->get_all();
- $xml->render(true);
+ $view->categories=$cat->get_all();
+ $view->render(true);
}
else
$this->not_authorized();
}
+
+ /*
+ * Get results
+ *
+ */
+ public function results($category, $limit){
+ $results = New Result_Model();
+ $cat = New Category_Model();
+ if ($cat->category_exists($category) AND $this->is_authorized() AND isset($limit)){
+ $view = new View('api/results');
+ $view->results = $results->get_results($category, $limit);
+ $view->render(true);
+ }
+ else
+ $this->not_authorized();
+ }
+
+ /*
+ * Submit results to selected category
+ *
+ * @param string $category Category to which results are submitted
+ */
+ public function update($category){
+ $cat = New Category_Model();
+ if ($cat->category_exists($category) AND $this->is_authorized()){
+ $xml = $this->get_xml();
+ $result = New Result_Model();
+ if ($result->insert($category,$_SERVER['PHP_AUTH_USER'], $xml['value'])){
+ print "OK";
+ die;
+ }
+ else {
+ header("HTTP/1.1 400 Bad Request");
+ echo "Invalid request";
+ die;
+ }
+ }
+ else {
+ header("HTTP/1.0 404 Not Found");
+ die('Category not found or not authorized');
+ }
+
+ }
}
\ No newline at end of file
return false;
}
+ /*
+ * Check if category exists
+ *
+ * @param string $category Category name (slug)
+ * @return bool True if exists and False otherwise
+ */
+ public function category_exists($category){
+ $results = $this->db->query("SELECT id FROM categories where slug = ?", $category);
+ if ($results->count()>0)
+ return true;
+ else
+ return false;
+ }
+
+ /*
+ * Get category id
+ *
+ * @param string $category Category name (slug)
+ * @return integer|bool Category id if successful or false
+ */
+ public function get_id($category){
+ $results = $this->db->query("SELECT id FROM categories where slug = ?", $category);
+ if ($results->count()>0)
+ return $results[0]->id;
+ else
+ return false;
+ }
+
}
\ No newline at end of file
#
# Host: localhost (MySQL 5.1.37)
# Database: speedfreak
-# Generation Time: 2010-03-17 14:16:47 +0200
+# Generation Time: 2010-03-19 11:11:11 +0200
# ************************************************************
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
UNLOCK TABLES;
+# Dump of table results
+# ------------------------------------------------------------
+
+DROP TABLE IF EXISTS `results`;
+
+CREATE TABLE `results` (
+ `cat_id` int(11) NOT NULL,
+ `user_id` int(11) NOT NULL,
+ `value` text NOT NULL,
+ `result_date` datetime NOT NULL,
+ KEY `cat_id` (`cat_id`),
+ KEY `user_id` (`user_id`),
+ CONSTRAINT `results_ibfk_1` FOREIGN KEY (`cat_id`) REFERENCES `categories` (`id`),
+ CONSTRAINT `results_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+
+
# Dump of table users
# ------------------------------------------------------------
PRIMARY KEY (`id`),
UNIQUE KEY `login_unique` (`username`),
UNIQUE KEY `email_unique` (`email`)
-) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
--- /dev/null
+<?php defined('SYSPATH') or die('No direct script access.');
+/*
+ * Results model for creating and manipulating results
+ *
+ * @author Artem Daniliants <artem@daniliants.com>
+ * @copyright (c) 2010 Speed Freak team
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License
+ */
+
+class Result_Model extends Model {
+
+ public function __construct(){
+
+ // load database library into $this->db
+ parent::__construct();
+ }
+
+ /*
+ * Fetch results
+ *
+ * @param string $category From which category should we get results
+ * @param integer $limit How many results to return
+ * @return object|bool Returns object containing results if everything is ok and false otherwise
+ */
+ public function get_results($category, $limit=10){
+ $results = $this->db->query("SELECT u.username as username, c.unit as unit, r.value as value, r.result_date as result_date, c.slug as slug FROM users u, results r, categories c WHERE r.user_id=u.id AND c.slug = ? AND r.cat_id=c.id ORDER BY value DESC LIMIT ".(int)$limit, $category);
+ if ($results->count()>0)
+ return $results;
+ else
+ return false;
+ }
+
+ /*
+ * Insert new result
+ *
+ * @param string $category Category name (slug)
+ * @return bool True if exists and False otherwise
+ */
+ public function insert($category, $username, $value){
+ $cat = New Category_Model();
+ $category = $cat->get_id($category);
+ $user = New User_Model();
+ $username = $user->get_id($username);
+ $results = $this->db->query("INSERT INTO results SET cat_id = ?, user_id = ?, value = ?, result_date = NOW()", $category, $username, $value);
+ if ($results)
+ return true;
+ else
+ return false;
+ }
+
+}
\ No newline at end of file
}
/*
+ * Get user id
+ *
+ * @param string $username Username
+ * @return integer|bool User id if successful or false
+ */
+ public function get_id($username){
+ $result = $this->db->query("SELECT id FROM users WHERE username = ?", $username);
+ if ($result->count()>0)
+ return $result[0]->id;
+ else
+ return false;
+ }
+
+ /*
* Check if supplied credentials are valid
*
* @param string $username Username
<categories>
<?php foreach ($categories as $k){ ?> <category description="<?php echo $k->description; ?>" unit="<?php echo $k->unit; ?>"><?php echo $k->slug; ?></category>
-<?php } ?></catgories>
\ No newline at end of file
+<?php } ?></categories>
\ No newline at end of file
--- /dev/null
+<?php echo "<?"; ?>xml version="1.0" encoding="utf-8" <?php echo "?>"; ?>
+
+<results>
+ <?php $i=1; foreach ($results as $r){ ?> <result username="<?php echo $r->username; ?>" position="<?php echo $i; ?>" date="<?php echo $r->result_date; ?>" unit="<?php echo $r->unit; ?>" value="<?php echo $r->value; ?>" />
+<?php $i++; } ?></results>
\ No newline at end of file