OmniAICreator/Qiita-1.07M huggingface dataset:
Google Colab上でGitHubからCloneして変更をPushするまでのまとめ

# 何の記事？
Google Colaboratory上でGitHubのレポジトリをcloneし、変更をpushするまでのメモ。特に変わったところはないです。
ちなみにColabではノードブックに関してはコマンドを打たなくてもpushまでできる便利な機能があります。
参考記事：[Colabratoryって画面上だけでGitHubにPushして差分まで見れちゃうって知ってた？](https://qiita.com/Suguru_Toyohara/items/fd495516237b0b395768)

# そもそもColabからGithubにpushする必要ってあるの？
環境難民にとっては結構起こりえます。
あと、いちいちローカル環境でcloneするまでも無いが、既存コードをforkしてちょっとreviseして試してバージョン管理したいときなど。

# 手順
流れとしてはDriveマウント→clone→config→add→commit→origin設定→pushです。
マウントは最初の1回だけでOK。
configとorigin設定はセッション中に1回だけでOK。

## 1. Google Driveをマウントする
ご存知の通りColabは[インスタンスの12時間ルール＆90分ルール](https://qiita.com/tomo_makes/items/b3c60b10f7b25a0a5935)があるので、作業ディレクトリの内容が一定時間で消えてしまいます。
当然`.git`なども保存されず、これではコード管理もやりようがないので、まずはGoogle Driveをマウントします。
UI上で左側のファイルボタンを押し、「ドライブをマウント」でマウントできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215987/e73d862e-9c60-e8de-22c1-a1136d672288.png)
これで自分のGoogleDrive上のファイルをノートブック上で扱えるようになり、保存もできるようになります。

## 2. Clone
Google Drive上に`ColabData`というような作業ディレクトリを作ります（作らなくても良いです）。
カレントディレクトリを移動しcloneします。

```
%cd /content/drive/My Drive/Colabdata/
!git clone https://github.com/reponame.git
```

## 3. Config（ユーザ名とメールアドレスを設定）
これを設定しないとcommitで怒られます。

```
!git config --global user.email "yourmail@gmail.com"
!git config --global user.name "username"
```

## 4. Add, Commit
特に変わったところはないです。

```
!git add file.py
!git commit -m "Added new file."
```

## 5. リポジトリ情報を明示的に記述してOriginを設定
ここが若干のハマりポイントです。
git cloneした時点でリモートサーバにoriginがデフォルトで設定されるのですが、ここにpushしても下記のように怒られます。

```
!git push origin master
# fatal: could not read Username for 'https://github.com': No such device or address
```

Colabでは、下記のように明示的にoriginに認証情報（ユーザ名、パスワード）を渡して設定する必要があります。

```
!git remote set-url origin https://username:password@github.com/reponame.git
!git push origin master
```

無事pushが通れば成功です。快適なColabライフをお送りください。

#まとめ
Colab上で、git cloneからpushまでの流れをまとめました。
下記に、一連のコマンドをまとめます。

```
%cd /content/drive/My Drive/Colabdata/
!git clone https://github.com/reponame.git
!git config --global user.email "yourmail@gmail.com"
!git config --global user.name "username"
!git add file.py
!git commit -m "Added new file."
!git remote set-url origin https://username:password@github.com/reponame.git
!git push origin master
```

以上です。
blocklyでobjectを動かす。 その10

#概要

blocklyでobjectを動かして見る。
obelisk.js、やってみた。

#写真
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/eb0af3fc-ae00-2130-3eb7-c15a8ae70cb9.png)



#ステージを作る。


```
<canvas id="canvas" width="300" height="300"></canvas>
```

#ブロックを書く。

```
Blockly.Blocks.say = {
	init: function() {
		this.jsonInit({
    		message0: "say x %1 y %2 z %3",
	    	args0: [{
        		type: "input_value",
		        name: "x",
		        check: "Number",
	        	align: "RIGHT"
        	},{
	        	type: "input_value",
	        	name: "y",
	        	check: "Number",
	        	align: "RIGHT"
	        },{
	        	type: "input_value",
	        	name: "z",
	        	check: "Number",
	        	align: "RIGHT"
		    }],
		    previousStatement: null,
		    nextStatement: null,
		    style: "text_blocks",
		    tooltip: Blockly.Msg.TEXT_PRINT_TOOLTIP,
		    helpUrl: Blockly.Msg.TEXT_PRINT_HELPURL
	    })
    }
};

```

#フローを書く。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/ccd32294-e46e-21f6-b179-3e6b253d8657.png)


#objectを書く。


```

Blockly.JavaScript.say = function(a) {
   	var b = Blockly.JavaScript.valueToCode(a, "x", Blockly.JavaScript.ORDER_COMMA) || 0,
		c = Blockly.JavaScript.valueToCode(a, "y", Blockly.JavaScript.ORDER_COMMA) || 0;
	    a = Blockly.JavaScript.valueToCode(a, "z", Blockly.JavaScript.ORDER_COMMA) || 0;

    return "k0.saa(" + b + "," + c + "," + a + ");\n"
};

var canvas = document.getElementById('canvas');
var point = new obelisk.Point(100, 100);
var pixelView = new obelisk.PixelView(canvas, point);
var kame = function(pixelView) {
    this.pixelView = pixelView;
};
kame.prototype.saa = function(x, y, z) {
    var p3d = new obelisk.Point3D(30 * x, 30 * y, (32 + 1) * z);
    var cubeDms = new obelisk.CubeDimension(30, 30, 32);
    var cubeColor = new obelisk.CubeColor().getByHorizontalColor(obelisk.ColorPattern.getRandomComfortableColor());
    var cube = new obelisk.Cube(cubeDms, cubeColor, false);
    this.pixelView.renderObject(cube, p3d);
};
var k0 = new kame(pixelView);
```

#成果物

https://embed.plnkr.co/plunk/MzkzFx6XPvT9OSHb


以上。
iOSデバイスでプログラミング環境構築




### 今時机やPCの前だけで作業できる環境はナンセンスでしょ？！
スキマ時間の有効活用や職場にラップトップ、タブレットを持ち込めないとき、旅行などのための環境構築です。
PCが壊れても別の端末ですぐ作業開始できる環境が大事。
布団の中でゴロゴロしながらもプログラミングできますし
旅先で重たいラップトップなんか持ちたくない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208182/cb657862-d46e-9737-849e-9e3822b709e1.png)

