OmniAICreator/Qiita-1.07M huggingface dataset:
【＠大阪】OutSystems 関西交流会＃１12/20グランフロント大阪の日程を追加しました。

【＠大阪】OutSystems 関西交流会＃１ OutSystemsのユーザー同士での情報交換、勉強を目的とした交流会です。

日程　12/20　18：50集合 ★参加者紹介 　　　　　　　　　　　　　　　　　　　　　　　　　　 15分

★OutSystems簡単プログラミングの紹介（参加者レベル次第で割愛） 15分 　（Excel展開での学習）

★開発者研修プログラム形式での学習紹介（参加者レベル次第で割愛） 15分 　（ブートキャンプ研修へのステップアップとして）

★【メインテーマ:自社内への技術伝承方法】 45分 　
　OutSystems考察前に抑えるJava,C#,AngularJS等との比較ポイント
 例java 　　　　　　例AngularJS　　　　　　　　　例C#　　　　　　OutSystems
 1. データ読み込み（基本3例）
 2.  Java　　　　　　　　　　　　　　　　　　　　　　　　　　　　　OutSystems "java.io.FileReader　　　　　　　　　　　　　　　　　　　　　　　OutSystemFile FileInputStream　　　　　　　　　　　　　　　　　　　　　　　　　OutSystemFile　　　　　　　　　 Files.readString　　　　　　　　　　　　 　　　　　　　　　　　　OutSystemFile 
 3.  Files.readAllLines" OutSystemFile
 4.   POI Excel展開OutSystemFile 
 5.   JDBC DBより抽出

基本処理（条件式・繰り返しなど） Outsystemsとしての定義を知り どの場所を変えると簡単に変えられるのかを確認 OutSystems
"if (条件) { If条件 // 条件TRUE時の処理 } else { // 条件FALSE時の処理 }" "int i = 0; ループ
// 繰り返し(while) while (i < 2) { System.out.println((i + 1) + ""回目の繰り返しです。""); i++; }" "// 繰り返し(for) for (int i = 0; i < 5; i++) { System.out.println(i); }" "// 配列を作成 配列 int n[] = new int[3];

// 配列に値をセット n[0] = 4; n[1] = 93; n[2] = 34;

// 一つずつ出力する for (int i = 0; i < 3; i++){ System.out.println(n[i]); }" "// 配列を作って ソート int[] foo = {10, 30, 5, 2, 11, 90};

// ソートさせる Arrays.sort(foo);"

データ出力（基本10例） Java OutSystems "java.io.FileWriter テキストファイル 
java.io.BufferedWriter 
java.io.PrintWriter 
java.io.IOException" 
"java.io.FileWriter CSV
 java.io.BufferedWriter
 java.io.PrintWriter
 java.io.IOException" 
POI Excel
 JasperReports PDF 
EspressReport レポーティング 
JDBC DB登録 
JFreeChart グラフ jsp WEBシステム上に表示
 "Stringクラス patterns（内部サブルーチン）
 Integerクラス" Flyway forge（外部サブルーチン）
★時間内で技術意見交換 終了20：55
自社内への技術伝承方法 管理コンソール (Lifetime)の紹介 自社独自のコンソールの組み方 外部連携の方法について紹介 バッチのスケジューリングをどうするか

★割り勘交流会　地下ビアホール 21：20～
Your requirements could not be resolved to an installable set of packages.のエラーが出たときの対処法

<h2>問題</h2>
`composer require maatwebsite/excel`
を実行したら、以下のエラーが出た。

`Your requirements could not be resolved to an installable set of packages.`

<h2>対処方法</h2>
--ignore-platform-reqsオプションに付けたら、実行できた。
phpバージョンのチェックを一時的に回避するオプションらしい。

`composer require maatwebsite/excel --ignore-platform-reqs`

<h2>参考ページ</h2>
https://stackoverflow.com/questions/29318709/how-can-i-resolve-your-requirements-could-not-be-resolved-to-an-installable-set
【JavaScript】Promise は Either Monad?

# イントロダクション

JavaScript における Promise は失敗か成功のどちらかを表し、どちらの場合も何らかの値を持つことができる。さらにメソッドチェーンによりパイプラインのようなものを作ることができ、失敗すると short-circuit する。この点において Promise は Either monad の async 版のような感じがする。ここでは JavaScript の Promise と Scala の Either の対応関係を示す。

Note: 筆者は関数型プログラミングに詳しくない。

# constructor

Promise の constructor である `Promise.resolve` と `Promise.reject` はそれぞれ Scala の `Right` と `Left` に対応している。

```js:JavaScript
const r = Promise.resolve(1)  // Resolve(1) と表記する
const l = Promise.reject(0)   // Reject(0)  と表記する
```

```scala:Scala
val r: Either[Int, Int] = Right(1)
val l: Either[Int, Int] = Left(0)
```

# `promise.then(f)`(1) = `either.map(f)`

Promise の `then` メソッドに**非 Promise を返す関数**を渡したときの動作は Either の `map` と同じである。

```js:JavaScript
r.then(x => x + 10)  // Resolve(11)
l.then(x => x + 10)  // Reject(0)
```

```scala:Scala
r.map(_ + 10)  // Right(11)
l.map(_ + 10)  // Left(0)
```

# `promise.then(f)`(2) = `either.flatMap(f)`

Promise の `then` メソッドに **Promise (一重)を返す関数**を渡したときの動作は Either の `flatMap` と同じである。

```js:JavaScript
r.then(x => Promise.resolve(3))  // Resolve(3)
r.then(x => Promise.reject(3))   // Reject(3)
l.then(x => Promise.resolve(3))  // Reject(0)
l.then(x => Promise.reject(3))   // Reject(0)
```

```scala:Scala
r.flatMap((x: Int) => Right[Int, Int](3))  // Right(3)
r.flatMap((x: Int) => Left[Int, Int](3))   // Left(3)
l.flatMap((x: Int) => Right[Int, Int](3))  // Left(0)
l.flatMap((x: Int) => Left[Int, Int](3))   // Left(0)
```

# `promise.catch(f)`(1) = `either.left.flatMap(f andThen Right)`

Promise の `catch` メソッドに**非 Promise を返す関数**を渡したときの動作は Either の `Left` に対してその関数を実行し、さらにその結果を `Right` で包んで `flatten` するのと同じである。

```js:JavaScript
r.catch(x => x + 10)  // Resolve(1)
l.catch(x => x + 10)  // Resolve(10)
```

```scala:Scala
r.left.flatMap(((x: Int) => x + 10) andThen Right[Int, Int])  // Right(1)
l.left.flatMap(((x: Int) => x + 10) andThen Right[Int, Int])  // Right(10)
```

# `promise.catch(f)`(2) = `either.left.flatMap(f)`

Promise の `catch` メソッドに **Promise (一重)を返す関数**を渡したときの動作は Either の `Left` に対して `flatMap` を実行するのと同じである。

```js:JavaScript
r.catch(x => Promise.resolve(x + 10))  // Resolve(1)
r.catch(x => Promise.reject(x + 10))   // Resolve(1)
l.catch(x => Promise.resolve(x + 10))  // Resolve(10)
l.catch(x => Promise.reject(x + 10))   // Reject(10)
```

```scala:Scala
r.left.flatMap(x => Right[Int, Int](x + 10))  // Right(1)
r.left.flatMap(x => Left[Int, Int](x + 10))   // Right(1)
l.left.flatMap(x => Right[Int, Int](x + 10))  // Right(10)
l.left.flatMap(x => Left[Int, Int](x + 10))   // Left(10)
```

# まとめ

以上の比較から、Promise の `then` メソッドは `map` と `flatMap` のオーバーロードのようなものであるということがわかる(ちなみに関数の返り値が何重もの Promise になっていたとしても、一気に flatten するという性質がある)。

`catch` メソッドについてはキレイに Scala コードで表現できなかったが、Left から Right に戻すという操作は関数型言語ではあまりしないのだろうか、と感じた。
$CIRCLE_WORKING_DIRECTORYのデフォルト値にハマった

## 手短に

環境変数に`~`を入れないでくれーーー

## 問題

CircleCIではjobに`working_directory`を設定しない場合、`~/project`つまり`/home/circleci/project`で作業が行われる。
例えば`checkout`するとこの直下に置かれるなど。（hogeリポジトリ直下に`src`ディレクトリがあると、checkoutすれば`/home/circleci/project/hoge/src`ではなく`/home/circleci/project/src`になる）

その値は`$CIRCLE_WORKING_DIRECTORY`によって[参照できる](https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables)が、デフォルト値は上のように`~/project`である。
しかしこれを使って`cd $CIRCLE_WORKING_DIRECTORY/src`などとcommandに書くと、`/bin/bash: line 0: cd: ~/project/src: No such file or directory`なる不可解なエラーに遭遇する。
`cd /home/circleci/project/src`と書き換えたり、sshして手で実行すれば普通に成功するのに、なぜcircleciは失敗するのか？

