Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion app/library/Controllers/IndexController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Controllers;

use App\GameLogic;
use App\Models\PlayersTable;
use App\Views\IndexView;
use App\Views\AbstractView;
use App\Views\JsonView;
Expand All @@ -29,6 +30,21 @@ private function getGridSize(): int
return $gridSize;
}

private function getCurrentTimeString(): string
{
return date('Y-m-d h:i:s');
}

private function calculateElapsedTime($startTimeU): int
{
if (!is_numeric($startTimeU)) {
return 0;
}

$now = (int) date('U');
return ($now - (int) $startTimeU);
}

/**
* It is used in Ajax requests.
* @noinspection PhpUnused
Expand All @@ -40,6 +56,9 @@ public function opponentsTurnAction(): AbstractView
$request = json_decode($requestJson, true);

$matrix = $request['matrix'] ?? [];
$playerName = $request['player_name'] ?? 'Unknown player';
$gridSize = $request['grid_size'] ?? 3;
$startTime = $request['start_time'] ?? 0;

$gameLogic = new GameLogic($matrix);

Expand All @@ -49,12 +68,17 @@ public function opponentsTurnAction(): AbstractView
$row = 0;
$col = 0;
if (!$isPlayerWin && $gameLogic->isFreeCellsLeft()) {
list($row, $col) = $gameLogic->findBestMove();
list($row, $col) = $gameLogic->findAMove();
$gameLogic->setComputersMove($row, $col);
$isGameOver = $gameLogic->isGameOver();
$isComputerWin = $gameLogic->doWeHaveWinner();
}

if ($isPlayerWin) {
$playersTable = new PlayersTable();
$playersTable->addRow($playerName, $gridSize, $this->calculateElapsedTime($startTime), $this->getCurrentTimeString());
}

$view = new JsonView();
$view->data = [
'is_game_over' => $isGameOver,
Expand Down
4 changes: 3 additions & 1 deletion app/library/Controllers/LeaderboardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ public function indexAction(): AbstractView
$view = new LeaderboardView();

// Todo: redo this crap!
$players = (new PlayersTable())->getLeaders(10);
$players = (new PlayersTable())->getTotalLeaders();
$playerCount = count((new PlayersTable())->getAllUniquePlayers());
$view->players = $players;
$view->playerCount = $playerCount;

return $view;
}
Expand Down
27 changes: 27 additions & 0 deletions app/library/GameLogic.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,33 @@ public function findBestMove(): array
return $this->findBestMove();
}

/**
* At least it doesn't recurse...
*/
public function findAMove(): array
{
$freeRows = $this->findPlayableRows();
$freeRow = array_rand($freeRows);
$freeColumn = $freeRows[$freeRow][array_rand($freeRows[$freeRow])];

return [$freeRow, $freeColumn];
}

public function findPlayableRows(): array
{
$playableRows = [];

foreach($this->matrix as $index => $row) {
$freeCells = array_keys($row, '');

if(count($freeCells)) {
$playableRows[$index] = $freeCells;
}
}

return $playableRows;
}

public function setComputersMove(int $row, int $col): void
{
$this->matrix[$row][$col] = 'O';
Expand Down
35 changes: 35 additions & 0 deletions app/library/Models/PlayersTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,48 @@ public function getLeaders(int $gridSize): array
FROM players
WHERE
grid_size = :grid_size
ORDER BY
play_time_seconds ASC
",
[
':grid_size' => $gridSize,
]
);
}

public function getTotalLeaders(): array
{
return $this->executeSql(
"
SELECT
name,
play_time_seconds,
grid_size,
ctime
FROM players
ORDER BY
grid_size DESC,
play_time_seconds ASC
LIMIT 20
",
[]
);
}

public function getAllUniquePlayers(): array
{
return $this->executeSQL(
"
SELECT DISTINCT
name
FROM players
ORDER BY
name ASC
",
[]
);
}

