OmniAICreator/Qiita-1.07M huggingface dataset:
​Python備忘録～個人的に興味を持った点～

# はじめに

なんちゃってなPythonの使いっぷり[^なんちゃって]に危機を感じて、現在、「Python 3 エンジニア認定基礎試験[^Python 3 エンジニア認定基礎試験]」の合格を目標として学習中の @daikikatsuragawa です。本記事では、Pythonの学習を通して、個人的に興味を持った点を備忘録として紹介します。気まぐれで随時更新、編集します。ご了承ください。

[^なんちゃって]: データ分析に取り組んでいた学生時代、Pythonを用いて12時間かかる計算を実施した。そのことを先輩に伝えたら「Pythonにはこんな書き方があって…」とアドバイスをいただき、その計算が10分くらいで完了するようになった。それくらい「Python」自体に疎い。
[^Python 3 エンジニア認定基礎試験]: [Python 3 エンジニア認定基礎試験](https://www.pythonic-exam.com/exam)

# 個人的に興味を持った点

### インタプリタを終了するコマンド

```console
quit()
```

### アクティベート状態から抜けるコマンド

```console
deactivate 
```

### 冪乗の計算

```py
3 ** 2
```

### マルチバイト文字（全角文字）を変数として使用可能

ただし、推奨はされていない。

```py
日本語 = 'JAPANESE'
```

### 異なるデータ型の結合は不可能

以下のコードはエラーとなる。

```py
'hoge' + int('1')
```

言語によってはできそうであるがPythonではできない。（JavaScriptやJavaではできるようだ[^あえて言うほどではない 数値 ⇔ 文字列変換 2019年人気プログラミング言語トップ10編 | TECHSCORE BLOG]。）
[^あえて言うほどではない 数値 ⇔ 文字列変換 2019年人気プログラミング言語トップ10編 | TECHSCORE BLOG]: [あえて言うほどではない 数値 ⇔ 文字列変換 2019年人気プログラミング言語トップ10編 | TECHSCORE BLOG](https://www.techscore.com/blog/2019/12/20/converting-between-numbers-and-strings-2019/)

### インデックスに負の値を指定すると末尾からの位置を示すことが可能

末尾は−1から順に、−2、−3…となる。範囲指定外の値を指定するとエラーが生じる。

```py
日本語 = 'JAPANESE'
print(日本語[-6])
```

```console
P
```

### 文字列はイミュータブル（変更不可）

リストのように指定した位置に値を代入できない。

※リストはミュータブル（変更可）

### formatによって文字列（数値）の結合が可能

```py
my_name = 'hoge'
your_name = 'fuga'
message = 'My name is {}. Your name is {}.'.format(my_name,your_name )
print(message)
```

```console
My name is hoge. Your name is fuga.
```

### リストに複数の型を混在して格納可能

```py
list = ['Python', 1 ]
```

ただし、並び替えを試みるとエラーが生じる。

### 位置引数

複数の引数を関数に渡す場合、引数の位置を入れ替えれば結果も変わる。

### 可変長引数

引数の数が可変。

### 複数の変数に複数の値を同時に代入

変数および値をカンマ`,`で区切ることで複数の変数に複数の値を同時に代入できる。

```py
a, b = 1, 2
```

### 数値の入れ替え

```py
a, b = 1, 2
a, b = b, a
```

他の言語でやるようなtempという変数を用意して…というものがいらない。

### in 演算子

```py
if 'a' in ['a','b','c']:
    print('hoge')
```

### 何もしないpass文

```py
def func():
    pass
```

何もしない`pass`文はたまに役に立つ。
    
### PEP8

Pythonコードのコーディング規約[^はじめに — pep8-ja 1.0 ドキュメント]。以下に例を示す。

- インデント＝スペース4つでタブはNG
- 1行79文字（全角39文字）

[^はじめに — pep8-ja 1.0 ドキュメント]: [はじめに — pep8-ja 1.0 ドキュメント](https://pep8-ja.readthedocs.io/ja/latest/)

### delとスライスを用いた要素の削除

以下のコードの場合、インデックス2〜4（5−1）の要素が削除される。

```py
list = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']
del list[2:5]
print(list)
```

```
['A', 'B', 'F', 'G', 'H', 'I', 'J', 'K']
```

# おわりに

本記事では、Pythonの学習を通して、個人的に興味を持った点を備忘録として紹介しました。もし、なにかございましたら、コメントなどをいただければ幸いです。

（2019年1月9日追記）
以下の記事に掲載していただきました！ありがとうございます！
- [【Python】Qiita 週間ストック数ランキング【自動更新】（2020年1月9日 00時00分更新 ）](https://qiita.com/kamata1729/items/eaf1d7b945b3a61a4fdd#_reference-2d95e1503fbd4732d077)
- [【毎日自動更新】Qiitaのデイリーストックランキング！ウィークリーもあるよ（2020年1月9日 00時22分更新 ）](https://qiita.com/takeharu/items/bb154a4bc198fb102ff3#_reference-05e2f96398a49d11217e)
- [【Python】Qiita 週間ストック数ランキング【自動更新】（2020年1月9日 13時01分更新 ）](https://qiita.com/kou_pg_0131/items/01127f188250a2d68dbf#_reference-887e78d18b45b0544e89)

# 参考

- [Pythonエンジニア育成推進協会監修 Python 3スキルアップ教科書](https://www.amazon.co.jp/o/ASIN/4297107562/gihyojp-22)
- [DIVE INTO EXAM](https://exam.diveintocode.jp/exam#exam-list)
Android HCE 調査メモ（その１）


# 目的
AndroidのHSEのサンプルを実行して、動作確認してみます。

# 環境
今回は以下の機種で動作確認しました。
#### Android開発環境
- ビルド環境
  - Android Studio 3.5.3

#### 端末
- 1台目
  - Sony SO-3L
  - Android 9.0 (API level 28)
- 2台目
 - Sharp SH-03J
 - Android 7.1.1 (API level 25)


# HSEについて
まずは、前提としてHCEについて説明します。

正式なドキュメントは以下を参照してください。
[ホストベースのカード エミュレーションの概要](https://developer.android.com/guide/topics/connectivity/nfc/hce)

簡単な説明をすると、Android上でユーザーの任意のアプリとNFCリーダとの通信を実現するための仕組みです。
通常、NFC通信はAndroidアプリまで通信が届きません。
NFCリーダからの通信は、通常はセキュアエレメントとの通信で完結します。
しかし、HCEの仕組みにより、NFCリーダーとAndroidアプリの直接通信が可能となります。

## 通信先アプリの選択方法について
通常はセキュアエレメントとの通信を行うと説明しましたが、それを任意のアプリにとの通信に切り替えるためには、どうすればよいのでしょうか？
アプリ側はAndroid OSに対し、Application ID (AID)を指定してServiceを登録します。
カード検知だけではアプリには通知は行きません。
カードリーダ側は検知後にApplication ID (AID)を指定して通信することで対象のアプリとの通信を開始します。
AID選択後の通信は Application Protocol Data Units（APDU）のプロトコルで行います。
AIDで選択したあとはAPDUでの通信のみの規定のみが決まっており、APDUプロトコル上での通信内容はアプリで自由に設定することになります。


## 対応範囲について
HCE（TypeA）はAPI level 19 ( Android 4.4 ) から実装されました。
詳細は以下を参照してください。

- [Android KitKat](https://developer.android.com/about/versions/kitkat?hl=ja)
- [CardEmulation](https://developer.android.com/reference/android/nfc/cardemulation/CardEmulation)

Type-FでのHCEの正式対応は API level 24 ( Android 7.0 ) 以降の対応となっています。

- [NfcFCardEmulation](https://developer.android.com/reference/android/nfc/cardemulation/NfcFCardEmulation)


# HSEの動作確認
まずは、HCEのサンプルのアプリをビルド、インストールします。

## 環境
今回は以下の機種で動作確認しました。

- 端末
  - Sony SO-3L
  - Android 9.0 (API level 28)

他の環境では今回確認していませんが、もっと前のVersionでも問題はないとは思います。

## Androidアプリ
以下のURLのソースを元にアプリを作成します。
https://github.com/googlearchive/android-CardEmulation

ソースコードを確認したところ、AIDは「F222222222」となっているようです。
`private static final String SAMPLE_LOYALTY_CARD_AID = "F222222222";`

ビルドできたらインストールして起動確認しておきます。




# HSE通信確認アプリ
対向側のReader側のアプリを作成、インストールします。

## 環境
今回は以下の機種で動作確認しました。

- 端末
 - Sharp SH-03J
 - Android 7.1.1 (API level 25)


## Androidアプリ
以下のURLのソースを元にアプリを作成します。
https://github.com/googlearchive/android-CardReader

こちらもソースコードを確認したところ、AIDは「F222222222」となっているようです。
`private static final String SAMPLE_LOYALTY_CARD_AID = "F222222222";`

# 動作確認
両方のアプリを起動し、通信を実行してみます。
CardReaderのLogを確認し、データ受信できていることを確認します。



# 次回
PCとの通信を確認します。
[Android HCE 調査メモ（その２）](https://qiita.com/tkhr68000/items/0ac45bfa42e03e04b44f)
time.Time型のSliceを昇順ソートしたい

`time.Time`型のSliceを昇順ソートするにはどのようにすればよいでしょうか? 

__まずGoのバージョンが1.8以降の場合は`sort.Slice`を使うのがもっとも簡単です。__

```go:main.go
package main

import (
	"sort"
	"time"
	"fmt"
)

func main() {
	times := []time.Time{
		time.Date(2020, 1, 4, 0, 0, 0, 0, time.Local),
		time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
		time.Date(2020, 1, 5, 0, 0, 0, 0, time.Local),
		time.Date(2020, 1, 2, 0, 0, 0, 0, time.Local),
		time.Date(2020, 1, 3, 0, 0, 0, 0, time.Local),
	}

	sort.Slice(times, func(i, j int) bool {
		return times[i].Before(times[j])
	})

	for _, t := range times {
		fmt.Println(t)
	}
}
```

これを実行すると、確かに昇順ソートできていることが確認できます。

```
$ go run main.go
2020-01-01 00:00:00 +0900 JST
2020-01-02 00:00:00 +0900 JST
2020-01-03 00:00:00 +0900 JST
2020-01-04 00:00:00 +0900 JST
2020-01-05 00:00:00 +0900 JST
```

__ただし、お使いのGoのバージョンが1.8未満の場合は、`sort.Slice`は利用できません。すこしまどろっこしいのですが、この場合は`sort.Interface`を実装した型を利用する必要があります。__

サンプルコードは次の通りです。

```go:main.go
package main

import (
	"fmt"
	"sort"
	"time"
)

type Times []time.Time

func (t Times) Len() int {
	return len(t)
}

func (t Times) Less(i, j int) bool {
	return t[i].Before(t[j])
}

func (t Times) Swap(i, j int) {
	t[i], t[j] = t[j], t[i]
}

func main() {
	times := []time.Time{
		time.Date(2020, 1, 4, 0, 0, 0, 0, time.Local),
		time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
		time.Date(2020, 1, 5, 0, 0, 0, 0, time.Local),
		time.Date(2020, 1, 2, 0, 0, 0, 0, time.Local),
		time.Date(2020, 1, 3, 0, 0, 0, 0, time.Local),
	}

	sort.Sort(Times(times))

	for _, t := range times {
		fmt.Println(t)
	}
}
```

これを実行すると、`sort.Slice`と同じように昇順ソートされていることがわかります。

```
$ go run main.go
2020-01-01 00:00:00 +0900 JST
2020-01-02 00:00:00 +0900 JST
2020-01-03 00:00:00 +0900 JST
2020-01-04 00:00:00 +0900 JST
2020-01-05 00:00:00 +0900 JST
```
Q3.A1セルの値を別のセルにコピーするには？

今回は、A1セルのデータを別のセルにコピーするマクロを作っていきます。
コピー先のセルはA3セルとします。

2通りの解答例をご紹介します。
以下となります。

```VB
Sub Q3_Answer_1()
    Range("A3").Value = Range("A1").Value
End Sub

Sub Q3_Answer_2()
    tmp = Range("A1").Value
    Range("A3").Value = tmp
End Sub
```

あえて、２つ作っています。


まず、1つ目のQ3_Answer_1()について。
こちらは直接、A1セルの値をコピーしているパターンです。
Q2で作ったマクロをちょいといじるだけのシンプルな構成です。
一番手っ取り早く書くならこれです。


続いて2つ目のQ3_Answer_2()。
こちらは、tmpという変数を用意して、そこに一旦、
A1セルのデータを格納しています。

なぜ、わざわざ変数に格納するという一手間を加えているのでしょうか？



たとえば、10個のセルに今回のようにA1セルの値をコピーしようとするとします。
Q3_Answer_1()のような書き方をすると、後で変えようとした時に、少々手間が発生します。

あとから、A1セルではなくて、やっぱりB1セルの値をコピーする必要が出てきたと
想定してみてください。

その場合、10箇所変更する必要が出てきます。
(A1をB1に変える)

ところが、一旦、最初に変数に格納しておくことによって、
後で変える場合の修正箇所は1か所で済むようになります。

分かりやすく数が多いバージョンを作ってみました。

![Q3-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560479/b5cdbcb5-2d8d-6496-7ea4-292bafacc54e.png)


この場合、後者はtmpに代入する箇所を変えるだけで対応することができますね。


今回のように非常にシンプルなマクロの場合は、単純に置換すれば済んだりしますが、
ある程度の規模のコードになってくると、単純に置換できない場合もあります。
ぜひ、変数に格納するというどういう利便性があるかというのは理解しておくといいですね。
JQueryを使わずjsとcssを使って背景画像のスライドショー 作成

JSの勉強を兼ねて、JQueryを使わずにJSとCSSで背景画像のスライドショーを作成しました。
※まだまだ勉強中なのでミス等あればコメントで教えていただければありがたいです。

####結果
まずは結果を表示します。こんな感じに仕上がりました。

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="js,result" data-user="shimamar" data-slug-hash="VwYQGZo" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="slideshow">
  <span>See the Pen <a href="https://codepen.io/shimamar/pen/VwYQGZo">
  slideshow</a> by RS (<a href="https://codepen.io/shimamar">@shimamar</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

####コード
コードを記載します。処理に直接関係ないところは省略しております。

```test.html
<div id="slideshow">
  <h1>Hello!</h1>
</div>
```
```test.css
div{
  height: 300px;
  width: 500px;
  transition: background-image 2.5S ease; /*背景画像をゆっくり変化させる*/
  background-image: url("最初に表示する画像パス");
}

h1{
  font-size: 30px;
  color: white;
  text-align: center;
  line-height: 300px;
}
```
```test.js
//スライドショー で表示させる画像パスを変数に格納
var setImage = [
  "画像01パス",
  "画像02パス",
  "画像03パス"];

//カウンターの初期値設定
var counter = 0;

//設定した画像パスをid="slideshow"のbackground-imageに設定する、繰り返す
function slideimage(){
    //カウンターが設定画像数より大きいか確認
    if( counter >= (setImage.length-1)){
        //カウンターを初期値に戻す
        counter = 0;
    }
    //背景画像を設定
    document.getElementById( "slideshow" ).style.backgroundImage = "url(" + setImage[counter] + ")";
    //カウントアップ
    counter++;
}

//3秒ごとに背景画像を切り替える
setInterval("slideimage()",3000);
```

####ポイント
cssの `transition` プロパティの設定時間を
JSの　`setInterval` の設定時間より**短く**したこと

同じにしてしまうとタイミングが重なってしまうせいなのか、
`transition` プロパティがうまく効かずにはっきりと切り替わりが起こってしまいます。

```
//JS
setInterval("slideimage()",3000); //3秒

//css
transition: background-image 2.5S ease; //2.5秒
```

####まとめ
ネットで検索するとスライドショー の作成方法はたくさん出てくるのですが主にJQueryで作成されている方が多く、自分の基礎勉強のためにもJSで実装してみました。

ただ、ゆっくり表示させるところがなかなかうまくいかず苦戦しました。
そして `background-image` プロパティでは無く <**img**>タグで画像指定した方が良かったのでは。。と振り返って思ったりもします。

まだまだ納得のいかない・わからないところもあるので、勉強を重ねてバージョンアップできればと思います。
Why PHP Array!?!? バグを生みそうなPHPの配列の仕様

#すべてが１になる

```php
<?php
$array = array(
    1    => "a",
    "1"  => "b",
    1.5  => "c",
    true => "d",
);
var_dump($array);
?>
```

この結果ってなんになると思います？

```
array(1) {
  [1]=>
  string(1) "d"
}
```

Why PHP Array!?
なんでこうなるの!?
どうやら「1」「"1"」「1.5」「true」は、すべて「1」と見なされるみたい。
結局の所

```php
<?php
$array = array(
    1  => "a",
    1  => "b",
    1  => "c",
    1  => "d",
);
var_dump($array);
?>
```

ってことらしい。
まぁ`1==true`は成り立つしね、まぁまぁ。
「1.5」は意味わからんけど。

#マイナス思考

```php
<?php
$array = array(
    100   => -100,
    -100  => 100,
);
var_dump($array);
?>
```

この結果ってなんになると思います？

```
array(2) {
  [100]=>
  int(-100)
  [-100]=>
  int(100)
}
```
Why PHP Array!?!?
これはキッチリわかれるんかい！？！？
じゃぁさっきの「1.5」もキーとして認めてあげて！！

#はい順番にならんで～

```php
<?php
$array = array(
         "a",
         "b",
    6 => "c",
         "d",
);
var_dump($array);
?>
```

この結果ってなんになると思います？

```
array(4) {
  [0]=>
  string(1) "a"
  [1]=>
  string(1) "b"
  [6]=>
  string(1) "c"
  [7]=>
  string(1) "d"
}
```

Why PHP Array!?!?!?
そこに並ぶの！？！？！？
2になると思ったよ…
キーの指定がない場合は、最後のキーを参照して格納するみたい。

#俺はオンリーワンだから
```php

<?php
$array = array(
           "a",
           "b",
    'X' => "c",
           "d",
);
var_dump($array);
?>
```

この結果ってなんになると思います？

```
array(4) {
  [0]=>
  string(1) "a"
  [1]=>
  string(1) "b"
  ['X']=>
  string(1) "c"
  [2]=>
  string(1) "d"
}
```
Why PHP Array!?!?!?!?
「'X'」の次は「'Y'」じゃないの！？！？！？！？
あくまでキーの整数値を参照ということみたい。

#ゴーストインザシェル

```php
$array = array(1, 2, 3, 4, 5);

foreach ($array as $i => $value) {
    unset($array[$i]);
}

$array[] = 6;
print_r($array);
```

この結果ってなんになると思います？

```
array(1) {
  [5]=>
  int(6)
}
```

Why PHP Array!?!?!?!?!?
`unset()`で消したはずじゃ！？！？！？！？！？！？
彼らのゴーストはまだ消えていないんだね…。

#まとめ
PHPの配列って癖が強い気がする…。
他の言語ってどうなんだろう？
MySql5.6で Mysql2::Error: Specified key was too long; max key length is 767 bytesエラーが出る時の解決法

### Mysql2::Error: Specified key was too long; max key length is 767 bytesエラーの解決法
### MySql5.6以前のバージョンは[こちら](https://qiita.com/yoheiW@github/items/bcbcd11e89bfc7d7f3ff)の記事が詳しいです

- - -

参加した友人とのプロジェクトで以下のコマンドを叩いたところ

```bundle exec rake ridgepole:apply```

以下のエラーに遭遇しました。

```[ERROR] Mysql2::Error: Specified key was too long; max key length is 767 bytes```

どうやらmy.cnfファイルが無く、そのせいで文字コードがutf8mb4ではなくutf8になってしまっているのが原因のよう。

```
mysql> show variables like "chara%";
+--------------------------+----------------------------------------------------------+
| Variable_name      | Value                          |
+--------------------------+----------------------------------------------------------+
| character_set_client   | utf8                           |
| character_set_connection | utf8                           |
| character_set_database  | utf8                           |
| character_set_filesystem | binary                          |
| character_set_results  | utf8                           |
| character_set_server   | utf8                           |
| character_set_system   | utf8                           |
| character_sets_dir    | /usr/local/Cellar/mysql@5.6/5.6.43/share/mysql/charsets/ |
+--------------------------+----------------------------------------------------------+
8 rows in set (0.00 sec)
```

[上記でも紹介した記事](https://qiita.com/yoheiW@github/items/bcbcd11e89bfc7d7f3ff)を見ると、my.cnfファイルを以下のように編集すれば良いとのことでした。

```
[mysqld]
...
character-set-server=utf8mb4

[client]
default-character-set=utf8mb4
```

MySql5.6以前のバージョンはこれで上手くいくと思うのですが、5.6以降は以下のように編集しないとダメなようです。

```
[mysqld]
character-set-server=utf8mb4
innodb_large_prefix=1
innodb_file_per_table=1
innodb_file_format=Barracuda
innodb_file_format_max=Barracuda
[client]
default-character-set=utf8mb4
```
使うコマンドは以下。

```
touch /etc/my.cnf
vi /etc/my.cnf
mysql.server restart
```

自分の場合はこれで上手くいったので、同じエラーが出た方は試してみてください。
Nuxt×vue-property-decoratorでvalidateメソッドを実装する

# Nuxt×vue-property-decoratorでvalidateメソッドを実装する方法

そんなにあり得ないパターンかなとは思いますが、個人開発で色々試しているときに引っかかった＆いい具合のGoogle検索結果が出なかったのでメモ程度に。

## `@Component`デコレータ内に書く
一言で言えば、`@Component`デコレータに指定すればいいです。

```typescript:例えばこんな感じ.vue
@Component({
  components: {
    Form: () => import('~/components/organisms/Form.vue'),
  },
  validate ({ params }) {
    // 数値のカテゴリIDじゃないと404にする
    return /^\d+$/.test(params.categoryId)
  },
})
export default class Post extends Vue {
```

このように、`@Component`デコレータ内に実装すればいいだけの話だったのですが、うっかり`Post`クラス内に書いてしまって動かずに困惑しました。

## 雑感
`nuxt-property-decorator`も調べてみましたが、特段こちらが`validate`メソッドをサポートしているわけでもないんですね。
discordbotを作ってみた

#きっかけ
普段ローカルでseleniumとかpyautoguiでRPAを作って
つまらない仕事
手順が多くてヒューマンエラーが出る仕事を自動化しているのですが、オンライン上で動き続けていないとこの先諸々不便。
でもそこに至る道までが分からん。

Django,Flaskは触ってみたけれどまだよくわからないしdeployってなんぞやということで知人のTRPG用にdiscordbotで作って遊びつつ学習してみた。

[Pythonで実用Discord Bot(discordpy解説)](https://qiita.com/1ntegrale9/items/9d570ef8175cf178468f)
神がいらっしゃるので参考にしました。

###基本的な処理
```python:discord.py
略
if message.content == '/yagi':
    result = "めぇー"
    await message.channel.send(result)
```
これで基本的にはコマンドに対して返信を返すことができたと。
となれば/yagi　というコマンドに対して　めぇーと返信が返せるね。

で、あればダイスロールも
・コマンドを指定して
・処理書いて
・返す
で完了できますね。（素人考え）

###ダイスを振ってみる
```python:discord.py
略
    s = message.content
    dicecheck  = re.match('^/[1-9]{1}[D]', s)
    if dicecheck:
        dice = 1
    else:
        dice = 0
```
として/nDNと書かれたらダイスロールであることを判定して

```python:discord.py
略
    if dice > 0:
        await message.channel.send('いちたりなくなーれ！')
        i = 0
        count = int(message.content[1:2]) + 1
        dim = int(message.content[3:])
        lst = []
        for i in range(1, count):
             rand_num =  random.randint(1, dim)
             lst.append(rand_num)
        await message.channel.send(lst)
```
※nDNでnは1-9,Nは好きな数字というお約束。
と、かなり力技ですがn回、N面ダイスをぶん投げる処理を入れてみます。
randomって本当にランダムな数字が返ってくるの？というカルドセプト的視点はこの際置いておきます。

あ、ついでにいちたりなくなるおまじないもかけましょうね。

デプロイしてみた。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304820/7c1907c0-b3db-7b6d-0350-87560513f0c9.png)

うん、ふれてる。
というわけでここまでは問題なくできたので、herokuにdeployしたbotでseleniumが動くかなーと試してみる。

###seleniumを動かしてみる
```python:discord.py
略
    options = Options()
    options.binary_location = '/app/.apt/usr/bin/google-chrome'
    options.add_argument('--headless')
    options.add_argument('--disable-gpu')
    browser = webdriver.Chrome(options=options)
    browser.implicitly_wait(10)
```

結果的に言えばこれで行けました。(herokuにseleniumとchrome追加するのは別途必要)
後はfind_elementを頑張る感じで。

となれば、beautifulsoupも行けるよね？と

###beautifulsoupも試してみる
```python:discord.py
略
elif message.content == '/ゆれた':
    res = requests.get('http://www.jma.go.jp/jp/quake/00000000093.html')
    soup = BeautifulSoup(res.text, 'html.parser')
    result = soup.select_one('table.textframe').get_text(strip=True)
    await message.channel.send(result)
```
※サンプルに気象庁の地震情報を引っ張ってくる想定です。
これでセッション中に地震が来ても大丈夫！　慌てずに/ゆれた　と入れればわかるよ！
ゆれてないって返したいね。わかる。

後はブラウザとか開けると便利かなーと思ったのだけどwebbrowser.open_newではダメ（当然か…）
ということでここはdiscordさんのURL形式っぽいのがかかれたらURLにする、でごまかしましょう。
動けばいいねん！

###ブラウザを開きたい
```python:discord.py
略
elif message.content == '/検索':
    await message.channel.send("https://www.google.co.jp")
```

解決。筋肉は全てを解決する。


というわけで、全くherokuとかdeployとか分からなかった素人でもできたよ。Qiita最高か…

後はコマンド部分をファジーにするとか、それに対してする処理を入れていけば拡張はできますね。
私はTRPGやらないので何の機能がいるかとんと分かりませんが…。
django.db.utils.ProgrammingError: permission denied for table django_migrationsの対処法

`django.db.utils.ProgrammingError: permission denied for table django_migrations`のエラーの対処に苦戦したので書いておこうと思います。

このエラーが出たときpostgresqlのdjango移行を実行中に、接続ファイルで使用されているpostgresqlのユーザーに対して権限設定がなされてないことが原因みたいです。なのでpostgresqlのユーザーに権限を持たせようと思います。


コマンドから`psql -U postgres`でpostgresにログインします。

```
>psql -U postgres

ユーザ postgres のパスワード:
psql (12.1)
"help"でヘルプを表示します。

postgres=#
```

次に使用したいデーターベースにログインします。（database nameは使用したいデータベースを入れてください。）

```
postgres=# ¥c database name
データベース"database name"にユーザ"postgres"として接続しました。
database name=#
```

そして権限を持たせるために3つのコードを入力します。(usernameは使用しようとしているユーザ名に書き換えてください。）

```
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public to username;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public to username;
GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public to username;
```


これでpostgresqlのユーザーに対して権限を持たせることができました。
【WordPress】サーバ移転でNotFoundになる場合の解決策

#きっかけ
WordPressのサイトをサーバ移転したところ、グローバルナビがリンク切れになった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91280/1fc438b6-8c59-162a-4634-d2f5d3b1c0b9.png)

#対策
２ヶ所を調整する。
① httpd.conf や .htaccess で Require all granted 行を追加する。
.htaccess が使えるならサービス再起動不要なのでよい。

```httpd.conf
<Directory "/var/www">
    AllowOverride All
    Require all granted
</Directory>
# systemctl restart httpd などサービス再起動する。
```

```:.htaccess
    Require all granted
```


② WordPress のパーマリンク設定を開き、単に「変更を保存」ボタンをクリックする。
変更されない場合は、便宜上どれか選択肢を選んで設定保存してまた戻して設定保存する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91280/5ddc53da-6063-744c-7cb5-8f3bad7ab3c7.png)

以上。
kb_pythonをDockerやSingularityで使えるようにした

[Kallisto | Bustoolsのチュートリアル](https://www.kallistobus.tools/kb_getting_started.html)のページで使われているkbというコマンドがDockerHubに登録されてなさそうなので、登録してみた。

といっても、pipでkb_pythonをとってきて、すぐkbを使えるようにしたいだけなので、minicondaのイメージをベースとして、
https://hub.docker.com/r/continuumio/miniconda/tags
Dockerfileはこんな感じで作った。
https://github.com/kokitsuyuzaki/Dockerfiles/blob/master/kb_python/Dockerfile

DockerHub側で、koki/kb_pythonというレポジトリを作ってから、

```bash
docker login
docker build -t koki/kb_python .
docker tag koki/kb_python:latest koki/kb_python:0.24.4
docker push koki/kb_python
```

として、DockerHub側にプッシュした。

あとは、
https://kengotakimoto.com/post-2645/
の記事を参考に、GitHub側のDockerfileが変更されるたびに、ビルドテストするようにもした。

これにより、

```bash
docker pull koki/kb_python:0.24.4
docker run -ti koki/kb_python:0.24.4 kb -v
```

や

```bash
singularity pull docker://koki/kb_python:0.24.4
singularity exec kb_python_0.24.4.sif kb -v
```

のように、DockerやSingulairy越しに、すぐにkbコマンドが使えるようになった。
MySQLでカラムの値を使った like による部分一致検索

## 先に結論

MySQLでDBのカラムの値を使って部分一致検索をするやり方

コツは、

- concat関数を使って、`%(カラムの値)%` という文字列を作る
- カラムの値が NULL or 空文字だった場合は、検索しないようにする

## 例
### テーブル定義
```sql
create table user
(
   id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
   name VARCHAR(256) NOT NULL UNIQUE,
   public_profile VARCHAR(256)
)
```

### クエリ
```sql
select id
from user u
where u.public_profile like concat('%', u.name, '%')
  and ifnull(length(u.name), 0) > 0;
```
LiveDataを使わずにRxでPagingする

みなさんPaging使ってますか？

公式ドキュメントを見ると、LiveDataを使わずにRxJava2を使用しても良いということだったのですが、いまいちどのように実装するのかがよくわからず試行錯誤した結果を書き残したいと思います。

##前提
- 以下の条件の方々を読者と仮定します
    - AAC Pagingがどのようなものか大体わかる
    - これからPagingを導入しようと思っている
    - LiveDataは導入していない


##やること
####AndroidXの場合
>***DataSourceFactory#toObservable*でPagedListのObservableを作成する**
>or
>***LivePagedListBuilder*を使うかわりに*RxPagedListBuilder*を使う**




####AndroidXじゃない場合
>***LivePagedListBuilder*を使うかわりに*RxPagedListBuilder*を使う**

まず、PagingのRxサポートはオプショナルなのでbuild.gradleに追加で記述が必要になります。
また、AndroidXでtoObservableしたい場合はktxも入れる必要があります

```gradle

implementation "androidx.paging:paging-runtime:$paging_version"
implementation "androidx.paging:paging-runtime-ktx:$paging_version"
implementation "androidx.paging:paging-rxjava2:$paging_version"
implementation "androidx.paging:paging-rxjava2-ktx:$paging_version"   
```

AndroidXでtoObservableを使う場合は公式のドキュメントを見れば困ることは特にないと思います。
RxPagedListBuilderを使用する場合はFactoryクラスとConfigをBuilderに突っ込めばOKです

```kotlin

    lateinit var pagedList: Observable<PagedList<YourObj>>

    fun setupPage() {
        val config = PagedList.Config.Builder()
                .setInitialLoadSizeHint(YOUR_LOAD_SIZE)
                .setPageSize(YOUR_PAGE_SIZE)
                .setEnablePlaceholders(false)
                .build()
        //DataSource.Factoryの継承クラス
        val factory = YourFactory() 
        pagedList = RxPagedListBuilder(factory, config)
                .buildObservable()
    }
```

こうしてできたObservableをサブスクライブして、onNextに入ってくるPagedListをsubmitしていくという寸法です。

##ハマったところ
###NestedScrollView内のRecyclerViewをPagingするとバグる
私がやった時はヘッダーが必要だったので、以下のようなレイアウト構成で実装しようと思っていました

- NestedScrollView
    - LinerLayout
        - TextView < これがヘッダー
        - RecyclerView < ここでPaging

ところが、このようにすると一度に全てのデータを読み込み、表示しようとしてしまうので動作が極端に重くなります。
PagingのSampleに同様のissueが建てられていましたが、どうも解決しなさそうです（RecyclerViewの仕様？）
うまくPagingを動作させつつスクロール部分の表示を要素にとって変えたい時には、サボらずに一つのRecyclerViewでViewHolderを切り替えて表示を出し分ける必要があるようです。


###RxPagedListBuilderのSchedulerの扱い
RxPagedListBuilderで作成したObservableは特別*subscribeOn*と*observeOn*を記述する必要がありません。（別途設定は可能  [ドキュメント](https://developer.android.com/reference/androidx/paging/RxPagedListBuilder.html)参照）
気を付けなければならないのはDataSourceがBuilderで設定したSchedulerのスレッド配下であるということです。
私の場合、DataSource内で通信して追加データを取得する際に、RetrofitでSingleを返すようにしていましたが、ワーカースレッドの入れ子状態になるために正常に結果が返ってこない自体に陥りました。
そのため、DataSource内の通信ではCallを使用することで回避しました。
初心者によるプログラミング学習ログ 207日目

#100日チャレンジの206日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

207日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>207日目<br><br>疲れていたので、さくっとできるprogateでjqueryとcss上級編、Ruby<br>寝落ちしました<a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a> <a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a> <a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1214635139294064640?ref_src=twsrc%5Etfw">January 7, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
MongoDB didn’t  work for openssl@1.1

## 背景

opensslのバージョンを1.1にアップデートしたら、MongoDBが動かなくなりました。↓このようなエラーが出ました。

```sh
$ mongod --version                                                                   
dyld: Library not loaded: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib
  Referenced from: /usr/local/opt/mongodb@3.2/bin/mongod
  Reason: image not found
```

念のため現在入っているopensslを確認

```
$ brew list openssl                                                                       
...
...
...
/usr/local/Cellar/openssl@1.1/1.1.1d/lib/libssl.1.1.dylib
...
...
...
```

## 解決方法
解決方法は２つあります。
１つ目は、opensslのバージョンを下げること
２つ目はmongodbバージョンを上げること

### 方法１ down the openssl version

``` sh
brew update && brew upgrade
brew uninstall --ignore-dependencies openssl;brew uninstall --ignore-dependencies openssl;brew install https://github.com/tebelorg/Tump/releases/download/v1.0.0/openssl.rb
```

バージョンが下がったことを確認

```
$ brew list openssl                                                                        
...
...
...
/usr/local/Cellar/openssl/1.0.2t/lib/libcrypto.1.0.0.dylib
...
...
...
```

MongoDBのバージョンを確認

```sh
$ mongod --version                                                                   
db version v3.2.21
git version: 1ab1010737145ba3761318508ff65ba74dfe8155
OpenSSL version: OpenSSL 1.0.2t  10 Sep 2019
allocator: system
modules: none
build environment:
    distarch: x86_64
    target_arch: x86_64
```

### 方法2 upgrade MongoDB version

`openssl@1.1`であることを確認

```
$ brew list openssl                                                                       
...
...
...
/usr/local/Cellar/openssl@1.1/1.1.1d/lib/libcrypto.1.1.dylib
...
...
...
```

じゃなかったら、`brew install openssl@1.1` を実行

```sh
$ brew upgrade mongodb                                                               
Error: No available formula with the name "mongodb"
```

おっと、Homebrew CoreからMongoDBが消えたからmongodbのバージョンはアップできないらしい。。。

しかし、↓これで解決できた！やったね！！

```
$ brew tap mongodb/brew
$ brew install mongodb-community@4.2
```

<font color="Red">※注意</font>
<font color="Red">既存のmongodbパスを書き換えないと動かないです!!!!</font>
なので、`~/.zshrc(私の場合)`にて、`export PATH="/usr/local/opt/mongodb-community@4.2/bin:$PATH"` を書き換えてください

mongodbバージョンを確認

```sh
$ mongod --version                                                                                      
db version v4.2.2
git version: a0bbbff6ada159e19298d37946ac8dc4b497eadf
allocator: system
modules: none
build environment:
    distarch: x86_64
    target_arch: x86_64
```

ちゃんとバージョンアップされたのが確認できた！

## 感想

`openssl`のバージョンを下げてもMongoDBは使えますが、`openssl`に依存しているライブラリは同じ`dyld: Library not loaded:`エラーが発生します。

なので、**方法2**の処理が妥当だと思います。
ripgrep でマッチしない行を出力する

# 問題

ripgrep という高速に動作する検索コマンドがある。これを使って日常的にソースコードを調べているが、ときどき検索したい文字が、他の文字の部分文字列になっていて、余分な行が出力されてしまうことがある。たとえば `unit` を検索したいのだが `unit_id` がたくさんヒットしてしまう、といった事が起こる。

ripgrep では正規表現が有効だが、否定先読みはできない。

https://github.com/BurntSushi/ripgrep/issues/188

# 解決策

最も簡単な方法は `--invert-match` (短縮形は `-v`)を使うこと。たとえば、下記のようにする。

```
rg unit | rg -v unit_id
```

ただし、色付けやグルーピングの情報が落ちてしまう。しかも、二つとも登場する行がヒットしなくなってしまう。例えば下記。

```
unit = unit_id
```

もっと良い方法があるかもしれない。
ag をインストールしているなら否定先読みができるらしい。 ag を使うべきか。
golangで文字列からsha256でハッシュ化する方法

# ハッシュ化
特定の文字列の不可逆変換をする処理ですが、golangではどう書くでしょうか。
結論。以下のようにしてできます。

```golang

package main

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
)

func main() {
	s := "Hello, World"
	b := getSHA256Binary(s)
	h := hex.EncodeToString(b)
	fmt.Println(b) // [3 103 90 197 63 249 205 21 53 204 199 223 205 250 44 69 140 82 24 55 31 65 141 193 54 242 209 154 193 251 232 165]
	fmt.Println(h) // 03675ac53ff9cd1535ccc7dfcdfa2c458c5218371f418dc136f2d19ac1fbe8a5
}

func getSHA256Binary(s string) []byte {
	r := sha256.Sum256([]byte(s))
	return r[:]
}
```

https://play.golang.org/p/XbpBCe_sGop

せっかくなので、一緒に使われることの多いhexへの変換も載せておきます
AndroidStudioのDesignタブにAttributeが表示されない

記事にするのも馬鹿らしい話なんですが、同じ所で躓いて時間の無駄遣いをする人が生まれないように戒めを込めて書いておきます。

#戒め
　AndroidStudioで追加ダウンロードが必要なコンポーネントを使う時は、一度AndroidStudioを再起動する。そうしないと、DesignタブにAttributeが表示されなかったり、Textタブで予測変換が効かなくなります。

##問題発生時の状況
　[TextInputLayout](https://qiita.com/hkurokawa/items/baf0dca930a32a5a7f92)なんて便利な物を知って、意気揚々とダウンロードし配置しました。<img width="407" alt="ダウンロードするじゃん.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455591/5c47b994-f420-5dfa-44a0-a02d63e68a24.png">
※画像はGridLayoutのものですが、やっていることは一緒です。

　さて、IDを割り振…Attributeが表示されていない…？？？
<img width="2048" alt="Attibuteでないじゃん.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455591/8958b760-2d88-3052-0673-3518f17a57a7.png">

　それなら、Textタブで…予測変換が出てこない？？？
<img width="2048" alt="予測変換でないじゃん.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455591/70f3066e-3fb4-093f-293f-91d20d0c65d4.png">


※ちなみに画像ははめ込み合成なので、何か変な部分があっても気にしないください。
##解決方法
　検索をかけてみたり、TextInputLayoutのドキュメントを読んでみたものの、特に何も記載されておらず…。そこでとりあえずAndroidStudioのタスクを切り、再起動してみたところ直りました。詳しくはわかりませんが、ダウンロードされたコンポーネントのデータは、再度読み込まないと表示されないんでしょうね…。10分も無駄にした悲しさ。
読書会「プログラマが知るべき97のこと」 #1 プロローグ

# 1. はじめに
単なる社内勉強会の記録。
実施したからには記録を残しておこうと思い投稿することにした。
#2.概要
みんなで[「プログラマが知るべき97のこと」](https://%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%81%8C%E7%9F%A5%E3%82%8B%E3%81%B9%E3%81%8D97%E3%81%AE%E3%81%93%E3%81%A8.com)を読み意見交換をする会を、1年間通して開催する。

#3.背景
**部署の所属メンバーで何か勉強会を始めようと思ったから**

2019/10から弊社の部署が新体制となって、メンバーが変わったことをきっかけに、何か自己啓発が必要だなぁ・・・ということで、せっかくなのでみんなでできることが何かないかしら、と考えたのが始まり。
一応これまでは、好きなテーマでライトニングトーク形式の発表会を実施してきたが、ネタがなくなってきたため、次にやってみたいことについてメンバーに意見を聞いてみた。
すると、「読書会に興味がある」という声があったので「読書会」を実施してみるか、という経緯で始める。

**書籍の選択について**
メンバーはベテランから新人までいろいろな人がいるため、本のレベルにより難易度が高すぎる・低すぎるというような差が出ないような内容の本を探した。
また、共通の興味や学習目的で集まっているメンバではないので、普遍的な内容で取り組めるもの、1年間続けるので負荷が少ない本がよかった。

**選んだ本：[「プログラマが知るべき97のこと」](https://%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%81%8C%E7%9F%A5%E3%82%8B%E3%81%B9%E3%81%8D97%E3%81%AE%E3%81%93%E3%81%A8.com)**
上記の結果、「プログラマが知るべき97のこと」に決定した。理由は以下。

* エッセイ形式で１本が短いため時間をかけずに簡単に読める
* Webで公開されているので、どこでも読める（各自で購入しなくてもよい）

#4.目的

**世界で活躍しているプログラマ達の知見を知る**
新人には教育として、ベテランには自分の仕事の再確認や、新たな発見があるように。	
**知識の共有**
上記の通り、新人からベテランまでメンバーがいるので、それぞれの立場で知識や意見を交換して共有する。
	
**メンバ同士がお互いを知り合う**
同じ課に所属しているとはいえ、業務が違うと話す機会もないため、読書会を通してお互いを知り合う機会としたい。

#5.メンバー
課員：9名

* 参加希望者がいればこの限りではない


#6.進め方
**開催頻度**

* 月1回、定例会議の場で実施
    * 可能なら増やしていきたい

**事前作業**

* その月の担当者（1名）を決定
* 担当者は当日までどのエッセイを取り上げるのかを準備、対象エッセイをメンバーに連絡
* 各メンバは事前に読んで意見をまとめておく
* 記事を選んで、以下のまとめを作成。各スライドで1枚づつ程度。内容は以下
    * 記事の概要
    * 記事を選んだ理由と感想
    * 議論タイムを設けるので、その議事をあらかじめ考えておく

**当日**

* 事前作業の内容を発表
* 議論タイム（担当者は司会を務めること）
* 議事録をとる

**事後作業**

* 記事をQiitaに反映して記録を残す

#まとめ
どうなるかわからないけど、とりあえずやってみることにする。
実施するなかで、進め方のルールはやりやすいように変えていく予定。
盛り上がらなくて、ダメならすぐにやめて、別のことに取り組む心意気。
議事については随時更新する。
Bigquery 横に長いテーブルの中身を条件句で集計する

## やりたいこと

BigQueryで集計するなかで
横に長く伸びているテーブルの中から一定条件を満たしたものだけをを集計したかったので調べました。
if(....) で頑張ることもできるのですが、項目が多くなると大変なので配列集計を使ってスマートに記述するやり方です

|id|user_id|name|description|photo|skill|
|---|---|---|---|---|---|
|1|101|public|public|closed|deleted|
|2|102|public|public|public|public|
|3|103|public|public|closed|public|
|4|104|public|closed|closed|public|

↓↓↓↓↓↓↓

|user_id|public_cnt|
|---|---|
|101|3|
|102|4|
|103|3|
|104|2|

## クエリサンプル

```
SELECT
  user_id, 
  (SELECT COUNTIF(_x = 'public') FROM UNNEST([name, description, photo, skill]) as _x) AS public_cnt
FROM item_display_statuses
;
```


https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions?hl=ja#countif
[Blue Prism] ブラウザベースのアプリケーションオブジェクトで「読み取り」ステージの「HTML属性を取得」を利用する際のTips

ブラウザベースのアプリケーションオブジェクトを作成する際に、「読み取り」ステージで「HTML属性を取得」を利用しようとして操作方法がわからなくなり、Blue Prism のサポートの方に教えていただいたので紹介します。

やりたかったこと
------------------------------

例えば下記のような img タグの class や src 属性を、「読み取り」ステージの「HTML属性を取得」を利用して取得したい。

<img width="1105" alt="target_sample.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528676/1e83e4f2-d95c-558d-8e73-1ce556ef70f5.jpeg">


``` html
<img alt="Event thumbnail placeholder" src="/assets/placeholder/news-thumb.jpg" class="img-responsive">
```

「読み取り」ステージの「HTML属性を取得」の使い方
--------------------------------------------------------------

ブラウザベースのアプリケーションオブジェクトでも、Internet Explorer を利用するか、Chrome を利用するかで、指定方法が微妙に変わってきます。


### Internet Explorer の場合

まず、アプリケーションモデラーで対象の要素をスパイしておきます。

このとき、属性タブの「名前」に表示されている文字列を、後から利用します。

<img width="503" alt="ie_spy.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528676/3ab86c2a-cb04-0ea6-1913-fde2b27867b5.jpeg">


オブジェクトのアクション内で対象のページを開き「読み取り」ステージで「HTML属性を取得」を選択します。このとき、「属性名」に先ほどスパイした画面で表示されていた属性タブに表示されていた「名前」の通りに指定する必要があります。下記の例では "クラス名" と指定しています。 "class" と指定しても動きません。

<img width="512" alt="ie_read.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528676/af8737b6-81af-5d4a-3fce-4a2efc76780b.jpeg">


スパイした際に取得てきていない属性（例えば src など）は「HTML属性を取得」を使って値を読み取ることができませんが、「HTMLを取得」を使って対象要素全体のHTMLを取得しておき、"Utility Strings" の "Get XML Attribute" を使うと、回避できるようです。ちょっと冗長ですね。。

<img width="404" alt="Get_XML_Attribute.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528676/dcd6f15d-5429-0729-9ee3-fca6dac195e6.jpeg">


### Chrome の場合

同じように、アプリケーションモデラーで対象の要素をスパイしておきます。Internet Explorer のスパイしている情報に比べ、項目が多いですね。

<img width="484" alt="chrome_spy.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528676/552964f7-3941-ee55-2c0b-076ce9b92394.jpeg">


オブジェクトのアクション内で対象のページを開き「読み取り」ステージで「HTML属性を取得」を選択します。このとき、「属性名」には、HTMLソース内での属性名（ここでは "class" ）を指定します。"src" など、Internet Explorer の時には取得できなかった属性も、1ステージで取得できました。

<img width="403" alt="chrome_get_attribute.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528676/25cf19c9-8b1d-526b-48ef-618fa1b5bf15.jpeg">



Chrome で指定するパラメーターの方がより直感的ですね。
非圧縮 ZIP(PKZIP) フォーマットのメモ

## 背景

* 複数ファイルを非圧縮 zip で一つのファイルにまとめたい
* 非圧縮 zip を, zlib や miniz など使わずに読みたい
* tar だとちょっとフォーマットがめんどい 

## 仕様

https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT

https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html

ヘッダは 30 bytes です. compression method が 0 だと非圧縮です.

読み込むときは, central directory に当たったらパース終了と判定すればよいでしょう.

標準では 2GB までのサポートです. 2GB 以上の場合は ZIP64 flag で扱います.

## サンプル

https://github.com/rogersce/cnpy

cnpy に npz(numpy npy データをまとめたもの. npz は圧縮もサポート) のロードとシリアライズサンプルコードがありますので参考になります.
【Vuex】mapState, mapGetters, mapMutations, mapActionsの最低限の使い方まとめ

## はじめに
Vuexの以下ヘルパーについて、最低限の使い方をまとめました。

大きく分けて以下**2つに分けて覚えればOK**です。

### 1.状態を呼び出す

- `mapState`
- `mapGetters`

### 2.状態を変化させる

- `mapMutations`
- `mapActions`


※Vuexの**導入方法**や**`state`とは？**という基本については当記事では触れていません。

## 環境
```yaml
OS: macOS Catalina 10.15.1
Vue: 2.6.10
vuex: 3.1.2
```

## `map○○`を使うメリット
以下のように**シンプルに呼び出せること**が最大のメリットです。

```javascript
this.$store.state.state1 //通常
this.state1 //mapState使用

this.$store.getters.getter1 //通常
this.getter1 //mapGetters使用

this.$store.commit('mutation1', 引数) //通常
this.mutation1(引数) //mapMutations使用

this.$store.dispatch('action1', 引数) //通常
this.action1(引数) //mapActions使用
```

## 使い方

### 1.Vuexから使うヘルパーをインポート
まず、全てのヘルパーに**共通の作業**です。
以下のように**そのコンポーネント内**で使うヘルパーをインポートします。

```javascript:Anything.vue
<script>
  import { mapState } from 'vuex'
//...
</script>
```

複数使う場合は`,`区切りで書けばOKです。

```javascript:Anything.vue
<script>
  import { mapGetters, mapMutations } from 'vuex'
//...
</script>
```

---

### 2.必要な`state`, `getters`, `mutations`, `actions`をリストアップ
このリストアップ方法は複数ありますが、そのバリエーションは公式ドキュメントや他記事をご参照下さい。

当記事では最も使われると思われる

- **スプレッド演算子**を使用して書く
- **ストア内の名前**と**テンプレート内で呼び出す名前**が同じになる

というパターンのみ記載します。


※ここから書く場所が

1. `computed`内
2. `methods`内

の２通りに分かれるのでご注意下さい。

#### 2-1.`mapState`, `mapGetters`の場合
#### `computed`内に書く
※mapGettersの場合を例にします。

```javascript:Anything.vue
<script>
  import { mapGetters } from 'vuex'

  export default {
//...
  computed: {
    ...mapGetters([
      'getter1',
      'getter2'
    ]),
    //スプレッド演算子を使うと他のものと共存できる。
    otherComputed() {
      //...
    }
//...
  }
</script>
```

#### 2-2.`mapMutations`, `mapActions`の場合
#### `methods`内に書く

```javascript:Anything.vue
<script>
  import { mapGetters } from 'vuex'

  export default {
//...
  methods: {
    ...mapActions([
      'action1',
      'action2'
    ]),
    //スプレッド演算子を使うと他のものと共存できる。
    otherMethod() {
      //...
    }
//...
  }
</script>
```

---
### 3.テンプレート内でリストアップしたものを使用する

#### 3-1.`mapState`, `mapGetters`

以下のように呼び出せます。

冒頭で触れたとおり、**非常にシンプルです**。

```javascript:Anything.vue
this.getter1
this.getter2
```

#### 3-2.`mapMutations`, `mapActions`

以下のように呼び出せます。

該当のactionに**引数がある場合**、`()`内に引数を入れればOKです。

```javascript:Anything.vue
this.action1(引数)
this.action2(引数)
```

## おわりに
最後まで読んで頂きありがとうございました:bow_tone1:

どなたかの参考になれば幸いです:relaxed:

## 参考にさせて頂いたサイト（いつもありがとうございます）
- [ステート | Vuex](https://vuex.vuejs.org/ja/guide/state.html)
- [ゲッター | Vuex](https://vuex.vuejs.org/ja/guide/getters.html)
- [ミューテーション | Vuex](https://vuex.vuejs.org/ja/guide/mutations.html)
- [アクション | Vuex](https://vuex.vuejs.org/ja/guide/actions.html)
- [モジュール | Vuex](https://vuex.vuejs.org/ja/guide/modules.html)
PHPで出力が始まってるかどうか調べる

PHPでheader()を利用する際、既にechoやprintなどで出力が始まっているとエラー(Warning)が出る場合がある。header()の前に出力が始まってるかどうか判定したい思って調べた。

次のようにするとバッファされてるせいかエラーが出ない。

```php:no_err.php
<?php
echo "start".PHP_EOL;
header('Content-Type: text/plain');
echo "end".PHP_EOL;
//結果
//start
//end
```
バッファをob_flush()するとヘッダが送信されるのでheader()でエラーが出る。

```php:err.php
<?php
echo "start".PHP_EOL;
ob_flush();//出力開始
header('Content-Type: text/plain');
echo "end".PHP_EOL;
//結果
//start
//Warning: Cannot modify header information - headers already sent by 
//(output started at /home/test/html/err.php:3) in /home/test/html/err.php
//on line 4
//end
```
出力が始まっていればヘッダも出力される筈なのでheaders_sent()を見れば良い。

```php:headers_sent.php
<?php
echo "start".PHP_EOL;
ob_flush();//出力開始
if(headers_sent()){
	echo "出力が始まってる！".PHP_EOL;
}else{
	header('Content-Type: text/plain');
}
echo "end".PHP_EOL;
//結果
//start 出力が始まってる！ end 
```
出力が始まってるかどうか判定できました。めでたしめでたし😇

ではない！

gzipなどを利用する際にはheaders_sent()をチェックしてもブラウザ側でエラーが出る。

```php:err_gz.php
<?php
echo "start".PHP_EOL;
if(headers_sent()){
	echo "出力が始まってる！".PHP_EOL;
	echo "end".PHP_EOL;
}else{
	header('Content-Encoding: gzip');
	echo gzencode("end".PHP_EOL);
}
```
firefoxでの結果
![firefox.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563735/022a8aa7-a339-b3d1-5dd9-63e893a443f2.jpeg)

出力される前にバッファされてるのでheaders_sent()時点ではまだヘッダが送信されない。ob_flush()を使えばヘッダが送信されてheaders_sent()は機能するがheader()は使えなくなる。

では、どうする？
バッファに入ってるデータの量が分かれば良いので、ob_get_contents()でバッファを調べる。

```php:ob_get_contents_gz.php
<?php
echo "start".PHP_EOL;
if(headers_sent() || strlen(ob_get_contents())){
	echo "出力が始まってる！".PHP_EOL;
	echo "end".PHP_EOL;
}else{
	header('Content-Encoding: gzip');
	echo gzencode("end".PHP_EOL);
}
//結果
//start 出力が始まってる！ end 
```
"start"を取り除けば無事にgzipされた"end"だけ表示される。

```php:ob_get_contents_gz_2.php
<?php
if(headers_sent() || strlen(ob_get_contents())){
	echo "出力が始まってる！".PHP_EOL;
	echo "end".PHP_EOL;
}else{
	header('Content-Encoding: gzip');
	echo gzencode("end".PHP_EOL);
}
//結果
//end 
```
めでたしめでたし😇
関数のデフォルト引数でリストを与えてしまうと・・・

```py:1
def test(x, l=[]): 
    l.append(x)
    return l

y = [1, 2, 3, 4]
r = test(7, y)
print(r)
```

```:1の実行結果
[1, 2, 3, 4, 7]
```

```py:2
def test(x, l=[]): 
    l.append(x)
    return l

r = test(100)
print(r)
r = test(100)
print(r)
```

```:2の実行結果
[100]
[100, 100]
```

同じ処理を二回したつもりが、
二回目は100が二個になる。

これは、リストが参照渡しであるが為に起こる。
バグに繋がる事が多いため、
リストやデイクショナリーの様に参照渡しのものをデフォルト引数におかない。

そこで以下の様に書く。

```py:3
def test(x, l=None):
    if l is None:
        l = []
    l.append(x)
    return l

y = [1, 2, 3, 4]
r = test(7, y)
print(r)

r = test(100)
print(r)
r = test(100)
print(r)
```

```:3の実行結果
[1, 2, 3, 4, 7]
[100]
[100]
```
Javascriptで自作のrange関数

## range

```javascript
export const range = (start, end, step = 1) =>
  [...Array(Math.floor((end - start + step) / step))].map(
    (_, i) => start + i * step
  )
```

## 例

### 1 - 10

```javascript
range(1, 10)
> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```

### 1 - 10 (3刻み)
```javascript
range(1, 10, 3)
> [1, 4, 7, 10]
```

### 1000 - 10000 (1000刻み)
```javascript
range(1000, 10000, 1000)
> [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000]
```
git commit を絵文字でデコる

# 背景
プロジェクトでコミットをデコっている人が居たので、面白そうだなぁと思っていました。
私も灰色の世界を少し色鮮やかにしてみたかったのでやってみました。

真面目な話、内容によるコミット粒度をもう見直したくて、少し意識を向けるためにこのように一定数にカテゴライズをしてみたらより意識できるのでは？と思ったのでその試みです。

# 目標

prefixとして頭に絵文字をつけて、視覚的にどんな意味合いのコミットかわかりやすくします。

![IMG_0896.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274090/7c935a1c-ca0a-2e3d-9167-fe2769b94be6.jpeg)

こんな感じで、何をしているコミットなのかパッとみ分かりやすいです。
PRコメントのやりとりやコミットコメントは、会話というより必要な情報の共有と明確化するのをなるべく意識しているので淡々とした文章になりがちです。

なので、このように少し可愛くしても大きな罪はないでしょう。

# やり方
これを実現する流れとしては、

1. 絵文字テンプレートを用意
2. 上記を`git config` に設定
3. 通常通り編集、差分`git add file`の手順を踏む
4. `git commit`を叩くとvimが立ち上がる
5. 設定したテンプレート見ながらコメント入力

という感じです。


## 絵文字テンプレートを用意する

自分で作成してもいいですし、公開されているものが沢山あるのでそちらを使ってしまった方が時間削減できます。
大体の絵文字の意味は共通認識されていると思いますが、たまに違うのもあったりします。

私は
https://gist.github.com/nownabe/85d8595fd142adc426fbfaf2bab015e0
を拝借させていただいて、自分用に改良しました。

よく使われるのはここに沢山載ってあるので参考に。
https://gitmoji.carloscuesta.me/

```
# ==== Emojis ====
# 🐛  :bug: バグ修正
# 👍  :+1: 機能改善
# ✨  :sparkles: 部分的な機能追加
# 🎉  :tada: 盛大に祝うべき大きな機能追加
# ♻️   :recycle: リファクタリング
# 🚿  :shower: 不要な機能・使われなくなった機能の削除
# 💚  :green_heart: テストやCIの修正・改善
# 👕  :shirt: Lintエラーの修正やコードスタイルの修正
# 🚀  :rocket: パフォーマンス改善
# 🆙  :up: 依存パッケージなどのアップデート
# 🔒  :lock: 新機能の公開範囲の制限
# 👮  :cop: セキュリティ関連の改善
```

このようにコメントアウトして作成してください。

## `git config` に設定
ファイルは適当な場所に保存しておいてください。
使用したいリポジトリの`git config`にそのパスを指定してテンプレートを設定します。

```
git config commit.template ~/TEMPLATE_FILE
```
とすれば設定できるはずです。

設定は以上です。
`--global`を設定すればグローバル設定も可能です。

## コミットをデコろう
あとはいつも通り

```
git add -A
```

なりして

```
git commit
```

を叩くと

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274090/57a4452e-39c1-c096-d67e-992a6f6b0a95.png)

こんな感じで設定したテンプレートが出てきます。
これを見ながら絵文字コードとコメントをvimで入力すればOKです。

## 補足
絵文字をコメントに載せるだけなら

```
git commit -m ":fire: fireeeee"
```
と普通にコードを入力すればできたっぽいです。
上記で行っているのはカンペ、チートシートの追加ですね。

憶えちゃえばいちいちvim開かなくても良さそうかも。

# 終わりに
ウチもコメント、デコれたﾖ
[MEMO] gem コマンドで Library not loaded: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib が出たときの対処法

`foreman`動かしたいから`gem`を叩いたら怒られた案件；

```bash
$ gem install foreman
ERROR:  Loading command: install (LoadError)
	dlopen(/Users/suzukalight/.rbenv/versions/2.6.2/lib/ruby/2.6.0/x86_64-darwin16/openssl.bundle, 9): Library not loaded: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib
  Referenced from: /Users/suzukalight/.rbenv/versions/2.6.2/lib/ruby/2.6.0/x86_64-darwin16/openssl.bundle
  Reason: image not found - /Users/suzukalight/.rbenv/versions/2.6.2/lib/ruby/2.6.0/x86_64-darwin16/openssl.bundle
ERROR:  While executing gem ... (NoMethodError)
    undefined method `invoke_with_build_args' for nil:NilClass
```

結論としては、`rbenv`でいったん`uninstall`してから`install`しなおす。そうするとopenssl向けのライブラリを再度構成してくれるっぽい；

```bash
$ rbenv uninstall 2.6.2
$ rbenv install 2.6.2
Downloading openssl-1.1.1d.tar.gz...

$ gem install foreman

（ここでターミナルを起こし直す）

$ foreman start -f Procfile.app.dev
```

ちなみに `brew update && brew upgrade` もやったけど、こちらは効果がなかった。

reference: https://teratail.com/questions/225461
【Rails】画像をリサイズしてアップロード

##ModelとTableを作成
```terminal
$ rails g model Hoge image
$ rails db:migrate
```

##gemを追加
```rb:Gemfile
gem 'carrierwave'
gem 'mini_magick'
```
```terminal
$ bundle install
```

##Uploaderを作成
```terminal
$ rails g uploader Hoge
```
画像を保存するディレクトリや、許可する拡張子等を必要に応じて修正。
よく使う設定はあらかじめコメントとして記載されています。

```app/uploaders/picture_uploader.rb
class HogeUploader < CarrierWave::Uploader::Base
  storage :file

  # アップロードファイルの保存先
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  # アップロード可能な拡張子のリスト
  def extension_whitelist
    %w(jpg jpeg gif png)
  end
end
```

モデルにマウント

```app/models/hoge.rb
class Hoge < ApplicationRecord
 #mount_uploader 画像名を保存するカラム名, アップローダー名
  mount_uploader :image, HogeUploader
end
```

##画像をリサイズ
```app/uploaders/picture_uploader.rb
class HogeUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick
  process resize_to_fill: [1000, 500]
.
.
```
`resize_to_fill`以外のオプションに関しては、以下の記事にわかりやすくまとめられています。
[CarrierWave + RMagick 画像のリサイズをまとめてみました](http://noodles-mtb.hatenablog.com/entry/2013/07/08/151316)

##Controller、Viewルーティングを作成
```terminal
$ rails g controller hoges index
```
```app/controllers/hoges_controller.rb
class HogesController < ApplicationController
  def index
    @new_image = Hoge.new
    @all_images = Hoge.all
  end

  def create
    @new_image = Hoge.new(hoge_params)
    if @new_image.save
      redirect_to hoges_url
    else
      render action: :index
    end
  end

  private

  def hoge_params
    params.require(:hoge).permit(:image)
  end
end
```
```erb:app/views/hoges/index.html.erb
<h2>画像アップロード</h2>
<%= form_with model: @new_image, local: true do |f| %>
  <%= f.file_field :image %>
  <%= f.submit 'アップロード' %>
<% end %>

<h2>アップロードした画像一覧</h2>
<% @all_images.each do |i| %>
  <%= image_tag "/uploads/hoge/image/#{i[:id]}/#{i[:image]}" %>
<% end %>
```
```config/routes.rb
Rails.application.routes.draw do
  get 'hoges', to: 'hoges#index'
  post 'hoges', to: 'hoges#create'
end
```

## 削除する場合
```rb
image_object = Hoge.first
image_object.remove_image! #画像のカラム名がhogeならremove_hoge!
image_object.save
```
##TODO
・画像をS3にアップロード
Jenkinsfile は Groovy 文としてどう解釈されるのか? (未完)

JSON や YAML と違って、Jenkinsfile に纏わり付く気持ち悪い雰囲気は、Jenkinsfile がただのデータではなく Groovy というプログラミング言語だからだろう。プログラミング言語なので設定ファイルの中で何でも出来てしまうのは便利な一方で、一歩間違えれば良からぬことが起こってしまうのでは無いかという潜在的な恐怖がある。その恐怖を克服するため、Groovy についてちょっと調べてみた。

## Jenkins のインストールと Pipeline の作成

なんとなくインストーラを使わずに Jenkins を設定してみる。

https://jenkins.io/download/ より Generic Java package をダウンロード

    java -jar jenkins.war

http://localhost:8080 にブラウザでアクセスして適当に初期化する。

https://jenkins.io/doc/book/pipeline/getting-started/ の通りに `example-pipeline` 作成して以下の Pipeline を作成する。

```
pipeline {
    agent any 
    stages {
        stage('Stage 1') {
            steps {
                echo 'Hello world!' 
            }
        }
    }
}
```

Build Now でこの Pipeline をを実行出来る。

### Jenkins にコマンドラインからアクセスする

いちいち Build Now を押すのは面倒なので、 CLI を設定する。

* Manage Jenkins > Configure Global Security > SSH Server で適当に設定する。例: 8081
* (User) > Configure > SSH Public keys に公開鍵を入れる。

    ssh localhost -p 8081 help
    ssh localhost -p 8081 build example-pipeline -f -v

これでコマンドラインからビルド出来る。

参考

* https://jenkins.io/doc/book/managing/cli/

## Pipeline を調べる。

Pipeline はただの設定ファイルではなく Groovy ファイルという事だった。ということは pipeline, agent, stage と言った識別子は Groovy オブジェクトなはずだ。調べてみた。

```
println "pipeline: $pipeline"

pipeline {
    // println "agent: $agent"
    agent any 
    stages {
        // println "stages: $stages"
        stage('Stage 1') {
            steps {
                println "steps: $steps"
            }
        }
    }
}
```

* pipeline 宣言の外側に println を書く事が出来た。pipeline はオブジェクトだった。
* pipeline 宣言のすぐ内側には println を書くことが出来なかった。
* stages 宣言のすぐ内側には println を書くことが出来なかった。
* stage 宣言のすぐ内側には println を書くことが出来た。steps はオブジェクトだった。

実行結果

```
$ ssh localhost -p 8081 build example-pipeline -f -v
Started example-pipeline #15
Started from command line by tyamamiya
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] echo
pipeline: org.jenkinsci.plugins.pipeline.modeldefinition.ModelInterpreter@1a666b03
[Pipeline] node
Running on Jenkins in /Users/tyamamiya/.jenkins/workspace/example-pipeline
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Stage 1)
[Pipeline] echo
steps: org.jenkinsci.plugins.workflow.cps.DSL@717597ff
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
Completed example-pipeline #15 : SUCCESS
```

## 宿題

特殊構文: http://groovy-lang.org/dsls.html によると、`pipeline {...}` のような構文は `pipeline({...})` のような関数呼び出しの省略形だという事だった。中括弧はクロージャを表すので `agent` や `stages` も関数だと思ったのだが println 出来なかった。そもそも `println` を探せないというエラーが出る。

```
WorkflowScript: 4: Undefined section "println" @ line 4, column 5.
       println "agent: $agent"
```

普通クロージャというと外の環境を取り込む物だが、Groovy の場合もっと複雑な事が出来るらしい。`agent` や `stages` が Groovy 的にどう解釈されるのか知りたい。
F-Droidを使ってオープンソースのAndroidアプリをインストールしよう。


## F-Droidとは？

> F-DroidはAndroidに対応したソフトウェアリポジトリおよびアプリケーションストアである。Google Playと機能は類似するが、扱っているのはフリーかつオープンソースのソフトウェアのみである。

[Wikipediaより](https://ja.wikipedia.org/wiki/F-Droid)


## インストール方法

https://f-droid.org/

からインストール！！

## おすすめアプリ

オープンソースの広告ブロッカー

[DNS66](https://f-droid.org/en/packages/org.jak_linux.dns66/)

をインストールしてAndroid端末から広告を一掃しよう！！！

#まとめ

オープンソースのアプリで快適なインターネットライフを。