## 原因

通常`export $DIR=~/src`などとするとbashは`~`を解釈した状態で環境変数を設定する。（[tilde expansion](https://www.gnu.org/software/bash/manual/html_node/Tilde-Expansion.html)）
しかし`"`で囲むとそれが無効化されて、`export $DIR="~/src"`は`~`そのものが環境変数の値として入る。

```bash
$ export DIR1=~/src

$ echo $DIR1
/home/circleci/src

$ export DIR2="~/src"

$ echo $DIR2
~/src
```

そして`~`の展開は、それが環境変数に入っている場合は**行われない**ようなのだ。

```bash
$ cd $DIR1  # 成功する

$ cd $DIR2
bash: cd: ~/src: No such file or directory  # ~がそのまま！
```

`$CIRCLE_WORKING_DIRECTORY`の値も丁度このように`~`自体が入ってしまっている。それにより`~`が解釈されず、単に`~`という名前のディレクトリとして扱われてしまっている。

CircleCIには展開済みの値を入れてほしい気がするがどうなのだろう。

## 対策

1. `cd /home/circleci/project/src`（展開済みの値を使う）
1. `working_directory`を必ず設定する
1. `eval cd $CIRCLE_WORKING_DIRECTORY/src`

1は意味が失われるし2は忘れた場合に分かりにくそうだし3はevalが気乗りしないしで一長一短という感じがする。
いや忘れてもcdなどしようとすれば気づくはずだし、2がベターだろうか。
[UE4] UE4のVisual Studio Projectを開く時にCustomize Visual Studio Window Titleプラグインが便利

直接UE4とは関係ありませんが、**Customize Visual Studio Window Title**というVisual Studio用のアドオンを紹介します。

![2019-12-04_17h33_35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/5bd11d0b-bd49-893f-e39e-0b7776b9827b.png)
ダウンロードページは以下
https://marketplace.visualstudio.com/items?itemName=mayerwin.RenameVisualStudioWindowTitle

## プラグインについて
UE4のプロジェクトで開発を行う場合、バージョン違いなどで複数のVisual Studioを開くケースがあるかと思います。このプラグインを導入していると親ディレクトリまでをウィンドウタイトルに表示してくれるので、親のディレクトリ名にバージョン名などをつけていれば、どのウィンドウが何を開いているかソリューション名が同じ場合でも判断できるようになります。
すごく単純な機能ですが、個人的にVisual Studioを使うなら必須というぐらい便利です。
![2019-12-04_17h52_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/5ecdf7e4-cd40-7429-3918-734e55b84db8.png)


## インストール方法
ダウンロードページよりプラグインを保存し、VisualStudioが入っている環境であればダブルクリックでインストールが可能です。
https://marketplace.visualstudio.com/items?itemName=mayerwin.RenameVisualStudioWindowTitle
![2019-12-04_17h45_28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/68ebdbef-0f11-86f9-4e1b-b4e86df038f9.png)

その後Visual Studioを再起動するとデフォルト設定で親ディレクトリが表示されるようになります。
![2019-12-04_17h42_39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/ba208b56-d4dd-7dad-e214-52bed01d0954.png)
GitHub ActionsでAndroidビルドとユニットテストとDeployGateに公開する

## 

####1.以下のDeployGateのAPIキーとユーザはGitHubのリポジトリページにあるSettings→Secretsから追加してください
DEPLOYGATE_API_KEY　・・・DeployGateのプロフィールページに記載されてます
DEPLOYGATE_USER　・・・DeployGateのユーザ名

###### 1.[Settings]をクリック
<img width="1079" alt="スクリーンショット 2019-12-05 10.12.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351880/2f4e4670-30ec-f389-8d8e-d95a388c933d.png">

###### 2.[Secrets]をクリック
<img width="266" alt="スクリーンショット 2019-12-05 10.16.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351880/a910008a-7bc2-0318-3f2c-4f4eca8c8662.png">

###### 3.以下の要領で[DEPLOYGATE_API_KEY]と[DEPLOYGATE_USER]を追加
<img width="776" alt="スクリーンショット 2019-12-05 10.17.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351880/cdc39e2a-fc47-00d0-cc2b-97eb7d8586a4.png">

###### 4.最終的にこのような感じ
<img width="766" alt="スクリーンショット 2019-12-05 10.18.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351880/6c1a28dd-8ec1-eb62-6ec1-e1d2af7cef72.png">

####2.GitHubのリポジトリページにあるActionsからymlファイルを追加します。

###### 1.[Actions]をクリック
<img width="1032" alt="スクリーンショット 2019-12-05 10.25.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351880/f7f3fc08-0faf-3efb-70ef-26429892a1b7.png">

###### 2.[Set up a workflow yourself]をクリック
<img width="1059" alt="スクリーンショット 2019-12-05 10.25.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351880/6afa4199-f959-933a-b4ae-33d3df94c406.png">

###### 3.プロジェクトルートに/.github/workflows/main.ymlがができるので以下の内容をコピペ

ymlファイルのファイル名はなんでも良い

```ruby:main.yml
name: Android CI

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v1
    - name: set up JDK 1.8
      uses: actions/setup-java@v1
      with:
        java-version: 1.8
    # The following generates a debug APK
    - name: Build with Gradle
      run: ./gradlew assembleDebug
    # The following is running unit tests
    - name: Unit Test
      run: ./gradlew test
    # The following is uploading debug apk to the deploygate
    - name: Distribute App
      run: |
       curl \
        -H "Authorization: token ${{secrets.DEPLOYGATE_API_KEY}}" \
        -F "file=@app/build/outputs/apk/debug/app-debug.apk" \
        -F "message=Any message" \
        "https://deploygate.com/api/users/${{secrets.DEPLOYGATE_USER}}/apps"
```

https://github.com/tokuyama-san/MyApplication/blob/master/.github/workflows/blank.yml

###### 4.[Start commit]ボタンをクリックしてymlファイルをリポジトリに登録します

###### 5.あとはリポジトリにプッシュするたびに、ビルド、ユニットテスト、DeployGateへdebugAPKアップロードまで行います。
関係データの表現まとめ

この記事は[古川研究室 Advent_calendar](https://qiita.com/advent-calendar/2019/flab) 4日目の記事です。
本記事は古川研究室の学生が学習の一環として書いたものです。内容が曖昧であったり表現が多少異なったりする場合があります。

## はじめに
同アドベントカレンダー2日目の記事として、[関係データの定義まとめ](https://qiita.com/forusufia/items/01a01cebc2228334ca84)を書きました。そちらでは図や表で関係データの定義や種類のお話をしていました。今回は関係データの「表現」についての記事になります。

前回同様に、書籍 MLPシリーズより「関係データ学習」の内容を読んで自分でまとめてみるというものです。前記事で触れなかったChapter 1の残りの部分に該当します。

## 関係データの表現

機械学習の分野で関係データを扱う際の表現方法は大きくわけて2つあります。

無向関係かつ2項関係の場合を例に挙げます。

### 1.グラフ表現

グラフは頂点(ノード)と、頂点の組で表す辺(エッジ)で定義される

グラフ$G = ｛V, E｝$
　頂点$V = ｛v_1, v_2, ... ,v_n ｝$
　　辺$E = ｛e_1, e_2, ... ,e_m｝$

次の図では円がノード、関係があるところをエッジで表しています。

![イラスト.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430554/e6935954-b5c2-b3c5-c32f-2d729c88bb1a.jpeg)

### 2.行列(多次元配列)表現

2項関係データであれば、行列で表すことができる

![イラスト2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430554/81ceb69e-1cbf-2fbf-78a0-6f352a8cded6.jpeg)

以上、2つの表現方法を示しました。

- 人の目で見るためのグラフ表現・・・解析結果の表示
- 解析の実装時に取り扱いが楽な行列表現・・・入力データなど

のように使い分けが考えられそうです。参考書籍では表現が容易(図を描きやすい？)ため行列表現を用いているようです。プログラムとして書く際には行列のほうが直接表現しやすいので、普段はそちらの表現方法を使うことになると思います。

### 観測データと未観測データ

関係データを数値で表現する場合に注意することがあります。

グラフ表現の例では無向関係を表しました。この場合は関係がある・無いをそのままノードがある・無いで表現できました。これを行列表現する際には関係がある場合を「1」、無い場合を「0」と置いて表現することができました。このとき関係が無いことを「ノードを書かない」、「0」で表せるのは、関係が無いことが「観測されている」場合のみです。あるオブジェクト同士の関係が、あるか無いかわからない「未観測」であるときは、その部分は値を定義できません。
未観測の部分を0にしてしまうことはできません。

個人的に刺さる注意点でした。

## おわりに
2回にわかれてしまいましたが、以上で関係データについてのおおざっぱなまとめになります。関係データを作るとき、扱うとき、それはどういうデータなのか考えるようになるきっかけとなれば幸いです。

## 参考文献
[1] MLP 機械学習プロフェッショナルシリーズ 関係データ学習 著：石黒勝彦,林浩平 講談社 2016/12/6
[2] 関係データ解析とInfinite Relational Model 
    https://qiita.com/takuti/items/8faf0e686cfbe68c2dfa
Amazon Lightsailで構築したRedmineに別で立てたDBを使わせる

Amazon Lightsailで構築したRedmineはデフォルトではインスタンス内に入っているMySQLを使用しています。
これを、Amazon Lightsailで別に構築したMySQLを使わせてみようと言うのが今回の趣旨です。

大まかな流れとしては以下のようになります。
1. Redmine側DBのダンプを取得
2. 新しく立てたDBにスキーマを作成してリストア
3. Redmineの設定ファイルを編集し、新しく立てたDBを使うようにする

### 1. Redmine側DBのダンプを取得
Lightsailで立てたインスタンスにsshで入ったらまず、mysqlのrootユーザーのパスワードを確認します。
rootのパスワードは`~/bitnami_application_password`に書かれています。
また、このパスワードはRedmineの管理者ユーザーのパスワードにもなっています。 (ログインIDはuser)

パスワードを確認できたら以下のコマンドを実行します。
bitnami_redmine_dump.sqlという名前でダンプファイルが作成されます。
`mysqldump -u root -p bitnami_redmine > bitnami_redmine_dump.sql`

このタイミングで何か適当なプロジェクトでも作っておくとRedmineのDBを切り替えた時に確認しやすいかもしれません。
切り替えが上手くいけばこのプロジェクトは表示されなくなるはずですから。

前
![pj.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542916/7e5aa81b-b78b-71ff-56e2-9e265421f34c.png)
後 (新しいDBには"前"の時点でのダンプを使うので、切り替えが上手くいけばPJ_2は表示されなくなるはず)
![pj2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542916/74be50d2-a9e4-48b1-1fd5-936dd49a4142.png)

### 2. 新しく立てたDBにスキーマを作成してリストア
新しく立てた方のmysqlにログイン
`mysql -u dbmasteruser -p -h （エンドポイント）`
(ユーザー名、パスワード、ホスト（エンドポイント）はコンソールから確認できます。)
![db.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542916/45c0ded6-6878-bc9a-832c-865e16e6d8d3.png)

ダンプのリストア先となるスキーマを作る
`create database bitnami_redmine`

mysqlからログアウト
`exit`

作ったスキーマにダンプをリストア
`mysql -u dbmasteruser -p -h （エンドポイント） bitnami_redmine < bitnami_redmine_dump.sql`

テーブルを確認するとPJ_1のレコードを確認できる。

```
mysql> select id, name from bitnami_redmine.projects;
+----+------+
| id | name |
+----+------+
|  1 | PJ_1 |
+----+------+
1 row in set (0.00 sec)
```

### 3. Redmineの設定ファイルを編集し、新しく立てたDBを使うようにする
このファイルは`/home/bitnami/apps/redmine/htdocs/config/database.yml`にあります。

```yaml
production:
  adapter: mysql2
  database: bitnami_redmine
  host: localhost
  username: bitnami
  password: xxxxxxxxxx
  encoding: utf8
  socket: /opt/bitnami/mysql/tmp/mysql.sock
```

production の database, host, username, password をそれぞれ新しく立てたDBに合わせて書き換えます。
書き換え終わったら保存してRedmineのインスタンスを再起動しましょう。

プロジェクト一覧を見てみるとPJ_2が表示されていないので、これでうまく切り替えできたことが分かりました。
![pj3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542916/4c8e071f-8ee1-bc39-700e-637ffebe5121.png)
sakuraエディタでよく使う正規表現まとめ

##大声では言えないけどやっぱりsakuraエディタのことが好きなんです！
巷では色々なエディタが流行り私も色々と使ってみたことがあります。
以下にあげられるエディタを使われているという方は多いと思います。

- Eclipse
- InteliJ
- Atom
- VS Code
- Sublime Text

しかしながら、起動の速さと動作の軽快さと種類の豊富さからいまだにやっぱり
***_sakuraエディタ_***を使うことが多いのではないでしょうか？

特に私が多く使う機能は***正規表現の置換機能***です。

以下に便利な正規表現を紹介します。

***CTRL+R***のご用意をお願いします！！！

###【よく使う正規表現①】 改行をすべてスペースに置換
以下の設定でできます。(置換後のテキストには空白文字を入れています)
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280363/e5e0f2a1-c35b-1136-90ce-31ce01c499a8.png)

###【よく使う正規表現②】正規表現内の文字を使用
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280363/fe689f8f-c219-a38e-3a37-0f6108fd9c9a.png)

扱いたい部分を括弧でくくる、$1の場合は括弧で括った最初という意味

###【よく使う正規表現③】URLからファイル名だけを抽出する

以下の正規表現でいけます

``` bash
#$1に置換する
.*\/([^/\\&\?]+\.\w{3,4}(?=([\?&].*$|$)))
```
![only_filename.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280363/5c0f8274-d8f8-f07a-e42d-543f798ae0b9.png)

###【よく使う正規表現④】パスからファイル名だけを抽出する

``` bash
#$2に置換する
(.*[\/|\\])([\w-]+\.\w+)
```
![onlyfile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280363/44842775-646c-05c7-cbb2-a16cf10e3cbb.png)



##更新履歴
- 2019/12/5 作成
- 2019/12/6 ファイル名だけ抽出できる2例を追加
[UE4]オブジェクトポジションの罠

マテリアルでそれぞれのオブジェクトの位置を取りたーい！というとき
アクタポジションノードやオブジェクトポジションノードを使うことがありますよね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463796/ba60beef-9670-2386-d10c-c5926dca4dc5.png)
https://docs.unrealengine.com/ja/Engine/Rendering/Materials/ExpressionReference/Coordinates/index.html

