OmniAICreator/Qiita-1.07M huggingface dataset:
Capistrano3のdeployでErrno::EINVAL: Invalid argument - recvfrom(2)

Capistranoでdeployコマンドを実行した時、`git:check`タスクで以下エラーとなり失敗する。

```
bundle exec cap production deploy
```

```
cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing on host <example.com>: Invalid argument - recvfrom(2)

Caused by:
Errno::EINVAL: Invalid argument - recvfrom(2)
```

# 環境
- Ubuntu 14.04.5 LTS (Bash on Windows)
- ruby 2.3.3
- bundler 1.16.1

```Gemfile.lock
    capistrano (3.10.1)
      airbrussh (>= 1.0.0)
      i18n
      rake (>= 10.0.0)
      sshkit (>= 1.9.0)
    capistrano-bundler (1.3.0)
      capistrano (~> 3.1)
      sshkit (~> 1.2)
    capistrano-rails (1.3.1)
      capistrano (~> 3.1)
      capistrano-bundler (~> 1.1)
    capistrano-rbenv (2.1.3)
      capistrano (~> 3.1)
      sshkit (~> 1.3)
    capistrano-rbenv-vars (0.1.0)
      capistrano (>= 3.0)
      capistrano-rbenv (>= 2.0)
    capistrano3-puma (3.1.1)
      capistrano (~> 3.7)
      capistrano-bundler
      puma (~> 3.4)
    sshkit (1.15.1)
      net-scp (>= 1.1.2)
      net-ssh (>= 2.8.0)
    net-scp (1.2.1)
      net-ssh (>= 2.6.5)
    net-ssh (4.2.0)

# 他省略
```

# 原因
net-ssh-4.2.0で発生しているよう
`recv(n)`で例外を吐いている。

```ruby:net-ssh-4.2.0/lib/net/ssh/bufferd_io.rb
    def fill(n=8192)
      input.consume!
      data = recv(n)
      debug { "read #{data.length} bytes" }
      input.append(data)
      return data.length
    rescue EOFError => e
      @input_errors << e
      return 0
    end
```

以下が参考になりそうだったが、よくわからなかった…
https://docs.ruby-lang.org/ja/latest/method/BasicSocket/i/recv.html
http://pubs.opengroup.org/onlinepubs/009695399/functions/recvfrom.html


# 回避策
色々調べたが情報がほとんど無く未解決
とりあえずsshではなくhttpsでcloneするようにしたらエラーは出なくなりました。

```ruby:deploy.rb
#set :repo_url, 'git@bitbucket.org:hoge/fuga.git'
set :repo_url, 'https://hoge@bitbucket.org/hoge/fuga.git'
```
vue-cliでエラーが表示され、プロジェクトを作成することができない。

```
npm install -g vue-cli
```

このコマンドを打つと、盛大にエラーがでた。

```
npm ERR! Darwin 16.7.0
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "install" "-g" "vue-cli"
npm ERR! node v6.9.5
npm ERR! npm  v3.10.10
npm ERR! path /usr/local/lib/node_modules/vue-cli/node_modules/abbrev
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall access

npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules/vue-cli/node_modules/abbrev'
npm ERR!     at Error (native)
npm ERR!  { Error: EACCES: permission denied, access '/usr/local/lib/node_modules/vue-cli/node_modules/abbrev'
npm ERR!     at Error (native)
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'access',
npm ERR!   path: '/usr/local/lib/node_modules/vue-cli/node_modules/abbrev' }
npm ERR! 
npm ERR! Please try running this command again as root/Administrator.

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/名前/Desktop/git/フォルダ/npm-debug.log
masashi-macbook:フォルダ 名前$ vue init webpack my-project

```

続くプロジェクトを作成するコマンドもエラーを返してしまい、 `npm run dev` できない。

一生懸命調べた結果、

```
sudo npm install -g vue-cli
```

これで解決した。
あとは今まで通り

```
vue init webpack tutorial_vuejs_todo_management 
```
このコマンドで先に進めます
ESXiのアップグレードを取り消す

ESXiのアップグレードに失敗した場合、以下の手順で前のバージョンの に戻す事が出来ます。

1. ESXi ホストのコンソール画面で、Ctrl+Alt+F2 を押して、[ダイレクト コンソール ユーザー インターフェイス (DCUI)] 画面を表示します。 
2. DCUI 画面で F12 を押して、ESXi ホストのシャットダウン オプションを表示します。 
3. F11 を押して再起動します。 
4. Hypervisor のプログレス バーの読み込みが開始されたら、Shift+R を押します。ポップアップ ウィンドウに次のような警告メッセージが表示されます。

```
現在のハイパーバイザーが完全に
ビルド X.X.X-XXXXXX で置換されます。よろしいですか?[Y/n]
```

5. Shift+Y を押すと、該当するビルドがロールバックされます。 
6. Enter を押して起動します。 


---------------------------------------------------
バージョン情報を表示するコマンド

```
[root@esxi:] esxcli system version get
      Product: VMware ESXi
      Version: 6.5.0
      Build: Releasebuild-531038
      Update: 0
      Patch: 19
```
クロスドメインとは

#クロスドメインとは
クロスドメインとはなんぞやっていうやつのメモ
AjaxでとてもリッチなWebアプリケーションを開発できるようになった。でも、ここで問題がそれがクロスドメイン問題らしい。

例えばブラウザからAサーバーにリクエストを送った場合、ブラウザからAjaxで別のサーバーにデータアクセスをした場合、セキュリティ面で引っかかるらしい
NGINXで接続元IPアドレス(X-Forwarded-For)を設定する

`NGINX(Proxy)`で接続元IP（`X-Forwarded-For`）を設定します。
オンプロミスで本番環境は`BIG-IP`が存在して、検証にはない場合など使えるかもしれません。
検証はdocker-composeで実施します。

## 設定

> `http, server, location`ディレクティブにproxy_set_headerで追加するだけです。

https://www.nginx.com/resources/admin-guide/reverse-proxy/　

```:nginx.conf
    location / {
        proxy_set_header X-Forwarded-for $remote_addr; <-----------追加
        proxy_pass   http://web;
    }
```

> `$http_x_forwarded_for`は`log_format`にデフォルトで存在するため、上記のみでwebサーバ側のログに出力されるはずです。
> `$http_x_forwarded_for`が存在しない場合は、下記の様に`log_format`を修正してください。

```:nginx.conf
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
```

