1
0

Finished Highscore API

This commit is contained in:
Mike Schwörer 2014-07-20 16:18:05 +02:00
parent 49b7368f44
commit e4a08ce32d
11 changed files with 661 additions and 1 deletions

View File

@ -24,6 +24,12 @@ updates -> Removed col 'Log'
ms4_log -> Added
entrys -> ms4_highscoreentries
games -> ms4_highscoregames
ms4_highscoreentries.IP -> length = 41
updateslog -> new table
<?php
$rows=Yii::app()->db->createCommand('SELECT * FROM {{updates}}')->queryAll();

View File

@ -91,6 +91,12 @@ return ArrayX::merge(
'blog/<id>' => 'blogPost/view/id/<id>',
'blog/<id>/<name>' => 'blogPost/view/id/<id>',
'Highscores/list.php' => 'Highscores/list', // Compatibility
'Highscores/insert.php' => 'Highscores/insert', // Compatibility
'Highscores/update.php' => 'Highscores/update', // Compatibility
'Highscores/list_top50.php' => 'Highscores/list_top50', // Compatibility
'Highscores/getNewID.php' => 'Highscores/newID', // Compatibility
'downloads/details.php' => 'programs/index', // Compatibility
'downloads/downloads.php' => 'programs/index', // Compatibility
'downloads/<id>' => 'programs/view', // Compatibility

View File

@ -51,4 +51,9 @@ class APIController extends MSController
$this->render('update', ['data' => $data]);
}
public function actionTest()
{
$this->render('test', []);
}
}

View File

@ -0,0 +1,222 @@
<?php
class HighscoresController extends MSController //TODO-MS Test online if it all works
{
const ENTRYLIST_PAGESIZE = 20;
public $layout = false;
/**
* @return array action filters
*/
public function filters()
{
return array(
'accessControl',
);
}
/**
* Specifies the access control rules.
* This method is used by the 'accessControl' filter.
* @return array access control rules
*/
public function accessRules()
{
return array(
array('allow',
'users'=>array('*'),
),
);
}
public function actionInsert($gameid, $check, $name, $rand, $points)
{
if (! is_numeric($gameid))
throw new CHttpException(400, 'Invalid Request');
if (! is_numeric($points))
throw new CHttpException(400, 'Invalid Request');
$entry = new HighscoreEntries();
$entry->GAME_ID = $gameid;
$entry->POINTS = $points;
$entry->PLAYER = $name;
$entry->PLAYERID = -1;
$entry->CHECKSUM = $check;
$entry->TIMESTAMP = time();
$entry->IP = $_SERVER['REMOTE_ADDR'];
if ($entry->checkChecksum($rand))
{
if ($entry->save())
{
$this->actionListEntries($gameid);
return;
}
else
{
echo 'Error while inserting';
return;
}
}
else
{
echo 'Nice try !';
return;
}
}
public function actionList()
{
if (!isset($_GET["gameid"]))
{
$this->actionListGames();
return;
}
else
{
$this->actionListEntries(intval(mysql_real_escape_string($_GET["gameid"])));
return;
}
}
public function actionListEntries($gameid)
{
if (! is_numeric($gameid))
throw new CHttpException(400, 'Invalid Request - [gameid] must be an integer');
if (!isset($_GET["start"]))
{
$start = 0;
}
else
{
$start = intval(mysql_real_escape_string($_GET["start"])) - 1;
if ($start < 0)
{
$start = 0;
}
}
if (isset($_GET["highlight"]))
{
$highlight= intval(mysql_real_escape_string($_GET["highlight"]));
}
else
$highlight = 0;
$game = HighscoreGames::model()->findByPk($gameid);
$this->render('listentries',
[
'game' => $game,
'start' => $start,
'highlight' => $highlight,
'pagesize' => self::ENTRYLIST_PAGESIZE,
]);
}
public function actionListGames()
{
$criteria = new CDbCriteria;
$games = HighscoreGames::model()->findAll($criteria);
$this->render('listgames',
[
'games' => $games,
]);
}
public function actionUpdate($gameid, $check, $name, $nameid, $rand, $points)
{
if (! is_numeric($gameid))
throw new CHttpException(400, 'Invalid Request');
if (! is_numeric($nameid))
throw new CHttpException(400, 'Invalid Request');
if (! is_numeric($points))
throw new CHttpException(400, 'Invalid Request');
$criteria = new CDbCriteria;
$criteria->addCondition('GAME_ID = ' . $gameid);
$criteria->addCondition('PLAYERID = ' . $nameid);
/* @var HighscoreEntries $entry */
$entry = HighscoreEntries::model()->find($criteria);
if (is_null($entry))
{
$entry = new HighscoreEntries();
$entry->GAME_ID = $gameid;
$entry->POINTS = $points;
$entry->PLAYER = $name;
$entry->PLAYERID = -1;
$entry->CHECKSUM = $check;
$entry->TIMESTAMP = time();
$entry->IP = $_SERVER['REMOTE_ADDR'];
if ($entry->checkChecksum($rand))
{
if ($entry->save())
{
$this->actionListEntries($gameid);
return;
}
else
{
echo 'Error while inserting';
return;
}
}
else
{
echo 'Nice try !';
return;
}
}
else
{
$entry->POINTS = $points;
$entry->PLAYER = $name;
$entry->CHECKSUM = $check;
$entry->IP = $_SERVER['REMOTE_ADDR'];
if ($entry->checkChecksum($rand))
{
$entry->update();
$this->actionListEntries($gameid);
}
else
{
echo 'Nice try !';
return;
}
}
}
public function actionList_Top50($gameid)
{
if (! is_numeric($gameid))
throw new CHttpException(400, 'Invalid Request - [gameid] must be an integer');
$game = HighscoreGames::model()->findByPk($gameid);
$this->render('list_top50',
[
'game' => $game,
]);
}
public function actionNewID($gameid)
{
$connection=Yii::app()->db;
$command=$connection->createCommand("SELECT MAX(PLAYERID)+1 AS NID FROM {{highscoreentries}} WHERE GAME_ID = $gameid");
$newid = $command->queryScalar();
if ($newid < 1024) {
$newid = 1024;
}
print $newid;
}
}

