OmniAICreator/Qiita-1.07M huggingface dataset:
[Python]Seleniumを用いたログイン処理の自動化方法 備忘録

* Seleniumを用いたWebページのログイン処理の自動化方法についてメモする。
  * 個人用メモ※何件も類似事例あり。


## 事前準備

* chromedriver取得
  * コードと同一階層に`chromedriver`を配置する。`chromedriver`の取得方法は[こちら](https://qiita.com/KWS_0901/items/7191b5f5d129aba6315c)を参照のこと。

## 構成

```
root_dir 	--- login.py
			|_ chromedriver.exe
			|_ conf/setting.conf
```



## コード

* `conf/setting.conf`

  * 設定ファイル。接続先のページ情報(URL,画面要素)とログイン情報を記述する。

  ```conf
  [PAGE_INFO]
  URL= TARGET_URL
  ELEM_ID_FORM_USERNAME=USERNAME_ID
  ELEM_ID_FORM_PASSWORD=PASSWORD_ID
  ELEM_ID_BTN_LOGIN=LOGIN_BTN_ID
  [USER_INFO]
  USERNAME = USERNAME
  PASSWORD = PASSWORD
  ```

* `login.py`

  * 上記設定ファイルの接続情報・ログイン情報をもとに、ログイン処理を行う。
    * 抽象的に記述しているため、対象のページの各画面要素を確認すること。

  ```python
  from selenium import webdriver
  from selenium.webdriver.chrome.options import Options
  from selenium.webdriver.support.ui import WebDriverWait
  from selenium.webdriver.support import expected_conditions as EC
  import time
  import configparser
  
  # 設定ファイル読み込み
  conf = configparser.ConfigParser()
  conf.read('conf/setting.conf')
  # ページ情報
  TARGET_URL = conf['PAGE_INFO']['URL']
  TARGET_ELEM_ID_USERNAME = conf['PAGE_INFO']['ELEM_ID_FORM_USERNAME']
  TARGET_ELEM_ID_PASSWORD = conf['PAGE_INFO']['ELEM_ID_FORM_PASSWORD']
  TARGET_ELEM_ID_LOGIN_BTN = conf['PAGE_INFO']['ELEM_ID_BTN_LOGIN']
  # ログイン情報
  USERNAME = conf['USER_INFO']['USERNAME']
  PASSWORD = conf['USER_INFO']['PASSWORD']
  
  
  with webdriver.Chrome("./chromedriver.exe") as driver:
  
      # ページ上のすべての要素が読み込まれるまで待機
      wait = WebDriverWait(driver, 15)
      driver.implicitly_wait(10)
      driver.get(TARGET_URL)
      wait.until(EC.presence_of_all_elements_located)
  
      # USERNAME 要素を指定 -> 入力
      elem_username = driver.find_element_by_id(TARGET_ELEM_ID_USERNAME)
      elem_username.send_keys(USERNAME)
  
      # PASSWORD 要素を指定 -> 入力
      elem_password = driver.find_element_by_id(TARGET_ELEM_ID_PASSWORD)
      elem_password.send_keys(PASSWORD)
  
      time.sleep(3)
  
      # ログインボタン要素を指定 -> クリック
      elem_login_btn = driver.find_element_by_id(TARGET_ELEM_ID_LOGIN_BTN)
      elem_login_btn.click()
  
      driver.quit()
  
  ```

  

## 動作確認

```shell
python login.py
```
指定フォルダ内にある全てのファイル名を取得するバッチ


#説明
指定フォルダ内にある全てのファイル名を取得する


```bat:exec.bat
@echo off
@REM /s:サブフォルダ検索 /r:正規表現 /i:大文字、小文字区別なし
@REM utf-8表示
chcp 65001

set /p IN="フォルダパスを入力してください（サブフォルダは全て検索対象）:"
set /p IN2="対象としたいファイル名を入力:"

dir /b /s %IN% >> path.txt

for /f %%a in (path.txt) do (
    echo %%a|find "%IN2%" >> log.txt
)

pause
```
php artisan optimize コマンドの罠


###php artisan optimize とphp artisan optimize:clearの違いについて

自分自身optimizeコマンドに関して大きく勘違いしており、上記のコマンド(optimize,optimize:clear)は同じであると思っていた。
実際にコマンドを打ってみると分かるが、出てくる内容は全く異なるものである。

```
# php artisan optimize:clear
Cached events cleared!
Compiled views cleared!
Application cache cleared!
Route cache cleared!
Configuration cache cleared!
Compiled services and packages files removed!
Caches cleared successfully!
```
```
# php artisan optimize
Configuration cache cleared!
Configuration cached successfully!
Route cache cleared!
Routes cached successfully!
Files cached successfully!

```
見ての通り、cacheするか、cacheを削除するかといった部分で大きく異なるところがある。
下記のサイトに非常にわかりやすい表が記載されていた

https://ichi-404.hatenablog.com/entry/2020/04/14/_%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E7%94%9F%E6%88%90%E3%83%BB%E5%89%8A%E9%99%A4%E7%B3%BB%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AE%E9%81%95%E3%81%84%E4%B8%80%E8%A6%A7

###php artisan optimize に関して

下記アップグレードガイドにて、php artisan optimizeは非推奨である旨が記載されている。

```
optimizeコマンド
以前から非推奨になっていた、optimize Artisanコマンドは削除されました。
PHP自身がOPcacheを含んだ、最近の向上により、optimizeコマンドは妥当なパフォーマンスの向上を提供できなくなりました。
そのため、composer.jsonファイルのscripts項目から、php artisan optimizeを取り除いてください。
```


https://readouble.com/laravel/5.6/ja/upgrade.html?header=optimize%60%25E3%2582%25B3%25E3%2583%259E%25E3%2583%25B3%25E3%2583%2589

OPcahceの影響がどのあたりに出るかは理解してないが、不要なコマンドであるということであろうか。

なんにせよ、もう少し裏側の仕組みを理解して追記していきたいと思う。
[sed] 文法メモ


# 概要

業務においては、`H` や `N` といった sed コマンドを使わずに
他の LL (python, rubyなど) を用いる方が良いと思う.

しかし、レガシーシステムで sed だけで実現した複雑な分岐に遭遇することもあるので
文法メモを書き出しておく.

**誤りがあれば、本ページを修正するか、もしくは破棄します**

　

　

## (1) 検索パターンと置換パターンについて

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/b1c654a5-3e17-d3f0-ada7-ce3afaf4f09f.png)

## (2) メタキャラクタ

前述の「**<font color="4477aa">検索</font>パターン**」と「**<font color="cc7747">置換</font>パターン**」の 2つに分かれる.

### (2-1) <font color="4477aa">検索</font>パターン

#### (2-1-1) <font color="4477aa">検索</font>パターンにおける特殊文字

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/267fe14b-ba12-d83c-ca0c-506248e4e637.png)

#### (2-1-2) <font color="4477aa">検索</font>パターンにおけるクラス文字

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/0fc4fc3d-bbbc-904f-42ad-9e0b9030eed1.png)

#### (2-1-3) <font color="4477aa">検索</font>パターンにおける実例

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/f1b8e217-3976-a428-fcfe-ba633db13397.png)


### (2-2) <font color="cc7747">置換</font>パターン

#### (2-2-1) <font color="cc7747">置換</font>パターンにおける特殊文字

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/a16ed20e-42e2-757e-20e5-7641b0e536e5.png)


## (3) 入出力コマンド

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/7c54176b-244e-719a-21fc-8a90d1381b75.png)


## (4) パターンスペース と ホールドスペース

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/12b35bb5-94c1-4599-eb9f-2c70f128ba00.png)

## (5) 分岐

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/8dd60119-649e-7a99-9cd1-733095d0ae5b.png)
[CSS]<header>と<main>の背景や文字が重なる？

# はじめに
本記事では、私が昨日
`headerとmainの背景や文字が重なる`ことを解決した方法を記述します。

# 結論
いきなり結論ですが、
`position absolute`が邪魔をしています。

これを記述していることで、本来下に来るはずの<main>で記述したものが、
出て来なくなります。

## 例
超簡単ですが、
①

```html
<div class="contents">
   <div class="top-content"> 
   </div>
   <div class="bottom-content">
   </div>
</div>
```

```css
.top-content{
  height: 250px;
  width: 500px;
  background-color: lightcoral;
}

.bottom-content{
  height: 250px;
  width: 500px;
  background-color: lightblue;
}
```