※[参考ソースコード](https://github.com/Thirosue/docker-sample/tree/master/nginx_x_forwarded_for "")

##　検証

+ コンテナ起動

```:bash
$ git clone https://github.com/Thirosue/docker-sample.git
$ cd docker-sample/nginx_x_forwarded_forpwd/
$ docker-compose up -d
Creating proxy ... done
Creating proxy ...
$ docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED                  STATUS              PORTS                  NAMES
782e7e485bba        nginx:1.13.1-alpine   "nginx -g 'daemon of…"   Less than a second ago   Up 2 seconds        80/tcp                 web
5e8a5f7c6e59        proxy                 "nginx -g 'daemon of…"   Less than a second ago   Up 2 seconds        0.0.0.0:8080->80/tcp   proxy
```

+ アクセス

> ローカルPCからブラウザで以下に接続

http://localhost:8080/

+ 確認

> proxyサーバの`$remote_addr`がwebサーバの`$http_x_forwarded_for`に設定されていることが確認できる

```:bash
################ proxyサーバの$remote_addrが
$ docker logs proxy
172.20.0.1 - - [16/Jan/2018:06:52:03 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36" "-"
################ webサーバの$http_x_forwarded_forに設定されていることが確認できる
$ docker logs web
172.20.0.3 - - [16/Jan/2018:06:52:03 +0000] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36" "172.20.0.1"
```
[HHKB Tips]capsをctrlに割り当てた状態でcapsのON/OFFをするためのショートカット


表題の通りですが、capsキーをctrlキーに割り当てて使っています。
HHKBをたまに、誤操作でcapsがONになって、イラッとするのでショートカットを調べました。

```
capsのON/OFF
fn + tab		
```

でやれます。

## 編集後記

macのログイン画面でcapsロック状態になってしまい、ニッチもサッチモいかなかったのです。
SpringSecurityの認証済みユーザの情報にuserId,password以外をもたせる方法と参照方法

#概要
自分用メモ、SpringSecurity関連のチュートリアルでは、認証に使うuserId,passwordはセッションから参照できるとあるが、他の任意のパラメータはどうなのとおもっただけです。
何の事はない、UserDetailsをimplementsしたクラスにgetterをつければいいだけでした。。


##簡単なクラス例

```java

public class User {
    private String userId;
    private String password;
    private String hoge;
    //getter,setter省略
}

public class UserDetailsImpl implements UserDetails {

    private final User user;
    
    public UserDetailsImpl(User user) {
        this.user = user;
    }

    public String getHoge() {
        return user.getHoge();
    }
    //Overrideすべきメソッド省略
}

```

認証方法は以前書いた記事を見てください
[SpringSecurityでDBログイン認証処理を実装してみた(MyBatis使用)](https://qiita.com/Hyuga-Tsukui/items/8c7e3d9201d07d2be089)
[SpringSecurityでDBログイン認証処理を実装してみた(MyBatis使用)その２](https://qiita.com/Hyuga-Tsukui/items/5b8e5173847d4791727e#_reference-296c0f6b0821165131b8)

###上記のようなユーザの認証後、セッションに保存されたユーザ情報にコントローラでアクセスする方法。AuthenticationPrincipalアノテーションを利用

```java
@Controller
public class Controller {
    
    @RequestMapping("/")
    public index(@AuthenticationPrincipal UserDetailsImpl userDetails) {
        System.out.println(userDetails.getUserId) // userId
        System.out.println(userDetails.getPassword) //password
        System.out.println(userDetails.getHoge) //hoge
    }
```
###おまけ、Thymeleafから参照する方法

```html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"> <!-- これを追加してThymeleafからSpringSecurityを利用 -->

<!-- 省略 -->
<body>
  <h>こんにちは、<span sec:authentication="principal.userId"></span>さん</h> <!-- principal.メンバ変数名　で参照できる　-->
</body>
someFunc(arr > n)という表現

ほとんど`numpy`を使ったことがなく、`np.where`に出会って一瞬だけ怯んだ時のメモ。

JavaやJavaScript等の言語をやっている人からすると、表題の関数に渡される引数は`true`(Pythonでは`True`)か、`false`(Pythonでは`False`)になるとお思いではないでしょうか？

ところがどっこい、それ以外が引数に渡される言語があるのです。その一つがPythonです。

Pythonには、[特殊メソッド](https://docs.python.jp/3.3/reference/datamodel.html#special-method-names)なる素晴らしい機能がありまして、演算子に対する振る舞いを、クラスごとに自前で定義することが可能です。もちろん比較演算子もそうです。

```py3
class YJSNPI(object):
    def __init__(self,val):
        self._v = val
    
    def __eq__(self,other):
        if (self._v == other) in (114514,True):
            return 114514
        else:
            return 1919810

if __name__ == '__main__':
    a = YJSNPI(5)
    b = 5
    print(a == b) # => 114514

    c = YJSNPI(5)
    print(a == c) # => 114514
    
    d = YJSNPI(10)
    print(a == d) # => 1919810
```

これと似た感じで、`True`や`False`以外のものを返させることができます。

以下ろくにドキュメントも読まず適当に予測して似せてみた`where`関数の実装です。`numpy`の振る舞いを見る限りもっと複雑なんでしょうけど、とりあえず比較演算子で対象要素、または対象要素のインデックスを取り出すことを目標としました。

```py3
class my_list(list):

    def __lt__(self, s):  # self.item < s
        return my_list(v < s for v in self)

    def __le__(self, s):  # self.item <= s
        return my_list(v <= s for v in self)

    def __eq__(self, s):  # self.item == s
        return my_list(v == s for v in self)

    def __ne__(self, s):  # self.item != s
        return my_list(v != s for v in self)

    def __gt__(self, s):  # self.item > s
        return my_list(v > s for v in self)

    def __ge__(self, s):  # self.item >= s
        return my_list(v >= s for v in self)

    def __getitem__(self, index):
        if type(index) in (list, my_list):
            return my_list(v for v, b in zip(self, index) if b)
        else:
            return super().__getitem__(index)

    @staticmethod
    def where(inds, *args):
        if len(args) >= 2:
            return my_list(args[not b] for b in inds)
        elif len(args) == 1:
            raise ValueError('either both or neither of x and y should be given')
        else:
            return my_list(i for i, b in enumerate(inds) if b)

if __name__ == '__main__':
    arr = my_list([8, 1, 7, 2, 6, 3, 5, 4, 5, 3, 7, 2, 8, 1])
    print(my_list.where(arr >= 5, 1, 0))
    # => [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
    print(my_list.where(arr != 5))
    # => [0, 1, 2, 3, 4, 5, 7, 9, 10, 11, 12, 13]
    # print(my_list.where(arr<5,2)) # => ValueError
    print(arr[arr >= 5]) # => [8, 7, 6, 5, 5, 7, 8]
```

@shiracamus様からいただいたコメントを元に修正させて頂きました。ありがとうございます。m(_ _)m
んで、結局Contributionのうち、投稿で勝ち得たいいねはどれぐらいなのさ

自分の投稿をすべて取得してJSONで保存します。

# コード

```ruby:qiita.rb
require "qiita"
require "json"

page = 1
client = Qiita::Client.new(access_token: "トークン")

items = []
loop do
  res = client.list_authenticated_user_items({per_page: 100, page:page})

  items.concat(res.body)

  break if res.next_page_url.nil?
  page += 1
end

puts JSON.generate(items)
```

`gem install qiita`が必要。
トークン使ってauthenticated_user_itemsを拾わなくても、通常のitem検索でuser:ユーザーid としても大丈夫なはずだ。

未認証でもリクエスト制限は一時間に60回。
一リクエストで投稿は100件取るので、5000ふがふが投稿数があってもまだ大丈夫。

これ自体は投稿記事を全部取得してJSONで吐き出すプログラム。
rubyで集計しても良かったが、後々別のことに活用できそうだったので、集計はjqにお願いした。



# 集計方法

```shell
ruby qiita.rb  | jq '[.[].likes_count] | add'
```


# 利用ライブラリ

* [increments/qiita-rb: Qiita API v2 client library and CLI tool, written in Ruby](https://github.com/increments/qiita-rb)

increments謹製！
自作の参考に既存物を探していたら家元が作っていたので試してみたかった。

* [jq](https://stedolan.github.io/jq/)

jq jq 説明無用

# 参考 モチベUP記事 その他

* [API v2 で Qiita の「いいね！」がサポートされました - 他 - Qiita Blog](http://blog.qiita.com/post/165002643239/like-apis-for-qiita-are-available)
* [jq コマンドを使う日常のご紹介 - Qiita](https://qiita.com/takeshinoda@github/items/2dec7a72930ec1f658af)
* [【まとめ】Qiita API ライブラリ/ラッパー - Qiita](https://qiita.com/suin/items/857f839e894f5da787f8)  

* [Ruby で do ~ while xxx の条件文を使いたい - Qiita](https://qiita.com/ironsand/items/b1ddaf8e489edfb327ed)
* [Rubyで複数の配列を１つの配列に結合するために色々やってみた - Qiita](https://qiita.com/na1412/items/65f883896c85011d6509)

***

* [Qiita API v2 を使って自身の全投稿をエクスポートするJavascriptを書いた - Qiita](https://qiita.com/yumetodo/items/ea9ecb5a30dbd120f955)

***

* [投稿記事やコメントに「いいね」できるようになりました（Contributionの算定基準も変わります）... - Qiita Blog](http://blog.qiita.com/post/153200849029/qiita-like-button)
* [Qiitaの新しいContribution算定ロジックを解読してみた - Qiita](https://qiita.com/iida-hayato/items/f756d1d1dc75ed17c46b)


# 動機

Contributionは算定ロジックにもある通り、編集リクエストとコメントのいいねも含まれてしまう。(いいことだ)
でも、編集リクエストの本来期する、「記事をより良くするリクエスト」ではなくて、
ちょっとしたtypo,リンク・タグミス,コードハイライトばっかり送っていた。
それでじりじり上がる通知が来ないContributionの上昇に複雑な気持ちだったので、自分がどれだけ**ゲタ**を履いているか確認したくなった。

でも実装当時はAPIが無くて、

[Qiita記事のストック数を確認するbookmarklet - Qiita](https://qiita.com/nh321/items/bcb57827aa08bd720596)

のようにスクレイピングするかで敬遠していた。

Qiitaのデータを扱った集計はたくさんあるけど、
記事単位だったり[^1] 
ランキングだったり(範囲外)。
全ユーザーの集計でもやっぱり集計上ユーザー画面を使うからか、Contributionだったり。
[Qiitaのあれこれをひたすら分析してランキング - Qiita](https://qiita.com/t_nakayama0714/items/07ce8bf3501268f96fe3)

と、「ランキングに乗らない程度のユーザーの投稿のみの合計いいね数」が、検索能力の低さも相まってQiita内では見つけられなかった。
=気にする人居ないってことなんですが…

今回はAPI実装後にモチベが持ち上がったのでさくっと作りました。

# 余話

で、肝心の結果が926でした。
50Contribution以上もゲタ履いてるとはさてはテングだなオメー
~~…となるはずでしたが、週をまたぐと計算方法が変わったのか、表示上が933。小数点込み合算後切り捨てから切り捨ててから合算に変わったのかな？~~
と記事を書いていたら計算方法がJust now?戻ったみたいです。
高いゲタを履いて頑張ります。

(anyenv+)rbenv+fishは設定が面倒臭い

[^1]: 増分計算や独自の重み付けすごいと思う
WordPressをEC2+ELB構成に移行したらハマった(上司が)

httpsで運用していたWordPress(4.8.x)を、EC2+ELB構成に移行したときにハマった(上司が)ので、それを記録する。

# (上司が)やったこと
- WordPressソースとテーブルダンプをEC2(& mysql)に展開
- `wp-config.php`に以下の行を追記

```
$_SERVER['HTTPS'] = 'on';
```

# (上司が)ハマった事象
- 管理画面にログインすると以下のエラーが表示され、にっちもさっちも行かなくなる

```
You do not have sufficient permissions to access this admin page.
Reason: The current user doesn't have the "read" capability that is required to access the "ダッシュボード" menu item.
```

# 直し方
`wp-config.php`の

```    
$_SERVER['HTTPS'] = 'on';
```

は、

```
require_once(ABSPATH . 'wp-settings.php');
```

より先に書くべし

以上

# (追記) `$_SERVER['HTTPS'] = 'on';` の推奨すべき書き方
公式リファレンスには、以下のように記載されています。
https://codex.wordpress.org/Function_Reference/is_ssl

```
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
    $_SERVER['HTTPS'] = 'on';
```
minikubeでkubernetes1.9を試してみる

# minikube

https://github.com/kubernetes/minikube

ローカル環境でkubernetesを立ち上げることができるソフトウェアです。
Kubernetes1.9が出たのでminikubeを使ってお試し環境を作ろうとしたらちょっとハマったのでメモ。

# いつものようにつくってみる（うまくいかない）

```
$ minikube start --kubernetes-version=v1.9.0
Invalid Kubernetes version.
The following Kubernetes versions are available when using the localkube bootstrapper:
    - v1.8.0
    - v1.7.5
    - v1.7.4
    - v1.7.3
    - v1.7.2
    - v1.7.0
    - v1.7.0-rc.1
    - v1.7.0-alpha.2
    - v1.6.4
    - v1.6.3
    - v1.6.0
    - v1.6.0-rc.1
    - v1.6.0-beta.4
    - v1.6.0-beta.3
    - v1.6.0-beta.2
    - v1.6.0-alpha.1
    - v1.6.0-alpha.0
    - v1.5.3
    - v1.5.2
    - v1.5.1
    - v1.4.5
    - v1.4.3
    - v1.4.2
    - v1.4.1
    - v1.4.0
    - v1.3.7
    - v1.3.6
    - v1.3.5
    - v1.3.4
    - v1.3.3
    - v1.3.0
```

あれ？まだサポートしていない？
どうもデフォルトの挙動であるlocalkubeを使った方式だとまだv1.9.0には対応していないようだ。

## --bootstrapper=kubeadm で作ってみる(うまくいく)

`--bootstrapper=kubeadm` を指定することでlocalkubeの代わりにkubeadmを使って構築してくれる。

```
$ minikube start --kubernetes-version=v1.9.0 --bootstrapper=kubeadm
Starting local Kubernetes v1.9.0 cluster...
Starting VM...
Getting VM IP address...
Moving files into cluster...
Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.
Loading cached images from config file.
```

本当にできているか確認

```
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.1", GitCommit:"3a1c9449a956b6026f075fa3134ff92f7d55f812", GitTreeState:"clean", BuildDate:"2018-01-04T19:59:01Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.0", GitCommit:"925c127ec6b946659ad0fd596fa959be43f0cc05", GitTreeState:"clean", BuildDate:"2017-12-15T20:55:30Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"linux/amd64"}
```

確かに　Server Versionが1.9.0になっている。


## はまったところ
minikubeで作ったクラスタが既にある場合は、deleteしてから実行しないとうまくいかないことがあった。

```
$ minikube start --kubernetes-version=v1.9.0 --bootstrapper=kubeadm
Starting local Kubernetes v1.9.0 cluster...
Starting VM...
Getting VM IP address...
Moving files into cluster...
Downloading kubeadm v1.9.0
Downloading kubelet v1.9.0
Finished Downloading kubeadm v1.9.0
Finished Downloading kubelet v1.9.0
Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
E1226 16:01:38.782453   98149 start.go:270] Error restarting cluster:  restarting kube-proxy: waiting for kube-proxy to be up for configmap update: timed out waiting for the condition
```

kube-proxyがうまくアップデートできない

minikubeの状況を確認

```
$ minikube status
minikube: Running
cluster: Stopped
kubectl: Correctly Configured: pointing to minikube-vm at 192.168.99.103
```

ひとまず削除する。

```
$ minikube delete
Deleting local Kubernetes cluster...
Machine deleted.
```

これで、上の手順を実行したらうまく動きました。
よくわからないときは一度deleteしましょう。
gnuplot tips

# gnuplot コマンド

## ticsの向きと位置を整える

```gnuplot
set xtics rotate by 90 right
set xtics center offset 0,0.5
```

## フォントの設定

```gnuplot
set term pngcairo transparent truecolor font "Times New Roman,25" size 1200,1000
```

## データプロットの方法を一括で指定

```gnuplot
set style data dot
```

### プロットの種類（キーワード）

- 直線 `line`
- ドット `dot`
- ポイント `points`

## コメント行の指定

```gnuplot
set datafile commentschars "@|#"
```

## セパレータの指定

```gnuplot
set datafile separator ","
```

または

```gnuplot
set datafile separator comma
```

## 軸目盛間隔の設定

- x軸→xtics
- y軸→ytics
- z軸→ztics

```gnuplot
set xtics 1
```

## paletteの色指定

```gnuplot
set palette defined (0"midnight-blue",1"blue",5"cyan",9"orange",13"red",14 "white")
```

色は名前ではなくて，color codeでも指定できる。

カラーコード
https://www.computerhope.com/htmcolor.htm
https://www.w3schools.com/colors/colors_picker.asp
https://www.rapidtables.com/web/color/html-color-codes.html

## スクリプト内に，任意のデータを作成してプロット

```gnuplot
$map1 << EOD
5 4 3 1 0
2 2 0 0 1
0 0 0 1 0
0 0 0 2 3
0 1 2 4 3
EOD

plot '$map3' matrix rowheaders columnheaders using 1:2:3 with image
```

## プロットするデータをプロット時に演算する

`using 1:($2*100)`

```gnuplot
plot "out_do4_matrix.dat" matrix using 1:2:3 with image, \
     "out_do4_matrix.dat" matrix using 1:2:($3 == 0 ? "" : sprintf("%g",$3) ) with labels
```

## Linuxのコマンドを実行する

```gnuplot
!ls
```

## 数式をプロットする

```gnuplot
set xrange [-10:10]
plot x*x
```

## グリッド線を描く

```gnuplot
set grid
```

**(ex)**

```gnuplot
set grid
set xtics 1
p "out_do2.txt" w l
```

```:out_do2.txt
1 1.16795
2 0.60632
3 6.7047
4 6.62016
5 1.79147
6 1.34219
7 2.84085
8 3.44192
9 2.30184
10 2.34568
11 1.79934
12 1.4279
13 1.34699
14 1.36219
15 0.847737
16 0.512655
17 0.156619
18 0.112709
19 0.00968867
20 0.00533321
21 0.010222
22 0.0148886
23 0.0161108
24 0.000555543
25 0.0012222
26 0.000111109
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/99215/f093bdad-4d63-4d7a-59da-f7997100befa.png)
flowtype と immutablejs メモ

