OmniAICreator/Qiita-1.07M huggingface dataset:
Ubuntuの初期設定とHDDのマウント

## システムのアップデート
```
$ sudo apt-get update
$ sudo apt-get upgrade
```
## hosts設定
特に変更しないけど、用途に応じて併記してもよし。

```
$ sudo vi /etc/hosts
127.0.0.1 localhost hoge.local
```

## network設定
固定IPアドレスを設定
※下記は環境に合わせ任意で

```
$ sudo vi /etc/network/interfaces


#iface inet dhcp
iface inet static
address 192.168.x.x
netmask 255.255.x.x
gateway 192.168.1.254　
dns-nameservers 192.168.1.254
```
ネットワークの更新

```
$ sudo /etc/init.d/networking restart
```

## ロケール設定
日本語がいい人向け(リモートの場合接続元のロケールとなる)
英語のままのほうが情報を得やすいので、ローカルのコンソールは"en_US.UTF-8"のがオススメ


```
$ sudo vi ~/.profile
export LANG="ja_JP.UTF-8"
```
```
$ sudo vi /etc/defaults/locale
LANG="ja_JP.UTF-8"
```

## 新規ディスクのマウント
※USB接続のアダプタやケースなんかで接続して認識できない場合は電力不足orアダプタ自体が容量に対応してるか確認。

### 追加したHDDにパーティションを作成
まずはディスク一覧を確認(余談ですがmacの場合は```diskutil list```)

```
sudo fdisk -l
```
追加したHDDが２台目であれば、/dev/sdbにある。

fdiskを使ってパーティションを作成。
※HDDを再利用する場合など必要に応じて、d コマンドでパーティションを削除。

```
sudo fdisk /dev/sdb
```

fdiskは対話形式のツールなので、コマンドを入力。mでコマンドを確認できる。
まずは0を入力して、gptにてパーティションを作成。
指示に従いながら実際にパーティションを切っていく。

```
n [新規にパーティションを作成]
p [基本領域にパーティションを作成]
1 [番号は１番 そのまま]
最初セクタ [そのまま]
Lastセクタ [開始位置から容量で指定できる、便利]
p 内容を確認して、問題がない事を確認
w 書き込む(パーティションを作成)
```

追加したHDDのフォーマット。パーティション毎に指定して実行。

```
$ sudo mkfs -t ext4 /dev/sdb
```
マウント先(test)を作成してマウントしてみる
上記とファイルシステムが違うと怒られます。

```
$ sudo mkdir /mnt/test
$ sudo mount -t ext4 /dev/sdb /mnt/test
```
これで拡張されたHDDが利用できるようになる。

###データの移行
データ移行は下記オプション付きで。所有権のコピーを含むので必ずrootで実行。
-a・・・属性保持（+d[シンボリックリンク]+r[再帰的]+p[属性保持]）
-v・・・コンソール表示

```
$ sudo cp -av [コピー元] [コピー先]
```



## fstabの設定
現在のfstabの内容を確認。見方は下記の通り。
ラベル/マウント位置/ファイルシステム/オプション（０でOK）/ディスクチェック優先順位（/は１）

```
cat /etc/fstab
# / was on /dev/sda1 during installation
UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX / ext4 errors=remount-ro 0 1
```
UUIDの代わりにラベル指定してあげたほうがわかりやすい。
マウントパーティションに対してラベルをつける。

```
$ lsblk
$ sudo e2label /dev/sdb hogehoge
```
ラベルの削除は ""で上書きしてあげればOK


```
$ blkid /dev/sdb
$ sudo mkdir /media/hogehoge
$ sudo vi /etc/fstab
LABEL=hogehoge /media/hoehoge ext4 defaults 0 2
```

## /homeを追加したディスクに移行
/home以下をコピーして権限を付与。
必要ならgnomeが共有の為に使う.gvfs ディレクトリを作成。

```
$ sudo cp -R /home/* /mnt/test
$ sudo chown -R test /mnt/test
$ sudo mkdir /home/[ユーザー名]/.gvfs

```
既存の/homeを退避して新しい/home(マウントポイント)を作成

```
$ sudo mv /home /home.bak
$ sudo mkdir /home
```
新たに増設したHDDに/homeをマウントする

```
$ sudo umount /mnt/test
$ sudo mount -t ext4 /dev/sdb1 /home
```
これで/homeを増設したHDDに割り当て完了。
起動時に/homeがマウントするよう/etc/fstabを設定。

・デバイスのUUIDを調べる

```
$ sudo blkid
```
以下の行を追加。

```
$ sudo vi /etc/fstab
# 拡張したHDD
UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX /home ext4 defaults 1 1
```
再起動後に/homeがちゃんと見られれば完了。
今週仕事などで調べたjavascriptがらみの知識とかサイトとか３

# 現場で使えるgulp入門 第1回 gulpとは何か
https://app.codegrid.net/entry/gulp-1

# javascriptの連想配列と配列の違い
http://qiita.com/katsukii/items/168bee174073ae7ec7e4

# 配列と連想配列の違い for Javascript
http://befine.jugem.jp/?eid=21

# JavaScriptの連想配列に要素を追加・削除する方法
http://uxmilk.jp/12852

# ES6 におけるJavaScriptのクラス定義
http://www.yunabe.jp/docs/javascript_class_es6.html

# javascriptのfor-in文は、for-each文の代わりじゃない
http://d.hatena.ne.jp/acid-panda/20101223/1293101252

# for..in文
http://www.ajaxtower.jp/js/for/index8.html

# javascript:多次元配列での連想配列(key:value)を取得するコード例
http://www.amelt.net/imc/programming/3547/

# JavaScriptの配列の使い方まとめ。要素の追加,結合,取得,削除。
http://qiita.com/takeharu/items/d75f96f81ff83680013f

# javascript 連想配列(オブジェクト)の要素数が知りたい。
http://chaika.hatenablog.com/entry/2014/08/07/103459

# PHPの配列操作になれた人が、JavaScriptの配列・連想配列・多次元配列・多次元連想配列を作成・ループを理解する
http://dev.adokikaku.com/cat-php/133/php%E3%81%AE%E9%85%8D%E5%88%97%E6%93%8D%E4%BD%9C%E3%81%AB%E3%81%AA%E3%82%8C%E3%81%9F%E4%BA%BA%E3%81%8C%E3%80%81javascript%E3%81%AE%E9%85%8D%E5%88%97%E3%83%BB%E9%80%A3%E6%83%B3%E9%85%8D%E5%88%97/

javascriptの連想配列について
http://q.hatena.ne.jp/1358949574

# 配列、連想配列（ハッシュ）のキーの存在を確認
http://shanabrian.com/web/javascript/array-key-exists.php

# JavaScriptで配列の中の連想配列（オブジェクト）をキーでソートする
http://kimizuka.hatenablog.com/entry/2014/05/19/000000

# javascript:多次元配列での連想配列(key:value)を取得するコード例
http://www.amelt.net/imc/programming/3547/

# プロパティと連想配列
http://so-zou.jp/web-app/tech/programming/javascript/grammar/object/#associative-array

# JavaScriptの連想配列（ハッシュ）はArrayオブジェクトでも作成できる！？
http://blog.asial.co.jp/611

# 【JavaScript】連想配列で要素数の取得
http://qiita.com/glaytomohiko/items/af4b025d7cd48c07266c

# 連想配列とはいったい・・・うごごごご
ただの配列とは何が違うのか・・・。
オライリーを読んでもいまいちわからなかったのでひたすらSampleを読みつつ動かす１週間でした。
FileTableの共有フォルダーにアクセス権を付与する

# 概要
特定のFileTableの共有フォルダーに特定のWindowsユーザーのアクセス権を付与する方法。

