OmniAICreator/Qiita-1.07M huggingface dataset:
UE4でレンダーターゲットテクスチャをピクセルシェーダあるいはコンピュートシェーダで描画する

#概要
UE4でレンダーターゲットテクスチャをピクセルシェーダあるいはコンピュートシェーダで描画し、マテリアルで使用するサンプルプロジェクトを作りました。
エンジン改造はせず、プロジェクトプラグインとして実装しています。
Githubにあげています。
何かいけてないことがあれば何でもご指摘ください。

#Githubレポジトリ
https://github.com/monguri/UE4ShaderPluginSandbox

#動機
描画パスを追加してVSPSあるいはCSを動かし、その結果を他のパスで使う、ということをしたかったので、その最初の検証としてHello World的なものを作りました。
せっかくなので公開しました。

#スクリーンショット
PIE前
![BeforePlay.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16365/bcaba67a-100a-0abf-4b60-b8e974ed40b3.jpeg)

PIE後
![AfterPlay.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16365/d6697d0e-0e5c-79a6-8462-4c40ae2135f7.jpeg)

#実装の補足説明
ベースとなっている知識については、下に参考にした資料をあげるのでそちらを見ていただいた方がいいと思いますので、このプロジェクトに限定した説明を書きます。

RenderTextureActorをマップに配置してTickを回し、Tickの中でレンダースレッドのコマンドキューにコマンドを追加しています。
レンダリングに関する部分はRenderTextureRenderingに分離しています。
コマンドは2つあり、一方はVSとPSでTextureRenderTarget2Dに描画をしています。
もう一方はCSでCanvasRenderTarget2Dに描画をしています。

PSはテクスチャのRチャンネルを塗りつぶしてるだけ、CSもGチャンネルを塗りつぶしてるだけの簡単なものになっています。
TextureRenderTarget2Dの方はスフィアのスタティックメッシュのマテリアルに使い、CanvasRenderTarget2Dの方はキューブのスタティックメッシュのマテリアルに使っているので、プレー後はそれらが赤と緑に塗りつぶされます。
結果は全く面白くもなんともないですが、これをベースにいろんなシェーダを書けば面白い表現ができるかもしれません。

CSでTextureRenderTarget2DでなくCanvasRenderTarget2Dを使っているのは、bCanCreateUAV = trueになっているからです。
ソースを追っていくとわかりますが、例えばDX11の場合だとテクスチャ作成時にD3D11_BIND_UNORDERED_ACCESSが立つかどうかになるため、UAVとして使うには必要です。

CanvasRenderTarget2Dは4.23からbCanCreateUAV = trueが追加されており、これが何の意図によるものだったのかは未確認です。
ちなみに4.22でもbCanCreateUAV = trueを加えれば動作することを確認しています。

#参考資料
##サイアメントの瀬尾さんのブログ記事
http://www.sciement.com/tech-blog/c/structured_buffer_compute_shader_ue4_part1/
最も参考にさせていただいた記事です。瀬尾さん、ありがとうございます。

レンダーターゲットでなくstructured bufferを出力バッファにしているところは違いますが、やってることはほとんど同じです。
https://github.com/HSeo/ComputeShaderUE419Test
UE4は4.20以降に関連する描画周りの書き方が変わっていて、こちらは4.20以降はビルドが通らなかったり実行時にシェーダのファイルパスが見つからないエラーが出たりしますが、UE4のLensDistortionプラグインとか参考にすればちょっとの修正で対応できます。

##Teraman氏のサンプル
https://github.com/Temaran/UE4ShaderPluginDemo
CSでUAVに描画をしたあと、それをVSPSで別のテクスチャにコピーしてマテリアルで使用しています。
Teramanさん、ありがとうございます。
これも4.23で動くように書き直そうかと思いましたが自作を優先しました。

##UE4のドキュメント
https://docs.unrealengine.com/ja/Programming/Rendering/ShaderInPlugin/Overview/index.html
Epicさん、いつもありがとうございます。

2019/10/26追記
##ヒストリアさんの記事
http://historia.co.jp/archives/12659/
4.22以降でGlobalShaderの動くサンプルが公開されてるものがないなーと思い今回の公開に踏み切ったのですが、ヒストリアさんでVSPSについては公開されてる記事があることを後から知りました。
コードについても丁寧な解説があるので読むことをおすすめします。

##参考にしたUE4のソースコード
LensDistortionプラグイン
VectorField.cpp

DispatchComputeShaderとかで検索すればたくさん面白いソースが見つかります。

#課題
そもそも検証としては、やってることが簡易すぎて、実装上の問題を見落としているかもしれません。
また、ちゃんと使うなら、用途に応じて、パスをはさむタイミング、非同期コンピュートの検討、パフォーマンス測定、レンダーテクスチャ以外の出力バッファの検討、テクスチャフォーマットの検討などいろいろ考えねばなりませんね。
それはまた別の機会に書かせていただくかもしれません。
iOS アプリからニフクラに現在時刻を問い合わせる

# はじめに

ニフクラを利用した iOS アプリを開発していた際に、ニフクラのデータストアのレコードに対する読み出し・書き込みの処理に現在時刻を使用する必要があり、実装方法を検討しました。

# 端末側で取得する「現在時刻」は当てにならない

iOS デバイス側では時刻を任意に設定できてしまうため、iOS アプリ側で次のようにして時刻を取得すると、実際の現在時刻とは異なる時刻を現在時刻として扱ってしまう可能性があります。

```swift
// 端末の時間を任意に設定できるため
// 本当の現在時刻が取得できるとは限らない
let date = Date()
```

# ニフクラ側で現在時刻を取得する

ニフクラ側から現在時刻を返してもらえるような機能[^1]が用意されているか少し調べてみましたが見つかりませんでした[^2]。そこで今回は、ニフクラのスクリプト機能により iOS アプリからニフクラに現在時刻を問い合わせるという方法をとることにしました。

## 現在時刻を返すスクリプト

ニフクラから現在時刻を返すためのスクリプトの例を以下に示します。

```js:getCurrentTime.js
module.exports = function (req, res) {
    res.status(200).json(new Date());
}
```

