OmniAICreator/Qiita-1.07M huggingface dataset:
名前付きパイプ(mkfifo)でsqlplusのspool結果を圧縮しながらファイル出力する。(Oracle Database)

表題の通り、名前付きパイプ(mkfifo)でsqlplusのspool結果を圧縮しながらファイル出力してみるやで彡(ﾟ)(ﾟ)

# 1. 名前付きパイプの作成(mkfifo)とgzipコマンドのバックグラウンド実行

下記コマンドを実行します。

(1). mkfifoコマンドで名前付きパイプを作成
(2). 名前付きパイプのcat結果をgzip圧縮して、ファイルにリダイレクトするコマンドをバックグラウンド実行

```sh
mkfifo gzip.pipe
cat gzip.pipe | gzip -c > orders.csv.gz &
ls -la

total 12
drwxrwxr-x.  2 opc opc 4096 Mar 26 13:47 .
drwxrwxr-x. 24 opc opc 4096 Mar 26 13:23 ..
prw-rw-r--.  1 opc opc    0 Mar 26 13:46 gzip.pipe ★名前付きパイプ
-rw-rw-r--.  1 opc opc    0 Mar 26 13:47 orders.csv.gz
-rw-rw-r--.  1 opc opc  413 Mar 26 13:28 orders_csv.sql
```

# 2. ファイル出力のSQL

下記がファイル出力のSQLです。spool先は名前付きパイプ(gzip.pipe)としています。

```sql
cat orders_csv.sql

-- orders_csv.sql
SET LINESIZE 32767;
SET PAGESIZE 0;
SET FEED OFF;
SET TRIMSPOOL ON;
SET TERMOUT OFF;
SET ARRAYSIZE 5000;
SET COLSEP ,
ALTER SESSION SET NLS_TIMESTAMP_FORMAT='YYYY/MM/DD HH24:MI:SS.FF';
-- spool to named pipe.
spool gzip.pipe
PROMPT ORDER_ID,ORDER_DATE,CUSTOMER_ID,ORDER_STATUS
SELECT ORDER_ID, ORDER_DATE, CUSTOMER_ID, ORDER_STATUS FROM ORDERS WHERE ROWNUM <= 10000;
spool off;
EXIT;
```

# 3. sqlplusでSQLを実行(ファイル出力)

sqlplus で SQL を実行して、ファイルを出力します。

```sql
sqlplus /nolog
CONNECT xxxxxxxx/yyyyyyyy@zzzzzzzz
@./orders_csv.sql

Connected.

Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

[1]+ Done cat gzip.pipe | gzip -c > orders.csv.gz ★バックグラウンドのgzipが終了している。
```

# 4. 圧縮ファイルの結果確認

gunzipコマンドで圧縮ファイルの結果を確認します。バッチリや！彡(^)(^)

```sh
ls -la
gunzip -c orders.csv.gz

total 140
drwxrwxr-x.  2 opc opc   4096 Mar 26 13:48 .
drwxrwxr-x. 24 opc opc   4096 Mar 26 13:23 ..
prw-rw-r--.  1 opc opc      0 Mar 26 13:49 gzip.pipe
-rw-rw-r--.  1 opc opc 128586 Mar 26 13:49 orders.csv.gz ★gzip圧縮されて出力されたファイル
-rw-rw-r--.  1 opc opc    378 Mar 26 13:48 orders_csv.sql

ORDER_ID,ORDER_DATE,CUSTOMER_ID,ORDER_STATUS
717508,2007/12/13 05:00:00.000000,952991,7
717509,2009/05/28 19:00:00.000000,728526,6
717510,2011/02/28 02:00:00.000000,914050,5
717511,2008/07/11 15:00:00.000000,385931,4
717512,2012/01/30 03:00:00.000000,953603,6
:
:
728011,2007/10/01 00:00:00.000000,830197,4
728012,2010/08/25 01:00:00.000000,39406,6
728013,2007/11/30 23:00:00.000000,280994,4
728014,2007/07/20 12:00:00.000000,342535,6
```

# 5. 名前付きパイプの削除(rm)

名前付きパイプはファイル同様にrmコマンドで削除できます。

```sh
rm gzip.pipe
ls -la

total 140
drwxrwxr-x.  2 opc opc   4096 Mar 26 13:54 .
drwxrwxr-x. 24 opc opc   4096 Mar 26 13:23 ..
-rw-rw-r--.  1 opc opc 128586 Mar 26 13:49 orders.csv.gz
-rw-rw-r--.  1 opc opc    378 Mar 26 13:48 orders_csv.sql
```

# 6. まとめ

圧縮しながらsqlplusでSPOOLできる！今回はsqlplusのspoolでしたが、応用は色々効きそう。
なお名前付きパイプによるxxしながら圧縮は、MySQL界隈では必須テクニックぽい？彡(ﾟ)(ﾟ)

 > MySQLのダンプファイルを圧縮しながら書き出す
 > http://huruyosi.hatenablog.com/entry/2015/10/20/014254
 > 　 
 > [mysql]dumpファイルのサイズを気にせずに別サーバへデータを転送する
 > https://qiita.com/qr_taka/items/7136550a8b8499bab592
Visual C#を使ってみた

Visual C#を使うに当たって基本的なことだと思っていることをまとめてみた。
### 変数の宣言
構文は　**データ型　変数名**
データ型の種類
int・・・整数を扱う。
float・・・少数を扱う。
string・・・文字を扱う。
bool・・・trueかfalseかのどれかを扱う。
他にもいろいろあるのだが、数が多いためよく使いそうなものを書いてみた。

###条件分岐
**if文**
条件に合わせて処理分岐する時に使う
簡単なプログラムを作ってみた

```
int a=10;
if(a>=10)  //条件式
{
　　MessageBox.Show("１０以上","message");  //条件がtrueの場合
}
 else 
{
　　MessageBox.Show("１０未満","message");   //条件がfalseの場合
}
```

結果は１０以上と表示される。

３つ以上分岐する場合は

```
int a=10; 
if(a>=10)  //条件式
{
　　MessageBox.Show("１０以上","message");  //条件１がtrueの場合
}
 else if(a>=5)
{
   MessageBox.Show("５以上","message");　　//条件２がtrueの場合
}
 else 
{
　　MessageBox.Show("５未満","message");   //条件すべてがfalseの場合
}
```
結果は先ほどと同じになるが、int a=10をint a=9にすると5以上が表示される。
分岐を増やすならelse ifを増やせばいい。　

他にもswitch文もある

```
int a = 10;
 switch (a >= 10)  //条件式または変数名
 {
   case true:
    MessageBox.Show("10以上", "message");  //trueの場合
    break;
   default:         
    MessageBox.Show("10未満", "message");   //true以外の場合
    break;
}
```
結果は１０以上と表示される。条件にtrueを使ったから分岐はfalseしかない
今回は紹介はしないが繰り返し処理を使って条件を整数にするとおもしろいものが作れる気がした。
###参考文献
金城　俊哉「Visual C#2017パーフェクトマスター」秀和システム
doc2vecの結果をtensorboardで可視化

[word2vecの結果をtensorboardで可視化する方法があった](https://yag-ays.github.io/project/embedding-visualization/)ので、これはdoc2でもいけるんじゃないかと思いやってみた結果。

#１．背景
上記のとおり、word2vecの結果をtensorboardで可視化すると、１個１個のプロットが
１ワードになっている。説明を読むと、「この可視化は単語の分散表現以外にも、ユニークなIDやラベルに対して固定長のベクトルが割り当てられていれば、一般的な特徴量やベクトル表現にも応用できます。」
とのことだったので、doc2vecも当てはまると思いやってみることに。


#２．工夫した点
#word2vecでは
    weights = model.wv.vectors
    labels = model.wv.index2word
とすればいい。
word2vecの１ワード毎の分散表現が　wv.vectorsに、
word2vecの１ワード自体がwv.index2wordに
格納されている。

#doc2vecでは
    weights =[]
    labels =[]
    for i in range(0,len(model2.docvecs)):
        weights.append(model2.docvecs[i].tolist())
        labels.append(model2.docvecs.index_to_doctag(i)) #model2.docvecs
とする。

doc2vecでもwv.vectors,wv.index2wordが出力可能なので、ここでハマった。
（自分としてはtensorboardの可視化した１つの点が１つの文章として表示したかった）
そこでdoc2vecではdocvecsの中に
・１文章毎の分散表現が入っている
・見出し（tag）はindex_to_doctagに入っている
ことを発見したので、それらをそれぞれweights,labelsに入れるようにプログラムを作成した。
デフォルトではnumpy.arrayなのでtolistなどをする必要がある点も注意。



#３．その他
出力してみた結果の図。イメージ通り。
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/385220/d063f459-1b52-b039-59ca-4726e9975b16.png)

tensorboardが可視化ツールとして面白そうと判明。


# 全体プログラム
    import torch
    import tensorboardX as tbx
    from tensorboardX import SummaryWriter
    writer = tbx.SummaryWriter()

    #word2vecの場合
    #weights = model2.wv.vectors
    #labels = model2.wv.index2word

    #doc2vecの場合
    weights =[]
    labels =[]
    for i in range(0,len(model2.docvecs)):
        weights.append(model2.docvecs[i].tolist())
        labels.append(model2.docvecs.index_to_doctag(i)) #model2.docvecs
    
    # DEBUG: visualize vectors up to 1000
    weights = weights[:1000]
    labels = labels[:1000]
    writer.add_embedding(torch.FloatTensor(weights), metadata=labels)
