OmniAICreator/Qiita-1.07M huggingface dataset:
CentOS+ApacheにLet's Encryptを導入

## Overview
`Linux CentOS` + `Apache` に `Let's Encrypt` を導入する方法を説明します。

## Installation
`Let's Encrypt` は、手動でインストールすることもできますが、`Cerbot` という自動化サービスがありますのでこちらを利用します。  

- 書き込み可能な任意の場所に `github` から `Cerbot` をダウンロードします。

```sh
cd /usr/local
```

```sh
git clone https://github.com/certbot/certbot.git
```

## Obtain a certificate
`Cerbot` を利用して、SSL証明書を取得します。

- ダウンロードした、`Cerbot` のディレクトリに入り、SSL証明書を取得するコマンドを叩きます。

```sh
cd certbot
```

```sh
./certbot-auto certonly --webroot -w /var/www/vhosts/www.mydomain.com/html -d www.mydomain.com -m contact@mydomain.com -n --agree-tos
```

Option | Description | Value
-------|-------------|------
| -w   | キュメントルート | `/var/www/vhosts/www.mydomain.com/html` |
| -d   | ドメイン名     | `www.mydomain.com` |
| -m   | 連絡先のメールアドレス | `hoge@hoge.com` |
| -n   | 対話入力をスキップする | |
| --agree-tos | 利用規約に同意する | |

※ キュメントルート、ドメイン名、連絡先のメールアドレスは、環境に合わせた任意の値を設定してください。

正常に証明書を取得できると、`/etc/letsencrypt/live/www.mydomain.com/` 以下に次のファイルを確認できます。

`cert.pem` `privkey.pem` `chain.pem` `fullchain.pem`

## Configure Apache
取得したSSL証明書をApacheサーバーに設定します。  

- 次のように `/etc/httpd/conf/httpd.conf` を編集します。

```conf
<VirtualHost *:443>
  ServerName www.mydomain.com
  DocumentRoot /var/www/html
  SSLEngine on
  SSLCertificateFile /etc/letsencrypt/live/www.mydomain.com/cert.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/www.mydomain.com/privkey.pem
  SSLCACertificateFile /etc/letsencrypt/live/www.mydomain.com/chain.pem
  
  <Directory "/var/www/vhosts/www.mydomain.com/html">
    ... 省略 ...
  </Directory>
</VirtualHost>
```

- Apache を再起動します。

```sh
service httpd restart
```

## Update certificate
`Let's Encrypt` 証明書は、90日の有効期限しかない。

- 次のコマンドで更新をします。

```sh
/usr/local/certbot/certbot-auto renew --post-hook "service httpd restart"
```

## Configure Cron
手動で更新をするのは、手間なので、`Cron` を使って自動化します。  

- `Cron` の設定ファイルを作成します。

```sh
vim /etc/cron.d/letsencrypt
```

- ファイルに以下を記述します。

```cron
PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/developer/bin
00 01 * * 01 root /usr/local/certbot/certbot-auto renew --post-hook "service httpd restart"
```

