OmniAICreator/Qiita-1.07M huggingface dataset:
ホーチミンでオススメの便利な仕事スペース

GYAOの玉利です。

GW前で仕事がとまるので、ベトナムにいってGW中の宿題をざくっと渡してきました。
ネタは貯まれど書く時間なしです。

ホーチミン中心部にひときわ目立つ、BITEXCO Towerをうろついていたら、仕事スペースを見つけました。

http://www.adventurefaktory.com/sgnworkcafenest/

内装は、お金持ちスタートアップのオフィスのような感じです。

電源も各所にあって便利です。


<img width="265" alt="スクリーンショット 2016-04-28 9.20.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/113049/d52d8d33-09b4-ff5e-064c-45515e7da1aa.png">

意識高すぎてちょっと入りにくい入口なのですが

![スクリーンショット_2016_04_28_9_22.png](https://qiita-image-store.s3.amazonaws.com/0/113049/7fa4c8df-15f8-b212-101e-eedf24c09b04.png)

中は広々です。

DA KAO のGEEK HUBでは開発してる人がいっぱいいますが、こっちはドヤラー御用達な感じですね。椅子もGEEK HUBの勝ち。でも場所がいいので会社を５時においだされたらこちらに移動して作業続行するのもいいでしょう。
[Cloud101]#2 HTTPとHTMLを感じる

# 0.AGENDA

1. curlの復習
2. telnetで同じことをやって見る
3. ブラウザのアドレスバーに入れるURLって何？
4. GWの宿題

# 1.curlの復習

-前回参照
http://qiita.com/nagahisa/items/ca8f4e9cc373edd0473d

# 2. telnetで同じことをやって見る

- 参考
http://masasuzu.hatenablog.jp/entry/20110205/1296886588

## (1)まず適当な（軽い）サイトに以下でアクセス
```
$ telnet kenzo-vps.nagahisa.me 80
Trying 160.16.89.214...
Connected to kenzo-vps.nagahisa.me.
Escape character is '^]'.
```

# (2)HEAD

```
HEAD / HTTP/1.1
HOST: kenzo-vps.nagahia.me

HTTP/1.1 200 OK
Server: nginx
Date: Wed, 27 Apr 2016 23:00:02 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 21 Apr 2015 15:38:08 GMT
Connection: keep-alive
ETag: "55366ee0-264"
Accept-Ranges: bytes

```

#(2)GET

```
GET / HTTP/1.1
HOST: kenzo-vps.nagahisa.me

HTTP/1.1 200 OK
Server: nginx
Date: Wed, 27 Apr 2016 22:57:44 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 21 Apr 2015 15:38:08 GMT
Connection: keep-alive
ETag: "55366ee0-264"
Accept-Ranges: bytes

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

```
# (3) GET と HEADの違いを見てみる

# (4) 対象サイトをブラウザで見て、「右クリック＞ソースを表示」を見てみる
![ViewSource.JPG](http://qiita-image-store.s3.amazonaws.com/0/79389/4a45ed6f-3e27-4273-f50a-6e9e31125868.jpeg)

# (5) 存在しないパスを指定

```
GET /hoge HTTP/1.1
HOST: kenzo-vps.nagahisa.me

HTTP/1.1 404 Not Found
Server: nginx
Date: Wed, 27 Apr 2016 23:06:12 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive

<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
```

404って出てきた！（前は200だった）

# (6) HTTPとHTML

https://ja.wikipedia.org/wiki/Hypertext_Transfer_Protocol
https://ja.wikipedia.org/wiki/HyperText_Markup_Language

## 3. ブラウザのアドレスバーに入れるURLって何？ (スミマセン、手抜きです :sweat_smile: )

# (1)URLって何？

https://ja.wikipedia.org/wiki/Uniform_Resource_Locator

# (2)ホスト名って何？

https://ja.wikipedia.org/wiki/Domain_Name_System

# (3)プロトコルって何？

# http://www.ubuntulinux.jp/ubuntu/mirrors

# (4)ポートって何？

https://ja.wikipedia.org/wiki/TCP%E3%82%84UDP%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%83%9D%E3%83%BC%E3%83%88%E7%95%AA%E5%8F%B7%E3%81%AE%E4%B8%80%E8%A6%A7

## 4.GWの宿題

- CentOSコマンドを手当たりしだいに試してみる

- できればWebサーバを立ち上げて簡単なHTML文書の作成・アクセステストを行う
・rootでないとインストールできないので、#1の "su -" や "sudo"を使う

Enjoy! :tada:
C言語ソースをpycparserで整形する

# 汚いC言語ソースを綺麗にする．


## 汚いコード
```c:main.c 
#include <stdio.h>
int main
()
{ int // how to 
    a=0; // comment ?
  if(a)printf("hello world\n"
     ) ;else{ printf /* is this ?*/
  ("good by\n");     } return 
0;}
```

## pycparserを使う

C言語パーサのpycparserを使う．

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

import sys
from pycparser import parse_file, c_parser, c_generator, c_ast

def main():
	text = ''.join(sys.stdin.readlines()) # 読み込む
	
	parser = c_parser.CParser() # パーサ
	ast = parser.parse(text, filename='<none>') # パースする

	generator = c_generator.CGenerator() # 生成器
	print(generator.visit(ast)) # 単にパースしたものを書き出すだけ

if __name__ =='__main__':
    main()
```
参考
- https://github.com/eliben/pycparser/blob/master/examples/c-to-c.py

## 整形

pycparserは#includeやコメントには対応していないので，
- grepで#includeを取り除く
- `gcc -E`でコメントを取り除く
それから整形

```sh:実行
$ cat main.c | grep -v "#include" | gcc -E - | python c2c.py 
int main()
{
  int a = 0;
  if (a)
    printf("hello world\n");
  else
  {
    printf("good by\n");
  }

  return 0;
}


$ 
```

# 用途
- 初心者の学生が書いたC言語のソースをきれいにする
C言語のmain関数のラッパー


# 目的
main.cに書かれたmain()関数がある．

```c:main.c
#include <stdio.h>
int main()
{
  printf("hello world\n");
  return 0;
}
```

これを外から呼び出す．

```c:newmain.c
#include <stdio.h>
int _main();

int main()
{
  printf("new main\n");
  _main();
  printf("new main\n");
  return 0;
}
#define main _main
#include "main.c"
```

# build & run

```sh:実行
$ gcc -o newmain newmain.c
$ ./newmain
new main
hello world
new main
$ 
```



# 用途
- 初心者の学生が書いたmain関数のチェック．
OSXのBlenderでOpenCVを使う

# 準備

## Homebrewでpython3を入れる

```
brew install python3
```

## OpenCV3をpython3サポート付きで入れる

```
brew tap homebrew/science
brew install opencv3 --with-python3
```

# blenderを起動

起動する際にPYTHONPATHにHomebrewで入れたOpenCV3のモジュールのパスを指定する。

```
PYTHONPATH=/usr/local/opt/opencv3/lib/python3.5/site-packages/ /Applications/blender.app/Contents/MacOS/blender
```

## 確認

blenderのコンソールで

```py
import cv2

cv2.__version__
capture = cv2.VideoCapture(0)
cv2.namedWindow("Capture", cv2.WINDOW_AUTOSIZE)
ret, image = capture.read()
cv2.imshow("Capture", image)
cv2.destroyAllWindows()
capture.destroy()
capture.release()
```
# 注意

blenderが古いと、Pyhton3.4だったり、もっと古いと2.x系だったりする。
そういう場合は、OpenCVモジュールが認識されないでエラーとなる。

# 関連投稿

- [BlenderをPythonから使えるようになるための第一歩 - Qiita](http://qiita.com/kjunichi/items/96b0effb9ef8e99b09bf)
- [Blenderの中のPythonでカレントディレクトリを知るには - Qiita](http://qiita.com/kjunichi/items/39462dd724acb3eb2b71)
- [直前に生成したプリミティブ等の名称を取得するには - Qiita](http://qiita.com/kjunichi/items/f4e836630613631d3a67)
- [PythonやBlenderでmrubyを動かす - Qiita](http://qiita.com/kjunichi/items/51127edd684cc646e5ec)
- [Blenderにpipを入れる - Qiita](https://qiita.com/kjunichi/items/a36fdc9db3876e068249)

# 関連記事

- [Blenderで初めてのアドオンを作るまで ～その2～](https://abrakatabura.hatenablog.com/entry/2017/04/28/062856)
- [Blenderで初めてのアドオンを作るまで ～その１～](https://abrakatabura.hatenablog.com/entry/2017/04/11/061849)
- [BlenderでPython使って最速降下曲線を描いてみる](https://abrakatabura.hatenablog.com/entry/2016/05/26/070858)
- [BlenderでエクスポートしたJSONがThree.jsで変な色になる問題が解決](https://abrakatabura.hatenablog.com/entry/2015/12/21/071507)
- [OSXのBlenderでctypesを試した](https://abrakatabura.hatenablog.com/entry/2015/01/31/091848)
- [blenderでgRPC(クライアント＆サーバ)を動かした](https://abrakatabura.hatenablog.com/entry/2019/03/18/212258)
Nagios の設定にpynagを使ってみる

# Overview
　Nagios の設定をWebから操作するのも表示するのも面倒くさいのでコマンドラインから何かできないと探していたが、[pynag](http://pynag.org/)なるものを見つけた。
　名前からして明らかにpythonである。これまでpythonは触って事が無いが、これを機会に覚えてみるのも良いだろうし、そもそもコマンドラインだけでも十分動作しそうなので使ってみることにする。

# How to install
　Cent5ですらepelに含まれていたので、epel repoを入れた後にyum installで完了
<pre>
 # yum install epel-release
 # yum install pynag
</pre>

# How to use
　とりあえずコマンドラインで使ってみる。
コマンドの中身を見る限り、デフォルトでは /etc/nagios を探しに行くようだ。
nagios.cfg に include していれば includeファイルも合わせて検索してくれるようなので
/usr/local/nagios 等にインストールしてしまっても /etc/nagiosにsymlinkでも貼っておけばいいんじゃなかろうか。
<pre>
    774 examples['config'] = '''
    775   # %prog config --set process_perfdata=1
    776   # %prog config --append cfg_dir=/etc/nagios/conf.d
    777   # %prog config --remove cfg_dir --old_value=/etc/nagios/conf.d
    778   # %prog config --get object_cache_file
</pre>

## list 
 以下のように叩くと、 define host　とかした所から項目を引っ張ってくれる。
どのような項目が取得可能かは、[こちら](https://assets.nagios.com/downloads/nagioscore/docs/nagioscore/4/en/configobject.html)を見ると良い。
<pre>
 $ pynag list host_name address where object_type=host
</pre>

# How to use in python programs

# Tips
技術英語 > and new features [take a back seat]. 

ソフトの再利用性に関する記事。
http://thecodist.com/article/the-myth-of-reusability

再利用したら開発が早く（安く）なるという考えの元に、その再利用コードの発展が書かれている。

再利用を進めていく中で、依存性が成長していき、

> Changes take longer and longer as any change have to be tested in a whole host of applications, and new features <font color=red>take a back seat</font>. 

http://eow.alc.co.jp/search?q=backseat&ref=wl

「待たされる」という意味になるのだろう。

<hr>
Oracle Live SQL

こんにちは。OracleのSQLを簡単に試せる環境ほしいなぁと思った事はありませんか。
学習用にvirtualboxにOracleをインストールする事はできますが、
環境構築するには少し手間で面倒くさいですよね。

そんなあなたにオススメしたいのはこちら！Oracle Live SQLです。
簡単なアプリ開発向けのSQLならオンラインで試すことができます。
環境構築は不要です。
ただし、制限がありますので、あくまで学習用になりますね^^;

■制限（私の知ってる限りです。他にもあるかもしれません。）
・Oracleのアカウント登録が必要（無料）
・サインイン中は利用可能（サインアウトすると作成したオブジェクトは削除されます）
・容量制限あり？


それでは、さっそく始めてみましょう。
1.https://livesql.oracle.com/apex/livesql/file/index.html
にアクセスします。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/113544/e24e8016-127d-e4b3-bf3a-bf5933645aeb.png)

2.Oracleのアカウントでログインしてください。
（アカウント登録方法はここでは省きますね。すみません。）
![2.png](https://qiita-image-store.s3.amazonaws.com/0/113544/d812eee0-638b-c378-66f0-94d7aabb9356.png)

3.TOP画面から左側メニューの『Schema』をクリックした画面が下記となっています。
なにやら英語の文字がかかれてますね。今は気にしないでください。
![3.png](https://qiita-image-store.s3.amazonaws.com/0/113544/731f2c51-2070-3e28-5d39-13564d2e5c1b.png)

4.左側メニューの『SQL Worksheet』をクリックしてください。SQLが記載できそうな画面が出てきました。
![4.png](https://qiita-image-store.s3.amazonaws.com/0/113544/9a4ffabb-532d-4473-ceda-4c781d03b86e.png)

5.さっそくSQLを書いてみましょう。
以下はサンプルのSQLです。テーブルを2つ作成してみましょう。
SQLを記載したら、右上の『Run』をクリックしてください。
![5.png](https://qiita-image-store.s3.amazonaws.com/0/113544/4a42b39e-ef84-3a27-12fd-6b760f850611.png)


6.左側メニューから『Schema』をクリック。
すると、先ほどは英語の画面だったのですが、今は4と5で作成したテーブル名が二つ表示されている事がわかります。
![6.png](https://qiita-image-store.s3.amazonaws.com/0/113544/2299c699-8e85-9a4d-ff71-7f30657f095a.png)

7.作成したテーブルBUMONをクリックすると、以下のような画面が表示されます。
テーブル情報が載ってますね。追加したカラムもちゃんと記載されてます^^
テーブル作成できました。やったね^^
![7.png](https://qiita-image-store.s3.amazonaws.com/0/113544/79245ece-1dd7-173c-55f7-a7a6bbac2e66.png)

8.データ投入も試してみましょう。
insert文を記載して、再度右上の『Run』をクリック!
![8.png](https://qiita-image-store.s3.amazonaws.com/0/113544/c11f8c7c-5562-6a01-6b31-12b2c0c153cc.png)

9.select * from テーブル名でinsertが正しく流れたか確認します。
SQL画面の下部にselectの結果が表示されています。
おーーデータ投入できました^^
![9.png](https://qiita-image-store.s3.amazonaws.com/0/113544/ee3eb26d-8d05-32b1-d278-7a182ea0092e.png)


10.PL/SQLも実行できるようです。
以下は簡単なサンプルです。
![11.png](https://qiita-image-store.s3.amazonaws.com/0/113544/c8a68079-ca40-cef3-9451-24b58bcd90e0.png)

いかがでしたでしょうか。環境構築しなくてもSQLを試せるなんて素敵ですよね。
ただし、あくまで学習用となりますが、参考にしていただけると幸いです。
Starling2.0のDevice contextをロストした際の挙動を理解する

Starling2.0からはDeviceContextをロストした（それまでにGPU描画した内容を失い、描画処理を続けられなくなった)後に自動的に復帰処理が働くのがデフォルトの動作になりました。（Starling.handleLostContextプロパティはもはや存在しません。）余計な手間が減って便利になりましたが、それでも手動で復帰処理を書かなくてはいけないケースも存在しますので、この周辺でどんな処理がなされているのか、手動で復帰処理を書かなくてはいけない場合はいつでどのようにすればいいのか、といった事をまとめてみます。

![title-logo.png](https://qiita-image-store.s3.amazonaws.com/0/8302/e5ec0dbf-fb12-2fde-46d2-3c36f3b9e234.png)

#Contextをロストした際に失われるもの
Contextをロストした際に失われるのは、GPUにアップロードしたテクスチャ情報です。他の描画に必要なパラメータなどは基本的に毎フレーム画面全体を描画し直す際に、再度GPUに送信されるので、特に気にせずとも良いのです。テクスチャはいろいろな方法で作ることができますが、Bitmap(画像ディスプレイオブジェクト)もしくはBitmapData(画像データ)から作ることを基本に考えます。

```sample.as
var texture:Texture = Texture.fromBitmapData(bitmapData);
```

Bitmap系以外には、Embedされた(画像関連の)クラスなどからテクスチャを作ることができますが、それぞれが結局は画像に変換されてテクスチャが作成されます。

参考：リファレンスマニュアル Textureクラス
http://doc.starling-framework.org/current/starling/textures/Texture.html

#復帰処理の詳細
Device Contextをロストして、再度Contextを得た際に各textureインスタンスのtexture.root.onRestore関数が呼びだされます。このonRestore関数はユーザ側で設定が可能ですが、Texture.fromBitmapDataなどでTextureクラスの静的メソッドでテクスチャを生成する際はデフォルトですでに設定されており、テクスチャの元となった画像を再度GPUにアップロードする処理が書かれています。ContextをロストしてもネイティブのBitmapDataは消失しません。

```sample.as
texture.root.onRestore = function():void
{
	texture.root.uploadBitmapData(bitmapData);
};
```

注意しなくてはいけないのは、このBitmapDataをTexture生成後に外部で破棄してしまっていると、再アップロード処理が行えなくなってしまうことです。メモリに無駄が出てしまいますがこのデフォルトの挙動を有効とするために、（かなり大きなテクスチャを扱っているような特殊な場合をのぞいて）BitmapDataは破棄せず保持しておくと良いでしょう。Embedされた画像クラスを元にテクスチャを作る場合は、画像クラスを再度インスタンス化すれば良いです。

#Videoテクスチャについて
カメラ、ビデオ、ストリーム映像など動画系のテクスチャ(Videoテクスチャ)を扱う場合も、自動で再アップロード処理が働きます。そもそもテクスチャ内容が刻々と変わっていくのがVideoテクスチャなので、再アップロードというよりもビデをテクスチャに再接続する、という感じですね。特にStarling利用ユーザ側でonRestore処理を書き換える必要はなささそうです。なお、Videoテクスチャの場合は、texture.root.onRestoreではなくtexture.onRestoreに復帰処理が書かれています。

#Renderテクスチャについて
このテクスチャは描画内容の自動復帰処理が行われません。動的に内容を描画していくテクスチャで全体の元となるBitmapDataは存在しないため当然なのですが、お絵かきソフトなどを作っている場合は描画内容を復活させたい場合もあるかもしれません。その場合は、ユーザのお絵かき手順を記録しておき、Contextロスト時にはその記録を元に描画しなおしてやるか、Stage.drawToBitmapDataを使って、適時BitmapData側にデータをバックアップしておくと良いかもしれません。

#外部から画像を再ロードする
BitmapDataを破棄してしまっている場合はどうすれば良いでしょうか。その画像データが外部から動的に読み込まれている場合であればonRestore関数の中で、Loaderクラスなどを使ってその画像を読み込み直し、texture.root.uploadBitmapDataしてやればOKです。

#AssetManagerに任せる
後者の方法（テクスチャ生成時にBitmapDataは破棄してしまい、Contextロスト時には外部から画像を読み込みしてテクスチャを再生成する事を自動で行ってくれるのがAssetManagerです。AssetManagerに任せておけば通常Contextロスト時の事をケアする必要はありませんが、AssetManagerの内部処理はなかなかにトリッキーです。状況によってよくわからない挙動を取る事もありますので、場合によっては自身でContextロスト時の処理を書く事も必要になるかと思います。

#Contextロスト時の処理を考慮する必要があるのはいつか
雑に箇条書きしてみます。他にもあるかと思いますが、参考としてください。

* Texture生成に使ったBitmapDataを変更または破棄したとき
* AssetManagerを通さず外部から読み込んだ画像を元にTextureを生成したとき
* RenderTextureを使っているとき

なお、DeviceContextをロストする可能性があるのはWindowsとAndroidだけはなく、その他どの環境であってもまれに再現するようです。

#関連イベントなど
Contextロスト時はStarlingインスタンスから`Event.CONTEXT3D_CREATE`が発行されます。（Starlingの初期化時も同じイベントが発行されるので注意。）また、AssetManagerからは全てのテクスチャの再生成が終わった時点で、`Event.TEXTURES_RESTORED`イベントが発行されます。これらのイベントを監視する事で、テクスチャの再生成待ちの間はゲームをPauseするなどの対応が取れそうです。

#おわりに
記事にするにあたって詳細を調べなおしたら細かいところの認識間違いがそこそこありました。きちんと発表する事で自分の理解も高まるので良い事です。ではでは。
Visual Studio Code チートシート

# 基本
端末で`code .`とすると、VS Code でカレントディレクトリを開く。
`code [ファイル名]`とすると、VS Code でファイルを開く。

#コマンド
|コマンド|内容|備考|
|---|---|---|
|Ctrl+Shift+P or F1|コマンドパレットを開く|>|
|Ctrl+B|サイドバーの開閉||
|Ctrl+\|画面分割||
|Ctrl+(数字)|ペイン切り替え||
|Ctrl+N|新規ファイル作成|新規フォルダ作成はまだ無いっぽい？|
|Ctrl+P|ファイルを検索して開く||
|Ctrl+K Ctrl+P|ワーキングファイルから検索して開く|~|
|Ctrl+T|全ファイルにまたがって参照検索して移動し、ファイルを開く||
|Ctrl+Tab|最近開いたファイルを巡回する|Alt+左右方向キー でも似たようなことができる|
|Ctrl+Shift+F|全ファイルにまたがってキーワード検索する||
|Ctrl+Shift+O|参照検索して移動する|＠|
|Ctrl+G|指定した行番号に移動する|：|
|Ctrl+Shift+\|対応するブラケットまで移動する||
|Alt+Click|マルチカーソルを追加する||
|Ctrl+Alt+上下方向キー|上下にカーソルを追加する|
|Ctrl+D|選択したキーワードにマッチする位置にカーソルを追加|Ctrl+Shift+L で該当箇所全て一度に追加できる|
|Shift+Alt+ドラッグ|矩形選択||
|Shift+Alt+左右方向キー|選択範囲を、ワード→行→ブロック→更に上のブロックといった感じに拡縮する|Shrink/expand selection|
|Ctrl+Space|インテリセンス||
|Ctrl+マウスホバー|シンボルの定義を表示|便利|
|Shift+F12 or Alt+F12|参照or定義検索の結果をインライン表示||
|F2|シンボルのリネーム|ファイル全体に適用される|
|Ctrl+Shift+M|警告やエラーのリストを表示|!|

#よく使いそうなもの
|コマンド|内容|備考|
|---|---|---|
|Ctrl+P|ファイルを検索して開く|**万能。** taskやgitとかもここから操作できる。`>`や`@`を続ければ他のコマンドや参照検索とかもできる。|
|Ctrl+\|画面分割||
|Ctrl+(数字)|ペイン切り替え||
|Ctrl+マウスホバー|シンボルの定義を表示|よく忘れるので|
|Ctrl+B|サイドバーの開閉|3分割すると邪魔なので隠したくなる。Ctrl+Shift+F などでサイドバーを開いてしまった後などに。|
|Alt+マウスクリック|マルチカーソルを追加する|マウスポチポチして追加できるようになるだけでも大分マシに|
|Shift+Alt+左右方向キー|選択範囲を、ワード→行→ブロック→更に上のブロックといった感じに拡縮する|凄そうなので積極的に試したい|
|F2|シンボルのリネーム|変数命名で心変わりしたときに|
|Ctrl+Shift+M|警告やエラーのリストを表示|火消しをしてる時間のほうが長い|
Erlangで「This is Anfield.」

前回、以下投稿でインストールからシェルで文字列出力しました。今回は.erlファイルを作成して、コマンドラインからコンパイル→実行したいと存じます。

**前回記事**
[CentOS7にErlangをインストールする](http://qiita.com/kaikusakari/items/e990747ee5e9c34372de)

**環境**

```bash:version
$ erl -version
Erlang (ASYNC_THREADS,HIPE) (BEAM) emulator version 7.3
```

**.erlファイル作成**

```erlang:anfield.erl
-module(anfield).
-export([whereami/0]).
whereami() -> io:fwrite("This is Anfield！\n").
```

**コンパイルと実行**

```erlang
$ erl
1> c(anfield).
{ok,anfield}
2> anfield:whereami().
This is Anfield！
ok
```

文法や、Erlangにおける関数デザインパターンも見えてきました。次回は有名な入門編のアルゴリズムを実装したいと存じます。今後はErlangを中心に投稿を続けたい。
[短文メモ][C++11]関数内のローカル変数を返すのに右辺値参照は要らない

#右辺値参照を使うと無駄なコピーを避けられるよ、と聞いたので

```cpp:ダメなコード
#include <vector>
#include <iostream>

using std::cout; using std::endl;

std::vector<int> && test(){
	std::vector<int> vec;
	// vectorにいろいろ挿入する処理(この記事と関係ないので省略)
	cout << 2 << endl;
	return std::move(vec);
}

int main()
{
	cout << 1 << endl;
	std::vector<int> v = test();
	cout << 3 << endl;
	return 0;
}
```

2まで表示されて、Segmentation Faultで落ちる。
似たようなことでハマった人がいないか、Stack Overflowで探してみると、やっぱりいたので、回答を要約すると。

#右辺値参照は、あくまでも参照の一種だ
関数を抜けだした時点でローカル変数は破棄されるので、ローカル変数の参照を返すのは、そもそも間違い。
右辺値参照だからとか、moveを使ったからとか、そんなのは関係ない。
古き良きC++時代の(左辺値)参照の場合と全く同じ理由で、ローカル変数の参照を返してはいけない。

#どうせコンパイラが最適化してくれるよ
return-value-optimization (RVO)と言って、こういう場合は無駄なコピーが発生しないよう、コンパイラが最適化してくれる。
だから、いらんことをしなくていい。

#結論：普通に値で返せ。
```cpp:普通のやりかた
std::vector<int> /* &&は不要 */ test(){
	std::vector<int> vec;
	// vectorにいろいろ挿入する処理(この記事と関係ないので省略)
	return vec; // std::move不要
}
```

#参考文献(似たようなことでハマった人たち)
[segmentation fault when moving std::vector [closed] - Stack Overflow](http://stackoverflow.com/questions/15703349/segmentation-fault-when-moving-stdvector)
[C++11 rvalues and move semantics confusion (return statement) -  Stack Overflow](http://stackoverflow.com/questions/4986673/c11-rvalues-and-move-semantics-confusion-return-statement)
WindowsからNASへファイル転送時エラー「アクセス中に問題が発生しました」の解決方法

## 問題となるエラー

Windows (Windows 7) から NAS (samba) にファイルを転送するとき、**特に 2 GB を超えるような大きなサイズのファイル**を転送するとき、

「XXXX にアクセス中に問題が発生しました
ネットワークへ接続しているか確認して、再試行してください。」

というエラーが発生することがあります。

![スクリーンショット 2016-04-27 23.49.19.png](https://qiita-image-store.s3.amazonaws.com/0/6390/0e3cc7fc-feab-af8d-e9fd-124c062483f3.png)

## 解決方法

まず、対象の NAS のファイルシステムが FAT32 とかの 2 GB までのファイルしか扱えないようなフォーマットではなくて、ちゃんと 2 GB 以上のファイルを扱えることを確認します。
それでもエラーが発生する場合、この原因は NAS ではなく、Windows 側にあります。タイムアウトが発生しています。

レジストリを変更します。
`\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters\` 内の `SessTimeout` を編集します。存在しなければ *DWORD (32 ビット) 値* で追加します。
値を例えば、600 とかに変更することで、タイムアウトを延ばすことができます。単位は秒で、この場合 600秒 = 10分 になります。これで、エラーが発生しなくなるはずです。ちなみにデフォルトのタイムアウトは 45 秒です。

## 参考資料

* LTFS-LE クライアントの構成 https://docs.oracle.com/cd/E48292_02/ja/E51139/html/client.htm
Material-uiのDialogを高さ１００％にする（v0.14.4限定）


v0.14.4限定の超暫定対処ですが、Material-uiのDialogを高さ１００％にするオプションを追加しました。

http://www.material-ui.com/#/components/dialog

このDialog、上下にpaddingがあって、高さ１００％になりません。
なのでスマホとか狭い画面では致命的に使えません。

今回プロダクションで必要になったため急遽無理やりに対応しました。
サンプルは、
https://github.com/p-l-interface/material-ui/tree/custom-v0.14.4-release/examples/dialog-full-height-example
です。

フォークして、v0.14.4を改造してます。
https://github.com/p-l-interface/material-ui/tree/custom-v0.14.4-release

rootで buildして、できたlib/dialog.jsを
examples/dialog-full-height-example/node_modules/material-ui/lib/dialog.jsと入れ替えると動きます。

実際に使うときは、それなりに配置してください

```js

 <Dialog
          open={this.state.open}
          title="Super Secret Password"
          actions={standardActions}
          modal={true}
          onRequestClose={this.handleRequestClose}
          autoScrollBodyContent={true}
          fullWidth={false}
          fullHeight={true}

        >
```



ついでに、fullWidthも追加しました。
fullHeight={true}にした場合は、縦横１００％になります。

おちついたら、ちゃんとつくってmaterial-uiにプルリクしようと思います。
showAsActionが効かない

ActionModeメニューのレイアウト定義ファイルにshowAsActionが効かない場合、対応する方法をメモします。

#menu定義ファイルにapp:showAsAction="always"を記述しているにも拘らず、メニューアイテムが・・・の中に入ってしまいます。

```
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_menu_item_search"
        android:icon="@android:drawable/ic_menu_search"
        android:onClick="onActionItemClicked"
        android:title="@string/action_menu_item_search"
        app:showAsAction="always">
    </item>
    <item
        android:id="@+id/action_menu_item_save"
        android:icon="@android:drawable/ic_menu_save"
        android:onClick="onActionItemClicked"
        android:title="@string/action_menu_item_save"
        app:showAsAction="always">
    </item>
</menu>
```

#プログラミングでメニューアイテムの該当属性を設定すれば、解決になります。

```
    @Override
    public void onActionModeStarted(ActionMode mode) {
        if (actionMode == null) {
            actionMode = mode;
            Menu menu = mode.getMenu();

            // Inflate your own menu items
            mode.getMenuInflater().inflate(R.menu.menu_action_mode2, menu);
            menu.getItem(2).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
            menu.getItem(3).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
        }

        super.onActionModeStarted(mode);
    }
```
ActionModeのメニューを動的に追加

画面のテキストを選択する時に、画面一番上にActionModeのメニューが表示される。
例えば、入力テキス枠に、文字をタップして、選択すると、「コピー」、「共有」などのメニューアイテムが出てくる。

この辺のメニューがAndroidのOS上でデフォルトで表示されるものだが、実は、カスタマイズすることも可能である。

#方法１
　　独自のメニューxmlを用意して、それを丸ごとに使う。

#方法２
　　デフォルトで表示されるメニューの一部を変更する。

今回は、独自のメニューを追加したいだけなので、方法2で実装する。

#実装
1.Menuレイアウトを定義する

```
menu_action_mode.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_menu_item_search"
        android:icon="@android:drawable/ic_menu_search"
        android:onClick="onActionItemClicked"
        android:title="@string/action_menu_item_search"
        app:showAsAction="always">
    </item>
    <item
        android:id="@+id/action_menu_item_save"
        android:icon="@android:drawable/ic_menu_save"
        android:onClick="onActionItemClicked"
        android:title="@string/action_menu_item_save"
        app:showAsAction="always">
    </item>
</menu>
```

2.自分のActivityクラスのonActionModeStartedメソッドを実装する

```
    @Override
    public void onActionModeStarted(ActionMode mode) {
        if (actionMode == null) {
            actionMode = mode;
            Menu menu = mode.getMenu();

            // 独自のメニューアイテムを追加する
            mode.getMenuInflater().inflate(R.menu.menu_action_mode, menu);
        }

        super.onActionModeStarted(mode);
    }
```

3.自分のActivityクラスにonActionItemClickedを実装する

　　onActionItemClickedが上記1でandroid:onClickに指定されたメソッドである。


```
    public boolean onActionItemClicked(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_menu_item_search:
                Intent intent = new Intent(this, Main2Activity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);
                break;
            default:
                // This essentially acts as a catch statement
                return false;
        }

        actionMode.finish();
        return true;
    }
```
オープンソース版PyMOLインストール （Windows）

# 目的

Windows 64 bit または 32 bitにPyMOLを入れる。
そのためにpythonのインストールからPyMOLのインストールまで解説する。


# 動機

[PyMOLの公式ページ](ttps://pymol.org)で登録することによって、Educational版のインストーラが入手可能であり、簡単にインストールできるが機能の制限も多い。制限はバージョンによって違うようだが、たとえばv1.74のEducation版ではray機能（レンダリング、きれいな画像を生成する機能）が使えない。またモデリング時のundo（直前の操作を戻す）もできない。
それに、32bit版しかない。

オープンソース版のPyMOLは、Edu版よりもバージョンが新しいのに加え機能に制限がない。
Edu版よりもインストールに手間はかかるが、それでも使う価値はある。

# (1) Pythonのインストール

anacondaおすすめ。（anacondaによるpython環境構築については、よく解説されています。良く使うモジュールも一緒にインストールしてくれるので、Pythonで他の解析等したい方は、anacondaの方が良いと思います。）

以下、Python公式ページからPythonをインストールした前提で解説する。anacondaを使った場合も、python.exeのPATHだけ変えれば良いので、ほとんど一緒。
[Pythonの公式ページ](https://www.python.org/)でPythonのインストーラ（.msi形式）をダウンロードする。

~~Python2.7とPython3.4の、2つのseriesがあるが，Python2.7をインストールする。なぜなら、これから紹介する方法ではオープンソースで公開されている最新版のPyMOLはPython2.7にしか対応していないからである（現在のところ）。ちなみに，Python3.4のほうが新しいが、まだまだPython2.7が使われることも多い。~~
（2018年3月27日追記）
Python3も使えるようになっていた。
Python3の場合も以下の方法でインストールできる。

pipというPythonパーケージのセットアップツールを使うが、Python3.4以上またはPython2.7.9以上のバージョンにしか含まれていないので注意。

コマンドプロンプトを開いて

```command
C:\Users\hoge> C:\Python27\python.exe
C:\Users\hoge> C:\Python27\Scripts\pip.exe
```

でpythonとpipがちゃんと動くことを確認する。

`C:\Users\hoge> C:\Python27\Scripts\pip.exe install wheel`

でインストールツールであるwheelをインストールする。


# (2)PyMOLに必要なパッケージをダウンロード
Pmw、numpy-mkl、pymol、pymol_launcherの4つをインストールする。
wheel（.whlの拡張子）のパッケージが以下のURLにある。
http://www.lfd.uci.edu/~gohlke/pythonlibs/
有志の方が非公式に公開しているサーバのようである（大学の研究室？）。結構頻繁にバージョンが更新されている。
pymol公式wikiでもこのサイトが紹介されている。

それぞれのパッケージをctrl+fで検索する。

現在見つかったのが、
Pmwは、
Pmw-2.0.1-py2-none-any.whl
Pmw-2.0.1-py3-none-any.whl
の2つ。
py2とpy3は、python2とpython3シリーズを表しているので、インストールしたpythonのバージョンに合うものをダウンロードする。

numpy+mklは、
http://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy
numpy-1.11.0+mkl-cp27-cp27m-win32.whl
numpy-1.11.0+mkl-cp27-cp27m-win_amd64.whl
numpy-1.11.0+mkl-cp34-cp34m-win32.whl
numpy-1.11.0+mkl-cp34-cp34m-win_amd64.whl
numpy-1.11.0+mkl-cp35-cp35m-win32.whl
numpy-1.11.0+mkl-cp35-cp35m-win_amd64.whl
みたいな感じ。
cp27、cp34、cp35はそれぞれpython2.7、3.4、3.5を表す。
win32、amd_64はそれぞれ32bitと64bit版を表す。
したがって、適合するものをダウンロードする。

pymolとpymol_launcherも同様。
pymol-1.7.6.0-cp27-none-win32.whl
pymol-1.7.6.0-cp27-none-win_amd64.whl
pymol-1.8.2.0-cp27-cp27m-win_amd64.whl
と
pymol_launcher-1.0-cp27-none-win32.whl
pymol_launcher-1.0-cp27-none-win_amd64.whl

pymolは、現在python2.7の64bit版で、一番新しいv1.8.2が使える。

これら4つのwhlファイルをどっかのディレクトリに置く。
たとえば`C:\Users\hoge\PyMOL_INSTALLATION`に置いたらコマンドプロンプトで

`C:\Users\hoge> cd C:\Users\hoge\PyMOL_INSTALLATION`
と打ってディレクトリを移動、
そこで

# (3) pymolのインストール

```
C:\Users\hoge\PyMOL_INSTALLATION> C:\Python27\Scripts\pip.exe install Pmw-2.0.1-py2-none-any.whl
C:\Users\hoge\PyMOL_INSTALLATION> C:\Python27\Scripts\pip.exe install numpy-1.11.0+mkl-cp27-cp27m-win_amd64.whl
C:\Users\hoge\PyMOL_INSTALLATION> C:\Python27\Scripts\pip.exe install pymol-1.8.2.0-cp27-cp27m-win_amd64.whl
C:\Users\hoge\PyMOL_INSTALLATION> C:\Python27\Scripts\pip.exe install pymol_launcher-1.0-cp27-none-win_amd64.whl
```

以上でインストール完了。

C:\Python27\PyMOL.exe
がデフォルトで作成される場所。

ファイルをダブルクリックで実行。

# 参考
https://pymolwiki.org/index.php/Windows_Install
拡張for文のちょっと便利な使い方

Java 7 以上で確認した．次のようなクラスA, B, Xがあるとする。

```java
public class A {
}
public class B<T> extends A {
}
public class X {
    public static <Z extends A> java.util.List<Z> get(Class<Z> clazz) {
        // dummy implementation
        return new ArrayList<Z>(); // ArrayList<>() is also valid in case of Java 8.
    }
}
```

このとき、`X#get()`を用いてBのインスタンスのリストを取得するために以下のように書こうとすると、

```java
List<B<?>> list = X.get(B.class);
```

次のコンパイルエラーになる。`List<B<?>>` へのキャストもできない。

```bash
Type mismatch: cannot convert from List<B> to List<B<?>>
```

ところが、以下のように拡張For文を用いてリストの要素を1つずつ取得すると、コンパイルエラーも警告も出なくなる。
フレームワークを作成する場合に少し便利なイディオムである。

```java
for (B<?> b : X.get(B.class)) {
    // do something with b.
}
```
postach.ioで独自ドメインを設定する

#はじめに#
Postach.ioを試用していて便利だったので、別サイトで使っている独自ドメインを設定して使うことにしました。その手順についてメモを残したいと思います。

#手順#
1. Postach.ioの管理画面からAcountsを開き、Billingから有料プランを購入します。
2. 独自ドメインを設定したいSiteのEditを開く。DetailsのCustom DomainのI'd like to use a custom domainにチェックを入れます。Custom Domain Nameに独自ドメイン名を指定します。
3. ドメイン管理サービスを開きます。例えば、お名前.comなどです。
4. お名前.comの場合、ログイン後、ドメイン設定→DNS関連機能の設定(→ドメイン名選択)→DNSレコード設定を利用する、の「設定する」を押す→登録済みの場合、TYPE A、TTL 300という箇所に、Value 54-227-242-252と指定して、保存する。
IPアドレスについては、公式ヘルプの[Using a Custom Domain](http://help.postach.io/post/using-a-custom-domain)に丁寧に説明されています。
5. しばらく時間を置くと、反映されて、登録したドメイン名からpostach.ioのサイトを開くことができるようになります。

#指定の副作用#
- 独自ドメインを指定すると、以前のxxx.postach.ioのURLは使えなくなり、独自ドメイン名に置換されたURLにリダイレクトされるようになる。
- 指定前の記事のURLは、ルートにリダイレクトされるようになる。
- Facebookで独自ドメインからなるURLをシェアしようとすると、キャッシュされている以前のサイトの情報が出てきてしまう。刷新するためには、Debuggerサイトでもう一度URLを読み込んであげる。"Enter a URL to see …"という箇所にURLをタイプして、デバッグボタンを押せばよい。
[Sharing Debugger](https://developers.facebook.com/tools/debug/)
Arukas.io CLI、まだ β なのに便利だった

[Arukas.io](https://arukas.io/) が `ステルス β` から `β` になったと聞いて。

（2016/05/02 追記：本家があれこれ更新されたので本文修正しました）

CLI もあるというので、早速 [GitHub リポジトリ](https://github.com/arukasio/cli) 見に行ったら開発環境は docker-compose ではなく Vagrant でした~~し、CircleCI こけてました~~が、まあ細かいことを気にしてはいけません。
使ってみたら便利だったのでレポートします。

# API キーを発行してもらう

[Arukas.io](https://arukas.io/) でアカウントを作って、ログインして
https://app.arukas.io/settings/api-keys ここで API キーを作ります。

# CLI インストール

~~2016/04/27 現在、コンパイル済みバイナリは配布されていないようなので~~
以下 3 パターンのどれかでインストールします。

## 方法 1. OS に合ったバイナリをもってくる

https://github.com/arukasio/cli/releases
ここから、手元の OS にあったバイナリを落としてきて

```bash:install-with-binary
cat << EOF >> .env
ARUKAS_JSON_API_TOKEN=<api-token>
ARUKAS_JSON_API_SECRET=<api-secret>
EOF
```

で OK です。

## 方法 2. Go 環境があるなら

```bash:install-with-golang
go get github.com/arukasio/cli/cmd/arukas

cat << EOF >> .env
ARUKAS_JSON_API_TOKEN=<api-token>
ARUKAS_JSON_API_SECRET=<api-secret>
EOF
```

## 方法 3. Docker 環境があるなら

```bash:install-with-docker
alias arukas="docker run --rm -e ARUKAS_JSON_API_TOKEN -e ARUKAS_JSON_API_SECRET arukasio/arukas"

export ARUKAS_JSON_API_TOKEN=<api-token>
export ARUKAS_JSON_API_SECRET=<api-secret>
```

# CLI を使ってみる

## run : 新しいアプリケーションの起動

Nginx を起動してみます。

`arukas run --instances 1 --mem 512 -p 80:tcp nginx`

（instances と mem は必須の引数で、それぞれ起動数と使用メモリ量です、たぶん）
返ってきた結果に `ENDPOINT` という列がありますが、これに `https://` をつければ、Nginx のハローページが表示されます。なんて簡単に立ち上がるんだ・・便利な世の中だ・・

## run : 引数多め版

[Arukas.io で Slack 自動招待フォーム](/pottava/items/cb3dad247d8e5778008e) のアプリを起動してみます。

`arukas run --app-name slack-test --name=slack --instances=1 --mem=512 -p 80:tcp -e SLACK_TEAM_NAME=MYTEAM -e SLACK_TEAM_DOMAIN=domain -e SLACK_TOKEN=token pottava/slack-invite:ja`

実はこのままでは起動しません。
引数である `name` が**世界中でユニークである必要がある**ためです。name を指定すると、これがサブドメインとなった `ENDPOINT` を用意してくれます。Arukas さん素敵です。

それにしても、構文がかなり Docker が意識されていて、慣れている方には優しい作りですね！

## ps : 起動中のアプリケーション一覧

`arukas ps`

いい感じ。

## ps -a : すべてのアプリケーション一覧

`arukas ps -a`

Docker と同じ。いいすね。

## start, stop : アプリケーションの起動・停止

`arukas start container-id`
`arukas stop container-id`

とても惜しいのですが、ここだけは Docker と違い、ID の短縮系は受け付けてくれません。どうやら Arukas の API エンドポイントが REST API すぎて融通が効かない模様です。はい・・。ここは `ps` の結果をコピペせざるを得ない・・

## rm : アプリケーションの削除

`arukas rm container-id`

私まだ試してませんが、たぶんこれで消えるのでしょう。

# 感想

Arukas.io への要望はたくさんありますが、CLI はいい感じ！
~~まだドキュメントも何もないけど、ソース読めばわかるしまあよし~~。余力があったらみんなで PR 投げていい感じに仕上げていきたいですね。

~~ちなみに、CLI インストール方法 3 の Docker イメージは [私が作った野良イメージ](https://hub.docker.com/r/pottava/arukas/) です。[Alpine Linux](http://qiita.com/pottava/items/970d7b5cda565b995fe7) は正義！6MB です。・・とはいえ、公式 CLI のリリースをウォッチしてるわけではないので、バージョンが古くなっていたらすいません。公式でもサポートしてくれるといいなあ~~
CLI の Docker イメージですが、超速で [公式に対応](https://hub.docker.com/r/arukasio/arukas/) されたようなので記事を更新しました。（2016/05/02）
一定時間入力が無い場合にのみ動作するフォームの作成

##　入力フォームにサジェスト機能を追加したい

googleの検索窓のように、フォームに文字入力した場合、検索結果をサーバーから取得し、結果一覧をサジェストとしてフォームに表示するような実装を行いたい。

すでにフロント側でサジェストとして表示する一覧のデータを持っているなら良いのですが、文字を1文字入力するたびに、サーバーにGETリクエストを投げるのはすごいイヤなわけです。外部APIと連携していれば、Rate Limitに達する可能性もあります。
かといって、エンターキーやボタンを押した際にサジェストを表示するのも、サジェストの意味あるの？という気がします。

そこで、最後の文字入力から1秒経過した場合に、サーバーにGETリクエストを投げる、という実装をしてみたいと思います。文字を入力した後、1秒以内に文字がタイプされた場合は、またタイマーがリセットされる、という仕組みです。

## コード

AngularJSを用いて書いてみました。実際の実行例はこちらから(http://jsfiddle.net/ADukg/8059/)
文字を入力して少し経つと、「サジェストの結果」に文字が出てきます。
また、連続して文字を入力した場合は、サジェストの結果に反映されません。

```html:form.html
<div ng-controller="MyCtrl">
  <form name="timeForm">
    <input type="text" name="firstName" ng-model="formString">
    <p>
    サジェストの結果:  {{showString}}
    </p>
  </form>
</div>
```

```js:main.js
var myApp = angular.module('myApp',[]);

function MyCtrl($scope) {
  // 処理待ち用のキュー
  $scope.searchQueue = [];
  $scope.showString = '';

  // 文字入力があるたびに、waitAndGo関数を実行
  $scope.$watch('formString', function() {
    waitAndGo($scope.formString);
	});

  // 一定時間文字入力が無い場合は処理を実行
  function waitAndGo(searchQuery){
    // 処理待ちのイベントが無いか確認し、ある場合は全て実行をキャンセルする
    if($scope.searchQueue.length > 0) {
      $scope.searchQueue.forEach(function(elem){
        clearTimeout(elem);
        $scope.searchQueue.shift();
      });
    }

    // 1秒間request関数の実行を待つ。setTimeOutのIDを取得し、処理待ち用のキューに格納する
    var eventId =  setTimeout(request, 1000, searchQuery);
    $scope.searchQueue.push(eventId);

    // サーバーへのリクエスト処理。ここでは便宜的にscopeへ代入します。
    function request(query) {
        $scope.showString = query;
        $scope.$digest();
    }
  }
}
```

文字が入力されるたびに、

1. 実行待ちのイベントは無いか確認
2. あれば全て削除
3. 入力された文字列でリクエストを実行するイベントを1秒間遅延させ、実行待ちのキューの中に登録

を、文字入力時ごとに、繰り返すことにより、ある程度まとまった文字列でGETリクエストを送信することが可能です。
オンラインSICP読書女子会 #10(1.3.3 無限連分数) まとめ


[オンラインSICP読書女子会 #10 (1.3.3~1.3.4) - connpass](http://ladiespp.connpass.com/event/30416/)のまとめです！

## 1.37
N_i, D_i がすべて1の無限連分数は1/φ (φは黄金比)

```lisp
;; 再帰プロセス
(define (cont-frac n d k)
  (define (iter i)
    (if (= i k)
	(/ (n i) (d i))
	#?= (/ (n i) (+ (d i) (iter (+ i 1))))))
  (iter 1))

(cont-frac (lambda (i) 1.0)
	   (lambda (i) 1.0)
	   20)

;; #?-    0.5
;; #?-    0.6666666666666666
;; #?-    0.6000000000000001
;; #?-    0.625
;; #?-    0.6153846153846154
;; #?-    0.6190476190476191
;; #?-    0.6176470588235294
;; #?-    0.6181818181818182
;; #?-    0.6179775280898876
;; #?-    0.6180555555555556
;; #?-    0.6180257510729613
;; #?-    0.6180371352785146
;; #?-    0.6180327868852459
;; #?-    0.6180344478216819
;; #?-    0.6180338134001252
;; #?-    0.6180340557275542
;; #?-    0.6180339631667064
;; #?-    0.6180339985218034
;; #?-    0.6180339850173578

;; 反復プロセス(末尾再帰)
(define (cont-frac n d k)
  (define (iter i result)
    (print i "->" result)
    (if (= i 0)
	result
	(iter (- i 1)
	      (/ (n i)
		 (+ (d i) result)))))
  (iter k 0))

(cont-frac (lambda (i) 1.0)
	   (lambda (i) 1.0)
	   20)


;; 20->0
;; 19->1.0
;; 18->0.5
;; 17->0.6666666666666666
;; 16->0.6000000000000001
;; 15->0.625
;; 14->0.6153846153846154
;; 13->0.6190476190476191
;; 12->0.6176470588235294
;; 11->0.6181818181818182
;; 10->0.6179775280898876
;; 9->0.6180555555555556
;; 8->0.6180257510729613
;; 7->0.6180371352785146
;; 6->0.6180327868852459
;; 5->0.6180344478216819
;; 4->0.6180338134001252
;; 3->0.6180340557275542
;; 2->0.6180339631667064
;; 1->0.6180339985218034
;; 0->0.6180339850173578
;; 0.6180339850173578
```

k = 11 くらいから4桁の精度になった

## 1.38 自然対数の無限連分数

```lisp
(define (cont-frac n d k)
  (define (iter i)
    (if (= i k)
	(/ (n i) (d i))
	(/ (n i) (+ (d i) (iter (+ i 1))))))
  (iter 1))

(define (n-cont-frac n)
  (define (n-iter j)
    (if (> j n)
	"end"
	(let ((ans
	       (cont-frac (lambda (i) 1.0)
			  (lambda (i)
			    (let ((div (quotient i 3))
				  (mod (modulo i 3)))
			      (if (= mod 2)
				  (- i div)
				  1.0)))
			  j)))
	  (print j "=>" (+ 2 ans))
	  (n-iter (+ j 1)))
	))
  (n-iter 1))

(n-cont-frac 10)
;; 1=>3.0
;; 2=>2.6666666666666665
;; 3=>2.75
;; 4=>2.7142857142857144
;; 5=>2.71875
;; 6=>2.717948717948718
;; 7=>2.7183098591549295
;; 8=>2.718279569892473
;; 9=>2.718283582089552
;; 10=>2.7182817182817183
;; "end"


;;反復プロセス
(define (cont-frac n d k)
  (define (iter i result)
    (if (= i 0)
	result
	(iter (- i 1)
	      (/ (n i)
		 (+ (d i) result)))))
    (iter k 0))
(n-cont-frac 10)

;; 1=>3.0
;; 2=>2.6666666666666665
;; 3=>2.75
;; 4=>2.7142857142857144
;; 5=>2.71875
;; 6=>2.717948717948718
;; 7=>2.7183098591549295
;; 8=>2.718279569892473
;; 9=>2.718283582089552
;; 10=>2.7182817182817183```
```

反復プロセスも再帰プロセスもちゃんとうごいてるっぽい！

## 1.39 tan_x の∞連分数



```lisp
(define (cont-frac n d k)
  (define (iter i)
    (if (= i k)
	(/ (n i) (d i))
	(/ (n i) (+ (d i) (iter (+ i 1))))))
  (iter 1))

(define (tan x)
  (cont-frac (lambda (i)
	       (if (= i 0) x
		   (* -1 (* x x))))
	     (lambda (i) (- (* 2 i) 1))
	     n))

(define pi 3.141592)
(tan (/ pi 4)) ;; 0.9999996732051569
```
入門 機械学習による異常検知 3章 を読んで

[入門 機械学習による異常検知](http://www.amazon.co.jp/%E5%85%A5%E9%96%80-%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%81%AB%E3%82%88%E3%82%8B%E7%95%B0%E5%B8%B8%E6%A4%9C%E7%9F%A5%E2%80%95R%E3%81%AB%E3%82%88%E3%82%8B%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-%E4%BA%95%E6%89%8B-%E5%89%9B/dp/4339024910)を少しずつ読んでいます。

3章「非正規データからの異常検知」を読み終えたので、備忘録がてら書いていきます。
自分用のメモなので、かなり適当です。ご容赦ください。

本の目次は[こちら](http://www.coronasha.co.jp/np/download/2032602805.pdf)。

3章では、タイトル通り、正規分布ではないデータや、正規分布かどうかわからないデータに対する異常検知の方法について書かれています。

#ガンマ分布当てはめ
標本データの分布が非対称な場合や、標本データが正の値しか取らない場合、正規分布を仮定するといろいろまずい。
そういう時には、標本データの分布を正規分布ではなく、ガンマ分布に当てはめる。分布の推定→異常度の定義→しきい値の設定という流れは、2章の正規分布の場合と同じ。

#混合正規分布と期待値最大化法
標本データの分布が、複数の正規分布の重ねあわせになっているような場合の分布の推定方法について解説。重ねあわせの分布から、各分布の重みπ、標本平均μ、標本分散σを推定するんだけど、まともにやると変数が多く、計算も複雑になる。なので、分布を推定するための方法として、期待値最大化法（EM法）を使う。

#近傍法
##k近傍法
データがまばらで分布がわからない場合などに用いられる。観測データと、近傍の標本データとの距離を元に異常かどうかを判別する。
・観測データの近傍のk個のデータが入る最小半径を元に異常かどうか判定する方法
・観測データの半径ε内に入るデータの個数を元に異常かどうかを判定する方法
標本データはすべて正常なデータのみというのが前提。ｋとεを決めてやる必要がある。すべてのデータ点数に対して距離を計算する必要があるので、データセットが大きいと計算量が膨大になる。

##局所外れ値法
観測データx'とｋ個の近傍のデータx''との距離と、近傍のデータx''とその周辺のｋ個の近傍のデータとの比を異常度（LOF: Local Outlier Factor）とし、異常かどうかを判別する。データの分布に濃淡があるような場合に用いる。

##カーネル密度推定
k近傍法における個々のデータ点を、確率的に拡張？したもの。難しい。データ間の距離を変数とした確率分布。パラメータｈの算出方法がよくわからなかった。

#クラスタリング
##k平均法
k個のクラスターに分ける。データとクラスター重心の距離の総和を最小化するように、クラスターへの分け方を決める。ｋを決めてやる必要がある。

##混合正規モデル
クラスタリングする際に、統計的な考え方を取り入れたもの。一旦クラスタに分けられたデータセットに対して、各クラスタの分布を推定。ここで、前述の混合正規分布モデルと期待値最大化法が再度登場する。新たな標本ｘが、どのクラスタに属するかを確率的に決める。２つ以上のクラスタが近接していて、クラスタ間に位置するデータが、どちらのクラスタに属するかを判別する場合などに有効。

#サポートベクトルデータ記述法
いわゆるワンクラスサポートベクターマシン。カーネルトリックを使ってデータを非線形写像することで、問題を簡単に扱えるようにする。どんなカーネルを使うのか、訓練データにおける異常標本の割合を決めてやる必要がある。高次元になると解釈が難しいので注意。
画像サーバの負荷対策：プロキシーキャッシュサーバ導入

## 目的
画像サーバの負荷軽減と台数削減。
##前提条件
現在、サーバは物理のみで構成されておりクラウドは利用できない。
※社内事情により、インフラのクラウド移行はもう少し先になる :cry: 
社内事情により、CDNの利用ができない。
## 現在の状況
オリジンサーバ：13台
ピーク時全体平均CPU使用率90%越え :astonished: 
## プロキシサーバの検討
varnishとnginxを検討してみる。単純にプロキシサーバとしての基本機能は変わらなさそう。
varnishは、ESI(部分キャッシュ)や細かいpurge機能が魅力であるが、今回はURLをキーとしたバイナリファイルのキャッシュのみの利用であるため、キャッシュに関しては多機能である必要はない。
プロキシサーバとしてリクエストをさばく能力や実績としてはnginxの方が良いと感じnginxを採用。
## キャッシュ方法
### １、nginxのproxy_cache
キャッシュをストレージへの保存（HDD or SSD)となる。
しかし、iowaitの発生でCPU負荷orロードアベレージが上げる懸念がある。
また、SSDが利用できない社内事情がある。
せっかく実装を終えても負荷が高くなり、メモリにキャッシュするという方針に変わることを想定すると
はじめからメモリにキャッシュする方法を選択したほうが良い。
メモリに保存したい場合は、nginxにtmpfsというメモリ上に仮想的なファイルシステムを実現できる機能がある。
キャッシュを明示的に削除する方法が必要だが、proxy_cacheに対するpurgeモジュールを利用することで
指定のキャッシュを削除することができる。

#### 懸念点
当社システムの事情で、元画像の更新が日々頻繁に行われる。（同じ画像ではなく別の各画像が更新される）
複数ユーザーが同時に大量の画像を更新することを想定すると、アプリ側からキャッシュの削除指示をhttpで行うことはプロキシサーバへのコストが高いと考えられる。
また、今後プロキシサーバを複数台のスケールアウトすることも考えた場合、キャッシュ使用効率や整合性を保ちやすいようキャッシュを共有できた方が良い。
そのため、プロキシサーバ内にキャッシュ保存することは避けたい。

### ２、KVSでバイナリキャッシュ
memcachedかredisを利用する方法がある。
KVSは、キャッシュサーバの再起動が必要となった際にキャッシュが消えてしまう問題がある
Redisでは永続化ができるが、障害などでサーバが停止して起動するまでの間に元画像の更新があった場合、リストアしたキャッシュとの整合性が取れなくなる。
キャッシュ期間分だけ整合性がとれない状況が生まれ問題となる。
元画像の更新と同時にキャッシュを削除しなければいけない要件があるため、永続化は不要となる。
また、一時的にキャッシュが消えることでバーストする問題もあるが、先ほど述べた整合性の問題は無視できないため致し方ないと考える。
（キャッシュ生成まで一時的にプロキシサーバが高負荷になるが仕方ない）。合わせて、画像サーバを削減した後で、キャッシュが動作しないことでサイトが高負荷な状態となるため、この件についてはプロキシキャッシュサーバを2台にするなどを検討中である。

#### redisとmemcachedどちらでも良いといえば良いのだが、下記理由でmemcachedを採用した。
・単純なset/getのみであればredisよりmemcachedの方がパフォーマンスが良いというベンチマークの記事が多い。
・永続化不要
・単純なバイナリキャッシュのみの利用
・マルチスレッド設定が簡単にできる（redisでは同じmasterをマルチプロセスで見る場合、クラスタ化する必要がある）

#### １の懸念点に対して２で解決できそう？
・削除指示をhttpリクエスト → TCPコネクション
コネクションプールするなどして接続コストを抑えれば、大量の削除に対するコストが抑えられそう。
少なくともnginxへの負担はなくなる。

2の場合であれば、元画像更新時にキャッシュの削除ではなく、キャッシュの更新を行うことが可能。
1の場合だと元画像更新時に削除するリクエストとキャッシュを生成するためのリクエストの２回処理が必要となる。

また、社内事情から画像の種類によってキャッシュ期間を細かく設定するケースも出てくる可能性もあり、
KVS利用の方が何かとキャッシュをコントロールする上で利便性があると感じた。

## キャッシュの削除
### 1、アプリ内からキャッシュの更新
元画像の更新処理が実行される際に、memcachedのキャッシュデータを更新する。
当社のレガシーシステムではアプリ側がperlで動作しているためCPANモジュールの「Cache::Memcached」を利用する。
### ２、URLから削除
整合性が取れないなど、キャッシュをピンポイントで意図的に削除したい場合に備え、削除用のURLを叩けばキャッシュが削除できるようにする。ただし、社内の人間からのみ削除可能するためIP制限をする。
### ３、LRUでの削除
CACHESIZEを超えた時点で古いものから自動削除される。

## nginxとmemcachedの連携
ngx_http_memcached_moduleを利用する。


## 導入後の改善結果
ピーク時のCPU負荷が抑えられ、平均負荷も下がりました :smile: 
アクセス頻度の高い画像のみをキャッシュ対象としているため、対象外の画像のリクエストはバックエンドに流れていますが、ピークタイムに効果が発揮できました。

ピーク時
CPU使用率： 92.2% → 41.5%

### プロキシキャッシュサーバの負荷
ピーク時
CPU使用率：1.0%

CPU負荷はほとんどない状態でリクエストを捌けています。nginxもmemcachedも負荷は余裕でした。

最終的に、バックエンドにある（オリジン）画像サーバは７台削減できました。
goでjson apiを叩く


goでjson apiを叩くサンプル(Decoderを使ったバージョンも追加)

```golang:json_sample.go
package main

import (
  "net/http"
  "fmt"
  "log"
  "encoding/json"
  "io/ioutil"
  "flag"
)

type JsonTestDate struct {
  Time string `json:"time"`
  Msec int64  `json:"milliseconds_since_epoch"`
  Date string `json:"date"`
}

func main(){
  useDecoder := false
  flag.BoolVar(&useDecoder, "decoder", false, "use json decoder")
  flag.Parse()

  res, err := http.Get("http://date.jsontest.com/")
  if err != nil {
    log.Fatal(err)
  }
  defer res.Body.Close()
  if res.StatusCode != 200 {
    fmt.Println("StatusCode=%d", res.StatusCode)
    return
  }
  //Dump response status line
  fmt.Printf("======Status line======\n")
  fmt.Printf("%s %s\n", res.Proto, res.Status)

  //Dump response header
  fmt.Printf("======Header======\n")
  for k, v := range res.Header {
    fmt.Printf("%s:%s\n", k, v)    
  }

  var d JsonTestDate
  if !useDecoder {
    //Dump response body (use json.Unmarshal)
    fmt.Printf("======Body (use json.Unmarshal)======\n")
    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
      log.Fatal(err)    
    }

    err = json.Unmarshal(body, &d)
    if err != nil {
      log.Fatal(err)    
    }
  } else {
    //Dump response body (use Decoder)
    fmt.Printf("======Body(use json.Decoder)======\n")
    decoder := json.NewDecoder(res.Body)
    err = decoder.Decode(&d)
    if err != nil {
      log.Fatal(err)    
    }
  }
  fmt.Printf("%v\n", d)
}

```


```bash
➜  golan go run json_sample.go -decoder=1
======Status line======
HTTP/1.1 200 OK
======Header======
Access-Control-Allow-Origin:[*]
Content-Type:[application/json; charset=ISO-8859-1]
Date:[Fri, 10 Jun 2016 14:28:38 GMT]
Server:[Google Frontend]
Content-Length:[100]
======Body(use json.Decoder)======
{02:28:38 PM 1465568918612 06-10-2016}
➜  golan go run json_sample.go
======Status line======
HTTP/1.1 200 OK
======Header======
Access-Control-Allow-Origin:[*]
Content-Type:[application/json; charset=ISO-8859-1]
Date:[Fri, 10 Jun 2016 14:28:43 GMT]
Server:[Google Frontend]
Content-Length:[100]
======Body (use json.Unmarshal)======
{02:28:43 PM 1465568923974 06-10-2016}
```
Raspberry piのnode.jsをV4系 LTSに入れ替える

#はじめに
本記事は、RASPBIAN JESSIE(2016-03-18)にて、node.jsのバージョンをV4系のLTSに入れ替える方法を記載します。

#古いバージョンを削除する。

デフォルトでインストールされているnode.jsはv0.10.29です。

```
pi@raspberrypi:~ $ node -v
v0.10.29
```

まずはこれを削除します。

```
pi@raspberrypi:~ $ sudo apt-get autoremove nodejs
```

#新しいバージョンをインストールする。

nvmを使って新しいバージョンのnode.jsインストールします。
また、今回はシステム全体で同じnpmおよびnode.jsの環境が使えるようにします。
そのため、/usr/localの配下にnvmをインストールします。

```
pi@raspberrypi:~ $ sudo mkdir /usr/local/nvm
pi@raspberrypi:~ $ sudo chmod 777 /usr/local/nvm
pi@raspberrypi:~ $ git clone https://github.com/creationix/nvm.git /usr/local/nv
m
pi@raspberrypi:~ $ . /usr/local/nvm/nvm.sh
```

次回から自動でnvmの環境が実行されるように、`/etc/profile.d/nvm.sh`を作成します。

```
pi@raspberrypi:~ $ sudo vi /etc/profile.d/nvm.sh
```

以下の内容を記載しておきます。

```
source /usr/local/nvm/nvm.sh
```

現時点(2016.4.27)での最新のLTSの4.4.3をインストールします。
※node.jsのLTSについては[こちら](https://github.com/nodejs/LTS)を参照。

```
pi@raspberrypi:~ $ nvm install v4.4.3
```

#sudoでnode.jsが動作できるようにする

GPIOを制御する場合等はnode.jsをsudoで動作させる必要があります。その為の設定をしておきます。

```
pi@raspberrypi:~ $ sudo visudo
```

以下のように、secure_pathの行をコメントアウトし、env_keepの行を追加します。

```
Defaults        env_reset
Defaults        mail_badpass
#Defaults        secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:...
Defaults        env_keep += "PATH"
```

npmもアップデートします。

```
pi@raspberrypi:~ $ npm update -g npm
```
以上です。
Dockerfileのコーディング規約を考えてみた

Dockerのコーディング規約はあるけど、Dockerfileのものはなくて、公式サイトのサンプルを見比べても決まったルールがなさそうだったので自分用のルールをまとめた。

# インデント

- スペース2つ（タブ文字は使わない）

```
RUN apt-get update && apt-get install -y \
  bzr \
  cvs \
  git \
  mercurial \
  subversion
```

# コメント

- 書かなくてもいいけど分かりにくいなと思ったら書く

```
# Jenkins home directory is a volume, so configuration and build history 
# can be persisted and survive image upgrades
VOLUME /var/jenkins_home
```

# 改行

- 処理のまとまり毎に入れる

```
ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH

RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"

WORKDIR $GOPATH
```

# RUNコマンドの連結

- 行末は \
- 改行後は2つスペースを空けて & で始める

```
RUN groupadd -g ${gid} ${group} \
  && useradd -d "$JENKINS_HOME" -u ${uid} -g ${gid} -m -s /bin/bash ${user}
```

# ABC順にする

- インストールするモジュールを複数書く場合、同じものを間違えて指定しないように

```
RUN apt-get update && apt-get install -y \
  bzr \
  cvs \
  git \
  mercurial \
  subversion
```

# ADDは使わない

- COPYを使おう

```
COPY requirements.txt /tmp/
RUN pip install --requirement /tmp/requirements.txt
COPY . /tmp/
```

# ベストプラクティス

コーディング規約じゃないけど

英語
https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/
日本語
http://docs.docker.jp/engine/articles/dockerfile_best-practice.html
Dockerのport forwardingでLinuxとOS Xでの違いにハマったという話

TL;DR
[Docker Machineのマニュアル](https://docs.docker.com/machine/get-started/)を読めばOK。

普段はLinuxをホストにして使ってるのでdocker run時に-p 8080:80とかした場合、↓のように127.0.0.1を使えばコンテナ内の80ポートにアクセスできてたわけで、特に何も考えてなかったのです。

```
curl http://127.0.0.1:8080/
```

でも、OS Xの場合だとOS Xとコンテナゲストの間にVirtualBoxがいるんですよね。なので、Linuxのノリで127.0.0.1を使うとアクセスできない。

```
$ curl -I http://127.0.0.1:8080/
curl: (7) Failed to connect to 127.0.0.1 port 8080: Connection refused
```

そのため、IPアドレスを調べておいて、

```
$ docker-machine ip
192.168.99.100
```

そのIPアドレスでアクセスする必要がある。

```
masami@zen:~$ curl -I http://192.168.99.100:8080/
HTTP/1.1 200 OK
Server: nginx/1.9.14
Date: Wed, 27 Apr 2016 13:52:56 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 05 Apr 2016 15:20:43 GMT
Connection: keep-alive
ETag: "5703d7cb-264"
Accept-Ranges: bytes
```

192.168.99.100はVirtualBoxのVMでホストオンリーアダプタに設定されているアドレスです。
Linux環境ではdocker-machineを使っていないので、この場合、VMを挟むのかどうかってのは調べて無いですが。
Wiresharkのキャプチャ

# 表示フィルタ(ディスプレイフィルタ)


フレームを取得すると、大量のフレームが表示される。

表示フィルタを使用して、表示したいフレームだけ表示する。


|フィルタ|説明|
|:---|:---|
|ip.addr == 192.168.1.1|送信元か宛先のIPアドレスが192.168.1.1|
|ip.src == 192.168.1.2|送信元のIPアドレスが192.168.1.2|
|ip.dst == 192.168.1.3|宛先のIPアドレスが192.168.1.3|
|icmp|icmpプロトコルのフレーム(他:tcp, udp, http, arp等)|
|tcp.port == 80|TCPポート番号80|
|tcp.srcport == 80|・・・|
|tcp.dstport == 80|・・・|
|udp.port == 53|UDPポート番号53|

    右クリックによるディスプレイフィルタが可能

---

# キャプチャフィルタ


表示フィルタは全てのフレームを取得した後、表示だけに適用される。

キャプチャフィルタはキャプチャの時、ルールを決める。

|フィルタ|説明|
|:---|:---|
|host 192.168.1.1|送信元か宛先のIPアドレスが192.168.1.1のフレーム|
|ip src host 192.168.1.2|送信元のIPアドレスが192.168.1.2のフレーム|
|ip dst host 192.168.1.3|宛先のIPアドレスが192.168.1.3のフレーム|
|icmp|icmpプロトコルのフレーム(他:tcp, udp, http, arp等)|
|tcp port 80|TCPポート番号80のフレーム|
|udp port 53|UDPポート番号53のフレーム|

---

# パケット一覧部概略


パケット一覧部概略は以下のようになっている。

|__No__|__Time__|__Source__|__Destination__|__Protocol__|__Length__|__Info__|
|:---|:---|:---|:---|:---|:---|:---|
||||||||

各項目の説明

|__項目__|説明|
|:---|:---|
|__No__|パケットの順番|
|__Time__|１番目のパケットからの経過時間|
|__Source__|送信元のIPアドレス|
|__Destination__|宛先のIPアドレス|
|__Protocol__|プロトコル|
|__Length__|フレームの長さ(Byte)|
|__Info__|パケットの意味|

---
Tera Termの操作方法（基礎）

# 接続に関する設定

1.　「設定」ー「TCP/IP」

2.　よく使うホストを登録しておく

3.　ホストリストに予め登録されたホストは、ブルダウンから接続先を選ぶことができる。

>　Keep-aliveの値が「0」に設定されていたら、Keep-aliveが無効になっていることを表す。

---

# コピペの設定

1.「設定」ー「その他の設定」ー「コピーと貼り付け」

2.「危険なクリップボード貼り付けを確認する」を有効にする。

    この機能により、改行を含むベースとを実行する際に確認メッセージが表される。
    想定外のコマンドの実行を防止できる。

3.「キーワードファイル」設定で`rm -rf`を含むコピペの際に確認メッセージが表わされる。

``` sh
rm -rf
reboot
shutdown
reload
write erase
write memory
```

「貼り付けの行間遅延」が`0msec`になっていないことを確認します。

 オススメのはデフォルトの`10msec`。

`Config流し込み`を行う際、同期ずれが発生しづらくなる。

---

# 操作ログの記録

1.「設定」ー「その他の設定」ー「ログ」

2.「設定」ー「その他の設定」ー「Cygwin」

    1. 「Cygwinインストール先のパス」を指定

    2. Tera TermでCygwinを操作できる。

    3. 64BitのWindowsの場合は`C:\cygwin64`に変更する必要がある。
　
---

# 設定ファイルの保存

設定ファイル名を`TERATERM.INI`として保存することで、

次回のTera Term起動時に設定が自動的に読み込まれます。

### 設定ファイルの手動読み込み

「設定」ー「設定の読み込み」

### 設定の自動読み込み

1.「Tera Termファイルをマウスの右のボタン」ー「プロパティ」

2.「リンク先の最後」ー`F=DEVELOP.INI` (DEVELOP.INIは例です。)
OS、ブラウザごとのCSSハックなどまとめ


## ブラウザごとのハック
### IE
```css
.sample{
  background: #cccccc\9; /* IE10以下 */
}

@media all and (-ms-high-contrast: none){
  .sample{
    background: #cccccc; /* IE10以上 */
  }
}

```
個人的にIEのverごとに対応することがあまりないのでIEでまとめました。
verごとに分ける場合は参考URLを参照。

### Firefox
```css
@-moz-document url-prefix(){
  .sample{
    background: #cccccc;
  }
}
```

### Chrome
```css
@media screen and (-webkit-min-device-pixel-ratio:0){
  .sample{
    background: #cccccc;
  }
}
```

### Safari
```css
@media screen and (-webkit-min-device-pixel-ratio:0) {
  ::i-block-chrome, .sample{
    background: #cccccc;
  }
}
```

## OSごとのハック
css_browser_selectorを使用するのがよいかも。
[GitHub](https://github.com/rafaelp/css_browser_selector)

```css:例
.win {
    /*Windows (全バージョン)のみ*/
}
.linux {
    /*linux（x11とlinux）のみ*/
}
.mac {
    /*Mac OSのみ*/
}
.iphone {
    /*iphoneのみ*/
}
.ipad {
    /*ipadのみ*/
}
.android {
    /*Google Androidのみ*/
}
```

上のjsはユーザーエージェントでクラスをつけている
### iPhoneのみ
```js:js
if ( navigator.userAgent.indexOf('iPhone') > 0 ) {
    $("body").addClass("iPhone");
};
```

### Androidのみ
```js:js
if ( navigator.userAgent.indexOf('Android') > 0 ) {
    $("body").addClass("Android");
};
```

## IEの条件付きコメント
```html
<!–[if IE 9.0]>
内容
<![endif]–>
```
IEの条件付きコメントはIE5〜9にしか対応していません。
IE10、11ではコメントとして解釈します。
今IE8以下に対応することはほとんどなくなってきてるので、使う機会もあまりなさそうですね。


## 参考URL
[IEのバージョン毎のハックを試してみる](http://cly7796.net/wp/css/hack-of-each-version-of-internet-explorer/)
[ブラウザまたはOS毎にCSSハックできるjs『CSS Browser Selector』](http://kotori-blog.com/css/css_browser_selector/)
[IE条件付コメントまとめ](http://html-coding.co.jp/knowhow/tips/000009/)