OmniAICreator/Qiita-1.07M huggingface dataset:
CentOSでgccへのパスが通ってない（と思われる）時の対処法

最小構成(minimum)でインストールしたせいでしょうか？`cpanm Moose`などがエラーになり、`-v`オプションで流れるログを熟読したところgccが入ってないと怒られました。

__そ、そんなはずないだろ！（震え声）__

で、

```
$ sudo yum -y install libgcc
（中略）
Package gcc-4.8.5-16.el7.x86_64 already installed and latest version
Nothing to do
```

ほーらね。入ってんじゃん。なんで怒られるんだろう？と。しかし、しかしですよ？

```
$ gcc -v
-zsh: gcc: command not found
```

__へ？パス通ってないの？__（ってなりますよね？）

で、(lib)gcc path centos7 zshとか色々ググっても全然見つからなくって途方に暮れてた[^1]んですが、解決しましたので緊急共有します。（前置き終わり）

```
$ sudo yum -y install gcc-c++
```

何故かは全くわかりません[^2]が、この後だと

```
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC) 
```

これでめでたく、

```
$cpanm Moose
```

が通りました。[^3]

---
### 2017/11/20の変更点

- タイトルの編集
- perlbrewは全く関係なかったようでしたので記載から削除
- その他、記載を改めた

