Release Template files

This commit is contained in:
2026-07-13 11:37:58 +02:00
parent e673b1954c
commit d21c1f24b7
238 changed files with 39672 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
<?php
include_once '../objects/db_table_object.php';
class DBObjectType extends DBTableObject
{
// database connection and table name
//private $conn;
//private $table_name = "sessioneventtypes";
protected $array_key = "type";
// object properties
public $id = -1;
public $displayName = "";
public $description = "";
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function toArray () : array
{
return array (
"id" => $this->id,
"displayName" => $this->displayName,
"description" => $this->description
);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function save ()
{
// query to insert record of new user signup
$query = "INSERT INTO " . $this->table_name . " SET displayName=:displayName, description=:description";
// prepare query
$stmt = $this->conn->prepare($query);
// sanitize
$this->displayName=htmlspecialchars(strip_tags($this->displayName));
$this->description=htmlspecialchars(strip_tags($this->description));
// bind values
$stmt->bindParam(":displayName", $this->displayName);
$stmt->bindParam(":description", $this->description);
// execute query
if($stmt->execute())
{
$this->id = $this->conn->lastInsertId();
return true;
}
return false;
}
}
?>

View File

@@ -0,0 +1,591 @@
<?php
include_once "../objects/db_table_object.php";
include_once "../objects/db_participates_results.php";
include_once '../score/score_algo1.php'; // for score calculation
class UserInGameSession extends DBTableObject
{
// database connection and table name
//private $conn;
protected $table_name = PARTICIPATES_TABLE_NAME;
protected $array_key = "participation";
// object properties
public int $userId = -1;
public int $sessionId = 0;
public float $score = 0;
public float $firePrecision = 0.0;
public float $reactionTime = 0.0;
public int $nbEnemyHit = 0;
public int $nbCivilsHit = 0;
public int $damageTaken = 0;
public $endStatus = 0;
public $avatar = "";
public $weapon = "";
public int $role = 0;
public $results = "";
//public $replayFileName = "";
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function toArray () : array
{
return array (
"userId" => (int)$this->userId,
"sessionId" => (int)$this->sessionId,
"score" => (float)$this->score ?? 0.0,
"firePrecision" => (float)$this->firePrecision ?? 0.0,
"reactionTime" => (float)$this->reactionTime ?? 0.0,
"nbEnemyHit" => (int)$this->nbEnemyHit ?? 0,
"nbCivilsHit" => (int)$this->nbCivilsHit ?? 0,
"damageTaken" => (int)$this->damageTaken ?? 0,
"endStatus" => (int)$this->endStatus ?? 0,
"avatar" => $this->avatar ?? "",
"weapon" => $this->weapon ?? "",
"roleId" => $this->role,
"resultsAsString" => $this->results
);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function readRow (array $row)
{
$this->userId = (int)$row['userId'];
$this->sessionId = (int)$row['sessionId'];
$this->score = (int)$row['score'];
$this->firePrecision = (float)$row['firePrecision'];
$this->reactionTime = (float)$row['reactionTime'];
$this->nbEnemyHit = (int)$row['nbEnemyHit'];
$this->nbCivilsHit = (int)$row['nbCivilsHit'];
$this->damageTaken = (int)$row['damageTaken'];
$this->endStatus = (int)$row['endStatus'];
$this->avatar = $row['avatar'];
$this->weapon = $row['weapon'];
$this->role = $row['role'];
$this->results = $row['results'];
//$this->replayFileName = $row['replayFileName'];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function sanitize ()
{
$this->userId=htmlspecialchars(strip_tags($this->userId));
$this->sessionId=htmlspecialchars(strip_tags($this->sessionId));
$this->avatar=htmlspecialchars(strip_tags($this->avatar));
$this->weapon=htmlspecialchars(strip_tags($this->weapon));
$this->role=htmlspecialchars(strip_tags($this->role));
$this->results=htmlspecialchars(strip_tags($this->results));
//$this->nbCivilsHit=htmlspecialchars(strip_tags($this->nbCivilsHit));
//$this->nbEnemyHit=htmlspecialchars(strip_tags($this->nbEnemyHit));
//$this->score=htmlspecialchars(strip_tags($this->score));
//$this->firePrecision=htmlspecialchars(strip_tags($this->firePrecision));
//$this->damageTaken=htmlspecialchars(strip_tags($this->damageTaken));
//$this->replayFileName=htmlspecialchars(strip_tags($this->replayFileName));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function load ()
{
// select all query with user inputed username and password
$query = "SELECT * FROM " . $this->table_name . " WHERE userId='" . $this->userId . "' AND sessionId='" . $this->sessionId . "'";
// prepare query statement
$stmt = $this->conn->prepare($query);
// execute query
$stmt->execute();
if($stmt->rowCount() > 0)
{
// get retrieved row
$row = $stmt->fetch(PDO::FETCH_ASSOC);
// retrieve session values
$this->readRow($row);
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function registerUser ()
{
//$this->sessionId = $session;
//$this->userId = $user;
//$this->avatar = $avatar;
//$this->weapon = $weapon;
if ($this->alreadyRegistered())
return false;
// query to insert record of new user signup
$query = "INSERT INTO " . $this->table_name . " SET sessionId=:sessionId, userId=:userId, avatar=:avatar, weapon=:weapon, role=:role";
// prepare query
$stmt = $this->conn->prepare($query);
// sanitize
$this->sanitize();
// bind values
$stmt->bindParam(":sessionId", $this->sessionId);
$stmt->bindParam(":userId", $this->userId);
$stmt->bindParam(":avatar", $this->avatar);
$stmt->bindParam(":weapon", $this->weapon);
$stmt->bindParam(":role", $this->role);
//$stmt->bindParam(":nbCivilsHit", $this->nbCivilsHit);
//$stmt->bindParam(":nbEnemyHit", $this->nbEnemyHit);
//$stmt->bindParam(":score", $this->score);
//$stmt->bindParam(":firePrecision", $this->firePrecision);
//$stmt->bindParam(":damageTaken", $this->damageTaken);
//$stmt->bindParam(":replayFileName", $this->replayFileName);
// execute query
return $stmt->execute();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function alreadyRegistered ()
{
$query = "SELECT * FROM " . $this->table_name . " WHERE userId=:userId AND sessionId=:sessionId";
// prepare query statement
$stmt = $this->conn->prepare($query);
// sanitize
$this->userId=htmlspecialchars(strip_tags($this->userId));
$this->sessionId=htmlspecialchars(strip_tags($this->sessionId));
// bind values
$stmt->bindParam(":sessionId", $this->sessionId);
$stmt->bindParam(":userId", $this->userId);
// execute query
$stmt->execute();
return $stmt->rowCount() > 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function updateUserScores ()
{
//$this->sessionId = $sessionId;
//$this->userId = $userId;
// load current values
$this->load();
$this->score = 0;
$query = "SELECT sessionType FROM Sessions WHERE id='" . $this->sessionId . "'";
// prepare query
$stmt = $this->conn->prepare($query);
$stmt->execute();
if($stmt->rowCount() > 0)
{
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row['sessionType'] == 0) // FireRange
{
$query = "SELECT R.id, R.hitPrecision, R.objectHitLocationX, R.objectHitLocationY, R.distance, R.objectHitTagLocation " . "
FROM " . REACTEVENTS_TABLE_NAME . " R, " . TRIGGEREVENTS_TABLE_NAME . " T " . "
WHERE R.srcEventSessionId=T.sessionId AND R.srcEventIndex=T.indexCount AND T.srcUserId=:userId AND T.sessionId=:sessionId";
// prepare query
$stmt = $this->conn->prepare($query);
// bind values
$stmt->bindParam(":sessionId", $this->sessionId);
$stmt->bindParam(":userId", $this->userId);
//$stmt->bindParam(":score", $this->score);
//$stmt->bindParam(":role", $role);
// execute query
$stmt->execute();
$totalPrecision=0;
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
$totalPrecision += $row['hitPrecision'];
$this->score = calculate_firerange_v1($totalPrecision);
}
else
{
$query = "SELECT R.id, R.hitPrecision, R.distance, R.reactType, P.nbCivilsHit " . "
FROM " . REACTEVENTS_TABLE_NAME . " R, " . TRIGGEREVENTS_TABLE_NAME . " T, " . $this->table_name . " P " . "
WHERE R.srcEventIndex=T.indexCount AND R.srcEventSessionId=T.sessionId AND P.sessionId=R.srcEventSessionId AND P.userId=T.srcUserId " . "
AND R.srcEventSessionId=:sessionId AND T.srcUserId=:userId AND (R.reactType=0 OR R.reactType=4 OR R.reactType=5)";
// prepare query
$stmt = $this->conn->prepare($query);
// bind values
$stmt->bindParam(":sessionId", $this->sessionId);
$stmt->bindParam(":userId", $this->userId);
//$stmt->bindParam(":score", $this->score);
//$stmt->bindParam(":role", $role);
// execute query
$stmt->execute();
if ($stmt->rowCount() > 0)
{
$totalPrecision=0;
$nbCivilHits=0;
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$nbCivilHits = $row['nbCivilsHit'];
if ($row['reactType']==0) // todo : to keep ?
$totalPrecision += $row['hitPrecision'];
}
$this->score = calculate_v1($totalPrecision, $nbCivilHits);
}
}
}
$query = "UPDATE " . $this->table_name . " SET score=:score WHERE sessionId=:sessionId AND userId=:userId";
// prepare query
$stmt = $this->conn->prepare($query);
// bind values
$stmt->bindParam(":sessionId", $this->sessionId);
$stmt->bindParam(":userId", $this->userId);
$stmt->bindParam(":score", $this->score);
// update overall averages for participation user
$query_Precision = "SELECT X.UserId AS UserId, SUM(X.NbShotsFired) AS nbFire, SUM(Y.HitPrecision) AS precisionTotal FROM " . "
(SELECT P.userID AS UserId, P.sessionId AS SessionId, TE.indexCount AS IndexCount, COUNT(DISTINCT TE.sessionId, TE.indexCount) AS NbShotsFired
FROM " . PARTICIPATES_TABLE_NAME . " P, " . TRIGGEREVENTS_TABLE_NAME . " TE " . "
WHERE P.sessionId=TE.sessionId AND TE.srcUserId=P.UserId GROUP BY P.UserId, P.sessionId, TE.indexCount) AS X
LEFT JOIN
(SELECT P.userID AS UserId, P.sessionId AS SessionId, TE.indexCount AS IndexCount, MAX(RE.hitPrecision) AS HitPrecision
FROM " . PARTICIPATES_TABLE_NAME . " P, " . TRIGGEREVENTS_TABLE_NAME . " TE, " . REACTEVENTS_TABLE_NAME . " RE
WHERE P.sessionId=TE.sessionId AND P.sessionId=RE.srcEventSessionId AND TE.srcUserId=P.UserId AND RE.srcEventIndex=TE.indexCount GROUP BY P.UserId, P.sessionId, TE.indexCount) AS Y
ON (X.UserId=Y.UserId AND X.SessionId=Y.SessionId AND X.IndexCount=Y.IndexCount) WHERE X.UserId=:userId
GROUP BY UserId";
$query_ReactionTime = "SELECT P.userID AS UserId, SUM(CASE WHEN RE.reactTime>0 THEN 1 ELSE 0 END) AS nbHits, SUM(RE.reactTime) AS reactTimeTotal
FROM " . PARTICIPATES_TABLE_NAME . " P, " . TRIGGEREVENTS_TABLE_NAME . " TE, " . REACTEVENTS_TABLE_NAME . " RE
WHERE P.sessionId=TE.sessionId AND P.sessionId=RE.srcEventSessionId AND TE.srcUserId=P.UserId AND RE.srcEventIndex=TE.indexCount AND P.UserId=:userId GROUP BY P.UserId";
$stmt_Precision = $this->conn->prepare($query_Precision);
$stmt_ReactionTime = $this->conn->prepare($query_ReactionTime);
$stmt_Precision->bindParam(":userId", $this->userId);
$stmt_ReactionTime->bindParam(":userId", $this->userId);
$stmt_Precision->execute();
$stmt_ReactionTime->execute();
$res_UpdatePrecision = true;
$res_UpdateReactionTime = true;
if ($stmt_Precision->rowCount() > 0 && $this->userId > 0)
{
// get retrieved row
$row = $stmt_Precision->fetch(PDO::FETCH_ASSOC);
$shotFired = $row['nbFire'];
// retrieve average precision per shot
$userPrecision = $row['precisionTotal']/($shotFired == 0 ? 1 : $shotFired);
$updatePrecision = "UPDATE " . USERS_TABLE_NAME . " SET avgPrecision=" . $userPrecision . " WHERE id=" . $this->userId;
$stmt_UpdatePrecision = $this->conn->prepare($updatePrecision);
$res_UpdatePrecision = $stmt_UpdatePrecision->execute();
}
if ($stmt_ReactionTime->rowCount() > 0 && $this->userId > 0)
{
// get retrieved row
$row = $stmt_ReactionTime->fetch(PDO::FETCH_ASSOC);
$shotHits = $row['nbHits'];
// retrieve average reactionTime per shot
$userReactionTime = $row['reactTimeTotal']/($shotHits == 0 ? 1 : $shotHits);
$updateReactionTime = "UPDATE " . USERS_TABLE_NAME . " SET avgReaction=" . $userReactionTime . " WHERE id=" . $this->userId;
$stmt_UpdateReactionTime = $this->conn->prepare($updateReactionTime);
$res_UpdateReactionTime = $stmt_UpdateReactionTime->execute();
}
return $stmt->execute() && $res_UpdatePrecision && $res_UpdateReactionTime;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function updateObjectives ()
{
// load current values
//$this->load();
// sanitize JSON string
//$this->results=htmlspecialchars(strip_tags($this->results));
// update participation with objective results in database
$query = "UPDATE " . $this->table_name . " SET results=:results WHERE sessionId=:sessionId AND userId=:userId";
// prepare query
$stmt = $this->conn->prepare($query);
// bind values
$stmt->bindParam(":sessionId", $this->sessionId);
$stmt->bindParam(":userId", $this->userId);
$stmt->bindParam(":results", $this->results);
return $stmt->execute();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function userLeaves ()
{
//$this->userId = $userId;
//$this->sessionId = $sessionId;
// load current values
$this->load();
// queries to update user stats
$query_NbShotFired = "SELECT COUNT(DISTINCT TE.indexCount) AS nbFire FROM " . TRIGGEREVENTS_TABLE_NAME . " TE WHERE TE.sessionId=:sessionId AND TE.srcUserId=:userId";
$query_NbEnemyHit = "SELECT COUNT(DISTINCT TE.indexCount, RE.hitTargetName) AS nbEnemyHits FROM " . TRIGGEREVENTS_TABLE_NAME . " TE, " . REACTEVENTS_TABLE_NAME . " RE WHERE TE.sessionId=:sessionId AND RE.srcEventSessionId=TE.sessionId AND RE.srcEventIndex=TE.indexCount AND TE.srcUserId=:userId AND RE.reactType=0";
$query_NbCivilHit = "SELECT COUNT(DISTINCT TE.indexCount, RE.hitTargetName) AS nbCivilHits FROM " . TRIGGEREVENTS_TABLE_NAME . " TE, " . REACTEVENTS_TABLE_NAME . " RE WHERE TE.sessionId=:sessionId AND RE.srcEventSessionId=TE.sessionId AND RE.srcEventIndex=TE.indexCount AND TE.srcUserId=:userId AND RE.reactType=1";
$query_PrecisionAndReactionTime = "SELECT SUM(X.precisionByShot) AS precisionTotal, SUM(X.reactTimeByShot) AS reactTimeTotal, COUNT(CASE WHEN X.reactTime > 0 THEN 1 ELSE 0 END) AS shots
FROM (SELECT COALESCE(RE.hitPrecision,0) AS precisionByShot, COALESCE(RE.reactTime,0) AS reactTimeByShot, RE.reactTime AS reactTime FROM " . TRIGGEREVENTS_TABLE_NAME . " TE, " . REACTEVENTS_TABLE_NAME . " RE WHERE TE.sessionId=:sessionId AND TE.srcUserId=:userId AND TE.sessionId = RE.srcEventSessionId AND TE.indexCount = RE.srcEventIndex AND (RE.reactType=0 OR RE.reactType=4 OR RE.reactType=5) GROUP BY TE.sessionId, TE.srcUserId, TE.indexCount) AS X";
// prepare queries
$stmt_NbShotFired = $this->conn->prepare($query_NbShotFired);
$stmt_NbEnemyHit = $this->conn->prepare($query_NbEnemyHit);
$stmt_NbCivilHit = $this->conn->prepare($query_NbCivilHit);
$stmt_PrecisionAndReactionTime = $this->conn->prepare($query_PrecisionAndReactionTime);
// bind values
$stmt_NbShotFired->bindParam(":sessionId", $this->sessionId);
$stmt_NbShotFired->bindParam(":userId", $this->userId);
$stmt_NbEnemyHit->bindParam(":sessionId", $this->sessionId);
$stmt_NbEnemyHit->bindParam(":userId", $this->userId);
$stmt_NbCivilHit->bindParam(":sessionId", $this->sessionId);
$stmt_NbCivilHit->bindParam(":userId", $this->userId);
$stmt_PrecisionAndReactionTime->bindParam(":sessionId", $this->sessionId);
$stmt_PrecisionAndReactionTime->bindParam(":userId", $this->userId);
// execute queries
$stmt_NbShotFired->execute();
$stmt_NbEnemyHit->execute();
$stmt_NbCivilHit->execute();
$stmt_PrecisionAndReactionTime->execute();
$shotFired=1;
if ($stmt_NbShotFired->rowCount() > 0)
{
// get retrieved row
$row = $stmt_NbShotFired->fetch(PDO::FETCH_ASSOC);
// retrieve nbFire value
$shotFired = $row['nbFire'];
}
if ($stmt_NbEnemyHit->rowCount() > 0)
{
// get retrieved row
$row = $stmt_NbEnemyHit->fetch(PDO::FETCH_ASSOC);
// retrieve nbEnemyHits value
$this->nbEnemyHit = $row['nbEnemyHits'];
}
if ($stmt_NbCivilHit->rowCount() > 0)
{
// get retrieved row
$row = $stmt_NbCivilHit->fetch(PDO::FETCH_ASSOC);
// retrieve nbCivilHits value
$this->nbCivilsHit = $row['nbCivilHits'];
}
if ($stmt_PrecisionAndReactionTime->rowCount() > 0)
{
// get retrieved row
$row = $stmt_PrecisionAndReactionTime->fetch(PDO::FETCH_ASSOC);
$shotsWithReactTime = (int)$row['shots'];
if ($shotsWithReactTime <= 0)
$shotsWithReactTime = 1;
// retrieve average precision per shot
$this->firePrecision = $row['precisionTotal']/($shotFired == 0 ? 1 : $shotFired);
// retrieve average reactionTime per shot
$this->reactionTime = $row['reactTimeTotal']/$shotsWithReactTime;
}
return $this->update() && $stmt_NbShotFired->rowCount() > 0 && $stmt_NbEnemyHit->rowCount() > 0 && $stmt_NbCivilHit->rowCount() > 0 && $stmt_PrecisionAndReactionTime->rowCount() > 0 /* && $stmt_Precision->rowCount() > 0 && $stmt_ReactionTime->rowCount() > 0*/;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function update ()
{
$query = "UPDATE " . $this->table_name . "
SET nbEnemyHit=:nbEnemyHit, nbCivilsHit=:nbCivilsHit, firePrecision=:firePrecision, reactionTime=:reactionTime " . "
WHERE sessionId='".$this->sessionId."' AND userId='".$this->userId."'";
// prepare query
$stmt = $this->conn->prepare($query);
// bind values
$stmt->bindParam(":nbEnemyHit", $this->nbEnemyHit);
$stmt->bindParam(":nbCivilsHit", $this->nbCivilsHit);
$stmt->bindParam(":firePrecision", $this->firePrecision);
$stmt->bindParam(":reactionTime", $this->reactionTime);
// execute query
if ($stmt->execute())
{
// once it has been updated, we have to update the averagePrecision field in the USERS_TABLE_NAME table
$query = "UPDATE " . USERS_TABLE_NAME . "
SET avgPrecision=(SELECT AVG(firePrecision) FROM " . PARTICIPATES_TABLE_NAME . " P WHERE P.userId='".$this->userId."'),
avgReaction=(SELECT AVG(reactionTime) FROM " . PARTICIPATES_TABLE_NAME . " P WHERE P.userId='".$this->userId."')
WHERE users.id='".$this->userId."'";
// prepare query
$stmt = $this->conn->prepare($query);
// execute query
return $stmt->execute();
}
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function updateScore ()
{
$query = "UPDATE " . $this->table_name . " SET score=:score WHERE sessionId=:sessionId AND userId=:userId";
// prepare query
$stmt = $this->conn->prepare($query);
// bind values
$stmt->bindParam(":sessionId", $this->sessionId);
$stmt->bindParam(":userId", $this->userId);
$stmt->bindParam(":score", $this->score);
return $stmt->execute();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function getAllUsersInSession ()
{
$query = "SELECT DISTINCT userId FROM " . $this->table_name . " WHERE sessionId=:sessionId";
// prepare query
$stmt = $this->conn->prepare($query);
// bind values
$stmt->bindParam(":sessionId", $this->sessionId);
// execute query
$stmt->execute();
$usersIdForSession = array();
// loop through results
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
// retrieve user ids
array_push( $usersIdForSession, $row['userId'] );
}
return $usersIdForSession;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function copy (UserInGameSession $otherParticipation)
{
$this->userId = $otherParticipation->userId;
$this->sessionId = $otherParticipation->sessionId;
$this->score = $otherParticipation->score; // need to call calculateAverages manually
$this->firePrecision = $otherParticipation->firePrecision; // need to call calculateAverages manually
$this->reactionTime = $otherParticipation->reactionTime; // need to call calculateAverages manually
$this->nbEnemyHit = $otherParticipation->nbEnemyHit; // total
$this->nbCivilsHit = $otherParticipation->nbCivilsHit; // total
$this->damageTaken = $otherParticipation->damageTaken; // total
$this->endStatus = $otherParticipation->endStatus; // TODO : mixed ?
$this->avatar = $otherParticipation->avatar;
$this->weapon = $otherParticipation->weapon;
$this->role = $otherParticipation->role; // TODO
if ($this->results != null && $otherParticipation->results != null)
$this->results = $otherParticipation->results;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function add (UserInGameSession $otherParticipation)
{
if ($this->userId != $otherParticipation->userId)
$this->userId = -1;
if ($this->sessionId != $otherParticipation->sessionId)
$this->sessionId = -1;
$this->score += $otherParticipation->score; // need to call calculateAverages manually
$this->firePrecision += $otherParticipation->firePrecision; // need to call calculateAverages manually
$this->reactionTime += $otherParticipation->reactionTime; // need to call calculateAverages manually
$this->nbEnemyHit += $otherParticipation->nbEnemyHit; // total
$this->nbCivilsHit += $otherParticipation->nbCivilsHit; // total
$this->damageTaken += $otherParticipation->damageTaken; // total
$this->endStatus = $this->endStatus; // TODO : mixed ?
if ($this->avatar != $otherParticipation->avatar)
$this->avatar = "various avatars";
if ($this->weapon != $otherParticipation->weapon)
$this->weapon = "various weapons";
$this->role = $this->role; // TODO
$this->addResults($otherParticipation);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function addResults (UserInGameSession $otherParticipation)
{
// add resultsObject debriefs
if ($this->results != null && $otherParticipation->results != null)
{
$resultsObject = UserInGameSessionResults::fromJsonString($this->results);
$otherParticipationResultsObject = UserInGameSessionResults::fromJsonString($otherParticipation->results);
if ($resultsObject != null && $otherParticipationResultsObject)
{
$resultsObject->add($otherParticipationResultsObject);
// update results string
$this->results = json_encode($resultsObject);
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function calculateAverages ($nb)
{
if ($nb > 0)
{
$this->score /= $nb; // average
$this->firePrecision /= $nb; // average
$this->reactionTime /= $nb; // average
$this->nbEnemyHit = $this->nbEnemyHit; // total
$this->nbCivilsHit = $this->nbCivilsHit; // total
$this->damageTaken = $this->damageTaken; // total
// calculate averages for scores of resultsObject
$resultsObject = UserInGameSessionResults::fromJsonString($this->results);
$resultsObject->calculateAverages($nb);
// update results string
$this->results = json_encode($resultsObject);
}
}
}
?>

View File

@@ -0,0 +1,118 @@
<?php
// Single ObjectiveDebrief
class ObjectiveDebrief
{
public $id = "";
public $description = "";
public float $score = 0.0;
public float $weight = 0.0;
public int $completed = 0;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function add (ObjectiveDebrief $otherDebrief)
{
if ($this->id == $otherDebrief->id)
{
// only add stats with same id
$this->score += $otherDebrief->score;
//$this->weight += $otherDebrief->weight; // weight should be the same if ids are the same
if ($this->completed != 1)
$this->completed = $otherDebrief->completed == 1 ? 1 : $this->completed;
}
}
}
// General GameSession debrief (multiple ObjectiveDebrief)
class UserInGameSessionResults
{
public ObjectiveDebrief $civilian;
public ObjectiveDebrief $time;
public ObjectiveDebrief $enemy;
public ObjectiveDebrief $health;
public ObjectiveDebrief $precision;
public ObjectiveDebrief $reactTime;
public ObjectiveDebrief $ammoLimit;
public ObjectiveDebrief $target;
public ObjectiveDebrief $overall;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function __construct ()
{
$this->civilian = new ObjectiveDebrief();
$this->time = new ObjectiveDebrief();
$this->enemy = new ObjectiveDebrief();
$this->health = new ObjectiveDebrief();
$this->precision = new ObjectiveDebrief();
$this->reactTime = new ObjectiveDebrief();
$this->ammoLimit = new ObjectiveDebrief();
$this->target = new ObjectiveDebrief();
$this->overall = new ObjectiveDebrief();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static function fromJsonString (string $jsonResults)
{
$instance = new self();
if (!empty($jsonResults))
$instance->createFromJsonArray( json_decode($jsonResults, true) );
return $instance;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private function createFromJsonArray ($missionDebriefData)
{
// Parse all objectiveDebrief JSON entries in data (civilian, time, enemy, etc.)
foreach ($missionDebriefData as $objectiveDebriefKey => $objectiveDebriefValue)
{
// Create an ObjectiveDebrief variable for each objectiveDebrief JSON entry
$debrief = new ObjectiveDebrief();
foreach ($objectiveDebriefValue as $debriefKey => $debriefValue)
{
// Read all JSON properties and assign them to the ObjectiveDebrief variable
$debrief->{$debriefKey} = $debriefValue;
}
// Assign ObjectiveDebrief variable to the corresponding property in UserInGameSessionResults
$this->{$objectiveDebriefKey} = $debrief;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function add (UserInGameSessionResults $otherParticipationResults)
{
$this->civilian->add($otherParticipationResults->civilian);
$this->time->add($otherParticipationResults->time);
$this->enemy->add($otherParticipationResults->enemy);
$this->health->add($otherParticipationResults->health);
$this->precision->add($otherParticipationResults->precision);
$this->reactTime->add($otherParticipationResults->reactTime);
$this->ammoLimit->add($otherParticipationResults->ammoLimit);
$this->target->add($otherParticipationResults->target);
$this->overall->add($otherParticipationResults->overall);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function calculateAverages ($nb)
{
$this->civilian->score /= $nb;
$this->time->score /= $nb;
$this->enemy->score /= $nb;
$this->health->score /= $nb;
$this->precision->score /= $nb;
$this->reactTime->score /= $nb;
$this->ammoLimit->score /= $nb;
$this->target->score /= $nb;
$this->overall->score /= $nb;
}
}
?>

View File

@@ -0,0 +1,149 @@
<?php
include_once '../objects/db_table_object.php';
include_once '../objects/db_triggerevent.php';
class ReactEvent extends DBTableObject
{
// database connection and table name
//private $conn;
protected $table_name = REACTEVENTS_TABLE_NAME;
protected $array_key = "reactevent";
// object properties
public int $id = -1;
public int $srcEventIndex = -1;
public int $srcEventSessionId = -1;
public int $reactType = -1;
public int $reactMode = -1;
public int $hitUserId = -1;
public string $hitTargetName = "";
public string $hitBoneName = "";
public float $damage = 0.0;
public int $targetKilled = 0;
public float$objectHitLocationX = 0.0;
public float $objectHitLocationY = 0.0;
public string $objectHitTagLocation = "";
public float $hitPrecision = 0.0;
public float $distance = 0.0;
public float $reactTime = 0.0;
public float $timeStamp = 0.0;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function toArray () : array
{
return array (
"id" => (int)$this->id,
"srcEventIndex" => (int)$this->srcEventIndex,
"srcEventSessionId" => (int)$this->srcEventSessionId,
"reactTypeAsInt" => (int)$this->reactType,
"hitUserId" => (int)$this->hitUserId,
"hitTargetName" => $this->hitTargetName ?? "",
"hitBoneName" => $this->hitBoneName ?? "",
"damage" => (float)$this->damage ?? 0.0,
"targetKilled" => ($this->targetKilled ?? 0) == 1 ? true : false,
"objectHitLocationX" => (float)$this->objectHitLocationX ?? 0.0,
"objectHitLocationY" => (float)$this->objectHitLocationY ?? 0.0,
"objectHitTagLocation" => $this->objectHitTagLocation ?? "",
"hitPrecision" => (float)$this->hitPrecision ?? 0.0,
"timestamp" => (float)$this->timeStamp ?? 0.0,
"distance" => (float)$this->distance ?? 0.0,
"reactTime" => (float)$this->reactTime ?? 0.0,
"reactModeAsInt" => (int)$this->reactMode ?? 0
);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function sanitize ()
{
$this->hitUserId=htmlspecialchars(strip_tags($this->hitUserId));
$this->srcEventIndex=htmlspecialchars(strip_tags($this->srcEventIndex));
$this->srcEventSessionId=htmlspecialchars(strip_tags($this->srcEventSessionId));
$this->reactType=htmlspecialchars(strip_tags($this->reactType));
$this->hitTargetName=htmlspecialchars(strip_tags($this->hitTargetName));
$this->hitBoneName=htmlspecialchars(strip_tags($this->hitBoneName));
$this->damage=htmlspecialchars(strip_tags($this->damage));
$this->targetKilled=htmlspecialchars(strip_tags($this->targetKilled));
$this->objectHitLocationX=htmlspecialchars(strip_tags($this->objectHitLocationX));
$this->objectHitLocationY=htmlspecialchars(strip_tags($this->objectHitLocationY));
$this->objectHitTagLocation=htmlspecialchars(strip_tags($this->objectHitTagLocation));
$this->hitPrecision=htmlspecialchars(strip_tags($this->hitPrecision));
$this->distance=htmlspecialchars(strip_tags($this->distance));
$this->reactTime=htmlspecialchars(strip_tags($this->reactTime));
$this->reactMode=htmlspecialchars(strip_tags($this->reactMode));
$this->timeStamp=htmlspecialchars(strip_tags($this->timeStamp));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function record ()
{
$canAddReactEvent = true;
// check that given srcEventId exists, otherwise create it
$query = "SELECT T.indexCount, T.sessionId FROM " . TRIGGEREVENTS_TABLE_NAME . " T WHERE T.indexCount=" . $this->srcEventIndex . " AND T.sessionId=" . $this->srcEventSessionId;
// prepare query
$stmt = $this->conn->prepare($query);
// execute query
$stmt->execute();
if($stmt->rowCount() == 0)
{
$canAddReactEvent = false;
$event = new TriggerEvent($this->conn);
$event->indexCount = $this->srcEventIndex;
$event->sessionId = $this->srcEventSessionId;
$event->srcUserId = 0;
$event->type = 0; // Fire
$event->successful = 1;
$event->timeStamp = $this->timeStamp;
if ($event->recordFromReact())
$canAddReactEvent = true;
}
if ($canAddReactEvent)
{
// query to insert record of new user signup
$query = "INSERT INTO " . $this->table_name . "
SET srcEventIndex=:srcEventIndex, srcEventSessionId=:srcEventSessionId, reactType=:reactType, reactMode=:reactMode, " . "
hitUserId=:hitUserId, hitTargetName=:hitTargetName, hitBoneName=:hitBoneName, damage=:damage, targetKilled=:targetKilled, " . "
objectHitLocationX=:objectHitLocationX, objectHitLocationY=:objectHitLocationY, objectHitTagLocation=:objectHitTagLocation, " . "
hitPrecision=:hitPrecision, distance=:distance, timeStamp=:timeStamp, reactTime=:reactTime";
// prepare query
$stmt = $this->conn->prepare($query);
// sanitize
$this->sanitize();
// bind values
$stmt->bindParam(":hitUserId", $this->hitUserId);
$stmt->bindParam(":srcEventIndex", $this->srcEventIndex);
$stmt->bindParam(":srcEventSessionId", $this->srcEventSessionId);
$stmt->bindParam(":reactType", $this->reactType);
$stmt->bindParam(":hitTargetName", $this->hitTargetName);
$stmt->bindParam(":hitBoneName", $this->hitBoneName);
$stmt->bindParam(":damage", $this->damage);
$stmt->bindParam(":targetKilled", $this->targetKilled);
$stmt->bindParam(":objectHitTagLocation", $this->objectHitTagLocation);
$stmt->bindParam(":objectHitLocationX", $this->objectHitLocationX);
$stmt->bindParam(":objectHitLocationY", $this->objectHitLocationY);
$stmt->bindParam(":hitPrecision", $this->hitPrecision);
$stmt->bindParam(":distance", $this->distance);
$stmt->bindParam(":reactTime", $this->reactTime);
$stmt->bindParam(":reactMode", $this->reactMode);
$stmt->bindParam(":timeStamp", $this->timeStamp);
// execute query
if ($stmt->execute())
{
$this->id = $this->conn->lastInsertId();
return true;
}
return false;
}
}
}
?>

View File

@@ -0,0 +1,11 @@
<?php
include_once '../objects/db_event_type.php';
class ReactEventType extends DBObjectType
{
// database connection and table name
//private $conn;
protected $table_name = REACTEVENTMODES_TABLE_NAME;
//protected $array_key = "type";
}
?>

View File

@@ -0,0 +1,11 @@
<?php
include_once '../objects/db_event_type.php';
class ReactEventType extends DBObjectType
{
// database connection and table name
//private $conn;
protected $table_name = REACTEVENTTYPES_TABLE_NAME;
//protected $array_key = "type";
}
?>

View File

@@ -0,0 +1,200 @@
<?php
include_once "../objects/db_table_object.php";
include_once "../objects/db_participates.php";
class GameSession extends DBTableObject
{
// database connection and table name
//private $conn;
protected $table_name = SESSIONS_TABLE_NAME;
protected $array_key = "session";
// object properties
public int $id = -1;
public $sessionType = 0;
public string $sessionName = "";
public $sessionDate = "";
public string $mapName = "";
public string $scenarioName = "";
public $success = 0;
public float $timeToFinish = 0.0;
public $score = 0;
public int $nbEnemyHit = 0;
public int $nbCivilsHit = 0;
public float $damageTaken = 0.0;
public $replayFileName = "";
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function toArray () : array
{
return array (
"id" => (int)$this->id,
"sessionTypeAsInt" => (int)$this->sessionType ?? 0,
"sessionName" => $this->sessionName ?? "",
"sessionDateAsString" => $this->sessionDate,
"mapName" => $this->mapName ?? "",
"scenarioName" => $this->scenarioName ?? "",
"success" => $this->success == 1 ? true : false,
"timeToFinish" => (float)$this->timeToFinish ?? 0.0,
"score" => (int)$this->score ?? 0,
"nbEnemyHit" => (int)$this->nbEnemyHit ?? 0,
"nbCivilsHit" => (int)$this->nbCivilsHit ?? 0,
"damageTaken" => (float)$this->damageTaken ?? 0.0,
"replayFileName" => $this->replayFileName ?? ""
);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static function withRow ($db, array $row)
{
$instance = new self($db);
$instance->readRow($row);
return $instance;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function readRow (array $row)
{
$this->id = (int)$row['id'];
$this->sessionType = $row['sessionType'];
$this->sessionName = $row['sessionName'];
$this->sessionDate = $row['sessionDate'];
$this->mapName = $row['mapName'];
$this->scenarioName = $row['scenarioName'];
$this->success = $row['success'];
$this->timeToFinish = (float)$row['timeToFinish'];
$this->score = $row['score'];
$this->nbEnemyHit = (int)$row['nbEnemyHit'];
$this->nbCivilsHit = (int)$row['nbCivilsHit'];
$this->damageTaken = (float)$row['damageTaken'];
$this->replayFileName = $row['replayFileName'];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function load ()
{
// select all query with user inputed username and password
$query = "SELECT * FROM " . $this->table_name . " WHERE id='" . $this->id . "'";
// prepare query statement
$stmt = $this->conn->prepare($query);
// execute query
$stmt->execute();
if($stmt->rowCount() > 0)
{
// get retrieved row
$row = $stmt->fetch(PDO::FETCH_ASSOC);
// retrieve user values
$this->readRow($row);
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function sanitize ()
{
$this->sessionType=htmlspecialchars(strip_tags($this->sessionType));
$this->sessionName=htmlspecialchars(strip_tags($this->sessionName));
$this->sessionDate=htmlspecialchars(strip_tags($this->sessionDate));
$this->mapName=htmlspecialchars(strip_tags($this->mapName));
$this->scenarioName=htmlspecialchars(strip_tags($this->scenarioName));
$this->replayFileName=htmlspecialchars(strip_tags($this->replayFileName));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function sanitize_stop()
{
$this->success=htmlspecialchars(strip_tags($this->success));
$this->timeToFinish=htmlspecialchars(strip_tags($this->timeToFinish));
$this->score=htmlspecialchars(strip_tags($this->score));
//$this->id=htmlspecialchars(strip_tags($this->id));
//$this->nbEnemyHit=htmlspecialchars(strip_tags($this->nbEnemyHit));
//$this->nbCivilsHit=htmlspecialchars(strip_tags($this->nbCivilsHit));
//$this->damageTaken=htmlspecialchars(strip_tags($this->damageTaken));
//$this->replayFileName=htmlspecialchars(strip_tags($this->replayFileName));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function start ()
{
// query to insert record of new user signup
$query = "INSERT INTO " . $this->table_name . "
SET sessionType=:sessionType, sessionName=:sessionName, sessionDate=:sessionDate, mapName=:mapName, scenarioName=:scenarioName, " . "
replayFileName=:replayFileName";
// prepare query
$stmt = $this->conn->prepare($query);
// sanitize
$this->sanitize();
// bind values
$stmt->bindParam(":sessionType", $this->sessionType);
$stmt->bindParam(":sessionName", $this->sessionName);
$stmt->bindParam(":sessionDate", $this->sessionDate);
$stmt->bindParam(":mapName", $this->mapName);
$stmt->bindParam(":scenarioName", $this->scenarioName);
$stmt->bindParam(":replayFileName", $this->replayFileName);
// execute query
if($stmt->execute())
{
$this->id = $this->conn->lastInsertId();
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function stop ()
{
//if (this->load())
{
$query = "UPDATE " . $this->table_name . "
SET success=:success, timeToFinish=:timeToFinish, score=:score, " . "
nbEnemyHit=(SELECT COUNT(DISTINCT Re.srcEventIndex, Re.hitTargetName) FROM " . REACTEVENTS_TABLE_NAME . " Re WHERE Re.srcEventSessionId=:id AND Re.reactType=0), " . "
nbCivilsHit=(SELECT COUNT(DISTINCT Rc.srcEventIndex, Rc.hitTargetName) FROM " . REACTEVENTS_TABLE_NAME . " Rc WHERE Rc.srcEventSessionId=:id AND Rc.reactType=1) " . "
WHERE id=:id";
// prepare query
$stmt = $this->conn->prepare($query);
// sanitize
$this->sanitize_stop();
// bind values
$stmt->bindParam(":id", $this->id);
$stmt->bindParam(":success", $this->success);
$stmt->bindParam(":timeToFinish", $this->timeToFinish);
$stmt->bindParam(":score", $this->score);
//$stmt->bindParam(":nbEnemyHit", $this->nbEnemyHit);
//$stmt->bindParam(":nbCivilsHit", $this->nbCivilsHit);
//$stmt->bindParam(":damageTaken", $this->damageTaken);
//$stmt->bindParam(":replayFileName", $this->replayFileName);
// execute query
return $stmt->execute();
}
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function getUsers ()
{
$query = "SELECT U.* FROM " . USERS_TABLE_NAME . " U, " . PARTICIPATES_TABLE_NAME . " P WHERE U.id=P.userId AND P.sessionId = '" . $this->id . "'";
// prepare query
$stmt = $this->conn->prepare($query);
// execute query
return $stmt->execute();
}
}
?>

View File

@@ -0,0 +1,11 @@
<?php
include_once '../objects/db_event_type.php';
class SessionType extends DBObjectType
{
// database connection and table name
//private $conn;
protected $table_name = SESSIONTYPES_TABLE_NAME;
//protected $array_key = "type";
}
?>

View File

@@ -0,0 +1,42 @@
<?php
include_once '../config/constants.php';
class DBTableObject
{
// database connection and table name
protected $conn;
protected $table_name = "";
protected $array_key = "";
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// constructor with $db as database connection
public function __construct($db)
{
$this->conn = $db;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function toArray () : array
{
return array();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function getResultArray ($status, $message) : array
{
return array (
"status" => $status,
"message" => $message,
$this->array_key => $this->toArray()
);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function executeQuery ($query)
{
$stmt = $this->conn->prepare($query);
$stmt->execute();
return $stmt;
}
}
?>

View File

@@ -0,0 +1,96 @@
<?php
include_once '../objects/db_table_object.php';
class TriggerEvent extends DBTableObject
{
// database connection and table name
//private $conn;
protected $table_name = TRIGGEREVENTS_TABLE_NAME;
protected $array_key = "triggerevent";
// object properties
public int $indexCount = -1;
public int $srcUserId = -1;
public int $sessionId = -1;
public int $type = -1;
public $successful = 0;
public float $timeStamp = 0.0;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function toArray () : array
{
return array (
"indexCount" => (int)$this->indexCount,
"sessionId" => (int)$this->sessionId,
"srcUserId" => (int)$this->srcUserId,
"typeAsInt" => (int)$this->type,
"timeStamp" => (float)$this->timeStamp,
"successful" => $this->successful == 1 ? true : false
);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function sanitize ()
{
$this->indexCount=htmlspecialchars(strip_tags($this->indexCount));
$this->sessionId=htmlspecialchars(strip_tags($this->sessionId));
$this->srcUserId=htmlspecialchars(strip_tags($this->srcUserId));
$this->timeStamp=htmlspecialchars(strip_tags($this->timeStamp));
$this->successful=htmlspecialchars(strip_tags($this->successful));
$this->type=htmlspecialchars(strip_tags($this->type));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function record ()
{
// query to insert record of new user signup
$query = "INSERT INTO " . $this->table_name . "
SET sessionId=:sessionId, indexCount=:indexCount, srcUserId=:srcUserId, type=:type, timeStamp=:timeStamp, successful=:successful
ON DUPLICATE KEY UPDATE srcUserId=:srcUserId, type=:type, timeStamp=:timeStamp, successful=:successful";
// prepare query
$stmt = $this->conn->prepare($query);
// sanitize
$this->sanitize();
// bind values
$stmt->bindParam(":indexCount", $this->indexCount);
$stmt->bindParam(":timeStamp", $this->timeStamp);
$stmt->bindParam(":successful", $this->successful);
$stmt->bindParam(":sessionId", $this->sessionId);
$stmt->bindParam(":srcUserId", $this->srcUserId);
$stmt->bindParam(":type", $this->type);
// execute query
return $stmt->execute();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function recordFromReact ()
{
// query to insert record of new user signup
$query = "INSERT INTO " . $this->table_name . "
SET sessionId=:sessionId, indexCount=:indexCount, srcUserId=:srcUserId, type=:type, timeStamp=:timeStamp, successful=:successful
ON DUPLICATE KEY UPDATE indexCount=:indexCount";
// prepare query
$stmt = $this->conn->prepare($query);
// sanitize
$this->sanitize();
// bind values
$stmt->bindParam(":indexCount", $this->indexCount);
$stmt->bindParam(":timeStamp", $this->timeStamp);
$stmt->bindParam(":successful", $this->successful);
$stmt->bindParam(":sessionId", $this->sessionId);
$stmt->bindParam(":srcUserId", $this->srcUserId);
$stmt->bindParam(":type", $this->type);
// execute query
return $stmt->execute();
}
}
?>

View File

@@ -0,0 +1,11 @@
<?php
include_once '../objects/db_event_type.php';
class TriggerEventType extends DBObjectType
{
// database connection and table name
//private $conn;
protected $table_name = TRIGGEREVENTTYPES_TABLE_NAME;
//protected $array_key = "type";
}
?>

View File

@@ -0,0 +1,300 @@
<?php
include_once '../objects/db_table_object.php';
class User extends DBTableObject
{
// database connection and table name
//private $conn;
protected $table_name = USERS_TABLE_NAME;
protected $array_key = "user";
// object properties
public int $id = -1;
public string $username = "";
public string $password = "";
public string $firstName = "";
public string $lastName = "";
public $created = "";
public int $leftHanded = 0;
public int $maleGender = 1;
public string $charSkinAssetName = "";
public string $weaponAssetName = "";
public $lastConnection = "";
public float $avgPrecision = 0.0;
public float $avgReaction = 0.0;
public float $avgFault = 0.0;
public float $avgRapidity = 0.0;
public int $size = 0;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static function withRow ($db, array $row)
{
$instance = new self($db);
$instance->readRow($row);
return $instance;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function readRow (array $row)
{
$this->id = (int)$row['id'];
$this->username = $row['username'];
$this->firstName = $row['firstName'];
$this->lastName = $row['lastName'];
$this->leftHanded = $row['leftHanded'];
$this->maleGender = $row['maleGender'];
$this->charSkinAssetName = $row['charSkinAssetName'];
$this->weaponAssetName = $row['weaponAssetName'];
$this->lastConnection = date('Y-m-d H:i:s');
$this->avgPrecision = (float)$row['avgPrecision'] ?? 0.0;
$this->avgReaction = (float)$row['avgReaction'] ?? 0.0;
$this->avgFault = (float)$row['avgFault'] ?? 0.0;
$this->avgRapidity = (float)$row['avgRapidity'] ?? 0.0;
$this->size = (int)$row['size'];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function toArray () : array
{
return array (
"id" => (int)$this->id,
"username" => $this->username ?? "",
"firstName" => $this->firstName ?? "",
"lastName" => $this->lastName ?? "",
"leftHanded" => ($this->leftHanded ?? 0) == 1 ? true : false,
"maleGender" => ($this->maleGender ?? 1) == 1 ? true : false,
"charSkinAssetName" => $this->charSkinAssetName ?? "",
"weaponAssetName" => $this->weaponAssetName ?? "",
"lastConnection" => $this->lastConnection,
"avgPrecision" => (float)$this->avgPrecision ?? 0.0,
"avgReaction" => (float)$this->avgReaction ?? 0.0,
"avgFault" => (float)$this->avgFault ?? 0.0,
"avgRapidity" => (float)$this->avgRapidity ?? 0.0,
"size" => (int)$this->size
);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function sanitize ()
{
$this->username=htmlspecialchars(strip_tags($this->username));
$this->password=htmlspecialchars(strip_tags($this->password));
$this->created=htmlspecialchars(strip_tags($this->created));
$this->lastConnection=htmlspecialchars(strip_tags($this->lastConnection));
//$this->firstName=htmlspecialchars(strip_tags($this->firstName));
//$this->lastName=htmlspecialchars(strip_tags($this->lastName));
//$this->leftHanded=htmlspecialchars(strip_tags($this->leftHanded));
//$this->maleGender=htmlspecialchars(strip_tags($this->maleGender));
//$this->charSkinAssetName=htmlspecialchars(strip_tags($this->charSkinAssetName));
//$this->weaponAssetName=htmlspecialchars(strip_tags($this->weaponAssetName));
//$this->avgPrecision=htmlspecialchars(strip_tags($this->avgPrecision));
//$this->avgReaction=htmlspecialchars(strip_tags($this->avgReaction));
//$this->avgFault=htmlspecialchars(strip_tags($this->avgFault));
//$this->avgRapidity=htmlspecialchars(strip_tags($this->avgRapidity));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function sanitize_update ()
{
//$this->username=htmlspecialchars(strip_tags($this->username));
//$this->password=htmlspecialchars(strip_tags($this->password));
//$this->avgPrecision=htmlspecialchars(strip_tags($this->avgPrecision));
//$this->avgReaction=htmlspecialchars(strip_tags($this->avgReaction));
//$this->avgFault=htmlspecialchars(strip_tags($this->avgFault));
//$this->avgRapidity=htmlspecialchars(strip_tags($this->avgRapidity));
$this->firstName=htmlspecialchars(strip_tags($this->firstName));
$this->lastName=htmlspecialchars(strip_tags($this->lastName));
$this->leftHanded=htmlspecialchars(strip_tags($this->leftHanded));
$this->maleGender=htmlspecialchars(strip_tags($this->maleGender));
$this->charSkinAssetName=htmlspecialchars(strip_tags($this->charSkinAssetName));
$this->weaponAssetName=htmlspecialchars(strip_tags($this->weaponAssetName));
$this->lastConnection=htmlspecialchars(strip_tags($this->lastConnection));
$this->size=htmlspecialchars(strip_tags($this->size));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function load ()
{
// select all query with user inputed username and password
$query = "SELECT * FROM " . $this->table_name . " WHERE id='" . $this->id . "'";
// prepare query statement
$stmt = $this->conn->prepare($query);
// execute query
$stmt->execute();
if($stmt->rowCount() > 0)
{
// get retrieved row
$row = $stmt->fetch(PDO::FETCH_ASSOC);
// retrieve user values
$this->readRow($row);
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//user signup method
function signup ()
{
if ($this->isAlreadyExist()) return false;
// query to insert record of new user signup
$query = "INSERT INTO " . $this->table_name . " SET username=:username, password=:password, created=:created, lastConnection=:lastConnection";
// prepare query
$stmt = $this->conn->prepare($query);
// sanitize
$this->sanitize();
// bind values
$stmt->bindParam(":username", $this->username);
$stmt->bindParam(":password", $this->password);
$stmt->bindParam(":created", $this->created);
$stmt->bindParam(":lastConnection", $this->lastConnection);
//$stmt->bindParam(":firstName", $this->firstName);
//$stmt->bindParam(":lastName", $this->lastName);
//$stmt->bindParam(":leftHanded", $this->leftHanded);
//$stmt->bindParam(":maleGender", $this->maleGender);
//$stmt->bindParam(":charSkinAssetName", $this->charSkinAssetName);
//$stmt->bindParam(":weaponAssetName", $this->weaponAssetName);
//$stmt->bindParam(":avgPrecision", $this->avgPrecision);
//$stmt->bindParam(":avgReaction", $this->avgReaction);
//$stmt->bindParam(":avgFault", $this->avgFault);
//$stmt->bindParam(":avgRapidity", $this->avgRapidity);
// execute query
if ($stmt->execute())
{
$this->id = $this->conn->lastInsertId();
return $this->load();
}
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// login user method
function login ()
{
// select all query with user inputed username and password
$query = "SELECT * FROM " . $this->table_name . " WHERE BINARY username='".$this->username."' AND BINARY password='".$this->password."'";
// prepare query statement
$stmt = $this->conn->prepare($query);
// execute query
$stmt->execute();
return $stmt;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Update user infos
function refreshConnectionDate ()
{
// select all query with user inputed username and password
$query = "UPDATE " . $this->table_name . " SET lastConnection = '" . date('Y-m-d H:i:s') . "' WHERE id='" . $this->id . "'";
// prepare query statement
$stmt = $this->conn->prepare($query);
// execute query
return $stmt->execute();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Notify if User with given username Already exists during SignUp
function isAlreadyExist ()
{
$query = "SELECT * FROM " . $this->table_name . " WHERE BINARY username='".$this->username."'";
// prepare query statement
$stmt = $this->conn->prepare($query);
// execute query
$stmt->execute();
return ($stmt->rowCount() > 0);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Update user infos
function update ()
{
$query = "UPDATE " . $this->table_name . "
SET firstName=:firstName, lastName=:lastName, leftHanded=:leftHanded, size=:size, maleGender=:maleGender, charSkinAssetName=:charSkinAssetName, " . "
weaponAssetName=:weaponAssetName, lastConnection=:lastConnection " . "
WHERE id=".$this->id;
// prepare query
$stmt = $this->conn->prepare($query);
// sanitize
$this->sanitize_update();
// bind values
//$stmt->bindParam(":username", $this->username);
//$stmt->bindParam(":password", $this->password);
//$stmt->bindParam(":avgPrecision", $this->avgPrecision);
//$stmt->bindParam(":avgReaction", $this->avgReaction);
//$stmt->bindParam(":avgFault", $this->avgFault);
//$stmt->bindParam(":avgRapidity", $this->avgRapidity);
$stmt->bindParam(":firstName", $this->firstName);
$stmt->bindParam(":lastName", $this->lastName);
$stmt->bindParam(":leftHanded", $this->leftHanded);
$stmt->bindParam(":maleGender", $this->maleGender);
$stmt->bindParam(":charSkinAssetName", $this->charSkinAssetName);
$stmt->bindParam(":weaponAssetName", $this->weaponAssetName);
$stmt->bindParam(":lastConnection", $this->lastConnection);
$stmt->bindParam(":size", $this->size);
// execute query
return $stmt->execute();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//user reset password methods
function resetPassword ()
{
if ($this->id < 1)
{
// find userId for this username
$query = "SELECT id FROM " . $this->table_name . " WHERE BINARY username='".$this->username."'";
// prepare query
$stmt = $this->conn->prepare($query);
// execute query
$stmt->execute();
if ($stmt->rowCount() != 1)
{
// no user found for this username (or multiple users, but this should not happen)
return false;
}
else
{
// get retrieved row
$row = $stmt->fetch(PDO::FETCH_ASSOC);
// retrieve user values
$this->id = (int)$row['id'];
}
}
// now that we have an id, run the update method
$query = "UPDATE " . $this->table_name . " SET password=:password WHERE id=".$this->id;
// prepare query
$stmt = $this->conn->prepare($query);
// sanitize
$this->password=htmlspecialchars(strip_tags($this->password));
// bind values
$stmt->bindParam(":password", $this->password);
// execute query
$stmt->execute();
// load user after password update
return $this->load();
}
}

View File

@@ -0,0 +1,11 @@
<?php
include_once '../objects/db_event_type.php';
class UserRole extends DBObjectType
{
// database connection and table name
//private $conn;
protected $table_name = USERROLES_TABLE_NAME;
//protected $array_key = "type";
}
?>

View File

@@ -0,0 +1,11 @@
<?php
include_once '../objects/db_event_type.php';
class SessionType extends DBObjectType
{
// database connection and table name
//private $conn;
protected $table_name = USERSTATUS_TABLE_NAME;
protected $array_key = "status";
}
?>

View File

@@ -0,0 +1,216 @@
<?php
class SessionDebriefRow
{
public $sessionId = -1;
public int $sessionTypeId = -1;
public $sessionType = "";
public $sessionName = "";
public $sessionDate = "";
public $mapName = "";
public $scenarioName = "";
public bool $sessionSuccessful = false;
public float $sessionDuration = 0.0;
public int $triggerTypeId = -1;
public $triggerType = "";
public int $shooterId = -1;
public $shooterName = "";
public int $shooterRoleId = -1;
public $shooterRole = "";
public int $shotIndex = -1;
public int $reactId = -1;
public int $reactModeId = -1;
public $reactMode = "";
public int $reactTypeId = -1;
public $reactType = "";
public int $targetUserId = -1;
public $targetUserName = "";
public int $targetRoleId = -1;
public $targetRole = "";
public $targetName = "";
public $targetBoneName = "";
public bool $targetKilled = false;
public float $hitLocationX = 0.0;
public float $hitLocationY = 0.0;
public $hitLocationTag = "";
public float $hitPrecision = 0.0;
public float $hitTargetDistance = 0.0;
public float $reactTime = 0.0;
public float $timeStamp = 0.0;
public int $nbHit = 0;
public int $nbKilled = 0;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static function withRow (array $row)
{
$instance = new self();
$instance->readRow($row);
return $instance;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function readRow (array $row)
{
$this->sessionId = $row['SessionId'];
$this->sessionTypeId = $row['SessionTypeId'];
$this->sessionType = $row['SessionType'];
$this->sessionName = $row['SessionName'];
$this->sessionDate = $row['SessionDate'];
$this->mapName = $row['MapName'];
$this->scenarioName = $row['ScenarioName'];
$this->sessionSuccessful = $row['SessionSuccessful'] == 1;
$this->sessionDuration = (float)$row['SessionDuration'];
$this->triggerTypeId = (int)$row['TriggerTypeId'];
$this->triggerType = $row['TriggerType'];
$this->shooterId = (int)$row['ShooterId'];
$this->shooterName = $row['ShooterName'];
$this->shooterRoleId = (int)$row['ShooterRoleId'];
$this->shooterRole = $row['ShooterRole'];
$this->shotIndex = (int)$row['ShotIndex'];
$this->reactId = (int)$row['ReactId'];
$this->reactModeId = (int)$row['ReactModeId'];
$this->reactMode = $row['ReactMode'];
$this->reactTypeId = (int)$row['ReactTypeId'];
$this->reactType = $row['ReactType'];
$this->targetUserId = (int)$row['TargetUserId'];
$this->targetUserName = $row['TargetUserName'];
$this->targetRoleId = (int)$row['TargetRoleId'];
$this->targetRole = $row['TargetRole'];
$this->targetName = $row['TargetName'];
$this->targetBoneName = $row['TargetBoneName'];
$this->targetKilled = $row['TargetKilled'] == 1;
$this->hitLocationX = (float)$row['HitLocationX'];
$this->hitLocationY = (float)$row['HitLocationY'];
$this->hitLocationTag = $row['HitLocationTag'];
$this->hitPrecision = (float)$row['HitPrecision'];
$this->hitTargetDistance = (float)$row['HitTargetDistance'];
$this->reactTime = (float)$row['ReactionTime'];
$this->timeStamp = (float)$row['TimeStamp'];
$this->nbHit = (int)$row['NbHit'];
$this->nbKilled = (int)$row['NbKilled'];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function toArray () : array
{
return array (
"SessionId" => (int)$this->sessionId,
"SessionTypeId" => (int)$this->sessionTypeId,
"SessionTypeAsString" => $this->sessionType,
"SessionName" => $this->sessionName,
"SessionDateAsString" => $this->sessionDate,
"MapName" => $this->mapName,
"ScenarioName" => $this->scenarioName,
"SessionSuccessful" => $this->sessionSuccessful,
"SessionDuration" => (float)$this->sessionDuration,
"TriggerTypeId" => (int)$this->triggerTypeId,
"TriggerTypeAsString" => $this->triggerType,
"ShooterId" => (int)$this->shooterId,
"ShooterName" => $this->shooterName,
"ShooterRoleId" => (int)$this->shooterRoleId,
"ShooterRoleAsString" => $this->shooterRole,
"ShotIndex" => (int)$this->shotIndex,
"ReactId" => (int)$this->reactId,
"ReactModeId" => (int)$this->reactModeId,
"ReactModeAsString" => $this->reactMode,
"ReactTypeId" => (int)$this->reactTypeId,
"ReactTypeAsString" => $this->reactType,
"TargetUserId" => (int)$this->targetUserId,
"TargetUserName" => $this->targetUserName,
"TargetRoleId" => (int)$this->targetRoleId,
"TargetRoleAsString" => $this->targetRole,
"TargetName" => $this->targetName,
"TargetBoneName" => $this->targetBoneName,
"TargetKilled" => $this->targetKilled,
"HitLocationX" => (float)$this->hitLocationX,
"HitLocationY" => (float)$this->hitLocationY,
"HitLocationTag" => $this->hitLocationTag,
"HitPrecision" => (float)$this->hitPrecision,
"HitTargetDistance" => (float)$this->hitTargetDistance,
"ReactionTime" => (float)$this->reactTime,
"TimeStamp" => (float)$this->timeStamp,
"NbHit" => (int)$this->nbHit,
"NbKilled" => (int)$this->nbKilled
);
}
}
class SessionDebriefRowWithTotals
{
public SessionDebriefRow $sessionRow;
public int $nbFiredShotsByUser = 0;
public int $nbEnemyHitsByUser = 0;
public int $nbCivilHitsByUser = 0;
public int $nbPoliceHitsByUser = 0;
public int $nbMissedShotsByUser = 0;
//public int $nbFiredShotsByIA = 0;
public int $nbEnemyHitsByIA = 0;
public int $nbCivilHitsByIA = 0;
public int $nbPoliceHitsByIA = 0;
//public int $nbMissedShotsByIA = 0;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static function withRow (array $row)
{
$instance = new self();
$instance->readRow($row);
return $instance;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function readRow (array $row)
{
$this->sessionRow = SessionDebriefRow::withRow($row);
if ($row['ReactTypeId'] == -1)
$this->nbMissedShotsByUser = (int)$row['NbShotsOfType'];
else if ($row['ShooterRoleId'] == 0)
{
$this->nbFiredShotsByUser = (int)$row['NbShotsOfType'];
switch ($row['ReactTypeId'])
{
case 0 : $this->nbEnemyHitsByUser = (int)$row['NbShotsOfType']; break;
case 1 : $this->nbCivilHitsByUser = (int)$row['NbShotsOfType']; break;
case 2 : $this->nbPoliceHitsByUser = (int)$row['NbShotsOfType']; break;
}
}
else if ($row['ShooterRoleId'] == 3) // IA
{
//$this->nbFiredShotsByIA = (int)$row['NbShotsOfType'];
switch ($row['ReactTypeId'])
{
case 0 : $this->nbEnemyHitsByIA = (int)$row['NbShotsOfType']; break;
case 1 : $this->nbCivilHitsByIA = (int)$row['NbShotsOfType']; break;
case 2 : $this->nbPoliceHitsByIA = (int)$row['NbShotsOfType']; break;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function toArray () : array
{
return array (
"session" => $this->sessionRow->toArray(),
"NbFiredShotsByUser" => (int)$this->nbFiredShotsByUser,
"NbEnemyHitsByUser" => (int)$this->nbEnemyHitsByUser,
"NbCivilHitsByUser" => (int)$this->nbCivilHitsByUser,
"NbPoliceHitsByUser" => (int)$this->nbPoliceHitsByUser,
"NbMissedShotsByUser" => (int)$this->nbMissedShotsByUser,
//"NbFiredShotsByIA" => (int)$this->nbFiredShotsByIA,
"NbEnemyHitsByIA" => (int)$this->nbEnemyHitsByIA,
"NbCivilHitsByIA" => (int)$this->nbCivilHitsByIA,
"NbPoliceHitsByIA" => (int)$this->nbPoliceHitsByIA
//"NbMissedShotsByIA" => (int)$this->nbMissedShotsByIA
);
}
}
?>

View File

@@ -0,0 +1,747 @@
<?php
//include_once "../objects/db_table_object.php";
include_once '../objects/db_session.php';
include_once '../objects/db_user.php';
include_once '../objects/db_view_sessiondebrief_row.php';
include_once '../objects/stats_user_globals.php';
//include_once '../objects/stats_user_in_session_row.php';
class StatsObject extends DBTableObject
{
// database connection and table name
//protected $conn;
protected $array_key = "stats";
protected $elements = array();
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
protected $excludeCalibrationSessionsFromStats = true;
protected function getCalibrationSessionsConstraint ($sessionsTableIndex="SD") : string
{
return $this->excludeCalibrationSessionsFromStats == true ? " AND " . $sessionsTableIndex . ".ScenarioName NOT LIKE '%Calibration%'" : "";
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
protected $minimumSessionDuration = 10;
protected function getSessionDurationConstraint ($sessionsTableIndex="SD", $allowZero=false) : string
{
return $this->minimumSessionDuration > 0 ? " AND (" . $sessionsTableIndex . ".timeToFinish > " . $this->minimumSessionDuration . ($allowZero ? " OR " . $sessionsTableIndex . ".timeToFinish = 0" : "") . ")" : "";
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
protected function getSessionsWithUserConstraint ($userId) : string
{
return $userId > 0 ? "SELECT DISTINCT UP.SessionId FROM " . PARTICIPATES_TABLE_NAME . " UP WHERE UP.userId=" . $userId : "";
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function toArray () : array
{
return $this->elements;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get users who took place in given session
public function fixDurations ()
{
$query = "SELECT S.id AS SessionId FROM " . SESSIONS_TABLE_NAME . " S, " . TRIGGEREVENTS_TABLE_NAME . " TE WHERE S.timeToFinish=0 AND S.id=TE.sessionId";
// prepare and execute query
$stmt = $this->conn->prepare($query);
$stmt->execute();
$nb = 0;
// get max time for trigger events in these sessions
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$subQuery = "SELECT COALESCE(MAX(TE.timeStamp),0) AS LastTriggerEvent FROM " . TRIGGEREVENTS_TABLE_NAME . " TE WHERE TE.sessionId=" . $row['SessionId'];
// prepare and execute query
$subStmt = $this->conn->prepare($subQuery);
$subStmt->execute();
while ($subRow = $subStmt->fetch(PDO::FETCH_ASSOC)) // should be only 1 row
{
if ($subRow['LastTriggerEvent'] != 0) // should always be true
{
$subQuery = "UPDATE " . SESSIONS_TABLE_NAME . " SET timeToFinish=" . $subRow['LastTriggerEvent'] . " WHERE id=" . $row['SessionId'];
// prepare and execute query
$subStmt = $this->conn->prepare($subQuery);
$subStmt->execute();
$nb++;
}
}
}
return $nb;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get users who took place in given session
public function getRawUsers ($sessionId)
{
// Check if we are looking for a specific session
$sessionConstraint = $sessionId > 0 ? " AND P.sessionId=" . $sessionId : "";
$query = "SELECT DISTINCT U.* FROM " . USERS_TABLE_NAME . " U LEFT JOIN " . PARTICIPATES_TABLE_NAME . " P ON U.id = P.userId " .
"LEFT JOIN " . SESSIONS_TABLE_NAME . " SD ON P.sessionId=SD.id " .
"WHERE U.id > 0" . $sessionConstraint . $this->getSessionDurationConstraint("SD");
//$query = "SELECT DISTINCT U.* FROM " . USERS_TABLE_NAME . " U, " . PARTICIPATES_TABLE_NAME . " P WHERE U.id = P.userId AND U.id > 0" . $sessionConstraint;
// prepare and execute query
$stmt = $this->conn->prepare($query);
$stmt->execute();
return $stmt;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get users who took place in given session
public function getUsersInSession ($sessionId)
{
// Check if we are looking for a specific session
$stmt = $this->getRawUsers($sessionId);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
//$sess = new GameSession($this->conn);
//$sess->readRow($row);
$user = User::withRow($this->conn, $row);
array_push( $this->elements, $user->toArray() );
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get sessions of given type that given user has taken part in
public function getRawSessions ($userId=-1, $typeId=-1)
{
// Check if we are looking for a specific user and/or type of session
$userConstraint = $userId > 0 ? " AND P.userId=" . $userId : "";
$typeConstraint = $typeId >= 0 ? " AND SD.sessionType=" . $typeId : "";
// Order results from newest to oldest session
$orderConstraint = " ORDER BY SD.id DESC";
//$query = "SELECT DISTINCT S.* FROM " . SESSIONS_TABLE_NAME . " S LEFT JOIN " . PARTICIPATES_TABLE_NAME . " P ON S.id = P.sessionId WHERE 1 " .
$query = "SELECT DISTINCT SD.* FROM " . SESSIONS_TABLE_NAME . " SD, " . PARTICIPATES_TABLE_NAME . " P WHERE SD.id = P.sessionId " .
$this->getCalibrationSessionsConstraint("SD") . $this->getSessionDurationConstraint("SD") . $userConstraint . $typeConstraint . $orderConstraint;
// prepare and execute query
$stmt = $this->conn->prepare($query);
$stmt->execute();
return $stmt;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get sessions that given user has taken part in
public function getSessionsForUser ($userId, $typeId=-1)
{
// Check if we are looking for a specific user and/or session
$stmt = $this->getRawSessions($userId, $typeId);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
//$sess = new GameSession($this->conn);
//$sess->readRow($row);
$sess = GameSession::withRow($this->conn, $row);
array_push( $this->elements, $sess->toArray() );
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// debrief mission : get stats for given session
public function getRawStatsForSession ($sessionId, $userId, $fromUser=-1)
{
$sessionStats = array();
// first create expected rows for results, so that every user will get stats (even if user didn't fire or received any shot)
if ($sessionId > 0 && $userId > 0)
{
// we want stats for a specific user in a specific session
// => we only need to create one default row, just in case user didn't fire or received any shot
$defaultRow = new UserStatsInSessionRow();
$defaultRow->createSessionAndUser($this->conn, $sessionId, $userId);
array_push( $sessionStats, $defaultRow );
}
else if ($userId == -1)
{
// we want stats for all users in a specific session
// => we need to create one default row for each user
$stmt_usersInSession = $this->getRawUsers($sessionId);
while ($row = $stmt_usersInSession->fetch(PDO::FETCH_ASSOC))
{
$defaultRow = new UserStatsInSessionRow();
$defaultRow->createSessionAndUser($this->conn, $sessionId, $row['id']);
array_push( $sessionStats, $defaultRow );
}
}
else if ($sessionId == -1)
{
// we want stats for a specific user in all sessions he took place in
// => we need to create one default row for each user
$stmt_sessionsForUser = $this->getRawSessions($userId);
while ($row = $stmt_sessionsForUser->fetch(PDO::FETCH_ASSOC))
{
$defaultRow = new UserStatsInSessionRow();
$defaultRow->createSessionAndUser($this->conn, $row['id'], $userId);
array_push( $sessionStats, $defaultRow );
}
}
else
{
// both $sessionId and $userId are set to -1
// => do nothing, this will (should) not happen
}
// Get fired shots
$stmt_firedShots = $this->getShotsFiredByUser($sessionId, $userId, $fromUser);
while ($row = $stmt_firedShots->fetch(PDO::FETCH_ASSOC))
{
// Only create stats row for shooters with id > 0
if ((int)$row['UserId'] > 0)
{
$statsRow = $this->findStats( $sessionStats, (int)$row['UserId'], (int)$row['SessionId'] );
if ($statsRow == null)
{
$statsRow = UserStatsInSessionRow::withRow($this->conn, $row);
$statsRow->setFiredShots($row);
array_push( $sessionStats, $statsRow );
}
else
$statsRow->setFiredShots($row);
}
}
// Get received shots
$stmt_receivedShots = $this->getReceivedHitsForUser($sessionId, $userId, $fromUser);
while ($row = $stmt_receivedShots->fetch(PDO::FETCH_ASSOC))
{
// Only create stats row for hit users with id > 0
if ((int)$row['UserId'] > 0)
{
$statsRow = $this->findStats ( $sessionStats, (int)$row['UserId'], (int)$row['SessionId'] );
if ($statsRow == null)
{
$statsRow = UserStatsInSessionRow::withRow($this->conn, $row);
$statsRow->setReceivedHits($row);
array_push( $sessionStats, $statsRow );
}
else
$statsRow->setReceivedHits($row);
}
}
// Get average precision and reaction time
$stmt_averages = $this->getPrecisionAndReactionTimeForUser($sessionId, $userId, $fromUser);
while ($row = $stmt_averages->fetch(PDO::FETCH_ASSOC))
{
// Only create stats row for hit users with id > 0
if ((int)$row['UserId'] > 0)
{
$statsRow = $this->findStats ( $sessionStats, (int)$row['UserId'], (int)$row['SessionId'] );
if ($statsRow == null)
{
$statsRow = UserStatsInSessionRow::withRow($this->conn, $row);
$statsRow->setPrecisionAndReactionTime($row);
array_push( $sessionStats, $statsRow );
}
else
$statsRow->setPrecisionAndReactionTime($row);
}
}
// Get total of targets killed in the session
$stmt_targetKilled = $this->getTargetKilledInSession($sessionId);
while ($row = $stmt_targetKilled->fetch(PDO::FETCH_ASSOC))
{
// Add totals stats to all rows of the same session
foreach ($sessionStats as $statsRow)
{
if ($statsRow->sessionId == (int)$row['SessionId'])
$statsRow->setTotalKills($row);
}
}
return $sessionStats;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// debrief mission : get stats for given session
public function getStatsForSession ($sessionId, $userId, $fromUser=-1)
{
$sessionStats = $this->getRawStatsForSession($sessionId, $userId, $fromUser);
// Parse workingStats array to output results
foreach ($sessionStats as $outputStats)
array_push( $this->elements, $outputStats->toArray() );
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// find a row of stats for given user and stats
function findStats (array $statsArray, int $userId, int $sessionId)
{
foreach ($statsArray as $row)
{
if (call_user_func_array(array($row, 'isForUserInSession'), array($userId, $sessionId)) === true)
return $row;
}
return null;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get stats : main call for getting stats from Unreal
public function get ($sessionId, $userId, $sessionType, $fromUserId=-1)
{
if ($sessionType == 0 || $sessionType == 1 || $sessionType == 7) // Firerange, Challenge or Long Range
$this->getResultsForSession ($sessionId, $userId, $fromUserId);
else if ($sessionId > 0 || $userId > 0)
$this->getStatsForSession ($sessionId, $userId, $fromUserId);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// user history : get user "all-time" totals
public function getUserHistory ($userId, $sessionId, $quickMode)
{
$userGlobals = new UserGlobalStats();
if ($quickMode == 1 && $userId > 0)
{
$userGlobals->totals->createSessionAndUser($this->conn, $sessionId, $userId);
$userGlobals->totals->averagePrecision = $userGlobals->totals->user->avgPrecision;
$userGlobals->totals->averageReactionTime = $userGlobals->totals->user->avgReaction;
$userSubConstraint = $userId >= 0 ? " AND P.UserId = " . $userId : ""; // always true
// Calculate date of first and last sessions
$query = "SELECT P.userID AS UserId, MIN(SD.SessionDate) AS MinDate, MAX(SD.SessionDate) AS MaxDate, " . "
COUNT(DISTINCT P.UserId, P.sessionId) AS NbSessions, SUM(SD.timeToFinish) AS TotalDuration " . "
FROM " . PARTICIPATES_TABLE_NAME . " P, " . SESSIONS_TABLE_NAME . " SD WHERE SD.id=P.sessionId " . $this->getCalibrationSessionsConstraint("SD") . $this->getSessionDurationConstraint("SD") . $userSubConstraint . " GROUP BY P.UserId";
// prepare and execute query
$stmt = $this->conn->prepare($query);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) // should be only 1 row
{
$userGlobals->setSessionTotals($row);
//$userGlobals->nbSessions = $row['NbSessions'];
//$userGlobals->totalDuration = $row['TotalDuration'];
//$userGlobals->firstSession = $row['MinDate'];
//$userGlobals->lastSession = $row['MaxDate'];
}
// Calculate shots fired
$userConstraint = $userId > 0 ? " AND SDTE.srcUserId=" . $userId : "";
$query = "SELECT COALESCE(SDTE.srcUserId,-1) AS UserId,
COALESCE(X.NbShotsFired,0) AS NbShotsFired,
COALESCE(X.NbShotsFired,0) - COALESCE(SUM(CASE WHEN Y.ReactTypeId>=0 AND Y.ReactTypeId<6 AND Y.ReactPrecision>0 THEN Y.NbHits ELSE 0 END),0) AS NbMissedShots,
SUM(CASE WHEN Y.ReactTypeId=0 AND Y.ReactPrecision>0 THEN Y.NbHits ELSE 0 END) AS NbEnemyHits,
SUM(CASE WHEN Y.ReactTypeId=1 AND Y.ReactPrecision>0 THEN Y.NbHits ELSE 0 END) AS NbCivilHits,
SUM(CASE WHEN Y.ReactTypeId=2 AND Y.ReactPrecision>0 THEN Y.NbHits ELSE 0 END) AS NbPoliceHits,
SUM(CASE WHEN (Y.ReactTypeId=4 OR Y.ReactTypeId=5) AND Y.ReactPrecision>0 THEN Y.NbHits ELSE 0 END) AS NbObjectHits,
SUM(CASE WHEN Y.ReactTypeId=6 AND Y.ReactPrecision>0 THEN Y.NbHits ELSE 0 END) AS NbDeadBodyHits
FROM " . SESSIONS_TABLE_NAME . " SD LEFT JOIN " . TRIGGEREVENTS_TABLE_NAME . " SDTE ON (SDTE.sessionId=SD.id)
LEFT JOIN " . REACTEVENTS_TABLE_NAME . " SDRE ON (SDTE.sessionId=SDRE.srcEventSessionId AND SDTE.indexCount=SDRE.srcEventIndex)
LEFT JOIN " . "
(SELECT TE.srcUserId AS ShooterId, COUNT(DISTINCT TE.sessionId, TE.indexCount) AS NbShotsFired FROM " . TRIGGEREVENTS_TABLE_NAME . " TE GROUP BY TE.srcUserId) AS X
ON X.ShooterId=SDTE.srcUserId
LEFT JOIN " . "
(SELECT TE.srcUserId AS ShooterId, RE.ReactType AS ReactTypeId, COUNT(DISTINCT TE.sessionId, TE.indexCount, RE.hitTargetName) AS NbHits, RE.id AS ReactId, RE.hitPrecision AS ReactPrecision
FROM " . TRIGGEREVENTS_TABLE_NAME . " TE, " . REACTEVENTS_TABLE_NAME . " RE
WHERE TE.sessionId = RE.srcEventSessionId AND TE.indexCount = RE.srcEventIndex AND TE.indexCount!=-1 AND RE.ReactType!=-1 GROUP BY ShooterId, ReactTypeId, ReactID) AS Y
ON (Y.ShooterId=SDTE.srcUserId AND Y.ReactId=SDRE.id)
LEFT JOIN " . "
(SELECT TE1.srcUserId AS ShooterId, COALESCE(COUNT(DISTINCT TE1.sessionId, TE1.indexCount),0) AS NbMissedShots FROM " . TRIGGEREVENTS_TABLE_NAME . " TE1, " . REACTEVENTS_TABLE_NAME . " RE1
WHERE TE1.sessionId=RE1.srcEventSessionId AND TE1.indexCount NOT IN (SELECT RE2.srcEventIndex FROM " . REACTEVENTS_TABLE_NAME . " RE2 WHERE RE2.srcEventSessionId=RE1.srcEventSessionId)) AS Z
ON (Z.ShooterId=SDTE.srcUserId) " . "
WHERE 1 " . $this->getCalibrationSessionsConstraint("SD") . $this->getSessionDurationConstraint("SD") . $userConstraint . " GROUP BY SDTE.srcUserId";
// prepare and execute query
$stmt = $this->conn->prepare($query);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$userGlobals->totals->setFiredShots($row);
//$userGlobals->totals->nbFiredShotsByUser = $row['NbShotsFired'];
//$userGlobals->totals->nbMissedShotsByUser = $row['NbMissedShots'];
//$userGlobals->totals->nbEnemyHitsByUser = $row['NbEnemyHits'];
//$userGlobals->totals->nbCivilHitsByUser = $row['NbCivilHits'];
//$userGlobals->totals->nbPoliceHitsByUser = $row['NbPoliceHits'];
//$userGlobals->totals->nbObjectHitsByUser = $row['NbObjectHits'];
//$userGlobals->totals->nbDeadBodyHitsByUser = $row['NbDeadBodyHits'];
}
// Calculate received hits
$userConstraint = $userId > 0 ? " AND X.TargetUserId=" . $userId : "";
$query = "SELECT COALESCE(X.TargetUserId, -1) AS UserId,
SUM(CASE WHEN X.ShooterRoleId=3 THEN X.NbHits ELSE 0 END) AS NbEnemyShotsIA,
SUM(CASE WHEN X.ShooterRoleId=1 THEN X.NbHits ELSE 0 END) AS NbEnemyShotsUser,
SUM(CASE WHEN X.ShooterRoleId=0 THEN X.NbHits ELSE 0 END) AS NbPoliceHits
FROM (SELECT TE.SessionId AS SessionId, RE.hitUserId AS TargetUserId,
(SELECT IFNULL((SELECT P.role FROM " . PARTICIPATES_TABLE_NAME . " P WHERE P.sessionId=TE.sessionId AND P.userId=TE.srcUserId),3)) AS ShooterRoleId,
COUNT(DISTINCT TE.indexCount, RE.hitTargetName) AS NbHits
FROM " . TRIGGEREVENTS_TABLE_NAME . " TE, " . REACTEVENTS_TABLE_NAME . " RE, " . SESSIONS_TABLE_NAME . " SD " .
"WHERE SD.id=TE.sessionId AND TE.sessionId = RE.srcEventSessionId AND TE.indexCount = RE.srcEventIndex AND TE.indexCount!=-1 AND RE.ReactType!=-1 " .
$this->getCalibrationSessionsConstraint("SD") . $this->getSessionDurationConstraint("SD") .
"GROUP BY SessionId, TargetUserId, ShooterRoleId) AS X
WHERE 1 " . $userConstraint . " GROUP BY X.TargetUserId";
// prepare and execute query
$stmt = $this->conn->prepare($query);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$userGlobals->totals->setReceivedHits($row);
}
// Calculate totals hits by type
$sessionConstraint = $sessionId > 0 ? " AND SDTE.SessionId = " . $sessionId : "";
$userConstraint = $userId > 0 ? " AND SDTE.SessionId IN (" . $this->getSessionsWithUserConstraint($userId) . ")" : "";
$query = "SELECT SUM(CASE WHEN X.ReactTypeId=0 THEN X.NbHits ELSE 0 END) AS NbEnemyKilled,
SUM(CASE WHEN X.ReactTypeId=1 THEN X.NbHits ELSE 0 END) AS NbCivilKilled,
SUM(CASE WHEN X.ReactTypeId=2 THEN X.NbHits ELSE 0 END) AS NbPoliceKilled
FROM " . SESSIONS_TABLE_NAME . " SD LEFT JOIN " . TRIGGEREVENTS_TABLE_NAME . " SDTE ON (SD.id = SDTE.sessionId)
LEFT JOIN
(SELECT TE.SessionId AS SessionId, RE.hitUserId AS TargetUserId, TE.srcUserId AS ShooterRoleId, COUNT(DISTINCT TE.indexCount, RE.hitTargetName) AS NbHits, RE.srcEventIndex AS TriggerIndex, RE.ReactType AS ReactTypeId
FROM " . TRIGGEREVENTS_TABLE_NAME . " TE, " . REACTEVENTS_TABLE_NAME . " RE WHERE TE.sessionId = RE.srcEventSessionId AND TE.indexCount = RE.srcEventIndex AND TE.indexCount!=-1 AND RE.ReactType!=-1 AND RE.TargetKilled=1
GROUP BY SessionId, TargetUserId, ShooterRoleId, ReactTypeId) AS X
ON (X.SessionId=SDTE.SessionId AND X.TriggerIndex=SDTE.indexCount)
WHERE 1 " . $this->getCalibrationSessionsConstraint("SD") . $this->getSessionDurationConstraint("SD") . $userConstraint;
// prepare and execute query
$stmt = $this->conn->prepare($query);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$userGlobals->totals->setTotalKills($row);
}
$query = "SELECT X.*, " .
"SUM(X.HitPrecision)/COALESCE(COUNT(DISTINCT X.SessionId, X.ShotIndex),1) AS AvgPrecision, " .
"SUM(X.ReactionTime)/COALESCE(SUM(CASE WHEN X.ReactionTime > 0 THEN CEILING(X.HitPrecision) ELSE 0 END),1) AS AvgReactTime " .
"FROM " .
"(SELECT TE.sessionId AS SessionId, S.sessionType AS SessionTypeId, ST.displayName AS SessionType, '' AS SessionName, '' AS SessionDate, '' AS MapName, S.scenarioName AS ScenarioName, " .
"0 AS SessionSuccessful, 0 AS SessionDuration, 0 AS TriggerTypeId, 'Fire' AS TriggerType, TE.srcUserId AS ShooterId, '' AS ShooterName, -1 AS ShooterRoleId, '' AS ShooterRole, " .
"TE.indexCount AS ShotIndex, RE.id AS ReactId, -1 AS ReactModeId, '' AS ReactMode, -1 AS ReactTypeId, '' AS ReactType, RE.hitUserId AS TargetUserId, " .
"'' AS TargetUserName, -1 AS TargetRoleId, '' AS TargetRole, RE.hitTargetName AS TargetName, RE.hitBoneName AS TargetBoneName, 0 AS TargetKilled, 0 AS HitLocationX, 0 AS HitLocationY, " .
"'' AS HitLocationTag, RE.hitPrecision AS HitPrecision, 0 AS HitTargetDistance, RE.reactTime as ReactionTime, 0 AS TimeStamp, 0 AS NbHit, 0 AS NbKilled " .
"FROM " . SESSIONS_TABLE_NAME . " S " .
"LEFT JOIN " . TRIGGEREVENTS_TABLE_NAME . " TE ON (S.id=TE.sessionId) " .
"LEFT JOIN " . REACTEVENTS_TABLE_NAME . " RE ON (TE.sessionId=RE.srcEventSessionId AND TE.indexCount=RE.srcEventIndex) " .
"LEFT JOIN " . SESSIONTYPES_TABLE_NAME . " ST ON (S.sessionType=ST.id) " .
"WHERE 1 " . $this->getSessionDurationConstraint("S") . $this->getCalibrationSessionsConstraint("S") .
" GROUP BY ShooterId, SessionId, TE.indexCount) AS X " .
"WHERE X.ShooterId = " . $userId . " AND X.SessionId IN (" . $this->getSessionsWithUserConstraint($userId) . ") GROUP BY X.ShooterId, X.SessionId ORDER BY X.SessionId ASC";
// prepare and execute query
$stmt = $this->conn->prepare($query);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$row['HitPrecision'] = $row['AvgPrecision'];
$row['ReactionTime'] = $row['AvgReactTime'];
$stats = SessionDebriefRow::withRow($row);
array_push( $userGlobals->sessionDebriefRows, $stats->toArray() );
}
}
else
{
// create SQL constraints for query
$sessionConstraint = $sessionId > 0 ? " AND SD.SessionId = " . $sessionId : "";
$userConstraint = $userId >= 0 ? " AND SD.ShooterId = " . $userId : "";
$userSubConstraint = $userId >= 0 ? " AND P.UserId = " . $userId : "";
// get raw results from query
$sessionStats = $this->getRawStatsForSession ($sessionId, $userId, -1);
$newNbFiredShotsForReactionTime = 0;
$nbSessions = 0;
foreach ($sessionStats as $row)
{
if ( ($userId == -1 || $row->userId == $userId) && ($sessionId == -1 || $row->sessionId == $sessionId) )
{
// Increase number of sessions for this user
$nbSessions++;
// Update precision average
$newPrecision = $userGlobals->totals->averagePrecision*$userGlobals->totals->nbFiredShotsByUser + $row->averagePrecision*$row->nbFiredShotsByUser;
$userGlobals->totals->averagePrecision = $newPrecision/max($userGlobals->totals->nbFiredShotsByUser + $row->nbFiredShotsByUser, 1.0);
// Update reactionTime average
if ($row->averageReactionTime > 0)
{
$newReactionTime = $userGlobals->totals->averageReactionTime*$newNbFiredShotsForReactionTime + $row->averageReactionTime*$row->nbFiredShotsByUser;
$newNbFiredShotsForReactionTime += $row->nbFiredShotsByUser;
$userGlobals->totals->averageReactionTime = $newReactionTime/max($newNbFiredShotsForReactionTime, 1.0);
}
// Update other fields
$userGlobals->totals->nbFiredShotsByUser = $userGlobals->totals->nbFiredShotsByUser + $row->nbFiredShotsByUser;
$userGlobals->totals->nbEnemyHitsByUser += $row->nbEnemyHitsByUser;
$userGlobals->totals->nbCivilHitsByUser += $row->nbCivilHitsByUser;
$userGlobals->totals->nbPoliceHitsByUser += $row->nbPoliceHitsByUser;
$userGlobals->totals->nbObjectHitsByUser += $row->nbObjectHitsByUser;
$userGlobals->totals->nbMissedShotsByUser += $row->nbMissedShotsByUser;
$userGlobals->totals->nbDeadBodyHitsByUser += $row->nbDeadBodyHitsByUser;
$userGlobals->totals->nbReceivedHitsFromEnemyIA += $row->nbReceivedHitsFromEnemyIA;
$userGlobals->totals->nbReceivedHitsFromEnemyUser += $row->nbReceivedHitsFromEnemyUser;
$userGlobals->totals->nbReceivedHitsFromPoliceUser +=$row->nbReceivedHitsFromPoliceUser;
$userGlobals->totals->totalEnemyKilled += $row->totalEnemyKilled;
$userGlobals->totals->totalCivilKilled += $row->totalCivilKilled;
$userGlobals->totals->totalPoliceKilled += $row->totalPoliceKilled;
// Update duration
$userGlobals->totalDuration += $row->session->timeToFinish;
// Update user and session ids
$userGlobals->totals->userId = $row->userId;
$userGlobals->totals->sessionId = $row->sessionId;
}
}
// Get number of sessions user took part in
$userGlobals->nbSessions = $nbSessions;
// Calculate averages for precision and reaction time
$query = "SELECT SD.*, SUM(SD.HitPrecision) AS TotalPrecision, COUNT(DISTINCT SD.ShotIndex, SD.TargetName) AS TotalShots" .
", SUM(SD.ReactionTime) AS TotalReactionTime, SUM(CEILING(SD.HitPrecision)) AS TotalHits, X.MinDate AS MinDate, X.MaxDate AS MaxDate" .
" FROM " . SESSIONDEBRIEFS_VIEW_NAME . " SD, " .
" (SELECT P.userID AS UserId, MIN(S.SessionDate) AS MinDate, MAX(S.SessionDate) AS MaxDate" .
//" FROM " . PARTICIPATES_TABLE_NAME . " P INNER JOIN " . SESSIONS_TABLE_NAME . " S ON S.id=P.sessionId WHERE 1 " . $userSubConstraint . " GROUP BY P.userId) AS X" .
" FROM " . PARTICIPATES_TABLE_NAME . " P, " . SESSIONS_TABLE_NAME . " S WHERE S.id=P.sessionId " . $userSubConstraint . " GROUP BY P.userId) AS X" .
" WHERE 1 " . $sessionConstraint . $userConstraint . " GROUP BY SD.SessionId, SD.ShooterId";
// prepare and execute query
$stmt = $this->conn->prepare($query);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
// read MIN and MAX dates
$userGlobals->firstSession = $row['MinDate'];
$userGlobals->lastSession = $row['MaxDate'];
// replace HitPrecision, ReactionTime and NbHit fields so that we don't have to create a new type for returning the results
$row['HitPrecision'] = (float)(($row['TotalPrecision'] ?? 0.0) / max(($row['TotalShots'] ?? 1.0), 1.0) );
$row['ReactionTime'] = (float)(($row['TotalReactionTime'] ?? 0.0) / max(($row['TotalHits'] ?? 1.0), 1.0) );
$row['NbHit'] = $row['TotalHits'] ?? 0;
$stats = SessionDebriefRow::withRow($row);
array_push( $userGlobals->sessionDebriefRows, $stats->toArray() );
//array_push( $this->elements, $stats->toArray() ); // old
}
if ($userGlobals->nbSessions == 1)
{
$userGlobals->firstSession = $sessionStats[0]->session->sessionDate;
$userGlobals->lastSession = $userGlobals->firstSession;
}
}
array_push( $this->elements, $userGlobals->toArray() ); // new
//return $userGlobals->toArray();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// debrief mission : get totals for given session and/or user
public function getReceivedHitsForUser ($sessionId, $userId, $fromUser=-1)
{
// create SQL constraints for query
$sessionConstraint = $sessionId > 0 ? " AND SDRE.srcEventSessionId = " . $sessionId : "";
$userConstraint = $userId > 0 ? " AND SDRE.hitUserId=" . $userId : "";
$query = "SELECT SDRE.srcEventSessionId AS SessionId, COALESCE(SDRE.hitUserId, -1) AS UserId,
SUM(CASE WHEN X.ShooterRoleId=3 THEN X.NbHits ELSE 0 END) AS NbEnemyShotsIA,
SUM(CASE WHEN X.ShooterRoleId=1 THEN X.NbHits ELSE 0 END) AS NbEnemyShotsUser,
SUM(CASE WHEN X.ShooterRoleId=0 THEN X.NbHits ELSE 0 END) AS NbPoliceHits
FROM " . REACTEVENTS_TABLE_NAME . " SDRE LEFT JOIN
(SELECT TE.SessionId AS SessionId, RE.hitUserId AS TargetUserId, TE.srcUserId AS ShooterRoleId, COUNT(DISTINCT TE.indexCount, RE.hitTargetName) AS NbHits, RE.id AS ReactId
FROM " . TRIGGEREVENTS_TABLE_NAME . " TE, " . REACTEVENTS_TABLE_NAME . " RE WHERE TE.sessionId = RE.srcEventSessionId AND TE.indexCount = RE.srcEventIndex AND TE.indexCount!=-1 AND RE.ReactType!=-1 GROUP BY SessionId, TargetUserId, ShooterRoleId) AS X
ON (X.SessionId=SDRE.srcEventSessionId AND X.TargetUserId=SDRE.hitUserId AND X.ReactId=SDRE.id) " .
" LEFT JOIN " . SESSIONS_TABLE_NAME . " SD ON (SD.id=SDRE.srcEventSessionId) " .
"WHERE 1 " . $sessionConstraint . $userConstraint . $this->getSessionDurationConstraint("SD") . " GROUP BY SDRE.srcEventSessionId, SDRE.hitUserId";
// prepare and execute query
$stmt = $this->conn->prepare($query);
$stmt->execute();
return $stmt;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// debrief mission : get totals for given session and/or user
public function getShotsFiredByUser ($sessionId, $userId, $fromUser=-1)
{
// create SQL constraints for query
$sessionConstraint = $sessionId > 0 ? " AND SDTE.SessionId = " . $sessionId : "";
$userConstraint = $userId > 0 ? " AND SDTE.srcUserId=" . $userId : "";
$query = "SELECT SDTE.SessionId AS SessionId, SDTE.srcUserId AS UserId,
COALESCE(X.NbShotsFired,0) AS NbShotsFired,
COALESCE(X.NbShotsFired,0) - COALESCE(SUM(CASE WHEN Y.ReactTypeId>=0 AND Y.ReactTypeId<6 AND Y.ReactPrecision>0 THEN Y.NbHits ELSE 0 END),0) AS NbMissedShots,
SUM(CASE WHEN Y.ReactTypeId=0 AND Y.ReactPrecision>0 THEN Y.NbHits ELSE 0 END) AS NbEnemyHits,
SUM(CASE WHEN Y.ReactTypeId=1 AND Y.ReactPrecision>0 THEN Y.NbHits ELSE 0 END) AS NbCivilHits,
SUM(CASE WHEN Y.ReactTypeId=2 AND Y.ReactPrecision>0 THEN Y.NbHits ELSE 0 END) AS NbPoliceHits,
SUM(CASE WHEN (Y.ReactTypeId=4 OR Y.ReactTypeId=5) AND Y.ReactPrecision>0 THEN Y.NbHits ELSE 0 END) AS NbObjectHits,
SUM(CASE WHEN Y.ReactTypeId=6 AND Y.ReactPrecision>0 THEN Y.NbHits ELSE 0 END) AS NbDeadBodyHits
FROM " . SESSIONS_TABLE_NAME . " SD LEFT JOIN " . TRIGGEREVENTS_TABLE_NAME . " SDTE ON (SD.id = SDTE.sessionId)
LEFT JOIN " . REACTEVENTS_TABLE_NAME . " SDRE ON (SDTE.sessionId=SDRE.srcEventSessionId AND SDTE.indexCount=SDRE.srcEventIndex)
LEFT JOIN
(SELECT TE.sessionId AS SessionId, TE.srcUserId AS ShooterId, COUNT(DISTINCT TE.indexCount) AS NbShotsFired
FROM " . TRIGGEREVENTS_TABLE_NAME . " TE GROUP BY TE.sessionId, TE.srcUserId) AS X
ON (X.SessionId=SDTE.SessionId AND X.ShooterId=SDTE.srcUserId)
LEFT JOIN
(SELECT TE.sessionId AS SessionId, TE.srcUserId AS ShooterId, RE.ReactType AS ReactTypeId, COUNT(DISTINCT TE.indexCount, RE.hitTargetName) AS NbHits, RE.id AS ReactId, RE.hitPrecision AS ReactPrecision
FROM " . TRIGGEREVENTS_TABLE_NAME . " TE, " . REACTEVENTS_TABLE_NAME . " RE
WHERE TE.sessionId = RE.srcEventSessionId AND TE.indexCount = RE.srcEventIndex AND TE.indexCount!=-1 AND RE.ReactType!=-1 GROUP BY SessionId, ShooterId, ReactTypeId, ReactID) AS Y
ON (Y.SessionId=SDTE.SessionId AND Y.ShooterId=SDTE.srcUserId AND Y.ReactId=SDRE.id)
LEFT JOIN
(SELECT TE1.sessionId AS SessionId, TE1.srcUserId AS ShooterId, COALESCE(COUNT(DISTINCT TE1.sessionId, TE1.indexCount),0) AS NbMissedShots
FROM " . TRIGGEREVENTS_TABLE_NAME . " TE1, " . REACTEVENTS_TABLE_NAME . " RE1
WHERE TE1.sessionId=RE1.srcEventSessionId AND TE1.indexCount NOT IN (SELECT RE2.srcEventIndex FROM " . REACTEVENTS_TABLE_NAME . " RE2 WHERE RE2.srcEventSessionId=RE1.srcEventSessionId)) AS Z
ON (Z.SessionId=SDTE.SessionId AND Z.ShooterId=SDTE.srcUserId)
WHERE 1 " . $this->getCalibrationSessionsConstraint("SD") . $this->getSessionDurationConstraint("SD") . $sessionConstraint . $userConstraint . " GROUP BY SDTE.SessionId, SDTE.srcUserId";
// prepare and execute query
$stmt = $this->conn->prepare($query);
$stmt->execute();
return $stmt;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// debrief mission : get totals for given session and/or user
public function getTargetKilledInSession ($sessionId)
{
// create SQL constraints for query
$sessionConstraint = $sessionId > 0 ? " AND SDTE.SessionId = " . $sessionId : "";
$query = "SELECT SDTE.SessionId AS SessionId, COALESCE(SDTE.srcUserId,-1) AS UserId,
SUM(CASE WHEN X.ReactTypeId=0 THEN X.NbHits ELSE 0 END) AS NbEnemyKilled,
SUM(CASE WHEN X.ReactTypeId=1 THEN X.NbHits ELSE 0 END) AS NbCivilKilled,
SUM(CASE WHEN X.ReactTypeId=2 THEN X.NbHits ELSE 0 END) AS NbPoliceKilled
FROM " . SESSIONS_TABLE_NAME . " SD LEFT JOIN " . TRIGGEREVENTS_TABLE_NAME . " SDTE ON (SD.id = SDTE.sessionId)
LEFT JOIN " . REACTEVENTS_TABLE_NAME . " SDRE ON (SDTE.sessionId=SDRE.srcEventSessionId AND SDTE.indexCount=SDRE.srcEventIndex)
LEFT JOIN
(SELECT TE.SessionId AS SessionId, RE.hitUserId AS TargetUserId, TE.srcUserId AS ShooterRoleId, COUNT(DISTINCT TE.indexCount, RE.hitTargetName) AS NbHits, RE.id AS ReactId, RE.ReactType AS ReactTypeId
FROM " . TRIGGEREVENTS_TABLE_NAME . " TE, " . REACTEVENTS_TABLE_NAME . " RE WHERE TE.sessionId = RE.srcEventSessionId AND TE.indexCount = RE.srcEventIndex AND TE.indexCount!=-1 AND RE.ReactType!=-1 AND RE.TargetKilled=1
GROUP BY SessionId, TargetUserId, ShooterRoleId, ReactTypeId) AS X
ON (X.SessionId=SDTE.SessionId AND X.TargetUserId=SDRE.hitUserId AND X.ReactId=SDRE.id)
WHERE 1 " . $this->getCalibrationSessionsConstraint("SD") . $this->getSessionDurationConstraint("SD") . $sessionConstraint . " GROUP BY SDTE.SessionId";
// prepare and execute query
$stmt = $this->conn->prepare($query);
$stmt->execute();
return $stmt;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// debrief mission : get averages for given session and/or user
public function getPrecisionAndReactionTimeForUser ($sessionId, $userId, $fromUser=-1)
{
// create SQL constraints for query
$sessionConstraint = $sessionId > 0 ? " AND SDTE.SessionId = " . $sessionId : "";
$query = "SELECT SDTE.SessionId AS SessionId, SDTE.srcUserId AS UserId, AVG(X.AvgHitPrec) AS AveragePrecision,
AVG(CASE WHEN X.HitPrecision > 0 AND X.ReactId > 0 THEN X.AvgReactTime END) AS AverageReactionTime
FROM " . SESSIONS_TABLE_NAME . " SD LEFT JOIN " . TRIGGEREVENTS_TABLE_NAME . " SDTE ON (SD.id = SDTE.sessionId)
LEFT JOIN " . REACTEVENTS_TABLE_NAME . " SDRE ON SDTE.sessionId=SDRE.srcEventSessionId AND SDTE.indexCount=SDRE.srcEventIndex
LEFT JOIN
(SELECT DISTINCT TE.SessionId AS SessionId, TE.srcUserId AS ShooterId, TE.indexCount, RE.hitTargetName, COALESCE(AVG(RE.hitPrecision),0) AS AvgHitPrec, COALESCE(AVG(RE.reactTime),0) AS AvgReactTime, COALESCE(RE.id,-1) AS ReactId, COALESCE(RE.hitPrecision,0) AS HitPrecision
FROM " . TRIGGEREVENTS_TABLE_NAME . " TE LEFT JOIN " . REACTEVENTS_TABLE_NAME . " RE ON TE.indexCount=RE.srcEventIndex AND TE.sessionId=RE.srcEventSessionId GROUP BY TE.SessionId, TE.srcUserId, TE.indexCount, RE.id, RE.hitTargetName) AS X
ON X.SessionId=SDTE.SessionId AND X.ShooterId=SDTE.srcUserId
WHERE 1 " . $this->getCalibrationSessionsConstraint("SD") . $this->getSessionDurationConstraint("SD") . $sessionConstraint . " GROUP BY SDTE.SessionId, SDTE.srcUserId";
// prepare and execute query
$stmt = $this->conn->prepare($query);
$stmt->execute();
return $stmt;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// debrief mission : get given users results in given session
public function getResultsForSession ($sessionId, $userId, $fromUserId=-1)
{
$userConstraint = $userId > 0 ? " AND SD.ShooterId=" . $userId : "";
$sessionConstraint = $sessionId > 0 ? " AND SD.SessionId=" . $sessionId : "";
$query = "SELECT SD.* FROM " . SESSIONDEBRIEFS_VIEW_NAME . " SD WHERE 1 " . $this->getCalibrationSessionsConstraint() . $userConstraint . $sessionConstraint . " GROUP BY SD.SessionId, SD.ShooterId, SD.ShotIndex";
//$query = "SELECT SD.* FROM (" . SESSIONDEBRIEFS_VIEW_QUERY . ") AS SD WHERE 1 " . $userConstraint . $sessionConstraint . " GROUP BY SD.SessionId, SD.ShooterId, SD.ShotIndex";
// prepare and execute query
$stmt = $this->conn->prepare($query);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$shot = SessionDebriefRow::withRow($row);
array_push( $this->elements, $shot->toArray() );
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// debrief mission : get stats for given session and/or user
/*public function getSessionDebrief ($sessionId, $userId, $fromUser=-1)
{
// prepare and execute query
$stmt = $this->getDebriefRows($sessionId, $userId);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
// create a SessionDebriefRow with this data
$stats = SessionDebriefRow::withRow($row);
array_push( $this->elements, $stats->toArray() );
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function getDebriefRows ($sessionId, $userId)
{
// create SQL constraints for query
$sessionConstraint = $sessionId > 0 ? " AND SD.SessionId = " . $sessionId : "";
$userConstraint = $userId >= 0 ? " AND (SD.ShooterId = " . $userId . " OR SD.TargetUserId = " . $userId . ")" : "";
//$query = "SELECT SD.* FROM " . SESSIONDEBRIEFS_VIEW_NAME . " SD WHERE 1 " . $sessionConstraint . $userConstraint;
$query = "SELECT SD.* FROM (" . SESSIONDEBRIEFS_VIEW_QUERY . ") AS SD WHERE 1 " . $sessionConstraint . $userConstraint;
// prepare and execute query
$stmt = $this->conn->prepare($query);
$stmt->execute();
return $stmt;
}*/
}
?>

View File

@@ -0,0 +1,48 @@
<?php
include_once '../objects/stats_user_in_session_row.php';
class UserGlobalStats
{
public int $nbSessions = 0;
public float $totalDuration = 0.0;
public string $firstSession = "";
public string $lastSession = "";
public UserStatsInSessionRow $totals;
public $sessionDebriefRows = array();
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function __construct ()
{
$this->totals = new UserStatsInSessionRow();
$this->sessionDebriefRows = array();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function setSessionTotals (array $row)
{
$this->nbSessions = (int)$row['NbSessions'];
$this->totalDuration = (float)$row['TotalDuration'];
$this->firstSession = $row['MinDate'];
$this->lastSession = $row['MaxDate'];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function toArray () : array
{
return array (
"nbSessions" => (int)$this->nbSessions,
"totalDuration" => (float)$this->totalDuration ?? 0.0,
"firstSessionAsString" => $this->firstSession ?? "",
"lastSessionAsString" => $this->lastSession ?? "",
"totals" => $this->totals->toArray(),
"sessionDebriefRows" => $this->sessionDebriefRows
);
}
}
?>

View File

@@ -0,0 +1,244 @@
<?php
include_once '../objects/db_user.php';
include_once '../objects/db_session.php';
class UserStatsInSessionRow
{
public GameSession $session;
public User $user;
public int $sessionId = -1;
public int $userId = -1;
public int $nbFiredShotsByUser = 0;
public int $nbEnemyHitsByUser = 0;
public int $nbCivilHitsByUser = 0;
public int $nbPoliceHitsByUser = 0;
public int $nbObjectHitsByUser = 0;
public int $nbMissedShotsByUser = 0;
public int $nbDeadBodyHitsByUser = 0;
public float $averagePrecision = 0.0;
public float $averageReactionTime = 0.0;
public int $nbReceivedHitsFromEnemyIA = 0;
public int $nbReceivedHitsFromEnemyUser = 0;
public int $nbReceivedHitsFromPoliceUser = 0;
public int $totalEnemyKilled = 0;
public int $totalCivilKilled = 0;
public int $totalPoliceKilled = 0;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function __construct ()
{
$this->session = new GameSession(null);
$this->sessionId = -1;
$this->user = new User(null);
$this->userId = -1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static function withRow ($db, array $row)
{
$instance = new self();
$instance->createSession($db, (int)$row['SessionId']);
$instance->createUser($db, (int)$row['UserId']);
//$this->readRow($row);
return $instance;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function createSessionAndUser ($db, int $sessionId=-1, int $userId=-1)
{
if ($sessionId > -1)
$this->createSession($db, $sessionId);
if ($userId > 0)
$this->createUser($db, $userId);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private function createSession ($db, int $id)
{
$this->session = new GameSession($db);
$this->session->id = $id;
$this->sessionId = $id; // keeping this field for easier access in UE
$this->session->load();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private function createUser ($db, int $id)
{
$this->user = new User($db);
$this->user->id = $id;
$this->userId = $id; // keeping this field for easier access in UE
$this->user->load();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function readRow (array $row)
{
$this->sessionId = $row['SessionId'];
//$this->sessionTypeId = $row['SessionTypeId'];
//$this->sessionType = $row['SessionType'];
//$this->sessionName = $row['SessionName'];
//$this->sessionDate = $row['SessionDate'];
//$this->mapName = $row['MapName'];
//$this->scenarioName = $row['ScenarioName'];
//$this->sessionSuccessful = $row['SessionSuccessful'] == 1;
//$this->sessionDuration = (float)$row['SessionDuration'];
//$this->triggerTypeId = (int)$row['TriggerTypeId'];
//$this->triggerType = $row['TriggerType'];
//$this->shooterId = (int)$row['ShooterId'];
//$this->shooterName = $row['ShooterName'];
//$this->shooterRoleId = (int)$row['ShooterRoleId'];
//$this->shooterRole = $row['ShooterRole'];
//$this->shotIndex = (int)$row['ShotIndex'];
//$this->reactId = (int)$row['ReactId'];
//$this->reactModeId = (int)$row['ReactModeId'];
//$this->reactMode = $row['ReactMode'];
//$this->reactTypeId = (int)$row['ReactTypeId'];
//$this->reactType = $row['ReactType'];
//$this->targetUserId = (int)$row['TargetUserId'];
//$this->targetUserName = $row['TargetUserName'];
//$this->targetRoleId = (int)$row['TargetRoleId'];
//$this->targetRole = $row['TargetRole'];
//$this->targetName = $row['TargetName'];
//$this->targetBoneName = $row['TargetBoneName'];
//$this->targetKilled = $row['TargetKilled'] == 1;
//$this->hitLocationX = (float)$row['HitLocationX'];
//$this->hitLocationY = (float)$row['HitLocationY'];
//$this->hitLocationTag = $row['HitLocationTag'];
//$this->hitPrecision = (float)$row['HitPrecision'];
//$this->hitTargetDistance = (float)$row['HitTargetDistance'];
//$this->reactTime = (float)$row['ReactionTime'];
//$this->timeStamp = (float)$row['TimeStamp'];
//$this->nbHit = (int)$row['NbHit'];
//$this->nbKilled = (int)$row['NbKilled'];
$this->userId = $row['UserId'];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function setFiredShots (array $row)
{
$this->nbFiredShotsByUser = (int)$row['NbShotsFired'];
$this->nbMissedShotsByUser = (int)$row['NbMissedShots'];
$this->nbEnemyHitsByUser = (int)$row['NbEnemyHits'];
$this->nbCivilHitsByUser = (int)$row['NbCivilHits'];
$this->nbPoliceHitsByUser = (int)$row['NbPoliceHits'];
$this->nbObjectHitsByUser = (int)$row['NbObjectHits'];
$this->nbDeadBodyHitsByUser = (int)$row['NbDeadBodyHits'];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function setPrecisionAndReactionTime (array $row)
{
$this->averagePrecision = (float)$row['AveragePrecision'];
$this->averageReactionTime = (float)$row['AverageReactionTime'];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function setReceivedHits (array $row)
{
$this->nbReceivedHitsFromEnemyIA = (int)$row['NbEnemyShotsIA'];
$this->nbReceivedHitsFromEnemyUser = (int)$row['NbEnemyShotsUser'];
$this->nbReceivedHitsFromPoliceUser = (int)$row['NbPoliceHits'];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function setTotalKills (array $row)
{
$this->totalEnemyKilled = (int)$row['NbEnemyKilled'];
$this->totalCivilKilled = (int)$row['NbCivilKilled'];
$this->totalPoliceKilled = (int)$row['NbPoliceKilled'];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function toArray () : array
{
return array (
"session" => $this->session->toArray() ?? "",
"user" => $this->user->toArray() ?? "",
"userId" => (int)$this->userId ?? -1,
"sessionId" => (int)$this->sessionId ?? -1,
"userId" => (int)$this->userId ?? -1,
"nbFiredShotsByUser" => (int)$this->nbFiredShotsByUser ?? 0,
"nbEnemyHitsByUser" => (int)$this->nbEnemyHitsByUser ?? 0,
"nbCivilHitsByUser" => (int)$this->nbCivilHitsByUser ?? 0,
"nbPoliceHitsByUser" => (int)$this->nbPoliceHitsByUser ?? 0,
"nbObjectHitsByUser" => (int)$this->nbObjectHitsByUser ?? 0,
"nbDeadBodyHitsHitsByUser" => (int)$this->nbDeadBodyHitsByUser ?? 0,
"nbMissedShotsByUser" => (int)$this->nbMissedShotsByUser ?? 0,
"averagePrecision" => (float)$this->averagePrecision ?? 0.0,
"averageReactionTime" => (float)$this->averageReactionTime ?? 0.0,
"nbReceivedHitsFromEnemyIA" => (int)$this->nbReceivedHitsFromEnemyIA ?? 0,
"nbReceivedHitsFromEnemyUser" => (int)$this->nbReceivedHitsFromEnemyUser ?? 0,
"nbReceivedHitsFromPoliceUser" => (int)$this->nbReceivedHitsFromPoliceUser ?? 0,
"totalEnemyKilled" => (int)$this->totalEnemyKilled ?? 0,
"totalCivilKilled" => (int)$this->totalCivilKilled ?? 0,
"totalPoliceKilled" => (int)$this->totalPoliceKilled ?? 0
);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public function isForUserInSession ($userIdToCheck, $sessionIdToCheck)
{
return $this->userId == $userIdToCheck && $this->sessionId == $sessionIdToCheck;
}
}
class Stats_ShotsPerUserPerSession_Row
{
public int $sessionId = -1;
public int $userId = -1;
public $username = "";
public int $nbShotsFired = 0;
public int $nbEnemyHits = 0;
public int $nbCivilsHits = 0;
public int $nbObjectHits = 0;
public int $nbDeadHits = 0;
public function __construct($row)
{
$this->sessionId = $row['sessionId'];
$this->userId = $row['userId'];
$this->username = $row['username'];
$this->nbShotsFired = $row['nbShotsFired'];
$this->nbEnemyHits = $row['nbEnemyHits'];
$this->nbCivilsHits = $row['nbCivilsHits'];
$this->nbObjectHits = $row['nbObjectHits'];
$this->nbDeadHits = $row['nbDeadHits'];
}
public function toArray () : array
{
return array (
"sessionId" => (int)$this->sessionId ?? -1,
"userId" => (int)$this->userId ?? -1,
"username" => $this->username ?? "",
"nbShotsFired" => (int)$this->nbShotsFired ?? 0,
"nbEnemyHits" => (int)$this->nbEnemyHits ?? 0,
"nbCivilsHits" => (int)$this->nbCivilsHits ?? 0,
"nbObjectHits" => (int)$this->nbObjectHits ?? 0,
"nbDeadHits" => (int)$this->nbDeadHits ?? 0
);
}
}
?>