Added attribute injection
This commit is contained in:
parent
3522bf245f
commit
01d1cbed9c
@ -6,9 +6,7 @@ use App\Service\Factorio;
|
|||||||
use App\Service\RuleChecker;
|
use App\Service\RuleChecker;
|
||||||
use Symfony\Component\Console\Attribute\AsCommand;
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
40
src/Command/UsersCommand.php
Normal file
40
src/Command/UsersCommand.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Command;
|
||||||
|
|
||||||
|
use App\Service\Factorio;
|
||||||
|
use App\Service\SimpleDatabase\PlayTimeRepository;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
#[AsCommand(
|
||||||
|
name: 'app:users',
|
||||||
|
description: 'List factorio server users',
|
||||||
|
)]
|
||||||
|
class UsersCommand extends Command
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly Factorio $factorio,
|
||||||
|
private readonly PlayTimeRepository $playTimeRepository,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
|
$players = $this->factorio->getOnlinePlayers();
|
||||||
|
|
||||||
|
$io->table(['Name', 'Time'], array_map(fn($player) => [
|
||||||
|
$player->getName(),
|
||||||
|
$this->playTimeRepository->getPlayTimeOnDay($player),
|
||||||
|
], $players));
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
@ -43,7 +43,10 @@ class Factorio
|
|||||||
|
|
||||||
$players = [];
|
$players = [];
|
||||||
foreach ($output as $line) {
|
foreach ($output as $line) {
|
||||||
$players[] = new Player(explode(' ', trim($line))[0]);
|
$lineSegments = explode(' ', trim($line));
|
||||||
|
if (count($lineSegments) >= 2 && $lineSegments[1] === '(online)') {
|
||||||
|
$players[] = new Player($lineSegments[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $players;
|
return $players;
|
||||||
@ -56,7 +59,7 @@ class Factorio
|
|||||||
|
|
||||||
public function whisper(Player $player, string $message): void
|
public function whisper(Player $player, string $message): void
|
||||||
{
|
{
|
||||||
$this->runCmd(['/whisper', $player->getName(), $message]);
|
$this->runCmd(['/whisper', $player->getName(), sprintf('[%s]', date('H:i:s')), $message]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function say(string $message): void
|
public function say(string $message): void
|
||||||
|
@ -3,12 +3,13 @@
|
|||||||
namespace App\Service\Rules;
|
namespace App\Service\Rules;
|
||||||
|
|
||||||
use App\Dto\Player;
|
use App\Dto\Player;
|
||||||
use App\Service\SimpleDataService;
|
use App\Service\SimpleDatabase\PlayTimeRepository;
|
||||||
|
use App\Service\SimpleDatabase\SimpleDataService;
|
||||||
|
|
||||||
class PlayTimeRule extends AbstractRule
|
class PlayTimeRule extends AbstractRule
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly SimpleDataService $storeData,
|
private readonly PlayTimeRepository $playTimeRepository,
|
||||||
private readonly int $defaultPlayTime = 60,
|
private readonly int $defaultPlayTime = 60,
|
||||||
private readonly int $timeBetweenChecks = 1,
|
private readonly int $timeBetweenChecks = 1,
|
||||||
) {}
|
) {}
|
||||||
@ -16,7 +17,7 @@ class PlayTimeRule extends AbstractRule
|
|||||||
private function timePerPlayer(Player $player)
|
private function timePerPlayer(Player $player)
|
||||||
{
|
{
|
||||||
$players = [
|
$players = [
|
||||||
// "Ardentsword" => "2:00",
|
// "Ardentsword" => "120",
|
||||||
];
|
];
|
||||||
|
|
||||||
return $players[$player->getName()] ?? $this->defaultPlayTime;
|
return $players[$player->getName()] ?? $this->defaultPlayTime;
|
||||||
@ -25,24 +26,22 @@ class PlayTimeRule extends AbstractRule
|
|||||||
public function check(Player $player): RuleResult
|
public function check(Player $player): RuleResult
|
||||||
{
|
{
|
||||||
$today = new \DateTimeImmutable();
|
$today = new \DateTimeImmutable();
|
||||||
$playerData = $this->getPlayerData($player);
|
$playTime = $this->playTimeRepository->getPlayTimeOnDay($player, $today);
|
||||||
|
|
||||||
// If the player has no data or the data is from a different day, we reset the time
|
// If the player has no data or the data is from a different day, we reset the time
|
||||||
if (!$playerData || $playerData['day'] !== $today->format('Y-m-d')) {
|
if ($playTime === false) {
|
||||||
$this->storePlayerData($player, $today, $this->timePerPlayer($player));
|
$this->playTimeRepository->storePlayTime($player, $today, $this->timePerPlayer($player));
|
||||||
return new RuleResult(RuleResultEnum::WARNING, sprintf('Extra time activated, set to %d minutes', $this->timePerPlayer($player)));
|
return new RuleResult(RuleResultEnum::WARNING, sprintf('Extra time activated, set to %d minutes', $this->timePerPlayer($player)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the player has time left, we decrease it and return denied if nothing left
|
// If the player has time left, we decrease it and return denied if nothing left
|
||||||
$timeLeft = $playerData['timeLeft'] - $this->timeBetweenChecks;
|
$playTime -= $this->timeBetweenChecks;
|
||||||
$this->storePlayerData($player, $today, $timeLeft);
|
$this->playTimeRepository->storePlayTime($player, $today, $playTime);
|
||||||
|
|
||||||
if ($timeLeft <= 0) {
|
if ($playTime <= 0) {
|
||||||
return new RuleResult(RuleResultEnum::DENIED);
|
return new RuleResult(RuleResultEnum::DENIED);
|
||||||
} elseif ($timeLeft <= 5) {
|
} elseif ($playTime <= 5 || $playTime === 30) {
|
||||||
return new RuleResult(RuleResultEnum::WARNING, sprintf('%d minute(s) left', $timeLeft));
|
return new RuleResult(RuleResultEnum::WARNING, sprintf('%d minute(s) left', $playTime));
|
||||||
}elseif($timeLeft === 30) {
|
|
||||||
return new RuleResult(RuleResultEnum::WARNING, sprintf('30 minutes left'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new RuleResult(RuleResultEnum::ALLOWED);
|
return new RuleResult(RuleResultEnum::ALLOWED);
|
||||||
@ -52,22 +51,4 @@ class PlayTimeRule extends AbstractRule
|
|||||||
{
|
{
|
||||||
return sprintf('PlayTimeRule, limited play time');
|
return sprintf('PlayTimeRule, limited play time');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function storePlayerData(Player $player, \DateTimeImmutable $day, int $timeLeft): void
|
|
||||||
{
|
|
||||||
$this->storeData->set(
|
|
||||||
sprintf('playTime-%s', $player->getName()),
|
|
||||||
[
|
|
||||||
'player' => $player->getName(),
|
|
||||||
'timeLeft' => $timeLeft,
|
|
||||||
'day' => $day->format('Y-m-d'),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getPlayerData(Player $player): ?array
|
|
||||||
{
|
|
||||||
return $this->storeData->get(
|
|
||||||
sprintf('playTime-%s', $player->getName())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -8,7 +8,7 @@ class TimeRule extends AbstractRule
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly string $start = '19:00',
|
private readonly string $start = '19:00',
|
||||||
private readonly string $end = '23:00',
|
private readonly string $end = '20:00',
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function check(Player $player): RuleResult
|
public function check(Player $player): RuleResult
|
||||||
@ -18,9 +18,12 @@ class TimeRule extends AbstractRule
|
|||||||
$end = new \DateTimeImmutable($this->end);
|
$end = new \DateTimeImmutable($this->end);
|
||||||
|
|
||||||
if ($now >= $start && $now <= $end) {
|
if ($now >= $start && $now <= $end) {
|
||||||
$fiveMinutesBeforeEnd = $end->sub(new \DateInterval('PT5M'));
|
// Always add 1 because we are a few seconds into the minute
|
||||||
if ($now >= $fiveMinutesBeforeEnd) {
|
$timeLeft = $end->diff($now);
|
||||||
return new RuleResult(RuleResultEnum::WARNING, 'Only 5 minutes remaining');
|
$minutesLeft = $timeLeft->i + 1;
|
||||||
|
$hoursLeft = $timeLeft->h;
|
||||||
|
if ($hoursLeft == 0 && ($minutesLeft <= 5 || $minutesLeft === 30)) {
|
||||||
|
return new RuleResult(RuleResultEnum::WARNING, sprintf('%d minute(s) left', $minutesLeft));
|
||||||
}
|
}
|
||||||
return new RuleResult(RuleResultEnum::ALLOWED);
|
return new RuleResult(RuleResultEnum::ALLOWED);
|
||||||
}
|
}
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Service;
|
|
||||||
|
|
||||||
use Symfony\Component\HttpKernel\KernelInterface;
|
|
||||||
|
|
||||||
class SimpleDataService
|
|
||||||
{
|
|
||||||
private string $file;
|
|
||||||
|
|
||||||
public function __construct(KernelInterface $kernel)
|
|
||||||
{
|
|
||||||
$this->file = $kernel->getProjectDir() . '/data.json';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function set(string $key, array $data): self
|
|
||||||
{
|
|
||||||
$all = $this->getAll();
|
|
||||||
$all[$key] = $data;
|
|
||||||
|
|
||||||
file_put_contents($this->file, json_encode($all, JSON_PRETTY_PRINT));
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get(string $key): ?array
|
|
||||||
{
|
|
||||||
return $this->getAll()[$key] ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAll(): array
|
|
||||||
{
|
|
||||||
if (!file_exists($this->file)) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return json_decode(file_get_contents($this->file), true);
|
|
||||||
}
|
|
||||||
}
|
|
47
src/Service/SimpleDatabase/PlayTimeRepository.php
Executable file
47
src/Service/SimpleDatabase/PlayTimeRepository.php
Executable file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service\SimpleDatabase;
|
||||||
|
|
||||||
|
use App\Dto\Player;
|
||||||
|
|
||||||
|
readonly class PlayTimeRepository
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private SimpleDataService $dataService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
private function getKey(Player $player): string
|
||||||
|
{
|
||||||
|
return sprintf('playTime-%s', $player->getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function storePlayTime(Player $player, \DateTimeImmutable $day, int $timeLeft): void
|
||||||
|
{
|
||||||
|
$this->dataService->set(
|
||||||
|
$this->getKey($player),
|
||||||
|
[
|
||||||
|
'player' => $player->getName(),
|
||||||
|
'timeLeft' => $timeLeft,
|
||||||
|
'day' => $day->format('Y-m-d'),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPlayTimeRaw(Player $player): ?array
|
||||||
|
{
|
||||||
|
return $this->dataService->get($this->getKey($player));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPlayTimeOnDay(Player $player, ?\DateTimeImmutable $day = null): false|int
|
||||||
|
{
|
||||||
|
if ($day === null) {
|
||||||
|
$day = new \DateTimeImmutable();
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $this->getPlayTimeRaw($player);
|
||||||
|
if (!$data || $data['day'] !== $day->format('Y-m-d')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $data['timeLeft'];
|
||||||
|
}
|
||||||
|
}
|
52
src/Service/SimpleDatabase/SimpleDataService.php
Executable file
52
src/Service/SimpleDatabase/SimpleDataService.php
Executable file
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service\SimpleDatabase;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||||
|
|
||||||
|
class SimpleDataService
|
||||||
|
{
|
||||||
|
private ?array $dataCache = null;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
#[Autowire('%kernel.project_dir%/data.json')]
|
||||||
|
private readonly string $dataFile
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function set(string $key, array $data): self
|
||||||
|
{
|
||||||
|
if ($this->dataCache === null) {
|
||||||
|
$this->dataCache = $this->getAll();
|
||||||
|
}
|
||||||
|
$this->dataCache[$key] = $data;
|
||||||
|
|
||||||
|
$this->writeCache();
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(string $key): ?array
|
||||||
|
{
|
||||||
|
return $this->getAll()[$key] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAll(): array
|
||||||
|
{
|
||||||
|
if ($this->dataCache !== null) {
|
||||||
|
return $this->dataCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_exists($this->dataFile)) {
|
||||||
|
$this->dataCache = [];
|
||||||
|
} else {
|
||||||
|
$this->dataCache = json_decode(file_get_contents($this->dataFile), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->dataCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function writeCache(): void
|
||||||
|
{
|
||||||
|
file_put_contents($this->dataFile, json_encode($this->dataCache, JSON_PRETTY_PRINT));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user