このうちアクタポジションは**ピボット位置**を。
オブジェクトポジションは**バウンディングボックスの中心位置**を返します。

こちらがアクターポジションを中心にぶん回した場合。
![ap.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463796/ecd83ca6-dae2-a423-0d39-7f5123796136.gif)

こちらがオブジェクトポジションを中心にぶん回した場合。
![op.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463796/c35d997a-285e-5c0c-8544-05b9362a955a.gif)

上記のようにこれら2つのノードは、名前が似ている割に結構挙動が違うので気をつける必要があるのですが、
特にオブジェクトポジションの**バウンディングボックスの中心位置**というところ、
これがたまに地雷となってしまうことがあります。



例えば、全く同じメッシュであっても、
バウンディングボックスを調整したりしていると、オブジェクトポジションの返す位置は異なります。
![op2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463796/79cc1354-deed-4377-98f9-684eb4985bda.gif)




また、全く同じメッシュであっても、
スケルタルメッシュとスタティックメッシュでは作られるバウンディングボックスが違ってたりもしますので、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463796/0a458456-638c-4c6e-25a1-bb93511bcbdf.png)
そうすると、スケルタルメッシュをスタティックメッシュとしてインポートし直すと挙動が変わってしまったりします。
![sksm.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463796/e64d35f8-b556-ff45-2d96-b10c7a9e9267.gif)

ちなみになんで違うかというと、実はスケルタルメッシュはバウンディングボックス作成時に足元から上の方に拡張するようになってたりするんですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463796/8a30c12b-bdea-0b0f-4131-9b0e00de2ea0.png)


そしてさらには、オブジェクトポジションは**インスタンシングされてるかどうか**でも挙動が変わったりします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463796/3eb46f44-9d9b-21fa-69b2-1361fc969802.png)
オブジェクトポジションは有り難いことに、インスタンスに対して使用するとインスタンスそれぞれ個別の位置を返してくれるのですが、
上記コードを見て頂くとわかるように
インスタンスの時は**バウンディングボックスの中心位置**ではなく、それぞれの**ローカル位置**を返します。

つまり、
スタティックメッシュアクタで並べている場合。
![smm.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463796/4a50345a-5f64-dede-6957-dc0fc90e93ef.gif)

インスタンスで並べている場合。
![ins.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463796/cf8c7d47-3f79-539d-33f5-876ff360f45f.gif)
このように挙動が異なってしまいます。
最適化の為にインスタンシングしたら挙動が変わってしまった、ということが起こり得るということですね。

とても便利なオブジェクトポジションノードですが、
上記のようなちょっとした罠がありますので、皆様ご使用の際はご注意頂けましたら幸いです。
（もちろん僕は見事にはまった経験があります。）
[HTML] GET メソッドの form で URL のクエリパラメータが消えてしまう

