From 83d8e35ab7cb340a8ac6206fb83ea6e317950bca Mon Sep 17 00:00:00 2001 From: AIZAWA Hina Date: Sun, 21 Jun 2020 10:06:49 +0900 Subject: [PATCH 01/10] Remove monthly stats and defaults to "current version group"'s stats Now, we requires PHP 7.4+ --- .circleci/config.yml | 168 ------------------------------ .github/workflows/ci.yml | 2 - Dockerfile | 34 +++--- README.md | 9 +- actions/entire/Weapons2Action.php | 35 +++---- composer.json | 4 +- docker/env/scl-env.sh | 2 +- docker/php/php-config.diff | 16 +-- models/EntireWeapon2Form.php | 54 +++++----- models/SplatoonVersion2.php | 53 ++++++++-- 10 files changed, 117 insertions(+), 260 deletions(-) delete mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index c355c1c5c..000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,168 +0,0 @@ -version: 2 -jobs: - build: - working_directory: /app - docker: - - image: centos:7 - - image: postgres:11 - name: postgres - environment: - POSTGRES_USER: statink - POSTGRES_PASSWORD: statink - POSTGRES_DB: statink - POSTGRES_INITDB_ARGS: "-E UTF-8 --locale=en_US.UTF8 -k" - - steps: - - run: yum update -y - - run: yum install -y curl epel-release gnupg2 scl-utils 'http://rpms.famillecollet.com/enterprise/remi-release-7.rpm' - - run: curl -fsSL 'https://rpm.nodesource.com/setup_10.x' | bash - - - run: yum-config-manager --add-repo 'https://rpm.fetus.jp/jp3cki.repo' - - run: yum-config-manager --disable jp3cki* - - run: yum-config-manager --enable jp3cki-h2o-mainline - - run: yum install -y ImageMagick brotli diffutils gcc-c++ git gzip h2o jpegoptim make nodejs patch php73-php-cli php73-php-fpm php73-php-gd php73-php-intl php73-php-json php73-php-mbstring php73-php-mcrypt php73-php-opcache php73-php-pdo php73-php-pecl-msgpack php73-php-pecl-zip php73-php-pgsql php73-php-process php73-php-xml php73-runtime supervisor unzip - - checkout - - restore_cache: - keys: - - php-dependencies-v1-{{ checksum "composer.lock" }} - - php-dependencies-v1- - - restore_cache: - keys: - - js-node10-dependencies-v2-{{ checksum "package-lock.json" }} - - js-node10-dependencies-v2- - - run: scl enable php73 -- make init - - save_cache: - key: php-dependencies-v1-{{ checksum "composer.lock" }} - paths: - - ./vendor - - save_cache: - key: js-node12-dependencies-v1-{{ checksum "package-lock.json" }} - paths: - - ./node_modules - - run: scl enable php73 -- ./yii secret/db postgres statink - - run: scl enable php73 -- make - - build4next: - working_directory: /app - docker: - - image: centos:7 - - image: postgres:12 - name: postgres - environment: - POSTGRES_USER: statink - POSTGRES_PASSWORD: statink - POSTGRES_DB: statink - POSTGRES_INITDB_ARGS: "-E UTF-8 --locale=en_US.UTF8 -k" - - steps: - - run: yum update -y - - run: yum install -y curl epel-release gnupg2 scl-utils 'http://rpms.famillecollet.com/enterprise/remi-release-7.rpm' - - run: curl -fsSL 'https://rpm.nodesource.com/setup_11.x' | bash - - - run: yum-config-manager --add-repo 'https://rpm.fetus.jp/jp3cki.repo' - - run: yum-config-manager --disable jp3cki* - - run: yum-config-manager --enable jp3cki-h2o-mainline - - run: yum install -y ImageMagick brotli diffutils gcc-c++ git gzip h2o jpegoptim make nodejs patch php74-php-cli php74-php-fpm php74-php-gd php74-php-intl php74-php-json php74-php-mbstring php74-php-mcrypt php74-php-opcache php74-php-pdo php74-php-pecl-msgpack php74-php-pecl-zip php74-php-pgsql php74-php-process php74-php-sodium php74-php-xml php74-runtime supervisor unzip - - checkout - - restore_cache: - keys: - - php-dependencies-v1-{{ checksum "composer.lock" }} - - php-dependencies-v1- - - restore_cache: - keys: - - js-node11-dependencies-v2-{{ checksum "package-lock.json" }} - - js-node11-dependencies-v2- - - run: scl enable php74 -- make init - - save_cache: - key: js-node11-dependencies-v1-{{ checksum "package-lock.json" }} - paths: - - ./node_modules - - run: scl enable php74 -- ./yii secret/db postgres statink - - run: scl enable php74 -- make - - build_el8: - working_directory: /app - docker: - - image: centos:8 - - image: postgres:12 - name: postgres - environment: - POSTGRES_USER: statink - POSTGRES_PASSWORD: statink - POSTGRES_DB: statink - POSTGRES_INITDB_ARGS: "-E UTF-8 --locale=en_US.UTF8 -k" - - steps: - # TODO: Should be updated to use Python 3.6 - - run: dnf update -y - - run: dnf install -y epel-release - - run: | - sed -i.bak \ - -e 's%^metalink=%#metalink=%' \ - -e 's%^\(\[epel\]\)%\1\nbaseurl=https://download.fedoraproject.org/pub/epel/$releasever/Everything/$basearch https://ewr.edge.kernel.org/fedora-buffet/epel/$releasever/Everything/$basearch/ https://sjc.edge.kernel.org/fedora-buffet/epel/$releasever/Everything/$basearch/ http://ftp.jaist.ac.jp/pub/Linux/Fedora/epel/$releasever/Everything/$basearch/ http://ftp.riken.jp/Linux/fedora/epel/$releasever/Everything/$basearch/%' \ - /etc/yum.repos.d/epel.repo - - run: dnf install -y 'dnf-command(config-manager)' 'https://rpms.remirepo.net/enterprise/remi-release-8.rpm' - - run: dnf module enable -y 'php:remi-7.4' 'nodejs:12' 'python27:2.7' - - run: dnf config-manager --add-repo 'https://rpm.fetus.jp/jp3cki.repo' - - run: dnf config-manager --save --disable jp3cki* - - run: dnf config-manager --save --enable jp3cki-h2o-mainline - - run: | - dnf install -y \ - @python27 \ - ImageMagick \ - brotli \ - diffutils \ - gcc-c++ \ - git \ - gzip \ - h2o \ - jpegoptim \ - make \ - nodejs \ - patch \ - php-cli \ - php-fpm \ - php-gd \ - php-intl \ - php-json \ - php-mbstring \ - php-mcrypt \ - php-opcache \ - php-pdo \ - php-pecl-msgpack \ - php-pecl-zip \ - php-pgsql \ - php-process \ - php-sodium \ - php-xml \ - unzip - - run: alternatives --set python /usr/bin/python2 - - checkout - - restore_cache: - keys: - - el8-php74-dependencies-v1-{{ checksum "composer.lock" }} - - el8-php74-dependencies-v1- - - restore_cache: - keys: - - el8-js-node12-dependencies-v1-{{ checksum "package-lock.json" }} - - el8-js-node12-dependencies-v1- - - run: make init - - save_cache: - key: el8-php74-dependencies-v1-{{ checksum "composer.lock" }} - paths: - - ./vendor - - save_cache: - key: el8-js-node12-dependencies-v1-{{ checksum "package-lock.json" }} - paths: - - ./node_modules - - run: ./yii secret/db postgres statink - - run: make -workflows: - version: 2 - build_current: - jobs: - - build - build_next: - jobs: - - build4next - build_el8: - jobs: - - build_el8 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54729b5bf..23f06b022 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,6 @@ jobs: strategy: matrix: php_version: - - '7.3' - '7.4' runs-on: 'ubuntu-latest' needs: @@ -89,7 +88,6 @@ jobs: strategy: matrix: php_version: - - '7.3' - '7.4' pgsql_version: - '9.5-alpine' # minimum requirement diff --git a/Dockerfile b/Dockerfile index c1b760110..8f9a4c17e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -33,21 +33,21 @@ RUN rpm --import \ make \ nodejs \ patch \ - php73-php-cli \ - php73-php-fpm \ - php73-php-gd \ - php73-php-intl \ - php73-php-json \ - php73-php-mbstring \ - php73-php-mcrypt \ - php73-php-opcache \ - php73-php-pdo \ - php73-php-pecl-msgpack \ - php73-php-pecl-zip \ - php73-php-pgsql \ - php73-php-process \ - php73-php-xml \ - php73-runtime \ + php74-php-cli \ + php74-php-fpm \ + php74-php-gd \ + php74-php-intl \ + php74-php-json \ + php74-php-mbstring \ + php74-php-mcrypt \ + php74-php-opcache \ + php74-php-pdo \ + php74-php-pecl-msgpack \ + php74-php-pecl-zip \ + php74-php-pgsql \ + php74-php-process \ + php74-php-xml \ + php74-runtime \ rh-postgresql95-postgresql \ rh-postgresql95-postgresql-server \ supervisor \ @@ -72,7 +72,7 @@ USER postgres RUN scl enable rh-postgresql95 'initdb --pgdata=/var/opt/rh/rh-postgresql95/lib/pgsql/data --encoding=UNICODE --locale=en_US.UTF8' ADD docker/database/pg_hba.conf /var/opt/rh/rh-postgresql95/lib/pgsql/data/pg_hba.conf ADD docker/database/password.php /var/opt/rh/rh-postgresql95/lib/pgsql/ -RUN scl enable rh-postgresql95 php73 ' \ +RUN scl enable rh-postgresql95 php74 ' \ /opt/rh/rh-postgresql95/root/usr/libexec/postgresql-ctl start -D /var/opt/rh/rh-postgresql95/lib/pgsql/data -s -w && \ createuser -DRS statink && \ createdb -E UNICODE -O statink -T template0 statink && \ @@ -88,7 +88,7 @@ RUN cd ~statink/stat.ink && \ su postgres -c "/opt/rh/rh-postgresql95/root/usr/libexec/postgresql-ctl stop -D /var/opt/rh/rh-postgresql95/lib/pgsql/data -s -m fast"' ADD docker/php/php-config.diff /tmp/ -RUN patch -p1 -d /etc/opt/remi/php73 < /tmp/php-config.diff && rm /tmp/php-config.diff +RUN patch -p1 -d /etc/opt/remi/php74 < /tmp/php-config.diff && rm /tmp/php-config.diff ADD docker/h2o/h2o.conf /etc/h2o/h2o.conf diff --git a/README.md b/README.md index 53f1b0396..a05bd8b1c 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,8 @@ Use a private channel if it is a security issue. REQUIREMENTS ------------ -- PHP 7.3+ (Recommended: 7.4+) - - Doesn't work with 7.2 or lower. (Uses statements and constants added in v7.3) +- PHP 7.4+ + - Doesn't work with 7.3 or lower. (Uses statements and constants added in v7.4, such as arrow function and typed property) - You should build/install with Argon2. [Install `php-sodium` if you use remirepo's PHP 7.4](https://github.com/remicollet/remirepo/issues/132#issuecomment-566513636). - PostgreSQL 9.5+ (Recommended: 11+) - Doesn't work with 9.4 or lower. (Uses features added in v9.5) @@ -72,11 +72,8 @@ https://stat.ink/ works with: Notes: - - We will soon be changing the minimum requirement to PHP 7.4. - The author wants to use the [typed properties](https://www.php.net/manual/en/migration74.new-features.php#migration74.new-features.core.typed-properties). - - Default version of PHP on CentOS 7 is 5.4.16. This application doesn't work on it. - We are using features and statements that were added up to PHP 7.3. + We are using features and statements that were added up to PHP 7.4. - Default version of PostgreSQL on CentOS 7 is 9.2.14. This application doesn't work with it. We are using features added in PostgreSQL 9.5 (e.g., jsonb, UPSERT). diff --git a/actions/entire/Weapons2Action.php b/actions/entire/Weapons2Action.php index 113b45a5a..f4699bacd 100644 --- a/actions/entire/Weapons2Action.php +++ b/actions/entire/Weapons2Action.php @@ -1,7 +1,7 @@ */ @@ -10,7 +10,6 @@ namespace app\actions\entire; -use stdClass; use DateInterval; use DateTime; use DateTimeImmutable; @@ -25,15 +24,20 @@ use app\models\StatWeapon2UseCount; use app\models\Subweapon2; use app\models\Weapon2; +use stdClass; use yii\db\Query; -use yii\web\ViewAction as BaseAction; +use yii\web\ViewAction; -class Weapons2Action extends BaseAction +class Weapons2Action extends ViewAction { public function run() { - $form = Yii::createObject(['class' => EntireWeapon2Form::class]); - $form->load($_GET) && $form->validate(); + $form = Yii::createObject([ + '__class' => EntireWeapon2Form::class, + ]); + if (!$form->load($_GET) || !$form->validate()) { + $form->updateToDefault(); + } return $this->controller->render('weapons2', [ 'form' => $form, @@ -247,21 +251,12 @@ private function getEntireWeaponsByRule(Rule2 $rule, EntireWeapon2Form $form) '{{map2}}.[[key]]' => $form->map, ]); } - if ($form->term == '') { + if ( + $form->term === null || + $form->term === '' || + $form->term === '*' + ) { // nothing to do - } elseif (preg_match('/^(\d{4})-(\d{2})$/', $form->term, $match)) { - // [$start, $end) - $start = (new DateTimeImmutable()) - ->setTimeZone(new DateTimeZone('Etc/UTC')) - ->setDate(intval($match[1], 10), intval($match[2], 10), 1) - ->setTime(0, 0, 0); - $end = $start->add(new DateInterval('P1M')); - $startPeriod = BattleHelper::calcPeriod2($start->getTimestamp()); - $endPeriod = BattleHelper::calcPeriod2($end->getTimestamp()); - $query->andWhere(['and', - ['>=', '{{stat_weapon2_use_count}}.[[period]]', $startPeriod], - ['<', '{{stat_weapon2_use_count}}.[[period]]', $endPeriod], - ]); } elseif (substr($form->term, 0, 1) === 'v') { if (!$v1 = SplatoonVersion2::findOne(['tag' => substr($form->term, 1)])) { throw new \Exception(); diff --git a/composer.json b/composer.json index 5b064e28e..81ecc9303 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "license": "MIT", "minimum-stability": "stable", "require": { - "php": ">= 7.3.0", + "php": ">= 7.4.0", "ext-PDO": "*", "ext-curl": "*", "ext-date": "*", @@ -105,7 +105,7 @@ "enabled": false }, "platform": { - "php": "7.3.15" + "php": "7.4.7" } }, "extra": { diff --git a/docker/env/scl-env.sh b/docker/env/scl-env.sh index 1c34c4a8f..6b043fa1f 100644 --- a/docker/env/scl-env.sh +++ b/docker/env/scl-env.sh @@ -1,3 +1,3 @@ -source /opt/remi/php73/enable +source /opt/remi/php74/enable source /opt/rh/git19/enable source /opt/rh/rh-postgresql95/enable diff --git a/docker/php/php-config.diff b/docker/php/php-config.diff index 3611559d0..5cb0b2ef9 100644 --- a/docker/php/php-config.diff +++ b/docker/php/php-config.diff @@ -1,6 +1,6 @@ -diff -ru php73.o/php-fpm.d/www.conf php73/php-fpm.d/www.conf ---- php73.o/php-fpm.d/www.conf -+++ php73/php-fpm.d/www.conf +diff -ru php74.o/php-fpm.d/www.conf php74/php-fpm.d/www.conf +--- php74.o/php-fpm.d/www.conf ++++ php74/php-fpm.d/www.conf @@ -21,7 +21,7 @@ ; Note: The user is mandatory. If the group is not set, the default user's group ; will be used. @@ -11,15 +11,15 @@ diff -ru php73.o/php-fpm.d/www.conf php73/php-fpm.d/www.conf group = apache @@ -420,3 +420,6 @@ - php_value[soap.wsdl_cache_dir] = /var/opt/remi/php73/lib/php/wsdlcache + php_value[soap.wsdl_cache_dir] = /var/opt/remi/php74/lib/php/wsdlcache - ;php_value[opcache.file_cache] = /var/opt/remi/php73/lib/php/opcache + ;php_value[opcache.file_cache] = /var/opt/remi/php74/lib/php/opcache + +php_admin_value[upload_max_filesize] = 12M +php_admin_value[post_max_size] = 13M -diff -ru php73.o/php.ini php73/php.ini ---- php73.o/php.ini -+++ php73/php.ini +diff -ru php74.o/php.ini php74/php.ini +--- php74.o/php.ini ++++ php74/php.ini @@ -356,7 +356,7 @@ ; threat in any way, but it makes it possible to determine whether you use PHP ; on your server or not. diff --git a/models/EntireWeapon2Form.php b/models/EntireWeapon2Form.php index 0f1f096d3..3bcd8bc15 100644 --- a/models/EntireWeapon2Form.php +++ b/models/EntireWeapon2Form.php @@ -1,16 +1,15 @@ */ +declare(strict_types=1); + namespace app\models; -use DateInterval; -use DateTimeImmutable; -use DateTimeZone; use Yii; use app\models\Map2; use yii\base\Model; @@ -28,11 +27,13 @@ public function formName() public function rules() { return [ + [['term'], 'required'], [['term', 'map'], 'string'], [['term'], 'in', 'range' => array_keys($this->getTermList()), ], - [['map'], 'exist', 'skipOnError' => true, + [['map'], 'exist', + 'skipOnError' => true, 'targetClass' => Map2::class, 'targetAttribute' => 'key', ], @@ -60,23 +61,27 @@ public function toQueryParams($formName = false) } $ret[$key] = $value; }; + foreach ($this->attributes as $key => $value) { $push($key, $value); } + return $ret; } + private $cachedTermList; public function getTermList(): array { - static $list; - if (!$list) { - $list = array_merge( - ['' => Yii::t('app', 'Any Time')], + if (!$this->cachedTermList) { + $this->cachedTermList = array_merge( + [ + '*' => Yii::t('app', 'Any Time'), + ], $this->getVersionList(), - $this->getMonthList() ); } - return $list; + + return $this->cachedTermList; } private function getVersionList(): array @@ -121,21 +126,18 @@ private function getVersionList(): array return $result; } - private function getMonthList(): array + public function updateToDefault(): self { - $interval = new DateInterval('P1M'); - $date = (new DateTimeImmutable()) - ->setTimeZone(new DateTimeZone('Etc/UTC')) - ->setDate(2017, 7, 1) - ->setTime(0, 0, 0); - $limit = (new DateTimeImmutable()) - ->setTimeZone(new DateTimeZone('Etc/UTC')) - ->setTimestamp($_SERVER['REQUEST_TIME'] ?? time()); - $formatter = Yii::$app->formatter; - $result = []; - for (; $date <= $limit; $date = $date->add($interval)) { - $result[$date->format('Y-m')] = $formatter->asDate($date, Yii::t('app', 'MMMM y')); - } - return array_reverse($result, true); + $this->term = vsprintf('~v%s', [ + $this->getLatestVersionGroup()->tag, + ]); + $this->map = ''; + $this->clearErrors(); + return $this; + } + + private function getLatestVersionGroup(): SplatoonVersionGroup2 + { + return SplatoonVersion2::findCurrentVersion()->group; } } diff --git a/models/SplatoonVersion2.php b/models/SplatoonVersion2.php index f07d1b794..eb4127697 100644 --- a/models/SplatoonVersion2.php +++ b/models/SplatoonVersion2.php @@ -1,14 +1,21 @@ */ +declare(strict_types=1); + namespace app\models; +use DateTime; +use DateTimeImmutable; +use DateTimeInterface; +use DateTimeZone; use Yii; +use yii\db\ActiveQuery; use yii\db\ActiveRecord; /** @@ -26,19 +33,45 @@ */ class SplatoonVersion2 extends ActiveRecord { + public static function find(): ActiveQuery + { + return new class (static::class) extends ActiveQuery { + public function __construct(string $modelClass, array $config = []) + { + parent::__construct($modelClass, $config); + + list(, $t) = $this->getTableNameAndAlias(); + $this->orderBy([ + "{{{$t}}}.[[released_at]]" => SORT_DESC, + ]); + } + + public function released(?DateTimeInterface $at = null): self + { + if (!$at) { + $at = (new DateTimeImmutable()) + ->setTimeZone(new DateTimeZone(Yii::$app->timeZone)) + ->setTimestamp($_SERVER['REQUEST_TIME'] ?? time()); + } + + list(, $t) = $this->getTableNameAndAlias(); + $this->andWhere(['<=', "{{{$t}}}.[[released_at]]", $at->format(DateTime::ATOM)]); + return $this; + } + }; + } + public static function findCurrentVersion($at = null): ?self { - if ($at === null) { - $at = (int)($_SERVER['REQUEST_TIME'] ?? time()); - } - if (is_int($at)) { - $at = gmdate('Y-m-d\TH:i:sP', $at); - } elseif ($at instanceof \DateTimeInterface) { - $at = $at->format('Y-m-d\TH:i:sP'); + if ($at !== null && !($at instanceof DateTimeInterface)) { + $ts = Yii::$app->formatter->asTimestamp($at); + $at = (new DateTimeImmutable()) + ->setTimeZone(new DateTimeZone(Yii::$app->timeZone)) + ->setTimestamp((int)$ts); } + return static::find() - ->andWhere(['<=', 'released_at', $at]) - ->orderBy('[[released_at]] DESC') + ->released($at) ->limit(1) ->one(); } From 27fcf36f52cd340e6cbfa27298c0dd46e0c0bb1a Mon Sep 17 00:00:00 2001 From: AIZAWA Hina Date: Sun, 21 Jun 2020 21:58:38 +0900 Subject: [PATCH 02/10] Add table definitions for rewrite entire/weapons2 --- migrations/m200621_120537_entire_weapon2.php | 106 +++++++++++++++++++ models/StatWeapon2EntireMain.php | 94 ++++++++++++++++ models/StatWeapon2EntireMainByVersion.php | 103 ++++++++++++++++++ models/StatWeapon2EntireMainByVgroup.php | 103 ++++++++++++++++++ models/StatWeapon2EntireSpecial.php | 94 ++++++++++++++++ models/StatWeapon2EntireSpecialByVersion.php | 103 ++++++++++++++++++ models/StatWeapon2EntireSpecialByVgroup.php | 103 ++++++++++++++++++ models/StatWeapon2EntireSub.php | 94 ++++++++++++++++ models/StatWeapon2EntireSubByVersion.php | 103 ++++++++++++++++++ models/StatWeapon2EntireSubByVgroup.php | 103 ++++++++++++++++++ 10 files changed, 1006 insertions(+) create mode 100644 migrations/m200621_120537_entire_weapon2.php create mode 100644 models/StatWeapon2EntireMain.php create mode 100644 models/StatWeapon2EntireMainByVersion.php create mode 100644 models/StatWeapon2EntireMainByVgroup.php create mode 100644 models/StatWeapon2EntireSpecial.php create mode 100644 models/StatWeapon2EntireSpecialByVersion.php create mode 100644 models/StatWeapon2EntireSpecialByVgroup.php create mode 100644 models/StatWeapon2EntireSub.php create mode 100644 models/StatWeapon2EntireSubByVersion.php create mode 100644 models/StatWeapon2EntireSubByVgroup.php diff --git a/migrations/m200621_120537_entire_weapon2.php b/migrations/m200621_120537_entire_weapon2.php new file mode 100644 index 000000000..11810f1d6 --- /dev/null +++ b/migrations/m200621_120537_entire_weapon2.php @@ -0,0 +1,106 @@ + + */ + +declare(strict_types=1); + +use app\components\db\Migration; + +class m200621_120537_entire_weapon2 extends Migration +{ + public function safeUp() + { + $tables = $this->tables; + array_walk($tables, fn ($def, $name) => $this->createTable($name, $def)); + + if (true) { + echo "\n"; + foreach (array_keys($tables) as $name) { + vprintf("./yii gii/model --tableName=%s --modelClass=%s --interactive=0 --overwrite\n", [ + escapeshellarg($name), + escapeshellarg(implode('', array_map('ucfirst', explode('_', $name)))), + ]); + } + } + } + + public function safeDown() + { + $this->dropTables(array_keys($this->tables)); + } + + public function getTables(): array + { + $tables = []; + + foreach ($this->versionMap as $vTableSuffix => $vRefs) { + foreach ($this->weaponMap as $wTableSuffix => $wRefs) { + $tableName = ($vTableSuffix === '') + ? sprintf('stat_weapon2_entire_%s', $wTableSuffix) + : sprintf('stat_weapon2_entire_%s_by_%s', $wTableSuffix, $vTableSuffix); + $def = array_merge( + ['rule_id' => $this->pkRef('rule2')->notNull()], + $vRefs + ? array_map(fn ($_) => $this->pkRef($_[0], $_[1])->notNull(), $vRefs) + : [], + $wRefs + ? array_map(fn ($_) => $this->pkRef($_[0], $_[1])->notNull(), $wRefs) + : [], + [ + 'battles' => $this->bigInteger()->notNull(), + 'wins' => $this->bigInteger()->notNull(), + 'avg_kill' => $this->double()->notNull(), + 'med_kill' => $this->double()->notNull(), + 'stddev_kill' => $this->double()->null(), + 'avg_death' => $this->double()->notNull(), + 'med_death' => $this->double()->notNull(), + 'stddev_death' => $this->double()->null(), + 'avg_special' => $this->double()->notNull(), + 'med_special' => $this->double()->notNull(), + 'stddev_special' => $this->double()->null(), + 'avg_point' => $this->double()->notNull(), + 'med_point' => $this->double()->notNull(), + 'stddev_point' => $this->double()->null(), + 'avg_time' => $this->double()->notNull(), + 'updated_at' => $this->timestampTZ()->notNull(), + ] + ); + $tables[$tableName] = $def; + } + } + + return $tables; + } + + public function getVersionMap(): array + { + return [ + '' => null, + 'version' => [ + 'version_id' => ['splatoon_version2', 'id'], + ], + 'vgroup' => [ + 'version_group_id' => ['splatoon_version_group2', 'id'], + ], + ]; + } + + public function getWeaponMap(): array + { + return [ + 'main' => [ + 'weapon_id' => ['weapon2', 'id'], + ], + 'sub' => [ + 'subweapon_id' => ['subweapon2', 'id'], + ], + 'special' => [ + 'special_id' => ['special2', 'id'], + ], + ]; + } +} diff --git a/models/StatWeapon2EntireMain.php b/models/StatWeapon2EntireMain.php new file mode 100644 index 000000000..f87fcf23e --- /dev/null +++ b/models/StatWeapon2EntireMain.php @@ -0,0 +1,94 @@ + + */ + +declare(strict_types=1); + +namespace app\models; + +use Yii; +use yii\db\ActiveQuery; +use yii\db\ActiveRecord; + +/** + * This is the model class for table "stat_weapon2_entire_main". + * + * @property integer $rule_id + * @property integer $weapon_id + * @property integer $battles + * @property integer $wins + * @property double $avg_kill + * @property double $med_kill + * @property double $stddev_kill + * @property double $avg_death + * @property double $med_death + * @property double $stddev_death + * @property double $avg_special + * @property double $med_special + * @property double $stddev_special + * @property double $avg_point + * @property double $med_point + * @property double $stddev_point + * @property double $avg_time + * @property string $updated_at + * + * @property Rule2 $rule + * @property Weapon2 $weapon + */ +class StatWeapon2EntireMain extends ActiveRecord +{ + public static function tableName() + { + return 'stat_weapon2_entire_main'; + } + + public function rules() + { + return [ + [['rule_id', 'weapon_id', 'battles', 'wins', 'avg_kill', 'med_kill', 'avg_death', 'med_death', 'avg_special', 'med_special', 'avg_point', 'med_point', 'avg_time', 'updated_at'], 'required'], + [['rule_id', 'weapon_id', 'battles', 'wins'], 'default', 'value' => null], + [['rule_id', 'weapon_id', 'battles', 'wins'], 'integer'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['updated_at'], 'safe'], + [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], + [['weapon_id'], 'exist', 'skipOnError' => true, 'targetClass' => Weapon2::class, 'targetAttribute' => ['weapon_id' => 'id']], + ]; + } + + public function attributeLabels() + { + return [ + 'rule_id' => 'Rule ID', + 'weapon_id' => 'Weapon ID', + 'battles' => 'Battles', + 'wins' => 'Wins', + 'avg_kill' => 'Avg Kill', + 'med_kill' => 'Med Kill', + 'stddev_kill' => 'Stddev Kill', + 'avg_death' => 'Avg Death', + 'med_death' => 'Med Death', + 'stddev_death' => 'Stddev Death', + 'avg_special' => 'Avg Special', + 'med_special' => 'Med Special', + 'stddev_special' => 'Stddev Special', + 'avg_point' => 'Avg Point', + 'med_point' => 'Med Point', + 'stddev_point' => 'Stddev Point', + 'avg_time' => 'Avg Time', + 'updated_at' => 'Updated At', + ]; + } + + public function getRule(): ActiveQuery + { + return $this->hasOne(Rule2::class, ['id' => 'rule_id']); + } + + public function getWeapon(): ActiveQuery + { + return $this->hasOne(Weapon2::class, ['id' => 'weapon_id']); + } +} diff --git a/models/StatWeapon2EntireMainByVersion.php b/models/StatWeapon2EntireMainByVersion.php new file mode 100644 index 000000000..88cfef326 --- /dev/null +++ b/models/StatWeapon2EntireMainByVersion.php @@ -0,0 +1,103 @@ + + */ + +declare(strict_types=1); + +namespace app\models; + +use Yii; +use yii\db\ActiveQuery; +use yii\db\ActiveRecord; + +/** + * This is the model class for table "stat_weapon2_entire_main_by_version". + * + * @property integer $rule_id + * @property integer $version_id + * @property integer $weapon_id + * @property integer $battles + * @property integer $wins + * @property double $avg_kill + * @property double $med_kill + * @property double $stddev_kill + * @property double $avg_death + * @property double $med_death + * @property double $stddev_death + * @property double $avg_special + * @property double $med_special + * @property double $stddev_special + * @property double $avg_point + * @property double $med_point + * @property double $stddev_point + * @property double $avg_time + * @property string $updated_at + * + * @property Rule2 $rule + * @property SplatoonVersion2 $version + * @property Weapon2 $weapon + */ +class StatWeapon2EntireMainByVersion extends ActiveRecord +{ + public static function tableName() + { + return 'stat_weapon2_entire_main_by_version'; + } + + public function rules() + { + return [ + [['rule_id', 'version_id', 'weapon_id', 'battles', 'wins', 'avg_kill', 'med_kill', 'avg_death', 'med_death', 'avg_special', 'med_special', 'avg_point', 'med_point', 'avg_time', 'updated_at'], 'required'], + [['rule_id', 'version_id', 'weapon_id', 'battles', 'wins'], 'default', 'value' => null], + [['rule_id', 'version_id', 'weapon_id', 'battles', 'wins'], 'integer'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['updated_at'], 'safe'], + [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], + [['version_id'], 'exist', 'skipOnError' => true, 'targetClass' => SplatoonVersion2::class, 'targetAttribute' => ['version_id' => 'id']], + [['weapon_id'], 'exist', 'skipOnError' => true, 'targetClass' => Weapon2::class, 'targetAttribute' => ['weapon_id' => 'id']], + ]; + } + + public function attributeLabels() + { + return [ + 'rule_id' => 'Rule ID', + 'version_id' => 'Version ID', + 'weapon_id' => 'Weapon ID', + 'battles' => 'Battles', + 'wins' => 'Wins', + 'avg_kill' => 'Avg Kill', + 'med_kill' => 'Med Kill', + 'stddev_kill' => 'Stddev Kill', + 'avg_death' => 'Avg Death', + 'med_death' => 'Med Death', + 'stddev_death' => 'Stddev Death', + 'avg_special' => 'Avg Special', + 'med_special' => 'Med Special', + 'stddev_special' => 'Stddev Special', + 'avg_point' => 'Avg Point', + 'med_point' => 'Med Point', + 'stddev_point' => 'Stddev Point', + 'avg_time' => 'Avg Time', + 'updated_at' => 'Updated At', + ]; + } + + public function getRule(): ActiveQuery + { + return $this->hasOne(Rule2::class, ['id' => 'rule_id']); + } + + public function getVersion(): ActiveQuery + { + return $this->hasOne(SplatoonVersion2::class, ['id' => 'version_id']); + } + + public function getWeapon(): ActiveQuery + { + return $this->hasOne(Weapon2::class, ['id' => 'weapon_id']); + } +} diff --git a/models/StatWeapon2EntireMainByVgroup.php b/models/StatWeapon2EntireMainByVgroup.php new file mode 100644 index 000000000..75ab0d430 --- /dev/null +++ b/models/StatWeapon2EntireMainByVgroup.php @@ -0,0 +1,103 @@ + + */ + +declare(strict_types=1); + +namespace app\models; + +use Yii; +use yii\db\ActiveQuery; +use yii\db\ActiveRecord; + +/** + * This is the model class for table "stat_weapon2_entire_main_by_vgroup". + * + * @property integer $rule_id + * @property integer $version_group_id + * @property integer $weapon_id + * @property integer $battles + * @property integer $wins + * @property double $avg_kill + * @property double $med_kill + * @property double $stddev_kill + * @property double $avg_death + * @property double $med_death + * @property double $stddev_death + * @property double $avg_special + * @property double $med_special + * @property double $stddev_special + * @property double $avg_point + * @property double $med_point + * @property double $stddev_point + * @property double $avg_time + * @property string $updated_at + * + * @property Rule2 $rule + * @property SplatoonVersionGroup2 $versionGroup + * @property Weapon2 $weapon + */ +class StatWeapon2EntireMainByVgroup extends ActiveRecord +{ + public static function tableName() + { + return 'stat_weapon2_entire_main_by_vgroup'; + } + + public function rules() + { + return [ + [['rule_id', 'version_group_id', 'weapon_id', 'battles', 'wins', 'avg_kill', 'med_kill', 'avg_death', 'med_death', 'avg_special', 'med_special', 'avg_point', 'med_point', 'avg_time', 'updated_at'], 'required'], + [['rule_id', 'version_group_id', 'weapon_id', 'battles', 'wins'], 'default', 'value' => null], + [['rule_id', 'version_group_id', 'weapon_id', 'battles', 'wins'], 'integer'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['updated_at'], 'safe'], + [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], + [['version_group_id'], 'exist', 'skipOnError' => true, 'targetClass' => SplatoonVersionGroup2::class, 'targetAttribute' => ['version_group_id' => 'id']], + [['weapon_id'], 'exist', 'skipOnError' => true, 'targetClass' => Weapon2::class, 'targetAttribute' => ['weapon_id' => 'id']], + ]; + } + + public function attributeLabels() + { + return [ + 'rule_id' => 'Rule ID', + 'version_group_id' => 'Version Group ID', + 'weapon_id' => 'Weapon ID', + 'battles' => 'Battles', + 'wins' => 'Wins', + 'avg_kill' => 'Avg Kill', + 'med_kill' => 'Med Kill', + 'stddev_kill' => 'Stddev Kill', + 'avg_death' => 'Avg Death', + 'med_death' => 'Med Death', + 'stddev_death' => 'Stddev Death', + 'avg_special' => 'Avg Special', + 'med_special' => 'Med Special', + 'stddev_special' => 'Stddev Special', + 'avg_point' => 'Avg Point', + 'med_point' => 'Med Point', + 'stddev_point' => 'Stddev Point', + 'avg_time' => 'Avg Time', + 'updated_at' => 'Updated At', + ]; + } + + public function getRule(): ActiveQuery + { + return $this->hasOne(Rule2::class, ['id' => 'rule_id']); + } + + public function getVersionGroup(): ActiveQuery + { + return $this->hasOne(SplatoonVersionGroup2::class, ['id' => 'version_group_id']); + } + + public function getWeapon(): ActiveQuery + { + return $this->hasOne(Weapon2::class, ['id' => 'weapon_id']); + } +} diff --git a/models/StatWeapon2EntireSpecial.php b/models/StatWeapon2EntireSpecial.php new file mode 100644 index 000000000..b8d342dd7 --- /dev/null +++ b/models/StatWeapon2EntireSpecial.php @@ -0,0 +1,94 @@ + + */ + +declare(strict_types=1); + +namespace app\models; + +use Yii; +use yii\db\ActiveQuery; +use yii\db\ActiveRecord; + +/** + * This is the model class for table "stat_weapon2_entire_special". + * + * @property integer $rule_id + * @property integer $special_id + * @property integer $battles + * @property integer $wins + * @property double $avg_kill + * @property double $med_kill + * @property double $stddev_kill + * @property double $avg_death + * @property double $med_death + * @property double $stddev_death + * @property double $avg_special + * @property double $med_special + * @property double $stddev_special + * @property double $avg_point + * @property double $med_point + * @property double $stddev_point + * @property double $avg_time + * @property string $updated_at + * + * @property Rule2 $rule + * @property Special2 $special + */ +class StatWeapon2EntireSpecial extends ActiveRecord +{ + public static function tableName() + { + return 'stat_weapon2_entire_special'; + } + + public function rules() + { + return [ + [['rule_id', 'special_id', 'battles', 'wins', 'avg_kill', 'med_kill', 'avg_death', 'med_death', 'avg_special', 'med_special', 'avg_point', 'med_point', 'avg_time', 'updated_at'], 'required'], + [['rule_id', 'special_id', 'battles', 'wins'], 'default', 'value' => null], + [['rule_id', 'special_id', 'battles', 'wins'], 'integer'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['updated_at'], 'safe'], + [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], + [['special_id'], 'exist', 'skipOnError' => true, 'targetClass' => Special2::class, 'targetAttribute' => ['special_id' => 'id']], + ]; + } + + public function attributeLabels() + { + return [ + 'rule_id' => 'Rule ID', + 'special_id' => 'Special ID', + 'battles' => 'Battles', + 'wins' => 'Wins', + 'avg_kill' => 'Avg Kill', + 'med_kill' => 'Med Kill', + 'stddev_kill' => 'Stddev Kill', + 'avg_death' => 'Avg Death', + 'med_death' => 'Med Death', + 'stddev_death' => 'Stddev Death', + 'avg_special' => 'Avg Special', + 'med_special' => 'Med Special', + 'stddev_special' => 'Stddev Special', + 'avg_point' => 'Avg Point', + 'med_point' => 'Med Point', + 'stddev_point' => 'Stddev Point', + 'avg_time' => 'Avg Time', + 'updated_at' => 'Updated At', + ]; + } + + public function getRule(): ActiveQuery + { + return $this->hasOne(Rule2::class, ['id' => 'rule_id']); + } + + public function getSpecial(): ActiveQuery + { + return $this->hasOne(Special2::class, ['id' => 'special_id']); + } +} diff --git a/models/StatWeapon2EntireSpecialByVersion.php b/models/StatWeapon2EntireSpecialByVersion.php new file mode 100644 index 000000000..0445059da --- /dev/null +++ b/models/StatWeapon2EntireSpecialByVersion.php @@ -0,0 +1,103 @@ + + */ + +declare(strict_types=1); + +namespace app\models; + +use Yii; +use yii\db\ActiveQuery; +use yii\db\ActiveRecord; + +/** + * This is the model class for table "stat_weapon2_entire_special_by_version". + * + * @property integer $rule_id + * @property integer $version_id + * @property integer $special_id + * @property integer $battles + * @property integer $wins + * @property double $avg_kill + * @property double $med_kill + * @property double $stddev_kill + * @property double $avg_death + * @property double $med_death + * @property double $stddev_death + * @property double $avg_special + * @property double $med_special + * @property double $stddev_special + * @property double $avg_point + * @property double $med_point + * @property double $stddev_point + * @property double $avg_time + * @property string $updated_at + * + * @property Rule2 $rule + * @property Special2 $special + * @property SplatoonVersion2 $version + */ +class StatWeapon2EntireSpecialByVersion extends ActiveRecord +{ + public static function tableName() + { + return 'stat_weapon2_entire_special_by_version'; + } + + public function rules() + { + return [ + [['rule_id', 'version_id', 'special_id', 'battles', 'wins', 'avg_kill', 'med_kill', 'avg_death', 'med_death', 'avg_special', 'med_special', 'avg_point', 'med_point', 'avg_time', 'updated_at'], 'required'], + [['rule_id', 'version_id', 'special_id', 'battles', 'wins'], 'default', 'value' => null], + [['rule_id', 'version_id', 'special_id', 'battles', 'wins'], 'integer'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['updated_at'], 'safe'], + [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], + [['special_id'], 'exist', 'skipOnError' => true, 'targetClass' => Special2::class, 'targetAttribute' => ['special_id' => 'id']], + [['version_id'], 'exist', 'skipOnError' => true, 'targetClass' => SplatoonVersion2::class, 'targetAttribute' => ['version_id' => 'id']], + ]; + } + + public function attributeLabels() + { + return [ + 'rule_id' => 'Rule ID', + 'version_id' => 'Version ID', + 'special_id' => 'Special ID', + 'battles' => 'Battles', + 'wins' => 'Wins', + 'avg_kill' => 'Avg Kill', + 'med_kill' => 'Med Kill', + 'stddev_kill' => 'Stddev Kill', + 'avg_death' => 'Avg Death', + 'med_death' => 'Med Death', + 'stddev_death' => 'Stddev Death', + 'avg_special' => 'Avg Special', + 'med_special' => 'Med Special', + 'stddev_special' => 'Stddev Special', + 'avg_point' => 'Avg Point', + 'med_point' => 'Med Point', + 'stddev_point' => 'Stddev Point', + 'avg_time' => 'Avg Time', + 'updated_at' => 'Updated At', + ]; + } + + public function getRule(): ActiveQuery + { + return $this->hasOne(Rule2::class, ['id' => 'rule_id']); + } + + public function getSpecial(): ActiveQuery + { + return $this->hasOne(Special2::class, ['id' => 'special_id']); + } + + public function getVersion(): ActiveQuery + { + return $this->hasOne(SplatoonVersion2::class, ['id' => 'version_id']); + } +} diff --git a/models/StatWeapon2EntireSpecialByVgroup.php b/models/StatWeapon2EntireSpecialByVgroup.php new file mode 100644 index 000000000..1ba2fd636 --- /dev/null +++ b/models/StatWeapon2EntireSpecialByVgroup.php @@ -0,0 +1,103 @@ + + */ + +declare(strict_types=1); + +namespace app\models; + +use Yii; +use yii\db\ActiveQuery; +use yii\db\ActiveRecord; + +/** + * This is the model class for table "stat_weapon2_entire_special_by_vgroup". + * + * @property integer $rule_id + * @property integer $version_group_id + * @property integer $special_id + * @property integer $battles + * @property integer $wins + * @property double $avg_kill + * @property double $med_kill + * @property double $stddev_kill + * @property double $avg_death + * @property double $med_death + * @property double $stddev_death + * @property double $avg_special + * @property double $med_special + * @property double $stddev_special + * @property double $avg_point + * @property double $med_point + * @property double $stddev_point + * @property double $avg_time + * @property string $updated_at + * + * @property Rule2 $rule + * @property Special2 $special + * @property SplatoonVersionGroup2 $versionGroup + */ +class StatWeapon2EntireSpecialByVgroup extends ActiveRecord +{ + public static function tableName() + { + return 'stat_weapon2_entire_special_by_vgroup'; + } + + public function rules() + { + return [ + [['rule_id', 'version_group_id', 'special_id', 'battles', 'wins', 'avg_kill', 'med_kill', 'avg_death', 'med_death', 'avg_special', 'med_special', 'avg_point', 'med_point', 'avg_time', 'updated_at'], 'required'], + [['rule_id', 'version_group_id', 'special_id', 'battles', 'wins'], 'default', 'value' => null], + [['rule_id', 'version_group_id', 'special_id', 'battles', 'wins'], 'integer'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['updated_at'], 'safe'], + [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], + [['special_id'], 'exist', 'skipOnError' => true, 'targetClass' => Special2::class, 'targetAttribute' => ['special_id' => 'id']], + [['version_group_id'], 'exist', 'skipOnError' => true, 'targetClass' => SplatoonVersionGroup2::class, 'targetAttribute' => ['version_group_id' => 'id']], + ]; + } + + public function attributeLabels() + { + return [ + 'rule_id' => 'Rule ID', + 'version_group_id' => 'Version Group ID', + 'special_id' => 'Special ID', + 'battles' => 'Battles', + 'wins' => 'Wins', + 'avg_kill' => 'Avg Kill', + 'med_kill' => 'Med Kill', + 'stddev_kill' => 'Stddev Kill', + 'avg_death' => 'Avg Death', + 'med_death' => 'Med Death', + 'stddev_death' => 'Stddev Death', + 'avg_special' => 'Avg Special', + 'med_special' => 'Med Special', + 'stddev_special' => 'Stddev Special', + 'avg_point' => 'Avg Point', + 'med_point' => 'Med Point', + 'stddev_point' => 'Stddev Point', + 'avg_time' => 'Avg Time', + 'updated_at' => 'Updated At', + ]; + } + + public function getRule(): ActiveQuery + { + return $this->hasOne(Rule2::class, ['id' => 'rule_id']); + } + + public function getSpecial(): ActiveQuery + { + return $this->hasOne(Special2::class, ['id' => 'special_id']); + } + + public function getVersionGroup(): ActiveQuery + { + return $this->hasOne(SplatoonVersionGroup2::class, ['id' => 'version_group_id']); + } +} diff --git a/models/StatWeapon2EntireSub.php b/models/StatWeapon2EntireSub.php new file mode 100644 index 000000000..83735bc3d --- /dev/null +++ b/models/StatWeapon2EntireSub.php @@ -0,0 +1,94 @@ + + */ + +declare(strict_types=1); + +namespace app\models; + +use Yii; +use yii\db\ActiveQuery; +use yii\db\ActiveRecord; + +/** + * This is the model class for table "stat_weapon2_entire_sub". + * + * @property integer $rule_id + * @property integer $subweapon_id + * @property integer $battles + * @property integer $wins + * @property double $avg_kill + * @property double $med_kill + * @property double $stddev_kill + * @property double $avg_death + * @property double $med_death + * @property double $stddev_death + * @property double $avg_special + * @property double $med_special + * @property double $stddev_special + * @property double $avg_point + * @property double $med_point + * @property double $stddev_point + * @property double $avg_time + * @property string $updated_at + * + * @property Rule2 $rule + * @property Subweapon2 $subweapon + */ +class StatWeapon2EntireSub extends ActiveRecord +{ + public static function tableName() + { + return 'stat_weapon2_entire_sub'; + } + + public function rules() + { + return [ + [['rule_id', 'subweapon_id', 'battles', 'wins', 'avg_kill', 'med_kill', 'avg_death', 'med_death', 'avg_special', 'med_special', 'avg_point', 'med_point', 'avg_time', 'updated_at'], 'required'], + [['rule_id', 'subweapon_id', 'battles', 'wins'], 'default', 'value' => null], + [['rule_id', 'subweapon_id', 'battles', 'wins'], 'integer'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['updated_at'], 'safe'], + [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], + [['subweapon_id'], 'exist', 'skipOnError' => true, 'targetClass' => Subweapon2::class, 'targetAttribute' => ['subweapon_id' => 'id']], + ]; + } + + public function attributeLabels() + { + return [ + 'rule_id' => 'Rule ID', + 'subweapon_id' => 'Subweapon ID', + 'battles' => 'Battles', + 'wins' => 'Wins', + 'avg_kill' => 'Avg Kill', + 'med_kill' => 'Med Kill', + 'stddev_kill' => 'Stddev Kill', + 'avg_death' => 'Avg Death', + 'med_death' => 'Med Death', + 'stddev_death' => 'Stddev Death', + 'avg_special' => 'Avg Special', + 'med_special' => 'Med Special', + 'stddev_special' => 'Stddev Special', + 'avg_point' => 'Avg Point', + 'med_point' => 'Med Point', + 'stddev_point' => 'Stddev Point', + 'avg_time' => 'Avg Time', + 'updated_at' => 'Updated At', + ]; + } + + public function getRule(): ActiveQuery + { + return $this->hasOne(Rule2::class, ['id' => 'rule_id']); + } + + public function getSubweapon(): ActiveQuery + { + return $this->hasOne(Subweapon2::class, ['id' => 'subweapon_id']); + } +} diff --git a/models/StatWeapon2EntireSubByVersion.php b/models/StatWeapon2EntireSubByVersion.php new file mode 100644 index 000000000..7eea2d33c --- /dev/null +++ b/models/StatWeapon2EntireSubByVersion.php @@ -0,0 +1,103 @@ + + */ + +declare(strict_types=1); + +namespace app\models; + +use Yii; +use yii\db\ActiveQuery; +use yii\db\ActiveRecord; + +/** + * This is the model class for table "stat_weapon2_entire_sub_by_version". + * + * @property integer $rule_id + * @property integer $version_id + * @property integer $subweapon_id + * @property integer $battles + * @property integer $wins + * @property double $avg_kill + * @property double $med_kill + * @property double $stddev_kill + * @property double $avg_death + * @property double $med_death + * @property double $stddev_death + * @property double $avg_special + * @property double $med_special + * @property double $stddev_special + * @property double $avg_point + * @property double $med_point + * @property double $stddev_point + * @property double $avg_time + * @property string $updated_at + * + * @property Rule2 $rule + * @property Subweapon2 $subweapon + * @property SplatoonVersion2 $version + */ +class StatWeapon2EntireSubByVersion extends ActiveRecord +{ + public static function tableName() + { + return 'stat_weapon2_entire_sub_by_version'; + } + + public function rules() + { + return [ + [['rule_id', 'version_id', 'subweapon_id', 'battles', 'wins', 'avg_kill', 'med_kill', 'avg_death', 'med_death', 'avg_special', 'med_special', 'avg_point', 'med_point', 'avg_time', 'updated_at'], 'required'], + [['rule_id', 'version_id', 'subweapon_id', 'battles', 'wins'], 'default', 'value' => null], + [['rule_id', 'version_id', 'subweapon_id', 'battles', 'wins'], 'integer'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['updated_at'], 'safe'], + [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], + [['version_id'], 'exist', 'skipOnError' => true, 'targetClass' => SplatoonVersion2::class, 'targetAttribute' => ['version_id' => 'id']], + [['subweapon_id'], 'exist', 'skipOnError' => true, 'targetClass' => Subweapon2::class, 'targetAttribute' => ['subweapon_id' => 'id']], + ]; + } + + public function attributeLabels() + { + return [ + 'rule_id' => 'Rule ID', + 'version_id' => 'Version ID', + 'subweapon_id' => 'Subweapon ID', + 'battles' => 'Battles', + 'wins' => 'Wins', + 'avg_kill' => 'Avg Kill', + 'med_kill' => 'Med Kill', + 'stddev_kill' => 'Stddev Kill', + 'avg_death' => 'Avg Death', + 'med_death' => 'Med Death', + 'stddev_death' => 'Stddev Death', + 'avg_special' => 'Avg Special', + 'med_special' => 'Med Special', + 'stddev_special' => 'Stddev Special', + 'avg_point' => 'Avg Point', + 'med_point' => 'Med Point', + 'stddev_point' => 'Stddev Point', + 'avg_time' => 'Avg Time', + 'updated_at' => 'Updated At', + ]; + } + + public function getRule(): ActiveQuery + { + return $this->hasOne(Rule2::class, ['id' => 'rule_id']); + } + + public function getSubweapon(): ActiveQuery + { + return $this->hasOne(Subweapon2::class, ['id' => 'subweapon_id']); + } + + public function getVersion(): ActiveQuery + { + return $this->hasOne(SplatoonVersion2::class, ['id' => 'version_id']); + } +} diff --git a/models/StatWeapon2EntireSubByVgroup.php b/models/StatWeapon2EntireSubByVgroup.php new file mode 100644 index 000000000..ea696fd8b --- /dev/null +++ b/models/StatWeapon2EntireSubByVgroup.php @@ -0,0 +1,103 @@ + + */ + +declare(strict_types=1); + +namespace app\models; + +use Yii; +use yii\db\ActiveQuery; +use yii\db\ActiveRecord; + +/** + * This is the model class for table "stat_weapon2_entire_sub_by_vgroup". + * + * @property integer $rule_id + * @property integer $version_group_id + * @property integer $subweapon_id + * @property integer $battles + * @property integer $wins + * @property double $avg_kill + * @property double $med_kill + * @property double $stddev_kill + * @property double $avg_death + * @property double $med_death + * @property double $stddev_death + * @property double $avg_special + * @property double $med_special + * @property double $stddev_special + * @property double $avg_point + * @property double $med_point + * @property double $stddev_point + * @property double $avg_time + * @property string $updated_at + * + * @property Rule2 $rule + * @property Subweapon2 $subweapon + * @property SplatoonVersionGroup2 $versionGroup + */ +class StatWeapon2EntireSubByVgroup extends ActiveRecord +{ + public static function tableName() + { + return 'stat_weapon2_entire_sub_by_vgroup'; + } + + public function rules() + { + return [ + [['rule_id', 'version_group_id', 'subweapon_id', 'battles', 'wins', 'avg_kill', 'med_kill', 'avg_death', 'med_death', 'avg_special', 'med_special', 'avg_point', 'med_point', 'avg_time', 'updated_at'], 'required'], + [['rule_id', 'version_group_id', 'subweapon_id', 'battles', 'wins'], 'default', 'value' => null], + [['rule_id', 'version_group_id', 'subweapon_id', 'battles', 'wins'], 'integer'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['updated_at'], 'safe'], + [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], + [['version_group_id'], 'exist', 'skipOnError' => true, 'targetClass' => SplatoonVersionGroup2::class, 'targetAttribute' => ['version_group_id' => 'id']], + [['subweapon_id'], 'exist', 'skipOnError' => true, 'targetClass' => Subweapon2::class, 'targetAttribute' => ['subweapon_id' => 'id']], + ]; + } + + public function attributeLabels() + { + return [ + 'rule_id' => 'Rule ID', + 'version_group_id' => 'Version Group ID', + 'subweapon_id' => 'Subweapon ID', + 'battles' => 'Battles', + 'wins' => 'Wins', + 'avg_kill' => 'Avg Kill', + 'med_kill' => 'Med Kill', + 'stddev_kill' => 'Stddev Kill', + 'avg_death' => 'Avg Death', + 'med_death' => 'Med Death', + 'stddev_death' => 'Stddev Death', + 'avg_special' => 'Avg Special', + 'med_special' => 'Med Special', + 'stddev_special' => 'Stddev Special', + 'avg_point' => 'Avg Point', + 'med_point' => 'Med Point', + 'stddev_point' => 'Stddev Point', + 'avg_time' => 'Avg Time', + 'updated_at' => 'Updated At', + ]; + } + + public function getRule(): ActiveQuery + { + return $this->hasOne(Rule2::class, ['id' => 'rule_id']); + } + + public function getSubweapon(): ActiveQuery + { + return $this->hasOne(Subweapon2::class, ['id' => 'subweapon_id']); + } + + public function getVersionGroup(): ActiveQuery + { + return $this->hasOne(SplatoonVersionGroup2::class, ['id' => 'version_group_id']); + } +} From 2eae8f3e4161a4a6e5ea94281b7d09a811403a0b Mon Sep 17 00:00:00 2001 From: AIZAWA Hina Date: Mon, 22 Jun 2020 01:45:39 +0900 Subject: [PATCH 03/10] Update auto-generate files template --- components/gii/Module.php | 22 ++ components/gii/generators/model/Generator.php | 200 ++++++++++++++++++ config/console.php | 2 +- config/web.php | 4 - views/gii/model/model.php | 4 +- views/migration/default_migration.php | 3 +- 6 files changed, 228 insertions(+), 7 deletions(-) create mode 100644 components/gii/Module.php create mode 100644 components/gii/generators/model/Generator.php diff --git a/components/gii/Module.php b/components/gii/Module.php new file mode 100644 index 000000000..1d8e184c8 --- /dev/null +++ b/components/gii/Module.php @@ -0,0 +1,22 @@ + + */ + +namespace app\components\gii; + +use Yii; +use yii\gii\Module as BaseModule; + +class Module extends BaseModule +{ + protected function coreGenerators() + { + return array_merge(parent::coreGenerators(), [ + 'model' => generators\model\Generator::class, + ]); + } +} diff --git a/components/gii/generators/model/Generator.php b/components/gii/generators/model/Generator.php new file mode 100644 index 000000000..f659c87ce --- /dev/null +++ b/components/gii/generators/model/Generator.php @@ -0,0 +1,200 @@ +columns as $column) { + if ($column->autoIncrement) { + continue; + } + + if (!$column->allowNull && $column->defaultValue === null) { + $types['required'][] = $column->name; + } + + switch ($column->type) { + case Schema::TYPE_SMALLINT: + case Schema::TYPE_INTEGER: + case Schema::TYPE_BIGINT: + case Schema::TYPE_TINYINT: + $types['integer'][] = $column->name; + break; + + case Schema::TYPE_BOOLEAN: + $types['boolean'][] = $column->name; + break; + + case Schema::TYPE_FLOAT: + case Schema::TYPE_DOUBLE: + case Schema::TYPE_DECIMAL: + case Schema::TYPE_MONEY: + $types['number'][] = $column->name; + break; + + case Schema::TYPE_DATE: + case Schema::TYPE_TIME: + case Schema::TYPE_DATETIME: + case Schema::TYPE_TIMESTAMP: + case Schema::TYPE_JSON: + $types['safe'][] = $column->name; + break; + + default: // strings + if ($column->size > 0) { + $lengths[$column->size][] = $column->name; + } else { + $types['string'][] = $column->name; + } + } + } + $rules = []; + $driverName = $this->getDbDriverName(); + foreach ($types as $type => $columns) { + if ($driverName === 'pgsql' && $type === 'integer') { + $offset = 0; + $limit = count($columns); + while ($offset < count($columns)) { + $tmpColumns = array_slice($columns, $offset, $limit); + $rule = vsprintf("[[%s], 'default', 'value' => null],", [ + implode(', ', array_map( + fn ($_) => "'" . addslashes($_) . "'", + $tmpColumns + )), + ]); + if (strlen($rule) > static::RULE_LIMIT) { + --$limit; + } else { + $rules[] = $rule; + $offset += $limit; + $limit = count($columns) - $offset; + } + } + } + + $offset = 0; + $limit = count($columns); + while ($offset < count($columns)) { + $tmpColumns = array_slice($columns, $offset, $limit); + $rule = vsprintf("[[%s], '%s'],", [ + implode(', ', array_map( + fn ($_) => "'" . addslashes($_) . "'", + $tmpColumns + )), + addslashes($type), + ]); + if ($limit > 0 && strlen($rule) > static::RULE_LIMIT) { + --$limit; + } else { + $rules[] = $rule; + $offset += $limit; + $limit = count($columns) - $offset; + } + } + } + foreach ($lengths as $length => $columns) { + $offset = 0; + $limit = count($columns); + while ($offset < count($columns)) { + $tmpColumns = array_slice($columns, $offset, $limit); + $rule = vsprintf("[[%s], 'string', 'max' => %d],", [ + implode(', ', array_map( + fn ($_) => "'" . addslashes($_) . "'", + $tmpColumns + )), + addslashes($type), + ]); + if ($limit > 0 && strlen($rule) > static::RULE_LIMIT) { + --$limit; + } else { + $rules[] = $rule; + $offset += $limit; + $limit = count($columns) - $offset; + } + } + } + + $db = $this->getDbConnection(); + + // Unique indexes rules + try { + $uniqueIndexes = array_merge($db->getSchema()->findUniqueIndexes($table), [$table->primaryKey]); + $uniqueIndexes = array_unique($uniqueIndexes, SORT_REGULAR); + foreach ($uniqueIndexes as $uniqueColumns) { + // Avoid validating auto incremental columns + if (!$this->isColumnAutoIncremental($table, $uniqueColumns)) { + $attributesCount = count($uniqueColumns); + + if ($attributesCount === 1) { + $rules[] = "[['" . $uniqueColumns[0] . "'], 'unique'],"; + } elseif ($attributesCount > 1) { + $columnsList = implode("', '", $uniqueColumns); + $rule = "[['$columnsList'], 'unique', 'targetAttribute' => ['$columnsList']],"; + if (strlen($rule) <= static::RULE_LIMIT) { + $rules[] = $rule; + } else { + $tmp = []; + $tmp[] = '['; + $tmp[] = ' ['; + foreach ($uniqueColumns as $_) { + $tmp[] = " '" . $_ . "',"; + } + $tmp[] = ' ],'; + $tmp[] = " 'unique',"; + $tmp[] = " 'targetAttribute' => ["; + foreach ($uniqueColumns as $_) { + $tmp[] = " '" . $_ . "',"; + } + $tmp[] = ' ],'; + $tmp[] = '],'; + $rules[] = implode("\n", $tmp); + } + } + } + } + } catch (NotSupportedException $e) { + // doesn't support unique indexes information...do nothing + } + + // Exist rules for foreign keys + foreach ($table->foreignKeys as $refs) { + $refTable = $refs[0]; + $refTableSchema = $db->getTableSchema($refTable); + if ($refTableSchema === null) { + // Foreign key could point to non-existing table: https://github.com/yiisoft/yii2-gii/issues/34 + continue; + } + $refClassName = $this->generateClassName($refTable); + unset($refs[0]); + $attributes = implode("', '", array_keys($refs)); + $targetAttributes = []; + foreach ($refs as $key => $value) { + $targetAttributes[] = "'$key' => '$value'"; + } + $targetAttributes = implode(', ', $targetAttributes); + $rules[] = "[['$attributes'], 'exist',"; + $rules[] = " 'skipOnError' => true,"; + $rules[] = " 'targetClass' => $refClassName::class,"; + $rules[] = " 'targetAttribute' => ["; + foreach ($refs as $key => $value) { + $rules[] = " '{$key}' => '{$value}',"; + } + $rules[] = " ],"; + $rules[] = "],"; + } + + return $rules; + } +} diff --git a/config/console.php b/config/console.php index 4a8860438..120fd9b0b 100644 --- a/config/console.php +++ b/config/console.php @@ -2,10 +2,10 @@ use app\commands\AssetController; use app\commands\MigrateController; +use app\components\gii\generators\model\Generator as GiiModelGenerator; use yii\caching\FileCache; use yii\db\Connection; use yii\gii\Module as GiiModule; -use yii\gii\generators\model\Generator as GiiModelGenerator; use yii\helpers\ArrayHelper; use yii\log\FileTarget as FileLogTarget; use yii\mutex\PgsqlMutex; diff --git a/config/web.php b/config/web.php index f92d58e6b..56e2bf8fb 100644 --- a/config/web.php +++ b/config/web.php @@ -2,7 +2,6 @@ declare(strict_types=1); use yii\debug\Module as DebugModule; -use yii\gii\Module as GiiModule; $params = require(__DIR__ . '/params.php'); $config = [ @@ -44,9 +43,6 @@ ]; if (defined('YII_ENV_DEV') && YII_ENV_DEV) { - $config['bootstrap'][] = 'gii'; - $config['modules']['gii'] = GiiModule::class; - $config['bootstrap'][] = 'debug'; $config['modules']['debug'] = [ 'class' => DebugModule::class, diff --git a/views/gii/model/model.php b/views/gii/model/model.php index d6e43a87b..b5208b773 100644 --- a/views/gii/model/model.php +++ b/views/gii/model/model.php @@ -1,4 +1,5 @@ + /** * @copyright Copyright (C) 2015-format('Y') ?> AIZAWA Hina * @license https://github.com/fetus-hina/stat.ink/blob/master/LICENSE MIT @@ -69,7 +71,7 @@ public static function getDb() public function rules() { - return []; + return []; } public function attributeLabels() diff --git a/views/migration/default_migration.php b/views/migration/default_migration.php index d2fe5d2e4..23b62e853 100644 --- a/views/migration/default_migration.php +++ b/views/migration/default_migration.php @@ -1,4 +1,5 @@ '', 'downCode' => implode("\n", [ "echo \"" . addslashes($className) . " cannot be reverted.\\n\";", - "return false", + "return false;", ]), ]) ?> From 775737f764f9f9226b6fe337fb01008e9e0e3759 Mon Sep 17 00:00:00 2001 From: AIZAWA Hina Date: Mon, 22 Jun 2020 03:11:14 +0900 Subject: [PATCH 04/10] regenerate model classes --- models/StatWeapon2EntireMain.php | 24 +++++++++++--- models/StatWeapon2EntireMainByVersion.php | 33 +++++++++++++++++--- models/StatWeapon2EntireMainByVgroup.php | 33 +++++++++++++++++--- models/StatWeapon2EntireSpecial.php | 25 ++++++++++++--- models/StatWeapon2EntireSpecialByVersion.php | 33 +++++++++++++++++--- models/StatWeapon2EntireSpecialByVgroup.php | 33 +++++++++++++++++--- models/StatWeapon2EntireSub.php | 25 ++++++++++++--- models/StatWeapon2EntireSubByVersion.php | 33 +++++++++++++++++--- models/StatWeapon2EntireSubByVgroup.php | 33 +++++++++++++++++--- 9 files changed, 230 insertions(+), 42 deletions(-) diff --git a/models/StatWeapon2EntireMain.php b/models/StatWeapon2EntireMain.php index f87fcf23e..961d25fbd 100644 --- a/models/StatWeapon2EntireMain.php +++ b/models/StatWeapon2EntireMain.php @@ -1,4 +1,5 @@ null], [['rule_id', 'weapon_id', 'battles', 'wins'], 'integer'], - [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death'], 'number'], + [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], + [['avg_time'], 'number'], [['updated_at'], 'safe'], - [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], - [['weapon_id'], 'exist', 'skipOnError' => true, 'targetClass' => Weapon2::class, 'targetAttribute' => ['weapon_id' => 'id']], + [['rule_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Rule2::class, + 'targetAttribute' => [ + 'rule_id' => 'id', + ], + ], + [['weapon_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Weapon2::class, + 'targetAttribute' => [ + 'weapon_id' => 'id', + ], + ], ]; } diff --git a/models/StatWeapon2EntireMainByVersion.php b/models/StatWeapon2EntireMainByVersion.php index 88cfef326..3cc458768 100644 --- a/models/StatWeapon2EntireMainByVersion.php +++ b/models/StatWeapon2EntireMainByVersion.php @@ -1,4 +1,5 @@ null], [['rule_id', 'version_id', 'weapon_id', 'battles', 'wins'], 'integer'], - [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death'], 'number'], + [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], + [['avg_time'], 'number'], [['updated_at'], 'safe'], - [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], - [['version_id'], 'exist', 'skipOnError' => true, 'targetClass' => SplatoonVersion2::class, 'targetAttribute' => ['version_id' => 'id']], - [['weapon_id'], 'exist', 'skipOnError' => true, 'targetClass' => Weapon2::class, 'targetAttribute' => ['weapon_id' => 'id']], + [['rule_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Rule2::class, + 'targetAttribute' => [ + 'rule_id' => 'id', + ], + ], + [['version_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => SplatoonVersion2::class, + 'targetAttribute' => [ + 'version_id' => 'id', + ], + ], + [['weapon_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Weapon2::class, + 'targetAttribute' => [ + 'weapon_id' => 'id', + ], + ], ]; } diff --git a/models/StatWeapon2EntireMainByVgroup.php b/models/StatWeapon2EntireMainByVgroup.php index 75ab0d430..910151c27 100644 --- a/models/StatWeapon2EntireMainByVgroup.php +++ b/models/StatWeapon2EntireMainByVgroup.php @@ -1,4 +1,5 @@ null], [['rule_id', 'version_group_id', 'weapon_id', 'battles', 'wins'], 'integer'], - [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death'], 'number'], + [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], + [['avg_time'], 'number'], [['updated_at'], 'safe'], - [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], - [['version_group_id'], 'exist', 'skipOnError' => true, 'targetClass' => SplatoonVersionGroup2::class, 'targetAttribute' => ['version_group_id' => 'id']], - [['weapon_id'], 'exist', 'skipOnError' => true, 'targetClass' => Weapon2::class, 'targetAttribute' => ['weapon_id' => 'id']], + [['rule_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Rule2::class, + 'targetAttribute' => [ + 'rule_id' => 'id', + ], + ], + [['version_group_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => SplatoonVersionGroup2::class, + 'targetAttribute' => [ + 'version_group_id' => 'id', + ], + ], + [['weapon_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Weapon2::class, + 'targetAttribute' => [ + 'weapon_id' => 'id', + ], + ], ]; } diff --git a/models/StatWeapon2EntireSpecial.php b/models/StatWeapon2EntireSpecial.php index b8d342dd7..1eecf6e1e 100644 --- a/models/StatWeapon2EntireSpecial.php +++ b/models/StatWeapon2EntireSpecial.php @@ -1,4 +1,5 @@ null], [['rule_id', 'special_id', 'battles', 'wins'], 'integer'], - [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death'], 'number'], + [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], + [['avg_time'], 'number'], [['updated_at'], 'safe'], - [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], - [['special_id'], 'exist', 'skipOnError' => true, 'targetClass' => Special2::class, 'targetAttribute' => ['special_id' => 'id']], + [['rule_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Rule2::class, + 'targetAttribute' => [ + 'rule_id' => 'id', + ], + ], + [['special_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Special2::class, + 'targetAttribute' => [ + 'special_id' => 'id', + ], + ], ]; } diff --git a/models/StatWeapon2EntireSpecialByVersion.php b/models/StatWeapon2EntireSpecialByVersion.php index 0445059da..a7628e554 100644 --- a/models/StatWeapon2EntireSpecialByVersion.php +++ b/models/StatWeapon2EntireSpecialByVersion.php @@ -1,4 +1,5 @@ null], [['rule_id', 'version_id', 'special_id', 'battles', 'wins'], 'integer'], - [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death'], 'number'], + [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], + [['avg_time'], 'number'], [['updated_at'], 'safe'], - [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], - [['special_id'], 'exist', 'skipOnError' => true, 'targetClass' => Special2::class, 'targetAttribute' => ['special_id' => 'id']], - [['version_id'], 'exist', 'skipOnError' => true, 'targetClass' => SplatoonVersion2::class, 'targetAttribute' => ['version_id' => 'id']], + [['rule_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Rule2::class, + 'targetAttribute' => [ + 'rule_id' => 'id', + ], + ], + [['special_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Special2::class, + 'targetAttribute' => [ + 'special_id' => 'id', + ], + ], + [['version_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => SplatoonVersion2::class, + 'targetAttribute' => [ + 'version_id' => 'id', + ], + ], ]; } diff --git a/models/StatWeapon2EntireSpecialByVgroup.php b/models/StatWeapon2EntireSpecialByVgroup.php index 1ba2fd636..4f634e2fb 100644 --- a/models/StatWeapon2EntireSpecialByVgroup.php +++ b/models/StatWeapon2EntireSpecialByVgroup.php @@ -1,4 +1,5 @@ null], [['rule_id', 'version_group_id', 'special_id', 'battles', 'wins'], 'integer'], - [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death'], 'number'], + [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], + [['avg_time'], 'number'], [['updated_at'], 'safe'], - [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], - [['special_id'], 'exist', 'skipOnError' => true, 'targetClass' => Special2::class, 'targetAttribute' => ['special_id' => 'id']], - [['version_group_id'], 'exist', 'skipOnError' => true, 'targetClass' => SplatoonVersionGroup2::class, 'targetAttribute' => ['version_group_id' => 'id']], + [['rule_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Rule2::class, + 'targetAttribute' => [ + 'rule_id' => 'id', + ], + ], + [['special_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Special2::class, + 'targetAttribute' => [ + 'special_id' => 'id', + ], + ], + [['version_group_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => SplatoonVersionGroup2::class, + 'targetAttribute' => [ + 'version_group_id' => 'id', + ], + ], ]; } diff --git a/models/StatWeapon2EntireSub.php b/models/StatWeapon2EntireSub.php index 83735bc3d..88134c21b 100644 --- a/models/StatWeapon2EntireSub.php +++ b/models/StatWeapon2EntireSub.php @@ -1,4 +1,5 @@ null], [['rule_id', 'subweapon_id', 'battles', 'wins'], 'integer'], - [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death'], 'number'], + [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], + [['avg_time'], 'number'], [['updated_at'], 'safe'], - [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], - [['subweapon_id'], 'exist', 'skipOnError' => true, 'targetClass' => Subweapon2::class, 'targetAttribute' => ['subweapon_id' => 'id']], + [['rule_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Rule2::class, + 'targetAttribute' => [ + 'rule_id' => 'id', + ], + ], + [['subweapon_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Subweapon2::class, + 'targetAttribute' => [ + 'subweapon_id' => 'id', + ], + ], ]; } diff --git a/models/StatWeapon2EntireSubByVersion.php b/models/StatWeapon2EntireSubByVersion.php index 7eea2d33c..15bcc7b22 100644 --- a/models/StatWeapon2EntireSubByVersion.php +++ b/models/StatWeapon2EntireSubByVersion.php @@ -1,4 +1,5 @@ null], [['rule_id', 'version_id', 'subweapon_id', 'battles', 'wins'], 'integer'], - [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death'], 'number'], + [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], + [['avg_time'], 'number'], [['updated_at'], 'safe'], - [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], - [['version_id'], 'exist', 'skipOnError' => true, 'targetClass' => SplatoonVersion2::class, 'targetAttribute' => ['version_id' => 'id']], - [['subweapon_id'], 'exist', 'skipOnError' => true, 'targetClass' => Subweapon2::class, 'targetAttribute' => ['subweapon_id' => 'id']], + [['rule_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Rule2::class, + 'targetAttribute' => [ + 'rule_id' => 'id', + ], + ], + [['version_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => SplatoonVersion2::class, + 'targetAttribute' => [ + 'version_id' => 'id', + ], + ], + [['subweapon_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Subweapon2::class, + 'targetAttribute' => [ + 'subweapon_id' => 'id', + ], + ], ]; } diff --git a/models/StatWeapon2EntireSubByVgroup.php b/models/StatWeapon2EntireSubByVgroup.php index ea696fd8b..4352ec529 100644 --- a/models/StatWeapon2EntireSubByVgroup.php +++ b/models/StatWeapon2EntireSubByVgroup.php @@ -1,4 +1,5 @@ null], [['rule_id', 'version_group_id', 'subweapon_id', 'battles', 'wins'], 'integer'], - [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death', 'avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point', 'avg_time'], 'number'], + [['avg_kill', 'med_kill', 'stddev_kill', 'avg_death', 'med_death', 'stddev_death'], 'number'], + [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], + [['avg_time'], 'number'], [['updated_at'], 'safe'], - [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, 'targetAttribute' => ['rule_id' => 'id']], - [['version_group_id'], 'exist', 'skipOnError' => true, 'targetClass' => SplatoonVersionGroup2::class, 'targetAttribute' => ['version_group_id' => 'id']], - [['subweapon_id'], 'exist', 'skipOnError' => true, 'targetClass' => Subweapon2::class, 'targetAttribute' => ['subweapon_id' => 'id']], + [['rule_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Rule2::class, + 'targetAttribute' => [ + 'rule_id' => 'id', + ], + ], + [['version_group_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => SplatoonVersionGroup2::class, + 'targetAttribute' => [ + 'version_group_id' => 'id', + ], + ], + [['subweapon_id'], 'exist', + 'skipOnError' => true, + 'targetClass' => Subweapon2::class, + 'targetAttribute' => [ + 'subweapon_id' => 'id', + ], + ], ]; } From 5c5f6dace54ecf3edab39c743cb3ac97bd26f833 Mon Sep 17 00:00:00 2001 From: AIZAWA Hina Date: Tue, 23 Jun 2020 00:39:05 +0900 Subject: [PATCH 05/10] fix pkeys --- components/gii/generators/model/Generator.php | 15 ++++++++++----- migrations/m200621_120537_entire_weapon2.php | 12 +++++++++++- models/StatWeapon2EntireMain.php | 1 + models/StatWeapon2EntireMainByVersion.php | 9 +++++++++ models/StatWeapon2EntireMainByVgroup.php | 9 +++++++++ models/StatWeapon2EntireSpecial.php | 1 + models/StatWeapon2EntireSpecialByVersion.php | 9 +++++++++ models/StatWeapon2EntireSpecialByVgroup.php | 9 +++++++++ models/StatWeapon2EntireSub.php | 1 + models/StatWeapon2EntireSubByVersion.php | 9 +++++++++ models/StatWeapon2EntireSubByVgroup.php | 9 +++++++++ views/gii/model/model.php | 6 +++++- 12 files changed, 83 insertions(+), 7 deletions(-) diff --git a/components/gii/generators/model/Generator.php b/components/gii/generators/model/Generator.php index f659c87ce..2b5c135a5 100644 --- a/components/gii/generators/model/Generator.php +++ b/components/gii/generators/model/Generator.php @@ -147,15 +147,20 @@ public function generateRules($table) } else { $tmp = []; $tmp[] = '['; - $tmp[] = ' ['; - foreach ($uniqueColumns as $_) { - $tmp[] = " '" . $_ . "',"; + $rule = "['{$columnsList}'],"; + if (strlen($rule) <= static::RULE_LIMIT - 4) { + $tmp[] = ' ' . $rule; + } else { + $tmp[] = ' ['; + foreach ($uniqueColumns as $_) { + $tmp[] = " '" . $_ . "',"; + } + $tmp[] = ' ],'; } - $tmp[] = ' ],'; $tmp[] = " 'unique',"; $tmp[] = " 'targetAttribute' => ["; foreach ($uniqueColumns as $_) { - $tmp[] = " '" . $_ . "',"; + $tmp[] = " '" . $_ . "',"; } $tmp[] = ' ],'; $tmp[] = '],'; diff --git a/migrations/m200621_120537_entire_weapon2.php b/migrations/m200621_120537_entire_weapon2.php index 11810f1d6..9ca328ca5 100644 --- a/migrations/m200621_120537_entire_weapon2.php +++ b/migrations/m200621_120537_entire_weapon2.php @@ -67,7 +67,17 @@ public function getTables(): array 'stddev_point' => $this->double()->null(), 'avg_time' => $this->double()->notNull(), 'updated_at' => $this->timestampTZ()->notNull(), - ] + ], + [ + vsprintf('PRIMARY KEY(%s)', implode(', ', array_map( + fn ($_) => "[[{$_}]]", + array_filter(array_merge( + ['rule_id'], + array_keys($vRefs ?? []), + array_keys($wRefs ?? []), + )), + ))), + ], ); $tables[$tableName] = $def; } diff --git a/models/StatWeapon2EntireMain.php b/models/StatWeapon2EntireMain.php index 961d25fbd..e6bcb00cb 100644 --- a/models/StatWeapon2EntireMain.php +++ b/models/StatWeapon2EntireMain.php @@ -57,6 +57,7 @@ public function rules() [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], [['avg_time'], 'number'], [['updated_at'], 'safe'], + [['rule_id', 'weapon_id'], 'unique', 'targetAttribute' => ['rule_id', 'weapon_id']], [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, diff --git a/models/StatWeapon2EntireMainByVersion.php b/models/StatWeapon2EntireMainByVersion.php index 3cc458768..78e007259 100644 --- a/models/StatWeapon2EntireMainByVersion.php +++ b/models/StatWeapon2EntireMainByVersion.php @@ -60,6 +60,15 @@ public function rules() [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], [['avg_time'], 'number'], [['updated_at'], 'safe'], + [ + ['rule_id', 'version_id', 'weapon_id'], + 'unique', + 'targetAttribute' => [ + 'rule_id', + 'version_id', + 'weapon_id', + ], + ], [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, diff --git a/models/StatWeapon2EntireMainByVgroup.php b/models/StatWeapon2EntireMainByVgroup.php index 910151c27..b044026d1 100644 --- a/models/StatWeapon2EntireMainByVgroup.php +++ b/models/StatWeapon2EntireMainByVgroup.php @@ -60,6 +60,15 @@ public function rules() [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], [['avg_time'], 'number'], [['updated_at'], 'safe'], + [ + ['rule_id', 'version_group_id', 'weapon_id'], + 'unique', + 'targetAttribute' => [ + 'rule_id', + 'version_group_id', + 'weapon_id', + ], + ], [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, diff --git a/models/StatWeapon2EntireSpecial.php b/models/StatWeapon2EntireSpecial.php index 1eecf6e1e..a1819606c 100644 --- a/models/StatWeapon2EntireSpecial.php +++ b/models/StatWeapon2EntireSpecial.php @@ -58,6 +58,7 @@ public function rules() [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], [['avg_time'], 'number'], [['updated_at'], 'safe'], + [['rule_id', 'special_id'], 'unique', 'targetAttribute' => ['rule_id', 'special_id']], [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, diff --git a/models/StatWeapon2EntireSpecialByVersion.php b/models/StatWeapon2EntireSpecialByVersion.php index a7628e554..c245ad3d4 100644 --- a/models/StatWeapon2EntireSpecialByVersion.php +++ b/models/StatWeapon2EntireSpecialByVersion.php @@ -60,6 +60,15 @@ public function rules() [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], [['avg_time'], 'number'], [['updated_at'], 'safe'], + [ + ['rule_id', 'version_id', 'special_id'], + 'unique', + 'targetAttribute' => [ + 'rule_id', + 'version_id', + 'special_id', + ], + ], [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, diff --git a/models/StatWeapon2EntireSpecialByVgroup.php b/models/StatWeapon2EntireSpecialByVgroup.php index 4f634e2fb..63aebd111 100644 --- a/models/StatWeapon2EntireSpecialByVgroup.php +++ b/models/StatWeapon2EntireSpecialByVgroup.php @@ -60,6 +60,15 @@ public function rules() [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], [['avg_time'], 'number'], [['updated_at'], 'safe'], + [ + ['rule_id', 'version_group_id', 'special_id'], + 'unique', + 'targetAttribute' => [ + 'rule_id', + 'version_group_id', + 'special_id', + ], + ], [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, diff --git a/models/StatWeapon2EntireSub.php b/models/StatWeapon2EntireSub.php index 88134c21b..0b8bbd968 100644 --- a/models/StatWeapon2EntireSub.php +++ b/models/StatWeapon2EntireSub.php @@ -58,6 +58,7 @@ public function rules() [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], [['avg_time'], 'number'], [['updated_at'], 'safe'], + [['rule_id', 'subweapon_id'], 'unique', 'targetAttribute' => ['rule_id', 'subweapon_id']], [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, diff --git a/models/StatWeapon2EntireSubByVersion.php b/models/StatWeapon2EntireSubByVersion.php index 15bcc7b22..f2f338fb9 100644 --- a/models/StatWeapon2EntireSubByVersion.php +++ b/models/StatWeapon2EntireSubByVersion.php @@ -60,6 +60,15 @@ public function rules() [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], [['avg_time'], 'number'], [['updated_at'], 'safe'], + [ + ['rule_id', 'version_id', 'subweapon_id'], + 'unique', + 'targetAttribute' => [ + 'rule_id', + 'version_id', + 'subweapon_id', + ], + ], [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, diff --git a/models/StatWeapon2EntireSubByVgroup.php b/models/StatWeapon2EntireSubByVgroup.php index 4352ec529..b078c273c 100644 --- a/models/StatWeapon2EntireSubByVgroup.php +++ b/models/StatWeapon2EntireSubByVgroup.php @@ -60,6 +60,15 @@ public function rules() [['avg_special', 'med_special', 'stddev_special', 'avg_point', 'med_point', 'stddev_point'], 'number'], [['avg_time'], 'number'], [['updated_at'], 'safe'], + [ + ['rule_id', 'version_group_id', 'subweapon_id'], + 'unique', + 'targetAttribute' => [ + 'rule_id', + 'version_group_id', + 'subweapon_id', + ], + ], [['rule_id'], 'exist', 'skipOnError' => true, 'targetClass' => Rule2::class, diff --git a/views/gii/model/model.php b/views/gii/model/model.php index b5208b773..3fdf0de33 100644 --- a/views/gii/model/model.php +++ b/views/gii/model/model.php @@ -71,7 +71,11 @@ public static function getDb() public function rules() { - return []; + return [ + + + + ]; } public function attributeLabels() From d1f235809b4e00dc047f9bcdca754683930eecf3 Mon Sep 17 00:00:00 2001 From: AIZAWA Hina Date: Wed, 24 Jun 2020 12:05:17 +0900 Subject: [PATCH 06/10] Update copyright comment --- components/gii/generators/model/Generator.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/components/gii/generators/model/Generator.php b/components/gii/generators/model/Generator.php index 2b5c135a5..004ef1f26 100644 --- a/components/gii/generators/model/Generator.php +++ b/components/gii/generators/model/Generator.php @@ -1,5 +1,12 @@ + */ + declare(strict_types=1); namespace app\components\gii\generators\model; From 0f7e2a6be5a919cbb4d95fb5f44da7229ac7efff Mon Sep 17 00:00:00 2001 From: AIZAWA Hina Date: Wed, 24 Jun 2020 16:05:23 +0900 Subject: [PATCH 07/10] Add GitHelper --- components/Version.php | 103 ++++++++++--------------------- components/helpers/GitHelper.php | 54 ++++++++++++++++ 2 files changed, 88 insertions(+), 69 deletions(-) create mode 100644 components/helpers/GitHelper.php diff --git a/components/Version.php b/components/Version.php index ac8d3daf6..e914df7a2 100644 --- a/components/Version.php +++ b/components/Version.php @@ -1,51 +1,54 @@ */ +declare(strict_types=1); + namespace app\components; use DateTimeImmutable; use DateTimeZone; use Exception; use Yii; +use app\components\helpers\GitHelper; class Version { - private static $revision = null; - private static $shortRevision = null; - private static $lastCommited = null; + private static ?string $revision = null; + private static ?string $shortRevision = null; + private static ?DateTimeImmutable $lastCommited = null; - public static function getVersion() + public static function getVersion(): ?string { - return Yii::$app->version; + $v = trim((string)Yii::$app->version); + return ($v !== '') ? $v : null; } public static function getRevision(): ?string { - self::fetchRevision(); - return self::$revision ?: null; + static::fetchRevision(); + return static::$revision ?: null; } public static function getShortRevision(): ?string { - self::fetchRevision(); - return self::$shortRevision ?: null; + static::fetchRevision(); + return static::$shortRevision ?: null; } public static function getLastCommited(): ?DateTimeImmutable { - self::fetchRevision(); - return self::$lastCommited ?: null; + static::fetchRevision(); + return static::$lastCommited ?: null; } public static function getFullHash(string $shortHash): ?string { - $lines = static::doGit(sprintf('git rev-parse %s -q', escapeshellarg($shortHash))); - return $lines ? array_shift($lines) : null; + return GitHelper::getLine(['rev-parse', $shortHash, '-q']); } public static function getVersionTags(?string $hash = null): array @@ -56,88 +59,50 @@ public static function getVersionTags(?string $hash = null): array return []; } - if (!$lines = static::doGit(sprintf('git tag --points-at %s', escapeshellarg($revision)))) { + if (!$lines = GitHelper::get(['tag', '--points-at', $revision])) { return []; } - $lines = array_filter($lines, function (string $line): bool { - return !!preg_match('/^v?\d+\.\d+\.\d+/', $line); - }); - - usort($lines, function (string $a, string $b): int { - return version_compare($b, $a); - }); + $lines = array_filter($lines, fn ($_) => (bool)preg_match('/^v?\d+\.\d+\.\d+/', $_)); + usort($lines, fn ($a, $b) => version_compare($b, $a)); return $lines; } - private static function fetchRevision() + private static function fetchRevision(): void { if ( - self::$revision !== null && - self::$shortRevision !== null && - self::$lastCommited !== null + static::$revision !== null && + static::$shortRevision !== null && + static::$lastCommited !== null ) { return; } try { - if (!$line = self::getGitLog('%H:%h:%cd')) { + if (!$line = static::getGitLog('%H:%h:%cd')) { throw new Exception(); } + $revisions = explode(':', $line); if (count($revisions) !== 3) { throw new Exception(); } - self::$revision = $revisions[0]; - self::$shortRevision = $revisions[1]; - self::$lastCommited = (new DateTimeImmutable()) + static::$revision = $revisions[0]; + static::$shortRevision = $revisions[1]; + static::$lastCommited = (new DateTimeImmutable()) ->setTimeZone(new DateTimeZone(Yii::$app->timeZone)) ->setTimestamp((int)$revisions[2]); } catch (Exception $e) { - self::$revision = false; - self::$shortRevision = false; - self::$lastCommited = false; - } - } - - private static function getGitLog($format) - { - $gitCommand = sprintf( - 'git log -n 1 --format=%s --date=raw', - escapeshellarg($format) - ); - if (!$lines = static::doGit($gitCommand)) { - return false; + static::$revision = null; + static::$shortRevision = null; + static::$lastCommited = null; } - return trim(array_shift($lines)); } - private static function doGit($gitCommand) + private static function getGitLog($format): ?string { - // FIXME: scl git19 があればそれを、無ければpathの通ったgitを使うひどい場当たりhack - if ( - file_exists('/usr/bin/scl') && - is_executable('/usr/bin/scl') && - file_exists('/opt/rh/git19/enable') - ) { - $cmdline = sprintf( - '/usr/bin/scl enable git19 %s', - escapeshellarg($gitCommand) - ); - } else { - $cmdline = sprintf( - '/bin/bash -c %s', - escapeshellarg($gitCommand) - ); - } - - $lines = $status = null; - $line = exec($cmdline, $lines, $status); - if ($status !== 0) { - return false; - } - return $lines; + return GitHelper::getLine(['log', '-n', 1, '--format' => $format, '--date' => 'raw']); } } diff --git a/components/helpers/GitHelper.php b/components/helpers/GitHelper.php new file mode 100644 index 000000000..8a57d5bfe --- /dev/null +++ b/components/helpers/GitHelper.php @@ -0,0 +1,54 @@ + + */ + +declare(strict_types=1); + +namespace app\components\helpers; + +class GitHelper +{ + public static function getUserName(): ?string + { + return static::getConfig('user.name'); + } + + public static function getUserEmail(): ?string + { + return static::getConfig('user.email'); + } + + public static function getConfig(string $name): ?string + { + return static::getLine(['config', $name]); + } + + public static function getLine(array $params): ?string + { + if (!$lines = static::get($params)) { + return null; + } + + $line = trim((string)array_shift($lines)); + return ($line === '') ? null : $line; + } + + public static function get(array $params): ?array + { + $params = array_merge(['git'], $params); + $cmdline = '/usr/bin/env ' . implode(' ', array_map( + fn ($k, $v) => is_int($k) ? escapeshellarg((string)$v) : sprintf('%s=%s', (string)$k, escapeshellarg($v)), + array_keys($params), + array_values($params), + )); + + $lines = []; + $status = null; + @exec($cmdline, $lines, $status); + return ($status === 0) ? $lines : null; + } +} From 7520f27649f61755c4f5847455554dc1530dfe5f Mon Sep 17 00:00:00 2001 From: AIZAWA Hina Date: Wed, 24 Jun 2020 16:05:51 +0900 Subject: [PATCH 08/10] Update model template --- views/gii/model/model.php | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/views/gii/model/model.php b/views/gii/model/model.php index 3fdf0de33..1055dd493 100644 --- a/views/gii/model/model.php +++ b/views/gii/model/model.php @@ -22,16 +22,43 @@ /* @var $rules string[] list of validation rules */ /* @var $relations array list of relations (name => relation declaration) */ -$now = (new \DateTimeImmutable('now', new \DateTimeZone('Asia/Tokyo'))) +declare(strict_types=1); + +use app\components\helpers\GitHelper; + +$now = (new DateTimeImmutable('now', new DateTimeZone('Asia/Tokyo'))) ->setTimestamp($_SERVER['REQUEST_TIME'] ?? time()); +$authors = array_filter( + [ + [ + 'AIZAWA Hina', + 'hina@fetus.jp', + ], + [ + GitHelper::getUserName(), + GitHelper::getUserEmail(), + ], + ], + fn ($_) => ($_[0] !== null && $_[1] !== null) +); + +$authorsFormatted = array_unique(array_map( + fn ($_) => sprintf('%s <%s>', $_[0], $_[1]), + $authors +)); + +$copyrightHolders = array_unique(array_map(fn ($_) => $_[0], $authors)); + echo " /** - * @copyright Copyright (C) 2015-format('Y') ?> AIZAWA Hina + * @copyright Copyright (C) 2015-format('Y') ?> * @license https://github.com/fetus-hina/stat.ink/blob/master/LICENSE MIT - * @author AIZAWA Hina + + * @author + */ declare(strict_types=1); From 4aa92dd52cfeaeb8760b714a4ca7361ad0c72160 Mon Sep 17 00:00:00 2001 From: AIZAWA Hina Date: Wed, 24 Jun 2020 16:27:49 +0900 Subject: [PATCH 09/10] Disable utility output --- migrations/m200621_120537_entire_weapon2.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/m200621_120537_entire_weapon2.php b/migrations/m200621_120537_entire_weapon2.php index 9ca328ca5..8ff952d6e 100644 --- a/migrations/m200621_120537_entire_weapon2.php +++ b/migrations/m200621_120537_entire_weapon2.php @@ -17,7 +17,7 @@ public function safeUp() $tables = $this->tables; array_walk($tables, fn ($def, $name) => $this->createTable($name, $def)); - if (true) { + if (false) { echo "\n"; foreach (array_keys($tables) as $name) { vprintf("./yii gii/model --tableName=%s --modelClass=%s --interactive=0 --overwrite\n", [ From 0b12310ffd024e319559b26528f5ba42b307219e Mon Sep 17 00:00:00 2001 From: AIZAWA Hina Date: Wed, 1 Jul 2020 10:48:53 +0900 Subject: [PATCH 10/10] wip --- commands/StatController.php | 6 +- commands/stat/StatWeapon2EntireTrait.php | 260 +++++++++++++++++++++++ 2 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 commands/stat/StatWeapon2EntireTrait.php diff --git a/commands/StatController.php b/commands/StatController.php index f05565f52..58cf9791f 100644 --- a/commands/StatController.php +++ b/commands/StatController.php @@ -1,7 +1,7 @@ */ @@ -46,6 +46,7 @@ class StatController extends Controller { + use stat\StatWeapon2EntireTrait; use stat\Weapon2Trait; /** @@ -55,6 +56,9 @@ class StatController extends Controller */ public function actionUpdateEntireWeapons() { + $this->updateStatWeapon2Entire(); + return; //FIXME + // $this->updateEntireWeapons1(); $this->updateEntireWeapons2(); } diff --git a/commands/stat/StatWeapon2EntireTrait.php b/commands/stat/StatWeapon2EntireTrait.php new file mode 100644 index 000000000..4c364fcf6 --- /dev/null +++ b/commands/stat/StatWeapon2EntireTrait.php @@ -0,0 +1,260 @@ + + */ + +declare(strict_types=1); + +namespace app\commands\stat; + +use DateTime; +use DateTimeImmutable; +use DateTimeZone; +use InvalidArgumentException; +use Yii; +use app\components\helpers\Battle as BattleHelper; +use app\models\Lobby2; +use app\models\Mode2; +use app\models\Rank2; +use app\models\Rule2; +use yii\db\Connection; +use yii\db\Expression; +use yii\db\Query; +use yii\db\Transaction; + +trait StatWeapon2EntireTrait +{ + // private const TYPE_MAIN = '_main'; + // private const TYPE_SUB = '_sub'; + // private const TYPE_SPECIAL = '_special'; + + // private const VERSION_ANY = ''; + // private const VERSION_VERSION = '_by_version'; + // private const VERSION_VGROUP = '_by_vgroup'; + + protected function updateStatWeapon2Entire(): void + { + $types = ['_main', '_sub', '_special']; + $versions = [null, '_by_version', '_by_vgroup']; + + Yii::$app->db->transaction( + function (Connection $db) use ($types, $versions): void { + $now = new DateTimeImmutable('now', new DateTimeZone('Etc/UTC')); + + foreach ($types as $type) { + foreach ($versions as $version) { + $this->makeStatWeapon2Entire($db, $now, $type, $version); + } + } + }, + Transaction::REPEATABLE_READ + ); + } + + private function makeStatWeapon2Entire( + Connection $db, + DateTimeImmutable $now, + string $typeSuffix, + ?string $versionSuffix + ): void { + $targetTableName = 'stat_weapon2_entire' . $typeSuffix . $versionSuffix; + fwrite(STDERR, "Updating {$targetTableName}...\n"); + + $ruleNawabari = Rule2::findOne(['key' => 'nawabari']); + $modeGachi = Mode2::findOne(['key' => 'gachi']); + $modeFest = Mode2::findOne(['key' => 'fest']); + $profreshionalRankIds = array_map( + fn ($rank) => (int)$rank->id, + Rank2::find()->andWhere(['key' => ['s+', 'x']])->all(), + ); + + $select = (new Query()) // {{{ + ->select(array_merge( + ['rule_id' => '{{b2}}.[[rule_id]]'], + $this->getVersionColumns($versionSuffix), + $this->getTypeColumns($typeSuffix), + [ + 'battles' => 'COUNT(*)', + 'wins' => 'SUM(CASE WHEN {{b2}}.[[is_win]] = {{p}}.[[is_my_team]] THEN 1 ELSE 0 END)', + ], + $this->getMetricColumns('kill'), + $this->getMetricColumns('death'), + $this->getMetricColumns('special'), + $this->getMetricColumns('point', sprintf('({{p}}.[[point]] - (CASE %s END))', implode(' ', [ + 'WHEN {{b2}}.[[rule_id]] <> ' . $ruleNawabari->id . ' THEN 0', + 'WHEN {{b2}}.[[is_win]] = {{p}}.[[is_my_team]] THEN 1000', + 'ELSE 0', + ]))), + [ + 'avg_time' => sprintf('AVG(CASE %s END)', implode(' ', [ + 'WHEN {{b2}}.[[rule_id]] = ' . $ruleNawabari->id . ' THEN 180', + 'ELSE EXTRACT(EPOCH FROM {{b2}}.[[end_at]] - {{b2}}.[[start_at]])', + ])), + 'updated_at' => new Expression($db->quoteValue($now->format(DateTime::ATOM))), + ], + )) + ->from(['b2' => 'battle2']) + ->innerJoin(['v' => 'splatoon_version2'], '{{b2}}.[[version_id]] = {{v}}.[[id]]') + ->innerJoin(['p' => 'battle_player2'], '{{b2}}.[[id]] = {{p}}.[[battle_id]]') + ->innerJoin(['w' => 'weapon2'], '{{p}}.[[weapon_id]] = {{w}}.[[id]]') + ->groupBy([ + '{{b2}}.[[rule_id]]', + ...array_values($this->getVersionColumns($versionSuffix)), + ...array_values($this->getTypeColumns($typeSuffix)), + ]) + ->andWhere(['and', + ['not', ['{{b2}}.[[lobby_id]]' => null]], + ['not', ['{{b2}}.[[mode_id]]' => null]], + ['not', ['{{b2}}.[[rule_id]]' => null]], + ['not', ['{{b2}}.[[map_id]]' => null]], + ['not', ['{{b2}}.[[weapon_id]]' => null]], + ['not', ['{{b2}}.[[is_win]]' => null]], + ['not', ['{{b2}}.[[version_id]]' => null]], + ['not', ['{{b2}}.[[start_at]]' => null]], + ['not', ['{{b2}}.[[end_at]]' => null]], + ['not', ['{{p}}.[[weapon_id]]' => null]], + ['not', ['{{p}}.[[kill]]' => null]], + ['not', ['{{p}}.[[death]]' => null]], + ['not', ['{{p}}.[[special]]' => null]], + ['not', ['{{p}}.[[point]]' => null]], + ['<>', '{{b2}}.[[lobby_id]]', Lobby2::findOne(['key' => 'private'])->id], + ['<>', '{{b2}}.[[mode_id]]', Mode2::findOne(['key' => 'private'])->id], + ['{{b2}}.[[is_automated]]' => true], + ['{{b2}}.[[use_for_entire]]' => true], + ['{{b2}}.[[has_disconnect]]' => false], + ['{{p}}.[[is_me]]' => false], + ['<', '{{b2}}.[[period]]', BattleHelper::calcPeriod2($now->setTime(0, 0, 0)->getTimestamp())], + ['or', + ['and', + ['{{b2}}.[[rule_id]]' => $ruleNawabari->id], + ], + ['and', + ['not', ['{{b2}}.[[rule_id]]' => $ruleNawabari->id]], + [ + '>=', + '({{b2}}.[[end_at]] - {{b2}}.[[start_at]])', + new Expression('(:minTime)::interval', [':minTime' => '30 seconds']), + ], + ], + ], + ['or', + // レギュラーマッチは(自分以外)全員分使う + ['and', + ['{{b2}}.[[rule_id]]' => $ruleNawabari->id], + ['<>', '{{b2}}.[[mode_id]]', $modeFest->id], + ], + // フェスマッチは敵チームのデータを使う + ['and', + ['{{b2}}.[[rule_id]]' => $ruleNawabari->id], + ['{{b2}}.[[mode_id]]' => $modeFest->id], + ['{{p}}.[[is_my_team]]' => false], + ], + // ガチマッチは自分以外の全員分使う。ただし、S+ と X のみ + ['and', + ['{{b2}}.[[lobby_id]]' => Lobby2::findOne(['key' => 'standard'])->id], + ['{{b2}}.[[mode_id]]' => $modeGachi->id], + ['{{p}}.[[rank_id]]' => $profreshionalRankIds], + ['or', + ['{{b2}}.[[rank_id]]' => $profreshionalRankIds], + ['{{b2}}.[[rank_after_id]]' => $profreshionalRankIds], + ], + ], + // リーグマッチは敵チームのデータを使う。ただし、S+ と X のみ + ['and', + ['{{b2}}.[[lobby_id]]' => array_map( + fn ($_) => (int)$_->id, + Lobby2::findAll(['key' => ['squad_2', 'squad_4']]), + )], + ['{{b2}}.[[mode_id]]' => $modeGachi->id], + ['{{p}}.[[rank_id]]' => $profreshionalRankIds], + ['{{p}}.[[is_my_team]]' => false], + ['or', + ['{{b2}}.[[rank_id]]' => $profreshionalRankIds], + ['{{b2}}.[[rank_after_id]]' => $profreshionalRankIds], + ], + ], + ], + ]); + // }}} + $sql = vsprintf('INSERT INTO %1$s (%2$s) %3$s ON CONFLICT ON CONSTRAINT %5$s DO UPDATE SET %4$s', [ + $db->quoteTableName($targetTableName), + implode(', ', array_map(fn ($_) => $db->quoteColumnName($_), array_keys($select->select))), + $select->createCommand()->rawSql, + implode(', ', array_map( + fn ($_) => vsprintf('%1$s = %2$s.%1$s', [ + $db->quoteColumnName($_), + $db->quoteTableName('excluded'), + ]), + array_filter( + array_keys($select->select), + fn ($_) => !in_array( + $_, + ['rule_id', 'special_id', 'subweapon_id', 'version_group_id', 'version_id', 'weapon_id'], + true + ), + ), + )), + $db->quoteColumnName($targetTableName . '_pkey'), + ]); + + $t1 = microtime(true); + $db->createCommand($sql)->execute(); + $t2 = microtime(true); + printf("done, %.3f sec\n", $t2 - $t1); + echo "cleanup...\n"; + $db->createCommand() + ->delete( + $targetTableName, + ['<>', 'updated_at', $now->format(DateTime::ATOM)] + ) + ->execute(); + $t3 = microtime(true); + printf("done, %.3f sec\n", $t3 - $t2); + } + + private function getVersionColumns(?string $versionTag): array + { + if ($versionTag === null) { + return []; + } elseif ($versionTag === '_by_version') { + return ['version_id' => '{{b2}}.[[version_id]]']; + } elseif ($versionTag === '_by_vgroup') { + return ['version_group_id' => '{{v}}.[[group_id]]']; + } + + throw new InvalidArgumentException(); + } + + private function getTypeColumns(string $typeTag): array + { + switch ($typeTag) { + case '_main': + return ['weapon_id' => '{{w}}.[[id]]']; + + case '_sub': + return ['subweapon_id' => '{{w}}.[[subweapon_id]]']; + + case '_special': + return ['special_id' => '{{w}}.[[special_id]]']; + + default: + throw new InvalidArgumentException(); + } + } + + private function getMetricColumns(string $metric, ?string $value = null): array + { + if ($value === null) { + $value = "{{p}}.[[{$metric}]]"; + } + + return [ + "avg_{$metric}" => "AVG({$value})", + "stddev_{$metric}" => "STDDEV_SAMP({$value})", + "med_{$metric}" => "PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY {$value})", + ]; + } +}