GitLab Meetup Tokyo #13: ChatOpsに行ってきました

　今回参加したイベントは[GitLab Meetup Tokyo #13: ChatOps](https://gitlab-jp.connpass.com/event/124425/)です。
LT発表をされた方々が抽選当たるか不安だったのでLT枠に…！と仰っていましたが、かくいう私も抽選運に自信がなかったのでブログ枠に申し込んでみました。というわけで簡単に感想をまとめたいと思います。(内容の要約はconnpass等にあがっている資料を見るのがおすすめです)

# GitLabのトレンド
　AWSを今の所家でも仕事でも一番使っているので、AWSとの連携が楽しみです。AutoDevOpsがどんなものか具体的にわかっていないけどとにかく突っ込んだら全部できる感じらしい。すごい(雑)。
　セキュリティテストという観点では、今まで**セキュリティテストの内容や概要がGitLabのversionに依存していたところを、機能を切り出すことで改善した**らしいです。すごい(再)。特にセルフホスティングだとなかなかすぐにバージョンが上がらないことも多いのでこれは嬉しいと思いました。現状全くその機能使えていないし知らないのでちょっと調べてみたいです。

# GitLabではじめる一人DevOps
　ポートフォリオなどの、できるだけお金や手間をかけずに運用したい非営利な個人プロジェクト向けの発表だったので、帰ってから試そう！と思える内容が満載でした。
　まず驚いたのは静的解析の、**「コードメトリクスでコードが複雑になりすぎていないかを確認し、リファクタリングのきっかけにする」**という話でした。そもそもコードメトリクスを知らないのですが、そんな使い方のできる機能があること自体も驚きでした。個人プロジェクトでそこまで大きなものはまだ持っていないのですが、これは普通に仕事の方で導入したいと思いました。
　あとは、GitLab BadgeもカバレッジやAngularのバージョンをパッと確認するのに便利そうなのでぜひつけてみたいです。テストカバレッジレポートの出力はもともとやってみたいなあと思っていたのでやります。
　**タグを切ると自動でリリースジョブが走る**、というのでそもそもタグの使い方がよくわかっていなかったのでなるほどそういう風に使うのかーと思いました。今はあるバージョンの開始時にその時のdevelopでタグを切ってあとはバージョン終わるまで更新内容をリリースノートに追記していく使い方をしていて、これなんでブランチとかコミットに紐づけないといけないんだろう…と思っていました。最新版ではもっとリリースノートに特化した機能があると公式ドキュメントで読んだ覚えがあるので全力でバージョンアップを待機するしかない…(セルフホスティング勢)。せっかくなのでそういう使い方ができないかも挑戦してみたいところです。

# GitLab ChatOpsセッション
　今回のメインテーマです。これまでのslackコマンド連携とはまた別物で、slackコマンドを使いながら、gitlab-ci.ymlと同じような制御・使い方のできるところが強みらしいです。今後、ユーザーの権限に応じて実行できる内容を変えたりとか、chat-replyでslackに表示する文言を選んだりとか夢広がる〜！な感じの様子。ちなみに現在はα版です。
　今のところプレマージやポストマージでかなり事足りてるのでどう使いたい、みたいなのは個人的には思いつきませんでしたが、(これはchatOpsの範疇ではないかもしれない？というのを承知の上で)手段はなんにせよslackから起票できるようにしたいなと思いました。slack上でやりとりしてIssue起票するか否か決まることが結構多いんですよね。

# マーケターがGitlabを使って見た話
　かなり新鮮なお話を伺うことができました。GitLabの万能さもさることながら、人事とのやりとりから監査の対応までGitLabでこなし、これからはマーケターもコード書けないと、と語るスピーカーの姿勢もすごいと思いました。**自分以外社長まで含め全員GitLabユーザーだった**ってなかなかないですよね 笑 

# まとめ
　GitLabでやりたいことリストがもさもさ増えました:hatching_chick:

　※「GitLabでのproject import/exportのversion差異で困ったことありませんか？」と、「Mattermost Plugin Bounty Programについて」は私の知識がなさすぎて感想をかけるほどではないのでぜひスライドなどをご確認ください。
Fiddlerでrequest headerを書き換える

古い記事でhttpsでもなかったのでメモ書きとして変数名など変更して記載。
それだけだとまた読んだときにわからなくなるので自身の解釈のコメントを追加。

正直公式ドキュメントともともとの英語のコメント読んだほうが良い。

```
//class Handlerのスコープに
//ヘッダーメニュー内に項目を追加
public static RulesOption("Add [header名を記載、メニューに表示される]")
//ここのbool変数でヘッダーに追加するかを制御する
var m_AddFlagBool: boolean = true;
```

```
//static function OnBeforeRequest(oSession: Session) のスコープに
//先の変数の値を確認してリクエストに内容を設定するか制御
if (m_AddFlagBool){
  //指定はkey, valueの組み合わせ
  oSession.oRequest[ "[key名]" ] = [value値];
}
```

引用は下記

http://hasegawa.hatenablog.com/entry/20070329/p1
ゼロから始めるNSX-v Vol.2 -NSXの構成要素-

# NSX for vSphereのコンポーネント

|Plane|NSX Component|Description|
|:--|:--|:--|
|Management Plane|NSX Manager|各コンポーネントの設定や操作を行う|
|Control Plane|NSX Controller|論理スイッチ、ルーティングなどの制御情報を管理する|
|Data Plane|Hypervisor Kernel Module, Edge Service Gateway|制御情報をもとにトラフィックを処理する|

各NSXコンポーネントのデプロイは以下の流れに沿って行う。

1. NSX Managerをデプロイする
2. vCenterにNSX Managerを登録する
3. NSX Controllerをデプロイする
4. ESXiホストにHypervisor Kernel Moduleをインストールする
5. Edge Service Gatewayをデプロイする


## NSX Manager

* 仮想アプライアンス（VMwareからOVAで提供される）
  * NSX Controllerなど、他のNSXのコンポーネントも同梱されている
  * vSphere HAを構成しているクラスタに展開するのが推奨
  * PostgreSQL、RabbitMQが内部で動作している
  * vCenterと同じくDNS, NTPは必須
* **NSX ManagerとvCenterは1対1対応**
  * vCenterが2台いる環境ならNSX Managerも2台必要
  * Cross-vCenter環境の場合は1台Primaryで他はSecondaryとして扱う
* 管理用のインターフェースはvCenter
  * NSX Managerが[REST API](https://docs.vmware.com/en/VMware-NSX-Data-Center-for-vSphere/6.4/nsx_64_api.pdf)を提供していてvCenterが叩いている
  * curlとか使えばCLIで直接操作できる、やったね！
  * NSX Manager自体もGUIはあるがvCenterの登録や自身の設定管理、バックアップ/リストアなど特殊な管理用の画面のみ


## NSX Controller

* 仮想アプライアンス
  * NSX ManagerからvCenterを経由してデプロイする
  * デプロイ時はvCenter上で動くEAM(vSphere ESXi Agent Manager)が仲介役
  * IPアドレスを指定してデプロイすることはできない（NSX Controller用のIPアドレスレンジを事前に定義しておいて、その中から採番される仕組み）
  * Paxosベースのアルゴリズムで動作するので3台の展開が必須
* クラスタを組んで動作するのでデータは冗長化されているがより安全にするため、以下の構成/設定が推奨されている
  * NSX Controllerを展開するクラスタを構成するESXiホスト群はToRスイッチの障害時に全滅しないように配置する
  * 同じESXiホスト上で複数のNSX Controllerを動作させない（DRSが使える場合はアンチアフィニティルールを適用する）
  * NSX Controllerを展開するクラスタでvSphere HAを構成しておく
* 論理スイッチ、ルーティング情報の収集/計算/配布を担当する
  * ワークロードはシャーディングによって動的に分散される
  * NSX Controllerにログインしないと担当しているシャードは見えない（GUIで見れない）
  * ノード故障時は故障ノードに割り当てられていたシャードは残ったノードに再配置される
* NSX Controller上では以下のサービス（ロール）が動く
  * API Provider
  * Persistence Server
  * Switch Manager
  * Directory Server
  * Logical Manager
* 各ロールにはMasterノードが存在し、Masterノードとして動作しているNSX Controllerが障害時は残りのNSX Controllerの中から新しいMasterノードを選出する


## Hypervisor Kernel Module, Edge Service Gateway

実際にトラフィックを処理するコンポーネント群

* Hypervisor Kernel Module: ESXiにVIBとしてインストール
  * Logical Switch
  * DLR(Distributed Logical Router)
  * DFW(Distributed FireWall)
* Edge Service Gateway: 仮想アプライアンスとして展開
  * ルーティング
  * ファイアウォール
  * ロードバランサ
  * VPN (IPSec/SSL/L2)
議事録のフォーマット作成が面倒なのでSeleniumで自動化する

定期的に参加している打ち合わせのため、事前に議事録のフォーマットを作成しておくというのがだんだん面倒になり自動化することにしました。
単純な作業を自動化するというのは素晴らしいですね。

# 環境・使った技術
Python3からSeleniumを使い、DocBaseに議事録フォーマットを作成するようにしました。

seleniumはpipでインストールすることが出来ます。

```
pip install selenium
```

Selenium実行用のブラウザはchromedriverを使用しました。
最新版をインストールして起動させたところ、エラーで落ちてしまったので安定版をインストールし直しました。

> chromediriverインストール先
http://chromedriver.chromium.org/downloads

# コード
seleniumの使い方は情報がたくさんあるので、各自調べてもらえればと思います。
ActionChainsクラスというあまり馴染みのないものが出てきたのでソースコードの下で軽く説明します。

```py:
from datetime import datetime
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time

# DocBaseのログイン画面を開く
driver = webdriver.Chrome('./chromedriver')
driver.get('https://docbase.io/users/sign_in')
time.sleep(1)

# ログイン
search_email_input = driver.find_element_by_name('user[encrypted_email]')
search_password_input = driver.find_element_by_name('user[password]')
search_email_input.send_keys('email')
search_password_input.send_keys('password')
time.sleep(1)
login_button = driver.find_element_by_name('commit')
login_button.click()

# 新しいメモの作成ページに移動
driver.get('https://team_name.docbase.io/posts/new')
time.sleep(1)

# フォーマットを入力して下書き保存
path = './test.text' # test.txtにはMarkdownで書いたフォーマットを記載しておきます。
action_chains = ActionChains(driver)
search_title_input = driver.find_element_by_name('post[title]')
search_textarea = driver.find_element_by_class_name('CodeMirror')
action_chains.click(search_textarea)
with open(path) as f:
    action_chains.send_keys(f.read()).perform()

post_date = datetime.today().strftime('%Y/%m/%d')
search_title_input.send_keys('{}議事録'.format(post_date))
time.sleep(2)

draft_save_button = driver.find_element_by_class_name('js-submit-button')
draft_save_button.click()
driver.close()
```

# ActionChainsについて
CtrlキーやShiftキーを押しながらの入力や、ファンクションキーの操作ができるクラスです。
DocBaseのテキスト入力時に、CodeMirrorというjsのライブラリが影響して通常のやり方では入力できなかったので、ActionChainsを利用して問題を解決しました。
今回の場合は、テキストエリアをクリックした状態でテキストを入力するという処理になっています。
perform()は、これまでのメソッドをビルドして実行するメソッドです。

# 一言
時間があるときに、cronでフォーマット作成を定期実行したり、作成した議事録フォーマットをslackとかで通知してみようと思います。

# 参考
[【Python】Seleniumの使用方法メモ](https://qiita.com/motoki1990/items/a59a09c5966ce52128be)
[CodeMirrorでブラウザ上で動作するコードエディタを作る](https://qiita.com/qmotas/items/90dbe1f8f60136cf39bf)
[【Python】key_down/click/perform・・・キーボードを押しながら要素をクリックをする](http://www.seleniumqref.com/api/python/actions/Python_key_down_click.html)
Magnific Popupでモーダル表示

○実装の背景
一月分のカレンダーが実装してあり、日付一日ごとに申請ボタンを実装している。
各日付にある残業申請ボタン押し込みで各一日ごとの申請フォームをモーダルで表示させたい。

モーダルの表示のさせ方は色々あるが、Magnific Popupで今回は実装。
画像をモーダル表示させたいときに使うことが多いのかな？

まずMagnific Popupを使用するためにプラグインをダウンロード。(右にあるDownload ZIPから)
ダウンロードは[こちら](https://github.com/dimsemenov/Magnific-Popup)
使用するファイルはdistディレクトリにある「jquery.magnific-popup.min.js」と「magnific-popup.css」なので、コピーして適当なフォルダに配置。以下は配置の参考に。
```/app/assets/stylesheets/magnific-popup.css```
```/app/assets/javascripts/jquery.magnific-popup.min.js```

```erb:show.html.erb
<tbody>
  <% @date.each do |date| %>  <!-- 月初から月末までの繰り返しを変数dateに格納  -->
    <tr>
      <!-- 第一項：申請 -->
      <td class="modal-open"><a href="#<%= date.attendance_day.day %>" class="btn btn-primary">残業申請</a></td>
      <!-- 第二項：日付 -->
      <td><%= date.attendance_day.month %>/<%= date.attendance_day.day %></td>  <!-- 変数dateから月と日を取得 -->
      <!-- 第三項：曜日 -->
      <td><%= @week[date.attendance_day.wday] %></td>  <!-- wdayメソッドは、その日の曜日を数値で戻す。(日曜が0) -->
    </tr>
  <% end %>
</tbody>
```
○ポイント
申請ボタンをクリックするとモーダルで表示したいので、```class="modal-open"```とする。
モーダルで表示される申請フォームは3/1、3/2、3/3...とそれぞれがユニークである必要があるので、aタグの中にユニークになるようにコードを書く。このとき、```#```を忘れないこと。

```erb:show.html.erb
<!-- 一日分の申請フォーム（モーダルで表示） -->
  <%= @date.each do |date| %>
    <div class ="white-popup mfp-with-anim mfp-hide" id="<%= date.attendance_day.day %>" style="background-color:white">
      <h3 align="center" style="padding-top:15px">残業申請</h3>
      <%= form_for(date, url: sample_path, method: :post) do |f| %>
        <table class="txt1 table table-bordered table-striped table-condensed">
          <thead>
            <tr>
              <th>日付</th>
              <th>曜日</th>
              <th>終了予定時間</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <!-- 日付 -->
              <td><%= date.attendance_day.month %>/<%= date.attendance_day.day %></td>
              <!-- 曜日 -->
              <td><%= @week[date.attendance_day.wday] %></td>
              <!-- 終了予定時間 -->
              <td><%= f.time_field :scheduled_end_time, class: 'form-control' %> </td>
            </tr>
          </tbody>
        </table>
        <%= f.submit "申請する", class: "btn btn-sm btn-primary" %>
      <% end %>
    </div>
  <% end %>
```
○ポイント
```class ="white-popup mfp-with-anim mfp-hide"```
このクラスはダウンロードしたプラグインのcssファイルに含まれるクラスを指定している。
なので何でもいいわけではない。
```id="<%= date.attendance_day.day %>"```
次に申請ボタンで書いたユニーク処理を、フォームではidとして書く。
申請ボタン側とフォーム側で相違があれば、モーダルは表示できない。

```erb:show.html.erb
<script>
// 1日分の申請フォーム　モーダル表示
  $(".modal-open").magnificPopup({
  delegate: 'a'
  // removalDelay: 500,
  // callbacks:{
  //   beforeOpen: function() {
  //     this.st.mainClass = this.st.el.attr('data-effect');
  //   },
  // },
});
</script>
```
○ポイント
delegate：それをクリックするとモーダルウィンドウを開く要素のセレクタ
'a'というのはa要素を意味する。
モーダルの開閉だけなら、これだけでおっけー。
delegateは開くためのセレクタのようだが、閉もなぜかできる。

コメントアウトさせている箇所はモーダルにアニメーションをつけるためには必要。
data-effectを今回もし指定するなら、申請ボタンのaタグ内に書く。
```<a href="#<%= date.attendance_day.day %>" class="btn btn-primary" data-effect="mfp-zoom-in"> ```のような感じ。
asyncの例文

わかりやすかったページを日本語にしました。
https://javascript.info/async-await

asyncキーワードから始めましょう。このように、関数の前に置くことができます。

```javascript
async function f() {
  return 1;
}
```

関数の前の「async」という言葉は、1つの簡単なことを意味します。関数は常にPromiseを返します。関数が実際にはPromiseではない値を返す場合でも、関数定義の先頭に“ async”キーワードを付けると、Javascriptは解決されたPromiseでその値を自動的にラップするように指示されます。

例えば、上のコードはの結果で解決されたPromiseを返します。1それをテストしましょう

```javascript
async function f() {
  return 1;
}

f().then(alert); // 1
```
…Promiseを明示的に返すこともできます。それは同じです。

```javascript
async function f() {
  return Promise.resolve(1);
}

f().then(alert); // 1
```

そのためasync、関数がPromiseを返すことを保証し、その中にPromiseでないことをラップします。簡単ですよね。


！！自分が知りたかったところがバッチリ書いてありました。
気が向いたら、オンラインエディタで実行してみてください〜
https://playcode.io/online-javascript-editor
pymc3でのモデル関数が条件分岐を含む場合の書き方

pymcで推定を行う際に、モデル関数がifを含む条件分岐がある場合についての書き方についてです。numpyとは少し書き方が違います。
teratailで回答した内容
[pymc3でのモデル関数が条件分岐を含む場合の書き方](https://teratail.com/questions/181020)
を再度編集したものです。
動作環境は、Win10、python3.5、Anaconda、Jupyterを利用。


**今回の条件分岐関数**
条件分岐を含むモデル関数
uの位置で、1次関数として立ち上がる関数です。

```python
def model_line(x, u, nor, bg):
    ud = x - u 
    if ud <= 0:
        f =  bg
    else:
        f = nor*ud + bg
    return f

```
**importモジュール**
前の関数を実行する前に以下のモジュールをインポートしておいてください。

```python
import pymc3 as pm
import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt
# import seaborn as sns
plt.style.use('seaborn-darkgrid')
np.set_printoptions(precision=2)
%matplotlib inline
```
**条件分岐を含む関数の作図**

```python
#条件分岐を含む関数の作図
xx = np.arange(3, 6.1, 0.1)

#引数はfloatで書く、np.vectorizeしています。
vec_model_line = np.vectorize(model_line)
y_data = vec_model_line(xx,4.5,1.0,1.0)

plt.plot(xx,y_data)
plt.show()
```
**グラフ表示**
![output_3_0.png](https://qiita-image-store.s3.amazonaws.com/0/165987/82b8b0e2-7528-853c-b198-bc42aab530d6.png)

**ノイズを付加**

```python
#ノイズを付加
noise=np.random.normal(1, 0.1, len(xx))
yy_data=y_data+noise
plt.plot(xx,yy_data)
plt.show()
```
**ノイズを付加したグラフ**
4.5付近で立ち上がっています。
![output_4_0.png](https://qiita-image-store.s3.amazonaws.com/0/165987/6495f131-8409-6a73-e70b-c003161327e6.png)

**モデル関数の書き換え**
事後分布を求める前に、model_line関数をpymc用に書き換えます。
pymc3のswich関数を用います。引数の1番目は条件、2番目は真の条件での実行、3番目は、偽の条件での実行を入力します。 
参考：[PyMC3を使って変化点検出のベイズ推論をする](https://qiita.com/hanon/items/467d27e077763bcadf2a)

```python
def model_line2(x, u, nor, bg):

    ud = x - u 
    f1=bg
    f2=nor*ud + bg
    
    return pm.math.switch(ud<=0,f1,f2)
```

**事後分布推定**

```python
# x, 
# u, gauss
# nor guass
# bg gauss
with pm.Model() as model:
    u= pm.Normal('u', mu=4.0, sd=1.0)
    nor = pm.Normal('nor', mu=1, sd=1)    
    bg = pm.Normal('bg', mu=1, sd=1)
    epsilon = pm.HalfCauchy('epsilon', 1)
    
    mu =model_line2(xx,u,nor,bg)

    y_pred = pm.Normal('y_pred', mu=mu, sd=epsilon, observed=yy_data)

    trace_model = pm.sample(2000, njobs=1)

pm.traceplot(trace_model)
plt.tight_layout()

plt.figure()
```

**計算結果**
![output_7_2.png](https://qiita-image-store.s3.amazonaws.com/0/165987/9dea746d-139c-e6db-a31f-0a78014c877d.png)

最初に設定したu=4.5,nor=1.0,bg=1.0にたいして、ノイズを足したものと比較すると、大体良い一致をしています。bgについては、ノイズを足すときに平均値を1にしているため2に近い値になっています。
How To Play Google Play Music On Alexa

# How To Play Google Play Music On Alexa
我が家にもやってきたAlexa、有効活用したいけどなかなか使い道が・・・
Amazon Music契約すれば音楽再生に使えそうだけど、いろいろあってGoogle Play Musicから離れられない・・・
AlexaからGoogle Play Musicを流せないものか・・・

で調べてたらYouTubeにこんなぴったりのタイトルの動画がありました。
[How To Play Google Play Music On Alexa](https://www.youtube.com/watch?v=nFzhZbmhFCQ)

英語なので手順書き起こしてみます。

# やってること
Amazon Echoと自分のAndroid端末がBluetoothでつながっていることが前提みたい

Echo(Alexa)にトリガーフレーズを話しかける
↓
IFTTT経由でAndroid端末にPushbulletメッセージが飛ぶ
↓
Pushbulletメッセージを受け取ったら、TaskerがGoogle Play Musicを立ち上げて再生
↓
Andoroid端末で再生される音楽がBluetoothでEchoのスピーカーから流れる

自分がやりたいことと違いました・・・
Alexa(Echo)から直接Google Play Musicを流せるのかと思った・・・
※途中でやる気なくしたので、Dash Automation以降の説明は割愛

## 1.IFTTTの設定
**Alexaに「Trigger Google Play Music」と話しかけると、IFTTT経由Pushbulletよりメッセージが飛ぶ**

IFTTTの"New Applet"：以下のAppletを作成する

- this:"Amazon Alexa" -> "Choose trigger":"Say a specific phrase":「Google Play Music」
- that"Pushbullet" -> "Push a note" -> "Message"に"Playgoogleplay"（内容は任意）

## 2.Taskerの設定
**Pushbulletで"Playgoogleplay"というメッセージが送られてきたら、Google Play Musicで音楽再生（あくまでAndroid端末上での再生）**

- ... -> "Preference" -> "Allow External Access"にチェック
- ... -> "More" -> "Android Settings" -> "Notification Access Service" -> "IFTTT"と"DashAutomation"と"Tasker"の通知許可
- "TASKS" -> "+" -> タスク名入力 -> 
    - "Task Edit" -> "+" -> "Media" -> "Media Control" 
    - "Action Edit" -> "Cmd": "Play [Simulated Only]"を選択 -> "App":"Google Play Music"を選択
- "PROFILES" -> "+" -> "Event" -> "UI" -> "Notification" 
    - "Owner Application" -> "IFTTT"と"Pushbullet"を選択
    - "Text" -> "Playgoogleplay"（※IFTTTのthatでPushbulletより送られるText）

## 3.Dash Automationをつかって何かしてる
以降割愛

# まとめ
**Alexa(Amazon Echo)から直接Google Play Musicを呼びたい！**
僕も流行りにのってGoでAPIサーバーを書きたい 〜 導入編 〜

現在、新しくプロダクトを作っています。さて、サーバーサイドの開発言語を選定する過程で、いつもなら慣れているPythonを迷わず選ぶのですが、「最近Goって流行ってるよなあ、キラキラしてていいなあ、俺もキラキラしたい！」と思うようになりました。

茶番はこれくらいにして、今回はGoで作るAPIサーバーの開発について、セットアップから運用まで備忘録も兼ねて何回かに分けて述べようと思います。

# Go言語のインストール
Go言語を使うには、まずGoのコンパイラをインストールしなければなりません。
macOSの場合はHomebrewで直接インストールすることができます

```
$ brew update && brew install go
```

# パッケージマネージャー dep

まず、APIサーバーを開発するのに必要なフレームワークやライブラリを一式揃えます。
ここでは、**dep**というパッケージマネージャーを用いて導入を行います。Go言語には他にも便利で強力なパッケージマネージャーがいつくか存在しますが、

- Goの公式チームが開発していること
- Go標準のパッケージマネージャになることを目指していること
- 競合の[Glide](https://github.com/Masterminds/glide)もdepへの移行を推奨していること

上記のような理由で**dep**を採用します。

macOSを利用している場合, Homebrewを用いて比較的簡単に導入することができます。

```terminal
$ brew update
$ brew install dep
```

Linuxの場合は`go get`を利用して導入してください。

```terminal
$ go get -u github.com/golang/dep/cmd/dep
```

`dep version`を実行して以下のような出力がされたらインストールに成功しています。

```terminal
dep:
 version     : v0.5.1
 build date  : 2019-03-11
 git hash    : faa6189
 go version  : go1.12
 go compiler : gc
 platform    : darwin/amd64
 features    : ImportDuringSolve=false
```

# プロジェクトの作成

次に、以下のようなディレクトリ構成で新しいGoプロジェクトを作成します。`$GOPATH/src`配下に自分のプロジェクトベースのディレクトリを作成します。ここでは、ソースをGithubに置く場合を示していますが、BitbucketやオンプレミスのGitLabに置く場合は`github.com`を`self_hosting_git.com`などに変更するだけで対応することができます。

```terminal
$ mkdir $GOPATH/src/github.com/user_name/your_repo
$ cd $GOPATH/src/github.com/user_name/your_repo
$ dep init
```

`dep init`を実行すると`Gopkg.toml`が作成されます。

# ライブラリの導入

depはソースに書いてある`import`文を自動的に認識してライブラリの導入を行うことができますが、ここではソースを書き始める前に事前に行おうと思います。depでのライブラリ追加コマンドは`dep ensure -add github.com/org/repo`です。まずは、今回APIサーバーを構築するに当たって重要となるマイクロフレームワーク**echo**の導入を行います。

```
$ dep ensure -add github.com/labstack/echo
```


# Echo Serverの作成

プロジェクトルートに`main.go`ファイルを作成し、以下のようなコードを書きます。

```go
package main

import (
	"net/http"
	
	"github.com/labstack/echo"
)

func main() {
	e := echo.New()
	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello, World!")
	})
	e.Logger.Fatal(e.Start(":1323"))
}
```

では実際に動作させて確認してみましょう。`go run main.go`でコンパイルが成功するとサーバーが立ち上がるはずです。[http://localhost:1323](http://localhost:1323)にアクセスして**Hello, World!**と表示されるか確認しましょう。

<img width="1532" alt="Screen Shot 2019-03-26 at 22.30.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/44018/8c5539d7-e7de-d036-ee4c-5f6e34da9dfb.png">

無事, Hello, World!と表示されました。成功です。


>>次回は、Goの基本の書き方を踏まえながら**Routing**について投稿したいと思います。
ビジュアルプログラミング言語 VL とは

# VLとは
vvvv 上で動作する、VL というビジュアルプログラミング言語の開発が進んでいます。
https://vvvv.org/documentation/vl
VLの動画群を作っていこうと思いますが、テキストでもまとめていければと思い、理解途中ですがまとめていきます。
公式の主張と僕の所感が混ざっているので注意してください。
VL には vvvv にはない用語が結構あるので、用語解説も一緒に書こうと思いましたが長くなるので別投稿で書きます。

次回：[「VL の概念と用語解説」](https://qiita.com/yhy_jp/items/7ba508155b014fa49280)

## VLに興味ある人が見るとよい資料（どちらも公式）
- The Gray Book
    - https://www.gitbook.com/book/vvvv/the-gray-book/details
- vvvv の girlpower/VL

## 背景
- とても複雑なプロジェクトでも vvvv が使われるようになっていきました。vvvvのキャパを超えるくらいに。
- それに伴い色々要望が出てきてそれを叶えたい

## VL のターゲット層
- テキストコードよりもビジュアルコードを好む人
- インタラクティブなプロトタイピングプログラミングを好む人（編集/コンパイル/エラー修正/コンパイル/実行、みたいな）
- データフローでオブジェクト指向で関数型スタイルのプログラミング言語を求めている人
- 最終的にはVVVVユーザのみんなにVLに親しんでほしいと思っている

## VLの特徴
- **VLは vvvv と独立した言語である**
    - VL で作ったノードや型を vvvv で使えますが、VL と vvvv は独立した言語です。
    - vvvv の世界と、VL の世界をきちんと分けて考える必要があります。
- **静的型付けのビジュアルプログラミング言語**
    - 型推論してくれます
    - まだ慣れていないだけでノウハウを貯めていけば恐らく解決しますが、意図しない型推論が起きたりして少しハマる事がたまにあります。
- **プログラミング言語であり、開発環境でもある**
    - Smalltalkのような感じをイメージするかもしれませんが、どちらかというと「VL」という言葉の指す物が、という意味合いです。
- **コンパイルと実行を動的にできる**
- **Nugetsが使えます**
    - Nugets とはパッケージマネージャで、これはライブラリのパッケージを管理して、インストールとかできるもの
- **vvvvで使用できるノードとデータタイプのライブラリとも捉えられる**
    - ノード群（パッケージ）をVLで作成し、vvvvで使えます
    - 一つのパッチに（vvvv でも使用できる）複数のノードを定義できます。
- **vvvv からシームレスに使用でき、vvvv に似ている所が多い**
- **.NETのライブラリが使えます**
    - vvvv の時には vvvv の世界で使えるようにラップしていましたが、VLでは何もせずそのままノード群として使えるようになります。
- **巨大なプロジェクトでの可読性や保守性をサポートする仕組みがあります**
- **ループが書ける**
    - vvvv はそのパラダイム上ループは自然な形では書けません。複数フレーム使用するか、Spectralノードを使用、C#で書く、などする必要がありました。
- **ステート（状態）を持つことができる**
    - vvvv は基本的にステートレスなので、前のフレームを FrameDelay で取ったり、S+H的なノード、QueueやParticleをストアとして扱いましたが、VLでは自然な形でステートを持てます
    - VLではステートレスなパッチとステートフルなパッチを厳格に分けれます
- **VL上で自分で型を定義できる**
    - 例えば、Particle型みたいなのが、pos/vec/color/age、を持っている、みたいなのが定義できます。vvvvではC#で型を作るか、各値をzipしてunzipしてみたいな事をしていましたが自然な形で書くことができるようになります。
- **Genericsをサポートしています**
    - 例えば＋というノードがあったとして、一つ定義したら String でも int でも適用できます。
    - ただ、それをvvvvの世界には持っていく事はできません
- **VL の世界では、Spread<int> と int が区別されます**
    - vvvv ではノードは基本的に全て Spreadable で、暗黙的に Spread 化され int は１要素だけの Spread<int> と見るのが基本でした
    - 将来的には vvvv のその概念を持ってくるかはまだ考え中
- **非同期に入力が取れます**
    - デバイスからの入力など。
    - vvvv は完全にフレームベースドでした。
- **スレッドを分けれます**
    - vvvv ではC#書かないとマルチスレッドができませんでした。
    - データフロー言語とマルチスレッドは相性がいいと思います。

## 感触
少しずつ慣れてきたという段階でまだ理解が浅いですが、言語としての正統進化だと感じます。
C#でノードを作ることがほぼ無くなると思います。
vvvv のフレームベースドで全てのノードは１フレームに１度しか評価されず、lazyな評価で下から辿っていく、という特徴は大きな制限にもなりますが利点も非常に多く、それに比べると VL ではバグが入り込む余地が当然増えるなどはあります。が、その辺りをきちんと認識しつつ、vvvv と適切に組み合わせたりVL自体の工夫によりいいとこ取りができそうだなと思っています。
【Pyhtonチートシート】辞書の基礎

# 辞書の基礎をまとめておく
* 個人的な覚書として辞書の使い方をまとめておく
* 特に難しいものは載せず、基本的なものだけを載せておく

# 辞書の作成

```Python:作成方法その1
drink = {}
drink['coffee'] = '黒'
drink['water'] = '透明'
print(drink)
# {'water': '透明', 'coffee': '黒'}
```
```Python:作成方法その2
drink = {'coffee': '黒', 
         'water': '透明'}
print(drink)
# {'water': '透明', 'coffee': '黒'}
```
# 辞書の値の更新
```Python
drink = {'coffee': '黒', 
         'water': '透明'}
print(drink)
# {'water': '透明', 'coffee': '黒'}

drink['water'] = '水色'
print(drink)
# {'water': '水色', 'coffee': '黒'}
```
# 辞書と値の追加
```Python:
drink = {'coffee': '黒', 
         'water': '透明'}
print(drink)
# {'water': '透明', 'coffee': '黒'}

drink['orange_juice'] = 'オレンジ'
print(drink)
# {'water': '透明', 'coffee': '黒', 'orange_juice': 'オレンジ'}
```
# 辞書の値の削除
```Python
drink = {'coffee': '黒', 
         'water': '透明'}
print(drink)
# {'water': '透明', 'coffee': '黒'}

del drink['water']
print(drink)
# {'coffee': '黒'}
```
# 辞書の値を削除しつつ値を利用
```Python
drink = {'coffee': '黒', 
         'water': '透明'}
print(drink)
# {'water': '透明', 'coffee': '黒'}

col = drink.pop('coffee')
print(drink)
print(col)
# {'water': '透明'}
# 黒
```

# 辞書にkeyが存在するのか判定する
```Python:
drink = {'coffee': '黒', 
              'water': '透明'}

'coffee' in drink
# True
'cola' in drink
# False
```

# 辞書にkeyが存在しなときに返り値を与える
```Python
drink = {'coffee': '黒', 
         'water': '透明'}

print(drink.get('coffee', '飲み物なし'))
print(drink.get('cola', '飲み物なし'))
# 黒
# 飲み物なし
```
プログラミングをうまく進めていくために必要なこと　＜初心者＞

[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしているryota_miraidenshiです。
今回は、プログラミングをしていてかなり重要だと思ったことについて書いておきます。

#プログラミング初心者が気をつけるべきこと
現在、自分はインターンでプログラミングを勉強しているのですが、そこでの勉強の仕方としてドットインストールの動画を見ながらだったり、チュートリアルを見ながら作業したりと言う勉強が中心です。
そこで必ず出てくるのが環境構築だと思います。
この環境構築が自分はとても苦手かつ最難関だと思っています。
と言うのも、環境構築はよくわからないコマンドを打つ必要があって理解が難しいですし、それを入力しても多くのエラーが出て、そのエラーを見ても何が悪いのかわからないと言うような負の連鎖が起こってしまうからです。
しかし今回話したいのは「環境構築を頑張ろう！」と言うのではなく、私のような初心者が絶対意識して欲しいのがチュートリアルなどの見ている教材に合わせた環境構築をすることです。
具体的にいえば***バージョンを揃える***と言うことです。

#バージョンに注意！！
私は今まで環境構築するときに限らず何においても最新が一番良いと言う考えでした。
しかし、バージョンと言うのはより便利にしていくものなので必要ないものは消されたり、新しい機能が追加したりしていきます。
ということは、以前できたことができなくなる、使い方が変わったということはたくさんあります。
私たち初心者は「きちんと手順通りに進めているのになんでこんなにエラーが出るのか」と悩むことが多くあると思います。
その時には進めている教材とバージョンが同じかどうかを確認するようにしましょう。

#おわりに
プログラム初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正しますのでどんどん指摘してください。
MySQLのカラム名、本当にそれで大丈夫ですか?


今回は、自分で作ったデータベースから情報を取りだそうとしたときに発生した問題についてお話しします。
#事の発端
データベースにある情報を全て取得し一覧として表示させるために、まずはSQL文を書こうとしました。
しかし、調べていくうちにSQLインジェクション対策なるものをしないと危ないとのことなので、SQLインジェクションを実施しようとしました。
まさか数日もかかることも知らずに…
#SQLインジェクションって?
SQLインジェクションは、データベース上に悪意のある人物が不正な操作をして改ざんしたり情報を盗み出したりされることです。
つまり、対策をしないとデータベースを攻撃され危険な状態になります。
そのため、SQL文を書く以上は対策が必要となります。
対策方法はいくつかありますが、私は静的プレースホルダを使うようにしました。
静的プレースホルダについて詳しく知りたい方は、他の記事の方が分かりやすいので探してみてください。
#静的プレースホルダを作成!しかし…
ここから、データベースに接続したり、静的プレースホルダを使うためのオプションを設定したりしますが、説明は割愛させていただきます。
上記が終わって、SQL文を実行するために名前付きプレースホルダを作ってバインドさせて実行させました。

```php
    $prepare = $dbh->prepare('SELECT * FROM 
    テーブル名 WHERE ○○ = ○○);
    $prepare->bindValue(':○○', (int)$○○, PDO::PARAM_INT);
    $prepare->execute();
```
上記が書いたコードです。
ここまで書いて思ったのは、全部のデータを表示させたいのにWHEREで指定したくないなということです。
でも何か書かないと対策できないので何か入れることにしました。
そこで、データベース上で登録させる度にデフォルトで「1」の数字を入れる**all**というカラムを追加させて、**all**に「1」と付く物があれば表示するようにすれば、全てのデータを取得できるのではないかと考えました。

```php
    $all = 1;
    $prepare = $dbh->prepare('SELECT * FROM テーブル名 WHERE all = :all');
    $prepare->bindValue(':all', (int)$all, PDO::PARAM_INT);
    $prepare->execute();
```
以上のように書きました。
後はfetchメソッドを使ってテーブルにechoさせれば表示できるなと思っていました。
しかし、全部コードを書いてもテーブルが表示されません。
「どこか間違えているのか?」と思って探しても、特に間違ったところは見つかりませんでした。
どの場合だと正しく動くのかなといろいろ試してみたとき、WHEREに他のカラム(年齢が書かれているageカラム)を入力して$allの中の数字を「24」にしてみると、ageが24のデータがしっかり出てきました。
これは実に奇妙なことです。
だって**allのときは何も表示されないのにageのときは問題なく表示される**のですもの。
#原因はまさかのカラム名!?
気になって他のカラムも試してみましたが、他のカラムも特に問題なく表示できました。
表示されないのはallのときだけ。
ここで、「allという文字は何か別の文字として反応しているのではないか?」ということに気づきました。
そして、データベースのallというカラムを**allNumber**という名前に変えてみました。

```
   all → allNumber
```


```php
    $allNumber = 1;
    $prepare = $dbh->prepare('SELECT * FROM 
    テーブル名 WHERE allNumber = :allNumber');
    $prepare->bindValue(':allNumber', (int)$allNumber, 
    PDO::PARAM_INT);
```
名前を変えた後、PHPコードも変えました。(本当に変える必要があるのはSQL文にあるWHEREの次のallNumberだけです)
すると、無事に全てのコードを表示することに成功しました。
#追記
どうやら、**all**という文字は「予約語」と呼ばれる特別な取り扱いが必要な文字のようです。
予約語と同じカラム名にする場合は、予約語を囲むと正しく動きます。
予約語の一覧は[予約語(https://dev.mysql.com/doc/refman/5.6/ja/reserved-words.html)](https://dev.mysql.com/doc/refman/5.6/ja/reserved-words.html)からご確認ください。
情報提供してくださいました[rana_kualu](https://qiita.com/rana_kualu)さん、ありがとうございます。
#最後に
この問題はプレースホルダについて調べても出てこないので、完全に手探りで自分のコードがどう動くかの確認をする必要がありました…
~~そのため、これからカラムを作ろうと考えている方は、**「all」**という名前を付けないようにしましょう。
また、同じように`NGネーム`などありましたら指摘していただけると助かります。~~
`追記`
予約語を囲えば正しく機能するので、カラム名を囲むようにしてみるとうまく動作すると思います。
プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正するのでどんどん指摘してください。
Gitlab project import exportのバージョン違いで困ったことありませんか

# GitLab project Import/Export

GitLabにはProjectのimport/export機能があります。
しかし、GitLabのバージョンによってexportしたファイルがimport出来ない場合があります。

| GitLab version | Import/Export version |
|:--|:--|
| 11.1 to current | 0.2.4 |
| 10.8 | 0.2.3 |
| 10.4 | 0.2.2 |
| 10.3 | 0.2.1 |
| 10.0 | 0.2.0 |
| 9.4.0 | 0.1.8 |
| 9.2.0 | 0.1.7 |
| 8.17.0 | 0.1.6 |
| 8.13.0 | 0.1.5 |
| 8.12.0 | 0.1.4 |
| 8.10.3 | 0.1.3 |
| 8.10.0 | 0.1.2 |
| 8.9.5 | 0.1.1 |
| 8.9.0 | 0.1.0 |

出典：https://docs.gitlab.com/ee/user/project/settings/import_export.html

せっかく、exportしたけれどの新しいGitLabへimport出来なかった！という方がいらっしゃらないでしょうか。

私も移行しようと思ったのですが、この問題で残念な思いをしたことがあります。


そんな時は自前でdockerを使って、bundle exec rake db:migrate RAILS_ENV=productionしちゃいます。

すでにProject import/exportができるバージョンでしたら、同じimport/exportバージョンのGitLabをdockerで立ち上げて、該当Projectをimport。
GitLabのdockerイメージをバージョンアップしたいバージョンまでアップデートします。
（基本的にはdocker runするだけ）

dockerイメージは基本、起動時にdb:migrateを実施するようになっていますので、GitLabのアップデートがすんなり出来ます。

アップデート後は再度exportすることで、import/exportのバージョンを合わせることができます。

GitLabもv11.9.0がリリースされましたし、exportして新しいGitLabを試してみてはいかがでしょうか。
doc2vecの引数documentsでのtagの設定方法

pandasに入ってるデータをdoc2vecで利用する方法ではまったのでメモ。
#１．背景
doc2vecはdocomentsとしてdocとtagを設定可能(TaggedDocument(doc, [i])の部分)。
tagがあると分散表現と文章見出しとが対応づけられて記憶されるから後から利用しやすい。


#２．はまった部分
最初は[チュートリアル](https://radimrehurek.com/gensim/models/doc2vec.html#gensim.models.doc2vec.TaggedDocument)通り
documents = [TaggedDocument(doc, [i]) for i, doc in enumerate(df['~~'])]
と書いていた。
が、これだと、学習済のmodelを別のプログラムでloadすると、元の文章の見出しとの対応が消えてしまっている。
上記だと
1 [0.001 0.002 0.003・・・]
2 [0.200 0.221 0.223・・・]
3 [0.300 0.324 0.335・・・]
などと数字と配列だけで記憶されてしまった。

#３．修正
そのため、pandasのiterrowsを使って、リスト内包表記でなく
TaggedDocument(doc, [i])の部分を
TaggedDocument(v['～～'], v['＊＊']) #~~や＊＊はpandasの列名
としてappendするように変更した。

    # doc2vecの関数
    def calc_doc2vec():
        #word2vecはdocumentとtagのセットが必要なのでpandasのiterrowsで作成  
        documents=[]
        for _, v in df.iterrows():
            documents.append(TaggedDocument(v['～～'], [v['＊＊']]))
        model = gensim.models.Doc2Vec(documents=documents, min_count=min_count, alpha=alpha, epochs=epochs, sample=1e-5)
        return(model)

でうまくいった。

#４．その他
もしかしたらDoc2Vecの引数で何とかなるかも。
enumarateとiterrowsはどちらが高速に実行されるのか気になる。
CentOSにyumでNodeJS最新版をインストール(NodeSource)

NodeJSで開発したアプリケーションを運用するために
CentOSに最新版(またはLTS)のNodeJSをインストールする手順です

パッケージマネージャ`yum`を使ってインストールしたいところですが
EPELリポジトリで提供されているnodejsは
バージョンが古めのLTS v6.xとなっています
※v6.xは2019年4月にサポート終了(EOL)予定となっています

そこでNodeJS公式サイトでも[案内されている](https://nodejs.org/ja/download/package-manager/#debian-and-ubuntu-based-linux-distributions-enterprise-linux-fedora-and-snap-packages)
[NodeSource](https://github.com/nodesource/distributions/blob/master/README.md)のリポジトリを追加してyumインストールします

### yumのリポジトリを追加

[ここ](https://github.com/nodesource/distributions/blob/master/README.md#installation-instructions-1)に記載されている１行のコマンドを実行します
最新版v11.xをインストールする場合

```
$ curl -sL https://rpm.nodesource.com/setup_11.x | bash -
```
※異なるメジャーバージョンのNodeJSをインストールする場合は上記コマンドのURLの数字部分が変わる

私の環境ではこのシェルスクリプトを使ったインストール方法では
エラーとなりうまくいかなかったので
シェルスクリプト実行時に出力されていたURLから
直接rpmをインストールしました

```sh:RPMファイルを直接インストールする場合
$ sudo yum install https://rpm.nodesource.com/pub_11.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm
```



```sh:インストール後のyumリポジトリディレクトリ
$ ls -1 /etc/yum.repos.d
CentOS-Base.repo
CentOS-CR.repo
CentOS-Debuginfo.repo
CentOS-Media.repo
CentOS-Sources.repo
CentOS-Vault.repo
CentOS-fasttrack.repo
epel-testing.repo
epel.repo
nodesource-el7.repo  ←←←追加されています
```

### NodeJSのインストール

yumでNodeJSをインストール

```
$ sudo yum install nodejs -y
```

```sh:インストールされたバージョンを確認
$ node -v
v11.12.0
```

#### npmを最新版にする

```
$ sudo npm update -g npm
```
※グローバルにインストール/アップデート/削除する場合はsudoで実行します

```
$ npm -v
6.9.0
```

#### パッケージをグローバルインストールする

npm代替のパッケージマネージャとして人気の[Yarn](https://yarnpkg.com/lang/ja/)をインストールする場合

```
$ sudo npm install -g yarn
```

```
$ which yarn
/usr/bin/yarn
```

#### Global install (yarn)

```
$ sudo yarn global add (パッケージ名)
```

例として、人気のNodeJSプロセスマネージャ[PM2](https://github.com/Unitech/pm2)をインストールしてみます

```
$ sudo yarn global add pm2
```

```
$ which pm2
/usr/local/bin/pm2
```
※yarn global addでインストールしたコマンドは/usr/local/binにインストールされました
IBM Cloud Container Registryのjp.icr.ioからイメージをプルする

# 経緯

最近IBM Cloud Container Registryでにjp.icr.ioドメインができたのですが、そこにpushしたイメージに対応したimagePullSecretがないためにIBM Cloud Kubernetes Serviceでpullできなかったので対応方法をメモ。

# 事象と原因

IBM Cloud Kubernetes Service（以下、IKS）のクラスタを作成すると自動的にIBM Cloud Container RegistryのためのimagePullSecretが作成され、それがdefaultネームスペースのdefaultサービスアカウントに紐づけられます。

```
$ kubectl describe sa default -n default
Name:                default
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  bluemix-default-secret                  # こやつ
                     bluemix-default-secret-regional         # こやつ
                     bluemix-default-secret-international    # こやつ
Mountable secrets:   default-token-zpj7t
Tokens:              default-token-zpj7t
Events:              <none>
```

こやつらは、IBM Cloud Container Registryに最近誕生したjp.icr.ioに対応していないようです。そのため、jp.icr.ioにpushしたイメージをpullしようとすると、コンテナ作成時に401エラーが発生してしまっています。

# 対応手順

素直にjp.icr.ioが使えるTokenを生成してしまいます。

## Tokenの作成

```
$ ibmcloud cr token-add --non-expiring

Requesting a registry token...

Token identifier   ********
Token              ****************************************************
```

## Secretの作成

```
$ kubectl create secret docker-registry jp-icr-secret --docker-server=jp.icr.io --docker-username=token --docker-password=${上で取得したToken値} --docker-email=${適当なメールアドレス}
```

## サービスアカウントにパッチ

```
$ kubectl patch serviceaccount/default --type='json' -p='[{"op":"add","path":"/imagePullSecrets/-","value":{"name":"jp-icr-secret"}}]'

$ kubectl describe sa default -n default
Name:                default
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  bluemix-default-secret
                     bluemix-default-secret-regional
                     bluemix-default-secret-international
                     jp-icr-secret                         # 追加
Mountable secrets:   default-token-zpj7t
Tokens:              default-token-zpj7t
Events:              <none>
```

これでイメージがプルできるようになります。もちろん必要に応じてそれぞれのネームスペースで実施が必要です。また、パッチせずにspecでimagePullSecretsを指定してもいいでしょう。

# もっといい方法？

IKSではIAMと紐づいてpullSecretが作れるようなのですが方法がさっぱりわからなかったのであきらめました。
update_columnとupdate_columnsの違い

- 特定の行の特定のカラムを更新する。
- 直接SQLが発行されバリデーションやコールバックは走らない。
- 更新日時だけを更新したい場合や、コールバックを走らせたくない場合に便利。

### 単数の場合
```
article.update_column(:title, 'title')
```

### 複数の場合
```
article.update_columns(hoge: "hoge", fuga: "fuga")
```

### 参考

- https://sakurawi.hateblo.jp/entry/update_attributes
- [update_column(name, value)](https://api.rubyonrails.org/v4.2/classes/ActiveRecord/Persistence.html#method-i-update_column)
- [update_columns(attributes)](https://apidock.com/rails/ActiveRecord/Persistence/update_columns)
- [Railsのupdate_columnsとupdate_countersのまとめ](http://o.inchiki.jp/obbr/230)
Lycheesyncを使う＋おまけ

# 概要
ここでいうLycheeは写真とか画像ファイルを管理・閲覧するためのネットワーク上で使えるツール（アプリ）のことです。このLycheeに関してはインストール方法がQiita含めいくつかのサイトで紹介されています。
しかし今日はLycheeのプラグインであるLycheesyncを試してみたのでその使用法およびレポートを簡単に書いていきます。あとLycheeに関するおまけなど。

* Lychee → https://lychee.electerious.com/

# 詳細
## Lycheesyncとは
よく見たらREADME.mdの一番下に書いてありますね。

> lycheesync	Sync Lychee with any directory containing photos	[More »](https://github.com/GustavePate/lycheesync)

この[More](https://github.com/GustavePate/lycheesync)の先にあるツールで、プラグインといってもLycheeの機能が拡張されるわけではなく、Lycheeのためのコマンドです。
通常Lycheeでは画像の追加はブラウザの画面で何らかの操作をすることで行っていきますが、このコマンドツールを使うことで特定のディレクトリにある画像をすべて（除外設定されたもの以外）アップロードでき、さらにそのあとディレクトリ内に画像を追加したときに、再度ツールを実行することで追加分だけをアップロードしたり挿入したりできます。
動作としてはLycheeが使うMySQLのデータベースをもりもり書き換える感じです。

## install
検証環境:

項目 | 内容（バージョン）
---|---
OS | Linux Mint 19.1 (Tessa) (x86)
Lychee | 3.1.6 (master)
PHP | 7.2.15-0
Python | 3.5.7

おおまかには以下にあるとおりです。
https://github.com/GustavePate/lycheesync
依存ライブラリに関して。そこそこいじられた環境ではある程度入っているものばかりですが、私の環境ではとりあえず```pillow, libjpeg-dev```の追加インストールが必要でした。あとはpython系に関しては……venvを使うのでとりあえず一通り言われたとおりにいれてみればいいと思います。リポジトリに書いてあるとおり、lycheesyncブランチのなかにpipでいれるものリストがあるので```pip install -r requirements.txt```してしまえば良いです。
（リポジトリの説明ではpyvenvを使っていますが標準のvenvでOKです。）

## configuration
これも書いてあるとおりですが、lycheesyncフォルダ内にある```ressources/conf.json```に必要なことを書いてあげます。

## command
書いてあるとおりですね。私の実行例は下記。
> python -m lycheesync.sync /home/user/Program/git/Lychee/uploads/import /home/user/Program/git/Lychee ./ressources/conf.json

# 考察
## MySQLへの登録idがおかしい（issue）
ということがあった。詳細は下記に書いておく。
https://gist.github.com/hakua-doublemoon/86abe780fb26e6921c587c796874380c
ただしlycheeのソートの設定をすれば気にならないので、リポジトリもそんなに活動してないみたいだし、公式にissueにはしない。
まあ個人的には下手にid振るよりこうしてSerialにしてしまえばいろいろ困らないと思ってはいる。

# 所感
* 基本的にはなかなか使える子だと思います。lycheeの画面から画像をimportするのが面倒だったので捗りそうです。
* 上記の問題を解決するために久々にSQLについて真面目に考えました。
* また下記のおまけに関してはjavascriptとにらめっこするはめになった。

# おまけ（lycheeそのものに関して）
## スマフォで見るときにスワイプ量を少なくしたい
* lycheeはスマフォではスワイプ操作で画像を変えられる賢い子ですが、一般のそういったビューワーに比べてスワイプ量が大きいです。
  + 私のExperiaで画面の半分ぐらい……
  + 指が疲れる
* 対処方法は、```dist/main.js```にある```tolerance:150```の値を50ぐらいにしてやること。
    + 変更後はブラウザのキャッシュを一度消さないとブラウザがロードしているjsが更新されないです。
Pythonで2019年の楽天打線組んだwww

## サマリー

* プロ野球開幕直前
* 今シーズンの楽天イーグルスの攻撃力について、Pythonで打線を組むシミュレーションプログラムを作成して、予想してみた
    * 個人的に、浅村選手が加入した影響がどのくらいなのか気になっていたので...
* 2018年の打線と2019年の打線を比較しました
    * 結果は最後に...

----

## 昨年の振り返り

[リーグ情報（セ・パ）2018年 | Baseball LAB［ベースボールラボ］プロ野球×データ](http://www.baseball-lab.jp/league/2018/)

* 順位 : 6位(勝率.414)
* 失点 : ３位(583失点)
 * 岸・則本らの活躍もあり、守備面はリーグ中位であった
* 得点 : 6位(520得点)
 * 攻撃面が良くなかった
  * アマダーはドーピング、ウィーラーは怪我

----

## 2018年の楽天打線
|打順|背番号|名前|打率|ホームラン|打点|
|:---|:---|:---|:---|:---|:---|
|1|25|田中　和基|0.265|18|45|
|2|5|茂木　栄五郎|0.247|7|24| 
|3|35|島内　宏明|0.292|11|53|
|4|8|今江　年晶|0.276|10|49|
|5|33|銀次|0.276|5|48|
|6|40|ウィーラー|0.269|15|58|
|7|6|藤田　一也|0.266|4|16|
|8|54|ペゲーロ|0.233|17|44|
|9|37|嶋　基宏|0.206|0|21|

[2018年楽天打線 - 日本プロ野球RCAA&PitchingRunまとめblog](http://ranzankeikoku.blog.fc2.com/blog-entry-2593.html)より

* 3割・30本を打った選手はゼロ
* これでは点にならない...

----

## 2018年のオフ

埼玉西武ライオンズから、[浅村栄斗](https://www.rakuteneagles.jp/team/player/detail/2019_3.html)選手を獲得

|名前|打率|ホームラン|打点|
|:---|:---|:---|:---|
|浅村　栄斗|0.310|32|127|

3割 30本を打っている、超一流選手です。

----

## 疑問？

浅村選手の加入により、どのくらい得点力が上がるのか？

↓

そうだシミュレーションしてみよう

----

## 手法

1. [昨年の実データ](http://npb.jp/bis/2018/stats/idb1_e.html)をもとに、各打者の確率を算出

* ヒット
* 二塁打
* 三塁打
* ホームラン
* 四死球
* アウト(三振・ゴロ・フライ)

2. これを実際の試合と同じく 3アウト * 9イニングすれば、1試合の得点になる

3. 試合を143試合すれば、1年間の総得点がわかる

というプログラムをPythonで作成しました。

----

## シミュレーションのルール

* ランナーの進塁はヒットの分だけ(ランナー2塁からのヒットは1・3塁とする)
* 143試合では値のばらつきが大きいので、143*10000試合の平均とする
* 送りバントなし
* 犠牲フライなし
* 併殺打なし

----

## 2018年の楽天打線シミュレーション

|打順|背番号|名前|打率|ホームラン|打点|
|:---|:---|:---|:---|:---|:---|
|1|25|田中　和基|0.265|18|45|
|2|5|茂木　栄五郎|0.247|7|24|
|3|35|島内　宏明|0.292|11|53|
|4|8|今江　年晶|0.276|10|49|
|5|33|銀次|0.276|5|48|
|6|40|ウィーラー|0.269|15|58|
|7|6|藤田　一也|0.266|4|16|
|8|54|ペゲーロ|0.233|17|44|
|9|37|嶋　基宏|0.206|0|21|

* 実際の値 520得点 / 143試合 = 3.636点 / 試合
* シミュレーション値 = 3.405点 / 試合

----

## 2019年の楽天打線シミュレーション

|打順|背番号|名前|打率|ホームラン|打点|
|:---|:---|:---|:---|:---|:---|
|1|25|田中　和基|0.265|18|45|
|2|5|茂木　栄五郎|0.247|7|24|
|3|3|浅村　栄斗|0.31|32|127|
|4|40|ウィーラー|0.269|15|58|
|5|35|島内　宏明|0.292|11|53|
|6|33|銀次|0.276|5|48|
|7|69|ブラッシュ|0.233|17|44|
|8|36|内田　靖人|0.198|12|25|
|9|37|嶋　基宏|0.206|0|21|

* 予想スタメンは[プロ野球オール写真選手名鑑 2019 (NSK MOOK)](https://www.amazon.co.jp/dp/4905411637/)のものを使用

* 新加入の浅村選手は西武時代の成績を使用
* 新加入のブラッシュ選手は2018年ペゲーロ選手の成績を使用
	
----

## 2019年の予測値

* 3.77点 / 試合
	* 2018年のシミュレーション値 3.405点 / 試合 から上昇
* シーズンでは 52.195 点の増加
	* 昨年あと+52点あれば、リーグ４位の得点力だった

----
	
## まとめ

* 浅村選手の加入は予想よりも影響が大きかった
* 今年は3位以内も狙えそうである
* 浅村選手を何番で起用すると良いのかも検証してみたい
three.jsのGeometryからBufferGeometryへの書き換えで躓いたところ

最近作っていたthree.jsでの作品で軽量化を図ろうと`Geometry`を`BufferGeometry`というものに書き換える作業がありました。
その中でも特にジオメトリの頂点をいじる時に迷った点がいくつかあったのでここに残しておきます。

#BufferGeometryについて
`BufferGeometry`は通常の`geometry`よりもより効率的な表現ができるみたいです。
いろいろな方の情報を見てみると生のwebGLを触る感覚で制御できるだとか。(知らなかった)
ただ、公式リファレンスにも書いてある通り、通常のジオメトリのほうが弄る分には楽らしいですね。

#わざわざこれを使う必要があるの？
実際、これを使わなくても通常のジオメトリでほぼ同じ処理はできます。
ただ、より多くの頂点がある場合には処理速度に差が出るので、Three.jsのページが重くなった時の改善策の一つとなりそうなので覚えておこうと思いました。

#通常のジオメトリとの違い
大きな違いとしてはバッファジオメトリは頂点などのデータを`BufferAttribute`を通して行うようです。
##インスタンス生成
通常のジオメトリ制作に関してはこのような形式になります。

```javascript:通常のジオメトリ
var geometry = new THREE.Geometry();

geometry.vertices.push(
	new THREE.Vector3( -10,  10, 0 ),
	new THREE.Vector3( -10, -10, 0 ),
	new THREE.Vector3(  10, -10, 0 )
);

geometry.faces.push( new THREE.Face3( 0, 1, 2 ) );

geometry.computeBoundingSphere();

```
そして`BufferGeometry`の場合は下記のとおりです。

```javascript:バッファジオメトリ
var geometry = new THREE.BufferGeometry();
var vertices = new Float32Array( [
        -10.0,  10.0,  0,
        -10.0, -10.0,  0,
         10.0, -10.0,  0,
] );
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );

```  
どちらも
`var material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );`
と
`var mesh = new THREE.Mesh( geometry, material );`
を書き加えてシーンに入れてしまえば下図のような赤い三角形が見えると思います（カメラのZ座標を`100`に設定しています。）
![ss.PNG](https://qiita-image-store.s3.amazonaws.com/0/288810/9603ad00-d315-d3f6-9369-720a1f715585.png)

PlaneやBoxといったプリミティブの生成に関してはほぼ変化がありません。クラス名にbufferが付くくらいです。
生成に関する引数も変わりません。

```javascript:planeの例
//Geometry
var planeGeo = new THREE.PlaneGeometry(width, height,widthSegments,Segments);
//BufferGeometry
var planeGeo_B = new THREE.PlaneBufferGeometry(width, height,widthSegments,Segments);
```

##頂点の座標を動かす
個別の頂点を指定して動かすためには全く別のメソッドを使います。
ですが引数の考えなどはほぼ同じであるため、その点に気を遣えば特に問題はありません。

```javascript
//Geometry
geometry.vertices[i].setX(posX);
//BufferGeometry
geometry_B.attributes.position.setX( i , posX);
```

##頂点座標の変化を更新するとき
これはどちらのジオメトリにも言えますが頂点情報を毎フレーム更新するには更新の許可をする文を記入しなければいけません。
これも通常のジオメトリとbufferジオメトリで記述する文章が異なるので注意です。

```  javascript
//Geometry
geometry.verticesNeedUpdate=true;
//BufferGeometry
geometry.attributes.position.needsUpdate = true;
```
##法線情報の更新
ジオメトリの頂点情報が変化すると法線も計算しなおした方がいいでしょう。
これに関してはどちらも利用するメソッドは同じです。

```javascript
geometry.computeVertexNormals ();
geometry_B.computeVertexNormals ();
```

ただ、通常のジオメトリには

```javascript
geometry.computeFaceNormals ()
geometry.computeFlatVertexNormals ()
```

のメソッドも存在しています。

##持っている頂点の数
あとここも地味に躓いた。微妙に名前が違うんですよね。

```javascript
//Geometry
geometry.vertices.length
//BufferGeometry
geometry_B.attributes.position.count
```

#さいごに
筆者の僕もThree.jsの初心者です。
ただ、このあたりの情報に関してはほとんど情報がなかったため、同じ道を通る方のために残しておくことにしました。
もし間違っている点、説明の至らない点がありましたら、遠慮なくコメント等で指摘頂けますと幸いです。随時更新いたします。
TensorFlow YOLOv3

#Memo#

TensorFlow、TF-SlimでYOLOv3を動かしてみる。

###[ネットワークを簡潔に書けるTF-Slimとは](https://www.sejuku.net/blog/50226)###

###[TF-Slimを使ってTensorFlowを簡潔に書く](http://workpiles.com/2016/12/tensorflow-tf-slim/)###

###[TensorFlowを用いた物体検出](https://www.koi.mashykom.com/tensorflow.html)###

###[tensorflow-yolo-v3](https://github.com/mystic123/tensorflow-yolo-v3/blob/master/README.md)###

###[Implementing YOLO v3 in Tensorflow (TF-Slim)](https://itnext.io/implementing-yolo-v3-in-tensorflow-tf-slim-c3c55ff59dbe)###

_I couldn’t find any implementation suitable for my needs on GitHub, thus I decided to convert this code written in PyTorch to Tensorflow._

適当な実装が見つからなかったので、下記のPytorchのそれを、TensorFlow用に書き直したらしい、すげ〜

[How to implement a YOLO v3 object detector from scratch in PyTorch](https://blog.paperspace.com/how-to-implement-a-yolo-object-detector-in-pytorch/)

そう言えばこのサイトは、[ここ]()でも遭遇してた。

###[Ubuntu16.04でtensorflow-gpuを動かす](https://qiita.com/sabaku20XX/items/7c9a04fdffecee27f163)###

引用させていただきました。

- 動かしたいtensorflowのバージョンを以下のリストから探してくる。
- 動かしたいtensorflowのバージョンのテストに使われてるCUDAとcuDNNのバージョンを調べる。

https://www.tensorflow.org/install/install_sources#tested_source_configurations


#TensorFlowって何だ#

#TF-Slimって何だ#