OmniAICreator/Qiita-1.07M huggingface dataset:
DockerでBitZenyマイニング

猫も杓子も仮想通貨の話題でいっぱいですが、今回はBitZenyをDockerを使ってマイニングしたいと思います。
macでbrewなんちゃらが壊れてたりしてうまく動かないときに使ってみてね。

# やり方

`docker run -e POOL_URL=<マイニングプールのURL> -e POOL_PORT=<マイニングプールのポート> -e USER=<ワーカーのユーザ名> -e PASSWORD=<ワーカーのパスワード> sanofc/znyminer`

# ソース

ここにあるよ。
https://github.com/sanofc/docker-cpuminer-bitzeny
SSHで簡単にサーバにログインする設定

## 簡単に言うと
- SSHする時に鍵とかユーザとか省略する、よくある手順です。

## 概要
- 某場所で仮想サーバの一部をお借りすることができたのでSSHの公開鍵認証をした。
- いつもは渡された手順で実施していたけど、勉強がてら自分で試し、結果をアウトプットすることにした。

## キーペア作成
- ssh-keygenで生成
  - [任意の秘密鍵ファイル名]は、既存の秘密鍵と被らないにファイル名をつける
  - パスフレーズの設定は任意


```
ssh-keygen -t rsa -b 4096 -C "[メールアドレス]"
```

```
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/[ユーザ名]/.ssh/id_rsa): /Users/[ユーザ名]/.ssh/[任意の秘密鍵ファイル名]
Enter passphrase (empty for no passphrase): 
Enter same passphrase again:
```

## 秘密鍵のパーミッション変更

```
chmod 600 ~/.ssh/[秘密鍵ファイル名]
```

## 公開鍵の置き場を作成

```
ssh [ユーザ名]@[サーバ名] -p [ポート番号]
mkdir ~/.ssh
exit
```


## 公開鍵をサーバに配置

```
scp -P [ポート番号] ~/.ssh/[公開鍵ファイル名] [ユーザ名]@[サーバ名]:/home/[ユーザ名]/.ssh/
```

## 公開鍵を登録

```
ssh [ユーザ名]@[サーバ名] -p [ポート番号]
cd /home/[ユーザ名]/.ssh/
cat [公開鍵ファイル名] >> authorized_keys
exit
```

## 公開鍵ログイン確認

```
ssh -i ~/.ssh/[秘密鍵ファイル名] [ユーザ名]@[サーバ名] -p [ポート番号]
```

## 別名でログインできるようにする

```
vi ~/.ssh/config
```

```
Host fmd
  Hostname [サーバ名]
  User [ユーザ名]
  Port [ポート番号]
  IdentityFile ~/.ssh/[秘密鍵ファイル名]
  PasswordAuthentication no
  TCPKeepAlive yes
```

## 別名でログイン

```
ssh fmd
```
MacでTypeScript, React, Visual Studio Code環境構築

# 概要
Visual Studio Codeで何かReactっぽいものをTypeScriptで書いてみよう！！
と思い立ち参考にさせてもらった素敵なサイトをメモしとく。

