OmniAICreator/Qiita-1.07M huggingface dataset:
Python Pandasにおいて文字列処理の方法

本日はPythonのライブラリのひとつpandasを使ってデータ分析を行なった。
pandasにおいてデータフレームの中で特定の文字列を含む行や列のみ抽出したいときに役に立つ関数について列挙する。

##目次
・isin
・contains


## pd.Series.str.contains関数

これはSeriesに適応できる関数である。DataFrameには使えないので、DataFrameからひとつずつSeriesを抽出して作る必要がある。

以下は適当に作ったデータフレームとする。

```python
data = pd.DataFrame(
    {'animal': ['dog', 'cat', 'wolf', 'bat'],
     'habitat': ['USA', 'Canada', 'Japan', 'Russia']})

```

|  | animal | habitat |
| ----- | ----- | ----- |
| 0 | dog | USA | 
| 1 | cat | Canada |
| 2 | wolf | Japan |
| 3 | bat | Russia |

```python
df[df['animal'].str.contains('at')]
```

以下のようにanimalで文字列'at'を含むデータフレームが出力される：

|  | animal | habitat |
| ----- | ----- | ----- |
| 0 | cat | Canada |
| 1 | bat | Russia |

```python
df[df['animal'].str.contains('an')]
```
これはこのように出力される

|  | animal | habitat |
| ----- | ----- | ----- |
| 0 | cat | Canada |
| 1 | wolf | Japan |

contains関数は引数にstrしか受け付けないので、listなど複数のstrを渡したい場合次のisin関数を使うことになる。

## isin関数


上のは結構使えるが、複数の単語を含むデータフレームを抽出したい場合、isin関数を使おう。
isin関数はlist系の引数を受け付けるので、numpyのarrayなども渡すことが可能となる。
ただし、containsとは違って文字列を含む値の抽出ではなく、その文字列と==の関係になるものを抽出してしまうことに注意！

```python
df[df.['animal'].isin(['cat', 'wolf'])]
```

出力：

|  | animal | habitat |
| ----- | ----- | ----- |
| 0 | cat | Canada |
| 1 | wolf | Japan |




以上！str系にはcatなどの文字列を結合する関数もあり、これも結構有能だが、また今度説明します。
Android Chromeからapkダウンロード＆インストールしようとしたらChrome落ちた

# 結論

Chromeの保存先がSDカードになっていたため、保存先を本体に修正した

# 各種version

Android: 9
Chrome: 73.0.3683.90

# 問題

Androidアプリのテストのために、作成したapkをDLしようとしたら、Chromeが落ちる。
もしくは、「繰り返し停止しています」ダイアログが出てしまう。

# 対応

自分の場合は、ダウンロードの保存先がSDカードになっているからぽかった。
1. Chromeを立ち上げ、画面右上の設定？（縦の３点ポチ）をタップ
2. 「設定」をタップ
3. 下の方の「ダウンロード」をタップ
4. ダウンロード場所が描かれているのでそれをタップ
5. 「ダウンロード場所」ダイアログが出てくるので、ダウンロード場所を「ダウンロード」に変更し、完了をタップ
vue.jsでTypeScriptを使おうとしてハマったこと。

# 拡張子が「.vue」のファイルをimportできなくなった
index.js や main.jsのファイル拡張子を.tsに変えたら軒並み.vueファイルのimport文がエラーに。。。

**【解決方法】**
・srcフォルダ直下に「sfc.d.ts」を作成し、以下を記述した
※srcフォルダ直下に作成すること。

```sfc.d.ts
declare module "*.vue" {
  import Vue from 'vue'
  export default Vue
}
```
  
  
# "These relative modules were not found..."みたいなエラーが発生する
僕の場合、こんな感じのエラーでした。
F12キー押下で当該ソースファイルに移動できるのになぜ・・・。

```
These relative modules were not found:

* ./router/index in ./src/main.ts
* ./store/index in ./src/main.ts
```

**【解決方法】**
・webpack.bese.jsのextensionsに「".ts"」を追記した。
・設定ファイルを独自に変更していて、webpack.base.jsに記載がない場合、どこかのファイルに記載されているはずなので探して書き換えればいいはず。
・書き換えてもダメならファイル名が間違っていないか、ディレクトリはあっているかを見てみましょう（意外とありがち））

```webpack.base.js
...
..
.
resolve: {
  extensions: ['.js', '.vue', '.json', ".ts"],　⬅︎ ココに「 ".ts" 」を追加しただけ
  alias: {
    'vue$': 'vue/dist/vue.esm.js',
    '@': resolve('src'),
  }
},
.
..
...
```

以上
PHP Mockey 特定のオブジェクトが引数として渡されたときの戻り値を切り替える方法

# 動作環境
PHP 7.2
PHPUnit 6.5.14
Mockery 1.2.2

# やりたいこと
Mockeryでモック化したUserRepositoryクラスのメソッド`isExist`の動作を引数によって切り替えたい

isExistメソッドの役割：指定されたユーザIDが存在している場合 true 存在していない場合 false を返す

# コード

```php

interface UserRepository
{
    /**
     * @param UserId $userId
     * @return bool true:ユーザが存在する false:ユーザが存在しない
     */
    public function isExist(UserId $userId): bool;
}

class UserId
{
    /**
     * @var int
     */
    protected $id;
    /**
     * UserId constructor.
     * @param int $id
     */
    public function __construct(int $id)
    {
        $this->id = $id;
    }

    /**
     * @return int
     */
    public function getId(): int
    {
        return $this->id;
    }
}
    
//~~~~~~~~~ 以下テストケース内

$mockUserRepository = \Mockery::mock(UserRepository::class);

$mockUserRepository->shouldReceive('isExist')
            ->byDefault()
            ->andReturn(true);

$mockUserRepository->shouldReceive('isExist')
            ->with(\Mockery::on(function (UserId $userId) {
                if ($userId->getId() === 999) { //ユーザIDが 999 の場合に andReturn に指定された値を返却する
                    return true;
                }
                return false;
            }))
            ->andReturn(false);


$this->assertTrue($this->mockUserRepository->isExist(new UserId(1))); // OK
$this->assertFalse($this->mockUserRepository->isExist(new UserId(999))); // OK

```


# ポイント

Mockeryの`with`メソッドは通常値を設定するだけで、動作を切り替えたりできますが、
今回のように「オブジェクトが引数」となる場合はだた`with`を使うだけだと想定どおりに動作してくれません。

```php:誤りのケース
$mockUserRepository->shouldReceive('isExist')
            ->byDefault()
            ->andReturn(true);
$mockUserRepository->shouldReceive('isExist')
            ->with(new UserId(999)) // new UserId(999) === new UserId(999) → false
            ->andReturn(false);

$this->assertTrue($this->mockUserRepository->isExist(new UserId(1))); // OK
$this->assertFalse($this->mockUserRepository->isExist(new UserId(999))); // NG defaultのほうが呼ばれてしまっている
```
[Laravel 5.8] デバッグに便利なメソッドまとめ

# SQL系

## toSql()  
クエリビルダの作成されるSQL文を確認する。

```php
>>> User::where('id', 1)->toSql();
=> "select * from `users` where `id` = ?"
```

クエリビルダ以外で使おうとするとエラーだったり、戻り値が想定とは異なってくる。

```php
>>> User::all()->toSql();
// BadMethodCallException with message 'Method Illuminate/Database/Eloquent/Collection::toSql does not exist.'

>>> User::find(1)->toSql();
=> "select * from `users`"
// find()のSQLではない
// $user = new User(); $user->toSql();の結果と同じ
```

## DB::enableQueryLog(), DB::pretend()  
バインディングしている値も確認できる。

```php
// QueryLog
\DB::enableQueryLog();
User::all();
User::find(1);
\DB::getQueryLog();

// またはpretend
\DB::pretend(function () {
    User::all();
    User::find(1);
});

// どちらも以下が返される。
=> [
     [
       "query" => "select * from `users`",
       "bindings" => [],
       "time" => 1.21,
     ],
     [
       "query" => "select * from `users` where `users`.`id` = ? limit 1",
       "bindings" => [
         1,
       ],
       "time" => 1.18,
     ],
   ]
```

# dump, log系

## dump()  
変数をdumpする。php標準のvar_dump()より見やすい。

```php
>>> dump([1,2,3]);
array:3 [
  0 => 1
  1 => 2
  2 => 3
]

>>> var_dump([1,2,3]);
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}

// 複数の値を一気に表示できる
>>> dump(1, 2, 3, 4);
1
2
3
4
```

## dd()
dumpした時点で処理を終了する（dump and die）。使い方はdump()と同じ

## info(), logger()
ログに書き出す。

```php
info('sample info');
// [2019-04-18 14:15:36] local.INFO: sample info

logger('sample debug');
// [2019-04-18 14:15:45] local.DEBUG: sample debug

logger()->error('sample error');
// [2019-04-18 14:16:37] local.ERROR: sample error
```

オブジェクトも書き出したいときは、print_r($object, true)とする。

```php
logger(new App\Eloquent\User);
// [2019-04-18 14:19:18] local.DEBUG: []

logger(print_r(new App\Eloquent\User, true));
// [2019-04-18 14:19:31] local.DEBUG: App\Eloquent\User Object
// ...(オブジェクトの情報)
```

