OmniAICreator/Qiita-1.07M huggingface dataset:
情報量の多い歴史を積み重ねるための実践的なコミット作法

## はじめに

Git などのバージョン管理システムはソフトウェア開発に不可欠になりました。

バージョン管理は単なるバックアップや共同編集のためのだけのツールではありません。
ある意味、貴重な設計ドキュメントです。積み重ねたコミットは後からそのソフトウェアを読み解く人(未来の自分も含む)にとって非常に貴重な情報源になります。歴史には、最新のスナップショットだけを見てもわからないたくさんの情報が詰まっているのです。

また、歴史は一直線に進むわけではありません。ブランチや、不具合を起こしたコミットの取り消し、脆弱性修正のバックポートなど様々なことが起こります。

この記事では、将来の誰か(自分含む)のために、またさまざまな操作のために、私が普段コミットするときに気をつけていることを整理してみます。

なお、特定のバージョン管理システムの話はしていないつもりですが、どうしても Git を前提にしてしまっているかもしれません。


## コミットログをちゃんと書く

まあ、みんなわかってますよね。よく語られている話題なので簡単に。

- **まとめ** を書く。コードの詳細を読まなくても何のコミットかわかるように。
- **What より Why**。 コードを見てわかることより、コードを見てもわからない、変更の理由のほうが大事。

というのを意識しつつ、「後で見てもなんでこんな変更してるのかわからないだろうな」と思うなら詳細に書けばよいし、自明なら簡潔に、でよいと思います。

