OmniAICreator/Qiita-1.07M huggingface dataset:
バッチ初心者が考えたバッチ

###yyyymmdd.*.logと命名されたログファイルが溜まったので、ディレクトリ内にある同日付の付いたログを固める



```console
!/bin/bash

CMDNAME=`basename $0`

#引数の確認　なければエラー
if [ $# -ne 1 ]; then
  echo "need a directory after the command" 1>&2
  echo "Ex. /var/log/10.0.0.254/" 1>&2
  exit 1
fi

#作業ディレクトリを引数から取る
d="$1"

#作業ディレクトリ内全体
FILES="$1"*

echo "work on directory $d"

#ループ
for f in $FILES
do
  echo "Processing $f"

  #日付のみ抽出
  #$f(/*/*/*/*/yyyymmdd.*.log)からまず
  #前方最後方一致で/を取り、残りのyyyymmdd.*.logから
  #前方最前方一致で.を取り、yyyymmddのみにし、fileへ代入
  file=$(echo "${f##*/}" | cut -f 1 -d '.')

#念のためファイルの存在確認
#あれば日付でまとめて.tar.gz化
if [ -f "$f" ]; then
  tar czf $d$file.log.tar.gz  $d$file.*
#  echo "$d$file.log.tar.gz  $d$file.*"
fi

done

exit 0
```
tensorflow-gpuを動くようにするためにすること

#初めに
パソコンを初期化したらtensorflowをgpuで動かすために色々入れなおさなきゃいけなかった。
そしたらいろいろ躓いたので、今後また入れなおすようにメモ

#環境
windows10
RTX2070
Ryzen 3700x
Anaconda

#道筋
Anacondaのダウンロード
環境の作成
tensorflowの依存環境の把握
cudaのダウンロード
cuDNNのダウンロード
パス

#バージョン
2019年にtensorflowが1.xから2.xになって書き方が結構変わったみたい
よってネット上に結構あるプログラムが動かないのでないっぽい
よって環境を二つ作って、一つは2.xの最新版、もう一つは1.xの最新版を入れる


#2.x

Python3.7
tensorflow-gpu==2.4.0
cudnn8.0.5
cuda11.0
keras-2.4.3


##環境作成


https://qiita.com/ozaki_physics/items/985188feb92570e5b82d

に環境の作り方がある。

```
Conda create -n 37tens24 python=3.7 anaconda
```

##versionの把握

次に、tensorflowの依存環境を把握

https://www.tensorflow.org/install/source_windows?hl=ja

最新版はなかったため、また時々間違っているため

https://www.kkaneko.jp/tools/win/keras.html

こちらで確認した
また、基本的にこのサイトに沿えば良い
最新版はkerasは依存間関係なさそう

```
pip install tensorflow-gpu==2.4.0
pip install keras
```




##cuda toolkit

https://developer.nvidia.com/cuda-toolkit-archive

ここからダウンロード

11.0をダウンロード
やり直すことを考えてlocalの方をダウンロードしたほうがいい(500MBぐらい)

実行
最初はすべてダウンロード

https://www.kkaneko.jp/tools/win/cuda.html

ここが詳しい

##cudnn

詳しい解説

https://www.kkaneko.jp/tools/win/cudnn805.html

https://developer.nvidia.com/cudnn

ここからダウンロード
そして解凍

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0
やり直すこと考えてこれをバックアップしてから解凍内容をコピペ


##pathの追加

___システム___ の環境変数の名前
CUDNN_PATH
値
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0
のように設定（管理者から）

なお、システムの環境変数の変更には管理者で開く必要がある。

https://www.lisz-works.com/entry/sys-env-admin

Windowsマーク右クリックからの管理者powershell

```
Start C:\Windows\system32\rundll32.exe sysdm.cpl, EditEnvironmentVariables
```


これで全て使えるようになる。




#1.x

37tens115
tensorflow-gpu==1.15.0
Cudnn7.4.2では動かないので7.6.5
Cuda10.0
Keras2.3.1
最新版の Keras は TensorFlow 1.15 では動かない． Keras のバージョン 2.3.1 をインストールする

二つ目かつ古いバージョンの場合、cudaは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/780a9356-e1e5-e70d-415b-493cdeb29933.png)
これだけでいい

このサイトが詳しい

https://www.kkaneko.jp/tools/win/cuda.html 

※ 複数の版の CUDA ツールキットをインストールする場合には， 複数のパスが設定される このとき・古い版の方が先に来ている場合には、後になるように調整する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/59ab722d-d52c-4866-7d16-65bf2cc50990.png)

Cudnn_pathは11のままで動いた



#まとめ
意外とすんなりいかず、大変なので頑張ってください。
機密データをリポジトリから削除する