※ `PATH` は、環境によって異なります。 `echo $PATH` で確認して置き換えてください。
※ `Cron` 設定の `00 01 * * 01` は、毎週月曜日の朝1時に実行するを意味します。  
(参考に https://crontab.guru/)

- `Cron` を再起動します。

```sh
service crond restart
```

以上になります。
AmazonLinux2でNginx+PHP7.3をインストールする。ついでにOPcacheとAPCuも

EC2インスタンス(AmazonLinux2)にNginx + php7.3の環境(OPcacheとAPCuも)を作成したので残しておきます。
参考になれば幸いです。


## EC2環境
Amazon Linux 2 AMI (HVM)
SSD Volume Type
ami-0f9ae750e8274075b

## EC2準備

### まず
AmazonLinux2 のインスタンスを立ち上げる
セキュリティグループの設定でssh(22),http(80)を適宜、許可する

### SSHログイン

```
ssh ec2-user@~~~
```

### パッケージ更新

```
# sudo yum -y update
```

### タイムゾーン変更

```
# timedatectl status
# sudo timedatectl set-timezone Asia/Tokyo
```

### 日本語ロケール追加

```
# localectl status
# sudo localectl set-locale LANG=ja_JP.UTF-8
# sudo localectl set-keymap jp106
```

## 諸々のインストール

### Nginx 
AmazonLinux EXTRAS リポジトリからインストールできるのは1.12.2でした。
(2019/04/01現在)

#### インストール&起動設定

```
# sudo amazon-linux-extras install nginx1.12  -y
# sudo systemctl start nginx
# sudo systemctl enable nginx
```

#### 接続確認
AWSのEC2 管理画面より、該当インスタンスのパブリック DNS (IPv4)または
IPv4パブリックIPにブラウザでアクセスするとnginxのデフォルトページが表示されるかを確認する。

### PHP関連
AmazonLinux EXTRAS リポジトリからインストールできるのは7.3.2もしくは7.2系でした。
(2019/04/01現在)

#### php7.3
##### インストール&起動設定

```
# sudo amazon-linux-extras install php7.3 -y
# sudo systemctl start php-fpm
# sudo systemctl enable php-fpm
```

##### 確認

```
# php -v
PHP 7.3.2 (cli) (built: Feb 15 2019 19:06:47) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.2, Copyright (c) 1998-2018 Zend Technologies
```

#### opcache

##### opcacheとは
opcacheとはコンパイルしたプログラムをメモリにキャッシュする仕組み。
これにより、２回目以降にプログラムにアクセスされた場合
キャッシュされたものを利用することでコンパイル処理を行う必要がなくなるため、
処理速度の向上が期待できる。

##### インストール
こちらはyumリポジトリからインストールを行う。

```
# sudo yum -y install php-opcache
```

##### 確認

```
# php -v
PHP 7.3.2 (cli) (built: Feb 15 2019 19:06:47) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.2, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.2, Copyright (c) 1999-2018, by Zend Technologies
```

#### APCu

##### APCuとは
APCuとはデータベースを参照して取得するデータ等をキャッシュへ保存し、
次回以降キャッシュを利用することで、サイトの高速化が期待できる。

##### インストール

```
# sudo yum -y install php-apcu
```

## 最終確認

### phpinf.phpの作成
nginxのデフォルトルート(/usr/share/nginx/html)にphpinfoを表示させる
phpinfoを作成する。

```/usr/share/nginx/html/phpinfo.php
<?php phpinfo(); ?>
```

### 再起動
php-fpm,nginxを再起動する。

```
# sudo systemctl restart php-fpm
# sudo systemctl restart nginx
```

### ブラウザで確認
ブラウザで先ほど作成したphpinfo.phpにアクセスする。

<img width="1004" alt="スクリーンショット 2019-04-01 16.33.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/10263/13e88f16-f5f6-2915-54d8-564d9ea638ba.png">
<img width="1005" alt="スクリーンショット 2019-04-01 16.34.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/10263/9a72323a-dd1f-c549-653a-e3eb6817dda7.png">


## 参考
[AmazonLinux2](https://aws.amazon.com/jp/amazon-linux-2/)
[Amazon Linux 2にExtrasレポジトリからNginxをインストールする](https://dev.classmethod.jp/cloud/aws/install-nginx-on-amazon-linux2-from-extras-repository/)
[Amazon Linux 2のExtras Library(amazon-linux-extras)を使ってみた](https://dev.classmethod.jp/cloud/aws/how-to-work-with-amazon-linux2-amazon-linux-extras/)
DevHubを集めてパワーアップするsfdx-devhub-pool

## 概要

Developer EditionでDevHub機能が有効化されたときにおそらく誰もが考えたとおもうのですが、案外誰もやってなさげだったので自重せずに作成されたSalesforce CLIプラグインです。皆まで言わないです。つまり10個DEを作ればDailyで50までScratch組織作成できます。

[sfdx-devhub-pool](https://github.com/stomita/sfdx-devhub-pool)

## インストール方法

```
$ sfdx plugins:install sfdx-devhub-pool
```

## 利用方法

以下のコマンドで、DevHubプールとして指定された組織の内のいずれか最も日別空きスロットの多い組織を利用してScratch組織を作成します。なおあらかじめDevHubを有効化した組織（Developer EditionなどでOK）を複数作っておく必要があります。`--devhubpoolusernames`(`-p`)オプションにそれらの組織の管理者のユーザ名をコンマ(,)区切りで指定します。あとのオプションは `force:org:create` と同じです。

```
$ sfdx devhubpool:org:create -p admin@hub01.example.org,admin@hub02.example.org -f path/to/project-scratch-def.json
```


CIなどでDevHubに接続する際にはJWTで接続すると思いますが、プールに指定したユーザアカウントで一気に認証するコマンドも作っています。接続アプリは[この前の記事](https://qiita.com/stomita/items/4b0efdec3792b4fa706b)を参照して１つを共有するようにしてください。

```
$ sfdx devhubpool:auth:jwt:grant -u admin@hub01.example.org,admin@hub02.example.org -f path/to/server.key -i CLIENT_ID
```

## 補足事項

ちなみに、利用規約等でこのような使い方を禁じてるところは現時点(2019/4/1)では見つけられていませんが、Developer Editionのアカウントの複数取得は禁じられてはいないと思うので、その限りにおいては大丈夫だとは思っています。しかしながら、現在OKであっても今後禁止される可能性はなくはないでしょう。どちらかというと作成数制限の緩和・解除の方向に行ってほしいところではあります。もちろんUnlimited Edition契約は腐るほどあるが日次200組織程度では収まらん！みたいな富豪なお客様にも有用にお使いいただけるものではないかと思います（たぶん有償ならいくらでも緩和してもらえるとは思うんですけどね）。
php4を終えて

こんにちは
未来電子テクノロジーでインターンをしています
今回はphp4を終えての学びをまとめていきたいと思います

<h1>リンクの作り方</h1>
リンクはshow.php というクラスを用いて作成します。
具体的には、
＜a　hre "show.php"＞
＜ｐ＞＜？php　/php＞　＜/a＞という形を使います
このphpの間に飛ばしたいサイトのリンクを挿入します。

<h1>Revieページの作り方</h1>
次にRevieページの作り方です
リンクを飛ばす以外にもそのサイトのRevieを記載したいときに以下の方法を使用します。
主には　class　REVIE｛Pribvate
           
　　　　　　　　　　　　　　　　　｝
の形を使用します。
 このprivateの後にRevieを付けたい商品のプロパティを記載します。

また多くの人のRevieを記載したいときはuserクラスを使用します。
具体的には
class　user　｛
　　　　　　　　　　privete
｝の形を持ちます
このpriveteの後に性別や名前を記入します。

Revieを記入する際に一人一人のuserを識別することもあると思います。
その際にはidクラスを使用しましょう。
具体的には
class　user　｛
privete　$id
｝
とすることで使用できます
このユーザークラスには、idのほかに先程の名前や性別の情報も記入します

<h1>まとめ</h1>
以上がphp4を終えてのまとめです。
次回からは課題作成に移るので復習を行って取り組みたいと思います。
プライベート環境のGitLabからAWS のCodeCommitにミラーリングする


プライベートな環境に構築したGitLabのリポジトリをAWS上のCodeCommitにミラーリングして反映させる手順になります。
CodeCommitをSourceとしてAWS Pipelineで色々繋げてCI/CD的なことをするのが目的です。

## AWS IAMでAWS CodeCommitのアカウントを作成

GitLabからAWS CodeCommitにミラーリングする設定をするときに使うので認証情報を払い出しておきます。

`IAM`→`ユーザ`→`認証情報タブ`→`AWS CodeCommit の HTTPS Git 認証情報`→`生成`ボタンクリックでアカウントを生成します。

## AWS CodeCommitで空のリポジトリ作成

<img width="1409" alt="2.png" src="https://qiita-image-store.s3.amazonaws.com/0/203061/7e26d04f-3d6d-4d1f-bba9-7b8b50d2c5fc.png">


## プライベートのGitLabプロジェクトを作成・ミラーリング設定

とりあえず、プロジェクトを新規に作って

<img width="1409" alt="1.png" src="https://qiita-image-store.s3.amazonaws.com/0/203061/47fb46a2-862c-0f9c-b345-be607043dd79.png">

`Settings`→`Repository`→`Mirror Repository`でAWS CodeCommitのリポジトリURL、先ほど払い出したアカウント情報を設定します。

ここまでで設定完了です。

## GitLabにPushしてCodeCommitに反映されることを確認

GitLabに適当なファイルをPushしたら、

<img width="1409" alt="3.png" src="https://qiita-image-store.s3.amazonaws.com/0/203061/f92de88e-ffe4-aa7c-1358-a08f915d596b.png">

以下のようにCodeCommitまで反映されることを確認します。

<img width="1411" alt="4.png" src="https://qiita-image-store.s3.amazonaws.com/0/203061/807a0785-e648-28a0-d675-281930ca306c.png">

<img width="1401" alt="5.png" src="https://qiita-image-store.s3.amazonaws.com/0/203061/0c2d677a-e976-ded1-cbdc-51f833258b28.png">
PDB 単位の AWRスナップショットを試す（Oracle Database 12c Release 2)

Oracle Database 12c Release 1 までは、AWRはCDB$ROOTコンテナに格納されていて、PDB 単位の情報は取得できませんでした。Oracle Database 12c Release 2 では、スナップショットの取得やレポートの出力を PDB の単位でも指定できるようになりました。

# PDB単位のスナップショット
Oracle Database 12c Release 1では、AWRスナップショットは、CDB$ROOTコンテナのSYSAUX表領域のみに格納されていましたが、Oracle Database 12c Release 2では、PDBのスナップショットは、各PDBのSYSAUX表領域にも格納されるようになりました。

# PDBのAWR自動取得
初期化パラメーターawr_pdb_autoflush_enabledをTRUEに指定すると、自動的なスナップショットが作成されます。デフォルト値はFALSEで自動取得は行われません。

```
SQL> ALTER SYSTEM SET AWR_PDB_AUTOFLUSH_ENABLED = TRUE;

システムが変更されました。
```

この初期化パラメーターはCDBの単位で指定すると、全PDBでAWRスナップショットが自動的に作成されます。各PDBでTRUEに指定すると、指定されたPDBでのみ自動的にAWRスナップショットが作成されます。

# AWRのカスタマイズ
AWRのカスタマイズ方法は、[AWR のカスタマイズを試す（Oracle Database 18c）](https://qiita.com/plusultra/items/0361a0c90a7bc55f6eba)で書いた方法と同じですが、PDB単位に変更できるようになっています。設定を参照するビューはAWR_PDB_WR_CONTROLです。下記の例では、自動取得間隔を10分に指定しています。
CDB単位の自動取得設定は、AWR_ROOT_WR_CONTROLビューを確認します。

```
SQL> EXEC dbms_workload_repository.modify_snapshot_settings (interval=>10);

PL/SQLプロシージャが正常に完了しました。

SQL> SELECT * FROM AWR_PDB_WR_CONTROL;

      DBID SNAP_INTERVAL        RETENTION            TOPNSQL        CON_ID
---------- -------------------- -------------------- ---------- ----------
 418462544 +00000 00:10:00.0    +00008 00:00:00.0    DEFAULT             3

SQL> SELECT * FROM AWR_ROOT_WR_CONTROL;

      DBID SNAP_INTERVAL        RETENTION            TOPNSQL        CON_ID
---------- -------------------- -------------------- ---------- ----------
2997541579 +00000 01:00:00.0    +00008 00:00:00.0    DEFAULT             0

```

PDB内だけのスナップショット情報を参照するには、AWR_PDB_SNAPSHOTビューを参照します。逆にCDBのスナップショット情報を参照するには、AWR_ROOT_SNAPSHOTビューを参照します。CDB$ROOTコンテナに接続しているときは、AWR_PDB_SNAPSHOTビュー、AWR_ROOT_SNAPSHOTビュー、DBA_HIST_SNAPSHOTビューは同じ内容を指しています。

AWR_PDB_SNAPSHOTビューのSNAP_ID列の値は、AWR_ROOT_SNAPSHOTビュー（DBA_HIST_SNAPSHOTビューと同じ）の、SNAP_IDとは別のIDが作成されます。

```
SQL> SELECT MAX(SNAP_ID) FROM AWR_PDB_SNAPSHOT;

MAX(SNAP_ID)
------------
           2

SQL> SELECT MAX(SNAP_ID) FROM AWR_ROOT_SNAPSHOT;

MAX(SNAP_ID)
------------
          52

SQL> SELECT MAX(SNAP_ID) FROM DBA_HIST_SNAPSHOT;

MAX(SNAP_ID)
------------
          52
```

# SNAPSHOTの手動作成
スナップショットの作成には、PDBに対して管理者権限で接続してから dbms_workload_repository.create_snapshotプロシージャを実行します。やりかたはCDBの場合と同じです。

```
SQL> SHOW con_name;

CON_NAME
------------------------------
O12R2APDB1
SQL> EXEC dbms_workload_repository.create_snapshot();

PL/SQLプロシージャが正常に完了しました。

SQL> SELECT MAX(SNAP_ID) FROM AWR_PDB_SNAPSHOT;

MAX(SNAP_ID)
------------
           3
```
Material Components for AndroidのChipに発生するRippleEffectを消す

# 概要
リストアイテム内にChipを表示している画面で、リストアイテムをタップするとChipにもRippleEffectが発生していました。
動作上は問題ありませんが、見た目に少し違和感を感じました。
リストアイテムをタップしてもChipにはRippleEffectが発生しないように修正しました。

![screenshot1.gif](https://qiita-image-store.s3.amazonaws.com/0/136368/81260a5e-e732-7508-f19d-b7b19c52f3bd.gif)

- rippleColorを透明にする
- clickListenerをnullにするとRippleEffectは発生しないがElevationが効かなくなる

# 詳細
## rippleColorを透明にする
`app:rippleColor="@android:color/transparent"`を指定するとRippleEffectの色を透明にできます。

```xml
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.chip.Chip 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:checkable="false"
    android:clickable="false"
    app:chipIconEnabled="false"
    app:closeIconEnabled="false"
    app:rippleColor="@android:color/transparent" />
```

![screenshot2.gif](https://qiita-image-store.s3.amazonaws.com/0/136368/8f422e22-ae77-3033-e6f0-3744d67753fc.gif)

## clickListenerをnullにするとRippleEffectは発生しないがElevationが効かなくなる
挙動を見たところ親のリストアイテムで発生したクリックイベントが子のChipに伝搬しているように思えました。
そのため、試しにChipのクリックリスナーにnullを設定してクリックイベントが伝搬しないようになるか試してみました。
結果的にRippleEffectは発生しなくなりましたが、タップ時のElevationがなくなってしまいました。
また、これまでは`android:clickable="false"`でクリック不可にしていたChipがクリックできるようになってしまいました。

```kotlin
(LayoutInflater.from(context).inflate(R.layout.chip, this, false) as Chip).setOnClickListener(null)
```

![screenshot3.gif](https://qiita-image-store.s3.amazonaws.com/0/136368/9372f7c2-d745-4796-69eb-dbd46d1665ac.gif)
nockでワイルドカードでマッチさせる

* persistをつける（付けないと2回目以降マッチしない）
* 正規表現か関数でマッチさせる

```js
  nock('http://test.system7000.com')
  .persist()
  .get(/.+/)
  .reply(200, 'ok')
```

or

```js
nock('http://test.system7000.com')
  .persist()
  .get(() => true)
  .reply(200, 'ok')
```
Google Play Consoleの時間指定公開の使い方

# 概要

Google Play Consoleの時間指定公開について実際に使ってみて分かったことを記載します。
これから使おうと思っている方はぜひ参考にしてみてください。

- 時間指定公開とは公開時間を指定して時限式に公開できる機能ではない
- 時間指定公開をONにすればクローズドアルファ版から製品版へアップロードしてもストアには公開されない

# 詳細
## 時間指定公開とは公開時間を指定して時限式に公開できる機能ではない

Google Play Consoleではストアの掲載情報やアプリ(apkファイル)のアップロードを行うと、それらを処理する時間が発生します。
そのため、アップロード直後にそれらの内容がストアに即時反映されるわけではありません。

時間指定公開とは、それらのアップロード処理を事前に終わらせておくことで、公開ボタンを押したタイミングでストアに即時反映できる機能のことです。
誤解を生みやすい名前ですが、時間指定公開を使っても時限式の公開はできません。

## 時間指定公開をONにすればクローズドアルファ版から製品版へアップロードしてもストアには公開されない

こちらは私が実際に使ってみて少しつまづいたポイントです。
時間指定公開をONにした状態でストアの掲載情報などを更新・アップロードすると、`変更ログを表示`という画面に変更履歴が表示されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/136368/43729c59-0fa8-f312-afc2-bbe89304de54.png)

しかし、アプリをクローズドアルファ版から製品版へアップロードした際はその操作がログに表示されませんでした。
ストアに公開されてしまったのではないかと非常に不安になったのでチャットサポートから問い合わせてみました。

`質問：時間指定公開をONにした状態でクローズドアルファ版から製品版へアップロードしたのですが、変更ログに表示が追加されず市場に公開されているのではないかと不安です。市場公開されているかご確認いただけますでしょうか。`

![image (1).png](https://qiita-image-store.s3.amazonaws.com/0/136368/e9973bf0-a190-5740-1c98-5a64de356f3c.png)

結論として、時間指定公開がONになっていれば製品版へのアップロードでもコンソール上部に表示される公開ボタンを押さない限りはストアへの反映は行われないとのことでした。
FlutterでWebViewをダイアログ内に表示する

# 概要
FlutterでWebViewをダイアログ表示するのに苦労したので残します。
今回の要件は、Firebase Hostingを用いてホスティングしたHTML文書をダイアログ内のWebViewで表示することです。

- FlutterのWebView表示には[flutter_inappbrowser](https://github.com/pichillilorenzo/flutter_inappbrowser)を使いました
- [flutter_webview_plugin](https://github.com/fluttercommunity/flutter_webview_plugin)はダイアログ表示ができない
- Flutter公式の[webview_flutter](https://github.com/flutter/plugins/tree/master/packages/webview_flutter)はHTMLの読み込みでバグがある

# 詳細
## FlutterのWebView表示には[flutter_inappbrowser](https://github.com/pichillilorenzo/flutter_inappbrowser)を使いました

使い方は簡単です。

```dart
/// これでWebViewが表示できる
InAppWebView(initialUrl: url);

/// ダイアログ内で表示する場合
showDialog(
  context: context,
  builder: (BuildContext context) {
    return InAppWebView(initialUrl: url);
  }
)
```

## [flutter_webview_plugin](https://github.com/fluttercommunity/flutter_webview_plugin)はダイアログ表示ができない

https://github.com/fluttercommunity/flutter_webview_plugin/issues/69
こちらのIssueで言及されていますが、このプラグインはFlutterのWidgetTree内に描画しているのではなくScaffoldの一番上に表示されてしまうため、Dialogのようなコンテナ内に表示できません。
実際にダイアログ内に入れて動かしてみたところ、ダイアログからはみ出るような形で描画されてしまいました。

![image (2).png](https://qiita-image-store.s3.amazonaws.com/0/136368/07960ec1-a396-4f63-9c12-e212d2f9d3ee.png)

## Flutter公式の[webview_flutter](https://github.com/flutter/plugins/tree/master/packages/webview_flutter)はHTMLの読み込みでバグがある

https://github.com/flutter/flutter/issues/29446
こちらのプラグインを使用したところ、ホスティングしたHTML文書を読み込んだ際に上記Issueと同様のエラーが発生しました。
コメントを見たところ、どうやら元を辿ればChomiumのバグのようです。

https://github.com/flutter/plugins/pull/1360
2019年3月27日現在、どうやら上記のプルリクエストでIssueの修正がされたようですが、こちらの[Issueコメント](https://github.com/flutter/flutter/issues/29446#issuecomment-475796924)によるとまだ修正しきれていないようで再オープンとなっています。
【Excel VBA】視認性の良いシンプルな罫線・フォント設定をするマクロ

# マクロ実行前後比較

【びふぉー】
![image.png](https://qiita-image-store.s3.amazonaws.com/0/293799/2358b5f3-691b-fc71-bc22-229e64c6bded.png)
【あふたー】
![image.png](https://qiita-image-store.s3.amazonaws.com/0/293799/c3bacbc6-24c4-be10-a07f-86aa94777607.png)

# 何のため
上図のように構造化した情報をリストアップした際、**セル結合による視認性向上をしたくないため**。
（フィルター抽出できなくなるじゃないかああああ）

上のセルと比較してセル内容が等しかったらフォントカラーを薄くし、セル内容が異なっていたら罫線を実線で引きます。
それらの範囲指定がベタ書きなので美しいコードではありません。その都度コード修正。
簡単なコードだからこの程度で良いかーという……。

# コード

```vb
    Sub 視認性良く罫線とフォント設定()

      '範囲選択
      Range("A1").Select
      Range(Selection, ActiveCell.SpecialCells(xlLastCell)).Select
      
      '書式設定を初期化
      Cells.FormatConditions.Delete
      
      '罫線書式設定
      Selection.FormatConditions.Add Type:=xlExpression, Formula1:="=$C1<>$C2"
      Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
      With Selection.FormatConditions(1).Borders(xlBottom)
          .LineStyle = xlContinuous
          .TintAndShade = 0
          .Weight = xlThin
      End With
      Selection.FormatConditions(1).StopIfTrue = False
    
      'フォント書式設定
      Range("B2").Select
      Range(Selection, ActiveCell.SpecialCells(xlLastCell)).Select
      Selection.FormatConditions.Add Type:=xlExpression, Formula1:="=B2=B1"
      Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
      With Selection.FormatConditions(1).Font
          .ThemeColor = xlThemeColorDark1
          .TintAndShade = -0.249946592608417
      End With
      Selection.FormatConditions(1).StopIfTrue = False
    
      '最後に罫線設定
      Range("A1").Select
      Range(Selection, ActiveCell.SpecialCells(xlLastCell)).Select
      '基本的に実線
      With Selection.Borders
          .LineStyle = xlContinuous
          .ColorIndex = xlAutomatic
          .TintAndShade = 0
          .Weight = xlThin
      End With
      '内側水平線のみ点線
      With Selection.Borders(xlInsideHorizontal)
          .Weight = xlHairline
      End With
    
    End Sub
```
画像を分割してアニメーションするときの注意点

EaselJSで描画した画像を1000くらいに分割し、トゥイーンで動かした時に気がついた注意点など。

やりたいことの結果はこちら。
https://279798.playcode.io/

注意点として、「刻んだ画像(以下ブロック画像)をモザイク状に再配置する計算を行うスクリプトではない」ということをご承知置きください。
再配置の設計図は別のスクリプトで生成し、JSON化してスクリプトに埋め込んでいます。

結果今回やってみて気がついたこととして、
1. 大量のビットマップインスタンスを扱うときは**cache**を使うこと
2. 各インスタンスは必要な時に生成し、必要が無くなったらインスタンスやトゥイーンをこまめに消すこと。
　**addChildして隠して存在させておくより、必要になったらaddChildし、必要が無くなったら即removeChildさせる**
　(=大量のインスタンスを生成させるようなプログラムの場合、大量のインスタンスを結合させる設計にすること)
3. 安易なクラス化はパフォーマンスを低下させる
4. **CreateJS 2.0Beta(ES Module版)では.updateCache("source-over")がまだ動作しない**:innocent:(半日悩んだ)
ということでした。

また、CreateJSのcache機能について色々なサイトを読みましたが、「ビットマップオブジェクトでは逆にパフォーマンスが低下する」「シェイプでしか意味がない」などの意見がいくつかありました。
バージョンの関係もあるかと思いますが、1.0.2を使って見た限りではビットマップでもパフォーマンスは向上するように感じました。

細かい解説は追々追記していきたいと思います。
もそ、プログラミングを学ぶ【Ruby & Rails復習編】〜続・エラーを解いてみよう！〜

新しい元号が発表され、時代の変化を感じている平成生まれアラサー、もそ。
子どものころに思い浮かべていたアラサー像とは程遠く、時の流れの残酷さを痛感しております...
私もディオみたいに時を止めたい（一瞬しか止まりませんが）

そんなことをぼやきつつ、今日もエラー問題のロープレを頑張っております。

前回に引き続き、今回もモデルとコントローラに関するエラー問題です。

##エラー発生、名探偵もそ出動！

まずは実際のエラー画面をみてみましょう。↓

<img width="1113" alt="664e908013878c67518484155316c1db.png" src="https://qiita-image-store.s3.amazonaws.com/0/372174/d679388d-2bb4-c32d-f9ec-0ecef07f340d.png">

まずは現場検証です。
**・ログインをした状態で、
・一覧ページから詳細ページをクリックしたとき**

に、事件（エラー）は発生しました。

さあ、名探偵もそ（桜ver.）の登場です。

![無題1172 2.jpeg](https://qiita-image-store.s3.amazonaws.com/0/372174/813017fc-7c32-8509-0d6f-cf7f0ce8db1a.jpeg)

もそは早速、２行目の**"Did you mean?comment comment="というコメント**と、
赤文字部分の記述に注目。

名探偵もその推理はこうです。

「このエラー文、３４行目の記述に出てくる"comments"は"comment"の間違いでは？と言っている」
「ということは、どこかの記述で"comment"という名前の記述があるに違いない...！」

ここでいう**「どこかのファイル」は一体どこなのか？**


赤くなっている部分の記述は、"showアクションではtweetとcommentsを表示する"という指示です。
このtweetとcommentsは、一つのツイートに対して多数のコメントという**一対多の関係**となっています。
つまり**アソシエーション**をしている可能性が高い。

ということは、これは**モデルフォルダ配下の記述が怪しいぞ...!**
コントローラの記述と、モデルの記述を見比べてみましょう。

```controller.rb

①   def show
②    @tweet = Tweet.find(params[:id])
③    @comments = @tweet.comments.includes(:user)
④   end
```

```model.rb
①_1  class Tweet < ApplicationRecord
②_2   belongs_to :user
③_3   has_many :comment
④_4　end
```

③と③_3をよーーく見てみてください。

③_3では、has_many :commentとなっています。
この部分の記述は has_many :comments が正解！

名探偵もそ、見事エラーを解決しました！


##解説とポイント

今回のポイントは、**コントローラファイルの変数はどこで定義されているか?**ということ。
([前回の記事](https://qiita.com/moso/private/7d39bbc2c26b17217333)でもモデルとアソシエーションについて書いているので、参考にしてみてください。)


コントローラの変数を定義しているのは**モデル**なのです。

```model.rb
①_1  class Tweet < ApplicationRecord
②_2   belongs_to :user
③_3   has_many :comments
④_4　end
```

実は先ほどの問題は、③_3の"comments" の部分を "comment"のままにして、コントローラファイルの③を


```rb
③  @comments = @tweet.comments.includes(:user)
```

としてもエラーは解決できます。
なぜなら、ファイル間で名前が一致していればプログラムを動かすことができるからです。

でもカリキュラムでは"has_many :comments"が紹介されていますし、そちらの表記の方が望ましいです。
何故でしょうか？

実はこれ、単純に英語表記の正しさだけではなく、**③の記述が複数個のtweet要素をもつ配列(=tweets)**ということを示せるのです。

このように記述することで、たとえば他の人がコードを見た時に混乱せずに内容を理解することができます。

<img width="375" alt="無題1175.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/372174/b119a894-b71e-4f7c-b369-569842e1715d.jpeg">



--
いかがだったでしょうか？

エラー問題に少し慣れてきたのか、はたまたプログラミング能力が覚醒しつつあるのか、だんだんと理解できるようになってきました！
桜の満開とともに私の能力も開花しますように...もその学習は続く。
量子アニーリングで計算するための初歩の初歩を考えてみた

量子コンピュータといろいろ世間で騒がれていますが、1982年にファイマンによって提唱されたもの（ゲート型）と、1998年に門脇、西森によって考えられた量子アニーリングっていうのがあります。量子アニーリングはやれることがとても限定的です。歴史的な説明は今後するとして、D-Waveが量子アニーリングをつかって本当に量子的な振る舞いを使って計算する機械を公開したっていうのが新しい扉を開けたと感じています。

D-WaveのLeapも日本から１分間つかえるし、HitachiのCMOSアニーラもAnnealing Cloud 経由で両方とも無料でつかえるので、本当にいい時代だとおもう。

量子アニーリングで計算するための初歩の初歩を考えてみたということで、本題に進んでいきます。量子アニーリングでは、イジング模型として、エネルギーの状態をハミルトニアン$H$で次の方程式のように表しますが、

$$H = \sum_{i<j} J_{ij} \sigma_i \sigma_j + \sum_i h_i \sigma_i $$

はじめのころは、これが全く何を言っているのか不明だった。

１、物理学的な意味
２、なんで量子アニーリングで計算できるのか？

の２点である。
１、物理学的な意味は、あまりわかっていない。一応、大学で量子力学の講義は受けて単位もらったけど、工学部で環境熱流体をやったので、そこまでちゃんとやっていないから、再度復習する必要があった。数冊量子力学の本を読んでみたが、このあたりはほとんど書いてないので、とりあえず、時間発展のハミルトニアンについてわかった気になって終わったというか、計算には物理学的な意味はあまり必要無いようにおもえる。ただし、知っていたほうがいいこともありそうなので、そのあたりはまた今度。

２、なんで量子アニーリングで計算できるのか、こっちがわからないと、アニーリングマシンで計算することができないので、ここでは簡単に説明していく。


$$H = \sum_{i<j} J_{ij} \sigma_i \sigma_j + \sum_i h_i \sigma_i $$

は、$\sum_{i<j} J_{ij} \sigma_i \sigma_j $　の相互作用項と、
$ \sum_i h_i \sigma_i $の磁場項の２つから成り立っている。

ここでは簡単に０、１、２、３の４個の量子ビットからなるモデルを考えてみる。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/260261/edb9ccba-1b49-ce8b-fdaf-59fc4fa9a709.png)

磁場項が0は−1、1は+1、2は-1、3は+1となっていて、相互作用が0-1の間は+1, 1-2の間が+1, 2-3の間が-1, 0−3の間が−1で、対角線の0-2の間は0,1−3の間も0としてある。これを先ほどのハミルトニアンでの式で記述すると、
磁場項が、
$$ 1 * \sigma_0 \sigma_1 + 1 * \sigma_1 \sigma_2 -1 * \sigma_2 \sigma_3 + 0 * \sigma_0 \sigma_2 + -1 * \sigma_0 \sigma_3 + 0* \sigma_1 \sigma_3 $$ 

と、相互作用が
$$ -1 * \sigma_0 + 1 * \sigma_1 -1 * \sigma_2 + 1* \sigma_3 $$

となり、整理すると、

$$ H =  \sigma_0 \sigma_1 +  \sigma_1 \sigma_2 - \sigma_2 \sigma_3  -  \sigma_0 \sigma_3  \\ 
 - \sigma_0 +  \sigma_1 - \sigma_2 +  \sigma_3 $$

となり、これをアニーリングマシンへ放り込めば計算結果がでてくる仕組みとなっている。

どう放り込むか？というと、Ising -1 or 1  のモデルもしくはQubo 0 or 1のモデルで行列をつくって、マシンに入れてあげればいい。

```
相互作用の項
---
0 0 -1
1 1 +1
2 2 -1
3 3 +1
---
磁場項の項
0 1 1
0 2 0
1 2 1
0 3 -1 
1 3 0
2 3 -1
```
というように、磁場項の方は量子ビットの番号と数値、相互作用の項は量子ビット間と数値　というようにあわらし、アニーリングマシンへ投げると結果が戻ってきます。

たとえば、これをHitachiのCMOSアニーラで公開されているannealing-cloudを
のイジングエディタで、上記をやってみると、
https://annealing-cloud.com/play/ising-editor.html

<img width="1132" alt="Screen Shot 2019-04-01 at 16.33.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/260261/9708b738-0450-5ecc-c5b2-c7e5db310ea7.png">

このような感じに設定して、　実行を押すと、結果が

<img width="1146" alt="Screen Shot 2019-04-01 at 16.35.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/260261/47491d0d-cde8-d29f-b658-b395089ad06d.png">

こんな感じに戻ってくるということになります。
エネルギー（ハミルトニアン）は最低で−6（この場合は１つだったが複数出る場合がある）で、

```
0番 +1
1番 -1
2番 +1
3番 +1
```
の時にこのエネルギーが一番引く状態（基底状態）を得られたということになります。
これらを応用していくと、様々な問題を解くことが可能になるといったわけです。

今日のところはこのくらいで終了です。
Google App Engine Go で Cloud Firestore Native Mode を使う

# Cloud Firestore
今回使う [Cloud Firestore](https://cloud.google.com/firestore/?hl=ja) ですが、[Firebase](https://console.firebase.google.com/?hl=ja) の技術をベースにして、Google Cloud Platform に統合されたサービスです。
ネット上で調べると、結構 Firebase に関する記事が出てきますが、作成方法などがちょっと違いますので、メモをまとめていきます。

Native mode については下記に参考：
[Native mode とは？](https://cloud.google.com/firestore/docs/firestore-or-datastore?hl=JA)

# GAE
サーバ上で利用する時は公式手順を参考すればできます：
[クイックスタート：サーバ](https://cloud.google.com/firestore/docs/quickstart-servers?hl=ja)

AppEngineを使う時の変更点：
1.  **プロジェクトの課金を有効化する必要があります。有効しないとデプロイ後は Cloud Firestore との Socket 通信時にエラーとなります**
2. コードの変更ところは下記のように：

```handlers.go
import (
	"google.golang.org/appengine"
	"google.golang.org/appengine/log"

	"cloud.google.com/go/firestore"
)

func TestHandler(w http.ResponseWriter, r *http.Request) {
	ctx := appengine.NewContext(r) // ここは要注意
	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		log.Errorf(ctx, "Failed to create client: %v", err)　// log関数の引数は違う
	}
	// Close client when done.
	defer client.Close()
}
```
ここで出した log は `gcloud app logs` では見れなくて、stackdriver logging で見れます。

# 後書き
初めての利用で公式ドキュメントを見ながらテストしてますが、間違っている点などありましたらコメント等でお知らせ下さい。
Swift5 マイグレーション手順

## 概要

- Swift4.2 から Swift５ にアップデートしたので手順を明記しておきます。

## 変更点

- Swift5の変更点については言及しませんのでこちらをご覧ください
- [Swift 5 Release Notes for Xcode 10\.2 \| Apple Developer Documentation](https://developer.apple.com/documentation/xcode_release_notes/xcode_10_2_release_notes/swift_5_release_notes_for_xcode_10_2)
- [来たるSwift5の新機能をまとめました \- Qiita](https://qiita.com/tamappe/items/64fbe4d0991cd222540e)

## 手順

### Xcodeをインストール

- Swift5でコンパイルするためにはXcode10.2をインストールする必要があります。
  - Xcode10.x をすでにインストール済みの人 [アップデート ストアリンク](https://itunes.apple.com/us/app/xcode/id497799835)
  - Xcode10.x をまだインストールしてない人 [Xcode10.2 ダウンロードリンク](https://download.developer.apple.com/Developer_Tools/Xcode_10.2/Xcode_10.2.xip)

### XcodeのSwiftバージョンを変更

- Xcode10.2起動
- Xcode > Build Setting > Swift Compiler - Language > Swift Language Version > Swift5 に切り替え

### Carthageのライブラリを更新

- Carthageを使用していない場合はスキップ
- こんな感じのエラーが出た場合

```
Module compiled with Swift 5.0 cannot be imported by the Swift 4.2.1 compiler
```

- コンパイルをやり直す必要がある

```
$ carthage update --platform iOS
```

- 注意：binaryでインストールしている場合はSwift5でコンパイルされたバイナリが公開されているか各ライブラリで確認が必要です（公開されていなければ使えません）
- いくつかコンパイルできないライブラリがあったので、対応されるまでPodに退避させました。

### Swift5に修正

- あとはコードを Swift４ -> Swift5 にコンバートしてください（投げやり）
glob.globにおけるbad character range * at position * の解決方法

## 問題のコード
とあるディレクトリ直下のファイルをマッチングしたい場合、glob.globを使いますが、その際によく見るエラーがありましたのでこれを解消したいと思います。

```python:sample.py
import glob
path = "D:\SAMPLE18\[201806] [HASK] [SAMPLE]"
files = glob.glob(os.path.join(path,"**"),recursive = True)
```

```python:console
bad character range u-0 at position 10
```
## 解決方法
これはマッチングしたいパス内に特殊文字が含まれているため、マッチングできないといった旨のエラーです。
上記コードでは、"**[**"が特殊文字であるため、マッチングに失敗しています。
ですので、パス内の特殊文字をエスケープします。

```python:sample.py
import glob
path = "D:\SAMPLE18\[201806] [HASK] [SAMPLE]"
path = glob.escape(path)
files = glob.glob(os.path.join(path,"**"),recursive = True)
```

上記コードではマッチングが正常に完了します。
また、他にも'?' 、 '*'のような特殊文字がリテラル文字列に含まれている場合も同様のエラーを出力するため、特殊文字が含まれいている可能性のあるディレクトリをマッチングする際は、エスケープした方が良いと思います。

WindowsOSとその他では、若干動作が異なる場合があるため、下記リンクも参照してください。
[python.org glob --- Unix 形式のパス名のパターン展開](https://docs.python.org/ja/3/library/glob.html)
Unityのエディタ拡張でPrefabを関連付けを残したままインスタンス化する

# はじめに
エディタ拡張で以下の方法でアセットフォルダからPrefabをインスタンス化すると
名前に(Clone)がついてPrefabとの関連付けが切れた状態でインスタンス化されてたので
名前に(Clone)をつけずにPrefabと関連付けを残したままインスタンス化する方法です。

該当コード(対応前)

```csharp
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(プレハブのパス);
var obj = Object.Instantiate(prefab, Vector3.zero, Quaternion.identity) as GameObject;
```

# 環境
Unity 2017.4.15f1

# やり方
Prefabのインスタンス化に[PrefabUtility.InstantiatePrefab](https://docs.unity3d.com/ja/current/ScriptReference/PrefabUtility.InstantiatePrefab.html)を使います。

```csharp
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(プレハブのパス);
var obj = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
```

これで(Clone)とつかず、関連付けが残ったままでインスタンス化されたと思います
NICT EXISTをUbuntuで動かす&アップデートする

# summary
基本的に、内部利用で適当にまずは作ってみたときのメモ。

- NICTが公開した [EXIST](https://github.com/nict-csl/exist) を、Ubuntu18.04LTSに入れる際に注意すべき点の記載
- 面倒だから、systemdで使えるようにした
    - `systemctl start exist`
- EXISTが更新された際に、追従する方法

# インストール

@bule_or_red氏の[記事](https://qiita.com/bule_or_red/items/cbe4adb8be375a6fda08) を参照

- https://qiita.com/bule_or_red/items/cbe4adb8be375a6fda08

Ubuntuで入れる際には以下の差分を検討

- Celeryの環境変数は、`/etc/sysconfig/celery` ではなく `/etc/celery/celery` 辺りで良さそう。
    - `/etc/sysconfig/` が無いからね。
- バイナリは `/bin/celery` ではなく、`/usr/local/bin/celery` に有る
    - `CELERY_BIN="/usr/local/bin/celery"`


## 注意点
再起動すると、`/var/run/celery/` は消えている。その為、`systemctl start celery.service` が失敗して動かなくなる

- 対策として、毎回ディレクトリ掘るか、後述のバッチファイルに組み込むか、別の場所(`/tmp`でも良いんでは？)にする。

# 起動スクリプト

二段階の作業が必要

- 起動用のスクリプトを用意する
- systemdの設定を書く

起動スクリプトを、適当に用意する。/opt/exist/ に入れているのであれば、`/opt/exist/start-exist.sh` とかでいい

```
#!/bin/sh
# mkdir /var/run/celery; chown root:root /var/run/celery ; <-- /tmpとかにしない場合は。
python3 /opt/exist/manage.py runserver 0.0.0.0:8000
```

以下を、`/etc/systemd/system/exist.service` として配置

```
[Unit]
Description=NICT EXIST daemon
Documentation=https://github.com/nict-csl/exist

[Service]
ExecStart = /opt/exist/start-exist.sh
ExecRestart = /bin/kill -WINCH ${MAINPID} ; /opt/exist/start-exiest.sh
ExecStop = /bin/kill -WINCH ${MAINPID}
Restart = no
Type = simple
User = root
Group = root

[Install]
WantedBy = multi-user.target
```

これでsystemdでコントロールできるはず。

- `systemctl [start|stop] exist`

# EXISTアップデート

## 各種ソースからの情報取得

/opt/exist に入れている場合は以下の調整が必要。

- /opt/exist/scripts/insert2db/conf/insert2db.confの用意
- アップデートの実行
    - `scripts/insert2db/[exploit|reputation|threat|twitter]/insert2db.py`
    - APIキー等を全く用意していない場合は、reputationとexploitだけは未設定で使える。

insert2db.confは以下だけでも行ける

```
[exist]
syspath = /opt/exist
```

## アップデート
EXIST自体のアップデートを適用する。

- /etc/exist/ で `git clone` する
- `python3 manage.py migrate` しないとダメそう

`git clone` だけだと、WEB画面は出るが検索はできない(検索の応答がない)状態になる。

以上、メモでした。
resource busy (Address already in use) への対処例 [OS X]

JavaScriptやElmをローカルで実行した際

``Ctrl-c``でプロセスをキルすることを忘れてしまい

上記のようなエラーが出てしまった場合の対処法です

# 環境
```shell
$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.3
BuildVersion:   18D109
```

# 例
``http://localhost:8000``　を使用していた場合

```
$ lsof -i -P | grep 8000
elm  [プロセス番号] [ユーザー名] 3u IPv4 ...

$  kill -9 [プロセス番号]
```
以上よりプロセスがキルされます
モブプロを導入する前にやったこと

# この記事について

モブプロをやってみたという記事はよく見るので、その前段階として「やり始める前に考えたこと、やったこと」をまとめ、これに則ってモブプロを始めてみようと考えています。
実際に始めてみたらまた別の記事を書くかもしれないです。

[「モブプログラミング・ベストプラクティス」](https://www.amazon.co.jp/dp/B07NW2S2XV/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)を参考にしています。
チームメンバー全員がこの本を読んだ上でモブプロしていきます。

# 1. なぜモブプロをやるかを決める

- リソース効率ではなくフロー効率をあげたい（詳しくは本を参照）
 - 知識の偏り（属人化）の解消
 - 全体の技術レベルの向上
- それぞれが知っていること、知らないこと、考えていることを知りたい（個人の暗黙知の共有）

# 2. チームをあらためて把握する
## チームの状況、状態を知る

- 心理的安全性は高い
 - 心理的安全性が高くなるまでのことは[こちら](https://nekonohitai.hateblo.jp/entry/2019/03/07/020726)に書きました 
- スクラムっぽくやっているが、SBLが途中で変わることはよくある
 - 緊急的な対応が多い（お問い合わせ、作業依頼、障害の対応）

## チーム、チームメンバーの性質を知る

### 性格診断・ビッグ5

ビッグ5は無料診断がいくつかあるみようです。探してみてください:raised_hand:
今回は簡易的な無料診断をしてみました。
（外交性はあまりモブプロにおいて大きな役割を果たさないらしい）

<img width="623" alt="ビッグ5診断結果" src="https://qiita-image-store.s3.amazonaws.com/0/114317/d2e1ed0b-f576-e14b-c814-8d810f450d3e.png">

結果を見て、このチームにおいては次のようなことを注意してモブプロをしていこうと思っています。

- 協調性が高い
 - 逆に言うと対立を恐れ、議論を避ける可能性がある。そのような状態が見えたら策を講じていく必要がある
- 開放性が高い
 - どんどんやってこ！
- 真面目さが高いが、とても高い人がいる
 - 全員が主体性を持って取り組みを続けられるように、バランスを取っていく

（診断に簡易的すぎるものを選んだのは少し後悔しています）

### ４Dシステム的な何か

（comming soon？）

# 3. どのようにやるか決める

## 参加メンバーを決める

バックエンドエンジニア4名。
いずれフロントエンドエンジニアやQAエンジニアなども含めることを検討。

## 周期を決める

まずは週1、2時間から。徐々に週1日にしていきたい。
（やってみてから考える）

## タイムテーブルを決める

1. 初回のみなんかやる
2. 10分ごとにタイピストを交換する
 3. 交換する際に git push 

## 歓迎行動を決める

- 全員で問題解決のために努力する
- 人ではなくコードを批判する
- HRTに則ったコミュニケーションを心がける
- 他のメンバーの意見を聞く、意見を避難しない 
- 疑問に思ったことはきちんと質問する

## あえてセオリーに反しようと考えていること

- 共通のIDEを使わない
 - 現状全員違うものを使っているため、すぐには難しい。それぞれのIDEの使い方を見るのも参考になるのでは？と思っている
- 個室がない
 - 半個室状態でやってみる
【PBCS】EPM Automate(EPM自動化)について(その２）

前記事：[【PBCS】EPM Automate(EPM自動化)について(その１）](https://qiita.com/iwa_gino/items/53b6a9d4e99785ac1bf3)


## 3. replayコマンド

SMartViewで操作を覚えさせて、同じ動作を（複数回）行ったときのパフォーマンスを検証できる機能
　・当コマンドを使用することで、SmartViewの負荷がリプレイされる
　　⇒高負荷でのパフォーマンス・テストが可能。システムテスト等に有効。
　　　例)高負荷のテスト環境でユーザー操作をテスト後、
　　　　本番環境移行後もサービスが問題なく実行されるかどうかを確認する
　　
#### 【前提】
・SmartViewがインストールされていること
・EPM Automateがインストールされていること
・Fiddlerがインストールされていること（Fiddlerを使ってHARファイルが作成出来る必要がある）
　https://www.telerik.com/download/fiddler
　　
#### 【実行の流れ - 目次】
①環境準備
②HARファイルの作成
③リプレイファイルの作成
④replayコマンドの実行

#### 【実行の流れ】

##### ①環境準備
　1.replayコマンドを実行するマシンに次のツールがインストールされていることを確認する（導入方法は【前提】を参照）
　　　・EPM Automate
　　　・SmartView
　　　・Fiddler
　2.Fiddlerのオプション設定を行う
　　　・Fiddlerを開く
　　　　※ポップアップが出た場合はNo
　　　・Tool > Option > HTTPSを開く
　　　・Decrypt HTTPS trafficをチェック
　　　・Trust the Fiddler Root certificate?⇒ Noを押下
　　　・OKを押下してオプションを閉じる

##### ②HARファイルの作成
　1.SmartViewから任意のPBCS環境にログインする
　2.Fiddlerを開く
　3.記憶させるSmartView操作を行う
　　例)Webフォームを開く⇒データ入力⇒データ送信
　　※証明書に関するポップアップが表示されることがあるので、その場合は「はい」をクリック
　4.File > Export Sessions > All Sessionsをクリック
　5.「Select Export Format」で、エクスポート形式として「HTTPArchive v1.1」を選択して「Next」をクリック
　6.任意の場所にHARファイルを保存する

##### ③リプレイファイルの作成
　1.新規Excelを開き、以下の要領で環境情報を入力する
　　列A：ユーザ名
　　列B：パスワード
　　列C：実行するHARファイル
　　※複数環境 または 複数ユーザーを使用する場合は複数行にして入力
　2.CSV形式でファイルを保存
　3.テキストエディタで開きなおし、「UTF-8」で上書き保存する

##### ④replayコマンドの実行
　1.コマンドプロンプトを開く
　2.epmautomateでログイン
　　-- epmautomate login [ユーザ名] [パスワード] [PBCS URL] [ドメイン名] 
　3.replayコマンドを実行
　-- epmautomate replay "リプレイファイル" trace=true[> "出力ログパス"（ログを残す場合）]


## 4. データ・ロード・ルール(FDMEE)の実行


```
epmautomate rundatarule 【データ・ロード・ルール名】 【開始期間】 【終了期間】 【インポート・モード】 【エクスポート・モード】 【取込ファイル名】
```


【コマンド例】


```
epmautomate rundatarule DLR_Actual 202704 202706 REPLACE STORE_DATA 202704_ActualData.csv
```

※【データ・ロード・ルール名】 【開始期間】 【終了期間】 は、
　FDMEEで事前に定義したものを使用します。（詳細はFDMEEの項参照）
※インポートモード、エクスポートモードの設定値は、EPMマニュアルを参照
※取込ファイル名はパスを含めない（マニュアルでは含めて表記されているが、実際そうすると取込エラーになった）

## 5. 受信/送信ボックスのファイル確認

・取込ファイルは事前にPBCS環境にアップロードされている必要があります。（EPMAutomateで実行可能）
・取込を確認するために、以下のコマンドでファイルの存在を確かめます。


```
epmautomate listfiles
```


## 6. ビジネス・ルールの起動


```
epmautomate runbusinessrule 【ビジネス・ルール名】 【置換変数に渡す値】
```


【コマンド例】

```
epmautomate runbusinessrule BR001_○○処理 P_Years=FY27 P_Period=M02
```
golangのテンプレートエンジンの動きを気軽に確認する方法


### src
---

```golang
package main

import (
	"fmt"
	"html/template"
	"os"
)

func main() {
	var templateDemo = `
	{{define "layout"}} 
	<html>
		<h1>{{ .title }}</h1>
		{{template "menu" .}}
		{{template "content"}}
		{{template "footer" .footerdata}}
	</html>
	{{end}}

	{{define "menu"}}<div>menu</div>{{end}}
	{{define "content"}}<div>content{{.none}}</div>{{end}}
	{{define "footer"}}<div>{{.fff}}</div>{{end}}
	`
	// ■stdout!!
	// <html>
	// 	<h1>title-str</h1>
	// 	<div>menu</div>
	// 	<div>content</div>
	// 	<div><a href="#">test</a></div>
	// </html>

	var err error

	t := template.New("templateActionDemo")

	t, err = t.Parse(templateDemo)
	if err != nil {
		fmt.Println("parsing failed: %s", err)
	}

	err = t.ExecuteTemplate(os.Stdout, "layout", map[string]interface{}{
		"title": "title-str",
		"footerdata": map[string]interface{}{
			"fff": template.HTML(`<a href="#">test</a>`), // non escape
		},
	})
	if err != nil {
		fmt.Println("execution failed: %s", err)
	}
	fmt.Println()
}
```

### 説明
---

htmlを書き出してテストしなくて済むのでとても楽になる。

Ginとかフレームワークを使うときも使える知識だと思います。

また、出来るだけ分かりやすいように、サンプル要素を詰め込んでみました。（変数名が酷いとか言わない）

ちょっとしたテストしたいときにどうぞ。

### おまけ（配列とMapについて）
---

```golang
package main

import (
	"fmt"
	"html/template"
	"os"
)

func main() {
	var templateDemo = `
	{{define "layout"}} 
	<html>
	    {{ $z := .listmap }}
		{{range .maplist}}
			<div>{{.code}}</div>
			<div>{{index $z .code 0}}</div>
			{{range (index $z .code)}}
				<div>{{.}}</div>
			{{end}}
		{{end}}
	</html>
	{{end}}
	`
	// 配列 or Mapのアクセスは、【index(固定文字) target変数 添字(num or str)(変数可)】
	// <html>
	// 		<div>code1</div>
	// 		<div>code1-list-value1</div>
	// 			<div>code1-list-value1</div>
	// 			<div>code1-list-value2</div>
	//
	// 		<div>code2</div>
	// 		<div>code2-list-value1</div>
	// 			<div>code2-list-value1</div>
	// </html>
	var err error

	t := template.New("templateActionDemo")

	t, err = t.Parse(templateDemo)
	if err != nil {
		fmt.Println("parsing failed: %s", err)
	}

	// 配列にMapが入っているオブジェクト
	maplist := make([]map[string]interface{}, 2)
	maplist[0] = map[string]interface{}{"code": "code1"}
	maplist[1] = map[string]interface{}{"code": "code2"}

	// Mapに配列が入っているオブジェクト
	listmap := make(map[string][]interface{}, 1)
	listmap["code1"] = []interface{}{"code1-list-value1", "code1-list-value2"}
	listmap["code2"] = []interface{}{"code2-list-value1"}

	err = t.ExecuteTemplate(os.Stdout, "layout", map[string]interface{}{
		"maplist": maplist,
		"listmap": listmap,
	})
	if err != nil {
		fmt.Println("execution failed: %s", err)
	}
	fmt.Println()
```

これがやりたかったが、めっちゃ苦労したので載せておきます。

### 参考URL
---

- [Golang Template-2: Template composition and how to organize template files ?](https://hackernoon.com/golang-template-2-template-composition-and-how-to-organize-template-files-4cb40bcdf8f6)
- [golangでテンプレートエンジンを使う(その2)](https://twinbird-htn.hatenablog.com/entry/2017/09/13/233000)
- [golang : template の range で index を使う](http://increment.hatenablog.com/entry/2016/04/27/203810)
オレオレ React 用 notification ライブラリをつくった

# TL;DR

[use-custom-notification](https://github.com/moriyuu/use-custom-notification) をつくった。npm は[こちら](https://www.npmjs.com/package/use-custom-notification)。

```tsx
const { notify } = useCustomNotification();
```

して

```tsx
<button onClick={() => notify({ children: "HelloWorld" })}>
  Say HelloWorld
</button>
```

すると良い感じに notification が出る。
demo は[こちら](https://use-notification.netlify.com/)。
hammerspoonを使って特定のアプリのショートカットキーを上書きする

# 経緯

MacのSkypeアプリは、文字を消そうと思って"^H"を押すと「ブラウザが開いてヘルプページが表示される」というひどい仕様になっている。
このままだと文字の編集中のストレスが尋常ではないので、このアプリでだけ"^H"を"delete"に上書きしたくなった。

つまり、Macで特定のアプリで特定のキーバインドを上書きする方法が必要になったのだが、hammerspoonを使ってうまく対応することができた。

# 対処方法

hammerspoonのconfigを次のように編集すると期待通りの動きになる。

```lua:~/.hammerspoon/init.lua
local function press_delete()
  hs.eventtap.event.newKeyEvent({}, 'delete', true):post()
  hs.timer.usleep(1)
  hs.eventtap.event.newKeyEvent({}, 'delete', false):post()
end
ctrl_h_hkey = hs.hotkey.new({'ctrl'}, 'H', press_delete, nil, press_delete)

hs.window.filter.new('Skype')
  :subscribe(hs.window.filter.windowFocused, function() ctrl_h_hkey:enable() end)
  :subscribe(hs.window.filter.windowUnfocused, function() ctrl_h_hkey:disable() end)
```

`hs.window.filter`でwindowの切り替えを検知し、Skypeがフォーカスされた時にキーリマップを有効にし、フォーカスが外れた時に無効にするようにしている。
キーのリマップ方法については参考記事を参考にした。


# 参考記事

- https://qiita.com/naoya@github/items/81027083aeb70b309c14
- http://rochefort.hatenablog.com/entry/2017/02/25/070000
【PBCS】EPM Automate(EPM自動化)について(その１）

# EPM Automateとは


①コマンドプロンプトからPBCS環境を操作する機能

②「EPM自動化」をインストールすることで使用可能
　（EPMCloud > 設定およびアクション > ダウンロード＞EPM自動化）
　　**注）64bitOSでのみ使用可能**

③バッチと組み合わせることで、ビジネス・ルール実行等の自動化が可能

## 参考資料
oracleマニュアル「 **Oracle Enterprise Performance Management Cloud EPM 自動化 の操作** 」
P.54～「コマンド実行のサンプル・シナリオ」参照

# 主なコマンドの紹介

## 1. PBCSへのログイン

・コマンドプロンプトから、PBCS環境にログインを行います。
・パスワードファイルを事前に作成しておくことで
　任意のフォルダ内に、暗号化したパスワードを保管しておくことができます。
#### ①パスワードファイルの作成（事前に行う）
　・コマンドプロンプトにて以下のコマンドを実行して作成

```
epmautomate encrypt 【PBCSログイン時のパスワード】 myKey C:\【パスワードファイルの格納場所を指定】\password.epw
```

【コマンド例】

```
epmautomate encrypt P@ssw0rd myKey C:\Oracle\EPMAutomate_key\password.epw
```
#### ②ログイン

```
epmautomate login 【PBCSのログインID】 【パスワードファイルのパス】 【接続先URL】 【接続先ドメイン名】
```
【コマンド例】

```
epmautomate login TESTID C:\Oracle\EPMAutomate_key\password.epw https://planning-test-a123456.pbcs.us6.oraclecloud.com a123456
```

#### ③ログアウト

```
epmautomate logout
```

## 2. getsubstvarコマンド
・代替変数の値を取得するコマンド

#### アプリケーション・レベルで特定の 1 つの代替変数の値を取得: 

```
epmautomate getsubstvar ALL name=CurYear
```


#### Plan2キューブで特定の 1 つの代替変数の値を取得: 

```
epmautomate getsubstvar Plan2 name=CurYear
```



「[【PBCS】EPM Automate(EPM自動化)について(その２）](https://qiita.com/iwa_gino/items/3093c5a0b1fe50f7a598)」に続く
平成を令和に一発で置換するスクリプト( sed )

平成を令和に一発で置換するスクリプトを書きました。
平成を使っているところは全角数字も使ってそうなので、全角数字対応です。
平成60年まで対応です。

`YOUR_FILE_NAME` を置換したいファイル名に変えてください。
ご使用は自己責任で。

```bash:reiwa.sh
sed \
-e 's/平成31年5月/令和元年5月/g' \
-e 's/平成31年５月/令和元年５月/g' \
-e 's/平成３１年5月/令和元年5月/g' \
-e 's/平成３１年５月/令和元年５月/g' \
-e 's/平成31年6月/令和元年6月/g' \
-e 's/平成31年６月/令和元年６月/g' \
-e 's/平成３１年6月/令和元年6月/g' \
-e 's/平成３１年６月/令和元年６月/g' \
-e 's/平成31年7月/令和元年7月/g' \
-e 's/平成31年７月/令和元年７月/g' \
-e 's/平成３１年7月/令和元年7月/g' \
-e 's/平成３１年７月/令和元年７月/g' \
-e 's/平成31年8月/令和元年8月/g' \
-e 's/平成31年８月/令和元年８月/g' \
-e 's/平成３１年8月/令和元年8月/g' \
-e 's/平成３１年８月/令和元年８月/g' \
-e 's/平成31年9月/令和元年9月/g' \
-e 's/平成31年９月/令和元年９月/g' \
-e 's/平成３１年9月/令和元年9月/g' \
-e 's/平成３１年９月/令和元年９月/g' \
-e 's/平成31年10月/令和元年10月/g' \
-e 's/平成31年１０月/令和元年１０月/g' \
-e 's/平成３１年10月/令和元年10月/g' \
-e 's/平成３１年１０月/令和元年１０月/g' \
-e 's/平成31年11月/令和元年11月/g' \
-e 's/平成31年１１月/令和元年１１月/g' \
-e 's/平成３１年11月/令和元年11月/g' \
-e 's/平成３１年１１月/令和元年１１月/g' \
-e 's/平成31年12月/令和元年12月/g' \
-e 's/平成31年１２月/令和元年１２月/g' \
-e 's/平成３１年12月/令和元年12月/g' \
-e 's/平成３１年１２月/令和元年１２月/g' \
-e 's/平成32/令和2/g' \
-e 's/平成33/令和3/g' \
-e 's/平成34/令和4/g' \
-e 's/平成35/令和5/g' \
-e 's/平成36/令和6/g' \
-e 's/平成37/令和7/g' \
-e 's/平成38/令和8/g' \
-e 's/平成39/令和9/g' \
-e 's/平成40/令和10/g' \
-e 's/平成41/令和11/g' \
-e 's/平成42/令和12/g' \
-e 's/平成43/令和13/g' \
-e 's/平成44/令和14/g' \
-e 's/平成45/令和15/g' \
-e 's/平成46/令和16/g' \
-e 's/平成47/令和17/g' \
-e 's/平成48/令和18/g' \
-e 's/平成49/令和19/g' \
-e 's/平成50/令和20/g' \
-e 's/平成51/令和21/g' \
-e 's/平成52/令和22/g' \
-e 's/平成53/令和23/g' \
-e 's/平成54/令和24/g' \
-e 's/平成55/令和25/g' \
-e 's/平成56/令和26/g' \
-e 's/平成57/令和27/g' \
-e 's/平成58/令和28/g' \
-e 's/平成59/令和29/g' \
-e 's/平成60/令和30/g' \
-e 's/平成３２/令和２/g' \
-e 's/平成３３/令和３/g' \
-e 's/平成３４/令和４/g' \
-e 's/平成３５/令和５/g' \
-e 's/平成３６/令和６/g' \
-e 's/平成３７/令和７/g' \
-e 's/平成３８/令和８/g' \
-e 's/平成３９/令和９/g' \
-e 's/平成４０/令和１０/g' \
-e 's/平成４１/令和１１/g' \
-e 's/平成４２/令和１２/g' \
-e 's/平成４３/令和１３/g' \
-e 's/平成４４/令和１４/g' \
-e 's/平成４５/令和１５/g' \
-e 's/平成４６/令和１６/g' \
-e 's/平成４７/令和１７/g' \
-e 's/平成４８/令和１８/g' \
-e 's/平成４９/令和１９/g' \
-e 's/平成５０/令和２０/g' \
-e 's/平成５１/令和２１/g' \
-e 's/平成５２/令和２２/g' \
-e 's/平成５３/令和２３/g' \
-e 's/平成５４/令和２４/g' \
-e 's/平成５５/令和２５/g' \
-e 's/平成５６/令和２６/g' \
-e 's/平成５７/令和２７/g' \
-e 's/平成５８/令和２８/g' \
-e 's/平成５９/令和２９/g' \
-e 's/平成６０/令和３０/g' \
-i '' YOUR_FILE_NAME;
```
【PBCS】ASO（集約ストレージ・オプション）について調べてみた

# ASO（集約ストレージ・オプション）とは

①Aggregate Storage Option（集約ストレージ・オプション）の略称

②データ量はBSO（ブロックストレージ・オプション）の **10分の1** 以下

③疎密設定なし（代わりに、 **階層タイプ** の設定あり）
　→ MDX使う時は階層タイプを **「動的」** に設定！

④属性次元、UDA、共有メンバ使用可（ただし、共有メンバには制限あり）

⑤データのインポートは **レベル０メンバのみ** で可能（親メンバーには自動で積み上がり）

⑥ **MDX式**  使用可能（※MDX式については近日掲載）

⑦BSO→ASOのデータ連携は **「データマップ」** 機能より可能（※データ・マップについては近日掲載）

⑧ASO→BSOへのデータ連携はできないが、 **@XREF関数** でコピー可

⑨ASOのデータクリアは下記の２つがある

| No | 種類  | 説明 |
| ------- | ------------- | ----------------- |
| 1 　| 物理消去 　| データ・ブロックごと削除  |
| 2 　| 論理消去 　| 値のみの削除  |

論理削除の場合、物理削除に比べて削除速度は速いが、
ブロックの整理はされないのでデータベースサイズが増える可能性がある。
　
**＜実行方法＞**
1. 物理削除：EPM Cloud ＞ アプリケーション ＞ 概要 ＞ アクション ＞ キューブのクリア より実行
2. 論理削除：手動で値を消去してデータ送信


###しかし・・・


>2. 論理削除：手動で値を消去してデータ送信

これをどうにか自動で消去できないものだろうか？
⇒ BSOでは **CLEARDATA** または **CLEARBLOCK** 等の計算コマンドを使用して削除が可能
⇒しかしASOの場合、類似の計算コマンドやオブジェクトがない
そして試行錯誤しました・・・

# ビジネス・ルールを使ったASOでのデータクリア

・ビジネス・ルールにて実装可能
・ **【式】オブジェクト** を選択し、下記の式にて実行することで実現可能
   
   ※ 数値だけでなく文字列もクリアできる
   ※ 割り算を挟むことでパフォーマンスが良くなる

```
"Member001"= ("Member001"-"Member001")/"Member001"
```

注）実行後の値は「#MISSING」ではなく、数値なら **「0」** 文字列なら **「空白」** となる


# ASOの計算順

・「**解決順(Solve Order)**」により計算順が決まる（csv、SmartView、Webから設定できる）
・初期値は「0」数値が大きいほど計算順が後になる

注）SmartView・csvでは、一度1以上に設定すると0に戻せない→webから戻す必要あり
【PBCS】値の有無で処理を分岐させる方法（IF）

PBCSのメンバー式、ビジネスルールで分岐処理は「IF」を使って記述できます。
値が入っているかどうかで処理を分岐していきます。

#値の有無で処理を分岐させる
以下の前提で記述します。
・メンバー「予算（Budget）」「計算用予算（Calc_Budget）」「入力用予算（Input_Budget）」を使用します。
　３つのメンバーは全てScenario次元です。
　また、Version次元の「実行予算（WorkingBudget）」に属しています。
・「予算」は、「入力用」に値があれば「入力用」を、なければ「計算用」の値を引っ張ります。

```
/* 入力用に値があるときは入力用を、入力用に値がないときは計算用を格納 */
IF("Input_RB"<> #MISSING )
　　　"Budget"="WorkingBudget"->"Input_Budget";
ELSE
　　　"Budget"="WorkingBudget"->"Calc_Budget";
ENDIF
```

#補足
空白は#MISSINGで表現し、「空白でない場合」＝「値がある場合」という記述をしています。
「->」は次元をまたぐ際に使用します。「->」前後が同次元の場合は不要です。
ABC - 074- A&B&C

#AtCoder ABC 074 A&B&C
[AtCoder - 074](https://atcoder.jp/contests/abc074)

#A問題

```java
	private void solveA() {
		int numN = nextInt();
		int numA = nextInt();

		out.println(numN * numN - numA);
	}
```

#B問題

 - 求めたい値は黄色の部分

　　　　　　　　　　　　　　　　![さんぷる.jpg](https://qiita-image-store.s3.amazonaws.com/0/365572/29f79432-9f01-b49d-685a-ebaddbad4757.jpeg)


 - こんな感じの実装
 - 1点1点sumしていけばよい

```java
	private void solveB() {
		int numN = nextInt();
		int numK = nextInt();

		int[] wk = IntStream.range(0, numN).map(i -> nextInt()).toArray();

		int res = Arrays.stream(wk).reduce(0, (sum, num) -> {
			return sum += Math.min(num * 2, (numK - num) * 2);
		});

		out.println(res);

	}
```

#C問題

 - $A*100*a + B*100*b + C*c + D*d \leqq numF \quad (a,b,c,dは任意の整数)$ が成り立つ {$a,b,c,d$} である
 - $E < 100 * (C*c + D*d) / (A*100*a + B*100*b)$ が成り立つこと（溶解度）
 - $100 * (C*c + D*d) / (A*100*a + B*100*b+C*c + D*d)$ が最大となる {$a,b,c,d$} を求める

 - 結論：何も考えずにforで書くのが一番良かった。再帰とか下手に考えるとTLEになる。

```java
	private void solveC() {
		int numA = nextInt();
		int numB = nextInt();
		int numC = nextInt();
		int numD = nextInt();
		int numE = nextInt();
		int numF = nextInt();

		int[][] memoC = new int[101][2];

		double noudoMax = -1;
		int water = 0;
		int sugar = 0;
		/*
		 * Aのloop・水AがF以下（未満ではない）
		 */
		for (int i = 0; (numA * 100) * i <= numF; i++) {
			int wA = (numA * 100) * i;
			if (wA > numF) {
				break;
			}
			/*
			 * Bのloop・水Aと水Bを足してF以下
			 */
			for (int j = 0; wA + ((numB * 100) * j) <= numF; j++) {
				int wB = (numB * 100) * j;
//				if (wA + wB > numF) {
//					break;
//				}
				if (wA + wB == 0) {
					continue;
				}
				/*
				 * Cのloop・水Aと水Bと砂糖Cを足してF以下
				 */
				for (int k = 0; wA + wB + (numC * k) <= numF; k++) {
					int sC = numC * k;
					if (numE < 100 * k / (wA + wB)) {
						break;
					}
					/*
					 * Dのloop・水Aと水Bと砂糖Cと砂糖Dを足してF以下
					 */
					for (int l = 0; wA + wB + sC + (numD * l) <= numF; l++) {
						int sD = numD * l;
						/*
						 * 全て0は対象外
						 */
						if (wA + wB + sC + sD == 0) {
							continue;
						}
						//						if (wA + wB + sC + sD > numF) {
						//							break;
						//						}
						/*
						 * 砂糖がEよりも多く水に溶けている場合は対象外
						 * 除算をしていないのは丸め誤差を気にしているため
						 */
						if (numE * (wA + wB) < 100 * (sC + sD)) {
							break;
						}
						/*
						 * 濃度計算：1000000を乗算しているのは丸め誤差対策
						 */
						double noudo = 1000000 * (sC + sD) / (wA + wB + sC + sD);

						if (noudoMax < noudo) {
							noudoMax = noudo;
							water = wA + wB;
							sugar = sC + sD;
						}
					}
				}
			}
		}

		out.println(water + sugar + " " + sugar);

	}
```
アセットパイプラインとは

#はじめに
学習中にアセットパイプラインという言葉を聞いて何なのか気になったので調べたことをアウトプットしようと思います。

#アセットパイプラインとは何なのか
Web画面上にデザインを反映させるためにHTMLに紐付くCSSやJavaScript、Imageファイルを記述・作成することです。

#アセットパイプラインの流れ
**1.コンパイル**
CoffeeScript, SCSS, ERB, Slim等で記述されたコードをコンパイルして、ブラウザが認識できるJSやCSSファイルとして扱う。

**2.アセットの連結**
複数のJS, CSSファイルを１つのファイルに連結する事で読み込み時のリクエストを減らし、全て読み込むまでの時間を短縮する。

例えば、Railsで開発をしていてコントローラ毎にCSSファイルを作成したいという時にapplication.cssに@import"users";とか書きますよね?あれのことです。

**3.アセットの圧縮**
スペース、改行、コメントを削除してファイルを最小化し通信量を節約する。

**4.ダイジェストの付与**
コードの内容からハッシュ値を算出してファイル名の末尾に付与する。こうする事でコードが変更されればキャッシュの影響で内容が反映されないといった問題を防ぐ。


#ブラウザにアセットを読み込ませるには
RailsでCSSを読み込むには`stylesheet_link_tag
`,
JavaScriptを読み込むには`javascript_include_tag
`というヘルパーメソッドを使うですがこれは既にapplication.htmlで記述されている。

これらはアセットパイプラインによって連結された結果のファイルです。

#連結結果のファイルをどうやって生成するか
application.cssやapplication.jsといったマニフェストファイルに記述する。

**・CSSの場合**

```ruby:application.css
@import "users";
```
といった感じで書く。


**・JavaScriptの場合**

```javascript:application.js
//= require rails-ujs
//= require jquery
//= require bootstrap-sprockets
//= require activestorage
//= require turbolinks
//= require_tree .
```

JSのマニフェストファイルは「//=」で始まる行をアセットパイプラインに指示を伝える行。

require_treeは指定されたディレクトリ配下の全てのファイルを読み込む。
VMware 環境の情報を一元取得できる RVTools のススメ


# RVTools のダウンロード・インストール

https://www.robware.net/rvtools/ からダウンロード・インストールします。
（Windows 上での稼働となります）

![Kobito.CurTsm.png](https://qiita-image-store.s3.amazonaws.com/0/101361/5df45576-1d02-5517-7db0-065d38dd3f86.png "Kobito.CurTsm.png")

# vCenter に接続
vCenter に接続するだけで、すべての情報を一元的に取得できます。

![Kobito.wG3G9w.png](https://qiita-image-store.s3.amazonaws.com/0/101361/2decf6f1-92d2-9167-e9dd-6d4de0b57918.png "Kobito.wG3G9w.png")

以下のような画面で情報を常に更新しながら閲覧することもできます。

![Kobito.p0Vrt4.png](https://qiita-image-store.s3.amazonaws.com/0/101361/089eddf5-cfc4-ec38-ba6c-f870fecd131f.png "Kobito.p0Vrt4.png")

エクセルへのエクスポート機能もあるので、エクセルで管理したい場合は定期的にエクスポートしてバージョン管理することもできます。

![Kobito.uWYyVy.png](https://qiita-image-store.s3.amazonaws.com/0/101361/b721dc48-0b93-a9f9-4ed3-61c18cfbb562.png "Kobito.uWYyVy.png")

# まとめ
非常に細かい情報も含めて、一度に取得できるので、vCenter の画面から情報を集める手間が省けます！
（vCenter の画面遷移って、結構時間かかりますよね）
システム移行前に現行環境の状態を把握したり、システム構築後の新環境の状態を記録する用途など、一度使ってみてはいかがでしょうか？

#参考
- [Top 10 VMware Admin Tools - Virtual Blocks](https://blogs.vmware.com/virtualblocks/2019/03/16/top-10-vmware-admin-tools/)