---
[^1]: [同じように困っている人なら見つけられた](https://stackoverflow.com/questions/29479481/gcc-installed-but-command-not-found)
[^2]: 詳しい方、コメントまたは編集リクエストお願いします。
[^3]: gzipがないって怒られるかもしれませんが、それは普通に`yum`でインストールできます。
NetworkXでネットワークの特徴量を計算する

# はじめに
みなさんはグラフの計算をするとき何を使ってますか？　[pajek](http://vlado.fmf.uni-lj.si/pub/networks/pajek/)？　それとも[igraph](http://igraph.org/r/)？
僕は [networkx](https://networkx.github.io)を使ってます。理由は**Python**だから。
pajekはwindows専用ソフトだからlinuxで動かないし（wineを使えば動くらしいけど）、igraphはRだから日本語の取り扱いとかパッケージのコンパイル周りのエラーがめんどくさい。
ネットワーク解析そのものを考えるとpajekやigraphの方が伝統があって良さげですが、プログラミング言語そのものの利便性も考えるとトータルでPython+networkxかなと思います。
今回はそんなnetworkxを使って基礎的なグラフの特徴量の計算の仕方を見てみたいと思います。
今回のコードはすべて[Gist](https://gist.github.com/Hiroyuki1993/f7f6c2b60d78170cd890959d1a315cd2)にも上げているのでよかったらそちらもご覧ください。

# ネットワーク全体の特徴量
## グラフの生成
まず最初に解析対象となるネットワークを生成します。networkxには完全グラフ、ランダムネットワーク、スモールワールドネットワークなど様々なグラフを生成する関数が用意されています。今回はスケールフリーネットワークで試してみます。

```py
import networkx as nx
G = nx.barabasi_albert_graph(30, 1)
```

視覚的に確認するには以下のメソッドを使います。

```py
pos = nx.circular_layout(G)
nx.draw_networkx(G, pos)
```
![scalefree.png](https://qiita-image-store.s3.amazonaws.com/0/176789/08d12b2f-c0e1-9442-7837-b79e6e0642af.png)

## 平均距離
```py
nx.average_shortest_path_length(G)
>> 3.949425287356322
```

ランダムグラフと比較して

```py
G_random = nx.connected_watts_strogatz_graph(30, 2, 1)
nx.average_shortest_path_length(G_random)
>> 5.917241379310345
```

スモールワールド性が確認できます。

## クラスター係数
```py
nx.average_clustering(G)
>> 0.0
```
例題のアルバート・バラバシモデルではクラスター係数が小さいという特徴がありますが、今回は０になりました。

# 中心性
## 次数中心性
```py
degree_centers = nx.degree_centrality(G)
sorted(degree_centers.items(), key=lambda x: x[1], reverse=True)[:5]
>>>
[(5, 0.27586206896551724),
 (0, 0.1724137931034483),
 (1, 0.13793103448275862),
 (4, 0.13793103448275862),
 (7, 0.10344827586206896)]
```
中心性はそれぞれのノード１つ１つに対して値が辞書形式で与えられます。
これを大きい順に並び替えるには[辞書の整列メソッド](https://qiita.com/shizuma/items/40f1fe4702608db40ac3)を使います。

## 近接中心性
```py
close_centers = nx.closeness_centrality(G)
sorted(close_centers.items(), key=lambda x: x[1], reverse=True)[:5]
>>>
[(1, 0.4027777777777778),
 (0, 0.3815789473684211),
 (5, 0.3717948717948718),
 (4, 0.31521739130434784),
 (2, 0.3020833333333333)]
```
次数中心性と同じ結果になると思っていましたが多少違ってました。他のすべてのノードから平均的に一番近いのは１番のノードみたいです。

## 媒介中心性
```py
between_centers = nx.betweenness_centrality(G)
sorted(between_centers.items(), key=lambda x: x[1], reverse=True)[:5]
>>>
[(1, 0.6379310344827587),
 (5, 0.6108374384236454),
 (0, 0.6059113300492611),
 (4, 0.3620689655172414),
 (8, 0.19704433497536947)]
```
媒介中心性はあるクラスターとあるクラスターを橋渡しするものが高くなる傾向がありますが、アルバート・バラバシモデルだとそもそもクラスターがないので他の指標とそんなに変わらない結果になってます。

## 固有ベクトル中心性
```py
eigen_centers = nx.eigenvector_centrality_numpy(G)
sorted(eigen_centers.items(), key=lambda x: x[1], reverse=True)[:5]
>>>
[(5, 0.6148871002455658),
 (1, 0.36311628358126075),
 (7, 0.2565216963136699),
 (0, 0.23924881680129484),
 (10, 0.2256761992171005)]
```
これはハブの近くにあるノードの中心性を押し上げるので、次数中心性の高い５のまわりのノードが軒並みランクインしてます。ちなみに`nx.eigenvector_centrality`では収束しなかったのでnumpyバージョンを使っています。
1602LCDをI2C変換アダプタを使ってArduinoで表示する。


##■概要
自分はインターフェースマニアなのか、LCDを見ると何となく買ってしまう。
だけど、LCD関係はとにかくピンがいっぱいあるのでどう繋げればいいのかわからず手を出しにくかった。
そんな中、AmazonでI2Cに変換できるというのがあったので使ってみようと思い立った。

<img src="https://qiita-image-store.s3.amazonaws.com/0/199149/be68e367-1add-e45d-9596-bcb58e043757.jpeg" width="400">




##■使用パーツ
* SD1602VBWB-XA-G-R(秋月で300円で投げ売りされてた)
* LCD-I2C アダプタ(FC-113?)
* Arduino nano(ELEGOO互換機)

##■配線

<img src="https://qiita-image-store.s3.amazonaws.com/0/199149/4646b46a-5a5e-724c-ed03-8ecfd9ec1765.png" width="400">

(トップ写真ではLED電源をArduinoから持ってきてたけど、写真取った後でアダプタから取ればいいじゃんって思い直した)

[秋月のHP](http://akizukidenshi.com/catalog/g/gP-02985/)からほぼ同じ名前のデータシートを引っ張ってきて、配線を確認。どうも15,16ピンを入れ替えているようなので、2ピンずらさなければならない模様。ちょっと惜しい。
適宜自分のLCDのピンアサインを確認して望まれたい。

| SD1602PIN|| FC-113PIN
|----|----|---|
|15|LED A(3.2)|--
|16|LED K(0V)|--
|1|VSS(0V)|1
|2|VDD(5V)|2
|3|V0(--)|3
|4|RS|4
|5|R/W|5
|6|E|6
|7|DB0|7
|8|DB1|8
|9|DB2|9
|10|DB3|10
|11|DB4|11
|12|DB5|12
|13|DB6|13
|14|DB7|14
|--|VCC(3.2V)|15
|--|VSS(0V)|16

| FC-113|Arduino nano
|----|----
|GND|GND
|VCC|5V
|SDA|A4
|SCL|A5

##■スケッチ
ネットで適当にLiquidCrystal_I2Cのライブラリを拾ってインポート。
注意点は、I2Cのアドレスがこのスケッチの初期値は0x27となっている所。(分かるようにコメント欄はあえて変えていない)
参考サイトを見ていると、内蔵チップの種類に応じて初期アドレスが変わっている様子。
 **チップにPCF8574Aが使われているとアドレス0x3Fとなる** みたい。 
(購入したAmazonのレビュー欄では0x27と書いている人が多いので、てっきり0x27と思っていたが、表示されなかったので色々調べていた)


```HelloWorld.
//DFRobot.com
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3F,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

void setup()
{
  lcd.init();                      // initialize the lcd 
 
  // Print a message to the LCD.
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Hello, world!");
  lcd.setCursor(0, 1);
  lcd.print("Arduino!");
}

void loop()
{
}
```

サンプルコードからの変更点は、上記アドレス変更のほか、2行目も表示されるか確認したかったので、"Arduino!"のところを加えている。

##■まとめ
一般的な?16ピンの1602LCDを、アダプタを使ってI2C変換することを確認。
状態表示のためにはモニタの有無で雲泥の差があるわけだが、ピン数が多くてなかなか導入しにくいLCDモニタ。
それがピン数の消費も少なく汎用的なI2Cで接続できるというのはとても良い。
今回は適当に買ってしまったLCDだったのでピン配置が微妙だったが、ピッタリ合うものと組み合わせれば、LCDの裏面に一体化させることも可能だ。
更にアダプタ自体も一個200円程度と安い。(自分の場合は5コセットで690円だった)
これで、「買ったはいいものの使わずに眠ってるLCD」を起こすことができそうだ。

アダプタが追加になる分、かさばるというのはあるが、そこまで小型化にこだわらないのであれば、電子工作初心者から上級者まで、幅広く使えそうだ。


##■参考サイト
[[I2C] 1602 LCD ディスプレイ (HD44780 + PCF8574A)-ＤＥＫＯのアヤシいお部屋。-](https://ht-deko.com/arduino/lcd_i2c.html)

↑アドレスで詰まっていたところを救われました。

[超小型ＬＣＤキャラクタディスプレイモジュール（１６×２行　白抜き）秋月](http://akizukidenshi.com/catalog/g/gP-02985/)

[HiLetgo 5V 1602LCD IIC/I2C/TWI/SPIシリアルインターフェイスモジュールポートarduinoに対応 (5個セット) [並行輸入品] Amazon](https://www.amazon.co.jp/gp/product/B010Q175VY/ref=od_aui_detailpages00?ie=UTF8&psc=1)
helm-swoop で前回のクエリを保持する

helm-swoop で前回の検索文字列を覚えていてほしいと思ったのでこうしてみました。

```init.el
(defun my-helm-swoop-resume-last-query ()
  "swoop with last query."
  (interactive)
  (helm-swoop :$query (if (boundp 'helm-swoop-last-query) helm-swoop-last-query "")))
(global-set-key (kbd "C-s") 'my-helm-swoop-resume-last-query)
```

それらしき関数なり設定なりが見当たらなかったので作ってみました。便利便利。

## 勘違いしていたので訂正
以降は 2017/11/24 に追記しました。

そもそも helm-swoop の仕様は前回の検索語をそのまま再現するようになっていました。私が前回の検索語をクリアするように設定していたのを忘れていました。その設定は

```init.el
(setq helm-swoop-pre-input-function (lambda () ""))
```

というものでした。つまりわざわざ関数を作らなくても良かったのです (マヌケ過ぎる)。

それでしばらく検索語が再現されるようにして使っていましたが不便です。新たな検索語を入れるときに minibuffer をクリアしないと再現された検索語に追記になってしまいます。これがどうも不便でクリアするように設定したようです。

そもそも `M-p` を押せばヒストリがたどれます。ですが、それはなんか遠いです。つまり `C-s` `M-p` はなんとなく面倒です。`isearch` のように2度押したら前回の検索語が入るようになって欲しいです。

ということで上記検索語クリアの設定はそのままにこうしてみました;

```init.el
(setq my-helm-swoop-trigger-key (kbd "C-s"))
(eval-after-load "helm-swoop"
  (lambda ()
    (define-key helm-map my-helm-swoop-trigger-key 'previous-history-element)))
(global-set-key my-helm-swoop-trigger-key 'helm-swoop)
```

`helm-map` に `C-s` なんてよく使いそうなキーをバインドしていいのかなと3秒だけ躊躇しましたがそんなキー使った記憶がないので設定しました。
GalaxyNote8のSideSyncをリモートデバッグに使う


毎回、実機を手元に持ってきてMacに繋いでデバッグしたり、画面を操作してデバッグするのが面倒くさいので考えました。
エミュレータとほぼ同じ感覚でMacの画面上でデバッグできます。

# 初回準備

初回だけ、2回目からは不要

## Qi対応の無線充電器を用意（おすすめ）
無線充電が出来ると置くだけで充電されるので、楽。

## WiFiは充電時のみ常時接続にする（おすすめ）

Note8で「設定」⇨「接続」⇨「WiFi」⇨「詳細設定」⇨「スリープ中にWi-Fi接続を維持」をタップし、「充電時」にする

## WiFiのIPアドレスを固定する。[^1]
 Note8で「設定」⇨「接続」⇨「WiFi」⇨「接続中のSSID」をロングタップ⇨「ネットワーク設定を管理」⇨「IP設定」を「静的」に変更して、任意のIPアドレスを入力[^2]

[^1]: ルータ側でMacアドレスを指定するIP固定もあり
[^2]: デートウェイやDNSはデフォルトのままで良いはず

## SideSyncのインストール

Note8と、macOSにインストール[^3]

[^3]: macOS版はインストール後に「システム環境設定」⇨「セキュリティとプライパイシー」⇨「プライバシー」⇨「アクセシビリティ」⇨「鍵をクリック」して、「SideSync」を許可する。（再インストール後も行う）

## SideSyncの接続設定

macOSとNote8のSideSyncを起動し、同じWiFiに接続していれば、SideSync（MacOS）の画面にNote8が表示されるはず
SideSyncの指示に従って接続設定する

## ADBのリモートデバッグ設定

Note8をUSBで接続して、下記のコマンドをmacOSで実行

IPやポートは環境に合わせて置き換え

```zsh
$ export PATH=$PATH:/Users/kogahirotaka/Library/Android/sdk/platform-tools # AndroidSDKのツールをパスに追加
$ adb tcpip 5555 # PCのポート待機を設定、5555〜5585までの任意
$ adb connect ${Note8のIPアドレス}:5555 # Note8に5555で接続
```

## ADBのリモートデバッグ接続確認

USBを抜いた後に、下記のコマンドでNote8が表示されることを確認

```zsh
$ adb devices # デバック端末リスト表示（確認用）
```


# 接続方法
2回目以降の接続方法、Qiの上に事前に置いておけば手元に無くても良い。

1. Qiの上にNote8を置く（充電中になるので、WiFi接続される）
1. adb tcpipとadb connectで接続

	```zsh
	$ adb tcpip 5555
	$ adb connect 192.168.10.88:5555
	```

1. adb shellでNote8のSideSync起動

	```zsh
	$ adb shell monkey -p "com.sec.android.sidesync30" -c "android.intent.category.LAUNCHER" 1 # SideSync起動
	```

1. AndroidStudioでデバッグ実行
1. SideSyncの画面上でデバッグ対象のアプリが起動

1. 使い終わったら、adb disconnectで切断

	```zsh
	$ adb disconnect # PCポート切断
	$ adb usb # USBモードへ
	```


#最後に
SideSyncアプリがデバッグ接続に対応してくれると、もっと接続が簡単になりそう
traviscibot で GitHub Pages を deploy したときに作成される謎の日付ファイル

travisbot で deploy すると謎の日付の入った空のファイルが作成される。

![000.PNG](https://qiita-image-store.s3.amazonaws.com/0/17669/f70ce939-c55f-8138-1164-2b350228799e.png)

`deployed at Sun Nov 19 15:04:20 UTC 2017 by Deployment Bot (from Travis CI)` というやつがそれで、今のところ[公式のドキュメントにも特に何も書いてない](https://docs.travis-ci.com/user/deployment/pages/)ので、はじめてみるとちょっとおどろく。

どこでできたんだこいつは……

## できたところ

- https://github.com/travis-ci/dpl/blob/5f87d05aa63fab081d60d176fc54fd66aae716f3/lib/dpl/provider/pages.rb#L56

ここだった

## 消したいと思ったけども

消したいけど、別に害はないし放置しておくことにした。何の意味があるんだろうかこのファイル。

## 参考

- https://github.com/travis-ci/dpl/issues/696
Cakephp3のページネーションで複数条件のorderbyを実現させる方法 

これが初投稿になりますので間違えてる部分やいい方法があったらズシズシ教えてください。

2017年9月からウェブ開発エンジニアとしてGENKIです。

業務でPHP、 CAKEPHPを使用したサービスの開発をしている中で見つけた解決策や自分の趣味でやってる開発の状況などを共有していく場にする予定です！

今回のお題は
「**Cakephp3のページネーションで複数条件のorderbyを実現させる方法**」
でしたのでここからはそのことについて！

もしコントローラー側のみで利用する場合は、

```
$this->paginate($commentsTable->find()
    ->order([
        'id' => 'DESC',
        'multi * multi DESC'
    ])
    ->limit(10)
);
```

この場合、1ページ目だけは正常に表示をされるがページネートで生成されたリンクからページを変更すると、
**SORT**と**Direction**がURLに追加されていてそれが悪さをする！
>これに気づかず前日には会社で(๑⁼̴̀д⁼̴́๑)ﾄﾞﾔｯ‼った自分が居た

この問題に対する解決策として幾つか参考URLを見つけて試してみたが問題は改善されず。。
(内容としては**SORT**と**Direction**をdisableだかfalseにするなどだったが、そうしてしまうと必要なQueryまで消してしまいページ切り替え後に絞込ができなくなってしまった)

```
<?= $this->Paginator->numbers() ?>
```
ページネーションを生成しているのはこのコードで生成された際のURLに**SORT**と**Direction**が付随してきてしまうのがエラーの原因になっている。ということは？？

```
$('.paging > li > a').each(function() {
    var $href = $(this).attr('href');	
    $(this).attr('href', $href.split('sort')[0]);
});
```
そういうことですね！

Jqueryで無理くり消してしまえば良いのではないか！！
ということで現在はこのように対応をしています！！

CakePHP使いの方でもっと全然いい方法をご存知の方がいらっしゃいましたらご教示いただければ幸いです！！

では！！ :)
お手軽フローディングラベル実装

# はじめに
そもそもフローディングラベルってなんぞやと思いますが、説明するよりみた方が早いと思いますので、先に完成形をお見せします。

![daa0bf48801d2e1f9d49145f0403afc6.gif](https://qiita-image-store.s3.amazonaws.com/0/210782/766c9708-c687-fd8a-6e54-b234dc2b8096.gif)


このように入力欄に何か入力するとプレースホルダの記述が上に見えるようになっています。
これをフローディングラベルと言います。

# 実装してみよう
今回はRailsを使ってますが、さわるのはhtmlとcssとjavascripの部分だけです。（javascriptは数行しか書きません。）

さっそくhtmlの部分から見てみましょう。
ユーザー編集画面のコードです。

```views/users/edit.html.slim
= form_for current_user do |f|
  .field
    label.field-label
      |First name
    = f.text_field :first_name, placeholder: 'First name', required: true, class: 'field-input'
```
slimで書いていますが、erbだと下のようになります。

```views/users/edit.html.erb
<%= form_for [current_user] do |f| %>
  <div class="field">
    <label class="field-label">
      First name
    </label>
    <%= f.text_field :first_name, placeholder: 'First name', required: true, class: 'field-iput' %>
<% end %>
```

次にcssのコードです。

```stylesheets/user.css

.field-label {
  color: #999;
  font-size: 14px;
  opacity: 0;
  transition: all .2s ease-out;
}

.field-not-empty .field-label {
  opacity: 1;
  padding-left: 5px;
}
```

``transition: all .2s ease-out;``はなくてもいいのですが、アニメーション設定があると良いUIになるので設定しておいていいかと思います。

次にjavascriptのコードです。

```views/users/edit.js.erb
('.field-input').on('input', function() {
  var $field = $(this).closest('.field');
  if (this.value) {
    $field.addClass('field-not-empty');
  } else {
    $field.removeClass('field-not-empty');
  }
});
```
ここのコードの流れですが、フォームに入力があれば動くようにしています。
``var $field = $(this).closest('.field');``で``.field-input``の親クラスをとってきています。
それが、``.field``です。
``if (this.value)``つまりこれはフォームに何かしらの文字があれば、``.field-inputに``もう一つ``.field-not-empty``クラスを追加して、もしフォームに文字がなかったら``.field-not-empty``クラスを消すということです。
クラスを追加したり、消したりしてることで何をやっているかというと、クラスが消えてる状態、つまりopacityで0にして見えないようにしていて、フォームに入力されたら、opacityを１にすることで文字を出しています。

# 参考サイト
http://uxmilk.jp/60672
https://webkikaku.co.jp/blog/htmlcss/floating-labels/
October CMS プラグイン実装テク：プラグインから自動的にファサードやサービスプロバイダを登録する

OctoberCMSプロジェクトの `config/app.php` を変更しなくても、プラグインから自動的にファサードやサービスプロバイダを登録できる。プラグインで追加したパッケージのファサードなどを利用可能にしたい場合などに便利。

Plugin.php の `boot()` メソッドで `App::register()` でサービスプロバイダを、`AliasLoader::alias()` でファサードを登録する。

下記は[pikanji/agent-plugin](https://github.com/pikanji/agent-plugin/blob/master/README_ja.md)での実装例。

```php:Plugin.php
class Plugin extends PluginBase
{
    public function boot()
    {
        // Enable jessengers/agent package and register Agent facade.
        App::register('Jenssegers\Agent\AgentServiceProvider');
        AliasLoader::getInstance()->alias('Agent', 'Jenssegers\Agent\Facades\Agent');
    }
```

ちなみに "Call to undefined method" とエラーになる場合は↓これで解決するかも。
[Laravelトラブルシューティング：facadeのメソッドが undefined エラーになる](https://qiita.com/pikanji/items/bb3f970b5a0c2e96c9e1)
[Java] StreamのCollectorsのメモ


# 個人的なメモ

* 忘れてしまうので、よく使いそうなパターンを記載
* 本当によく使うパターンは、自家版 Collectorsクラス/メソッドを作ってもいいのかも

# Collectors#toMap()

## LinkedHashMapを使いたい

明示的に LikedHashMap を使いたい。
ついでに、キー重複を許したい。

```java
	public static <T, K, V> Collector<T, ?, Map<K, V>> toMap(
			Function<? super T, ? extends K> keyMapper,
			Function<? super T, ? extends V> valueMapper) {

		return Collectors.toMap(
				keyMapper,
				valueMapper,
				(a, b) -> b,
				LinkedHashMap::new);
	}
```

キー重複を許したくない場合には、例外を投げる。

`(a, b) -> { throw new IllegalStateException(～); }`

詳細は、標準の２引数 Collectors#toMap() を参照。

## TreeMap を使いたい

キーで自然にソートしたい。
ほぼ同じ。

```java
	public static <T, K, V> Collector<T, ?, Map<K, V>> toTreeMap(
			Function<? super T, ? extends K> keyMapper,
			Function<? super T, ? extends V> valueMapper) {

		return Collectors.toMap(
				keyMapper,
				valueMapper,
				(a, b) -> b,
				TreeMap::new); // ★ここ
	}
```

TreeMapにComparator を指定したいときは、コンストラクタ参照ではなくラムダ式で指定。

# Collectors#toSet()

## LinkedHashSetを使いたい

ここは toSet() ではなく、toCollection() を使うのがポイント。

```java
	public static <T> Collector<T, ?, Set<T>> toSet() {
		return Collectors.toCollection(LinkedHashSet::new);
	}
```

## TreeSetを使いたい

基本同じ。

```java
	public static <T> Collector<T, ?, Set<T>> toTreeSet() {
		return Collectors.toCollection(TreeSet::new);
	}
```

# Collectors#groupingBy

## LinkedHashMapを使いたい

```java
	public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(
			Function<? super T, ? extends K> classifier) {

		return Collectors.groupingBy(classifier,
				LinkedHashMap::new, // ★ここ
				Collectors.toList());
	}
```

## TreeMapを使いたい

同じ。

```java
	public static <T, K> Collector<T, ?, Map<K, List<T>>> orderedGroupBy(
			Function<? super T, ? extends K> classifier) {

		return Collectors.groupingBy(classifier,
				TreeMap::new, // ★ここ
				Collectors.toList());
	}
```

## 要素をListじゃなくSetにしたい

…良いメソッド名が思いつかない。

```java
	public static <T, K> Collector<T, ?, Map<K, Set<T>>> groupingBySet(
			Function<? super T, ? extends K> classifier) {

		return Collectors.groupingBy(classifier,
				TreeMap::new,
				Collectors.toCollection(LinkedHashSet::new)); // ★ここ
	}
```

もちろん目的に応じて、TreeSetや、普通の Collectors.toSet() でもOK。

## グルーピング時にListに詰める要素も変換したい

```java
	public static <T, K, D> Collector<T, ?, Map<K, List<D>>> groupingBy(
			Function<? super T, ? extends K> classifier,
			Function<? super T, ? extends D> mapper) {

		return Collectors.groupingBy(classifier,
				LinkedHashMap::new,
				Collectors.mapping(mapper, // ★ここ
						Collectors.toList()));
	}
```

もちろん、List じゃなくて Set でもOK。

# Collectors#collectingAndThen

変更不可な Map や List を生成したい場合。

```java
	public static <T, K, V> Collector<T, ?, Map<K, V>> toConstMap(
			Function<? super T, ? extends K> keyMapper,
			Function<? super T, ? extends V> valueMapper) {

		return Collectors.collectingAndThen(
				Collectors.toMap(
					keyMapper,
					valueMapper),
				Collections::unmodifiableMap);
	}
```
Play Framework&ScalikeJDBCでDB接続しようとした時にエラーが出た

# エラー内容
出たエラーメッセージは以下の通り。
`IllegalStateException: Connection pool is not yet initialized.(name:'default)`
# 原因
DBs.setupAll()を実行しないと接続準備が行われず、そのことに起因して上記エラーが発生していました。
# 対応
自前で実装するのもめんどくさいなと思っていたところ、scalikejdbc-play-initializerというモジュールがScalikeJDBC側で用意されていたとのこと。見落としていました。
## モジュール追加
```scala:build.sbt
libraryDependencies ++= Seq(
  "mysql" % "mysql-connector-java" % "5.1.36",
  "org.scalikejdbc" %% "scalikejdbc"                  % "3.1.0",
  "org.scalikejdbc" %% "scalikejdbc-config"           % "3.1.0",
  "org.scalikejdbc" %% "scalikejdbc-play-initializer" % "2.6.0-scalikejdbc-3.1"
)
```
## 設定ファイルに追記
```scala:conf/application.conf
# ↓これを追加
play.modules.enabled += "scalikejdbc.PlayModule"
```
以上を追記して再起動したところ、無事にDB接続が行われました。
# 補足
このscalikejdbc-play-initializerの中のソースにおける以下のメソッドでDBs.setupAll()が実行されてコネクションプールがセットアップされている模様です。
参考URL:https://github.com/scalikejdbc/scalikejdbc-play-support/blob/2.5.1/scalikejdbc-play-initializer/src/main/scala/scalikejdbc/PlayInitializer.scala#L50-L54

```scala:scalikejdbc-play-initializer/src/main/scala/scalikejdbc/PlayInitializer.scala
  def onStart(): Unit = {
    DBs.setupAll()
    GlobalSettings.loggingSQLErrors = loggingSQLErrors
    opt("closeAllOnStop", "enabled")(playConfig).foreach { enabled => closeAllOnStop = enabled.toBoolean }
  }
```
# まとめ
記載内容に誤りや気になる点などございましたら、ご指摘頂けますと助かります。
Laravelトラブルシューティング：facadeのメソッドが undefined エラーになる

Laravel や OctoberCMS で確かにFacadeを登録していてクラスは読み込まれているのに、なぜか

```
Call to undefined method
```
となる。。。

そんな時は、これで解決。

```
php artisan clear-compiled
```
DNSサーバの設定

# レコード名

## Aレコード

Aレコードはドメイン名と対応するIPアドレスを ドメイン名:IPアドレス = 1:n で定義する。同じIPと別ドメイン名を並べて定義すれば IPアドレス:ドメイン名 = 1:n できる。サブドメインなどをつけないで設定するときはAレコード。

## CNAMEレコード

CNAMEレコードはすでにAレコードで定義されてるドメイン名と別名を定義する。なのでここは ドメイン名:参照ドメイン名 を書くことで IPアドレス:ドメイン名 = 1:n を定義することができる。

## TXT（Text）レコード

ホストの情報を記述するために使われます。電子メールの送信元認証技術であるSPFやDomainKeysなどに利用されます。

## MX（Mail eXchanger）

メールサーバーを指定します。優先順位を付けることで、複数のメールサーバーを指定することができます。
firestoreにgoogle app script

## 課題
 - アプリのバックエンドにfirebase ( auth / firestore / cloud function ) を使用している
 - その時のマスタデータの扱いにスプレッドシートを使いたい

## 作戦
 - spread sheet => gas => firestore


## APEENDIX
https://github.com/grahamearley/FirestoreGoogleAppsScript

## やったこと
### GASへライブラリの読み込み
メニューからリソース => ライブラリ => `MX2_NUfxVpaA1XPcZ_N-3wWb_Hp7BVbw3` を入力
保存

### サービスアカウントの作成
下記のページにアクセスし新規アカウントを作成
https://console.developers.google.com/projectselector/iam-admin/serviceaccounts
※ cloud databaseのowner(書き込み、読み込み)のアクセス権にする
※ json形式で鍵を保存

### メールアドレスと鍵を使ってstoreにアクセス

※ データはオブジェクト
※ keyは保存したjson形式の鍵の中のprivate_keyを使う
`var key = "-----BEGIN PRIVATE KEY-----\n{省略}==\n-----END PRIVATE KEY-----\n",`
`FirestoreApp.createDocumentWithId("FirstCollection", "FirstDocument", data, email, key, projectId)`


### データ更新 
`FirestoreApp.updateDocument("FirstCollection/FirstDocument", data, email, key, projectId)`
3次元配列の結合numpy.dstack

# 3次元配列の結合 dstack
三次元目で結合してくれる。

```python
a.shape #((640, 480, 1))
b.shape #((640, 480, 1))
np.dstack((a, b))
#((640, 480, 2))
```

opencvでBGRのBだけを取得して、他のGRを全部0で作られた画像を作成。

```python
img = cv2.imread('363.jpg') #(640, 480, 3)
ze = np.zeros((640, 480,1))

blue = img[:,:,:1]
blue = np.dstack((blue, ze))
blue = np.dstack((blue, ze))
print(blue.shape)
print(blue[:,:,1])

cv2.imshow('blue', blue[:,:,1])
cv2.waitKey(0)
```
もちろん画像はめっっちゃ青
【Swift4】Bundle.mainは@IBDesignableでは動作しない

しばらく@IBDesignableで宣言したUIView+xibをXCodeに表示しない理由が分からなかったので、メモしておきます。

xibとセットで作成したUIViewを部品化して、StoryBoard上のUIViewControllerなどに貼り付けた場合、
UIViewを@IBDesignableで宣言してXCodeで表示させると思います。
この場合はちょっとしたトリックが必要で、次にあげるようなxibをロードしてUIViewに貼り付ける等な実装が必要です。

下記は部品化したいUIView+xibを@IBDesignableで表示する場合に便利な親クラスの記述です。

```swift:Swift

import UIKit

class ChildView: UIView
{
    override init(frame: CGRect)
    {
        super.init(frame: frame)
        makeView()
    }
    
    required init?(coder aDecoder: NSCoder)
    {
        super.init(coder: aDecoder)
        makeView()
    }

    private func makeView()
    {
        let xibView: UIView? = loadNib()
        if let _xivView = xibView
        {
            addSubview(_xivView)
            addConstraint(toChildView: _xivView)  // <-- UIView+Constraint
        }
    }

    // Xibをロードする
    private func loadNib() -> UIView?
    {
        //let xibView: UIView?  = Bundle.main.loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)?.first as? UIView
        let xibView: UIView?  = Bundle(for: type(of: self)).loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)?.first as? UIView
        return xibView
    }
    
    func addConstraint(toChildView childView:UIView)
    {
        childView.translatesAutoresizingMaskIntoConstraints = false;
        
        self.addConstraints([NSLayoutConstraint(item: childView, attribute:.top, relatedBy:.equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 0),
                             NSLayoutConstraint(item: childView, attribute:.bottom, relatedBy:.equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0),
                             NSLayoutConstraint(item: childView, attribute:.left, relatedBy:.equal, toItem: self, attribute: .left, multiplier: 1.0, constant: 0),
                             NSLayoutConstraint(item: childView, attribute:.right, relatedBy:.equal, toItem: self, attribute: .right, multiplier: 1.0, constant: 0)])
    }
}

```

ところで、loadNib()ですが、

```swift:Swift
let xibView: UIView?  = Bundle(for: type(of: self)).loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)?.first as? UIView
```

は動作しますが、

```swift:Swift
let xibView: UIView?  = Bundle.main.loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)?.first as? UIView
```
では動作しません。つまり、Bundle.mainは@IBDesignableでは利用できないと思われます。
XCode上でエラーが発生します。Buildするとちゃんと動作するので、@IBDesignableの（Xcode用のBuildの問題でしょう。
シングルトンのインスタンス化が@IBDesignableでは利用できないのかもしれませんが、十分な調査はできていません。
React と PWA で講義の時間確認するだけのやつを作った

以前作ったものを PWA 対応と、ついでに見た目を変えました。
アプリは「4限何時からだっけ？」を解決する、完全に身内向けのものです。
ですが主に PWA のイントロについて書きたいと思います。


![Dentime.png](https://qiita-image-store.s3.amazonaws.com/0/40717/a50e9267-0e9c-20b5-8274-e93859ec8bfd.png)

使っているもの

* React.js
* Flow
* styled-components
* GitHub pages

リポジトリ: https://github.com/elzup/dentime


# PWA 対応

![Developer_Tools_-_https___elzup_github_io_dentime_.png](https://qiita-image-store.s3.amazonaws.com/0/40717/3ae4a5d5-a578-c352-27d0-22504f35612d.png)

Google Chrome Developer tools の Audits のナビゲーションに従ったのみです。


manifest.json で icon やテーマカラー、バックグラウンドカラーの設定をしました。自動で作られるスプラッシュ画面やナビゲーションバーの色に関係してきます。

設定内容は Devtool の Applications タブで確認できます。
![Developer_Tools_-_https___elzup_github_io_dentime_.png](https://qiita-image-store.s3.amazonaws.com/0/40717/ab846cc8-464e-e81d-85cb-d58dff1e043f.png)


あとは「noscripts タグ入れてね」や「テーマカラーとナブバーの色を合わせてね」など細かいところです。




![pwa.png](https://qiita-image-store.s3.amazonaws.com/0/40717/af2207c5-4017-3b2f-fdb4-4dd7c5db6de2.png)

右: PWA なので Android chrome で開くとインストールを促してくれます。
左2つ: テーマカラーが反映されています。

ServiceWorker でオフラインでも起動します。それどころか今回は時計しか使っていないので機能も動きます。

# iOS対応
iOS の PWA 対応はまだされてません。なのでホーム画面へ追加でも快適に使えるように最低限の設定をしました。
Safari のバー非表示とホーム画面アイコンの設定が下ので出来ます。


```index.html
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="apple-touch-icon" href="%PUBLIC_URL%/icon-2x.png" />
```
PythonでSlackに画像をアップロードする方法

#Pythonでファイルをアップロード
slackのfiles.uploadAPIを使って、画像をアップロードします。

```py3
import requests

files = {'file': open(filePath, 'rb')}
param = {'token':accessToken, 'channels':channelId}
res = requests.post(url="https://slack.com/api/files.upload",params=param, files=files)
```
slackに投稿できる項目はいくつかあり、上記は最低限にしています。
ファイル名や、文章なども指定できます。
各種パラメータは以下で確認が可能です。
https://api.slack.com/methods/files.upload/test
accessTokenもこちらで確認できます。

channelsは、channel名ではなく、別途IDを調べる必要があるので注意してください。
https://api.slack.com/methods/channels.list/test
上記で確認が可能です。
Test Method というボタンを押すと画面下部にJSONで以下のような返却があると思います。
idという部分になります。

```json
{
            "id": "C51JZCCUA",
            "name": "iot",
            "is_channel": true,
            "created": 1492640603,
            "creator": "U45GBV6C8",
            "is_archived": false,
            "is_general": false,
            "unlinked": 0,
           ...
}
```



#使い道
これでpepperで撮った画像をslackで通知して誰かきた時などにも、通知がいくようにできますね。
GolangでのUDP処理メモ

# 疑問
Go で UDP 送信する際、DialUDP() でUDPConnを作って、send()するが、DialUDP()って実際何をしているのだろうか？

```go
func DialUDP(network string, laddr, raddr *UDPAddr) (*UDPConn, error)
```

socket作る？bindもしちゃう？
システムコールするものなので、大量に呼び出すものではないよね？

というあたりを確認したい。

# ソース追ってみる

`DialUDP()` から追っかける。

```go:net/udpsock.go
func DialUDP(network string, laddr, raddr *UDPAddr) (*UDPConn, error) {
	switch network {
	case "udp", "udp4", "udp6":
	default:
		return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(network)}
	}
	if raddr == nil {
		return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
	}
	c, err := dialUDP(context.Background(), network, laddr, raddr)
	if err != nil {
		return nil, &OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
	}
	return c, nil
}
```

`DialUDP()` は `dialUDP()` を呼ぶ。

```go:net/udpsock_posix.go
func dialUDP(ctx context.Context, net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
	fd, err := internetSocket(ctx, net, laddr, raddr, syscall.SOCK_DGRAM, 0, "dial")
	if err != nil {
		return nil, err
	}
	return newUDPConn(fd), nil
}
```

`dialUDP()` は `internetSocket()` を呼ぶ。その際、sotype に SOCK_DGRAM を、proto に 0 を、mode に "dial" を指定。mode は後で family 判定に使っているが、"listen" 以外は無視されているな。

```go:net/ipsock_posix.go
func internetSocket(ctx context.Context, net string, laddr, raddr sockaddr, sotype, proto int, mode string) (fd *netFD, err error) {
	if (runtime.GOOS == "windows" || runtime.GOOS == "openbsd" || runtime.GOOS == "nacl") && mode == "dial" && raddr.isWildcard() {
		raddr = raddr.toLocal(net)
	}
	family, ipv6only := favoriteAddrFamily(net, laddr, raddr, mode)
	return socket(ctx, net, family, sotype, proto, ipv6only, laddr, raddr)
}
```

`internetSocket()` は family を判定後、`socket()` を呼ぶ。family は AF_INET か AF_INET6。



```go:net/sock_posix.go
func socket(ctx context.Context, net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr) (fd *netFD, err error) {
	s, err := sysSocket(family, sotype, proto)
（略）
	if fd, err = newFD(s, family, sotype, net); err != nil {
（略）
	if err := fd.dial(ctx, laddr, raddr); err != nil {
（略）
}

```

`socket()` は結局 `socket(2)` システムコールを呼んだ後、`fd.dial()` を呼ぶ。

```go:sock_posix.go
func (fd *netFD) dial(ctx context.Context, laddr, raddr sockaddr) error {
	var err error
	var lsa syscall.Sockaddr
	if laddr != nil {
		if lsa, err = laddr.sockaddr(fd.family); err != nil {
			return err
		} else if lsa != nil {
			if err := syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
				return os.NewSyscallError("bind", err)
			}
		}
	}
（略）
```

`fd.dial()` 中で `bind(2)` システムコールを呼んでいる。ここで local address を使っているので、ソースが同じでデスティネーションの違うUDPDial()を呼ぶとエラーになるのだなぁ。なるほど。
Dockerhubの自動ビルドの通知をSlackで受けるための一番手軽な方法

DockerhubではDockerイメージの自動ビルドとそこからWebhook機能でPOSTリクエストを送信することができます。
しかしjsonの型が違うので、そのリクエストを直にSlackに送信することはできません。

Dockerイメージのビルドが完了したことをSlackに通知するために色々試行錯誤していましたが、結局`Google Cloud Functions`（もしくはAWS Lambdaなどそれに準ずるもの）を使うのが一番手軽だという結論になりました。

GitHubに変更をプッシュしたら通知を待つだけなので結構便利ですが、あまりやっている人がいないように感じたので紹介したいと思います。

<!--more-->

## 設定方法

### Slack Incoming Webhook

1. [Incoming Webhooks](https://slack.com/apps/A0F7XDUAZ-incoming-webhooks)を自分のSlackチームに登録します
2. `Webhook`を1つ作成します。
    - 設定はすべてデフォルトでOKです。ユーザ名やアイコンも後に作成するリクエストに含めることができます。チャンネルだけ好きなものを設定しましょう。

### Google Cloud Functions

1. [Cloud Functions](https://console.cloud.google.com/functions)のページにアクセス
2. `Function`を作成する
3. 以下のプロパティを入力
    - Trigger: HTTP trigger
    - Source code: 下記コード（先程作成した`Webhook`のURLを記述してください）
    - Function to execute: sendToSlack

- index.js

```js
var request = require('request');

exports.sendToSlack = function sendToSlack(req, res) {
  var slack_endpoint = "<WebhookのURL>";
  var repo_name = req.body.repository.repo_name;
  var pusher = req.body.push_data.pusher;
  var desc = "New image was pushed to " + repo_name + " by " + pusher;
  var repo_url = req.body.repository.repo_url;
  var text = desc + "\n" + repo_url;
  var username = "dockerhub";
  var icon_emoji = ":whale:";

  var post_data = {
    "text": text,
    "username": username,
    "icon_emoji": icon_emoji
  };

  var options = {
    uri: slack_endpoint,
    form: JSON.stringify(post_data)
  }

  request.post(options, function (error, response, body) {
      console.log(body)
      if (!error && response.statusCode == 200) {
        res.status(200).send('Success');
      } else {
        res.status(response.statusCode).send('Fail')
      }
    }
  );
};
```

- package.json

```json
{
  "name": "sample-http",
  "version": "0.0.1",
  "dependencies": {
    "request": "2.83.0"
  }
}
```

### Dockerhub

1. Dockerhubページの`Build Settings`より、自動ビルドの設定を実施する
    - https://docs.docker.com/docker-hub/builds/#create-an-automated-build
2. `Webhooks`より、先程作成した`Function`のURLを登録する
    - https://docs.docker.com/docker-hub/webhooks/

## 使い方

ただ変更をプッシュするだけです。
通知が来るのを待ちましょう。
ちなみに上記のコード通りに設定すると以下のようなメッセージがSlackに送信されます。

![dockerhub-slack-integration-sample](http://res.cloudinary.com/iwataka/image/upload/v1511096621/dockerhub-slack-integration-sample.png)

アイコンはとりあえずクジラの絵文字を使っていますが、もっと`Docker`っぽいものにできるような気がします。
興味のある方は設定を変更してもっと格好よくしてみてください。

`Google Cloud Fucntions`についてももっと面白い使い方があると思うので模索して見たいと思います。
大量のTwitterアカウントの生存確認方法 めんどくさい作業を一括で!

# 動機
Twitterでいままでリプライを送ったひとたちをリストにまとめてみました。
手作業で確認してみると、アカウントが消されていたり凍結されている人結構いる...

本当の動機はアカウント凍結を食らったからです。(誤BANだと思います...)
昔会話したことがある人達をリストにまとめて、ひとつずつチェックしていったら生きていない人が結構多くてめんどくさくなったからです。
その時の話→[(Twitter凍結を食らった人たちへ) twilog.orgから今までに会話したことある人を取得する](https://qiita.com/redshoga/items/ee43c6106a655ac01eb7)


# 用意するもの
Twitterのアカウントのリンクが書かれているファイル

![tmp.jpg](https://qiita-image-store.s3.amazonaws.com/0/91558/c4f6f749-b35f-5407-6cc5-2dc6ac5de006.jpeg)


# 方法
ファイルを用意して、プログラム中のパスを書き換えて実行する。`python check_acocunts.py`
内部の動作は、ファイル中のリンクにアクセスしてPyQueryを使ってスクレイピングしてアカウントが削除されているか判断しています。

**※API使える人はそっちでやりましょう。この方法は正攻法ではありません。**
※wait_timeはtwitter.comにアクセスした後に待つ秒数です。小さくすると処理は早くなりますが、twitter.comサーバに負担をかけることになります。最悪アカウント削除されます(?)。
※ちなみにこのプログラムはユーザの名前が"凍結済みアカウント"と設定されている人は死亡アカウントにカウントされます。(いないと思うけど)

```python:check_accounts.py
import time
import urllib.request
from pyquery import PyQuery as pq
import codecs

fname = "Twitterのアカウントのリンクが書かれているファイル.txt"
out_file = True
wait_time = 30

def write_file(fname, array):
    f = codecs.open(fname, 'w', 'utf-8')
    f.writelines("\n".join(array))
    f.close()

def is_alive_account(url):
    try:
        with urllib.request.urlopen(url) as res:
            html = res.read().decode("utf-8")
            dom = pq(html)
            title = dom('h1').text()
            if title == "凍結済みアカウント":
                return False
            else:
                return True
    except urllib.error.HTTPError:
        return False

if __name__ == "__main__":
    f = open(fname)
    lines = f.readlines()
    f.close()

    alive_accounts = []
    dead_accounts = []

    for (idx, line) in enumerate(lines):
        url = line.rstrip('\r\n')
        dead_or_alive = is_alive_account(url)
        print(f"{idx+1}/{len(lines)}", "生存" if dead_or_alive else "死亡", url)

        if dead_or_alive:
            alive_accounts.append(url)
        else:
            dead_accounts.append(url)

        time.sleep(wait_time)

    print("alive_accounts", len(alive_accounts))
    print("dead_accounts", len(dead_accounts))

    if out_file:
        write_file("alive_accounts.txt", alive_accounts)
        write_file("dead_accounts.txt", dead_accounts)
```

# まとめ
いい感じに生きている人達を抽出できました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/91558/ed172ecc-ffac-d9f5-32df-ea941ef59c7a.png)

ちなみに私のいままでのリプライを送ったことある人達の生存率は63.93%でした。消えすぎでは?

~~なんだこのまったく需要が無さそうな記事は~~
VBAでのスクレイピングメモ（書き途中)

#[前提1]ハンドラーのオブジェクト構造をまず理解
ハンドラーとか格好良くいっているけども、要はIEを操作するためのクラスオブジェクトのことを言っている。

┏ html(Document) ━━━━━━━━━
┃ ┏ Form ━━━━━━━━━━━━━
┃ ┃ ┏ INPUT ━━━━━━━━━━━
┃ ┃ ┃
┃ ┃ ┗━━━━━━━━━━━━━
┃ ┗ ━━━━━━━━━━━━━
┗━━━━━━━━━━━━━━

VBAやっている人なら理解できると思いますが、
┏ book(Workbook) ━━━━━━━━━━━━━━
┃ ┏ Sheet(WorkSheet) ━━━━━━━━━━━━━
┃ ┃ ┏ Cells/Range ━━━━━━━━━━━
┃ ┃ ┃
┃ ┃ ┗━━━━━━━━━━━━━━━
┃ ┗ ━━━━━━━━━━━━━━━━
┗━━━━━━━━━━━━━━━━━━

のような感じです。
詳しくは[Microsoftの詳細ページ](https://msdn.microsoft.com/ja-jp/library/system.windows.forms.htmldocument)でご覧あれ


#[前提2]
スクレイピングを行う場合、取得したい文字列や、飛びたいリンクが書かれているHTMLタグを探すわけだけど、じゃあ何を使って特定するか…？？

３つある。

①Class属性
②Name属性
③Id属性

```text:サンプルHTML
　①Class属性
  <FORM ACTION="sample" METHOD="POST" CLASS="testClass">
  <INPUT TYPE="HIDDEN" NAME="NO" VALUE="0">
  </FORM>

　②Name属性
  <FORM ACTION="sample" METHOD="POST" NAME="testName">
  <INPUT TYPE="TEXT" NAME="AIUEO" SIZE=60 VALUE="">
  </FORM>

　③Id属性
  <FORM ACTION="sample" METHOD="POST" ID="testId">
  <INPUT TYPE="TEXT" NAME="AIUEO" SIZE=60 VALUE="">
  </FORM>

　①＋②＋③の全部乗せ
  <FORM ACTION="sample" METHOD="POST" CLASS="testClass" NAME="testName" ID="testId">
  <INPUT TYPE="TEXT" NAME="AIUEO" SIZE=60 VALUE="">
  </FORM>


```


基本Formタグとかには①、②、③のいずれかはある場合が多いが、ない時もある。
前提はこの辺にして、
じゃあ実際にどうやって値を取得・設定していくか。



#１．テキストボックスに値を設定する

##①の場合
objIE.document.getElementsByClassName("testClass")(0).Value = "入力したい文字列";
で取ってくる。この属性の場合複数取得される可能性があるので、
HTMLソース上、取得したいタグが何個目のtestClassであるのか把握しておく必要がある。

##②の場合
この場合は楽勝
objIE.Document.Forms("testName").Item("AIUEO").Value = "入力したい文字列";
でいける。
けど、同じnameが複数あったらどういう挙動なのか不明。

##③の場合

■クラス
↓"default_btn"クラスの１個目とかで指定
objIE.document.getElementsByClassName("default_btn btn_big_size")(0).Click

■JAVASCRIPTの実行
objIE.navigate "JavaScript:login(this)"
$().data 完全解析

jQueryの使われたコードからjQueryを外そうとしてふと手が止まるものの1つ、`$().data`について掘り下げてみます。

なお、コードベースとしては、公式サイトにおいてある、[開発版の3.2.1](https://code.jquery.com/jquery-3.2.1.js)を使います。

# 2つの機能

`$().data`は、元来は「DOM要素にJavaScriptの値を紐付ける」だけの機能だったのですが、あとからHTMLの方に`data-*`属性が出現した結果、以下の2ステップを経るようなメソッドとなってしまいました。

0. 読み出し時点で値がなければ、`data-*`属性を参照する
1. それ以降は、従来通りjQuery内部のデータだけ参照する

ということで、この2つが中途半端につながって、混乱を招く結果となっています。

## `data-*`属性の読み出し

まず、`data-*`属性が読み出されるのは、以下のような場合に限られます。

* `$(elem).data()`と全データをリクエストした場合（ただし、1要素あたり1回限りかつ、その時点でデータがセットされていない場合のみ）
* `key`に対応するデータをセットせずに`$(elem).data('key')`で値を参照した場合（かつ、jQuery側に`undefined`以外のデータが入っていない場合）

以上の条件に当てはまる場合、`data-*`属性から値を読み出しますが（`camelCase`というキーは`data-camel-case`のように変換されます）、取り出した文字列には以下のような変換が入ります。

* `true`、`false`、`null`の場合…対応するJavaScriptの値になる
* 数値…JavaScriptの数値と**同じ表記**の場合に限って、数値に変換される（たとえば、`3`は数値に変換されるけど、`3.0`や`+3`はされない、など）
* `{...}`や`[...]`の形…JSONとみなして変換を試みる（失敗してもtry-catchして文字列そのままになる）

## データの保存/読み出し

では、次はDOMノードへのデータ保存/読み出しをどのようにしているか見ていきましょう。jQueryのソースにはこんなコメントが付いています。

```jquery.js
//	Implementation Summary
//
//	1. Enforce API surface and semantic compatibility with 1.9.x branch
//	2. Improve the module's maintainability by reducing the storage
//		paths to a single mechanism.
//	3. Use the same single mechanism to support "private" and "user" data.
//	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
//	5. Avoid exposing implementation details on user objects (eg. expando properties)
//	6. Provide a clear path for implementation upgrade to WeakMap in 2014
```

ということで、「`WeakMap`の導入も視野に入れた」「シンプルな仕組み」が構築されています。

具体的に仕組みを追いかけてみると、`Data`というクラスが存在して、インスタンスそれぞれにユニークなIDである`expando`プロパティを持っています。そして、データをセットできるのは「ノード以外のJavaScriptオブジェクト」「エレメントノード」「ドキュメントノード」に限定されていて、コメントノードやテキストノードは処理から除外されます。

昔はDOMオブジェクトにそのまま値を割り当ててしまうと、DOMとJavaScriptをまたいだ循環参照が発生して、メモリリークしてしまうという問題があったため、`expando`名のプロパティにはキーだけ入れて、実際の中身は別に保管する、というような仕組みが必要だったのですが、jQuery 3.2.1はIE 9以上が対象ということで、そのような問題が起きないからか、DOMに`expando`の名前で追加したプロパティに直接値を書き込む、というシンプルな仕組みとなっていました。

…というか、モダンブラウザが前提なら、勝手にDOMへプロパティを増やしても（名前の衝突を別にすれば）問題にならない、ということなんですね。
【Python】画像読み込み時の記述方法による実行速度の比較

# 初めに
[前回の記事（Neural Network Console を用いた超解像処理の実装）](https://qiita.com/Lickey/items/3090b7e620a248e6ab95)が初投稿にもかかわらず、23いいねと予想以上のいいねをいただきました。（2017/11/19 現在）本当にありがとうございました。
そして今回は、前回のNeural Network ConsoleのGUI操作ではなく、Pythonで文字による実装を行いました。その時に、画像の読み込みについて一つ検証を行いましたので、メモを残しておきます。
#配列の生成方法
複数の配列をまとめた配列の生成方法には主に２種類あります。１つはそれぞれの配列を生成しつつ連結をしていくもの、もう１つは[]の中にfor分で繰り返し処理をしていくものです。いくつかの記事を眺めていると、どうやらこの２つは内部で行われている処理は違うようで、実行速度やメモリに差があるようです。そのため、今回のこの記事では機械学習における大量の画像の読み込みを行う際に、この２つの記述法によってどのくらいの違いがあるのかを検証していきます。
なお、この記事内では１つ１つ連結していく表記を「連結表記」、[]内にfor分を用いる表記を「内部表記」と呼ぶことにします。

##記述方法サンプル
###アウトプット

```
[0 1 2 3 4 5 6 7 8 9]
```
- 連結表記


```python:append.py
import numpy as np

lst = []
for i in range(10):
    x = np.array(i)
    lst.append(x)

print(np.array(lst))
``` 
- 内部表記

```python:in.py
print(np.array([i for i in range(10)]))
```

#ソースコード

```python:test.py
import time
import random
import numpy as np
from PIL import Image


# 内部表記
def in_create(lst):
    return np.array([np.array(Image.open("{}{}.png".format(path,lst[i]))) for i in range(len(lst))])

# 連結表記
def append_create(lst):
    res = []
    for i in range(len(lst)):
        img = Image.open("{}{}.png".format(path,lst[i]))
        arr = np.array(img)
        res.append(arr)
    return np.array(res)


# 変数設定
path = "data\dataset\\train\\input0\\"
l = [i for i in range(30000)]
num = 100

# 内部表記の測定\
start = time.time()
for i in range(num):
    x = in_create(l)
elapsed_time = (time.time() - start) / num
print ("内部表記:{}[sec]".format(elapsed_time))

# 連結表記の測定
start = time.time()
for i in range(num):
    x = append_create(l)
elapsed_time = (time.time() - start) / num
print ("連結表記:{}[sec]".format(elapsed_time))
```
今回は機械学習のために用意した128x128のカラー画像30000枚を一気に読み込んで配列にするまでにかかる時間を計測しました。また、それぞれ100回処理を繰り返し平均の時間を表示するようにしました。
#結果

```
>python test.py
内部表記:17.044339520931246[sec]
連結表記:17.479241828918457[sec]
```
ということで、内部表記を行った方が処理速度がわずかに早いことがわかりました。
#まとめ
この計測の後にも、２,３回計測をしなおしましたが、どの場合においても内部表記の方がわずかに時間が速かったです。
また、実行中に託すマネージャーを除いていると、内部表記は使用しているメモリは最大1.5GiBでしたが、連結表記は1.5GiBまで使用メモリが上昇した後に最後の瞬間だけ2GiBまで上昇する現象が起きました。今回の計測に当たり、使用メモリも厳密に測りたかったのですが、なぜか導入がうまくできなかったため、「使用メモリに関しても内部表記の方が良い」とは言い切れませんが、連結表記よりも受けるメリットは大きそうです。
ただし、コードの可読性が若干下がるというデメリットはありますが、、、。
Java界隈でよく見るしょうもないエラーログと例外処理

*ちょっとした愚痴のようなものです。真に受けないでください。*

# 例えばこういうのは例外ではなく論外である。
* XXXCommonException
  * 「なんでもかんでもこの例外でとりあえず上げる」というタイプ。**即時殺処分すべき**。
     * ただし「とりあえずswitchのdefaultみたいなノリで拾えるようにしたいからこれを継承しろ」というやつで、これがabstractであるなら許す。**大抵そんな頭はない**。
* XXXWarningException
  * ログレベルを例外で管理したいという発想は分からないでもないのだが、それなら**マーカーインターフェースなりアノテーションなりもっと使うべきものがある**。
     * せめて上記のCommon同様にabstractならよいのだが、もちろん**そんな頭はない**。

# なんで駄目なのさ？
そもそも「例外」という機構は、**「これこれこういう理由で処理がぶっ飛んだ時どうしますか？」という記述を可能にするために生まれた**ものである（といっても怒られんと思う）。
送出される「例外」というものはまさにその「これこれこういう理由」であり、**「なんちゃらの一般的事由で処理が吹っ飛びました」とか言われても「ふざけんな」としか返せないのだ**。

# わかった、じゃあそれぞれの理由をそれっぽく分類して例外クラスを作ればいいのか？
**よくない**。もちろん全く駄目だとは言わないが、**その前にやることがある**。

## 責務の決定
**「誰が、どこまで、何をするか」を決めておくということ。**
例えば「あるファイルを読み取ってパースし、オブジェクトとして保持する」という操作があったとする。
この時（やや細かめだが）「あるファイルの場所を渡すやつ」「あるファイルを読むやつ」「読んだものをパースするやつ」「保持するやつ」の4人が登場人物として現れる。

はたしてこいつらは何をどこまですべきだろうか？
常識的に考えると、「あるファイルの場所を渡すやつ」は、少なくとも「ファイルの場所であろうものを」「（おそらくは）文字列で」「欠損なく」渡してくれるものであると仮定する必要があるだろう。
この仮定の基に考えると、「あるファイルを読むやつ」はいちいち「このファイルの場所っぽいものは本当にファイルの場所を示しているんだろうか？」なんて余計なことを考えずに済むし、いざ読みに行ってファイルが無かったとしても「おい、お前が渡してきた情報で探しに行ったけどなかったじゃねーか！」と文句（=例外）をいうことができる。

なおこれをかっこよくいうとCoC、**契約による設計**というやつになる。
何、「例外関係ないじゃないか！」って？何を言っているんだ。**例外は契約が守られない時に使うものだと言っているんだよ**。

## 今あるものの活用
**引数が正しくないならおとなしくIllegalArgumentException投げろよ**。以上。

……流石に雑すぎるのでもう少し掘り下げる。
例えば以下のようなAPIを準備するとする。2つの引数をとり、a/bの結果を返すというものだ。
（所詮例示なので、あまりにもあんまりな代物なのは勘弁してほしい）

```java:ex1.java
public int div(int a, int b){
    return a/b;
}
````
しかしこれはよろしくない、と批判を受けた。なぜなら`div(1,0)`とでもするとArithmeticException（.netの民にはDivideByZeroExceptionと言ったほうが通りがいいかもしれない、かくいう私もDBZE派……）が起こってしまうからだ。

そうするとどうするか？まあ、バリデーションを用意することになろう。
*さて、ここでわざわざ新規の例外クラスを作成すべきだろうか？*

答えはもちろん「**場合による**」である。
たとえば先の例のように、「個々の例外をある程度まとめて引っ掛ける」用途が想定されるのならば、これは作成すべきであろう。多数の例外を引っ掛けるのはやはり見苦しいものだ。
逆に言えば、何かしら**作る理由がないのなら、今あるものを使うべき**である。
難しいことではない。要するに車輪の再発明は馬鹿げているからやめろというだけのことでしかない。

# まとめ
**契約を守って楽しくコーディング！！**

あと、**頼むから自分から型システムぶっ壊しに行く真似だけはやめろ**。
（もっとも、どっちかというとこれはコード値の類をナマの数字で扱うおバカに言うべきな気はするが……）
ファイル操作でよく使うモジュール[os,shutil,glob]

こちらもご参考に
[Pathlibチートシート](https://qiita.com/meznat/items/a1cc61edb1e340d0b1a2)

#モジュールのインポート
```import.py
import os
import shutil
import glob
```
#パス関連
現在のパスを取得
`os.getcwd()`
カレントディレクトリの変更
`os.chdir(path)`
ディレクトリの作成
`os.mkdir(path)`
パスにある要素のリスト取得
`os.listdir(path)`
絶対パスを返す。(ただし、`os.path.join(path,filename)` に同じ)
`os.path.abspath(filename)`
パスの末尾の名前を取得
`os.path.basename(path)`
パスの親フォルダ名を取得
`os.path.dirname(path)`
パスが存在すればTrue
`os.path.exists(path)`
パスの結合
`os.path.join(path,filename)`
パスを末尾とそれ以外に分離
`os.path.split(path)`
##globを使った検索
指定した拡張子(例えばjpg)のリストを取得
`glob.glob(path+'/*.jpg')`
再帰的にファイルを検索する
`glob.glob(path+'/*.jpg, recursive=True)`
正規表現でも検索できる
`glob.glob(path+'/*[0-9].jpg)`


#ファイル操作
ファイルのコピー
`shutil.copy(from_path, to_path)`
ディレクトリ全体のコピー
`shutil.copytree(from_path, to_path)`
ファイルの削除
`os.remove(path)`
ディレクトリ全体の削除
`shutil.rmtree(path)`
ファイル名の変更
`os.rename(before_path, after_path)`
フォーカスされてるセルが隣のセルの下に潜ってしまう


# 問題
tvOSでコレクションビューを実装していると、フォーカスしているセルが隣のセルより下に潜り込んでしまうことがあります。

![before.gif](https://qiita-image-store.s3.amazonaws.com/0/35008/c0d672b7-2af5-9325-36f2-c94590bcb1dd.gif "before.gif")

なんとも気持ち悪いですね。

# 前に持ってくる
こういう時は、`UIView#bringSubview(toFront:)` を呼ぶか、 `layer.zPosition`を変更して前に持ってきてあげる必要があります。
`didUpdateFocus`で実装するとこんな感じになると思います。

```swift
    override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
        if context.nextFocusedView == self {
            self.layer.zPosition = 1.0
        } else {
            self.layer.zPosition = 0.0
        }
        super.didUpdateFocus(in: context, with: coordinator)
    }

```

これでフォーカスされているセルは一番前に来ますね。
しかし、フォーカスが他に移った瞬間にzPositionを元に戻しているので、これではアニメーション中に重なる順序がおかしくなってしまいます。

![before002.gif](https://qiita-image-store.s3.amazonaws.com/0/35008/38c22769-03a5-7cd5-c488-17ba92f19c43.gif "before002.gif")

右側のセルが被ってしまっているのがわかりますか？

# 後にフォーカスされた方がより前に来るようにする

幸いaddCoordinatedAnimationsにcompletionを渡せるので、以下のように実装することができました。

```swift
private var intermediateZPosition: CGFloat = 0.5
private var workItem: DispatchWorkItem?
private func triggerResetSharedVariable() {
    workItem?.cancel()
    workItem = DispatchWorkItem {
        intermediateZPosition = 0.5
    }
    if let workItem = workItem {
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3.0, execute: workItem)
    }
}

...

    public func applyCoordinatedZPositionState(context: UIFocusUpdateContext, coordinator: UIFocusAnimationCoordinator) {
        var completion: (() -> ())?
        if let next = context.nextFocusedView, next.isDescendant(of: self) {
            self.layer.zPosition = 1.0
        } else if let previous = context.previouslyFocusedView, previous.isDescendant(of: self) {
            intermediateZPosition += 0.000001
            self.layer.zPosition = intermediateZPosition
            completion = {
                if let f = UIScreen.main.focusedView, !f.isDescendant(of: self) {
                    self.layer.zPosition = 0.0
                    triggerResetSharedVariable()
                }
            }
        }
        coordinator.addCoordinatedAnimations(nil, completion: completion)
    }
```

これで、完全にフォーカスのアニメーションが終わるまではzPositionが維持されるようになりました。

![after.gif](https://qiita-image-store.s3.amazonaws.com/0/35008/5d99389c-2ffc-2bb0-ac2d-e50c8f43b621.gif "after.gif")

ライブラリにしてありますので、ご利用ください。
https://github.com/toshi0383/FocusZPositionMutating

# toshi0383/FocusZPositionMutating

必要な処理をコピー&ペーストしてもらってもいいのですが、これだけのためにいちいちそういうことするのも面倒だと思うので、AppDelegateに以下の1行を書くだけでセットアップが済むようにしてあります。

```swift
UIView.fzpm_swizzleDidUpdateFocus()
```

あとは、重なる順番を管理してほしいビューを`FocusZPositionMutating`のprotocolに適合させれば、`didUpdateFocus`で勝手に上の処理を呼んでくれます。

```swift
class ZPositionView: UIView, FocusZPositionMutating { }
```

`UIView#isDescendant(of:)` で判定しているため、フォーカス可能なビューである必要はありません。

# まとめ
フォーカスでビューが重なってしまう時はzPositionに気をつけましょう。
AbemaTVの番組表は基本的に隣のセルと被りまくるので管理が大変だったのですが、ライブラリ化できたのでコードがスッキリしました。

Exampleに何種類かサンプル用意してあるので気になる方はチェックしてみてください。
https://github.com/toshi0383/FocusZPositionMutating

以上です！
YAMAHA DS-Liteとnetvolantednsを共存させる設定

前提条件
1.フィルター型ルーティングを利用
　指定した範囲のみDS-Liteの利用を想定
2.DS-Liteはtunnel1に設定
3.pp1へISPの接続設定

解決方法は以下2つ
1.netvolantednsのルーティングを個別に記入する
以下サンプル

```
ip route 118.151.171.189 gateway pp 1
```

2.フィルター型ルーティングにすべて許可を追加する
以下サンプル

```
ip route default gateway tunnel 1 filter 100 gateway pp 1 filter 1000
ip filter 100 pass 192.168.0.2-192.168.50 * * * *
ip filter 1000 pass * * * * *
```
スクラム開発って何？要点まとめ


## はじめに
以前、書籍「[スクラム実践入門 成果を生み出すアジャイルな開発プロセス](http://gihyo.jp/book/2015/978-4-7741-7236-1)」を読んだ際のメモ。
今さら感はあるが、要点のまとめとして現在スクラム開発現場で仕事をしている、またはこれから導入しようとしている方々のちょっとした参考にでもなればと思い投稿する。

## 導入
- ラグビーのスクラムに由来
- アジャイル開発手法の一つで、多くの開発現場で採用されてきている  
※アジャイルとは「すばやい」「俊敏な」という意味で、反復 (イテレーション) と呼ばれる短い開発期間単位を採用すること
- ソフトウェア開発の目的および手段の不確実性に対応するもの

### 手法と役割
- 手法：スプリント、スプリントレビュー、スプリントレトロスペクティブ
- 役割：プロダクトオーナー(PO)、スクラムマスター(SM)
  - POは課題達成志向リーダー、SMは人間関係志向リーダー

### 自己組織化

- スクラムチームはスクラムイベントを通じて自己組織化していく
 - 3つのロール – PO、SM、開発チーム。上下関係はない

## 5つのスクラムイベント
- スプリント …　ステップバイステップでプロダクトとスクラムチームを成長させる
- スプリントプランニング …スプリントの計画を作る。リファインメント
- デイリースクラム …日々の進捗、予定、問題を共有する
- スプリントレビュー …仕事の成果を確認する
- スプリントレトロスペクティブ …仕事の進め方を改善する

## スクラムにおける作成物
- プロダクトバックログ …何を実現するかの一覧
- スプリントバックログ …今何を行うかの一覧
  - ToDo(まだ誰も手をつけていないもの)
  - Doing(誰かが着手しているもの)
  - Done(完了したもの)
- インクリメント …スプリントで作ったもの


## プラクティス
- パターン
 - 状況(コンテキスト)
 - 問題
 - 空気(フォース)
 - 解決

- インセプションデッキ …10の課題でプロジェクトを導く
- リーンキャンバス …プロダクトを1枚で定義する
- ユーザストーリー …ユーザ視点で要求を簡潔に記述する
 - 良いユーザストーリーを作るには'INVEST'が必要
  - Independent：独立している
  - Negotiable：調整可能である
  - Valuable：ビジネス価値がある
  - Estimable：見積もり可能である
  - Small：手ごろなサイズである
  - Testable：テストが可能である
- ユーザストーリーマッピング …ユーザ体験を時間軸で整理する
- プランニングポーカー …開発チーム全員で見積もりをする
- スパイク …技術的不確実性を取り除く(ための事前調査)
- バーンダウンチャート …プロジェクトの進捗を見える化する
- パーキングロット …アイデアを一時退避する。ファシリテーションテクニックの一つ
- KPT …レトロスペクティブを効果的に実施する
 - Keep：良かったことや続けたいこと
 - Problem：困ったことや改善したいこと
 - Try：良かったことを伸ばす案や困ったことを解消する案
- 技術的負債の返済
- 継続的なインテグレーション


### スクラム導入事例と目的
- 作業の属人化の回避
- 割り込みタスクをある程度は許容する
- コミュニケーション不全による信頼低下を避けるべき。企画運営ー開発間などのゴールや目的意識の共有が必要
- プロダクトバックログおよびスクラムチームの分割

## 問題と解決策
- 開発チームの強み弱みの可視化、スキルの底上げ
- スラクムへの理解度を上げる勉強会を開催する
 - 意欲がわかない理由を明らかにする
- スクラムイベントの参加者票を作成　ステークホルダー参加の推奨・非推奨

### 役割別の問題
- **プロダクトオーナーが抱える問題**
 - プロダクトオーナーと権限を有するステークホルダーの権限すり合わせまたは委譲
- **開発チームが抱える問題**
 - サポートチームをつける　そのサポートチームにもスクラムを適用
 - インクリメントの受け入れ条件を作る
 - 外側のチームを巻き込む
- **スクラムマスターが抱える問題**
 - 「GROWモデル」でスクラム導入の目的を整理する
 - Goal(目標)、Reality(現状)、Resources(資源)、Options(選択肢)、Will(意思)

### ケーススタディ
- スプリントプランニング(ストーリーポイント)は1日1人あたり5~6時間程度が多いようだ
- 個別の依頼は即答を避ける
- スプリントレビューはただの進捗共有会ではない　アイスブレークのように場を和らげた上で行った方が緊張をほぐし、積極的に意見を出したり、参加したりしてもらうのに効果的→お菓子を食べながらレビュー
- グラウンドルール、ワーキングアグリーメントを作る

## 最後に
スクラム開発現場を開発メンバー(Tリーダー)として2年ほど経験した感想には以下のようなことが挙げられる。
・スクラムという体裁(型)だけ導入しても意味はなく、理解を持ってある程度専任的に取り回しのできる舵取り/牽引役もしくは評価役が必要
・「自己組織化を促す」という点では有効かつ効果的なシステム
・プロジェクト自体がイテレーションを回すサイクルに向いているかの判定をどこかでするべき
大切なのは「自ら課題を発見し、素早く効果を上げるプロダクトづくり」ができるか否かだ。そのためには手法そのものに固執する必要はなく、仕組みのいいところだけを取り入れつつ旧来の手法に戻る、または新たな方法を模索してもいいように思う。