Git リポジトリへのパスワードや SSH キーといった機密データをコミットする場合、そのデータを履歴から削除することができます。 不要なファイルをリポジトリの履歴から完全に削除するには、git filter-branch コマンドと [BFG Repo-Cleaner](https://rtyley.github.io/bfg-repo-cleaner/) は、リポジトリの履歴を書き換えます。

ここにはgit filter-branchを使ってすべてのbranchesとtagsの履歴を削除するスクリプトです。

```sh
#!/bin/bash

branches=(master 1.0.0 1.0.1 ...)
key_file="file or path will be deleted"
for br in "${branches[@]}"; do
    echo $br
    git checkout "$br"
    git filter-branch --force --index-filter "git rm --cached --ignore-unmatch $key_file" --prune-empty --tag-name-filter cat
    git add . && git commit -m "delete Sensitive Data" && git push origin --force --all
done

git push origin --force --tags
```

参照

1. [機密データをリポジトリから削除する] (https://docs.github.com/ja/free-pro-team@latest/github/authenticating-to-github/removing-sensitive-data-from-a-repository)
2. [ファイルをリポジトリの履歴から削除する](https://docs.github.com/ja/free-pro-team@latest/github/managing-large-files/removing-files-from-a-repositorys-history)
MySQL8のテーブルにCSVファイルをまるごとインポートする手順

# やりたいこと

* MySQL8のテーブルにCSVファイルをまるごとインポートしたい。
* mysqlのコマンドラインを使いたい。


# 環境

* CentOS8+MySQL8


# DBの構成

```sql
CREATE DATABASE yamato CHARACTER SET utf8;
```

usersテーブルが下記の構造で作成済みであるとする。

```sql
CREATE TABLE `users` (
  `id` bigint unsigned NOT NULL,
  `gender` varchar(255) NOT NULL,
  `age` int unsigned NOT NULL,
  `marriage` varchar(255) NOT NULL,
  `pref` varchar(255) NOT NULL,
  `job` varchar(255) NOT NULL,
  `hobby` varchar(255) NOT NULL,
  `y` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
```

この、yamato.users に、CSVファイルからデータをインポートしたい。


# CSVファイルの構造

### users.csv

文字コードはutf8とする。

```csv
id,性別,年齢,婚姻,都道府県,職業,趣味,y
1,男性,39,既婚,愛媛県,フリーランス,映画,no
2,男性,79,既婚,滋賀県,会社役員,アウトドア,no
3,男性,29,未婚,京都府,無職,音楽,no
4,女性,28,既婚,新潟県,会社役員,テレビゲーム,no
5,女性,73,未婚,青森県,会社員,映画,no
6,男性,71,未婚,石川県,学生,オートバイ,yes
7,女性,78,未婚,群馬県,学生,読書,no
8,女性,65,既婚,徳島県,フリーランス,映画,no
9,女性,34,既婚,宮崎県,自営業,アウトドア,no
10,女性,69,既婚,茨城県,会社員,映画,no
11,男性,67,既婚,山梨県,フリーランス,音楽,no
```





# 取り込み

## CSVファイルの一行目（ヘッダ）を削除する。

```
id,性別,年齢,婚姻,都道府県,職業,趣味,y
```
をviで削除する。ちなみに、

```
LOAD DATA LOCAL INFILE
```

実行時、末尾に



```
IGNORE 1 LINES
```

を付与すれば、ヘッダ一行を飛ばしてくれるので、その場合はviで削除しなくてもOK。



## CSVファイルを下記に置く。




```
/home/yamato/csv/users.csv
```


## コマンドラインからMySQLに接続する。

MySQLにrootで接続する。
`--local-infile=1` を付与しないと取り込めないので注意する。

```
mysql --local-infile=1 -u root -p
```


## 



## 下記コマンドで取り込む。

mysql>


```
SET GLOBAL local_infile=on; 
```

```
load data local infile "/home/yamato/csv/users.csv" into table yamato.users fields terminated by ',' optionally enclosed by '"';
```


結果を確認する。CSVの5万行がすべて正常に取り込まれた。

```
Query OK, 50000 rows affected (0.80 sec)
Records: 50000  Deleted: 0  Skipped: 0  Warnings: 0
```



### テーブルの中身を確認する。


```
mysql> select * from users limit 10;
+----+--------+-----+----------+-----------+--------------------+--------------------+-----+
| id | gender | age | marriage | pref      | job                | hobby              | y   |
+----+--------+-----+----------+-----------+--------------------+--------------------+-----+
|  1 | 男性   |  39 | 既婚     | 愛媛県    | フリーランス       | 映画               | no  |
|  2 | 男性   |  79 | 既婚     | 滋賀県    | 会社役員           | アウトドア         | no  |
|  3 | 男性   |  29 | 未婚     | 京都府    | 無職               | 音楽               | no  |
|  4 | 女性   |  28 | 既婚     | 新潟県    | 会社役員           | テレビゲーム       | no  |
|  5 | 女性   |  73 | 未婚     | 青森県    | 会社員             | 映画               | no  |
|  6 | 男性   |  71 | 未婚     | 石川県    | 学生               | オートバイ         | yes |
|  7 | 女性   |  78 | 未婚     | 群馬県    | 学生               | 読書               | no  |
|  8 | 女性   |  65 | 既婚     | 徳島県    | フリーランス       | 映画               | no  |
|  9 | 女性   |  34 | 既婚     | 宮崎県    | 自営業             | アウトドア         | no  |
| 10 | 女性   |  69 | 既婚     | 茨城県    | 会社員             | 映画               | no  |
+----+--------+-----+----------+-----------+--------------------+--------------------+-----+
10 rows in set (0.00 sec)

```


```
mysql> select count(id) from users;
+-----------+
| count(id) |
+-----------+
|     50000 |
+-----------+
1 row in set (0.06 sec)
```
Jupyter notebook の結果を Qiita に上げるために markdown にする

Google colaboratory を使っていて、できあがった Jupyter notebook のファイル（.ipynb） を Qiita にアップしたいとき markdown に変換するのですが、これをコマンドラインで行ないたいと思ってもすぐには思い出せない。かといってググってもすぐには見つからないのでメモします。

```Python
jupyter nbconvert --to markdown Untitled.ipynb 
```

以上ッ！
curl でgetしてみる

curlを使ってリクエストを送ってみました。

今回はただの郵便番号取得APIに対してgetしてみる。


以下コマンドプロンプトにて。。

```
rem 文字化けするのでUTF8に変更
chcp 65001

rem curl実行
curl https://zipcloud.ibsnet.co.jp/api/search?zipcode=9000025 -x http://proxy.hoge.co.jp:8080
```

ちゃんとレスポンス返ってきました

```
{
        "message": null,
        "results": [
                {
                        "address1": "沖縄県",
                        "address2": "那覇市",
                        "address3": "壺川",
                        "kana1": "ｵｷﾅﾜｹﾝ",
                        "kana2": "ﾅﾊｼ",
                        "kana3": "ﾂﾎﾞｶﾞﾜ",
                        "prefcode": "47",
                        "zipcode": "9000025"
                }
        ],
        "status": 200
}
```
Mac ターミナル　絶対パスの指定について

#絶対パスの指定について覚えたこと
**/**がルートディレクトリ（Macintosh HD)の場所

```
/users/YourName(自分の名前）
上記がホームディレクトリ
```

絶対パスで指定する時は基本 

```
cd /users/YourName/desktop
```
といったような操作をすると出来る
未来ファンダンラーンをやってみた

年明けのタイミングのふりかえりとして、未来ファンダンラーンをやってみました。

**「いまから3ヶ月後、4Qの目標を達成できた！という気持ちになる」**

という体で、「3ヶ月後にできたこと」＝やるであろうことを付箋に書き、それを紹介(自慢！)しながらFun/Deliver/Learnに貼っていきます。わざと過去形で、「○○をやってお客様にすごい喜ばれました！ 自分も嬉しかったです」みたいな。

ダーツの矢は、最後のまとめとして、これから3ヶ月どういうバランスを狙っていくか？を全員で示したものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17131/10a26d8c-912c-4474-4b71-6906312e431e.png)

これからやることをイメージして共有するという内容になるので、インセプションデッキ作りのタイミングで取り入れたり、簡易な代替としても使えそうです。

# やり方

例として今回の進め方を説明してみます。今回は10人でやって、全体で30分弱。ツールはMiroでした。

1. 次の重要マイルストーン(今回は3ヶ月後)に、マイルストーンの目標を達成した気持ちになる。どんなことを、どんなふうにやったか想像する
2. 1人ずつ付箋に、自分がやった(やるだろう)ことを書き出す。仕事、機能、作業など、なんでもいい。5分間程度
3. その間にFun/Done/Learnの枠を用意する。今回は、チーム外への価値提供や貢献にフォーカスするため、Done→Deliverにしました
4. 1人ずつ順番に、付箋を紹介しつつ、Fun/Deliver/Learnの中に貼っていく。わざと過去形でしゃべる。たとえば「マニュアルを作りました。別部署と協力してやったのでDeliverで、初めての作業なのでLearnもありました。ドキュメント中心なのでFunはなかったですね」という感じで。周りの人は「あれは大変だったねー」「すごいいいデキだったよね！」「おかげで助かりました」などとノリよくわいわいしましょう
5. 1枚紹介したら次の人へ。1人1枚ずつでぐるぐる回しながら進める。時間が足らなくなったら、残りは説明せず、全員同時に、自分のものを枠内に貼ってしまってもよいです
6. 最後に、気持ちをいま現在に戻して、付箋のバランスを見ながら、Fun/Deliver/Learnのどのあたりのバランスを狙っていくとよいか考え、そこにダーツのアイコンを1人1箇所貼る(星マークとかのほうがよいかも)。今回だと、Deliver重視だけどFunもほしいし、Learnもできれば狙いたい、みたいな感じになっています
7. ファシリテーターがてきとうにまとめる。今回はこんなことを言いました。「これが向こう3ヶ月で狙いたいバランスですね。なにか判断に迷ったとき、このバランスに近づくように考えると、たとえばDeliverを最優先しようとか、チームの方向性をそろえられますね」。余裕があれば、全員で言語化して残せるとよいかもしれません。インセプションデッキにおけるトレードオフスライダーのような役割も果たせます

# やってみての気づき

今回やってみた中で、みなさんの発言に以下のような傾向が見られました。どんな傾向があるか意識して聞いていると、メンバーが今後の見通しをどう考えているか情報収集でき、ひいてはリスク対策にもつなげられそうです。

- かならずしも計画通り、理想的に終わったとは、言わない人が多い。どういうところに苦労した、と具体的な話もあった。
- 「お客様から使いにくいところをフィードバックしてもらえた」のように、誰からどんな学び(Learn)が得られるか言明があった。
- プロダクトとして必須のアウトプットについて、複数人が「自分がやった」と言った。協力して進められそうな関係性が見えた。
- ダーツの位置がかなり集中し、しかもど真ん中ではなかった。マイルストーンへの方向性がすでにそろっている。

スクラムマスターが情報収集する手法としても、役に立ちそうです。

年明けに限らず、なんらかの大きなリリース後とか、マイルストーン達成後などのタイミングでも使えると思います。インセプションデッキ作りに含めてもよさそうです。
[RxSwift]combineLatestについて

Rxの学習過程で学んだことを後からでも見れるようにメモしていきます
本記事はこちら[RxSwift](https://github.com/ReactiveX/RxSwift/tree/main/RxExample/RxExample/Examples)を参考にしています

# CombineLatestとは
`Observable`シーケンスのいずれかが要素を生成するたびに、指定された`Observable`シーケンスを、1つのタプルの`Observable`シーケンスにマージする。

# 使用例
各`TextField`に入力した値をリアルタイムで合計し、ラベルに表示する。
といった機能を作っていきます。

数値入力用の`TextField`を3つと合計結果表示用の`Label`をひとつ用意しいます。


```swift

Observable.combineLatest(textField1.rx.text.orEmpty, textField2.rx.text.orEmpty, textField3.rx.text.orEmpty) { textValue1, textValue2, textValue3 -> Int in
            return (Int(textValue1) ?? 0) + (Int(textValue2) ?? 0) + (Int(textValue3) ?? 0)
        }
        .map { $0.description }
        .bind(to: label.rx.text)
        .disposed(by: disposeBag)
```
# 結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774264/96470071-782d-f281-2135-87f45a7ce134.png" width="260"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774264/ccacc54d-d8e1-1ae3-c43e-a3ce72dbac93.png" width="270">
rbenvでRubyのバージョンが切り替わらないときの対応

rbenvでRubyのバージョンが切り替わらなかったので、それのメモです。

# 事象
rbenvでバージョンを切り替えても変わりません

```bash
$ rbenv versions
  system
  2.6.6 
* 2.7.1 (set by RBENV_VERSION environment variable)
$ rbenv global 2.6.6
$ rbenv versions
  system
  2.6.6 
* 2.7.1 (set by RBENV_VERSION environment variable)
```

# やったこと
`set by RBENV_VERSION environment variable`と言われているのですが、特にどこにも書いていません。
また`.zshrc`で`export RBENV_VERSION=2.6.6`をすると、rbenvのversionはうまく変更されますが、
rubyのバージョンを確認しようとするとエラーになります。

```bash
$ rbenv versions
  system
* 2.6.6 (set by RBENV_VERSION environment variable) 
  2.7.1
$ ruby -v
/Users/naoto.koyama/.rbenv/versions/2.7.1/bin/ruby: invalid option -:  (-h will show valid options) (RuntimeError)
```

# 原因
Ruby 2.7の警告を抑制するために`.zshrc`に書いているRUBYOPTの設定を書いていることが原因でした

```bash
$ cat ~/.zshrc
...
export RUBYOPT='-W:no-deprecated -W:no-experimental' # <- これが原因
```

上記を削除してから以下のコマンドを打てばOKです

```bash
$ unset RUBYOPT
$ rbenv global 2.6.6
$ rbenv versions
  system
* 2.6.6 (set by /Users/naoto.koyama/workspace/portal/.ruby-version)
  2.7.1
$ ruby -v
ruby 2.6.6p146 (2020-03-31 revision 67876) [x86_64-darwin20]
```

# 参考
[rbenvのrubyコマンドがすべて「invalid option -: (-h will show valid options) (RuntimeError)」それRUBYOPTが原因かも](https://qiita.com/hirocueki2/items/010c777d2125ee120a8e)
Javaでbyte配列をgzip圧縮してファイル出力する

タイトルの処理を作成した際に試行錯誤したメモ。

## とりあえず書いたソース
こんな感じでbyte配列をgzipにしてファイルに出力してました。
先に別用途でファイル出力する処理を書いていたのを改造した際に、あれこれ調べながら付け足し付け足ししてしまい、今思うと謎に冗長な書き方をしてます。

```java:test.java
        byte[] bytes = output.toByteArray();
        // byte[]をgzip化
        String gzipStr = "";
        try {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            GZIPOutputStream gzip = new GZIPOutputStream(out);
            gzip.write(bytes);
            gzip.close();
            gzipStr = out.toString();
            out.close();
        }catch (IOException e) {
            e.printStackTrace();
            return;
        }
    	// gzip化したデータをファイル書き出し
        String file = "出力ファイルパス";
        try(PrintWriter writer = new PrintWriter(
            new BufferedWriter(
            new OutputStreamWriter(
            new FileOutputStream
              (file),"UTF-8")))) {
            writer.print(gzipStr);
            
        } catch (IOException e) {
            e.printStackTrace();
        }
```

### エラー内容
↑のJavaをコンパイルして実行し、出力したファイルを解凍しようとすると下記のエラーが。

```
01-05 08:35:22.294 6117-6117/? W/System.err: java.io.IOException: unknown format (magic number ef1f)
01-05 08:35:22.294 6117-6117/? W/System.err:     at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:109)
01-05 08:35:22.294 6117-6117/? W/System.err:     at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:88)
　以下略
```

恥ずかしながら何もわからず、「gzip マジックナンバーとは」とかでググるところから。([マジックナンバー (フォーマット識別子) - wikipedia](https://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%B8%E3%83%83%E3%82%AF%E3%83%8A%E3%83%B3%E3%83%90%E3%83%BC_(%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88%E8%AD%98%E5%88%A5%E5%AD%90)))

gzipはファイルの先頭が「1f8b」で始まり、これがマジックナンバー（形式を判断するための符号）なのですが、このファイルは「ef1f」から始まっているためファイル形式が判定できないよということみたいです。

### バイナリファイルを確認
Stirlinで出力したファイルを確認してみると、確かに最初が「1f8b」ではないですね。（でも「ef1f」でなく「1fef」のような…）
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/738160/5cc35b1c-e6d6-4909-15c2-746d799d3f69.png)

##ソース修正
出力時にこねくり回しているのが悪いのかな、と調べて下記サイトを発見。
[ANDROIDでGZIPファイルの圧縮・展開をする - TECHBOOSTER](https://techbooster.org/android/15542/)

えーこんなにシンプルに書いていいの、と驚きながら参考にさせていただきソースを修正したものがこちら：

```java:test.java
        byte[] bytes = output.toByteArray();
        String file = "出力ファイルパス";
        try {
            GZIPOutputStream gzip = new GZIPOutputStream(new FileOutputStream(file));
            gzip.write(bytes);
            gzip.close();
        }catch (IOException e) {
            e.printStackTrace();
            return;
        }
```

これでファイル出力したら正常に解凍できました。

バイナリファイルも先頭が「1f8b」になりましたので、大丈夫そうです。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/738160/9177bc8a-3362-0e0b-7bbf-5fbec6f5b924.png)

***
諸事情によりIDEを使わずテキストエディタで書いたんですが、importだけですっかり気が滅入りました…JavaはIDEを使おう……
【Normalization】instance norm : BatchNormよりInstanceNorm?

<h1>Instance Normalization: The Missing Ingredient for Fast Stylization</h1>
Instance NormはBatch NormのBatch Size=1の時と等価である。
Instance Normはスタイル変換という2枚の画像を組み合わせて、両方の画像の特徴を合わせた画像を生成するタスクで使われている。


<h2>計算式</h2>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/2436dda4-f578-33ae-c7a5-b647a57dfd30.png)
[pytorch引用](https://pytorch.org/docs/stable/generated/torch.nn.InstanceNorm2d.html)

数式通り平均からの差分をとり、標準偏差で割っています。
標準偏差で割る事でデータの分散の影響を受けにくくなる。




<h1>結果</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/34aa3aa3-3937-4bbb-a4e0-ee76073aa8dd.png)

左下の画像(zero pad)より右下の画像(zero pad + instance norm)の方が、入力の画像の特徴を壊さずstylization出来ている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/0647f93b-4d8d-d05c-7b17-31bf69385320.png)
Batch NormよりInstance Normの方が良くstylizationされている

<h1>結論</h1>
・入力画像の光の加減や影響を受けにくくなるはず
・次は他のタスクに使われている論文をまとめたい

<h1>参考文献</h1>
Instance Normalization: The Missing Ingredient for Fast Stylization
https://arxiv.org/pdf/1607.08022.pdf
python　chromedriver自動更新


pythonで簡易RPAを実施しているのでけれど、
chromedriverを手動で更新していたがめんどくささが限界に。。

重い腰を上げ調べてところ下記の記事が役に立ちました。

https://yuki.world/python-selenium-chromedriver-auto-update/

###１．pipでweb_drivermanagerをインストール

pip install webdriver_manager --proxy=proxy.hoge.com:8080

※うちはproxy環境なのでproxyオプションつけています。通常不要。

###２．pythonファイルに参照import

from webdriver_manager.chrome import ChromeDriverManager

###３．pythonファイルのdriver初期化をちょこっと変更

driver = webdriver.Chrome(ChromeDriverManager().install())

自動化された。。すばらしい。

以上
LIFFでQRコードリーダーを実装する

# 対象読者
LIFFでQRコードリーダーを実装しようとして画面に表示されなかったデベロッパー向けです。
LIFFを実機で確認できるまでの全体のフローを知りたい方は、他の記事を参考にしてください。
また、実際に実装した際にNuxt.jsを用いたため、jsをベースにこの後も話を進めます。

# LIFFのバージョン

```
liff.getVersion()

> 2.6.0
```

# 今回詰まった点
QRコードリーダーを実装する際は、以下の２つの機能を実装する必要があります。

1. デバイスのカメラの映像をスクリーンに表示する
2. JavaScriptのQRコードスキャンのライブラリを用いて画像にQRコードがあるかを判別する

1.の実装をするには[WebRTC](https://developer.mozilla.org/ja/docs/Web/API/WebRTC_API)というAPIの`navigator.mediaDevices.getUserMedia()`というメソッドを用いる必要があります。今回発生した問題はまさにここで、iPhoneでLINEを開いて確認してみると、なんとLIFFブラウザではこのAPIが対応しておらず表示がされません。ただ、Androidのスマートフォンで見てみると、LIFFブラウザでも問題なく動作しました。調べてみると、LIFFブラウザはiOSとAndroidでそれぞれ別のWebViewが使われおり（下参照）、iOSのWKWebViewがWebRTCに対応していなかったようです。
> iOS：12.0以降。WKWebView (opens new window)が使用されます。
Android：5.0以降
LINE：v9.14.0以降

# 解決方法

解決方法は至ってシンプルで、QRコードリーダーのページのみ、WebRTCに対応しているブラウザで開く、これだけです。
`navigator.mediaDevices.getUserMedia()`のブラウザの対応状況はIEを見ないフリをすれば、全てに対応しています。
![スクリーンショット 2021-01-04 22.27.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405522/2c58355a-1850-b9dd-4eea-2cb557986e38.png)

ただし、　iOSのChromeやfirefoxは、WKWebviewが使われており、先に述べた理由から、正常に動きませんでした。
そのため、スマホを利用する前提のアプリケーションを想定する場合は、どのブラウザがWebRTCに対応しているかを確認して要件を決めた方がいいと思います。

（注）なお、iOS14.3からChromeとFireFoxで`getUserMedia()`が利用できるようになったようです。

##　LIFFブラウザからWebブラウザを開く方法
LIFFブラウザからWebブラウザを立ち上げるには、`liff.openWindow()`メソッドを使用します。（[ドキュメント参照](https://developers.line.biz/ja/reference/liff/#open-window)）

```js
toQRCodeReader() {
  // LIFFブラウザで立ち上げていた場合
  if (liff.isClient) {
    liff.openWindow({
      url: URL,           // full path
      external: true      // true: 外部ブラウザで開く
    })
  // それ以外
  } else {
    this.$router.push(PATH)
  }
}
```
##　WebブラウザからLIFFブラウザを開く方法
ドキュメントに記載のある通り、`liff.openWindow()`メソッドの外部ブラウザでの利用は、保証対象外です。そのため、jsの通常のページ遷移を行う必要があります。

```js
location.href=URL
```
 注意点としてはここに書くURLは**アプリのフルパスではなく、LIFF URL**になります。URLの詳しい設定方法は[ドキュメント](https://developers.line.biz/ja/docs/liff/opening-liff-app/#redirect-flow)を参考にしてください。こうすることでページ遷移をするときに、ポップアップが出て、LINEで開くかを聞いてくれるようになります。（ただ、AndroidのChromeではポップアップが出ずにそのままブラウザ内で遷移しました。要検証かもです）

以上で正常に動くQRコードリーダーが実装できます。


# 補足 ： QRコードリーダーの実装
「以上でQRコードリーダーが実装できます。」って言ってるけどQRコード実装の部分の説明全然ないやん。と思われた方用に。
実際に実装する際に参考した記事を貼っておきます。

・[[HTML5] QRコードリーダーを作成する](https://blog.katsubemakito.net/html5/qrcode-reader)
・[Webの技術だけで作るQRコードリーダー](https://qiita.com/shora_kujira16/items/a9e3aa0b06525c00a7e0)
Sphinxを以前使用していたなー

と
Qiita記事で紹介されていた
[忙しい研究者のためのテストコードとドキュメントの書き方](https://qiita.com/hmkz/items/0689cd85fb3e1adcda1a?utm_source=Qiita%E3%83%8B%E3%83%A5%E3%83%BC%E3%82%B9&utm_campaign=ec948d6603-Qiita_newsletter_444_01_06_2021&utm_medium=email&utm_term=0_e44feaa081-ec948d6603-39108994)
を見て思い出しました(^_^;)

今は情シス業務だから使っていないけど懐かしかったのでメモ失礼します。

そのうちドキュメントからコードに起こしてくれるようになる未来が来ると思っていました(^_^;)
Pandasで「ImportError: Install xlrd >= 0.9.0 for Excel support」エラー。 openpyxlを使うように変更して解決

『Python実践データ100本ノック』のサンプルで、エクセルファイルを読み込むコードを試していたら、以下エラー発生。

```python
ImportError: Install xlrd >= 0.9.0 for Excel support
```


## 解決方法

### openpyxlをインストール

```python
pip install openpyxl
```

### pandasのread_excel()のパラメータにengineを指定

```python
# 修正前
# kokyaku_data = pd.read_excel("kokyaku_daicho.xlsx")

# 修正後
kokyaku_data = pd.read_excel("kokyaku_daicho.xlsx", engine="openpyxl")
```

Pandasのデフォルトのengineがxlrdだけど、最近xlsxファイル非対応になってしまったため、engineをopenpyxlに切り替えてあげることでエラー回避できました。

xlrdのほうもそのうち修正されるだろうけど、それまでは上記で対処するのがよいみたいです。

## 試したこと
参考までに、エラー発生後試したことメモしておきます。

色々やったけど、多分上記対応のみでいけるはず・・・

[こちらの記事](https://qiita.com/7110/items/557c87f806595bce70d4)を参考に、xlrdをインポートしてみる。

```python
pip install xlrd
```

しかし今度はインストールしたxlrdはxlsxファイルをサポートしてないとのエラーが発生。

```python
XLRDError: Excel xlsx file; not supported
```

[こちらの記事](https://oku.edu.mie-u.ac.jp/~okumura/python/201212.html)で、Pandas1.2.0で解消したことを知る。

[参考：Pandasの1.2.0関連の記事](https://pandas.pydata.org/docs/whatsnew/v1.2.0.html)

そこで一度Pandasをアンインストールし、1.2.0をインストール。2021/1/6時点では、バージョン指定しない場合1.1.3になるようだったので、バージョン指定してインストール。

```python
pip install pandas==1.2.0
```

ちなみに、condaでインストールしようとすると失敗した。
また、numpyが1.19.5に自動更新された。

すると今度は下記エラー

```python
ValueError: Your version of xlrd is 2.0.1. In xlrd >= 2.0, only the xls format is supported. Install openpyxl instead.
```

どういうこと？と調べてみたところ、

- openpyxlをインストール
- pandasのread_excel()のパラメータにengineを指定

とすればよいとのこと。


```python
pd.read_excel("sample.xlsx", engine="openpyxl")
```

参考：[https://teratail.com/questions/310586](https://teratail.com/questions/310586)
メール関連　勉強メモ

## メール関連の勉強メモ
### MTA（メール転送エージェント：Message Transfer Agent）
  * ネットワーク上でメールを転送・配送するソフトウェア。 
  * メールを受け取って次の適切な配信先を決定するのが主な役割
  * 配信先への送信・転送はMDAが行う
  * 利用者とのメール送受信やMTA間のメール送受信にはSMTP通信プロトコルが標準的に用いられる。
  * SMTPサーバーのプログラムの１つ
電子メールクライアント（MUA)・・・メールソフトのこと

#### 種類
  * Sendmail
  * Courier-MTA
  * Postfix
  * qmail
  * Exim
  * Apache James
  * Microsoft Exchange Server

### qmail（きゅーめーる）
  * メールサーバーソフトウェア・MTA
  * Sendmailの問題点を解消するためにつくられた。

### 特徴
  - 設定がシンプル
  - Sendmail,Postfixと互換性なし
  - セキュリティが強固
  - 高速なメール配信が可能
  - MailDir形式で安全なメッセージ保管ができる
  - インストールに手間がかかる


### メールアドレスの仕様
https://www.nic.ad.jp/ja/dom/system.html

### envelope-from
  * envelope（エンベロープ）
  * もともと封筒の意味
  * mail関数の5番目の引数。「-f」と送信者のアドレスを設定する
  * 電子メールの送受信にサーバーが使用する宛先や送信者名などの付加情報や、Webサービスに使われるXMLの付加情報
  　　* 例として、SOAPにおいて用いられるSOAPエンベロープなどがある。 
  * メールのヘッダーに書かれるenvelope-fromは、メッセージヘッダのFromとは別のもの。厳密な送信先を示し、エラーメール(bounce:バウンス)の送信先になる

#### ヘッダFrom
    メールクライアント(Microsoft OutlookやMozilla Thunderbirdなど)でメールを受信したときに、「差出人」欄に表示されている情報です。
    これは、封筒の中の便箋に書かれている差出人に例えることができ、実際の差出人とは異なる情報を表示することもできます。

#### ヘッダTo
    メールクライアント(Microsoft OutlookやMozilla Thunderbirdなど)でメールを受信したときに、「宛先」欄や「Cc」欄に表示されている情報です。
    これは、封筒の中の便箋に書かれている宛先に例えることができ、実際の宛先とは異なる情報を表示することもできます。

#### エンベロープFrom
    メールを手紙に例えると、封筒に記載されている差出人です。メールの世界では、この情報が正しいものでないと正しくメール送信ができないので、「エンベロープFrom」が本当のメールの差出人となります。
    これはメールクライアントの「差出人」欄に表示されている情報とは異なる場合があります。
    また、送ったメールがエラーで届かなかった場合、エラーメールはこのエンベロープFromのアドレス宛に届きます。

#### エンベロープTo
    メールを手紙に例えると、封筒に記載されている宛先です。この情報が正しいものでないと正しくメール送信ができないので、エンベロープToが本当のメールの宛先となります。
    これはメールクライアントの「宛先」欄や「Cc」欄に表示されている情報とは異なる場合があります。
Rails6でvue.jsを使った開発を行うための設定に挑戦

Rails x Vue.jsを用いた開発に挑戦している。手探りなので間違っている箇所もあるかもしれないが自分なりに検索してやってみた。そういう記事としてご覧いただけると嬉しいです。

### 環境構築

①npmを導入(ホームディレクトリでOK)

```terminal
brew install npm
```

②npmのパッケージをアプリに導入(アプリのディレクトリで)

```terminal
npm init
```

ここで対話プロンプトが起動し、いくつか入力を求められる。()内はnpmコマンドがデフォルトで用意した値。

```terminal
package name: (a) sample
version: (1.0.0) 0.0.0
description:
entry point: (index.js)
test command:
git repository:
keywords:
author: 
license: (ISC)
```

name…packageの名前。ソースコードでimportやrequireをする際に使われる。

version…最初なので1.0.0とか0.0.0とかで答えておく。更新するたびにバージョンを変える必要あり

description…パッケージの説明。特に入力しないと以下のように表示される

```json
"description": "This README would normally document whatever steps are necessary to get the application up and running.",
```

アプリを使うための説明はREADMEに書いたから見てくれや〜って感じのこと言ってる

main…モジュールの中で最初に呼ばれるスクリプトファイル。パッケージをrequireした際に最初に呼ばれるファイル。今回はmain.jsとした。

test command…コマンドを使ってソースコードの実行ができるようにする設定。何も入力せずenterを押すと

```json
"test": "echo \"Error: no test specified\" && exit 1"
```

こんな感じの値が保存される。

これは

```
npm test
```

というコマンドに対してecho以下の出力を出しますよ、という意味。実際に実行すると

```
% npm test

> アプリ名@0.1.0 test 
> echo "Error: no test specified" && exit 1 ここ

Error: no test specified
npm ERR! Test failed.  See above for more details.
```

こんな感じでechoのところが出力される。

repository…紐付けるgitリポジトリを指定。.gitが存在している場合特に入力していなくても勝手に現在紐付いているgitリポジトリのurl入力される。

author…パッケージの著作者。

license…パッケージの権利情報。標準ではISCとなっているのでそれに倣った。

対話シェルで入力していないものも含めて最終的に以下のようなpackage.jsonができた。

```json
{
  "name": アプリ名,
  "private": true, (公開したくない場合true)
  "dependencies": {
    "@rails/actioncable": "^6.0.0-alpha",
    "@rails/activestorage": "^6.0.0-alpha",
    "@rails/ujs": "^6.0.0-alpha",
    "@rails/webpacker": "4.3.0",
    "turbolinks": "^5.2.0",
    "vue": "^2.6.12"
  },
  "version": "0.1.0",
  "devDependencies": {
    "vue-loader": "^15.9.6",
    "webpack": "^5.11.1",
    "webpack-dev-server": "^3.11.1"
  },
  "description": "This README would normally document whatever steps are necessary to get the application up and running.",
  "main": "main.js", (パッケージを呼び出した時に最初に呼ばれるソースコード)
  "directories": {
    "lib": "lib",
    "test": "test"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": 紐付けているgitリポジトリ
  },
  "author": 自分で設定した著作者,
  "license": "ISC",
  "bugs": {
    "url": リポジトリのissue
  },
  "homepage": リポジトリ名のreadme
}
```



③webpack, vue-loaderを導入

```
#ローカルインストール
npm install webpack vue-loader  --save-dev
npm install vue --save

#グローバルインストール
npm install webpack -g 
```

これらをインストールするとnode.jsのモジュールがnode_modulesフォルダに大量にインストールされるが、これらはpackage.jsonに依存関係が記述されていることで勝手に読み込んでくれる。よってgitにpushする必要がない。

なのでgitignoreをいじる

```.gitignore
node_modules/
```

こうするとnode_modulesがgitにpushされなくなる。

【参考】

vue.jsを用いた開発の導入

https://qiita.com/m0a/items/34df129d6d8991ebbf86

node_modulesをgitignoreに含める理由とか

https://qiita.com/growsic/items/b2965c0ba3b0aaae1ff8

package.jsonの中身

https://qiita.com/dondoko-susumu/items/cf252bd6494412ed7847

npmコマンドでpermission deniedされたので参照したやつ

https://qiita.com/okohs/items/ced3c3de30af1035242d

vue-loaderってなに

https://vue-loader-v14.vuejs.org/ja/



【次やること】

package.jsonの細かい設定の修正
Serverless FrameworkとAWS Lambda with Pythonの環境にpipインストール

pipインストールが必要なAWS LambdaのPythonスクリプトをServerless Frameworkでデプロイする方法です。

gemインストールが必要なAWS LambdaのRubyスクリプトについては[前回](https://qiita.com/suzuki-navi/items/1369b11a8f5d7f467645)の記事で書きました。

# 手順概要

プラグインを入れれば簡単にできます。

1. `serverless plugin install -n serverless-python-requirements`
2. `requirements.txt` 作成
3. あとは普通にデプロイすると勝手にいろいろやってくれる


# 手順詳細

## Serverless Frameworkのサービス作成

```console
$ serverless create --template aws-python3
Serverless: Generating boilerplate...
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v2.16.1
 -------'

Serverless: Successfully generated boilerplate for template: "aws-python3"
Serverless: NOTE: Please update the "service" property in serverless.yml with your service name
```

ファイルが3つ生成されます。

```
.gitignore
handler.py
serverless.yml
```


## プラグインインストール

`serverless-python-requirements` というプラグインをインストールします。


```console
$ serverless plugin install -n serverless-python-requirements
```

以下のファイルやディレクトリが増えます。

```
node_modules
package.json
package-lock.json
```

Serverless FrameworkがNode.jsで実装されているので、Pythonのプロジェクトなのに `node_modules` や `package.json` が存在することになるようです。


## ソースコード

### serverless.yml

`serverless.yml` は以下の内容にします。 `plugins` のところの記述はプラグインをインストールすると勝手に追記されています。

`serverless.yml`

```yaml
service: sample

frameworkVersion: '2'

provider:
  name: aws
  runtime: python3.8
  region: ap-northeast-1

functions:
  hello:
    handler: handler.hello

plugins:
  - serverless-python-requirements
```

### requirements.txt

サンプルのライブラリとして `jpholiday` というライブラリを使ってみます。日本の祝日を判定するライブラリです。

`requirements.txt` を作成し、以下の内容にします。ライブラリ名1行のみのファイルです。

```
jpholiday
```

サンプルとして `jpholiday` というライブラリを使ってみます。日本の祝日を判定するライブラリです。


### Pythonソースコード

`handler.py`

```python
import datetime
import jpholiday

def hello(event, context):
    holidayName = jpholiday.is_holiday_name(datetime.date(2021, 8, 8))
    print(holidayName) # CloudWatch に "山の日" と書き出される
```


## デプロイ

ここまで作成してから `serverless` コマンドでデプロイすると、Lambda本体だけでなく、 `serverless` コマンドが自動でライブラリをインストールしたイメージを作成し、AWS LambdaのLayerとしてアップロードしてくれます。

```console
$ serverless deploy -v
```


## 実行

デプロイ後にAWSマネジメントコンソールでLambdaを見ると次のように見えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/b3d4992e-d630-91ba-11f1-7544f1a23ed9.png)

Rubyと違ってLayerではなくLambdaに直接ライブラリが保管されるようです。

2021/01/29 追記
`serverless.yml`に設定を書き加えればLayerになりました。次の記事に書きました。
[AWS Lambda + Python + Serverless FrameworkのLayerにpipインストール](https://suzuki-navi.hatenablog.com/entry/2021/01/29/181135)

# リンク

- (Ruby版) [Serverless FrameworkとAWS Lambda with Rubyの環境にgemインストール](https://qiita.com/suzuki-navi/items/1369b11a8f5d7f467645)
flexを使ってコンテンツを並べる

#flexを使ってコンテンツを並べる方法

flexを使ってdivタグを並べることが多いのでけれど左右・中央寄せについてよく忘れるので、
まとめました。

###flexの指定

display:flex;

###フレックスアイテム(子ども）の並べる方向
※スタイルはフレックスコンテナ（親）に記述
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653035/c877b752-13a9-22ba-c4f7-14881ca909ce.png)

###フレックスアイテム(子ども）の位置
※スタイルはフレックスコンテナ（親）に記述
display:flex;
flex-direction:row ※省略可

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653035/542efdac-c560-aede-164d-2a2bcd2481e9.png)

中央:center　左：flex-start　右：flex-end　上：flex-start 下：flex-end
（※なお、flex-direction:rowの場合。flex-direction:columnの場合変わってくるので注意）

<p class="codepen" data-height="500" data-theme-id="light" data-default-tab="css,result" data-user="thithi7110" data-slug-hash="PoGexLP" style="height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="PoGexLP">
  <span>See the Pen <a href="https://codepen.io/thithi7110/pen/PoGexLP">
  PoGexLP</a> by thithi7110 (<a href="https://codepen.io/thithi7110">@thithi7110</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<!-- URLを古いものに変更 -->
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
(自分用)Flask(httpauthを使わないログイン)

#やる事
- `httpauth`を使わずSQLからアカウントデータ持ってきてログイン

#やる
```python:python
def getConnection():
    return pymysql.connect(
        host='ホスト名',
        db='db名',
        user='ユーザ名',
        password='パスワード',
        charset='utf8',
        cursorclass=pymysql.cursors.DictCursor
    )

#テンプレートからアカウント名とパスワード受け取ってる前提で
@app.route('/index', methods=["POST"])
def index():
    name = request.form["受け取ったアカウント名のやつ"]
    sc_number = request.form["受け取ったパスワードのやつ"]
#パスワードでアカウントデータ選択
    sql = "SELECT * FROM test_login where sc_number =" + str(sc_number)
    cursor = connection.cursor()
    cursor.execute(sql)
    sc_sql = cursor.fetchall()
#正しいパスワードが受け取れてるかの確認
    if len(sc_sql) <= 0:
        y = 0
    else:
        y = 1
#辞書形のリストになってて使い辛いから直す
        sc_number_sql = [d.get('パスワードのKey名') for d in sc_sql]
        sc_name_sql = [d.get('アカウント名のKey') for d in sc_sql]
        sc_number_send = sc_number_sql[0]
        sc_name_send = sc_name_sql[0]
    cursor.close()
    connection.close()
    if y == 1:
         return render_template("index.html", name = sc_name_send, sc_number=sc_number_send)
    else:
         return "Name or Password is False(`A´)"
```
- 一応入力テンプレートも

```html:html
<form action="/index" method="post">
        <label for="name">名前</label>
        <input type="text" name="name">
        <p></p>
        <label for="sc_number">学籍番号</label>
        <input type="password" name="sc_number">
        <button type="submit" name="belong" value="1">送信する</button>
        <p></p>
        <button type="submit" name="belong" value="0">外部の方</button>
</form>
```

#終わりに
- `httpauth`とSQLの兼ね合いを考えている暇が無くて書いた
- 普通にログインデータ保持するの忘れてた！今度セッション使ったやつ書く
- [書いた！](https://qiita.com/pokurin123/items/b9a7e95829d7fd39945a)
Docker Composeの基本とコマンド


# Docker Composeとは

複数のコンテナを定義し実行するDockerアプリケーションのためのツール。YAMLファイルを使ってアプリケーションサービスを設定。主に、以下の場合に使う。

- `$docker run`コマンドが長くなるとき
- 複数のコンテナをまとめて起動するとき


# YAMLファイルの書き方例

dockerのコマンドが以下の場合のYAMLファイル例。

```bash
$ docker build .
$ docker run -it -v ~/Desktop/myapp:/myapp -p 3000:3000 <image> bash
```

YAMLファイルは以下のとおり。

```yaml
version: '3'

services:
  web:
    build: .
    ports:
      - '3000:3000'
    volumes:
      - '.:/myapp'
    tty: true
    stdin_open: true
```

webの命名は任意だが、webかappがよく使われる。dockerのコマンド（runオプション）とYAMLファイルの対応は以下のとおり。

|dockerコマンド |YAMLファイル |
|:--|:--|
|build   |build:   |
|-i   |stdin_open: true   |
|-t   |tty: true   |
|-v   |volumes:   |
|-p   |ports:   |


# Docker Composeコマンド

Dockerコマンドとの対応は以下の通り。

|コマンド |Dockerコマンド |
|:--|:--|
|docker-compose build   |docker build <buil contexts>   |
|docker-compose up   |docker run <image>   |
|docker-compose ps   |docker ps   |
|docker-compose exec \<sevice> \<command>   |docker exec \<container> \<command>   |
|docker-compose up --build   |buildしてrun   |
|docker-compose down   |stopしてrm   |


# 参考：公式ドキュメント
[英語](https://docs.docker.com/compose/)
[日本語](https://docs.docker.jp/compose/toc.html)
pandas1.0以上でのjapandasのimport

pandas1.0以上の環境でjapandasを使うとエラーが起こるようです。
この問題への解決方法の実装がjapandasのgithubにPRされています。
しかしこのPRは2020/6/23に出されていますが、どうやら放置されているようです。
今回はこのPRのコードでlib/python3.8/site-packages/japandasを置き換えたらうまくimportできました。
手順をメモしておきます。

## バージョン・環境
python 3.8.5
pandas 1.2.0
matplotlib 3.3.3
mplfinance 0.12.7a4
WSL2
venvで環境構築
壊れても大丈夫なpython仮想環境で作業することをおすすめします。

## エラー内容
japandas を import すると以下のようなエラーが出ます。

```
----> 1 import japandas

~/env38/lib/python3.8/site-packages/japandas/__init__.py in <module>
      2 # coding: utf-8
      3 
----> 4 import japandas.core.strings                                                          # noqa
      5 import japandas.io.data                                                               # noqa
      6 from japandas.io.data import DataReader                                               # noqa

~/env38/lib/python3.8/site-packages/japandas/core/strings.py in <module>
      6 from unicodedata import normalize
      7 
----> 8 from pandas.compat import PY3, iteritems, u_safe
      9 import pandas.core.strings as strings
     10 

ImportError: cannot import name 'PY3' from 'pandas.compat' (/home/myname/env38/lib/python3.8/site-packages/pandas/compat/__init__.py)

```
https://github.com/sinhrks/japandas/pull/63
(変更内容https://github.com/sinhrks/japandas/pull/63/files)
のPRがこの問題を解決するみたいです。
詳しい原理はわからなかったのですが、pandasの仕様が変わったせいかと思っています。
wrapperのつらいところだと思いました。

## 作業内容
適当な場所にPRコードをcloneする。
(2020/1/5にcloneしました。)

```
cd ~/work
git clone -b si https://github.com/simaki/japandas.git
```
site-packageのjapandasを消す。
(自分の場合は/home/myname下にvenvで環境を作りました。各自の環境で読み替えてください)

```
rm -rf /home/myname/env38/lib/python3.8/site-packages/japandas
```
コピーしてくる。

```
cp -r ~/work/japandas/japandas/ /home/myname/env38/lib/python3.8/site-packages
```
変更が更新されているか確認する。

```python:/home/myname/env38/lib/python3.8/site-packages/japandas/core/strings.py

#!/usr/bin/env python
# coding: utf-8

from __future__ import unicode_literals

from unicodedata import normalize

import pandas.core.strings as strings
```
となり、`from pandas.compat import PY3, iteritems, u_safe` がなくなっていますね。

ここで `import japandas` をしたらエラーが出たので、`matplotlib`と`mplfinance`をインストール。

ここまでやったら、import japandas できました。

```
In [9]: import japandas

```

## もっと賢い方法があったら教えて下さい
最初ローカルにインストールして、そのjapandasをsite-packageより優先して参照するみたいなやり方ができないか考えていましたがうまくできませんでした。
あまりlibをいじりたくないので。

この方法でもその他の方法でも良い方法があればぜひ教えて下さい。
お読みいただきありがとうございました。
Proxyに阻まれ、Pythonやpipで接続エラーになり、Retryされてしまう

自社開発環境はproxyサーバを介してネットワーク接続しているため、
ことあるごとにネットワークエラーになる。

例えばpipを実行時に単純に実行すると以下のようにRetryingが繰り返されます。

<pre>
C:\Users\thithi7110>pip install webdriver_manager
Collecting webdriver_manager
Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ConnectTimeoutError(<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at 0x0000000004144DA0>, 'Connection to pypi.python.org timed out. (connect timeout=15)')': /simple/webdriver-manager/
  Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ConnectTimeoutError(<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at 0x0000000004144EB8>, 'Connection to pypi.python.org timed out. (connect timeout=15)')': /simple/webdriver-manager/
  Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ConnectTimeoutError(<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at 0x00000000041824E0>, 'Connection to pypi.python.org timed out. (connect timeout=15)')': /simple/webdriver-manager/
Operation cancelled by user

</pre>

そこで実行時に

--proxy=<プロキシサーバ名>:<proxyポート> 
をつけて実行してみます。
ここでは以下の設定で実施しています。
プロキシサーバ名：proxy.hoge.co.jp
proxyポート:8080


```CMD
C:\Users\thithi7110>pip install webdriver_manager --proxy=proxy.hoge.co.jp:8080
Collecting webdriver_manager
  Downloading https://files.pythonhosted.org/packages/dd/3c/2e2d71aeb28ee73ecaf12b545542b082ca81c8c091bb05028c52c42696ce/webdriver_manager-2.4.0-py2.py3-none-any.whl
Collecting crayons (from webdriver_manager)
  Downloading https://files.pythonhosted.org/packages/5b/0d/e3fad4ca1de8e70e06444e7d777a5984261e1db98758b5be3e8296c03fe9/crayons-0.4.0-py2.py3-none-any.whl
Collecting requests (from webdriver_manager)
```

無事ダウンロードが始まりました。

pythonを実行する際には、以下のように、
http_proxyとhttps_proxyを設定したあとにpythoを実行すればうまくいきました。

set http_proxy=http://proxy.hoge.co.jp:8080
set https_proxy=https://proxy.hoge.co.jp:8080

```hoge.bat
rem proxy設定
set http_proxy=http://proxy.hoge.co.jp:8080
set https_proxy=https://proxy.hoge.co.jp:8080
python "fugafuga.py"
```
ReactでCan't perform a React state update on an unmounted component.の原因と解決


プログラミング開始7ヶ月目の者です。

ReactのクラスコンポーネントのcomponentDidMountについてです。

メソッド内でsetTimeoutの記述をしました。

```react
  // 表示される毎に実行
  componentDidMount() {
    setTimeout(() => {
      this.setState({ isVisible: !this.state.isVisible });
    }, 1000);
  }
```

それでsetTimeoutで値が切り替わる前に別のLink（Router）に飛ぶとエラーが出ました。

#エラー
<font color="Red">Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.</font>

#原因
componentDidMountしたのにunmountedされたまま、別のLinkに移った為です。
「マウントされないcomponentで<font color="Red">state</font>を更新しようとしています。<font color="Red">componentWillUnmount</font>でキャンセルしてね。」

#解決
componentWillUnmount用に変数とメソッドを追加し代入する。
これで別のページに移ったときにcomponentWillUnmountでキャンセルされます。


```react
  // unmount用の変数
  handle;

  // 変数に代入
  componentDidMount() {
    this.handle = setTimeout(() => {
      this.setState({ isVisible: !this.state.isVisible });
    }, 1000);
  }
  // unmount用メソッドを追加 引数に変数を入れる。
  componentWillUnmount() {
   clearTimeout(this.handle);
  }
```
<details><summary>修正サンプル。</summary><div>

```react
const props = {
  visible: {
    opacity: 1,
  },
  hidden: {
    opacity: 0,
  },
}
const Box = posed.div(props)

export default class Can extends React.Component {

  handle;

  state = {
    isVisible: false,
  };
  // mount
  componentDidMount() {
    this.handle = setTimeout(() => {
      this.setState({ isVisible: !this.state.isVisible });
    }, 1000);
  }
  // unmount
  componentWillUnmount() {
   clearTimeout(this.handle);
  }
  render() {
    return (
      <Box pose={this.state.isVisible ? 'visible' : 'hidden'}>出現</Box>
    );
  }
}
```

</div></details>


#参考
エラーで悩んでいた時に見つけた [記事](https://nekoniki.com/20200917_react_warning_unmounted_component) です。


以上です！
Macでブラウザタブの最速移動


* 左タブ移動 Cmd+Shift+[
* 右タブ移動 Cmd+Shift+]

他にも

* 戻る Cmd+[
* 進む Cmd+]
* 新規タブ Cmd + t
* 直近で消したタブの削除 Cmd + Shift + t
* タブを削除 Cmd + w
* 履歴 Cmd + y
* 検索 Cmd + l

大体のブラウザで動作します。そして、ターミナルなど色んなアプリで動作します。

Ctrl+Tabでも左タブ移動ができてすごく便利なのですが、Ctrl+Shift+Tabを押すときに小指でShift押して薬指でTab押すと、Ctrl押す指がなくて、小指と薬指の間にもう一つ指が欲しいってなってしまいます。
というわけで Cmd+Shift+[ に変えましょう。
【Unity】UI ToolkitのMouseDown・MouseUpの最小実装

[【Unity】UI ToolkitをランタイムUIとして使ってみる](https://qiita.com/ohbashunsuke/items/4037bb19c059884003aa)に引き続き、
Unityの次世代UIシステムにあたる**UI Toolkit**について調査していきます。

あくまで**ランタイムUI**として使う想定の検証です。

## 今回作るもの

マウス押下している時に色が変わるサンプルを作っていきます。
![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/47ed35e1-db25-80e0-d4a0-9660ab371bb8.gif)


## 環境

- Unity2020.2.0f1
- UI Toolkit 1.0.0-Preview.13

## PointerDownEventとPointerUpEventを使う

MouseDown・MouseUpに反応するVisualElementに対してイベントを登録**(RegisterCallback)**していきます。

uxmlファイルから見ていきます。

```xml:MouseDownUpTest.uxml
<ui:UXML xmlns:ui="UnityEngine.UIElements" editor-extension-mode="False">
    <ui:VisualElement name="container" style="height: 100%; width: 100%; background-color: rgba(255, 252, 0, 255);" />
</ui:UXML>
```
`container`という名前の`VisualElement`が1つだけ全画面に配置してあるシンプルな構成です。


## C#側からVisualElementにイベント登録

C#のソースコードです。

```csharp:MouseDownUpTest.cs
// _documentはUIDocumentのこと
var visualTree = _document.rootVisualElement;

// VisualElement : "conainer"をvisualTreeから検索して取得
VisualElement container = visualTree.Q("container");

// イベント登録
container.RegisterCallback<PointerDownEvent>(OnPointerDown);
container.RegisterCallback<PointerUpEvent>(OnPointerUp);
```
`VisualElement`であるcontainerを取得して、`RegisterCallback`メソッドでイベントを登録しています。


## コールバック先でイベントターゲットのVisualElementを取得する

```csharp:MouseDownUpTest.cs
// MouseUpしたら色を赤色にする
private void OnPointerDown(PointerDownEvent evt)
{
    var ve = (VisualElement) evt.target;
    ve.style.backgroundColor = Color.red;
}

// MouseUpしたら色を黄色にする
private void OnPointerUp(PointerUpEvent evt)
{
    var ve = (VisualElement) evt.target;
    ve.style.backgroundColor = Color.yellow;
}
```
ポイントは`(VisualElement) evt.target`の部分でVisualElementにキャストしているところでしょうか。公式サンプルがこうなってるので、それにならった形を取りました。

## EventSystem(UI Toolkit)が必ず必要

**「イベントが通知されないな〜？？」**

と思った時はEventSystemがシーンに配置してあるかチェックしてみましょう。
必ずシーンに1つ必要です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/a34b099c-af9d-2753-5c89-7ff5174d8242.png" width=240 />




## 最後に

以上UI ToolkitにおけるMouseDown・MouseUpの最小実装でした。
ソースコード全文は[Gist](https://gist.github.com/baobao/5d5204b55323cea4a930f03145edac9f)にアップしています。
Udemy ビジネスパーソンに贈る業務効率化大全 〜Google Apps Scriptによる業務の自動化〜 セクション12:業務効率化⑨：Web情報を可視化する（Webスクレイピング)

## Webスクレイピング・ワークフロー
**Webスクレイピング**とは、Webページなどから情報を取得すること。

### ワークフロー
1. GASを用いて、Webページから情報を取得する。
2. スプレッドシートに取得した情報を反映させる。

### 必要な知識
1. 外部ライブラリを読み込む方法(簡単に作業が出来る。)
2. Webスクレイピングを行う方法

##　外部ライブラリを読み込む
1. GAS内のリソースからライブラリを選択
2. 外部ライブラリ(M1lugvAXKKtUxn_vdAG9JZleS6DrsjUUV)をペーストし保存

## 入手したい情報を取得してくる
入手したい情報(今回ならば受講者数とレビュー数)を取得する。

```gas:gas
function scraping() {
  var url = 'https://scraping-for-beginner.herokuapp.com/udemy';
  var response = UrlFetchApp.fetch(url);
  var content = response.getContentText('UTF-8');
  
  var parser = Parser.data(content);
  
  var subscribers = parser.from('<p class="subscribers">').to('</p>').build();
  subscribers = Number(subscribers.split(':')[1]);
  
  var reviews = parser.from('<p class="reviews">').to('</p>').build();
  reviews = Number(reviews.split(':')[1]); 
  
  var today = new Date();
  return[today, subscribers, reviews];
}
```

## シートに書き込む

シートとGASを連携させ、`sheet.getEange`で情報を書き込む。

```gas:gas
function writeData(){
  var results = scraping();
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('データ');
  
  var lastRow = sheet.getLastRow();
  sheet.getRange(lastRow+1, 1, 1, 3).setValues([results]);
}
```

##最後に
洗練さんでインターン(Udemy ビジネスパーソンに贈る業務効率化大全 〜Google Apps Scriptによる業務の自動化〜 セクション12:業務効率化⑨：Web情報を可視化する（Webスクレイピング))です。
[Udemy ビジネスパーソンに贈る業務効率化大全 〜Google Apps Scriptによる業務の自動化〜 セクション12:業務効率化⑨：Web情報を可視化する（Webスクレイピング)](https://www.udemy.com/course/gas_for_operational_efficiency/learn/lecture/17126720#notes)

最後に
現在ここでインターンしています。
まだまだ駆け出しですが頑張ります！やる気は人一倍です！
[洗練](https://senren.work/)
Djangoで時刻をユーザーの地域（UTC）に合わせて表示させる

<b>django-tz-detect</b> を使う。 （ソースコードは[こちら](https://github.com/adamcharnock/django-tz-detect)）
2019年にリリースされたオープンソースライブラリで、MITライセンス適用済。
＜実行環境＞
Python：3.7.4　Django：2.2.17

###１．ライブラリのインストール

```python
pip install django-tz-detect
```

###２．setting.pyを編集

####INSTALLED_APPSの末尾に以下を追加

```python:setting.py

INSTALLED_APPS (
    'tz_detect',#追加
)

```

####TEMPLATESに`'django.template.context_processors.request'`があるか確認（なければ追加）

```python:setting.py
TEMPLATES = [
    {
        ...
        'OPTIONS': {
            'context_processors': [
                ...
                'django.template.context_processors.request',#なければ追加
            ],
        },
    },
]
```

####MIDDLEWAREの末尾に`tz_detect.middleware.TimezoneMiddleware`を追加

```python:setting.py

MIDDLEWARE = (
    'tz_detect.middleware.TimezoneMiddleware',#追加
)
```

###３．url を追加する

```python:urls.py
urlpatterns = [
    url(r'^tz_detect/', include('tz_detect.urls')),#追加
]
```

###４．HTMLの編集

####先頭に`{% load tz_detect %}`、bodyタグ内に`{% tz_detect %}`を追加
この時、`{% tz_detect %}`は読み込みの関係で\</body>の直前に記述するのが望ましい。

```html:base.html
{% load tz_detect %}
<head></head>
<body>
{% tz_detect %}
</body>
```

タイムゾーンの設定を変更して、ブラウザを上げなおして完成。
（反映まで１～２分かかることもある）
ssh先 & dirを指定→pecoで選んだfileをscpする

## 動作環境
- pecoが入ってる
- rubyが入ってる
- 他にもあるかも

```zsh
function scp_file {
    ssh -qt $1 "QUOTING_STYLE=literal ls -1 $2" > /tmp/lsfiles

    # peco で選択した文字列をrubyに渡してshell safeにする
    valid_file_name=$(cat /tmp/lsfiles | peco | ruby -rshellwords -e "print(Shellwords.escape(gets.chomp))")

    scp "$1":"$2/$valid_file_name" $3
}
```

`scp_file remove_host_name remote_host_path client_path`
で実行可能。


## 背景
色々エスケープしないとscpできないファイル名(記号とかスペースとか)のものをscpしたいことが多かった
[Shellwords.escape](https://docs.ruby-lang.org/ja/latest/method/Shellwords/m/shellescape.html) 君の存在を知ってしまった
もっといい方法あったら誰かがコメントしてくれると思った
LaravelのユニットテストでDBにないエラーを明確にする

### Problem

When `seeInDatabase` asserting was failed, I can’t not known where the path of  properies is not match.

Example: With bellow test, I will receive the bellow message.

##### Test code:

```php
    $this->seeInDatabase('les_knowledge', [
        'lesson_id' => $lesson->id,
        'number' => 1,
        'content_en' => '~ years old DIFFFFFFFFFF',
        'explanation_en' => 'In Japan, you are born as a 0 year-old and turn 1 on your first birthday.',
    ]);
```

##### Test result:


```javascript
Unable to find row in database table [les_knowledge] that matched attributes
    [{
        "lesson_id":98,"number":1,
        "content_en":"~ years old DIFFFFFFFFFF",
        "explanation_en":"In Japan, you are born as a 0 year-old and turn 1 on your first birthday."
    }]
```

*It is hard to find where is the path don’t match.*

### Solution
Create a function likes a bellow.

```php
    function seeInDatabaseAndHasProperties($table, array $filter, array $properties, $connection = null){
        $this->seeInDatabase($table, $filter, $connection);
        $model = (array)DB::table($table)->where($filter)->first();
        $this->assertEquals($properties, Arr::only($model, array_keys($properties)));
    }
```

##### Test code will be:

```php
    $this->seeInDatabaseAndHasProperties('les_knowledge',
    [
        'lesson_id' => $lesson->id,
        'number' => 1,
    ], [
        'content_en' => '~ years old DIFFFFFFFFFF',
        'explanation_en' => 'In Japan, you are born as a 0 year-old and turn 1 on your first birthday.',
    ]);
```

##### Test result will be:

```php
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
Array (
    -    'content_en' => '~ years old DIFFFFFFFFFF'
    +    'content_en' => '~ years old'
    'explanation_en' => 'In Japan, you are born as a 0...thday.'
)
```
*Now you can easily see which properties don’t match.*
Original post is: https://khoinv.com/post/639359603705020416/clear-errors-not-found-in-the-database-laravel