[ブログ](https://noblogrammar.com/setup-ios/)に引っ越しました。
アラフィフの素人VBAリーマンが、次に取り組むものは

#EXCEL-VBAに飽き足らない

会社でもEXCELを使った仕事は今更ながら多すぎる

そこでVBAを覚えて、いろいろプログラミングの模索をしているのであるが・・・

実際のところ、そろそろ限界である。

最近はＵＩＰＡＴＨなどの、ＲＰＡツールがＶＢＡの次に使われるものと
言われているが・・・


#Win32Api

さてＶＢＡを拡張しようと思ったら、まっさきに取り組むのはＤＬＬ開発である。

ＤＬＬというのは、コンパイル済みのＥＸＥファイルで、
そこに関数などを書いておけば、これをＶＢＡから使うことができる。

さて仕事で、使うとなったら、どんな時が考えられるだろう？

・画像処理
・ＡＩ処理
・ＲＰＡ処理（いわゆるＥＸＣＥＬアプリケーションの外側の開発）


#勉強法

そんなわけで、いきなりプログラム開発環境が必要になるのであるが、
なにせ最新のVISUAL　STUDIO　2019をインストールしても、
そもそもVBA拡張を素人がやっている時代は、もう10年も前である。

ゆえに、最新のＩＤＥを入れても、そもそもチンプンカンプンなのである。

それに、最近のトレンドは、WINDOWSよりも、ＷＥＢの方にシフトしているので、
そもそも時代錯誤もはなはだしいのである。

#オープンソースの活用

画像処理系で言えば、ＯＰＥＮＣＶを使いこなすことが、一番良い。

しかしながら、ＯＰＥＮＣＶはｃ＋＋、ＰＹＴＨＯＮを正式にカバーしているが、
そうなると、入りやすい順番で言えば、ＰＹＴＨＯＮ一択になってしまう。

この時に困るのが、ＷＩＮＤＯＷＳでＰＹＴＨＯＮを動かす環境を
作る必要がある。

特に、仕事での使用だと、素人が作ったアプリをわざわざＰＹＴＨＯＮを入れて
使ってもらうことは、ハードルが高すぎる。

その選択としては、ＷＥＢアプリにしてしまって、ＰＹＴＨＯＮ処理を
隠蔽してしまうことが手っ取り早い。

なので、それが選択できるような状況であれば、そこそこＰＹＴＨＯＮを使えばいいだろう。

#ＷＥＢアプリ開発

さて、気軽にＯＰＥＮＣＶや、ＡＩ開発と言ったことに取り組むのは楽だ。
しかしながら、いざアプリとしてサービス構築するとなると、
この先には、地獄の覚悟が必要である。

まずＷＥＢを立ち上げるのに、ＰＹＴＨＹＯＮでサーバーを書く必要がある。
そのためには、ＦＬＡＳＫやＤＪＡＮＧＯと言ったフレークワークの勉強が必要である。

その後に、クライアント側を構築するにあたっては、
ＨＴＭＬ，ＣＳＳ，ＪＡＶＡＳＣＲＩＰＴ（Ｊクエリー）などと言う
いまどきの言語を総ざらいする必要がある。
（正直言って、ＶＢＡからスタートした素人では、少なくとも3か月はかかるだろう）

#ｃ＋＋

そこで、いまさらながら舞い戻ってくるのであるが、
デスクトップアプリの方であるが、これがまたまた難解である。

何故かというと、VISUAL　STUDIOというツールを完璧に使いこなす必要がある。

このソフトが一筋縄に行かないのは、マイクロソフトのWINDOWS技術を
完全に理解しないとならない。


それこそｃ＋＋と言えば、ＷＥＢ技術が一般になる前の言語なので、
いわゆるフレームワークが古い。

最近は、．ＮＥＴというフレームワークが一般的であるが、
．ＮＥＴはｃ＃、ＶＢしかサポートしていないからだ・・・

それにＥＸＣＥＬにはバージョンがあって、３２ｂｉｔと６４ｂｉｔで
せっかく作ったライブラリが動かなくなったりして、
いわゆる最新技術のフレームワークで、そもそもコンセプトの古い
ＥＸＣＥＬ，ＶＢＡをマッチさせるのは、至難の業になってくる。

#取り組むべきもの

さて、こういう風につらつら、書いてきたが、
ＶＢＡの次に取り組むものとしては、やはり現時点では、
ＯＰＥＮＣＶをｃ＋＋で使いこなすのが、
最優先になってくる。

#c#というもの

さて、ｃ＋＋の前に、C#は一体なんぞや？
という疑問が出てくる。

そもそも、ＶＢＡを知っている人間からすれば、実はＣ＃ではなく
ＶＢの方が、入りやすいのではないかと思ってしまう。

しかしながら、世の中の流れなのか、はっきり言って、ＶＢ．ＮＥＴでの
入門は、すごく危険である。

とにかく実行速度が、遅くなるらしくて、．ＮＥＴの技術を
使いこなすのであれば、その経過でＶＢを触るのもありである。

しかしながら、最終的にはＣ＃を触ることが、一つの選択にはなってくる。

#OPENCVSHARP

一応C++の関数を、C#でも使えるようにする、ライブラリが世の中には存在する。

しかしながら、そもそもｃ＋＋でのコンパイラも使いこなせないものが
C#に飛びつくのは、かなり危険である。

C#というのは、そもそもＪＡＶＡとよく似た文法であって、
そこの世の中の流れを、マイクロソフトが対抗したものだ。

なので、C#が完全に使えるようになってくると、やっとエンジニアとしては
飯が食える状態になったと言えるのではないか。

（しかしながら、世の中と３０年以上のギャップを埋めるには、
相当の代償を払わないと、いまの現役エンジニアにはかなわないだろう）

#総まとめ

アラフィフのオッサンエンジニアが、いまから頑張ってできることは
この長い時代の技術の進化を、頑張れば数年でワープできることだ。

だから、昔の書物を入手して、最新の技術から俯瞰して、
その技術を学びなおすことが良いと思う。

これはスマホ一色の現代人が、そもそもスマホが出てくる前の
時代をタイムマシンに乗ってさかのぼっていくようなものだ。

#先人の知恵を借りるという事

いつの時代にも、学ぶべきものはある。

先人の知恵と言うものは、つねに馬鹿にはならないし、
現代人だからと言って、先人が歩いた道を知らずに、
どうやって道を切り開いてきたかの、そのエッセンスを知らずには、
この先の道を進むことはできないである。

#吉村昭の小説「漂流」

私の大好きな小説に、吉村昭の「漂流」と言うのがある。

この中で出てくる主人公は、江戸時代の船乗りで、
無人島に流れ着き、たった一人で、その困難を乗り越えて、
最終的には何十年もかけて、日本に帰ってくるという偉業を無しとげている。

もしも、仮に今の自分が、その難破船に乗った一員だったとして、
ケータイ電話も、食料も何にも持たずに乗船していたら、
いくら現代に生きて、いろんな知識を持っていたとして、
この状況で、生き抜く知恵を出すことはできない。

要するに現代人は、現代だから存在できるのであって、
江戸時代に行ってしまえば、おそらく当時の人よりは
劣っていて、時代の差と言うものは、何の優位性もないという事である。

昔の人の知恵を馬鹿にすることはできない。
つまり、今を学ぶということは、つまりそれは過去を知る。

そういうことである。

#つづき
https://qiita.com/EasyCording/items/bbfe363abf1eed542f98
【Day34】積み上げ日記

##予定
■スキプラさんnote④⑤
■Bootstrap

##完了
■スキプラさんnote④⑤

##学習時間
4h

##学習ポイント
■news-textが少しずれている
→１個前にpタグを使っていると、余白ができてしまう

■リンクの下線、色をなくす
text-decoration: none

■div.container と書くと、
div class=“container”とショートカットできる。

Bootstrap
■class=“container”>class”row”の中に、
class=“col-(prefix)―(columns)

■グリッドシステムのルール
①class="container"の中に
②class="row"の中に
③col-{prefix}-{column}の形式で
④コラムは合計で１２にする

##疑問点
○hidden {prefix}は、どのタイミングで使うのか。

##計画通り進んだか？
進まなかった。スキプラさんnoteは有益でうまく咀嚼しながら理解できた。その後のBootstrapは、思いの外便利さをを感じ、使いながらでないと理解できないなと感じたため、もう少し時間を割こうと思う。

来週までにグリッドシステムを習得し、友人の店舗サイトを作成する。

##参考サイト
■techacademy magazine
https://techacademy.jp/magazine/6270
【Python】ABC133B(右上三角形問題)【AtCoder】

プログラム初心者がつまずきそうな箇所。
重複なしの2重ループ。
俺はこれ系の問題を`右上三角形問題`と勝手に定義しているw

#[ABC133B](https://atcoder.jp/contests/abc133/tasks/abc133_b)
Difficulty:137
添字とかあると問題理解するのが大変・・・
とりあえずD次元とかいわれても想像できないので2次元でイメージする。
要は
①異なる2点間の距離の組み合わせすべて計算して
②それぞれの距離が整数かどうか
を調べればおk

##①異なる2点間の距離の組み合わせすべて計算
<img width="146" alt="スクリーンショット 2020-03-21 6.20.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183481/04ce6b4c-50f8-59c7-e215-577500f4353c.png">
異なる2点間の距離の組み合わせ
=**右上の三角形（黄色の部分！）**を全探索すればよい！だから`右上三角形問題`！！！
（A点とB点、A点とC点、・・・D点とE点）


右上三角形の全探索(5行*5列)をコードにするとこんな感じ

```python:test.py
for i in range(5):
    for j in range(i+1,5):
        #距離の計算
```
iは、0行目(A行)、1行目(B行)、2行目(C行)、3行目(D行)、4行目(E行)
iが0のときjは、`range(1,5)`→`1,2,3,4`
iが1のときjは、`range(2,5)`→`2,3,4`
iが2のときjは、`range(3,5)`→`3,4`
iが3のときjは、`range(4,5)`→`4`
iが4のときjは、`range(5,5)`→なしなのでなにも処理されません。
⇨しっかり**右上の三角形（黄色の部分！）**の10箇所(4+3+2+1+0)が全探索できてる！

ここが理解できれば、どんな右上三角形問題が来ても「もう何も怖くない」

##②それぞれの距離が整数かどうか
こっちは簡単。
`%1==0` or `is_integer`
どっちでもいいと思うよ。俺は英語苦手マンなので前者を使います。

##①＋②
まとめるとこんな感じかなぁ

```python:test.py

def LI(): return list(map(int,input().split()))
N,D = LI()
X = [LI() for _ in range(N)]
_ans = 0
for i in range(N):
    for j in range(i+1,N):
        temp = 0
        for k in range(D):
            temp += (X[j][k]-X[i][k])**2
        if temp**0.5%1==0:
            _ans += 1
print(_ans)
```
`temp = 0`の記述する場所は、問題数をこなしていけば感覚的にわかるようになると思う。
あと2点間の距離の公式は中学数学を思い出す事！


#類題 (右上三角形問題の重複なしの３重ループ問題)
これとくとより理解が深まると思います。
[AOJ(ITP1_7_B) 組み合わせの数](
https://onlinejudge.u-aizu.ac.jp/courses/lesson/2/ITP1/7/ITP1_7_B)

こんな感じ〜

```python:test.py
def LI(): return list(map(int,input().split()))
while 1:
    n,x = LI()
    if n==x==0:
        break
    _ans = 0
    for i in range(1,n+1):
        for j in range(i+1,n+1):
            for k in range(j+1,n+1):
                if i+j+k==x:
                    _ans += 1
    print(_ans)
```
この記事の本題とは外れますが、おまけのおまけの話をすると、
`k=x-i-j (kの条件：1<=k<=n and j<k)`
とおくことで2重for文で解けます！！！

**(2020/05/07 追記)**
現在は、上の3重for文の問題
`itertools.combinations`を使ってコードを書きます！
詳細はこちら！
[【Python】初中級者が解くべき過去問精選 100 問を解いてみた【Part1/22】](https://qiita.com/rudorufu1981/items/8ae8beeba7b047f2687c)

**(2020/05/26 追記)**
<img width="146" alt="スクリーンショット 2020-03-21 6.20.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183481/04ce6b4c-50f8-59c7-e215-577500f4353c.png">
※補足
上の図において

- 右上三角形の全探索
    - `itertools.combinations(range(N),2)`
- 右上三角形+斜線部分の全探索
    - `itertools.combinations_with_replacement(range(N),2)`

となります。
`itertools.combinations_with_replacement`は重複組み合わせ！！！

おわり！
Teams Live Eventを匿名で視聴する手順

# はじめに

Microsoft TeamsにはYoutube Liveのようなライブイベント配信機能があります。

本稿では、Teams Live Eventをアプリケーションをインストールせず、アカウント登録も一切不要で、匿名で簡単に視聴する手順について説明します。

なお、本当に簡単なので別に手順書が必要とは思いませんが、「簡単だ」ということを理解していただく意味でもご覧になっていただけたらと思います。

# 環境

モダンなブラウザがあれば視聴可能です。私自身はChromeおよびChromium版のEdgeで動作を確認済みです。

# 手順

まずは配信者が公開している視聴用のURLを取得し、ブラウザで開きましょう。

すると次のようにTeamsの起動許可を聞かれますので、「キャンセル」してください。

![ss07-0002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99262/92714dbd-d948-3d99-3a1a-d60e596730a3.png)

つづいて「代わりにWebで視聴する」を選択します。

![ss07-0003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99262/9400ad4f-1240-b103-5ead-12863c43a2da.png)

そして「匿名で参加」をクリックしましょう。

![ss07-0004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99262/adc5f882-42ce-5ede-e621-1bf0119c26d9.png)

すると次のような画面が開かれ、配信を視聴できます。

![ss07-0005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99262/185b39ff-bd09-2107-40e4-8cb685268557.png)

右側のQ&A欄は、配信者がQ&Aを有効にしていれば開かれます。

以上です。
簡単でしょう？
heatrapyに熱伝達+温度で入熱できる機能を追加する

## やったこと
heatrapyでの一次元非定常伝熱解析で熱伝達率と温度で入熱出来る機能を追加しました。
もともと、任意の位置への入熱は出来る仕様なので、それを利用しました。  

## 改修点

- system.pyのclass single_objectをいじってます

set_input_heat_transferで入力条件をセットして、computeで計算する際に熱を入れていきます。時間毎の温度差に応じて、各々の時間ステップで入熱しています。

```henko.py
class single_object(object):
    def __init__(self, amb_temperature, materials=('Cu',), borders=(1, 11),
                 materials_order=(0,), dx=0.001, dt=0.1, file_name='data.txt',
                 boundaries=(0, 0), Q=[], Q0=[], heat_points=(1, -2),
                 initial_state=False, h_left=50000., h_right=50000.,
                 materials_path=False):

    【中略】

        self.input_heat_transfer = False #これをTrueにすると熱伝達率+温度での入熱を入れる

    【中略】

    def set_input_heat_transfer(self,input_heat_transfer_point,Heat_transfer_coefficient,Heat_transfer_temparature):
        """熱伝達率と温度でを任意の位置へ追加します。現状、一点のみへの入熱です
        
        Arguments:
            input_heat_transfer_point {int} -- 入熱するポイントです。一番上の場合は、1です
            Heat_transfer_coefficient {float} -- 熱伝達率[W/(m2K)]
            Heat_transfer_temparature {float} -- 熱伝達に使用される温度です[K]
        """
        self.input_heat_transfer=True
        self.input_heat_transfer_point = input_heat_transfer_point
        self.Heat_transfer_coefficient = Heat_transfer_coefficient
        self.Heat_transfer_temparature = Heat_transfer_temparature

    【中略】

    def compute(self, timeInterval, write_interval, solver='explicit_k(x)',
                modeTemp=False, numFlag=0.5, modeTempPoint=1):

            #熱伝達率と温度でインプットする場合
            if self.input_heat_transfer:
                td = self.temperature[self.input_heat_transfer_point][0]
                self.Q0[self.input_heat_transfer_point] = self.Heat_transfer_coefficient * (self.Heat_transfer_temparature - td)/self.dx
                print(td,self.Q0)
```

## はまったところ  
思ったような入熱になりませんでした。理由は単純で単位のミスでありました。Q0計算のところで、self.dxで割っているところです。熱伝達率の単位は[W/(m2 K)]の場合です。

## テスト
銅でやってみました。
【インプット】

- 初期温度 : 293[K]
- 材料　：銅（物性値はheatrapyに入っている値
- 長さ : 20mm
- 境界条件：両端断熱
- 入熱ポイント：端部（x=0)
- 熱伝達率:700[W/(m2K)]
- 雰囲気温度:900[K]
- 解析時間:30秒

```heat_transfer_test.py
import heatrapy as ht
import pandas as pd
import os

if os.path.exists("heat_transfer.txt"):
    os.remove("heat_transfer.txt")
    
example = ht.single_object(amb_temperature=293, materials=('Cu',), borders=(1,21),materials_order=(0,),
                            dx=0.001, dt=0.001, file_name='heat_transfer.txt',boundaries=(0,0), Q=[], Q0=[],initial_state=False)

example.set_input_heat_transfer(1,700,900)

example.compute(timeInterval=30, write_interval=10, solver='implicit_k(x)')

df = pd.read_csv("heat_transfer.txt")
df=df.drop("heat[1](W)", axis=1)
df=df.drop("heat[-2](J)", axis=1)
df = df.set_index("time(s)")
df.plot(figsize=(15,8))
```

【結果】
よい感じですね。dtの値は注意が必要です。dtを小さくすると精度は上がりますが、解析時間が長くなります。回しながら良いdtの値を探していく必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274127/26194bdf-f5ea-6bb6-6c60-10f94a5e1cca.png)


## ソースコード
ソースコードは以下です。
https://github.com/myao9494/heatrapy
テストは、heat_transfer_test.ipynbです
初心者によるプログラミング学習ログ 268日目

#100日チャレンジの268日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
268日目は、

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>268日目<br>・webサイト模写<br>・下層ページ　2、3ページ目作成<br>・一部flexboxの並びがうまくいかない<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1241092748842643456?ref_src=twsrc%5Etfw">March 20, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Mファイルの依存関係を確認

# はじめに
今回は，mファイルの依存関係を確認する方法についてメモします。

# コード
`target.m`というファイルがどの関数やクラスに依存しているかを調べるには，以下のコードを実行します。

```matlab
file = 'target.m';                                       % 対象ファイル名を設定
flist = matlab.codetools.requiredFilesAndProducts(file); % リストの取得
disp(string(flist).');                                   % 文字列に変換し，表示
```

# おわりに
自作のライブラリの整理などを行う際にご活用ください。
また，Qiitaなどに投稿する前に確認するのにも使えるかもしれませんね。

# おまけ
必要なツールボックスについての情報が必要な場合には，以下のコードで取得できます。

```matlab
file = 'target.m';                                            % 対象ファイル名を設定
[~, plist] = matlab.codetools.requiredFilesAndProducts(file); % リストの取得
disp(string({plist.Name}).');                                 % 文字列に変換し，表示
```

# 参考文献
[matlab.codetools.requiredFilesAndProducts](https://jp.mathworks.com/help/matlab/ref/matlab.codetools.requiredfilesandproducts.html) （公式ドキュメント）
STM32CubeIDE日本語化(Ubuntu)

既にSTM32CubeIDEがUbuntuにインストールされている状態を想定

# Pleiadesをダウンロード
- [Pleiades](https://mergedoc.osdn.jp/) からLinux用Pleiadesプラグインをダウンロード

- pleiades.zipを展開する

# Pleiadesのインストール
基本的にはPleiadesのreadmeに従うがEclipseへのインストールと異なる点があるので注意

- 展開してできたplugins,featuresディレクトリを/opt/st/stm32cubeide_1.3.0にコピー

```terminal:端末
sudo cp -r features /opt/st/stm32cubeide_1.3.0/
sudo cp -r plugins /opt/st/stm32cubeide_1.3.0/
```

- /opt/st/stmcubeide_1.3.0/stm32cubeide.iniの最終行に以下追加

```ini:stm32cubeide.ini
-Xverify:none
-javaagent:plugins/jp.sourceforge.mergedoc.pleiades/pleiades.jar
```

- CubeIDEを-cleanオプションをつけて起動

```terminal:端末
cd /opt/st/stm32cubeide_1.3.0
./stm32cubeide -clean
```
# 実行例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400001/cae4bb40-7282-7438-c1f3-703fecdf4369.png)
時々忘れるので「MFA前提でAWS CLI を使う方法」をメモ

# 概要
MFAを有効にしている前提でAWS CLIを使うときの方法を忘れて、ハマる事象の回避のためのメモとリンク

# 要するに
1. aws sts get-session-tokenでキーを取得
2. exportでキーを設定
3. aws xxを打てる状態に

# 手順
AWS公式ページを見て実行するのみ。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/authenticate-mfa-cli/

# ↑だと、あまりに味気ないので
以下、追記しました。（2020/4/15）

## aws sts get-session-tokenでキーを取得
以下の環境変数に代入する値を取得します。
* AWS_ACCESS_KEY_ID
* AWS_SECRET_ACCESS_KEY
* AWS_SESSION_TOKEN

```
$aws sts get-session-token --serial-number arn:aws:iam::[アカウントID]:mfa/[ユーザ名] --token-code [6桁のコード]
CREDENTIALS	[AWS_ACCESS_KEY_IDに代入する値：20文字]	2020-01-25T12:27:52Z	[AWS_SECRET_ACCESS_KEYに代入する値：40文字]	[AWS_SESSION_TOKENに代入する値：292文字]
```
※文字数は実績から取っただけなので参考。出力仕様は[こちら](https://docs.aws.amazon.com/cli/latest/reference/sts/get-session-token.html#output)。

## exportでキーを設定
=の後ろは上で取得した値を使う

```
export AWS_ACCESS_KEY_ID=
```

```
export AWS_SECRET_ACCESS_KEY=
```

```
export AWS_SESSION_TOKEN=
```

## aws xxを打てる状態に
ベタに以下をうってみて、リストが返ってきたらOK。

```
$aws s3 ls 
```

# まとめ
とかはなし
MATLABでフォルダをそれぞれ圧縮する

# はじめに
今回は，MATLAB上でフォルダをそれぞれ圧縮する方法をメモします。

# モチベーション
研究の引継ぎ用にデータを残したかったのですがデータ容量が多すぎたため，圧縮しまくりました。

# コード
圧縮したいフォルダ群があるところまで移動して，以下を実行します。

```matlab 
listing = dir;                              % フォルダとファイルの一覧取得
folders = listing([listing.isdir] == true); %フォルダのみ抜き出す
mkdir('zip');                               % 保存先のフォルダを作成
for i = 3:length(folders)                   % 実質3つめからが実在のフォルダ
    zip(['./zip/', listing(i).name], listing(i).name); % 同名のzipファイルに圧縮
end
```

# おわりに
ディスク容量を無駄に消費しないように，普段から整理をしておくべきでした・・・。
（私と同じく）さぼりがちな方は，これを役立ててもらえれば幸いです。
macOSでUnityを開いてVRM作業をするときのメモ

### 前書き

macでVRMを触る人って相当なマイノリティなのでは？
と思うほど、ネット上に情報が少ない...

ので、自分がハマったことを色々メモしておこうと思う。
（溜まったネタ帳から逐次追記してくので、この記事も逐次更新される...）

### モデルが表示されない

元々、Unityでハイポリの3Dのモデルを開くことがそんなに多くなかったので、面を食らった。
そう、Scene/Game View でモデルが透明 or 真っ黒なのである。

- Player Settings で Metal Editor Support を有効にする
- Camera の Rendering Path を Deferred にする

で、大体解決した。
【JS】querySelectorAll()メゾッド使用時にaddEventListener()メゾットが動かなかった

# 問題
`querySelectorAll()`メゾッドでセレクタを指定して、`addEventListener()`メゾッドでクリックイベントを仕込もうとしたときです。

```js:main.js
  const target = document.querySelectorAll('nav a');
  const closeNav = function () {
    const close = document.getElementById('global-nav');
    close.classList.toggle('nav-open');
  };
  target.addEventListener('click', closeNav);
```

**`addEventListener()`が動かない…**

Consoleではこのように怒られています。
![スクリーンショット 2020-03-21 2.25.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575953/365f2882-e3d0-7d09-bae2-49ba91fe81b8.png)

`Uncaught TypeError: target.addEventListener is not a function`

どうやら`target.addEventListener`が関数(function)として認識されていないようです。

`querySelector()`ではうまく動いたのに…


# 原因
まず`querySelectorAll()`メゾッドのリファレンスを読むと
> Document の querySelectorAll() メソッドは、与えられた CSS セレクターに一致する文書中の要素のリストを示す静的な (生きていない) NodeList を返します。

とあります。
文書中の要素のリストを示す静的な (生きていない) NodeList を返す…

さらに、`querySelectorAll()`メゾッドの返値という`NodeList`を調べると

> NodeList オブジェクトはノードの集合であり、 Node.childNodes などのプロパティや document.querySelectorAll() などのメソッドの返値として用いられます。
>> NodeList は Array とは異なりますが、 forEach() メソッドで処理を反復適用することは可能です。 Array.from() を使うことで Array に変換することができます。

とありました。
このことから、**`querySelectorAll() `の返値は配列ではないがリスト状になっており、`forEach()`メゾッドを使えば処理することができる**という解釈にいたりました。

# 解決
```js:main.js
  const targetList = document.querySelectorAll('nav a');
  const closeNav = function () {
    const close = document.getElementById('global-nav');
    close.classList.toggle('nav-open');
  };
  targetList.forEach(function (target) {
    target.addEventListener('click', closeNav);
  });
```

まず`querySelectorAll() `メゾッドの返値はリストということで、`targetList`という変数名にしました。
そして、**`targetList`内のひとつひとつの要素に`addEventListener()`メゾッドが実行されるように、`forEach()`メゾッドで`targetList`を回しました。**

無事、エラーが解消され、望んだ動きをしてくれるようになりました。

# まとめ
- `querySelectorAll()`メゾッドは配列ではないがリスト状の`NodeList`を返す。
- `forEach()`メゾッドでリストの中身ひとつひとつに処理をあてることができる。

# 参照
- [MDN web docs - EventTarget.addEventListener()](https://developer.mozilla.org/ja/docs/Web/API/EventTarget/addEventListener)
- [MDN web docs - Document.querySelectorAll()](https://developer.mozilla.org/ja/docs/Web/API/Document/querySelectorAll)
- [MDN web docs - NodeList](https://developer.mozilla.org/ja/docs/Web/API/NodeList)
フォルダ構成図の作成方法

フォルダ構成図の作成方法を調べたら、何通りかでてきたのでまとめてみた。

## 環境
- Windows10 Home 

## フォルダ構成図の作成方法

### テキスト入力による作成
"けいせん（罫線）"と入力して、スペースで"┣"や"┗"に変換。
あとはこれらを組み合わせて作成。

下記の記事に変換された記号がまとまっているので、これをコピペして使うのもよさそう。
[ディレクトリ構成図を書くときに便利な記号](https://qiita.com/paty-fakename/items/c82ed27b4070feeceff6)

### コマンドプロンプトによる作成
コマンドプロンプトを開き、下記を実行。

```
tree "フォルダ構成図を作成したいフォルダのパス" /f > "ファイルの保存先"/ファイル名.txt
```
※コマンドプロンプトは、下記手順で開く。
1. Windowsキー + Rキーで「ファイル名を指定して実行」ダイアログを表示。
2. 入力欄に`cmd`と入力して[OK]ボタンを押下。

### 作図ツールによる作成
Excelの図形や[draw.io](https://www.draw.io/)で頑張って作成。

### UMLによる作成
UMLの書き方は「[PlantUML Cheat Sheet](https://qiita.com/ogomr/items/0b5c4de7f38fd1482a48)」などを参考。

UMLを実行するためのツールは、VSCodeの拡張機能やdraw.ioをなどを使用すればいい。
VSCodeでUMLを書きたい場合は、PlantUMLをインストール。
ただし、Javaの実行環境なども別途インストールしなくてはいけない。

詳しくは下記参考。
[Visual Studio Code で UML を描こう！](https://qiita.com/couzie/items/9dedb834c5aff09ea7b2)

draw.ioの場合は、先ほど説明したとおり作図機能で直接作成することもできるが、UMLを埋め込んで作成することもできる。
詳しくは下記参考。
[【動画付き】 draw.io 使い方まとめ 〜エンジニアでなくても使えるTips集〜](https://qiita.com/G-awa/items/8fd414700b68b2bcafcc)
ClusterのVRモード起動手順の違和感

### まえがき

某ウイルス騒動でリアルイベント中止が相次ぐなが、株が上がりつつある「[Cluster](https://cluster.mu)」。
色々イベントが増えてきて、ちょっとご無沙汰していたが、最近またちょいちょい使うようになった。

で、これまた先日、Oculus Link用に環境構築したので、そうだ、VRモードでやってみよう！
と思ったのだが、結構つまづいたり、起動に違和感を覚えたので、軽く纏めてみる。

### 困ったこと

私の環境はこんな感じでPCとVRのプレイ空間が離れているので、
Oculus Link してる時、Oculus Quest 側からデスクトップを操作している。

![スクリーンショット 2020-03-21 2.16.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6047/88fc3440-d5c6-a751-1634-15449a676e40.png)

当然、Clusterを起動する時、Quest側でブラウザを開いて、そこから起動をするわけだが...
__入室ボタンを押した後、Cluster側にフォーカスが移って、無限待機状態になる。__

この場合、Oculusメニューを開いてDesktop側に戻った後、ブラウザ側のポップアップからVRモードで入室、、を選んで再びCluster側に戻れば続行できるのだが、それがめちゃくちゃめんどくさい。

というのも、デスクトップ側に戻しても、定期的に強制的にCluster側にフォーカスが戻って、目的のポップアップのボタンがなかなか押せないジレンマ。。
（なおその際、__SteamVRの警告画面がCluster側に表示されて、そこで押すボタンを間違えるとClusterが終了する。__）

### 何が違和感か？

そもそも、Clusterはブラウザで "入室" ボタンを押して、Cluster.exe を インテント起動する。
そして、VRモードかデスクトップモードで起動するかのダイアログを表示して、その選択後にアプリ開始となる。

VRモードでプレイする場合、ヘッドマウントディスプレイをつけるのはそのタイミングを想定されているようだ。

が、VRのプレイ空間とPCが離れている場合、このフローに従うのがめんどくさく、
冒頭の通り、Quest側で完結する起動フローを取ると罠にはまる。

### どうなってほしいか？

- Cluster.exe アプリ内でイベント検索や入室機能を内蔵しブラウザ不要にする
- ブラウザ側の入室ボタンを押す前にオプションを選ぶようにして、ボタンを押した後にCluster側にフォーカスが移っても問題なくプレイができるようにする

のどちらかになってほしいところ。

今後、Linkではなく、Quest単体でのClusterサポートを考慮するなら前者が望ましいところだが、アプリ内にWeb実装と同じようなものを組むのは二重開発でコストがかかるので、後者が妥当かなぁというところ。
FirestoreのGeoFireStoreで任意の値をwhereで絞るクエリでハマった件

GeoFireStoreのMap型をwhereで絞るクエリで躓いたので、メモ。（３０分くらいハマった）  

## やりたかったこと
GeoFireStoreで、別途保持している任意の値をwhereで絞り込みたい。
https://geofirestore.com/index.html  

```geofirestore.ts  
interface GeoDocument {
    g: string;
    l: GeoPoint;
    d: DocumentData;
  }
```
上記のような型指定されており、下記のようにdの中に任意の値を入れられます。この時dはマップ型。

```typescript
sample = {
    ...
    d: { 
       id : 'hogehoge',
       coordinates: [35......° N, 139...° E]
    };
  }
``` 

なので、firestore公式サンプルに乗っているマップ型の場合を参考にwhere句で絞り込む

```typescript
  const geofirestore: GeoFirestore = new GeoFirestore(firestore);
  const geocollection: GeoCollectionReference = geofirestore.collection('geo');
  const ref = geocollection.where("d.id", '==', id).get();
```  

これだとなぜか取れない。
ちなみに通常のマップ型は以下のようにクエリを書くことで解決します。

```typescript
 const ref = fireStore.collection('doc').where('test.is_map','==',true).get();
```

###  解決方法=> dは記入せず、直接マップ以下のキー名で絞り込む。

```typescript
  const geofirestore: GeoFirestore = new GeoFirestore(firestore);
  const geocollection: GeoCollectionReference = geofirestore.collection('geo');
  const ref = geocollection.where("id", '==', id).get();
```  

理由がイマイチピンときていないのですが、とりあえずハマったのでメモ..
さくらインターネットのメールボックスを他のサーバサービスと併用する話

# 概要
結構時間を使ったし、あまり書いている人がいなかったのでここに残しておきます。



## 1.最初に
さくらインターネットのメールアドレスサービスが結構安い！
(月々87円)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89227/942c2293-d51a-fac0-eb9c-436c9d068f3c.png)


ということで、メールボックスサービスだけを使いたくて契約しました。
が、`MX`の設定を色々いじってもうまく行かないということで問い合わせました。

## 2.結論

結論として、こんな感じです。

```
① 対象ドメインのDNS設定を全部消す。
② メールボックスサーバへ紐付ける。
③ 再度、DNSへ他社サービスへの設定を行う。
```
(結構、設定変更が色々反映されるまで時間がかかるようなのでゆっくり行うのが吉です。)

ちなみに私はさくらで取得したドメインを使っていたため、他社の場合は異なる可能性があります。
最後に`CNAME`設定の最後の`.`は忘れないように注意！
【Linux】遺伝統計ソフトPLINKを使ってみた

#はじめに

仕事で統計遺伝学が必要になりそうなので、遺伝統計ソフトのPLINKを使ってみた。
最近、いい感じの本が出版されたんで、ハンズオンでやってみた。

[ゼロから実践する　遺伝統計学セミナー](https://www.yodosha.co.jp/yodobook/book/9784758120920/index.html)

ただ、この本はWindows用に書かれているので、Macでのやり方を備忘録的に書いていこうかなー、と。
この本いいです。

#PLINKのダウンロード
以下のページからPLINKのMacOS版をダウンロード。

[PLINK](https://www.cog-genomics.org/plink/)

Macのターミナルを起動。
ターミナル上で、``cd``コマンドで作業ディレクトリを指定する。

```sh:作業ディレクトリの指定
$ cd /作業ディレクトリのパス/
```
ダウンロードした**PLINK**（PLINK実行ファイル）を作業ディレクトリに移動する。

#PLINKの起動
ターミナル上で、``./plink``と入力する。

```sh:PLINK起動
$ ./plink
```

実行結果

```sh
PLINK v1.90b6.16 64-bit (19 Feb 2020)          www.cog-genomics.org/plink/1.9/
(C) 2005-2020 Shaun Purcell, Christopher Chang   GNU General Public License v3

  plink <input flag(s)...> [command flag(s)...] [other flag(s)...]
  plink --help [flag name(s)...]

Commands include --make-bed, --recode, --flip-scan, --merge-list,
--write-snplist, --list-duplicate-vars, --freqx, --missing, --test-mishap,
--hardy, --mendel, --ibc, --impute-sex, --indep-pairphase, --r2, --show-tags,
--blocks, --distance, --genome, --homozyg, --make-rel, --make-grm-gz,
--rel-cutoff, --cluster, --pca, --neighbour, --ibs-test, --regress-distance,
--model, --bd, --gxe, --logistic, --dosage, --lasso, --test-missing,
--make-perm-pheno, --tdt, --qfam, --annotate, --clump, --gene-report,
--meta-analysis, --epistasis, --fast-epistasis, and --score.

"plink --help | more" describes all functions (warning: long).
```

PLINKは``./plink --(コマンド) (引数)``で実行。

#ファイルの読み込み

ファイルの読み込みコマンドは``--file``と``--bfile``。
``--file``は、**ped|map**形式のジェノタイプデータを読み込む。
``--bfile``は、**bed|bim|fam**形式のジェノタイプデータを読み込む。
NGSデータは**vcf**形式が基本だけど、**ped|map**形式に変換したデータ、**ped|map**形式をバイナリ形式に変換した**bed|bim|fam**形式を使ったりする。

``--out``は、出力ファイルの名前を指定する。

今回のファイルは、作業ディレクトリ内に格納した**SNP.bed**、**SNP.bim**、**SNP.fam**の**bed|bim|fam**形式とする。
なので``--bfile``の引数は、ファイルの拡張子前の``SNP``となる。

```sh:ファイルの読み込み
$ ./plink --bfile SNP --out test
```
これを実行すると**test.log**というファイルが生成する。
このファイルはテキストエディタか、次のコマンドで開く。

```sh

$ less test.log
```

#アレル頻度の計算
``--freq``でそれぞれのSNPのアレル頻度を計算できる。

```sh:SNPのアレル頻度を計算
$ ./plink --bfile SNP --out test1 --freq
```
出力したファイルはテキストエディタか、次のコマンドで開く。

```sh

$ less test1.frq
```

#SNPのフィルタリング
解析をする前に、ゲノムデータのフィルタリングを行って、マイナーアレル（MAF）頻度が1%あるいは0.5%以下のSNPを除外する。
GWASでの御作法的な。
``--maf（数値）``で数値以下のMAFのSNPを除外する。
``--make-bed``でフィルタリング後のデータを新しい**bed|bim|fam**形式ファイルとして作成。
今回は1%以下のSNPを除外する。

```sh:マイナーアレル頻度でSNPをフィルタリング
$ ./plink --bfile SNP --out test2 --maf 0.01 --make-bed
```
Laravelでスコープ

##定義方法

scope名は必ず最初にscopeを名前の初めに付ける必要がある.
・scopeUserName
・scopeBookSerialNo
上記のようにスコープ名をつける。

```php
public function scope+名前($query, 引数)
	{
	  # 処理内容
	  return 絞り込んだビルダ(検索条件)
	}
```

##ローカルスコープ

定義したメソッドを呼び出す場合に実行することができるスコープ。
逆に定義していれば自動的にスコープメソッドが実行されるものはグローバルスコープ。

```Person.php
# scopeの定義
  public function scopeNameEqual($query, $str)
  {
    return $query->where('name', $str);
  }
```

```PersonController.php
  public function search(Request $request){
    $input_val = $request->input;
    $item = Person::NameEqual($input_val)->first();
    $params = ['input' => $input_val, 'id' => $request->id, 'item' => $item];
    return view('person.find', $params);
  }
```

##スコープを複数繋げて利用する

２種類のスコープを定義

```Model.php
  // $min(変数の値)以上のageを検索するスコープ
  public function scopeAgeGreaterThan($query, $min)
  {
    return $query->where('age', '>=', $min);
  }

  // $max(変数の値)以下のageを検索するスコープ
  public function scopeAgeLessThan($query, $max)
  {
    return $query->where('age', '<=', $max);
  }
```
下記サンプルのように条件をつなげて使う

例：ageが "リクエストで受け取った値"　〜　"値＋１０" の間のデータを取得するスコープ
()

```Controller.php
    $min = $request->input * 1;
    $max = $min + 10;
    $items = Person::ageGreaterThan($min)->ageLessThan($max)->get();
```

##グローバルスコープ
####明示的にメソッドを呼び出さなくても自動的にスコープの検索ありきで検索が実行される

1.use Illuminate\Database\Eloquent\Builder; ←Builder使えるようにする
2.bootメソッドでモデルの初期化を行う
3.bootメソッド内でaddGlobalScopeクロージャを書く
4.addGlobalScopeクロージャの中でスコープの処理を定義していく

こうすることでモデルクラスでbootメソッドがオーバーライドされる

```Model.php
use Illuminate\Database\Eloquent\Builder;

class Person extends Model
{
  // グローバルスコープ定義 //
  protected static function boot()
  {
    parent::boot();
    static::addGlobalScope('age', function(Builder $builder){
      $builder->where('age', '>', 20);
    });
  }
  ...
  ...
  ...
}
```


##Scopeクラス作成(グローバルスコープ)

複数のモデルや、その他のプロジェクトなどでも利用されるような汎用性の高い処理は```Scopeクラス```を使うと便利.

###Scopeクラスの作成
1.Scopesディレクトリ(名前は任意)を作成。
2.Scopeクラスの作成(仮でScopePersonというクラスにします)

常に20歳より年上のみを取得するスコープを作成するため下記コード記載

```Scopes/ScopePerson.php
<?php
namespace App\Scope;

use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class ScopePerson implements Scope
{
  public function apply(Builder $builder, Model $model)
  {
    $builder->where('age', '>', 20);
  }
}
```

Model側でグローバルスコープを定義
・useしてScopePersonを参照できるようにしたら```static::addGlobalScope(New ScopePerson)```してあげるだけ


```Model.php
use App\Scope\ScopePerson;

  // グローバルスコープ定義 //
  protected static function boot()
  {
    parent::boot();
    static::addGlobalScope(New ScopePerson);
  }
```

こうすることで
```Person::all();```等で複数データを取得した場合に自動的にageが20以下のものはフィルターされる
alpineのタイムゾーンを設定する

# goでtime.Now()するとUTCで困った
なにも考えず(知らずに)にdockerfileを以下のように書いていた

```docker
FROM golang:1.13 as builder
WORKDIR /go/src/hoge
ENV GO111MODULE on 
COPY go.mod .
COPY go.sum .
RUN go mod download  
COPY . .

FROM alpine:3.9  
COPY --from=builder /go/src/hoge/main /usr/local/bin/main
EXPOSE 8080
ENTRYPOINT ["/usr/local/bin/main"]
```
するとgoでtime.Now()したときにUTCが帰ってくる
サーバも当然こうなる

```sh

/ # date
Fri Mar 20 16:05:22 UTC 2020
```

WEBアプリはJSTで色々計算したいので無理やりこう書いてやれば変換できる

```golang
//jst > utc
jst, _ := time.LoadLocation("Asia/Tokyo")
now := time.Now() //utc
nowJST := now.In(jst).Format("2006/01/02")
```
と思ったけど

```golang
time.LoadLocation("Asia/Tokyo")
```
ここでzoneinfoが無いとエラーになるので
まずは無理やりmacの中のzoneinfoをコピーして今感じにdockerを修正

```docker

FROM alpine:3.9  
COPY --from=builder /go/src/go-larn/main /usr/local/bin/main
#追加
ADD ./Tokyo.tar.gz /  
EXPOSE 8080
ADD ./views /views 
ENTRYPOINT ["/usr/local/bin/main"]
```
これで無理やりgoでUTCからJSTに変換できるようになる。

と長い前置きはここまで。

## dockerを修正してtimezoneを設定
やりたいことは２つ

- timezoneの設定
- zonefileの追加

```
FROM alpine:3.9  
COPY --from=builder /go/src/go-larn/main /usr/local/bin/main
# zonefileの追加
RUN apk add tzdata
# timezoneを
ENV TZ=Asia/Tokyo
EXPOSE 8080
ADD ./views /views
ENTRYPOINT ["/usr/local/bin/main"]
```

起動後に実際にサーバに入って確認

```sh
/ # date
Sat Mar 21 01:27:02 JST 2020
```

ちゃんと修正されていますね。
あとはgoのソース直さないと・・・^^;
JavaScriptでプレビュー機能 onKeyup onchange

# プレビュー機能作成
プレビュー機能とは(名前が正しいかわかりませんが)、Qiitaの投稿時の右側の画面のように、入力すると非同期で表示がされる機能のことです。

ブログ記事を書く際や、マークダウンでの記述の場合はよく使用されますよね！
今回は基礎ということで簡単なプレビューを作成致します。

**完成品**
<img width="1413" alt="スクリーンショット 2020-03-21 1.26.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517237/e6ce807b-fd0f-bf26-641a-c626bbcbae48.png">


**HTML5**

```html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
#sampleForm,
#sampleOutput {
    padding: 150px;
    width: 25vw;
    height: 50vh;
    margin: 10px;
    /* padding: 10px; */
    border: 1px solid gray;
    border-radius: 10px;
    display: inline-block;
}
#sampleForm {
    background-color: #f0f8ff;
}
#sampleOutput {
    background-color: #00ffff;
}
#sampleForm * {
    margin: 0 0 0 0;
    vertical-align: text-top;
}
</style>
<body>
    <form id="sampleForm">
        【入力欄】
        <br />
        名前：<input type="text" name="formName" value="">
        <br />
        地域：
            <select name="formArea">
                <option selected>関東</option>
                <option>東海</option>
                <option>関西</option>
            </select>
        <br />
        年齢：
            <select name="formAge">
                <option selected>10代</option>
                <option>20代</option>
                <option>30代</option>
            </select>
        <br />
        コメント：<textarea name="formComent"></textarea>
        <br />
    </form>
    <div id="sampleOutput">
        【出力欄】
        <br />
        名前：<span id="sampleOutputName"></span>
        <br />
        地域：<span id="sampleOutputArea"></span>
        <br />
        年齢：<span id="sampleOutputAge"></span>
        <br />
        コメント：<span id="sampleOutputComent"></span>
        <br />
    </div>
    <script src="js/script.js"></script>
</body>
</html>
```

```js

// !非同期 フォームの内容の変更を特定の要素に即反映
window.onload = function () { //load イベント発生時に呼び出す関数への参照または関数式
    getValue(); //関数の中にValueを定義します。
    var $formObject = document.getElementById( "sampleForm" ); //id要素の取得
    for( var $i = 0; $i < $formObject.length; $i++ ) { //上記のidの入った変数$formObjectの配列の長さ分for分で回します
        $formObject.elements[$i].onkeyup = function(){
            getValue(); //配列で回したValueに対してKeyupされた時にgetValue関数を起動させます。
        };
        $formObject.elements[$i].onchange = function(){
            getValue();//配列で回したValueに対してKeyupされた時にgetValue関数を起動させます。
        };
    }
    document.getElementById( "sampleOutputLength" ).innerHTML = $formObject.length;
}
function getValue() { //getValue関数を定義します
    var $formObject = document.getElementById( "sampleForm" );
    document.getElementById( "sampleOutputName" ).innerHTML = $formObject.formName.value;
    document.getElementById( "sampleOutputArea" ).innerHTML = $formObject.formArea.value;
    document.getElementById( "sampleOutputAge" ).innerHTML = $formObject.formAge.value;
    document.getElementById( "sampleOutputComent" ).innerHTML = $formObject.formComent.value;
}
```

　
以上説明は簡単にコメントアウトで行なっております。
簡単な記述になるので是非コピペして変更をして楽しんでみては。
安くて優秀なプログラミング学習サービスが増える中、値段相応のプログラミングスクールになにを求めるべきか考えてみた。

最近安くて優秀なプログラミング学習サービスが増えている。

以下のサービスを要求するフェーズに応じて使っていけば、
数十万単位のプログラミングスクールは使わず目的を達成できる。

#プログラミングの基礎学習をしたい！
[progate]
:https://prog-8.com/dashboard
[paizaラーニング]
:https://paiza.jp/works/mypage
[ドットインストール]
:https://dotinstall.com/
[udemy]
:https://www.udemy.com/


#わからないこと質問したい！
[udemy]
:https://www.udemy.com/
[menta]
:https://menta.work/member/dash
[stackoverflow]
:https://ja.stackoverflow.com/


#コードレビュしてもらいたい！
[menta]
:https://menta.work/member/dash


#ポートフォリオ作りしたい！
[techpit]
:https://www.techpit.jp/
[menta]
:https://menta.work/member/dash


-----------------------------------

と、安いサービスでプログラミング学習の要点は事足りてしまう。

では数十万のプログラミングスクールにあって上記のサービスにはない付加価値は何か？
列挙してみた。

#プログラミングスクールに求める、一部のプログラミングスクールのサービス一覧

・対面でカリキュラム以外の点を回答してくれる

・業務レベルのコードレビューでレベルを引き上げてくれる。(生徒のレベルも必要)

・チーム開発が学べる

・卒業生は教室利用自由

・卒業生はその教室の教師になれる

・仲良くなったら仕事を降ってくれる

・転職成功キャッシュバック

・スクール参加者同士でのコミュニティに所属できる

・スクールで開催される勉強会・飲み会で雑談が出来る

-----------------------------------

こんな所だろうか、ちなみにコミュニティ要素もオンラインサロンで代替出来る。

話しが変わるが、スクールに行けばプログラミング教師としてやっていけるか見定めることも出来るかも。
メンターや先生が優秀なら、自分をレベルアップさせ次の道へ行けるし、
メンターや先生のレベルが低いor感じ悪い、であれば、自分の中の教師としての可能性の発見や自信にもつながるかも。
ローカル環境においてあるnpmライブラリをyarnでインストールして試すときにキャッシュでハマった

## 最初に結論だけ

各種 `yarn` コマンド実行時にキャッシュ置き場を指定。ライブラリの変更を反映したいときは `rm -rf` で直接そのディレクトリを削除してやる

```bash
# addやremoveのときに --cache-folderを指定しておく
yarn add --cache-folder ./ycache -D path/to/some-library/some-library.tgz
yarn remove --cache-folder ./ycache some-library

# 再度インストールしたいときは指定したキャッシュ置き場を消して、再度--cache-folderを指定して実行
rm -rf ./ycache
yarn add --cache-folder ./ycache -D path/to/some-library/some-library.tgz
```

## 起こった事象

- ライブラリのディレクトリで `yarn pack` を実行してtgzファイルを作成
- 試す側のディレクトリで `yarn add path/to/library/library.tgz`
- yarnのキャッシュによって古いものがインストールされる
- `yarn cache list --pattern library` で確認するとたしかにキャッシュがあるので、 `yarn cache clean library` でキャッシュを削除
- 改めて `yarn cache list` で確認すると出てこないので消えてそう
- 今一度 `yarn add path/to/library/library.tgz`
- **何故か古いのがインストールされる**


## キャッシュ置き場指定以外に試したこと

`yarn cache dir` でキャッシュを保存してるディレクトリが取れるので、そこから該当ライブラリのキャッシュを直接指定して消したりはしたけどダメだった
`tgz` ファイルを消しても `yarn add` が成功するのでキャッシュに引っかかってるのは間違いないんだけど・・・
ArduinoでNintendo Switch自動化(途中経過)

#まえがき
個人メモ
作業進めながらその都度記事作成

ポケモン剣盾での乱数消費が作業は単純なんだけど時間をバカ食いするので自動化したいねというモチベーション。
ついでにHDMIキャプチャした画像から自動孵化→ボックスで個体値確認して理想個体以外逃すまでもやれたらやる。

１回目
環境構築＋書き込み
今回はとりあえずLチカの確認

#用意するもの（今回の作業で）
- Arduino Micro
安い互換ボードでいけると思うけどなんとなくArduinoという名前のものを買いたかったのでArduino
USBデバイスとして認識させれるマイコンのってたら何でもいい（と思う）ちゃんと調べてないので他の人の記事でだいたいこのボードの互換使ってたからこれにした

- microUSB ケーブル
PCとArduinoをつなげる
それだけ

#環境準備
##Arduino IDEのインストール

https://www.arduino.cc/en/main/software

![スクリーンショット (21).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606061/0937fbe3-f9bb-2b5f-2557-c47a2879df16.png)
![スクリーンショット (22).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606061/15d5ff92-ea32-0de6-4ddb-af957c2ef30e.png)

ここからインストーラーを落として実行
インストーラーでの操作は特に弄るとこはない（と思う）のでバーっと流れで

##VSCodeの準備
###インストール
拡張機能を使ったらVSCode上で操作できるらしいのでVSCodeのセットアップ
ちなみに私VScodeのバージョンは1.43.1

VSCode本体のダウンロードは省略（元々入れてたので）
一応サイトURL
https://code.visualstudio.com/

###拡張機能
VSCodeをインストールしたら拡張機能を入れる
![スクリーンショット (24).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606061/84daeed8-a73b-bb73-d75b-2112fd241235.png)

1.左の正方形が並んだアイコンのとこクリックして
2.出てきたタブの上の方のテキストボックスで「Arduino」を検索
3.Arduino for Visual Studio Code みたいな説明のとこをクリック
4.インストールをクリック（画像だとインストール済みなので[無効にする][アンインストール]と表示）
5.画像赤丸のとこの歯車をクリック
6.拡張機能の設定（英語だとExtentionなんちゃら）をクリック
7.Arduino:PathのとこにArduinoを保存した場所（デフォだと多分"C:\Program Files (x86)\Arduino")を記述

###使い方とか設定とか

1.拡張機能を入れたら表示(View)からコマンドパレットを開く（Ctrl+Shift+Pでも出る）
2.そこからArduino:Exapmpeを選択（画像だと上に来てるけどもうちょい下の方に出る）
3.新しく表示されたタブのBuilt-in Example → 01.Basics → Blinkを選択

![スクリーンショット (25).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606061/0f732a47-b994-3e74-9f45-8d4867402b3f.png)

![スクリーンショット (26).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606061/b27ca8cf-4d30-168a-a3a6-4f4df34de3ac.png)

![スクリーンショット (27).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606061/3af95cef-0480-8b67-9e93-a6baab447637.png)

3.Arduino:Exapmpeを選択したら別ウィンドウが表示される
4.<Select Bord Type>をクリック
5.出てきたボックスから自分の使うボードを選択（今回はArduino Micro）
6.ボードをPCに接続
7.デバイスマネージャーでArduinoのCOM番号を確認(今回はCOM3）
8.arduino.jsonを開きさっき確認したCOM番号に書き換え

![スクリーンショット (29).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606061/bb457bf8-d3e6-99d5-2aa0-0cea461c9160.png)

![スクリーンショット (30).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606061/6f268d39-6216-538f-9ac2-6d77cc14d2b5.png)

![スクリーンショット (32).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606061/c409cfd2-621b-6df3-4115-2679e3e6d88b.png)

9.コマンドパレットからVerifyを選択してコンパイル
成功したら以下の出力 [Done] Finished verify sketch - Blink.ino
10.コマンドパレットからUploadでボードに書き込み

これでデフォのプログラムを書き込んでLチカさせることができた
一部Define(Serialとか)がエラー出してるっぽいの設定を調べないといけない

![l6033.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606061/205e44c5-eba3-8922-bdd9-349c2f6aa86a.png)


###VSCodeの出力の文字化け

やってる途中は放置してたけど、コンパイルの際の日本語部分の出力が文字化けしたので以下の記事で解決
https://qiita.com/nori-dev-akg/items/e0811eb26274910cdd0e
自動デプロイ

チーム開発自動デプロイ
less log/unicorn.stderr.log
less log/production.log
ログ確認方法エラー文を確認

config/deploy/production.rb
server '52.198.126.131', user: 'ec2-user', roles: %w{app db web}
の記述が違う場所にしていた
Capfile
require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git
の記述がコピペの際ぬけていた

ローカル環境：bundle exec cap production deploy
上二つのミスでできなかった（他にもいっぱいあったがありすぎ、焦りで覚えていない）

S3の導入とEncrypted Credentials機能実装、はまだ残っているが土日に入る前にほぼ終わらせられたのは良かった。
わからないことが多すぎ、いろいろ調べていくうちに自分が何を調べなくちゃいけないのか、どうしてエラーが出ているのか、どうやって直したのか、どこから調べていくのか、考えても考えても前進しないことが本当に大変だった。
Kotlin向け高機能RowMapper、KRowMapperを作った

`SpringFramework 5.3`/`SpringBoot 2.4`にて、コンストラクタ呼び出しでマッピングを行う`DataClassRowMapper`が追加されました。
機能面では`KRowMapper`の方が勝っていると思いますが、外部ライブラリを導入する程の苦しみを感じていない場合、こちらの利用をお勧めします。

https://spring.pleiades.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/core/DataClassRowMapper.html

https://qiita.com/wrongwrong/items/84b729d0a105b7111131

---

# 前書き
以前弊社の技術ブログで紹介した`Kotlin`向け`BeanPropertyRowMapper`的なものですが、この度`KRowMapper`として`OSS`化しました。

- [KotlinフレンドリーなBeanPropertyRowMapper的なものを作った \- MicroAd Developers Blog](https://developers.microad.co.jp/entry/2019/11/18/060000)

この記事では、`KRowMapper`の基本的な使い方についてまとめます。
`0.2`時点での内容です。

ライブラリのソースコードは`GitHub`に公開してあります。

- [ProjectMapK/KRowMapper: RowMapper for Kotlin\.](https://github.com/ProjectMapK/KRowMapper)

# 導入方法
`JitPack`にて公開しており、`Maven`や`Gradle`といったビルドツールから利用できます。
詳しい導入方法は以下のリンクからご確認ください。

- [ProjectMapK / KRowMapper](https://jitpack.io/#ProjectMapK/KRowMapper)

# 開発背景
冒頭の技術ブログで述べた通り、`Kotlin`の`data class`等で使える`BeanPropertyRowMapper`的なものの需要が有ったためです。

# なにができるか
`RowMapper`のインターフェースから、コンストラクタやファクトリーメソッドを呼び出すことができます。

```kotlin
// before
val dst = jdbcTemplate.query(query) { rs, _ ->
    Dst(
            rs.getString("foo"),
            rs.getString("bar"),
            rs.getInt("baz"),
            ...
    )
}

// after
val dst = jdbcTemplate.query(query, KRowMapper(::Dst))
```

## KRowMapperの引数
`KRowMapper`の引数は、基本的にはコンストラクタやファクトリメソッド、インスタンス関数を含むメソッドリファレンス（≒ `KFunction<*>`）です。

クラスを引数とすることで、プライマリコンストラクタ、もしくは`KConstructor`アノテーションを振ったコンストラクタ/ファクトリーメソッドを呼び出し対象とすることも可能です。

## 命名ケースの変換
`KRowMapper`は、デフォルトではキャメルケースでカラムとのマッチングを行います。
DBがスネークケース等の命名規則を採用している場合、以下のように変換関数を渡すことで対応できます。

```kotlin
KRowMapper(::Dst) { colName: String ->
    // 何らかの変換関数、こっこではGuavaを用いている
    CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, colName)
}
```

### Javaへの対応に関して
基本的に`Java`のクラス・関数には対応しません。
マッピングには`Kotlin`のメタデータを利用していることと、`Java`では引数の名前が取得できない場合があることが理由です。

# 終わりに
今回は自作の`Kotlin`向け`BeanPropertyRowMapper`的なライブラリ、`KRowMapper`に関して書きました。
紹介していない機能や開発中の機能等有りますが、長くなるので個別の記事としてまとめようと思います。

PR、質問等も募集中です。
是非使ってみて下さい。
【JitPack】build.gradleでapi指定した依存が参照先で利用できない現象に対処した話【JitCI】

# TL;DR
- `JitCI`で手動ビルドした場合、`api`で指定した依存が参照先で利用できないことが有る
  - 当然その依存は参照先で個別に取得しなければ利用できない
- `GitHub`のリポジトリに`Webhook`を追加してからリリースによる自動ビルドを行った所正常に動作した

# 状況
自作ライブラリを公開する際、`Shared`モジュールを参照先でも利用するため、ライブラリの`build.gradle`では`api`指定で`Shared`モジュールへの依存を記述していました。

- [ビルド依存関係の追加  \|  Android デベロッパー  \|  Android Developers](https://developer.android.com/studio/build/dependencies?hl=ja#dependency_configurations)

所が、いくらリリースを行っても参照先で`Shared`モジュール内の内容を参照できないという問題が発生しました。

一方、同様の指定を行っていた別のライブラリでは参照先から正常に`Shared`モジュールを参照できたため、恐らく原因は`JitPack`側に有りそうでした。

# 対処
当該ライブラリのリポジトリで、`JitCI`向けの`Webhook`の設定を忘れていたことが発覚したため、以下の手順で設定しました。

- [【JitPack】pushでCI \-> publishまで走るようにする【JitCI】 \- Qiita](https://qiita.com/wrongwrong/items/78504ca623b00de934f0)

すると問題が解決し、正常に依存が伝播するようになりました。
【H2】できるだけシンプルにJdbcTemplateを用いたテストが行えるようにする【SpringBoot】

# やりたいこと
自作の`RowMapper`をテストするため、単一クラスで完結する範囲でDBの初期化 & データ挿入を行った上で`JdbcTemplate`を取得する必要が出ました。
当初はフレームワーク等を用いたりDIしたりする必要が有るかなと考えましたが、コンフィグを書くのが面倒なので、`Java(Kotlin)`内でべた書きする形で解決を模索しました。

# やり方
最終的に以下の方針に落ち着きました。

1. DBは`H2`のインメモリモードで、アプリケーションから起動する
2. 1で`DataSource`が取得できるので、この時点で`JdbcTemplate`を取得する
3. テーブル作成/データ挿入などのDB操作は`JdbcTemplate`経由で行う

## サンプルコード
```kotlin
import org.h2.jdbcx.JdbcDataSource
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource
import org.springframework.jdbc.core.simple.SimpleJdbcInsert
import javax.sql.DataSource

/* 略 */

// DBをインメモリモードで起動
val dataSource: DataSource = JdbcDataSource().apply {
    setUrl("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS APP\\;SET SCHEMA APP;")
}

// JdbcTempalte取得
val jdbcTemplate: JdbcTemplate = JdbcTemplate(dataSource)
// テーブル作成
jdbcTemplate.execute("""
    CREATE TABLE IF NOT EXISTS `foo_table` (
      `foo_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
      `foo_name` VARCHAR(255) NOT NULL,
      `foo_status` ENUM('active', 'archive', 'deleted') NOT NULL,
      `is_bar` ENUM('true', 'false') NOT NULL,
      `description` VARCHAR(1023) NULL DEFAULT NULL,
      PRIMARY KEY (`foo_id`)
    );
""".trimIndent())

// あらかじめ用意しておいたデータをinsert、ここではオブジェクトをSimpleJdbcInsertでinsertしている
val data = FooInsert(10, "Foo", FooStatus.archive, false, null)
SimpleJdbcInsert(jdbcTemplate).withTableName("foo_table").execute(BeanPropertySqlParameterSource(data))
```

## おまけ: build.gradle
`gradle.kts`ですが、以下のように依存を設定しました。

```kotlin:build.gradle.kts
dependencies {
    /* 略 */

    // 使うのはRowMapperのみなため他はexclude、またバージョンそのものは使う相手に合わせるためcompileOnly
    compileOnly(group = "org.springframework", name = "spring-jdbc", version = "5.2.4.RELEASE") {
        exclude(module = "spring-beans")
        exclude(module = "spring-jcl")
        exclude(module = "spring-tx")
    }

    // テスト実行時には実体が無いと困るため、別口でimplementation
    testImplementation(group = "org.springframework", name = "spring-jdbc", version = "5.2.4.RELEASE")
    // https://mvnrepository.com/artifact/com.h2database/h2
    testImplementation(group = "com.h2database", name = "h2", version = "1.4.200")

    /* 略 */
}
```

# 参考にさせて頂いた記事
- [H2 DBのインメモリデータベースにDDLをロードする方法 \(コネクションプールつき\)](https://gist.github.com/seraphy/10454776)
【Intellij IDEA(Ultimate)】Run/Debug ConfigurationsのBefore launchを触る

# 前書きの前書き
この記事は[MicroAd \(マイクロアド\) Advent Calendar 2019](https://qiita.com/advent-calendar/2019/microad)で公開しようとして書ききれなかった内容を再編集したものです。
そのため、`Intellij IDEA(Ultimate)`のバージョンが若干古く、当該バージョンで踏んだバグの情報も残っていますが、現状そのバグが残っているか等は確認していません。

# 前書き
`Intellij IDEA(Ultimate)`の`Run/Debug Configurations`では、`Java/Kotlin`のビルド・実行だけでなく、様々な設定を行うことができます。

この記事ではメイン以外のタスク実行を設定する例として、`Before launch`による逐次実行[^tikuji]を触ってみます。

記事本編にはあまり関係ありませんが、プロジェクトは以下の記事から引き続き利用します。

- [【Intellij IDEA\(Ultimate\)】Run/Debug Configurationsを触ってみる \- npm編 \- Qiita](https://qiita.com/wrongwrong/private/a9b3d564e76c7f425159)

[^tikuji]: いくつか挙動を当たった限り逐次実行で正しいはずですが、`IntelliJ IDEA 2019.2.3`において前のタスクの終了前に次のタスクが実行される現象が発生したため（IDEを再起動したりしている内にローカルで再現しなくなった）、注意が必要かもしれません。

# 基本設定

`Run/Debug Configurations`ウィンドウの右下には`Before launch: Build, Active tool window`という項目が必ず表示されます。
ここに追加したタスクはメインで設定したタスクの前に上から実行されます。

画像の通り、この項目には`Run/Debug Configurations`で設定できる内容が同様に設定できます。
また、`Run Another Configuration`を選択することで、`Run/Debug Configurations`で設定した内容を実行することもできます。

![スクリーンショット 2019-12-01 19.39.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280230/f6ec38d1-707e-c204-4920-ea9a8a7e8e57.png)

これを設定することで、実行前にシェルスクリプトを走らせたり、`Docker`を起動したりといった、複数のコンフィグを組み合わせた複雑な挙動を実現することができます。

ただし、逐次実行の途中であっても実行したタスクが落ちた時点で全ての実行はストップするので、その点には注意が必要です。

# 補足: Multirun Pluginについて
`Before launch`が逐次実行なのに対して、並列で何かを実行したいということも有ると思います。
そういった時には`Multirun Plugin`が利用できます。

この`Plugin`を追加することで、画像のように、追加可能なコンフィグに`Multirun`が加わります。

![スクリーンショット 2019-12-01 19.53.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280230/45ae036e-c695-6e8f-f273-7ead0dc12ffa.png)