参考: [Gitのコミットメッセージの書き方](http://postd.cc/how-to-write-a-git-commit-message/)

また、そのリポジトリのローカルルールや慣習は確認しておきましょう。

- 必ず英語で書く
- バグトラッキングシステムのチケット番号を入れる

など。

## ひとつのコミットに複数の内容を混ぜない

論理的に違う内容をひとつのコミットに **混ぜない**。
これは typo の修正など、**些細なものでも同じ** です。機能追加と typo 修正は混ぜてはいけない。

typo に気がついたときに直すのはよいこと ([ボーイスカウトルール](https://xn--97-273ae6a4irb6e2hsoiozc2g4b8082p.com/%E3%82%A8%E3%83%83%E3%82%BB%E3%82%A4/%E3%83%9C%E3%83%BC%E3%82%A4%E3%82%B9%E3%82%AB%E3%82%A6%E3%83%88-%E3%83%AB%E3%83%BC%E3%83%AB/)) だと思いますが、コミットは分けましょう。その変更が間違っていたら後から revert (取り消し) するかもしれません。一緒に typo 修正したのまで一緒に取り消されてしまいます。

空行やスペースの追加・削除など、(特にエディタの設定によっては)いつのまにか入ってしまうこともあるでしょう。こういうのも混ぜないようにしましょう。余計な変更が入っていると、後からその変更を revert したり別のブランチに取り込んだりする際にコンフリクトしやすくなります。

コミット (や push) の前に **diff を確認する習慣**をつけるとよいです。

## 機械的な変更は独立したコミットにする

ファイル名変更、クラス名変更といった、機械的に処理できる (でも変更量は大量になりがちな) 変更と、ややこしいロジックの変更は別コミットにするといいでしょう。後者の重要な変更内容が、前者の大量の変更に埋もれてしまうのを防ぎます。

コードレビューもしやすいです。


## なんとなくコメントアウトしない

変更前のコードをコメントアウトして残したりしていませんか ?
それはバージョン管理システムの仕事です。いつでも古いコードは参照できるのだから、不要なものはばっさり削除しましょう。もし残しておく何らかの意味があるのなら、理由をコメントしておきましょう。

これ、変更の内容に自信がない人がやりがちです。コードレビューしてもらうなど、別の方法で確信を深めるとよいでしょう。

## ソースコードに変更履歴を書かない

こういうやつです。

```
// 2018/02/03 〇〇を変更 (yamada)
// 2017/12/24 △△を追加 (tanaka)
```

20世紀にはよく見かけました。さすがにもういないですかね…。
これもバージョン管理システムの仕事です。


## 外部からファイルを取り込むときは変更ゼロでまずコミットする

外部ライブラリのとあるファイルだけ利用するとか、外部ベンダーや他チームからリリースされたファイルを取り込むなど、自分が作ったのではないファイルをリポジトリに取り込むことがあります。

このとき以下のようにしましょう。

- まず **一切の変更をせずに** コミットしましょう。変更が必要なら別コミットで。いきなり自分の変更を加えてしまっては、あとから何を変更したのかわからなくなってしまいます。
- どこから取り込んだのか、**トラッキングできる情報** をコミットログに含めましょう。ソフトウェア名、バージョン、URL、commitid など。

習慣になってしまえば簡単なことですが、意外にできていない人を見かけます。

同様に、ツールで生成したファイルをコミットする際や、リポジトリの統合・引っ越しなどのときにも上記の習慣は有益です。
また、何らかの理由でバイナリファイル(ビルド成果物)をリポジトリに入れる場合にも、元となったソースコードとそのバージョンは何か、など来歴がわかる情報をコミットログに入れましょう。  


## ライセンスが異なるファイルは分離する

外部からのファイルを取り込む際にはライセンスに注意して、ライセンスの異なるファイルはできるだけ別リポジトリ・別ディレクトリに分離するようにしましょう。

ライセンスが異なるファイルが混在する状況は危険です。知らぬ間にライセンス違反を犯すリスクが高まりますし、利用者にも管理の負担を強いることになります。

\# (コミット作法というよりソフトウェアの構成管理に関する話題ですかね)

## 「本家」があるときは変更を最小限にする

どこか「本家」の開発元があって、それを変更して利用している場合。
「本家」の最新版をマージする際にコンフリクトが発生しにくいように工夫しましょう。

- 変更は別ファイルにして、その言語の include 機能で取り込むなどする
- 行は変更をできるだけ避ける。行の追加で対応する。
- ファイル・行は削除しない

など。いつもとは変更方法も変わってきます。

こういう小手先が通用しないぐらい変更するなら、 Pull Request を出して「本家」に取り込んでもらったほうがよいですね。

# まとめ

自分が習慣にしているコミット作法を整理してみました。

ソフトウェアはちゃんと動くことが一番重要です。最新のスナップショットが正しければいいのですから、コミット作法は直接的にはそれには寄与しません。
でも、長い目で見れば、よいコミットは確実にチームの生産性や情報伝達を改善に寄与します。未来への投資だと思って誠実に少しずつ歴史を積み重ねましょう。
Google Cloud Storage Sql が素晴らしすぎる

# GCPを使おう

とにかくめちゃくちゃ速いらしい。
管理はGoogleがやってくれて安心。

・MYSQL
・PostgreSQL

の２つを選択可能。

# 速度はどうなの？

まず、レイテンシー（サーバー同士の反応速度）を計測してみよう。
conoha 、 gcp 共に東京リージョンを選択。

conoha から gcp へ

```

curl -kL ‘35.99.127.199’ -o /dev/null -w “%{http_code}\t%{time_total}” 2> /dev/null


```

GCPへ 0.125秒
同じCONOHA同士へ 0.126秒
2回目以降は 0.01～0.06とほぼおなじレイテンシー。

**レイテンシーは気にしなくても良いレベル**



# sqlはどっちが速いの？


約80万行レコードのテーブルで
インデックスを貼っていない ip 列で。ソート。

```

SELECT 
  SQL_NO_CACHE * 
FROM 
  mes 
ORDER BY 
  `ip` DESC 
LIMIT 
  5;

```

## conoha 8GB (自作mariaDB 10.2)

1673 ms


## GCP 3GBプラン デフォルト

計測していないけど、遅い。

## GCP 7.5GBプラン

1243 ms

## GCP 15GBプラン

589 ms


**結局世の中、金。**




# 早速使う

場所は東京なので asix-northeast1 を選択

データベースのフラグ

character_set_server
utf8mb4

default_time_zone	
+09:00

# コマンドラインから使う

mysqlデータをエクスポートする場合は、cmder というアプリでmysqlのパスを通して使うと良い。

```

mysql -h 35.129.127.121 -u root -p

```

みたいな感じで。

# バックアップ復元

ストレージを作成
nearline にしておき、そこにSQLデータをアップロード。
GUIから行う。
データベース名は ハイフンが使えないので注意。



# phpmyadmin 使えるの？

使えません。
heidisql という windows　クライアントを使おう。



# レプリカについて

フェイルオーバーする時、マスターインスタンスに接続するサービスは30秒ほどダウンタイムが発生します。
フェイルオーバーする時、リードレプリカも再作成されます。
リードレプリカが再作成されるため、リードレプリカに接続するサービスは1分ほどダウンタイムが発生します。


また、アクセス数で1台でスッ壊れるようなものだと、2台あってももう一台がスッ壊れるので、
2台構成ではなく、3台以上の構成をすること。
YMF825boardをAVRマイコンでMIDI音源化する

FM音源YMF825が載ったボードが発売されたので入手して、AVRマイコンを使いUSB－MIDIデバイスとして鳴らしてみました。

Sound Cloud　[Town.mid](https://soundcloud.com/9pjn56jr5bvj/ymf825-townmid)
###構成
以前YMF262やYM2151をUSBの複合デバイス（MIDIとHID）としてコントロールしたのですがデバイスドライバやlibusb関係のインストールなど導入が複雑だったので今回はMIDIを2chとし制御に1ch使う事でドライバ関係のインストールを不要にしています。
![無題-24bitカラー-03.jpg](https://qiita-image-store.s3.amazonaws.com/0/205783/af443c4e-a0ea-8665-7e06-4a09fe19bb6d.jpeg)

###ハードウェア
YMF825bordはアンプ内蔵、miniジャックまで付いているので手元にあったAtmega32U4のマイコンボードとYF825boardをSPIとリセット関係の接続をしたのみです。
![YMF825.jpg](https://qiita-image-store.s3.amazonaws.com/0/205783/54929f27-322b-43ac-44e0-22fa3de4df22.jpeg)


###ソフトウェア(マイコン側)
USB-MIDIのライブラリは[LUFA](http://www.fourwalledcubicle.com/LUFA.php)のDual MIDI Device Demo (Class Driver APIs)を使用しました、これはAtmelStudioへインストールしてメニューから選択すれば簡単にUSBデバイスを作れる優れもので他にもHID,CDC,Mouseなどいろんなデバイスをサポートしています。
![無題-キャプチャされた画像-02.jpg](https://qiita-image-store.s3.amazonaws.com/0/205783/e9e5c922-74b6-7b58-26c8-50061ff85550.jpeg)

MIDIクラスドライバがMIDIメッセージの解読を行ってくれるので、プログラマはMIDIメッセージに対応する処理を作成するだけなので楽にMIDIデバイスが作成できます。

```DualMIDI.c
			if ((ReceivedMIDIEvent.Event == MIDI_EVENT(0, MIDI_COMMAND_NOTE_OFF))){
				//ノートオフ
				ch = ReceivedMIDIEvent.Data1 & 0x0f;
				i = ReceivedMIDIEvent.Data2;
				note_off_func(ch,i);
	
			}
```
一部の処理（マイコンからYMF825へのSPIの送信割り込み処理、PitchBendの計算）は速度を稼ぐためアセンブリ言語で書き直しました。

####MIDIサポート
　Velocity
　Hold
　Expression
　Modulation
　PartLevel
　システムエクルシーブメッセージによる音色送信

###PC側ソフトウェア(Javaで作成したToneEditor)
以前作ったToneEditorをYMF825用に改造しました、今更swingアプリケーションです。
演奏と音色コントロールが別々のソフトウェアなので、演奏中にパラメータを触ったりして音色を変化させることが出来音色の編集が大変楽です。
![無題-キャプチャされた画像-01.jpg](https://qiita-image-store.s3.amazonaws.com/0/205783/d8c8fb6d-e3ab-3e46-888c-1bf5030ab050.jpeg)

Java Sound APIを使いYMF825boardへMIDIのシステムエクルシーブメッセージを利用してコマンドを送っています。
こちらの記事が大変参考に成りました[Java Sound でMIDI機器を操る](http://blog.bonar.jp/entry/20090322/1237711377)
4バイトのコマンドを上下4bitづつに分解してヘッダを省いた10byteのシステムエクルシーブメッセージにして送信しているので他のMIDI機器にこのデータが流れると何が起こるかは分かりません(^^;)

```Command

フォーマット 
"0xf0, COMMAND_hi, COMMAND_lo, DATA１_hi, DATA1_lo, DATA2_hi, DATA2_lo, DATA3_hi, DATA3_lo, 0xf7"


0. YMF825のリセット
1. レジスタへ書き込み DATA1=addres,DATA2=data
2.Playモード設定
  DATA1=0 mono_mode
  DATA1=1 Poly_mode
  DATA1=3 Poly_mode2: 指定チャンネルの＋８チャンネルを同時発音させます
5. EEPROM　write       DATA1番地へData2を書き込み
6. EEPROM tone read   EEPROMのDATA1番音色データを上位と下位4bitづつに分けた６２バイトのシステムエクルシーブメッセージで返す
9. write burst          音色バッファのYMF825へ全書き込み
10. write data and burst 音色バッファをDATA1番地へDATA2を書きこみ後書き込み
11. write data only      音色バッファのDATA1番地へData2を書き込み

```





###感想
YMF825はOPL系と言う事に成っていますがOPL3に比べてパラメータも増えてより~~変な~~深い音作りが楽しめます。

###ソース
GitHub
[shigosenCCneko/YMF825MIDI_CONTROL](https://github.com/shigosenCCneko/YMF825MIDI_CONTROL)
GitHubのライセンスを変更する

GitHubのライセンスの変更手順
今回は、Apache-2.0をMITに変更する

![license1.png](https://qiita-image-store.s3.amazonaws.com/0/118567/8f044b41-fcb2-ddf1-f4be-272bde531712.png)

# Create new file

![license2.png](https://qiita-image-store.s3.amazonaws.com/0/118567/b489d4bc-f85d-fedf-d9f3-5299f0bbb208.png)

# LICENSEと入力する

![license3.png](https://qiita-image-store.s3.amazonaws.com/0/118567/6f0a5a89-cc07-ad6f-b105-ab4475a18201.png)

# Choose a license templateが出現

![license4.png](https://qiita-image-store.s3.amazonaws.com/0/118567/0fe42e78-263a-93c9-c03f-aa1d01d1cab7.png)

# ライセンスの選択と必要情報を記入
Review and submitを押す

<img width="1490" alt="スクリーンショット 2018-02-03 18.33.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/118567/4ac7534c-b178-0376-1e22-bea17a8f5df9.png">

# ライセンステンプレートが生成される
コミットする
<img width="1161" alt="スクリーンショット 2018-02-03 18.33.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/118567/6d220900-2878-5e3f-4ab8-24da57bd8d18.png">

# MITに変わった！
<img width="1157" alt="スクリーンショット 2018-02-03 18.34.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/118567/4ffd8a6d-f9f7-b8aa-67a0-417233ba53f8.png">

# おわり
ライセンスがないレポジトリに新たに追加する場合も同じ手順で可能
https://github.com/bassaer/license-update
Flutter /WSL

ひとつの実装で Android iOS 両方向けのアプリがつくれるという夢のプロジェクトのひとつ、Flutter です。マイナーな Dartlang を使うとはいえこういう選択肢が現実的になっていくといいなあという想いがあります。

いつものように、公式 Get started に従って進めます。
https://flutter.io/setup/
まず最初に Operating system を選択させられます。WSL 上にいる身としては一瞬かたまりますが、落ち着いて Linux を選択して進みます。

```sh
$ git clone -b dev https://github.com/flutter/flutter.git
$ export PATH=`pwd`/flutter/bin:$PATH
```

ふむふむ。git repo に build が置かれているようですね。

```sh
$ flutter doctor
```

doctor ってやるのは brew とかの文化なんですかね。Dart sdk を download しはじめるので、しばらく待ちます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/210165/79077411-e434-162f-4c47-c5e85396f528.png)

まじか...

わたしの環境は以前に Windows Insider に切り替えている (slow ring ですが) ので、安定環境ではこうはならないのかもしれません。また今度試してみようと思いますが今日はまさかのここまで。
[zsh]bash→zshをmacでやってみた

久しぶりですね。
開発環境を便利にしたいと思いbash→zshをやってみました。

基本的には、[初心者向け：Zshの導入](https://qiita.com/iwaseasahi/items/a2b00b65ebd06785b443)を見ながらやればスムーズに出来ました。

まとめるとこんな感じ。
(Homebrewは入っている前提で話を進めます。)

# インストール〜起動

Homebrewでzshをインストール

```
$ brew install zsh
```


/etc/shellsに下記を追加

```sh:/etc/shells
/usr/local/bin/zsh
```

ログインシェルを変更

```
$ chsh -s /usr/local/bin/zsh
```

# 環境設定

## oh-my-zshをインストール

```
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"
```

## oh-my-zshのプラグインをインストール

- シンタックスハイライト: zsh-syntax-highlightingをgit clone

```
$ git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
```

- コマンド補完: zsh-completions をgit clone

```
$ git clone https://github.com/zsh-users/zsh-completions ~/.oh-my-zsh/custom/plugins/zsh-completions
```



```sh:~/.zshrc
#10行目ぐらいにあるものを変更
#テーマはhttps://github.com/robbyrussell/oh-my-zsh/wiki/themesからお好きなものをお選びください
ZSH_THEME="candy"

#pluginsにzsh-syntax-highlighting、zsh-completionsを追加(54行目ぐらい)
plugins=(
  git
  zsh-syntax-highlighting
  zsh-completions
)

# zsh-completionsのリロード設定を適当な位置に追加
autoload -U compinit && compinit -u
```

これで

```
$ source ~/.zshrc
```

すると基本的には環境設定は完了です。

# bash_profileをzprofileに変更

絶対変なところあるだろうなと思いながら色々触ってると、pyenvがうまく動いていないことが判明。
bash_profileは読み込んでもらえなくなるみたいですね。

```
% cat .bash_profile >> .zprofile
```

として、zprofileに同じ内容を追記しておきましょう。
これで基本的にはうまくいくはず。

また何か問題が出てきたら追記します。
【R】dplyr mutateの中で複数列名を選択して合計する


# 選んだ列の行だけを足したい

たくさん列があって、バラバラに位置している変数たちの値を合計したいとき

例えば↓の表のうち、<b>aa</b>,<b>vv</b>,<b>ew</b>,<b>ss</b>,の列だけを合計した変数を作りたいとします

![image.png](https://qiita-image-store.s3.amazonaws.com/0/143058/3d37c04e-b959-16f0-3deb-02b8775ef53a.png)


# 解決策

```sample.R


library(dplyr)

df <-  data.frame(ID = c("AA","BB","CC"),
                  a1 = c(NA,2,3),
                  aa = c(1,NA,6),
                  cc = c(NA,2,2),
                  d4 = c(NA,6,NA),
                  vv = c(NA,2,9),
                  dd = c(NA,2,2),
                  ew = c(3,2,NA),
                  ss = c(NA,5,3),
                  kk = c(6,NA,NA)
                  )

  # 合計したい変数名をベクトルで用意する
namelist <- c("aa","vv","ew","ss")

  # one_ofで選択して行を足す
df_added <- df %>% 
  mutate(sum_row = select(., one_of(namelist)) %>% 
                   rowSums(na.rm = T))

# > df_added
# ID a1 aa cc d4 vv dd ew ss kk sum_row
# 1 AA NA  1 NA NA NA NA  3 NA  6       4
# 2 BB  2 NA  2  6  2  2  2  5 NA       9
# 3 CC  3  6  2 NA  9  2 NA  3 NA      18

```

このくらいの列数だとあまり大変ではないですが、
合計したい列数が多いときは,`select(., one_of())`から`rowSums`につなげる書き方は便利かなと思いました

詰まった時の助けになれば幸いです
もっと良い方法があれば、是非ご教示ください！

# 参考
Macでupdatedbコマンドを実行する。

以前locateコマンドの設定は行ったのだが、検索結果を見てみると情報が古かったので``updatedb``を実行して最新の状態にすることにした。

しかし、うまくいかない。

```
$ sudo updatedb
Password:
sudo: updatedb: command not found
```

どうやらMacでは``/usr/libexec/locate.updatedb``を使う模様。ちなみにsudoコマンドで実行しないとパーミッションでエラーになる。

```
$ /usr/libexec/locate.updatedb
/usr/libexec/locate.updatedb: line 97: /var/db/locate.database: Permission denied

$ sudo /usr/libexec/locate.updatedb
Password:
```

SUCCESS! などの表示がないので不安だが、locateコマンドを実行すると確かに最新の状態になっていた。

これでよし。
HTTPCookieStorageによるCookieの操作

#概要
HTTPCookieStorageを用いたCookieの追加・削除等の操作をまとめました。

```swift:HTTPCookieStorageによるCookieの操作
class CookieManager {
    // HTTPURLResponseから特定のCookieを探し、HTTPCookieStorageに保存する
    func loadCookie(name: String, response: HTTPURLResponse) {
        if let fields = response.allHeaderFields as? [String: String], let url = response.url {
            for cookie in HTTPCookie.cookies(withResponseHeaderFields: fields, for: url) {
                if (cookie.name == name) {
                    HTTPCookieStorage.shared.setCookie(cookie)
                }
            }
        }
    }
    
    // Url, Key, ValueからCookie文字列を生成し、HTTPCookieStrageに保存する
    func setCookie(url: URL, key: String, value: String) {
        let cookieStr = key + "=" + value + ";Secure"
        let cookieHeaderField = ["Set-Cookie": cookieStr]
        let cookies = HTTPCookie.cookies(withResponseHeaderFields: cookieHeaderField, for: url)
        
        HTTPCookieStorage.shared.setCookies(cookies, for: url, mainDocumentURL: url)
    }

    // HTTPCookieStorageから特定のCookieを取得する
    func getCookie(name: String, url: URL) -> String? {
        if let cookies = HTTPCookieStorage.shared.cookies(for: url) {
            for cookie in cookies {
                if (cookie.name == name) {
                    return cookie.value
                }
            }
        }

        return nil
    }
    
    // HTTPCookieStorageに特定のCookieが保存されているかを調べる
    func isCookieSet(name: String, url: URL) -> Bool {
        if let cookies = HTTPCookieStorage.shared.cookies(for: url) {
            for cookie in cookies {
                if (cookie.name == name) {
                    return true
                }
            }
        }
        
        return false
    }
    
    // HTTPCookieStorageから特定のCookieを削除する
    func removeCookie(name: String, url: URL) {
        if let cookies = HTTPCookieStorage.shared.cookies(for: url) {
            for cookie in cookies {
                if (cookie.name == name) {
                    HTTPCookieStorage.shared.deleteCookie(cookie)
                }
            }
        }
    }
}
```
MeCabの出力フォーマットを指定する方法

[MeCab](http://taku910.github.io/mecab/)の出力フォーマットを指定する方法についてまとめます。

# 出力フォーマット指定方法 (正攻法)
##オプション
|オプション|指定するもの|
|:--:|:--:|
|`-F`, `--node-format`|通常の形態素の出力フォーマット|
|`-U`, `--unk-format`|未知語形態素の出力フォーマット|
|`-B`, `--bos-format`|Headerの出力フォーマット|
|`-E`, `--eos-format`|Footerの出力フォーマット|

##オプションに与える文字列
[MeCab: Yet Another Japanese Dependency Structure Analyzer](http://taku910.github.io/mecab/format.html)をご覧ください。
なお、`%f[N]`の指定方法については[MeCab辞書について | Yuta Hayashibe](https://hayashibe.jp/tr/mecab/dictionary/)を参考にすると良いかと思います。

##例
```bash:例
$ echo "本日は晴天なり。" | mecab -F "%m\n"
本日
は
晴天
なり
。
EOS
```

# 出力フォーマット指定方法 (バッドノウハウ)
IPAdicの場合、上記の方法で出力フォーマットの変更が可能です。
しかし、それ以外の辞書 (`-d {辞書のパス}`オプションで指定) の場合、上記の通りにオプションを指定しても、__出力フォーマットは変更されない__かと思います。
これはMeCabのバグに起因するものであり、__`-O ""`をオプションとして付与する__というバッドノウハウを用いることで解消されます。

```bash:例
$ echo "本日は晴天なり。" | mecab -d /var/lib/mecab/dic/unidic -O "" -F "%m\n"
本日
は
晴天
なり
。
EOS
```

なお、この方法はMeCabのPythonバインディングの1つである[natto-py](https://github.com/buruzaemon/natto-py)においても用いることが可能です ([natto-py 0.9.0](https://github.com/buruzaemon/natto-py/releases/tag/0.9.0)以降のみ)。

#関連リンク
* [Fix handling of `node-format` when `output-format-type` is set by polm · Pull Request #38 · taku910/mecab](https://github.com/taku910/mecab/pull/38)  
MeCabのバグを修正する (と考えられる) Pull Request
* [Ubuntu 18.04 LTSのPythonでMeCabを動かす方法 - Qiita](https://qiita.com/SUZUKI_Masaya/items/685000d569452585210c)

#参考文献
* [[小ネタ] mecab + unidic で出力フォーマットを整形する方法 – NaviPlus Engineers' Blog](http://tech.naviplus.co.jp/2014/05/14/%E5%B0%8F%E3%83%8D%E3%82%BF-mecab-unidic-%E3%81%A7%E5%87%BA%E5%8A%9B%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88%E3%82%92%E6%95%B4%E5%BD%A2%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/)
ESP32+MicroPythonで温湿度センサAM2320を扱う

結論から言うと，dhtモジュールでDHT22の1-Wireモードとして扱えば読み取れます．

### 接続方法

AM2320|ESP32
:--|:--
1: VDD|3V3
2: SDA|任意のIOピン+プルアップ(3V3と～10kΩ抵抗で接続)
3: GND|GND
4: SCL|GND

![esp32_am2320.jpg](https://qiita-image-store.s3.amazonaws.com/0/1045/aadcc6b7-09b0-c136-c765-65c322c37ae3.jpeg)

### 読み取り

```
>>> import machine,dht
>>> d = dht.DHT22(machine.Pin(21))
>>> d.measure()
>>> d.temperature()
24.7
>>> d.humidity()
52.4
```

なお，プルアップ出来ていない等で通信に失敗すると下記のようにタイムアウトエラーになります．

```
>>> d.measure()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "dht.py", line 16, in measure
OSError: [Errno 110] ETIMEDOUT
```

### 参考

- [12. Temperature and Humidity — MicroPython 1.9.3 documentation](https://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/dht.html)

AM2320の操作例を探していたところ，上記チュートリアルにAM2320のピン説明が載っていて，もしやと思って試したらあっさり読めました．I2Cでゴリゴリ書かなくて済んだ．
NanoPi NEOの起動SDカードがMacで認識できないのを修正する方法

NanoPi NEOの起動SDカードをMacにさすと認識できなくて、
「セットしたディスクは、このコンピュータで読み取れないディスクでした。」
と言われてしまいます。
rootfsのext4の部分がMacで読めないのは理解できますが、bootのパーティションはVFATなので、Macで読み書きできていいはず。

実はこれはbootのパーティションのIDが誤っているのが原因でした。
Linuxでは無視してくれるけど、Macではそれではじいているのでした。
以下のようにして修正することができます。

#パーテションの情報を見てみる

LinuxにNanoPi NEOの起動SDカードを挿します。
そのデバイスファイルが/dev/sdc とすると、fdiskのpコマンドで状態を見ることができます。

```
$ sudo fdisk /dev/sdc
[sudo] password for koba: 

Command (m for help): p

Disk /dev/sdc: 7948 MB, 7948206080 bytes
245 heads, 62 sectors/track, 1021 cylinders, total 15523840 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0e5a3eb0

   Device Boot      Start         End      Blocks   Id  System
/dev/sdc1           49152      131071       40960   83  Linux
/dev/sdc2          131072    15523839     7696384   83  Linux
```

/dev/sdc1はVFATなのに、Linuxと同じIDになっています。これが誤り。


#パーティションIDの修正

引き続きfdiskコマンドで
t
1
b
と入力し、
p
で状態を確認します。

```
Command (m for help): t
Partition number (1-4): 1
Hex code (type L to list codes): b
Changed system type of partition 1 to b (W95 FAT32)

Command (m for help): p

Disk /dev/sdc: 7948 MB, 7948206080 bytes
245 heads, 62 sectors/track, 1021 cylinders, total 15523840 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0e5a3eb0

   Device Boot      Start         End      Blocks   Id  System
/dev/sdc1           49152      131071       40960    b  W95 FAT32
/dev/sdc2          131072    15523839     7696384   83  Linux
```

この状態を書き込むには w を入力します。

```
Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)

WARNING: If you have created or modified any DOS 6.x
partitions, please see the fdisk manual page for additional
information.
Syncing disks.
```

書き込みの後fdiskコマンドが終了します。

このSDカードをMacに挿すと、今度はbootパーティションの読み書きができるようになります。
【Python】標準入出力とログファイルへのログ作成方法の試行錯誤メモ

PythonにはJavaでいうlog4JやC#でいうlog4netみたいな有名なログ管理方法がないようなので、
仕方なく自分で調べつつ、試行錯誤してみたときのメモとなります。
いい方法があれば情報共有して頂けますと有り難いです。

「Python ログ」あたりでGoogleで検索すると下記のサイトが出ると思うのですが、
そちらのサイトで勉強しつつ、ログファイル出力する方法や設定値をiniファイルへ持たせるようにしています。

「ログ出力のための print と import logging はやめてほしい - Qiita」
https://qiita.com/amedama/items/b856b2f30c2f38665701
https://qiita.com/amedama/items/b856b2f30c2f38665701#%E9%95%B7%E3%81%8F%E3%81%AA%E3%81%A3%E3%81%9F

一応Python2,3、WindowsとLinuxでの動作確認はしています。
happy coding!


``` main.py
import configparser
# 必要に応じてエラーレベルは設定してあげて下さい
from logging import getLogger, StreamHandler, Formatter,FileHandler, DEBUG, WARNING


def make_logger(logDirectory, error_level):
    u""" ログ設定を行う"""
    logger = getLogger(__name__)
    logger.setLevel(error_level)
    # フォーマッタを生成する
    fmt = Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    # 標準出力用ハンドラーを生成する
    stdHandler = StreamHandler()
    stdHandler.setLevel(error_level)
    # ハンドラーにフォーマッターを設定する
    stdHandler.setFormatter(fmt)
    logger.addHandler(stdHandler)

    # ファイル出力ハンドラーを生成する
    # 現在日付
    todayYYYYMMDD = date.today().strftime("%Y%m%d")
    fileHandler = FileHandler(logDirectory.replace(os.path.sep, '/') + '/' + todayYYYYMMDD + '.log')
    fileHandler.setFormatter(fmt)
    # ロガーにハンドラーを設定する
    logger.addHandler(fileHandler)
    return logger


if __name__ == '__main__':
    # 設定ファイルより各種設定を読み込む
    ini_file = configparser.ConfigParser()
    # 実行するpythonファイルと同名のinifileを読み込む
    ini_file.read(args[0].replace('.py', ".ini"), encoding='utf-8')
    # ログ設定
    logger = make_logger(ini_file.get('logger', 'logDirectory'), ini_file.get('logger', 'error_level'))
    # ログ出力を行う
    logger.info('info')
    logger.warn('warn')

```

``` main.ini
[logger]
logDirectory = C:\Dev\Log
error_level = WARNING

```
WEB技術リンクまとめ

#WebAPI
[ASP.NET Web API 入門](http://www.atmarkit.co.jp/ait/articles/1307/30/news077.html)
WebAPIの基本的な使い方について。

#自己ホスト
[WebAPIの自己ホスト](http://blog.okazuki.jp/entry/20130429/1367249433)
WebAPIを自己ホストする方法について。

#アップロードファイル受け取り
[MediaTypeFormatterの作成](http://gooner.hateblo.jp/entry/2014/04/29/mediatypeformatter/)
Raspberry Pi から GoogleHome を喋らせる & 音声ファイル再生（google-home-notifier）

# Raspberry Pi から GoogleHome を喋らせる & 音声ファイル再生（google-home-notifier）
google-home-notifier を利用して、Raspberry Pi から指定の文字列や音声ファイルをGoogleHomeで再生します。
[google-home-notifier](https://github.com/noelportugal/google-home-notifier)

## 準備
必要なパッケージをインストールします。
Node.jsは導入されているので省略します。

~~~
$ sudo apt-get install git-core libnss-mdns libavahi-compat-libdnssd-dev
~~~

## google-home-notifier の入手
google-home-notifierをgit から clone します。

~~~
$ git clone https://github.com/noelportugal/google-home-notifier
~~~

## google-home-notifier のインストール
google-home-notifier をインストールします。

~~~
$ cd google-home-notifier
$ npm install
~~~

## 喋らせる
インストールディレクトリ内の「example.js」を参考に 以下のスクリプトを作成し、Google Home を喋らせます。
「ip」に GoogleHome のIPアドレスを入力します。
「googlehome.notify」の引数に喋らせたい文言を設定します。

~~~notify.js
const googlehome = require('./google-home-notifier')
const language = 'ja';

var deviceName = 'GoogleHome';
var ip = '<GoogleHomeのIPアドレス>';

googlehome.ip(ip, language);
googlehome.device(deviceName, language); 

googlehome.notify('こんにちわ。私はGoogleHomeです。', function(notifyRes) {
	  console.log(notifyRes);
});
~~~

~~~
$ node notify.js
~~~


## 仕組み
Google Text To Speech で文字列を音声化して、GoogleHomeで再生しているようです。

### Google Text To Speech
Google翻訳で確認できます。文字列を入力してスピーカーのアイコンを押すと音声出力されます。
https://translate.google.com/

「こんにちわ。私はGoogleHomeです。」と入力して、出力されている音声は以下でした。
MP3でした。
https://translate.google.com/translate_tts?ie=UTF-8&q=%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%82%8F%E3%80%82%E7%A7%81%E3%81%AFGoogleHome%E3%81%A7%E3%81%99%E3%80%82&tl=ja&total=1&idx=0&textlen=21&tk=972902.571097&client=t&prev=input


## 音声ファイルの再生
音声ファイルを再生しているということで、ネットワーク上のMP3ファイルを指定して再生することも可能です。


~~~play.js
const googlehome = require('./google-home-notifier')
const language = 'ja';

var deviceName = 'GoogleHome';
var ip = '<GoogleHomeのIPアドレス>';

googlehome.ip(ip, language);
googlehome.device(deviceName, language); 

googlehome.play('http://<MP3ファイルのURL>', function(notifyRes) {
  console.log(notifyRes);
});
~~~


~~~
$ node play.js
~~~

## ところで
「example.js」を実行すると以下のように表示されます。


~~~
$ node example.js

～（略）～
Endpoints:
    http://<GoogleHomeのローカルIPアドレス>:8091/google-home-notifier
    https://xxxxxx.ngrok.io/google-home-notifier
GET example:
curl -X GET https://xxxxxx.ngrok.io/google-home-notifier?text=Hello+Google+Home
POST example:
curl -X POST -d "text=Hello Google Home" https://xxxxxx.ngrok.io/google-home-notifier
~~~
ngrok を利用して間接的にGoogleHomeがインターネットに公開されているようです。
GoogleHomeを喋らせるだけであれば、グローバルにGoogleHomeを公開する必要はありません。
python: deploy abortion on heroku

##エラー内容

```
-----> Python app detected
 !     The latest version of Python 3 is python-3.6.4 (you are using python-3.6.3, which is unsupported).
 !     We recommend upgrading by specifying the latest version (python-3.6.4).
       Learn More: https://devcenter.heroku.com/articles/python-runtimes
-----> Installing requirements with latest Pipenv…
       Your Pipfile.lock (c8a67b) is out of date. Expected: (cb4136).
       Aborting deploy.
 !     Push rejected, failed to compile Python app.
 !     Push failed
```

##仮説1

バージョン管理か正常に同期できていないのではないか。ローカルサーバーとデプロイ先のデータが一致していないのでは。

##解決策

[こちら](https://github.com/pypa/pipenv/issues/884)より`pipenv update`を実行。

<img width="458" alt="Screen Shot 2018-02-03 at 12.06.45 AM.png" src="https://qiita-image-store.s3.amazonaws.com/0/87666/e148ea2d-86df-d065-8815-d2fe9049d8c3.png">

その後のコメントにも書いてある通りこれは`virtualenv`の方からファイルを取ってくるだけなので`pipenv install --ignore-pipfile`、`git add .`と`git commit -m "..."`を実行。無事にデプロイできるように。
Juliaでグラフラプラシアンを用いた合意形成を計算する

# 内容
- グラフラプラシアンの固有値をプロットした
  - <a href='https://qiita.com/taki__taki__/items/941ab27ca103b2429783' target='_blank'>Juliaでグラフラプラシアンの固有値を求めて描画する - Qiita</a>
- 例題のグラフラプラシアンに対応したグラフを参考に、最も簡単な合意形成を考えてみる


# 例題状況のグラフ
- 隣接行列 $A$ を図示すると以下の系が得られる

![graph1.png](https://qiita-image-store.s3.amazonaws.com/0/7181/523a028a-a604-0eba-f454-85f28a01465b.png)

# 概要
- ノード数が5つなので、状態変数5つをベクトル化し $x = (x_1, x_2, x_3, x_4, x_5)$ と表す
- 状態変数 $x_i$ の時間変化は、自身の値と制御器（コントローラ）の入力を関数 $f$ によって処理した結果決定されると仮定する
  - $\frac{dx_i(t)}{dt} = f_i(x_i(t), u_i(t))$
- 制御器 $u_i$ は、自分自身の状態変数値 $x_i$ と、自分の近傍の状態変数値によって決定される関数とする
  - 例えば $u_1(t) = c(x_1(t), x_4(t))$
    - 時刻 $t$ におけるノード1への制御信号は、自分の状態値 $x_1$ と $A$ で規定される近傍からの状態値 $x_4$ によって決定する
- 合意形成
  - 制御器により$\lim_{t\to\infty} x_i(t) = \alpha$となる合意値$\alpha$を達成すること
  - 例えば $\alpha=\frac{1}{N} \sum_{i} x_{0i}$ であるとき、平均値合意である

# グラフラプラシアンで表現される系
- 具体的なシステム $f, c$ について、以下の積分系を仮定する
    - $x_i(0) = x_{0i}$
    - $\frac{dx_i(t)}{dt} = u_i(t)$
    - $u_i(t) =  -\sum_{j\in\mathcal{N}i} x_i(t) - x_j(t) $ 
      - i番目のノードの近傍$N_j$中のノードjに対する状態変数値の差分が制御信号として入力される



- 行列 $A$ とグラフラプラシアンを思い出す
- 上の積分系は $\frac{dx(t)}{dt} = -Lx(t)$ という行列形式で表される。

# 計算例
- 初期値として $x(t) = (1, 3, 5, 7, 9)$ を与える
- この系が合意を達成することを確認する 
- 実行結果
    - 4.712程度の値に収束する（合意が形成される）

![ex3.png](https://qiita-image-store.s3.amazonaws.com/0/7181/a1ab1368-aeba-591f-96df-42e95f787e2a.png)


# コード
```julia
using PyPlot

# 初期値
x = [1, 3, 5, 7, 9]

# グラフラプラシアンL
A = [0 0 0 1 0;
     1 0 1 0 0;
     0 0 0 0 1;
     0 1 0 0 0;
     1 0 0 0 0]
D = diagm(squeeze(sum(A, 2), 2))
Δ = maximum(D)
L = D - A

# シミュレーション
Δt = 0.05
tf = 10
xx = []
for t in 0:Δt:tf
    push!(xx, x)
    Δx = -L*x
    x += Δx * Δt
    print(x)
end

# plot
t = 0:Δt:tf
figure(figsize=(6, 3))
plot(t, xx)
grid(true)
savefig("ex3.png", format="png", dpi=300)
```
カスタムモデルを利用したカスタムAdapterの要素の削除方法

## カスタムAdapterの要素が消えない！

カスタムモデルを使ったAdapterの要素を、adapter.remove(item)で消そうとしても消えません。

```java:ダメな例
@Override
public void onItemClick(final AdapterView<?> adapterView, View view, final int i, long l) {
            OriginalItem item = (OriginalItem) mItemAdapter.getItem(i);
            mItemAdapter.remove(item);
            list.setAdapter(mItemAdapter);
}

```
これだと削除されません。

## どうしよう！

なので、カスタムAdapterクラスに削除機能を実装します。

```java:ItemAdapter.java

//省略

public void delete(int pos){
        itemList.remove(pos);
}

//省略
```

カスタムAdapterの要素が保持されてるItemListはArrayList<>型なので、positionで削除することができます。

あとはこれを呼ぶだけです。

```java:実装例
@Override
public void onItemClick(final AdapterView<?> adapterView, View view, final int i, long l) {
            mItemAdapter.delete(i);
            list.setAdapter(mItemAdapter);
}

```
Kerasに「PILが無い」と怒られた場合の対策

KerasをPython3系で使っていて、以下のようなエラーで止まった場合が対象。

```
raise ImportError('Could not import PIL.Image. '
ImportError: Could not import PIL.Image. The use of `array_to_img` requires PIL.
```

素直にPILをインストールしようとしても、
pythonのバージョンが2.6じゃないとダメだと言われてしまう。

```
>conda install PIL
Fetching package metadata .............
Solving package specifications: .

UnsatisfiableError: The following specifications were found to be in conflict:
  - pil -> python 2.6*
  - python 3.5*
Use "conda info <package>" to see the dependencies for each package.
```

conda infoすると、PILの更新は2014年で止まっている模様。

```
pil 1.1.7 py26_0
----------------
file name   : pil-1.1.7-py26_0.tar.bz2
name        : pil
version     : 1.1.7
build string: py26_0
build number: 0
channel     : defaults
size        : 746 KB
arch        : x86_64
date        : 2014-01-01
license_family: Other
md5         : ebf2863cd37405f13d6096d1981e188d
noarch      : None
platform    : win32
url         : https://repo.continuum.io/pkgs/free/win-64/pil-1.1.7-py26_0.tar.bz
2
dependencies:
    python 2.6*
```

PILのFork版であるPillowを使いましょう。

```
Pillow is the “friendly PIL fork” by Alex Clark and Contributors. PIL is the Python Imaging Library by Fredrik Lundh and Contributors. 
```


```
>conda install Pillow
```

Pillowについてはこちらのページが参考になりました。
[PIL/Pillow チートシート](https://qiita.com/pashango2/items/145d858eff3c505c100a)
Windows Mixed Reality for SteamVR をGTX860Mで起動できなくてGTX1070を買った。WinMR

![WinMRsteamVR.jpg](https://qiita-image-store.s3.amazonaws.com/0/147524/d8bd8155-b66f-888c-191b-c8a46960cdaf.jpeg)
#自分の環境で起きた問題
Windows Mixed Reality for SteamVR が起動できない。
#結論
GPU(GTX860M)が弱すぎた。GTX1070のPCを買ったら全く問題なかった。
#経緯
2015年に購入したGTX860Mマシンでもクリフハウス入ったり、Unityで作ったシーンに入ったりできた。Qualityが低いかもしれないが動作は問題なかった。![GPUspec.jpg](https://qiita-image-store.s3.amazonaws.com/0/147524/e4de39df-4c1b-5944-ff9f-09e9b54d703c.jpeg)

WinMR専用のコンテンツは少ないので、クリフハウスで一通り遊ぶとやることがなくなる。SteamVRを使うとVRchatやゲーム等、他のヘッドセット向けに作られたコンテンツをプレイできるのでSteamVRは必須となる。そこで、SteamとWindows Mixed Reality for SteamVRをインストールするがエラーに悩まされる。
**エラー306**
![steamVR_306.jpg](https://qiita-image-store.s3.amazonaws.com/0/147524/77e3e61e-b866-2e7e-8445-00a16f17106a.jpeg)

405 コンポジターはデバイスを作成できません。　とか言ってる。
調べると、起動しているexeに管理者権限が必要らしい。トラブルシューティング→システムレポートを見るとAdmin:Noとなっている。
![steamVR_306_report.jpg](https://qiita-image-store.s3.amazonaws.com/0/147524/82105d75-05fc-5828-4272-45fff74620e5.jpeg)


vrmonitor.exeのプロパティから管理者権限をつけてやる。
![steamVR_306_admin.jpg](https://qiita-image-store.s3.amazonaws.com/0/147524/9d4585df-dda9-5497-e75e-189395b202cd.jpeg)

エラー306は止まったが、今度はエラー301が出る。
**エラー301**
![steamVR_301.jpg](https://qiita-image-store.s3.amazonaws.com/0/147524/bbc215bc-c0f0-9b34-86ec-7b09c16471f8.jpeg)

調べるとGPUの割り当てがうまく行ってないかもしれないので、NVIDIA コントロールパネルからGPUを使うように設定する。（CPU内蔵のGPUを放棄するのか、普通の動画再生はパフォーマンスが激落ちした）
![NVIDIAコントロールパネル.jpg](https://qiita-image-store.s3.amazonaws.com/0/147524/5fddd16d-34f6-fa42-e1bb-c1e39b363a7e.jpeg)

これでエラー301は解消され、SteamVRの起動ができた！
・・・しかし、しばらくの暗黒空間の後に「初期化に失敗しました」とのこと。SteamVRの必要スペックを見ると、推奨はGTX1070で、満たさないとQualityは落ちるが動かない訳じゃないよ的なことが書いてあるので、ここで心を折らずに有識者に聞いてみる。
![WinMRsteamVR2.jpg](https://qiita-image-store.s3.amazonaws.com/0/147524/4d0af295-0e08-2753-374d-09cf13cfba6d.jpeg)

有識者に聞いてみると、「WinMRはいろいろ不安定なことあるから、スペック高いPC買った方が早いよ。」と言われ、それに従ってGTX1070のPCを買った。すると全く問題なくSteamVR起動できた。それどころか、クリフハウスにコントローラの影が出るなど快適だった。無駄に時間使ったので、そんな人が減ることを祈ってQiitaの記事を書く。


ちなみに、SteamVR Performance Test というのがあり、GTX1070マシンで試した結果は最強だった。
![SteamVRベンチ.jpg](https://qiita-image-store.s3.amazonaws.com/0/147524/93b28d4b-108d-5d8f-f648-ae20b2d270d9.jpeg)


GTX860Mマシンだと、そもそもGPUが認識されていない・・・:sob:
![steamVR_PerformanceTest1.jpg](https://qiita-image-store.s3.amazonaws.com/0/147524/a79b521f-39f1-190c-4882-e15bc4428503.jpeg)

GTX1070で快適にSteamVRが起動でき、下記のようなコンテンツを楽しめるようになりました^^ やった～
　・VRchat
　・Google Earth VR
　・SteamVRに投稿されている様々なシーン
　・SteamVR標準のお絵かきとか


以上です。
java.util.Date, java.sql.Date, LocalDate, ZonedDateTimeの変換方法

# 目的
Java8にLocalDateが追加されて、非常に便利ではある。しかしJDBC使用時はjava.sql.Date, POI使用時にはjava.util.Dateを使用するが、LocalDateでは相互運用は考えられていない。そこで、業務でよく使用する3つについて、ついでにZonedDateTimeも、相互運用が楽になるように変換方法をまとめた。

# 各変換方法

- java.sql.Date→LocalDate

```java:sqlDateとutilDateとLocalDate.java
public LocalDate convertToLocalDate(java.sql.Date sqlDate){
	return sqlDate.toLocalDate();
}
```

- java.sql.Date→java.util.Date

```java:sqlDateとutilDateとLocalDate.java
public java.util.Date convertToUtilDate(java.sql.Date sqlDate){
	return sqlDate;
}
```

- java.util.Date→LocalDate

```java:sqlDateとutilDateとLocalDate.java
public LocalDate convertToLocalDate(java.util.Date utilDate){
	return utilDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}
```

- java.util.Date→java.sql.Date

```java:sqlDateとutilDateとLocalDate.java
public java.sql.Date convertToSqlDate(java.util.Date utilDate){
	return new java.sql.Date(utilDate.getTime());
}
```

- LocalDate→java.util.Date

```java:sqlDateとutilDateとLocalDate.java
public java.util.Date convertToUtilDate(LocalDate localDate){
	 return java.util.Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
}
```

- LocalDate→java.sql.Date

```java:sqlDateとutilDateとLocalDate.java
public java.sql.Date convertToSqlDate(LocalDate localDate){
	return java.sql.Date.valueOf(localDate);
}
```

- java.util.Date→ZonedDateTime

```java:sqlDateとutilDateとLocalDate.java
public ZonedDateTime convertToZonedDateTime(java.util.Date utilDate){
	return utilDate.toInstant().atZone(ZoneId.systemDefault());
}

```

- java.sql.Date→ZonedDateTime

```java:sqlDateとutilDateとLocalDate.java
public ZonedDateTime convertToZonedDateTime(java.sql.Date sqlDate){
	return sqlDate.toLocalDate().atStartOfDay(ZoneId.systemDefault());
}
```

- LocalDate→ZonedDateTime

```java:sqlDateとutilDateとLocalDate.java
public ZonedDateTime convertToZonedDateTime(LocalDate localDate){
	return localDate.atStartOfDay(ZoneId.systemDefault());
}
```

- ZonedDateTime→java.util.Date

```java:sqlDateとutilDateとLocalDate.java
public java.util.Date convertToUtilDate(ZonedDateTime zonedDateTime){
	return java.util.Date.from(zonedDateTime.toInstant());
}
```

- ZonedDateTime→java.sql.Date

```java:sqlDateとutilDateとLocalDate.java
public java.sql.Date convertToSqlDate(ZonedDateTime zonedDateTime){
	return java.sql.Date.valueOf(zonedDateTime.toLocalDate());
}
```

- ZonedDateTime→LocalDate

```java:sqlDateとutilDateとLocalDate.java
public LocalDate convertToLocalDate(ZonedDateTime zonedDateTime){
	return zonedDateTime.toLocalDate();
}
```

# まとめ
java.util.Date, java.sql.Date,LocalDate,ZonedDateTimeの変換方法をまとめた。ソースは、テストも含めて[こちら](https://github.com/xaatw0/quiita/blob/master/src/sqlDateとutilDateとLocalDate.java)にあります。
SQL_4大命令_基礎

最近勉強したクエリのメモ(・∀・)
この4つが分かれば簡単な調査とか更新が可能！

# SQL　4大命令

・ select（検索）
・ update（変更）
・ delete（削除）
・ insert（追加）

※このメモには書いてないが、update / delete / insert　を実際に更新する際は、トランザクションをつけたほうが良い。

## 使用例 select

■ 全てのカラムを抽出

```sql
select * from テーブル名
```

■ 抽出するカラムを指定

```sql
select カラムA, カラムB from テーブル名
```

■ 抽出する条件を指定

```sql
select * from テーブル名
where カラムC = '日本食'
```

■ 抽出する条件を複数指定

```sql
select * from テーブル名
where カラムC = '日本食' and カラムE >= '2018-02-05'
```

■ 抽出する条件を〜から〜までを指定

```sql
select * from テーブル名
where カラムE between '2018-02-05' and '2018-02-08'
```

■ 抽出する条件を()内のどれかに一致する場合の指定

```sql
select * from テーブル名
where カラムC in ('日本食', '洋食') 
```

■ 抽出する条件を()内のどれにも一致するしない場合の指定

```sql
select * from テーブル名
where カラムC not in ('日本食', '洋食') 
```

■抽出する条件を曖昧に指定　(後方一致var)

```sql
select * from テーブル名 
where カラムC like '%食' 
```

■抽出する条件を曖昧に指定　(前方一致var)

```sql
select * from テーブル名 
where カラムC like '日本%' 
```

■抽出する条件を曖昧に指定　(前方後方一致var)

```sql
select * from テーブル名 
where カラムC like '%本%' 
```

■ 抽出する条件をNULLに指定(nullの抽出は特殊)

```sql
select * from テーブル名
where カラムB is null
```

■ 抽出する条件をNULLじゃないデータを指定(nullの抽出は特殊)

```sql
select * from テーブル名
where カラムB is not null
```

## 使用例 update 

■ 全てのカラムAを更新

```sql
update テーブル名
set カラムA = カラムA + 000
```

■ 更新する条件を指定して更新

```sql
update テーブル名
set カラムA = カラムA + 000
where カラムB = A01
```

## 使用例 delete

■テーブル内全てのデータを削除

```sql
delete from テーブル名
```

■削除する条件を指定

```sql
delete from テーブル名
where カラムC = '日本食'
```

## 使用例 insert

■追加するカラムを指定(2行目で指定したカラム順に、3行目データを入れる)

```sql
insert into テーブル名
(ID, code, category)
values (12345, A05, '洋食')
```

■カラムを指定せずに追加

```sql
insert into テーブル名
values (12345, A05, '洋食','肉料理','2018-0205')
```

以上！
オフラインリアルタイムどう書く E21 の問題

@Nabetani さんが主催するオフラインでリアルタイムに「どう書く」をやるイベント( https://yhpg.doorkeeper.jp/events/69404 )で問題を出させてもらいました。

問題は「ドキドキロシアンルーレット」という名前で、詳細は
http://mtsmfm.github.io/2018/02/03/doukaku-e21.html
です。

実装ができた方はこちらのコメント欄からリンクを張っていただくと見つけやすくて助かります。
似たような問題をもっと解きたいという方は、Doorkeeper の コミュニティページ
http://yhpg.doorkeeper.jp/
に @Nabetani さんの過去問リンク集がありますので、そちらをご覧になると良いと思います。
ディレクトリ内のShift-JISをUTF-8に一括変換する

nkfが強いです。brewで入れましょう。

```terminal
$ nkf -Lu -w --overwrite *
```
ファイルを個別に指定する場合は`*`を適宜変更します

## KWSK

`nkf --help`

```
Usage:  nkf -[flags] [--] [in file] .. [out file for -O flag]
 j/s/e/w  Specify output encoding ISO-2022-JP, Shift_JIS, EUC-JP
          UTF options is -w[8[0],{16,32}[{B,L}[0]]]
 J/S/E/W  Specify input encoding ISO-2022-JP, Shift_JIS, EUC-JP
          UTF option is -W[8,[16,32][B,L]]
 m[BQSN0] MIME decode [B:base64,Q:quoted,S:strict,N:nonstrict,0:no decode]
 M[BQ]    MIME encode [B:base64 Q:quoted]
 f/F      Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl
 Z[0-4]   Default/0: Convert JISX0208 Alphabet to ASCII
          1: Kankaku to one space  2: to two spaces  3: HTML Entity
          4: JISX0208 Katakana to JISX0201 Katakana
 X,x      Convert Halfwidth Katakana to Fullwidth or preserve it
 O        Output to File (DEFAULT 'nkf.out')
 L[uwm]   Line mode u:LF w:CRLF m:CR (DEFAULT noconversion)
 --ic=<encoding>        Specify the input encoding
 --oc=<encoding>        Specify the output encoding
 --hiragana --katakana  Hiragana/Katakana Conversion
 --katakana-hiragana    Converts each other
 --{cap, url}-input     Convert hex after ':' or '%'
 --numchar-input        Convert Unicode Character Reference
 --fb-{skip, html, xml, perl, java, subchar}
                        Specify unassigned character's replacement
 --in-place[=SUF]       Overwrite original files
 --overwrite[=SUF]      Preserve timestamp of original files
 -g --guess             Guess the input code
 -v --version           Print the version
 --help/-V              Print this help / configuration
Network Kanji Filter Version 2.1.4 (2015-12-12) 
Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa).
Copyright (C) 1996-2015, The nkf Project.
```
WEBAPI経由でWindowsサーバ上に配置したBATを実行させようとしたときに想定通りの結果にならなかった話


## やりたかったこと ##

Windowsサーバ上で実行させるpythonの処理をAPI経由で呼び出したい  
※PythonじゃなくてもなんかしらのEXEでも同じようなことはできるような仕組みにはしておきたい。

## やったこと ##
C#のWEBAPIをIIS上に配置して、それ経由でBATを実行させようとした。
※BATはpythonの処理を引数指定で呼び出す程度のもの
BATにしたのは引数などの調整をする際にAPIのほうを修正するのがめんどくさそうだったから。

呼び出しとしては以下

	//プロセス起動
	System.Diagnostics.Process p = System.Diagnostics.Process.Start("BATのフルパス", id);
	p.WaitForExit();

## どうにも起動しない。 ##

**APIを呼び出しても起動しない。**

以下の順で解決していった。


### 1. BAT内でxxx.pyを呼び出していたが、どうもpyがPythonと関連づけられていなかった。 ###
Pythonと関連づけられていなかったので、python xxx.py のように記載したが、Pathも設定されていなかった。  
→Pythonについてはフルパスで設定。  
※ここまでは手動でBATを実行してもうまくいかないのでWEBAPIとかは直接関係ない単なるショボミスな話



### 2.Pythonをフルパスにしたことで上手くいくかと思ったが、処理結果が想定通りにならない。 ###
手動起動ではうまくいくのでWEBAPI経由だとうまくいかなかった。  
Process.Start()で呼び出しているが、起動されていなさそう。


結論としては  
WEBAPI経由だとIISユーザとして起動されることになるのだが、それに対する権限を付与してなかった。  
→BAT格納フォルダやログ出力フォルダに対してeveryoneのフルコントロール権限を付与。  
※正確に権限を付与するのであれば「IIS_IUSRS」にすべきなんだろうけど、とりあえずeveryoneで実施。

これで動作した。

## 結論 ##
気が付けばどうってことないが、思いつかないと結構ハマった。
Atomのphp-debug使い方備忘録

# 概要
Atom の php のデバッグパッケージ php-debug が使えなくて、やっと使えるようになったので、備忘録として投稿したいと思います。

ブレイクポイントを設定してから対象の URL にアクセスしても反応がありませんでした。 php.ini の設定も php-debug の設定も特に間違いはありませんでした。

## 解決方法
解決方法としては２つ有りました。というか、自分がただ単に使い方を知らなかっただけみたいです。

１つはパラメータに XDEBUG_SESSION_START を追加したらデバッグできるようになりました
例）localhost:8000/・・・・?XDEBUG_SESSION_START

もう１つは、chrome の Xdebug helper という拡張機能を追加する方法です。
オプションでエディタと IDEKey を設定すれば使えるようになります。
デバッグのアイコンからデバッグを起動させた状態で更新してアクセスし直せばブレイクポイントで止まるはずです。


ちなみに、php-debug で文字化けが起きる場合は、以下の方法で解決できます。

Atom のファイル→環境設定→パッケージ→php-debugの設定→View Code を開いて lib/engines/dbgp/dbgp-instance.coffee を下記の URL のように修正する
https://github.com/gwomacks/php-debug/compare/master...tiibun:multibyte-variables


以上です。
TortoiseSVNの使い方

#:boy_tone1:はじめに
TortoiseSVNを使っているのですが、いまいち使い方が分からずに毎回検索してしまうので、基本的な使い方をまとめました。

#:turtle:TortoiseSVNとは
TortoiseSVNは、Subversion (SVN)のクライアントで、Windowsのシェルエクステンションとして機能します。Subversionのコマンドを実行する必要がなく、直観的に、簡単に使えます。バージョン管理をするためのツール。
[TortoiseSVN公式ページ](https://tortoisesvn.net/downloads.html)

#:red_car:インストール方法
[TortoiseSVN公式ページ](https://tortoisesvn.net/downloads.html)から、「Downloads」タブから、ダウンロードします。

![2018-02-02_00h56_14.png](https://qiita-image-store.s3.amazonaws.com/0/214243/75b7cad3-1c67-b1e3-19fc-9bae38586df6.png)

デフォルトの設定のまま進め、インストールをします。
任意の場所で、右クリックすると、「TortoiseSVN」が表示されるようになっています。



###:flag_jp:日本語化するには
[TortoiseSVN公式ページ](https://tortoisesvn.net/downloads.html)から「Language packs」の「Japanese」をダウンロードします。

![2018-02-02_00h22_09.png](https://qiita-image-store.s3.amazonaws.com/0/214243/f8ef377e-54df-d8a6-7d14-098b33835bb0.png)


ダウンロードが終わり、PCにインストールし終わったら、TortoiseSVNの日本語設定をします。
任意の場所で右クリックし、「TortoiseSVN」→「Settings」で、「Language：」を「日本語（日本）」に変更し、「適用」をクリックすると日本語設定になります。

![2018-02-02_01h04_46.png](https://qiita-image-store.s3.amazonaws.com/0/214243/084c1cae-ad39-3ff9-2c4e-bef77651649e.png)

# :girl_tone2:基本用語
- リポジトリ :ソフトウェア開発に用いるバージョン管理システムなどで、プログラムのソースコードや、データやファイルなどを一元的に管理する格納場所のこと。
- トランク :ソースコードのバージョン管理などにおいて、現在主流となっているコードの系統のこと。
- ブランチ :ソースコードのバージョン管理などにおいて、主流の系統から枝分かれした別の系統のコード群のこと。
- タグ :バージョン管理番号とは別に、ファイルに対して特定の名前をつけること。
- チェックアウト :空のディレクトリに、リポジトリからバージョン管理下のファイルをダウンロードし、ローカルの作業コピーを作成すること。
- コミット :トランザクション処理が成功したときに、その結果を確定させること。
![2018-02-03_15h53_43.png](https://qiita-image-store.s3.amazonaws.com/0/214243/720b69af-bee7-8de7-fb28-b90ec92c8041.png)



#アイコン説明
![2018-02-03_15h11_44.png](https://qiita-image-store.s3.amazonaws.com/0/214243/f33b32f8-904b-4f50-9e41-829285c8fdef.png)通常
![2018-02-03_15h12_32.png](https://qiita-image-store.s3.amazonaws.com/0/214243/18db9319-2b28-6f11-ebb3-f3602928dad6.png)変更
![2018-02-03_15h13_14.png](https://qiita-image-store.s3.amazonaws.com/0/214243/663d2bf2-cbdb-8c73-df2a-57ecd1edde65.png)追加
![2018-02-03_15h14_32.png](https://qiita-image-store.s3.amazonaws.com/0/214243/46057d38-b12a-ad42-38b3-f082dc134aa1.png)削除
![2018-02-03_15h15_02.png](https://qiita-image-store.s3.amazonaws.com/0/214243/6ff586a2-0400-fab8-f629-5c4c3705b268.png)競合
![2018-02-03_15h15_29.png](https://qiita-image-store.s3.amazonaws.com/0/214243/b7a2bcfc-4788-5fbc-92fe-80b9fa77f719.png)ロック

「TortoiseSVN」→「設定」の「アイコンセット」から確認できます。





#:imp:初心者の方要注意
####変更を行う場合は必ず必ず右クリック「TortoiseSVN」で行う

![2018-02-08_11h12_57.png](https://qiita-image-store.s3.amazonaws.com/0/214243/309750b9-ecc1-659f-d41a-4c22d6072b84.png)



####コミットしたフォルダを削除したい場合
フォルダやファイルなどを削除するときは、必ず右クリック「TortoiseSVN」→「削除」で行う。
普通にdeleteキーなどで削除すると、「紛失」というステータスになってしまい、サーバー上にはフォルダは残っているが、ローカルにはフォルダが存在していない...！ということになってしまいます。

####コミットや更新ができない場合
とりあえず「クリーンアップ」を行ってみる！<br>
サーバーの問題などで、実行が正常に終了しなかった場合、作業コピーが矛盾した状態のままになってしまうことがあります。「TortoiseSVN」→「クリーンアップ」 をフォルダーに対して実行します。

####間違えてタグを打ってしまった場合
「TortoiseSVN」→「リポジトリブラウザー」で変更履歴を確認できます。<br>間違えて行ってしまった変更のタグの上で、右クリックをし、「削除」をクリック。
コンセントをリモコンで操作する（Raspberry Pi & irMagician & リモコンコンセント）

# コンセントをリモコンで操作する（Raspberry Pi & irMagician & リモコンコンセント）
以下の記事で、Raspberry Pi から家電を操作しました。
赤外線リモコンがあれば、Raspberry Pi から操作できます。
[Raspberry Pi と irMagician（赤外線モジュール）で家電を操作する](https://qiita.com/minatomirai21/items/7581777065f27621ee0c)

では、リモコンのない家電はどうしよう。
コンセントの抜き差しで、電源の入と切を切り替えられる家電であれば、以下の製品で操作可能です。
[電機器具専用 リモコンコンセント [品番]07-8251 | (株)オーム電機OHM](http://www.ohm-electric.co.jp/product/c23/c2313/19582/)

## 電源ONのデータ

~~~on.json
{"postscale": 100, "freq": 38, "data": [5, 39, 39, 13, 12, 13, 12, 13, 28, 13, 28, 13, 28, 13, 28, 13, 12, 13, 12, 13, 162, 39, 39, 13, 12, 13, 12, 13, 28, 13, 28, 13, 28, 13, 28, 13, 12, 13, 12, 13, 162, 39, 39, 13, 12, 13, 12, 13, 28, 13, 28, 13, 28, 13, 28, 13, 12, 13, 12, 13], "format": "raw"}
~~~

## 電源OFFのデータ

~~~off.json
{"postscale": 100, "freq": 38, "data": [1, 1, 8, 39, 39, 13, 12, 13, 28, 13, 12, 13, 12, 13, 28, 13, 12, 13, 28, 13, 28, 13, 162, 39, 39, 13, 12, 13, 28, 13, 12, 13, 12, 13, 28, 13, 12, 13, 28, 13, 28, 13, 162, 39, 39, 13, 12, 13, 28, 13, 12, 13, 12, 13, 28, 13, 12, 13, 28, 13, 28, 13], "format": "raw"}
~~~
Raspberry Pi と irMagician（赤外線モジュール）で家電を操作する

# Raspberry Pi と irMagician（赤外線モジュール）で家電を操作する
リモコンで操作可能な家電を、Raspberry Pi （赤外線モジュール）から操作します。
今回の赤外線モジュールは、大宮技研の irMagician を使用します。

[irMagician – 高機能／低価格赤外線リモコン | 大宮技研 合同会社](http://www.omiya-giken.com/?page_id=837)

## Raspberry Pi の初期設定
### 設定ファイル編集
Raspberry Pi の「/boot/cmdline.txt」に記載されている「console=serial0,115200」を削除します。 

~~~
$ sudo vi /boot/cmdline.txt
~~~

~~~編集前の　/boot/cmdline.txt
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait splash plymouth.ignore-serial-consoles
~~~

~~~編集後の　/boot/cmdline.txt
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait splash plymouth.ignore-serial-consoles
~~~

### 再起動
irMagician をUSB接続して再起動します。

~~~
$ sudo reboot
~~~

### 確認
「ls /dev/ttyACM0」を実行し、「ttyACM0」が表示されれば使用準備が整いました。

~~~
$  ls /dev/ttyACM0
/dev/ttyACM0
~~~

## スクリプトのダウンロード
python から irMagician を利用するためのスクリプト「irmcli.py」をダウンロードします。
https://github.com/netbuffalo/irmcli.git 

## 赤外線の学習
リモコンの赤外線データをモジュールに学習させます。
以下のコマンドを実行の上、赤外線モジュールにリモコンの赤外線を照射します。

~~~
$ python irmcli.py -c
Capturing IR...
'

~~~


## 赤外線の照射
学習させた赤外線を、赤外線モジュールから照射します。

~~~
$ python irmcli.py -p
Playing IR...
... Done !
~~~

学習させた赤外線を照射しても、家電を操作できない場合があります。
[エアコンが irMagician（赤外線モジュール）で操作できない](https://qiita.com/minatomirai21/items/e432ed4a7bcce79ac7c8)



## 赤外線データの保存
モジュールが学習した赤外線データをJSONファイルとして Raspberry Pi に保存します。

~~~
 $ python irmcli.py -s  -f filename.json
Saving IR data to filename.json ...
Done !
~~~

~~~filename.json
{"postscale": 100, "freq": 38, "data": [175, 1, 205, 135, 66, 9, 7, 9, 7, 9, 7, 9, 7, 9, 7, 9, 7, 9, 24, 9, 7, 9, 24, 9, 24, 9, 24, 9, 24, 9, 24, 9, 24, 9, 7, 9, 24, 9, 7, 9, 7, 9, 7, 9, 7, 9, 24, 9, 7, 9, 7, 9, 7, 9, 24, 9, 24, 9, 24, 9, 24, 9, 7, 9, 24, 9, 24, 9, 24, 9, 86, 135, 33, 9], "format": "raw"}
~~~


## 保存した赤外線データの照射
Raspberry Pi に保存したデータをもとに赤外線を照射します

~~~
$ python irmcli.py -p -f filename.json
Playing IR with filename.json ...
... Done !
~~~

## 参考
[irMagicianをSiriから使う | 大宮技研 合同会社](http://www.omiya-giken.com/?page_id=2100)
エアコンが irMagician（赤外線モジュール）で操作できない

# エアコンが irMagician（赤外線モジュール）で操作できない
テレビを irMagician で操作することはできたのですが、エアコンの操作ができませんでした。
どうやら、エアコンのリモコンの赤外線データが大きすぎて、irMagician が学習しきれなかったようです。
学習リモコン（ADRSIR）は大容量バッファを搭載しており、エアコンを操作できました。
[Raspberry Pi と 学習リモコン（ADRSIR）で家電を操作する](https://qiita.com/drafts/140aa6e506bda70e0483)

## あるテレビの「消音」のデータ
~~~tv_mute.json
{"postscale": 100, "freq": 38, "data": [175, 1, 205, 135, 66, 9, 7, 9, 7, 9, 7, 9, 7, 9, 7, 9, 7, 9, 24, 9, 7, 9, 24, 9, 24, 9, 24, 9, 24, 9, 24, 9, 24, 9, 7, 9, 24, 9, 7, 9, 7, 9, 7, 9, 7, 9, 24, 9, 7, 9, 7, 9, 7, 9, 24, 9, 24, 9, 24, 9, 24, 9, 7, 9, 24, 9, 24, 9, 24, 9, 86, 135, 33, 9], "format": "raw"}
~~~

## あるエアコンのデータ

~~~aircon.json
{"postscale": 100, "freq": 38, "data": [128, 1, 199, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 125, 52, 25, 7, 19, 7, 6, 7, 6, 7, 6, 7, 19, 7, 6, 7, 6, 7, 6, 7, 6, 7, 19, 7, 6, 7, 19, 7, 19, 7, 6, 7, 19, 7, 19, 7, 19, 7, 19, 7, 19, 7, 6, 7, 6, 7, 19, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 19, 7, 6, 7, 19, 7, 6, 7, 6, 7, 6, 7, 19, 7, 19, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 19, 7, 19, 7, 19, 7, 6, 7, 19, 7, 6, 7, 19, 7, 19, 7, 10, 52, 25, 7, 19, 7, 6, 7, 6, 7, 6, 7, 19, 7, 6, 7, 6, 7, 6, 7, 6, 7, 19, 7, 6, 7, 19, 7, 19, 7, 6, 7, 19, 7, 19, 7, 19, 7, 19, 7, 19, 7, 6, 7, 6, 7, 19, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 19, 7, 6, 7, 6, 7, 6, 7, 6, 7, 19, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 19, 7, 6, 7, 19, 7, 6, 7, 19, 7, 6, 7, 10, 52, 25, 7, 19, 7, 6, 7, 6, 7, 6, 7, 19, 7, 6, 7, 6, 7, 6, 7, 6, 7, 19, 7, 6, 7, 19, 7, 19, 7, 6, 7, 19, 7, 19, 7, 19, 7, 19, 7, 19, 7, 6, 7, 6, 7, 19, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 19, 7, 6, 7, 6, 7, 19, 7, 6, 7, 6, 7, 19, 7, 6, 7, 19, 7, 6, 7, 19, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 19, 7, 6, 7, 19, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 19, 7, 19, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 19, 7, 19, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 19, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 19, 7, 19, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 19, 7, 19, 7, 6, 7, 19, 7, 6, 7, 6, 7, 19, 7, 6, 7], "format": "raw"}
~~~

エアコンのリモコンは、リモコンの液晶画面に表示されている情報を、毎回すべて送信しているようで、容量が大きいようです。