# 基礎学習
1. [5分で理解する React.js](https://qiita.com/tomzoh/items/7fabe7cb57dd96425867#%E3%82%B5%E3%83%BC%E3%83%90%E3%81%8B%E3%82%89%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB)
2. [覚えておきたいReactの実装でよく使う基本的な構文（書き方）](https://mae.chab.in/archives/2956#post2956-4)

# とりあえず何か作ってみる！！
1. [TypeScriptでReactを書く – webpackを使った開発環境の構築方法](https://mae.chab.in/archives/59782#post59782-6)  
↑めちゃわかりやすい
    1. npmを使用するのでnode.jsをインストールしとく  
    https://qiita.com/akakuro43/items/600e7e4695588ab2958d
    1. node.jsインストールでディレクトリ無いって怒られる  
    https://blog.yug1224.com/archives/5693a5e0fef2539c7d5b149d
1. ディレクトリ、ファイルをクラス毎に分けるために以下リンクのES6module方式を利用  
[TypeScript超入門(3)：モジュール](https://qiita.com/ringtail003/items/f7ed257c86e5522f6e59#es6-module)

# 非同期通信（ajax）も絡めて何か動かしたい

1. ページアクセス時にReactで画面に何か表示
2. 画面上の操作を契機に裏でajaxが動くような何か

上記の課題を自分に与えてとりあえずなんだか動くものは出来た。
https://github.com/shintaro123/typescript_react

非同期通信が無限ループして焦ったが以下を参考に取り急ぎ回避
[Reactで宣言的に書けないサーバー通信](https://qiita.com/uryyyyyyy/items/cf8ba60d32b7e9e30f64)

# 今後の調査対象
何も考えず動くもの作ったけど、時間見つけて以下ちゃんと勉強しよう

1. stateで何を持つか、何をpropsで渡すかの明確な設計指針
1. 非同期通信の無限ループ問題の正解検討
1. どこまでテンプレートで、どこまでReactにするのか指針
1. Fluxというキーワードがちょくちょく出てくる。これも調べたい。
1. そもそもTypeScriptちゃんと勉強しよう。。
Railsのプロジェクトに途中から参加するときの手順と躓くポイント(書き途中)

# まずはGithubからリポジトリをクローン
GithubにあるクローンURLを使って以下のコマンドを実行する

``` 
$ git clone https://github.com/xxx/yyy.git
 ```
※非公開リポジトリの場合は先にGithubに招待しておいてもらう

# 次にRubyのバージョンを合わせる
####1. 使っているバージョンのrubyをrbenvでインストール

使っているrubyのバージョンを聞いて
そのバージョンのrubyがすでにパソコンに入っているかを確認

```
$ rbenv versions
  2.2.3
* 2.4.2
  2.5.0
```

入ってなかった場合インストールをする

```
rbenv install 2.3.0
```


####2. localのディレクトリのデフォルトのバージョンに設定する

```
rbenv local 2.3.0
```

# bundlerをインストールしGemをインストール

```
gem install bundler
bundle install
```

### ここでエラーが出た。

```
An error occurred while installing rmagick (2.16.0), and Bundler cannot
continue.
Make sure that `gem install rmagick -v '2.16.0'` succeeds before bundling.
```

rmagickをインストールするためにはImageMagicとpkg-configが必要
version7以上だと対応していないので6以下を入れる

すでにImageMagickが入っている人は一度アンインストールする

```
brew uninstall imagemagick
```
その後ImageMagicのver6台をインストールし、pkg-configをインストールするために

```
brew install imagemagick@6
brew install pkg-config
```

その後パスを通すために

```
export PKG_CONFIG_PATH=/usr/local/opt/imagemagick@6/lib/pkgconfig
```

最後にようやくお目当のrmagickをインストール

```
gem install rmagick
```

ちなみにこちらの記事もとても参考になった
https://qiita.com/fyhcu/items/8aa117bfef4279100fce

# rails用のDataBaseを作って統合する

```
rake db:create
rake db:migrate
```

### ここで再び問題が。
データベースを作るときにmysqlのパスワードを求められたがパスワードを忘れた。

#### 対策
1.まずmysqlのサーバーを止める
※私の場合はmacの設定からmysqlの設定にとべ、そこでサーバーを止められた
2.mysqlにセーフモードで入る

```
mysqld_safe --skip-grant-tables &
```
3.mysqlの中で

```
mysql -u root
use mysql;
update user set authentication_string=password("password") where user='root';
flush privileges;
quit
```
を実行してrootのパスワードを変更する

#参考
###全体の筋道
https://qiita.com/yh2020/items/efd888854acf89af5ca7
###RMagickインストール関係
https://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwiS_Lbj06DZAhUQQLwKHQT1A0IQFggnMAA&url=https%3A%2F%2Fqiita.com%2Fniwasawa%2Fitems%2F1144f20a9f2de4b76977&usg=AOvVaw0v8_VVC8auHiAx9u6TDrwu
https://qiita.com/h-sakano/items/532aabbbddab84f58307
###mysql関係
https://qiita.com/y1row/items/994ecf8b478b7aac4c7d
https://liginc.co.jp/web/programming/mysql/87393
https://qiita.com/ahaha0807_alg/items/7323a5d2dd365308cb94
motionEyeOSからGoogleDriveにアップロードされたファイルをGoogleAppsScriptで定期的に消す(ゴミ箱のも)

#motionEyeOSでGoogleDriveにアップロードしてたら新しいファイルがアップロードされなくなった
#理由
motionEyeOSはGoogleDriveの空きに関係なくどんどんアップロードする。
なので設定次第では1ヶ月もしない内に無料ストレージ分の15GBを食いつぶしてしまう。
保存先の空き容量が無いので保存できなくなっていた。

#対策
motionEyeOSはどんどんアップロードするだけなので
GoogleDrive側で自動で消す仕組みにした。

今回利用したのは GoogleAppsScript。


〜2019/06/11追記〜
当初作ったのだとゴミ箱がいっぱいで結局容量を食いつぶしてしまうので
Googleで用意されているAPIを呼び出すことでゴミ箱からも削除されるように変更した




#詳細
##motionEye OSがアップロード先のフォルダから条件にあった古い作成日のフォルダを消す

##GoogleAppsScriptコード
```code.gs
/* motioneye OSが自動作成するGoogleドライブ内の特定のフォルダから古い作成日のフォルダをゴミ箱に移す */
function trashTemporaryFile() {
  var folderID = "9dfoHogeHogeHogedas9sadfn"; //時限削除したいフォルダのID（GoogleDriveでフォルダを選択した時のURL末尾ID）
  var days = 14; //日数

  var folder = DriveApp.getFolderById(folderID);
    var folders = folder.getFolders();  
    while(folders.hasNext()) {
      var file = folders.next();
      if (new Date() - file.getDateCreated() > days * 24 * 60 * 60 * 1000) {
        //ゴミ箱に（ファイル完全削除ではない）
        file.setTrashed(true);
      }
    }
  //ゴミ箱を完全に空にする(Drive API)
  /*https://qiita.com/TakashiHamada/items/d932b1c7ed991b575109*/
  Drive.Files.emptyTrash();

}
```

#解説
motionEye OSは標準だと以下のようなフォルダでファイルを貯めていく。

- motionEyeOSの設定で指定したパス
    - YYYY-MM-DD
    - YYYY-MM-DD

「motionEyeOSの設定で指定したパス」には、その日のファイル保存時に新規でフォルダが作成されていくので
対象パスの中にあるフォルダの作成日が所定の日数より古ければ
ゴミ箱に移動させるようにした。

上記のソースでは フォルダIDをブラウザURLから特定して
何日以上かをコード内に指定すりゃ良い。

〜2019/06/11追記〜
ここまでだとゴミ箱にファイルが残り続けて、
ドライブの容量がいっぱいになった後には追加保存ができなくなる。

なのでプロジェクトにAPIを紐づけして
APIからゴミ箱を削除できるように追加した。



#環境

| システム情報 | バージョン |
|:--|:--|
| motionEye Version | 0.37.1 |
| Motion Version | 4.0.1+git2a140fa |
| OS Version | motionEyeOS 20171008 |
| Google API | REST API Drive v2|



#最後に
GoogleAppsScriptの設定方法はどこぞで探しておくんなまし。


#参考記事
Google app script + REST API v2でファイルを完全削除またはゴミ箱を空にする
https://qiita.com/TakashiHamada/items/d932b1c7ed991b575109
CryptoCompare API で仮想通貨の日毎の価格を取得する

漢なら, 仮想通貨の価格ヒストリを取得したいですね!

やりましょう!

## CryptCompare API を使う

"cryptocurrency historical price" などで検索すると, CryptoCompare API がおすすめ, みたいな結果が帰ってきます.

https://www.cryptocompare.com/api/

なんだかいろいろデータが取れそうでわくわくしますね!

API limit も 6000 回/時間なので普通に利用する場合では制限にひっかかることはないでしょう.

## daily の価格を取得する.

https://www.cryptocompare.com/api/#-api-data-histoday-

`limit` で取得したい日の数を指定します.
`toTs` を指定した場合, `toTs` で指定した日付(unixtime)から, `limit`
 日ぶんを遡って取得します.

`fsym`, `tsym` のシンボルは大文字で指定する必要があります.

`CCCAGG` は CryptoCompare Current Aggregate の略でした.
 
https://github.com/ExodusMovement/cryptocompare/issues/4

python requests を使って, python
 で ZEC/JPY の日毎の価格を取得してみます.

```
#!/usr/bin/env python
# 
import json
import os
import sys
import datetime
import requests

def main():
    payload={'fsym': "ZEC", 'tsym': "JPY", 'limit':365}
    r = requests.get("https://min-api.cryptocompare.com/data/histoday", params=payload)
    j = r.json()
    print(j["Response"])
    if j["Response"] == "Success":
        for d in j["Data"]:
            timestamp = d["time"]
            open_price = d["open"]

            textualdate = datetime.datetime.fromtimestamp(timestamp)
            print("{0}, {1}, open = {2}".format(timestamp, textualdate, open_price))

main()
```

```
Success
1486857600, 2017-02-12 09:00:00, open = 3735.53
1486944000, 2017-02-13 09:00:00, open = 3662.07
1487030400, 2017-02-14 09:00:00, open = 3571.5
1487116800, 2017-02-15 09:00:00, open = 3791.85
1487203200, 2017-02-16 09:00:00, open = 3984.13
1487289600, 2017-02-17 09:00:00, open = 3831.4
```

Voila! 日毎の価格の取得に成功しました! 

## TODO

* timezone を考慮する
* hourly の価格を取得する.
* 取引所ごとの価格の平均をとってみる
tooltipの代わりになるProgress

#tooltipの代わりになるprogress　(AutoHotkey)
by neokix

![progress.gif](https://qiita-image-store.s3.amazonaws.com/0/237470/a5fde4c4-232e-5c08-9da7-5d6af146b6a7.gif)


##tooltipとは
tooltipは，アイコンなどを合わせたときに出る，説明のかかれたオレンジ色の箱です．
AutoHotkeyでは，tooltip, xxxxx で表示させることができます．tooltip, で消去できます．

```autohotkey:tooltip_eg
Esc::
   tooltip, すべてを格納します
   Winminimizeall
   Sleep, 300
   tooltip,
   return
```

##じゃあなんでProgressを使うの?
tooltipは便利なのですが，カスタマイズ性に欠けます．もう少し大きく表示したり，色を変えたりしたいでしょう．フェードアウトするような機能も実装してみたいとなるはずです．
そこで，Progressを使います．これはもともと，インストール画面などのProgress(進捗状況)を知らせるために使われるものです．

難点は，Progressは非常に複雑なオプションをもっていることでしょうか···．

https://autohotkey.com/docs/commands/Progress.htm

といってもなんか面倒くさいと思われるかもしれませんので，ここではお勧めのProgressの使いかたを載せておきます．

##おすすめの使い方

```autohotkey:Progress_howto
F1:: ;自分のHotkeyで
   Settimer remprog, 1000
   Progress, b zh0 fs15 w200 x50 y200 ctffffff cw008080, これはサンプル, , progtip, Segoe UI Black
   ;;;;;;;;;;;;;;;;;;;;;;
   ;;;;Your code here;;;;
   ;;;;;;;;;;;;;;;;;;;;;;
Return

remprog:
   Sleep, 200
   WinSet, TransColor, 000000 150, progtip
   Sleep, 100
   Settimer, remprog, off
   Progress, off
return
```
このように，Gosubでサブルーチン化すると，別コードの邪魔をしません．また，WinSetでTranscolorを指定することで，透明になるようなエフェクトを表現できます．

ちなみに，Progress部分の各オプションは以下のようになっています．これは，上のオプションと合わせて変更してみてください．

```autohotkey:Progress_options_eg

Progress, b境界なし zh0タイトルバーなし fs15フォント数 w横幅 x位置 y位置 ctフォント色 cwバックグラウンド色, 表示するテキスト, タイトル, フォント名

```
いかがでしょうか．
ほんの少しだけ上等になる···かもしれません．

なにか面白いものができたらぜひ見せてください!では!
Node.jsでslackログイン

node.jsでslackログインして、ユーザーの情報を取得して表示するところまでやる。
基本的には[このドキュメント](https://api.slack.com/docs/sign-in-with-slack)に沿っておこなう。備忘録。

## Slack appをつくる
上記ドキュメントの `Create your Slack app if you haven't already`の `Create a Slack app now`からSlackアプリを作る。
ClientIDなどができてることを確認。
また、Redirect URIが必要なので、FeatureのPermissionのところからRedirect URLを設定する。
一旦、ローカルでやるので、http://localhost:3000/slack/auth/redirect とか入れておく。

## slack loginボタンを設置する
`/views/index.ejs` のなかに、

```html
<a href="https://slack.com/oauth/authorize?scope=identity.basic&client_id=your_client_id&state=testapp">
  <img src="https://api.slack.com/img/sign_in_with_slack.png" />
</a>
```

を設置する。
※ 確認のために、stateを追記している。
※ profile画像も取得したい場合は、`scope=identity.basic, identity.avatar`とするなどscopeを追加する。（必要に合わせてpersmissionも追加する必要があるかも）

## 返ってきたcodeを使って、access tokenや情報を取得するようにする
`/routes/slack.js` にslackログインのやり取りを書いていく。
npmのrequestを利用する。https://github.com/request/request

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

router.get('/auth/redirect', function(req, res, next) {
	let code = req.query.code;
	let state = req.query.state;

	if (typeof code !== 'undefined' && state == "testapp") {
		request.get('https://slack.com/api/oauth.access?client_id=' + your_client_id + '&client_secret=' + your_client_secret + '&code=' + code, function(err, response, body) {
			let result = JSON.parse(body);

			// これで結果が取得できる
			console.log('result: ', result);
			console.log('userName:', result.user.name);
		});
	}

});
```

あとは、取得したデータをDB格納したり、sessionを良い感じにしたりするとOK。

レポジトリはこちら。https://github.com/mazeltov7/SlackLoginTest

ログインセッション周りは、
- [Express.js + Session + Sequelizeで簡易ログイン(SessionStore利用)](https://qiita.com/mazeltov7/items/ac07031bedb3b863eca9)
に書いてます。
[Swift4] 正規表現でキャプチャした文字列を抽出する

```swift
extension String {

    /// 正規表現でキャプチャした文字列を抽出する
    ///
    /// - Parameters:
    ///   - pattern: 正規表現
    ///   - group: 抽出するグループ番号(>=1)
    /// - Returns: 抽出した文字列
    func capture(pattern: String, group: Int) -> String? {
        let result = capture(pattern: pattern, group: [group])
        return result.isEmpty ? nil : result[0]
    }
    
    /// 正規表現でキャプチャした文字列を抽出する
    ///
    /// - Parameters:
    ///   - pattern: 正規表現
    ///   - group: 抽出するグループ番号(>=1)の配列
    /// - Returns: 抽出した文字列の配列
    func capture(pattern: String, group: [Int]) -> [String] {
        guard let regex = try? NSRegularExpression(pattern: pattern) else {
            return []
        }
        
        guard let matched = regex.firstMatch(in: self, range: NSRange(location: 0, length: self.count)) else {
            return []
        }
        
        return group.map { group -> String in
            return (self as NSString).substring(with: matched.range(at: group))
        }
    }
}
```

＜使用例＞

```swift
let pattern = "^(https?)://([^/]+)/?"
let str = "https://www.google.co.jp/"

print(str.capture(pattern: pattern, group: 2))
// Optional("www.google.co.jp")

print(str.capture(pattern: pattern, group: [1, 2]))
// ["https", "www.google.co.jp"]
IFTTTで連携したDropboxの英語ぽい日付入りのファイル名をNode.jsで扱う

# 背景

[IFTTT](https://ifttt.com/)では条件を指定して、[Dropbox](https://www.dropbox.com/ja/)に日付入りのファイルを作成する事が出来る。

この条件に最近AlexaやSiriを[homebridge](https://github.com/nfarina/homebridge)経由でIFTTTのWebhooksを指定できる事を
知った。

# 問題

[Node.js](https://nodejs.org/)で[fs.watch](https://nodejs.org/docs/latest/api/fs.html#fs_fs_watch_filename_options_listener)で指定したディレクトリの監視がOSが限定されるようだが
出来る。

でも、ファイルの追加削除がrenameイベントで通知されてしまう。
何も考えないでこのrenameイベントを契機に処理を行うと
溜め込んだ古いファイルを削除しても動いてしまう問題がある。

Dropboxのファイル名を解釈することで、古いファイルが
削除されても、これを無視する事が可能になる。


# Node.jsで日付入りのファイル名を扱う

Dropboxに作成されるファイル名は人間が読みやすい形式なので、
なんとかNode.jsで扱える形式にパースする必要がある。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">IFTTT経由のDropboxのファイル名を作成日付にしてるが、タイムゾーンがJSTっぽくてなんで俺が日本にいるの分かるのだろう？と思ったら、IFTTTの設定でタイムゾーンを指定してて、JSTをちゃんと指定していた為だったっぽい</p>&mdash; kjunichi (@kjunichi) <a href="https://twitter.com/kjunichi/status/962881121129185280?ref_src=twsrc%5Etfw">2018年2月12日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 日付を扱う便利なライブラリを入れる

[moment.js](https://momentjs.com/)を使うと、幅広い日付の形式に対応していて、
今回の形式の日付も簡単に扱うことできた。

## 日付ファイル名が10分以内に作成されたかをチェックするコード

```javascript
const moment = require("moment");

const checkFilename = (name) => {
  const now = moment();
  const origDateStr = name.split(" at ")[0];
  if (name.split(" at ")[1]) {
    const origTimeStr = name.split(" at ")[1].substring(0, 7);
    const origDateTime = moment(`${origDateStr}${origTimeStr}`, "MMMM D, YYYYhh:mma");

    if (now.diff(origDateTime) < 10 * 60 * 1000) {
      // 10分位内に作成されたファイル
      return true;
    }
  }
  return false;
};

// DropBoxには以下のようなファイル名でファイルが作成される
checkFilename("February 12, 2018 at 11/35AMT1-2On.txt");

// IFTTTで指定したDropboxのパスを設定
const path = "/Users/kjunichi/Dropbox/IFTTT/MakerWebooks/hoge";

fs.watch(path, (event, filename) => {
  // console.log(event + " to " + filename);
  if (checkFilename(filename) && event === "rename") {
    // IFTTTで通知された際に行う処理を実行する

  }
});
```

# 関連記事

- [アレクサで「iPhoneを探す」をpuppeteerを使って出来るようにした](https://abrakatabura.hatenablog.com/entry/2018/07/08/101607)
Chart.jsでグラフにマウスオーバーした際の選択した値を取得

## やりたいこと
Chart.jsでグラフにマウスオーバーした際のラベルや値を取得します。

## 前提
以前に私の方で投稿した[バブルチャート](https://qiita.com/someone7140/items/5784fe8213b1c5ee0e27)のサンプルソースを前提に、該当箇所を抜粋したソース例を記します。

##ソース例
```test_chart_bubble.html
<!--バブルチャートの箇所 -->
<canvas id="bubblechart" height="450" width="600"></canvas>
<!--選択したバブルのラベルを表示 -->
<div id="bubbleLabel"></div>
```

```chart_bubble_test.js
//マウス移動時のイベント
	$("#bubblechart").mousemove(function (e) {
		// 描画使用したオブジェクトからelementを取得
	    var element = bubbleChart.getElementAtEvent(e);
	    if (element.length > 0) {
	    	// 選択したdatasetのラベルを表示
	    	$("#bubbleLabel").text( bubbleChart.config.data.datasets[element[0]._datasetIndex].label );
	    }
	});
```

##参考
[円グラフの各項目にそれぞれ違うイベントをさせたい](https://teratail.com/questions/47455)
Cloud Function のHTTPトリガーのrequest contextと response contextはExpressのものと同等



Cloud Functionのrequest contextとresponse contextのAPIドキュメントが見つからない。ドキュメントには下記のように書かれている。

```
/**
 * Responds to any HTTP request that can provide a "message" field in the body.
 *
 * @param {Object} req Cloud Function request context.
 * @param {Object} res Cloud Function response context.
 */
```
> https://cloud.google.com/functions/docs/writing/http

使ってみた感じ Express のものと同等のようだ。

* [Request](http://expressjs.com/ja/4x/api.html#req)
* [Response](http://expressjs.com/ja/4x/api.html#res)

version 4 のもののリンクを貼ったがどのバージョンなのかまでは確認していない。
emulatorの中身見れば分かるような気もする。

Firebaseのドキュメントのほうがだいぶ親切そう。

> https://firebase.google.com/docs/functions/http-events?hl=ja
CircleCIのScheduling Jobの注意点など

# CircleCIのScheduling Jobの注意点など

### 対象

CircleCI 2.0

### Schedulingとは

CircleCIでは、jobを定期的に実行するための仕組みとしてworkflowにscheduleという設定を行うことができる。
多くの場合はgit pushなどのイベントをトリガーとしてjobを実行すれば良いが、End-To-Endテストなど極端に時間がかかるjobや、脆弱性のチェックなどリポジトリ以外の要因によって結果が変わる場合があるjobについては定期的にjobを実行させた方が望ましい。
それを実現するための仕組みがSchedulingである。

### なぜCircleCIのSchedulingを使うのか

定期的な処理を実行する仕組みとしては、cronやJenkinsなども挙げられる。
これらに対してCircleCIのSchedulingを使う利点として、CIという用語にも使われているContinuous(持続的)という点が挙げられる。
cronやJenkinsの問題点は、ジョブの設定がソースコードと分離されているというところにある(もちろんソースコード用に設定情報を配置することもできるが、設定情報を配置しただけでは動作しない)。このことにより、開発者がジョブの設定を認知していなかったり、ジョブが失敗しても気づきにくく、結果としてCIの持続性が失われてしまうリスクがある。
そのため、ソースコード上に設定を配置するだけで動くCIであるCircleCIのSchedulingを使うことが望ましい。なお、この点はTravisCIなど別のCIも同等である。

### 使い方

実行時間の設定方法はcronの設定と同様となる。以下に毎日20:00(デフォルトでUTC)にdaily-jobを実行する場合の設定を示す。

```
version: 2
jobs:
  daily-job:
    # 省略

workflows:
  daily-workflow:
      triggers:
        - schedule:
            cron: "0 20 * * *"
            filters:
              branches:
                only:
                  - master
      jobs:
        - daily-job
```

### 注意点1. 動作確認

上記のようなCircleCIの設定をPull Requestで追加する場合、動作確認において以下の問題点がある。

1. masterブランチで動作する設定にしていると、Pull Requestのブランチでは動かない
2. 指定した時刻にならないと確認できない

これらを解決するには、対象のjobをAPIで実行して確認するか、一時的にブランチや時刻を変更したcommitをpushするといった方法を取らなければならない。

### 注意点2. 結果の通知

CircleCIには、Slackなどのチャットツールやメールにjobの結果を通知する機能があり、設定によりJobの失敗/復旧時のみ通知するように設定することができる。
しかし、この設定はJobやWorkflowを区別できないという問題がある。
例えば、上記のScheduling Jobの設定だけでなく、masterへのマージにより実行されるJobの設定がある場合、Scheduling jobで失敗となった後に、マージ時のjobが成功すると、それにより復旧したという通知が飛んでしまう。

これを回避するには、Scheduling Jobだけを実行するためのブランチを別途用意するか、CircleCIの通知機能は使わずSlackのAPIを直接叩くという回避策が考えられる。
前者はmasterブランチのコード中に設定が見えなくなってしまう問題があり、またmasterブランチの更新を取り込むためにjobの中でmasterをマージするような設定が必要になる。
また、通知機能により表示されるメッセージの文言は柔軟に設定できず、Jobの失敗内容もメッセージに表示したい場合などにも対応できない。
そのため、通知機能では要件を満たせず、SlackのAPIなどを直接叩かざるを得ないケースも多いだろう。

### まとめ

CircleCIのSchedulingは便利ではあるものの、まだ実用性に乏しい感は否めないため、今後の改善を期待したい。
Node.js 学習日記

# Node.js学習日記

## 参考サイト

[ドットインストール](https://dotinstall.com/lessons/basic_nodejs/26204)

- いまこれをやっている
- 動画が2013年と古いので心配

[基礎から学ぶNode.js](http://gihyo.jp/dev/serial/01/nodejs)

- gihyo.jpのnode.jsまとめ

## はじめに

1. 開発環境の構築(自分はvagrantがあるので、vagrant)
2. [node.jsをインストール](https://nodejs.org/ja/) **これをしないと始まらない**
- [@akippikoさん](https://qiita.com/akippiko/items/3708016fc43da088021c)と[@yama-takeさん](https://qiita.com/yama-take/items/b1f89235d7987c0ec926)のページがわかりやすい
  - portの番号はVagrantfileによって違う（自分の場合は3000のみで、localhost:3000で表示）

## Node.js 学習まとめ

### ノンブロッキング処理

```js
setTimeout(function () {
  console.log("hello");
}, 1000); // コールバック関数
console.log("world");
```

出力

```js
world
hello
```

worldが先に出力され次の処理がブロックされない

### ブロッキング処理

```js
var start = new Date().getTime();
while (new Date().getTime() < start + 1000);
console.log("world");
```

この書き方だと、`while (new Date().getTime() < start + 1000);`の処理が終わらないと次の処理
`console.log("world");`が始まらない

## 他のファイルからコード読み込む

### exports

ファイルを呼び出すときに使用

```js
exports.port = 3000;
```

読み込む側

```js
require('ファイルディレクトリ')
```

## 他のファイルを読み込む

readFile('ファイルディレクトリ', '文字コード', // コールバック関数)

## npm

- Node Package Manager の略
- Node.jsのパッケージを管理するためのシステム
- `npm install パッケージ名`と入力すると、そのディレクトリに`node_modules`が作成されその中に各パッケージが作成される
- [npm](https://www.npmjs.com/)に様々なパッケージがある
某プログラマーコミュニティサイトのタグを全て取得するrubyプログラム

#投稿前に第5条(ユーザー資格の取消)を熟読してぎりぎりなんじゃないかと思ったrubyプログラマです!!


nokogiriとmechanizeをインストール
正直他のhttpクライアントで良かったと思う

```
% sudo gem install nokogiri
% sudo gem install mechanize
```

lazyメソッドか何かで最大ページ数の333を取り出せたと思うがやってない(やりたい)
xpathの構造をchromeの検証機能使わず(26×4なのか...とかいちいち手動でやらずに)調べられるようにしたい(クローリングする前処理のメタ的に便利なやつ作りたい)
proxyは各自で適当に(コメントアウトして串刺さずにやってもいいけどもちろん自己責任で)

```ruby:xiita_tag.rb
require 'mechanize'
require 'nokogiri'
require 'benchmark'

class Crowlling
  def crawl(url)
    agent = Mechanize.new
    # example: agent.set_proxy('hoge.com', 6060, 'email%40example.com', 'password')
    agent.set_proxy('', , '', '')
    agent.get(url).body
  end

  def parse(html)
    @elements ||= []; (1..26).map{|div_id|(1..4).map{|sub_id|@elements << Nokogiri::HTML.parse(html).xpath("//*[@id='main']/div/div[#{div_id}]/div[#{sub_id}]/div/div/a").text}}
    @elements
  end

  def make_file(all)
    File.open('tags.txt','w+'){|result|result << all}
  end
end

time = Benchmark.realtime do
  c = Crowlling.new
  @html ||= []; (1..333).map{|id|"https://xiita.com/tags?page=#{id}"}.each{|url|@html << c.crawl(url)}
  @all_tag ||= []; @html.each{|html|@all_tag << c.parse(html)}
  c.make_file(@all_tag)
end
puts "processing time #{time}s"
```

ちなみにタグ全部取り出せると
https://xiita.com/tags/Ruby/items?page=1
https://xiita.com/tags/Ruby/items?page=2
とかイテレーションして取り出せる(サイトの初期からタグ無しで投稿できたか次第だけど最初期からタグ必須なら(記事重複はするけど)全記事取得できるっぽい)
(ちなみにxiita.comというドメインは使われてないらしい)
JavaScriptのmap / filter / reduceっていつも雰囲気で書いてるけど実際どんな挙動するんだっけ？

miyachi（[@_38ch](https://twitter.com/_38ch)）です。
for文で無理やり配列操作するよりスマートな方法をしっかり覚えておきたい。
そしてアローで書きたい。
# filter
配列の中から条件に合うものだけを抽出する。

```javascript
var words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];

const result = words.filter(word => word.length > 6);

console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
```
words配列の中から6文字以上のものだけを抽出しています。

# map
Pythonで言うところのlambda的な書き方。配列の各要素に対して、関数を呼び出し、その結果から新しい配列を作成する。

```javascript
var array1 = [1, 4, 9, 16];

const map1 = array1.map(x => x * 2);

console.log(map1);
// expected output: Array [2, 8, 18, 32]
```
array1の各要素を2倍して新しい配列を作成している。

```javascript
var users = [{id: 0, name: 'Mike'},
            {id: 1, name: 'John'},
            {id: 2, name: 'Tom'}];

var names = users.map(user => user.name);

console.log(names);
// expected output: Array ['Mike', 'John', 'Tom']
```
オブジェクト配列から特定のキーのみを指定して配列を作ることも可能。

# reduce
累積値を求める時とかに使う？

```javascript
var array = [1,2,3]
var reduced = array.reduce((cumulativeValue, element) => cumulativeValue + element);

console.log(reduced);
// expected output: 6(1~3の累積値)
```

とりあえずこの三つは覚えておきましょう。
CLI で頑張ってブランチ名を覚えない

大した話ではないが，新しい職場で学んだ，Git のちょっと便利な tips を2つ．
ざっくりと GitHub Flow (`master` ブランチに Pull Request 経由で Feature 開発用ブランチにマージし，すぐにデプロイ可能にするような運用) を念頭においてほしい．

## Feature ブランチを remote repository に push するときは `HEAD` 参照で良い
これまで，機能を開発してリモートブランチに push するときにブランチ名を書いていた．

```bash
$ git checkout -b feature/sample-development
$ git commit -m "色々な開発をしてコミットする"
$ git push origin feature/sample-development
```

が，この push 時のブランチ参照は，そのブランチで作業している限り `HEAD` で良い．

```bash
$ git checkout -b feature/sample-development
$ git commit -m "色々な開発をしてコミットする"
$ git push origin HEAD # `head` でもよい
```

`HEAD` がどういうものか理解していれば当然なのだけど，最初に教科書で学んだときのやりかたでずーっとやることで無駄をしてたなぁと反省．
ただし， `master` など大事かつ慎重に運用しなければいけないブランチに間違って `push -f` してしまう可能性もあるため，その場合はリモート側 (GitHub や BitBucket, GitLab など) の設定でカバーしたい．

## 直前にいたブランチを参照するときは `-` でよい
競合の解消やブランチグラフの美化のために，リモートで更新された `master` に追従する際にも，基本的に　Feature ブランチの名前は覚えなくても良い．
たとえば， リモートの最新の `master` を取得して，現在開発している Feature ブランチをその `master` の上に Rebase する作業を考える．

```bash
$ # 今 feature/sample-development ブランチ上にいるとする
$ git fetch upstream
$ git checkout master
$ git merge upstream/master # ここまでの操作を git pull でできるならそれでも可
$ git checkout feature/sample-development
$ git rebase master # もしくはローカルの master の追従をしないときは `rebase upstream/master`　でも
```

どの Feature ブランチを `checkout` すればよいのかに悩むケースがあるが，この場合は `master` をチェックアウトする前のブランチに戻りたいので，実は `-` で代用できる． [^1]

```bash
$ # 今 feature/sample-development ブランチ上にいるとする
$ git fetch upstream
$ git checkout master
$ git merge upstream/master
$ git checkout -
$ git rebase master
```

[^1]: これ，ドキュメント上で見つけられないのだけれど，どこに書いてあるんだろう… そんな状況でこの記事書いてて恐縮です…
[Pythonメモ] 関数の引数に可変値を使う時の注意

関数の引数でつまづいたのでメモします

# 結論
* デフォルト引数は初期化時のみ読み込まれる
* 関数の引数は共有渡しのため、可変値を取るときは注意

## デフォルト引数
### 注意点
以下の2つのprint文は、それぞれlistの要素が一つであることを予想します

```python
def pick(member, team=[]):
    team.append(member)
    return team

print(pick('Jill'))
print(pick('Bob'))
```

結果は予想外のものになります

```pycon
>>> ['Jill']
>>> ['Jill', 'Bob']
```

これはpick関数のteamのデフォルト引数が一度しか読み込まれていないためです
つまり、teamがデフォルト値の時は同じオブジェクトを参照していることになります


### 解決策
[pythonチュートリアル](https://docs.python.jp/3/tutorial/controlflow.html#default-argument-values)にも記載ある通り、関数のデフォル値が可変の場合は一旦Noneにします

```python
def pick(member, team=None):
    if team is None:
        team = []
    team.append(member)
    return team

print(pick('Jill'))
print(pick('Bob'))
```

結果は期待通りになります

```pycon
>>> ['Jill']
>>> ['Bob']
```

## 引数に可変値を取るとき
### 注意点
無事にデフォルト引数による驚きを回避しましたが、通常の可変値を関数の引数に取る場合も注意が必要です
以下のようにあらかじめリストを用意した後に関数を実行します

```python
team_a = ['Jill', 'Bob']

def pick(member, team=None):
    if team is None:
        team = []
    team.append(member)
    return team

team_b = pick('Sam', team=team_a)

print(team_a)
print(team_b)
```

team_aにSamを加える動作を実行しました
team_bにはSamが存在し、team_aには存在しない事が期待値です
結果は以下のようになります

```pycon
>>> ['Jill', 'Bob', 'Sam']
>>> ['Jill', 'Bob', 'Sam']
```

これは関数の引数が共有渡しである事が原因になります
同じオブジェクトを参照しに行くので、破壊的変更を加えると元の引数に影響が及びます

### 解決策
この事象の回避策は引数に不変値を用いるか、コピーを作成する事です
先ほどのpick関数は以下のようになります

```python
team_a = ['Jill', 'Bob']

def pick(member, team=None):
    if team is None:
        team = []
    else:
        # teamのコピー作成
        team = list(team)
    team.append(member)
    return team

team_b = pick('Sam', team=team_a)
print(team_a)
print(team_b)
```

結果は期待通りになります

```pycon
>>> ['Jill', 'Bob']
>>> ['Jill', 'Bob', 'Sam']
```


関数に限らずエイリアスなのかコピーなのか気をつけていきたいです
[C#]デジカメで撮った写真から「カメラのモデル」を取る

# プロパティの「カメラのモデル」が欲しい
15年以上のデジカメで撮った画像ファイルが大量にありまして。
で、途中でデジカメを何回か買い替えているので、どのファイルがどのカメラで撮ったやつだ？を把握したくなり。
Windows上でプロパティ見たら、「カメラのモデル」があるわけですよ。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/221879/efc0b2d0-3c17-844a-0c63-8cd53201a399.png)


プロパティで見れるってことは、アプリから引っこ抜ける手があるはずで、それをいろいろやってみた次第。

## Image.PropertyItemsを参照する
[マイクロソフトのページ](https://msdn.microsoft.com/ja-jp/library/system.drawing.imaging.propertyitem_properties(v=vs.110).aspx)を見た感じ、
この列挙体の中にいる模様。
ってことは、Imageクラス作ってあげれば、参照できるってことですな。

## idはいくつ？
・・・が、わからない点が。idっていくつなのだ？
なので、また[マイクロソフトのページ](https://msdn.microsoft.com/ja-jp/library/system.drawing.imaging.propertyitem.id(v=vs.110).aspx)を参照。

わかるようなわからないような。仕方ないので、全部引っこ抜いてみた。

```CSharp:Test.cs
string imgFile = "D:\\IMG_6473.JPG";

using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(imgFile))
{
    foreach (System.Drawing.Imaging.PropertyItem item in bmp.PropertyItems)
    {
        //データの型を判断
        if (item.Type == 2)
        {
            //ASCII文字の場合は、文字列に変換する
            string val = System.Text.Encoding.ASCII.GetString(item.Value);
            val = val.Trim(new char[] { '\0' });
            //表示する
            Console.WriteLine("{0:X}:{1}:{2}", item.Id, item.Type, val);                        
        }
    }
}
//結果
10E:2:                               
10F:2:Canon
110:2:Canon PowerShot SX710 HS
132:2:2018:01:01 08:05:18
9003:2:2018:01:01 08:05:18
9004:2:2018:01:01 08:05:18
9290:2:09
9291:2:09
9292:2:09
5041:2:R98
A430:2:
```
というわけで、id=0x0110が当たりと判明！

## データを取ってみる。
```CSharp:ImageUtil.cs
string imgFile = "D:\\IMG_6473.JPG";

using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(imgFile))
{
    var item = bmp.PropertyItems.FirstOrDefault(v => v.Type == 2 && v.Id == 0x0110);
    if (item != null)
    {
        //ASCII文字の場合は、文字列に変換する
        string val = System.Text.Encoding.ASCII.GetString(item.Value);
        val = val.Trim(new char[] { '\0' });
        //表示する
        Console.WriteLine("{0:X}:{1}:{2}", item.Id, item.Type, val);                                            
    }
}

//結果
110:2:Canon PowerShot SX710 HS
```

取れた！
組込みに近いものをTDDで開発してみる〜問題提起編〜

# はじめに

下記の続きです。

[組込みに近いものをTDDで開発してみる〜準備編〜](https://qiita.com/tomoyuki-nakabayashi/items/23b064e3cea11dcc4152)

リアルタイムで内容を考えているため、ご意見・ご要望があれば、ぜひご連絡下さい。
[コードはgithubで公開中](https://github.com/tomoyuki-nakabayashi/TDDforEmbeddedSystem)

## 前回からの変更点と決定事項

### ビルドツール

ビルドツールをAutotoolsからCMakeに変更しました。
CMake version 2.8以降が必須環境となります。

### プロダクトコード

プロダクトコードはC言語にします。
あまり複雑なコードを書く予定がないため、生C言語で続ける予定です。コードが複雑になれば、glibの利用を検討します。

### 作るもの

**キーボードの「A」ボタンを押すと、caps lockのLEDがON/OFFする。**

とりあえずここから始めて、その場のノリと思いつきとフィードバックで仕様拡張していきます。
今回掲載するコードを除き、TDDで作っていきます。
最終的には、ラズパイなどの別ハードで、キーボード以外のハードウェアを使用し、ちゃんと移植できたよね、めでたしめでたし、としたいですね！
現時点で本当に具体的なハードウェアを選定していないです。ほら、その方が実際の開発っぽいでしょ？

# 問題提起

さて、作るものに戻って、**キーボードの「A」ボタンを押すと、caps lockのLEDがON/OFFする**と言われてプログラムを作るとき、どのような実装になるでしょうか？

愚直に作ると、概ね次のような疑似コードになるのではないでしょうか。

```c
static void mainloop() {
  do {
    キーイベントを取得
    if (Aボタンが押された) {
      write(LEDをトグル);
    }
  } while (何らかの条件を満たすまで);
}

int main() {
  mainloop();
  return 0;
}
```

上の疑似コードを実際に作ると次のようなコードになりました。
libevdevの動作は、前回のライブラリ理解のためのテストで確認しましたね。

```c
#define KEYBOARD_DEVICE "/dev/input/event2"
#define LED_DEVICE      "/sys/class/leds/input2::capslock/brightness"

#define KEY_RELEASED 0
#define KEY_PRESSED 1

static void mainloop() {
  struct libevdev *dev = NULL;
  int key_fd = open(KEYBOARD_DEVICE, O_RDONLY|O_NONBLOCK);
  int rc = libevdev_new_from_fd(key_fd, &dev);

  if (rc < 0) {
    fprintf(stderr, "Failed to init libevdev (%s)\n", strerror(-rc));
    exit(1);
  }

  int led_fd = open(LED_DEVICE, O_WRONLY|O_NONBLOCK);
  if (led_fd < 0) {
    fprintf(stderr, "Failed to init LED device.\n");
    exit(1);
  }

  bool led_on = false;
  do {
    struct input_event ev;
    rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
    if (rc == 0) {
      if (ev.type == EV_KEY && ev.code == KEY_A && ev.value == KEY_PRESSED) {
        led_on = !led_on;
        char buf[2];
        snprintf(buf, 2, "%d", led_on ? 1 : 0);
        write(led_fd, buf, 2);
      }
    }
  } while (rc == 1 || rc == 0 || rc == -EAGAIN);

  libevdev_free(dev);
  close(key_fd);
  close(led_fd);
}

int main() {
  mainloop();
  return 0;
}
```

Linux環境がある方は実際に動かすことができます。
前回記事を参考に、キーボードデバイスとLEDデバイスを確認し、2つのマクロ（*KEYBOARD_DEVICE, LED_DEVICE*）のパスを修正して下さい。
ビルドし、**build/bad_example/bad_example**を実行すると、「A」キーを押すたびにLEDがONされたりOFFされたります（環境によりroot権限が必要です）。

さて、このコードは一見、問題がないように見えますが、多くの問題を内包しています。

* 全てのコードが意図通りに動作していることが明確でない。（エラー処理、終了時の動作確認ができない）
* ロジックとハードウェアが密結合しており、ハードウェア変更、追加がロジックに影響する（オープン・クローズドの原則違反）。
* mainloop関数を変更する理由が複数存在する（単一責務の原則違反）。例えば、キーイベント追加、LEDデバイス追加、双方ともにmainloopへの修正が発生する。

これらの理由のため、機能拡張を繰り返していくと、機能追加が次第に困難になり、デグレを起こさずに機能追加することが難しくなります。

次回からは、今回のコードをTDDで開発するとどうなるか、を実際にやってみて、順に機能を追加していきます。

次：
[組込みに近いものをTDDで開発してみる〜file open編〜](https://qiita.com/tomoyuki-nakabayashi/items/648109594612fd4b518a)
なんでQuaternion使うか？(&ジンバルロック)

#はじめに
Unityなどでクオータニオンを目にする機会は多いと思いますが、なんで使うのかはわからないけど便利だから使うみたいなことはよくあると思います.そこで少しでもクオータニオンを使うメリットをかければいいなと思っています！
さっそくクオータニオンを使う大切な事実として**任意の回転は１つの軸で表現できる**ということがあります.いまいち、ぴんとは来ないかも知れませんが、これがクオータニオンを使う最大のメリットであり理由なのではないかなと思っています.


#クオータニオンを使うことでのメリット

例えば、空にいる飛行機を見るとします、そのときオイラー角を用いた回転ではx、y、z、の基本軸に対して何度回転させるかということが必要になってくると思いますが、それは意外とめんど臭いことなんです.このめんど臭く感じる感覚はクオータニオンについてなんとなくわかってきたら理解できるはずです.ではクオータニオンを用いたらどのようになるかというと、**目的へのベクトルがわかれば回転できてしまう**ということです.

##Unityで試してみる
###クオータニオンと積ベクトルの積を用いた回転
```csharp
pos = gameObject.transform.position;
//回転の中心を（1,2,3)とする
Vector3 RotCenter = new Vector3(1, 2, 3);
pos -= RotCenter;
pos = Quaternion.AngleAxis (Mathf.PI * Mathf.Rad2Deg, Vector3.up) * pos;
pos += RotCenter;
gameObject.transform.position = pos;
```
クオータニオンによる回転は原点中心なので回転させたいオブジェクトの座標から引いてから回転させ、最後にもう一回足してあげてます.
もう１つ大切なこととしてクオータニオンの回転度数は度数法を用いています.

またベクトルとクオータニオンの積で回転を示していますが、実際の計算ではこのようになっています.


```math
q(xi,yi,zi,w) \times \vec{v}(x,y,z) \times  \bar{q}
```



###Slperを使った場合の回転
```csharp
Quaternion targetRot;
	public GameObject target;
	void Start () {
		target = GameObject.Find ("target");
	}

	void Update () {
		targetRot = Quaternion.LookRotation (target.transform.position - gameObject.transform.position);
		transform.rotation = Quaternion.Slerp(transform.rotation, targetRot, Time.deltaTime);
	}
```
LookRotation関数は目的のベクトルへ回転させるためのクオータニオンを取得します.その回転を表すクオータニオンを随時更新して、Slerp関数（球面補完してくれる関数）を用いて回転させています.
またLookRotation関数の第1引数は正面方向のZ軸、第2引数はY軸に相当します。それらの外積を求めてX軸を求め、Z軸ともとまったX軸の外積を求めることで正確にY軸を求めることでその座標系への回転を表すクオータニオンを算出しているみたいです.




#補足
##ジンバルロック
よくクオータニオンについて書いてあるサイトを眺めているとこんなことが書いてあります.『クオータニオンを使うことでジンバルロックの影響を受けない』 ....急にこんなことを言われても困りますよね.そのためこれから自分が理解している範囲でジンバルロックがどんなものかということを書いて行こうと思います.

###ジンバルロック問題とは
ジンバル（ジンバル自体がよくわからない場合は下の参考の動画を！）の軸には親子関係があり、Z軸周りに回転するとY軸が、Y軸周りに回転するとX軸が回転します、X軸周りに回転しても、他の軸は回転しません。またそれぞれの回転角度はオイラー角における回転の順番（ヨー・ピッチ・ロール）と対応しています。（Z軸周りをヨー、Y軸周りをピッチ、X軸周りをロール）そして本題のジンバルロックの時の状態ですが、それはY軸に関して90度回転させ、X軸に関する回転軸がZ軸と被ってしまった時、回転順序の最後のX軸回転による制御ができなくなってしまことをジンバルロックというらしいです.

参考：https://www.youtube.com/watch?v=zc8b2Jo7mno


###ジンバルロックに関してクオータニオンを使うと嬉しいこと
オイラー回転は３軸を使って回転するのでこのジンバルロックがおこってしまいますが、クオータニオンは４元数なのでこの問題を解決してくれます.（４元数とは、4つの実数を組み合わせたもので、4つの要素のうち、ひとつは実部、残り３つは虚部）
冒頭で書いた**任意の回転は１つの軸で表現できる**ということを思い出すとクオータニオンでは回転軸と回転角度がわかれば回転を表現することができる.つまりこれは二次元平面での回転に帰着するためジンバルロックがおきないのであると考えています.

#おわりに
自分も数学的な部分で理解していない部分はありますが、この記事が何かの役に立てたらなと思います.また間違いなどがありましたらコメントください.
uglify-esでの「ES6対応」の意味

UglifyESを使おうとしたら、ちょっと想定外だったことがありました。

# `uglify-js`と`uglify-es`
JavaScriptをminifyするソフトウェアとしてUglifyJSが有名ですが、npmから`uglify-js`として入れると、ES5専用のものが入ってしまうので、ES6の構文があるとエラーになります。

従来のUglifyJSとは別ブランチで、ES6対応版の開発が進んでいますが、こちらはnpmに`uglify-es`という名前で登録されています。

## Webpackからの利用

WebpackにもUglifyJSを使うプラグイン（`webpack.optimize.UglifyJsPlugin`）が標準で添付されていますが、Webpack 3の時点では、標準添付版は`uglify-js`を呼び出す仕様となっています。`uglify-es`を使いたい場合、別に`uglifyjs-webpack-plugin`のVer.1系列を入れる必要があります（なお、Webpack 4では標準添付版も`uglify-es`使用に切り替える予定とのことです）。

# バージョン対応の意味

そして、babelの設定も`env`標準にしてES5への強制変換を止め（もっとも、IE11も対象なので、残るのは`let`・`const`ぐらいでしょうが）、その他を色々書き換えながらチェックしていたところ、IE11でコードが動かなくなってしまいました。確認してみると、アロー関数がそのまま吐き出されてしまっていました。

「デフォルトでは`uglify-es`の入力はES2017、出力はES5だったのにおかしいな」と思い、[`uglify-es`のドキュメント](https://github.com/mishoo/UglifyJS2/tree/harmony#output-options)を確認していたところで、真相が判明しました。

>  The `ecma` option will only change the output in direct control of the beautifier. Non-compatible features in the abstract syntax tree will still be output as is. For example: an `ecma` setting of `5` will **not** convert ES6+ code to ES5. （強調も原文ママ）

ということで、ES6で来たコードは、（`uglify-es`で圧縮変換されない限り）ES6のままで出力されてしまうのです。もちろん、事前にbabelで適切な形に変換してあれば問題はないのですが、ちょうどES6で書いてあったモジュールを`import`しようとした（＆`node-modules`はbabelから除外していた）こともあって、そのまま出力まで素通りした、ということでした。

# 関連記事

* [【webpack】(2018年1月現時点で)ES2015 (ES6)のままminifyする方法](https://qiita.com/ota-meshi/items/9e9bfcbfab00e109494f)
Raspberry PIとGPSを使って自分の位置をさくっと収集する方法

# はじめに

自分の位置を予測する方法についての記事を書いたら、収集する方法についての問い合わせがあったので、収集方法についての記事を書きます。

データの利用例は以下のURLをご参照下さい。

[GPSで取得した位置情報のログを学習し、数分後に自分がどこにいるのかを予測する](https://qiita.com/mix_dvd/items/fda2ba62f2fe60588851)

# 準備

- [Raspberry PI 3 model B](http://amzn.to/2BoUXU0)
- [GPSモジュール](http://akizukidenshi.com/catalog/g/gK-09991/)

# OSインストール

以下のURLよりOSのイメージをダウンロード

[RASPBIAN](https://www.raspberrypi.org/downloads/raspbian/)

以下のソフトウェアを使ってmicroSDに書き込む

[Etcher](https://etcher.io)

microSDをラズパイに挿して電源を投入し、しばらく待ったらログイン画面が出るので、pi、raspberryと入力してログイン。

# GPS関連の設定

## 初期設定

設定プログラムを実行。

```
sudo raspi-config
```

「5 Interfacing Option」ー「P6 Serial」を選択し、有効化。

## プログラムのインストール

以下のコマンドを実行。

```
sudo apt-get -y install gpsd gpsd-clients python-gps
```

## 起動設定の変更

```
sudo nano /boot/cmdline.txt
```

「console=serial0,115200」を削除


## gpsd設定変更 

```
sudo nano /etc/default/gpsd
```

以下の二箇所を修正。

```
USBAUTO="false"
DEVICES="/dev/serial0"
```

設定後、以下のコマンドを実行。

```
sudo shutdown -h now
```

# GPSモジュールの接続

下図のとおり接続。

![20180128_センシングプラザ紹介.001.jpeg](https://qiita-image-store.s3.amazonaws.com/0/114240/b9970fa8-a84b-1ea5-58c1-49be099ccff2.jpeg)

接続後、電源を投入。

# 動作確認

以下のコマンドを実行し、正しくデータが収集できていることを確認。

```
gpsmon
```

# データ収集

以下のスクリプトで取得した位置情報をSQLiteに保存。

```py:getGPS.py
#!/usr/bin/env python

from gps import *
import sqlite3
from datetime import datetime, timedelta

if __name__ == '__main__':
    
    dbname = "gpslog.db"
    conn = sqlite3.connect(dbname)
    c = conn.cursor()
    
    session = gps()
    
    session.stream(WATCH_ENABLE|WATCH_NEWSTYLE)
    
    dt_buff = ""
    
    for report in session:
        
        if report['class'] == "TPV":
            
            dt = datetime.strptime(report['time'].replace('T', ' ')[:19],'%Y-%m-%d %H:%M:%S')
            dt = str(dt + timedelta(hours=9))
            lon = report['lon']
            lat = report['lat']
            
            if dt != dt_buff:
                sql = "INSERT INTO log VALUES('{}',{},{})".format(dt[:19], lon, lat)
                c.execute(sql)
            
            dt_buff = dt
            
            time.sleep(1)
```

上記スクリプトを以下のコマンドで実行。

```
chmod a+x getGPS.py
./getGPS.py
```

# 自動起動

起動時に自動実行されるように設定。

```
sudo nano /etc/rc.local
```

以下の一行を「exit 0」の前に追記。

```
/home/pi/getGPS.py &
```

以上。
three.jsで.copy()と.set()を間違えた時に警告する

[three.js](https://threejs.org/) の基本的なクラスである[`Vector*`](https://threejs.org/docs/#api/math/Vector3), [`Quaternion`](https://threejs.org/docs/#api/math/Quaternion), [`Matrix*`](https://threejs.org/docs/#api/math/Matrix4) (*は3とか4とか)には`clone`, `copy`, `set`, `fromArray`という関数が定義されています。これらは

* `clone`: 同一のプロパティをもつインスタンスを複製して返す
  * 例: `const vec3_ = vec3.clone();`
* `copy`: ただひとつの引数（同じクラスのインスタンス）のプロパティをそのインスタンスのプロパティにコピーする
  * 例: `vec3_.copy(vec3);`
* `set`: 引数ひとつひとつをそのインスタンスのプロパティひとつひとつにセットする
  * 例: `vec3.set(1, 2, 3);`
* `fromArray`: ただひとつの引数（配列）の要素をそのインスタンスのプロパティひとつひとつにセットする
  * 例: `vec3.fromArray([1, 2, 3]);`

……と覚えるまでが大変です。
この記事では特によく使う`copy`と`set`について引数を間違えていると即座にランタイムで警告を出せるようにします。

## .copy()
```js
const overrideCopyFunction = function(cl, args) {
    // 元のcopy関数
    const cp = cl.prototype.copy;
    cl.prototype.copy = function(from) {
        // fromの「名前がargsに含まれるプロパティ」に数値でないものが含まれる場合に例外を返す
        if(args.some(function(x) { return (typeof from[x]) != "number"; }))
            throw new Error(); // お好きなメッセージをどうぞ
        // 本来のcopy関数を呼ぶ
        return (cp.bind(this))(from);
    };
};
overrideCopyFunction(THREE.Vector3, ["x", "y", "z"]);
overrideCopyFunction(THREE.Quaternion, ["x", "y", "z", "w"]);
```

こんな感じに`Vector3`の`copy`関数を上書きします。
`overrideCopyFunction`の引数には対象クラスとプロパティ名の配列を指定します。
`copy`関数では他の物理演算エンジンのベクトルなどを使いたい場合もあるため、ここでは「数値型の`.x`, `.y`, `.z`プロパティをもつオブジェクト」が渡された場合以外の際に例外を投げるようにしています。

## .set()
```js
const overrideSetFunction = function(cl) {
    const st = cl.prototype.set;
    cl.prototype.set = function(...from) {
	if(from.some(function(x) { return (typeof x) != "number"; }))
	    throw new Error();
	return (st.bind(this))(...from);
    };
};
overrideSetFunction(THREE.Vector3);
overrideSetFunction(THREE.Quaternion);
```

`set`についても`copy`と同様に関数を上書きします。
新しい`set`関数では引数のうち数値型でないものが含まれる場合に例外を投げ、そうでない場合にはその引数をオリジナルの`set`関数にそのまま引き渡します。

## 実行例
### 適用前
```js
> v
< Vector3 {x: 1, y: 2, z: 3, isVector3: true, set: function, ...}
> v2
< Vector3 {x: 4, y: 5, z: 6, isVector3: true, set: function, ...}
> v.set(7, 8, 9)
< Vector3 {x: 7, y: 8, z: 9, isVector3: true, set: function, ...}
> v.set(v2)
< Vector3 {x: Vector3, y: undefined, z: undefined, isVector3: true, set: function, ...}
```
2つ目の`set`で`v`が破壊されます。

```js
> v
< Vector3 {x: 1, y: 2, z: 3, isVector3: true, set: function, ...}
> v2
< Vector3 {x: 4, y: 5, z: 6, isVector3: true, set: function, ...}
> v.copy(v2)
< Vector3 {x: 4, y: 5, z: 6, isVector3: true, set: function, ...}
> v.copy(7, 8, 9)
< Vector3 {x: undefined, y: undefined, z: undefined, isVector3: true, set: function, ...}
```
2つ目の`copy`で`v`が破壊されます。

### 適用後
```js
> v
< Vector3 {x: 1, y: 2, z: 3, isVector3: true, set: function, ...}
> v2
< Vector3 {x: 4, y: 5, z: 6, isVector3: true, set: function, ...}
> v.set(7, 8, 9)
< Vector3 {x: 7, y: 8, z: 9, isVector3: true, set: function, ...}
> v.set(v2)
< Error
```

```js
> v
< Vector3 {x: 1, y: 2, z: 3, isVector3: true, set: function, ...}
> v2
< Vector3 {x: 4, y: 5, z: 6, isVector3: true, set: function, ...}
> v.copy(v2)
< Vector3 {x: 4, y: 5, z: 6, isVector3: true, set: function, ...}
> v.copy(7, 8, 9)
< Error
```
ちゃんとエラーが帰ってきます。
Raspberry Pi から IFTTT に連携する

# Raspberry Pi から IFTTT に連携する

Raspberry Pi から IFTTT に連携する方法を記載します。
IFTTT では、this に Webhook を設定し、Raspberry Pi から HTTP Request します。

![0.png](https://qiita-image-store.s3.amazonaws.com/0/235420/3919c0b0-8b08-5a04-63ae-8f98a9ddf828.png)


## IFTTT の設定
### this の設定
IFTTT の this に Webhooks を設定します。
![001.jpg](https://qiita-image-store.s3.amazonaws.com/0/235420/5271c8a7-bd0a-6d8a-343d-f7e945346b44.jpeg)
![002.jpg](https://qiita-image-store.s3.amazonaws.com/0/235420/3b730a07-9f76-db3b-5231-b4eea7a527e1.jpeg)

今回は、Event Name に raspberrypi と指定します。
![003.png](https://qiita-image-store.s3.amazonaws.com/0/235420/3dc1952a-4198-3040-653c-9f07a80372e6.png)

|項目 | 設定値 |
|:--|:--|
|Event Name   |raspberrypi   |


### that の設定
今回は、Beebotte に REST API で Publish して、Raspberry Pi に MQTTメッセージを Subscribe させます。

詳細は、以下の記事を参照ください。
[IFTTT から Raspberry Pi に指示を出す](https://qiita.com/minatomirai21/items/4c4e777b43ede1e42900)

![004.png](https://qiita-image-store.s3.amazonaws.com/0/235420/6959a507-1b6e-6406-04f0-a64f3b8b1b3b.png)

|項目 | 設定値 |
|:--|:--|
|URL   |https://api.beebotte.com/v1/data/publish/raspberrypi/action?token=＜TOKEN＞   |
|Method   |POST   |
|Content Type   |application/json   |
|Body   |{"data" : "{{Value1}},{{Value2}},{{Value3}}"}   |


## Webhook の設定確認
IFTTT の Search で Webhooks を検索、表示します

![005.png](https://qiita-image-store.s3.amazonaws.com/0/235420/4454153f-21ce-1567-cb02-621ee63675f9.png)


［Documentation ］を選択します。

![006.png](https://qiita-image-store.s3.amazonaws.com/0/235420/54fbb941-caa5-7be1-c892-bcb4ae48ec85.png)


POST 先のURLが表示さるので控えます。

![007.png](https://qiita-image-store.s3.amazonaws.com/0/235420/b149f267-a17a-6015-fd17-530324c9e433.png)


今回設定した Event Name から、URLは以下のようになります。



|項目 | 設定値 |
|:--|:--|
|URL   |https://maker.ifttt.com/trigger/rasspberrypi/with/key/＜key＞  |

また、POSTするJSONの形式は以下であることが確認できます。
変数は3つまで設定できるようです。


|項目 | 設定値 |
|:--|:--|
|JSON body   |{ "value1" : "", "value2" : "", "value3" : "" }   |




## Raspberry Pi（Node-RED）の設定

### IFTTT へ メッセージを送信する設定
http request ノードにて POST します。
その前に、function ノードで POST する JSON を作成します。

![101.jpg](https://qiita-image-store.s3.amazonaws.com/0/235420/6a5de1fd-41eb-4055-45af-743c9afa6642.jpeg)


function ノード

~~~
var payload={ "value1" : "値１", "value2" : "値２", "value3" : "値３" }
msg.payload=payload
return msg;
~~~
![102.jpg](https://qiita-image-store.s3.amazonaws.com/0/235420/6f16e37f-b4c3-90dd-9738-aa9ae72de5e0.jpeg)



http request ノード

|項目 | 設定値 |
|:--|:--|
|メソッド   |POST   |
|URL   |https://maker.ifttt.com/trigger/rasspberrypi/with/key/＜key＞   |
|出力形式   |文字列   |

![103.jpg](https://qiita-image-store.s3.amazonaws.com/0/235420/c959ea8c-6230-1542-ac47-5f12f01f5c28.jpeg)


### Beebotte から MQTTメッセージを受信する設定

以下の記事を参照ください。
[IFTTT から Raspberry Pi に指示を出す](https://qiita.com/minatomirai21/items/4c4e777b43ede1e42900)

## メッセージの送受信
inject ノードによりメッセージを送信します。
送信が成功すると、http request ノードから以下のメッセージが出力されます。

~~~
"Congratulations! You've fired the raspberrypi event"
~~~

mqtt inノードでは以下のメッセージを受信します。

~~~
{ data: "値１,値２,値３", ispublic: true, ts: 1518436824359 }
~~~

![104.jpg](https://qiita-image-store.s3.amazonaws.com/0/235420/fa3cac63-94c7-13f2-28fb-e5c3de98a883.jpeg)
TypeScriptのaddEventListenerで苦しんだところまとめ

# やろうとしたこと
TypeScriptでaddEventListener。
イベントリスナーにおいて、イベント発生元（今回はinput type=file）の情報を取得しようとした。

```typescript
const image1 =
      document.getElementById('image1');
image1!.addEventListener(
  'change',
  (event) => {
    this.handleInputChange(event.target.files![0]);
  },
  false,
);
```
# 問題1

以下のエラーが発生。

```
TS2339: Property 'files' does not exist on type 'EventTarget'.
```

## 問題1の解決

以下の記事でEventをwrapする方法をご教示いただき、上記のエラーは解消。
https://qiita.com/wamei/items/43753e03821964719f31

# 問題2

EventTargetの型の問題は解決するものの、次は以下のエラーが発生。

```
TS2345: Argument of type '(event: HTMLElementEvent<HTMLInputElement>) => void' is not assignable to parameter of type 'Ev
entListenerOrEventListenerObject'.
  Type '(event: HTMLElementEvent<HTMLInputElement>) => void' is not assignable to type 'EventListenerObject'.
    Property 'handleEvent' is missing in type '(event: HTMLElementEvent<HTMLInputElement>) => void'.
```

（未だにTypeScriptのエラーメッセージは慣れない。）

どうやらTypeScript v2.6から追加されたStrict function typesに起因するものらしい。

## 問題2の解決①
tsconfigに以下の設定を加えることでも回避可能です。

```json
"strictFunctionTypes": false
```

## 問題2の解決②
とはいえせっかくなのでお作法に則りエラーを解決したく思い調べて見た所、以下の記法で解決することができました。

```typescript
image1!.addEventListener(
  'change',
  {handleEvent: (event: HTMLElementEvent<HTMLInputElement>) => {
    this.handleInputChange(event.target.files![0]);
  }},
  false,
);
```

見栄えが悪いので、addEventListenerの第二引数はオブジェクトとして切り出して定義した方がいいかもしれませんね。

# まとめ
あまり掘り下げられておりませんが、一旦備忘録として残しておきます。
認識が誤っている箇所などございましたら、ご指摘頂けますと助かります。
圏論について

# javascriptに足りないもの　と　圏論
初めての投稿になります。
お手柔らかに接していただけると幸いです。
なお、記事に対する意見は諸々あると思いますが、間違いなどの指摘をいただければとも思います。
訂正については、指摘に基づいて行いたいと思います。

さて、プロフィールにも書いた通りですが
個人的に***webRTC***の1対1接続を作り、そのイベントを拾ってその変化を***DOM***に反映させるときにオブジェクト指向の限界を知ることになり、関数型プログラミングのために必要な拡張を模索するjavascript難民が私です。　ただ、一般の関数型プログラミングのスタイルを提示する***javascript Ninja***の方々とは少し異色なことをしています。

もちろん私は、javascriptに足りないものを考えているので、プログラムは自然と
***Object.defineProperties***によるプロトタイプ拡張を前提としています。

# 圏論に対する誤解
## 圏論は難しい
この誤解を生んでいるのは専門的な論理学者や圏論に携わる人々のせいだと思っています。
つまり、圏論に携わる人々は、圏論の用語を使わなければ会話が出来ないのです。
しかし、圏論の用語を使わずとも、簡単な会話が出来る方法があります。
## 重要なのは像（具体的な値）ではなく、***矢印***とその***意味***
あなたが関数型プログラミングするときに重要なのは、***3種類の矢印***を区別しているか？
ということです。
## 3本の矢と3つの観点
矢印は3つの意味を持ちます。
1. 射　（像：実際の値を対象とする）
2. 関手　（圏：像の集合（要素が一つの場合や空の場合もある）を対象とする）
3. 自然変換　（関手の集合（たとえ関手が一つでも）一つの圏と考えたものを対象とする）

自分が関数を定義したときに、上記のどの規模で利用しているかが重要だといえます。
矢印とその意味のほうが、実際の値（像またはその集合である圏）よりも重要だという例示になりますが。

>「自然数 b が a で割り切れる」ことを射 a → b と定めても圏ができる。

引用：[物理学者のための圏論入門](http://www.phys.cs.is.nagoya-u.ac.jp/~tanimura/lectures/tanimura-category.pdf) 

圏論をうまく理解できない人は、数学が結果主義の産物であると考えがちだとも思います。
関数型プログラミングが分からない人にとって、nullは奇異なものとして考えられるでしょう。
しかしながら、自己関手（自分を再定義できる向きの矢印を持つ関数のこと） 「２で割り切れるなら商、でなければ null」という関手（2.に説明した矢印）はmayBeモナド（ここで言うモナドは、正確にはクライスリ圏と呼ばれる圏の一種です。）を定義するのです。
# javascript上では…？
## 全てがオブジェクト。
実はjavascriptも同じはずです。その証拠に、null と undefined 以外はconstructorを持ち合わせています。
つまり全ての有効値は、Object.prototypeを継承しており、オブジェクトです。
（かなり乱暴な言い方ですが…）
では、Object.prototypeを拡張して関数型プログラミングに対応するのは悪いことでしょうか？
いえ、私は必要なことだと感じています。
## わざわざ配列に入れて関数型する？
既に値も関数もオブジェクトとして扱われています。
そして、関手、モナドなどは、型クラスとして定義できるものなので、つまりはクラスです（笑）
参考：[functor-monad-applicative.js](https://gist.github.com/tlareg/1b56607c8fca5f235db445a9ac619880)

しかしながらコードを見比べてみると、大差がないところが山ほどあることに気が付くでしょう。
そうです。
そこを埋めるだけで、非純粋関数型言語、javascriptの完成です！

# 関数型プログラミングが分かりやすいわけ
## 文脈に依存したプログラミングをしよう！

我々の思考は何に依存しているか？
それは文脈です。
可読性の高いプログラムというのは、つまり文脈として分かりやすいということです。
何をしているのかが自明なプログラムにコメントは必要ありません。
コメントが必要なソースコードは抽象度が低く、ソースコードによって意味を伝えることができないのです。

モナドは、その手続きをそのまま文脈として書き下すための規則だと理解しています。
だから、Objectは単射にも対応するmapができるべきです。もちろん、圏として扱えるbindもね

以上とりとめもなく書きましたが、以前書いたライブラリに[de.js](https://github.com/johnny-shaman/de.js-webRTC-Template)というのがあります。今は、サンプル用のソースコードのほうしか更新していませんが；

そして次回ライブラリは、もっと純粋関数型言語に近いものを提供できると確信しています。
そう　私にはやらなくてはならないことがある！

以上
お付き合いいただき、ありがとうございました。

その他参考:
[javascript-functor-applicative-monads-in-pictures](https://medium.com/@tzehsiang/javascript-functor-applicative-monads-in-pictures-b567c6415221)
nRF52 の Electrical Specification


# GPIOから取り出せる電流

http://infocenter.nordicsemi.com/pdf/nRF52832_PS_v1.0.pdf
ここの151ページに「20.4 Electrical Specification」がある。

![image](https://qiita-image-store.s3.amazonaws.com/0/139524/cf62eda4-2bb0-20bd-09bc-cdc962ac14f8.png)
（一部抜粋）

上の記述では、例えば GPIOのソース&シンク電流は low drive mode と high drive mode があることなどがわかる。

# 消費電流

BLEを使う場合はここらへんかな。

![image](https://qiita-image-store.s3.amazonaws.com/0/139524/5eb7fe17-8ccc-956e-9d27-ce2e8375dfd1.png)

一緒に使うモジュール（CPUとかメモリとか）の消費電流を足し合わせる必要がある。


![image](https://qiita-image-store.s3.amazonaws.com/0/139524/778a36a2-28b1-a2bc-ff64-e4da6d3b9e08.png)
Superagentでの共通処理

# superagentで共通処理をする方法
Reactで開発しているとsuperagentかfetchAPIを使うことが多いと思うが、superagentで成功時も失敗時でも行う共通処理の書き方を調べるのにちょっと苦労したので投稿。

# 答え
```javascript:superagent.js
fetchData () {
 request
  .get(url)
  // 省略
  .then(res => {
  // 成功時
  })
  .catch(err => {
  // 失敗時
  })
  .then(() => {
  // ここが共通処理
  }
}
```

このように、thenをcatchの後にもう一度書くと、成功時にも失敗時にも実行する処理がかけます。
この書き方だと、２つ目のthenは、１つ目のthenかcatchの中が終了してから実行されます。これは、then内にあるコールバック関数()=>{}によるもので、もし、共通処理を最初に行いたいなら、

```javascript:superagent.js
fetchData () {
 request
  .get(url)
  // 省略
  .then(
  // 共通処理
  )
  .then(res => {
  // 成功時
  }
  .catch(err => {
  // 失敗時
  }
}
```
みたいに、（アロー）関数を外してやればOKです。

# then/catchじゃなくてendとか使ってるのは古い
ちなみに、then/catchでなくend((res,err)=>{})なんか使ってるのはもう古いのでthen/catchに変えていこう

# なんで苦労したか
superagentのドキュメントにはthen/catchは書いてあるが、共通処理については記述がなかった。Githubのソースコードを読み、superagentがPromiseを用いた実装であるとわかった（知らなかった...）ので、Promiseでのやり方を調べたら解決した。fetchAPIも同じようにやれます。

# おまけ
superagentとfetchAPIのどちらがいいかは人によるが、ReactNativeはfetchAPIをサポートしてるので、Reactで使うならfetchAPIでいいんじゃないかと思っている。