一応、[MSDN](https://msdn.microsoft.com/ja-jp/library/gg492061(v=sql.110).aspx#BasicsSecurity)に

> **FileTable セキュリティとファイル システム アクセス**
> ファイル システム API には、FileTable に格納されているファイルまたはディレクトリへのハンドルを開くための、FileTable の行全体に対する適切な SQL Server 権限 (つまり、テーブル レベルの権限) が必要です。 FileTable の列に対する適切な SQL Server 権限がユーザーに与えられていない場合、ファイル システム アクセスは拒否されます。

という説明があるが、これだけだと具体的にどうすればいいかわかりにくいため、補足的なメモ。

# 前提
FileTable自体は正常に作成済み（管理者権限ユーザーで共有フォルダーにアクセス可能）であること。

FileTableを使用可能とするための一連の手順については、以下のページが参考になる。

- [SQL Server開発の利便性を向上させるFileTable／シーケンスオブジェクト／ページング機能 (1/4)：CodeZine（コードジン）](https://codezine.jp/article/detail/6602)

# フォルダーの「セキュリティ」の設定は必要ない
一般的に共有フォルダーのアクセス権を設定する場合、フォルダー自体のセキュリティを設定（エクスプローラでフォルダーのプロパティを表示して「セキュリティ」タブを操作）するが、FileTableの共有フォルダーの場合はその必要はない。

FileTableの共有フォルダーのアクセス権設定は、SQL Server Management Studio上の操作で完結する。

# インスタンスにログインを作成する

共有フォルダーへのアクセスを許可したいWindowsユーザーがSQL Serverインスタンスのログインとして追加されていない場合、新規に作成する。

```sql
USE [master]
GO

-- ログインの作成
CREATE LOGIN [MYDOMAIN\USER1] FROM WINDOWS WITH DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[日本語];
```

![img01.png](https://qiita-image-store.s3.amazonaws.com/0/135864/29604e10-bad6-9eef-c297-ae601eb18c8f.png)


# データベースにユーザーを作成し権限を付与する

FileTableが属するデータベースに、上記のログインと紐づくユーザーを作成する。
ユーザーにはFileTableに対するGRANT ALLと同等の権限（DELETE/INSERT/REFERENCES/SELECT/UPDATE）およびVIEW DEFINITION権限を付与する。

```sql
USE [mydatabase]
GO

-- ユーザーの作成
CREATE USER [MYDOMAIN\USER1] FOR LOGIN [MYDOMAIN\USER1] WITH DEFAULT_SCHEMA=[dbo];

-- ユーザーへの権限付与
GRANT DELETE ON OBJECT::[dbo].[sample_filetable] TO [MYDOMAIN\USER1];
GRANT INSERT ON OBJECT::[dbo].[sample_filetable] TO [MYDOMAIN\USER1];
GRANT REFERENCES ON OBJECT::[dbo].[sample_filetable] TO [MYDOMAIN\USER1];
GRANT SELECT ON OBJECT::[dbo].[sample_filetable] TO [MYDOMAIN\USER1];
GRANT UPDATE ON OBJECT::[dbo].[sample_filetable] TO [MYDOMAIN\USER1];
GRANT VIEW DEFINITION ON OBJECT::[dbo].[sample_filetable] TO [MYDOMAIN\USER1];
```

作成されたユーザーの例
![img02.png](https://qiita-image-store.s3.amazonaws.com/0/135864/d8911f28-4755-3d44-7837-afecf69a693b.png)

付与された権限の例
![picture03.png](https://qiita-image-store.s3.amazonaws.com/0/135864/80ff76d3-2e0d-802b-2f47-931080197a0d.png)

以上で、指定したユーザーから指定した共有フォルダーへのアクセスが許可される。
![img04.png](https://qiita-image-store.s3.amazonaws.com/0/135864/f61e9e3b-a222-bcd3-3671-dd085f4b8475.png)
bundle installしたらGemfile.lockに`RUBY VERSION`が追記されるようになった件

タイトル通りです。

~~~diff
diff --git a/Gemfile.lock b/Gemfile.lock
index 1458fa6..ef52729 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -124,8 +124,5 @@ DEPENDENCIES
   tzinfo-data
   wdm (~> 0.1.0)
 
-RUBY VERSION
-   ruby 2.2.2p95
-
 BUNDLED WITH
    1.12.5
~~~

bundlerバージョン:1.10.5
gemバージョン：2.4.6
rubyバージョン：2.2.2

# 結論
bundlerを最新にアップデートしたらGemfile.lockに追記されなくなりました。
bundlerバージョン:1.10.5→1.12.5

~~~sh
$ gem update bundler

Updating installed gems
Updating bundler
Fetching: bundler-1.12.5.gem (100%)
Successfully installed bundler-1.12.5
Parsing documentation for bundler-1.12.5
Installing ri documentation for bundler-1.12.5
Installing darkfish documentation for bundler-1.12.5
Done installing documentation for bundler after 7 seconds
Parsing documentation for bundler-1.12.5
Done installing documentation for bundler after 3 seconds
Gems updated: bundler

 $ bundle -v

Bundler version 1.12.5
~~~
Espec, PhoenixFramework, MongoDBなアプリケーションでテスト時のDBのcleanupをやってみた


## 状況

PhoenixFramework + Mongodbな環境でAPIのテストをしていたのだが、テストごとに必要なDBのcleanupがめんどくさい。最初はテストが少なかったので個別に書いていたが、だんだん漏れが出てきたので一括でできる方法を模索していた。とりあえず対応できたのでまとめてみた。

## 環境

Elixir           1.3.1
PhoenixFramework 1.2.0
Espec            0.8.28
EspecPhoenix     0.5.0
MongodbEcto      0.1.2
MongoDB          3.2.0
 

## 解決方法

`spec_helper.exs`に`Espec.configure`を設定し、`config.finally`でMongoDBのcommandを実行し、collectionをdropする。

## 概要

EspecPhoenixの[README](https://github.com/antonmi/espec_phoenix)には、`Ecto.Adapters.SQL.Sandbox.checkout/1`を使う例が書いてあるがMongoDBなので使えない。
なので、強引だが処理ごとにDBをdropする方法を実践してみた。

```
ESpec.configure fn(config) ->
  config.before fn ->
  end

  config.finally fn(shared) ->
    Mongo.Ecto.command(YourApp.Repo, listCollections: 1) # collectionの一覧を取得
    |> get_in(["cursor", "firstBatch"]) 
    |> Enum.each(fn(x) ->
      if x["name"] != "categories" do
        Mongo.Ecto.command(YourApp.Repo, drop: x["name"]) # collectionを１つずつdrop
      end
    end)
  end
end
```

## おまけ

RDBな環境(MySQL,PostgreSQLなど)だとEspecPhoenixの例が使えるので楽。

```
ESpec.configure fn(config) ->
  config.before fn(_tags) ->
    :ok = Ecto.Adapters.SQL.Sandbox.checkout(YourApp.Repo)
  end

  config.finally fn(_shared) ->
    Ecto.Adapters.SQL.Sandbox.checkin(YourApp.Repo, [])
  end
end
```

## まとめ

今回の方法で今のところ上手くいっているが、テストが増えてくると実行時間も関わってくる。その時にどう対応しようか？というのが今後の悩み。
MongoDBのAdapterがEcto2.0に対応していないので、今後のPhoenixFramework + MongoDBの組み合わせはちょっと不安要素が大きいので要注意。
全てのcollectionをtruncateするfunctionがMongodbEctoの0.1.4に導入されているが、Ectoとの依存関係が上手く解決できずに導入できなかった。それが解決できればもっと楽にcleanup処理ができそう。
Angular2 animation


## 背景

Angular2のAnimationsに関するドキュメンが少なかったので書きました。[公式ドキュメント](https://angular.io/docs/ts/latest/guide/animations.html)を参考にしております。

lacoさんの[記事](http://qiita.com/laco0416/items/b9639f614d4728299173)より少し新しい内容になっております

## 概要

ウェブアプリケーションにアニメーションを導入することで、リッチでスムーズなインターフェイスを提供する事が出来ます。パフォーマンスが気になるところですが、CSSアニメーションを使うことでネイティブと同等のパフォーマンスで動くアニメーションを作ることが出来ます。

## Angular Animations

Angularアニメーションは、WebAnimationAPIがサポートされているブラウザ上で動きます。各ブラウザのサポート状況は[こちら](http://caniuse.com/#feat=web-animation)で確認できます。
> 
非対応のブラウザについてはこちらの[ポリフィル](https://github.com/web-animations/web-animations-js)を読み込ませて下さい。
*より軽量なポリフィルをAngularチームが開発中で近日中に公開するそうです。*

### Let's build

それではelementの属性値によって変化する（２パターン）アニメーションを作ってみましょう。


まずは必要なモジュールを@angular/coreからimportしましょう

```ts
import {Component, trigger, state, style, transition, animate, OnInit} from '@angular/core';
```

Animationsは@Component内で宣言します

```ts
@Component({
  ...
  animations: []
})
```

アニメーションのトリガを[trigger](https://angular.io/docs/ts/latest/api/core/index/trigger-function.html)を使い作成します。

```ts
@Component({
  ...
  animations: [
    trigger('buttonState', [])
  ]
})
```

>
今回は再生／停止ボタンを作りますので、（ボタンのステータス変化をトリガにする）ということで、buttonStateという名前にします

トリガのステータス（play、stop）を[state](https://angular.io/docs/js/latest/api/core/index/state-function.html)で宣言します。
また、その際のスタイルを[style](https://angular.io/docs/ts/latest/api/core/index/style-function.html)で宣言します。

```ts
  animations: [
    trigger('buttonState', [
      state('play', style({
        "background-image": 'url("/images/play.svg")',
        transform: 'scale(1.1)'
      })),
      state('stop', style({
        "background-image": 'url("/images/stop.svg")',
        transform: 'scale(1)'
      }))
    ])
  ]
```

>
playの際は背景イメージを変更し、ボタンの大きさを少し大きくします。
stopの際は背景イメージを変更し、ボタンの大きさをもとの大きさに戻します。

次に、トリガのステータスが変化した際のアニメーションを[transion](https://angular.io/docs/js/latest/api/core/index/transition-function.html)で宣言します。

```ts
  animations: [
    trigger('buttonState', [
      state('play', style({
        "background-image": 'url("/images/play.svg")',
        transform: 'scale(1.1)'
      })),
      state('stop', style({
        "background-image": 'url("/images/stop.svg")',
        transform: 'scale(1)'
      })),
      transition('play => stop', animate('100ms ease-in')),
      transition('stop => play', animate('100ms ease-out'))
    ])
  ]
```

> 
playからstopに変化した際は、[animate](https://angular.io/docs/ts/latest/api/core/index/animate-function.html)を使い100ミリ秒でイージングで変化させる
stopからplayに変化した際も同様

ここまででアニメーションの作成は完成です。
次にテンプレートに、このアニメーションをアタッチします。

```ts
<button class="btn" @buttonState="state" (click)="onClick()"></button>
```

>
アニメーションさせたいエレメントに対して"@トリガ名"とした属性を付け加えます。valueには、現在のステータスが入ったプロパティを指定します。

次に、現在のステータスが入るプロパティを宣言します。

```ts
@Component({
  ...
})
export class AppComponent implements OnInit{
  public state : string;

    ngOnInit(): void {
      this.state = "stop";
    }

    private onClick() {
      this.state = this.state === "play" ? "stop" : "play";
    }
}
```

>
stateプロパティを宣言し、ngOnInitで初期化します。
クリック時に現在の値から新しいプロパティ値を設定します


以上で完成になります。

>
完成したサンプルは下記をご参考下さい
[GitHub](https://github.com/monkick/angular-demo-animation)
Linux findコマンド

1. ファイル名で検索

    ```
    $ find ./ -name "*.rb"
    ```

1. ファイルサイズで検索

    ```
    $ find . -size 0  # empty file
    $ find . -size 1000c  # 1000バイト
    $ find . -size 1000k  # 1000KB
    $ find . -size +1000c  # 1000バイト以上
    $ find . -size -1000c  # 1000バイト以下
    ```
1. ファイルタイプで検索

    ```
    $ find ./ -type f # ファイル
    $ find ./ -type d # フォルダ
    $ find ./ -type l # symbolic link
    ```
1. 権限で検索
権限の確認は[こちら](http://qiita.com/masashi-t-h/items/5f4c4fa768642aad9e06)
特定権限マッチ -
いずれかマッチ +

    ```
    $ find ./ -perm -g+w # グループに書き込み権限がある
    $ find ./ -perm 644
    $ find . -perm +111 # ユーザー，グループ，その他のユーザーのいずれかに実行権限ある
    ```
1. 時間で検索

    ```
    $ find . -amin 120 # 最後にアクセスした時間が2時間前
    $ find . -atime 2  # 最後にアクセスした時間が2日前
    $ find . -mmin -10 -mmin -20 # 10分前から20分前までに変更されたファイル
    $ find . -mtime -10 -mtime -20 # 10日前から20日前までに変更されたファイル
    $ find . -newermt "2015-10-01" -and ! -newermt "2016-01-31" -ls # 2015-10-01から2016-01-31までのファイル
    ```

1. ファイル検索して削除

    ```
    $ find . -size 0 | xargs rm -rf # 空ファイルを全部削除
    ```
Git for Windowsを64bit版にしたらrsyncが使えなくなったのをどうにかしたメモ

前職でMac OSだったころそうしてたので現職でも引き続きrsyncを使いたいと思ったものの、Windows環境に移ったのですんなりとは行かず、それでも調べたら

rsyncをGit for Windowsに混ぜる - Weblog - Hail2u.net
https://hail2u.net/blog/software/install-rsync-to-git-for-windows.html

このやり方でバッチリ動いていたのだが、最近Git for Windowsを64bit版にした所rsyncが上手く動かなくなってしまった。

どうも以前、32bit版のGit for WindowsにはMSYS1のファイル郡が同梱されていたものが、現在はMSYS2になっているようで、ssh連携あたりで上手く行かないらしい、多分。

それならMSYS2版を入れればいいのだろうと思ってやってみたら上手く行ったのでメモ。

1. [MSYS2 installer](http://msys2.github.io/)をインストール
2. 案内に従ってセットアップを終わらせる
3. pacmanでrsyncを導入 ```pacman -S rsync```
4. MSYS2のインストールフォルダ内からrsync.exeを探し、Git for Windowsの```user/bin/```内にコピー
5. Git Bashからrsyncが使える！

##参考
こっそりと。: msys2の導入
http://camisoul.blogspot.jp/2015/10/msys2.html
標準ライブラリのhashlibでハッシュ化してログインのパスワードを比べる


Pythonの標準ライブラリにはハッシュ化を簡単にできるライブラリがあるらしいので使ってみた

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

import hashlib

if __name__ == "__main__":

	# hashオブジェクトの作成
	md5 = hashlib.md5()

	# 文字列のセット
	md5.update("password")

	print md5.digest()
	print md5.hexdigest()
```

```test1.pyの出力結果
_Mﾌ;Zｧeﾖ・ﾞｸぱ
5f4dcc3b5aa765d61d8327deb882cf99
```

`import hashlib`とかいてimportする。
1.使用したいアルゴリズムに合わせてオブジェクトを作成する(今回はmd5を使用)
2.作成したオブジェクトにハッシュ化したい文字列をセットする
3.`.hexdigest`でハッシュ化する（`.digest`はよくわからない）

ハッシュ化したら元の文字列を知ることはできないそうです。
なので、パスワードがほかの人に知られることはない！！

## 元のパスワードと入力されたパスワードが一致しているか調べる
入力されたパスワードもハッシュ化して、比べればいい。

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

import hashlib
import sys

def createHash(password):

	# ハッシュオブジェクトの作成
	hashObj = hashlib.md5()

	# ハッシュ化する文字列を指定
	hashObj.update(password)

	# ハッシュ化したものを返す
	return hashObj.hexdigest()


if __name__ == "__main__":

	# 元のパスワードをハッシュ化
	checkPass = createHash("password")

	# コマンドライン引数を取得
	password = sys.argv[1]

	# ハッシュ化
	password = createHash(password)

	# 入力されたパスワードが一致しているか
	if checkPass == password:
		print u"ログイン成功"
	else:
		print u"ログイン失敗"
```

```hash_test.pyの実行結果
\python>hash_test.py pass
ログイン失敗

\python>hash_test.py password
ログイン成功

\python>hash_test.py Password
ログイン失敗
```

大文字・小文字も区別しているらしい（当然といえば当然か...）


### 参考文献
>[ドキュメント](http://docs.python.jp/2/library/hashlib.html, "14.1. hashlib — セキュアハッシュおよびメッセージダイジェスト — Python 2.7.x ドキュメント")
>[ハッシュ化について](http://e-words.jp/w/%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E9%96%A2%E6%95%B0.html, "ハッシュ関数とは｜メッセージダイジェスト関数｜ハッシュアルゴリズム - 意味/定義 ： IT用語辞典")
Scalaの「高カインド型」について調べてみました。

現在Scalaに入門中なのですが、「高カインド型」(Higher kinded types)という用語の意味がよく分からなかったので調べてみました。

# 参考資料

[独習 Scalaz — 型を司るもの、カインド](http://eed3si9n.com/learning-scalaz/ja/Kinds.html)
[Iterator パターンの本質 | eed3si9n](http://eed3si9n.com/ja/essence-of-iterator-pattern)
[カインド (型理論) - Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%AB%E3%82%A4%E3%83%B3%E3%83%89_(%E5%9E%8B%E7%90%86%E8%AB%96))
[Scala: Types of a higher kind | Atlassian Blogs](http://blogs.atlassian.com/2013/09/scala-types-of-a-higher-kind/)

# 用語の前提

* 型とカインド

```
型 - 値に付いているラベルのこと。(Int, String、List[Int]等)
カインド - 基本型もしくは型コンストラクタ(後述)に付いているラベルのこと。(A, F[A]等)

注)
上記の「A」のように、型パラメータを必要としない型を「プロパー型」「基本型」もしくは「データ型」という。
Aは「*」、F[A]は「* -> *」のようにして表す記法もある。(むしろその記法の方が正式かもしれない)

注)
基本型のことを、「0個の型パラメータをとる」と見なして「零項(0階)の型コンストラクタ」とする場合もあるらしい。
```

* 関数と型コンストラクタ

```
値コンストラクタ - 値を引数にとって値を返すなにか。要するに関数のこと。
型コンストラクタ - 型を引数にとって型を返すなにか。
```

* 一階と高階

```
一階関数 - 値を引数にとる関数のこと。
高階関数 - 関数を引数にとる関数のこと。
```

# 結論

「高カインド型」とは、要するに「高階の型コンストラクタ」のことで、高階関数が
「関数を引数にとる関数である」のと同様に、
「**型コンストラクタを型パラメータにとる型コンストラクタである**」と考えてよいと思われます。

下記のように、関数と照らし合わせて覚えると頭に入りやすいのではないでしょうか。

| 階数 | 関数 | 型コンストラクタ |
|:-----------|:------------|:------------|
| 一階 | 値 -> 値 | 型 -> 型 |
| 高階 | 関数 -> 値 | 型コンストラクタ -> 型 |

# カインドの用途

関数やクラスの引数の「型」がコンパイル時にチェックされるのと同様に、関数やクラスの「型パラメータ」のチェックをコンパイル時に行う用途で使用されているものと思われます。

要するにGenerics系の機能を持っている言語なら多分必ず備えている機能なのかなと。
(ただし[こちら](https://ja.wikipedia.org/wiki/%E3%82%AB%E3%82%A4%E3%83%B3%E3%83%89_(%E5%9E%8B%E7%90%86%E8%AB%96))の資料を見る限りでは、「高カインド型」の機能を持っている言語はScalaやHaskell等ごく一部のようですが)

# 具体例

(`:kind`(省略形は`:k`)は、型のカインドを表示するコマンドです)

```scala
scala> class MyClass0
scala> class MyClass1[A] {}
scala> class MyClass2[A[_]] {}
scala> class MyClass3[A[B[_]]] {}
scala> class MyClass4[A[B[C[_]]]] {}

scala> :k -v MyClass0
MyClass0's kind is A
*
This is a proper type.

scala> :k -v MyClass1[Int]
MyClass1's kind is F[A]
* -> *
This is a type constructor: a 1st-order-kinded type.

scala> :k -v MyClass2[MyClass1]
MyClass2's kind is X[F[A]]
(* -> *) -> *
This is a type constructor that takes type constructor(s): a higher-kinded type.

scala> :k -v MyClass3[MyClass2]
MyClass3's kind is Y[X[F[A]]]
((* -> *) -> *) -> *
This is a type constructor that takes type constructor(s): a higher-kinded type.

scala> :k -v MyClass4[MyClass3]
MyClass4's kind is Z[Y[X[F[A]]]]
(((* -> *) -> *) -> *) -> *
This is a type constructor that takes type constructor(s): a higher-kinded type.
```

* MyClass0 零階の型コンストラクタ(プロパー型)
* MyClass1 一階の型コンストラクタ
* MyClass2 二階の型コンストラクタ
* MyClass3 三階の型コンストラクタ
* MyClass4 四階の型コンストラクタ

# まとめ

カインドに関しては、「Higher kinded types」とか「higher-order types」とか「Higher kind Generics」とかtype constructor parameter」とか色々な用語が使用されているのが、初心者にとっての分かりにくさの一つの原因だと思うので、用語を統一してほしいとこですね(-_-;)
RaspberryPiで多桁の7セグLEDを点灯する


# RaspberryPiで多桁の7セグLEDを点灯する

今回は温度センサーと7セグLEDを用いた、ロギング機能付きのデジタル温度計を作ってみることにします。


今回表示用のLEDとして用いたのは、aitendoさんで売ってる、ダイナミックドライブ方式で3桁表示できる
白色の7セグLED（カソードコモン型）です。

![image](https://qiita-image-store.s3.amazonaws.com/0/136367/3c7f03f9-f061-cc0d-4085-b0415d3e8adf.png)

## ダイナミックドライブ方式

全てのセグメントが独立に点灯・消灯制御できるようにする制御方式をスタティックドライブ方式といいますが、
3桁の7セグ（＋ドット）を独立に駆動するには、セグメント24本＋コモン1本の25本のピンが必要になります。

一方、今回使うダイナミックドライブタイプのモジュールは、12本の足しかありません。うち1本はダミーなので
実質的に11本で制御することになります

3つの桁に対応するコモン線3本と、各桁8個のセグメントに対応する8本のアノード線の入力の組み合わせにより、
時分割で入力信号を高速に切り替えながら点灯することで、残像によりすべての桁・セグメントを表示できる方式です。

このダイナミックの具体的な制御方法については詳細の説明は後述します。

## 端子とセグメント／桁の対応関係を調べる

今回用意した3桁LEDにはモジュールの端子がどの桁のどのセグメントに対応しているのかの記載が見つからなかったので、手探りで調べてみることにしましょう。

ちゃんと7セグの仕様書があってどの端子がどれに繋がってるかわかってる場合はこの工程は不要ですが、通電チェックを兼ねて、確認のためにやっておいても損はないでしょう。


まずはRaspberryPiから電源をとって、通電してみることにします。
VCC(3.3V)および、GNDの端子のそれぞれ一本をジャンプワイヤ―で接続ブレッドボードまで伸ばします。

![image](https://qiita-image-store.s3.amazonaws.com/0/136367/a198e648-5315-2308-dd55-5fbca5b4c4a3.png)

VCCとGNDはどこの列からとってもいいのですが、今回はそれぞれ、左列の一番上のピン、右列の上から3番目ピンを使います。
そしてVCC側に抵抗（今回使ったのは100Ω）をとりつけ、GND側の配線をLEDモジュールのピンのいずれかに接続。
VCC側は取り付けた抵抗を経由し、GNDと接続した以外のピンに対し、順次接触していきます。
点灯すれば、どの桁のどのセグメントが点灯したかを紙などにメモしていきます。

もし点灯しない場合はいずれかのケースといえます。

* アノード(+)とカソード(-)が逆
* 両方ともアノード・あるいはカソード
* 回路がどこかしらで断線している

調べてみた結果、ピン番号 11, 7, 4, 3, 1, 10, 5, 3 がA～G, DPのアノード（全桁共通）にそれぞれ対応、12, 9, 8がそれぞれの桁のカソード線（全セグメント共通）に対応していることが判りました。
このピン配置は、秋月電子さんで扱っているC-5335Rと全く同じです。

この配列が標準なのでしょうか？

* http://akizukidenshi.com/download/ds/paralight/C-533SR.pdf

![image](https://qiita-image-store.s3.amazonaws.com/0/136367/a9a85589-ff46-9a3f-93ff-fe0bfbc0181c.png)



## 配線をしてみよう

アノード(+)側のピン8本に、それぞれ抵抗を接続していきます。
今回は縦方向に配線するのが難しいため、、短めのジャンパピンで横の列に配線を引っ張り、7セグモジュールと平行になるように取り付けます。

抵抗のピンは長さが余るので、必要な長さに切断したほうが綺麗にまとまるでしょう。

今回は100Ωの金属皮膜抵抗を利用しました。金属皮膜抵抗はカーボン抵抗より大きめになる傾向があります。こいつは特にでかいです。同じ100Ωでももう少し小さいタイプの抵抗はあるので、配線がしやすいものを選ぶとよいでしょう。

スッキリした配線にするには、ジャンパピンやワイヤーは極力ボードに密着させるのがポイントです。抵抗のワイヤー部分は長さが余るので、適当な長さのところでニッパーで切断してもよいでしょう。

写真では2本ほど配線が見えていますが、セグメントのピンと抵抗の大部分は、7セグLEDと抵抗の裏側を通して抵抗に配線しています。

配線がうまくいっているかは、RaspberryPiのVCCとGNDで通電して確認してもいいですし、電池ボックスがあればそれでもいいです。
Swiftのクロージャについて整理してみた。


あるアプリ開発で、クロージャがすんなり理解できずに思いっきりハマったので、自分の頭の整理ついでに簡単にまとめてみました。

# クロージャとは何か
- クロージャは簡単に言うと、自分を囲むスコープの変数を使うことができる。
- 変数に関数を代入できる。

Wikiや公式で書いているクロージャの説明はハッキリ言って理解しにくいので、いまはこういう認識で良いかと・・・


## クロージャの書式
```swift:closureFmt
{ (引数1: 型1, 引数2 : 型2, ...複数可) -> 戻り値の型 in 
	return 戻り値 
}
```
クロージャの書式は上記のようになる。
例えば、String型の引数を何らかの処理をして、String型で返す場合は以下のようになる。

```swift:closureExp
{ (str: String) -> String in 
	//処理とか
    return 戻り値 
}
```

### 簡単な例
```swift:closure1
func selfInfo(name: String) -> () -> Void {
    
    func hello() -> Void {
        print("私の名前は\(name)です")
    }
    return hello
}

var myName = selfInfo("山田太郎")

myName()    // 私の名前は山田太郎です
```

selInfoは `()-> Void`という型の関数を返す関数です。
func helloの型は`()-> Void`の挨拶をする関数です。（->Voidは省略できます。）

上記の例で分かることは、SelfInfoのnameという引数を、中にあるhello関数が自分の変数として使うことできる点です。

```swift:closure2
func selfInfo(name: String) -> () -> Void {
    
    var count = 1
    func hello() {
        print("私の名前は\(name)です。この挨拶は\(count)回目です。")
        count += 1
    }
    return hello
}

var myName = selfInfo("山田太郎")

myName()    // 私の名前は山田太郎です。この挨拶は1回目です。
myName()    // 私の名前は山田太郎です。この挨拶は2回目です。
myName()    // 私の名前は山田太郎です。この挨拶は3回目です。
```

selfInfo内で宣言されているcountという変数を、中にあるhello関数が値を自分のものとして操作することが出来ていることがわかります。

## 結局何がいいの？
クロージャの書式はハッキリ言ってわかりにくいです。どういうシチュエーションで使うと使い勝手が良いみたいな解説でよく使われる例がsort()関数とクロージャの組み合わせです。ここで同じようなものを書いても、既にいろいろなところに溢れている情報なので、ちょっと違った解説を書いてみたいと思います。

### クロージャの型を省略できる
Swiftのクロージャは型推論が出来ます。
本来、厳密に型まで書いてクロージャを使うと以下のようになります。

```swift:closure3
let add: (Int, Int) -> Int = {(int1: Int, int2: Int) -> Int in
    return int1 + int2
}

let result = add(10, 20) // 30
```

Swiftでは、このクロージャの型を以下のように省略ができます。

```swift:closure4
let add = {(int1: Int, int2: Int) -> Int in
    return int1 + int2
}
```

### returnを省略できる
```swift:closure5
let add = {(int1: Int, int2: Int) -> Int in int1 + int2}
```

処理の長さにもよりますが、一行で書いても問題ない内容なら、上記のようにreturnを省略することもできます。（ただし、複数の返り値がある場合は別）

### 引数の型も省略できる

```swift:closure6
let add = {(int1, int2) -> Int in int1 + int2}
```

##自分が引っかかったポイントとクロージャの恩恵
あるAPIを操作していた時に、値を取得出来ないという事象が発生しました。
理由としては、APIなどの通信は別スレッドとして処理するため、値が返ってくる前にメインスレッドで値をretrunしていて、空のデータが返ってきてしまうというものです。この問題点は別スレッドの"処理が終わってから"値を返すという動作を記述していなかったという点です。
実際はもう少し複雑ですが、以下のようにして、クロージャを使って値を取得することが出来ました。


```swift:closure7
func request(comp: (response: String) -> Void) {
    
    let url = "http:~~~~"
    // 非同期処理
    let response = "JSON！！！"
    
    comp(response: response)
}

var responseAns = ""
request { (response) in responseAns = response}
print(responseAns)
```

SwiftTaskなどを使えば、もっと直感的な記述ができますが、何が起きているか理解する必要もあるので、クロージャの理解は必須だと思います。
[Ergodox Ez]あなたに向いているかの判断基準とErgodox Ez以外の選択肢一覧

Ergodox Ez、いいですね。2週間前に届いてからメロメロです。
みんなにおすすめしたいんですが、値段が日本円にして3万円超と高いのと人を選ぶキーボードであるためErgodox向きかどうかの判断基準を書いてみました。
購入するかどうかの意思決定にお役立てください。

## 必須となるスキル

* C言語による簡単なプログラミングができる
    * キーマップのカスタマイズに必要であるため

## 以下に多く該当するならErgodox Ez向き

Ergodox Ezの利点はセパレートかつ高さ調整ができること、キーマップがおよそもっとも柔軟で複雑なマクロもプログラムにより定義できること、キーマップをハードウェア側で持つためポータビリティが高いことです。
逆に欠点を挙げると3万円超という価格やデフォルトのキーマップでは日本語環境ではほぼそのまま使えない点などです。

以上の特徴からErgodox Ezに向いている人を上げるならこんな感じ。

* コストおよびコストパフォーマンス視点
    * ほぼ毎日キーボードで数時間作業をする
    * 良いキーボードには3万円以上出しても良いと考えている
    * HHKBやRealForce, Majestouchで満足していない
* キーマップ視点
    * キーマップを変更したことがある
    * デフォルトのキーマップに不満がある
    * OS側でのソフトウェアマッピングに失敗して(エンターキーをマッピングし忘れたりとか)ログインできなくなることが心配
    * デュアルブートで複数種類のOSを操作しているため、キーマップをハードウェア側で持ちたい
* エルゴノミクス視点
    * 肩こりがひどい
    * 通常のキーボードの肩を丸めた姿勢に不条理を感じている
    * 合理的なキー配置とキーマップでタイピングがしたい
* ドヤ顔クールデバイスアピールがしたい

## 逆に以下で多く該当するならErgodox Ez以外のプロダクトがおすすめ

* キーマップを自分でカスタムしたくない
* 有線接続がイヤ
* 単純にタイピングを速くしたい(キー配置・キーマップの最適化の結果速くなるかもしれないが、他の要因の方がタイピング速度には影響しやすい)
* キーボードに3万円はどう考えても高いと感じる
* プログラミング経験がない
* キーボードでの作業頻度が低い

## Ergodox向きではなかったあなたのための選択肢

製品の紹介とErgodox Ezと比較した時の利点・欠点

* [Kinesis Contoured Keyboard](http://www.edikun.co.jp/kinesis/)
    * 古くからある代表的なエルゴノミクスキーボード
    * 利点
        * 古くからありウェブ上に利用ノウハウの蓄積がある
        * キーマップの変更がハードウェア側で可能でしかもプログラミング知識がいらない
    * 欠点
        * 実売45,000円前後
        * 左右で分離していないため細かいポジション調整はできない
* [Kinesis Freestyle2 Keyboard](http://www.edikun.co.jp/kinesis/freestyle.htm)
    * Kinesis社のセパレートキーボード
    * 利点
        * 実売16,000円~
        * 長期の販売によりオプションや保証が充実している
    * 欠点
        * [英字配列しかなく、キー配置も独特](http://edikun.ocnk.net/data/edikun/product/KB800PB-us_key2.jpg)
        * キースイッチがメンブレン
* [Microsoft Sculpt Ergonomic Keyboard](https://www.microsoft.com/accessories/ja-jp/business/sculpt-ergonomic-keyboard-for-business/5kv-00006)
    * Microsoftが昔から出し続けているエルゴノミクスキーボードの現行世代版
    * 利点
        * 圧倒的流通量と長期の研究開発による高い品質
        * ワイヤレス
        * 実売6,000円
    * 欠点
        * キースイッチがメンブレン
* [Matias Ergo Pro](https://www.diatec.co.jp/products/det.php?prod_c=1913)
    * メカニカルキーボードMajestouchで有名なFILCOが出したセパレートキーボード
    * 利点
        * メカニカルといえばで信頼のFILCO
        * 左右を合体させれば普通のテンキーレスキーボードと同じ専有面積
        * 実売26,000円
    * 欠点
        * [英字配列しかなく、キー配置も独特](https://www.diatec.co.jp/image_prod/FK403QPC_layoutL.jpg)
        * Undo, Cut, Copy, Pasteキーが格好悪い
* [μTRONキーボード](http://www.personal-media.co.jp/utronkb/)
    * キーボードマニアしか知らない。教えてくれた人曰く「東プレ静電容量式のセパレート版」
    * 利点
        * エルゴノミクス界では僕が知る限り唯一の静電容量式
        * キーの各行が一般的なQWERTYキーボードと同じくキー幅半分ずつずれていて馴染みやすい
        * 少なくとも[2008年には販売](http://akiba-pc.watch.impress.co.jp/hotline/20081129/etc_tron.html)しており実績はある
    * 欠点
        * 実売50,000円
        * 情報がかなり少ない
* [エスリル ニューキーボード − NISSE](http://www.esrille.com/keyboard/ja-jp/)
    * 利点
        * エルゴノミクスキーボードでは数少ないワイヤレス接続が可能
        * 多彩なキーマップが購入時に指定可能
        * ファームウェア書き換えによるキーマップ変更が可能
    * 欠点
        * 最安50,000円, キースイッチ変更(+4,000円)Bluetooth(+10,000円)ポインティングデバイス追加(+6,000円)
* その他クラウドファウンディング系キーボード
    * [keyboardio](https://shop.keyboard.io/)など
    * 利点
        * 各々独自の視点で既存のキーボードの欠点を克服しており、後発な分確実に進歩している
        * ドヤ顔クールデバイス感は高い
    * 欠点
        * 基本的に高価
        * 本当にリリースされるかわからない
[Ergodox Ez] Apple JIS キーボードに寄せたキーマップを晒す

Ergodox Ez届いたので自分流にキーマップ作りました。Ergodox普及のためにも晒します。

https://github.com/bigwheel/qmk_firmware/blob/master/keyboards/ergodox/keymaps/osx_jis_bigwheel/keymap.c

## キーマップの意図

基本的に[AppleのJISキーボード](https://www.amazon.co.jp/dp/B005DPEZOY)準拠で配置しています。
また[先駆者の金言](http://qiita.com/kei_s/items/40a896d1a1c70f2961e0#reset-%E3%82%AD%E3%83%BC%E3%82%92%E3%82%A2%E3%82%B5%E3%82%A4%E3%83%B3%E3%81%99%E3%82%8B)に従いRESETキーをLAYER1,2に追加しています。それ以外はLAYER1,2はほぼ変更していません。

```
 * ,--------------------------------------------------.           ,--------------------------------------------------.
 * |   1    |   2  |   3  |   4  |   5  |   6  | Hyper|           | PrScr|   7  |   8  |   9  |   0  |   -  |   ^    |
 * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
 * | Tab    |   Q  |   W  |   E  |   R  |   T  | Down |           |  Up  |   Y  |   U  |   I  |   O  |   P  |   @    |
 * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
 * | Ctrl   |   A  |   S  |   D  |   F  |   G  |------|           |------|   H  |   J  |   K  |   L  |   ;  |   :    |
 * |--------+------+------+------+------+------| LEFT |           | RIGHT|------+------+------+------+------+--------|
 * | LShift |   Z  |   X  |   C  |   V  |   B  |      |           |      |   N  |   M  |   ,  |   .  |   /  |   \    |
 * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
 *   | ~L1  | LAlt | LGui |      | Eisu |                                       | Kana |   |  |   [  |   ]  |  ~L2 |
 *   `----------------------------------'                                       `----------------------------------'
 *                                        ,-------------.       ,---------------.
 *                                        | App  | Home |       | PgUp |  Ctrl  |
 *                                 ,------|------|------|       |------+--------+------.
 *                                 |      |      | End  |       | PgDn |        |      |
 *                                 | Space|Backsp|------|       |------|  Del   |Enter |
 *                                 |      |ace   | Esc  |       | Alt  |        |      |
 *                                 `--------------------'       `----------------------'
```

## 主な参考元

* [Ergodox EZ を使ってみよう \- Qiita](http://qiita.com/kei_s/items/40a896d1a1c70f2961e0)
* [日本語配列でバリバリにErgoDox EZを使う \- Qiita](http://qiita.com/shuh/items/b94215d3b946d3ded0fe)
OGP や Twitter Cards ではスマートフォンで「動画のその場再生」ができないので注意

タイトルの通りです。
2016/08/07 現在、og:video や Twitter Cards (Player) では、タイムライン上で展開された動画のその場再生（ = WebView を開かずに再生）ができないので要注意です。
なお LINE は og:video を指定した場合も PC, SP いずれも動画のその場再生ができないので、これも要注意です。流石にサムネイルは出してくれますが。
なお動画は .mp4 を指定しています。

以下、調べた結果です。

　  | 動画のサムネイル表示 | 動画のその場再生
---|---|---
Twitter Web (PC) | ◯ | ◯
Twitter Web (SP) | ◯ | ×
Twitter アプリ (PC) | × | ×
Twitter アプリ (SP) | × | ×
Facebook Web (PC) | ◯ | ◯
Facebook Web (SP) | ◯ | ×
Facebook アプリ (SP) | ◯ | ×
LINE (PC) | ◯ | ×
LINE (SP) | ◯ | ×
iOS10-day-by-dayが公開されたみたいですね

iOS新機能のサンプルリポジトリ　
day by dayシリーズのiOS10版が公開されたみたいですね。

[iOS10 Day by Day](https://github.com/shinobicontrols/iOS10-day-by-day)
・01 - Messages
・02 - Thread Sanitizer
・03 - Xcode Extensions
・04 - UIViewPropertyAnimator

*OSバージョン別のサンプルも整理されていて良いですね。*

[・iOS9 Day by Day](https://github.com/shinobicontrols/iOS9-day-by-day)
[・iOS8 Day by Day](https://github.com/shinobicontrols/iOS8-day-by-day)
[・iOS7 Day by Day](https://github.com/shinobicontrols/iOS7-day-by-day)
VSCodeでPythonを実行できるようにしたい

### VSCodeでPythonをポチッと実行したい

## 環境
* windows7
* VSCode1.3.1
* python3.5


## 前提
実行構成ファイルの`tasks.json`が存在しない状態。
（`tasks.json`が存在する前提で説明されている記事があってちょっとハマったので。）


## やってみよう

### 手順１
F1（もしくは Ctrl+Shift+P）キーを押して Command Palette を開いて、tasksと入力します。
出てきた一覧の中から「タスク：タスクランナーの構成」を選びます。
![image1.png](https://qiita-image-store.s3.amazonaws.com/0/129708/813bc4ad-1da6-a6ba-832e-dc81b0e90b67.png)


### 手順２
更に一覧が出てくるので「Others 任意の外部コマンドを実行する例」を選択します。
![image2.png](https://qiita-image-store.s3.amazonaws.com/0/129708/3c4e555f-1def-c242-b963-6cfeaf8c9f42.png)


選択すると、`tasks.json`が作成されます。
![image3.png](https://qiita-image-store.s3.amazonaws.com/0/129708/64bf84c6-784e-b8ec-cb2e-5d0891846724.png)


### 手順３
`tasks.json`を図のように変えて保存しておしまい
![image4.png](https://qiita-image-store.s3.amazonaws.com/0/129708/d99a486d-4f2b-663e-9988-817c42b855c7.png)



pythonファイルを作成したら、Ctrl+Shift+Bでガンガン実行しちゃいましょう！
デバッグのやり方はまた今度。
Linux file閲覧 less

## less
### オプション
<hr>
行数表示: N
パターン検索: p パターン
改行なし: S
キーバインド

###キーバインド
<hr>
１ページ進む: Space
１ページ戻る: b
半ページ進む: d
ページの先頭に移動: g
ページの最後に移動: G
パターン前方検索: /パターン
パターン後方検索: ?パターン
前方検索繰り返し: n
後方検索繰り返し: N
エディタ起動: v
終了: q
tail -f で改行なし的な

### tail -f で改行なし的な
<hr>
$ less -S+F access_log
通常のlessに戻す: Ctrl+C
tail -f に切り替え: Shift+F
selenium メモ

# click

* 動作：クリック
* 対象：クリックする要素
    * 例：ボタン画像をクリック
    * //img[contains(@src,'http://test.tes/button.png')]
    * 例：２番めのボタン画像をクリック
    * xpath=(//img[contains(@src,'http://test.tes/button.png')])[1]
* 値：なし

# pause

* 動作： 一時停止
* 対象： ミリ秒
    * 例： 1000
* 値：　なし

# store

* 動作：値を保存する
* 対象：保存する値
    * 例： ランダムな値0or1を生成して、0の場合はtrue
        * javascript{Math.floor(Math.random()*2) == 0}
* 値：保存先
    * 例： isZero

# storeElementPresent

* 動作：　要素を検索して存在するかどうかを保存する
* 対象：検索する要素
    * 例：//img[contains(@src,'http://test.tes/button.png')]
* 値：保存先
    * 例：ok

# label

* 動作：ラベルを付ける（ジャンプ先になる）
* 対象：ラベル名
    * 例：jump1
* 値：なし（メモを書いても良い）

# gotolabel

* 動作：ラベルにジャンプ
* 対象：ラベル名
    * 例：jump1
* 値：なし

# gotoIf

* 要プラグイン
* 動作：対象がtrueになれば値のラベルにジャンプ
* 対象：${ok}
* 値：ジャンプ先のラベル名
    * 例：jump1
JerseyでリクエストエンテティJSONをBean ValidatorでvalidateしてエラーJSONレスポンスを返すチュートリアル

参考文献
--------
* Bean Validation specification  
http://beanvalidation.org/1.1/spec/
* Jersey User Guide: 18. Bean Validation Support  
https://jersey.java.net/documentation/latest/bean-validation.html
* Jersey User Guide: 7.3. WebApplicationException and Mapping Exceptions to Responses  
https://jersey.java.net/documentation/latest/user-guide.html#d0e6664

Bean Validationを依存関係に追加する
---------------------------------
```
<dependency>
    <groupId>org.glassfish.jersey.ext</groupId>
    <artifactId>jersey-bean-validation</artifactId>
</dependency>
```
(versionはBOMで指定されたものを使うので書かない)

リクエストエンテティJSONにアノテーションで制約を付与する
-----------------------------------
```
class RequestBean {
 
    @NotNull
    private String propertyA;
 
    ...
}
```
リソースクラスのメソッドにアノテーションで制約を付与する
---------------------------------------------------
```
@Path("/")
class MyResourceClass {
 
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public void doSomething(@Valid @NonNull RequestBean user) {
        ...
    }
}
```

ConstraintViolationExceptionのExceptionMapperを実装する
------------------------------------------------------
```
@Provider
public class ConstraintViolationExceptionMapper implements ExceptionMapper<ConstraintViolationException> {
    @Override
    public Response toResponse(ConstraintViolationException ex) {
        return Response.status(Status.BAD_REQUEST)
            .entity(buildEntityFrom(ex))
            .type(MediaType.APPLICATION_JSON_TYPE)
            .build();
    }
```
ConstraintViolationの各パラメータには以下の値が格納されている:
* rootBean: リソースオブジェクト 
* leafBean: リクエストエンテティBean
* propertyPath: <メソッド名>.arg0.<リクエストエンテティBeanのプロパティ名>
(リクエストエンテティ自体がnullの場合は　<メソッド名>.arg0　)

(Jersey User Guide:18.7.1. ValidationErrorに記載されているように、
デフォルトでマッピングする機能もあるので、要件に合うのであればそれを使ってもよい)
「ExcelでSQL」のノウハウ


# 元ネタ

[Excelの集計をSQLでおこなう方法。VLOOKUP()やSUBTOTAL()の限界を超えろ！！](http://mukaer.com/archives/2010/10/17/excelsqlvlookup/)
という記事。

# 私的改造

* セルB1：ファイル指定(xls?/csv/mdbを対象)(指定がなければブック内のワークシートを対象)
* セルB2：SQL文(いちいちVBEを開かなくてもいいように)

https://gist.github.com/acknpop/873beccfaf9e9051d1e9214fa406dc71

多量のデータを扱うとExcel自体の安定性が悪くなるのが悩みの種。

# SQL記法のノウハウ

このSQLの記法はMicrosoft Accessに準拠するので、標準SQLとは異なる癖があります。SQLの専門家の方々には常識なのかもしれませんが、当方、SQLもExcelもVBAも門外漢なもので。

* SQL文は512文字まで（多分）

* ワークシートの特定領域だけをテーブルとして扱いたい

```SQL
[Sheet1$A3:F]
```

* 文字列の結合には & を用いる(標準SQLでは||)

* 特定フィールドとして固定の文字列を埋め込みたい

```SQL
'文字列' as フィールド名
```

* フィールド名に空白が含まれる場合の指定

```SQL
[フィールド 名] as エイリアス
```

* SQL文中で条件判断したい

```SQL
iif(条件文, 真, 偽)
```

* 文字列を部分抽出したい

```SQL
mid(文字列, 位置, 長さ)
```

* 文字列長を取得したい

```SQL
len(文字列)
```

* フィールドAが他のフィールドBに含まれているかどうかを調べたい

```SQL
フィールドB LIKE '%' & フィールドA & '%'
```

* FULL OUTER JOIN

http://homepage2.nifty.com/mathpara/programing/access_fulljoin.htm

とりあえず。
mysql

内部結合
http://www.dbonline.jp/mysql/select/index14.html

データをグループ化
http://www.dbonline.jp/mysql/select/index9.html

外部結合(OUTER JOIN句)
http://www.dbonline.jp/sqlite/join/index2.html

サブクエリを使った検索条件の設定
http://www.dbonline.jp/mysql/select/index20.html
specファイルからrpmbuild時にInstalled (but unpackaged) file(s) found となる

specからrpmbuildすると、

```sh
error: Installed (but unpackaged) file(s) found:
```

内容そのまま、インストールされるがパッケージんは含まれてないファイルがあるということ。

この場合、specファイルのfilesセクションにインストールされるファイルのリストを追記することで解消する。

```
%files
%defattr(-,root,root,-)
/path/to/dir/
/path/to/file/
```

または

```
%define _unpackaged_files_terminate_build 0
```

として、エラーを無視するようにする。

今回自分の場合はドキュメントがなかったのでエラーが出ていた。
この場合はspecファイルに

```
%define _unpackaged_files_terminate_build 0
```

を追記することで解消する。
Arduino + モノクロ液晶でゲームを作る


# 概要

子供の頃、手のひらサイズのキーチェーンゲームでよく遊びました。
小さなモノクロ液晶に、幾つかのボタンで構成された小型のゲーム機です。

こういうのです（画像は[アルゴ算法堂](http://sampodo.cocolog-nifty.com/top/2009/08/post-67d7.html)様からお借りしました）。
![rimg0090.jpg](https://qiita-image-store.s3.amazonaws.com/0/129201/395dae71-79b0-c3d0-5b3b-9841e3a4d424.jpeg)

とても懐かしいですね・・・。


ところで、こういったキーチェーンゲームなら作れるのではないか？
と思い、小型液晶とArduinoを使って作って見ました。


# 使用材料

* Arduino UNO R3 (開発とArduinoライタとして)
* ATMEGA328P（[秋月で250円](http://akizukidenshi.com/catalog/g/gI-03142/)）
* モノクログラフィック液晶　AQM1248A （[秋月で750円](http://akizukidenshi.com/catalog/g/gK-07007/)）
* 16MHzセラロック（[秋月で35円](http://akizukidenshi.com/catalog/g/gP-00525/)）
* ユニバーサル基板（[秋月で60円](http://akizukidenshi.com/catalog/g/gP-03229/)）
* タクトスイッチ（[秋月で1個10円](http://akizukidenshi.com/catalog/g/gP-03647/)）
* ICソケット 
* ロジックレベルコンバーター（[ebayで2個100円程度](http://www.ebay.com/sch/i.html?_sacat=0&_nkw=Logic+Level+Converter&rt=nc&LH_BIN=1)）

# モノクロ液晶 AQM1248A の利用

秋月から届いた状態では、液晶はまだハンダ付けされていません。
まずはハンダ付けを行いましょう。

次に、液晶とArduinoの接続です。
今回は、この液晶を利用するために、しなぷすさんの作成されたライブラリを使います。
https://synapse.kyoto/hard/MGLCD_AQM1248A/page001.html

液晶の接続は下記のように行います。
注意点として、この液晶は3.3Vで動作します。
Arduino UNOと接続する際には、Arduinoの5V → 液晶の3.3Vに信号の電圧を変換してあげなければいけません（でないと最悪液晶が壊れます）。
今回は、ロジックレベルコンバーターを間にはさみました。

（見づらいので、[しなぷすさんのサイトをご参考にして下さい](https://synapse.kyoto/hard/MGLCD_AQM1248A/page003.html#index3_5)）
今回は

| 液晶 (AQM1248A)| Arduino |
| --- | --- |
|CS|8|
|RS|7|
|SCLK|6|
|SDI|5|
 
 につなぎました。

![AQM1248AとArduinoの接続_ブレッドボード.png](https://qiita-image-store.s3.amazonaws.com/0/129201/5037e525-80e4-7b40-454f-cb636677cecd.png)

接続が終わったら、[ライブラリをダウンロード](https://synapse.kyoto/hard/MGLCD_AQM1248A/page013.html#index5_1)し、インストールして下さい。
[HelloWorld](https://synapse.kyoto/hard/MGLCD_AQM1248A/page013.html#index5_2_2)が動けばOKです。

# ゲームの作成

今回は、延々と上にジャンプしていくゲームを作成しました。
ソースコードは[githubに上げています](https://github.com/alf-ytakada/arduino_jumpgame)。

動画はこちら
[![arduino + モノクロ液晶で簡単なゲーム](http://img.youtube.com/vi/TXPs62E_doE/0.jpg)](http://www.youtube.com/watch?v=TXPs62E_doE)

開発時にはArduinoで動作を確認し、プログラムがfixした後は、
空のATMEGA328PにArduinoブートローダ書き込み→プログラム書き込みを行い、ユニバーサル基板上に実装しました。

液晶はユニバーサル基板にハンダ付けしようか悩みましたが、ちょっと液晶がお高いので、後々取り外せるようにICソケットをハンダ付けし、そこに液晶を差し込む形にしました（笑）


# スコア表示
登ったスコアを表示するために数字を表示していますが、
ライブラリ同梱のフォントは、デフォルトの横表示にのみ対応していました。
その為、縦表示を行うためには別途フォントを準備する必要があります。
今回は、[しなぷすさんのサンプルゲーム](https://synapse.kyoto/hard/AQM1248A_shield/page001.html#index2_4)に同梱されているフォント画像データを元に、ライブラリ内に同梱されているツール（MGLCD\extras\BMP2H.exe）を利用し、回転した画像からビットマップデータを生成して利用しました。


# 感想

Arduinoとライブラリのおかげで、比較的簡単にゲームを作ることが出来ました。
乾電池2個で動作するので、外に持ち出して遊べます（笑）
夏休みの工作にいいかもしれません。


次回はカラー液晶を使ってゲームを作ってみたいと思います。
【iOS 10】Today Extension (Widget) の高さを調節する

※本記事は、[一般に公開されている情報](https://developer.apple.com/reference/notificationcenter) を元に作成しています
※図は [What's New in iOS 10 \- Overview \- iOS Human Interface Guidelines](https://developer.apple.com/ios/human-interface-guidelines/overview/whats-new/) より引用しています

# これは何

iOS 10から `NCWidgetDisplayMode` という概念が追加されました。これに伴い、Today Extension（以下Widget）の高さを調節する方法も変わっています。何も対応しないとOSが決めた高さに固定されます。
この記事ではiOS 10で Widget の高さを調節する方法を解説します。

## 検証環境

* Xcode 8 beta 4

# NCWidgetDisplayModeとは

[公式ドキュメント](https://developer.apple.com/reference/notificationcenter/ncwidgetdisplaymode)には次のように書かれています。

> The modes that can be toggled between when the More button is activated within a widget running in iOS.

"More button" というのは下図の "Show More" ボタンのことを指しているものと思われます。

![image](https://qiita-image-store.s3.amazonaws.com/0/8292/247b2bdb-ff68-ecbc-a047-6515fb9f5138.png)

このボタンが押される度に `NCWidgetDisplayMode` が切り替わります。値は

* Compact (default)
* Expanded

が用意されています。

# 高さを調節する

`NCWidgetDisplayModeExpanded` をセットします。こうすることで Widget に「Show More」ボタンが現れ、ユーザが高さを調節することができるようになります。（iOS 10未満のデバイスで実行するとクラッシュするので注意）


```swift
override func viewDidLoad() {
    super.viewDidLoad()
    self.extensionContext?.widgetLargestAvailableDisplayMode = NCWidgetDisplayMode.Expanded
}
```

次に `widgetActiveDisplayModeDidChange` を実装します。このメソッドは名前の通り `NCWidgetDisplayMode ` が変更される度に呼ばれます。

```swift
func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize){
    if (activeDisplayMode == NCWidgetDisplayMode.Compact) {
        self.preferredContentSize = maxSize;
    }
    else {
        self.preferredContentSize = CGSize(width: 0, height: 200);
    }
}
```

`activeDisplayMode` に現在のモードが渡ってくるので、それによって Widget のサイズを調整します。設定できる最大サイズは `maxSize` で取得できます。


これで Widget の高さが調節できました :smile: 

# 参考リンク

* [NCWidgetDisplayMode \- NotificationCenter \| Apple Developer Documentation](https://developer.apple.com/reference/notificationcenter/ncwidgetdisplaymode)
* [How to resize the height of widget in iOS 10? \| Apple Developer Forums](https://forums.developer.apple.com/thread/48930)
* [What's New in iOS 10 \- Overview \- iOS Human Interface Guidelines](https://developer.apple.com/ios/human-interface-guidelines/overview/whats-new/)
あるボタンを押した時のアニメーション効果を連打しても確実に付けさせたい

あるボタンを押した時に、
ぽよんと反応するようなアニメーション効果を与えたい。
その要素を押したら、例えば `.click-animation`のような、ぽよんとするCSSアニメーションを付けたクラスを、付与させる事が多いが、そんな時の実装MEMO。

要素を押した時に、`.click-animation`が既に付与されていたら、削除してから付与しないとアニメーションしなく、また削除して即付与してもアニメーションしないので、`setTimeout()`などで適当な一定時間待って付与する事が多かった。

```
$(target).removeClass('click-animation');
setTimeout(function() {
    $(target).addClass('click-animation');
}, 10);
```

もしくは、`webkitAnimationEnd`などを使って、アニメーション後にクラス削除などしていた。

```
$(target).addClass('click-animation');
$(target).on('webkitAnimationEnd', function() {
    $(target).removeClass('click-animation');
});
```

ただこれだと連打した場合に反応してくれない場合がある。
結論、`requestAnimationFrame`を使うと良さそう。

```
$(target).removeClass('click-animation');
requestAnimationFrame(function() {
    $(target).addClass('click-animation');
});
```

これだと高橋名人ばりに連打した場合も確実にアニメーション効果を与える事ができた。
ブラウザの次のレンダリングフレームを待ってクラス付与してるから確実ということだろうか。

Google I/O 2016の[実装サンプル](https://github.com/GoogleChrome/ui-element-samples/blob/gh-pages/swipeable-cards/cards.js#L166-L175)とかでも、`requestAnimationFrame`を使った要素の付与や削除をやってるようだった。
MethodInvokerの水平展開…


# 背景
BackgroundWorker使ってると、裏タスク側からフォームにアクセスしたくなりますよね
そんな時Control.Invokeを使え！ってのは余りにも有名
でも、delegateを毎回定義するの大変なんですよー
基本１回しか使わないのでメソッド定義するのも悩ましくてさ

# 対策
っても何の事はもなく、MSもきちんと考えてくれてました

```csharp
delegate void MethodInvoker();
```

と云うのが標準で定義されているので、それと匿名関数を組み合わせれば…

```csharp
this.Invoke((MethodInvoker)delegate() {
    textBox1.Text = "むふっ";
});
```

はい、出来上がり

# 展開
そこでふと考えた…
パラメータ渡したかったり、結果を受け取りたいときはどうすれば良いんだ！
自分で `delegate` 定義しろって事かい？
よーし、何とかしてやろうじゃないか

```csharp
delegate void MethodInvoker<T1>(T1 arg1);
delegate void MethodInvoker<T1, T2>(T1 arg1, T2 arg2);
delegate void MethodInvoker<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);
        :
```

序に…

```csharp
delegate T0 FunctionInvoker<T0>();
delegate T0 FunctionInvoker<T0, T1>(T1 arg1);
delegate T0 FunctionInvoker<T0, T1, T2>(T1 arg1, T2 arg2);
delegate T0 FunctionInvoker<T0, T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);
    :
```

引数は `arg9` 位まで用意しとけば良いかな、ふふん楽勝楽勝
まったく `Console.WriteLine` のオーバーロードみたいに引数９つ分位用意しといてくれればいいのに
全くMSも気が利かない

# 結果
いっぱい定義並べて満足しました

```csharp
string name = this.Invoke((FunctionInvoker)delegate<string>() {
    return textBox2.Text;
});
```

って確かに使えるし、満足満足………
<br/><br/>
……
でもさー
よーく考えたら画面部品じゃなければ普通にアクセスできるんですよねー
わざわざパラメータで渡さなくたって、わざわざ戻り値で返さなくたって、そこら辺の変数に触り放題じゃん

という事で、標準定義のMethodInvokerだけあれば何の問題もない事に今更気づくと云う…

思い付きで手を動かすのは良くないなぁ
でもま、楽しかったから良しとするか、と云うお話
STNSを使ったlinuxユーザ管理の検証環境を作りました

ある程度の数のサーバを扱っていると、linuxユーザの管理が大変になってきます。もちろん手で設定するのは大変ですが、AD系ではオーバースペックかつ、導入の手間が大きい場合があります。

そこで、STNSを使い、ユーザと公開鍵の管理のみをシンプルに行えるようにし、STNSサーバのみ変更することで対応できるようにし、linuxユーザ管理の手間を下げることができます。

公式に[インストールガイド](http://stns.jp/ja/install)がありますが、Debianの場合少し違うのと、多少ハマったので、[Debian jessieで簡単に構築検証できる環境](https://github.com/reiki4040/STNS_sample)を作りました。

Vagrant/virtualboxを使って仮想サーバを作り、そこにSTNSとそれを使ってログインすることができる環境をansibleで作ります。

# 検証方法

[README](https://github.com/reiki4040/STNS_sample)の通りに進めれば、STNSサーバとそれを使ってログインできるクライアント側のサーバが出来上がります。

出来上がった後は、以下のようにstns_server側のstns.confを変更して、検証を進めることができます。

```
# STNSサーバに接続
vagrant ssh stns_server

# 設定ファイルを編集
sudo vi /etc/stns/stns.conf

# STNSのリロード
sudo service stns reload
```

もしくはansibleのtemplateをいじっても良いです。

# ハマったことなど

その他、検証中にはまったことをいくつか書きます。

## /etc/nsswitch.confの編集に注意

検証している際に、 `/etc/nsswitch.conf`のフォーマットを誤って更新してしまったことがありました。その場合、他のユーザでもログインできなくなるので注意してください。

たまたまvagrantユーザでログインしていたコンソールでは、`Who are you?`と聞かれて何もできなくなりました。検証用のサーバなので、`vagrant destroy`で消して作り直せば問題ないですが、運用中のサーバでは気をつけましょう。

**playbookの内容は、使っているboxに合わせてあるので、自分で構築したサーバにはうまく適用できない場合があります。**


## stns-key-wrapperのエラーが出てログインできない。（解決済み）

--- 2016.08.08追記 ---
STNS libnss 0.2.0にて、配置場所が変更になり、この問題は発生しなくなりました。検証用のplaybookも修正しています。
--- ここまで ---

クライアント側で、Opensshのconfigにsans-key-wrapperを指定しますが、以下のエラーが出てログインできない状態になります。sshしてる側は、ただの`Permission denied`です。

ログインしようとしているサーバの`/var/log/auth.log`または`/var/log/syslog`に以下のようなエラーが出ます。

```
sshd[14922]: error: Unsafe AuthorizedKeysCommand: bad ownership or modes for directory /usr/local/bin
```

調べると、鍵のファイルなどの権限が広く設定されている場合に発生するものです。ディレクトリを700,ファイルを600(鍵ファイルの場合）するように促されます。

しかし、`/usr/local/bin`の権限を変えるのは、、、ということでsampleでは、/stnsというディレクトリを作り、そこに`stns-key-wrapper`をコピーして権限を変えて、sshdの設定で指定しています。

不思議なのは、一度権限を変えてログインできるようになると、そのあとは権限を戻しても特にエラーにならない点です。

ここはちょっと何が正解かはわかっていない状態です。

## Debian 7 (wheezy)の場合、Opensshをバックポートから入れる必要がある。

[こちら](http://qiita.com/harukasan/items/0784e1e45083d1e0a602)の記事にあるように、使われているAuthorizedKeysCommandがOpenSSH 6.2以降からになるためです。wheezyは通常だとOpenssh6.0が入ります。

## nscdが起動しない

エラーで起動しませんでしたが、キャッシュならとりあえずはいらないかなと思ったのと、なくても動くので、詳しくは調べていません。

# その他

他にも、STNSでsudoパスワードの管理を行うことができます。こちらはまた別途書こうと思います。

また、参考の記事のように、WebAPIのインターフェイスを満たせば、独自のバックエンドを作ることもできるようなので、自分たちのシステムでユーザと公開鍵などを扱っていれば、連携も行いやすいかなと思います。

# 参考等

- [STNS公式](http://stns.jp/)
- [STNSのDebian jessie検証環境](https://github.com/reiki4040/STNS_sample)
- [OpenSSH 6.2を使って公開鍵認証もLDAPで行いたい](http://qiita.com/harukasan/items/0784e1e45083d1e0a602)
- [STNSのバックエンドをつくろう](http://qiita.com/sawanoboly/items/d8b017760d8b51d7ded4)
【Python】BeautifulSoupを使ってテーブルをスクレイピング

頻繁な更新のあるテーブルやコピペがしにくいテーブルなどからの
データ収集をちょっとでも効率化できないかと思い今回は、
pythonでスクレイピングしてCSVに書き出すコードを書いてみました。


#設定した環境
MacBook Air (13-inch, Mid 2011)
プロセッサ： 1.8 GHz Intel Core i7
メモリ： 4 GB 1333 MHz DDR3
バージョン： 10.11.5
Python: 3.6.2

#準備

BeautifulSoupをインストールします。
BeautifulSoupはHTMLやXMLからデータを取得することのできるライブラリーです。

今回はpipを使ってインストールしました。

```sh
$ pip3 install beautifulsoup4
Collecting beautifulsoup4
  Downloading beautifulsoup4-4.6.0-py3-none-any.whl (86kB)
    100% |████████████████████████████████| 92kB 1.8MB/s 
Installing collected packages: beautifulsoup4
Successfully installed beautifulsoup4-4.6.0
```

他にはeasy_installやapt-get、直接コードをダウンロードしてインストールする方法などがあります。
詳しく以下の公式Documentの"Installing Beautiful Soup"を読んでいただければと思います。

https://www.crummy.com/software/BeautifulSoup/bs4/doc/


#テーブル要素をスクレイピングしてみる

beautifulsoup4がインストールできたら、
さっそくO'Reillyの新刊情報を取得してみましょう。

※書籍の情報テーブルのイメージ
![スクリーンショット 2016-08-07 10.38.23.png](https://qiita-image-store.s3.amazonaws.com/0/8222/7c18a5bd-fec8-18d7-d66a-bac83773286b.png)

**2019/03/20更新**：書き込みファイルをwithで開くようにしました。

```py3:scraping_table.py
import csv
from urllib.request import urlopen
from bs4 import BeautifulSoup
import ssl
ssl._create_default_https_context = ssl._create_unverified_context

# URLの指定
html = urlopen("https://www.oreilly.co.jp/ebook/")
bsObj = BeautifulSoup(html, "html.parser")

# テーブルを指定
table = bsObj.findAll("table", {"class":"tablesorter"})[0]
rows = table.findAll("tr")

with open("ebooks.csv", "w", encoding='utf-8') as file:
    writer = csv.writer(file)
    for row in rows:
        csvRow = []
        for cell in row.findAll(['td', 'th']):
            csvRow.append(cell.get_text())
        writer.writerow(csvRow)
```


書き出されたCSVはこんな感じになります。
定期的に実行すれば新刊情報を逃すことはありませんね！
ちなみに上のコードではget_text()で指定したので"カートに追加"の列の画像リンクは空になっています。

```
ISBN,Title,価格,発行月,カートに追加
978-4-87311-755-3,パフォーマンス向上のためのデザイン設計,"2,073",2016/06,
978-4-87311-700-3,データ分析によるネットワークセキュリティ,"3,110",2016/06,
978-4-87311-754-6,UX戦略,"2,592",2016/05,
978-4-87311-768-3,Pythonからはじめる数学入門,"2,419",2016/05,
978-4-87311-767-6,あなたの知らないところでソフトウェアは何をしているのか？,"2,246",2016/05,
978-4-87311-763-8,発酵の技法,"3,110",2016/04,
978-4-87311-765-2,初めてのAnsible,"2,764",2016/04,
978-4-87311-764-5,カンバン仕事術,"3,110",2016/03,
```

#他のサイトに応用する方法
基本的にはコードの以下の部分を修正することで他のサイトのテーブルも簡単に取得できます。

1. 取得したいテーブルのclass名を変更する
2. サイト内に同じclass名のテーブルが複数ある場合は、何番目かを[ ]の中の番号で指定する

```py3
#テーブルを指定
table = bsObj.findAll("table",{"class":"tablesorter"})[0]
rows = table.findAll("tr")
```

#CSVについて

自分はMacを使っているので、書き出されたCSVはutf-8でした。
そのままExcelで読み込むと文字化けするので、文字コードを変換して、整形すると使いやすいです。
変換の方法を知りたい方は[こちら](http://help.peatix.com/customer/portal/articles/530797-%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89%E3%81%97%E3%81%9F%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E6%96%87%E5%AD%97%E5%8C%96%E3%81%91%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6-for-mac)からどうぞ（別サイト）