public function addRow(string $name, int $gridSize, int $playTimeSeconds, string $date): void
{
$this->executeSql(
Expand Down
6 changes: 4 additions & 2 deletions app/library/Views/IndexView.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

class IndexView extends AbstractView
{
public int $gridSize;
public int $gridSize;
public string $playerName;

public function __construct()
{
$this->setTitle("Hello player!");
$this->playerName = ($_GET['player_name']) ?? "Player Name";
$this->setTitle( "Hello " . $this->playerName . "!");
}

public function render(): void
Expand Down
2 changes: 1 addition & 1 deletion app/library/Views/Layouts/app.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use App\Views\Layouts\AppLayout;

<link href="/www/bootstrap.min.css" rel="stylesheet">
<link href="/www/style.css?<?= time() ?>" rel="stylesheet">
<script src="/www/script.js"></script>
<script src="/www/script.js?<?= time() ?>"></script>
</head>

<body>
Expand Down
3 changes: 3 additions & 0 deletions app/library/Views/LeaderboardView.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ class LeaderboardView extends AbstractView
/** @var array[][] */
public array $players;

/** @var int */
public int $playerCount;

public function __construct()
{
$this->setTitle("Leaderboard");
Expand Down
5 changes: 4 additions & 1 deletion app/library/Views/index.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
?>
<div class="toolbar">
<form>
<label for="player_name">Player name</label>
<input type="text" name="player_name" id="player_name" value="<?= $this->playerName ?>">
<label for="grid_size">Grid size</label>
<input
type="number"
Expand All @@ -17,6 +19,7 @@
name="grid_size"
value="<?= $this->gridSize ?>"
/>
<input type="hidden" name="start_time" id="start_time" value="<?= date('U') ?>">
<input type="submit" value="Play">
</form>
</div>
Expand All @@ -31,7 +34,7 @@
$button_id = 'game_grid_' . $row . '_' . $col;
?>
<td>
<button id="<?= $button_id ?>" onclick="makeMove('<?= $button_id ?>')"></button>
<button id="<?= $button_id ?>" onclick="makeMove('<?= $button_id ?>')"> </button>
</td>
<?php } ?>
</tr>
Expand Down
23 changes: 22 additions & 1 deletion app/library/Views/leaderboard.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,26 @@
?>

<div class="row content-container col-xs-12">
<?php var_export($this->players) ?>
<table class="table">
<tr>
<th></th>
<th scope="col">Name</th>
<th scope="col">Play time (s)</th>
<th scope="col">Grid size</th>
<th scope="col">Date</th>
</tr>
<?php for ($row = 0; $row < count($this->players); $row++) { ?>
<tr>
<th scope="row"><?= $row+1 ?></th>
<td><?= ($this->players[$row]['name']) ?? '' ?></td>
<td><?= ($this->players[$row]['play_time_seconds']) ?? '' ?></td>
<td><?= ($this->players[$row]['grid_size']) ?? '' ?></td>
<td><?= ($this->players[$row]['ctime']) ?? '' ?></td>
</tr>
<?php } ?>
</table>

<?php if($this->playerCount) : ?>
<strong>Total players: <?= $this->playerCount ?></strong>
<?php endif; ?>
</div>
13 changes: 12 additions & 1 deletion app/www/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ function makeOpponentsTurn() {
let row = 1;
let col = 1;
let rowTexts = [];
let playerName = document.getElementById('player_name').value ?? 'Player name';
let startTime = document.getElementById('start_time').value ?? 0;
let gridSize = document.getElementById('grid_size').value ?? 3;

do {
const buttonId = `game_grid_${row}_${col}`;

Expand Down Expand Up @@ -38,7 +42,14 @@ function makeOpponentsTurn() {
"Accept": "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({ matrix: matrix }),
body: JSON.stringify(
{
matrix: matrix,
player_name: playerName,
start_time: startTime,
grid_size: gridSize
}
),
}
)
.then((response) => {
Expand Down
18 changes: 14 additions & 4 deletions app/www/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,21 @@ body {
width: 100px;
}

#game_grid {
padding: 1px 0 0 1px;
border: 5px solid black;
background-color: black;
}

#game_grid button{
width: 20px;
height: 20px;
padding: 2px;
margin: 0;
display: block;
width: 40px;
height: 40px;
padding: 0 2px 2px;
margin: 0 1px 1px 0;
background-color: white;
color: black;
font-size: 30px;
text-align: center;
line-height: 0;
}