You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

562 lines
19 KiB

<?php namespace App\Controllers;
/******************************************************************************************************************
* RPSLS - Rock, Paper, Scissors, Lizard, Spock Game
*
* @file app/Controllers/GameController.php
* @package App\Controllers
* @description
* Main Controller for Game.
* @author Rick Hays
* @date 11/15/2019
* @license MIT
* @copyright Copyright © 2019 - Rick Hays, All Rights Reserved.
*
* Revisions:
* YYYY-MM-DD XX Description
******************************************************************************************************************/
use App\Libraries\Location;
use App\Models\UserModel;
use App\Models\PlayModel;
use App\Models\LogModel;
class GameController extends BaseController
{
private $session;
/***************************************************************************************************************
* GameController constructor.
*/
public function __construct()
{
$this->session = session();
if (empty($this->session->get('ip')) && empty($this->session->get('UserID')))
{
$this->CreateSession();
$this->CreateLogRecord();
return redirect()->route('/');
}
else
{
return redirect()->route('play');
}
}
/***************************************************************************************************************
* @method index
* @description
* Main page for game, Start/Home Page.
*/
public function index()
{
$HeaderData = $this->getHeaderData();
echo view('inc/head');
echo view('inc/header', $HeaderData);
echo view('game');
echo view('inc/footer');
}
/***************************************************************************************************************
* @method createUser
* @description
* Creates user for game play.
* @param $UserName
* @param $UserID
*
* @return \CodeIgniter\HTTP\RedirectResponse
* @throws \ReflectionException
*/
public function createUser($UserName, $UserID)
{
$UserName = esc($UserName);
$UserID = esc($UserID);
$dbUsers = new UserModel();
// Validate User Name
if (!$this->validateUserName($UserName)) return redirect()->to(base_url() . '/getUser');
$UserID = $this->saveUserData($UserID, $UserName);
$UserData = $dbUsers->find($UserID);
// Add user to the Session
$data =
[
'UserID' => $UserID,
'UserName' => $UserName,
'Wins' => $UserData['Wins'],
'Loses' => $UserData['Loses'],
'Ties' => $UserData['Ties']
];
$this->session->set($data);
// Pass off to PLAY()
return redirect()->route('play');
}
/***************************************************************************************************************
* @method endGame
* @description
* Destroys Session and sends them back to Home Page.
* @return \CodeIgniter\HTTP\RedirectResponse
*/
public function endGame()
{
// Close Session
$this->session->destroy();
// Goto Index page
return redirect()->route('/');
}
/***************************************************************************************************************
* @method getUser
* @description
* Prompt Screen to get user name for game play.
*/
public function getUser()
{
$getUserData = ['UserName' => $this->session->getFlashdata('UserName'), 'ErrorCode' => $this->session->getFlashdata('ErrorCode')];
$HeaderData = $this->getHeaderData();
echo view('inc/head');
echo view('inc/header', $HeaderData);
echo view('getUser', $getUserData);
echo view('inc/footer');
}
/***************************************************************************************************************
* @method play
* @description
* Main Play Page/Function Logic.
*
* @param null $PlayerPick
* @todo REFACTOR GAME PLAY!!
*
* @return \CodeIgniter\HTTP\RedirectResponse|false|string
* @throws \ReflectionException
*/
public function play($PlayerPick = null)
{
$UserID = $this->session->UserID;
if ($PlayerPick)
{
$W = 0; // Win
$L = 0; // Lose
$T = 0; // Tie
$ComputerPick = $this->ComputerPick();
$textResult = '';
$TextResults =
[
'RL' => 'Rock Crushes Lizard!',
'RS' => 'Rock Crushes Scissors!',
'PR' => 'Paper Covers Rock!',
'PS' => 'Paper Disproves Spock!',
'SP' => 'Scissors Cuts Paper!',
'SL' => 'Scissors Decapitates Lizard!',
'LS' => 'Lizard Poisons Spock!',
'LP' => 'Lizard Eats Paper!',
'SS' => 'Spock Smashes Scissors!',
'SR' => 'Spock Vaporizes Rock!',
'TIE' => 'No One Wins This Time.',
'DRAW' => 'Danger, Danger Will Robinson, that does not compute!',
];
/** GAME LOGIC */
switch(strtoupper($PlayerPick))
{
case 'ROCK':
switch(strtoupper($ComputerPick))
{
case 'ROCK': $textResult = 'TIE'; $W = 0; $L = 0; $T = 1; break;
case 'PAPER': $textResult = 'PR'; $W = 0; $L = 1; $T = 0; break;
case 'SCISSORS': $textResult = 'RS'; $W = 1; $L = 0; $T = 0; break;
case 'LIZARD': $textResult = 'RL'; $W = 1; $L = 0; $T = 0; break;
case 'SPOCK': $textResult = 'SR'; $W = 0; $L = 1; $T = 0; break;
default: $textResult = 'DRAW'; $W = 0; $L = 0; $T = 0;
}
break;
case 'PAPER':
switch(strtoupper($ComputerPick))
{
case 'ROCK': $textResult = 'PR'; $W = 1; $L = 0; $T = 0; break;
case 'PAPER': $textResult = 'TIE'; $W = 0; $L = 0; $T = 1; break;
case 'SCISSORS': $textResult = 'SP'; $W = 0; $L = 1; $T = 0; break;
case 'LIZARD': $textResult = 'LP'; $W = 0; $L = 1; $T = 0; break;
case 'SPOCK': $textResult = 'PS'; $W = 1; $L = 0; $T = 0; break;
default: $textResult = 'DRAW'; $W = 0; $L = 0; $T = 0;
}
break;
case 'SCISSORS':
switch(strtoupper($ComputerPick))
{
case 'ROCK': $textResult = 'RS'; $W = 0; $L = 1; $T = 0; break;
case 'PAPER': $textResult = 'SP'; $W = 1; $L = 0; $T = 0; break;
case 'SCISSORS': $textResult = 'TIE'; $W = 0; $L = 0; $T = 1; break;
case 'LIZARD': $textResult = 'SL'; $W = 1; $L = 0; $T = 0; break;
case 'SPOCK': $textResult = 'SS'; $W = 0; $L = 1; $T = 0; break;
default: $textResult = 'DRAW'; $W = 0; $L = 0; $T = 0;
}
break;
case 'LIZARD':
switch(strtoupper($ComputerPick))
{
case 'ROCK': $textResult = 'RL'; $W = 0; $L = 1; $T = 0; break;
case 'PAPER': $textResult = 'LP'; $W = 1; $L = 0; $T = 0; break;
case 'SCISSORS': $textResult = 'SL'; $W = 0; $L = 1; $T = 0; break;
case 'LIZARD': $textResult = 'TIE'; $W = 0; $L = 0; $T = 1; break;
case 'SPOCK': $textResult = 'LS'; $W = 1; $L = 0; $T = 0; break;
default: $textResult = 'DRAW'; $W = 0; $L = 0; $T = 0;
}
break;
case 'SPOCK':
switch(strtoupper($ComputerPick))
{
case 'ROCK': $textResult = 'SR'; $W = 1; $L = 0; $T = 0; break;
case 'PAPER': $textResult = 'PS'; $W = 0; $L = 1; $T = 0; break;
case 'SCISSORS': $textResult = 'SS'; $W = 1; $L = 0; $T = 0; break;
case 'LIZARD': $textResult = 'LS'; $W = 0; $L = 1; $T = 0; break;
case 'SPOCK': $textResult = 'TIE'; $W = 0; $L = 0; $T = 1; break;
default: $textResult = 'DRAW'; $W = 0; $L = 0; $T = 0;
}
break;
default:
// TODO: SOME RETURN ERROR GOES HERE
// AS WE SHOULD NEVER GET HERE...
}
// Text for Play Result of who Won, Lost or Tied.
if ($W === 1 && $L === 0 && $T === 0) $PlayResult = 'WINNER';
elseif ($W === 0 && $L === 1 && $T === 0) $PlayResult = 'LOSER';
elseif ($W === 0 && $L === 0 && $T === 1) $PlayResult = 'TIE';
else $PlayResult = 'DRAW';
$this->addPlay( $this->session->UserID, $this->session->UserName, $this->session->ip, $PlayerPick, $ComputerPick, $PlayResult);
$data =
[
'Wins' => $this->session->Wins + $W,
'Loses' => $this->session->Loses + $L,
'Ties' => $this->session->Ties + $T,
];
$this->session->set($data);
$this->updateDBCounts($this->session->UserID, $this->session->Wins, $this->session->Loses, $this->session->Ties);
////////////////////////////////////////////////////////////////////////////////////////////////////////
$data =
[
'PlayerPick' => $PlayerPick,
'ComputerPick' => $ComputerPick,
'Result' => $PlayResult,
'ResultText' => $TextResults[$textResult],
'Wins' => $this->session->Wins,
'Loses' => $this->session->Loses,
'Ties' => $this->session->Ties,
];
return json_encode($data);
}
else
{
$playData =
[
'UserID' => $this->session->UserID,
'UserName' => $this->session->UserName,
'Wins' => $this->session->Wins,
'Loses' => $this->session->Loses,
'Ties' => $this->session->Ties,
];
if (empty($UserID))
{
return redirect()->to(base_url() . '/getUser');
}
else
{
$HeaderData = $this->getHeaderData();
echo view('inc/head');
echo view('inc/header', $HeaderData);
echo view('play', $playData);
echo view('inc/footer');
}
}
}
/**
*************************************************************************************************************
* @method testUser
* @description
* Returns UserID from User Name if one exists else it will return a 0.
*
* @param $UserName
*
* @return string
*/
public function testUser($UserName)
{
// TODO: Have it compare more then name to equal the same
// if not the same country and city then its a new user
// and they should pick a different name, as this one
// belongs to someone else. This will keep stats correct!
return $this->getIDfromUserName($UserName);
}
/***************************************************************************************************************
* @method top10
* @description
* Logic for the Top10 page.
*/
public function top10()
{
//Table Models
$dbUsers = new UserModel();
$dbPlay = new PlayModel();
// Queries
$TotalPlays = $dbPlay->query("SELECT COUNT(Result) AS Total FROM plays")->getRow();
$TotalWinsPlayer = $dbPlay->query("SELECT COUNT(Result) AS Total FROM plays WHERE Result = 'WINNER'")->getRow();
$TotalLosesPlayer = $dbPlay->query("SELECT COUNT(Result) AS Total FROM plays WHERE Result = 'LOSER'")->getRow();
$TotalTiesPlayer = $dbPlay->query("SELECT COUNT(Result) AS Total FROM plays WHERE Result = 'TIE'")->getRow();
// echo '##### RESULT: ' . $TotalsWinsPlayer->Total . ' #####';
$Win10 = $dbUsers->select('UserName, Wins')->OrderBy('Wins', 'DESC')->findAll(10);
$Lose10 = $dbUsers->select('UserName, Loses')->OrderBy('Loses', 'DESC')->findAll(10);
$Tie10 = $dbUsers->select('UserName, Ties')->OrderBy('Ties', 'DESC')->findAll(10);
$PlayerPicks = $dbPlay->select('PlayerPick, COUNT(PlayerPick) AS Total')->groupBy('PlayerPick')->OrderBy('Total', 'DESC')->findAll(5);
$ComputerPicks = $dbPlay->select('ComputerPick, COUNT(PlayerPick) AS Total')->groupBy('ComputerPick')->OrderBy('Total', 'DESC')->findAll(5);
// Combine Results for View
$PageData =
[
'Win10' => $Win10,
'Lose10' => $Lose10,
'Tie10' => $Tie10,
'PlayerPicks' => $PlayerPicks,
'ComputerPicks' => $ComputerPicks,
'TotalWinsPlayer' => $TotalWinsPlayer,
'TotalLosesPlayer' => $TotalLosesPlayer,
'TotalTiesPlayer' => $TotalTiesPlayer,
'TotalPlays' => $TotalPlays
];
$HeaderData = $this->getHeaderData();
echo view('inc/head');
echo view('inc/header', $HeaderData);
echo view('top10', $PageData);
echo view('inc/footer');
}
// #############################################################################################################
// ### START OF PRIVATE FUNCTIONS
// #############################################################################################################
/***************************************************************************************************************
* @method addPlay
* @description
* Adds (Inserts) Game Play Results to the DB.
*
* @param $UserID
* @param $UserName
* @param $IP
* @param $PlayerPick
* @param $ComputerPick
* @param $Result
*
* @throws \ReflectionException
*/
private function addPlay($UserID, $UserName, $IP, $PlayerPick, $ComputerPick, $Result)
{
$dbPlay = new PlayModel();
$data =
[
'UserID' => $UserID,
'UserName' => $UserName,
'IP' => $IP,
'PlayerPick' => $PlayerPick,
'ComputerPick' => $ComputerPick,
'Result' => $Result
];
$dbPlay->insert($data);
}
/***************************************************************************************************************
* @method ComputerPick
* @description
* Returns the Computers Pick/Choice.
* @return string
*/
private function ComputerPick()
{
mt_srand(crc32(microtime()));
$pick = mt_rand(0,4);
$ComputerPicks = array('Rock', 'Paper', 'Scissors', 'Lizard', 'Spock');
return $ComputerPicks[$pick];
}
/***************************************************************************************************************
* @method CreateLogRecord
* @description
* Inserts a Log Record at start of New Session.
* @throws \ReflectionException
*/
private function CreateLogRecord()
{
$dbLog = new LogModel();
$data =
[
'IP' => $this->session->get('ip'),
'City' => $this->session->get('city'),
'State' => $this->session->get('region_name'),
'Country' => $this->session->get('country_name'),
];
$dbLog->insert($data);
}
/***************************************************************************************************************
* @method CreateSession
* @description
* Creates a new session for start of Game Play.
*/
private function CreateSession()
{
$Location = new Location();
$this->session->set($Location->Data);
}
/***************************************************************************************************************
* @method getPageName
* @description
* Returns the current page name, used for menu to show active page.
* @return string
*/
private function getPageName()
{
return $this->request->uri->getSegment(1);
}
/***************************************************************************************************************
* @method getHeaderData
* @description
* Creates array of header page data to pass into view.
* @return array
*/
private function getHeaderData()
{
$page = $this->getPageName();
$data =
[
'page' => $page,
];
return $data;
}
/***************************************************************************************************************
* @method getIDfromUserName
* @description
* Returns UserID from User Name if one exists else it will return a 0.
*
* @param $UserName
*
* @return string
*/
private function getIDfromUserName($UserName)
{
$UserName = esc($UserName);
$dbUsers = new UserModel();
$row = $dbUsers->select('id')->where('UserName', $UserName)->findAll(1);
return (empty($row['0']['id'])) ? '0' : strval($row['0']['id']);
}
/***************************************************************************************************************
* @method saveUserData
* @description
* Either saves (Inserts) the new user, or it will save (Update) a current user in the DB.
* This will return the UserID once Updated/Inserted into the DB.
*
* @param $UserID
* @param $UserName
*
* @return string
* @throws \ReflectionException
*/
private function saveUserData($UserID, $UserName)
{
$dbUsers = new UserModel();
if ($UserID !== '0')
{
// UPDATE
$data =
[
'id' => $UserID,
'IP' => $this->session->get('ip'),
];
}
else
{
// ADD (Create)
$data =
[
'UserName' => $UserName,
'Wins' => 0,
'Loses' => 0,
'Ties' => 0,
'IP' => $this->session->get('ip'),
'City' => $this->session->get('city'),
'State' => $this->session->get('region_name'),
'Country' => $this->session->get('country_name'),
'CountryCode' => $this->session->get('country_code'),
'FlagURL' => $this->session->get('flagUrl'),
];
}
$dbUsers->save($data);
return $this->getIDfromUserName($UserName);
}
/***************************************************************************************************************
* @method updateDBCounts
* @description
* This will update user scores from game play.
*
* @param $UserID
* @param $Wins
* @param $Loses
* @param $Ties
*
* @throws \ReflectionException
*/
private function updateDBCounts($UserID, $Wins, $Loses, $Ties)
{
$dbUsers = new UserModel();
$UserID = esc($UserID);
$Wins = esc($Wins);
$Loses = esc($Loses);
$Ties = esc($Ties);
$data =
[
'id' => $UserID,
'Wins' => $Wins,
'Loses' => $Loses,
'Ties' => $Ties,
];
$dbUsers->save($data);
}
/**
*************************************************************************************************************
* @method validateUserName
* @description
* Backend user name validation.
*
* @param $UserName
*
* @return bool
*/
private function validateUserName($UserName)
{
$Valid = TRUE;
$validation = \Config\Services::validation();
if (!$validation->check($UserName, 'required|regex_match[/^([0-9a-zA-Z-_@\.]*)$/]'))
{
$data =
[
'UserName' => $UserName,
'ErrorCode' => 'User Name can only contain characters: (a-z, A-Z, 0-9, - _ @ .) Only.'
];
$this->session->setFlashdata($data);
$Valid = FALSE;
}
return $Valid;
}
}