## [おまけ] dump-server
dump情報をターミナルで表示できる。まずは起動する。
（**dump-serverを起動しておくと、ビューではdump情報が表示されなくなります**）

```sh
$ php artisan dump-server
```

以下のようにdump()しておき・・・

```php:routes/web.php
Route::get('/', function () {
    dump(User::where('id', 1)->toSql());
    return view('welcome');
});
```

`/`にアクセスすると、ターミナルで以下のように表示してくれる。

```sh
GET http://localhost/
---------------------

 ------------ --------------------------------- 
  date         Thu, 18 Apr 2019 15:47:22 +0900  
  controller   "Closure"                        
  source       web.php on line 49               
  file         routes/web.php                   
 ------------ --------------------------------- 

"select * from `users` where `id` = ?"
```
Linuxの基礎

UNIXとLinuxの違い(実はMacOSもUnix、AndoridはLinux)
https://eng-entrance.com/unix_linux

#パス  
パスを用いることでコマンド実行時のファイルやディレクトリの位置を指定できる。

```command:パス指定の例
$ cat /usr/local/src/test.txt
# 絶対パスの指定例。
# 絶対的な位置というのはルートディレクトリから見たときの位置。絶対パスを指定する際は/からパスを記載する。
```


#ディレクトリー

相対パスの指定例
**1.ルートディレクトリ(ディレクトリの中でも頂点にあたるディレクトリを【/】で表す)**
    ex) cd /
    ex) cd /user ルートディレクトリ配下にあるuserディレクトリに移動

**2.カレントディレクトリ(現在作業を行なっているディレクトリを【.】で表す)**
    ex) cd ./src 

**3.親ディレクトリ(カレントディレクトリの1つ上の階層のディレクトリを【..】で表す)**
    ex) cd ../www

**4.ホームディレクトリ(Linuxにログインした際のディレクトリを【~】で表す)**
    ex) cd ~ （cdとだけ入力してコマンドを実行しても同じ結果)

#権限
Linuxでは全ての情報をファイルとして格納し、様々な制御を行う。
※ファイルは誰かの所有物として扱う。
Linuxは複数のユーザーが利用できる前提となっているため、で、ファイルへのアクセス権限を管理する必要がある。

```command:現在のディレクトリーにあるファイルに付与されている権限を見るコマンド
$ ls -l
```
```command:実行例
drwxr-xr-x  25 suzuki  staff  800  4 18 12:47 sample_app
```
|rwxr-xr-xは以下を許可している|
userに読み出し/書き出し/実行
groupに読み出し/実行
otherに読み出し/実行
あとに続く内容は、リンク数、ユーザー名、グループ名、ファイルサイズ(byte数)、更新日時、ファイル名を表している。

|実行ファイルの種類を示す記号|
「-」 →ノーマルファイル
「d」 →ディレクトリ (上記実行例はこれに当たる)
「l」→シンボリックリンク

- chmod(チェンジモード):ファイルのアクセス権を変更するコマンド

```command:実行対象のファイル例
-rw-r--r-- 1 app app         0  3月  3 20:24 test.txt
```
```command:実行コマンド
# 600の説明は下記の対象表を見ると分かりやすい
chmod 600 test.txt
```
```command:実行後（groupとotherの権限は排除した）
-rw------- 1 app app         0  3月  3 20:24 test.txt
```

|対象表|
<img width="852" alt="スクリーンショット 2019-04-19 10.00.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114933/e445c46c-1711-d2d9-d28a-f5feb37017a9.png">

```command:違う方法
# chmod 変更対象 変更方法 変更内容 対象ファイル
#　このコマンドではユーザーに実行権限を与えている
$ chmod u+x test.txt
```

- chown(チェンジオーナー)：所有者を変更するコマンド

```command:オーナーをsatoに変更
# スーパーユーザー権限が必要なため、sudoコマンドで実行する
$ sudo chown sato test.txt
```
Elixir: データ処理パイプラインを効率化するツールBroadway