このスクリプトをニフクラのコンソールから[アップロード](https://mbaas.nifcloud.com/doc/current/script/basic_usage_javascript.html#スクリプトのアップロード)します。アップロード時に選択するメソッドは `GET` にしておくものとして、以下でこのスクリプトをアプリ側から実行する方法について説明します。

## iOS アプリからスクリプトを実行する

上に示したスクリプト `getCurrentTime.js` を iOS アプリから実行する方法を説明します。iOSアプリの開発環境は以下のとおりです。

- Xcode v11.1 (11A1027)
- ニフクラ mobile backend iOS SDK v3.0.2[^3]


ニフクラが提供する SDK を使ってスクリプトを実行し、スクリプトが返す値をデコードすればよいのですが、デコードする際には注意が必要です。

`JSONDecoder` はデフォルトでは `yyyy-MM-dd'T'HH:mm:ssZ` 形式の日時を扱うことを前提としているらしく、ニフクラが返す `yyyy-MM-dd'T'HH:mm:ss.SSSZ` 形式（ミリ秒が含まれている）の日時をデコードすることができません。

以下のようにして、想定している日付フォーマットを `JSONDecoder` クラスの `dateDecodingStrategy` に指定してからデコードすると、期待どおりの結果が得られるようになります。

```swift
let script = NCMBScript(name: "getCurrentTime.js", method: .executeWithGetMethod)!
script.execute(nil, headers: nil, queries: nil) { data, error in
    if let error = error {
        // TODO: エラー処理
        return
    }
    guard let data = data else {
        // TODO: エラー処理
        return
    }

    // デフォルトのJSONDecoderでは
    // ニフクラが返す日時情報をデコードできないため、
    // dateDecodingStrategyの設定が必要
    let decoder = JSONDecoder()
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
    decoder.dateDecodingStrategy = .formatted(formatter)

    do {
        let date = try decoder.decode(Date.self, from: data)
        // TODO: 得られた現在時刻を利用する
    } catch {
        // TODO: エラー処理
    }
}
```


[^1]: Cloud Firestore で提供されている [`serverTimestamp()`](https://firebase.google.com/docs/reference/swift/firebasefirestore/api/reference/Classes/FieldValue#/c:objc(cs)FIRFieldValue(cm)fieldValueForServerTimestamp) のようなAPIがあるのが理想的でした。
[^2]: 古い情報ですが、ニフクラのユーザコミュニティでもサーバ側の現在時刻を取得する方法について言及がありました。そこでは、サーバ時間の取得方法として、データストアで適当なデータを作成して `createDate` や `updateDate` の値を参照する方法が提案されていました。
 https://github.com/NIFCloud-mbaas/UserCommunity/issues/260
[^3]: [ニフクラ mobile backend Swift SDK](https://github.com/NIFCloud-mbaas/ncmb_swift) も提供されていますが、そちらは Deployment Target が iOS 12.0 のため、今回はより古い OS バージョンを対象とするアプリでも利用可能は ニフクラ mobile backend iOS SDK の方を使用しています。（将来的には Swift SDK の方も使っていきたいと思っています。）
Javascript JQuery

```html:jquery
<html>
<head>
  <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
</head>
</body>
  <input type="text" id="text1">
  <button id="register">追加</button>
  <div id='id1'></div>

<script>
  let items = [];

  function createTable() {
    if (items.length <= 0) {
      $('#id1').html('');
      return;
    }
    let table = '<table border="1">';
    for (const i in items) {
      table += `<tr><td>${items[i]}</td><td><input type='button' onclick='update(${i})' value='編集'></td><td><input type='button' onclick='del(${i})' value='削除'></td></tr>`;
    }
    table += '</table>';
    $('#id1').html(table);
  }

  $('#register').click(() => {
    items.push($('#text1').val());
    createTable();
  });

  function del(i) {
    items.splice(i, 1);
    createTable();
  }

  function update(i) {
    items[i] = $('#text1').val();
    createTable();
  }
</script>
</html>
```

```html:jquery
<html>
<head>
  <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
</head>
</body>
  <input type="text" id="text1">
  <button id="register">追加</button>
  <button id="search">検索</button>
  <table id='tbl'></table>

<script>
  let items = [];

  function createTable(items) {
    let tbl = '';
    for (const i in items) {
      tbl += `<tr><td>${items[i]}</td><td><button class="item" id="update-${i}">編集</button></td><td><button class="item" id="delete-${i}">削除</button></td></tr>`;
    }
    $('#tbl').removeAttr('border');
    if (tbl) { 
      $('#tbl').attr('border','1');
    }
    $('#tbl').html(tbl);
  }

  $('#register').click(() => {
    items.push($('#text1').val());
    createTable(items);
  });

  $('#search').click(() => {
    const val = $('#text1').val();
    const items2 = items.filter(i => i.indexOf(val) >= 0);
    items = items2;
    createTable(items);
  });

  $(document).on('click', '.item', function() {
    const tmp = $(this).attr('id').split('-');
    const type = tmp[0];
    const id = tmp[1];
    if (type === 'update') {
      items[id] = $('#text1').val();
    } else if (type === 'delete') {
      items.splice(id, 1);
    }
    createTable(items);
  })
</script>
</html>


```
FreePBX から slack 連携

FreePBXでslackに着信番号通知

## これは
元職場で同僚だったmahさんの[fax2slack](https://github.com/mah-jp/fax2slack) をヒントに3CXにぶら下げた FreePBX で着信した電話番号の通知番号をslackに投下する奴です。


## 必要なもの
- SIPサーバ(なんでも)
- 着信専用のFreePBX
- Slack の WEB hook URL


## FreePBXの設定(この手順わすれそうなのでこれを書いた)
1. WEBコンソールにログイン後 アドミン → カスタム宛先 を選択
2. Add Destination を押す
3. Target に mycustom-app,s,1 と入力し 説明を適当に入れて Submit


```conf:/etc/asterisk/extensions_custom.conf
[mycustom-app]
exten => s,1,System("[SCRIPT PATH]" ${CALLERID(num)})
exten => s,n,Wait(300)
exten => s,n,Hangup
```
これで script path のスクリプトを実行してくれます。
user は asterisk の権限で動くので権限周りは確認しておくとよい。

あとはスクリプトを適当に書けば着信した番号を拾う事のできるシステムの完成。
macOS Catalina で MacOS X Lion のインストールUSBディスクを作成する

実家に眠っていた10年前のMacBook (Early 2008)を工場出荷状態に戻そうとしてHDDを初期化したら再インストールができなくなってインストールディスクが必要になったものの、作成できずに四苦八苦した記録です。

# 環境

インストールディスクを作成するために使ったマシンです。

* MacBook Air Mid 2013
* macOS 10.15
* Homebrew 2.1.15

インストールディスクはポータブルHDDに作成しました。

* 30GBくらいの外付けUSB HDD（ずっと昔のEeePCについてたやつ）

# 1. Mac OS X Lionのインストーラーを入手する

すでに通常の手段でのAppStoreからのダウンロードができなくなっています。
再インストールを施したかった古いMacBookのリカバリーモードからも、AppleIDを入力してもインストーラーを入手できず再インストールに失敗していたようです。


しかしAppStoreにはまだデータは残っているようで、 [`mas-cli`](https://github.com/mas-cli/mas) を使用して以下の手段でダウンロードできました[^oldmac]。

```bash
$ brew install mas
$ mas install 444303913
```

ダウンロードが終わると `/Applications` に `Install Mac OS X Lion.app` （Mac OS X Lion インストール）が出現しています。

[^oldmac]: こちらの記事を参考にしました https://applech2.com/archives/how-to-create-usb-installer-lion-to-high-sierra.html

# 2. 書き込み可能なディスクイメージを作成する

`Install Mac OS X Lion.app` の中には `InstallESD.dmg` というイメージファイルがあり、これがいわゆるインストールディスクのイメージになっています。
これをUSBメモリに書き込めばいいのですが、これが一筋縄ではいかない[^createinstallmedia]。

[^createinstallmedia]: 当時はまだ `createinstallmedia` なんていう便利なコマンドは付属していないんです！　El Capitan以降の最近のmacOSインストーラーにはついてくるので、多分簡単にディスク作れると思います。

検索すると良く出てくるのは[Install Disk Creator](https://macdaddy.io/install-disk-creator/) もしくは [DiskMaker X](https://diskmakerx.com) を使用する方法ですが、Install Disk Creatorはプログレスバーが進まず、DickMaker Xは途中で要求される `ASObj-CRunner.app` が64bit対応しておらず[^catalina]に作業を完遂できない、という状態でした。

[^catalina]: macOS Catalinaから32bitアプリは動作しなくなりました。

ディスクユーティリティからdmgをUSBディスクに書き込もうとしても `Could not validate sizes - その操作は許可されていません` というエラーが出るだけで書き込みできず。

ところが、ブータブルなISOファイルをimgファイルにして書き込むのに使う `hdiutil` を使ったらうまく行ったので、その方法をご紹介します。

```bash
$ hdiutil convert -format UDRW -o ~/Lion.img /Applications/Install\ Mac\ OS\ X\ Lion.app/Contents/SharedSupport/InstallESD.dmg
```

これでホームディレクトリ直下に `Lion.img` ができているはず。
これを `dd` でUSBメモリに書き込みます。
ここでは書き込み対象を `/dev/disk2` とします。（使用前にフォーマットとアンマウントを済ませておく必要があります。）

```bash
$ sudo dd if=~/Lion.img.dmg  of=/dev/disk2 bs=1m
```

これで出来上がり！
USBメモリがインストールディスクになりました。


# 3. インストールに使う

インストール先のMacBookにUSBメモリを挿し、 `option` を押しながら電源を投入。
USBメモリが表示されているはずなので、これを選んで起動。

すると復元ユーティリティが立ち上がるので、「Lionをインストール」を選んでウィザードの通りに進行すればインストールは完了！
お疲れ様でした！！

久しぶりにLionの画面を見たぞ！！　このころはまだウィンドウの閉じるボタンに立体感があったんですね！！　なつい！！
MVCの理解

自分なりに腑に落ちた言い回しと言いますか、そういう物を書いてみます。
※初学者の参考になれば幸いです。
## モデル
`rails g model cotent:text`などと叩いてテーブルを作るとする。
そのテーブルを扱いたい。どうするのか？
**A.テーブルを操作するためのモデルと呼ばれる特殊なクラスを用いて、データベースを使う**
※クラスは設計図のようなもの
## ビュー
> モデルのデータを取り出してユーザが見るのに適した形で表示する要素である。すなわち、UIへの出力を担当する。例えば、ウェブアプリケーションではHTML文書を生成して動的にデータを表示するためのコードなどにあたる。

参照URL
[Model View Controller（Wikipedia）](https://ja.wikipedia.org/wiki/Model_View_Controller)

## コントローラー
> ユーザからの入力（通常イベントとして通知される）をモデルへのメッセージへと変換してモデルに伝える要素である。すなわち、UIからの入力を担当する。モデルに変更を引き起こす場合もあるが、直接に描画を行ったり、モデルの内部データを直接操作したりはしない。

参照URL
[Model View Controller（Wikipedia）](https://ja.wikipedia.org/wiki/Model_View_Controller)

## 余談
コントローラーとビューは早い段階で理解できていましたが、モデルというのが曖昧だったので書いてみました。（というかモデルの事だけを書き留めておこうと思ったら中途半端だったのでVとCについても引用してきただけなのは内緒）
MVCって何かわかる？っていう質問に対しての回答になっていればいいのですが・・・。
JALI tool のメモ

http://jaliresearch.com/

## 何か?

vtuber などで, 任意の音声を与えて speech animation させたい用です.

台本と音声から, よろしく speech animation を作ってくれます.
基本的には Phoneme(Viseme)のアニメーション(時系列重み)を計算してくれるだけで, これに対応した rig が必要になります. 基本的には後述の jRig を使います.
(キャラクタの静的メッシュを与えたら, よろしく唇や顎, 目や表情を作ってくれるわけではない)

筆者は Maya plugin を調達しましたが, 最近では Unity plugin や C++ SDK も出ているようです.
少なくとも Maya plugin は, リアルタイム用途ではありません(オフラインで animation 作る用)

似たようなツールとしては, iClone の lip sync でしょうか. ただし iClone だと, FBX で import/export できる rig 限定になります. 動かしたいキャラクタを Maya で生成している場合は rig が iClone に変換してインポートできればいいですが, できない場合は JALI くらいになるかも?(https://facefx.com/ も同様なことができそうですが, 未検証) 

## コンポーネント

いくつかコンポーネントがあります. Maya の plugin との前提で話をします.

### jAnalyze

テキスト(台本)と音声データから phoneme 位置の alignment 情報を計算します
(中身的にはほぼ Montreal Forced Aligner 動かしているだけっぽい)

筆者は自前で MFA を動かしてアラインメントデータ作成対応したので, jAnalyze のライセンスは調達しませんでした.

### jSync

テキスト, 音声データとアラインメント情報から, speech アニメーションデータを生成します.
生成時間は数百ミリから数秒で終わります(機械学習などは使っていないっぽい)

似たようなことができるものに, VisemeNet があります.

https://github.com/yzhou359/VisemeNet_tensorflow

ただ, VisemeNet だと毎フレームのキーフレームデータになります. jSync だとアニメーションカーブなので, あとでアニメーション調整ができます.

また, VisemeNet よりは jSync のほうが品質がよいし, VisemeNet だと足りないパラメータ(Viseme)があったりします. eye blink なども VisemeNet は出力できません(eye blink については適当にランダムで生成でもよさそうですが)

とりあえず jSync がどんなものか試したいときは, 評価版を使ったり, VisemeNet を動かしてみるといいでしょう.
VisemeNet を試したい場合, 推論だけする VisemeNet-infer を作りましたのでこちらを使うとよいでしょう: https://github.com/lighttransport/VisemeNet-infer

ちなみに, jSync は, ドキュメントには記載が無いのですが, ネットワーク認証をしていて, ネットに繋がっていないと Maya がクラッシュするので注意ください(2 週間くらいこれでハマった)

## jAmbient

筆者がライセンスを調達したときにはありませんでした.
ambient motion を音声データからよろしく設定するものでしょう.
(一応秋くらいにアップデートで ambient motion 対応すると連絡がありましたが, 今の所まだ連絡はありません) 

たとえば音声データからそれっぽい首の動きをするとか, ambient gaze motion とか.
(eye blink や眼球運動(サッカード)などは, 現状の jSync でそこそこ出すことができます)

## jRig

jSync の出すデータは, 基本 jRig と連動しています,

この手の出始めのツールにあるあるですが, 基本ドキュメントも説明動画もほぼありません. サポートも問い合わせてもまともに返事が無いので, 自分でいろいろ手探りで使い方を調べる必要があるため, どのパラメータがどのような動きをするのかを知るリファレンスとして jRig は必要になるので, 基本 jRig も必須です.

中身的には Viseme, FACS, jaw/lip のボーンのパラメータのブレンドをする Maya カスタムノード(dll)です. Viseme/FACS(表情)は, skinning と blendshapes で実現しています.


それぞれのパラメータのブレンドを Maya の標準ノードで構築すると膨大になるので, 一つの native dll にして対応しています(input/output が 200 個くらいある, 1 個のノードになっている!). 残念ながらソースコードは公開していないようなので, 基本的にはキャラクタ rig は jRig node を含んだ形にして作ることになるでしょう.

## Viseme 形状の制作

jSync は各 Viseme(Jaw/Lip + Tongue)のパラメータを出してくれるだけなので, 動かしたいキャラクターが各 Viseme でどのような口の形になるかは自身で設定(モデリング, リギング)しなくてはなりません.

https://developer.oculus.com/documentation/audiosdk/latest/concepts/audio-ovrlipsync-viseme-reference/

や, JALI, VisemeNet の論文, Phoneme -> Viseme mapping などでググって調べる必要があります.
(youtube 英会話発音動画とか参考になるかも)

もしくは IPA(Internal Phonetic Alphabet, https://en.wikipedia.org/wiki/International_Phonetic_Alphabet )を参考にして, 実際にアクターに発音してもらい, パフォーマンスキャプチャ -> 3D 復元して生成するという手もあります.

ただし, IPA は英語用なので, 日本語など他の言語では調整が必要. 日本語は母音ベースなので, 英語に比べれば viseme パターンは少なめと思われますが,

https://docs.aws.amazon.com/ja_jp/polly/latest/dg/ph-table-japanese.html

音素の組み合わせの動きなどもきちんと考えようとすると, 英語よりは難しくなってくるかも...?

ところで, Amazon Polly のドキュメントは専門的で参考になりますね.

## TODO

* [ ] TTS であれば Tacotron などを使ってアラインメントを計算して jSync に渡す(MFA は今回のような speech animation 用に使うには使いづらい)
Django フォームセットでPOSTでの取得の仕方がわからない。

![11111111111111111111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433444/7bbb0a55-56af-ac4e-d7f0-23c8fee6d3f2.png)


```python:form.py
class 案内Form(forms.Form):    
    会社別=forms.CharField(required=False,max_length=3,widget=forms.TextInput(attrs={'class': "form-control"}))
```
```python:views.py
class 案内View(TemplateView):  
    def __init__(self):
        案内FormSet=formset_factory(案内Form,extra=6)
        #buf=フォーム初期値入力
        buf={'会社別':1,'会社別':2,'会社別':3,'会社別':4,･･･}
        formset =案内FormSet(initial=buf)
        self.params = {
            'guide':formset,                       
        }
    def post(self, request):           
        formset = 案内FormSet(request.POST)
        #print(formset)でエラーが出る。
        print(formset)        
        return render(request, 'jw/guide.html', self.params)
```

```html:guide.html
 <tbody>
・・・・・省略・・・・ 
<tr>
  <td>1</td>
  <td><input type="text" name="form-0-会社別" value="1" class="form-control" maxlength="3" id="id_form-0-会社別"></td>
  <td>
    <ruby>
      <rb>十九</rb>
      <rt>ジュウク</rt>
      　<rb>太郎</rb>
      <rt>タロウ</rt>
    </ruby>
  </td>
  <td>10/04</td>
  <td>新規</td>
  <td>SN-1F</td>
  <td>提出物</td>
  <td>入金</td>
  <td></td>
  <td>株式会社ジューク</td>
</tr>
<tr>
  <td>2</td>
  <td><input type="text" name="form-1-会社別" value="2" class="form-control" maxlength="3" id="id_form-1-会社別"></td>
  <td>
    <ruby>
      <rb>山崎</rb>
      <rt>ヤマサキ</rt>
      　<rb>太郎</rb>
      <rt>タロウ</rt>
    </ruby>
  </td>
  <td>10/04</td>
  <td>新規</td>
  <td>SN-1F</td>
  <td>提出物</td>
  <td>入金</td>
  <td></td>
  <td>株式会社ヤマダ</td>
</tr>
・・・・・省略・・・・              
</tbody>
Element UI (Vue Component Library) の導入

# はじめに
フロント : Vue
バック : Laravel
で開発をしていた際に、楽にUI作れないかなーと思い探した結果見つけた

- Element UI

を導入してみます。

# インストール
[公式ドキュメント](https://element.eleme.io/#/en-US/component/quickstart)
npm でインストールします。

> `npm i element-ui -S`

[npm installの-Sオプションについて](https://qiita.com/havveFn/items/c5beda8572aa8c1e6be6)
上記にもある通り、「-S」は必要ないかもしれないですが、私は公式通りに導入しました。

# app.jsに追記
公式ドキュメントの通りに下記を追記

```js:app.js
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';

Vue.use(ElementUI);

new Vue({
  el: '#app',
  render: h => h(App)
});
```

# 終わりに
上記手順が終われば、あとは公式ドキュメントにあるようなボタン、ラジオボタン、チェックボックスが使えるようになります。超便利で手軽！！

# 関連記事
[【Element UI】Component Sample](https://qiita.com/coffee_penguin/items/e7527f4e7d1757e81959)
【Node.js（Express4）】POSTデータの受け取り

# はじめに
``Express4.16``以降からPOSTデータの受け取りに``body-parser``をわざわざ使わなくてもよくなったらしい。
本記事では、フォームからのPOSTデータの送信を想定している。

## ``body-parser``使う版
```:command
$ npm install body-parser --save
```

```js:index.js
var express = require('express');
var bodyParser = require('body-parser');
var app = express();

app.use(bodyParser.urlencoded({ extended: false }));

app.post('/', function (req, res) {} =>{
  res.json({
    msg: 'Hello World!',
    data: req.body
  });
});
```

## Express4.16以降のやつ
```js:index.js
var express = require('express');
var app = express();

app.use(express.urlencoded({extended: true}));

app.post('/', function (req, res) {
  res.json({
    msg: 'Hello',
    data: req.body
  })
})
```

## 参考サイト
* https://www.npmjs.com/package/body-parser
    * body-parserのほう
* https://expressjs.com/ja/api.html#req
    * 上記じゃないほう
コンテナとKubernetesとEKSの概要を理解する

## はじめに
最近コンテナ技術に興味があっていろいろ調べてみたので、
自分なりに理解したコンテナ、Kubernetes、EKSの概要を紹介してみます。

自分の理解が違うようであればご指摘いただけると嬉しいです。

## コンテナ技術とは
- OS上に他のプロセスからは隔離されたアプリケーション実行環境を構築する技術のこと
- 仮想的な動作環境をより少ないコンピュータリソースで実現する
- VMは仮想環境ごとに異なるOSの上でアプリを動かすが、コンテナはOSを共有し、その上に空間を区切ってアプリを動かす
![vm_container.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251142/1c86365a-b3ea-b9d8-fb83-d03c4ff1d9f0.jpeg)


- コンテナのデファクトスタンダードは[Docker](https://www.docker.com/)

<img width=40% alt="docker.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251142/2a199428-9604-129b-2a2b-a6aaacacd7ee.png">

## コンテナ技術のメリット
- コンテナイメージを作成することで環境のパッケージ化ができる
    - どんな場所でも同じように動かせる
- 起動が高速である
    - ゲストOSの起動が必要ないため
- アプリケーションのデリバリ方法が簡単かつ統一されている
    - docker push/pull/run等のコマンド
- メモリ消費が抑えられる

⇨ **同一の環境を高速にたくさん起動できるので、スケールがしやすい**

## Kubernetesとは
- コンテナはスケールがしやすい≒コンテナの管理が難しい…  
⇨コンテナの管理を便利にしてくれるのがKubernetes
- コンテナを動かすマシンにあるエージェント(kubelet)とAPIサーバ(マスターコンポーネント)が通信をすることで、コンテナに対して様々な操作をすることができる
- いろんなことができるよ
    - ホストの管理
    - コンテナの起動/停止のスケジューリング
    - コンテナの死活監視
    - 自動修復
    - 負荷分散
    - アプリケーション設定の管理  
    などなど

<img alt="Kubernetes.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251142/508adb2a-9664-5392-2614-b62458968aef.jpeg">

## EKSとは
- Kubernetes環境で実行されているアプリケーションをAWS上で動かすためのマネージドサービス
- KubernetesをAWSで使いたいときのためのサービス
- コンテナが稼働するためのマシン（データプレーン）はEC2を使用する

<img width=30% alt="Amazon-Elastic-Container-Service-for-Kubernetes@4x.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251142/a68b738e-5273-fd4e-bad4-3d643a42e79e.png">


## EKSとEC2の関係性
- EKS⇨コンテナの管理をする場所
- EC2⇨実際にコンテナが稼働する場所
![EKSとEC2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251142/fdaedec9-5650-2a6a-db54-d6dc708870a3.jpeg)

## ECR
- コンテナのイメージを管理するリポジトリ
- Dockerfileをビルドして作成したイメージをECRにプッシュし、そのイメージをもとにEKSでコンテナを実行する
- パブリック公開はできない
![流れ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251142/a523ccdc-b887-3288-efa4-731cfc9126f3.jpeg)


## 参考資料
- [AWS公式ドキュメント](https://docs.aws.amazon.com/index.html?nc2=h_ql_doc)
- [Googleのコンテナ](https://cloud.google.com/containers/?hl=ja)
- [「それコンテナにする意味あんの？」迷える子羊に捧げるコンテナ環境徹底比較](https://dev.classmethod.jp/cloud/aws/cmdevio2019-container/)
- [Kubernetes: 構成コンポーネント一覧](https://qiita.com/tkusumi/items/c2a92cd52bfdb9edd613#kubelet)

## より詳しく知るには
[AWSオンラインカンファレンス](https://aws.amazon.com/jp/about-aws/events/aws-innovate/)の「[はじめてのコンテナワークロード](https://aws.amazon.com/jp/about-aws/events/aws-innovate/sessions/#container)」というセッションがおすすめです！
コンテナオーケストレーションの仕組みについてわかりやすく解説されています。
勉強ログ_day2_MySQL入門①

# はじめに
非エンジニアの勉強ログ。
**超初心者プレイ**のため、内容は自分の勉強メモです。

### 今日のゴール
- MySQLとやらに触ってみる

### 環境
- ホストOS：Windows10 Pro 1903
- [こちら](https://qiita.com/kantan/items/099e2c3ed700f1781df8)で構築した環境を利用する
- MySQL:

### 参考資料・引用元など
- ドットインストール：[MySQL入門](https://dotinstall.com/lessons/basic_mysql_v3 "MySQL入門")
- Qiita：[【新人教育 資料】SQLへの道 〜DB編〜](https://qiita.com/devopsCoordinator/items/9b70e506150888e190be)
- Qiita：[よく使うMySQLコマンド集](https://qiita.com/CyberMergina/items/f889519e6be19c46f5f4)
- わわわIT用語辞典：[DBサーバ](https://wa3.i-3-i.info/word14407.html)
- [MySQLサーバを動かす](https://www.yokoweb.net/2018/05/13/ubuntu-18_04-server-mysql/)

# データベースについて
- データを格納するために用意したサーバ
- 今回はRDBを学ぶ。リレーショナルデータベース
    - 行：レコード
    - 列：フィールド／カラム
- データベースの中身を扱う言語を「SQL（エスキューエル）」と言う
- 取り扱うデータベースの種類によって若干言語の書き方がかわる。今回は「MySQL」
    - 行のうしろがセミコロン「;」で終わる。忘れないように注意
    - 大文字小文字が区別されない

# MySQLサーバに接続する
- 作成済みの開発環境でMySQLサーバが動いていた　なぜだ　わからん（sudo service mysqld status　で確認した）
    - 確認したら、ドットインストールの途中でパッケージで色々入れていた
- MySQLサーバへの接続終了：\q

# MySQLをコマンドでいじる
### データベース一覧の表示
```ruby:mysql-shell
mysql > show databases;
```
### データベースの作成
```ruby:mysql-shell
mysql > create database testdb01;
```
### データベースの削除　！！！危険な作業だから、間違えないよう注意！！！　
```ruby:mysql-shell
mysql > drop database testdb01;
```


# あとがき
- Qiitaで下書きが出来ることに気づいたので、昨日フォーマット作って保存した
- GUIでしかデータベース見たことなかった。CUIで見るとこんな感じなんだね
とりあえずの最低限Gitコマンド

#コマンドで扱う
プログラミングを初めてから、ずっと**GitHubDesktop**を利用していた。
しかし現場に入ってから、コマンドでGitを扱うことが増えたため、使用する頻度が高いと感じるコマンドを備忘録として書いておく。

#コマンド一覧
```
//ファイルの登録
$ git add <ファイル名>
```
```
//ファイルの変更、追加をコミット
$ git commit -m "コミットメッセージ"
```
```
//ローカルの変更を確認
$ git status
```
```
//コミットの変更履歴を確認する
$ git status
```
```
//リモートにプッシュ
$ git push origin <ブランチ名>
```
```
//ブランチをマージ
$ git merge <ブランチ名>
```
```
//ブランチの移動
$ git checkout <ブランチ名>
```
```
//作業内容を一時避難
$ git stash
```
```
//一時避難させた内容を一覧表示
$ git stash list
```
```
//一時避難させた内容を復活させる
$ git stash apply <stash名>
```
【64日目】echo true ? 1 : false ? 2 : 0;　正しく計算できますか？　ーPHPの結合規則と優先順位について

突然ですがPHP駆け出しエンジニアのみなさま！
タイトルの問題、正しく計算できるでしょうか？
私は初見は引っかかってしまいました。

答えは「２」です。

正しく計算できた方、なぜそうなるかきちんと説明できますか？

この記事を読んで、明日からは「演算子」について自信をもってコードを書けるようになりましょう！

# 1　演算子
## 1.1 演算子とは
演算子とは「値に対して行ってなにがしか別の値を生み出すような操作」のことです。
簡単に言えば、値を変化させるような操作すべてを表します。
PHPでは単項、二項、三項演算子が扱われ、タイトルの問題は三項演算子が「ネスト（入れ子）」になっているものです。

## 1.2　演算子の種類と優先順位
ここでは演算子の詳細な解説は省きます。知らないものがあった場合はグーグル先生に聞いてください。
演算子には、種類によって結合法則と優先順位が異なります。
それぞれの語句の意味を説明したうえで、結合法則と優先順位をまとめたマトリクスを提示します。

### 1.2.1 結合法則
結合法則とは、２つの値を演算子を用いて演算する際に、右辺と左辺どちらから評価されるのかを決める法則である。
結合法則には左結合と右結合と、結合しないものとに分類される。
特に、PHPの場合、他の言語と異なり三項演算が左結合となることに留意が必要である。

PHPでは多数派は左結合となるので、右結合と結合しない例のみを列挙しておく。

#### 1.2.1.1　右結合の演算子の一覧

- (int)など、＠　キャスト、エラー制御演算子
- ！　論理演算子
- =, +=, -=, *=, /=, .=, %=, &=, |=, ^=, <<=, >>=, =>　代入演算子

#### 1.2.1.2　結合なしの演算子の一覧

- new, clone オブジェクトの生成、複製
- ++, --　加算子、減算子
- instanceof　型
- <, <=, >, >=, <>　比較演算子
- ==, !=, ===, !==　比較演算子

### 1.2.2 優先順位
演算子の優先順位とは、複数の演算子が連続した場合に、どの演算子から先に評価していくかを定めたルールである。
例えばイメージしやすいものであれば、同じ代数演算子でも*と/は+や-よりも優先順位が高い。
いくつもの演算子が用いられる場合や、ネストで式を記述する際には、わかりやすくするために()を明示的に用いて優先順位を示すのも良い。

例えば

```
2 * 3 + 5
```

であれば

```
((2 * 3) + 5)
```

のような意味です。

## 1.3 演算子の結合法則と優先順位の表
上から順に優先順位が高く評価される演算子となります。

| 結合法則| 演算子 | 説明 |
|:-:|:-:|:-:|
| 結合しない  | new, clone  | オブジェクトの生成、複製  |
| 右結合  | [  | 配列のブラケット  |
| 結合しない | ++, --  | 加算子、減算子 |
| 右結合  | ~, -, (int)など, @  | キャスト、エラー制御演算子  |
|  結合しない  |  instanceof | 型  |
| 右結合  | !  | 論理演算子  |
| 左結合 | *, /, %  | 代数演算子  |
| 左結合  | +, -, .  | 代数演算子、文字列演算子  |
| 左結合  | <<, >> | ビット演算子  |
| 結合しない  |  <, <=, >, >=, <> |  比較演算子 |
| 結合しない  | ==, !==, ===, !==  | 比較演算子  |
|  左結合 | &  | ビット演算子、　参照  |
|　左結合  | ^  | ビット演算子　|
| 左結合  | || ビット演算子  |
| 左結合  |＆＆ |  ビット演識 |
| 左結合　| ｜｜  | 論理演算子  |
| 左結合  | ?, :  | 三項演算子
|  右結合 | =, +=, -=, *=, /=, .=, %=, &=, ｜=, ^=, <<=, >>=, |  代入演算子 |
|  左結合 | and  |論理演算子  |
|  左結合 | xor  |論理演算子 |
|  左結合 | or  | 論理演算子 |
|  左結合 | . |   |

こう見ると、同じ種類の演算子の間でも優先順位がつけられていることわかりますね。


# 2 タイトルの問題の解説
タイトルの問題を再掲します。

```
echo true ? 1 : false ? 2 : 0;
```

起きがちな間違いは、単純に左から進めて言って「１」と答えることです。


この問題は、結合法則のみで解くことができます。
結合法則の評に基づき評価される順に（）を付けて書き直すと

```
echo ②(  ①( true ? 1 : false? ) ? 2 : 0);
```

となります。
まず、三項演算は左結合のため、演算子？、:の左から評価します。

最初①部の処理です。
？の左にあるtrueが評価され、真です。
次に真の場合は:の左側である１を評価し、１となります。

ここまで評価した段階で①括弧内が整理され、この式は

```
echo ②( ①(1) ? 2 : 0);
```

と表すことができると思います。
すると、②の挙動とは、
「三項演算子「？」の前にある①（１）を評価し、真ならば２を、偽ならば０」を表示することとなります。
本問では、（１）は真なので、答えは２となります


このように括弧を表示するとネスト構造の演算子はみやすくなります。
思わぬエラーを引き起こさないように気をつけていきましょう！
PHP

```php5:php

<html>
<body>

<form action='test.php' method='get'>
  <input type='text' name='txt1'>
  <?php 
    if (isset($_GET['txt1'])) {
      echo  $_GET['txt1'];
    }
  ?>
  
  <br/>

  <input type='text' name='txt2'>
  
  <?php 
    if (isset($_GET['txt2'])) {
      echo  $_GET['txt2'];
    }
  ?>
  <br/>
  <input type='submit'>
</form>

<hr/>

<form action='test.php' method='post'>
  <input type='text' name='txt3'>
  <?php 
    if (isset($_POST['txt3'])) {
      echo $_POST['txt3'];
    }
  ?>
  <br/>
  <input type='submit'>
</form>


<?php

$items = [['name' => '吉田', 'age' => 20, 'genderId' => 0], ['name' => '田中', 'age' => 30, 'genderId' => 1]];
$gender = [0 => '男', 1 => '女'];

$tbl = '<table border=1>';
foreach ($items as $i => $val) {
  $tbl .= '<tr><td>' . $val['name'] . '</td><td>' . $val['age'] . '</td><td>' . $gender[$val['genderId']] . '</td></tr>';
}
$tbl .= '</table>';
echo $tbl;

// $html = file_get_contents('https://stocks.finance.yahoo.co.jp/stocks/history/?code=USDJPY=X');
// echo $html;
// var_dump($items);

?>

</body>
</html>
```
AWSで、パブリックサブネットに作成したインスタンスのIPを取得する




作業用に使えそうだったのでメモ
AWSで、パブリックサブネットに作成したインスタンスに、ElasticIPアドレスを割り当てていないと、
再起動の際に毎回違うパブリックIPが割り当てられるので、取得が面倒ですよね。。
ElasticIPアドレスを割り当てていない作業用のssh踏み台サーバーへ楽にssh出来る方法を考えてみました

インスタンスを起動したタイミングで以下のシェルを実行すると、
楽にsshできるようになります

```shell:実行方法
./getPublicIpAddress.sh
ssh test_server1
```

```shell:getPublicIpAddress.sh
#!/bin/bash
ip=$(aws ec2 describe-instances --filter "Name=tag:Name,Values=test_server1" | jq '.Reservations[].Instances[].PublicIpAddress' )
echo $ip
sed  -i -e  "/test_server1$/s/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}/${ip//\"/}/" /etc/hosts
```

\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}：IPアドレス変換用の正規表現
${ip//\"/}：変数をパラメータ展開して、変数ipについている”を除外

```shell:/etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
0.0.0.0 test_server1
```

シェル実行によって「0.0.0.0 (ネームタグの名前)」の部分が置き換わります
停止時に実行するとnullが入ってしまうので、起動時に実行します

```shell:/etc/ssh/ssh_config
Host test_server1
 User ec2-user
 IdentityFile /(鍵の場所)/my-keypair.pem
```

ローカル環境：CentOS7
firelensを使用した、ログ分割と監視処理


**■１〜３回の内容を再設計した記事を書きました。**
[ FireLens/fluentbit構成の見直しと改修] (https://qiita.com/antennix/items/ebad3bcb33cbd168923d)


## はじめに
ここ最近、FireLensの機能選定を行っており
fluentbitのカスタムイメージを作成し、FireLensに接続するまでの機能調査を行いました。
１回目の記事です。

[２回目](https://qiita.com/antennix/items/496cf08199253dc1e6cb) ローカルで、datadog/S3へデータを転送できるdockerイメージを作成する

[３回目](https://qiita.com/antennix/items/d6d19be67dff43ab34e8) Firelensで、datadog/S3へデータを転送できるdockerイメージを作成する

### FireLens実装サンプル
https://github.com/antennix/firelens

## 概要
VPC内で稼働しているwebアプリケーションのEC2インスタンスを、fargate化したいという話がありました。
改修に伴い、fargateコンテナをステートレスにする為、ログの管理方法が話題に上がりました。

また、監視業務を内製化したいという要望もあった為、ログの検知システムも検討しました。

## 構成図
- A:アクセスログ、B:エラーログ、C:アプリケーションログの三種類をS3に保存します。
- B,Cのみログ監視を行い、特定の要件を満たした場合、slackにアラートを発報します。
- 突然のコンテナの破棄に対して、ログが失われないように設計します（ステートレス）

![開発構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477542/77087867-4a2a-911b-2eeb-0f60bc24d2b7.png)



## 検討した内容
Firelens,FluentBit,datadogを組み合わせて検討する事になりました。

### FireLens
**FireLensは、ECSのコンテナの標準出力を、fluentd/fluentbitにお手軽に転送できる機能です。**

- 簡単な転送なら、JSONの設定だけで、自動でfluentdのコンテナを起動し、転送してくれます。
- 複雑な設定も、専用の設定ファイルを作成すれば可能です。
- 標準の追加プラグインを使いたい場合は、カスタムしたfluentd/fluentbitのコンテナを作成すると、可能です。

https://docs.aws.amazon.com/en_us/AmazonECS/latest/userguide/using_firelens.html#firelens-using-fluentbit


### Fluent Bit
Firelensの記事は、Amazon Kinesis Data Firehoseや、Amazon CloudWatch Logsとの
連携記事が多く見られますが、
bigqueryやazure等、組み込みoutput pluginへの出力も可能です。

**Amazon / aws-for-fluent-bit (fluentbit v1.3.2)**
https://hub.docker.com/r/amazon/aws-for-fluent-bit/tags
**fluentbit output plugin**
https://docs.fluentbit.io/manual/output
v1.2.0からサポートされている、datadogを使用する事にしました。

なお、fluentdでも同様の機能は実装可能ですが
コンテナ費用の事を考え、軽量なfluentbitを選択しました。

### datadog
https://app.datadoghq.com
クラウド監視ツールですが、機能の一つとしてログ監視機能(datadog logs)があります。
元々使用経験もあり、ログの整形機能（pipeline）や、リアルタイムアラート機能
S3へのアップロード機能もあり、要件を満たせそうでした。

### S3へのアップロード
datadogにはS3へのアップロード機能があり、ログを全種まとめてdatadogで管理する案もありましたが
アクセスログのレコード数が非常に多く、datadogを経由すると膨大なコストが掛かる可能性があり
アクセスログだけはdatadogの監視を通さず、fluentbitからs3に直接アップロードすることにしました。

実現可能なプラグインは存在しましたが、標準のfluentbitコンテナには搭載されていないので
カスタムのfluentbitのコンテナを作成する必要が出てきました。
https://github.com/cosmo0920/fluent-bit-go-s3

## 実装手順
- ローカルで、datadog/s3へデータを転送できるdockerイメージを作成する
- 作成したdockerイメージを元に、firelensで動作するように調整する

あと２回ほど記事を書いてまとめようと思うので、時間が出来次第更新致します。
Slackにpythonからメッセージを送信する

# 概要
slackのapiをたたいてslackにpythonからメッセージを送信する。

# やること
- [1. slackのワークスペースを作成](#1-slackのワークスペースを作成)
- [2. slack-appを作成](#2-slack-appを作成)
- [3. Slack Appをチャネルに追加する](#3-Slack-Appをチャネルに追加する)
- [4. python-apiを実装](#4-python-apiを実装)

#1. slackのワークスペースを作成

#2. slack-appを作成
参考 ([Slack API 推奨Tokenについて] (https://qiita.com/ykhirao/items/3b19ee6a1458cfb4ba21))
##2-1. [Slack api](https://api.slack.com/apps)にアクセスする。
##2-2. install your app to your workspace
名前などを決めてappを作成する。
##2-3. 権限の追加
OAuth PermissionsのScopesで以下の権限を追加する。
- chat:write ~~:user~~ (Send messages on the user’s behalf)
##2-4. token取得
install Appの
「Bot User OAuth Access Token」を使用(botの発言)。
「OAuth Access Token」を使用すると個人の発言になる。

#3. Slack Appをチャネルに追加する
1. SlackからAppを選択
- その他 --> チャネルにこのアプリを連携させる --> チャネルを選択


#4. python-apiを実装
```python
import requests


class SlackDriver:

    def __init__(self, _token):
        self._token = _token  # api_token
        self._headers = {'Content-Type': 'application/json'}

    def send_message(self, message, channel):
        params = {"token": self._token, "channel": channel, "text": message}

        r = requests.post('https://slack.com/api/chat.postMessage',
                          headers=self._headers,
                          params=params)
        print("return ", r.json())


if __name__ == '__main__':
    token = ''  # TODO your token.
    slack = SlackDriver(token)
    slack.send_message("Hello World! from python", "#random")
```
tokenをセットする。  
必要に応じてチャネル名、メッセージを変更する


## 参考
- [必要な Slack API はどれ？](https://api.slack.com/lang/ja-jp/which-api)
- [Slack API 推奨Tokenについて](https://qiita.com/ykhirao/items/3b19ee6a1458cfb4ba21)
- [chat.postMessage api](https://api.slack.com/methods/chat.postMessage) (機能を追加するならよく読む)
- [Slack api](https://api.slack.com/apps)
- [https://github.com/st34-satoshi/slack-api](https://github.com/st34-satoshi/slack-api)

## 終わりに
[python-slackclient](https://github.com/slackapi/python-slackclient) というとても便利なライブラリがあるが、うまく使えなかった。sslがおかしいとか言われる...

### これから
~~slackからのメッセージを受信できるようにしたい~~
[SlackからPythonサーバーにメッセージを送信する](https://qiita.com/stu345/items/030dbfca8363583d24ad)
【Java】src/main/resourcesにあるファイルを読み込む

Javaで`src/main/resources`にあるファイルを読み込むのに少し手間取ったので備忘録です。

# 1. ルートからの絶対パスで取得

```src/main/resources/sample1.txt
sample1
```

```src/main/java/Foo.java
public void sample1() {
    String path = "src/main/resources/sample1.txt";
    try (BufferedReader br = Files.newBufferedReader(Paths.get(path))) {

        System.out.println(br.readLine());

    } catch (IOException e) {
        e.printStackTrace();
    }
}
```

```:実行結果
sample1
```

# 2.  クラスパスからの相対パスで取得

```src/main/resources/sample2.txt
sample2
```

```src/main/java/Foo.java
public void sample2() {
    String path = "/sample2.txt";
    // staticメソッドの場合はFoo.class.getResourceAsStreamのように書く(Fooはクラス名)
    try (InputStream is = getClass().getResourceAsStream(path);
        BufferedReader br = new BufferedReader(new InputStreamReader(is))) {

        System.out.println(br.readLine());

    } catch (IOException e) {
        e.printStackTrace();
    }
}
```

```:実行結果
sample2
```

# 注意点
1.と2.では、テストの際、`src/test/resources`に同名ファイルが有るときの動きが異なります。

```src/test/resources/sample1.txt
test1
```

```src/test/resources/sample2.txt
test2
```

```src/test/java/FooTest.java
public class FooTest {
  @Test
  public void testInput() throws Exception {
    Foo foo = new Foo();
    foo.sample1();  // src/main/resources/sample1.txtを読み込む
    foo.sample2();  // src/test/resources/sample2.txtを読み込む
  }
}
```

```:実行結果
sample1
test2
```

1.の場合は、パスを直書きしているので当たり前ですが、`src/main/resources`ディレクトリ下の`sample1.txt`を読み込みます。
2.の場合は、`src/main/resources`に優先して`src/test/resources`ディレクトリ下の`sample2.txt`を読み込んでいます。

なお、`src/test/resources`ディレクトリに`sample2.txt`がなければ、そのまま`src/main/resources`ディレクトリ下の`sample2.txt`が読み込まれます。

# まとめ
とりあえず`Class#getResourceAsStream`を使っておけば良いかと。
何か問題があれば教えていただけると助かります。

参考:
[リソースの取得](http://blog.livedoor.jp/kotani08/archives/13190751.html)
[【Java】クラスパス上のファイルを取得する方法の違いについて](https://teratail.com/questions/15456)

# 余談
`Class#getResourceAsStream`ではなく、`Class#getResource`経由で絶対パスを取得し、`Paths#get`に渡したところ `java.nio.file.InvalidPathException`となりました。

```java
String filename= "/sample2.txt";
String filepath = getClass().getResource(filename).getPath();
Path path = Paths.get(filepath); // java.nio.file.InvalidPathException
```

どうもWindows環境ではドライブレター部分のエスケープが必要なようで、以下のように置換したところ取得できました。

```java
String filename= "/sample2.txt";
String filepath = getClass().getResource(filename).getPath();
Path path = Paths.get(filepath .replaceFirst("^/(.:/)", "$1")); // OK
```

参考: [create Java NIO ファイル・パスの問題](https://code-examples.net/ja/q/961118)


<br>
最後までお読み頂きありがとうございました｡
質問や不備についてはコメント欄か[Twitter](https://twitter.com/ka2_kamaboko)までお願いします。
DSP FMラジオ RDA5807FP+ATTINY85+AQM0802A その2 RDA5807FP編

#はじめに
* 電池駆動DSPラジオのその2。RDA5807FPについての記事です。
* RDA5807Mに関する過去記事が２つあるので参照願います。

#使用したもの
* RDA5807FP。Aliexpressで調達しましたが、Aitendoさんでも入手可能です。
* ピッチ変換基板：　Aitendoさんの[これ](http://http://www.aitendo.com/product/11260)を利用しました。取扱終了版の方です。
* 水晶：32.768KHzの水晶（円筒形）。CHIPの発振用。
* セラミックコンデンサ：0.1μF（パスコン、表面実装）、100pF（アンテナ用）
* データシート。検索してください。Aitendoさんの商品ページにもあります。

#DIP化
* ハーフピッチなのではんだ付けはそれほど難しくありません。
* pin10 と pin11 の間にパスコンをはんだ付けしています。これもそれほど難易度は高くないと思います。
![5807fp.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482773/87d39711-cc4a-a14e-1716-24fa003ccdff.jpeg)

#周辺部品
* データシートの参考回路を参照しています。
* 発振用の水晶を pin9 に接続。
* 外部アンテナとの間に100pFを挿入。

#GPIOピン
* 5807FPは、5807Mと大きな違いはないのですが、5807FPにはGPIOピンが3本あり、これらのピンを活用できます。ここでは、GPIO2(pin16)を利用して、周波数表示のトリガーとしてみます。
* [過去記事](https://qiita.com/dabodabo/items/ad3fe3ae8c8518156d23)でも触れましたが、SEEK機能で選局する場合、選局が終わってから情報を読みに行くべきなので、このGPIOピンを使って割込みで処理をすることにします。
* データシートを見ると（レジスタ設定をすれば）、選局が完了する（STC==1)と、GPIOピンがトリガ(a low interrupt) を出すことになっています。
* トリガを計測してみると、下の画像の通り、約5msのトリガが出ています。これをATTINY85側で受けて、割込み処理をしてみます。
![5807fp_gpio.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482773/974aff97-c9cf-ca82-5e98-8b48947cedcd.jpeg)

#GPIOピン用のレジスタ設定
* STCトリガのレジスタ設定ですが、以下の3か所を設定する必要があります。詳細はデータシート見てください。
    * 04Hのbit14 
    * 04Hのbit3:2
    * 05Hのbit15

#おまけ
* 本記事はここまで。回路図、コードなどは後日投稿します。
Cloud FunctionsからFirestoreの24時間以内のデータだけを取得する



これで取れました。

```java

// 現在の時間から24時間前を取得
      var agoDate = new Date();
      agoDate.setHours(agoDate.getHours() - 24);

      const timelineDataSnap: FirebaseFirestore.QuerySnapshot = await db
        .collection("timeline")
        .doc(doc.id)
        .collection("images")
        .where("created_at", ">", admin.firestore.Timestamp.fromDate(agoDate))
        .get();
```
N体計算コードについて(REBOUND,GADGETについての覚書)

#N体計算コードについて
N体計算コードとは天文学などにおいて質量をもつ粒子が複数ある場合においてそれらが重力の影響下でどのように運動するかを数値計算を用いて解くコードである.

太陽と地球のみの運動を考える時はお互いが互いの共重心の周りのみを運動することを考えればいいけれど三体以上(太陽月地球など)を考える時はお互いの重力の影響で解析的に解けなくなるらしいので計算機を用いて計算する.

ただ,自分で一からコードを書くのは大変なので先駆者の方々が作ったコードを使うことが多い.ただその説明が軒並み英語で見づらいのでここにまとめていく.英語が読める人はリンクから直接飛んだ方がいいです.

このページでは

1.REBOUND
2.GADGET-2
に関して,もしくは天文計算についての覚書を書き込んでいく.ほかにもたくさんコードがあるので随時書き込んでいきます.先人たちが偉大なコードをたくさん作ってくれたのにしょぼい説明しかできないことをお詫びします.
こんなコードもあるよってのがありましたら教えていただけるとありがたいです.


###REBOUND
[REBOUND](https://rebound.readthedocs.io/)はデブにはきつい名前の計算コード
わかりやすく見やすいホームページだからか使ってみたくなる.


以下はトップページにある特徴をまとめる.

-シンプレクティック積分を保証(エネルギー保存を考慮して計算してくれる.されなきゃ困る)
　　　　-時間刻みを短くしたら高精度な非シンプレクティック積分をしてくれるらしい
-衝突及びGranular dynamics(粉体力学?)をサポート
　　　　-SPH(Smoothed Particle Hydrodynamics)計算とかもできるのか???
-C言語(C99に基づく)で作られているがPython版もある
-Real-time,3D OpenGLによる視覚化が可能.
-OpenMP及びMPIを用いた並列化が可能
-ライブラリを必要とせず,オープンソースで開発されている.コードは[Githubのページ](http://github.com/hannorein/rebound)で公開中
　　　　-設定が簡単なことをアピールしているらしい.
-ほかのモジュールも簡単に計算に入れられるよ.

とのこと.

###GADGET-2
[GADGET-2](https://wwwmpa.mpa-garching.mpg.de/gadget/)はいろいろいじってみたくなる名前をしている.
N体計算及びSPH計算ができることをアピールしている.
並列化されたパソコン上でたくさん動かせるらしい.スーパーコンピューターで動くってアピールされているけれどあんまり一般人はスパコンを持たない(一応PCでも動くってさ). hierarchical tree algorithmとSPH法を組み合わせる.

以下にまた特徴を列挙.
-重力の影響を考えるためにHierarchical multipole expansionを用いる.
-追加TreePM法(短距離ではTree法を用い,長距離間ではFFTに基づくParticle Mesh法を用いるもの)で計算する.PM法の二層目では高解像度の領域に置き換えられる
    -つまり僕はメッシュ法が何かを知らなければいけない.
-SPH法で計算できるよ!
-モナハンの提案した,人工の速度に基づく特徴速度(Signal-Velocity)によるパラメタ化ができるらしい.
    -モナハンだれ
-長距離間粒子と短距離間粒子で異なるタイムステップによる計算ができる.
-parallel I/Oに対応していろんなフォーマットで出力できる
-MPIに対応

とかいろいろあるみたいです.
CentOS7 isoファイルダウンロード

#はじめに
この記事はLinuxに初めて触れる方に向けた記事です。
Linuxの勉強を始める方、会社でLPIC取得を推奨されている方を対象としています。

#CentOSとは
端的に言ってしまえば無料のLinuxだと思ってもらえれば大丈夫です。
とりあえずLinuxを触ってみたいという方には最適です。

#CentOSのダウンロード方法
今回はCentOS7のisoファイルをダウンロードします。

１．以下にブラウザでアクセスします。
https://www.centos.org/download/
![pic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238625/e5777a10-1c5d-28e9-fc25-2387f089ed24.png)

２．画面下部にあるOlder Versionsの「then click here」をクリックします。
![pic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238625/1e9ae7c3-3000-8067-bd59-389317b5f6ff.png)

３．CentOS Linux Version 7 のCD and DVD ISO Images列に「mirrors」という名前のリンクがあるのでクリックします。
![pic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238625/715fa4a8-5be6-2ebf-d7da-98d4c55702af.png)

４．ISOイメージ入手先を選択します。今回は理化学研究所のISOイメージを利用します。
![pic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238625/7a76dc37-6880-5935-03b6-9551af7d6454.png)

５．.isoのリンクをクリックすれば、isoファイルをダウンロードできます。何をダウンロードしたら良いかわからない方は「Minimal」の記載があるisoファイルをダウンロードすれば大丈夫です。
![pic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238625/b760dcd7-563c-aba5-8ed8-5c7a2b4bb60d.png)

#最後に
ダウンロードしたisoファイルはDVD、USB等に焼いて使用します。仮想サーバの構築であればISOファイルはそのまま使用することができます。
#PowerApps Tips ~コントロールを画面外に配置する

#はじめに
PowerApps、特にキャンバスアプリのよいところ(の一つ)は、ドラッグ＆ドロップで各種コントロール(アプリの構成要素・パーツ)を自由に配置して、簡単に画面を作成し、データをコネクターによってつなげることができることです。
しかし、パーツのレイアウトや形状の細かな変形(おもに回転や歪み)には、いつも使っているPowerPointなどと比べて融通がきかないところがあります。
今回は、このような少しの制約を緩和するTIPSを紹介します。

#パーツはどこまで動かせるか
基本的にはコントロールは画面(Screen)内に収める必要があります。実際、ドラッグ＆ドロップでコントロールを移動できる範囲や、XY座標、幅・高さの直接指定では画面内に収まるように制限されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/d6d93755-9da0-b3ec-3b65-b5ffaded84cd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/fa626bbe-5054-f743-901e-803df1cf3bc7.png)

**ということで、画面の中にしかコントロールは配置できません！**　基本的には。

#画面外に配置する/はみ出させるためには

回避方法はあります。それが **「"0"を入れる」/「数式で表す」**という方法です。
最初の例では、円のX座標(左上の角)を-10と指定したところ、書き戻されてしまいました。
これを、 ``` Circle1.X : 0-10```と指定するだけで、画面外に飛びさせることができます。
また、幅も同様に、画面の横幅が640だったとしても、```Circle1.Width :  0+800``` と指定することで、画面幅よりも広くできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/c788b3c3-a49b-fd3d-5b05-975071989729.png)
※図では簡便のために-100にしています。

画面だけでなく、この方法はコンテナーやコンポーネントにも有効です。

#利用例1
簡単な利用例を見ていきます。

まずはスクロール可能なスクリーンにおいて、スクロールバーの部分だけを画面外に追い出してみます。
スクロール可能な画面は、Canvasという特殊なコントロールで構成されていますが、残念ながらこれにはスクロールバーを隠す設定が存在しません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/1267c7e4-8a56-94d4-ca1c-d776d5f5eeb4.png)

この場合には、CanvasのWidthの定義に+15をしてあげることで、スクロールバーを追い出すことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/306bf391-39e1-71b8-4f56-c2794ec64e25.png)


#利用例2
ほかの利用例として、画像の一部を画面に表示させることが可能です。
横に広い画像をスクリーンに配置して、部分的に利用したい場合、幅の制約があるので、下図のように残念な仕上がりになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/34499759-0fa1-9dec-b5f3-84b9554e66e1.png)
そこで、X座標を少し左(マイナス位置)に、幅をスクリーンよりも大きくとります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/7807b11e-1a6c-220e-45fa-330a51c9073f.png)

これによって、結果的に画像の一部をきりとって表示させることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/0afa207d-0504-29cb-5475-abceab2a470e.png)


#おわりに
このように、幅や座標を数式で指定することによって、ドラッグ＆ドロップでは実現できないようなレイアウトが可能になります。

皆さんもぜひ試してみてください。
Hidennotareの使い方(1) SheetCursorクラス

Hidennotare の紹介
https://qiita.com/RelaxTools/items/573b8ea1c1745bb73240

Hidennotare
https://github.com/RelaxTools/Hidennotare

Hidennotare Wiki
https://github.com/RelaxTools/Hidennotare/wiki

#SheetCursorの使い方

何回か分けてHidennotare の使い方を解説していきたいと思います。
以下のような表を読むクラス「SheetCursor」について解説します。
クラス名の通りでシートの表を読むときに使用します。

###Sheet1の内容

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69810/09985f11-647a-8b92-be5c-7183aee9efa8.png)

##ソースコード

```vb

    'ICursor インターフェースを使用する
    Dim IC As ICursor

    Set IC = SheetCursor.CreateObject(Sheet1, 3, "B")

    Do Until IC.Eof

        Debug.Print IC("C")
        Debug.Print IC("D")
        Debug.Print IC("E")

        IC.MoveNext
    Loop
```

##結果

```
A1
B1
C1
A2
B2
C2
A3
B3
C3
```
##解説

###コンストラクタ

コンストラクタの内容は以下のとおり。
**Sheet1**を読む。
**3行目**から**下**に向かって読む。
**B列**が空文字列("")になったら終了。表の途中で空文字列にならない**列**を指定する。

右に向かって読むことも可能です。詳しくはWikiへ。
https://github.com/RelaxTools/Hidennotare/wiki/SheetCursor

```vb
    Set IC = SheetCursor.CreateObject(Sheet1, 3, "B")
```

###EOFプロパティ

B列の内容が空文字列("")になった時に True になります。

```vb
    Do Until IC.Eof
```

###Itemプロパティ

省略可能です。現在の行のC列のRangeを返却します。"C"は文字列ですが、行番号も使用可能です。その場合には、3を指定してください。

```vb
    IC("C")

    IC.Item("C")

    IC.Item("C").Value

    IC.Item(3).Value

    どれも同じ結果になります。enum 等使う場合は列番号がよいですね。
    Range を返却するので以下のような書き方も可能です。

    IC.Item(3).Offset(0, 1).formula

```
###MoveNextメソッド

現在の行を次に移動します。

```vb
    IC.MoveNext
```

以上です。Excelでは一番良く使う機能ですね。おためしあれ。
EV3の動作確認（愛知県立名古屋高等技術専門校 組込みシステム科）

#準備
SDカードをPCにセット
フォーマットする
「sdcardフォルダ」を開いて「ev3rtフォルダ」と「uImsge」をSDカードにコピー

SDカードをEV3にセット
EV3の画面下中央の四角いボタンを押す
「EV3RT Console」と表示される

タッチセンサーを２に接続
カラーセンサーを３に接続
モーター２個をＢとＣに接続

EV3の画面下中央の四角いボタンを押す
「SD card」の表示の左に「＞」を確認

EV3の画面下中央の四角いボタンを押す
「app」の表示の左に「＞」を確認

EV3の画面下中央の四角いボタンを押す
ブザー音
LEDオレンジ点灯

EV3の画面のすぐ下左寄りのボタンを押す
「EV3RT Console」と表示される

カラーセンサーをコース紙の白い部分に当ててタッチセンサーを押す
カラーセンサーをコース紙の黒い部分に当ててタッチセンサーを押す

#モーターの回転を確認
カラーセンサーの当て方で回転が変わる

#終了
EV3の画面下右のボタンを押す
「Shutdown」と表示される
EV3の画面下中央の四角いボタンを押す
年末まで毎日webサイトを作り続ける大学生 〜5日目 ドラッグ&ドロップで簡単なゲームを作る〜

##はじめに
初めまして。
年末まで毎日webサイトを作っている者です。
今日はドラッグ$ドロップを使って簡単なゲームを作りました。
扱う技術レベルは低いですが、同じように悩んでる初心者の方を勇気付けられれば幸いです。
今日は5日目。(2019/10/23)
よろしくお願いします。

##サイトURL
https://sin2cos21.github.io/day5.html

##やったこと
3つの箱を用意して、それをドラッグ＆ドロップで右側に移動できるようにしました。
ドラッグした回数も表示しています。
レイアウトはこんな感じ↓

![スクリーンショット 2019-10-23 23.15.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516248/4fd08b5c-d36e-dfa5-f020-0d0456d4c0c2.png)

移動させた時にドロップできるポイントに入っていれば、ドロップ先の色が少し変わります↓

![test1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516248/d3e9e857-d9d1-bdfa-2540-c3cc1846984c.gif)


##こだわったところ
箱ごとドロップさせるのに苦労しました・・・。
終わってみたらシンプルな構造でしたが、今日はドラッグ&ドロップの基礎を学んだという感じです。
javascriptはこれだけです↓

```javascript

<script>
        function drag($event) {
            $event.dataTransfer.setData("Text", $event.target.id);
        };

        function drop($event) {
            var test = event.dataTransfer.getData("text");
            var test2 = document.getElementById(test);
            $event.currentTarget.appendChild(test2);
            $event.preventDefault();
        }

        var $count = 0;
        function count() {
            document.getElementById("count").innerHTML = ++$count;
        }

        function change() {
            document.getElementById("wrapper2").style.backgroundColor = "rgba(0, 0, 0, .1)";
        }

        function change2() {
            document.getElementById("wrapper2").style.backgroundColor = "transparent";
        }

    </script>
```

関数dragとdropで移動させています。
countで移動回数を数えています。
changeとchange2はドロップ可能状態になったらドロップ先の色を変えるために加えました。

##感想
やればやるほど分からないことが増えていきますが、それでも動くものを作れて発信できるのはいいですね。
まだ$eventやらdataTransferやらよく理解できていませんが、今後も作りつつ調べるスタイルで行こうと思います。
今週はドタバタしているので明日と明後日のサイト制作は苦労しそうですが頑張ります！

##参考
- ドラッグ＆ドロップイベント ≪ イベント ≪ DOM ≪ JavaScript（ジャバスクリプト）リファレンス(http://alphasis.info/javascript/dom/event/draganddrop/)
- HTML ドラッグ＆ドロップ API - Web API | MDN(https://developer.mozilla.org/ja/docs/Web/API/HTML_Drag_and_Drop_API)


上2つのサイトがとても分かりやすかったです。ありがとうございます。
EV3RT開発環境セットアップ（愛知県立名古屋高等技術専門校 組込みシステム科）

#開発環境のセットアップ
docker toolbox をインストール（最初だけ）
PCのＣドライブ直下にtmpフォルダを作成（最初だけ）
共有フォルダのzipファイルを解凍して「ev3rt」フォルダをそこにコピー（最初だけ）

「Docker Quickstart Terminal」を管理者権限で起動

Dockerのコマンドラインで「docker images」と打って
REPOSITORY ...
ev3rt_tools ...
ubuntu ...
の3行が出なければ（最初だけ）
$ cd /c/tmp/ev3rt
$ docker load -i ev3rt_tools.tar
処理が終わったら「docker images」と打って上の3行が出ればOK
$cd /c/tmp
でフォルダから出る
Windowsのエクスプローラーで「ev3rt」のフォルダを
/c/Users/自分のID/Documents
に移動
（ここまで最初だけ）

$ docker run -it --rm -v /c/Users/自分のID/Documents/ev3rt/:/ev3rt/ ev3rt_tools /bin/bash
Toppers開発環境のコンテナが起動したらコンテナのコマンドラインで
＃ ls
でev3rtの中身が見えればOK

＃ unzip ev3rt-beta7-3-release.zip（最初だけ）
＃ tar Jxvf ev3rt-beta7-3-release/hrp2.tar.xz（最初だけ）
＃ cd hrp2/cfg（最初だけ）
＃ make（最初だけ）

アプリケーションのビルド
＃ cd /ev3rt/hrp2/sdk/workspace
＃ make app=ビルドしたいアプリケーションのフォルダ名
ビルドが始まる

Windowsのファイルエクスプローラーで
ドキュメント＞ev3rt＞hrp2＞sdk＞workspace
ここにある app が実行ファイル
任意のファイル名に変更する

PCとEV3をUSBケーブルで接続
EV3の中央ボタンを押して電源を入れるとエクスプローラーにEドライブが開く
E:\ev3rt\apps\
に先ほどの名前を変更したファイルをここにコピー
USBケーブルを抜く
EV3でアプリケーションを起動する

#開発環境のシャットダウン
dockerコンテナのシャットダウン
＃ exit
dockerのシャットダウン
$ exit

#次回のコンテナ起動
デスクトップで
DockerQuickstartTerminalのアイコンを右クリック「管理者として実行」
Dockerのコマンドラインで
$ cd ~/Documents/ev3rt
$ docker run -it --rm -v /c/Users/自分のID/Documents/ev3rt/:/ev3rt/ ev3rt_tools /bin/bash
Toppers開発環境のコンテナが起動したらコンテナのコマンドラインで
＃ ls
でev3rtの中身が見えればOK

＃ cd hrp2/sdk/workspace
＃ make app=ビルドしたいアプリケーションのフォルダ名
BigQuery API の Cloud クライアント ライブラリの使用方法

### 概要
Firebase Functions から Google BigQuery の API を実行するまでに結構てこずったので記録しておこうと思います。ネットで検索するといろいろ情報はあるし公式サイトも充実しているのですが、私が知りたい部分が抜けているような感じがしたので、私が実行できた書き方を紹介致します。

### 前提
・プロジェクトは作成済
・BigQuery にデータが既に有る

### サービスアカウントキー作成
サービスアカウントキーの作成に関しては公式サイトの手順通りに進めれば大丈夫です。
https://cloud.google.com/bigquery/docs/quickstarts/quickstart-client-libraries?hl=ja

BigQuery API を有効化にしていきます
<img width="657" alt="Screen Shot 2019-10-23 at 22.53.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136882/00d22008-f221-74a1-f18b-c5ef15955593.png">
検索するとすぐに出てくるので選択
<img width="1135" alt="Screen Shot 2019-10-23 at 22.55.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136882/7c97a1a6-deb9-766b-effc-59d46ca7658f.png">
「有効」をクリック
<img width="263" alt="Screen Shot 2019-10-23 at 22.58.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136882/1096c9cb-5030-6d29-474e-a20985212ceb.png">
「認証情報」→「認証情報を作成」→「サービス アカウント」を選択
<img width="895" alt="Screen Shot 2019-10-23 at 22.49.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136882/18e5e994-8635-5a50-2602-f0a58d9a1a8f.png">
「サービス アカウント名」を入力し、「作成」をクリック
＊ID は自動で作成されます
<img width="1091" alt="Screen Shot 2019-10-23 at 23.03.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136882/9472ea9f-f2f7-32e0-1539-84942d03f707.png">
役割は「オーナー」を選択し、「続行」をクリック
<img width="1095" alt="Screen Shot 2019-10-23 at 23.05.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136882/f986d723-6569-f6e3-2381-620536a44c2d.png">
「キーを作成」→「JSON」→「作成」を選択するとダウンロードされます。その後、「完了」をクリックで終了です。
<img width="1400" alt="Screen Shot 2019-10-23 at 23.09.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136882/372cbb35-eb37-c687-e69a-87be669f4b25.png">

### クライアント ライブラリのインストール
```shell
npm install --save @google-cloud/bigquery
```

### ソースコード
＊このソースは Firebase Functions から呼び出す想定の書き方となっています

```typescript
const { BigQuery } = require("@google-cloud/bigquery");

export async function index() {
  const bigQuery = new BigQuery({
    projectId: "xxxx",
    credentials: require("[path]/xxxx.json") // ダウンロードした JSON ファイル
  });

  // クエリ
  const sqlQuery = `
    SELECT
      xxxxx
    FROM
      \`xxxxx\`
    WHERE
      xxxx = xxxx
  `;

  const options = {
    query: sqlQuery,
    location: "US" // BigQuery の location
  };

  const [rows] = await bigQuery.query(options);

  console.log([rows]);
}
```
projectId はホーム画面で確認できます
<img width="678" alt="Screen Shot 2019-10-23 at 23.24.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136882/44b08460-06bf-9f00-bcb5-e7942d5df6dc.png">

以上となります。