会社のプロジェクトに flow を導入しようとしたメモ。
環境は以下。

- React
- Redux
- Redux-Observable
- Immutable
- normalizr

今どきのテンプレのようなフロントエンド環境です :sparkle: 

## flow のインストール
https://qiita.com/takanorip/items/603365d2471104ac7d51 を参照

## immutable.js のtypeを使う

e.g.

```javascript
// @flow
import React from 'react';
import { Map } from 'immutable';
import type { Map as MapType } from 'immutable';

type Props = {
  users: MapType,
  selected: string,
};

type State = {
  selected: string,
};

export default class UserSelector extends React.Component<Props, State> {
  static defaultProps = {
    users: new Map()
  };
  constructor(props: Props) {
    super(props);
    this.state = { selected: props.selected };
  }
  componentWillReceiveProps(nextProps: Props) {
    if (nextProps.selected) {
      this.setState({ selected: nextProps.selected });
    }
  }
  render() {
    this.props.users.valueSeq().map(user => (
      <div>
        {user.get('id') === this.state.selected && <p>{user.get('name')} selected</p>}
        {user.get('id') !== this.state.selected && <p>{user.get('name')}</p>}
      </div>
    ));
  }
};
```
こんな感じ。動作確認してないですが、たぶん動くんじゃないかと予想 :thinking:
[nodejs] supertestのendは使わなくてもよい