[Broadway](https://github.com/plataformatec/broadway#broadway)は、Elixirでデータ処理パイプラインを効率化するためのオープンソースのツールです。同時並行かつマルチステージでデータを統合し、データ処理のパイプラインが構築できます。Amazon SQSやRabbitMQなどのさまざまなソースから、データが利用できるということです。


# おもな機能
Broadwayにより、同時並行の[`GenStage`](https://hexdocs.pm/gen_stage/GenStage.html)トポロジーを定める負担が減り、シンプルな設定APIで同時生成や同時処理、バッチの扱いなどが自動的に定義できます。データの取得や処理にかかる時間とコストがともに下げられるのです。

- [**バックプレッシャー**](http://e-words.jp/w/%E3%83%90%E3%83%83%E3%82%AF%E3%83%97%E3%83%AC%E3%83%83%E3%82%B7%E3%83%A3%E3%83%BC.html) - `GenStage`を活用して、上流のソースから必要なイベントだけを受け取るので、パイプラインがあふれません。

- **自動通知** - パイプラインの終わりやエラーが起こったときには、自動的にメッセージが送られます。

- **バッチ処理** - バッチ処理が組み込まれており、メッセージをサイズや時間によってグループ化できます。Amazon SQSのようにバッチでメッセージが効率的に処理できるシステムでは、時間とコストの両面から重要です。

- **データ損失を最小限にする耐障害性** - データの損失は最小限に抑えられる設計です。 プロデューサーは他のパイプラインから分離され、障害が起きた場合には自動的にサブスクライブし直されます。それに対して、ユーザーコールバックはステートレスです。そのため、エラーはローカル処理できます。予期しないバグに対しては、ダウンストリームコンポーネントのみが再起動されます。データの損失を防ぐためです。

- **グレースフル(graceful)シャットダウン** - VMと統合してグレースフルシャットダウンができます。Broadwayを監視ツリーの一部として起動することにより、VMがシャットダウンしたときは、必ずすべてのイベントをフラッシュすることが保証されます。

- **組み込みテスト** - 組み込みテストのAPIが予め備わっているので、テストメッセージをパイプラインで簡単にプッシュでき、イベントを正しく処理したことが確かめられます。

- **パーティショニング** - 動的パーティションにもとづいて、メッセージがバッチ処理できます。たとえば、パイプラインに`user_id`やメールアドレスなどに応じたバッチが必要だとします。その場合は、[`Broadway.Message.put_batch_key/2`](https://hexdocs.pm/broadway/Broadway.Message.html#put_batch_key/2)を呼び出せばよいのです。

- **Rate-limiting** (未実装)
- **Statistics/Metrics** (未実装)
- **Back-off** (未実装)


# インストール
`mix.exs`の依存(`deps`)に`:broadway`を加えてください。

```elixir
def deps do
  [
    {:broadway, "~> 0.1.0"}
  ]
end
```


# `Broadway`ビヘイビアを使う
つぎのふたつを定義します。

1. パイプラインの設定
2. `Broadway`ビヘイビアを実装するモジュール


## 例
Broadwayプロセスを開始するには、モジュールで`use Broadway`を呼び出して、`start_link`関数を定めます。GitHubの「[A quick example: SQS integration](https://github.com/plataformatec/broadway#a-quick-example-sqs-integration)」に掲げられているのは以下の例です。依存関係には[BroadwaySQS](https://github.com/plataformatec/broadway_sqs#broadwaysqs)が加えられ、SQS認証情報を設定したものとされています。

```elixir
defmodule MyBroadway do
  use Broadway

  alias Broadway.Message

  def start_link(_opts) do
    Broadway.start_link(__MODULE__,
      name: __MODULE__,
      producers: [
        sqs: [
          module: {BroadwaySQS.Producer, queue_name: "my_queue"}
        ]
      ],
      processors: [
        default: [stages: 50]
      ],
      batchers: [
        s3: [stages: 5, batch_size: 10, batch_timeout: 1000]
      ]
    )
  end

  def handle_message(_processor_name, message, _context) do
    message
    |> Message.update_data(&process_data/1)
    |> Message.put_batcher(:s3)
  end

  def handle_batch(:s3, messages, _batch_info, _context) do
    # Send batch of messages to S3
  end

  defp process_data(data) do
    # Do some calculations, generate a JSON representation, process images.
  end
end
```

Broadwayモジュールを定めたら、アプリケーション監視ツリーの子として`{MyBroadway, []}`というかたちでに加えてください。


# 参考

- Plataformatec blog「[Announcing Broadway](http://blog.plataformatec.com.br/2019/02/announcing-broadway/)」
- GitHub「[Broadway](https://github.com/plataformatec/broadway#broadway)」
- 公式ドキュメント「[Broadway behaviour](https://hexdocs.pm/broadway/Broadway.html)」
ハッカー倫理の再確認　(Steven LevyのHackerEthics)

　IT技術者/専門家に開発されたIT技術やシステムは、その程度の違いはあるが、その背景にある倫理観や思想を実現する方向で実現される。そのため、将来の開発されるであろうIT技術・システムを予想、想像する際に、背景にある倫理観や思想は有効なヒントとなる。
　この記事は、IT技術者/専門家の倫理観や思想の中で、最も有名で影響力のあるもののひとつ、StevenLevyの「HackerEthics」を取り上げる。

#Steven LevyのHacker Ethics
Steven LevyのまとめたHackerEthicsは次の6つである。

```
 - コンピュターへのアクセス、加えて、何であれ、世界の機能の仕方について教えてくれるものへのアクセスは無制限かつ全面的でなければならない。
　 実地体験の要求を拒んではならない！ 
　(Access to computers and anything which might teach you something about the way the world works 
　should be unlimited and total. Always yield to the Hands-On Imperative!)
 
 - 情報はすべて自由に利用できなければならない。 (All information should be free.)

 - 権威を信用するなーー反中央集権を進めよう。 (Mistrust Authority -- Promote Decentralization.)

 - ハッカーは、成績、年齢、人種、地位のような、まやかしの基準ではなく、そのハッキングによって判断されねばならない。
  (Hackers should be judged by their hacking, not bogus criteria such as degrees, age, race, or position.)

 - 芸術や美をコンピュータで作り出すことは可能である。 (You can create art and beauty on a computer.)

 - コンピュータは人生をよいほうに変えうる。 (Computers can change your life for the better.)
```

#Hacker Ethicsとは
　日本語では「ハッカー倫理」と訳される。ITの発展に多大に寄与してきた「Hacker」と呼ばれた人々の観点に立つ倫理観・道徳である。

　SetenLevyが著書「ハッカーズ」(1984年)でこのEthicsを発表したことで、広く世に知れわたることになった。今でもIT技術者/専門家のEthicsとして最も有名なものの一つである。
　当時のHackerに共通した倫理観をLevyがとりまとめたもので、Levyが提唱したというものではない。

　米国の1960-70年代の若手エンジニアとして活躍したHackerの思想が強く反映されたこのEthicsは、自由主義的で共同体主義的な(いわゆるヒッピー文化と重なるような)考え方が見られる。
　
>参考 STEWART BRAND 「WE OWE IT ALL TO THE HIPPIES」(TIME誌 SPECIAL ISSUE, Spring 1995 Volume 145, No. 12)

　なお、ここでいう「Hacker」は、技術力の高いエンジニア、もしくは専門家という意味。当時からHackerは技術はあるが反社会的な活動をおこなう如何わしい者たちというイメージをもたれていたが、Levyは意図的にその悪意を排除しよう努めているようである。
　「ethics」には「倫理」「道徳」(=ethic)に加えて「倫理学」「道徳原理」という意味も含んでいるが、それは「Hacker Ethics」に述べられる「倫理」が、世間一般が信じえる典型的な倫理ではなく、世の中に異なる価値観が存在しているのだから常に大多数の信奉する倫理と一致しなくても正当性がある、ということが強調された「倫理」を示しているように思われる。

#LevyのHackerEthicsに対する批判と対立
```
「Linuxは、知的財産という観点から見れば、何にでも取り付くガン細胞のようなものだ」
「皆がオープンソースを使えば、すべてをオープンソースにしなければならなくなる」
マイクロソフトCEO　スティーブバルマー
```

　「HackerEthics」もしくはそれに類する考え方は、当時から一般的な規範、慣習、モラルとギャップがあった。現在の価値観に照らし合わせても同様である。たとえば、個人のプライバシーの保護は、ITに求められる重要な観点の一つだが、「HackerEthics」では(意図的であるかどうか別にして)触れられていない。
　そのため、「HackerEthics」のような考え方に対する批判は、数多く行われている。マイクロソフトCEOスティーブ・バルマーが行ったオープンソースに対する批判は、その顕著な例の一つである。
　一方で、「HackerEthics」の信念から、シェアウェアや組織による情報の管理を強く批判するエンジニアも存在し、厳しい対立も見られた。

#今も続く、その影響
```
「『情報は自由(タダ)を求める（Information wants to be free）』と言ったのが1984年。
それからちょうど20年になるが、今もなお、この考え方は有効だと思っている」 

「今のような形のコンピューター・コミュニケーションの技術が登場してから約50年。
この流れは、あと30年ぐらいは続くんじゃないか」 

スチュアート・ブランド
```

```
「必要なのは、信用ではなく暗号化された証明に基づく電子取引システムであり、
これにより希望する二者が信用できる第三者機関を介さずに直接取引できるようになる。」
サトシ・ナカモト
```

　巨大組織に占有されたコンピュータ、情報を個人のものにしたパーソナルコンピュータやインターネット、フリーウェアを実現するGPLライセンスやオープンソース、さらに権力機関や特別な権限を持つ発行者を否定する通貨であるbitcoinなど、その影響は現在においても容易に見ることができる。
　SNSによる情報の管理、著作権や企業秘密の拡大が見られる現在のIT業界において、「HackerEthics」はすでに存在しない、という主張もあるが、過去、現在の影響を鑑みると、これから開発される技術やシステムにおいても一定の影響力を与え続けることは十分予想できる。ITの今後を占う際には、知っておきたい倫理である。
RでTwitterのツイートを取得する

#まずTwitterAPIを取得する
Twitterのツイートを持ってくるにはTwitterAPIが必要です。
取得には英語で100wordほどの取得理由を送る必要があります。一番の難関。
☆詳しくは割愛します☆
(追記：rtweetを使えばTwitterAPIはなくてもツイートの取得できるみたいです)
#パッケージをインストールしてAPIを設定する
twitteRというパッケージをインストールします。

```r
install.packages("twitteR")
library(twitteR)

APIKey <- "取得したAPI Key"
APISecret <- "取得したAPI secret key"

accessToken <- "取得したAccess token"
accessSecret <- "取得したAccess token secret"

setup_twitter_oauth(APIKey, APISecret, accessToken, accessSecret)
```
最後の行を実行するとYES or NOと出ると思うのでYESにする。
出なければ気にしなくていいかな

#ツイートの分析をする
今回はペプシの公式アカウント(@pepsi_jpn)がやっているプレゼントキャンペーンの本田のじゃんけんの勝率を調べてみようと思います。
userTimelineというものを使います。指定したユーザーのツイートを現在から過去にn個取得します。

```r
tws <- userTimeline("pepsi_jpn", n = 3200) #userTimelineの上限が3200っぽい
tws <- twListToDF(tws) #データフレームにする

lose <- tws[grep("あなたの勝利",tws$text),] #grep関数で一致するものを抽出する
win <- tws[grep("本田圭佑の勝利",tws$text),]

p <- 100*nrow(win)/nrow(tws) #本田圭佑のじゃんけんの勝率
# 実行結果
#"2019-04-18 05:19:22 UTC" "2019-04-18 05:21:30 UTC"の間で
> nrow(win)
[1] 3199
> nrow(lose)
[1] 1
> p
[1] 99.96875
```
勝率がわかりました。さすが本田圭佑ですね。
ただ今回の場合勝率を出すには3200戦じゃ少ないからもっとやったほうがいいですね。
注意点として、じゃんけんの勝敗に関するツイートのみをしていた場合にこの方法が使えます。
途中に別のツイートが入っていた場合は取り除かなければいけないです。(winとloseの合計で別のツイートがあるかわかります。)
Evil 有効下で paredit-forward/backward をちゃんと動くようにする

# 背景
Emacs でS式を書く時には ParEdit がとても便利ですが、Evil と併用すると `paredit-forward` と `paredit-backward` が上手く動いてくれません。カッコとカーソルとの相対的な位置関係が素の Emacs と Evil で異なるためですが、これを気にしながら Lisp を書くのは無駄に疲れるので挙動を修正します。

既に [evil-paredit.el](https://github.com/roman/evil-paredit) は存在していますが、`paredit-forward` と `paredit-backward` に関しては考慮されていないようです(たぶん)。

# コード

```emacs-lisp
;; Evil compatibility fix
(defun evil-end-of-line-p ()
  (let ((offset (if (evil-emacs-state-p)
                    0
                  1)))
    (eq (- (line-end-position) offset) (point))))

(defun evil-paredit-forward (origfun arg)
  (funcall origfun)
  (unless (evil-emacs-state-p)
    (backward-char)))

(defun evil-paredit-backward (origfun arg)
  (if (evil-end-of-line-p)
      (forward-line)
    (forward-char))
  (funcall origfun))

(advice-add 'paredit-forward :around #'evil-paredit-forward)
(advice-add 'paredit-backward :around #'evil-paredit-backward)
```

# やっていること
基本的には`paredit-forward`した後に1文字戻り、`paredit-backward`する前に1文字進むようにするだけです。ただし、Evil の Normal State でカーソルが行末にある時に1文字進もうとするとエラーが出てしまうので、行末かどうかを判定してから、行末であれば次行の先頭に、そうでなければ次の文字にカーソルを移動させるようにしています。
Ubuntu 16.04 LTS に docker-compose をインストールする

何かに躓いたら追記しようと思っていましたが、特に問題が無かったので、
ほぼ[公式ドキュメント：Install Docker Compose][1]の抜粋＆日本語化になってしまいました。


##### 動作環境
* Ubuntu 16.04.6 LTS / x86_64
* Docker version 18.09.4, build d14af54

# インストール

docker-composeのバイナリをダウンロードします。
"1.24.0"は執筆時点の最新バージョンです。
バージョンは[docker-composeのGitHub上のリリースページ][2]を参照してください。

```shell
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
```
ダウンロードしたものを確認してみると

```shell
$ ls -l /usr/local/bin/docker-compose
-rw-r--r-- 1 root root 16154160  4月 18 16:35 /usr/local/bin/docker-compose
```
のように実行権限がついていませんので、実行権限を追加します。

```shell
# 実行権限の付与
$ sudo chmod +x /usr/local/bin/docker-compose
# 結果の確認
$ ls -l /usr/local/bin/docker-compose
-rwxr-xr-x 1 root root 16154160  4月 18 16:35 /usr/local/bin/docker-compose
```

# 動作確認

続いて、実際に実行できるか確認してみます。

```shell
$ docker-compose --version
docker-compose version 1.24.0, build 0aa59064
```
もし"/usr/local/bin"にパスが通っていない場合、

```:docker-composeのバージョン確認結果(エラーの場合)
The program 'docker-compose' is currently not installed. You can install it by typing:
sudo apt install docker-compose
```
や、"No such file or directory"と表示されますので、パスに"/usr/local/bin"を追加するか、
パスの通っているところにシンボリックリンクを作成します。
ここでは[公式ドキュメント：Install Docker Compose][1]に倣って、シンボリックの作成例を示します。

```shell
$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
```
少なくとも大抵の環境で"/usr/bin"にはパスが通っていると思いますが、
シンボリックリンク作成後も問題があるようであれば以下のコマンドでパスの確認をしてみてください。

```shell
$ echo $PATH
```

[1]:https://docs.docker.com/compose/install/
[2]:https://github.com/docker/compose/releases/
Laravel の dump をスマートにする Laravel Dump Server

# 概要

Laravel 5.7 から dump-server という機能が使えるようになりました。
(参考: [Laravel Dump Server to Ship With Laravel 5\.7 \- Laravel News](https://laravel-news.com/laravel-dump-server-laravel-5-7))

今回こちらの導入をしたので軽くまとめます。

# Laravel Dump Server とは


Laravel の `dump()` の結果をコンソールに出力させるためのツールです。

[beyondcode/laravel\-dump\-server: Bring Symfony's Var\-Dump Server to Laravel](https://github.com/beyondcode/laravel-dump-server)
![68747470733a2f2f6265796f6e64636f2e64652f6769746875622f64756d707365727665722f64756d707365727665722e676966.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10092/dbffa7f2-576e-dda5-2474-1eeb0ff8b964.gif)

Laravel のヘルパ関数の `dump()` をそのまま実行すると、 HTTP レスポンスに割り込む形で内容が出力されるので開発時に何度もブラウザ画面をリロードせざるを得なかったりしますが、Dump Server を使うと出力がコンソールに回されるため、処理を中断されずに変数の中身を確認することが出来ます。
サーバサイドの既存機能のデバッグや改修に役立つはず。



# 導入方法 (共通)

リポジトリのページの記載そのままです。
詳細はGitHub にある README を参照してください。

## 1. composer でパッケージをインストール

```sh
composer require --dev beyondcode/laravel-dump-server
```

## 2. config ファイルを生成

`config/debug-server.php` が生成されます。

```sh
php artisan vendor:publish --provider=BeyondCode\\DumpServer\\DumpServerServiceProvider
```

# 導入方法 (Laradock)

Laradock で Dump Server を使いたい場合は、上記に追加で少しいじる必要がありました。

## 3. `docker-compose.yml` を編集

php-fpm の 9912 番ポートを開けます。

```yml:laradock/docker-compose.yml
php-fpm:
  ...
  ports:
    - "9912:9912"
```

## 4. workspace を再ビルドする

```sh
docker-compose build workspace
```

## 5. `config/debug-server.php` で host を変更

```php:laravel/config/debug-server.php
return [
    // 公開された 9912 を参照するよう変更する
    'host' => 'tcp://workspace:9912',
];
```

.env で環境毎に分けるのが良さそうです。

# 使い方

artisan からサーバーを起動するだけです。

```sh
php artisan dump-server
```

起動した状態で `dump()` を実行すると、上記コマンドを実行したコンソール上で `dump` の引数に渡した値が出力されていきます。
(終了する時は `ctrl + D`)

HTML形式での出力も可能なようですが、そちらは今回は試していません。

# 参考

- [How to use outside of Vagrant Box? · Issue \#10 · beyondcode/laravel\-dump\-server](https://github.com/beyondcode/laravel-dump-server/issues/10)
「入門 監視」を読んでの監視設計まとめ 3

# アラート

監視の中でも特にうまくやる必要がある重要な部分。

## アラートの種類

* 誰かをたたき起こすためのアラート
  * 緊急な対応が求められ、システムがダウンしているもしくはしているもの
  * 電話、テキストメッセージ、アラームなど様々な方法がある 
* 参考情報としてのアラート
 * すぐに対応する必要はないが来たことは確認すべきもの
 * ジョブの失敗など 

後者が前者と関連している場合はある。

## より良いアラートの仕組みを作る方法

* アラートにメールを使うのをやめる
* 手順書を書く
* 固定の閾値を決めることだけが方法ではない
* アラートを削除し、チューニングする
* メンテナンス期間を使う
* まず、自動復旧を試す

大事だと思ったところをピックアップします。

### アラートにメールを使うのをやめる

メールは誰かをたたき起こすものでもないし、そのために使おうと思うべきではない。
その代わりにそれぞれのアラートの使い道を考える。使い道は下記の3つ

* すぐに応答かアクションが必要なアラート -> SMS,PagerDutyなどのページャに送る
* 注意が必要だがすぐにアクションはいらないアラート -> 社内のチャットなど
* 履歴や診断のために保存しておくアラート -> ログファイル

### 手順書を書く
手順書はアラートが来た時に素早く自分たちが対処できるようにするもの。
複雑になったシステムは誰しも知っているわけではなく、知識を広める良い方法になる

良い手順書は特定のサービスについて以下のような質問に答えるように書かれていること

* これは何のサービスで何をするものか
* 誰が責任者か
* どんな依存性を持っているか
* インフラ構成はどのようなものか
* どんなメトリクスやログを送っていて、それらはどういう意味なのか
* どんなアラートが設定されていて、その理由は何なのか

書くアラートには対象サービスの手順書のリンクを入れる。

ただし、アラートに対応する手順がコピーアンドペーストできるくらいなら問題解決を自動化してアラートをなくす方向にするべきである。

### アラートを削除し、チューニングする

アラートの見直しに関する項目です。
多すぎるアラートはストレスになり、だんだんと監視システムを信用しなくなっていき、最終的には無視されるようになってしまう。そうなってしまう前にアラートを減らすいくつかの方法は下記の3つ

* 初心に戻り、すべてのアラートは誰かがアクションする必要がある状態か
* 1か月間のアラート履歴を見て、どんなアラートがあり・どんなアクションをしたか・各アラートの影響はどうだったか・削除してしまえるアラートはないか・閾値を変更できるか・内容を正確にできないか
* アラートを完全に削除するために、どんな自動化の仕組みを作れるか

少しの取り組みで、アラートのノイズを大きく減らせる

# オンコール

オンコールとは何か問題が起こったときに呼び出しに答えられるようにしている担当のこと。
この後の章にもでてくる設計をちゃんと行えば減りそうな事象なのでまずはそっちを詳しく書こうと思っているのと組織的に柔軟にできることが少ないので、詳しくは割愛します。

# インシデント管理

ITILから来た概念で定義としては
**「予定していないITサービスの中断、または、ITサービス品質の低下 - ITIL 2011」**

インシデント管理のプロセスとしては以下のようなものがある
1. インシデントの認識
2. インシデントのロギング
3. インシデントの分類
4. インシデントの優先順位付け
5. 初期診断
6. 必要に応じたレベル2サポートへのエスカレーション
7. インシデントの解決
8. インシデントのクローズ
9. インシデント発生中におけるユーザコミュニティとのコミュニケーション

ITILでは定義しているがこのプロセスを採用しつつもシンプルにすると…

1. インシデントの認識(監視が問題を認識)
2. インシデントの記録(インシデントに対して監視の仕組みが自動でチケット作成)
3. インシデントの診断、分類、解決、クローズ（オンコール担当がトラブルシュート、問題を修正し、チケットんコメントや情報を添えて解決済みとする）
4. 必要に応じて問題発生中にコミュニケーションをとる
5. インシデント解決後、回復力を高めるために改善策を考える

### 振り返り
シンプルにしたプロセスの「5. インシデント解決後、回復力を高めるために改善策を考える」で
インシデントに関する議論の場を常に設けるべきである。

利害関係のあるすべての組織から人を集め、何が問題で、なぜ発生して、再発防止にはチームでどう対応していくか議論する。
そこでよくない習慣・文化として「誰かを非難するという文化」
ミスした人が罰せられたり問題を隠さざるを得ないような状況では内部に潜む法等の問題を改善することはできない
CentOS7.6でyumが「Failed to perform setup on example.jp」とお手紙が来た

# yum-cronさんからお手紙が来た
~~読まずに捨てた。~~
以下の通りの内容だった。
>Yum: Failed to perform setup on example.jp
>
>Plugins failed to initialize with the following error message: 
>Error: rpmdb open failed
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137451/9920eac7-ab96-522e-0ddd-fefb90c5f48d.png)

なーんかrpmdbが壊れてるらしい。
OSはCentOS 7.6。


# 直す
なんで壊れたかはわからない。

## ディスク容量の様子
```:console
[root@example ~]# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda4        16G  2.9G   13G  19% /
devtmpfs        236M     0  236M   0% /dev
tmpfs           245M     0  245M   0% /dev/shm
tmpfs           245M   33M  213M  14% /run
tmpfs           245M     0  245M   0% /sys/fs/cgroup
/dev/vda2       497M  284M  214M  57% /boot
tmpfs            49M     0   49M   0% /run/user/1001
tmpfs            49M     0   49M   0% /run/user/1000
```
ディスク容量は十分。

## とりあえずrpmdbを消す

```:console
[root@example ~]# ls -l /var/lib/rpm/__db*
-rw-r--r-- 1 root root  270336 Apr 18 16:15 /var/lib/rpm/__db.001
-rw-r--r-- 1 root root   81920 Apr 18 16:15 /var/lib/rpm/__db.002
-rw-r--r-- 1 root root 1318912 Apr 18 16:15 /var/lib/rpm/__db.003
[root@example ~]# rm -f /var/lib/rpm/__db*
[root@example ~]# ls -l /var/lib/rpm/__db*
ls: cannot access /var/lib/rpm/__db*: No such file or directory
```

これでもう大丈夫。

# 参考
- [yumやrpmコマンド実行時にエラーが出たときの対処 | Pocketstudio.jp log3](http://pocketstudio.jp/log3/2012/01/21/howto_recover_yum_and_rpm_errors/) - 同様の問題への対処の例
OAuth2.0 State の役割

## はじめに

[前回](https://qiita.com/naoya_matsuda/items/6033b33d8582e0e9a096)は OAuth2.0 の認可コードグラントフローの I/F についてまとめました。
その中でいきなり登場した*State*にフォーカスしてまとめます。

## アジェンダ

1. 認可コードグラント(復習)
1. CSRF のための state
1. OAuth2.0 の CSRF(Cross-Stie-Request-forgery)
1. state を使用した認可コードグラントフロー
1. まとめ

## 認可コードグラント(復習)

またか！って思われるかもしれませんが、認可コードフローはフローが長く
どこの話してるのかわかりにくいので、書いています。
(毎回すこしづつ改修してるので更に見やすくなっている...はず...)
![Authorization_code_ground_flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351271/a8405fdd-5df0-0e9d-1874-0206dba0d3c7.png)


## CSRF 対策のための State

[RFC6749](https://tools.ietf.org/html/rfc6749)の state の説明にはっきりと CSRF 対策のために導入すべき、と記載されています。

```
The parameter SHOULD be used for preventing cross-site request forgery
訳) このパラメータはcross-site request forgery(CSRF)対策のために使用すべき
```

これだけ読んで、おお、なるほど CSRF のためか。。。
とはならないですよね。
少なくとも私はなりませんでした。

ということで OAuth2.0 における CSRF とはどんなものなのかまとめます。

## OAuth2.0 の CSRF(Cross-Stie-Request-forgery)

OAuth2.0 での CSRF はいわゆる一般的な CSRF とは少し意味が違います。
OAuth2.0 における CSRF 攻撃とは、*攻撃の標的となったユーザに攻撃者のリソースを処理させる権限を与える*ことです。

実際のフローは下記のようになります。
![Cross_Stie_Request_forgery_flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351271/f5942123-6f95-00b7-19e0-f3a525d50cb5.png)


1. **攻撃者**が認可フローを開始し認可画面で認可を行う
1. 通常、*認可後*のレスポンスからリダイレクトするところを、何らかの方法でリダイレクトさせずに、止める
1. 本来リダイレクトを行う値(RedirectURI + 認可コード)を攻撃対象者に送りつけ、実行させる
1. すると攻撃者のリソースを処理することができる情報を持つトークンが、攻撃対象者に紐付けられる

このような状況下だと、以下のようなことが起こります。
攻撃対象者が Qiita への投稿をサードパーティ製のアプリで行うとします。
しかし、投稿は攻撃対象者自身のアカウントではなく、攻撃者のアカウントに投稿されてしまいます。

## state を使用した認可コードグラントフロー

上記のような問題が発生する理由は、認可したユーザと認可後のリダイレクトを行ったユーザが一緒であることが担保されていない事です。
そこで、認可画面の前後で行われている処理が同じ人であるということを担保するための値が State です。
State を使用すると、下記の図のようになります。
![Cross_Stie_Request_forgery_state_flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351271/01e5b5b5-de80-014f-1bcf-6f2b033c6e0d.png)

1. 認可リクエスト時にセッションに紐づく State を発行し、State も一緒に送ります。
1. 認可サーバは送られてきた値をそのまま返却し
1. 認可コードがリダイレクトされた際に、state の検証を行い、誤っていればリソースに対する処理を行わない

というフローになり、CSRF 攻撃を防いでいます。

## まとめ

今回は OAuth2.0 と CSRF 対策についてまとめました。
Stateを使うことでcross-site request forgery(CSRF)を防げます。
が、このやり方だと、認可プロバイダが、クライアント正しくstateを使用できているか、を判断できません。
そのため、今日ではstateの代わりにPKCEを使用して、CSRFの対策を行ったりするようです。
次回はPKCE周りについてまとめる予定です。
ElasticSearch query実行時のcacheについて

elasticsearchのquery実行時のcacheについて調べてみた備忘です。

## Node Query Cache

 - filterクエリに含まれるqueryのみquery実行時にcacheされる
 - query cacheはnodeごとに、全shardで共有される
 
[reference](https://www.elastic.co/guide/en/elasticsearch/reference/master/query-cache.html)

## request cache

 - sizeが0でないリクエストはcacheされない。0より大きい場合はクエリごとに明示的にcacheの利用を以下のように指定する必要がある。リクエストごとのrequest_cacheはindexごとの設定より優先される。

```
GET /my_index/_search?request_cache=true
{
  "size": 0,
  "aggs": {
    "popular_colors": {
      "terms": {
        "field": "colors"
      }
    }
  }
}
```

 - request cacheは、キーとしてqueryのjson全体を利用する。current timestampや乱数を利用しているscriptが含まれていると、cacheは正常に動作しない。

 - request cacheはshardごとに送られるqueryごとに格納される。

[reference](https://www.elastic.co/guide/en/elasticsearch/reference/current/shard-request-cache.html)
Python3 文字列を一文字ずつ分割

###list を用いる
例："Hello"を一文字ずつ分割したいとき

```python3:
word = list("Hello")
print(word)
>>>
['H', 'e', 'l', 'l', 'o']
```

標準入力から取得する場合

```:入力
HEllo
```

```python3:
word = list(input())
print(word)
>>>
['H', 'e', 'l', 'l', 'o']
```

##4月19日追記
@shiracamus　さんより分割代入による方法を教えていただきました。
※コメント欄参照
【忘備録】XYZ→RGBへの変換

1. XYZ表色系
2. 刺激値X,Y,Zを求める。
3. IEC（http://k-ichikawa.blog.enjoy.jp/etc/HP/js/CIEXYZ2/cie3.html）の中から、変換したい様式を選択して三原色 R,G,Bに変換。
4. 対応する波長を選ぶ。
Rails Console から ActiveStorage にファイルをアタッチする方法


ActiveStorage で色々試したみたかったので、 Console でアタッチできる方法を調べたときのメモ

Post モデルに、 has_one_attached :image してる想定

attach に File.open して渡す

```
$ bin/rail c
irb(main):001:0> post = Post.first
irb(main):002:0> post.image.attach(io: File.open("#{Rails.root}/tmp/test2.jpg"), filename: "test2.jpg", content_type: 'image/jpg')
irb(main):003:0> post.image.blob
  Post Load (0.6ms)  SELECT  `posts`.* FROM `posts` ORDER BY `posts`.`id` DESC LIMIT 1
  ActiveStorage::Attachment Load (0.4ms)  SELECT  `active_storage_attachments`.* FROM `active_storage_attachments` WHERE `active_storage_attachments`.`record_id` = 3 AND `active_storage_attachments`.`record_type` = 'Post' AND `active_storage_attachments`.`name` = 'image' LIMIT 1
  ActiveStorage::Blob Load (0.4ms)  SELECT  `active_storage_blobs`.* FROM `active_storage_blobs` WHERE `active_storage_blobs`.`id` = 9 LIMIT 1
=> #<ActiveStorage::Blob id: 9, key: "amiLLH8AjxFhUSuvfvo3mFZa", filename: "text.jpg", content_type: "image/jpeg", metadata: {"identified"=>true, "width"=>1478, "height"=>1108, "analyzed"=>true}, byte_size: 728402, checksum: "FWotSOkUUkLMxmmearPQNQ==", created_at: "2019-04-18 07:11:40">
```
Eagleでデフォルトのlibrariesディレクトリ外の.lbrファイルを読み込む

やりたいことは単純です。これだけ！…

ダウンロードしてきたサードパーティ製のライブラリファイル（*.lbr）をプロジェクトで使えるようにしたい（Add partの候補に出てくるようにしたい）。

普段Eagleを使わないので、めちゃくちゃ単純なことなのになんだかできなくて、時間をとってしまいました…。

※ デフォルトのディレクトリ（`~/Documents/EAGLE/libraries/`）はPATHに入ってるっぽいんですが、その他のディレクトリに配置している場合は、手動で追加してあげないといけません。

1. **Library Manager**を開く
2. **Available**タブの**Browse**を押し、使いたいライブラリファイル（*.lbr）を選択
3. **Available**タブの表に今選択したライブラリが表示されるので、その行選択して、右下にある**Use**をクリック
   <img width="961" alt="スクリーンショット 2019-04-18 16.43.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4404/9adc6cf4-96a4-02b6-15cb-49882e41d4d7.png">

以上で、**Add part**の選択肢に先程追加したライブラリが現れるようになります。

<img width="917" alt="スクリーンショット 2019-04-18 16.47.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4404/54719d7f-8849-405e-8630-5ef534b0386e.png">

メデタシ*2

---

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">&quot;eagle  lbr　読み込み&quot;でググると、10年前に書いた自分の記事が上位に引っかかる。なんだ、このブルーオーシャン感は・・・</p>&mdash; Naokazu Terada (@naokazu_terada) <a href="https://twitter.com/naokazu_terada/status/1118772842022047745?ref_src=twsrc%5Etfw">2019年4月18日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ググった結果過去の自分の記事にあたるということもたまにありますが、今回もそうでした（知りたかった内容は微妙に違いますが）。

ただ、[この10年前の記事](http://labs.karappo.net/interact/index.php?itemid=223)では下記のように書いてますが、現在はもうそんなことはないようです。せっかくなので、補足しておきます。

> lbrファイルの頭文字が小文字でないと認識されません。
PythonのtelnetlibでNW機器(Cisco)にリモートログイン

#NW機器(Cisco)にtelnetログイン
複数のNW機器(主にCisco)にtelnetでログインしてconfigファイル出力し
ホスト名.txtに書き込む。

採取にあたってホスト名とIPアドレスを紐づけたファイルを用意しておく。  

ファイル記載例： 
host 1.1.1.1
hoge 2.2.2.2


```python:python.py
# -*- coding: utf-8 -*-

import telnetlib

clients = {}

def main():
    clients = read_file()
        
    for client in clients:
        client_ip_address = clients[client]
        show_run = telnet(client_ip_address)
        wrire_file(client, show_run)


def read_file():
    with open('client_ip.txt', mode='r') as f:
        ftext = f.readlines()
        
        for ip_address in ftext:
            field_split = ip_address.split(' ')
            hostname = field_split[0]
            ip_address = field_split[1]       
            rep_ip_address = ip_address.replace('\n', '')
            clients[hostname] = rep_ip_address

        f.close()
        
    return clients

def wrire_file(client, show_run):
    with open(client + 'txt', mode='w') as wf:
        wf.writelines(show_run)
    wf.close()


def telnet(client_ip_address):
    tn = telnetlib.Telnet(client_ip_address)

    tn.read_until(b'Password:')
    tn.write(b'cisco' + b'\n')
    tn.read_until(b'>')
    
    tn.write(b'en' + b'\n')

    tn.read_until(b'Password:')
    tn.write(b'cisco' + b'\n')

    tn.read_until(b'#')
    tn.write(b'ter len 0' + b'\n')
    tn.write(b'show run' + b'\n')
    
    tn.read_until(b'#')
    tn.write(b'exit' + b'\n')
    
    show_run = tn.read_all().decode('ascii')
    return show_run

    tn.close()
        

if __name__ == '__main__':
    main()

```
Library not loaded: libmysqlclient.18.dylib (LoadError) などが起きた時

# 状況
Mac OS で Rails の開発環境を構築しているとして、`rails s` などで rails server を起動しようとした時に `Library not loaded: libmysqlclient.18.dylib (LoadError)` が発生して起動しないことがある。
よくある解決方法は、Mysql を再インストールしよう的な内容もあるが、原因と対処についてメモとして残しておく。

# なぜ発生するのか?

概ね下記の仮設に該当するだろう
- Homebrew などで Mysql を version up / uninstall / install した
- 複数の rails アプリを local 環境で bundler によって管理しているが、ある bundler 環境で構築した mysq12 の設定と、別な bundler 環境に存在する mysql2 の設定が異なり、各々異なった mysql version のクライアントライブラリを指定している。
    - 以前 rails アプリを bundler で構築して、新規に rails アプリをインストールしたがその時に mysql の version を追加したなど

# 対策

## 方針
そもそも `libmysqlclient.18.dylib` なんて存在するかどうかは保証されない。また、わざわざそのために Mysql をバージョンダウンするのも不毛である。mysql2 gem を install する時に複数あるかもしれない mysql のどのバイナリを使用して install するのかを指定するだけである。

from rubydoc ( https://www.rubydoc.info/gems/mysql2/0.5.2#Configuration_options )

> --with-mysql-config[=/path/to/mysql_config] - Specify a path to the mysql_config binary provided by your copy of MySQL. The mysql2 gem will ask this mysql_config binary about the compiler and linker arguments needed. This option is mutually exclusive with --with-mysql-dir.

## 実行
homebrew で install した version が @5.x などにはいるので、適宜読み替えること。

```sh
bundle exec gem uninstall mysql2
bundle config build.mysql2 --with-mysql-config=/usr/local/Cellar/mysql\@5.x/5.x.xx/bin/mysql_config
bundle exec bundle
```

# 参考
https://stackoverflow.com/questions/7139210/install-the-mysql2-gem-for-a-specific-mysql-client-version
https://www.rubydoc.info/gems/mysql2/0.5.2#Configuration_options
Progateで学べるReactの内容を整理してみる（前半）

アプリとかこれから作りたいんだったらReactとかReact Nativeがいいよーって話を聞いたので、ProgateのReactコースを受講してみることにしました。
https://prog-8.com/languages/react

せっかくなので、自分に定着させることを目的とするアウトプットとして、無料会員で利用できる「React学習コースⅠ」を要約してみます。
すでに会員の方はこちらを補足資料として、まだの方はこの機会に会員登録をして受講してみてもらえると、学習仲間ができて嬉しいです。

なお私自身がプログラミング初心者であり、間違いに気づいてない部分も多々あるかと思いますので、お気づきの点あればご指摘いただけると幸いです。

##React学習コースⅠ
###Reactとは
JavaScript（JS）のライブラリ。
JSで記述されたrenderメソッドのreturn内に、HTMLとほとんど同じ**JSX**を記述することでブラウザに表示させることができる。

下記`<div>`タグ内がJSX

```react:App.js
import React from 'react'; // Reactを呼び出す
class App extends React.Component {
	render() {
		return (
			// JSX開始
			<div>
				<h1>Hello World</h1>
				<p>Reactを学ぼう</p>
			</div>
			// JSX終了
		);
	}
}
export default App;
```

###JSXとHTMLの違い・JSXの注意点
return内に入れられるのは単一の要素。上記でいうとdivタグの階層には
2つ以上並列で入れることができない。その配下には（上記のh1やpタグのように）入れられるので、divタグのような1つの要素内に記述する。

imgタグなど単独タグ・空要素は`<img src='https://www.jp/abc.jpg' />`のように、末尾にスラッシュを入れてタグを閉じておく必要がある。

###JSXにJSを埋め込む
render内でもreturnの外にはJSを記述できる。記述したJSは中かっこ`{ }`で囲むことでJSX内に埋め込むことができる。

```react:App.js
	render() {
		const text = 'Hello World'; // JSで定義
		return (
			<div>
				<h1>{ text }</h1> {/* 中かっこで囲って埋め込む */}
				<p>Reactを学ぼう</p>
			</div>
		);
	}
```

なお上記のように、コメントタグはJSとJSXで書き方が異なる。

###イベントとstate
イベント：指定したタイミングで実行できる処理
state：ユーザーのアクションを受けて変化する値

```react:イベント.js
render() {
	<button 'イベント名'= {() => { '処理' }}> </button>
}
```



まずは前半のここまで。
Craft CMS で特定のエントリを取得する

Craft CMS のテンプレートでは、最低でも5つの方法で特定のエントリを取得できる。

## エントリ ID で絞り込む

```twig
{% set entry = craft.entries.id(123).one() %}
```

## スラグで絞り込む 

```twig
{% set entry = craft.entries.slug('event1234').one() %}
```

異なるセクションであれば同一のスラグをセットできるため、以下のようにセクション自体を絞り込んでしまってもよい。

```twig
{% set entry = craft.entries.section('event').slug('event1234').one() %}
```

## タイトルで絞り込む

```twig
{% set entry = craft.entries.title('Craft CMS の管理画面 URL を変更する').one() %}
```



## URI で絞り込む

```twig
{% set entry = craft.entries.uri('news/123').one() %}
```

ドメインを除く、パスを指定。

## 任意のフィールドの値で絞り込む

```twig
{% set entry = craft.entries.modelNumber('ABCD1234').one() %}
```

ただし、型番を入力するためのフィールドを `プレーンテキスト` タイプでハンドル名 `modelNumber` として作成しているものとする。

## 参考：プラグイン内から特定エントリを取得する

```php
use craft\elements\Entry;

$entry = Entry::find()->id(123)->one();
```

プラグイン内で特定のエントリを取得する場合でも、似たような記法で記述できる。
【WinActor】ディクショナリやデータ一覧の代替案

WinActorでディクショナリやデータ一覧が使えずお困りの方は、参考にしていただけると幸いです。

ファイルパスやセルの位置などをノードに直接指定するのは、セルの位置が変わった時に変更の手間と変更漏れリスクがあるので、Excelで設定マスタを外出しにして、初期処理として読み込んだ値を変数に格納する運用にしています。
UiPathのディクショナリのような運用がWinActorでもできることを期待していましたが、残念ながら実現できないようです。
データ一覧に設定マスタをインポートしても、変数に格納される訳ではありませんでしたので、別の方法で作成しました。

■用意する変数
・設定マスタパス
・設定マスタ列
・設定マスタ行
・設定マスタセル位置
・処理結果
・設定マスタのKey列
※少し手間ですが、最初だけですので頑張りましょう！

１．設定マスタを用意する
下図のようなKey-Valueとなるマスタを用意する。
![設定マスタ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398977/43432508-3821-bf3b-64ab-52356db87e47.png)

２．Key列を1つずつ変数に登録する。
少し手間ですが、最初だけですので頑張りましょう！

３．設定マスタを選択
使用ノード：選択ボックス
・ファイル選択結果：設定マスタパス

４．設定マスタ選択判定
使用ノード：分岐
条件：設定マスタパス <> 空白
※空白だった場合はシナリオ停止ノードを入れました。

５．設定マスタ列初期化
使用ノード：変数値設定
・変数名：設定マスタ列
・値：Value列(例ではDを設定)

６．設定マスタ行初期化
使用ノード：変数値設定
・変数名：設定マスタ行
・値：ヘッダを除く一番上の行(例では3を設定)

７．設定マスタセル位置初期化
使用ノード：07_文字列操作\03_連結\文字列の連結(２つ)
・文字列1：設定マスタ列
・文字列2：設定マスタ行
・連結結果：設定マスタセル位置

８．Valueの取得
使用ノード：18_Excel関連\12_書式\Excel操作(値の取得)
・ファイル名：設定マスタパス
・シート名：
※空白だとアクティブなシートが対象になります
・セル位置：設定マスタセル位置
・格納先変数：Keyとして登録した変数

９．次の行へ
９－１．設定マスタ行カウントアップ
使用ノード：カウントアップ
・計算結果：設定マスタ行
・加算値：1

９－２．設定マスタセル位置設定
使用ノード：07_文字列操作\03_連結\文字列の連結(２つ)
・文字列1：設定マスタ列
・文字列2：設定マスタ行
・連結結果：設定マスタセル位置

８と９を設定マスタの最後まで繰り返す
※９は設定マスタに登録している分だけ必要なので、サブルーチン化して呼び出す形にしたほうが便利です。

９を用意した利点は、開発中に、設定マスタの見直し(行の追加、削除)があった場合に、流動的に対応できることです。
セル位置を直接指定してしまうと、場合によっては全行ズレてしまうことになりかねません。

１０．設定マスタを閉じる
使用ノード：18_Excel関連\01_ファイル操作\Excel操作(保存なしで閉じる)
・ファイル名：設定マスタパス
・実行結果：処理結果

以上が、WinActorによるディクショナリやデータ一覧の代替案でした。
しつこいようですが、最初の登録さえしてしまえば、後はとても楽になります。
Ruby クラス と インスタンス

#クラスとは
とある種類のオブジェクトの属性とメソッドをまとめて定義しておく型のようなもの
例えば、、、人クラスの場合
【共通の属性】
名前、年齢、性別、職業、身長、国籍
【共通のメソッド】
「話す」「歩く」「食べる」「考える」「笑う」「泣く」
上記のような型をあらかじめ定義しておけば、この型に沿って個別のオブジェクトを効率良く生産することができます。
#インスタンスとは
オブジェクト同士で共通しそうな部分をクラスという型で定義します。
そこで、クラスから生まれたオブジェクトのことをインスタンスといいます。
例えば、、、人クラスから生まれたインスタンスの場合
【共通の属性】と【共通のメソッド】を全て受け継いている。
##クラスの定義の仕方

```
class 頭文字半角英大文字クラス名
  # 変数/メソッドの定義
end
```
##新しくインスタンスを生成する

```
頭文字半角英小文字インスタンス名 = クラス名.new
```
例えば、、、人クラスからインスタンスを生成する場合

```
class People
end
people = People.new
```
##クラスメソッド

```
 class クラス名
    def self.メソッド名
      # 処理
    end
  end
```
##インスタンスメソッド

```
class クラス名
    def メソッド名
      # 処理
    end
  end
```
###クラスメソッドとインスタンスメソッドの違い
クラスメソッドは、クラスに対して使用し、クラスで共通の情報を使用する。
インスタンスメソッドは、インスタンスに対して使用し、インスタンスごとに異なる個別の情報を使用します。

| 特徴 | インスタンスメソッド | クラスメソッド |
|:-----------|------------|------------|
| 定義方法 | メソッド名の前にselfはつけない | メソッド名の前にselfをつける |
| 用途 | インスタンスごとの属性を用いる場合 | 属性は関係のない共通の処理 |
| 呼び出せるオブジェクト | クラスのインスタンス | クラス自身 |

#クラス変数とインスタンス変数について
##クラス変数とは？
クラス全体で使用できる変数です。クラス内であればどこでも使えるのでクラスメソッド、インスタンスメソッドの両方で使うことが出来ます。クラスを通して、値が共通の情報に使用します。

```
@@クラス変数 = 値
```

##インスタンス変数とは？
共通の属性としてインスタンスに定義できる変数です。その値は、個々のインスタンスによって別々に設定できます。

```
@インスタンス変数 = 値
```
##initializeメソッド
Rubyにあらかじめ設定されているメソッドで、インスタンスの生成と同時に実行したい処理を自動的に実行できます。

```
class クラス名
    def initialize
      # 生成のときの処理
      puts "クラス名のインスタンスが生成されました" # 例
    end
  end

  インスタンス = クラス名.new
```
上記のインスタンスが生成されたときにinitializeの中が呼び出される。
##クラスの継承

```
class 子クラス < 親クラス
end
```
React Context APIをつかってmaterial-uiをつかいやすいようにしてみた

material-uiのコンポーネントにbool値をうまく渡せるようにしたかった。
Slideにstateを渡していい感じに動きができる


create-react-appを使って環境を作る



まずはApp.jsから

```javascript:src/App.js
import SimpleSlide from "./Slidecard";
import SlideContext from "./context";

import Switch from "@material-ui/core/Switch";

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      checked: false
      //handleChange: this.handleChange
    };
  }
  handleChange = () => {
    this.setState(state => ({ checked: !state.checked }));
  };

  render() {
    return (
      <SlideContext.Provider value={this.state}>
        <Switch
          checked={this.state.checked}
          onChange={this.handleChange}
          aria-label="Collapse"
        />
        <SimpleSlide />
      </SlideContext.Provider>
    );
  }
}
```


つぎにcontextをつくって、

```javascript:src/context/index.js
import React from "react";

const SlideContext = React.createContext();
export default SlideContext;
```


これはmaterial-ui.comからコピペして少しリファクタリングしたやつ。
Consumerでcheckedを受けとってる。

```javascript:src/Slidecard.js
import React from "react";
import PropTypes from "prop-types";
import { withStyles } from "@material-ui/core/styles";
import Switch from "@material-ui/core/Switch";
import Paper from "@material-ui/core/Paper";
import Slide from "@material-ui/core/Slide";
import SlideContext from "./context";

const styles = theme => ({
  root: {
    height: 180
  },
  wrapper: {
    width: 100 + theme.spacing.unit * 2
  },
  paper: {
    zIndex: 1,
    position: "relative",
    margin: theme.spacing.unit
  },
  svg: {
    width: 100,
    height: 100
  },
  polygon: {
    fill: theme.palette.common.white,
    stroke: theme.palette.divider,
    strokeWidth: 1
  }
});

class SimpleSlide extends React.Component {
  // state = {
  //   checked: false
  // };

  render() {
    const { classes } = this.props;
    // const { checked } = this.state;

    return (
      <SlideContext.Consumer>
        {({ checked }) => {
          return (
            <div className={classes.root}>
              <div className={classes.wrapper}>
                <Slide direction="up" in={checked} mountOnEnter unmountOnExit>
                  <Paper elevation={4} className={classes.paper}>
                    <svg className={classes.svg}>
                      <polygon
                        points="0,100 50,00, 100,100"
                        className={classes.polygon}
                      />
                    </svg>
                  </Paper>
                </Slide>
              </div>
            </div>
          );
        }}
      </SlideContext.Consumer>
    );
  }
}

SimpleSlide.propTypes = {
  classes: PropTypes.object.isRequired
};

export default withStyles(styles)(SimpleSlide);
```


https://codesandbox.io/embed/github/takanorifukuyama/MUI-SimpleSlide-contextAPI/tree/master/
https://github.com/takanorifukuyama/MUI-SimpleSlide-contextAPI
Android Studio 3.4.0に上げたら怒られたこと

## Android Studio。あげられるようになったら上げるだろ？
怒られた..

```
Gradle DSL method not found: 'destination()'
```
😹

## 原因

> The ConfigurableReport.setDestination(Object) method has been deprecated and is scheduled to be removed in Gradle 5.0. Please use the method ConfigurableReport.setDestination(File)

Android Studio 3.4.0に上げた際にこの部分のDeprecatedが許容してくれなくなっていた

なので、以下のように直した

既存↓

```groovy
jacocoTestReport {
    group = "Reporting"
    reports {
        xml.enabled true
        html.enabled true
        csv.enabled false
        xml.destination "${buildDir}/reports/coverage"
        html.destination "${buildDir}/reports/coverage"
    }
}
```

解決↓

```groovy
jacocoTestReport {
    group = "Reporting"
    reports {
        xml.enabled true
        html.enabled true
        csv.enabled false
        xml.destination file("${buildDir}/reports/coverage")
        html.destination file("${buildDir}/reports/coverage")
    }
}
```

file()でくくってあげることで、型を変えるってだけでした。
R8関連で躓くかと思いきや、まさかのこれ。

deprecated放置したのがいけないんですけどね。😇

ちなみにこういう風に書いている場合も同じくfile()で括ってあげればOK👍

```groovy
        xml.enabled true
        html.enabled true
        csv.enabled false
        xml{
            destination "${buildDir}/reports/coverage"
        }
        html{
            destination "${buildDir}/reports/coverage"
        }
```

good luck
作ったpythonの仮想環境をjupyter labに認識させる方法

仮想環境の中にipykernelを入れるだけ。
仮想環境中で下のコマンドを打てば良い。


```terminal

pip install ipykernel
python -m ipykernel install --user --name xxx --display-name "xxx"
```

↑xxxという仮想環境をjupyter環境で使用したい場合
pyenv, pipenv 環境でjupyter notebook使う時にsqliteに関するエラーが出たとき

## 環境
- ubuntu 18.04
- pyenv 1.2.9-2-g6309aaf2
- pipenv, version 2018.11.26

### jupyter 関連
- jupyter 1.0.0
- jupyter-core 4.4.0
- ipywidgets 7.4.2

## エラー

pipenvでpython 3.6.8を使ってjupyter notebookを起動しようと
しているところ。

```shell-session
(someenv)$ jupyter notebook
Traceback (most recent call last):
  File "/home/hoge/.local/share/virtualenvs/someenv-EUFWfC8N/lib/python3.6/site-packages/notebook/services/sessions/sessionmanager.py", line 10, in <module>
    import sqlite3
  File "/home/hoge/.pyenv/versions/3.6.8/lib/python3.6/sqlite3/__init__.py", line 23, in <module>
    from sqlite3.dbapi2 import *
  File "/home/hoge/.pyenv/versions/3.6.8/lib/python3.6/sqlite3/dbapi2.py", line 27, in <module>
    from _sqlite3 import *
ModuleNotFoundError: No module named '_sqlite3'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/hoge/.local/share/virtualenvs/someenv-EUFWfC8N/bin/jupyter-notebook", line 6, in <module>
    from notebook.notebookapp import main
  File "/home/hoge/.local/share/virtualenvs/someenv-EUFWfC8N/lib/python3.6/site-packages/notebook/notebookapp.py", line 86, in <module>
    from .services.sessions.sessionmanager import SessionManager
  File "/home/hoge/.local/share/virtualenvs/someenv-EUFWfC8N/lib/python3.6/site-packages/notebook/services/sessions/sessionmanager.py", line 13, in <module>
    from pysqlite2 import dbapi2 as sqlite3
ModuleNotFoundError: No module named 'pysqlite2'
```


## 解決策
原因はsqliteが入っていなかったからなのだが、pythonのインタプリタも再インストしないといけないのが注意点。

### 1.sqlite入れる

https://stackoverflow.com/questions/29022473/importerror-no-module-named-pysqlite2-when-running-tests-in-python-3-ubuntu

ここを参考にしてsqliteとその依存を入れる。

```shell-session
$ sudo apt install libsqlite3-dev libreadline6-dev libbz2-dev libssl-dev libsqlite3-dev libncursesw5-dev libffi-dev libdb-dev libexpat1-dev zlib1g-dev liblzma-dev libgdbm-dev libmpdec-dev
```

### 2.pythonインタプリタ一旦消す
pythonインタプリタのsetup時にsqlite関連のパッケージがあると、使えるようにしてくれるみたいなので、pyenvで使おうとしているpythonインタプリタを一旦消していれ直す。

```shell-session
$ pyenv versions
* system (set by /home/hoge/.pyenv/version)
  3.6.8
  3.7.2
$ pyenv uninstall 3.6.8
pyenv: remove /home/hoge/.pyenv/versions/3.6.8? y
$ pyenv versions
* system (set by /home/hoge/.pyenv/version)
  3.7.2
```

### 3.入れ直す
入れ直す。（Pipfileが書いてあるとする。）

```shell-session
$ pipenv install
Warning: Python 3.6.8 was not found on your system...
Would you like us to install CPython 3.6.8 with pyenv? [Y/n]: Y]\
Error: invalid input
Would you like us to install CPython 3.6.8 with pyenv? [Y/n]: Y
Installing CPython 3.6.8 with pyenv (this may take a few minutes)...
✔ Success! 
```

うごいた。

```shell-session
$ pipenv shell
Launching subshell in virtual environment...
$ jupyter notebook
[I 15:23:07.943 NotebookApp] Writing notebook server cookie secret to /run/user/1000/jupyter/notebook_cookie_secret
[I 15:23:08.055 NotebookApp] Serving notebooks from local directory: /home/hoge/Works/someenv
```

## おわりに
ぶっちゃけpipenv と pyenvはこのエラーにあんま関係ない。この辺の使って真っさらな環境に新しくjupyter notebook入れようとすると起きやすいとおもう。
Win10でGoogleIMEだとキーボードが英語キーボードと認識されてしまう……

という問題が発生していて
Google先生で調査しているのですが
見つからないので忘備録として記事表記失礼します。

いったんアンインストールしてGoogleIMEインストールがいいのかな？？？
でも辞書に一杯登録したんだよな……
Vimにプロジェクトツリーを追加する。(mac)

vimってプロジェクトツリーを見ることできないのかなーと思って調べていたんですが、できるみたいなので早速導入。
今回はNERDTreeというプラグインを使用しました。

基本的にはこちらの方の記事を参考にさせて頂きました。
https://qiita.com/zwirky/items/0209579a635b4f9c95ee
ただ、一部うまくいかなかった部分があるのでメモ置き。

1, NEOBUNDLEのインストール

```
$ curl https://raw.githubusercontent.com/Shougo/neobundle.vim/master/bin/install.sh | sh
```

2, ~/.vimrcに以下を記述。

```
set nocompatible
filetype off

if has('vim_starting')
    set runtimepath+=~/.vim/bundle/neobundle.vim
    call neobundle#rc(expand('~/.vim/bundle/'))
endif

"insert here your Neobundle plugins"
NeoBundle 'scrooloose/nerdtree'

filetype plugin indent on
```


3, バンドルインストール

```
:NeoBundleInstall
```

ここまでやっていけると思ったんですが、vimを開こうと思ったら以下のようなメッセージが表示されました。

```
[neobundle] neobundle#rc() is removed function.
[neobundle] Please use neobundle#begin()/neobundle#end() instead.
[neobundle] neobundle directory is empty.
[neobundle] `NeoBundle` commands must be executed within a neobundle#begin/end block.  Please check your usage.
```

要は
「neobundle#rc()って書き方は止めたから、代わりに#begin()/neobundle#end()って書き方でやってくれよ。あと、NeoBundleコマンドはその中に記述してね」
ってことらしい。

なので、2の記述を以下に変更

```
set nocompatible
filetype off

if has('vim_starting')
    set runtimepath+=~/.vim/bundle/neobundle.vim
    call neobundle#begin(expand('~/.vim/bundle/'))
      NeoBundle 'scrooloose/nerdtree'
    call neobundle#end()
endif
filetype plugin indent on

```

これで再度vimを開き、:NERDTreeToggleと入力したら表示されるようになりました。
Bitbucketでフォーク先から飛んできたプルリクをローカルで確認したい

探したら公式ドキュメントがありました。
https://ja.confluence.atlassian.com/bbkb/how-to-locally-fetch-and-checkout-a-pull-request-724402529.html

大事なところだけ抜粋するとGitコマンドは

```
git fetch <フォーク先リポジトリのURL> <ブランチ名>
```
です。例えば

* フォークしたユーザー名：hoge
* リポジトリ名：fuga
* ブランチ名：piyo

の場合コマンドは

```
git fetch https://bitbucket.org/hoge/fuga piyo
```
になります。
ブランチのURLが`https://bitbucket.org/hoge/fuga/branch/piyo`だからと言って

```
git fetch https://bitbucket.org/hoge/fuga/branch/piyo
```

とすると痛い目を見るのでお気を付けください。