OmniAICreator/Qiita-1.07M huggingface dataset:
n8nを簡単にKubernetes上にデプロイして使う方法

オープンソースのワークフローツールn8nをKubernetesで使った時のメモです。
https://n8n.io

デフォルトでは作成したデータが保存されないため、PVを用意する必要があります。
また認証を有効にしています。
`N8N_BASIC_AUTH_USER` と ` N8N_BASIC_AUTH_PASSWORD` を設定してください。

http://ノードのIPアドレス:32567 でアクセスができるようになります。

## PVなしのパターン
```yaml:n8n.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: n8n

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: n8n-deployment
  namespace: n8n
spec:
  replicas: 1
  selector:
    matchLabels:
      app: n8n
  template:
    metadata:
      labels:
        app: n8n
    spec:
      containers:
      - name: n8n
        image: n8nio/n8n
        ports:
        - containerPort: 5678
        env:
        - name: N8N_BASIC_AUTH_ACTIVE
          value: "true"
        - name: N8N_BASIC_AUTH_USER
          value: "n8n"
        - name: N8N_BASIC_AUTH_PASSWORD
          value: "n8n"
        - name: GENERIC_TIMEZONE
          value: "Asia/Tokyo"

---
apiVersion: v1
kind: Service
metadata:
  name: n8n-deployment
  namespace: n8n
spec:
  type: NodePort
  selector:
    app: n8n
  ports:
  - protocol: TCP
    port: 5678
    nodePort: 32567
```

```bash
kubectl apply -f n8n.yaml
```

## PVありのパターン
```yaml:n8n-with-pv.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: n8n

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: n8n-pvc
  namespace: n8n
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 2Gi

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: n8n-deployment
  namespace: n8n
spec:
  replicas: 1
  selector:
    matchLabels:
      app: n8n
  template:
    metadata:
      labels:
        app: n8n
    spec:
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: n8n-pvc
      containers:
      - name: n8n
        image: n8nio/n8n
        ports:
        - containerPort: 5678
        env:
        - name: N8N_BASIC_AUTH_ACTIVE
          value: "true"
        - name: N8N_BASIC_AUTH_USER
          value: "n8n"
        - name: N8N_BASIC_AUTH_PASSWORD
          value: "n8n"
        - name: GENERIC_TIMEZONE
          value: "Asia/Tokyo"
        volumeMounts:
        - name: data
          mountPath: /root/

---
apiVersion: v1
kind: Service
metadata:
  name: n8n-deployment
  namespace: n8n
spec:
  type: NodePort
  selector:
    app: n8n
  ports:
  - protocol: TCP
    port: 5678
    nodePort: 32567
```

```bash
kubectl apply -f n8n-with-pv.yaml
```
初心者のKubernetes入門（書籍 Kubernetes 実践入門の写経から学ぶ）Deployment 編

# 背景
個人的にインフラの知識以上にこれからのアプリケーションが動く環境を作ってデプロイしたりしてこれからの知識を身に着けたい。そしてより一層、自分の知識のアップデートをしたいと思いました。

その中でこの本に出会い、これから少しずつやったことを残し、未来の自分への手紙としてもあり、見つめ直せればと思いました。

