OmniAICreator/Qiita-1.07M huggingface dataset:
英語

```
Consumers should not eat any romaine lettuce product, including "whole heads of romaine, hearts of romaine, and bags and boxes of precut lettuce and salad mixes that contain romaine, such as spring mix and Caesar salad.
```

```
Consumers should not eat any romaine lettuce product,
 S                     V                 o

非制限用法

, including 

, such as
```


```
A similar outbreak caused by contaminated romaine lettuce occurred in December, Gottlieb said, and affected the United States and Canada. 


非制限用法？
caused by



```
AWS Cloud9 でgithubの設定をする

# 環境
- AWS Cloud9 (シンガポールリージョンのEC2上で動作）
- Amazon Linux2
- bash

# できるようになりたいこと
SSH認証でgithub上のリモートリポジトリにpushできるようにする

# 手順
普通のLinux環境における設定とおなじ
## 公開鍵の設定
### キーペアを作成する
いくつかの記事だと、デフォルトでキーペアがすでに存在していると書かれているものもあったが、現在はない様子
なので、githubに登録する用の秘密鍵/公開鍵のペアを作成する

```
#cloud9上のbash
$ cd ~/.ssh
$ ssh-keygen
#ここでキーを出力するディレクトリやパスワードを聞かれるのでよしなに入力する
```

### 作成した公開鍵をコピーしてgithubに登録する
1. 「Settings」→「SSH and GPG keys」→「New SSH key」ボタンをクリック
2. titleにわかりやすい名前（例：cloud9など）、Keyにコピーした公開鍵をペーストする
3. 「Add SSH Key」をクリック
4. 公開鍵の登録完了

## リポジトリの設定
### リポジトリをclone
リポジトリをcloneするときは、「Use SSH」から`git@github.com:username/repository_name.git`をコピーしてcloneする

```
$ git clone git@github.com:username/repository_name.git
#このとき、先ほどssh-keygenで生成した際に入力したパスワードを聞かれるので入力する
#パスワードが一致すればgit cloneがはじまる
```

### 設定されているリモートリポジトリの確認
リモートリポジトリの確認
先ほどcloneしたリポジトリが設定されているはず

```
$ git remote -v
origin  git@github.com:username/repository_name.git (fetch)
origin  git@github.com:username/repository_name.git (push)
```
### コミットしてみる
なにもcommitするものがなければ、`--allow-empty`オプションをつけてcommitする

```
$ git commit --allow-empty
$ git push origin master
```
これで、githubのユーザ名やパスワードを聞かれずにリモートリポジトリにpushできればOK!
[cocoa][swift]BUKURO.swift 2018-02 を振り返る

<p>2018年2月16日（金）の夜間、東京都豊島区の<a href="http://co-forest.com/">池袋コワーキングスペース OpenOffice FOREST</a>におきまして、「BUKURO.swift 2018-02」を開催致しました。</p>

<p>今回の勉強会は、MOSAがNPO法人を解散して任意団体になるということで、新たな体制に移行するための準備チームのメンバーでスタートアップイベントを行うにあたって、準備的な意味合いもあって共催としました。</p>

# 勉強会について
<ul>
<li>Cocoa勉強会 関東 Swift分科会 です。</li>
<li>ほぼ毎月、池袋コワーキングスペース OpenOffice FOREST で開催してます。</li>
<li>macOS/iOS/watchOS/tvOSプログラマーのための勉強会です。</li>
<li>プログラムに関する知識や経験を共有を目的としています。</li>
<li>会の活動内容や発表資料、サンプルコードは公開を前提としています。</li>
<li>申し込みは、connpassから。<br /><a href="https://cocoa-kanto.connpass.com/">https://cocoa-kanto.connpass.com/</a></li>
</ul>

# 概要
<ul>
<li>発表資料は<a href="https://cocoa-kanto.connpass.com/event/75430/">connpassページ</a>からどうぞ！</li>
<li>会場の様子は、ハッシュタグ『#cocoaswift #cocoastudy #bukuroswift』でtweetしています。</li>
</ul>

# デザイン・パターン
<p>iOSアプリケーション開発の現場ではデザインパターンが話題となっていますが、最近の傾向では、Microsoftの.NETフレームワーク由来のものが流行っているようです。<br />
でも、そもそも異なる環境向けのものを無理やり適用しようとしているように見えますし、そこで説明されるMVCはCocoaとは異なるものです。<br />
この発表は、とはいっても現場で.NET由来のデザインパターンが選択されたら従うしかないということで、それぞれのフレームワークの内容を発表者が理解するために、資料化したものです。</p>

# NSDcoument複数ファイルフォーマット その2
<p>意図せず、今回は『Document-based Application特集』になってしまいました。<br />
発表者が製作中のアウトラインプロセッサにOPML形式ファイルのサポートを追加する際の試行錯誤の発表です。<br />
自動保存機能が追加された事による「Save To…」と「Export…」のメニュー項目問題が勉強になりました。</p>

# NSDcoument複数ファイルフォーマット その3
<p>新規ドキュメントの機能にテンプレートを組み込むお話です。<br />
これについては、他で説明されているのを見たことがないので、貴重だと思います。</p>

# Developer’s Tech Lab『Document-based Applicationについて』
<p>MOSA de BB掲示板であった質問を切っ掛けに、取り上げることにして見ました。<br />
ホストも興味がある項目なので勉強になったのと、参加者のコメントから、認識に間違いがないか確認できたのがよかったです。</p>

# BUKURO.makers『コピー機を作る』
<p>BUKURO.swiftの運営が軌道に乗ってきたということで、今後、色々と挑戦して見たいと思っています。その一つに、ある分野に特化した勉強会で、以下を考えています。</p>
<dl>
<dt>BUKURO.makers</dt><dd>ものづくり</dd>
<dt>BUKURO.games</dt><dd>ゲーム開発</dd>
<dt>BUKURO.ai</dt><dd>人工知能</dd>
<dt>BUKURO.blockchain</dt><dd>ブロックチェーン</dd>
</dl>
<p>今回はその第一弾でMakers関連をやってみました。将来的には独立した勉強会にしたいのですが、まだ早いと思うので、BUKURO.swiftに間借りしてやってみました。<br />
その第一回の発表を参加された方が事前に用意していくれたのが嬉しいです。<br />
なんと、コピー機を自作するという内容でした。今後が楽しみです。</p>

# BUKURO.makers『Arduino UNOにESP-WROOM-02をつなぐ』
<p>水位計を自作するため、Auduino UnoにWiFiシールドを繋ぐという発表でした。</p>

【関連情報】
<a href="https://qiita.com/advent-calendar/2018/cocoa">Cocoa Advent Calendar 2018</a><br />
<a href="https://cocoa-kanto.connpass.com/event/75430/">BUKURO.swift 2018-02</a><br />
<a href="https://cocoa-kanto.connpass.com/">Cocoa.swift</a><br />
<a href="https://www.facebook.com/groups/cocoa.kanto/">Cocoa勉強会 関東</a><br />
<a href="http://www.bitz.co.jp/weblog/">Cocoa練習帳</a><br />
<a href="https://qiita.com/m_yukio">Qiita</a><br />
fortran+MPIコーディング入門(4) オブジェクト指向コードの並列化 

前回まででMPIの基本的機能は説明しました。ですが通信については組み込み型のみを対象としていました。

MPIは1991年に開発されており、当時のfortranの仕様であった手続き型パラダイムで書かれています。その後オブジェクト指向パラダイムが主流となり、fortranもfortran2003でオブジェクト指向がサポートされました。オブジェクト指向言語ではクラスとそのインスタンスを対象にプログラミングします。今回はそのようなクラスをMPIで扱う方法を解説します。

目次
1. [並列処理とは](https://qiita.com/Bluepost59/items/58e111fe486c4aeb48bf)
1. [プロセス並列の基本] (https://qiita.com/items/5cce1174ac48367948bc)
2. [集団通信] (https://qiita.com/Bluepost59/items/f1871b37669b38352a7c)
3. [1対1通信] (https://qiita.com/Bluepost59/items/f1426e8cb098d6632402)
4. オブジェクト指向コードの並列化 ←今ココ

# クラスを通信する
## MPIデータ型
MPIで通信するためには、前回までで述べた通り、送受信データの型を指定する必要があります。それはMPIで定義された型でなければならず、integerやdouble precisionなど組み込み型のみが定義されています。

つまり、**自分で定義したクラスはそのままではMPIコマンドを使って通信することができません**。そのため自分で「クラスのすべてのメンバを通信してやる」というコマンドも用意してやる必要があります[^1]。

## 実装する場所
サブルーチンの実装の場所については、次のようにいくつかの選択肢が思いつきます。

1. 通常のモジュールサブルーチンとして。
1. 通信するクラスをコンポジットするクラスのメンバ関数として。<br>例えば、particleをメンバに持つsystemクラスのメンバ関数として。
1. 通信するクラスのメンバ関数として。

基本的にはどの方法でも実装できます。通信するクラスのメンバ関数にするのは少し難しそうな気もしますが、特に問題なく動作します。

# 例
例として、次のクラスを通信します。

```fortran
  type smp
     integer :: id
     double precision :: xx
     character(len=40) :: name
   contains
     procedure :: return_id => smp_return_id
     procedure :: bcast => smp_bcast
  end type smp
```

## bcastをメンバとして実装する

```fortran
subroutine smp_bcast(self,ierr)
    class(smp) self
    integer :: ierr
    
    call mpi_bcast(self%id, 1, mpi_integer, 1, mpi_comm_world, ierr)
    call mpi_bcast(self%xx, 1, mpi_double_precision, 1, mpi_comm_world, ierr)
    call mpi_bcast(self%name, 40, mpi_character, 1, mpi_comm_world, ierr)

end subroutine smp_bcast
```

MPIだからといって大変なところは、ierrを作らないといけないことくらいしかありません。実際のところ、MPIコマンドの組み立て上通信されるクラスのメンバにするよりは、それをコンポジットにするクラスのメンバとして実装するのが設計しやすいと思います。

# 注意点
* クラスを使う場合、クラスは別ファイルのmoduleとして宣言して分割コンパイルする場合も多いと思いますが、use文でonlyを使わない場合、mpif.hのincludeは一番最初にコンパイルするものだけにしないと多重取り込みでエラーが出ます。

* fortranのcharacter型はC言語のように中身は配列なので、配列同様の扱いをする必要があります。例えばallocateしないで使ったりはできません。

[^1]: C++のboostのmpiでは構造体やクラスも送れるので、ひょっとするとうまくやるとfortranでもできるのかも知れません。僕はよく知りません。

[^2]: 先に述べている通り、MPIという規格は20年以上前に設計されたもので、当時はまだ手続き型言語が主流だったのでMPIコマンドもそれに倣ったものになっています。<br>私感ですが、**手続き型とオブジェクト指向型の最大の違いは「コマンドの主語」です**。手続き型ではコマンドは命令で主語はコンピュータです。そのためMPIコマンドも（mpi_という接頭辞を除けば）sendやbcastといったコンピュータが行う処理になっています。<br>それに対して、**オブジェクト指向型ではコマンドの主語はオブジェクトです**。各クラスが何か動作をするという書き方で書きます。
データ分析のためのpython入門

#### pythonの基礎
- python初心者の方向けに基礎文法をまとめてみました。このあとはデータの前処理や可視化、統計分析などの記事も書きたいと思います。またこの記事ではpythonのjupyter notebook環境で動かすことを前提としたpython3のコードを書いています.


### 環境構築について
- ローカルに環境構築する方法はAnacondaを用いるのがオススメ。anacondaは結構重いのでインストールに時間がかかります。
- anacondaのインストール方法や詳細については下記URLを参照
- [Anaconda](https://knowledge.sakura.ad.jp/17235/)

### jupyter notebookとは
- ノートブックと呼ばれるファイルにpythonのコードを書いていきます。
- プログラム、実行結果、コメント文、図を表示できる
- データサイエンティストの間では最もよく使われているらしい

#### notebookの基本的な使い方
- 新しいファイルを作る ->new->Python3
- shift+Enter->セル内のプログラムを実行し、下にセルを追加する
- control+Enterでセルの実行
- セルはmarkdownとしても使える
- 他の形式のファイルにexportできる->file->Download as
- キーボードアイコンをクリックするとショートカットキーを参照できる。

### 四則演算
```python
print(5+2)#7
print(5-2)#3
print(2*3)#6
print(7/3)#2.3333333333333335 ->floatで帰ってくる
```
- 小数点を明示的に切り捨てるとき

```python
print(7//3)#2
```

-剰余算=何か手割ったときの余り(mod)

```python
print(7%3)#1
```

-コメントの書き方

```python
#この1行だけコメントです
```
-複数行のコメント

```python

"""
コメント
コメント2
コメント3
"""
```

- 改行とprint文
- Python では、改行が文の区切りとなる
- 出力するときはprint()を使う

 
```python

print("Hello World!")
```

- 文を数行に分けて記述したい場合は、行末にバックスラッシュ\を書く
- コードが長くなったときは改行するのがオススメ

```python
print("Hello \
world111111111111111\
1111111111111111111111111111111\
1111111111111111111111111111111111111111111111111111")
```

#### データの型
##### String型
- String (文字列型)は" "か' 'で囲む(統一した方が後から見やすい)
- string型の足し算は連結になる

```python
print("A")#A
print("1"+"2")#12
type("1")#str
```
- 上記の場合1や2も文字列型として扱われる

##### 数値型
```python
#int 
1
#float
3.12
#複素数
1+4j
#bool型
True
```

- type関数を使うと型の名称を出力することができる

```python

type("A")#str
type(1)#int
type(2.4)#float
type(True)#bool
```

#### 比較演算子
- 大小関係の比較をする
- 演算子の計算結果はbool型で返ってくる

```python
1>0.89#True
3<2#False
4>=4#True
```
#### 変数と動的型付け言語
#####変数
- ~~変数とはデータを箱に格納したもの~~
- Pythonにおける変数は文字や数値などのオブジェクトに付ける名札
- 変数は値を変更することができる
- 一つのイコールでもカンマで区切れば複数の変数にそれぞれ値を代入できる
- 変数目は最初の文字に数値は使えない

```python
x=2
a=3.14
b=1+3j;
c,d=21,11.1
print(x,a,b,c,d)#2,3.14,1+3j,21,11.1
```

- ~~変数を初期化する際に値を何も持たせたくないときは空文字のnanを代入する~~ 
- csvファイルを読み込む時、入力がない場合などにはNAN(=not a number)になる
- NANを代入したいときは下記のようになる

```python
import numpy as np#ここでおまじないを唱えないとnanが使えない
e=np.nan
```
- NaNとは別物でnullオブジェクトを表すNoneがある
- [nullオブジェクトNoneとは](https://www.sejuku.net/blog/50205)

### pythonは動的型付け言語
- **pythonは変数の宣言をする際にデータの型を明記する必要がない**
- **代入した値の型を自動的に識別することができる**
- **この挙動を動的型付けという**

#### 比較演算子を用いた条件分岐
```python3
#python
data=1
if data<2:
    print("2より小さいデータです")
elif 4<=data<5:
    print("4以上5未満")
else:
    print("6以上のデータ")
```
```C
//C言語で書くと
int data=1;
if(data<2){
    printf("2より小さいデータです");
}
else if(data>=4&&data<5){
    printf("4以上5未満");
}
else{
    printf("6以上のデータ");
}

```
- elifはC言語でいうelse ifに相当
- 条件を複数並べる場合の「かつ」は`and` (C言語では`&&`)、「または」は`or` ( 
C言語では`||`)
- ==は等価な値かどうかを判定し、isは同一のオブジェクトかどうかを判定
- **Cでは文を { ... } で囲むことでブロック(複文)を構成するが、Python では{}の代わりにインデント(行頭の空白文字の数)が重要な意味を持ち、同じ数の空白でインデントされた文がブロックとみなされます。**

#### for()文による繰り返し
- 一番簡単なやり方は繰り返しの幅を設定する方法
- 幅はrange関数を使って指定する

```python

for i in range(0,3):
    print(i)
#0,1,2
```
- 変数iをrange(0,3)の範囲で変化させながらprint(i)を繰り返し実行する
- iのインクリメントは自動で行われる。
- for文の中身はインデントする
Laravelでoldとerrorsをコントローラ内で設定する方法

設計もせず簡易ツールをいいかげんに作った際に`old`と`errors`をコントローラ内で設定したくなりましたが、方法がわからなかったので調べてみました。

![test.png](https://qiita-image-store.s3.amazonaws.com/0/156195/1ed9e7e7-c5f3-15cf-334c-708952aa17ec.png)

# やりたいこと

図のような状況で②の処理でエラーが出た際に`back()`を使うと記事を特定できずに最初のページに戻ってしまいエラーも`old`も表示できない。
なので②の直前の状態でエラーが出力されたページを出したい。
つまり、②の処理でエラーが出たら記事詳細画面に記事を特定した状態でエラーとoldを補完した状態にコントローラから遷移させたい。

# 注意

こんなことをしなくても良いようにちゃんと設計しましょう。

## コントローラーから`old`を設定する方法

```php
$request->session()->all();
```

で確認するとわかりますが`_old_input`に`old`データが保持されている。
設定する方法は以下になります。

```php
$request->session()->flash('_old_input', ['key' => 'value']);
```

## コントローラーから`errors`を設定する方法

```php
$request->session()->all();
```

で確認するとわかりますが`errors`に`ViewErrorBag`というオブジェクトで保持されている。
設定する方法は以下になります。

```php
use Illuminate\Support\ViewErrorBag;

$errors = new ViewErrorBag();
$errors->put('default', $validator->errors());
$request->session()->flash('errors', $errors);
```

`ViewErrorBag`を自分で作る場合は`MessageBag`を`put`する。
`$validator->errors()->add()`を使い`$validator->errors()`を`put`するか、
`new MessageBag()`で`MessageBag`を作成し`put`で内容を追加して`put`するか。


## エラーが発生した際の遷移する方法

```php
$id = $request->id;
$input_list_for_old = $request->all();

$request->replace([
    'id' => $id// 詳細画面で記事が特定できるようにする（詳細画面にidをPOSTしている状態を再現）
]);
$request->session()->flash('_old_input', $input_list_for_old);
$errors = new ViewErrorBag();
$errors->put('default', $validator->errors());
$request->session()->flash('errors', $errors);

return $this->methodName($request);// 詳細画面のコントローラを呼び出す
```

## 成功時の処理

成功時にoldは削除する

```php
$request->session()->flash('_old_input');
```

## 遷移先メソッドでerrorsを設定する方法

errorsはミドルウェアShareErrorsFromSessionでセットされており、
メソッド呼び出しではミドルウェアの呼び出しは行われなかったので、
遷移後のコントローラのviewにerrorsをセットする処理が必要。

```php
if ($request->session()->get('errors'))
{
    $data['errors'] = $request->session()->get('errors');
    $request->session()->flash('errors', new ViewErrorBag());// errorを使用したら空をセットしておく
}

return view('template', $data);
```
アカデミアの囚人

今回は「黒魔術からの防衛術」ということで、自分がいた黒魔術（ブラック）研究室について書きます。極力事実に基づいて書きますが、私怨が混ざっている箇所もあると思うのであしからず。

# 見てほしい人
* D進しようと思っている学生。
* 特に、D進したいけど迷っている学生。

# 要約
* 旧帝大、応用物理系の理論の研究室の話。
* B4のときに入って、M1の3月までD進しようと思っていた。
* しかし学振や奨学金返還免除を取るどころか論文が1つも出せなかったので、「自分は黒魔術にかけられているらしい」と気づいて、就職することにした。

# 自分が入った黒魔術研究室であったこと
## 古い言語や不自由なライブラリの使用を強制する
* シミュレーション業界ではfortranがスタンダード（これは悪くない）
* しかしいまだにFORTRANコード（全部大文字なのがミソ）がありがたく受け継がれてくることがある
* もちろんオブジェクト指向なんて誰も知らない

## コード管理がガバガバ
* 研究室の多数の学生が研究に使う大規模コードのメンテナンスが、研究室OBの顔も見たことがないプログラマに任されている。（以前は契約でお金が流れていたらしい。今はコネでやってるのか契約でやってるのかは知らない。）
* OBだから教授は盲信しているが、ろくにテストもしないでリリースしていたり、とにかくガバガバ。
* バージョン管理もええ加減（git？何それ？）なので、以前に修正されたバグが再び復活していたりする。
* バグを報告すると「あなたが加えた修正が悪いんでしょう？」と文句をつける。
* そのバグを踏み抜いてデバッグに時間がかかると、学生が責められる。

## 指導もしないのにダメ出しはする
* 「文字が小さい」「図が汚い」と資料を一切見ない。
* 定期的に報告に来いとは言うが、建設的な議論ができないので段々モチベーションが下がりおっくうになる。
* なので、やっつけで資料を作って、つっぱねられてますますやる気がなくなる。

## マネジメント能力が皆無
* 上述の状況に問題意識を持ってリファクタリングやツールの導入など改善の努力をしても、それは努力したとみなされない。
* 相談しても「それは大変ですね。それで？」で終わり。
* 他のスタッフや学生も見て見ぬふりで助けてくれない。

# 黒魔術に対する防衛策
## 基本的にサボる
* ろくに面倒を見てももらえないのに、自分だけ骨身削ってゴリゴリ努力しても報われない。

## 副業をする
* Pythonやってたら、就職で異世界に転生できた。
* 研究を極力サボるようにしたら時間ができたので、大型二輪免許を取った（副業？）。

# まとめ
* **プログラミングを扱う研究室≠情報系**。アカデミアは極めて保守的なので、**本業が情報でないのに最新の情報技術にキャッチアップしている人はごくまれ**。
* 「研究者としてやっていくなら結局実力主義なんだし、教授がクソでも自分が能力があればいけるやろ」は無理。**指導がちゃんとしてないと最悪死ぬ**。よくて神経系の薬が手放せなくなる。
* **アカデミアに残るだけが生きる道じゃない。「自分は研究職しかできない」と思ってる人でも、大学のほかにも道がある**。
Qiitaでのコード記入法

# コード記入法

難しいと　思ってたけど
以外と簡単だった…
 ```言語:ファイル名 
　記述・・・・
最後にまたバッククオート3つで囲むだけでok



>```java:java.file
>public static void main(String args[]){
>    System.out.println("Hello World");
>}
>```
RaspbianでMinecraftのサーバを立てる

（以前どこかに書いたような…思い出せないので再掲）

MinecraftのPiEditionではなくて、通常(PC,Mac)版でマルチプレイをする時のサーバです。一家に一台あると楽しいと思います。クライアント側はライセンスが必要ですが(^^;

以下のURLからサーバ用のプログラムをダウンロードします。

https://minecraft.net/ja-jp/download/server/

Raspbianに直接手に入れる場合は以下のような感じ。

```
wget https://launcher.mojang.com/v1/objects/3737db93722a9e39eeada7c27e7aca28b144ffa7/server.jar
```

必要なパッケージをインストールします。Javaとscreenコマンド。screenは今回の説明では割愛していますが、実際に運用するときはあると便利です。

```
sudo apt install oracle-java8-jdk screen
```

先程のプログラム(server.jar)が置かれているディレクトリで以下を実行します。

```
java -Xmx1024M -Xms1024M -jar server.jar nogui
```

初回の実行は eula.txt というファイルが生成されて、直ぐに終了してしまいます。このファイルを開いて、中身を編集し、falseをtrueに書き換えます。これで規約に同意したことになるみたいです。

```
eula=true
```

再び、上記のコマンドを実行すると今度は地形の生成が始まりますので少しそのまま待ちます。

Mac(またはPC)のMinecraftを起動し、「Direct Connect」または「Add Server」を選択します。

![Screen Shot 2018-11-21 at 23.01.10.png](https://qiita-image-store.s3.amazonaws.com/0/50780/6fa30258-61d6-093f-2d04-a6174d7d439c.png)

「Address」に「raspberrypi.local」と入力します。この名前はセットアップした際のものを使ってください（raspberrypi.localが規定の名前ですが、スクリーンショット内では「raspi05.local」となっています）。

![Screen Shot 2018-11-21 at 23.05.35.png](https://qiita-image-store.s3.amazonaws.com/0/50780/b2c3a4f1-7a4f-c5c2-bfe4-a889aef9468e.png)

あとは、普通のマルチサーバと同様に接続するだけ！！Raspberry Piの中に広大な世界が！

![Screen Shot 2018-11-21 at 23.07.47.png](https://qiita-image-store.s3.amazonaws.com/0/50780/33da97da-4b7d-0039-2e1f-7b0f49e9fba4.png)

最初はRaspberryPi 2で実験しましたが、やはりリソース不足のようで、ちょっと激しく動き回ると「move too fast」などと警告が出てサーバが落ちてしまいました。RaspberryPi 3では、そこそこ動いているようですが、スペック的にギリギリではあるかもしれません。

RaspberryPiに固定IPを割り当てれば、インターネットに公開して遠隔地の誰かと一緒にプレイすることも可能です。セキュリティのこととか、諸々周辺知識も必要になりますが、サーバの運用体験にはピッタリかもしれませんね。
【GCP】Cloud SDKの概要

##Cloud SDKとは
Google Cloud Platformプロダクト向けの統合コマンドラインツール。
GCPのさまざまなプロダクトやサービスにコマンドラインからアクセスができ、
インタラクティブに実行することや、自動スクリプトで実行することもできるツール。

##提供されているツール
- gcloud
- bq
- gsutil

各種の gcloud コマンドを実行すると、追加のコンポーネントが自動的にインストールされる。
例えば、 gcloud を使用して App Engine アプリケーションをデプロイすると、
各言語の Google App Engine 拡張機能が自動的にインストールされる。

##gcloud
GCPで多くの一般的なタスクを実行するために使用できるコマンドラインツール。
以下のようなことが出来る。

- Google Compute Engine 仮想マシン インスタンスと他のリソース
- Google Cloud SQL インスタンス
- Google Kubernetes Engine クラスタ
- Google Cloud Dataproc クラスタとジョブ
- Google Cloud DNS マネージド ゾーンとレコードセット
- Google Cloud Deployment Manager のデプロイ

##bq
bqは Google BigQuery でデータを操作するために使用できるコマンドラインツール。
データセット、テーブルなどの BigQuery のエンティティを管理したり、
データに対してクエリを実行することが出来る。

##gsutil
Google Cloud Storage でタスクを実行するために使用できるコマンドラインツール。
以下のようなことが出来る。

- Google Cloud Storage バケットの作成、管理
- バケットへのオブジェクトのアップロード、オブジェクトのダウンロード、オブジェクトの削除
- オブジェクトの移動、コピー、名前変更
- 保存されたデータへのアクセスの管理


##おわりに
gcloudコマンドでできることが山ほどあるので今回はざっくりの概要のみにしておいた。
試験に出そうな できることと、できないことをまとめるのも良さそう。

####参考サイト
https://cloud.google.com/sdk/
https://cloud.google.com/sdk/docs/
ACMの証明書を自動更新できなかった話

AWSではSSL証明書も発行できますが、使い方によっては手間取ったりもします。

## AWSで発行できる証明書の概要

AWSでは、[AWS Certificate Manager](https://aws.amazon.com/jp/certificate-manager/)といって、SSL証明書を自前で発行する仕組みがあります。一応「無料」ということになってはいるのですが、秘密鍵は**利用者にも手に入らない**ので、単なるEC2などにセットすることはできません。

CloudFrontやELBなどを通じてセットする必要があるので、EC2単機で動かしているサービスなどでは、ELBを追加する分の料金が発生します。

## 認証方法

もちろん、SSL証明書を出す以上、適切な認証が必要となります。これにもいくつかの方法があって、

* DNS認証（Route53なら自動設定も可能）
* Eメール認証

と選ぶことができます。ただ、Eメール認証の場合は証明書が切れるたびに再認証が必要となるので、選べるならDNS認証を選びたいところです。

### DNS認証の内容…と失敗

DNS認証を行う場合、CNAMEレコードを適切に設定します、例えば、`jkr2255.example.com`に証明書を出したい場合、`_hogepiyofuga.jkr2255.example.com`のCNAMEとして、`_foobarbaz.acm-validations.aws`[^1]のように設定します（`hogepiyofuga`や`foobarbaz`は、実際にはAWSからランダムな文字列を指定されます）。一度設定したままにしておけば、半永久的に自動更新される、とのことです。

証明書を切らせるトラブルを起こしたこともありますし、更新不要になるのはいいなと思ってDNSを設定しようとしたのですが、当該ドメインはとあるレンタルサーバでも使っているのでDNS設定をそちらでする必要がありました。で、指定のとおりに設定しようとしたのですが、DNSレコードのドメイン名としてアンダーバーで始まるものを**受け付けず**、問い合わせてもできないという結果が返ってきました（なお、アンダーバーは**ホスト名**としては適切でないものの、**ドメイン名**としては問題ない、とのことです）。

## 結論

AWSと他サービスを連携して使う場合、他サービス側から制約がかかってくることもある[^2]。


[^1]: `.aws`というトップレベルドメインは（現状では[Amazonグループ専用として](http://www.nic.aws/)）実在して、[http://acm-validations.aws/](http://acm-validations.aws/)にアクセスすると、ACMのページにリダイレクトされます。
[^2]: もちろん、AWS以外のDNSでもアンダーバーを通す例もありましたが。
numpy cumsum()

# numpyのcumsum()関数について

##処理内容
要素を足し合わせたものを、配列として出力する。

###サンプルコード
```python
a = np.array([1,2,3,4,5,6])
#下記どちらの書き方でもOK
np.cumsum(a)
a.cumsum()
```
###実行結果
```python
>>>array([ 1,  3,  6, 10, 15, 21])
>>>array([ 1,  3,  6, 10, 15, 21])
```
実行結果は同じ。
ちなみにaxisで加算方向を変更できる。

```python
a = np.array([1,2,3,4,5,6]).reshape(2,3)
print(a)
>>>array([[1, 2, 3],
          [4, 5, 6]])

np.cumsum(a, axis=0)
>>>array([[1, 2, 3],
          [5, 7, 9]])

np.cumsum(a, axis=1)
>>>array([[ 1,  3,  6],
          [ 4,  9, 15]])

#ちなみに多次元のarrayに対してaxis指定せずにcumsum()実行すると、、、、
np.cumsum(a)
>>>array([ 1,  3,  6, 10, 15, 21])
```

*[参考]*
[SciPy.orgドキュメント](https://docs.scipy.org/doc/numpy/reference/generated/numpy.cumsum.html)
atom-ide の ide-python の初期化が終わらない

# この記事について
個人的にatomでpython環境をWindows上で構成していた時に困ったことのメモ。

# 環境
- Windows 10
- atom 1.32.2 x64
    - atom-ide-ui 0.13.0
    - ide-python 1.0.0
- python 3.6.6
    - pip 18.1
    - python-language-server **0.21.2**

# 問題
[ide-pythonのドキュメンテーション](https://github.com/lgeiger/ide-python)にしたがってインストールしたが，"initializing for hogehoge"という表示が終わらない。

# 解決策
結論から言うと，python-language-serverのバージョンを下げればよい。（[githubのissue#119](https://github.com/lgeiger/ide-python/issues/119#issuecomment-417171455)より）
具体的には，コンソールなどから以下の操作をすればよい。

~~~
    python -m pip uninstall python-language-server
    python -m pip install python-language-server[all]==0.20.0
~~~

これで，pylsのバージョンをさげることができ，自分の環境では問題の解決が確認できた。

# 後書き
最新バージョンに罠があるというパターンだった。
Google検索で必死に日本語サイトを探すよりも，公式の英語情報を読むこと大切なのを再認識できた。
あと，地味にQiita初投稿でした。（Markdownはlatexよりも楽だなぁ・・・）
Macの環境構築のメモ書き

#Macの環境構築のメモ書き
パソコンの買い替え時に、参考にしてくださったら、幸甚です。

brewをインストールする

```
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

Brewcaskをインストールする

```
brew tap caskroom/cask
brew cask --version
```

pycharmをインストールする

```
brew cask install pycharm-ce
```

Googlecromeをインストールする

```
brew cask install google-chrome
```

Firefoxをインストールする

```
brew cask install Firefox
```

Pipをインストールする方法

```
sudo easy_install pip

```
Pipのコマンド一覧

```

pip
```
Squidを使ってプロキシサーバーを構築する時の備忘録

業務でプロキシサーバーが必要になったのでその時のメモ書き。

## Squidのインストールコマンド

```sh
yum install -y squid
```

## Squidの設定ファイル操作

```sh
vi /etc/squid/squid.conf
```

## Squidの設定変更箇所（2箇所）

1）　 設定のコメントアウト

```sh:コメントアウトする前
# And finally deny all other access to this proxy
http_access deny all
```

```sh:コメントアウトする後
# And finally deny all other access to this proxy
# http_access deny all
```

2）　 設定の追記（最終行）

以下のxxx.xxx.xxx.xxxは、グローバルIPアドレス。
http://www.ugtop.com/spill.shtml のあなたのＩＰアドレス(IPv4)が該当箇所。

```sh:最終行に追記
acl myacl src xxx.xxx.xxx.xxx/255.255.255.255
http_access allow myacl
http_access deny all
#　↑　http_access deny all より上の部分でマッチしていれば接続OKになる

forwarded_for off
header_access X-Forwarded-For deny all
header_access Via deny all
header_access Cache-Control deny all
```

## Squidのキャッシュクリア

```sh
squid -z
```

## Squidの起動

```sh
service squid start
```

## ファイヤーウォールの設定：ポート開放

ポート番号は、3128（初期設定）

```sh
sudo firewall-cmd --add-port=3128/tcp --zone=public --permanent
```

## ファイヤーウォールの設定：IP開放

```sh
sudo firewall-cmd --add-source=xxx.xxx.xxx.xxx/32--zone=public
```

## ファイヤーウォールを再起動

```sh
 sudo firewall-cmd --reload
```

## プロキシサーバ経由で接続するためのWindowsの設定

![internet.png](https://qiita-image-store.s3.amazonaws.com/0/230829/ff7fa55b-e9bc-899d-6a79-ecef62dd72b5.png)

## プロキシサーバーのアクセスログ確認

```sh
sudo tail -10  /var/log/squid/access.log
```
bash で配列、連想配列をシェル関数の引数として渡す

# 本投稿について

## 説明すること
* bash で `declare` コマンドを使用して配列や連想配列を宣言する方法
* 配列や連想配列をシェル関数の引数として渡す方法

**※declare による名前参照を使用するため bash 4.3 以降でしか動作しません。**

## 説明しないこと
* 配列や連想配列の細かい操作
* 配列、連想配列、名前参照以外の `declare` コマンドの使用方法

# 使用するコマンド

ここでは `declare` コマンドを使用します。
`declare` は bash で変数を宣言したり、変数に属性を与えたりするためのコマンドです。
`declare` コマンドの使い方は `man bash` にて以下のように記載されています。

```
declare [-aAfFgilnrtux] [-p] [name[=value] ...]
```

ここで使用するオプションは以下のものです。

| オプション | 説明 |
|---:|---|
| -a | 配列変数を宣言 |
| -A | 連想配列変数を宣言 |
| -n | 変数の名前参照を行う |
| -p | 変数の属性と値の表示 |

# 配列変数、連想配列変数の宣言
bash で `declare` コマンドを使用することで配列変数や連想配列変数を宣言することができます。

## 配列変数の宣言
`declare` コマンドを使用して配列宣言をする場合は以下のようにします。

``` bash
declare -a array=("1" "2" "3")
```

`declare -p` を使用すると変数の内容を表示できます。

``` bash
declare -p array
```

結果は以下のように表示されます。

```
declare -a array=([0]="1" [1]="2" [2]="3")  
```

`${array[@]}` で配列の全要素が参照できます。

``` bash
echo ${array[@]}
```

結果は以下のように表示されます。

```
1 2 3
```

## 連想配列の宣言
`declare` コマンドを使用して配列宣言をする場合は以下のようにします。

``` bash
declare -A hash=(["a"]="A" ["b"]="B" ["c"]="C")
```

`declare -p` を使用すると変数の内容を表示できます。

``` bash
declare -p hash
```

結果は以下のように表示されます。

```
declare -A hash=([a]="A" [b]="B" [c]="C" )
```

`${hash[@]}` で連想配列の全要素が参照できます。

``` bash
echo ${hash[@]}
```

結果は以下のように表示されます。

```
A B C
```

`${!hash[@]}` で連想配列の全キーが参照できます。

``` bash
echo ${!hash[@]}
```

結果は以下のように表示されます。

```
a b c
```

# 配列、連想配列をシェル関数の引数として渡す
シェル関数の引数はコマンドラインと同様の形式で渡されるらしく通常は配列や連想配列を引数として渡すことはできないようです。
ですが、シェル関数内で引数に対して `declare -n` を使用して名前参照することで引数に渡した配列や連想配列をシェル関数内で参照することが可能となります。

ここでは先ほど宣言した連想配列 `hash` を使用します。
※配列の場合は同様のため説明しません。


``` bash
# 第１引数を連想配列として参照し各要素の値を表示する関数
print_hash_val()
{
        declare -n ref=$1
        for val in ${ref[@]};
        do
                echo "val = $val"
        done
}

# 連想配列変数を宣言
declare -A hash=(["a"]="A" ["b"]="B" ["c"]="C")

# シェル関数を呼び出して hash の各要素を表示
print_hash_val hash
```

結果は以下のように表示されます。

```
val = A
val = B
val = C
```
SQLite3のJSON機能が便利だった3

#過去記事

[SQLite3のJSON機能が便利だった](https://qiita.com/SoraKumo/items/0e3455684d6f17d36895)
[SQLite3のJSON機能が便利だった2](https://qiita.com/SoraKumo/items/091328b5e5d18e357ed3)

#今回の内容
　今回はテーブルの内容を抽出する時に、一部分だけをJSONとして取得する
　実はこれが恐ろしいほどに便利なのだ

##　1 テーブルとデータの作成

　内容は太郎君と次郎君の好きな言語を保存したものである
　今回、テーブル内のデータにはJSONを使用しない

###　　1.1 SQL文
```SQL
create table users(users_id primary key,users_name text);
create table langs(langs_id primary key,langs_name text);
create table binds(users_id integer,langs_id integer,primary key(users_id,langs_id),
    FOREIGN KEY(users_id) REFERENCES users(users_id),FOREIGN KEY(langs_id) REFERENCES langs(langs_id));

insert into langs values(1,'C');
insert into langs values(2,'C++');
insert into langs values(3,'Java');
insert into langs values(4,'Perl');
insert into langs values(5,'PHP');

insert into users values(1,'太郎');
insert into users values(2,'次郎');

insert into binds values(1,1);
insert into binds values(1,2);
insert into binds values(1,5);
insert into binds values(2,3);
insert into binds values(2,4);
insert into binds values(2,5)
```

##　2 普通に結合して抽出してみる

###　　2.1 SQL文
```SQL
select * from users natural join langs natural join binds
```

###　　2.2 抽出結果
|users_id|users_name|langs_id|langs_name|
|:---|:---|:---|:---|
|1|太郎|1|C|
|1|太郎|2|C++|
|1|太郎|5|PHP|
|2|次郎|3|Java|
|2|次郎|4|Perl|
|2|次郎|5|PHP|

###　　2.3 欲しいデータはそれじゃ無い

　このデータを希望の形で抽出するとすれば、一つの太郎君に対して複数の言語という組み合わせのデータが欲しいのだ
　決して増殖した太郎君と次郎君が欲しいわけでは無い

　欲しいのはこの形はこれだ！

|名前|好きな言語|
|:---|:---|
|太郎|C,C++,PHP|
|次郎|Java,Perl,PHP|

##　3 あっさり実現可能だった

###　　3.1 SQL文

```SQL
select users_name,lang_names from users natural join
    (select users_id,json_group_array(langs_name) as lang_names from binds natural join langs group by users_id)
```
###　　3.2 抽出結果
|users_name|lang_names|
|:---|:---|
|太郎|["C","C++","PHP"]|
|次郎|["Java","Perl","PHP"]|

###　　3.3 これはヤバいよ

　グループ化とjson_group_arrayを組み合わせたら、あっさり欲しい情報をJSONの配列にまとめることが出来た
　あまりに便利すぎておしっこをチビリそうである

#まとめ

　json_group_arrayやjson_group_objectはこんなに便利な機能なのに、Google先生に聞いても日本語の解説は皆無だった
　英語で見てもろくに情報が載っていない
　ぶっちゃけ「いいね」とかは押さなくて良いので、この内容を目立つところに広めて欲しい
　使う人が使えば、とんでもなく便利なのだ

　現在Node.jsでSPA(SinglePageApplication)用のフレームワークを開発中である
　その中で今回のシリーズ記事の内容を所々で使っている
　おかげでデータの入出力がかなり楽になった

　おそらく他のDBにも同等の機能があるのだろう
　我こそはと思う人は、ぜひそういう記事をまとめ欲しい
WindowsフォームをMVPっぽくしてみる

# はじめに

Windowsフォームはきれいにコードを書くのが難しい？らしいので、
Model-View-Presenterというパターンで構成要素を分割してみました。

# 実装

## Viewデザイン

画面はこんな感じでラベル２つとボタンを１つ配置。
これがViewになります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/212876/b80cd144-1f3e-78f4-0957-1dfc00d45aac.png)

## Viewインターフェース

先ほどのフォーム(View)に情報を流し込むためのインターフェースを定義。
ボタンを押したときにメッセージボックスを出したいので、デリゲートも入れます。
こいつがフォーム(View)に実装されることになります。

```cs:IMainForm.cs
public interface IMainForm
{
    string Title { get; set; }
    string Author { get; set; }
    Action<string> ShowMessageCommand { get; set; }
}
```

## Presenter

次はPresenter。こいつがViewで表示される情報を準備します。
コンストラクタでViewを受け取り、さっきのインターフェース経由で情報を渡します。

```cs:MainFormPresenter.cs
public class MainFormPresenter
{
    private IMainForm _view;
    public MainFormPresenter(IMainForm view)
    {
        _view = view;
        Initialize();
    }

    private void Initialize()
    {
        // HACK: 本当はこのあたりはModelから取得されるはずのデータ
        _view.Title = "MvpWinFormsTest!";
        _view.Author = "mono";
        _view.ShowMessageCommand += (msg) =>
        {
            MessageBox.Show(msg);
        };
    }
}
```

## View

Viewのコードビハインド。
IMainFormを実装することで、Presenterからの情報の受取口を付けてやります。

```cs:MainForm.cs
public partial class MainForm : Form, IMainForm
{
    public MainForm()
    {
        InitializeComponent();
    }

    public string Title
    {
        get { return label1.Text; }
        set { label1.Text = value; }
    }
    public string Author
    {
        get { return label2.Text; }
        set { label2.Text = value; }
    }
    public Action<string> ShowMessageCommand { get; set; }

    private void button1_Click(object sender, EventArgs e)
    {
        ShowMessageCommand("button1 Clicked!");
    }
}
```

## Presenterインスタンスの生成

フォームを表示する時に、フォームに紐づいたPresenterも作ってやります。

```cs:Program.cs
static class Program
{
    /// <summary>
    /// アプリケーションのメイン エントリ ポイントです。
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        var f = new MainForm();
        var p = new MainFormPresenter(f);
        Application.Run(f);
    }
}
```

# 動作

ボタンも含めうまく動いているようです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/212876/300dd570-2dc0-72a1-8021-6306d7f6ce72.png)

# まとめ

MVPらしき方法で動かすことができました。
雰囲気としては、MVVMのデータバインドがやっていることを自分で組んでいるような感じがしました。
今回以下のような疑問が残りました。

- メッセージ表示をデリゲートでやったけど、ViewからPresenterを参照できるようにして、メソッドを呼び出した方がいいのかな
- 画面遷移・入力ダイアログはどうやって実装しよう
- DataGridViewとかBindingSourceとかDataTableとか使いだしても、うまく組めるのか
- この方法でコードの保守性は上がるのはどんな場面か

色々サンプルを探してみたのですが、ゴチャゴチャした画面は見当たらなかったです。
WinForms対応のMVP用の部品も色々あったのですが、ディスコンのものばかりで試していません。
もうちょっと凝った画面も作ってみようかなと思います。


# 参考資料
mrts/winforms-mvp: Windows Forms example of the Passive View variant of the Model-View-Presenter pattern
https://github.com/mrts/winforms-mvp
Electronより軽くて手軽なlorca製デスクトップガワアプリのススメ

最近ScrapboxをデスクトップPWAとして使い始めました。
やはりデスクトップアプリとしてDockに表示されるだけで体験はすごく良くなるなー

PWAもっといろんなサービスで使えるようになってほしいです（オフライン動作とかとりあえず要らないんでアプリとしてインストールだけでもさせてほしいなぁ）

Webサービスのデスクトップアプリ化で感じる利点は、具体的にはショートカットやSpotlightで呼び出しやすいといったことくらいなのですが、OSのインタフェースから自然に使えるという体験はヘビーユースしているWebサービスを更にヘビーに使うきっかけになりえるなと。

自分自身、よく使うWebサービスは個別アプリにしたいと日頃から思っており、Electronを使ってよく使うWebサービスは個人利用用にアプリ化したりしてました。
ただElectronはアプリサイズが大きいのと、Gmail等一部のWebサービスはそのまま開いても動かない(Ramboxとかはどうやっているんだろう)のが悩みでした。

今回使ってみた[lorca](https://github.com/zserge/lorca)はその部分を解決しており、PWAが広まるまでの代替として割と最適感があります。

# lorcaってなに

lorcaはHTML5アプリケーションを構築するための非情に小さなライブラリで、ElectronのようにChromiumを内蔵するのではなくインストール済のChromeブラウザを利用して動作しています。

lorcaはGoのライブラリであり、類似の[carlo](https://github.com/GoogleChromeLabs/carlo)よりも手軽にガワデスクトップアプリを作ることができます。
(carloではアプリケーションアイコンの設定に別ライブラリが必要だったりとひと手間かかる)

追記:
以下のサンプルでは、Spotlightから起動したときに別ウィンドウとして開かれてしまうという問題があります。解決したい...

## lorcaでガワアプリを作ってみよう

(今回はMacOSでMacOS向けアプリを作ってみますが、Windowsもbuild用のシェルスクリプト以外は同じでいけると思います。)

まずはGolangをインストール

```bash
brew install go
```

```bash
go get github.com/zserge/lorca
```

`~/go/src/github.com/shwld/gcal-client` みたいなディレクトリを作ってそこで作業します。

goファイルを作りましょう。これがガワアプリの全てです。

```go:main.go
package main

import (
	"os"
	"os/user"
	"github.com/zserge/lorca"
)

func main() {
	user, err := user.Current()
	if err != nil {
			panic(err)
	}
	dir := user.HomeDir + "/.lorca-app"
	os.MkdirAll(dir, os.ModePerm);
	ui, _ := lorca.New("https://calendar.google.com", dir, 2000, 1000, "--start-maximized")
	defer ui.Close()
	<-ui.Done()
}
```

次に[image2icon](https://itunes.apple.com/jp/app/image2icon-独自のアイコンを作ろう/id992115977?mt=12)とかでicon.icnsファイルを作ってディレクトリの中に配置します。
iconの画像はicons8から取得しました。

あとはbuild用のシェルスクリプトを作ればおしまい！

```bash:build-macos.sh
#!/bin/sh

APP="gCal.app"
mkdir -p $APP/Contents/{MacOS,Resources}
go build -o $APP/Contents/MacOS/gCal
cat > $APP/Contents/Info.plist << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleExecutable</key>
	<string>gCal</string>
	<key>CFBundleIconFile</key>
	<string>icon.icns</string>
	<key>CFBundleIdentifier</key>
	<string>net.shwld.gcal-client</string>
</dict>
</plist>
EOF
cp icon.icns $APP/Contents/Resources/icon.icns
find $APP
```

シェルを実行するだけでアプリが出来上がりです！
ビルドがすぐに終わる上にファイルサイズが小さいのでとーってもに手軽でよい！

今回作ったのはgoogle calendarのガワアプリでソースコードはこちらです。
https://github.com/shwld/gcal-client

自分用にガワアプリ作ってお気に入りのWebサービスをもっとヘビーに使おうぜ！
JavaScriptのString#replaceは思っていたより高機能だった

# TL; DR
Stringオブジェクトの`replace`メソッドは、第２引数に関数をとれて便利。

# はじめに
JavaScriptで文字列置換したいときに、`replace`メソッドをよく使います。例えば、スペースをハイフンにしたければこんな具合です。

```JavaScript
"foo bar".replace(" ", "-") // => "foo-bar"
```

ただ、これだと最初にマッチしたスペースしか置換されません。

```JavaScript
"foo bar baz".replace(" ", "-") // => "foo-bar baz"
```

第１引数には正規表現も書けるので、`g`オプションをつけた正規表現を使えばすべてのスペースが置換できます。

```JavaScript
"foo bar baz".replace(/ /g, "-") // => "foo-bar-baz"
```

できました。ここまでは単純な置換です。

# 置換パターン

さて、もっと込み入ったことをしたいとします。例えば、各単語をかっこで囲みたいとしましょう。`"foo bar baz"`を、`"(foo) (bar) (baz)"`にします。このようなマッチした文字列を使い回す置換は、**置換パターン**が便利です。

```JavaScript
"foo bar baz".replace(/\w+/g, "($&)") // => "(foo) (bar) (baz)"
```

ここでは、マッチした文字列を表す`$&`という置換パターンを使いました。

キャプチャした文字列を`$1`, `$2`... で参照することもできます。

```JavaScript
"John,male\nJane,female".replace(/(\w+),(\w+)/g, "name: $1, gender: $2") // name: john, gender: male\nname: jane, gender: female
```

話はこれで終わりません。更に高度なことができます。

# 第２引数の関数指定

`replace`の第２引数には関数が指定できます。第１引数がマッチするたびに呼ばれます。引数には、マッチした文字列に関する情報が入ります。

```JavaScript
"foo bar baz".replace(/\w+/g, match => match.toUpperCase()) // => "FOO BAR BAZ"
```

これでもう何でもありですね。ちょっとした自作テンプレートのようなこともできます。

```JavaScript
const bindings = {
  host: 'example.com',
  port: 8080
}
// キャプチャした文字列は２つ目の引数に入ります。
// ２つ以上キャプチャした場合は３つ目、４つ目…の引数に入ります。
"http://{{host}}:{{port}}".replace(/{{(\w+)}}/g, (_, key) => bindings[key]) // => "http://example.com:8080"
```

便利。

# 参考文献
[String.prototype.replace() - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter)
LIFF+Vue.js(Vue Router) のClient Routingでエラーになる問題


# LIFF+Vue.js(Vue Router) のClient Routingでエラーになる問題

### 対象者
* LINEのLINE Front-end Framework 利用者
* Vue.js/vue router 利用者
* Client Routingをhashで実施している方

### 問題
vue routerを利用してClient Routingを実施したアプリをLIFFへデプロイすると、
ホワイトアウトする。

### バージョン
`package.json` 一部抜粋

```json
{
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
  },
  "dependencies": {
    "axios": "^0.18.0",
    "buefy": "^0.7.1",
    "moment": "^2.22.2",
    "vue": "^2.5.17",
    "vue-class-component": "^6.0.0",
    "vue-cli-plugin-s3-deploy": "^3.0.0",
    "vue-property-decorator": "^7.0.0",
    "vue-router": "^3.0.1",
    "vuex": "^3.0.1"
  },
  "devDependencies": {
    "@types/jest": "^23.1.4",
    "@vue/cli-plugin-babel": "^3.1.1",
    "@vue/cli-plugin-typescript": "^3.1.1",
    "@vue/cli-plugin-unit-jest": "^3.1.1",
    "@vue/cli-service": "^3.1.4",
    "@vue/test-utils": "^1.0.0-beta.20",
    "babel-core": "7.0.0-bridge.0",
    "ts-jest": "^23.0.0",
    "typescript": "^3.0.0",
    "vue-template-compiler": "^2.5.17"
  }
}
```

### 解決方法
履歴管理方法を `URL Hash` => `HTML5 History API` へ変更することで解消されます。
具体的には、 `VueRouter` の `mode` プロパティを `history` へ変更します。

```js
import VueRouter from 'vue-router'

export default new VueRouter({
  mode: 'history', // ← 'hash' から
  routes: [ ],
})
```


### 原因
LIFFアプリの起動時に、下記のようなURLが生成されます。
元URL: `https://example.com/app`
↓
LIFF起動: `https://example.com/app#xxxx=ooooo`

起動時に `#` を末尾に、その後に `=` 区切りで情報を付与しています。
(付与されている詳細な情報については、指定されている値が気になるので割愛します。)

LIFF側で `#` を付与してしまうため、 hashベースのルーティングを利用している場合、
意図しないパスへと変更されてしまいます。
そのため、ホワイトアウトしてしまう問題が発生します。

vue routerでは、HTML5ベースのHistory APIに対応していたため、
そちらに切り替えることで、対応することができました。


### 所感
URLに情報を付与する場合は、ドキュメントに記載もらえるとありがたいと思いました。
また、付与されている情報がセンシティブな点も気になりましたが、
基本ユーザーには見えないように、LIFF側で担保されているはずです。


### 参考
* [Vue.js入門 基礎から実践アプリケーション開発まで](https://gihyo.jp/book/2018/978-4-297-10091-9)
* [Vue Router: HTML5 History モード](https://router.vuejs.org/ja/guide/essentials/history-mode.html)
* [SPAのルーティングのはなし](https://www.slideshare.net/ushiboy/spa-76170499)
* [LIFF APIリファレンス](https://developers.line.biz/ja/reference/liff/)
Dockerのoverlay2でMySQLが起動しない問題を解決する

公式のMySQLコンテナは、Storage Driverがoverlay、overlay2だとMySQLが起動しないことがあります。

Docker for Mac(Windows)は、デフォルトのStorage Driverがoverlay2なので、この問題を回避するために、Storage Driverをaufsに変更していました。

![aufs_win.png](https://qiita-image-store.s3.amazonaws.com/0/38162/d864d263-7cad-8913-28ee-c0db2bbfb3c5.png)

※ちなみに、CoreOSではdevicemapperに変更していました。
https://qiita.com/yKanazawa/items/1827325c92fd4651a912


しかし、先日リリースされた、Docker for Windows 2.0.0.0-Mac78(Win78)では、aufsへの切り替えができなくなっていました。


なので、この問題に本格的に向き合うことになったのですが、以下のGitHub issueが大変参考になりました。

MySQL does not start with overlay2 and overlay but starts with aufs
https://github.com/docker/for-linux/issues/72

Fatal error: Can't open and lock privilege tables: Table storage engine for 'user' doesn't have this option
https://serverfault.com/questions/870568/fatal-error-cant-open-and-lock-privilege-tables-table-storage-engine-for-use


MySQLの起動前に以下のコマンドを実行することで、MySQLが起動できるようになります。

```
find /var/lib/mysql -type f -exec touch {} \;
```
MyBatis-SpringのMapper生成でハマった

# MyBatisのMapper生成でハマった
## 現象
Mapperのinterfaceを定義しているのに、以下のエラーが発生する。

```text
2018-11-21 22:08:22.200  WARN 5084 --- [           main] o.m.s.mapper.ClassPathMapperScanner      : No MyBatis mapper was found in '[～.adapter.customer, ～.port.models]' package. Please check your configuration.

～～～

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2018-11-21 22:08:25.497 ERROR 5084 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Field customerRecordMapper in ～.adapter.models.customer.CustomerRepositoryAdapter required a bean of type '～.adapter.models.customer.CustomerRecordMapper' that could not be found.


Action:

Consider defining a bean of type '～.adapter.models.customer.CustomerRecordMapper' in your configuration.

Disconnected from the target VM, address: '127.0.0.1:51847', transport: 'socket'

Process finished with exit code 1

```

## 環境
Maven2で以下の依存

```xml:pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.12</version>
</dependency>
```

## 原因
MapperをAutowiredしているクラスに以下のアノテーションがなかった。

```java
@MapperScan(basePackages = { "jp.personal.gi.examazon.customerservice.model.adapter.models.customer"})
```

前作ったサンプルでは、なくても動いたはずなのに...

[参考サイト](https://blog.csdn.net/qinxian20120/article/details/80255976)
フォルダ単位でプロジェクトのRailsバージョンを管理する方法

1. mkdir **プロジェクト名**
2. cd **プロジェクト名ディレクトリ**
3. bundle init
4. vi Gemfileに```gem 'rails', "5.2.1"```を追記 #5.2.1と書かれている所でバージョンを指定している
5. bundle install --path vendor/bundle
6. bundle exec rails new --database=mysql .  　#最後の . は必ず書くこと
7. Gemfile overwrite? ときかれたらyでエンター
8. ```rails -v```をしてみると、4.で指定したバージョンのRailsがインストール出来ていると確認できる。

以上。
matplotlibのspecgram

matplotlibのspecgramを翻訳したもの。

Call signature:

```python
matplotlib.pyplot.specgram(x, NFFT=256, Fs=2, Fc=0, detrend=malab.detrend_none, window=mlab.window_hanning, noverlap=128, cmap=None, xextent=None, pad_to=None, sides='default', sides='default', scale_by_freq=None, mode='default', scale='default', **kwargs)
```

|パラメータ名|データ|説明|
|:--|:--|:--|
|x|1次元配列またはシーケンス|データを含む配列またはシーケンス|
|Fs|スカラー|サンプル周波数(単位時間あたりのサンプル数)。フーリエ周波数freqを単位時間ごとのサイクルで計算するために使用される。デフォルト値は2|
|window|長さNFFTの関数またはベクトル|窓関数。参照窓関数を作成するには、numpy.blackman(), numpy.hamming(), numpy.bartlett(), scipy.signal(), scipy.signal.get_sindow()などを使用。デフォルトはwindow_hamming()。|
|sides|{'default', 'onesided', 'twosided'}|スペクトルのどちら側を返すかを指定。デフォルトは実際のデータに対しては片面、複雑なデータに対しては両面返す。'onesided'では片側のスペクトル、'twosided'では両側のスペクトル|
|pad_to|int|FFTを実行するときにデータセグメントが埋められるポイントの数。デフォルトはNone。|
|NFFT|int|FFTの各ブロックで使用されるデータポイントの数。デフォルト値は256。|
|detrend|{'default', 'constant', 'mean', 'linear', 'none'}|fft-ingの前に各セグメントに適用され、平均または線形傾向を除去するように設計された関数。|
|scale_by_freq|bool|結果の密度値をスケーリング頻度でスケーリングするかどうかを指定する。|
|mode|{'default', 'psd', 'magnitude', 'angle', 'phase'}|使用するスペクトルの種類。デフォルトは'psd'でパワースペクトル密度。'magnitude'はマグニチュードスペクトル。'angle'はアンラッピングなしの位相スペクトル。'phase'はアンラッピングを伴う位相スペクトルを返す。|
|noverlap|int|ブロック間の重複ポイントの数。デフォルト値は128。|
|scale|{'default', 'linear', 'dB'}|スケーリングスペック。'linear'はスケーリングされない。'dB'はdBスケールで値を返す。|
|Fc|int|xの中心周波数。デフォルトは0。|
|cmap|matplotlib.colors.Colomapインスタンス|Noneの場合、rcによって決定されるデフォルトを使用する。|
|xextent|Noneまたは(xmin, xmax)|x軸に沿った画像範囲。|
|**kwargs||スペクトログラムを作成するimshowに追加するkwargが渡される。|

|戻り値名|データ|説明|
|:--|:--|:--|
|spectrum|2次元の配列|列は連続するセグメントのピリオドグラム。|
|freqs|一次元配列|スペクトルの行に対応する周波数。|
|t|一次元配列|セグメントの中点に対応する時間。|
|im|AxesImageクラスのインスタンス|スペクトログラムを含むimshowによって作成された画像。|
Kotlin + Gson で非Null許容なJSON変換

#なぜこれをやろうと思ったか
サーバから受け取った、JSONをStringエンコードして、オブジェクトにカカッと変換したい。
しかも、非Null許容で、Realmには保存しないで、そのまま使いたい。

保存する場合は、Realmの便利関数があるので、そっちを使うが、保存をしない条件だとこちらで頑張る必要がある。

Moshiを使うことも想定されるが、
1.jsonパーサーを二つも入れたくない
2.Realmと相性が良いのはやっぱGson

と言うのもあって、Gsonで踏ん張ることに。

人によってはnullを許容するなどするが、筆者が非null許容派の過激派組織に所属しているため、nullは許容できない。
（非Null許容派とNull許容派の論争は別でw）

#具体的にどんなケースよ？
以下のRealmオブジェクト、SampleObjがあったとする。

```kotlin:SampleObj.kt

//非Null許容のオブジェクトサンプル
open class SampleObj: RealmObject() {
    @PrimaryKey
    var sm_id : Int = 0
    var name = ""
}
```

受け取るJSONは

{"sm_id":0,"name":"andy"}
や
{"sm_id":0,"name":null}

を想定する。

API側はnull出さないと書いてあっても、受け取る内容を書き換えられるなどの、可能性も考慮するとアプリ側で正確に受け取る必要がある。

そのままGsonで受け取ると、nullを参照した時点でアプリが落ちるのでこれをどうにかしたい。

#どうしたか
以下のExtensionを作成した。

```kotlin:sample.kt
#StringがまともなJSONだったら、クラスの情報とDesilializerを与えるとオブジェクトにして返してくれる拡張
fun <T> String.jsonTo(type: Class<T>, typeAdapter: Any): T {
	val builder = GsonBuilder().registerTypeAdapter(type,typeAdapter).serializeNulls().generateNonExecutableJson().create()
	return builder.fromJson(this,type)
}
fun <T> String.jsonTo(type: Class<T>): T {
	val builder = GsonBuilder().serializeNulls().generateNonExecutableJson().create()
	return builder.fromJson(this,type)
}
```
#内容の説明
簡単に言うと、GsonBuilderにserializeNullsがあるから、それ使おうぜ！って話です。

Gson側でうまく処理してくれているとは思うのですが、若干不安。。。

マサカリ、募集中です！w
お待ちしています！
waitUntilの対象をasync functionで書く

小ネタですが、見事にはまり込んでしまったので書いていきます.

## `waitUntil`とは

Service Workerを使うと「インストール」というプロセスが発生しますが、Service Worker内で行う処理はキャッシュ処理、`fetch`による通信など、非同期なもので溢れています。

そこで、イベントオブジェクトに`waitUntil()`というメソッドが生えていて、この`waitUntil`に`Promise`を渡せば、`Promise`が完結したところでインストール完了となる（`Promise`が失敗すればインストール失敗となる）、というものとなっています。

## やらかしたパターン

多くの場合、キャッシュを開く`caches.open().then()`から始めて自然と`Promise`を渡すようにできるのですが、ある時この処理をasync functionで書こうとしました。

```失敗作.js
addEventListener('install', e => {
  e.waitUntil(async () => {
    const cache = await caches.open(CACHE_NAME);
    // 後略
  });
});
```

こうしてみたところ、引数の関数には入ることもなく処理が進んでしまいました。

## 冷静に考えれば

よくよく考えれば、上に書いたように、`waitUntil()`が取るものは`Promise`であって、関数ではありませんでした。ということで、その場でasync functionを実行して`Promise`を得ておきましょう。

```修正版.js
addEventListener('install', e => {
  e.waitUntil((async () => {
    const cache = await caches.open(CACHE_NAME);
    // 後略
  })());
});
```
Revamp your Logistics Management system by integrating IoT and GPS technology

Before going forward, let’s first apprehend what logistics management is.

Logistics management is an elementary factor that ensures the success of business operations, and squarely impacts the bottom line through seamless planning, controlling and moving the goods and services from origin to destination.

By perusing the logistics management definition, the logistics management seems a piece of cake. However, in reality, it’s quite complex and crucial as it involves the flow and storage of goods into and out of the business, which has a direct effect on business revenue. Besides, with the increasing customer demands and the need for providing faster and quality services, managing the logistics with traditional methods has become beyond the bounds of possibility.

All the issues can be iron out embracing internet of things technology. By making IoT a central nervous system of the logistic system, the entire logistics value chain from warehousing operations to freight shipping to the last-mile delivery will enjoy the far-reaching payoffs.

With IoT app development, the businesses will have complete visibility and control over every logistic activity that improves the operational efficiency, safety, security, and customer experience in an amazing way.

With the pervasive presence of mobile, RFID tags, actuators, GPS sensors, Bluetooth low energy sensor, Wi-Fi direct, and consumerization of IT, the sensor-based technology is gaining grounds across the diverse industry verticals. In logistic space, IoT is promising the transformational shift with the logistic process automation that eliminates manual interventions, improves the quality and lowers the cost with predictive analytics.

By revolutionizing the way people, process, and assets connect, collaborate and work together, the technology has unfolded a slew of opportunities. In essence, the sensing technology makes sense for the logistics management with higher transparency, integrity control, and real-time insights. Know in details.. https://www.prismetric.com/revamp-your-logistics-management-system-by-integrating-iot-and-gps-technology/
Pythonista3でiPhoneのGPSデータを取得する

iOSアプリであるPythonista3。
iPhone,iPadでもプログラミング言語Pythonを使えるということで、
Python歴数か月の私は興味本位でダウンロードしました。
使ってみて思ったのは、PCにはないiPhone,iPadの機能を利用できるのが良い！
タイトルのGPSや通知機能とか、アプリを作っている実感がありますねー。

さて今回は、
「iPhoneのGPSデータを取得し、csvファイルで保存する」スクリプトを
紹介します。

本来ならスクリプト一つで十分なのですが、アプリ化を考えていますので、
UIも一緒に説明します。簡単にUIを利用できるのもPythonista3の魅力ですね。

まずは使用時の説明を。
![gps-logger_ui.png](https://qiita-image-store.s3.amazonaws.com/0/315296/d058e4c2-1ae6-5d0f-0d19-e022dde2be9f.png)

「GPS LOGGER」と書かれたテキストビューがあり、その下に2つのボタン(NEW,ADD)があります。
どちらかのボタンをタップすると、
![gps-logger_ui_playing.png.jpg](https://qiita-image-store.s3.amazonaws.com/0/315296/b3a59520-a704-7da6-f83d-40383c620c38.jpeg)

このように、GPSデータを取得時間とともに表示します。
データは一応個人情報になるので消してます。悪しからず。

続いてスクリプト。

```py
# -*- coding:utf-8 -*-
# location はGPSデータを取得する標準モジュールです
import ui,location,csv,datetime,time   

# NEWボタンをタップすると呼ばれるメソッド
def shinki(sender):
	label = sender.superview['label1'] 
	now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') # 現時刻を取得

	# 1.GPSデータを取得
	location.start_updates() # GPSデータ更新を開始
	gps=location.get_location() # GPSデータを取得する
	location.stop_updates()# GPSデータ更新を終了

	# 2.GPSデータを画面に表示
	gps_text = '' 
	for g in gps:
		gps_text=gps_text + str(g)+':'+str(gps[g])+'\n'
	label.text=now + '\n' + gps_text # UIのテキストビューにGPSデータを代入
	
	# 3-1.GPSデータを編集して、csvファイルに保存
	gps_dict = {'time':now} # GPSデータはディクショナリ型。
	gps_dict.update(gps) # 先に取得時間を入れ、次にGPSデータを追加
	
	# 3-2.csvファイル用にヘッダー(ディクショナリ型)を作成
	gps_rows=[] # 空のリストを作成
	gps_rows.append(gps_dict)
	parameters = ['time','latitude','longitude','altitude','timestamp','horizontal_accuracy','vertical_accuracy','speed','course']
	header = dict([(val,val) for val in parameters])

	# csvファイルを開いて、gps辞書を書き込む
	with open('gps_log.csv',mode='w', encoding='utf-8') as f:
		writer = csv.DictWriter(f,parameters, extrasaction='ignore')
		writer.writerows(gps_rows)

v = ui.load_view()
v.present('sheet')
```
上記のスクリプトはNEWボタンのメソッドですが、ADDボタンも99%同じです。
違うのはメソッド名をtsuika()としていることと、csvのモードをmode='a'としていることの2点です。

なお、各ボタンの編集画面で、メソッドを設定する必要があるので注意してください。
![gps-logger_ui_NEW button.jpg](https://qiita-image-store.s3.amazonaws.com/0/315296/36797195-758a-b439-73f6-c1bbfb35d2fe.jpeg)
![gps-logger_ui_ADD button.jpg](https://qiita-image-store.s3.amazonaws.com/0/315296/45003924-29ff-c9ab-410d-e980165bb7a7.jpeg)

スクリプト「gps logger.py」を実行し、ボタンを押すと、冒頭にある通りGPSデータが表示されます。また、スクリプトと同じディレクトリにcsvファイルが保存されているはずです。
あと、これは今検討中ですが、location.start_updates() のあとにtime.sleep(1)
を入れたほうがいいかもしれません。GPSデータの更新時間に余裕を持たせるという意味で。

長くなりましたが、説明は以上です。
次はcsvファイルを読み込んでマップデータを作成するスクリプトを紹介します。

参考にしたURL：
http://omz-software.com/pythonista/docs/ios/location.html
(小ネタ) Timerクラスでタイムアウト処理を行う

Dartで数秒wait(sleep)したいというのはよくあるニーズだと思いますが、方法を検索すると、大抵は `Future.delayed(Duration(..))` のサンプルがHITします。
個人的にはこの方法で困った事が無かったので、無操作/無通信タイムアウト処理を実装するにもこの周辺を調べれば良いと考えましたが、タイマキャンセルの方法が見つかりません。

調査の結果、なんだTimerクラスを使えばよかったんじゃん、という記事です。

## なぜタイマキャンセル出来ないのか

https://api.dartlang.org/stable/2.1.0/dart-async/Future/Future.delayed.html にもありますが、Future.delayedの中でTimerクラスが使用されています。
が、Timerのインスタンスへの参照が保持されていません。

```dart:Future.delayed
factory Future.delayed(Duration duration, [FutureOr<T> computation()]) {
  _Future<T> result = new _Future<T>();
  new Timer(duration, () {
    try {
      result._complete(computation?.call());
    } catch (e, s) {
      _completeWithErrorCallback(result, e, s);
    }
  });
  return result;
}
```

Timerクラス自体は`cancel()`メソッドを持っているのですが、誰も`cancel()`メソッドを呼べないのです。
(理由はあるかもしれませんが深追いはしません)

## タイマをキャンセルする

しかしFuture.delayedの実装を見たおかげで、Timerクラスを直接呼べば良いということが分かりました。

```dart
/// イメージ（60秒間、無通信なら終了する）
class WatchDog {
  Timer _timer;
  void ondata(String s) {
    _timer?.cancel(); // 一度タイマをキャンセルし、
    _timer = Timer(Duration(seconds: 60), _nodata); // もう一度60秒で張り直す。
    something(s);
  }
  void _nodata() => exit(0);
}
```

TimerクラスはJavaScriptで言うsetTimeout()、clearTimeout()相当なだけなので、なーんも新規性は無い話でしたが、Timerクラスに辿り着くまでに案外時間が掛かりました ...

## タイムアウトの別実装

RxDartパッケージの`debounce`オペレータを使った方が、スマートな場合があるかも知れません。

```dart
import 'dart:async';
import 'package:rxdart/rxdart.dart';

void main(List<String> args) {
  final streamController = StreamController<String>();
  final observable = Observable(streamController.stream);
  listener(observable);
  emitter(streamController);
}

void listener(Observable observable) {
  // debounceを用い、500msの間イベントが発生しなければ呼び出される様にする
  observable.debounce(Duration(milliseconds: 500)).listen((s) {
    print('timeout(over 500ms): $s');
  });
}

void emitter(StreamController streamController) {
  Future(() {}) // async/awaitを使いませんが、理由は特にありません
      .then((_) => streamController.add('400ms-1'))
      .then((_) => Future.delayed(Duration(milliseconds: 400)))
      .then((_) => streamController.add('600ms-1'))
      .then((_) => Future.delayed(Duration(milliseconds: 600)))
      .then((_) => streamController.add('400ms-2'))
      .then((_) => Future.delayed(Duration(milliseconds: 400)))
      .then((_) => streamController.add('600ms-2'))
      .then((_) => Future.delayed(Duration(milliseconds: 600)));
}
```

実行すると、以下の様にコンソールに出力されます。

```
timeout(over 500ms): 600ms-1
timeout(over 500ms): 600ms-2
```