②


```html
<div class="contents">
   <div class="top-content"> 
   </div>
   <div class="bottom-content">
   </div>
</div>
```

```css
.top-content{
  height: 250px;
  width: 500px;
  background-color: lightcoral;
  position: absolute;
}

.bottom-content{
  height: 250px;
  width: 500px;
  background-color: lightblue;
}
```

というものがあったとします。

## 実際の図
①

![position absoluteの画像１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1768158/18e43f84-4962-57f4-c858-a2bc07b1aebf.png)

②

![position absoluteの画像２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1768158/ae7cf14e-d9d3-ce8f-cd21-6adf323fdbc4.png)

青色が消えました。

`position absolute`を使用すると、
「位置が浮いてしまう」というみたいです。

# 終わりに
結論はかなり簡単な話でしたが、
何時間も悩んでいました。

悩んでいる途中で`検証`を使ったらかなり便利なことに気がつき、
検証で原因を突き止めました。

CSSで実験をしたいとき、検証を使うと良いかもしれませんね！

以下参考サイトです。
[position:absoluteを使うと次のブロックが重なってしまう](https://teratail.com/questions/27989)
[CSSのposition:absoluteとrelativeの使い方を理解する！要素を重ねる方法](https://natsukimemo.com/position-absolute-relative)

明日も頑張ろう！！
[Ruby] all?メソッドとinclude?メソッドの合わせ技

##はじめに
少し前にall?メソッドとinclude?メソッドを記事にしましたが、この二つを使うと配列の中に複数の要素が含まれているか確認するのにとても便利だったため、合わせ技を記事にしておきます。
↓それぞれの基本的な使い方はこちらをご確認ください。

https://qiita.com/minhee/items/815d10da29b0eb0dbf68


https://qiita.com/minhee/items/43ba0ec0866988052fb1


##all?とinclude?の合わせ技

配列の中に複数の要素があるかどうかを調べる際にこの二つを組みわせるとすっきりとコードを記述することができます。
例えば、
[1, 2, 3, 4, 5]このような配列があったとして、1と3と5の全てがあるかどうかを調べたいとします。
ここでinclude?の登場ですが、include?の引数は一つしか渡せません。
もしinclude?だけでこれを実現しようとすると下記のようになります。

```ruby
array = [1, 2, 3, 4, 5]

array.include?(1) && array.include?(3) && array.include?(5)
=> true

array.include?(1) && array.include?(3) && array.include?(6)
=>false
```

all?と組み合わせば上記のようなコードをすっきり書くことができます。
調べたい複数要素も配列にしておきます。

```ruby
array1 = [1, 2, 3, 4, 5]
array2 = [1, 3, 5]

array2.all?{|n| array1.include?(n)}
=> true

array2 = [1, 3, 6]
array2.all?{|n| array1.include?(n)}
=> false
```
このようにall?のブロック変数に一つずつ放り込む特徴を利用して引数を一つしか取れないinclude?を使えるようにしてあげます。
[sed]【1行野郎】単語区切りで置換する


|本シリーズのトップページ|
|:--|
|https://qiita.com/robozushi10/items/5d1313fa11ede179ddad|

# 概要

「yakkety」という単語なら「artful」に置換するが、「**a**yakkety」などだったら置換しない.

```bash
$ sudo sed 's/\<yakkety\>/artful/g' /etc/apt/sources.list
```
【1行野郎】最新の chromedriver をダウンロードする [2021/08/25確認済み]


# 概要

2021/08/25 に動作確認済み.

`https://chromedriver.storage.googleapis.com/<最新バージョン>/chromedriver_linux64.zip`
にアクセスして、`chromedriver_linux64.zip` をダウンロードする

# 留意点

恐らく別途 xmllint のインストールが必要だと思う.

また、将来バージョン付与のルールが変更になったら、
下記 🛑 のソート条件を変更してやる必要がある.

# コード

```bash
$ wget https://chromedriver.storage.googleapis.com/ -O - | \
   xmllint --format - --xpath="/ETag/Key/" | \
   grep -i linux64 | \
   sort -t'.' -k 1,1n 🛑| \
   sed -n '$s%<Key>\(.*\)</Key>%\1%p' | \
   xargs -I@ wget https://chromedriver.storage.googleapis.com/@ 

```
week コマンド パラリンピックバージョン

[week]: https://github.com/kaz-utashiro/App-week
[optex]: https://github.com/kaz-utashiro/optex
[Getopt::EX]: https://github.com/kaz-utashiro/Getopt-EX
[Getopt::EX::i18n]: https://github.com/kaz-utashiro/Getopt-EX-i18n
[termcolor]: https://github.com/kaz-utashiro/Getopt-EX-termcolor
[Getopt::EX::Colormap]: https://metacpan.org/pod/Getopt::EX::Colormap

![スクリーンショット 2021-08-25 19.49.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36551/9e7771dd-a6c2-782d-2201-ef74e2725a0b.png)
![スクリーンショット 2021-08-26 12.21.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36551/79f5aac9-aee4-2056-c264-7f27907e5252.png)


# week コマンドの続き

- [ターミナルで使える色っぽいカレンダー - Qiita](https://qiita.com/kaz-utashiro/items/603f4bca39e397afc91c)
- [ライオンズカラーのカレンダーと termcolor モジュール - Qiita](https://qiita.com/kaz-utashiro/items/38cb50a4d0cd34b6cce6)
- [Tokyo2020 カレンダーと i18n モジュール - Qiita](https://qiita.com/kaz-utashiro/items/be37a4d703f9d2208ed1)
- [week コマンドの金メダル仕様と和暦表示 - Qiita](https://qiita.com/kaz-utashiro/items/d894932819b83a0be611)

# パラリンピックカラー

パラリンピックが始まるので、そのシンボルカラー3色を使ったデザインを作ろうとしてみたが、どうもうまくいかなくて、一度は諦めた。

その後、いろいろ試してみて、五輪カラー5色、東京大会のエンブレムカラー2色、パラリンピックカラー3色を組み合わせて、一応見られるものになったのでリリースして、会期中は使うことにしましょう。地味な色使いです。

![スクリーンショット 2021-08-25 19.52.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36551/02d59d81-d68a-e957-3855-3df96048ad2e.png)

リバースビデオバージョンは作ってません。どうも、絵心がなくこういうのは不得手なので、気になった人は、どんどん直しちゃってください。

ちなみに、定義はこんな感じ。マクロには、こういう風に日本語も使えます。

```
define パラ赤　#aa272f
define パラ青　#00549f
define パラ緑　#008542
option --para2020 \
        --paralympic-dow \
        --cm FRAME=白/パラ青 \
        --cm *DAYS=*WEEK=I;パラ緑/白 \
        --cm *MONTH=I;黒/白 \
        --cm THIS*=I;白/パラ赤,THISDAY=+DS
```

# リポジトリ

https://github.com/kaz-utashiro/App-week

# インストール

cpan で公開しているので、cpanm (cpanminus) を使ってインストールします。

```
$ curl -sL http://cpanmin.us | perl - App::week
```
magento、ナビが無い時

# はじめに

magentoをインストールしてきました。
しかし、ナビが無いのです。
驚きの白さ。

![764D2613-4B0F-4A1E-B40F-6DF5A6E88A33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148394/f93a1d64-af2c-0195-cf48-78b81280a204.png)



# 最終更新日
2021年8月25日


# 環境の情報
OS
ubuntu 20.04


# 詳しく
ナビがありません。
そんな時は、管理画面にある、カテゴリを確認してみます。もし、何も入っていなければ何かしら登録してみます。

お好みで下記をします。

①サンプルを取ってくる。
②カテゴリに何か登録する。


# 参考

こちらを参考までに。

https://docs.magento.com/user-guide/catalog/navigation-top.html

https://devdocs.magento.com/guides/v2.4/install-gde/install/sample-data-after-composer.html

# 完成すると
こうなります。
![DC3500D2-847B-4872-82AB-7A7998580FA2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148394/56e2c25c-0056-d361-6479-a107d30a68fc.png)
小型 Sed 集

# はじめに

Qiita に投稿した小型の Sed 集.

|コンテンツ|一言|
|:--|:--|
|[「コメント『#』のみ」「空行」「スペースのみ」を取り除く](https://qiita.com/robozushi10/items/5addd649fdabe24a9833)|<font color=#449944>削除</font>|
|[単語区切りで置換する](https://qiita.com/robozushi10/items/e3186875914176cc8bde)|<font color="blue">置換</font>|
|[コロン「:」区切りによる最短一致と最長一致の取り出し](https://qiita.com/robozushi10/items/1e56eece082643fb58da)|<font color=Red>最短</font><font color=#ff6600>パターンマッチ</font>|
|[連続しない複数行を表示する (例: 2〜4行目と9〜13行目)](https://qiita.com/robozushi10/items/8458ee9e446cff11cf9f)|<font color=#ff6600>パターンマッチ</font>|
|[連続しない複数行を抽出する (例: 1行目とパターンマッチ行)](https://qiita.com/robozushi10/items/540897bd59f529952d39)|<font color=#ff6600>パターンマッチ</font>|
|[特定の文字から特定の文字が現れるまでの区間を抽出し、最終行を削除する](https://qiita.com/robozushi10/items/541179c826cc9ea5f1ea)|<font color=#ff6600>パターンマッチ</font>|
|[行頭「#」と空白のみの行を削除して表示させる](https://qiita.com/robozushi10/items/517fa7e2b0e1c1af2751)|<font color=#ff6600>パターンマッチ</font>|
|[ログから ANSI Color を削除する](https://qiita.com/robozushi10/items/03152fcc20756a75d732)|<font color=#449944>削除</font>|
matlab / simulinkの円形のsum blockの完全な向きの変え方

# まとめ
円形を選択した時にやりたい操作ですね
### 右回転
command(⌘) + R
### 左回転
shift(⇧) + command(⌘) + R
### <span style="color: red;">左右</span>の（鏡像）反転
command(⌘) + I

## 上下の反転について
そんな操作はないですね<br>
その代わり**ブロックパラメータ>メイン>符号リスト**をいじれば解決します

### 1入力1出力の場合
#### 直線
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540440/b7788e2a-cc49-7d8b-163c-ff0338dc4600.png)
#### 上直角
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540440/295fca28-cb7d-cb21-c33a-30597aec68c7.png)
#### 下直角
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540440/6aed747a-7986-0589-dca8-db53216f5d3c.png)

### 2入力1出力の場合
#### 上下直角
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540440/ed0ef893-5818-52db-93ce-554b27d2c8f1.png)
#### 上直角空き
これがデフォルトでお出しされることが多い
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540440/4831ab14-7a5a-fc02-751d-2f21dc900ace.png)
#### 下直角空き
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540440/b0d319a8-434e-85b5-1960-6b67c4a91292.png)
#### 45°分け
かっこいいから好き
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540440/f5d51d0c-5893-49f1-f54c-8eeaf4d2da57.png)


# 感想
`|`は空白端子を意味するらしい
やってみたところこの記事にあるような単語を使っても検索結果には出てこなかったので共有しときます
[sed]【1行野郎】連続しない複数行を抽出する (例: 1行目とパターンマッチ行)

|本シリーズのトップページ|
|:--|
|https://qiita.com/robozushi10/items/5d1313fa11ede179ddad|

# 概要

docker images コマンドの結果のうち、ヘッダである「1行目」と「パターン一致行」を表示させる.

```bash
$ docker images | sed -n -e '1p' -e '/^maho/p'
REPOSITORY      TAG    IMAGE ID            CREATED             SIZE
maho/webapl     0.1    714ae03094e1        17 minutes ago      66.1MB
```

以上.
3.21(難) 指数分布2

## 1.方針

2.7で用いた小技を利用する．今，X>tより，

```math
\begin{align}
x-t&= \int_0^xdy-\int_0^tdy\\
&= \int_t^xdy
\end{align}
```

である．

## 1.答案

```math 
\begin{align}
r(t)&= \mathbb{E}_{X\sim f_X}[X-t|X\geq t]\\
&= \int_t^\infty(x-t)P[X=x|X\geq t]dx\\
&= \int_t^\infty (x-t)\frac{P[X=x]}{P[X\geq t]}dx\\
&= \int_t^\infty(x-t)\frac{f_X(x)}{1-F_X(t)}dx\\
&= \frac{1}{1-F_X(t)}\int_t^\infty(x-t)f_X(x)dx\\
&= \frac{1}{1-F_X(t)}\int_t^\infty dx\int_t^xdyf_X(x)\\
&= \frac{1}{1-F_X(t)}\int_t^\infty dy\int_y^\infty dxf_X(x)\\
&= \frac{1}{1-F_X(t)}\int_t^\infty\{\int_y^\infty f_X(x)dx\}dy\\
&= \frac{1}{1-F_X(t)}\int_t^\infty 1-F_X(y)dy\\
&= \frac{1}{1-F_X(t)}\int_t^\infty 1-F_X(x)dx
\end{align}
```

今，指数分布の分布関数は

```math
F_X(x)=1-e^{-\lambda x}
```

なので，

```math
\begin{align}
r(t)&= \frac{1}{1-(1-e^{-\lambda t})}\int_t^\infty\{1-(1-e^{-\lambda x})\}dx\\
&= \frac{1}{e^{-\lambda t}}\int_t^\infty e^{-\lambda x}dx\\
&= \frac{1}{e^{-\lambda t}}\left[-\frac{1}{\lambda}e^{-\lambda x}\right]_t^\infty\\
&= \frac{1}{\lambda}
\end{align}
```

## 2.方針

```math
x^2=2\int_0^xtdt
```

を用いる．

## 2.答案

```math
\begin{align}
2\int_0^\infty r(t)\{1-F_X(t)\}dt&= 2\int_0^\infty\frac{1}{1-F_X(t)}\int_t^\infty 1-F_X(x)dx\{1-F_X(t)\}dt\\
&= 2\int_0^\infty dt\int_t^\infty dx\{1-F_X(x)\}\\
&= 2\int_0^\infty dx\int_0^xdt\{1-F_X(x)\}\\
&= 2\int_0^\infty x\{1-F_X(x)\}dx\\
&= \int_0^\infty 2x\{\int_x^\infty f_X(t)dt\}dx\\
&= \int_0^\infty dx\int_x^\infty dt2xf_X(t)\\
&= \int_0^\infty dt\int_0^tdx2xf_X(t)\\
&= \int_0^\infty\{2\int_0^t2xdx\}f_X(t)dt\\
&= \int_0^\infty t^2f_X(t)dt\\
&= \mathbb{E}_{X\sim f_X}[X^2]
\end{align}
```

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
Bot Framework ComposerでQnA Maker に接続した場合に質疑が終わらず他のトリガーに反応しないことがある

# 概要

- Bot Framework ComposerでQnA Maker に接続した場合に質疑が終わらず他のトリガーに反応しないことがある
- Bot Framework Composerで[QnA Makerを接続](https://docs.microsoft.com/en-us/composer/how-to-add-qna-to-bot?tabs=v2x)することができる。この際、[QnA MakerでMulti-Turn構成](https://docs.microsoft.com/ja-jp/azure/cognitive-services/qnamaker/how-to/multiturn-conversation)を行っている際に、Multi-Turn（複数ターン会話）の作りによっては、QnA Maker接続した動作のまま他のトリガーに反応しないことがある
- そのため、いつまでたってもQnA Makerの応答しか行わず、QnA Makerのアクションから抜けられない状態となり、QnA Makerに回答してしまうと想定のトリガーがによる制御ができない状態となってしまう

# 原因

- Multi-Turnが完了するまでは、QnA Maker接続のアクションの中で動作している状態となる。そのため例えば、Multi-Turnをループしているならば、QnA Maker接続のアクションを完了することができない。そのため他のトリガーには反応しない

# 暫定対策

- Multi-Turnをループしない構成とすることで、Multi-turnが終了する形とする

# 根本対策（未解決）

- Multi-Turnの中でMulti-Turnを中断するような動作ができればよいが、今のところ対策を確認できていない

# 参考

https://docs.microsoft.com/en-us/composer/how-to-add-qna-to-bot?tabs=v2x

https://docs.microsoft.com/ja-jp/azure/cognitive-services/qnamaker/how-to/multiturn-conversation
[sed]【1行野郎】特定の文字から特定の文字が現れるまでの区間を抽出し、最終行を削除する


|本シリーズのトップページ|
|:--|
|https://qiita.com/robozushi10/items/5d1313fa11ede179ddad|

# 概要

後述の図のように、
「Containers:」の開始から「Conditions:」が現われるまでを抽出し、その後に最終行を削除する

```bash
$ kubectl describe pods init-sample | \
    sed -n  '/^Containers:/,/Conditions:/p' | \
    sed '$d'
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/8a369ee5-7d0b-c0b4-2843-6d7136a8fce5.png)
FlutterでうっかりAndroid Studioのパスを上書きしてどうにもならなくなった時の話

### FlutterでうっかりAndroid Studioのパスを上書きしてどうにもならなくなった時の話

**MacOSでのお話です**

Mac版のAndroid Studioを入れて、何を血迷ったか「flutter config --android-studio-dir」でAndroidStudioのパスを再設定してしまいました。

Android Studioのパスをいろいろ変え、flutter doctorを何通りかやってみましたが（以下は一例）

```Bash
$ flutter config --android-studio-dir /Applications/Android Studio.app/Contents/MacOS/studio
```
全然修正できず（泣）


こちらのサイトを拝見して、

https://qiita.com/kaitoland/items/6fe41fdcfeb3bbdb4001

### これでうまくいきました

```Bash
$ flutter config --android-studio-dir=""
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221026/b5cdda6a-2da2-551a-d7c6-655a2aa46904.png)
[sed]【1行野郎】行頭「#」と空白のみの行を削除して表示させる


|本シリーズのトップページ|
|:--|
|https://qiita.com/robozushi10/items/5d1313fa11ede179ddad|

# 概要

行頭「#」と空白のみの行を削除して表示させる.

下記のどれかを実行すれば良い

```bash
$ sed -r -e '/^(\s*)$/d' -e '/^#/d' /etc/dnsmasq.conf
$ sed -e '/^[[:space:]]*$/d' -e '/^#/d' /etc/dnsmasq.conf
$ grep -E -v '^\s*$' /etc/dnsmasq.conf
```
Vueでお絵かきアプリ作成3(canvas使用)

#趣向
vueでお絵かき機能を作成する機会があったため作ってみました！
![スクリーンショット 2021-08-15 17.37.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/843952/9ffc5175-6583-9e15-6d03-252324b66008.png)

#2の続き
[前回の2はこちら](https://qiita.com/ryotaro_tech/items/4fb9b4d57d966a63092c)
このページでは「前に戻る」「次に進む」が動作できるようにしていきたいと思います。

まずはhtml。画面に「進む」と「戻る」のボタンを追加します。
@clickを忘れずに。

```HAML:html
<div class="controller history">
    <label>戻る：</label>
    <div class="history-box js-canvas-history" @click="back">
        <i class="fas fa-undo-alt"></i>
    </div>
</div>
<div class="controller history">
    <label>進む：</label>
    <div class="history-box js-canvas-history" @click="next">
        <i class="fas fa-redo-alt"></i>
    </div>
</div>
```

次にvue
戻す用スタックとやり直し用スタックをdataに用意します。
今回は戻す用スタックの最大保持数を10までにします。
描写時に戻す用スタックにどんどん先頭にデータを入れていくようにします。
戻るを押した場合、戻すようスタックに入れた先頭データを取得して、描写するようにしています。
また、進むの場合もほぼ同様なものになります。

```JavaScript:JavaScript
new Vue({
  el: '#app',
  data() {
    return {
      redoDataStack: [],
      undoDataStack: [],
    }
  },
  methods: {
    // 描画開始（mousedown）
    dragStart:function(e) {
      let x = e.layerX
      let y = e.layerY
      this.context.beginPath();
      this.context.lineTo(x, y);
      this.context.stroke();
      this.isDrag = true;

      this.context.getImageData(0, 0, this.canvas.width, this.canvas.height)
      // やり直し用スタックの中身を削除
      this.redoDataStack = [];
      // 元に戻す用の配列が最大保持数より大きくなっているかどうか
      if (this.undoDataStack.length >= 10) {
          // 条件に該当する場合末尾の要素を削除
          this.undoDataStack.pop();
      }
      // 元に戻す配列の先頭にcontextのImageDataを保持する
      this.undoDataStack.push(this.context.getImageData(0, 0, this.canvas.width, this.canvas.height));
    },
    // 一つ前に戻る
    back: function() {
      // 戻す配列にスタックしているデータがなければ処理を終了する
      if (this.undoDataStack.length <= 0) return;
      // やり直し用の配列に元に戻す操作をする前のCanvasの状態をスタックしておく
      this.redoDataStack.push(this.context.getImageData(0, 0, this.canvas.width, this.canvas.height));
      // 元に戻す配列の先頭からイメージデータを取得して
      let imageData = this.undoDataStack.pop();
      // 描画する
      this.context.putImageData(imageData, 0, 0);
    },
    // 一つ後に進む
    next: function() {
      // 戻す配列にスタックしているデータがなければ処理を終了する
      if (this.redoDataStack.length <= 0) return;
      // やり直し用の配列に元に戻す操作をする前のCanvasの状態をスタックしておく
      this.undoDataStack.push(this.context.getImageData(0, 0, this.canvas.width, this.canvas.height));
      // 元に戻す配列の先頭からイメージデータを取得して
      let imageData = this.redoDataStack.pop();
      // 描画する
      this.context.putImageData(imageData, 0, 0)
    },
  },
});
```

![スクリーンショット 2021-08-25 19.41.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/843952/b79e3a1a-1167-8e7b-0ce0-d2aafa89aebf.png)![スクリーンショット 2021-08-25 19.41.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/843952/50b284e6-5a71-7ad5-c83b-f6837870b143.png)


これで進む戻るが実装できました。🙌
今回は前回のものと比べ少し複雑だったかもしれません。
次回は「リセット」と「画像ダウンロード」とデータを「更新」できるように
したいと思います。
M5CameraやラズパイなどのMJPEGデータを中継するNode.jsサーバ

## M5Cameraに最初に書き込まれているのは使いやすいけど…

複数からのアクセスでstreamが見れない！

M5Cameraのコード変えてもいいけど…中継するサーバー作って、複数のM5Cameraの映像を管理するのもありかなぁと思い作りました。

## 環境
* Node.js v14.15.0
* ライブラリ
    * [mjpeg-server](https://github.com/gluxon/node-mjpeg-server) 0.3.1
    * [mjpeg2jpegs](https://www.npmjs.com/package/mjpeg2jpegs) 1.0.6


## M5Cameraに書き込むコード

https://github.com/tkyko13/M5CameraMDNS

自分が作ったMDNSに対応させたM5Camera用のプラグラムです

最初にあったコードに追記する形なのでできることは変わりません

## Node.js側のソースコード

```js
const express = require('express');
const http = require('http');
const app = express();
const mjpeg2jpegs = require('mjpeg2jpegs');
const mjpegServer = require('mjpeg-server');

const PORT = 8800;

// 複数のクライアントに対応
let buff = Buffer.alloc(0);

// サーバー開始直後にm5cameraから画像取得処理開始
const httpOption = {
	hostname: 'm5camera_1.local',
	path: '/stream',
	port: 81,
	responseType: 'arraybuffer',
	headers: {
		'Content-Type': 'image/jpeg',
	},
};
const httpHandler = mjpeg2jpegs((mjpegRes) => {
	let processBuff = Buffer.alloc(0);
	mjpegRes.on('imageData', (data) => {
		// 送られ続けているデータをつなげてためていく
		processBuff = Buffer.concat([processBuff, data]);
	});
	mjpegRes.on('imageEnd', () => {
		// 1枚の画像データが完成のタイミング
		buff = Buffer.concat([processBuff]);
		processBuff = Buffer.alloc(0);
	});
});
http.request(httpOption, httpHandler).end();

// motionJpegサーバ
app.get('/', async (req, res) => {
	// モーションjpegサーバーの作成 リクエストごとに作成
	const mjpegReqHandler = mjpegServer.createReqHandler(req, res);

	let c = 0;
	const interval = setInterval(() => {
		mjpegReqHandler.write(buff);
		console.log(c++); // ここの無限ループが抜けられない

       if (false) {// クライアントが切断したらここを通らせたい
          mjpegReqHandler.close();
          clearInterval(interval);
       }
	}, 100);
});

app.listen(PORT, () => {
	console.log('Running at http://localhost:' + PORT);
});
```

`mjpeg2jpegs` を使ってM5Cameraの映像バッファーをまずは取得する

`mjpeg-server` でそのバッファーを配信

### 無限ループが終わらせられなかった…

コード内にも書いてある部分を抜けられなかった

サーバにアクセスし、別のページとかに遷移しちゃってもカウントが止まっていない

https://github.com/gluxon/node-mjpeg-server/blob/master/examples/server.js

ライブラリのexampleにも無限に配信するものがあるわけではなく、配信用途にMJPEGはあってないのかなぁと思いました

## おまけ　MJPEGをWebサイトで見る

```html
<img src="http://localhost:8800"/>
<!-- or -->
<img src="http://m5camera_1.local:81/stream"/>
```

簡単ですね
【React】Objects are not valid as a React child (found: object with keys {STATUS_TEXT}). If you meant to render a collection of children, use an array instead.の対処法

<h2>症状</h2>
Reactでコンポーネントを分割する際に、以下のエラーメッセージが表示されてしまいました。
翻訳すると、「オブジェクトはReactの子としては無効です（見つかった：キーが{STATUS_TEXT}のオブジェクト）。子のコレクションをレンダリングする場合は、代わりに配列を使用してください。」でした。


```terminal:error
Error: Objects are not valid as a React child (found: object with keys {STATUS_TEXT}). If you meant to render a collection of children, use an array instead.
```

以下がOrder_Statusを渡して、それに対応したTEXTを返すだけのcomponentです。(シンプルに値をもらって、それに対応する文字列を返すだけのコンポーネントです)

```react:taskStatusText.jsx
import {STATUS_TEXT:TASK_TEXT} from "../component/text"

export const taskStatusText = (order_status) => {
    const STATUS_TEXT = []
    
    switch (order_status){
        case "1":
            return{
                STATUS_TEXT:TASK_TEXT.TASK_STATUS_UNFINISHED_TEXT,
            }
        case "2":
            return{
                STATUS_TEXT:TASK_TEXT.TASK_STATUS_FINISHED_TEXT,
            }
        case "3":
            return {
                STATUS_TEXT:TASK_TEXT.TASK_STATUS_TASK_CANCEL_TEXT,
            }
        case "4":
            return {
                STATUS_TEXT:TASK_TEXT.TASK_STATUS_ORDER_CANCEL_TEXT,
            }
    }
}
```

下記componentから上記のコンポーネントを呼び出して、返ってきた文字を出しています。

```react:Order.jsx
import React,{useState} from "react";
import {taskStatusText} from "../component/taskStatusText "

export const Hoge =(status) => {
const [statusValue,setState] = useState(taskStatusText(state.task.order_status))
  return(
    <div>
      {statusValue}
    </div>
  )
}
```

<h2>解決方法</h2>
返ってきたものが配列に入っているSTATUS_TEXTを指定してやることで、解決しました。
エラー内容からはよくわかりませんでしたが、オブジェクトのまま表示させようとしていたため、怒られていたのかもしれません。

```react:Order.jsx
import React,{useState} from "react";
import {taskStatusText} from "../component/taskStatusText "

export const Hoge =(status) => {
const [statusValue,setState] = useState(taskStatusText(state.task.order_status))
  return(
    <div>
      {statusValue.STATUS_TEXT}
    </div>
  )
}
```

<h2>参考</h2>

https://stackoverflow.com/questions/52428879/objects-are-not-valid-as-a-react-child-if-you-meant-to-render-a-collection-of-c
Fatal error: Allowed memory size of のエラーについて

# はじめに

メモリが足らないエラーで詰まりましたので、メモ。



# 最終更新日
2021年8月25日


# 環境の情報
OS
ubuntu 20.04


# 状況

```
/src$ bin/magento sampledata:deploy
```

しようとするとコケました。


```
Updating dependencies (including require-dev)
PHP Fatal error:  Allowed memory size of 2147483648 bytes exhausted (tried to allocate 4096 bytes) in /src/vendor/composer/composer/src/Composer/DependencyResolver/Solver.php on line 223

Fatal error: Allowed memory size of 2147483648 bytes exhausted (tried to allocate 4096 bytes) in /src/vendor/composer/composer/src/Composer/DependencyResolver/Solver.php on line 223

Check https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors for more info on how to handle out of memory errors.


https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors

```

メモリが足りないよう。

# 対策


```
/src$  php -i | grep php.ini
Configuration File (php.ini) Path => /etc/php/7.4/cli
Loaded Configuration File => /etc/php/7.4/cli/php.ini
```

探す。
↓

```
/src$ cd  /etc/php/7.4/cli/
```

移動する。
↓

```
/etc/php/7.4/cli$ ls
conf.d  php.ini  php2.ini
/etc/php/7.4/cli$ cat php.ini
/etc/php/7.4/cli$ vi php.ini
memory_limit =-1
（-1が上限）
```
↓

```
/etc/php/7.4/cli$ php -r "echo ini_get('memory_limit').PHP_EOL;"
-1
```

↓

```
/src$ bin/magento sampledata:deploy
```
やり直して出来ました。
Azure Functionsで作成した関数のHttpTriggerエンドポイントを保護する


作成した関数のエンドポイントを簡易的に保護する方法になります。

公式Doc👉[関数のアクセスキー](https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-bindings-http-webhook-trigger?tabs=csharp#function-access-keys)

## HttpTriggerのAzure関数を追加する

VisualStudio上で追加したいディレクトリで右クリック → [追加] → [新しいAzure関数]  
Triggerの選択画面がでるので、Http Trigerを選択します。  
デフォルトで作られる関数はおそらく👇こんな感じです。（既に保護していた場合はuthorizationLevel.Annonymousの箇所がFunctionだったりAdminになってるかもです）

```C#
 public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Annonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            string name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;

            string responseMessage = string.IsNullOrEmpty(name)
                ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
                : $"Hello, {name}. This HTTP triggered function executed successfully.";

            return new OkObjectResult(responseMessage);
        }
```

## この状態でAzure Functionsへデプロイするとどうなる？

デプロイはできます。この関数のURLを叩くと、動いてくれます。  
しかし、認証等ないのでこの関数のURLを知ってしまえば誰でも使えてしまいます。  
ですので、URLが特定されづらいものにしたほうがよりセキュアなものになります。  

## 関数のURLを特定しづらいものにするには？

先程、関数を追加したときのデフォルトのコードを見ると、「AuthorizationLevel.Annonymous」というものがあります。  
こちらのAnnonymousを「Function」or「Admin」などに変えてあげてください。  

```C#
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] 
```

変えた後、再度デプロイします。  
再度、関数のURLを叩くと401となるのが確認できるかと思います。(local実行ではおそらく確認できないので再デプロイして試してください。)  
これを設定してあげると、リクエストするときに関数のURLの他に関数キーが必要になります。  
Portal上の👇の画面の[コードとテスト]から[関数のURLの取得]でParameterに関数キーがくっついた状態で取得できると思いますので、その状態でリクエストすると認証は通るかと思います。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467168/844882a0-630d-efa6-2a94-d2e261b65aa6.png)

この関数キーはデプロイすると自動で作成してくれるので自分で作成する必要はとくにありません。  
再デプロイしてもキーが変わることもないです。

### 関数キーの確認・変更

関数キーはPortal上から関数に飛んで、[関数キー]という項目を押すと確認できます。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467168/3c0dcd35-d4be-ac00-6b3d-9e7949b62503.png)

もし関数キーが漏洩してしまった場合はコチラから再度変更できます。  
各関数ごとに違う関数キーも付けることができるのでお試しください。  

### 注意

今回の方法でどこかしらでこの関数のURLを指定していた場合（例えばフロントエンドなど）、  
URLは漏洩してしまうので、そこらへんは考慮が必要になります。  

## まとめ

特に関数のURLが公開されてないのであれば関数キーを使った方法は、十分セキュアなのかなと思います。
VBA FileSystemObjectでディレクトリーを再帰的表示するマクロ

Dirで探索するよりもこっちのほうが楽でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339882/d2dc506f-9bf7-ebd1-061d-ab5f6ab8126a.png)

<h3>メインプログラム</h3>

```vb:Sub&#x20;Main
Sub ボタン1_Click()

    Dim fso                 As FileSystemObject
    Dim fd                  As Object
    Dim file                As Object
    
    Dim location            As String
    
    
    Set fso = New Scripting.FileSystemObject
    Set fd = Application.FileDialog(msoFileDialogFolderPicker)
    
    If Not fd.Show Then
        MsgBox "ダイアログキャンセル", vbExclamation
        Exit Sub
    Else
        location = fd.SelectedItems(1)
    End If
    
    '親フォルダーのファイル探索
    For Each file In fso.GetFolder(location).files
           Debug.Print file.path
    Next file
    
    Call getAllFiles(location, fso)
    
End Sub

```
<h3>再帰的に表示する関数</h3>

```vb:Sub&#x20;getAllFiles
Sub getAllFiles(ByVal path As String, ByRef fso As FileSystemObject)
    
    Dim files               As Object
    Dim file                As Object
    Dim fol                 As Object
    Dim folders             As Object
    
    Set folders = fso.GetFolder(path).SubFolders
    
    If IsObject(folders) Then
        For Each fol In folders

            Set files = fso.GetFolder(fol).files

            If IsObject(files) Then
                For Each file In files
                'ここで操作
                    Debug.Print file.path
 
                Next file
            End If
            
            Call getAllFiles(fol, fso)
            Set files = Nothing
            
        Next fol
    End If
    
End Sub
```

<h2>実行結果</h2>

![huihi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339882/63be7d15-c911-b09c-8c16-da09093772a4.png)
ホスト(macos)からdocker上のredis sentinelに接続

# Overview
docker上にテスト用のredis sentinelを動かして、ホスト上で動いているプログラムから接続する

# Problem
`sentinel get-master-addr-by-name `で返却されるマスタのIPはdocker環境上のIPなので、ホストからは繋げない。

# 解決
- hostモードで動かす => macosは対応していない？後日ドキュメント確認
- lo0にループバックアドレスにエイリアスを追加 => 暫定対応

# エイリアス追加
```
sudo ifconfig lo0 alias ${DOCKER_SUBNET}
```

# テスト
```go
package main

import (
	"context"
	"fmt"

	"github.com/go-redis/redis/v8"
)

func main() {
	opt := redis.FailoverOptions{}
	opt.MasterName = "master"
	opt.SentinelAddrs = []string{"127.0.0.1:26379"}
	opt.Password = "xxxx"

	r := redis.NewFailoverClient(&opt)

        ctx := context.TODO()
	r.Ping(ctx)
	
	err := r.Set(ctx, "test", "yeah!", 0).Err()
	if err != nil {
		panic(err)
	}
	val, err := r.Get(ctx, "test").Result()
	if err != nil {
		panic(err)
	}
	fmt.Println("key", val)
}
```
DockerfileでCMDとENTRYPOINTを使ったときに、コンテナが起動しない、リスタートし続ける

# はじめに

「[15Stepで習得 Dockerから入るKubernetes コンテナ開発からK8s本番運用まで](https://amzn.to/2Wid1MK)」という本を学習している中で、Kubernetesの環境を構築することになり、1からの構築をしています。

その過程でDockerについて深くやることになっていますが、色々エラーが起きます。

今回は、Dockrfile内で、CMDコマンドやENTRYPOINTコマンドを使うとコンテナが落ちたり、リスタートを繰り返したり問題が起きてなかなか検索しても解決にたどり着けなかったため、まとめていきたいと思います。
(検索の仕方がわるかった？)

# 問題

以下のファイルを用意します。

`Dockerfile`

```Dockerfile
FROM ubuntu:20.04

COPY entrypoint.sh /tmp
ENTRYPOINT ["/tmp/entrypoint.sh"]
```

`docker-compose.yml`

```
version: '3'
services:
  ubuntu:
    restart: always
    build: .
    container_name: 'ubuntu'
    tty: true
```

`entrypoint.sh`

```entrypoint.sh
echo "Hello World!"
```

このコンテナを起動するとエラーが発生します。

```
$ docker-compose up
```

エラー

```
Recreating ubuntu ... done
Attaching to ubuntu
ubuntu    | Hello World
ubuntu exited with code 0
```

コンテナの中に入ってみると以下のようなエラー

```
$ docker-compose up -d
$ docker exec -it ubuntu sh
```

```
Error response from daemon: Container 16cf0c04abe4de2f466683069ac9a2511e743b813ea8088401278fa525d91057 is restarting, wait until the container is running
```

`ENTRYPOINT`を使わず、`CMD`を使ってみます。

```Dockerfile
FROM ubuntu:20.04

CMD ["echo", "hello world!"]
```

しかし、同じエラーが発生します。

`CMD`と`ENTRYPOINT`を使った時だけエラーになり、そこをなくすとコンテナは問題なく起動しました。


# 解決方法

[DockerでENTRYPOINTを指定すると、コンテナが起動しない](https://teratail.com/questions/81699)

こちらの記事で原因がわかりました。

CMDやENTRYPOINTを指定した場合、コンテナでコマンドを起動した後にコンテナを終了してしまうようです。
ですので、シェルスクリプトの中で終了しないようにする工夫が必要になります。

たとえば、シェルスクリプトの中で`無限ループ`を発生させます。

```entrypoint.sh
#!bin/sh

echo "Hello World"

while true
do
sleep 10
done
```

これで解決しました。

CMDであれば、以下を参考にしてみてください。

- [Dockerのコンテナを起動したままにする](https://qiita.com/reflet/items/dd65f9ffef2a2fcfcf30)


また、リスタートし続ける現象

```
Error response from daemon: Container 16cf0c04abe4de2f466683069ac9a2511e743b813ea8088401278fa525d91057 is restarting, wait until the container is running
```

は、docker-compose.ymlで`restart: always`にしているため、ENTRYPOINTでコマンド実行したあとコンテナが落ちて、再度起動したために表示されています。起動→シェル実行→終了→リスタートを繰り返していました。

# 余談
メモ程度に私のやりたかったことをまとめておきます。

docker-in-dockerをUbuntuで行っており、コンテナ内で`service docker start`コマンドで起動する必要がありました。しかし、シェルスクリプトに`service docker start`を書いて、コンテナを起動するとエラーになります。

これは、シェルスクリプトを実行中に起動できないことから起因してそうでした。
そこで、コンテナ内で`bash entrypoint.sh`コマンドをすることでコンテナ内で行うコマンドをすべて一括して行うことにしました(DockerfileでENTRYPOINTをするのをやめました)

# おわりに

この原因に気付くまでに時間がかかってしまいました。
しっかりとデバックができるようになるともっと早く解決できるようになりそうです。

Dockernのデバックあんまり知らないので学んでいきたいです。

# 参考
- [DockerでENTRYPOINTを指定すると、コンテナが起動しない](https://teratail.com/questions/81699)
- [Dockerのコンテナを起動したままにする](https://qiita.com/reflet/items/dd65f9ffef2a2fcfcf30)
【TypeScript入門】可変長引数、レストパラメーターとは

# まとめ
可変長引数は内部的にanyとして扱われるので、安全ではない。そこでTypeScriptでは、レストパラメーターを使用する。

# 可変長引数とは
* 関数の呼び出しの際に引数の数をいくつ渡してもOK
* 全く型安全ではない
* argumentsで受け取るやつ

# レストパラメーター
* パラメーターに```...```を用いることで型定義できる。
* パラメーターの最後に１つだけ指定できる

```typescript
const sumProductsPrice = (...productsPrice: number[]): number => {
  return productsPrice.reduce((prevTotal, productPrice) => {
    return prevTotal + productPrice
  }, 0) // 0: prevTotalの初期値
}

 const sum = sumProductsPrice(1, 2, 3,)
 console.log('sample: Total:', sum)
//sample: Total: 6

```
UIトラブルシューティング

ハマった内容について記録します。

# Buttonオブジェクト等のUnityEvent(OnClick等)に自作関数が表示されない
プリミティブな型以外の引数を指定している関数の場合、OnClickに登録することはできない。
以下の記事を参考にすると、引数の型がEnumであれば登録できるようになる。

https://qiita.com/atomicZAMURAI/items/a49519e98c133c1fcdfe
対象フォルダ（サブフォルダ含む）から特定の文字列を検索するバッチ


#説明
一括で対象文字列をファイル群から検索するバッチ

#使用用途
ソースレビューの際不要なコメント、未解決の課題とうがないか探すのに使う


```bat:exec.bat
@echo off
@REM /s:サブフォルダ検索 /r:正規表現 /i:大文字、小文字区別なし
@REM utf-8表示
chcp 65001

set /p IN="フォルダパスを入力してください（サブフォルダは全て検索対象）:"

for /f %%a in (readfile.txt) do (
    findstr /s/r/i ¥/¥/.*%%a %IN%¥* >> log.txt
)

pause
```

```bat:readfile.text
TODO
仮
確認
可能性
？
?
未設定
未完成
未定義
未確認
暫定
問い合
問合
不要
削除
課題
QA
```
Power Query エディタでテーブルの行を絞り込むとき、うっかりやらかしていること

何回か発言していたのだけど念押しで言っておきますね。Power Query は Excel ではないですからね。ワークシート上での操作のノリで "適用するステップ" をキメたら駄目ね。間違った処理がされることがあっても、パフォーマンスが悪くなってもよいのだというのなら、ご自由にどうぞ。

# ポチポチ操作で出力される条件が異なることがある
以前ポストしたので詳しくはこっちで。

https://qiita.com/PowerBIxyz/items/53a35414cf62765c38e4

ポチポチ操作で候補を選択するとき、選択した候補の割合で Table.SelectRows 関数の *condition* が異なるのだ。表示しきれない候補が存在することもあるし、のちのちデータが追加されることがあるのだから操作が簡単な分得られる結果について注意深く観察することが大事。

# 最適ではない Table.SelectRows 関数を使ってしまう
Table.SelectRows 関数の目的としてはテーブルの行を絞り込むことにある。しかし、その理解では不十分だ。

https://docs.microsoft.com/en-us/powerquery-m/table-selectrows

```text:Table.SelectRows&#x20;(Power&#x20;Query)
Table.SelectRows(table as table, condition as function) as table
```
***table* すべての行で *condition* を評価する**ということだ。**すべての行**というのが当たり前で重要なのだけど、すべての行を評価する必要がない、もしくは、すべての行を評価するべきではないパターンの行の絞り込みもあるよね。

例えば、

|Column1|
|:--:|
|1|
|2|
|3|
|4|
|5|
|6|
|7|
|...|
というテーブルがあったとき、先頭の2行に絞り込みたいのに、

```text:この処理がしたかったの？(Power&#x20;Query)
Table.SelectRows( table, each [Column1] <= 2 )
```
という処理を華麗にキメちゃう人が多いんだよね。よく考えてね。 **"先頭の"** という必要な条件はどこにやったんだい？違うよね。処理される予定のテーブルは、わずか10万行かもしれないし100億行かもしれないよね。 100億回の評価をしたいの？

```text:こうだよね(Power&#x20;Query)
Table.FirstN( table, 2 )
```

ソースが 1GB の CSV ファイルとしたとき、選択した手段に間違いがなければ 4KB ほどの読み込みで済むところ、1GBまるまる読み込むっていうことになるわけ。

**行の並び替えと組み合わせ**
対象の列で最小の値になる1行に絞り込むなら、

```text:こうだよね(Power&#x20;Query)
Table.MinN( table, { "Column1", Order.Accending }, 1 )
```

Table.MinN、Table.MaxN は内部的に Table.Sort が含まれているので、

```text:こうだよね(Power&#x20;Query)
Table.FirstN(
    Table.Sort( table, { "Column1", Order.Ascending } ),
    1
)
```

クエリフォールディングが利用できる記述になる可能性が高いので、この記述が望ましいわけ。不用意に Table.Buffer 関数使ったり、Table.AddIndexColumn 関数で Index列を追加してアレコレするというのはやらないほうがよいのである。

# Table.SelectRows 関数 以外で テーブルの行を絞り込む関数
Table.SelectRows 関数 以外で テーブルの行を絞り込む関数があるわけで、

https://docs.microsoft.com/en-us/powerquery-m/table-skip

https://docs.microsoft.com/en-us/powerquery-m/table-firstn

https://docs.microsoft.com/en-us/powerquery-m/table-lastn

https://docs.microsoft.com/en-us/powerquery-m/table-removefirstn

https://docs.microsoft.com/en-us/powerquery-m/table-removelastn

https://docs.microsoft.com/en-us/powerquery-m/table-maxn

https://docs.microsoft.com/en-us/powerquery-m/table-minn

それぞれを使用し得られた結果がたまたま同じということはある。でも、Mashup engine の動作が異なるので、どのような動作をしているのかよーく勉強するとよい。クエリフォールディングが利用できる記述/できない記述も踏まえてね。

# 思ったこと🙄
テーブルの行を絞り込みたいなというとき、Table.Skip、Table.FirstN で要件を満たすなら優先して検討することでトラブルは激減する。また、Table.Sort 関数の挙動がよくわからんというなら、Table.MaxN、Table.MinN を使うとよい。

Power Query の処理はどんだけ拗らせても速くはならないのだ。じゃぁどう向き合うかは簡単。処理が遅くならない、もしくは遅くなりにくい選択をすべきなんじゃね？
 
# その他
https://powerbi.connpass.com/

http://qiita.com/PowerBIxyz/items/6c4735cb5b5712e70981

http://qiita.com/PowerBIxyz/items/52e563037b855a099ca9

- [Power BI 勉強会 - connpass](https://powerbi.connpass.com/)
- [Power BI Desktop を使い始めるには](http://qiita.com/PowerBIxyz/items/6c4735cb5b5712e70981)
- [Excel で Power Query を使い始めるには](http://qiita.com/PowerBIxyz/items/52e563037b855a099ca9)
オブジェクト指向プログラミングPart5 抽象クラス MQL5

[← オブジェクト指向プログラミングPart1](https://qiita.com/aisaki180507/items/d343b1ad46c8d3807ec2)

[← オブジェクト指向プログラミングPart4 ポリモーフィズム　(前回)](https://qiita.com/aisaki180507/items/efb14c10abf9ee6c3fe3)
***
##純粋仮想関数と抽象クラス
　__純粋仮想関数__とは基底クラス内で宣言だけをして定義付けをしないメンバ関数のことです。純粋仮想関数がひとつでもあれば、そのクラスを__抽象クラス__と呼びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1882169/def8abc7-9cc7-22db-4444-3f8b042491d9.png)


　抽象クラスは定義してないメンバ関数(純粋仮想関数)を含むため、プログラム内で抽象クラスを呼び出してもコンパイルエラーとなります。抽象クラスを使うためには__必ず純粋仮想関数をオーバーライド__(派生クラスで同じ関数を宣言、定義すること)をして、__抽象クラスではなく派生クラスを呼び出して__使うようにしなければいけません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1882169/87e31ea3-3782-1bf5-c39c-ebe63ac90c34.png)


###何のために抽象クラスを作るのか
 * __基底クラスを呼び出せないようにする(必ず派生クラスを使うようにする)__
 * __派生クラスで必ず定義しなければいけない関数を指定する(必ずオーバーライドさせる)__

　このふたつが抽象クラスを作る大きな理由です。基底クラスと派生クラスの関係はPart3で解説しましたが、実際にひとつの基底クラスに対して複数の派生クラスに枝分かれしてプログラムを書いていけば、基底クラス自体を呼び出して使うメリットがなくなっていきます。
　
　そこで基底クラスを単体で使うことはなくして、__派生クラスの土台__としてだけ機能させよう。というのが抽象クラスです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1882169/56c8bf48-2367-119d-d3ac-f93a3efc8318.png)


###実際に書いてみる

```.cpp
// 基底クラス (抽象クラス)
class CRen{
public: 
   virtual double Position_Sizing() = 0;  // 純粋仮想関数
};

// 派生クラス
class CPractice :public CRen{
private:
   double lot_size;
   
public:
   void   set_lot_size(double Lots) { lot_size = Lots; };
   double Position_Sizing(); // 純粋仮想関数をオーバーライド
   
};

double CPractice::Position_Sizing() 
{
   //ここにポジションサイジングのロジックを書く
   lot_size += 0.1;
   
   return lot_size;
}

int OnInit()
  {
   double Lots = 0.1;
   
   CPractice practice;     // 派生クラスオブジェクト生成
   
   
   practice.set_lot_size(Lots);
   
   Lots = practice.Position_Sizing();
   
   Print("ロット数は",Lots);
   
   
   return(INIT_SUCCEEDED);
  }
```
実際に動作すると↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1882169/b46a8e5c-8b37-a351-5a8e-adb26f481aef.png)


　ここでは__Position_Sizing()__という純粋仮想関数を使って抽象クラスを作ってみました。抽象クラス内では__Position_Sizing()__を定義付けしていないですが、その後オーバーライドしているため、コンパイルエラーは発生していません。

* __純粋仮想関数をオーバーライドしていない__
* __プログラム内で派生クラスではなく抽象クラスを呼び出している__

このような時はコンパイルエラーとなります。

* __派生クラスで作るつもりだった関数を書き忘れた__
* __呼び出すつもりじゃなかった基底クラスを間違えて呼んだ__

こういったヒューマンエラーをコンパイルエラーで気付かせてくれるのも抽象クラスを使うメリットになります。
　

　抽象クラスは派生クラスの数が多くなってくるほどに恩恵を受けると思います。特に複数人で開発するときなどでは非常によく使われる技術なので、ぜひ覚えてみてください。
React勉強日記　#1

# 初めてのReact
初めまして．Reactの備忘録として記事を書いていこうかなと思います．

## プロジェクトの立ち上げ
nodeとyarnがインストールされていることを確認し，任意のディレクトリに移動した後

```terminal:terminal
npx create-react-app プロジェクト名
cd プロジェクト名
```

プロジェクトを起動したいときは

```terminal:terminal
yarn start
```

## よく使うファイルについて

下のようなディレクトリ構成になっており初学者が触るのはsrcフォルダの内部．

>プロジェクト名/
├ node_modules/
├ public/
├ src/
　├ App.js
　└  index.js

index.jsがトップページになっており，JSX記法で書かれている．

```react:index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

```
ReactDOM.render()の第1引数の中にApp.jsが入っているのが分かりますよね？ここでApp.jsのコンポーネントを取得しているわけです．このように，Reactではコンポーネントがコンポーネントを次々呼び出して大きなコンポーネント，詰まるところページを形成しているのですね．

また，第2引数のgetElementById('root')でpublic フォルダの index.html の id 属性が root の div 要素を取得しています．つまり，ReactDOM.render()はトップページでidがrootのdiv要素にApp.jsなどのコンポーネントを描画しているのです．

## 最後に
三日坊主にならなければ続きを更新したいと考えています．
OS system command Run ... / Ruby case / Python case / golang case / Nim case 

## Ruby

```ruby:oscommand.rb
current = "test"
system("ls")
system("mkdir" ,"./#{current}")
#system("rm" , "-r", "./#{current}")
```

```terminal
> ruby oscommand.ruby
```

## Python
```python:oscommand.py
import 'os'

os.system("ls")
os.system("mkdir ./test")
#os.system("rm -r ./test")
```


```terminal
> python oscommand.py
```

## golang

```golang:oscommand.go
package main

import (
    "log"
    "os/exec"
)

func main(){
    title := "test"
    cmd := exec.Command("zip","-4", title + ".zip","-r","./" + title)
    err := cmd.Run()
    if err != nil {                                                                          
        log.Fatal(err)
    }
    cmd = nil
    cmd = exec.Command("rm","-r","./" + title)
    err = cmd.Run()
    if err != nil {
        log.Fatal(err)
    }
    cmd = nil
}
```

```terminal
> go run oscommand.go
```

## Nim

```nim:oscommand.nim
import os

discard execShellCmd("ls")
discard execShellCmd("echo")
discard execShellCmd("mkdir ./test")
discard execShellCmd("echo")
discard execShellCmd("ls")
discard execShellCmd("rm -r ./test")
discard execShellCmd("echo")
discard execShellCmd("ls")
```

```terminal
> nim c -r oscommand.nim
```

https://nim-lang.org/docs/os.html#execShellCmd,string
TextViewの内容を動的に変更する方法

自作androidアプリ　[Flexible Dice](https://play.google.com/store/apps/details?id=com.chelak.dice)　
では、TextViewを動的に変更することでダイスロールを表現しています。その際に結構迷ったので備忘録的にメモします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344513/6102ee3d-9058-12b2-3bac-ab0bcc81101c.png" width="160" height="326" class="jop-noMdConv"> <a href='https://play.google.com/store/apps/details?id=com.chelak.dice&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Google Play で手に入れよう' src='https://play.google.com/intl/en_us/badges/static/images/badges/ja_badge_web_generic.png'/ width="200"></a>

## 方法
色々調べた結果、以下のことがわかりました。  
・画面更新の方法として`invalidate()`という命令文があるが、これはどうやら更新を予約するだけのものらしい。
・その場では更新されず`invalidate()`のスレッドが終了した後（アイドル時）に画面の更新が行われる。
・そもそも`invalidate()`はステータスを更新するほとんどの命令文（`set○○()`など）の際に暗黙に実行されているらしい。

結論としては、`invalidate()`は書く必要がなく、別スレッドでステータスを変更して元のスレッドに戻ればよいです。
そうすれば別スレッドが終了した時点で画面の更新が行われ、変更点が反映されます。  

## 例
`Thread{ }.start()`で別スレッドを生成することができます。

例えば、下記のプログラムは　[Flexible Dice](https://play.google.com/store/apps/details?id=com.chelak.dice)　の左上に表示されているさいころの面と数を表すテキスト（1D10など）を動的に変更するスクリプトです。

```kotlin
Thread{
            activity?.runOnUiThread {
                val textViewDice = view.findViewById<TextView>(R.id.textView_dice)
                textViewDice.text = "DICE: " + number.toString() + "D" + face.toString()
            }
        }.start()
```

アイデア次第でいろいろできそうですね。
AppStoreの審査通過後作業を自動化する

#審査が通ったあとは喜ぶだけで、次のリリースと向き合いたい。
AppStoreに公開されたあとの作業って忘れがちな上に毎回手間ですよね。
今回は以下の作業をBitriseやGASを使って自動化しました。

- Slackでステークホルダーに連絡
- GithubでRelease Tagをきる
- FirebaseにdSYMをupload


# 公開されたことを検知する(GAS)
App Store Reviewのステータス変更は自動メールで通知されます。
公開完了後の通知メールがGmailで受信しているかGASで検索します。
検索方法は泥臭いですが、以下の条件です

条件は以下です。

- メールの差出人がApp Store Connectか
- メールのタイトルに"Ready for Sale"が含まれるか

```.js
  // タイトルのチェック.
　　　　// 今回は公開時のメールを検索.
  var title = message.getSubject();
  var regexp = new RegExp("Ready for Sale");
  
  return (title.match(regexp) != null) ? true : false;
```

本文からバージョン番号を取得しておくと、連絡の内容やrelease tagに利用できるので抽出しましょう.

```.js
  var body = message.getPlainBody();
  var regexp = new RegExp(App Version Number: *.*.*);

  var versionLineStr = body.match(regexp)
  if (!versionLineStr) {
    return null
  }
  var versionString = versionLineStr[0].replace("App Version Number: ","")
　　　　// 1.0.0などストアストアのバージョンが入ります.ビルドナンバーも取得することは可能です。
  return versionString
```

# ステークホルダーに連絡(GAS + Slack App)
前述のメールがヒットした場合は本文からバージョン情報を抽出し、通知メッセージを整形します。
Slackでステークホルダーに通知します。

# release tagを切る(GAS + Github API)
前述のステップが完了したら、Github APIを利用してrelease tagを切ります.
APIにはtitleや、bodyを入れられるので
これをトリガーにBitriseを動かすという作戦です。

# App Store Connect上のdSYMをDLしFirebaseにuploadする(Bitrise + fastlane)
App Store Connect上のdSYMをDLするにはAPIKeyを利用した方法では接続できず、ID/PASSWORDを利用する方法しかありません。
2FAが必須となってから自動化の大きな壁になってしまっていましたが、Bitriseに今は任せることができます。[参考ドキュメント](https://devcenter.bitrise.io/getting-started/connecting-to-services/connecting-to-an-apple-service-with-apple-id/)
**ただし、月に1回設定画面でセッションの更新が必要です。2FAを入力するだけです**
Bitrise上で管理する、AppStoreConnectの認証情報を使い、fastlaneで以下のlaneを実行します。

- download_dsyms
- upload_symbols_to_crashlytics

```.rb
# laneは特殊なことはしておらず、必要なものを組み合わせているだけです.
lane :upload_dsyms do
    download_dsyms(
      version: 'latest'
    )

    # FirebaseにdSYMをアップロード
    upload_symbols_to_crashlytics(binary_path: './scripts/Firebase/upload-symbols', gsp_path: "./path/to/GoogleService-Info-release.plist")
  end
```

#今後やりたいこと
これで審査提出後に自動リリースを選択しておけば、あとは全て自動化できました。手動リリースの場合もリリースボタンを押せば、そのあとは自動です。
Meta情報の提出に関してもBitrise + faslaneで自動化は可能なので今後取り組んでいきたいと思います。


# 全体図はだいたい、こんな感じです


![Release自動化概要図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103494/a110a57b-4268-3434-bc6b-3a6adb3a029f.png)