Files
core/hwe/sammo/Event/Action/ChangeCity.php
T
Hide_D 42fac46062 refac: brandonwamboldt/utilphp 의존 코드 수정
- 실제 의존성 제거는 이후에에
2025-10-07 19:26:22 +09:00

190 lines
6.3 KiB
PHP

<?php
namespace sammo\Event\Action;
use sammo\Util;
use sammo\DB;
//기존 시나리오에서 개시 1월에 내정을 깎는 것을 모사.
class ChangeCity extends \sammo\Event\Action{
const AVAILABLE_KEY = [
'pop'=>true,
'agri'=>true,
'comm'=>true,
'secu'=>true,
'trust'=>true,
'def'=>true,
'wall'=>true,
'trade'=>true,
'pop_max'=>true,
'agri_max'=>true,
'comm_max'=>true,
'secu_max'=>true,
'def_max'=>true,
'wall_max'=>true,
];
const REGEXP_PERCENT = '/^(\d+(\.\d+)?)%$/';// 123.5% [1]=float
const REGEXP_MATH = '/^([\+\-\/\*])(\d+(\.\d+)?)$/'; //+30 [1]=기호, [2]=float
private $queries;
private $targetType = 'all';
private $targetArgs = [];
public function __construct($target, array $actions){
//values 포맷은 key, value로
if(!$target){
$this->targetType = 'all';
}
else if(is_string($target)){
$this->targetType = $target;
}
else if(is_array($target)){
$this->targetType = $target[0];
$this->targetArgs = array_slice($target, 1);
}
else{
throw new \InvalidArgumentException('올바르지 않은 targetType 입니다.');
}
$queries = [];
foreach($actions as $key => $value){
if(!key_exists($key, self::AVAILABLE_KEY)){
throw new \InvalidArgumentException('지원하지 않는 city 인자입니다 :'.$key);
}
if(!is_int($value) && !is_float($value) && !is_string($value)){
throw new \InvalidArgumentException('int, float, string이어야 합니다.');
}
if($key == 'trust'){
$queries['trust'] = $this->genSQLTrust($value);
continue;
}
if($key == 'trade'){
if($value === null){
$queries['trade'] = null;
}
else{
$queries['trade'] = Util::valueFit((float)$value, 95, 105);
}
continue;
}
$queries[$key] = $this->genSQLGeneric($key, $value);
}
$this->queries = $queries;
}
private function genSQLTrust($value){
//민심은 max값이 100으로 고정이므로 처리 방식이 다름.
if(is_float($value)){
if($value < 0){
throw new \InvalidArgumentException('음수를 곱할 수 없습니다.');
}
return DB::db()->sqleval('least(100, `trust` * %d)', $value);
}
if(is_int($value)){
return DB::db()->sqleval('%i', Util::valueFit($value, 0, 100));
}
$matches = null;
if(preg_match(self::REGEXP_PERCENT, $value, $matches)){
$value = Util::round((float)$matches[1]);
return DB::db()->sqleval('%i', Util::valueFit($value, 0, 100));
}
if(preg_match(self::REGEXP_MATH, $value, $matches)){
$op = $matches[1];
$value = $matches[2];
if($op == '/' && $value == 0){
throw new \InvalidArgumentException('0으로 나눌 수 없습니다.');
}
return DB::db()->sqleval('least(100, greatest(0, `trust` %l %d, 0)))', $op, $value);
}
throw new \InvalidArgumentException('알 수 없는 패턴입니다.');
}
private function genSQLGeneric($key, $value){
$keyMax = $key.'_max'; //comm, comm_max
if(is_float($value)){
if($value < 0){
throw new \InvalidArgumentException('음수를 곱할 수 없습니다.');
}
return DB::db()->sqleval('least(%b, ROUND(%b * %d, 0))', $keyMax, $key, $value);
}
if(is_int($value)){
return DB::db()->sqleval('least(%b, %i)', $keyMax, max(0, $value));
}
$matches = null;
if(preg_match(self::REGEXP_PERCENT, $value, $matches)){
$value = Util::round((float)$matches[1]);
return DB::db()->sqleval('ROUND(%b * %d, 0)', $keyMax, $value/100);
}
if(str_ends_with($key, '_max') && preg_match(self::REGEXP_MATH, $value, $matches)){
//key가 아예 최대치에 대한 값이면 연산은 결과값이 0보다만 높게.
$op = $matches[1];
$value = $matches[2];
if($op == '/' && $value == 0){
throw new \InvalidArgumentException('0으로 나눌 수 없습니다.');
}
return DB::db()->sqleval('greatest(0, ROUND(%b '.$op.' %i, 0))', $key, $value);
}
if(preg_match(self::REGEXP_MATH, $value, $matches)){
$op = $matches[1];
$value = $matches[2];
if($op == '/' && $value == 0){
throw new \InvalidArgumentException('0으로 나눌 수 없습니다.');
}
return DB::db()->sqleval('least(%b, greatest(0, ROUND(%b '.$op.' %i, 0)))', $keyMax, $key, $value);
}
throw new \InvalidArgumentException('알 수 없는 패턴입니다.');
}
private function getTargetCities($env){
$targetType = $this->targetType;
if($targetType == 'all'){
return DB::db()->queryFirstColumn('SELECT city FROM city');
}
if($targetType == 'free'){
return DB::db()->queryFirstColumn('SELECT city FROM city WHERE nation = 0');
}
if($targetType == 'occupied'){
return DB::db()->queryFirstColumn('SELECT city FROM city WHERE nation != 0');
}
if($targetType == 'cities'){
if(is_numeric($this->targetArgs)){
return DB::db()->queryFirstColumn('SELECT city FROM city WHERE city IN %ls', $this->targetArgs);
}
else{
return DB::db()->queryFirstColumn('SELECT city FROM city WHERE name IN %ls', $this->targetArgs);
}
}
throw new \InvalidArgumentException('올바르지 않은 cond 입니다.');
}
public function run(array $env){
$cities = $this->getTargetCities($env);
DB::db()->update('city',
$this->queries
, 'city IN %li', $cities);
return [__CLASS__, DB::db()->affectedRows()];
}
}