OmniAICreator/Qiita-1.07M huggingface dataset:
phpで[0,...10]までの配列を2個、3個、2個……となるようにarray_chunkしようとしたら大変なことになった

たまにこういうことってあると思うんですね。
画面上の列の構成が1行目は2個、2行目は3個……みたいな。
CSSで対応できないこともないんですが、PHP側でそういう対応が必要になってしまった場合に。

2個ずつ、3個ずつ、ということであればarray_chunk一発で簡単だったんですが……

# まずはシンプルにッ！

```simple_chunk.php
$azunyan = range(0, 10);

$peropero = [];
while (count($azunyan)) {
    $peropero[] = array_splice($azunyan, 0, count($peropero) % 2 ? 3 : 2);
}

// [[0,1], [2,3,4], [5,6], [7,8,9], [10]]
var_dump($peropero);
```

シンプルに実装してみました。
2個、3個となるように、array_spliceに渡す値を制御しています。
生のPHPでやるのであれば、これが普通だと思います。

# :fire::fire:燃え上がる反骨心:fire::fire:

:fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire:
何をトチ狂ったのか、\$azunyanを用意したくないし、
\$peroperoの空配列の変数も事前に用意したくないし、
[]で繋ぎ合わせたくないという反骨心が生まれてしまいましたッ！！
:fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire::fire:

## yieldしてみようッ！

```yield_chunk.php
$peropero = iterator_to_array((function ($values) {
    while (count($values)) {
        yield array_splice($values, 0, 2);
        if (count($values)) yield array_splice($values, 0, 3);
    }
})(range(0, 10)));

var_dump(var_dump);
```

$peroperoに随時追加しないようにするのであれば、2個、3個……というchunkの結果を返す関数を作ればいいのでは？
けど関数だと結局、内部で変数を定義して処理しないといけなさそうだな……ならiteratorにして、結果を配列として受け取るようにしてしまえばいいのでは？という発想から誕生したコードになります。

これでも分割はできるんですが、whileの中で条件分岐ができなくなってしまったため、
yieldが2段階構成＋if文が必要になるし、行も増えてしまうというイマイチな作りに。

## 行は減らしたいし、ifも書きたくないッ！

```chunk_splice_merge.php
$peropero = call_user_func_array("array_merge", array_map(function($target) {
    return array_filter([array_splice($target, 0, 2), $target]);
}, array_chunk(range(0, 10), 5)));

var_dump($peropero);
```

行は減らしたいし、ifも書きたくないという贅沢な条件を満たしてみました。

2個、3個……という流れにするんであれば……
まず5個ずつに分割して、それを更に2個、3個に分割して、最終的にflatすれば良くないかという結論に。

flatする関数が生のphpでは存在しないという事実に心が折れかけましたが、
javascriptでいうスプレッド演算子的なのがあれば、array_mergeで2次元を1次元に落とせるのではと。
call_user_func_arrayの存在を思い出して、array_mergeで呼んであげています。

yieldの時に問題になったif文はarray_filterを実行することで取り除くようにしています。

# 結論ッ！
こんな見にくい処理をprに出したら怒られてしまうので、最初からシンプルに書いた処理にしておきましょう。
オフラインリアルタイムどう書く E27 の問題をRubyで解く

問題はこちら
http://nabetani.sakura.ne.jp/hena/orde27cardgame/
元の問題は71問ありますが後半省略しました。

``` ruby
class Array
  def same?
    self.uniq.size == 1
  end
  def seq?
    self.map.with_index{|n ,i| n - i}.uniq.size == 1
  end
end

def card_score(cs)
  tr = cs.transpose
  if tr[0].same?
    return 0 unless tr[1].seq?
  elsif tr[1].same?
    return 0 unless tr[0].seq?
  else
    return 0
  end
  {2=>1,3=>4,4=>9,5=>16,6=>25,8=>49}[cs.size]
end

def solve(q)
  cards = q.split(',').map{|cd| cd.split('').map{|c| c.ord}}
  score = 0
  cards.permutation{|pm|
    [[8],[6,2],[5,3],[4,4],[4,2,2],[3,3,2],[2,2,2,2]].each{|pat|
      ss = 0
      i = 0
      pat.each{|sz|
        sc = card_score(pm[i,sz])
        if sc == 0
          ss = 0
          break
        end
        ss += sc
        i += sz
      }
      score = ss if ss > score
    }
  }
  score == 0 ? '-' : score.to_s
end

DATA.readlines.each do |line|
  no,q,a = line.strip.split(/\s+/)
  ans = solve(q)
  print no + "\t" + ans
  puts ans == a ? ' o' : ' x'
end
__END__
0	A1,A2,A3,A4,B3,C3,D5,E5	11
1	A1,B2,C3,D4,E5,F6,G7,A8	-
2	A3,A5,A4,A6,A7,A1,A2,A8	49
3	G2,G1,A1,F1,C1,E1,B1,D1	26
4	E3,G3,D4,F3,D3,C3,B3,A3	9
5	A1,C1,C2,E3,B1,B2,A2,D3	9
6	D2,E2,C1,B2,C2,B1,A2,A1	20
7	C2,B3,B4,A1,A2,B2,B1,C1	11
8	D1,B1,D3,C3,D2,B2,C1,B3	4
9	C1,F5,F6,B2,C2,D2,F4,C3	-
10	D2,A2,C2,E2,F2,B2,C3,C1	9
```
（windows版）mongoDBが起動しない

##はじめに
windowsのmongoDBが起動しなくなってしまって解決するまでに半日かかったので忘れないように原因と解決方法を残そうと思います。

OS: Windows7
mongoDB: v4.0.2

##エラーについて
「mongo」コマンド実行時に以下のエラーが出るようになりました。