supertestのREADMEを読むと、リクエスト実行の最後に`end()`関数でエラーを処理したり、`expect`の第二引数に`done`を渡してやるみたいなことが書かれていて、あまり深く考えずにそのまま書いていたのですが、`done`を使わずに`Promise`を返すように書きたいので何とかできないか色々やってみました。

```js:test/test.js
describe('GET /users', () => {
  it('respond with json', done => {
    request(app)
      .get('/users')
      .expect(200)
      .end(function(err, res) {    // この辺がうっとうしい
        if (err) return done(err)  // この辺がうっとうしい
        assert.ok()
        done()                     // この辺がうっとうしい
      })
  })
})
```

READMEをちょっとスクロールしたら **Promise support** って書いてあったので普通にいけそうです。
こんな感じになりました。

```js:test/test.js
describe('GET /users', () => {
  it('respond with json', () => 
    request(app)
      .get('/users')
      .expect(200)
      .then(res => {
        assert.ok()
      })
  )
})
```

# supertestが返すTestオブジェクト
supertestで使う`.get()`とか`.expect()`みたいな関数は、supertestで実装されている`Test`というクラスのインスタンスを返します。
これ自体は`Promise`ではないのですが、`then`と`catch`を実装していて`Promise`を返してくれます。さらにこの`Promise`が、内部で`end()`を実行してくれて、エラーが発生したときには`reject(err)`してくれるので、こっちを使ったほうがスッキリ書けていい感じです。

# 独自の例外処理
あまり思いつかないですが、どうしても独自の例外処理を書く必要が出てきた場合は、`catch`に書けば実行されます。
ただし、エラーを投げないと、例外発生時にもテストが正常終了してしまうので注意です。

```js:test/test.js
describe('GET /users', () => {
  it('respond with json', () => 
    request(app)
      .get('/users')
      .expect(200)
      .then(res => {
        assert.ok()
      }).catch(err => {
        console.error(err)
        throw err
      })
  )
})
```

- node 9.4.0
- supertest 3.0.0
- superagent 3.8.2
Fuelでリクエストパラメータを付与したHTTP通信

# 検証環境
この記事の内容は、以下の環境で検証しました。

* Intellij IDEA ULTIMATE 2017.2
* Kotlin 1.1.61
* Fuel 1.12.0
* Java 1.8
* Gradle Projectで作成

# はじめに
下記の記事では、Fuelを利用したHTTP通信を説明しました。今回は、リクエストパラメータを送信する方法について説明していきます。

https://casareal-ls.qiita.com/naoi/items/bd97274e012501f884aa

# 目標
Fuelライブラリーを利用したHTTP通信で、リクエストパラメータを送信する実装方法を理解する。

# 実装

## 準備
Fuelを使用するため、Gradleに以下を追記します。

```groovy
repositories {
    jcenter()
}

dependencies {
    compile 'com.github.kittinunf.fuel:fuel:1.12.0'
}
```

## 実装例

実際にFuelでパラメータを付与したHTTP通信のコード例です。

```kotlin
package jp.co.casareal.fuelparam

import com.github.kittinunf.fuel.httpGet
import com.github.kittinunf.fuel.httpPost


fun main(args: Array<String>) {

    // GETによるHTTP通信
    "http://localhost:8080/param".httpGet(listOf("q" to "casareal")).response { request, response, result ->
    }

    // POSTによるHTTP通信
    "http://localhost:8080/param".httpPost(listOf("bbb" to "ccc")).response { request, response, result ->
    }

}
```

## 解説
リクエストパラメータを付与するには、下記の形式で記述します。

```kotlin
"URLを記述".httpXXX(listOf("パラメータ名" to "値")).response関数 or responseString関数
```

* 付与するリクエストパラメータは、httpXXXメソッドの引数にPairのリスト形式で渡します。
* 付与したリクエストパラメータの値は、エンコードされたうえでサーバに送信されます。
* httpPost関数で送信すると、送信するデータはHTTPリクエストのボディ部に格納されます。

# まとめ
Fuelだとリクエストパラメータの付与はシンプルに実装できます。
また、リクエストパラメータを付与してHTTP通信する方法は、この記事に乗せている関数以外にも存在するの本家のサイトで確認してください。
デコレーター付きのクラスを返す関数とESLint

React + MobX のデコレーターを使って、デコレーター関数を自作しようとした時、ESLintで詰まった。

こう書いても、動作はするがESLintが死ぬ。

```js:RequireLogin.js(誤)
import React from 'react'

@inject('userStore')
@observer
export default (ComposedComponent: *) => class RequireLogin extends React.Component<Props> {
  render() {
    if (this.props.userStore.guest) return <div>LOGIN REQUIRED</div>
    else return <ComposedComponent />
  }
}
```

ESLintを通すにはこうする。

```js:RequireLogin.js(正)
import React from 'react'

export default (ComposedComponent: *) => {
  @inject('userStore')
  @observer
  class RequireLogin extends React.Component<Props> {
    render() {
      if (this.props.userStore.guest) return <div>LOGIN REQUIRED</div>
      else return <ComposedComponent />
    }
  }

  return RequireLogin
}
```

ちなみにこれの使い方は単純で

```js:Home.js
import React from 'react'
import requireLogin from './RequireLogin'

@requireLogin
export default class Home extends React.Component<Props> {
  render() {
    return <div>Hello</div>
  }
}
```


参考: https://github.com/yannickcr/eslint-plugin-react/issues/419
scrapydにクローラーのプロジェクトを登録してからデーモン化するDockerfile

## なにをするの？
　1. サーバーを一時立ち上げ
　2. サーバー初期設定
　3. サーバー一旦終了
　4. CMDでデーモン化

これを一度のビルドで収めようと思います。ニッチなTipsかもしれませんが、サーバー立ち上げないと初期設定できない状況は他でもありそうなのでまとめておきます。

## scrapydについて
　
　scrapydは、サーバを立ち上げたあとに管理したいCrawlerプロジェクトを登録(deploy)してあげないといけません。Dockerでscrapydだけ立ち上げて、ホスト側でdeployしてもよいのですが、半自動になるためDockerの魅力が減ってしまいます。サーバー立ち上げ、初期設定、サーバー一旦終了、CMDでデーモン化を一度のビルドで収めようと思います。

## コードと説明

全Dockerfileはこちら。
GitHub https://github.com/naronA/docker_news_crawler