View File

@ -0,0 +1,149 @@
<?php
/**
* This is the model class for table "{{highscoreentries}}".
*
* The followings are the available columns in table '{{highscoreentries}}':
* @property integer $GAME_ID
* @property string $POINTS
* @property string $PLAYER
* @property integer $PLAYERID
* @property string $CHECKSUM
* @property string $TIMESTAMP
* @property string $IP
* @property HighscoreGames $GAME
*/
class HighscoreEntries extends CActiveRecord
{
/**
* @return string the associated database table name
*/
public function tableName()
{
return '{{highscoreentries}}';
}
/**
* @return array validation rules for model attributes.
*/
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('GAME_ID, PLAYER, CHECKSUM, TIMESTAMP, IP', 'required'),
array('GAME_ID, PLAYERID', 'numerical', 'integerOnly'=>true),
array('POINTS', 'length', 'max'=>20),
array('PLAYER, IP', 'length', 'max'=>41),
array('CHECKSUM', 'length', 'max'=>32),
// The following rule is used by search().
// @todo Please remove those attributes that should not be searched.
array('GAME_ID, POINTS, PLAYER, PLAYERID, CHECKSUM, TIMESTAMP, IP', 'safe', 'on'=>'search'),
);
}
/**
* @return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'GAME' =>
[
self::HAS_ONE,
'HighscoreGames',
[
'ID' => 'GAME_ID'
]
],
);
}
/**
* @return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'GAME_ID' => 'Game',
'POINTS' => 'Points',
'PLAYER' => 'Player',
'PLAYERID' => 'Playerid',
'CHECKSUM' => 'Checksum',
'TIMESTAMP' => 'Timestamp',
'IP' => 'IP',
);
}
/**
* Retrieves a list of models based on the current search/filter conditions.
*
* Typical usecase:
* - Initialize the model fields with values from filter form.
* - Execute this method to get CActiveDataProvider instance which will filter
* models according to data in model fields.
* - Pass data provider to CGridView, CListView or any similar widget.
*
* @return CActiveDataProvider the data provider that can return the models
* based on the search/filter conditions.
*/
public function search()
{
// @todo Please modify the following code to remove attributes that should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('GAME_ID',$this->GAME_ID);
$criteria->compare('POINTS',$this->POINTS,true);
$criteria->compare('PLAYER',$this->PLAYER,true);
$criteria->compare('PLAYERID',$this->PLAYERID);
$criteria->compare('CHECKSUM',$this->CHECKSUM,true);
$criteria->compare('TIMESTAMP',$this->TIMESTAMP,true);
$criteria->compare('IP',$this->IP,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
/**
* Returns the static model of the specified AR class.
* Please note that you should have this exact method in all your CActiveRecord descendants!
* @param string $className active record class name.
* @return HighscoreEntries the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
//####################################
//########### MY FUNCTIONS ###########
//####################################
/**
* @param $rand
* @return string
*/
public function generateChecksum($rand)
{
$game = HighscoreGames::model()->findByPk($this->GAME_ID);
/* @var $game HighscoreGames */
if ($this->PLAYERID >= 0)
return md5($rand . $this->PLAYER . $this->PLAYERID . $this->POINTS . $game->ID);
else
return md5($rand . $this->PLAYER . $this->POINTS . $game->ID);
}
/**
* @param $rand
* @return bool
*/
public function checkChecksum($rand)
{
return $this->generateChecksum($rand) == $this->CHECKSUM;
}
}

View File

@ -0,0 +1,118 @@
<?php
/**
* This is the model class for table "{{highscoregames}}".
*
* The followings are the available columns in table '{{highscoregames}}':
* @property integer $ID
* @property string $NAME
* @property string $SALT
* @property HighscoreEntries[] $ENTRIES
*/
class HighscoreGames extends CActiveRecord
{
/**
* @return string the associated database table name
*/
public function tableName()
{
return '{{highscoregames}}';
}
/**
* @return array validation rules for model attributes.
*/
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('NAME, SALT', 'required'),
array('NAME', 'length', 'max'=>63),
array('SALT', 'length', 'max'=>6),
// The following rule is used by search().
array('ID, NAME', 'safe', 'on'=>'search'),
);
}
/**
* @return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'ENTRIES' =>
[
self::HAS_MANY,
'HighscoreEntries',
[
'GAME_ID' => 'ID'
],
'order'=>'POINTS DESC'
],
);
}
/**
* @return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'ID' => 'ID',
'NAME' => 'Name',
'SALT' => 'Salt',
);
}
/**
* Retrieves a list of models based on the current search/filter conditions.
*
* Typical usecase:
* - Initialize the model fields with values from filter form.
* - Execute this method to get CActiveDataProvider instance which will filter
* models according to data in model fields.
* - Pass data provider to CGridView, CListView or any similar widget.
*
* @return CActiveDataProvider the data provider that can return the models
* based on the search/filter conditions.
*/
public function search()
{
// @todo Please modify the following code to remove attributes that should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('ID',$this->ID);
$criteria->compare('NAME',$this->NAME,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
/**
* Returns the static model of the specified AR class.
* Please note that you should have this exact method in all your CActiveRecord descendants!
* @param string $className active record class name.
* @return HighscoreGames the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
//####################################
//########### MY FUNCTIONS ###########
//####################################
/**
* @return string
*/
public function getListLink()
{
return '/Highscores/list?gameid=' . $this->ID;
}
}

View File

@ -49,7 +49,8 @@ class ProgramUpdates extends CActiveRecord
'ProgramUpdatesLog',
[
'programname' => 'Name'
]],
]
],
);
}