>
\>mongo
MongoDB shell version v4.0.2
connecting to: mongodb://127.0.0.1:27017
2018-10-06T22:12:18.898+0900 E QUERY    [js] Error: couldn't connect to server 127.0.0.1:27017, connection attempt failed: SocketException: Error connecting to 127.0.0.1:27017 :: caused
by :: �Ώۂ̃R���s���[�^�[�ɂ���ċ��ۂ��ꂽ���߁A�ڑ��ł��܂���ł����B :
connect@src/mongo/shell/mongo.js:257:13
@(connect):1:6
exception: connect failed

肝心な部分が文字化けしてますが、そもそもエラーが出るようになった理由は分かっていて、私の場合はCドライブの容量が足りなくなったことでした。
なので私はmongoDBのデータをDドライブに移管することにしました。
（これが悲劇の始まりでした。。）

##試したこと
とりあえずCドライブにあった「MongoDB」フォルダをごっそりDドライブに移管しました。
で、環境変数のパスを変更しました。

あとは他の方の記事を参考に
・D:\MongoDB\Server\4.0\data\mongod.lockを削除
・D:\MongoDB\Server\4.0\bin\mongod.cfgの中のパスの記載を変更
した後、
`mongod '--dbpath D:\MongoDB\Server\4.0\data'`
を実行すると一応起動はできたのですが、プロセスがデーモンになってくれません。

これでは不便なので、デーモンになるようにいろいろと調べた結果、
`start /b mongod '--dbpath D:\MongoDB\Server\4.0\data'`
を実行しましたが、
>Start-Process : 引数 '--dbpath D:\MongoDB\Server\4.0\data' を受け入れる位置指定パラメーターが見つかりません。

のエラーに。。

そしてついに伝家の宝刀「PC再起動」を試しましたが、それでもうまくいかず、半分諦めてしまいました。

##分かったこと
が、その後いろいろ調べて分かったことは、windowsの場合、mongoDBのインストール時にwindowsサービスにmongoDBが登録されていて、PC起動時にそれが自動実行されてmongoDBが起動するおかげで、普段いきなり「mongo」コマンドが使えているという事実でした。

で、その自動実行のコマンドがレジストリに登録されているということなので確認してみると確かにCドライブのままになっていました！
なのでここをDドライブに変更して（[Windowsのサービスのパスを変更する](https://whitemitt.com/2012/04/06-204920.htm)）、サービスを右クリック⇒開始を押したら無事に「mongo」コマンドが使えるようになりました！

##おわりに
いやー、環境構築系でハマるとほんと泣きそうになりますよね。
解決策っぽい記事があってもツールのバージョンが違ったりOSが違ったりで余計にハマってしまったり。。
今回はWindows×mongoDB×ディレクトリ変更というニッチな記事になったかもしれませんが、いつか困っている誰かの助けになればいいなと思います。

こちらからは以上です。
結局Yarnは速いのか2018秋

Yarnはキャッシュするので速いという話をよく聞いていて、Yarnしか使ってなかったが、最近npmを使う機会があって気づいたのは、そこまで遅くないなということ。6.xになってから爆速になったという噂もそういえばあった。

*この記事は速さのみに絞っているので、npmは`audit`があるだとか、yarnの`upgrade-interactive`は至高だとか言う話は置いておきます。

# 計測環境
- MacBook Pro (13-inch, 2018)
- macOS High Sierra Version 10.13.6
- Node.js v10.11.0
- npm v6.4.1
- Yarn v1.10.1

```json:package.json
{
	"private": true,
	"dependencies": {
		"@types/bcrypt": "^3.0.0",
		"@types/joi": "^13.6.0",
		"@types/koa": "^2.0.46",
		"@types/koa-bodyparser": "^5.0.1",
		"@types/koa-router": "^7.0.32",
		"@types/react": "^16.4.15",
		"@types/react-dom": "^16.0.8",
		"bcrypt": "^3.0.1",
		"concurrently": "^4.0.1",
		"del-cli": "^1.1.0",
		"joi": "^13.7.0",
		"koa": "^2.5.3",
		"koa-bodyparser": "^4.2.1",
		"koa-router": "^7.4.0",
		"onchange": "^5.0.2",
		"parcel-bundler": "^1.10.1",
		"pg": "^7.5.0",
		"prettier": "^1.14.3",
		"react": "^16.5.2",
		"react-dom": "^16.5.2",
		"reflect-metadata": "^0.1.12",
		"ts-node": "^7.0.1",
		"tslint": "^5.11.0",
		"typeorm": "^0.2.7",
		"typescript": "^3.1.1"
	}
}
```

- 計測は`/usr/bin/time`を使用

# lockファイルなしの場合
npm: `15.93 real        23.63 user        14.89 sys`
Yarn: `15.55 real         8.09 user        12.14 sys`

# lockファイルありの場合
npm: `11.88 real        19.40 user        13.19 sys`
npm ci: `8.00 real         2.47 user         0.40 sys`
Yarn: `8.46 real         5.81 user        11.53 sys`

# 考察

- 新規インストールは大して変わらないが、lockファイルが存在するときの高速化はYarnが勝る。
- そもそもnpmはlockファイルがあろうがなかろうが依存関係を解決するらしいので、Yarnが速いのは当たり前か。
- ただし依存関係を解決しないciコマンドだと、Yarnと同じくらいでしかもユーザーCPU時間が半分以下。
- 既存プロジェクトを引っ張ってきて最初のインストールは`npm ci`、その後は`npm i`を使ったら、Yarnとほぼ同じの速さ。

# 結論

Yarnは速くない。他の機能でどっちを使うか決めよう。

# 注意

ベンチマーク素人です。アドバイス頂けたらありがたいです。
MacにElixirをインストールする方法など

#環境とバージョン
Mac：10.13.6
Erlang：21.1
Elixir：1.7.3

#インストール方法
今回は、ErlangをerlenvでElixirをexenvでインストールをします。
まず、Homebrewがインストールされていないなら下のリンクからインストールする。
[Homebrew](https://brew.sh/index_ja)

Homebrewのインストールが済んだら、以下のコードを一行ずつターミナルで実行する。
breｗからopensslをインストールし、Erlenvをgitで取得する。

```bash
brew update
brew install openssl
echo 'export PATH="/usr/local/opt/openssl/bin:$PATH"' >> .bash_profile
source ~/.bash_profile
cd
git clone https://github.com/talentdeficit/erlenv.git .erlenv
echo 'export PATH="$HOME/.erlenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(erlenv init -)"' >> ~/.bash_profile
source ~/.bash_profile
```

次に、Erlangをインストールする。
※ビルドの部分の・・・には自分のPCの名前を入れる。

```bash
// ダウンロードと解凍
curl -O http://erlang.org/download/otp_src_21.1.tar.gz
tar zxf otp_src_21.1.tar.gz
cd otp_src_21.1
```


```bash
//ビルド
./configure --prefix=/Users/・・・/.erlenv/releases/21.1 --enable-smp-support --enable-threads --enable-darwin-64bit --enable-kernel-poll --enable-hipe --without-javac --enable-dirty-schedulers --enable-sharing-preserving --enable-lock-counter --disable-sctp --with-ssl=/usr/local/opt/openssl --without-obdc
```

※ビルドの記述は分けずに入力してください

```bash
touch lib/wx/SKIP lib/odbc/SKIP
make
sudo make install
erlenv global 19.1
erlenv rehash
```

これで、Erlangのインストールは完了です。
下記のコードを実行して、正常にインストールされているか確認してください。

```bash
erl
```

確認ができたら、ctrl+cで抜けます。

次に、brewからexenvをインストールします。

```bash
brew install elixir-build
brew install exenv
echo 'export PATH="$HOME/.exenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(exenv init -)"' >> ~/.bash_profile
source ~/.bash_profile
```

※ここで下記のメッセージが表示されたら`cd`を入力して.bashrcを作成してください。

```bash
-bash: .bashrc: No such file or directory
```

最後に、Elixirをインストールします。

```bash
exenv install -l
exenv install 1.7.3
exenv global 1.7.3
elixir -v
```

※インストールできるバージョンは1行目の`exenv install -l`を実行したときに、表示されるので表示されているバージョンをインストールしてください。

これでElixirのインストールは完了です。

#Elixerを学び始めてつまづいたこと

@piacere_ex さんが連載している[Excelから関数型言語マスター](https://qiita.com/piacere_ex/items/6714e1440e3f25fb46a1)の記事で学んでいた際につまづいたことについてまとめたいと思います。

この記事は、機能を一つずつ詳しく解説してくれているのでとてもわかりやすかったです。特に、forの説明は、C言語などをかじっている私からするととても助かりました。

唯一つまづいたところは、Phoenixのインストールです。
今回、私がインストールしたElixirのバージョンは1.7.3です。
このバージョンでは、記事の通りPhoenixをインストールをしてもインストールすることができない。
その理由は、Phoenixのホームページに書いてあった。
Elixirのバージョンが1.4より後のものは、

```bash
mix local.hex
```

このコードを入力する必要があるようです。
AWS IAM ハンズオン

[AWS IAM](https://qiita.com/leomaro7/items/7b7018c120830bfe730e)も事前に読んで見ましょう！



##1.IAMユーザーを作成する##
IAM を開き、「ユーザー」から「ユーザーを追加」をクリックします。
![スクリーンショット 2018-10-06 20.23.51.png](https://qiita-image-store.s3.amazonaws.com/0/280929/919cfe06-1282-7dec-fcdd-ad694c11f16b.png)

ユーザー名は適当な名前を入力します。
「プログラムによるアクセス」を選択した場合は、アクセスキー
「AWS マネジメントコンソールへのアクセス」を選択した場合は、パスワードの生成をしていきます。
今回は、「AWS マネジメントコンソールへのアクセス」にし、「カスタムパスワード」を設定、「パスワードのリセットが必要」はチェックせず、「次のステップ」に進みます。
*後から、「プログラムによるアクセス」によるアクセスキーを追加することが可能です。
![スクリーンショット 2018-10-06 20.29.26.png](https://qiita-image-store.s3.amazonaws.com/0/280929/9a523e5a-17c1-e575-3648-3591478c6cd8.png)

予め権限がついているグループがある場合、グループに所属させれば、個別にアクセス権限を作成しなくてもいいです。
ここでは個別にグループを作成し、S3にフルアクセスをつけます。
「既存のポリシーをアタッチ」を選択し、「AmazonS3FullAccess」にチェックを入れ、「次のステップ」へと進みます。
*自分でポリシーを作成することも可能ですが、予めAWSで用意されたポリシーがあります。*
![スクリーンショット 2018-10-06 20.36.48.png](https://qiita-image-store.s3.amazonaws.com/0/280929/fb2b4b27-5007-ece8-c839-f542243c7ed7.png)

「ユーザの作成」をクリックします。
![スクリーンショット 2018-10-06 20.38.15.png](https://qiita-image-store.s3.amazonaws.com/0/280929/ca997fd6-e31d-9beb-27ef-8cefed2d8dfa.png)

パスワードなどの情報は「CSVのダウンロード」で確認することとなります。
![スクリーンショット 2018-10-06 20.39.49.png](https://qiita-image-store.s3.amazonaws.com/0/280929/8066d094-8da5-6af4-9bc5-4ecd9d885d11.png)



##2.プログラムによるアクセスキーを追加する##
1.では「AWS マネジメントコンソールへのアクセス」のみにしましたが、「プログラムによるアクセス」によるアクセスキーを追加していきます。

作成したIAMユーザを選択します。
![スクリーンショット 2018-10-06 20.52.44.png](https://qiita-image-store.s3.amazonaws.com/0/280929/a06c72b0-a3af-28cb-1cc5-ba65331fdea2.png)

「認証情報」から「アクセスキーの作成」をクリックします。
![スクリーンショット 2018-10-06 21.37.14.png](https://qiita-image-store.s3.amazonaws.com/0/280929/04553b53-9563-b4da-835a-37ba9e2208e9.png)

アクセスキーが作成されます。
*アクセスキーは1度のみしか表示されません*
![スクリーンショット 2018-10-06 20.54.47.png](https://qiita-image-store.s3.amazonaws.com/0/280929/ff988f75-3c71-b3e1-0256-350f98c8cbe6.png)



##3.MFA デバイスの割り当て##
セキュリティを高めるために多要素認証を設定します。

[MFA デバイスの割り当て]の「管理」をクリックします。
![スクリーンショット 2018-10-06 20.53.02.png](https://qiita-image-store.s3.amazonaws.com/0/280929/18a00c46-6ded-f5a9-3f19-9ea3fc5b04e6.png)

「続行」します。
![スクリーンショット 2018-10-06 20.58.53.png](https://qiita-image-store.s3.amazonaws.com/0/280929/ebea9c5b-845f-432a-7a57-cb35a4bc0cc0.png)

[Google Authenticator ](https://itunes.apple.com/us/app/google-authenticator/id388497605?mt=8)などをスマホにインストールし、QRコードを読み込み表示された認証コードをAWSに入力し、「仮想MFAの有効化」をクリックします。
・認証コード１：今表示されている数字を入力
・認証コード２：認証コード１の次に表示された数字を入力
![スクリーンショット 2018-10-06 21.40.40.png](https://qiita-image-store.s3.amazonaws.com/0/280929/0698b30d-0bac-10bb-d3b4-418ada284523.png)

実際にログインするときに、ワンタイムパスワードを入力する必要が出てきます。
![スクリーンショット 2018-10-06 21.43.40.png](https://qiita-image-store.s3.amazonaws.com/0/280929/cc5bc8ff-ab2d-06fc-1169-672b5dd03cfe.png)

＊ちなみにMFAデバイスは紛失したり、後初期化しないように！
　ただ、そんな時は↓があるようです。
参考：[MFA デバイスの紛失および故障時の対応](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_mfa_lost-or-broken.html)



##4.IAM ユーザーのサインインリンクを変更する##
お気に入りに登録すれば問題ないですが、覚えやすいものに変更することも可能です。

画面右側の「カスタマイズ」をクリックし、「アカウントエイリアス」に任意のものを入力。
![スクリーンショット 2019-01-31 20.58.39.png](https://qiita-image-store.s3.amazonaws.com/0/280929/483a0ff9-18d9-3af6-23df-6cc1c08c8a05.png)
15秒で理解するmain関数からのreturnとexitとquick_exitとか

# お詫びと訂正

初投稿時は15秒で目を通せそうな内容でしたが(当社比)、現状15秒では無理そうです。

# はじめに

@celluloce に記事投稿の少し前にはなしたメモをせっかくだから上げておくだけです。

なお話がややこしくなるのでsignalとの絡みは割愛します。

# main関数からのreturn文

- main関数のスコープにある変数やstatic storageな記憶期間の変数のデストラクタが呼ばれる(C++)
- というかautomatic storageな記憶期間の変数のデストラクタを呼んだあと`exit`を呼ぶ
- なので、`atexit`で登録された関数が呼ばれる

```cpp:atexitで登録した関数が呼ばれる
#include <iostream>
#include <cstdlib>
void on_exit()
{
    std::cout << "on_exit called" << std::endl;
}
int main(){
    std::atexit(on_exit);
    return 0;
}
```

```plain:実行結果
on_exit called
```

https://wandbox.org/permlink/QxiWKjAxiDbXHj9w

# `exit`呼び出し

- `atexit`で登録された関数を呼び出してから終了する
- static storageな記憶期間の変数のデストラクタが呼ばれる(C++)
- つまりC++では概ね`quick_exit`を使うべき(C++)

# `quick_exit`呼び出し

- `at_quick_exit`で登録された関数を呼び出してから終了する
- C11/C++11から
- 主にマルチスレッドプログラムの同期をキャンセルしてプログラムを終了させるときに。
- Cストリームのバッファはフラッシュされない。
- 一切のデストラクタを呼びたくないときもこっち(C++)

# `_Exit`呼び出し

- 基本`quick_exit`と同じ。というか`quick_exit`が`at_quick_exit`で登録された関数を呼び出したあとにこれに処理を投げるので当たり前だけど

# `abort`呼び出し

- 基本`_Exit`と同じ。がしかし、これは**異常終了を通知**する。
- `at_quick_exit`で登録された関数を呼び出さないと思うんだけど、C11規格書(N1570)やC++17規格書(N4659)を読んでも該当文章が見つからない・・・

# まとめ

|                                            | main関数からのreturn文 | exit | quick_exit | _Exit      | abort      |
|--------------------------------------------|------------------------|------|------------|------------|------------|
| `atexit`で登録された関数の呼び出し          | ○                      | ○    | ✕          | ✕          | ✕          |
| `at_quick_exit`で登録された関数の呼び出し    | ✕                      | ✕    | ○          | ✕          | ?          |
| Cストリームバッファのフラッシュなど        | ○                      | ○    | 処理系定義 | 処理系定義 | 処理系定義 |
| static storageな期間をもつ変数の破棄       | ○                      | ○    | ✕          | ✕          | ✕          |
| thread local storageな期間をもつ変数の破棄 | ○                      | ○    | ✕          | ✕          | ✕          |
| automatic storageな期間をもつ変数の破棄    | ○                      | ✕    | ✕          | ✕          | ✕          |

「Cストリームバッファのフラッシュなど 」というのは、

- Cストリームバッファのフラッシュする
- 開いているすべてのCストリームを閉じる
- `tmpfile`関数で作られた一時ファイルの除去

の3点セットのこと。

# ref

storageについては
[C++のメモリーの話とストレージの有効期間の話をしようか](https://qiita.com/yumetodo/items/067b2db266ae0779f030)

デストラクターとは？という人は
[C++入門者に贈るclass入門とclass/structキーワードの使い分け](https://qiita.com/yumetodo/items/b0ff58617f2733d4ffa1)

# License

[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/deed.ja)

<a href="https://commons.wikimedia.org/wiki/File:CC-BY_icon.svg#/media/File:CC-BY_icon.svg"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/CC-BY_icon.svg/1200px-CC-BY_icon.svg.png" alt="CC-BY icon.svg" width="88px"></a>
KibelaからLineに通知する

# 手順
* LineNotifyからtokenを発行する
* GoogleAppsScriptで以下を作成してtokenを張り付ける
* GoogleAppsScriptで発行されたアプリケーションのURLをKibelaの[ここ](https://my.kibe.la/team/settings/outgoing_webhooks/generics/new)で設定する

```javascript
var postUrl = "https://notify-api.line.me/api/notify";
var token = "line側で発行して張り付ける";

function doPost(e){
  
  var json = e.postData.getDataAsString();
  var params = JSON.parse(json);
  
  // 新規、更新、削除
  var actionType = params["action"];
  // ブログ、WIKI、コメント
  var resourceType = params["resource_type"];
  // 実行した人の名前
  var name = params["action_user"]["account"];
  // URL
  var url = params[resourceType]["url"];
  // 通知メッセージ
  var message = "";
  
  // wikiの更新は頻繁にあるし削除は見なくても良さそうなので
  // 新規以外は通知しない
  if(actionType != "create"){
    
    return;
    
  }
  
  message = resourceType + "：" + actionToJapanese(actionType)  + "\n" + name + "\n" + url;
  
  var options =
  {
    "method"  : "post",
    "payload" : "message=" + message,
    "headers" : {"Authorization" : "Bearer "+ token}
  };

  // lineに投げる
  UrlFetchApp.fetch(postUrl,options);
}

function actionToJapanese(actionType){
  switch(true){
    case actionType == "create":
      return "投稿";
      
    case actionType == "update":
      return "更新";
      
    case actionType == "delete":
      return "削除";
  }
}
```

# 参考
KibelaのwebhoockDoc
https://docs.kibe.la/api-documents/japanese/outgoing-webhook
Kibelaの投稿をSlackに通知する
https://qiita.com/yakimeron/items/5e2414c80947a68b6b52
【Adobe Audition】Adobe Premiere を使って簡単ノイズ除去

# はじめに

`適応ノイズリダクション`っていうかんたんにノイズ除去できるものがありますが、
**ぶっちゃけそんな音消えないし** **ちっちゃい音も一緒に消えるし** **なんか最初の部分だけノイズ入るし** で
そこまで使えないので、 **Adobe Audition**を使って音を消してみました。

ちなみに前提として**音声いじるの初心者**です。
素人からすると「え？ノイズなくない？」って思うレベルのものしか作れません。あとなんの値をいじったからどうなるとかもわかりません。ほぼ感覚値です。

**とりあえずどうしてもPremiereでノイズ消せない！助けて！**って人向け and 自分むけの備忘録です。

# Auditionで音声ファイルを開く
Premiereのノイズ除去したい音声を右クリック `Adobe Auditionでクリップを編集`してAuditionを開きます

# ノイズのキャプチャ
ノイズを除去するために、**ノイズのサンプリング**をして、それをもとデータに読ませます。
まずはサンプリングから

**ノイズだけをサンプリング**するなら**環境音しか入っていない箇所**を取得すればいいのです（持論）

<img width="740" alt="スクリーンショット 2018-10-06 20.57.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/63740/9c858dfc-e712-0229-a24f-9cd352a28af8.png">

環境音のみの箇所をまずは**ドラック**で範囲指定します。
そこで右クリック `ノイズプリントをキャプチャ`を選択して、ノイズのサンプルを取得します。

次に、ノイズキャンセルしたい箇所（おそらくファイル全体の場合が多いのでは？)を選択し、
タブの `エフェクト -> ノイズリダクション/リストア -> ノイズリダクション(プロセス)` を選択

<img width="703" alt="スクリーンショット 2018-10-06 21.01.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/63740/a4ee9729-ec5c-721f-448a-8b0980401416.png">

**すごい画面**がでてきます。
ぶっちゃけここに来た時点でノイズかなり減りますが、気になる方は**ノイズリダクション**の値や、**削減値**、**上の青いバー**を調整してください。

この画面での音の確認は、下の`三角ボタン`で確認できます。

調整終えたら`適応`ボタンを押して、いつものプレビュー画面で音声の確認。問題なければ`cmd+S`を押すと、**Premiereに音声データが反映されています！**これでノイズ除去完了です！

# まとめ
手順をまとめます。

1. Premiereでノイズ除去対象のファルを右クリック`Adobe Auditionでクリップを編集`してAuditionを開く
2. ノイズ入の環境音を範囲選択、右クリック`ノイズプリントをキャプチャ`からサンプリング
3. ノイズ除去エリアを選択し、タブの `エフェクト -> ノイズリダクション/リストア -> ノイズリダクション(プロセス)` を選択
4. **ノイズリダクション**の値や、**削減値**、**上の青いバー**を調整し、ノイズ除去
5. `cmd+S`でPremiereに反映される！

----------------------------

ちょっと手順多かったので、もっと簡単にできるよとか、もっときれいに編集する方法あるよとかあればお教えください。
初学者なので修正リクエストもお待ちしてます！
ニコニコ動画の情報をブラウザからJSONで取得してコメント部分をPythonで抜き出す

#はじめに
多少手作業があるが、ニコニコ動画のコメントをざっくりと抜出すのにお手軽かなと。

#ブラウザの開発者ツールからレスポンスデータを抜き取る
Chromeです。Windowsだと <kbd>F12</kbd> で開発者ツールの画面を表示。
[Network]のタブを表示して、コメントを取得した動画をリロード。
たぶん、`api.json/`のレスポンスデータがそれだが、適当なコメントの文字列で検索してもいい。
見つかったら、[Response]のタブでJSON文字列をコピーするか、`api.json/`を右クリックして[Copy] > [Copy response]をクリックする。

#JSON文字列からコメント部分をPythonで抜き取る
```python
import io
import json

with open('niconico.txt', 'r') as f:
	for x in  json.load(f):
		if 'chat' in x:
			y = x['chat']
			print ('%s\t%s' % (y['no'], y['content']))
```
とりあえずファイル名は固定にして、標準出力へ出力。
出力内容はコメントの番号とコメントのみで、タブで区切っている。
コメント時の動画の位置やコメントした日時が欲しい場合一工夫必要。
自動化するとなったら詳しい情報を記載してくれているすばらしい記事があるのでそちらを参照。

#参考にした記事など
- [【Python入門】JSONをパースする方法 - Qiita](https://qiita.com/Morio/items/5170c103647ef3a4aa69)
- [複雑なJSONから特定のデータを取り出す - Qiita](https://qiita.com/jumpyoshim/items/3b138d3ebbdaa873eaa5)
- [ニコニコ動画のコメントをJSONで取得する - Qiita](https://qiita.com/tor4kichi/items/74939b49954d3e72d789)
（作成中）PyCon mini Hiroshima 資料一覧

https://pyconjp.connpass.com/event/91821/
https://hiroshima.pycon.jp/

#### PyCon mini Hiroshima にて発表があった方々の資料をまとめています。


- [Pythonの10年と今、これから](https://www.slideshare.net/ssuserafaef6/python10-118423089)
- [Pythonで遊ぼうコンピュータ将棋]
- [Pythonコミュニティを通じて学んだこと]
- [Python初心者がPyTorchをいじって機械学習の計算してみた]
- [Google Cloud PlatformとPythonのいま](https://slideship.com/users/@rhoboro/presentations/2018/10/GDSukf3ibUD8BV1xk4H8Xy/)
- [舞え！ひろしま Kaggler]
- [Introduction to Data Science in Python （Visualization ver.）](https://www.slideshare.net/ksnt/pyconmini-hiroshima-2018-118202503)
- [Pythonで動物の行動データを解析する研究をするには]
【Game a Week】９週間目

# Game A Week
1. 一週間（月曜日から日曜日）に一本ゲームをリリースする。
2. 日曜日（まで）に制作したゲームを何らかの手段で公開する。
3. 制作したゲームはGame A Weekが終わるまで改変しては行けない。

# 前置き
先週の作品：[【Game a Week】8週間目](https://qiita.com/hota1024/items/3977845e7af8ec302929)

# 今回作ったゲーム
今回はUnityを使ってアクションゲームを作ってみました。

# 使った技術
| 名前 | 説明 |
|:-:|:-:|
| [Unity](https://unity3d.com/)  |  ゲーム開発環境  |

# ゲームの詳細
名前は「UpBox」。
<https://github.com/hota1024/UpBox-Unity>で公開しています。

<img width="375" alt="IMG_0471.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/154299/e8509fb1-6bbc-3997-504d-b5749555be19.png">

「Tap Here to Start」をタップするとゲームが始まります。

<img width="375" alt="IMG_2ACA6AA6D445-1.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/154299/b6a42009-26d8-ea66-844e-64e43c9c23ce.jpeg">

左上の「1m」はスコアです。
画面中央の四角がプレイヤーです。
赤いオブジェクトはすべて障害物で当たるとゲームオーバーです。

画面をタップ長押しすることでプレイヤーを上に移動させることができます。
逆にタップを離すとプレイヤーが下へ落ちてしまいます。

下からは壁が迫ってきます。
<img width="375" alt="IMG_35757C6150B2-1.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/154299/0c43d9ca-84d8-d3af-bfce-1edbdc21599d.jpeg">


# 9週間目の感想
今週は1週間目のと同じUnityを使ってゲームを作りました。

1つ悩んだことがあり、`Mathf.Deg2Rad`を`Mathf.Deg2Rad(angle)`でやっても動かなくてよく見たらこれ掛け算してラジアンに変換するんですね(`angle * Mathf.Deg2Rad`)。

# 最後に
ここまで読んでいただきありがとうございます。
良ければアドバイスや質問よろしくおねがいします。
mongoidで配列の値が特定のモデルのデータに含まれているかを一括検索する方法

## 前提事項を確認
`mongoid` はRailsにおける ActiveRecordのような感覚で、MongoDBを扱えるようにしたgemです。

## 検証時のローカル環境
- MongoDBのバージョン ： 3.4.9
- mongoidのバージョン : 7.0.2

#### *事前にbrewの以下のコマンドでMongoDBを入れておくこと

```ruby
$ brew install mongodb
```

#### *ざっくり用語まとめ
|MongoDB|RDB|
|------|---|
|データベース|データベース|
|コレクション|テーブル|
|ドキュメント|レコード|
|フィールド|カラム|

## 配列の値が特定のモデルのデータに含まれているか一括検索

#### `モデル名.in(フィールド名: 配列)` を使う

*検証例として `name` という、文字列フィールドを持つモデルがあるという前提

```ruby
class Topic
  include Mongoid::Document
  field :name, type: String
end
```

```ruby
# Rails consoleにて実施

# 検証用のデータを作成
Topic.create(name: "hoge")
=> #<Topic _id: 5bb8958194685c0aa2e866dc, name: "hoge">
Topic.create(name: "fuga")
=> #<Topic _id: 5bb8958794685c0aa2e866dd, name: "fuga">

# 検索条件用の配列を用意する
names = %w(hoge fuga fuge)
=> ["hoge", "fuga", "fuge"]

# モデル.in(name: 配列)で、配列内の値と一致するデータを一括検索できる
Topic.in(name: names).to_a
=> [#<Topic _id: 5bb8958194685c0aa2e866dc, name: "hoge">, #<Topic _id: 5bb8958794685c0aa2e866dd, name: "fuga">]

```

## 素朴な疑問 : `.to_a` って何で末尾に付けてるの？

#### 付けない場合と付けない場合を比較してみる

```ruby
# .to_a を付けない場合
Topic.in(name: names)
=> #<Mongoid::Criteria
  selector: {"name"=>{"$in"=>["hoge", "fuga", "fuge"]}}
  options:  {}
  class:    Topic
  embedded: false>

# .to_a を付けた場合
Topic.in(name: names).to_a
=> [#<Topic _id: 5bb8958194685c0aa2e866dc, name: "hoge">, #<Topic _id: 5bb8958794685c0aa2e866dd, name: "fuga">]
```

#### 結論
 `.to_a` を付けないとクエリが発行されないので、データを取得して値として使うことが出来ないため
（レポート）BPStudy#132〜 0 to 1. 事業のつくりかたを語る

https://bpstudy.connpass.com/event/95001/

# 第1部 無人コンビニ『600』を支える技術と社内制度
- バリューの策定
        - 2人目が入って来た時に指標になる。
    - 形骸化した時に、納得できない時に
    - ビジネスモデルに繋がる
    - 利他性
- 業務体制の構築
- 完全週休三日制
    - スイッチングコストが良い
    - KPIに対する優先順位が正しく行える。

- ６００の組織
    - 1人であっても組織図を書く
        - 目線が変えられる
        - 二人目が来た時に、権限でもめない
- KPIは一つに絞る。
    - ただし、ステージが変わればKPIを変える
    - 目線がブレないようにする

# 第2部 connpass, PyQ。自社サービスプロジェクトから学んだ事業開発の進め方
- 事業開発にプロセスはある。（仮説）
## 事業開発の7つのステップ
- 立ち止まる
    - アイディア（着想）を得るには、ないが必要？
    - 視点 
    - 現状の不を解決し、あるべき姿にする
    - 負の発見ができれば、
    - 負の発見の視点。めんどくさい、辛いの感情。
    - めんどくさい、やらないと➡︎頑張る➡︎　思考停止。
- 不を認識する
    - 不の存在範囲を確認する。
        - 自分➡︎自社➡︎社会
- アイディア（着想）を得る
    - どういう姿になれば、嬉しいか
    - 二層式洗濯機➡︎全自動洗濯機
    - 電話・メール➡︎LINE
- 進むべきか考える
    - 時間を使ってでも取り組むことか考える
- 目指す方向を描く
    - 製品ビジョン
        - コンセプト
        - 構想
        - 特徴
        - やらないこと
- アイディアを試作する
    - ツールプロトタイプ
    - LP
    - 動くプロトタイプ
- 反復する
- 作る
    - MVP
    - 製品開発

- 初めは、1人で回して　一回回すのに１日程度でできる？
- 複数人の時には、ツールだったりで見えるかするとよい。

https://scrapbox.io/shimizukawa/BPStudy-132
Material UI の Dialog 内のコンポーネントで Returnキーが押されたらDialogを閉じる。

# TL;DR

今現在、業務で関わっているSPA開発で [Material UI](https://material-ui.com/)を多用しており、 [Dialog](https://material-ui.com/api/dialog/) を使うところもありそうなので、使い方を調べがてら主題のスパイクを行ったので共有します。

# 目的

公式ドキュメントにあるサンプル

- [Simple Dialogs](https://material-ui.com/demos/dialogs/#simple-dialogs) 

をもとにして、以下の AS IS: から TO BE: になるように手を入れました。

### AS IS：

以下のダイアログ

<img width="624" alt="スクリーンショット 2018-10-06 20.17.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/74659/3379dc33-6257-08d6-4c31-b1f6a5f62147.png">


が開いたときに、元のサンプルでは、メールアドレスや "add account" の各`<ListItem>` でマウスがクリックされたら、それが選ばれてダイアログが閉じるようになっている。

### TO BE： 

各 `<ListItem>` の上にマウスが乗っている状態で Returnキーが押されたら、それが選ばれて、ダイアログが閉じるようにする。

# 作ったもの

いちおう、 TO BE になるような修正ができたので、以下に上げました。

- https://github.com/jun68ykt/dialog-spike

create-react-app で作ったアプリのひな形をもとに作成しました。以下にて動かすことができます。

- git clone git@github.com:jun68ykt/dialog-spike.git
- cd dialog-spike
- yarn install
- yarn start


元のサンプルコードから手を入れた部分は以下です。

- [Dialog closed onKeyDown of CR(13) key on ItemList](https://git.io/fx3Mi)


## より良い方法があれば

より良い方法があれば是非ご教示ください。
Macで圧縮したくてエクセルファイルをそのままzipcloakしようとしたら暗号化できちゃって焦った

しょーもない感じの話なんですが。

#　やりたかったこと
Macを使ってまして。
でも一般的（そろそろレガシー気味）なIT企業（笑）のシステムエンジニア（笑）であるところの僕としてはごくごく普通にエクセルファイルをzip圧縮して提出、なんてことを求められるわけです。

とりあえず編集自体はnumbersでなんとかしたんですけど、問題はzip圧縮。

特にパスワードを掛ける方法ですね。
これが地味なところで詰まったので、備忘を兼ねてメモしておきます。


# 圧縮してからzipcloak。
とりあえず、やりかたとしては**エクセルファイルを直接ではなく、圧縮してからzipcloak**する形になります。

普通にエクセルファイルのコンテキストメニューから圧縮してできたzipファイルに対して`zipcloak 圧縮したzipファイルのパス`とterminalから叩き込みます。
そうするとパスワードを聞かれるので、入力すると**zipファイルがパスワード付きのzipファイルに変換されます。**


# 焦るポイント
まあここまでは普通に、単なるパスワード付きzipファイルの作成方法なんですが。

zipcloakはあくまでzipファイルにパスワードかけるだけなので、zip圧縮をするわけじゃないんですよね。
ちょっと僕、ここのところを勘違いしてまして。

そのせいでちょっと焦ることになりました。

どういうことかっていうと、他のファイルならちゃんと**zipファイルを指定しろよ**ってエラーを吐いてくれるんですけど、エクセルファイルは事実上のzipファイルなせいで**zipcloakはxlsxファイルに対しても効いちゃう**んですよね。


```bash:オイオイオイ暗号化してるわxlsx
mbp:ziptest raging_alpaca$ ls
fuga.xlsx	hoge.zip
mbp:ziptest raging_alpaca$ zipcloak fuga.xlsx 
Enter password: 
Verify password: 
encrypting: _rels/.rels
encrypting: docProps/core.xml
encrypting: docProps/app.xml
encrypting: xl/workbook.xml
encrypting: xl/_rels/workbook.xml.rels
encrypting: xl/theme/theme1.xml
encrypting: xl/worksheets/sheet1.xml
encrypting: xl/sharedStrings.xml
encrypting: xl/styles.xml
encrypting: [Content_Types].xml
mbp:ziptest raging_alpaca$

```

……。

**当然ながら、この状態だとnumbersとかopenofficeとかからも開けなくなります。**

 ![スクリーンショット 2018-10-06 20.14.38.jpg](https://qiita-image-store.s3.amazonaws.com/0/214031/4de2e4ac-202a-a5e2-32dc-3c2ea70c1b3e.jpeg)

焦ります。

拡張子をzipにすれば開けるのか？というとそういうわけでもないようで。
どうやって戻すかといえば、もう一度zipcloakを`-d`オプション付きで実行することで戻せます。

```bash:
mbp:ziptest raging_alpaca$ zipcloak -d fuga.xlsx 
Enter password: 
decrypting: _rels/.rels
decrypting: docProps/core.xml
decrypting: docProps/app.xml
decrypting: xl/workbook.xml
decrypting: xl/_rels/workbook.xml.rels
decrypting: xl/theme/theme1.xml
decrypting: xl/worksheets/sheet1.xml
decrypting: xl/sharedStrings.xml
decrypting: xl/styles.xml
decrypting: [Content_Types].xml
mbp:ziptest raging_alpaca$ 

```

使うときは`-O`をつけて、`zipcloak -O [新しいファイル名] [圧縮したいファイル名]`として使う方が無難かも……？
いや必要ないか。

```
mbp:ziptest raging_alpaca$ zipcloak -O fuga2.xlsx fuga.xlsx 
Enter password: 
Verify password: 
encrypting: _rels/.rels
encrypting: docProps/core.xml
encrypting: docProps/app.xml
encrypting: xl/workbook.xml
encrypting: xl/_rels/workbook.xml.rels
encrypting: xl/theme/theme1.xml
encrypting: xl/worksheets/sheet1.xml
encrypting: xl/sharedStrings.xml
encrypting: xl/styles.xml
encrypting: [Content_Types].xml
mbp:ziptest raging_alpaca$ ls
fuga.xlsx	fuga2.xlsx	hoge.zip
mbp:ziptest raging_alpaca$ 

```


# 追記
そのあと送ったら「文字化けしとーが」ということを言われてしまいました。

調べたら、Macのコンテキストメニューからの圧縮はMac用のフォーマットで固めるという罠があるらしいですね。

そのへんをどうにかするには素直にアプリに頼るのがよさそうです。
いろいろ出てるようですが、とりあえずググって最初に出てきたこちらを使うことにしました。

- https://tida.me/macwinzipper

ドラッグドロップで圧縮できて、パスワードを数字4桁までで掛けられます。
適当に選んだ割には、僕の場合にはちょうどいい感じの作りでした。
FacebookとLinkedInから学ぶローカライズ（Family Name？それともLast Name？ ）

ローカライズ、主にWebアプリケーションなどの英語対応と日本語対応を目的とした名前周りの調査を行ってみました。

その前に、念のため英語おさらいしてみます。

* 姓：Last Name / Family Name
* 名：First Name
* ミドルネーム：Middle Name

![Facebook English.png](https://qiita-image-store.s3.amazonaws.com/0/37334/39aee301-f5ad-527a-cf40-5d8fc1ee5fec.png)

## 結論

FacebookとLinkedInを比較してみたところ、それほど違いはないが、Facebookの方が上手く多言語にローカライズされており、直感的に使いやすくわかりやすい印象を受けた。尚、姓名は両者とも英語で「Last Name」と表示し、「Family Name」という言葉は使っていない。

### 共通点

* 両者とも英語で`Family Name`という言葉は使われておらず、`Last Name`が使われている
* 両方とも、日本向けには「ふりがな」の入力欄を作っている。Facebookは「姓（カタカナ）」「名（カタカナ）」で、LinkedInでは「ふりがな（姓）」「ふりがな（名）」
* 両方とも、英語向けにはFirst Name, Last Nameの入力欄を作っている
* 両者とも、（アプローチは異なるものの）旧姓を入力することができる

### 共通しない点

* FacebookではMiddle Nameの欄を作っており、LinkedInでは作っていない（LinkedInでは、First Nameに含める事ができる）

### どっちがいいと思うか？

私が思うに、Facebookの方が1歩上手でしょう。利用者は様々な疑問を抱きながら利用しています。例えば、私は英語圏でMichaelという英語名を頂きました。さて、LinkedInのプロフィールのどこに実名と英語名を表記するか？ということになりました。調べると、「Former Name（以前の名前）似でも入れておけば良い」とのことで、そうしました。（※日本語では「旧姓」と表示されるが、英語では「旧名」とも読み取れる。現に、留学生が読みづらい名前を行き先の国に合わせて名前を少し変えたりするためにも使います。）

Facebookではひとまず実名を入れて、旧名やニックネームやスペリングのバリエーションなどはすべてまとめて「別名」に突っ込めるので、迷うことはありませんでしたが、LinkedInではどこに入力したらよいか分からず、前述の通り、調べた上でFirst Nameにミドルネームのイニシャルとファーストネームを一緒に入れたり、Former Nameに実名か英語名を入れるといった方法で回避することになりました。

## スクリーンショット

この件についてリサーチした時のスクリーンショットを公開します。

### Facebook

#### 英語

![Facebook English.png](https://qiita-image-store.s3.amazonaws.com/0/37334/39aee301-f5ad-527a-cf40-5d8fc1ee5fec.png)

名、ミドルネーム、姓　の3つで構成。ニックネームを複数追加できる。

#### 日本語

![Facebook Japanese.png](https://qiita-image-store.s3.amazonaws.com/0/37334/2106c6b3-1167-46bf-32ee-3a66ade60206.png)

（ごめんなさい、`(katakana)`と書いてあるにもかかわらず、間違えて「ひらがな」を入れていました！そもそも、なぜカタカナなのでしょう？）

カタカナで日本語の読み方を入力できる。日本では同じ文字に様々な読み方が使われるため必要という判断でしょう。

### LinkedIn

#### 英語（現在利用中）

![LinkedIn English.png](https://qiita-image-store.s3.amazonaws.com/0/37334/641aeab1-463d-ad0e-8451-4ff9bfdd863b.png)

Former Nameは日本語版で表示すると、「旧姓」と訳されます。

#### 日本語

<img width="781" alt="LinkedIn Japanese.png" src="https://qiita-image-store.s3.amazonaws.com/0/37334/57f77bd9-e2b0-28f4-ecad-ae271c48c47f.png">

Phoneticはあいまいで、何を入れたらいいかはっきりしません。なので、日本語表示に変えてスクリーンショットをとってみました。

![LinkedIn Japanese in Japanese.png](https://qiita-image-store.s3.amazonaws.com/0/37334/9f836ab5-bd8d-165c-28f5-c7eb129603c5.png)

「ふりがな」になりました。つまり、「ひらがな」で名前の読み方を入れるのでしょう。

#### 中国語

<img width="778" alt="LinkedIn Chinese.png" src="https://qiita-image-store.s3.amazonaws.com/0/37334/e50fef90-d07b-696e-f84f-7c673a42a1b6.png">

中国語は勉強中ですが、日本語のように1つの漢字に複数の読み方があることは少なく、おそらくそれ故に「ふりがな」のような項目は提供されていないものだと思われます。

### おまけ

ベトナム人の友達に、「ミドルネームって使うの？」と聞いてみたところ、ミドルネームは使うそうですが、「Webサイトでミドルネームの入力欄を作る必要はなく、無視してよい」とのことでした。それほど重要ではないようです。
Angular FormGroupの setValue() と patchValue()

## 何が違うの？

- `setValue()`は全プロパティに対して、値をセットしているかをチェックします。
- `patchValue()`はチェックしません。


### どう言う事？

例えば下記のようなformをビルドしたとします。

```typescript
form = new FormGroup({
    firstName: new FormControl(''),
    lastName: new FormControl(''),
    age: new FormControl(null),
    birthday: new FormControl(''),
});
```

このフォームに、サービスから取得した下記jsonデータをセットします。

```
customer: {
    firstName: 'Tanaka',
    lastName: 'Taro',
    birthday: '',
}
```

#### setValue の場合

`customer.age`に値を付与していないと、console上にエラーが出ます。
`ERROR内容: Must supply a value for form control at index: age.`

```typescript
form.setValue(customer); // Console error: Must supply a value for form control at index: age.
```

また、逆にjson側にformには存在しないプロパティが存在する場合もconsole上にエラーが出ます。

#### patchValue の場合

チェックはせず、存在するプロパティにだけ値を付与します。

```typescript
form.patchValue(customer);
```

## Angular内部のコードを確認

- [setValue( )](https://github.com/angular/angular/blob/master/packages/forms/src/model.ts#L1261)
- [patchValue( )](https://github.com/angular/angular/blob/master/packages/forms/src/model.ts#L1304)


`setValue()`は `this._checkAllValuesPresent()` で`throw new Error()` をしているのを確認できます。

```typescript
setValue(value: {[key: string]: any}, options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void {
    this._checkAllValuesPresent(value);
    Object.keys(value).forEach(name => {
        this._throwIfControlMissing(name);
        this.controls[name].setValue(value[name], {onlySelf: true, emitEvent: options.emitEvent});
    });
    this.updateValueAndValidity(options);
}

/** @internal */
_checkAllValuesPresent(value: any): void {
    this._forEachChild((control: AbstractControl, name: string) => {
        if (value[name] === undefined) {
            throw new Error(`Must supply a value for form control with name: '${name}'.`);
        }
});
```
PythonからToggl APIを呼ぶ

僕は普段の生活において、[Toggl](https://toggl.com/)を使用して自分が何に時間を使っているのかを計測しています。
本家サイトでは期間毎に集計したレポートを見ることができるのですが、このAPIを呼び出すスクリプトを書いてみました。

# 何をしたいか
Togglでは、各タスク毎にプロジェクトを設定することができるので、１日に費やした１プロジェクトの合計時間を計算し、それをアプリに組み込みたい。

# token と workspace_idを確認する
APIのtokenは[プロフィール画面](https://toggl.com/app/profile)の１番下から確認できます。
workspace_idは、正しい確認の方法がわからないのですが、「Projects」タブのURLを確認して
「https\://toggl.com/app/projects/(workspace_id)/list/page/1」
の中の「projects」と「list」の間がworkspace_idのようです。

# コード
``` python:toggl.py
import requests
import pprint
import sys
from datetime import date

proj = sys.argv[1]  # 集計したいプロジェクト名 
API_TOKEN = ''  # 確認したトークンを設定
W_ID = ''       # 確認したworkspace_idを設定
MAIL = ''       # 登録したメールを設定


def get_toggl():
    headers = {'content-type': 'application/json'}
    today = date.today().isoformat()
    params = {
        'user_agent': MAIL,
        'workspace_id': W_ID,
        'since': today,
        'until': today
    }
    auth = requests.auth.HTTPBasicAuth(API_TOKEN, 'api_token')
    return requests.get('https://toggl.com/reports/api/v2/summary', auth=auth, headers=headers, params=params)


if __name__ == '__main__':
    summary = get_toggl().json()['data']

    for data in summary:
        project = data['title']['project']
        if project == proj:
            time = float(data['time']) / 3600000
            print(time)

```
Django プロジェクトの settings.py に定義された変数を利用する

DjangoProject/settings.py に定義した変数をmodels.pyやviews.pyで使いたいことがあります。
たとえば settings.py に PRIVATE_DIR が定義されているとします。

```Python:DjangoProject/settings.py 
PRIVATE_DIR = 'c://tmp/'
```

この変数を、同じDjangoプロジェクトの中にある他のPythonファイルから利用するには、次のように書きます。

```Python:*.py 
from django.conf import settings
PRIVATE_DIR = getattr(settings, "PRIVATE_DIR", None)
```

##参考
https://stackoverflow.com/questions/7867797/how-do-i-reference-a-django-settings-variable-in-my-models-py
素数列挙を7行で Python

# Python 7行 素数列挙
“Python 素数列挙”と検索にかけるといろんな人が素数列挙をしていますが、どれだけ短くできるのか気になったのでやってみました。

## プログラム
7行まで縮めることができました。

```Python:PN_short.py
pn=[2];A=1000
for L in range(3,A):
	chk=True
	for L2 in pn:
		if L%L2 == 0:chk=False
	if chk:pn.append(L)
print(pn)
```

行数:7  
変数の数:5(ループ変数含)  
関数の数:6  

Aの値はどこまで素数列挙するか指定する変数です。

ネットで素数判定を引っ張ってきてA=10000まで調べましたが全て素数でした。

7行目はprintで表示しているだけなので実質6行です。

## 解説

1行目:`pn=[2];A=1000`  
pnはprimenumberの略です。  
最初に素数である2をリストに入れます。  
Aはどこまで素数列挙するか指定する変数ですので自由に変えてください。
***
2行目:`for L in range(3,A):`  
3~Aまでループして素数かどうか判定します。
***
3行目:`chk=True`  
素数かどうかチェックする変数です。
***
4行目:`for L2 in pn:`  
素数を抽出した分だけループします。  
L2には抽出した素数が入ります。
***
5行目:`if L%L2 == 0:chk=False`  
素数で割れたらchkをFalseにします。
***
6行目:`if chk:pn.append(L)`  
素数判定の変数chkがTrueなら素数なので、pnに追加します。
***
7行目:`print(pn)`  
pnを表示します。
***
***
最後まで見てくれて本当にありがとうございます!  
もしかしたら他の人がもっと短く書いているかもしれませんが紹介でした。

追記
昔の私よ、`if chk == True:`は`if chk:`でいいんだぞ。
PythonistaでWhois Search

## はじめに

iOS上でPythonを実行できるとんでもないApp「Pythonista 3」を利用して，ブラウザで閲覧中のページのWhois情報を確認できるようにしてみました。

- [Pythonista 3](https://itunes.apple.com/jp/app/pythonista-3/id1085978097?l=en&mt=8)

## 実行環境

- iPad Air 2 (iOS 11.4.1)
- Pythonista 3 version 3.2
- Google Chrome version 69.0.3497.105

### ライブラリ

`whois`は標準ではインストールされていないと思うので，追加してください。
StaShが使えるのであれば，`pip install whois`でOKです。
StaShが使えないなら，こんなくだらないことをしていないで使えるようにしましょう。

## ソースコード

```python:whois.py
import appex
import socket
from urllib.parse import urlparse
from whois import whois


def pad(value, length):
	return value + ' ' * (length-len(value)) + ': '


def print_data(title, value):
	if value is None:
		value = 'N/A'
	print(f'{title}{value}')


def main():
	url = appex.get_url()
	host = urlparse(url).netloc
	addr = socket.gethostbyname(host)
	print(f'{host} ({addr})')
	try:
		info = whois(host)
		max_len = max([len(k) for k in info])
		for k, v in info.items():
			if type(v) is list:
				padding = ' ' * (max(len(k), max_len)+2)
				print_data(pad(k, max_len), v[0])
				for i in range(1, len(v)):
					print_data(padding, v[i])
			else:
				print_data(pad(k, max_len), v)
	except:
		print('Failed to get information')

if __name__ == "__main__":
	if appex.is_running_extension():
		main()
```

## [共有]に追加

1. [Settings] > [Share Extension Shortcuts]を開く
2. +マークをタップする
3. ファイルを選択し，必要に応じてタイトルやアイコンを編集する
4. Done!

## 実際に使ってみる

ブラウザの[共有]メニューから[Run Pythonista Script]を選択し，登録したショートカットをタップします。
<img src="https://qiita-image-store.s3.amazonaws.com/0/211353/dc6d7024-5728-2be3-3021-e078798bd8af.png" width="60%">
画像では途中で切れていますがこんな感じの情報を確認できます。
実際にこの機能が役に立つのかは不明ですが……
Django Dataframe形式のデータをModelのデータとして取り込む

# やりたいこと
DataframeのデータをModelのデータとして取り込みさせ、
テンプレートを利用してWeb上に表示させたい。

# 環境
| 項目       |       Version |    
|:----------------:|:-----------------:|
| Django             |              2.1.1 |
| python           |            3.6.5 |
| pandas             |              0.23.4 |
※DBはSQLite(Django初期設定のまま)を使用。

# 経緯
自作のモジュールで抽出したデータを表形式で一覧表示させたかった。 
csvにしようかとか色々模索したのだが、データを使って色々やりたいこともあり、Modelを利用してデータ保存するのが一番楽でよかった。
備忘も兼ねて初投稿してみました...

# 手順
### ルート（url）の設定
お試しということで、データ登録用（登録確認）urlとデータ一覧表示用urlの準備をします。

```python:urls.py
from django.urls import path
from . import views


app_name = 'polls'
urlpatterns = [
    path('create/', views.create_userdata, name='create'),
    path('list/', views.UserListView.as_view(), name='list'),
]
```

### Modelの作成
（姓, 名）のフィールドをもったユーザモデルを作成します。 

```python:models.py    
from django.db import models


class User(models.Model):
    first_name = models.CharField(primary_key=True, max_length=100)
    last_name = models.CharField(max_length=100)
```

### Viewの作成
`update_or_create`を利用すると、登録対象のデータが既に存在している場合、指定したカラムの値を更新することができて便利です。
今回の例は`first_name`を主キーに指定しているので、単にオブジェクトのcreateとするのは主キー重複エラーが発生する可能性がありよろしくないです。

```python:views.py
from django.http import HttpResponse
from django.views.generic import ListView
import pandas as pd

from .models import User


def create_userdata(request):
    userdata = pd.DataFrame({
        "first_name": ["Satou", "Tanaka", "Katou", "Suzuki"],
        "last_name": ["Miyuki", "Yumi", "Kenta", "Asuka"]
    })

    for user in userdata.itertuples():
        User.objects.update_or_create(first_name=user.first_name, defaults={"last_name": user.last_name})

    return HttpResponse('Created UserData!!')


class UserListView(ListView):
    model = User
```

### テンプレートの作成
{{姓}} : {{名}} がリスト形式で表示されるようにします。　

```python:user_list.html
<ul>
  {% for data in user_list %}
  <li>{{ data.first_name }} : {{ data.last_name }}</li>
  {% endfor %}
</ul>
```

### マイグレーション、Django起動
一通り準備が整ったので、コンソールからマイグレーションさせてDjangoを起動させます。

```bash
igimia$ python ./manage.py makemigrations
igimia$ python ./manage.py migrate
igimia$ python ./manage.py runserver
```

# 実行結果
### Modelデータ生成
`http://127.0.0.1:8000/polls/create/`にアクセスすると
`Created UserData!!`と画面に表示されます。
SQLiteの中身をSelectしてみると...

```sql
sqlite> select * from polls_user;
Satou|Miyuki
Tanaka|Yumi
Katou|Kenta
Suzuki|Asuka
```
ちゃんと保存できた！

### 一覧表示
`http://127.0.0.1:8000/polls/list/`にアクセスするとSelectした結果のようにリストが表示されます。


### 注意事項
データをcreate/updateした後すぐにListを表示させても変更が反映されていないときがあります。キャッシュとか関係あるのだろうか...??
頻繁にDataframeからModelのデータとしてcreate/updateをするようなものにはあまり適していないのかもしれません（いい方法があるのかもしれないですが）。


大量データのcreate/updateでどのくらい時間がかかるのか試してみたいところです...
.MTSファイル動画を変換する方法

# 目標
HDビデオカメラに保存されているMTS/M2TSの映像を編集するために、Final Cut Pro、iMovieを取込できるようにしたいです。

# 背景
・googleで検索した結果は無料DL版の変換アプリがたくさんありますが、
　対象ファイル5分までしか変換できないが多かったです。
　[mts ファイル 変換](https://www.google.co.jp/search?rlz=1C5CHFA_enJP815JP815&ei=Mny4W7yODMb48QXcwafwAw&q=mts+%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB+%E5%A4%89%E6%8F%9B&oq=mts+%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB+%E5%A4%89%E6%8F%9B&gs_l=psy-ab.3...0.0.0.200400.0.0.0.0.0.0.0.0..0.0....0...1c..64.psy-ab..0.0.0....0.PaXHXnAxrQI)

# なにを選んだのか？
[HandBrake](https://handbrake.fr/)を利用し、無料、かつ時間を関係なく変換できます。
<img width="1762" alt="1538818833961.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/73135/abc1f6e4-e0fc-124c-df1e-7ad7ceb0c36a.jpeg">

# 使い方法
[HandBrake](https://freesoft.tvbok.com/freesoft/dvd_copy/handbrake.html)の使い方については他のサイトもあるため、ここは割愛。
Rubyのメソッド定義「引数編」

RubyレシピブックでRubyの学習を進めています。

# Rubyのメソッド定義の基本

メソッドの定義の方法は下記のようにします

```ruby
def メソッド名
  # 処理内容
  p 'Hello, World'
end
```

# 引数を伴う場合

```ruby
def メソッド名（引数）
  # 処理内容
  p "Hello, #{引数}"
end
```

このとき、引数として定義する方法として4パターンがあげられます。

1. param（通常の引数）
2. param = val（デフォルト値付き引数）
3. *param（可変長引数）
4. &param（ブロックをProc化して受け取る引数）

## 1~3を使ったメソッド例

```ruby

def output(a=1, *b, c)
  p [a, b, c]
end

output(2)           # => [1, [], 2] 
output(2, 3)        # => [2, [], 3]
output(2, 3, 4)     # => [2, [3], 4]       
output(2, 3, 4, 5)  # => [2, [3, 4], 5]
```

## ブロック付きのメソッド例

```ruby
def map_with_index(list)
  result = []
  list.each_with_index do |item, idx|
    value = yield [item, idx]
    result << value
  end
  return result
end

p map_with_index([1, 2, 3]) { |item, idx| item * idx } # => [0, 2, 6]
```

ブロック付きメソッドを定義する場合、メソッドに渡されたブロックを実行するための`yield`を用いる。
yieldは付与された引数をブロックパラメータとしてブロックに渡す。
AnsibleとJupyterを使った実行結果をpandasで可視化してみた

JupyterとAnsible Kernelで色々な可能性が無いか探っている@sky_jokerxxです。
今回は、[Ansible Jupyter Kernel](https://github.com/ansible/ansible-jupyter-kernel)とJupyterを使ってnotebookで実行した結果を表で可視化できないか試してみました。
ここでは、例としてAnsibleを使ったテストケースをモデルにやってみようと思います。

# テストシナリオ

ここでは `shell` モジュールを使って三つほど簡単な試験をします。

* `ls /opt` が確認したい
* `ls /root` でパーミッション関連で確認できないものは失敗することを確認したい
* `sl` でインストールされていないコマンドが実行された時に失敗することを確認したい

# 結果イメージ

以下のようなイメージです。

|   | test case |  results   |
|---|-----------|------------|
| 0 | ケース名  | リターン値 |
| 1 | ケース名  | リターン値 |
| 2 | ケース名  | リターン値 |

# 実際に作ったもの

[![](https://qiita-image-store.s3.amazonaws.com/0/180118/f11a8383-5945-693e-b6eb-bbddae95dce6.png)](https://github.com/sky-joker/ansible_jupyter_test_case/blob/master/01_Ansible%20Kernel%E3%81%A8Jupyter%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E3%83%86%E3%82%B9%E3%83%88%E4%BE%8B.ipynb)

上図をクリックすればnotebookが保存されているgithubリポジトリへ飛びます。

# 説明

Jupyter Ansible Kernelでは1つのセルに1つのタスクしか書けません。
そのため、ここでは1つのセルに1つのshellモジュールを使ったテストパターンを作っています。
各セルの結果を、それぞれのregisterに格納します。
最後のpythonコードでregister変数から `変数名` と `結果` を取得し `pandas` を使って表形式に可視化してみます。

## pythonコードについて

`test_case_name` 変数はregisterで設定する変数名を設定してください。
Ansible側のregisterでは必ず変数の最後は数字を入力してください。

`case_number` にはテスト数を入力してください。

# 実際にやってみる

こんな感じに可視化されます。
今回は `0` 以外の場合は<font color="#FF0000">赤字</font>にしてみました。

![ansible_jupyter_test_output.gif](https://qiita-image-store.s3.amazonaws.com/0/180118/fc2e1054-6e5c-c1da-3532-f7c68cb33352.gif)

# 最後に

Jupyterを使ってAnsibleを実行することでアウトプットや可視化が残せるのでエビデンスとして使えるのでは？と思っています。
後は、見た目をもう少し分かりやすく仕上げてあげれば横展開もいけるかもしれませんね :)
個人的で暫定的な「ビザンチン・ジェネラルズ問題」のまとめ

# この記事は何？
a private tentative summary for "Byzantine Generals Problem" from wikipedia.[^1]

# Byzantine Generals Problem - ビザンチン将軍群問題
『相互に通信しあう何らかのコンポーネント群において、
情報伝達上の過失か故意かに関わらない問題か、
個々のコンポーネントの過失か故意かに関わらない問題によって
設計者の意図しない情報が伝達される可能性がある場合に、
システムが総体としては設計者の意図通りの合意を形成可能かを問う問題。』ではダメか？

「Two Generals' Problem - 二人の将軍群問題 を一般化したものと言える。」という。

## Byzantine Failure - ビザンチン故障/ビザンチン障害/ビザンチン・フォールト
あらゆる Byzantine Failure は以下のいずれかの群に分類できる。

- omission failures - 不作為障害群
- commission failures - 作為障害群


## Byzantine Fault Tolerance - BFT - ビザンチン・フォールト耐性
「ビザンチン将軍群問題が発生しても全体として正しく動作するシステムを Byzantine Fault Tolerance があるという。」という。[^2]

## Byzantine Fault Tolerability - ビザンチン・フォールト耐用性
『ビザンチン将軍群問題が発生した場合にもシステムが全体としては意図通り動作するかどうか。』ではダメか？

## resilience - 回復力
resilience とは、ビザンチン故障の状態にあるプロセスを何個まで許容し対処できるかを表す数値。
(ここでの「プロセス」と「コンポーネント」は同一の意味か？)

```pseudo-code.txt
# 「古典的な解決法(early solution)の多くは
# "プロセス数 > 3 * 回復力" の場合の解が存在しない。」という。
if (processCount > (3 * resilience))
{
	# 古典的な解決法では解決不能
}
```

## 参考
[^1]: https://ja.wikipedia.org/wiki/%E3%83%93%E3%82%B6%E3%83%B3%E3%83%81%E3%83%B3%E5%B0%86%E8%BB%8D%E5%95%8F%E9%A1%8C
[^2]: https://en.wikipedia.org/wiki/Byzantine_fault_tolerance
Security Daysに行ってきたよ

###Security Daysに参加してきました

2018年10月3日～5日に開催されたセキュリティのイベント

一般的な対企業(経営者や社内のセキュリティ担当など)向けのイベントでセミナーとブース展示が行われます。



対企業向けなのでエンジニア向きではないかなと正直あまり期待はしていませんでしたが、まだまだ未熟者の自分にとっては色々と勉強になることもありました。


特に私が興味をもったのがメールです。

メールは仕事においてはこれからも使われるであろうものです。
(エンジニアなどを中心にチャット形式にするべきだ！という意見ありますが、それはまた別の機会に…。企業はメールを利用したがっているようなので。)



しかしメールは簡単にアドレスを偽造できるとのこと。
どうやら簡単にできるみたいです。


今回、セキュリティにおいて一番大事なことの1つに「結局は人」ということをどの企業も伝えたいし、それを大前提として製品の開発やサービスの提供をしているのだなぁと感じました。




そしてメールは人と人の直接的なメッセージのやり取りです。
攻撃者は"メール"というものが利用される限り、そこを突いてくるということ。




これを機にメールを使った攻撃(攻撃ではなく悪い手段という表現が適切か)方法についてまとめてみようかな？
Slackで投稿したファイルを保存したい


## 概要
- Slackで毎日挙げているファイルがあり、それを全部読みたいと思った
- しかも月別にまとめたい
- 検索でも出来るが一々ダウンロードするのが面倒
- 楽に、早く作る必要があった(１時間以内)
- 全然汎用的じゃないですが、何かの役に立てば幸いです！

## 使うもの
- Pythonを使用
- SlackのAPI
    - [files.list](https://api.slack.com/methods/files.list)
        - Slackに挙げられたファイルの一覧を取得するAPI
        - ダウンロードするためのリンクなども入っている
        - [一度Testerを使ってどんなデータが返ってくるか確認した](https://api.slack.com/methods/files.list/test)
- UnixTime
    - SlackのAPIでは時間をUnixTimeで記述する必要があった
    - コードを書くのが面倒だったので、こちらのサイトを使わせていただきました
        - https://tool.konisimple.net/date/unixtime

## 方法
### [SlackのLegacyTokenを取得する](https://api.slack.com/custom-integrations/legacy-tokens)

- あまりおすすめされていないけど、自分だけで利用するなら楽
- GitHubなどにあげないように注意

### TestページでAPIを叩いてリクエストとレスポンスを確認する

- `ts_from`, `ts_to`で期間を指定(UnixTime)
- レスポンスの`url_private_download`を取得し、こちらにアクセスするとファイルをダウンロードできる


## コード
```python

import requests
import json
import os.path

def fileDownload():
    print('fileDownload')
    
    # 大文字の所は自分の欲しいファイルなどに変換
    # ts_from, ts_toなどはUnixTimeで記述
    url = "https://slack.com/api/files.list?token=LEGACYTOKEN&channel=CHANNELID&ts_from=1535727600&ts_to=1538319600&user=USERID&pretty=1"
    
    result = requests.get(url)

    data = json.loads(result.text)

    # ファイルをダウンロードするためにヘッダーが必要
    headers = {'Authorization': 'Bearer '+LEGACYTOKEN}
    count = 0
    for file in data["files"]:
        file_url = file["url_private_download"]
        file_title = file["title"]
        
        # 同じファイル名の物があると上書きされてしまうため存在を確認する
        if os.path.exists(file_title):
            print("重複しました")
            count = count + 1
            file_title = file_title + str(count)
        response = requests.get(file_url, headers=headers)
        with open(file_title, 'wb') as f:
            # ファイルを保存する  
            f.write(response.content)

if __name__ == '__main__':
    fileDownload()
```

- 最後にこのファイルをpython ファイル名で叩くだけです
- お役に立てたら幸いです
【Unity】バックグラウンド動作時のキー入力取得

Unityがバックグラウンドで動いているとき，Inputクラスではキー入力を取得できません。

そこで，以下のリンクにあるパッケージを利用します。
英語ですが，使い方もほぼ書いてあります。
https://github.com/Elringus/UnityRawInput

サンプルソース

```
using UnityEngine;
using UnityRawInput;

public class RawKeyInputTest : MonoBehaviour
{
	public bool WorkInBackground;
	public bool InterceptMessages;

	private void OnEnable ()
	{
		RawKeyInput.Start(WorkInBackground);
		RawKeyInput.OnKeyUp += LogKeyUp;
		RawKeyInput.OnKeyDown += LogKeyDown;

	}

	private void OnDisable ()
	{
		RawKeyInput.Stop();
		RawKeyInput.OnKeyUp -= LogKeyUp;
		RawKeyInput.OnKeyDown -= LogKeyDown;
	}

	private void OnValidate ()
	{
		RawKeyInput.InterceptMessages = InterceptMessages;
	}

	private void LogKeyUp (RawKey key)
	{
		Debug.Log("Key Up: " + key);
	}

	private void LogKeyDown (RawKey key)
	{
		Debug.Log("Key Down: " + key);

		//Aが押されたら
		if (RawKeyInput.IsKeyDown(RawKey.A)) {
			print ("test");
		}
	}


}

```

よく使うと思うのはこの部分

```

		//Aが押されたら
		if (RawKeyInput.IsKeyDown(RawKey.A)) {
			print ("test");
		}

```
ここで特定のキーの入力を取得できます。
RawKey.取得したいキー　のように書き，あとはキー入力で行いたい処理を書けばOKです。
PhpStormのshellをfishに変える


個人的なメモ

## Homebrewを入れてない場合は入れる

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

一応確認

```
brew doctor
Your system is ready to brew.
```

## fishをインストールする

```shell
brew install fish
```

インストールできたか確認してみる

```shell
fish -v
```

デフォルトのシェルをfishに変更

```
echo /usr/local/bin/fish >> /etc/shells
chsh -s /usr/local/bin/fish
```

## PhpStormでfishをデフォルトシェルにする

- `Command + ,`で設定を開く
- Tool > Terminalを開く
- Application Settings > Shell pathに「/usr/local/bin/fish」を設定

以上
【書評】ザ・ドリーム・マネージャー

ザ・ドリーム・マネージャー という本の感想です。

いわゆる自己啓蒙系の本ではありますが、チームビルディングや顧客との信頼関係構築の面で役に立つ知識となりそうでした。

普段、プログラミングのお仕事しつつ、人材開発の会社もやってますが両方の視点からメモしてみました。多分役に立たないので、概ね自分用メモです。

## 気になったフレーズ

### おたがいの夢が実現できるよう助け合うのが、あらゆる人間関係の大切な基本
- プロジェクトチーム内で、メンバーの夢を応援できる風土ができあがれば、かなりチームビルディング面で意味がありそう
- 顧客との関係性も同じ感じで作れるのだろうか
	- ビジネスの場で自身の夢を語る機会はかなり勇気が必要そう

### 人は静かな絶望の中に生きている
- アメリカの思想家の言葉
	- 「人は生きていく中で夢を無意識にあきらめていく」ような意味
- 「いつまでプログラミングをやっているのだろう？」とかいうエンジニアにとってのキャリア問題も同じ感じなのかもしれない

### 人は会社のために存在しているのではない、会社が人間のために存在している
- 自分が会社の歯車である感覚が生まれたら、たしかに辛い

### 大切なのは完璧を求めることではなく、自分が進歩していることに注意を向ける、こと
- 結果も大事だけど、プロセスも大事

### 他人に夢を押し付けない
- 親の期待ほど面倒なものはない、みたいな感覚

### 我が社で物足りなくなった場合に外の働き口を探す
- そこまで面倒みてくれる会社があるのか、とビックリ


## 自己紹介と感想
IT系のベンチャー企業に入社してもうすぐ15年（アルバイトの頃からだと18年）になりますが、プロダクト開発、受託開発、プロジェクトマネジメント、組織開発・HRM、子会社設立、と様々な経験を積ませてもらい、今は、また、サーバサイドエンジニアとしてのキャリアを進めています。

同時に、複業として、企業向けに人材開発や、個人向けのキャリア相談を行う会社も経営しています。

自分が何者で、今何をしたいのか未だよく説明できない（笑）のですが、この本の中にある「夢」の実現に向けて、もがいているのかも、と思いました。

今いる会社には「ドリームマネージャー」みたいな役割の人はいないですが、会社として「夢を応援します」というスタンスは感じられるし、良い環境なんだろうなと思いました。