# 問題

GET メソッドの form 要素の action 属性で指定した URL のクエリパラメータが消えてしまう

```html
<!-- 送信時に URL のクエリパラメータから part=bass が消える。 -->
<form action="/members?part=bass" method="GET">
  <input type="text" name="members[name]">
  <input type="submit"> 
</form>
```

# 原因

仕様らしい。[W3C 仕様書](https://www.w3.org/TR/2011/WD-html5-20110525/association-of-controls-and-forms.html#submit-mutate-action) には次のように書かれている。

> Let query be the result of encoding the form data set using the application/x-www-form-urlencoded encoding algorithm, interpreted as a US-ASCII string.
> Let destination be a new URL that is equal to the action except that its \<query\> component is replaced by query (adding a U+003F QUESTION MARK character (?) if appropriate).

意訳: 送信先を action 属性の値と同じ URL にする。ただし、URL の query 部分は form データをエンコードした結果で置き換えられる。

仕様がないね。

# 対策

input[type="hidden"] を使ってフォームデータにパラメータを加える。

```html
<!-- 送信時にクエリパラメータから part=bass が消える。 -->
<form action="/members" method="GET">
  <input type="hidden" name="part" value="bass">
  <input type="text" name="members[name]">
  <input type="submit"> 
</form>
```

# 参考

* [[MDN] フォームデータの送信](https://developer.mozilla.org/ja/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data)
* [[Stack Overflow] ruby on rails - slim dynamic conditional class](https://stackoverflow.com/questions/15242170/slim-dynamic-conditional-class)
Railsチュートリアル 1.5.2 Herokuへのデプロイで発生したエラーへの対処

## はじめに
Railsチュートリアル1.5.1~1.5.3をそのまま実行していく中で発生したエラーです。
エラー時の状況

1. herokuへのデプロイを実施
2. $ git push heroku master には成功しているようだがネット上で表示されない
3. rails server 上では問題なく表示される
4. もう一度push herokuをすると「Everything up-to-date」と表示される

上記以外の状況の場合は最後に追記してあるのでそちらも見てみてください。

##内容
- 情報
- 実行内容と発生したエラー
- 解決方法
- その他の問題の場合

##情報
### PC
- MacBook Pro(15-inch,2019)
- プロセッサ 2.6GHz 6コアIntel Corei7
- メモリ 16GB 2400MHz DDR4
- グラフィックス Intel UHD Graphics 630 1536 MB

###開発環境
- AWS　Cloud9
- Ruby 2.6.3
- Ruby on Rails 5.1.7
- Git 2.14.5
- heroku/7.35.0 linux-x64 node-v12.13.0
- Bitbucket

## 実行内容と発生したエラー
Railsチュートリアル1.5.1の手順に従いHerokuのセットアップ
1.5.2で下記を実行

```ruby:qiita.rb
$ git push heroku master
```
問題なく終了したように見えたので帰ってきたURL(.gitと.comがある)を開く。

```
https://damp-fortress-5769.herokuapp.com
https://git.heroku.com/damp-fortress-5769.git
```
.gitは「Method Not Allowed」と表示されるだけなので注意。
.comの方を開くと「Application　error」ログの詳細を確認しろとの表示。
だが、初心者なためログを見ても何が何だか分からず、とりあえずpush後の情報を確認。

<img width="700" alt="WARNING.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545044/eb759966-feda-4e78-1195-3a7c87dc1e1a.png">
一度目の物が消えてしまったのでこれと少し内容は違うがほぼ同内容が返ってきていた。
いくつかWARNIGが出ているがあまり重要ではないと判断。（ちなみに一度目は2つ目のWARNIGがGemにrailsのバージョンを記載しろというものだったのでその通りにしたが結果は変わらなかった)

###解決方法
いくつか試したが多くのエラーパターンがあるように思われたので端的に解決に至ったもののみを記しておく。
[この質問](http://qiita.com)の通りにしたら解決した。
手順としては、

・ /hello_app/config/database.yml　を開く
・ 内容を*1に書き換え
・ 変更を保存(⌘ + S)
・ $ git add .
・ $ git commit -m "change_database.yml"
・ $ git push
・ $ git push heroku master

これで無事デプロイに成功。
*1
>default: &default
  # adapter: sqlite3 を削除
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

>development:
  <<: *default
  adapter: sqlite3 # 追加
  database: db/development.sqlite3

>production:
  <<: *default
  adapter: postgresql
  database: db/production.pg

###その他の問題の場合
初心者だからこそのエラーパターンがいくつかあったので追記しておく。

- SSH認証に失敗している
メッセージが表示されているはずなのでもう一度手順通りに公開鍵を追加する。

- .gitと.comのうち、.gitのURLを開いている
.comのURLがデプロイされた物なのでそちらを開く
あまりないと思うが質問サイトの投稿者の中にいた。

- 変更内容を保存せずにaddやcommitをしている
ほぼ無い状況だろうが自分が何回もやらかしているので一応
Rのggplot2を使って棒グラフを作成する

 

今回はRのパッケージggplot2を使って色々なグラフを作成してみたいと思います。

#ggplot2とは
Rには様々なデータを可視化する方法がありますが、その中でもggplot2は比較的簡単に綺麗なグラフを作成することができます。

ggplot2は入力すべき情報とオプションが統一されているため、あるグラフで使い方を覚えてしまえば、他の種類のグラフを作成する際にも同じ使い方でグラフを作成することができます。

また、他のパッケージと比べて関数の種類ごとに使い方やオプションを覚える必要がないので、学習効率が良いと思います。

## ggplot2のインストール
それでは早速ggplot2をインストールしてみましょう。

Rのコンソールから以下のようにコマンドを実行すればOKです。

同時にサンプルデータを取得するために「gcookbook」もインストールしておきましょう。

```r
install.packages("ggplot2")
install.packages("gcookbook")
library(ggplot2)
library(gcookbook)
```

## 棒グラフを作成してみる
それではまずは棒グラフから作成してみましょう。

 今回使うデータを見てみましょう。今回はgcookbookの中にあるpg_meanというデータを使います。

棒グラフを作成するときはgeom_bar()をたしてやることでできます。

もし折れ線グラフを作成したい場合はgeom_lineと記述することで作成することができます。

```
> pg_mean
 group weight
1 ctrl 5.032
2 trt1 4.661
3 trt2 5.526
```

## グラフのプロット

```r
ggplot(pg_mean, aes(x = group, y = weight)) + geom_bar(stat = "identity")
```

![graph1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539965/c788de49-5ea3-1a20-a555-8f0c4e599dd2.png)

### 色をつける 
先ほどの棒グラフに色をつけてみましょう。geom_barの中にfillとcolourを指定するだけで色をつけることができます。


```r
ggplot(pg_mean, aes(x = group, y = weight)) +
     geom_bar(stat = "identity", fill = "lightblue", colour = "black")
```
![graph2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539965/01e6525c-9b09-f76a-3c82-d610fd8dee48.png)


### グループ化する
 
次は棒グラフをグループ化してみましょう。グループ化する方法はfillに変数を与えて、geom_bar("position="dodge")を用います。

次に使うデータセットは２つのカテゴリがあります。カテゴリごとにグループ化し、棒グラフを作成してみましょう。


```r
> cabbage_exp
 Cultivar Date Weight sd n se
1 c39 d16 3.18 0.9566144 10 0.30250803
2 c39 d20 2.80 0.2788867 10 0.08819171
3 c39 d21 2.74 0.9834181 10 0.31098410
4 c52 d16 2.26 0.4452215 10 0.14079141
5 c52 d20 3.11 0.7908505 10 0.25008887
6 c52 d21 1.47 0.2110819 10 0.06674995
> ggplot(cabbage_exp, aes(x = Date, y = Weight, fill = Cultivar)) +
    geom_bar(stat = "identity", position = "dodge")
```
![graph3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539965/101458ac-4d51-5c43-aa78-4920d3ec16b4.png)

 
## ドットプロット
 

最後はドットプロットを作成してみたいと思います。

ドットプロットの場合は一番簡単な方法として、geom_point()と記述することで作成することができます。


```r
tophit <- tophitters2001[1:25,]
tophit
ggplot(tophit, aes(x = avg, y = name)) + geom_point()
```
![graph4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539965/6ccca7d0-6870-ef6d-5290-af42243196e0.png)


これでも良いのですがせっかくなのでドットのサイズや体裁を整えてみましょう。

```r
ggplot(tophit, aes(x = avg, y = reorder(name, avg))) +
    geom_point(size = 3) + #ドットのサイズを変更
    theme_bw() + #背景色をなくす
    theme(axis.text.x = element_text(angle = 60, hjust = 1),
                panel.grid.major.y = element_blank(),
                panel.grid.minor.y = element_blank(),
                panel.grid.major.x = element_line(colour = "grey60", linetype = "dashed"))
```
![graph5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539965/86902c45-573e-9e16-c506-239ea9656750.png)


avgでソートしたのでさっきのグラフよりは見やすくなりました！


このようにggplot2は綺麗なグラフが簡単に書けるのでオススメです。最初はわからないことばかりでつまずくかもしれませんが、Rを使っていくのであればggplotを使いこなせるようになった方がRだけで分析結果のアウトプットもできるため良いと思います。



次回は折れ線グラフなどを紹介したいと思います。
ScalaのWebフレームワークPlay用の認証ライブラリSilhouetteの使い方

会社でplayframework認証ライブラリのSilhouetteを使ったので雑にまとめ。
実装は公式のExample見ればだいたい行ける。
https://www.silhouette.rocks/docs/examples

## Silhouetteでできること
- パスワード認証
- OAuth認証
    - https://www.silhouette.rocks/docs/providers#section-social-providers
- Cookie/bearer/basic

## Identity
- 認証対象となる存在
    - 例えばユーザなど
- 認証用のユニークな識別子を保つ必要がある
    - User name, emailなど
- 実装上は`Identity`というマーカートレイトをモデルに継承させる
- その上でモデルに`LoginInfo`型のプロパティをもたせる
    - わざわざモデルに持たせないでも、他に方法があるらしいがこれが一番楽っぽい

## Identity Service
- Identityの永続化を担保する
    - 言ってしまえばidentity用のrepositoryみたいなもの
- IdentityServiceトレイトを継承し、retrieveメソッドをオーバーライドする

## Authenticator
- 認証方式を設定・決定するオブジェクト
- Cookieやbearerなど色々ある
    - https://www.silhouette.rocks/docs/authenticator#section-list-of-authenticators
    - 各認証方式のpros/consがまとめられてていい
- 具体的な設定
    - https://www.silhouette.rocks/docs/config-authenticators

## Authenticator Service
- Authenticatorと協調して動作し、tokenの作成、リクエストへの埋め込みなどをおこなう
- 実装はもともと用意されているので自分で実装する必要はない
- ただ永続化のためのキャッシュ層などの設定は行う必要がある
    - AuthenticatorRepositoryを与える

### BearerTokenAuthenticatorService
- リクエストからbearer tokenを抜き出してそれをAuthenticatorRepositoryから探し、ログインしているかどうかを判断してくれる
- Secureなルートへのフックされる認証を行う
- 成功した場合はlogin infoを返す

## AuthInfo
- パスワードやOAuthで使用するtokenなどの認証情報を表す
- パスワードの場合はハッシュ化されたパスワード、ハッシュ方法などが記録される

## Provider
- リクエストからの認証情報の読み取り、及び認証操作を担保する

### CredentialsProvider
- パスワードベースの認証を行う
- リクエストからの認証の抜き出しは行わずに、Credentialsを用意してauthenticateメソッドに渡すとAuthInfoRepositoryをベースにパスワード認証をこなってくれる

## AuthInfoRepository
- AuthInfoを永続化する

## Environment
- Silhouetteが用いる認証設定をまとめたオブジェクト
- IdnetityService、AuthenticatorService、Seq(RequestProvider)、EventBusを与えて初期化する
    - RequestProviderはなくてもいい
- EnvironmentがアプリケーションにDIされて一連の認証が暗黙的に行われる

## Secureなルートへのアクセスの認証手順
- Authenticator serviceがヘッダーなどからtokenを取得する
- Tokenがキャッシュに存在する場合は認証を成功させる
- AuthenticatorSerivceでの認証が失敗した場合に、自前で定義したRequest Providerがある場合はそちらでの認証操作を定義する

## Sign Upの流れ
- identifierからlogin infoを作成する
- Login infoから既にあるかもしれないidentityを取得する
    - 存在した場合は既に存在するユーザなのでsign upを失敗させる
    - 存在しない場合は登録作業を行う
	- パスワードをハッシュ化する
	- identifierがかぶっていない場合は登録を行う
	- Login infoと紐付けてハッシュ化したパスワードを保存する
	- Login infoからtokenを作成する

## Sign inの流れ
- identifierとpasswordの組み合わせをCredentialsProviderが認証する
    - credentialsからlogin infoを作成
    - Login infoに紐付いたパスワードを取得
    - 取得したパスワードをアンハッシュし生のパスワードと比較
    - 認証が成功したらlogin infoを返す
- Login infoをもとにIdentity ServiceからIdentityをretrieve
    - Identityが存在すればlogin infoからtokenを作成し、キャッシュに保存
    - Identityが存在しない場合は認証が失敗する
【コード０行】Firebase CrashlyticsからのクラッシュをSlackに通知する

この記事は [ZOZOテクノロジーズ #1 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech) 5日目の記事になります。

ZOZOTOWNのAndroidを担当しております、 [shogo.yamada](https://twitter.com/yshogo87)と申します。

アプリがクラッシュしたらSlackに通知したいということはよくあると思いますが、Firebase Crashlyticsだとコードを１行も書かずに実現できます。今日はその方法について紹介します。


## FirebaseのブロジェクトからSlackに繋げる

まずはFirebaseのコンソールを開き、
プロジェクト→プロジェクト設定→統合 の順に選択していきます。

![スクリーンショット 2019-12-04 17.08.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139360/fbdcbbe7-0545-7309-8e9e-f3801df02024.png)


ここにSlackの項目があるので、Slackの中の「インストール」を選択しましょう。


![スクリーンショット 2019-12-04 17.11.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139360/ab093c08-e462-019b-87cd-5e66c54eb6ac.png)


そしたら `Incomming Webhook URL` が求められるので、Slack側から取得します。


## Slack側の設定

Slackアプリから「Customize App」からWebを開きます。

![スクリーンショット 2019-12-04 17.19.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139360/45ffcd02-e069-a139-1093-80ae6602830f.png)

そしたら、下記の手順で進みます。

App管理→Appディレクトリを検索…」の検索窓で検索して「Incoming WebHook」を選択します。


![スクリーンショット 2019-12-04 17.22.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139360/8a1f5f4c-3e7b-07b6-3c37-7bdcf6e7a67a.png)


そしたら 「Add To Slack」を選択しましょう。

そしたらチャンネルを選択して Webhookを作成します。

![スクリーンショット 2019-12-04 17.25.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139360/1c126954-c57f-0279-372f-4e459f2465ce.png)


Webhook URLをコピーしましょう。


## FirebaseにURLをコピペする

そしたら、コピペして確認して送信を押しましょう。

![スクリーンショット 2019-12-04 17.27.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139360/59b2388b-3d37-7c64-93f0-fe5057691a66.png)


これで完了です。

テストのため、Firebaseのページから「テストメッセージを送信」ボタンを押してみましょう。

ちゃんと通知されれば完了です。

![スクリーンショット 2019-12-04 17.29.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139360/a803419b-2079-45a8-0a49-de143a545c65.png)


## あとはクラッシュが起きるのを待つ


そしたらクラッシュが起きるのを待ってみましょう。
通知されるはずです。

![スクリーンショット 2019-12-04 17.31.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139360/10b3641e-a73f-d314-7fd9-9a031207a40d.png)
railsで超シンプルなコメント機能を作った時の手順

rails g controller comment
rails g model Comment post_id:integer comment:string
rails db:migrate


ルート
  post "comments/create/:id" => "comment#create" # :idはcommentテーブルのpost_id参照に使う

コントローラ
  def create
        @comment = Comment.new(post_id: params[:id],
                               comment: params[:comment])
        @comment.save
        redirect_to "/"
  end

ビュー
       formforを取り付けたいビューに張り付け
        @comment = Comment.new()をformforに連動するアクションに張り付け



posts/showの下部にコメント入力と送信、表示を取り付ける。
最初はコメント入力と送信


formtagに変更

    <%= form_tag("/comments/create/#{@a.id}") do %>

      <textarea name="comment"></textarea>
      <input type="submit" value="コメント投稿" %>

    <% end %></br>
VSCodeの設定メモ

##前提
・MacOS
・Node.jsがインストール済み

##VSCodeの入手先
以下のサイトからダウンロード。

https://code.visualstudio.com/


##日本語化
左の一番下のアイコン または ⇧⌘X で拡張機能を表示。
<img width="454" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427357/b0196c79-97f1-5001-0acf-22c44ed7de40.png">


検索フォームに「Japanese」と入力。
先頭に表示される「Japanese Language Pack〜」の「Install」を押下。
<img width="572" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427357/b188f6c5-bbfe-c149-5add-768c29340d89.png">


完了すると右下に「Restart Now」が表示されるので、押下する。
<img width="690" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427357/cf2311dc-ebca-b249-b1c1-bfa696790a96.png">

再起動後、メニューが日本語になっていればOK
<img width="754" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427357/38234e2d-aa5b-ca25-c1f0-6a9bdc5683ac.png">

##ESLintパッケージのインストール
同様に拡張機能からESLintをインストール

##Node.jsパッケージのインストール
同様に(略

<img width="534" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427357/db54d23f-6cc6-e1e8-1b04-16a93a55ae2b.png">


##ローカルインストール済のnode, npmをターミナルで使用する設定
settings.jsonに下記のPATHを追加する。
~/Library/Application Support/Code/User/settings.json

```json
{
    "terminal.integrated.env.osx": {
        "PATH": "$HOME/.nodebrew/current/bin:$PATH"
    }
}
```

ターミナルを再起動し、バージョン表示を確認。

```shell-session
$ npm -v
5.6.0
$ node -v
v8.11.1
```
PHPの画像認証ライブラリ「Securimage」を使ってみた


#画像認証とは

ロボットによる迷惑投稿を防止する仕組みで画像に表示された文字を入力欄に正しく記載し送信しない限り投稿が完了しません。
今回は以下のようなよく見かけるタイプの画像認証をPHPライブラリの[Securimage](https://www.phpcaptcha.org/)で実装してみました。
![キャプチャ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10793/b7bffec3-a664-fd92-592d-ff22c97a5b61.png)

#Securimageをインストールしてみる
[公式サイト](https://www.phpcaptcha.org/)にアクセスしてSecurimageをダウンロードします。
落ちてきたzipファイルを展開したらsecurimageというフォルダがあるので、それを丸ごと任意の場所へ設置するだけです。（今回はサンプルなのでドキュメントルートの直下に置きました）

```html:PHP
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>画像認証サンプル</title>
</head>
<body>
<?php require_once('./sample.php'); ?>
<form method="post">
<p><img id="captcha" src="./securimage/securimage_show.php"></p>
<p><input type="text" name="captcha_code" placeholder="表示されている文字を入力してください"></p>
<p><button type="button" id="button">画像再生成</button></p>
<p><input type="submit" value="認証"></p>
</form>
<script src="./sample.js"></script>
</body>
</html>
```

生成される画像によっては認識が困難なものもあるので、
再生成できるようにJavaScriptを設置します。

```javascript:認証画像を再生成するJavaScript
const button = document.getElementById('button');
button.addEventListener('click', function() {
    const captcha = document.getElementById('captcha');
    captcha.src = './securimage/securimage_show.php?' + Math.random();
}, false);
```

画像認証の判定プログラムです。
```$securimage->check($_POST['captcha_code'])```の返り値が真偽値となっており、
その値によって認証を判定しています。

```php:画像認証プログラム
require_once './securimage/securimage.php';
$securimage = new Securimage();

if(isset($_POST['captcha_code'])) {
  if($securimage->check($_POST['captcha_code']) === true) {
    echo '画像認証OK';
  } else {
    echo '画像認証エラー';
  }  
}
```

##オプションについて
Securimageにはいろいろなオプションが標準で用意されています。
使い方は**securimage_show.php**の```$img->show();```より前に、適用したいオプションを記載するだけです。**securimage_show.php**内には既にサンプルとしてオプションが記載されています。

```php:画像の大きさ
// 高さで大きさを指定する
$img->image_height    = 90;
$img->image_width     = $img->image_height * M_E;
```

```php:認識のしやすさ
// 文字のゆがみの比率
$img->perturbation  = .75;
// ラインの数
$img->num_lines     = 8;
```

```php:各色の指定
// ラインの色
$img->line_color      = new Securimage_Color("#ff8888");
// テキストの色
$img->text_color      = new Securimage_Color("#ff6666");
// 背景の色
$img->image_bg_color  = new Securimage_Color("#ffffff");
```

#まとめ
ライブラリを使うことで、非常に簡単に画像認証を実装する事ができました。
生成される画像についてはフォントやサイズ、色等を調整することが可能なので、サイトのイメージも損なうことなく実装する事ができそうです。
画像認証を管理画面のログインフォーム等に実装する事でセキュリティレベルの向上が期待できます。(ランディングページなどのフォームに実装する際はCVRが低下しないか検証する必要がありそうです。)
ちなみに、個人的にはgoogleのreCAPTCHAより導入のハードルは低いように感じました。


画像認証の忘備録でした！
Jetpack Compose用の新機能Live Previewでつまづいた件

# 本記事について
[FUN Advent Calendar 2019 Part2](https://adventar.org/calendars/4179)，6日目の記事です

急遽Part2に参加しました．
Part1用の記事を書いている中で，方向性がずれていってしまった一部をPart2の記事にすることにしました．
多少(かなり)の手抜き感はお許しください．

# 概要
もともとはPart1用にプレアルファ版で利用できるようになった，[Jetpack Compose](https://developer.android.com/jetpack/compose/)についての記事を書いていました．
その導入の中で，Live Previewという機能が追加されていることを知りました．
どんなもんなのか自分で試している中で，つまづいた部分をまとめていきます．

# Live Preview
Live PreviewはJetpack Composeに伴って追加された新機能になっています．
そもそもJeapack Composeとは宣言的にUIを作成することのできるライブラリです．
Jeapack Composeを利用することによって，従来のAndroidアプリ開発大きく変わるのは，Layoutファイルを使わなくなることです．
その代わり，Kotlinファイルに直接UIを書いていくことができます．

ここで問題になってくるのか，UIの確認ができなくなることです．
以前は，Layoutファイルの中でUIの調整を行い，UIの確認をDesignで確認していました．
しかし，Jetpack Composeを利用すると，アプリを実行させるまでUIの確認ができなくなってしまいました．

そこで，Jetpack Composeのプレアルファ版の中でLive Previewが追加されました．
Live Previewを利用することで，Jetpack Composeで記述したUIがどのような表示になるか確認できます．
※Jetpack Composeの書き方についての説明はしないので，[こちら](https://developer.android.com/jetpack/compose/tutorial)をご参照ください．

# 実際にLive Previewを使ってみる

早速Live Previewがどんな感じなのか試してみましょう．
基本的は使い方は`@Composable`の前に`@Preview`を追加するだけのようです．
実際に簡単なUIに`@Preview`を追加してみました．
<img width="1103" alt="スクリーンショット 2019-12-04 14.04.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225369/abb35a0f-69cc-25a8-7123-859704caa87a.png">
ちーんΣ（・□・；）
これでもアプリ自体は実行できますが，Live Previewは機能していません．
なんでだろうと思いつつ，サイトを読み直してみると
` To create a live preview, create a new composable function that takes no parameters and includes a @Preview annotation before @Composable, as shown below`
との記述がありました．ようは`@Preview`を付けた関数には，引数をつけるなとのことです．

そこで，`@Preview`をつける関数には引数を与えず，UI用の関数に引数を与えるように変更しました．
![スクリーンショット 2019-12-03 21.24.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225369/81f98bad-7d8e-1165-3e49-6666d0b85e2f.png)
結局だめでした．
しかし，[公式サンプルアプリ](https://github.com/android/compose-samples)を眺めていたところ，Class内では使っていないとこが判明しました(そもそも公式サンプルアプリではUI用の関数はClassの中に書いていないんですね)．

<img width="1083" alt="スクリーンショット 2019-12-04 12.57.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225369/2ed8264a-1d75-ccc0-9163-1621d93478aa.png">

なんとか表示できました(Dark仕様にしていることもあり，かなーーり見辛いですが一応表示されています)．
なぜクラスの中で表示されないのか原因はよくわからないです．
[公式サイト](https://developer.android.com/jetpack/compose/setup)には記述されていないような感じでした(知っている方いらっしゃいましたらコメント欄にでも...)．

結論としては，Live Previewを使用する場合には，UI用のファイルを用意して利用するのが現状のベストっぽいです．

# まとめ
この記事では，Jetpack Compose用の新機能であるLive Previewを導入した際に自分がつまづいたことを書きました．
Live Previewと言う割には，レイアウト変更後`Build & Refresh`を押さないと更新されないので少々使い勝手が悪い印象を受けました．
また，画像のように背景が透過になっていて，このままだと見辛いのもどうにかにして欲しいと感じました．
アプリを実行した際のデフォルトの背景は白なので，この部分も背景のデフォルトは白にして欲しいところです．
今後，どのような変更が加わってくるのかによって，かなり使い勝手が変わってくるように感じます．

# 参考サイト
- Jetpack Compose : https://developer.android.com/jetpack/compose
- Tutorial Jetpack Compose Basics : https://developer.android.com/jetpack/compose/tutorial
- compose-samples : https://github.com/android/compose-samples
- Use Android Studio with Jetpack Compose : https://developer.android.com/jetpack/compose/setup
メモ：新規作成のユーザが外部で如何してもアクセスできない原因

新規作成のユーザが外部で如何してもアクセスできない原因
・該当ユーザのプロファイルの中に、ログイン時間帯の制限とログイン IP アドレスの制限の領域が何か制限がありますか確認します。
ngrokでInvalid Host headerエラーを解消した方法

## 状況
awsのEC2上にWebpackDevServerでサーバを建て、スマホからEC2環境のQAを実施しようとした。
ngrokでトンネル掘ってアクセスしたら **Invalid Host header** となってアクセスできない。
この記事では **Invalid Host header** を解消した方法を記載します。

この方法は以下の環境でも機能するようです。

- Angular or React dev server
- Vue dev server
- react express app
- ng app using MSAL

## まずは結論から（解消方法）
起動コマンドにオプションを追加する
以下のどちらでも行けます。
`ngrok http 8080 -host-header="localhost:8080"`
`ngrok http --host-header=rewrite 8080`


# 自分が辿った流れ
## 手段
[ngrok](https://ngrok.com/)(エングロックと発音するらしい)を使ってEC2環境を公開。

## 手順
基本的にはngrokサイトに記載の方法に従った。
1. ngrokサイトでフリーアカウントを作成
2. EC2上のubuntuにngrokをインストール
3. ngrokのサイトに記載されている起動コマンドだとうまく行かない
4. 解消方法のオプションを試したらうまくいった

参考にしたのはこれです。
https://gist.github.com/xola139/906cff7d4c2460e6de1dd6998386a0d8

`./ngrok http 8080`
　→　これだと公開URLにアクセスしても **Invalid Host header** エラーでアクセスできない。
![スクリーンショット 2019-12-04 16.53.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357158/a28daf7a-dd5f-3155-f0e8-e3c35cf30e81.png)
IBM API Connect 環境依存の値をコントロールする

#はじめに

API Connectを利用したAPIのシステムアーキテクチャーでは、API Connectがリソースサーバーの役割を担うことは稀で、大抵のケースにおいて他のリソースサーバー(バックエンドサーバー)へAPIを中継することになります。

そこでよくある問題が、テスト環境ごとに異なるバックエンドサーバーのURLをどのように保持するか？というものです。

ここでは、API定義のプロパティーにカタログごとの値を設定する方法をご紹介します。
なお、APIC v2018では、より良い方法が採用できるので、最後にご紹介します。

#前提条件

2019/12時点のIBM Cloud API Connectサービスを利用します。
IBM CloudのAPI Connectは v5ベースになります。

なお、本記事で作成するAPI定義は、[ここ](https://github.com/yo24/APIC-env-variable)からダウンロード可能です。

#試すこと

API Connectサービスに、2つのカタログを用意します。
カタログ名は、env1、env2とします。
env1、env2に同じAPIを公開し、カタログごとに異なるバックエンドサーバーのAPIを呼び出してみます。

#バックエンドサーバーのAPI

バックエンドサーバーのAPIは、同じIBM Cloud上のSandBoxカタログ上に作成します。
このAPIは2つ作成し、それぞれ以下のJSONをレスポンスします。

```json:backend_api_response-env1用
{"message" : "stub1だよ" }
```

```json:backend_api_response-env２用
{"message" : "stub2だよ" }
```

#API定義(アセンブル)

env1、env2カタログに公開するAPIの処理内容(アセンブル)は下図の通りです。
invokeポリシーで、バックエンドサーバーのAPIにアクセスします。
ここで、バックエンドサーバーのAPI URLは、```$(backend_url_root)/stub```としています。
URLの前半部分は、「backend_url_root」としてプロパティー化します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135384/68b71f50-aa0a-24b1-500b-0520763db213.png)

#API定義(プロパティー)

プロパティー登録内容は、下図の通りです。
backend_url_rootプロパティーに対して、env1、env2カタログで異なる値を設定しています(赤枠部分)。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135384/eff1b70b-d259-ea97-cf25-3862915201d5.png)

バックエンドサーバーのAPI URLは、invokeポリシーの設定値を踏まえると、以下のようになります。

```text:env1用
https://api.us-south.apiconnect.appdomain.cloud/xxx/sb/env-api-stub1/stub
```

```text:env2用
https://api.us-south.apiconnect.appdomain.cloud/xxx/sb/env-api-stub2/stub
```
※host名は、API Connectサービスをデプロイしたリージョンに依存します
※xxxは、本来サービスごと（オンプレ版だとプロバイダー組織ごと）に設定されますが、ここではマスクしています

#API実行

先ほど記載したAPI定義を、env1/env2カタログに公開し、実行します。
以下は、curlコマンドでAPIを呼び出した結果です。
記載の通り、レスポンス内容からバックエンドサーバーのAPIを呼び分けていることが分かります。
なお、カタログへの公開方法は、本記事の主題から逸れるので省略します。

```console:env1カタログ
curl https://api.us-south.apiconnect.appdomain.cloud/xxx/env1/env-api/go
'{"message" : "stub1だよ" }'
```

```console:env2カタログ
 curl https://api.us-south.apiconnect.appdomain.cloud/xxx/env2/env-api/go
'{"message" : "stub2だよ" }'
```
※URLにはカタログ名が含まれており、URLからカタログが推察できます
　(https://ホスト名/プロバイダー組織名/カタログ名(env1 or env2)/APIごとのURL)


#APIC v2018では

APIC v2018からは、カタログにプロパティーを設定することができ、環境変数のような扱いが可能になります。

これにより、API定義に設定を保持する必要がなく、より環境間のポータビリティーが増します。
なお、API定義からカタログのプロパティーを参照する方法は、API定義のプロパティーと同じです -> ```$(プロパティー名)```

下図は、v2018のカタログ-プロパティー設定画面例です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135384/e0eb8a3d-9ebe-c78c-6435-159e2bb69026.png)


#まとめ

本記事では、バックエンドサーバーのAPI URLを題材に、環境間で異なる値をプロパティーで解決する方法をご紹介しました。

注意点としては、今回の手法は、あくまでカタログ名が異なる前提ということです。
例えば、本番とテスト環境で、アカウントを分けてカタログ名を同じにするケースでは適用できません。

逆に、テスト環境が複数あって、カタログで論理分割する際には有効な手段になります。
【AWS】既存のECS ClusterにFargate Spotを適用させる


## 概要
今年のre:inventでFargateにもspot Instanceみたいなものを使えるようになりました。
お値段とかどんなサービスかはクラメソさんのブログを見てください。
[【最大70%引きで使用可能、東京でも利用可能】AWS Fargate Spotがリリースされました。](https://dev.classmethod.jp/etc/aws-fargate-spot/)


今回は既存のClusterに適用にするにはマネジメントコンソールでのやり方がわからなかったためCLIでやりました。
そのための手順のみ記載していきます。

## 手順
### AWS CLIのアップデート

CapacityProviders用のコマンドがいるのでバージョンを最新にします。

```bash:console
pip install --upgrade awscli
```

今回の手順は以下のバージョンで行いました。

```bash:console
$ aws --version
aws-cli/1.16.296 Python/3.7.4 Darwin/18.7.0 botocore/1.13.32
```

### CLIコマンド


```
aws ecs put-cluster-capacity-providers \
     --cluster [クラスター名] \
     --capacity-providers FARGATE FARGATE_SPOT \
     --default-capacity-provider-strategy capacityProvider=FARGATE,weight=1,base=1\ \
     --profile [プロファイル名]
```

参照記事には、`--capacity-providers `には既に設定されているCapacityProvidersも全部書きましょうとありますが、ないので`FARGATE`,`FARGATE_SPOT`の2つでOKです。
`--default-capacity-provider-strategy`に関しては、デフォルトでのCapacityProvidersと割合（weight）及び最低必要数（base）を記載します。

### Update Cluster

コマンド実行後にCapacityProvidersタブにこのように表示されます。

![スクリーンショット 2019-12-04 17.02.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33165/2a81e0aa-2832-59f1-6a1c-1fc1ba046bfe.png "スクリーンショット 2019-12-04 17.02.07.png")

あとは、右上の`Update Cluster`を押すと以下のように割合設定できます。

![スクリーンショット 2019-12-04 17.02.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33165/d13fe039-e311-1626-b52b-5a81405a1aad.png "スクリーンショット 2019-12-04 17.02.34.png")

## 注意点
2019/12/04時点ではCapacityProvidersタブにあるCapacityProviderを選択して`Deactivate`を押すと消えます。
消えたあとに`Update Cluster`画面に戻っても、もとに戻せないのでまたCLIからです。

検証中ですが、設定だけしても次回タスクが`FARGATE_SPOT`で上がってこない可能性あります。
その場合、CLIでサービスを強制deployしたら行けました。
こちらは、検証後に再度アップします

## 2019/12/21 追記
その後の調べた内容を[ブログ](https://hisa-tech.site/fargate-spot-on-existing-cluster/)にまとめました。


## 参照記事
[Using AWS Fargate Capacity Providers](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/fargate-capacity-providers.html#fargate-capacity-providers-create-cluster)
Javaをはじめよう - 開発環境をつくる②

今回は,前回説明していなかったIDEのダウンロード,インストール方法について説明します。
「なんとなくわかる」などの方はこの回をスルーしても大丈夫です。
※**この記事は2019/12/04現在のモノです。表記が古い場合があります**
#Pleiades All in One(Eclipse)の導入
###ダウンロードしよう
ダウンロードリンク: https://mergedoc.osdn.jp/
このページに飛んだら,自分のパソコンの_bit数_に合ったものをダウンロードしてください。
>bit数の確認方法(Win10)
「設定」を開く→左上の「システム」を選択→左の項目を下までスクロールし,「ⓘバージョン情報」を選択→「デバイスの仕様」項目の「システムの種類」に書いてあります。
![mergedoc.osdn.jp_ (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545051/fb7d00bb-e633-949d-0bf6-b62fdb1f4059.png)


64bitの場合は,最新版の「2019-9」をクリック。32bitの場合は,32bit最終版「2018-9」をクリック。
![mergedoc.osdn.jp_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545051/d0f603f9-6358-91e9-7645-bb5973608239.png)

32,64bit同様で,今回はJavaのIDEを導入するのでWindowsの場合は「Windows」,Macの場合は「Mac」のJavaを選択してください。また,「Full Edition」と「Standard Edition」の2種類がありますが,今回は「Full Edition」を選択してください(コンパイラ,JDKがインストールされているため)。
![mergedoc.osdn.jp_ (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545051/dca62c59-d333-9484-a487-b1756852cbb4.png)

クリックすると下のようなテキストが現れるのでリンクをクリックします。
するとダウンロードが開始します。
※1.5GBほどあります。気長に待ちましょう...
![05cd746ea17fc2187002f6c3ae4d5248.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545051/47a98188-dfcc-493a-f7bb-610b31947a03.png)

###解凍しよう
※**注意　Windowsの場合,この解凍は7-Zip(無料)が必要です。 Windows標準または別の解凍アプリケーションで解凍を行った場合正常に動作しない可能性があります。**
>7-Zipのダウンロードページ https://sevenzip.osdn.jp/
こちらも自分のbit数に合ったものをダウンロードしてください。
bit数を間違うと使えません。

ダウンロードされたzipファイルを右クリックして,「7-Zip」を選択→「展開...」を選択し,解凍先をCドライブに指定して解凍してください。
これで解凍は完了です。

###起動してみよう
起動後,**ワークスペース**の指定をします。
特にこだわりがない場合は,そのまま「起動」を押しましょう。
![install04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545051/bdc0cd73-17bc-7122-e909-8ece36b0eed8.png)

これで日本語化されたEclipseの導入が完了しました。次回化は少しコードに触れていきたいと思います。

前) Javaをはじめよう - 開発環境をつくる①
https://qiita.com/_Hage_K/items/117095082ef3bc1b4ccb

次) 後日投稿
Facebookログインで`クエリを実行できませんでした。`と出る対処法

## 環境など
- Facebook SDK v5.9
- FirebaseUI
- Android

## 内容
Facebookログインをログイン画面へ行く前に下記エラーがでました。

```
Caused by: SERVER_ERROR: [code] 1675030 [message]: クエリを実行できませんでした。 [extra]:
```

結論から言うと下記サイトの通りだったのですが、自動翻訳っぽくてわかりにくかったので少し説明します。
https://codeday.me/jp/qa/20190218/288009.html

`facebook for developers`にて`役割>役割`で`テスター`を登録しておかないと上記エラーが出るようです。
管理者はテスターになれない上に、友達登録しておかないと、追加対象として出てこないようなので、
新規アカウントを作成し自分で友達登録を行い、新規アカウントをテスター登録することで、ログインできるようになりました。

2019年10月頃にサンプル作成したときには必要なかったのですが、2019年11月に実装した時には必要になってました。

管理画面上の差分を探したら、APIバージョンが`ｖ4.0`と`ｖ5.0`で差分がありました。
結構苦労したので備忘録として記事化しました。
[UE4] New Audio Engine(Audio Mixer)の設定方法について

UnrealEngineのオーディオ機能は現在大きく分けて2つのものが存在します。
従来から実装されていたAudio Deviceと現在積極的に開発を行っているNew Audio Engineと呼ばれるものです。
（New Audio Engineに関しては多プラットフォームへの互換性を重視し開発しています）

New Audio Engineは実装内ではAudio Mixerとしていることが多いので、
もし実装の中身を見る場合はAudioMixerで検索して頂くと情報が見つかりやすいかと思います。
**4.24でAudio Mixerがデフォルトで有効化されました**
![2019-12-04_15h54_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/b4afc3b7-72d8-a9a1-767e-7eb3379203c8.png)

# 設定の確認方法
アウトプットログなどで、**au.IsUsingAudioMixer ?**を実行すると、どちらのオーディオ機能を使用しているか確認することが出来ます。
こちらのコマンドの結果が1の場合New Audio Engineを使用している状態となります。
![2019-12-04_16h13_57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/01621df6-cf21-f1f1-c07e-772bd537ddc7.png)


# 設定の変更方法について
4.23ではデフォルト設定が従来のAudio Deviceとなっているため、以下に変更方法を紹介します。
2通りの設定があり、INIファイルでの設定か起動引数で変更が可能です。
(検証の際は引数で、プロジェクト自体に設定する場合はINIファイルで、といった使い分けができるかと思います。)

それぞれ設定例を以下で紹介します。

## 1.INIファイルベース
INIファイルで設定する場合は、Configの[Audio]セクションでUseAudioMixerをTrue宣言します。
例として**Engine/Config/Windows/WindowsEngine.ini**に以下のように追加すると設定を変更できます。
![2019-12-04_16h17_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/7cc8962f-f569-7cbb-9668-ee2c3bf516be.png)

## 2.起動引数
起動引数に-audiomixerを追加することで変更が可能です。
例ではEditorのショートカットに追加しています。
![2019-12-04_16h28_57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363894/929efc6d-1ee6-5ac2-51f6-b743391ed602.png)
Jestテスト実行時「Unknown custom element」が発生した場合の対処法

## 問題の現象
Jestテスト実行時、以下のようなVuetifyコンポーネントの`Unknown custom element`の警告が出た場合

```bash
$ yarn test
yarn run v1.17.3
$ jest --config jest.config.js
 PASS  test/Button.spec.js
  Button
    ✓ is a Vue instance (18ms)

  console.error node_modules/vue/dist/vue.runtime.common.dev.js:621
    [Vue warn]: Unknown custom element: <v-btn> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
    
    found in
    
    ---> <Button>
           <Root>

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.588s
Ran all test suites.
✨  Done in 5.91s.
```

## 前提
### package.json
```json:package.json
{
  "scripts": {
    "test": "jest --config jest.config.js",
  },
}
```

### コンポーネント
```vue:components/Button.vue
<template>
  <v-btn large color="primary" @click="log">
    ボタン
  </v-btn>
</template>

<script>

export default {
  name: 'Button',
  methods: {
    log() {
      console.log('hoge')
    }
  }
}
</script>

```
### テストコード
```js:test/Button.spec.js
import { mount } from '@vue/test-utils'
import Button from '@/components/Button.vue'

describe('Button', () => {
  test('is a Vue instance', () => {
    const wrapper = mount(Button)
    expect(wrapper.isVueInstance()).toBeTruthy()
  })
})
```

## 対応内容
- JestがVuetifyコンポーネントを認識できるように、警告が出たタグのモックを作成する

```js:test/jest.setup.js
import Vue from 'vue'
import VueTestUtils from '@vue/test-utils'

Vue.config.silent = true

// Mock Vuetify components
VueTestUtils.config.stubs['v-btn'] = '<button><slot /></button>'
```

```js:jest.config.js
module.exports = {
  setupFiles: ['<rootDir>/test/jest.setup.js'],    // Load Mock setting
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/$1',
    '^~/(.*)$': '<rootDir>/$1'
  },
  transform: {
    '^.+\\.js$': 'babel-jest',
    '.*\\.(vue)$': 'vue-jest'
  },
  moduleFileExtensions: ['js', 'json', 'vue']
}

```

## 参考サイト
- [#Nuxt.js で Jest を利用したテストを実装する際にエンカウントしたワーニングやエラーの対処法メモ - the industrial](https://omiend.hatenablog.jp/entry/2019/07/12/150852)
- [Enable Vue-Test-Utils to work with Nuxt · Issue #4115 · nuxt/nuxt.js](https://github.com/nuxt/nuxt.js/issues/4115)