View File

@ -0,0 +1,8 @@
<?php
/* @var $this HighscoresController */
/* @var $game HighscoreGames */
for ($i = 0; $i < 50; $i++)
{
print($game->ENTRIES[$i]->POINTS . '||' . htmlentities($game->ENTRIES[$i]->PLAYER) . "\r\n");
}

View File

@ -0,0 +1,102 @@
<?php
/* @var $this HighscoresController */
/* @var $game HighscoreGames */
/* @var $start int */
/* @var $highlight int */
/* @var $pagesize int */
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta charset="utf-8"/>
<title>highscores</title>
<style type="text/css">
<!--
body {
background-color: #DDF;
padding: 1em 1em 0em;
}
table {
margin: auto;
width: 80%;
text-align: center;
border-spacing: 0px;
}
table td {
padding: 2px 0px;
}
caption {
font-weight: bolder;
text-decoration: underline;
font-size: x-large;
}
a {
color: #008;
text-decoration: underline;
}
a:hover { text-decoration: none; }
#headline > td { text-decoration: underline; }
#highlight {
font-weight: bolder;
background-color: #CCF;
}
-->
</style>
</head>
<body>
<table>
<caption><?php echo $game->NAME; ?></caption>
<tr id="headline" >
<td>rank</td>
<td>points</td>
<td>name</td>
</tr>
<?php
$current = 0;
foreach ($game->ENTRIES as $entry)
{
$current++;
if ($current >= $start && $current - $start <= $pagesize)
{
if ($current == $highlight)
echo '<tr id="highlight">';
else
echo "<tr>";
echo "<td>$current</td>";
echo "<td>$entry->POINTS</td>";
echo "<td>$entry->PLAYER</td>";
echo "</tr>";
}
}
$more = max(0, $start - $pagesize);
$less = $start + $pagesize;
echo '<tr>';
if ($start > 0)
echo '<td><a href="' . "/Highscores/list?gameid=$game->ID&start=$more&highlight=$highlight" . '">[more points]</a></td>';
else
echo '<td></td>';
echo '<td></td>';
if ($start + $pagesize < count($game->ENTRIES))
echo '<td><a href="' . "/Highscores/list?gameid=$game->ID&start=$less&highlight=$highlight" . '">[less points]</a></td>';
else
echo '<td></td>';
echo '</tr>';
?>
</table>
</body>
</html>

View File

@ -0,0 +1,36 @@
<?php
/* @var $this HighscoresController */
/* @var $games HighscoreGames[] */
?>
<html>
<head>
<meta charset="utf-8"/>
<title>highscores</title>
<style type="text/css">
<!--
body {
background-color: #DDF;
padding: 1em 1em 0em;
}
a {
color: #008;
text-decoration: underline;
}
a:hover { text-decoration: none; }
-->
</style>
</head>
<body>
<?php
foreach ($games as $game)
{
echo '<a href="' . $game->getListLink() . '">' . $game->NAME . '</a><br>' . "\r\n";
}
?>
</body>
</html>

View File

@ -0,0 +1,7 @@
<?php
/* @var $this APIController */
/* @var $gm HighscoreGames */
$gm = HighscoreGames::model()->findByPk(1);
echo nl2br(print_r( $gm->ENTRIES, true));