feat: Constraint 시스템에 NoPaneltyKey 추가

This commit is contained in:
2024-06-08 16:15:19 +00:00
parent ad223a9c75
commit 9415d79a3a
3 changed files with 180 additions and 69 deletions
+130 -69
View File
@@ -1,9 +1,11 @@
<?php <?php
namespace sammo\Constraint; namespace sammo\Constraint;
abstract class Constraint{ abstract class Constraint
private function __construct(){ {
private function __construct()
{
} }
const REQ_GENERAL = 0x10; const REQ_GENERAL = 0x10;
@@ -18,7 +20,8 @@ abstract class Constraint{
const REQ_NUMERIC_ARG = self::REQ_ARG | 0x4000; const REQ_NUMERIC_ARG = self::REQ_ARG | 0x4000;
const REQ_BOOLEAN_ARG = self::REQ_ARG | 0x8000; const REQ_BOOLEAN_ARG = self::REQ_ARG | 0x8000;
const REQ_ARRAY_ARG = self::REQ_ARG | 0x10000; const REQ_ARRAY_ARG = self::REQ_ARG | 0x10000;
const REQ_BACKED_ENUM_ARG = self::REQ_ARG | 0x20000;
const REQ_VALUES = 0; const REQ_VALUES = 0;
protected $general = null; protected $general = null;
@@ -37,182 +40,241 @@ abstract class Constraint{
protected $tested = false; protected $tested = false;
protected $reason = null; protected $reason = null;
abstract public function test():bool; abstract public function test(): bool;
static public function requiredValueType():int{ static public function requiredValueType(): int
{
return static::REQ_VALUES; return static::REQ_VALUES;
} }
public function setGeneral(array $general){ public function setGeneral(array $general)
{
$this->general = $general; $this->general = $general;
$this->tested = false; $this->tested = false;
$this->reason = null; $this->reason = null;
} }
public function setCity(array $city){ public function setCity(array $city)
{
$this->city = $city; $this->city = $city;
$this->tested = false; $this->tested = false;
$this->reason = null; $this->reason = null;
} }
public function setNation(array $nation){ public function setNation(array $nation)
{
$this->nation = $nation; $this->nation = $nation;
$this->tested = false; $this->tested = false;
$this->reason = null; $this->reason = null;
} }
public function setArg($arg){ public function setArg($arg)
{
$this->arg = $arg; $this->arg = $arg;
$this->tested = false; $this->tested = false;
$this->reason = null; $this->reason = null;
} }
public function setEnv($env){ public function setEnv($env)
{
$this->env = $env; $this->env = $env;
$this->tested = false; $this->tested = false;
$this->reason = null; $this->reason = null;
} }
public function setCmdArg($cmd_arg){ public function setCmdArg($cmd_arg)
{
$this->cmd_arg = $cmd_arg; $this->cmd_arg = $cmd_arg;
$this->tested = false; $this->tested = false;
$this->reason = null; $this->reason = null;
} }
public function setDestGeneral(array $general){ public function setDestGeneral(array $general)
{
$this->destGeneral = $general; $this->destGeneral = $general;
$this->tested = false; $this->tested = false;
$this->reason = null; $this->reason = null;
} }
public function setDestCity(array $city){ public function setDestCity(array $city)
{
$this->destCity = $city; $this->destCity = $city;
$this->tested = false; $this->tested = false;
$this->reason = null; $this->reason = null;
} }
public function setDestNation(array $nation){ public function setDestNation(array $nation)
{
$this->destNation = $nation; $this->destNation = $nation;
$this->tested = false; $this->tested = false;
$this->reason = null; $this->reason = null;
} }
static public function build(array $input):self{ static public function build(array $input): self
{
$self = new static(); $self = new static();
foreach($input as $key=>$value){ foreach ($input as $key => $value) {
if($value === null){ if ($value === null) {
continue; continue;
} }
switch($key){ switch ($key) {
case 'general': $self->setGeneral($value); break; case 'general':
case 'city': $self->setCity($value); break; $self->setGeneral($value);
case 'nation': $self->setNation($value); break; break;
case 'cmd_arg': $self->setCmdArg($value); break; case 'city':
$self->setCity($value);
break;
case 'nation':
$self->setNation($value);
break;
case 'cmd_arg':
$self->setCmdArg($value);
break;
case 'destGeneral': $self->setDestGeneral($value); break; case 'destGeneral':
case 'destCity': $self->setDestCity($value); break; $self->setDestGeneral($value);
case 'destNation': $self->setDestNation($value); break; break;
case 'destCity':
$self->setDestCity($value);
break;
case 'destNation':
$self->setDestNation($value);
break;
} }
} }
return $self; return $self;
} }
public function checkInputValues(bool $throwExeception=true):bool{ public function checkInputValues(bool $throwExeception = true): bool
{
$valueType = static::requiredValueType(); $valueType = static::requiredValueType();
if(($valueType&static::REQ_GENERAL) && $this->general === null){ if (($valueType & static::REQ_GENERAL) && $this->general === null) {
if(!$throwExeception){return false; } if (!$throwExeception) {
return false;
}
throw new \InvalidArgumentException('require general'); throw new \InvalidArgumentException('require general');
} }
if(($valueType&static::REQ_CITY) && $this->city === null){ if (($valueType & static::REQ_CITY) && $this->city === null) {
if(!$throwExeception){return false; } if (!$throwExeception) {
return false;
}
throw new \InvalidArgumentException('require city'); throw new \InvalidArgumentException('require city');
} }
if(($valueType&static::REQ_NATION) && $this->nation === null){ if (($valueType & static::REQ_NATION) && $this->nation === null) {
if(!$throwExeception){return false; } if (!$throwExeception) {
return false;
}
throw new \InvalidArgumentException('require nation'); throw new \InvalidArgumentException('require nation');
} }
if(($valueType&static::REQ_DEST_GENERAL) && $this->destGeneral === null){ if (($valueType & static::REQ_DEST_GENERAL) && $this->destGeneral === null) {
if(!$throwExeception){return false; } if (!$throwExeception) {
return false;
}
throw new \InvalidArgumentException('require dest general'); throw new \InvalidArgumentException('require dest general');
} }
if(($valueType&static::REQ_DEST_CITY) && $this->destCity === null){ if (($valueType & static::REQ_DEST_CITY) && $this->destCity === null) {
if(!$throwExeception){return false; } if (!$throwExeception) {
return false;
}
throw new \InvalidArgumentException('require dest city'); throw new \InvalidArgumentException('require dest city');
} }
if(($valueType&static::REQ_DEST_NATION) && $this->destNation === null){ if (($valueType & static::REQ_DEST_NATION) && $this->destNation === null) {
if(!$throwExeception){return false; } if (!$throwExeception) {
return false;
}
throw new \InvalidArgumentException('require dest nation'); throw new \InvalidArgumentException('require dest nation');
} }
if (!($valueType&static::REQ_ARG)) { if (!($valueType & static::REQ_ARG)) {
return true; return true;
} }
if($valueType === null){ if ($valueType === null) {
if(!$throwExeception){return false; } if (!$throwExeception) {
return false;
}
throw new \InvalidArgumentException('require arg'); throw new \InvalidArgumentException('require arg');
} }
if((($valueType&static::REQ_STRING_ARG)===static::REQ_STRING_ARG) && !is_string($this->arg)){ if ((($valueType & static::REQ_STRING_ARG) === static::REQ_STRING_ARG) && !is_string($this->arg)) {
if(!$throwExeception){return false; } if (!$throwExeception) {
return false;
}
throw new \InvalidArgumentException('require string arg'); throw new \InvalidArgumentException('require string arg');
} }
if((($valueType&static::REQ_BOOLEAN_ARG)===static::REQ_BOOLEAN_ARG) && !is_bool($this->arg)){ if ((($valueType & static::REQ_BOOLEAN_ARG) === static::REQ_BOOLEAN_ARG) && !is_bool($this->arg)) {
if(!$throwExeception){return false; } if (!$throwExeception) {
return false;
}
throw new \InvalidArgumentException('require bool arg'); throw new \InvalidArgumentException('require bool arg');
} }
if((($valueType&static::REQ_INT_ARG)===static::REQ_INT_ARG) && !is_int($this->arg)){ if ((($valueType & static::REQ_INT_ARG) === static::REQ_INT_ARG) && !is_int($this->arg)) {
if(!$throwExeception){return false; } if (!$throwExeception) {
return false;
}
throw new \InvalidArgumentException('require int arg'); throw new \InvalidArgumentException('require int arg');
} }
if((($valueType&static::REQ_NUMERIC_ARG)===static::REQ_NUMERIC_ARG) && !is_numeric($this->arg)){ if ((($valueType & static::REQ_NUMERIC_ARG) === static::REQ_NUMERIC_ARG) && !is_numeric($this->arg)) {
if(!$throwExeception){return false; } if (!$throwExeception) {
return false;
}
throw new \InvalidArgumentException('require numeric arg'); throw new \InvalidArgumentException('require numeric arg');
} }
if((($valueType&static::REQ_ARRAY_ARG)===static::REQ_ARRAY_ARG) && !is_array($this->arg)){ if ((($valueType & static::REQ_ARRAY_ARG) === static::REQ_ARRAY_ARG) && !is_array($this->arg)) {
if(!$throwExeception){return false; } if (!$throwExeception) {
return false;
}
throw new \InvalidArgumentException('require array arg'); throw new \InvalidArgumentException('require array arg');
} }
if ((($valueType & static::REQ_BACKED_ENUM_ARG) === static::REQ_BACKED_ENUM_ARG) && !($this->arg instanceof \BackedEnum)) {
if (!$throwExeception) {
return false;
}
throw new \InvalidArgumentException('require backed enum arg');
}
return true; return true;
} }
public function reason():?string{ public function reason(): ?string
if($this->tested === false){ {
throw new \RuntimeException(get_class($this).'::test가 실행되지 않음'); if ($this->tested === false) {
throw new \RuntimeException(get_class($this) . '::test가 실행되지 않음');
} }
return $this->reason; return $this->reason;
} }
public static function testAll(array $constraintPacks, array $input, array $env):?array{ public static function testAll(array $constraintPacks, array $input, array $env): ?array
foreach($constraintPacks as $constraintArgs){ {
if (!$constraintArgs){ foreach ($constraintPacks as $constraintArgs) {
if (!$constraintArgs) {
continue; continue;
} }
$constraintName = $constraintArgs[0]; $constraintName = $constraintArgs[0];
$method = __NAMESPACE__.'\\'.$constraintName.'::build'; $method = __NAMESPACE__ . '\\' . $constraintName . '::build';
/** @var \sammo\Constraint\Constraint $contraint */ /** @var \sammo\Constraint\Constraint $contraint */
$constraint = call_user_func($method,$input); $constraint = call_user_func($method, $input);
assert($constraint instanceof Constraint); assert($constraint instanceof Constraint);
$constraint->setEnv($env); $constraint->setEnv($env);
if(count($constraintArgs) == 2){ if (count($constraintArgs) == 2) {
$arg = $constraintArgs[1]; $arg = $constraintArgs[1];
$constraint->setArg($arg); $constraint->setArg($arg);
} }
if(!$constraint->test()){
if($constraint->reason() === null){ if (!$constraint->test()) {
throw new \RuntimeException('Reason is not set:'.$constraintName);
if ($constraint->reason() === null) {
throw new \RuntimeException('Reason is not set:' . $constraintName);
} }
return [$constraintName, $constraint->reason()]; return [$constraintName, $constraint->reason()];
} }
@@ -220,5 +282,4 @@ abstract class Constraint{
return null; return null;
} }
}
}
@@ -2,6 +2,8 @@
namespace sammo\Constraint; namespace sammo\Constraint;
use sammo\Enums\PenaltyKey;
class ConstraintHelper{ class ConstraintHelper{
static function AdhocCallback(callable $callback):array{ static function AdhocCallback(callable $callback):array{
@@ -176,6 +178,10 @@ class ConstraintHelper{
return [__FUNCTION__]; return [__FUNCTION__];
} }
static function NoPanelty(PenaltyKey $penaltyKey):array{
return [__FUNCTION__, $penaltyKey];
}
static function OccupiedCity(bool $allowNeutral=false):array{ static function OccupiedCity(bool $allowNeutral=false):array{
return [__FUNCTION__, $allowNeutral]; return [__FUNCTION__, $allowNeutral];
} }
+44
View File
@@ -0,0 +1,44 @@
<?php
namespace sammo\Constraint;
use sammo\Enums\PenaltyKey;
use sammo\Json;
class NoPanelty extends Constraint{
const REQ_VALUES = Constraint::REQ_GENERAL|Constraint::REQ_ARG|Constraint::REQ_BACKED_ENUM_ARG;
public function checkInputValues(bool $throwExeception=true):bool{
if(!parent::checkInputValues($throwExeception) && !$throwExeception){
return false;
}
if(!key_exists('penalty', $this->general)){
if(!$throwExeception){return false; }
throw new \InvalidArgumentException("require penalty in general");
}
if(!($this->arg instanceof PenaltyKey)){
if(!$throwExeception){return false; }
throw new \InvalidArgumentException("require penalty key");
}
return true;
}
public function test():bool{
$this->checkInputValues();
$this->tested = true;
/** @var PenaltyKey */
$checkKey = $this->arg;
$peneltyList = JSON::decode($this->general['penalty']);
if(!key_exists($checkKey->value, $peneltyList)){
return true;
}
$this->reason = "징계 사유: {$peneltyList[$checkKey->value]}";
return false;
}
}