Raspberry Piで動かしているので`FROM resin/rpi-raspbian`になっていますがDebian系なら大丈夫です。
途中で自作のクローラーをgithubのリポジトリをcloneしていますので、自宅の環境じゃないと動きません。
[news_crawler](https://github.com/naronA/news_crawler)scrapy.confに設定してあるFTPサーバーアドレスを変えれば動くかも？

以下コードの抜粋です。

``` dockerfile
WORKDIR /root
RUN git clone https://github.com/naronA/news_crawler news_crawler

WORKDIR /root/news_crawler
RUN pip3 install -r requirements.txt scrapyd scrapyd-client
RUN crontab cron.conf
RUN cp -rf scrapyd.conf /root/scrapyd.conf

RUN cd /root \
    && scrapyd & sleep 10s \
    && cd /root/news_crawler/news_crawler \
    && scrapyd-deploy \
    && curl http://localhost:46800/listprojects.json

EXPOSE 46800

WORKDIR /root
CMD ["/usr/local/bin/scrapyd", "--pidfile="]
```

　大切なのは　`cd /root && scrapyd`して最後に`WORDDIR /root`としているとことろ。scrapydは、起動したディレクトリにdbsディレクトリを作成して設定を保存するので、初期設定とDockerのデーモン化時のディレクトリをあわせる必要があります。
　あとは、scrapydをバックグラウンドにするので`scrapyd & sleep 10s`のようにsleep 10sを入れましょう。sleepがないとサーバーが立ち上がる前にdeployしようとしてしまい失敗します。各RUNでshの新しいプロセスが立ち上がり、最後にプロセスが終了するのでscrapydとscrapyd-deployは1つのRUNの中に収めましょう。

もっと賢いやり方があるかもしれませんが、自宅のサーバーはこれで動いております。
arduinoでi2c　その3

#概要
arduinoでi2cやってみた。
フルスクラッチでi2cスキャナー、書いてみた。


#サンプルコード

```
#include <inttypes.h>
#include <compat/twi.h>

#define F_CPU 			16000000UL
#define SCL_CLOCK 		50000L
void i2c_init(void)
{
	TWSR = 0;
	TWBR = ((F_CPU / SCL_CLOCK) - 16) / 2;
}
unsigned char i2c_start(unsigned char address)
{
	uint8_t twst;
	TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
	while (!(TWCR & (1 << TWINT)));
	twst = TW_STATUS & 0xF8;
	if ((twst != TW_START) && (twst != TW_REP_START)) return 1;
	TWDR = address;
	TWCR = (1 << TWINT) | (1 << TWEN);
	while (!(TWCR & (1 << TWINT)));
	twst = TW_STATUS & 0xF8;
	if ((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK)) return 1;
	return 0;
}

void setup()
{
	unsigned char c;
	unsigned char address;
	int nDevices;
	Serial.begin(115200);
	i2c_init();
	Serial.println("\nI2C Scanner");
	Serial.println("Scanning...");
	nDevices = 0;
	for (int i = 1; i < 127; i++)
	{
		address = i << 1 | 0;
		c = i2c_start(address);
		if (c == 0)
		{
			Serial.print("I2C device found at address 0x");
			if (i < 16) Serial.print("0");
			Serial.print(i, HEX);
			Serial.println("  !");
			nDevices++;
		}
	}
	if (nDevices == 0) Serial.println(" No I2C devices found\n");
	else Serial.println("done\n");
}
void loop()
{
	delay(100);
}

```

以上。
Sublime Textで日本語文字列を検出するには?

ローカライズ作業で日本語のまま残っている箇所がないかを確認するために便利です。

正規表現オプションを有効にした検索窓に
`[^/x01-/x7E]+`
と入れると、全角文字だけを検索できます。
要らなくなった古いAngularプロジェクトを公開した

[一人もくもく会](https://mokumoku.alphabrend.com) をリリースした当時、フロントはAngular2を使っていた。ただ、リリースしてすぐ下記の理由で使うのをやめた。

* ちゃんとクローラが画面を解析できていなかった（詳しく調べてはないが多分クローラの場合だけエラーが出てたっぽい）
* 一人でAngularはしんどすぎて無理

それでもいい勉強にはなったし、全く使ったことない人からしたら得るものもあるかもしれないので一応Githubに公開しておくことにした。（決してきれいなものではない）

[https://github.com/dala00/mokumoku-front](https://github.com/dala00/mokumoku-front)

リポジトリを見れば全部の情報はあるのだが、一応下記にいくつか特筆しておく。

### 共通ステートを扱うクラス

Angularを使っているとデータを適当に扱うと、変数などに入れてもちゃんとアプリケーションには反映されないので、ちゃんとAngularのライフサイクルに組み込むような管理クラスを作らなければならない。

なのでObservableやSubjectを駆使してクラスを作った。当時適当に試行錯誤して作ったので現在の正しいやり方とは違うかもしれない。

```typescript:data.serivice.ts
import { Injectable } from '@angular/core';
import { Subject, Observable, Subscription } from 'rxjs';
import { User } from '../models/user';

@Injectable()
export class DataService {

  data: any[];
  private updateSources: any;
  private syncs: any;

  constructor() {
    this.data = [];
    this.updateSources = {};
    this.syncs = {};
  }

  set(key: any, value?: any) {
    if (value !== undefined) {
      const originalKey = key;
      key = {};
      key[originalKey] = value;
    }

    this.data = Object.assign(this.data, key);
    for (let currentKey in key) {
      if (this.updateSources[currentKey] != undefined) {
        this.updateSources[currentKey].next(key[currentKey]);
      }
    }
  }

  get(key: string | number) {
    if (this.data[key] == undefined) {
      return null;
    }
    return this.data[key];
  }

  sync(key: string | number, callback: (data: any)=>void) {
    if (this.syncs[key] == undefined) {
      const updateSource = new Subject<any>();
      this.updateSources[key] = updateSource;
      this.syncs[key] = updateSource.asObservable();
    }
    this.syncs[key].subscribe(result => callback(result));
    if (this.data[key] != undefined) {
      callback(this.data[key]);
    }
  }

  del(key: string | number) {
    delete this.data[key];
  }
}
```

### WerckerによるCI

WerckerによるCIをしているのでそのサンプル。ただテストするだけではなく、カバレッジを取って適当なサーバーに送信して見れるようにしている。テストにChromeが使われるので、chromiumが入ったイメージをベースに作ったboxを使っている。

```yaml:wercker.yml
box: dala00/chromium-xvfb-angular-cli

build:
  steps:
    - npm-install

    - script:
        name: npm list
        code: |
          npm list --depth=0

    - script:
        name: test start
        code: |
          ng test --single-run --code-coverage

    - script:
        name: echo nodejs information
        code: |
          echo "node version $(node -v) running"
          echo "npm version $(npm -v) running"

coverage:
  steps:
    - add-ssh-key:
        keyname: COVERAGE_KEY
        host: hostname

    - create-file:
        name: write key
        filename: $HOME/.ssh/id_rsa
        overwrite: true
        content: $COVERAGE_KEY_PRIVATE

    - script:
        name: Set permissions for ssh key
        code: chmod 600 $HOME/.ssh/id_rsa

    - script:
        name: Scp coverage html
        code: scp -o StrictHostKeyChecking=no -r coverage/* user@host:dir
```

### デプロイスクリプト

deploy.js。ローカルで本番ビルドしたものをデプロイするプログラムを作っていた。ロールバックとかもできるようにしている。

まあ本来こんなのはCIで行うか、本番環境でビルドさせるものだと思うので必要ないと思うが。
/ 1つで複数行コメントアウトする方法

# はじめに
`/` 1つで複数行コメントアウトする方法です。
`/**/`でコメントアウト、`//`で一行コメントアウトが出来る言語でないと出来ません。

# やり方
最初の`//*`は`//`が`*`をコメントアウトしています。`/`を一つ消すと`/*`になり全体がコメントアウトされます。
最後を`//*/`にしてるのは、最初の`//`が`*`をコメントアウトした時に`*/`が残ってしまうので、`//`で`*/`をコメントアウトしています。
>* コメントアウト有効
>
>``` c
>/*
>for (int i = 1; i <= 10; i++) {
>  printf("%d ", i);
>}
>//*/
>```
>
>* コメントアウト無効
>
>``` c
>//*
>for (int i = 1; i <= 10; i++) {
>  printf("%d ", i);
>}
>//*/
>```

`//*`を`// /*`にしても大丈夫です。エディタの機能で一行コメントアウトが出来る場合はこちらの方が楽です。自分もこちらをよく利用しています。
>* コメントアウト無効
>
>``` c
>// /*
>for (int i = 1; i <= 10; i++) {
>  printf("%d ", i);
>}
>// */
>```

# 応用編
これを応用することで複数のコメントを切り替えることが出来ます。
切り替えたいコードの間に`/*/`を挟むことで切り替えが出来ます。
パターンAの場合は`/*/`が`/*`として利用され、パターンBの場合は`/*/`が`*/`として利用されます。
>* パターンA
>
>``` c
>// /*
>printf("Pattern A\n");
>/*/
>printf("Pattern B\n");
>// */
>```
>
>* パターンB
>
>``` c
>/*
>printf("Pattern A\n");
>/*/
>printf("Pattern B\n");
>// */
>```

`/*/`を2行挟むことで全体を有効にしたり好きなパターンのみを有効にさせる方法もあります。
1行目の`/*/`が前のコードのコメントアウトを管理していて、2行目の`/*/`が次のコードのコメントアウトを管理しています。

>* 全体有効
>
>``` c
>// /*
>printf("Pattern A\n");
>/*/
>/*/
>printf("Pattern B\n");
>// */
>```
>
>* 全体無効
>
>``` c
>/*
>printf("Pattern A\n");
>/*/
>/*/
>printf("Pattern B\n");
>// */
>```
>* パターンA C Dが有効
>
>``` c
>// /*
>printf("Pattern A\n");
>// /*/
>/*/
>printf("Pattern B\n");
>/*/
>// /*/
>printf("Pattern C\n");
>/*/
>/*/
>printf("Pattern D\n");
>// /*/
>/*/
>printf("Pattern E\n");
>// */
>```

# (おまけ) スライドです。
[https://www.slideshare.net/smicle/slash-1](https://www.slideshare.net/smicle/slash-1)
radiko の利用できる放送局の一覧をJSONに変換

radiko.jp で利用できる放送局は次の API で取得できます。
例えば、北海道の放送局は、

```bash
wget http://radiko.jp/v2/station/list/JP1.xml
```

XML なので処理しにくいので　JSON にし、日本全国の放送局の一覧に変換しました。

```py3:radiko_xml_json.py
#! /usr/bin/python3
# -*- coding: utf-8 -*-
#
#	radiko_xml_json.py
#
#						Jan/16/2018
# --------------------------------------------------------------------
import xml.dom.minidom
import	sys
import	json
import requests
#
# --------------------------------------------------------------------
def file_write_proc(file_name,str_out):
#
	fp_out = open(file_name,mode='w',encoding='utf-8')
	fp_out.write(str_out)
	fp_out.close()
#
# --------------------------------------------------------------------
# [6-6]: 
def	xml_to_dict_proc (xml_str_in):
	unit_aa = {}
#
	dom_in=xml.dom.minidom.parseString (xml_str_in)
	stations=dom_in.getElementsByTagName ("name")

	for station in stations:
		parent=station.parentNode
		id=parent.getElementsByTagName("id")[0].firstChild.nodeValue
		name=parent.getElementsByTagName("name")[0].firstChild.nodeValue
		print("\t",id,name)
		unit_aa[id] = name
#
	return	unit_aa
# --------------------------------------------------------------------
# [6]: 
def area_parser(key):
	print(key)
	url_radiko = "http://radiko.jp/v2/station/list/" + key + ".xml"
	rr=requests.get(url_radiko)
	xml_str = str(rr.content,'utf-8')
	unit_aa = xml_to_dict_proc (xml_str)
#
	return unit_aa
# --------------------------------------------------------------------
print ("*** 開始 ***")
#
json_file= "stations.json"
#
dict_aa = {}
#
for it in range(47):
	key = "JP%d" % (it+1)  
	unit_aa = area_parser(key)
	dict_aa[key] = unit_aa
#
out_str = json.dumps(dict_aa)
file_write_proc(json_file,out_str)
#
print ("*** 終了 ***")
# --------------------------------------------------------------------
```

作成された json
![radiko_jan16.png](https://qiita-image-store.s3.amazonaws.com/0/179446/66768bbd-fe9e-2bfb-1437-f788713fbc87.png)
C++ Builder XE4 > TCP > Connect()失敗と次回のConnect成功までの時間 > 30秒 or 60秒

```txt:動作環境
C++ Builder XE4
```

```Unit1.cpp
	// 1. Connect
	IdTCPClient1->Host = m_ipAdrs;
	IdTCPClient1->Port = m_localPort;
	IdTCPClient1->ConnectTimeout = 1000; /* msec */
	IdTCPClient1->ReadTimeout = 2000; /* msec */
	try {
		IdTCPClient1->Connect();
	} catch (Exception &exc) {
		String msg = exc.Message;
		IdTCPClient1->Disconnect(); /*** (1) ***/
		return false;
	}
```

上記のような処理でTCP接続を行い、コマンドを送信する。
その処理を毎秒実行しているとする。

処理中に下記を行う

1. 通信ケーブルを切断する
2. 通信ケーブルを接続する
   - >> 復帰(Connect成功)するまで時間がかかる

30秒で復帰する場合もあれば、60秒で復帰する場合もある。

復帰時間のdecisive factorはC++ Builder(+Indy)側によるものか、相手側の装置の通信実装によるものかの切り分けはできていない。
汎用的なユーティリティコードとは何か（リーダブルコードのつづきとして）

# はじめに

* [「リーダブルコード」](https://www.oreilly.co.jp/books/9784873115658/)が目に入ったのでなんとなく読み直した。だいぶ前に読んだきりだったが、理解されるコードを書こう、というコンセプトは今でも古くならないし改めて勉強になった。
* "13章 短いコードを書く" において、多分守備範囲じゃないから詳しく書いていないんだろうなという部分があって、わりと間違いやすいところなのでもうちょっと詳しく書いてあると嬉しいのになーと思ったのでつづきを書いてみる。

# "13章 短いコードを書く" の内容

* 汎用的なユーティリティコードを作り、重複コードを削除することによって、コードを短くして理解しやすくする。
* いっていることは本当にその通り。
* それではその汎用的なユーティリティコードはどうやって作るのか？

# 共通汎用コードというアンチパターン

* 重複するコードを何も考えずにひとつの "汎用ユーティリティライブラリ" に詰め込んでいくと、あとあとでまずいことになることが多い。

## 例1) 誰も使わない汎用コード

* 汎用ユーティリティライブラリ「GenericUtils」にはプロジェクトで重複して記述された汎用的なコードが詰まっている。
* しかしながらライブラリ名から何をするコードなのかが推測しづらく、詳細なドキュメントや派手な宣伝もないため、書いた人以外誰も使い方や使いどころを知らない。
* 「GenericUtils」を使えば 1 行で終わる処理もあったが、誰もそんなことは知らなかったので毎回毎回汎用的な処理が再実装されている。

## 例2) 膨らみ続ける汎用コード

* 汎用ユーティリティライブラリ「CompanyNameUtility」社内のプロジェクトを横断して汎用的に再利用できそうなコードをまとめた汎用ユーティリティライブラリだ。これは当社の叡智の詰まった誇るべきライブラリなので、全てのプロジェクトで利用することが義務付けられている。
* 実際便利なコードもそこここにありはするするしそのまま使うぶんには問題ないのだが、個々のプロジェクト向けにちょっとカスタマイズしたいとなった場合に、あまりにも広く使われているため変更する際の影響範囲が計りしれず、変更をためらわれてしまう。
* そのため個々のプロジェクトに合わせたほとんど同じロジックのコードが雪だるま式に増えていってしまい、もう誰も管理できない状態になっている。

# 汎用コードはドメイン特化コード

* 汎用コードとはただ重複したコードのことではなく特定のドメイン（分野・領域）に特化したコードのこと。
* 例えば「リストの操作で頻出するコード」だったり「座標計算のための複雑なコード」だったりというもののことであり、ライブラリ化する場合はそのドメインごとに分割することで管理しやすく再利用されやすいコードになる。

# ドメインに特化していないけど重複するコードはどうするか

* 特定のドメインのコードであると仕分けられない場合、まずはそのコードが複数のことを同時にやろうとしていないかどうかを考えてみて、本当にそうであった場合は分割してみる。
* それでもやっぱり特定のドメインのコードであると判別できない場合は、汎用的に使われることはおそらく無いので、プロジェクト固有のユーティリティとしてまとめて管理するのはそこまで悪いアイディアでは無い。

## "ユーティリティ" にはもっといい名前があるかもしれない

* 説明する上で都合がいいとはいえ本当は「ユーティリティ」という名前よりももっといい名前があるかもしれないので一度考えて見たほうがいい。
* 「ユーティリティ」だと「なんか便利なもの」以上の意味がないしなんでも入れられるので深く考えずにただの「共通コードのゴミ溜め」になってしまうことがある。
* ちゃんと考えれば「特定のテーブルをオブジェクトとして扱った時に共通して利用されるコード」だったり「データを HTML に変換する時によく現れがちなコード」だったりに分けられるかもしれない。
* それぞれのドメインごとに適切にまとめていくことで、より理解しやすいコードがかけるようになる。
DeepLearningについてメモ

勉強中に感じたことのメモ。
内容の真偽については保証できません。


#行列演算
ニューラルネットワークの、入力に対して重みを掛ける積和演算を、行列の積で表すことができる。
人間が読みやすくなる。
計算量は変わらない。

#Python
Pythonは、行列演算が簡単にできるような仕組みになっている。（ライブラリ？）
配列を投げると、勝手にforeachして、勝手に要素ごとに演算を行い、勝手に元の配列と同じ構造に並べて、返してくれる。
他の言語でfor分3重ループ20行ぐらいの処理が、2～3行で書けたりする。
計算量は変わらない。

#ニューラルネットワークの構造を決めるのは人間
ニューラルネットワークの出力ノード数や、中間層の層数やノード数は人間が決める。
例えば、手書きの数字の推論であれば、出力ノード数は10個にする。
ステップ関数/シグモイド関数や、恒常関数/ソフトマックス関数の選択も人間が決める。
構造を決めてからでないと学習ができない。
中間層は何パターンか作って学習させて、正解率が高くなったものを選ぶ？
推論モデルを実装するマシンのリソースや処理時間などの制約を受ける。

#シグモイド関数
出力が0～1の間で実数を出力する。
シグマ文字に似ているのでシグモイドと呼ぶ。

#DLには学習と推論の2つのフェーズがある
###学習
学習は、訓練データ（大量）を入力して、出力値と期待値の誤差を逆伝搬させて、ニューラルネットワークの重み（積和演算の係数）を決定するフェーズ。
超ハイスペックなマシンで学習させる。
訓練データのうち、出力期待値とセットになったものを教師データと呼ぶ。
教師がなくただデータが大量にあるだけの場合も学習する手法はある。
###推論
推論は、学習で決定したモデルを使用して、個々の入力データを分析するフェーズ
エッジコンピュータへインプリメントして、実務を行う。
スペックは高いとは限らない。

#DLの出力は、分類と回帰の2つの出力方式がある
DLで解く問題には、大きく分けて、分類問題と回帰問題の2つの問題がある。
###分類
分類はデジタル値で出力する問題
画像から動物か車かを推論したり、動物の種族を推論するなど
###回帰
回帰はアナログ値を出力する問題
例えば画像から体重を推論するなど

#ソフトマックス関数
出力ノードすべての合計値が1となるような、比率を出力するように、出力値を補正する関数。
回帰問題の出力段に使用する。
入出力の順位は変わらないので、1位の結果だけ出力する場合には、ソフトマックス関数を通しても通さなくても結果は変わらない。
分類問題の場合はソフトマックス関数を通さずに、1位の結果だけ出力することが多い。
分類問題でも、猫の確率88%犬の確率12%などと出力する場合は使用する。
PythonのFlaskで学ぶWebアプリケーション制作講座 第0章 〜はじめに〜 

# この資料について

サークルのWebアプリケーション製作講座用に書いている資料です。
対象読者は何らかのプログラミング言語を少し触ったことはあるけど、Pythonははじめてという方を対象にしています(ちなみにサークルでは最初にC言語をします)

Githubのほうで[公開](https://github.com/ikaro1192/CCS_WebLec)していましたが，Qiitaに移してみることにしました．

その後、Zennに移しました

https://zenn.dev/ikaro1192/books/999b71a570cb89024716
python numpyのリストと組み込みリストの違い?

#はじめに
python3をwindows10上で動かしており、とあるデータ処理をpythonで書いている途中でつまづいたので、ここでメモしておきます

#データを取り出してグラフ表示
以下のようなテキストファイルからy軸、x軸の値をそれぞれ取り出してグラフ表示するために、pythonでプログラミングしているところでわからないことが出てきました。それが、以下にあるgenfromtxtの配列の扱いです。

```mass.txt
0.1 , 1
0.4 , 2
0.1 , 3
0.8 , 4
0.6 , 5
0.3 , 6
...
```

#genfromtxt
numpyのライブラリの中にテキストファイルからデータを簡単に取り出すことのできるfenfromtxtというものがありました。以下に例となるコードを示しておきます。

```python3:genfrom.py
import numpy as np
import matplotlib.pylab as plt

data=np.genfromtxt('mass.txt',delimiter=',')
x=data[:,0]
y=data[:,1]
plt.plot(x,y,label="data")
plt.legend()
plt.show

```
これはデータを取り込む部分とグラフ表示の部分を抜き出したものですが、genfromtxtの部分だけ取り出すと、以下のようになります。

```
data=np.genfromtxt('mass.txt',delimiter=',')
x=data[:,0]
y=data[:,1]
```
mass.txtファイルから","区切りでデータを読み込み、スライスでy軸、x軸それぞれの値を取り込んでいます。
ここで、もともとデータをリストにfloatで取り出しているため、

```
list=[[0.1 , 1] [0.4 , 2]...]
x=list[:,0]
y=list[:,1]
```
と書いたところTypeErrorとなり、
`TypeError: list indices must be integers or slices, not tuple`
と表示されてしまいました。
どうして、タプル扱いになったのか見当もつかなかったためとりあえず、data=genfromtxtのdataを出力させてみると、

```
[[0.1   1. ]
 [0.4   2. ]
 ...,
 [0.6   5. ]
 [0.3   6. ]]
```
と表示されました。この配列表記は文字列でもなく、要素間に","もないためどういう宣言をしたらこういう出力結果になるのかわかっていません...


とりあえず、ここまで頭を整理させるために書きました。~~また、わかったら編集しなおします。~~


:arrow_right: @LouiS0616 さんにコメントで教えていただきました。感謝します。
　genfromtxtによる配列はnumpyのndarryという多次元配列を用いており、pythonに組み込まれているリストとは出力結果自体も少し異なるみたいです。実際に自分でもやってみたのですが、配列の出力には","が入っていませんでした。numpyの配列はメモリ上に連続的に入れられるため変更不可ってことは、知っていたのですが、出力結果や使える文法も違うことは知りませんでした…　

出力結果
`[0 1]`

```python3:arr00.py
import numpy as np
a=np.array([0,1])
print(a)
```

自分はもともとpythonに組み込まれているリストを使いたかったのでfor文で書くことにします。
以下、@shiracamus　さんに教えていただいたfor文でも1行で２次元配列の列だけを新しくリストに取り出す方法

出力結果
`[1, 3, 5, 7, 9, 11]
[2, 4, 6, 8, 10, 12]`

```python3:flist00.py
data=[[1,2],[3,4],[5,6],[7,8],[9,10],[11,12]]

x=[d[0] for d in data]
y=[d[1] for d in data]

print(x)
print(y)
```
リストを作り、その中でfor文を回せるなんて初めて知りました:frowning2:
感謝します。
AWS SAMを利用してGolangなLambdaをデプロイする

AWS LambdaがGoのサポートを開始したのでAWSSAMを利用してのデプロイを試してみました

# 実行環境

```bash
$ go version
go version go1.9.2 darwin/amd64
$ aws --version
aws-cli/1.11.149 Python/3.4.2 Darwin/17.3.0 botocore/1.7.7
```

# ソースコード

[Lambda Function Handler (Go)](https://docs.aws.amazon.com/lambda/latest/dg/go-programming-model-handler-types.html)のコードをそのまま利用します。

```go:main.go
package main

import (
	"context"
	"fmt"

	"github.com/aws/aws-lambda-go/lambda"
)

func HandleRequest(ctx context.Context, name string) (string, error) {
	return fmt.Sprintf("Hello %s!", name), nil
}

func main() {
	lambda.Start(HandleRequest)
}
```

# テンプレート

```yaml:template.yml
AWSTemplateFormatVersion: "2010-09-09"
Transform: 'AWS::Serverless-2016-10-31'
Resources:
  App:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: lambda-go-sample # ファイル名
      Runtime: go1.x 
      CodeUri: build # ビルドファイル設置ディレクトリ
      Timeout: 1
```


# デプロイ

```bash
GOARCH=amd64 GOOS=linux go build -o build/lambda-go-sample
aws cloudformation package \
	--template-file template.yml \
	--s3-bucket [パッケージアップロード先s3バケット] \
	--s3-prefix lambda-go-sample \
	--output-template-file .template.yml
aws cloudformation deploy \
	--template-file .template.yml \
	--stack-name lambda-go-sample \
	--capabilities CAPABILITY_IAM
```
# 実行結果

```bash
$ aws cloudformation describe-stack-resources --stack-name lambda-go-sample
{
    "StackResources": [
        {
            "Timestamp": "2018-01-16T02:42:50.589Z",
            "StackName": "lambda-go-sample",
            "LogicalResourceId": "App",
            "ResourceType": "AWS::Lambda::Function",
            "ResourceStatus": "CREATE_COMPLETE",
            "PhysicalResourceId": "lambda-go-sample-App-1U7U6E46GZAW3",
            "StackId": "arn:aws:cloudformation:ap-northeast-1：xxx:stack/lambda-go-sample/de118db0-fa66-11e7-b9ae-50fa13f400ad"
        },
        {
            "Timestamp": "2018-01-16T02:42:45.996Z",
            "StackName": "lambda-go-sample",
            "LogicalResourceId": "AppRole",
            "ResourceType": "AWS::IAM::Role",
            "ResourceStatus": "CREATE_COMPLETE",
            "PhysicalResourceId": "lambda-go-sample-AppRole-WVOATNOP8JWV",
            "StackId": "arn:aws:cloudformation:ap-northeast-1:xxx:stack/lambda-go-sample/de118db0-fa66-11e7-b9ae-50fa13f400ad"
        }
    ]
}
$ aws lambda invoke --function-name lambda-go-sample-App-1U7U6E46GZAW3 --payload '"Lambda"' out.txt
{
    "StatusCode": 200
}
$ cat out.txt
"Hello Lambda!"
```


# あとがき

pythonやnodeと違って事前にビルドしたものをデプロイする必要がありますが、CD環境さえ整えてしまえば些細な問題ですね。
次はGitHub + CodePipeline + CodeBuild + CloudFormationによるGolangなAWS LambdaのCD環境の構築方法についてまとめたいと思います。

# 参考

- [AWS Lambda Supports Go](https://aws.amazon.com/jp/about-aws/whats-new/2018/01/aws-lambda-supports-go/)
- [Lambda Function Handler (Go)](https://docs.aws.amazon.com/lambda/latest/dg/go-programming-model-handler-types.html)
IP-SEC VPNのDNS設定

# VPNを敷いたが拠点から本社にあるサーバが見えないといった問題。

よくあるのでメモとして残します。

## ルータのDNSはデフォルトではプロバイダ―の提供するDNSになっている
よって、'dns server' コマンドによって本社にあるDNSサーバを追加しましょう。

```
#
# DNS configuration
#

dns server 192.168.xxx.xxx <-- 本社のDNSサーバ
dns server pp 1
dns private address spoof on
```

dns server コマンドで DNS サーバーが明示的に指定されている場合には、そちらの設定が優先される。dns server コマンドに指定したサーバーから返事がない場合には、相手先への接続と DNS サーバーの通知取得が行われます。
よって、本社のDNSサーバへアクセスして解決できないときはプロバイダ―のDNSをアクセスします。
curlコマンドをPythonやnode.jsのコードに変換する方法

# curlでAPIを試す
curlコマンドでAPIの振る舞いを試すということがあると思います。
振る舞いがわかれば、あとはそれを実際にコードの中で使おうという流れになると思うのですが、私の場合pythonのrequestsモジュールを使って書き換えようと思ったときに、少しつまづきました。

APIのリファレンスを見ると、こうやってcurlで書くと取得できるよと、curlコマンドのサンプルが記載されていたりするのですが、それをそのままコピーして使うことはもちろんできても、コードに書き換えるときに、

* __curlのこのオプションは一体何を表しているのか__
* __他のモジュールを使って書く場合は、どうやって書けばいいのか__

など発生します。

そんなときに見つけたのが、こちら

#コピペするだけ 
[Convert curl syntax to Python, Node.js, PHP](https://curl.trillworks.com/)

curlコマンドをそのまま左側のテキストエリアにコピペすれば、右側のテキストエリアにPythonのrequests,Node.js,PHPのコードに変換してくれます。

![sample.png](https://qiita-image-store.s3.amazonaws.com/0/137532/703a1756-8b9c-b235-6b69-26c39bf4b056.png)

#実際の例
[リクルートのTalk API](https://a3rt.recruit-tech.co.jp/product/talkAPI/)をcurlからPythonのrequestsにした例

---
**Before(curl command)**

```
curl -X POST https://api.a3rt.recruit-tech.co.jp/talk/v1/smalltalk \
-F "apikey=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" \
-F "query=おはよう"
```

**After(Python requests)**

```py3
import requests

files = {
    'apikey': (None, 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'),
    'query': (None, '\u304A\u306F\u3088\u3046'),
}

response = requests.post('https://api.a3rt.recruit-tech.co.jp/talk/v1/smalltalk', files=files)

```
---

requestsの書き方が違って何回かコードを書き直すという手間がなくなりますね。
pythonで和暦

つらい。

`datetime.strptime` の中身見てみたら[ものすごい武闘派](https://github.com/python/cpython/blob/master/Lib/_strptime.py#L318)だったので早々に諦めて、
ざっくり欲しいとこだけ実装することにした。

いっそもう皇紀にしたらいいんじゃないかな。


```py3:jp_era.py
import datetime


class JpEra:
    def __init__(self, shorthand, era_name, begin_date, end_date=datetime.date.max):
        self.shorthand = shorthand
        self.era_name = era_name
        self.begin_date = begin_date
        self.end_date = end_date

    def in_term(self, target_date):
        return self.begin_date <= target_date <= self.end_date

    def jp_year(self, year):
        return year - (self.begin_date.year - 1)


JP_ERA = (
    JpEra("M", "明治", datetime.date(1868,  9,  8), datetime.date(1912,  7, 29)),
    JpEra("T", "大正", datetime.date(1912,  7, 30), datetime.date(1926, 12, 24)),
    JpEra("S", "昭和", datetime.date(1926, 12, 25), datetime.date(1989,  1, 7)),
    JpEra("H", "平成", datetime.date(1989,  1,  8)),
)


def parse_jp_datetime(target_str, fmt='%y.%m.%d %H:%M'):
    """
    '元年' がめんどくさいのでとりあえずショートハンドのみ
    :target_str: 'H30.01.15 09:52'
    :fmt:
    :return: datetime.datetime
    """
    x, xs = target_str[0], target_str[1:]
    for era in JP_ERA:
        if x != era.shorthand:
            continue

        # 2100年以降とか元号が３桁になったりするとおかしくなるけどまぁいいや
        c = datetime.datetime.strptime(xs, fmt)
        y = era.begin_date.year + c.year % 100 - 1
        return datetime.datetime(y, c.month, c.day, c.hour, c.minute, c.second)

    raise ValueError('unknown era `%s`.' % x)


def jp_era(target_date):
    """
    :target_date: datetime.date(2018, 1, 15)
    :return: (shorthand, era_name, jp_year)
    """
    for era in JP_ERA:
        if era.in_term(target_date):
            return era.shorthand, era.era_name, era.jp_year(target_date.year)

    raise ValueError('should not be reached here `%s`.' % target_date)
```

```py3:test_jp_era.py
import unittest

import datetime
from jp_era import *


class TestJpEra(unittest.TestCase):
    def test_jp_era(self):
        args_and_expects = [
            [[datetime.date(2018, 1, 15)], ('H', '平成', 30)],
            [[datetime.date(1989, 1, 7)], ('S', '昭和', 64)],
            [[datetime.date(1989, 1, 8)], ('H', '平成', 1)],
        ]

        for args, expect in args_and_expects:
            self.assertEqual(jp_era(*args), expect)

        self.assertRaises(ValueError, lambda: jp_era(
            datetime.date(1000, 1, 1)))

    def test_parse_jp_date(self):
        args_and_expects = [
            [['H30.01.15 09:52'], datetime.datetime(2018, 1, 15, 9, 52)],
            [['H01.01.8 10:00'], datetime.datetime(1989, 1, 8, 10, 00)],
            [['S64.01.7 10:00'], datetime.datetime(1989, 1, 7, 10, 00)],
            [['S90.01.15 09:52'], datetime.datetime(2015, 1, 15, 9, 52)],   # NOTE: 議論の余地がある
        ]

        for args, expect in args_and_expects:
            self.assertEqual(parse_jp_datetime(*args), expect)

        self.assertRaises(
            ValueError, lambda: parse_jp_datetime('X10.01.15 09:52'))


if __name__ == "__main__":
    unittest.main()
```
Cent OSへTomcatインストール

＝＝＝＝＝＝＝＝＝＝＝＝＝
●catalinaについて
tomcatのコードネームが catalina(カタリナ) です。
様々なところで catalina という単語がでてくるので、tomcat＝catalina という脳内変換をしましょう。

●ポート番号について
デフォルトでは 8005（SHUTDOWN）、8009（AJP3）、8080（HTTP）という構成になっています。

●ログについて
デフォルトでは ${CATALINA_HOME}/logs/catalina.out  にログが出力されます。
tomcat運用中には頻繁に参照することになるため、このパスはつねに把握しておきましょう。
＝＝＝＝＝＝＝＝＝＝＝＝＝

●tomcatとjdkのダウンロード
tomcatとjdkのバージョンはできるだけ合わせておく

●ファイルの解凍
tarでいつも通り解凍

●解凍したディレクトリの移動
例)
jdkは/usr/local/jdk-9.0.1 という名前で移動
tomcatは/usr/local/tomcat-9.0.1 という名前で移動
※バージョン番号はつけておく

●シンボリック作成
/usr/local/jdk-9.0.1 は /usr/local/javaにリンクを張る
/usr/local/tomcat-9.0.1 は /usr/local/tomcatにリンクを張る
※バージョンアップ作業などではシンボリック先を変えれば楽になる
※シェルスクリプト内でのパス指定が楽になる

●tomcatユーザ作成と所有者変更
useraddでtomcatユーザを作成
chownで/usr/local/tomcat 以下全部のファイルの所有者変更

●環境変数の定義
tomcatユーザのbashrcかbash_profile に記述する
※.bash_profileと.bashrcは、共にログインしたときに実行される設定用のシェルスクリプト。
  .bash_profileは、ログイン時だけに実行される設定ファイル。ここでは、環境変数の設定などが行われる（内容はディストリビューションによって異なる）。
  .bashrcは、ログイン時に.bash_profileから読み込まれるという形で実行されるが、別のシェルが起動したときにも実行される。

tomcatの起動スクリプト内にも記述する
※起動スクリプトは手動で作成してsystemctlで利用できるようにしておく
＝＝＝＝＝＝＝＝＝＝＝＝＝
JAVA_HOME=/usr/local/java
CATALINA_HOME=/usr/local/tomcat
PID_FILE=${CATALINA_HOME}/logs/tomcat.pid
CLASSPATH=${CATALINA_HOME}/lib/servlet-api.jar:${CATALINA_HOME}/lib
TOMCAT_USER=tomcat
export JAVA_HOME CATALINA_HOME PID_FILE CLASSPATH TOMCAT_USER
＝＝＝＝＝＝＝＝＝＝＝＝＝

●ダイレクトに起動・停止する場合
tomcatユーザで下記を実行

/usr/local/tomcat/bin/startup.sh
/usr/local/tomcat/bin/shutdown.sh
＝＝＝＝＝＝＝＝＝＝＝＝＝