# 引用や参考と今回の自分の勉強用の書籍の紹介
[技術評論社『Kubernetes実践入門』のサンプルコード](https://github.com/kubernetes-practical-guide/examples)
[Kubernetes実践入門 プロダクションレディなコンテナ＆アプリケーションの作り方](https://gihyo.jp/book/2019/978-4-297-10438-2)
![](http://image.gihyo.co.jp/assets/images/cover/2019/9784297104382.jpg)


## 実際の学びについて

書籍を読みながら、章ごとに少しずつ進めていきたいと思います。
GitHub のソースコードも使いながら学んで行きたいと思います。

# 勉強開始

- https://github.com/kubernetes-practical-guide/examples/blob/master/ch1.3.5/my-deploy.yaml

```yaml:my-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deploy
spec:
  replicas: 3 #Podレプリカの数
  strategy: #デプロイ戦略の指定 (1)
    type: RollingUpdate
    rollingUpdate: # RollingUpdateの設定 (2)
      maxSurge: 25%
      maxUnavailable: 25%
  selector:
    matchLabels:
      app: my-deploy
  template: #Podテンプレート
    metadata:
      labels:
        app: my-deploy
    spec:
      containers:
      - name: nginx
        image: k8spracticalguide/nginx:1.15.5
```

# コマンド郡

## 実行前

<img width="1151" alt="スクリーンショット 2020-04-10 20.01.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174596/23e8cbc1-e87e-508b-65c1-886cbee82168.png">

## Deployment のマニュフェストファイルを適用する
```
$ kubectl apply -f my-deploy.yaml
```

## 実行後

<img width="1160" alt="スクリーンショット 2020-04-10 19.59.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174596/5c3b25b3-ed34-bbaf-d20a-a5eedd57f21a.png">

## Pod の確認画面
<img width="1148" alt="スクリーンショット 2020-04-10 20.04.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174596/34a584bc-cf4f-7ead-9465-183adca0e6e1.png">

## 次は Service をやっていきます。

この Service を終わったら、Nginx 使ってデプロイして参照できるところまでやってみたいと思います。

# 最後に

今はまだ、初期段階ですが、自身で入門的なReactのアプリをデプロイできるまでを行えるように続けていきます。

この記事を読んでいる方々とも一緒に、初歩からジョジョにアプリをデプロイまで学び、言語（JavaScript/PHP/Java等々）どんなアプリでも基本的なデプロイができるところまで、今は不安と希望が持ち合わせて、山を越えようと思います。
超えたら、もっと勇気の希望を持つことができると思っています。
Ruby の開発版に右代入演算子とエンドレスメソッド定義構文が入った

[ブログ記事](http://secret-garden.hatenablog.com/entry/2020/04/10/195207)からの転載です。


Ruby の開発版に右代入演算子と実験的にエンドレスメソッド定義構文が新しく追加されました。

## 右代入演算子

* チケット：https://bugs.ruby-lang.org/issues/15921
* pull request：https://github.com/ruby/ruby/pull/3012

左辺値を右辺の変数に代入する `=>` 演算子が新しく追加されました。
これは `expression => variable` のように書くことができます。

```ruby
# 左辺値を右辺の変数に代入する
42 => result
p result
# => 42

# メソッドチェーンの最後に代入演算子を書くことができる
(1..).lazy.select { _1 % 2 == 0 }.map { _1 * 2 } => x
p x.first(10)
# => [4, 8, 12, 16, 20, 24, 28, 32, 36, 40]
```

`=>` を使うことで左から処理を書いて自然とその流れのまま変数に代入する事ができます。
これは書いてて気持ちいいですね。
その反面、変数定義を探す場合、いつも左側を見る癖が付いているので右側に変数定義があると見落としてしまいそうなのがちょっと心配です。
また、次のように演算子を伴う式を左辺で書くとシンタックスエラーになりました。

```ruby
# syntax error, unexpected =>, expecting end-of-input
1 + 2 => result
```

これは意図してないような気がするんですがどうなんでしょうね。

### [追記]

`=>` は Hash を定義する時にも使われており例えば現行の Ruby でも

```ruby
meth(key => value)
```

と書くことができます。
なので

```ruby
meth a => result
```

というコードは

```ruby
meth(a) => result
```

ではなくて

```ruby
meth(a => result)
```

と解釈されます。
同様に

```ruby
1 + 2 => result
```

も

```ruby
(1 + 2) => result
```

ではなくて

```ruby
1 + (2 => result)
```

と解釈されるのでえらーになるんですかね？

### [追記 2]

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">1 + 2 =&gt; result がエラーになるのはうっかり忘れてたので直した <a href="https://t.co/a5lEu1OUaq">https://t.co/a5lEu1OUaq</a></p>&mdash; ( Φ _⊞) (@n0kada) <a href="https://twitter.com/n0kada/status/1249196962819256323?ref_src=twsrc%5Etfw">2020年4月12日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

とのことで `1 + 2 => result` がエラーになることは意図していなかったらしいです。
最新版では以下のコードが動作します。

* 対応コミット：https://github.com/ruby/ruby/commit/022c7bbea98ef41556941a21ef6f0656bb49c75f

```ruby
1 + 2 => result
result   # => 3
```

演算子の優先順位の問題、意図してるのかどうか判断するのがむずかしいなー。



## エンドレスメソッド定義構文

* チケット：https://bugs.ruby-lang.org/issues/16746
* pull request：https://github.com/ruby/ruby/pull/2996

実験的にエンドレスメソッド定義構文が追加されました。
エンドレス、と言っても永遠という意味ではなくて『`end` を書かずにメソッドを定義する』という意味のエンドレスです。
これにより `def value(args) = expression` という形でメソッドを定義する事ができるようになります。
もともとは今年のエイプリルフールネタで建てられたチケットがそのまま導入された形になります。
これを利用することで以下のような形でメソッドを定義する事ができます。

```ruby
def hello(name) =
  puts("Hello, #{ name }")

hello("endless Ruby") #=> Hello, endless Ruby
```

```ruby
def inc(x) = x + 1

p inc(42) #=> 43
```

```ruby
x = Object.new

def x.foo = "FOO"

p x.foo #=> "FOO"
```

```ruby
def fib(x) =
  x < 2 ? x : fib(x-1) + fib(x-2)

p fib(10) #=> 55
```

これは普通に便利そうですね。
ただし、 `def value = 42` のように代入演算子を使用するので以下のような動作を期待するんですが、これはエラーになります。

```ruby
value = 42
# 外のスコープの値を使用したい
def hoge = value

# error: undefined local variable or method `value' for main:Object (NameError)
p hoge
```

`end` がないことでスコープが曖昧に見えるので個人的には外にある変数はキャプチャされてもいいんじゃないかなあ、と思うんですがどうなんでしょうね。
この構文自体あんまりよく思ってない人もいるようなので今後どうなるのかは気になります。
nreal light DevKitでコントローラが反応しない場合の対応方法

# 開発者キットがやっと届いたぞい
公式で受付開始直後に注文していたのですが、3rd batchまで回され、コロナの影響もあったりなかったり？でやっと本日届きました。
レンズセットだから遅くなったのかもしれないです
![pict.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150289/1951e295-9831-df14-d9e7-7f01bf57f59e.png)

# 早速起動する
こういうのは説明書を読むよりさっさと電源入れますよね

1. 四角いのにある細長いボタンを長押し
2. グラスをかけて、USB-Cケーブルを四角いのに挿す
3. グラスの視界の向こうに3つの項目と、その下に英語の操作説明が表示される（きれい！）
3. 丸いのを外して、裏側（赤い面）にあるスライドスイッチをONにする
4. 丸いのの表側にあるライトが点滅する
5. 

そして何も反応しない。。。。。。

# コントローラを手動でペアリングする
というわけで、ここからが本題です。
この丸いの（コントローラ）は、四角いの（コンピューティングユニット）とBluetoothで自動で接続されて、ライトが点灯状態になるはずですが、
我が家に来た子は何故だか点滅状態で上手に接続してくれません。
手動で接続しようにも、四角いのには電源ボタンしかないのでどうしたこっちゃな状態です。
インターフェースがないなら無理やり繋いでやろう

1. Windows PCとUSB-Cで接続する
2. PCにVysorを入れる
3. いつもの見慣れたAndroid画面が出てくるので、Bluetoothの設定から手動でペアリング
4. コントローラのライトが点灯！

まだまだ情報が少ないので、試行錯誤しながらの日々ですが
夢の膨らむガジェットですねえー
UIAutomationを使ってスクロールバーをRangeValuePatternで動かそうとしたときにハマった

# 結論

**.NET Framework版**のUIAutomationClientを使いましょう！
C++などから利用するCOM実装のUIAutomationや.NET Core版のUIAutomationではうまく動きません

# 経緯
個人で開発している ExpTabBarというエクスプローラーにタブを付けるシェル拡張を開発している最中、タブ切り替え時にスクロール位置を復元する機能を実装しようと思い試行錯誤していた

ご存じの通りWindows10になってからのエクスプローラーのファイルビューは、ListViewなどの標準コンポーネントが使用されておらず　独自実装のウィンドウとなっており スクロールバーなどのUI部品から ウィンドウハンドルを取得できなくなっている

ウィンドウハンドルが取得できないのならどうしようといろいろ調べた結果
Windowsに標準実装されているUIAutomationという機能を使えばいいことが分かり
それではさっそくとUI Spyを使ってスクロールバーのElementを調査し、スクロール位置の取得と、RangeValuePatternを使ってスクロール位置の変更が確認できたので、自分のアプリケーションに実装してみたのだが

````C++
HRESULT	hr;
CComPtr<IUIAutomation2>	spUIAutomation;
hr = CoCreateInstance(CLSID_CUIAutomation8, NULL, CLSCTX_INPROC_SERVER, __uuidof(IUIAutomation2), (void**)&spUIAutomation);
ATLASSERT(spUIAutomation);

CComPtr<IUIAutomationElement>	spListViewElement;
hr = spUIAutomation->ElementFromHandle(ListView.m_hWnd, &spListViewElement);
if (FAILED(hr))
	AtlThrow(hr);

CComVariant varProp;
varProp.vt = VT_I4;
varProp.intVal = UIA_ScrollBarControlTypeId;
CComPtr<IUIAutomationCondition>	spCondition2;
hr = spUIAutomation->CreatePropertyCondition(UIA_ControlTypePropertyId, varProp, &spCondition2);
if (FAILED(hr))
	AtlThrow(hr);

CComPtr<IUIAutomationElement>	spScrollBarElement;
hr = spListViewElement->FindFirst(TreeScope_Children, spCondition2, &spScrollBarElement);
if (spScrollBarElement == NULL)
	AtlThrow(hr);

CComPtr<IUIAutomationRangeValuePattern> spRangeValuePattern;
hr = spScrollBarElement->GetCurrentPatternAs(UIA_RangeValuePatternId, IID_PPV_ARGS(&spRangeValuePattern));
if (spRangeValuePattern == NULL)
	AtlThrow(hr);

double scrollPos = 0;
hr = spRangeValuePattern->get_CurrentValue(&scrollPos);
````

get_CurrentValueで取れる値が、UISpyと異なり
さらにSetValueでスクロール位置の変更が効かなかった(UISpyでは変更できた)

なんで動かねえんだよくそがあああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああああ

と、何十時間もの調査の結果
自分のコードでUIElementから取得したAutomationIdが"NonClientVerticalScrollBar"なのに対して、UISpyで表示されるAutomationIdが"Vertical ScrollBar"なことに気づく
googleでぐぐってみると以下のURLにたどり着いた
https://www.csharpcodi.com/csharp-examples/FlaUI.Core.Conditions.ConditionFactory.ByAutomationId(string)/

UIA2とUIA3では同じように違っていた、
この違いが動かない原因なのでは...と、FlaUIというライブラリを調べて調査した結果が、結論に記したことである

# おわりに
ちょっとマイクロソフトさん同じUIAutomationなのに、使ってるライブラリの違いで動くとか動かないとかいうバグを作るのはやめてください

てっきり.NET版のUIAutomationCoreはCOM版のラッパーだと思ってたのに、こんな結果になるとは思わなかった

同じ.NETでも.NET Coreの
using UIAutomationClient;
と書いて利用するUIAutomationは正常に動作しません

# おまけ 
正常に動作するC#版のソース
UIAutomationClientとUIAutomationTypesを参照に追加してね

````C#
// using System.Windows.Automation;
var listViewElm = AutomationElement.FromHandle((IntPtr)0x00031186/*フォルダービューのウィンドウハンドル*/);
var condScrollbarCtrl = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ScrollBar);
var scrollbarElm = listViewElm.FindFirst(TreeScope.Children, condScrollbarCtrl);
var rangeValuePattern = (RangeValuePattern)scrollbarElm.GetCurrentPattern(RangeValuePattern.Pattern);
// 現在のスクロール位置
Console.WriteLine("Hello World! {0}", rangeValuePattern.Current.Value);
// スクロール位置の変更
rangeValuePattern.SetValue(50000);
````
【Vue.js】スコープ付きCSS（Scoped CSS）

## はじめに
スコープ付きCSSを使用することでスタイルが反映できる範囲を対象のコンポーネント内（同ディレクトリ内）に限定することができる。
他のコンポーネントに影響を与えないのでクラス名の衝突などを防ぐことができる。
styleタグにscopedオプションをつけて```<style scoped>```を配置することでスコープ付きCSSを利用できる。
そうすることで「data-v-xxxxxx」のようなユニークな属性が付与されたタグとセレクタに変換される。

```sample.html
<div class="sample" data-v-aaaaaa>
  <span class="title" data-v-aaaaaa>sample</span>
</div>
```
```sample.css
span.title[data-v-aaaaaa] {color:red;}
```


###### スコープとは？
スコープとは影響が及ぶ範囲。定義されたデータ、メソッド、テンプレートがスコープとなる。

#### 子コンポーネントの扱い
コンポーネント内に子コンポーネントが存在する場合、子コンポーネントのルート要素は親スコープのCSSと子スコープのCSS両方の影響を受ける（親コンポーネントからでも子コンポーネントのスタイルが変更できる）


### 親コンポーネントから子コンポーネントに干渉
親コンポーネントで子コンポーネントのスタイルを指定する場合は特殊なセレクタを使用する。

```sample.vue
/* cssの場合 */
<style scoped>
.parent >>> .child { ... }
</style>

/* scssの場合 */
<style scoped>
.parent /deep/ .child { ... }
</style>
```

#### 注意すること
スコープをつけることでCSSがコンポーネント内に限定され、クラス名を指定しない```p {color: red;}```といったスタイルの定義も可能になる。しかし、クラス名の指定が全くないとUIの構造として何を意味するスタイルか分かりづらく、ブラウザのパフォーマンスも低下してしまうので、クラス名をつけることが望ましい。
WPF UniformGridで要素を縦に並べる方法、任意の行数や列数で並べる方法

元々出来た事なのか、出来なかった事なのか
今更わからないのだが、検索するとなかなか出てこない。
実は、標準で如何様にでも出来るので、公開しようかと。

UniformGridは中の子要素を等間隔で並べてくれる便利なコンテナ。
Scrollviewerと組み合わせると、スクロール可能なサムネイルパネルを簡単に実装できる。
ただし、子要素を自動的に並べるため、子要素の大きさやUniformGridの大きさによっては
意図するレイアウトにならないケースも。
そこで誰しもが「縦に一列で並べる指定がしたい。縦に三つ並べて横並びに増やしたい」なんて事を発想するだろう。
そこで指定すべきプロパティがある。
それは<b>Rows</b>と<b>Columns</b>だ。

<h2>「縦一列で並べたい場合」</h2>

        <UniformGrid Columns="1">
            <Button Height="100" Width="100" Content="Button"/>
            <Button Height="100" Width="100" Content="Button"/>
            <Button Height="100" Width="100" Content="Button"/>
            <Button Height="100" Width="100" Content="Button"/>
        </UniformGrid>


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464438/a0833788-00c7-19e2-d952-d340f27bf01e.png)

<h2>「縦に三つ並べて横並びに増やしたい場合」</h2>

       <UniformGrid Rows="3">
            <Button Height="100" Width="100" Content="Button"/>
            <Button Height="100" Width="100" Content="Button"/>
            <Button Height="100" Width="100" Content="Button"/>
            <Button Height="100" Width="100" Content="Button"/>
            <Button Height="100" Width="100" Content="Button"/>
            <Button Height="100" Width="100" Content="Button"/>
            <Button Height="100" Width="100" Content="Button"/>
            <Button Height="100" Width="100" Content="Button"/>
            <Button Height="100" Width="100" Content="Button"/>
            <Button Height="100" Width="100" Content="Button"/>
            <Button Height="100" Width="100" Content="Button"/>
            <Button Height="100" Width="100" Content="Button"/>
        </UniformGrid>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464438/3c60ffba-5998-d7e0-ef11-26596eaec85a.png)
PowerShellで印刷の設定を変更してから印刷を行う

とりあえず白黒指定

```powershell
 $printer = Get-WmiObject Win32_Printer | Where-Object Name -eq "***" # 印刷したいプリンタの名前
 $printer.SetDefaultPrinter()
 Set-PrintConfiguration $printer.name -Color $False
 Start-Process "***" -Verb Print # 印刷したいファイルの名前
```

プリンタへの出力は`Out-Printer`というコマンドレットもあるが、こちらはテキスト限定。幅広いファイルを処理するならPrint動詞に頼るのが良いと思われる。

# その他の注意点

## `Set-PrintConfiguration -Color $False`がエラーになるプリンタがある

Microsoft Print To PDFなど。実在するプリンタにはないと信じたい・・・。

ただ、スクリプトで書く場合はエラーになっても落ちないような仕組みが必要になりそう。事前にプロパティの存在をチェックするとか。

## `Set-PrintConfiguration -Color $False`を無視するプリンタがある

試した限りではSend To OneNote 2016(デスクトップ版OneNoteに付属の仮想プリンタドライバ)が該当。

同じく実在するプリンタにそんなものはないと信じたい・・・。

## Start-Processで、Print動詞がないファイルを指定してしまった場合は

For文で回している場合などうっかりPrint動詞がないファイル(icsとか)を指定しまう可能性は割とありそう。

これもエラーが起こったときに落ちないようにする必要がある。try, catchくらいしかやれることがないが。

# そのほか実際に使う場合に必要になりそうなコマンド

## 事前に直前までデフォルト指定されていたプリンタを取得する

処理が終わったあと通常使うプリンタを戻すのに使う。

```powershell
 $default = Get-WmiObject Win32_Printer | Where-Object default
 ...
 $default.SetDefaultPrinter()
```

あたりで。

# そもそもそんなことしないでデフォルトプリンタで印刷すればいいのでは？

わたしもそう思っていた。しかし今のWindowsには、Microsoft Print To PDFやSend To OneNoteなど、仮想プリンタドライバとして振る舞うソフトがいくつか含まれている。

そのため、ユーザーが思っている「通常使うプリンタ」と、PCに設定されている「通常使うプリンタ」が異なっている ということはまああり得る。

また、今のWindowsには「Windowsで通常使うプリンターを管理する」という設定もあり、その確率は上がっていると思われる。なのでプリンタはちゃんと名前で指定しておくのがベター。
JavaScriptでIPアドレスを正規表現を使ってreplaceする方法

# この記事は？

JavaScriptでIPアドレスを置換する時の書き方についての記事です。
忘れないように書いておきます。

# やり方

## IPv4の場合


```javascript

const ipv4 =  "192.1.1.1" ;
const ipv4Regex = new RegExp(
    "[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"
  );
console.log(ipv4.replace(ipv4Regex, "0.0.0.0"));

> "0.0.0.0"
```
## IPv6の場合

```javascript

const ipv6 =  "2001:0db8:1234:5678:90ab:cdef:0000:0000" ;
const ipv6Regex = new RegExp(
    "((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))",
  );
console.log(ipv6.replace(ipv6Regex, "0:0:0:0:0:0:0:0"));

> "0:0:0:0:0:0:0:0"
```

IPv6はアドレスの省略されることもありますが、それも対応可能です

```javascript
const ipv6 =  "2001:0db8::3456:0000:0000:0000" ;
const ipv6Regex = new RegExp(
    "((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))",
  );
console.log(ipv6.replace(ipv6Regex, "0:0:0:0:0:0:0:0"));

> "0:0:0:0:0:0:0:0"
```

以上
CentOS 8でのgrubの設定

#0. 作業内容
・CentOS 8において、grub2画面でのOS選択待機時間を減らしたい。
(その他の設定も弄ってみたい)

#1. 管理者権限でgrub設定を変更
```
$ sudo vi /etc/default/grub
```
```
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto resume=/dev/mapper/cl-swap rd.lvm.lv=cl/ro$
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
```

#2. システムへの変更の反映
BIOSベースのマシンは、rootで

```
grub2-mkconfig -o /boot/grub2/grub.cfg
```

UEFIベースのマシンは、rootで

```
grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
```


###grub2-mkconfigとは？
***
GRUB 2 スクリプトはユーザーのコンピューターを検索して、スクリプトが見つけたオペレーティングシステムに基づくブートメニューを構築します。最新のシステムブートオプションを反映させるために、カーネルが更新されるか新規カーネルが追加されると、ブートメニューは自動的に再構築されます。
しかし、特定のエントリーを含むメニューの構築や、エントリーの特定の順番をユーザーが希望する場合もあります。GRUB 2 では基本的なブートメニューのカスタマイズが可能で、画面に表示されるものをユーザーが制御できます。
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/sec-customizing_the_grub_2_configuration_file
***
PowerShellでTIFFをJPEGに変換

# PowerShellでTIFF画像をJPEGに変換する。
TIFFをJPEGに変換するだけの作業が多いので作成。

とりあえずこんな関数を作成。

```powershell

function Convert2-jpg
	{
	begin { Write-Host "TIFF画像をJPGに変換"
		[Void][System.Reflection.Assembly]::LoadWithPartialName( "System.Drawing" )
		 }
	
	process	{
		trap {
			"対象ファイルをパイプラインで入力してください"
			"異常終了!"
			break
			}
		Write-Host "$_"
		$img = [System.Drawing.Image]::FromFile( "$_" )
		$outfile = $_.fullname + ".jpg" 
		Write-Host $outfile
		$img.save( "$outfile" , "jpeg" )
		$img.dispose()
		}
	
	end	{ Write-Host "変換完了" }
	}
```

PowerShellのプロファイルとして保存しておく。

変換するときはPowerShellを立ち上げ、

```
PS C:\> dir hoge*.tif -Recurse | Convert2-jpg
```
こんな感じでパイプラインで渡してやると変換される。
ファイル名が .tif.jpg となるのはご愛敬
Chromeでtext-decoration-thicknessが使えるようになるまでの身代わりコードを考えた

## 解決フロー

1. `Chrome`では`text-decoration-thickness`がまだ対応できない
2. `border-bottom`とか似たようなことができる他のコードを試す
3. `border-bottom`だとテキストの箇所だけではなく、`h1`要素全てに下線が引かれてしまう
4. 3の状態になるのは`h1`タグがブロックレベル要素だから
5. h1タグをインライン要素にして、`border-bottom`を使用してみる
6. **解決**



## 発生した問題
`h1`タグに太さを調整できる下線を引きたいのに、`text-decoration-thickness`が`Chrome`では対応していなかった



```style.css
h1{
  text-decoration: underline;
  text-decoration-color: red;
  text-decoration-thickness: 4px; <-chrome未対応(2020/04/10時点)
}
```


![NoneTextdecorationthickness.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218398/6ca24fe7-66c3-45b0-cc00-9ef000dd837e.png)


## 試したこと
調べてみたら、`CSS`には他にも下線を引けるコードがあると判明。
`border-bottom`とか。
「これで良いじゃん!」と思って試してみたらこれで良くなかった。

![NoneTextdecorationthickness1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218398/e233afb4-60e3-5a54-377e-36cd2fc1054b.png)

```style.css
h1{
  border-bottom: 4px solid red;
}
```

`h1`要素全体に下線が引かれてしまっているのが問題。
テキスト部だけで良いのに。

### `border-bottom`での問題
テキスト部以外にも下線が引かれてしまう理由は、`h1`タグはページ構成の中で一つの塊として扱われるブロックレベル要素だから。
だから、`border-bottom`は「h1タグのテキスト」ではなく、「h1タグ」を対象として動いている。
`border-bottom`を使って、テキスト部だけに下線を引きたいならその対象を「h1タグのテキスト」にしてあげればいい。


## 解決法
h1タグに`display: inline-block`を与えて、インライン要素にして`border-bottom`を使用する。

```style.css
h1{
  display: inline-block;
  border-bottom: 4px solid red;
}
```

![NoneTextdecorationthickness2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218398/8d8325b0-24d2-8908-3c9b-de97411ee60c.png)

**解決!!**

## 感想
正直、`text-decoration`系よりも`border-bottom`系の方がサポートというか色々な属性?があるからそっちを使った方が良いのでは?
まぁ今回は`border-bottom`を使うときは`display: inline-block`を使うと、より多様な使い方ができると分かったということで。

## 参考資料
[text-decoration-thickness](https://developer.mozilla.org/ja/docs/Web/CSS/text-decoration-thickness)
[ブロックレベル要素とインライン要素](http://www.htmq.com/htmlkihon/005.shtml)
[HTMLやCSSで【アンダーライン】を引くベストな方法ってどれ？比較してみました。](https://www.seleqt.net/programming/the-best-way-draw-underline/)
Create React App の Redux テンプレートのディレクトリ構造を分析する

# create-react-app コマンドで Redux テンプレートを使用して作成する

```bash
$ npx create-react-app todo --template redux
```

```bash
$ cd todo
$ yarn start
```

# http://localhost:3000 へアクセス

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149578/60e7d103-3490-d4a8-e239-f83aae2f2996.png)

 
# node_modules 以外のディレクトリ構造

```bash
$ tree -I node_modules
.
├── README.md
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
├── src
│   ├── App.css
│   ├── App.js
│   ├── App.test.js
│   ├── app
│   │   └── store.js
│   ├── features
│   │   └── counter
│   │       ├── Counter.js
│   │       ├── Counter.module.css
│   │       └── counterSlice.js
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   ├── serviceWorker.js
│   └── setupTests.js
└── yarn.lock
```

# package.json の中身

```json
{
  "name": "todo",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@reduxjs/toolkit": "^1.1.0",
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-redux": "^7.1.3",
    "react-scripts": "3.4.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}
```

# 作成されたテンプレートのディレクトリ構造を確認する

```bash
├── README.md
├── package.json
├── public
# => 静的ファイル置き場
├── src
│   ├── App.css
    # => App.js で使用する CSS ファイル
    # ※ import './App.css'; で読み込む
│   ├── App.js
    # => アプリケーションのメインコンポーネント
│   ├── App.test.js
    # => App.js のテストコード
│   ├── app
│   │   └── store.js
        # => Redux の store
│   ├── features
│   │   └── counter
│   │       ├── Counter.js
            # => Counter コンポーネント
            # ※ 画面に表示されている数字を上げ下げ出来る。
│   │       ├── Counter.module.css
            # => Counter コンポーネントの CSS ファイル
            # ※ import styles from './Counter.module.css'; で読み込む
            # ※ className={styles.button} の様に使う
            # ※ コンポーネント内で独自のスタイルを定義したいときに使う
│   │       └── counterSlice.js
            # => Counter コンポーネントの “slice” オブジェクト
            # ※ reducer 関数を持つオブジェクト
            # ※ reducer の名前に基づいて、action type の文字列と action creator を作成できる
            # ※ slice オブジェクトについては、Redux Toolkit の公式ドキュメントを参照 [1]
│   ├── index.css
    # => メイン CSS ファイル
    # ※ グローバルなスタイルを定義したいときに使う
│   ├── index.js
    # => メイン JS ファイル
│   ├── logo.svg
│   ├── serviceWorker.js
    # => Service Worker 設定ファイル
    # => Service Worker を使いたいときに使用する
│   └── setupTests.js
    # => テスト実行前の初期設定ファイル
└── yarn.lock
```

[1] [Basic Tutorial | Redux Toolkit](https://redux-toolkit.js.org/tutorials/basic-tutorial#introducing-createslice)
js ファイルから JSDoc で d.ts の型を参照して型チェックする ( jest.config.js を例に)

# 概要
jsにd.tsの型をつけ、補完したり、間違った値を入れたら分かるようにする

# 方法

```js
// @ts-check
/**
 * @type {import('@jest/types').Config.InitialOptions}
 */
const config = {
  ...
};

module.exports = config;

```

# 備考
- VSCodeでしか確認していない
- `@typedef` でもimportが使える
- allowJsとcheckJsを有効にしたら `// @ts-check` 不要かもしれない

# 参考
https://www.reddit.com/r/javascript/comments/aezwdh/using_typescript_declaration_files_with_jsdoc/
https://gist.github.com/hrdtbs/f7e567c0738725a16a9de7326dc11127
マインクラフトコマンド紹介　#1

# 始めに
![mu_san1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615707/03ba3c4d-cddf-ff5a-252c-9696eaae408c.png)
皆さん初めまして！マインクラフターのムー＃です。
今日からQiitaでマインクラフトのコマンド紹介をしていきたいと思います！！

## 今日のコマンド
今日のコマンドはマインクラフトで魔法が使えるようになるコマンドです！
魔法といっても色々ありますが今日紹介するのは浮遊魔法です、実際に使ってみると、
![2020-04-10_18.21.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615707/ab6341eb-3eaa-a145-0070-51d70e6e9761.png)
![2020-04-10_18.21.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615707/da493e16-284d-626b-1ae6-945c7067497a.png)
![2020-04-10_18.21.25_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615707/046e0dd5-d39e-96e7-2f7c-afacbbec6726.png)
![2020-04-10_18.22.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615707/de1417de-f9da-de7b-f30f-8ec9a4bde045.png)
こんな感じに白いモヤに当たった動物が空に飛んで行きそのまま落下して死にます。

###この魔法の仕組み
この魔法は全部で七つのコマンドからできています!![2020-04-10_18.27.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615707/717f6094-a908-1025-e9bd-83169da75d59.png)

①/execute as @a[scores={useRod=1..}] at @s run summon minecraft:armor_stand ~ ~ ~ {NoGravity:1b,Marker:1b,Invisible:1b,Tags:["magicalBall"]}

②/execute as @a[scores={useRod=1..}] at @s run tp @e[tag=magicalBall,limit=1,sort=nearest] ~ ~ ~ ~ ~

③/execute as @e[type=armor_stand,tag=magicalBall] at @s run tp ^ ^ ^1.0

④execute as @p[scores={useRod=1..}] at @s run playsound minecraft:entity.wither.shoot master @p[scores={useRod=1..}] ~ ~ ~ 60 2

⑤/scoreboard players set @a[scores={useRod=1..}] useRod 0

⑥execute as @e[tag=magicalBall] at @s run effect give @e[type=!player,distance=..1.5] minecraft:levitation 1 25

⑦execute as @e[tag=magicalBall] at @s run particle minecraft:effect ~ ~1.5 ~ 0.1 0.1 0.1 0.02 10

 - 事前に入力するコマンド
 - /scoreboard objectives add useRod minecraft.used:minecraft.carrot_on_a_stick

####最後に
今回のコマンドは「パイセンのマイクラ攻略教室」というサイトに掲載されている内容をアレンジしたものになります
コマンドの⑥と⑦の後半を変更すれば自分なりにアレンジすることができます！

#####参考にさせていただいたサイト
https://hollys-command-lecture.hatenablog.com/entry/how-to-magicball
TouchBarにEscキーが表示されなくなったときの対処法

# 環境
MacOS Catalina v10.15.3

# 何が起こったか
いつの間にか、デフォルトで表示されているTouchBarの列にescキーが表示されなくなっていました。
（Fnキーを押したときに表示される列には表示される）

# 対処法
私の環境では、下記サイトに書かれている方法で解決しました。
https://www.reddit.com/r/MacOS/comments/f6thi6/escbutton_disappeared_in_touch_bar/

操作は簡単で、アクティビティモニタから
TouchBarServerを選択し、終了するだけ。

# 他に試したこと
システム環境設定からキーボードの設定、TouchBarに表示する項目を変えたりしてもだめでした。
Unityのはじめかた 〜設定編〜

#はじめに
研究室の引継ぎ資料の代わりの投稿 part 2．

この記事はUnity Hubがインストールされている前提で書いていく．
なかったら[前回の記事](https://qiita.com/yui666a/items/21b3f24610b13009114a)を参考にして欲しい．
前回同様なるべく丁寧に書くつもりだけど，わからないところがあったらコメントで聞くか，他の人の記事を読んで欲しい．

この記事では，

0. チュートリアルについて
1. Unityプロジェクトの作成
2. Unityの設定

あたりまで説明する．

#チュートリアルについて
Unity Hubを起動し，左側にある"使い方を学ぶ"を選択すると，様々なプロジェクトやチュートリアルがある．
初級，中級などランク分けされてて，動画や画像でしっかり説明されているので分かりやすいのだが，なんせ全部「英語」．
日本語も用意してくれてたら強くおすすめできるのだけれど，英語に拒絶反応がある人は適当に調べて日本人が日本語で書いている記事で始めてみるといいかもしれない．

#Unityプロジェクトの作成
そんなどうでもいい話は置いといて，早速初めて行きたいと思う．
左側にある"プロジェクト"を選択し，新規作成をクリックする．新規作成の右にある下向きの三角を押すとUnityのバージョンを選択できるが，基本的には普通に新規作成をクリックするだけでいい．
<img width="977" alt="スクリーンショット 2020-03-03 18.53.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432442/59b54d34-597c-da47-d68b-58a0ad72af4d.png">

作成したいプロジェクトが2次元のプロジェクトか，3次元のプロジェクトか選択する．
プロジェクト名を入力し，保存先を指定して作成ボタンをクリックするとプロジェクトが作成される．
新規プロジェクトを作成すると，少し時間がかかるが固まった訳ではないので大人しく待とう．
<img width="980" alt="スクリーンショット 2020-03-03 18.59.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432442/a00f1d04-820c-1a8f-9b4c-50e0b984a154.png">

ウィンドウが開くとグレーの味気ない画面が表示される．
下の画面のAssetStoreやSceneなどはドラッグ&ドロップすることで場所を移動させることができる．
僕はこの配置がやりやすいのだが，人によってそれぞれ違うと思うので，やっていくうちに自分なりの配置を探して欲しい．
<img width="1440" alt="スクリーンショット 2020-03-03 19.09.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432442/5e3dcae9-aab2-5d5a-2f80-13ee5af4df7c.png">

SceneやGame，Projectなどのウィンドウはそれぞれ以下の役割を持つ．
以下の6つは特によく使うウィンドウで，メニューバーの Window > General からも表示することができる．
**Scene**
ゲームオブジェクトを配置する空間
**Game**
プロジェクトを実行した時に見る画面
**Inspector**
ゲームオブジェクトの詳細な設定を表示，変更する
**Hierarchy**
Sceneに存在するゲームオブジェクトの階層などを表示する
**Project**
プロジェクトのフォルダ
**Console**
ログやエラーを表示する

#Unityの設定
##エディタをVS Codeに変更する
まず，VS Code（任意のエディタ）を指定のエディタに設定する．

メニューバーのUnity > Preferences... > External Toolsを選択する．
<img width="1440" alt="スクリーンショット 2020-03-03 19.35.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432442/84517e8e-934f-ff76-4661-dbbdb38ac3f6.png">

External Script EditorをVS Code（任意のエディタ）に変更する．
おそらくはじめは表示されてないので，Browse...からVS Code（任意のエディタ）を直接指定する．
<img width="1440" alt="スクリーンショット 2020-03-03 19.43.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432442/f570064b-e9c7-b685-02e6-400208f1e62a.png">

##Android端末で実行する準備
上と同じく，メニューバーのUnity > Preferences... > External Toolsを選択する．
Androidという項目にある"SDK"及び"NDK"を選択する．NDKの項目にある"Download"ボタンを押すとちゃんとダウンロードされるのだが，SDKはページに飛ぶだけなので自分で選択してダウンロードしてほしい．

#おわりに
更新が遅くなってしまって申し訳ないです．
次は基本操作を書いていこうと思います．
sh / Makefile で特定のエラーコードを無視したい

# TL; DR

shell スクリプトの場合

```sh
# エラーコード 1 を無視
cmd.sh || exit $(($? - 1))
# 複数のエラーコードを無視したい場合 （下記は 1, 2 を無視）
cmd.sh || ( exit $(($? - 1)) ) || ( exit $(($? - 1)) )
```

Makefile の場合

```make
TARGET:
	# エラーコード 1 を無視
	cmd.sh || exit $$(($$? - 1))
	# 複数のエラーコードを無視したい場合 （下記は 1, 2 を無視）
	cmd.sh || ( exit $$(($$? - 1)) ) || ( exit $$(($$? - 1)) )
```

**追記**：こちらの方法ではエラーコードを変えるという荒っぽいことをしてますが、エラーコードを変えたくない場合の方法、[コメント](https://qiita.com/smatsumt/items/1c599348c123a06458c8#comment-a3e347dce7fb00e7f072)いただきました。よかったら、そちらもご覧ください。

# はじめに

shell スクリプトや Makefile の処理で、「このエラーは処理を続けてほしいんだけど」みたいなこと、たまにありますよね。

sh だと

```shell
cmd.sh || true  # エラーコードが常に 0 になる
```

Make だと

```make
TARGET:
	# 頭の "-" で、エラーを無視するようになる
	-cmd.sh
```

とかやると、エラーを無視してくれますが、あらゆるエラーが無視されます。そうなると、想定外のエラー発生時にも処理が進んでしまうので、できれば特定のエラー時だけ無視するようにしたいところです。

# そこで

```sh
# エラーコード 1 を無視
cmd.sh || exit $(($? - 1))
```

`1` のところを別の数値にすれば、好きなエラーコードを指定することができます。

`||` は、前のコマンドがエラーコード 1 以上で終わった場合に、後ろのコマンドを実行するようにします。
`$?` で直前のコマンドのエラーコードとり、`$(( ))` で計算ができるので、1 を引いて、それを新しいエラーコードにしています。

これで、もしエラーコードが `1` なら新しいエラーコードが `0` になって、正常とみなされ処理が継続される、その他のエラーコードならやはり非 `0` なので、エラーで停止する、という寸法です。

Makefile でも基本的に同じです。`$$` としないと sh のコマンドに `$` が渡らないので、そこだけ注意です。

```make
TARGET:
	# エラーコード 1 を無視
	cmd.sh || exit $$(($$? - 1))
```

# 応用編: 複数のエラーコードを無視したい

複数のエラーコードを正常としたいときも、同じものをつなげていけばOK、、、なのですが、このままだと最初の exit で処理が終わってしまうので `( )` とサブシェルにしてあげましょう。（なお、sh スクリプトの場合に、後ろに処理がある場合も `( )` でくくってあげる必要があります）

```sh
# 複数のエラーコードを無視したい場合 （下記は 1, 2 を無視）
cmd.sh || ( exit $(($? - 1)) ) || ( exit $(($? - 1)) )
```

また、2 つめ以降の `$?` には、それまでの計算が反映された値が入るので、そこには注意が必要です。上の例の場合、２つめの `exit` も `-1` してますが、一つ前ですでに `1` 引かれているので、最初のエラーコードが `2` の場合に、ここで `0` となります。

```sh
cmd.sh || ( exit $(($? - 1)) ) || ( exit $(($? - 2)) )
```

とすると、エラーコード `1`, `3` を無視することになります。

# あとがき

わりとよくあるニーズな気がするのですが、少しググってもページを見つけられなかったので、書いてみました。

「もっとよいやり方があるよ！」という方、ぜひ教えてもらえるとありがたいです :pray:
ValueError: shape mismatch: objects cannot be broadcast to a single shape

juoyter-notebookでグラフ表示の勉強中にでたエラーです。

縦(value)1~6、横(y_pos)a~fの簡単な棒グラフを表示させたい。

# コード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582508/e0ea0df4-ea86-023d-ed37-fb16014975d4.png)

# エラー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582508/f03ad686-4adb-e3ed-91f8-8638adc938a8.png)

直訳すると、
ValueError：形状の不一致：オブジェクトは単一の形状にブロードキャストできません

不一致と思われるものは定義した値くらい？
値を見にいく、
1, 2, 3, 4, 5, 6
a, b, c, d, f
eが抜けている！！
# 解決コード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582508/a930e322-5783-1c86-65a3-f0219845cadf.png)

'e'を追加して無事成功
# 表示成功

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582508/a964ebde-ec0d-1e2c-4e78-a4c99c5b3df6.png)
コロナ対策エンジニア～1週目終了～Teams・Slack・Zoom～（2020年4月）

これまで以下の記事を投稿させていただいた勉強会について記載します。

[「コロナ対策エンジニア～ みんなでCOVID-19ウイルスと戦おう～」](https://qiita.com/gomasa/items/a5565eb2d4e659978330)
[「コロナ対策エンジニア～1日30分の在宅勤務・テレワークのオンライン勉強会～」]
(https://qiita.com/gomasa/items/593d0b13c2a6c377e8ff)

今週はTeams・Slack・Zoomについて勉強会がありました。
昼時12:15～12：45と短時間でテレワークに活用できるツールの勉強ができます。
少しだけ簡単に感想を記載します。

##Microsoft Teamsを使った在宅勤務Tips
開催日時：2020年4月8日（水） 12:15 - 12:45
タイトル：僕なりの Microsoft 365 を使った長期在宅勤務を乗り切るコツ（家庭円満も大事♪）
発表者　：中村 太一（AvePoint Japan 株式会社 / Microsoft MVP）

[【動画はこちら】](https://www.youtube.com/watch?v=WFF5cqapZi8&feature=youtu.be)
[【資料はこちら】](https://speakerdeck.com/taichinakamura/pu-narifalse-
microsoft-365-woshi-tutachang-qi-zai-zhai-qin-wu-wocheng-riqie-rukotu-jia-ting-yuan-man-moda-shi)

内容としては在宅勤務のメリットやTeamsをその中でどう生かしているか、との話でした。
また、「チーム」と「チャネル」の使い分けなど、最初戸惑う部分の説明もありました。
私は会社でTeamsを使っているので、あるある、と思いながら拝聴させて頂きました。

途中でちょっとだけ話が出てきたYammer。
私の会社ではテレワークになってからYammerが大活躍。
テレワークで困ったことや、自分たちのテレワーク写真のアップなど、
情報共有の場として大活躍しています。
今までTeamsがあればYammerいらないかも、と思っていましたが、
このコロナ問題でYammerの存在価値を感じています。

最後に出てきたPower Platform活用のお話。
私もテレワークの中でPower Platformを活用できないか試行錯誤中です。
参考例の説明がありましたら、色々な可能性があるな、と感じています。

##30分でランチ勉強！完全初心者向け、今日から使えるSlackの使い方ガイド 
開催日時：2020年4月9日（木） 12:15 - 12:45
タイトル：完全初心者向け、今日から使えるSlackの使い方ガイド
発表者　：中野 優太郎（所属：Lean In Tokyo）

[【動画はこちら】](https://www.youtube.com/watch?v=8EW7bc4LHts&feature=youtu.be)
[【資料はこちら】](https://speakerdeck.com/covid19engr/wan-quan-chu-xin-zhe-xiang-ke-jin-ri-karashi-eruslackfalseshi-ifang-gaido)

私は利用したことがなかったSlackの勉強会でした。
初心者向けということで、概要と便利機能について教えてもらいました。
TeamsやYammerを使っていると、近い機能であるな、とは思いました。
結局、何をやるかによって、どのツールを利用するかが決まるのだと思います。


##30分でランチ勉強！Zoomを使ったリモートワーク技～ビジネス力UP！ついでに自動化ツール実演も！～
開催日時：2020年4月10日（金） 12:15 - 12:45
タイトル：リモートワークの楽しみ方～Zoom編～使える技と意識すべき点　ついでにZoomにも活用できる自動化ツールも実演
発表者　：チャラ電Mitz（所属：フリーのコミュニティプロデューサー）

[【動画はこちら】](https://www.youtube.com/watch?v=QYRshfoMpu4&feature=youtu.be)

今セキュリティ問題で話題のZoomの回でした。
うちの会社ではZoomは使用禁止。
セキュリティ騒動が収まるまではビジネスでは利用できなさそうです・・・
勉強会の中でも「機密情報は取り扱うな！」との話が！！

ただ、本日の説明で「バーチャル背景」や「Snap Camera」という機能は面白いと感じました。
ビジネスでは利用できませんが、プライベートでは利用できそうです。
例えばテレワークの合間に同僚とやり取りする気分転換等は使えそうな雰囲気でした。

こういった特色があるのは嬉しいですね。
ツールを差別化して、場面によって使い分けすることを考えることができますから。


##オンライン勉強会の内容について
勉強会の最新の内容は以下の通りです。

■2020年4月13日（月） 12:15 - 12:45
[Microsoft Power Appsでリモート出退勤管理アプリを作る](https://power-covid19.connpass.com/event/172167/)

■2020年4月14日（火） 12:15 - 12:45　　★NEW
[30分でランチ勉強！世界18万人のエンジニアが参加するCall for Codeとは](https://power-covid19.connpass.com/event/172672/)

■2020年4月15日（水） 12:15 - 12:45
[Microsoft Power Automateで健康状態報告フローを作る](https://power-covid19.connpass.com/event/172166/)

■2020年4月16日（木） 12:15 - 12:45
[30分でランチ勉強！みんなが楽々使えるビジネス版 LINE で、テレワークでも楽しくコミュケーション](https://power-covid19.connpass.com/event/172645/)

■2020年4月17日（金） 12:15 - 12:45　　★NEW
[濃厚接触確認アプリのオープンソース開発者求む！](https://power-covid19.connpass.com/event/172809/)

■2020年4月22日（水） 12:15 - 12:45　　★NEW
[【就活生向け】21卒内定者が語るポートフォリオの重要性と便利なサービス](https://power-covid19.connpass.com/event/173052/)

##私の利用しているテレワークツール
ちなみに、私の利用しているテレワークツールはOffice365になります。
別の記事でも書きましたが、Skype for Businessが大活躍してくれています。
そしてYammerとMicrosoft Stream。
コロナ対策エンジニアで紹介された以外にも色々なツールがあって、
テレワークをする中で色々な活用手段が見つかっています。

自分自身で見つけた活用手段は、また機会があれば情報展開していきたいと思います。
rails -v を行った際の Permission denied

macos
自分用のメモです

# /usr/local/bin/rbenv-communal-gem-home を確認


```
mkdir: /usr/local/bin/../version_cache: Permission denied
/usr/local/bin/rbenv-communal-gem-home: line 21: /usr/local/bin/../version_cache/2.6.3: No such file or directory
```
となっていたので、rbenv-communal-gem-home　をエディタに表示して確認してみる

```
$ open /usr/local/bin
# usr/local/binディレクトリをオープン
```

``` rbenv-communal-gem-home.
if [ "$1" = "--complete" ]; then
  exec rbenv-versions --bare
fi

rbenv_version="${1:-$(rbenv-version-name)}"
if [ -L "$RBENV_ROOT/versions/$rbenv_version/lib/ruby/gems" ]; then
  cachedir="${BASH_SOURCE%/*}/../version_cache"
  cachefile="$cachedir/$rbenv_version"
  if [ -f "$cachefile" ]; then
    communal_version="$(cat $cachefile)"
  else
    mkdir -p "$cachedir"
    communal_version="$("$RBENV_ROOT/versions/$rbenv_version/bin/ruby" -rrbconfig -e 'puts RbConfig::CONFIG["ruby_version"]')"
    echo "$communal_version" > "$cachefile"
  fi

  echo "$RBENV_ROOT/gems/$communal_version"
else
  exit 1
fi
```
こうなってた。すなわち

```
mkdir: /usr/local/bin/../version_cache: Permission denied
```
は、　mkdir -p "$cachedir"　でディレクトリ作りたいけど、このgemにはその権限がない。だと思う。

```
/usr/local/bin/../version_cache/2.6.3: No such file or directory
```
は、 echo "$communal_version" > "$cachefile" の際に cachefileが存在しないために出てきたエラーだと思う。(cachedirが存在しない、作成できなかったため)

# cachefileのパスに含まれているcachedirを有効にする

```
# cachedir="${BASH_SOURCE%/*}/../version_cache" を消して
cachedir="${BASH_SOURCE%/*}/../Cellar/rbenv-communal-gems/1.0.1_1/version_cache"
```
アーキテクチャとは

#アーキテクチャとは
構造や設計思想のこと。
アーキテクチャの種類として
・MVC
・MVVM
・レイヤード
・ヘキサゴンナル
・オニオン
・クリーン
・VIPER　　などがある。

##アーキテクチャの簡単な流れ
オニオンアーキテクチャを例にすると
ユーザーインターフェース（指示を出す）
↓
アプリケーションサービス（計画を作る）
↓
ドメインサービス（命令をする）
↓
ドメインモデル（命令を受けて作業）

この流れがないと複数人で作業をしたときに、人それぞれのやり方でやることになり、ディレクトリやデータの流れがめちゃくちゃになってしまうため、指針とか方向性をしっかり定めるためにある。

##複数のアーキテクチャがある理由
今までのアーキテクチャで、できないことができたから新たに作られていった。

##MVCとは
Model　View Controllerの頭文字を組み合わせたものでアーキテクチャの一つ

`Model`はデータを格納している場所
`View`はユーザーが見る画面
`Controller`はModelとViewを繋ぐもの


簡単に図に表すとこんな感じ
<img width="500" alt="スクリーンショット 2020-04-10 17.55.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537459/dc8f3ed2-6b8a-0409-f9a4-dfb5f5613b5f.png">

MVCは３つに分かれているので変更点があったときに修正がしやすくなる。

#まとめ
アーキテクチャは重要！！！！
ソケットプログラミング　タイムアウト付きconnect

#概要
クライアントサイドのソケットプログラミングでタイムアウト付きコネクトをする実装です。

昔実装したものを思い出し思い出し書き起こしました。

connect()は同期型ですのでエラーか接続するまで待ってしまいます。
永遠に待たれると困る場合はタイムアウト機能が欲しくなりますが、connect()自体には任意の時間でのタイムアウトするような機能はありません。

タイムアウトを行うためには、一度非同期にしてからconnect()を行います。
その後、同期型に戻してからselect()で待ちます。
このselect()でタイムアウトを実現します。

以下にコードを記載します。

```cpp:LinuxC_TimeoutConnect.cpp

//タイムアウト付きコネクト(非同期コネクト)
int Connect(SOCKET & socket, count struct sockaddr * name, int namelen, timeval timeout)
{
	//接続前に一度非同期に変更
	int flags = fcntl(soket, F_GETFL);
	if(-1 == flags)
	{
		return -1;
	}
	int result = fcntl(socket, F_SETFL, flags | O_NONBLOCK);
	if(-1 == result)
	{
		return -1;
	}

	//接続
	reuslt = connect(socket, name, namelen);
	if(SOCKET_ERROR == reuslt)
	{
		if(EINPROGRESS == errno)
		{
			//非同期接続成功だとここに入る。select()で完了を待つ。
			errno = 0;
		}
		else
		{
			//接続失敗 同期に戻す。
			fcntl(socket, F_SETFL, flags );
			return -1;
		}
	}

	//同期に戻す。
	result = fcntl(socket, F_SETFL, flags );
	if(-1 == result)
	{
		//error
		return -1;
	}

	//セレクトで待つ
	fd_set readFd, writeFd, errFd;
	FD_ZERO(&readFd);
	FD_ZERO(&writeFd);
	FD_ZERO(&errFd);
	FD_SET(socket, &readFd);
	FD_SET(socket, &writeFd);
	FD_SET(socket, &errFd);
	int sockNum = select(socket + 1, &readFd, &writeFd, &errFd, &timeout))
	if(0 == sockNum)
	{
		//timeout error
		return -1;
	}
	else if(FD_ISSET(socket, &readFd) || FD_ISSET(socket, &writeFd) )
	{
		//読み書きできる状態
	}
	else
	{
		//error
		return -1;
	}

	//ソケットエラー確認
	int optval = 0;
	socklen_t optlen = (socklen_t)sizeof(optval);
	errno = 0;
	result = getsockeopt(socket, SOL_SOCKET, SO_ERROR, (void *)&optval, &optlen);
	if(result < 0)
	{
		//error
	}
	else if(0 != optval)
	{
		//error
	}

	return 0;
}

```

Linux の場合はソケットオプションを読みだして、SO_ERRORが0かを確認する必要があります。
参考：[Man page of CONNECT](https://linuxjm.osdn.jp/html/LDP_man-pages/man2/connect.2.html)　の エラー、EINPROGRESS

Windowsでは必要ないです。

また、Linux版のselect()では引数に渡したタイムアウト値(ここではtimeval timeout)の値を更新してしまいます。
Windows版では更新しませんでした。


以下、Windows版です。

```cpp:WinC_TimeoutConnect.cpp

//タイムアウト付きコネクト(非同期コネクト)
int Connect(SOCKET & socket, count struct sockaddr * name, int namelen, timeval timeout)
{
	//接続前にいったん非同期に変更
	unsigned long mode = 1;
	int result= ioctlsocket(socket, FIONBIO, &mode);
	if(NO_ERROR != result)
	{
		return -1;
	}

	//接続
	result= connect(socket, name, namelen);
	if(SOCKET_ERROR == result)
	{
		int errono = WSAGetLastError();
		if(WSAEWOULDBLOCK == errono)
		{
			//非同期接続成功だとここに入る。select()で完了を待つ。
			errno = 0;
		}
		else
		{
			//接続失敗
			//同期型に戻す。
			mode = 0;
			ioctlsocket(socket, FIONBIO, &mode);
			return -1;
		}
	}

	//同期型に戻す。
	mode = 0;
	result= ioctlsocket(socket, FIONBIO, &mode);
	if(0 < result)
	{
		//error
		return -1;
	}

	//セレクトで待つ
	fd_set readFd, writeFd, errFd;
	FD_ZERO(&readFd);
	FD_ZERO(&writeFd);
	FD_ZERO(&errFd);
	FD_SET(socket, &readFd);
	FD_SET(socket, &writeFd);
	FD_SET(socket, &errFd);
	int sockNum = select(socket + 1, &readFd, &writeFd, &errFd, &timeout))
	if(0 == sockNum)
	{
		//timeout
		return -1;
	}
	else if(FD_ISSET(socket, &readFd) || FD_ISSET(socket, &writeFd) )
	{
		//読み書きできる状態
	}
	else
	{
		//error
		return -1;
	}


	return 0;
}

```
Vueのレンダリング時インクリメントした値がおかしかった件

# TL;DR

```
[Vue warn]: You may have an infinite update loop in a component render function.
```

これが起こる理由としては、レンダリング中に変数の値を変更すると無限ループが発生する。

詳しい解説は下記
[You may have an infinite update loop in a component render function. 問題の調査](https://qiita.com/amuyikam/items/b1580a20a0b12aee0d48)


# なにをしようとしたら起こったか

下記のように`computed`と`computed`の検証を行っていた。

```html

<div id="app">
  <p>
    {{incNum}}
    {{incNum}}
    {{incNum}}
  </p>
  <p>
    {{incNumMet()}}
    {{incNumMet()}}
    {{incNumMet()}}
  </p>
  <pre>{{$data}}</pre>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

```
```javascript
const app = new Vue({
  el:"#app",
  data:{
    num:0
  },
  computed:{
    incNum:function(){
      return ++this.num;
    }
  },
  methods:{
    incNumMet:function(){
      return ++this.num;
    }
  }
})
```

・出力結果

```
405 405 405

406 407 408

{
  "num": 408
}
```

なんかめちゃくちゃインクリメントされてる・・・

で、下記の様にエラーが出ていた

```
[Vue warn]: You may have an infinite update loop in a component render function.

(found in <Root>)
```

# 原因

描画時にdata内のパラメーターを変更すると無限ループが起こるらしい。
ただ、Vue側が１００回で止めてくれるのでブラウザが固まることはない。

詳しい説明は下記

[You may have an infinite update loop in a component render function. 問題の調査](https://qiita.com/amuyikam/items/b1580a20a0b12aee0d48)

# 解決策

結論としては一度だけ実行する`v-once`ディレクティブを使用すれば良い

・v-onceを追記

```html

<div id="app" v-once>
```

・出力結果


```
1 1 1

2 3 4

{
  "num": 4
}
```
【BizRobo】ブランチの特徴

v10.4

# 基本
BizRoboの独特なフロー制御として、ブランチがある。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/d2f4251a-a874-798d-d2c2-fb7cc80234a1.png)
上記のフローを作成した場合、ステップの実行順序は 1 → 2 → 3 → 4 → 5 となる。

# ブランチと変数のスコープ
BizRoboでは各ステップの状態がすべて記憶されており、フローが別のブランチへ移ると、状態がすべてブランチの分岐前に戻る。例えば以下のように、ステップごとに文字列を変数へ結合してみる。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/cf523403-1d91-cbbc-bc41-3848104ce6e5.png)
この実行結果のログは、以下の通りとなる。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/df6087dd-b244-5e27-386c-25b069928ab6.png)

この通り、1つ目のブランチの最後のログは「123」となっているが、ステップ1の後から分岐した2つ目のブランチの最後のログは「145」となっている。変数の状態が分岐前に一度戻っていることがわかる。
ステップごとの状態がスタックのように積み上げられているとイメージすると、わかりやすいかもしれない。

変数の設定で「グローバル」を選ぶと、変数の状態がブランチによって元に戻らなくなる。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/f371b397-9a00-9466-0156-3f96266652b2.png)
変数1をグローバルにしてさきほどのフローを実行すると、ログは以下のようになる。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/e4c63333-be82-e227-4c9c-ced85c7105b8.png)

ブランチは合流させることもできる。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/cdbf6971-cab9-7381-7a00-d00a2db5c226.png)
上記のフローを実行した場合、ログは以下のようになる。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/2205e70e-6413-64f9-f2f0-e9074a047385.png)
合流先のステップ6以降が2回実行される。
個人的には、一度分岐したブランチは特に理由がない限り合流させないほうが良いと思う。あまり分岐＆合流を繰り返すと、フローが分かりづらくなる。

# エラー時の動き
ロボットでエラーが発生した場合、**エラーが起きたブランチの後続のステップのみ**がスキップされ、エラー前に分岐したブランチはエラー後も実行される。ロボットの実行がすべてスキップされるわけではない。
※Design Studio でデバッグ実行する場合は、エラーのたびにフローが一時停止する。

以下のようなロボットがあり、step 3 でエラーが起きた場合を例にする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/694fe385-2246-99f4-cbba-3494cc31739b.png)
この場合、step 4 は実行されないが、step 5 はエラーの後、実行される。
つまり、ブランチを分けるのであれば、それぞれはほぼ完全に独立した処理であるべきで、見た目のためにブランチを分けたりすると、エラー発生時に予期しない動作を重ねる懸念がある(独立した処理ならロボットを分けるほうが良いが)。

この特性を活かした使い方として、プログラム言語にある try-finally のような実装が可能。
フローの冒頭にブランチを分けて、最後のブランチに終了処理を実装しておけば、ロボットが正常に終了してもエラーになっても実行される。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/76e20ad6-f15c-fb6e-fb3c-5b97a2166468.png)

ブランチとはあまり関係がないが、ステップでエラーが起きた時にどうするかは、ステップのプロパティの「エラー処理」のタブで変更できる。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/58409cbc-0afd-fe0d-df89-48c4cbfb9575.png)
「テスターちゃん」で学ぶソフトウェアテスト⑦

#1. 「テスターちゃん」について
初心者(新人)向けに描かれたソフトウェアテストの漫画になります
たまたまJSTQBについて調べていた時に見付けたブログの記事がきっかけで読むようになりました
[JSTQBを取るメリット5選](http://testerchan.hatenadiary.com/entry/2018/02/15/001117)

今でも更新がある度にチェックしたり、書籍版を読み返したりしたり、とテスト関連の資料として活用しています

[Blog](http://testerchan.hatenadiary.com/)
[書籍版](https://books.rakuten.co.jp/rb/16202142/)

#2. LOG
[「テスターちゃん」で学ぶソフトウェアテスト①](https://qiita.com/156Musik/items/46111ec9cfae5f9aa88d)
[「テスターちゃん」で学ぶソフトウェアテスト②](https://qiita.com/156Musik/items/3c1a91126dc15bd2bf40)
[「テスターちゃん」で学ぶソフトウェアテスト③](https://qiita.com/156Musik/items/1a9450a15aa3607fe2d5)
[「テスターちゃん」で学ぶソフトウェアテスト④](https://qiita.com/156Musik/items/77d4471ae21aac937f78)
[「テスターちゃん」で学ぶソフトウェアテスト⑤](https://qiita.com/156Musik/items/b89e104010dfcced3fd0)
[「テスターちゃん」で学ぶソフトウェアテスト⑥](https://qiita.com/156Musik/items/ebb1d2339c3a256f8ec9)
「テスターちゃん」で学ぶソフトウェアテスト⑦ :point_left_tone1:イマココ
[「テスターちゃん」で学ぶソフトウェアテスト⑧](https://qiita.com/156Musik/items/fb1aa75351660c1150f8)

#3. モブテストのやり方

##3.1 モブテストって何？
- 一つの場所に集まって
- 一つの画面を見ながら
- みんなで探索テストをする

技法である

一人がデバイスを操作する人、他の人がどう言うテストをするか指示を出す人になって、テストを進める

##3.2 役割
**ドライバー**
・操作する人のこと
・基本的に「No thinking」
・他の人の指示で手を動かす

**ナビゲーター**
・ドライバー以外の人が担当する
・ドライバーに指示を出す

##3.3 モブテストの基本的なフロー

###①事前準備
・ファシリテーターを決める
・大きな画面がある部屋を確保する
・仕様把握を行う
　⇒いきなりやっても案が出ないこともあるので、あらかじめ把握しておくことが必要

###②開始
・今回の目的を伝える
・ドライバーを決める
・ナビゲーターを決める

###③モブテスト実行
・4～5分くらい

###④振り返り
・5～10分くらい

###⑤ 
・③と④を繰り返す

補足
・指示は細かいより抽象化されている方がいいらしい
　自分の考えが相手の解釈を通して出ていく時に新しい発見があるかも

##3.4 メリット
・テストのやり方や考え方を共有出来る
　⇒みんないろんな知見を持っているが、それを他人に伝えることが少ないため
・それぞれの**得意**を合わせることで、よりよい結果を出せる可能性もある

補足
・企画者や開発者を交えてテストを行うと新しい観点が出てきそう
　どんなテストをしているか、や、出たバグを直に伝えることが出来る
5rep - Embulk CSV・TSV読み込み 

# 汎用的な読み込み方法
- guess.ymlに読み込みフォーマット　パースフォーマット記載
- 下記TSV読み込み
- 読み込んだらstdoutにoutput

``` guess.yml
in:
  type: file
  path_prefix: ./{File Name}
  delimiter: "\t"
  quote: '"'
  escape: '\'
  null_string: ''
out:
  type: stdout
```

# guessコマンドでファイル読み込みファイル生成

``` shell
$ embulk guess ./guess.yml -o config.yml
```

- 生成後ファイル
- ファイルを読み込む際columns名指定・型指定などを記述する必要があるがguessコマンドでよしなに生成してくれる

``` config.yml
in:
  type: file
  path_prefix: ./{File Name}
  file_ext: .tsv
  parser:
    charset: UTF-8
    newline: LF
    type: csv
    delimiter: "\t"
    quote: '"'
    escape: '"'
    trim_if_not_quoted: false
    skip_header_lines: 0
    allow_extra_columns: false
    allow_optional_columns: false
    columns:                                      # サンプルです
    - {name: c0, type: long}
    - {name: c1, type: long}
    - {name: c2, type: string}
    - {name: c3, type: timestamp, format: '%Y-%m-%d %H:%M:%S%z'}
    - {name: c4, type: string}
    - {name: c5, type: string}
    - {name: c6, type: string}
    - {name: c7, type: string}
    - {name: c8, type: long}
    - {name: c9, type: timestamp, format: '%Y-%m-%d %H:%M:%S.%N%z'}
out:
  type: stdout
```