OmniAICreator/Qiita-1.07M huggingface dataset:
SpringのAOPについて


AOPとはアスペクト指向プログラミング(Aspect Oriented Programming)の略で、複数のクラスに点在する横断的な関心事を中心に設計や実装を行うプログラミング手法のことです。

[Spring徹底入門 Spring FrameworkによるJavaアプリケーション開発](https://www.amazon.co.jp/Spring徹底入門-Spring-FrameworkによるJavaアプリケーション開発-株式会社NTTデータ/dp/4798142476/)に載っているAOPの説明について、重要だと思う箇所をまとめます。*（後で見返せるように書籍のページ数を記載しています）*

# AOPの用語
AOPの代表的な用語について(P.59)

* Aspect
AOPの単位となる横断的な関心事を示すモジュールそのもののこと。
例としては、「ログを出力する」「例外をハンドリングする」「トランザクションを管理する」などがAspectと呼ばれる。  
  
* Join Point
Aspectを実行するポイント(メソッド実行時や例外スロー時など)のこと。
Spring AOPでのJoin Pointはメソッドの実行時です。
  
* Advice
特定のJoin Pointで実行されるコードのこと。
横断的な関心事を実装する箇所。
Around、Before、Afterなど複数の種類が存在する。
  
* Pointcut
実行対象のJoin Pointを選択する表現(式)のこと。
Join Pointのグループと捉えられる。
Spring AOPでは、Bean定義やアノテーションでPointcutを定義する。
例えば、○○Controllerという名前のクラスでのみ実行とか、findで始まるメソッド名の場合のみ実行するなどを決めるものです。
ワイルドカード指定が出来ます。
  
* Weaving
アプリケーションコードの適切なポイントにAspectを入れ込む処理のこと。
Spring AOPでは実行時にWeavingを行う。
  
* Target
AOP処理によって処理フローが変更されたオブジェクトのこと。
Advicedオブジェクトと呼ばれる場合もある。

# Springで利用可能なAdvice
Spring AOPでは以下の5つのAdviceを利用できる。(P.60)

|Advice|概要|
|:----|:----|
|Before|Join Pointの前に実行されるAdvice。|
|After Returning|Join Pointが正常終了した後に実行されるAdvice。例外がスローされた場合は実行されない。|
|After Throwing|Join Pointで例外がスローされた後に実行されるAdvice。正常終了した場合は実行されない。|
|After|Join Pointの後で実行されるAdvice。正常終了、例外に関わらず実行される。|
|Around|Join Pointの前後で実行されるAdvice。|

# Pointcut式
以下のソースコードの様にexecutionなんたらと書いて、実行対象のJoin Pointを選択する記述方法。(P.69)

```java
@Aspect
@Component
public class MethodStartLogAspect {

    // *Controllerというクラス名の任意のメソッドで実行するAdviceの例
	@Before("execution(* *..*Controller.*(..))")
	public void startLog(JoinPoint jp) {
		System.out.println("メソッド開始:" + jp.getSignature());
	}
}
```

## メソッド名で対象のJoin Pointを選択する
メソッド名のパターンを指定して対象のJoin Pointを表現するときには、execution指示子を使用する。

```java
execution(* com.example.domain.*Service.find*(..))

/*
上記例では、

戻り値が*
パッケージ名がcom.example.domain
型、クラス名が*Service
メソッド名がfind*
引数が任意の0以上の引数

を表している。
*/
```

## Pointcut式で利用可能なワイルドカード
Pointcut式で利用可能なワイルドカードは以下です。(P.70)

|ワイルドカード|説明|
|:----|:----|
|*|基本的には任意の文字列を表すが、パッケージを表現する場合は、任意のパッケージ1階層を表す。メソッドの引数を表現する場合は、1つの数の引数を表す。|
|..|パッケージを表現する場合は、任意の(0以上の)パッケージを表す。メソッドの引数を表現する場合は、任意の(0以上の)数の引数を表す。|
|+|クラス名の後に指定することにより、そのクラスとそのサブクラス／実装クラスすべてを表す。|

# 参考元
## 書籍
[Spring徹底入門 Spring FrameworkによるJavaアプリケーション開発](https://www.amazon.co.jp/Spring徹底入門-Spring-FrameworkによるJavaアプリケーション開発-株式会社NTTデータ/dp/4798142476/)
ROSのTFからSLAMの結果を受信する。

##目的
ROSのTFからSLAM(gmapping/cartographerなど)の自己位置推定結果を受信する。


[ROSのLidarSLAMまとめ](http://qiita.com/nnn112358/items/814c0fb0d2075eb71da0)


##実装
TFで、"map"→"base_link(or base_footprint)"を受信する。


```
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <nav_msgs/Odometry.h>
#include <tf/tf.h>
#include <tf/transform_datatypes.h>
#include <tf/transform_listener.h>
#include <iostream>
using namespace std;

int main(int argc, char *argv[]){
    ros::init(argc, argv, "tf_check");
    ros::NodeHandle n;
    tf::TransformListener listener(ros::Duration(10));
  
    ros::NodeHandle private_nh("~");
    string tf_name1;
    string tf_name2;
    private_nh.param("tf_name1",tf_name1,std::string("/base_link"));
    private_nh.param("tf_name2",tf_name2,std::string("/map"));

    double x_m=0.0, y_m=0.0, th_m=0.0;

    tf::StampedTransform trans_slam;

    while (n.ok())  {
    try {
        listener.lookupTransform(tf_name2, tf_name1,ros::Time(0), trans_slam);
        x_m = trans_slam.getOrigin().x();
        y_m = trans_slam.getOrigin().y();
        th_m = tf::getYaw(trans_slam.getRotation());
    }
    catch (tf::TransformException &ex)  {
        ROS_ERROR("%s", ex.what());
        ros::Duration(1.0).sleep();
        continue;
    }

    cout<< "SLAM result" << ",";
    cout<< x_m << ",";
    cout<< y_m << ",";
    cout<< th_m/M_PI*180.0<< endl;

    }

```



##参考
MyEnigma:世界で一番簡単なtfの使い方
http://myenigma.hatenablog.com/entry/20130210/1360491625
tf,tf2完全理解,Koji Terada,第五回ROS勉強会 @名古屋
https://www.slideshare.net/kojiterada5/tftf2
golangのnet/httpパッケージの構造体 Request を知る

# HTTP プロトコルについて
まず、HTTPプロトコルについて復習.
HTTPはTCPをベースにしてデータをやりとりするプロトコルです。じゃあTCPの上でどのような制御をしているのかというと、メッセージをやりとりする際のフォーマットが決められており、それに基づいて動作を制御しています。
メッセージフォーマットは下記の通り

| Request Message  | format |Example |
|:-----------------|:------------------|:------------------|
| リクエストライン      |[Method] [Path] [version]|GET / HTTP/1.1|
| ヘッダーライン       |[Header Key]: [header Value] |Content-Type: text/html; charset=utf-8|
| ボディーライン       |POSTのBody部分（省略可）||


curlコマンド等でリクエストを送った際に下記のような表示をみたことがあると思います。

```
$ curl -v http://www.example.com
* Rebuilt URL to: http://www.example.com/
*   Trying 2606:2800:220:1:248:1893:25c8:1946...
* TCP_NODELAY set
* Connected to www.example.com (2606:2800:220:1:248:1893:25c8:1946) port 80 (#0)
> GET / HTTP/1.1
> Host: www.example.com
> User-Agent: curl/7.51.0
> Accept: */*
> 
```

この `>` の１行目がリクエストライン、２行目以降がヘッダーライン、ボディーラインはGETリクエストのため省略されています。ヘッダーラインの終わりは空行にします。
何が言いたいかというと、Requestの構造体には、HTTPのプロトコルを満たすために、Method / Path / Version / Header / Body 等の変数が用意されている必要があるということです。このフォーマットを知っていればRequestが何で構成されているかなんとなくわかるのではないでしょうか。

# Request構造体
## 定義されている変数
Requestの中身は[こちらのDocument](https://golang.org/pkg/net/http/#Request)に記載があります。
[変数名] [型名] の順に記載しています。

- Method string
- URL *url.URL
- Proto　string
- ProtoMajor int
- ProtoMinor int
- Body io.ReadCloser
- GetBody func() (io.ReadCloser, error)
- ContentLength int64
- TransferEncoding []string
- Close bool
- Host string
- Form url.Values
- PostForm url.Values
- MultipartForm *multipart.Form
- Trailer Header
- RemoteAddr string
- RequestURI string
- TLS *tls.ConnectionState
- Cancel <-chan struct{}
- Response *Response

## HTTP Requestメッセージに落とし込む
まず、メソッドを利用するために下記の変数は使われる

- Method string

その次はPath
(RequestURIは素のリクエスト先が文字列で記載されている。各要素が区切られたURL構造体の中にPathが存在する)

- URL *url.URL
- RequestURI string

HTTPのバージョンも必要

- Proto　string
- ProtoMajor int
- ProtoMinor int

headerラインで取得できる情報はこれ

- Host string
- ContentLength int64

Body部の変数

- Body io.ReadCloser
- Form url.Values
- PostForm url.Values
- MultipartForm *multipart.Form

とりあえずこれだけ分かれば、GOでHTTPサーバをListenした時にRequestの値を使いこなせるのではないかと思います。
そのほかの項目も記載しようと思ったけど、[Document](https://golang.org/pkg/net/http/#Request)みた方が正確なので。。。
小説家になろうのランキングで一話あたりの平均文字数を表示させたい


小説家になろうのランキングで、新しく読むものを探すときに
一話あたりの平均文字数を表示させたいと思った。
(1話がどのくらいのボリューム感なのか知りたいのです。)
総文字数と総話数が出てるので、そこから引っ張ってくれば表示は出来そう。

jqueryを使っているみたいなので、そのまま利用させてもらう事にして
[小説を読もう！ || 小説ランキング[日間]](http://yomou.syosetu.com/rank/list/type/daily_total/)
上で、下記のスクリプトを実行でひとまず平均文字数の表示ができた。

```js
$(".rank_table").each(function(){
    var s=$(this).children().text().match(/全(\d+)部分/);
    if(s!=null){
        var t=$(this).find(".marginleft").text().match(/([0-9,]+)文字/)[1].replace(/,/g,'');
        $(this).append("<b>平均文字数:"+Math.round(t/s[1])+"</b>");
    }
})
```

まあ、話数とか文字数を正規表現で強引に抜き出しているので
ページの作りが変わってしまうと、使えなくなってしまうのだけど。

完全に小説家になろうのランキング専用になるけど
後でまた使いそうなので
ブックマークレットにしておこうとしたら
Qiitaだとjavascriptのリンク張れなかったので
とりあえずソースだけ置いておく。

```js
javascript:(function(){$(".rank_table").each(function(){var s=$(this).children().text().match(/全(\d+)部分/);if(s!=null){var t=$(this).find(".marginleft").text().match(/([0-9,]+)文字/)[1].replace(/,/g,""); $(this).append("<b class=\"average\">平均文字数:"+Math.round(t/s[1])+"</b>");}})})()
```

もし使う人いれば、手動でブックマークに突っ込んでください。
ROSのTFへOdometoryを入力する

##目的
ROSのgmappingなどでSLAMを行うためには、
TFで、"odom"→"base_link(or base_footprint)"の発行を行う必要がある。

[ROSのLidarSLAMまとめ](http://qiita.com/nnn112358/items/814c0fb0d2075eb71da0)

##実装
TFで、"odom"→"base_link(or base_footprint)"の発行を行うソースは以下

```
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <nav_msgs/Odometry.h>

void odom_calc(double &state_odom_x,double &state_odom_y,double &state_odom_th){
	//ここでエンコーダ値を読み取り、オドメトリ変換する演算を行う。
}

int main(int argc, char **argv){
	tf::TransformBroadcaster odom_broadcaster;
	ros::Time current_time;
	current_time = ros::Time::now();

	ros::Rate r(30.0);
	
	double state_odom_x=0.0;//オドメトリX座標[m]
	double state_odom_y=0.0;//オドメトリY座標[m]
	double state_odom_th=0.0; //オドメトリ姿勢[rad]
	
	while(nh.ok()){
	odom_calc(state_odom_x,state_odom_y,state_odom_th);
	current_time = ros::Time::now();
			
	//tf odom->base_link
	geometry_msgs::TransformStamped odom_trans;
	odom_trans.header.stamp = current_time;
	odom_trans.header.frame_id = "odom";
	odom_trans.child_frame_id = "base_link";

	odom_trans.transform.translation.x = state_odom_x;
	odom_trans.transform.translation.y = state_odom_y;
	odom_trans.transform.translation.z = 0.0;
	geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(state_odom_th);
	odom_trans.transform.rotation = odom_quat;
	odom_broadcaster.sendTransform(odom_trans);

	ros::spinOnce();
	r.sleep();
	}
}
```

###確認
rvizでtfが発行されていることを確認する。
座標系があっているかをよく確認する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/73020/94ae8709-91f9-2a53-bf40-2820a5fa039d.png)



##参考：
ROS wiki Publishing Odometry Information over ROS
http://wiki.ros.org/ja/navigation/Tutorials/RobotSetup/Odom
Swift4のCodableに喜び勇んで飛びついたらとんでもない落とし穴が開いていた

もともとNSCodingでチマチマとencode/decodeを書くのに本当に辟易していた上に、さらにJSON書き出しも実装しなきゃ、みたいな状況が重なって鬱になってたところに、Swift4のCodableを使うとJSON書き出しも永続化もイッパツ、みたいな情報が入ってきたんですよ。そんな自分のニーズにドンピシャな機能があればそりゃあまあ飛びつくじゃないですか。

ということで、早速使ってみたらまあコーディングの楽なこと。やっぱり最新機能はええべな・・・と思ってたわけですが、そこにはとんでもない落とし穴があったわけです。

これは今作ってるシーケンサーアプリのデータ構造の一部なんですが、ポイントは、シーケンスの中には音符イベント(SequenceEventNote)とピッチベンドイベントみたいな違った種類のイベントがあって、それをSequenceEventというスーパークラスで抽象化しているところです。これにより、すべてのイベントをひっくるめてシンプルなArrayとして扱えるようにしたわけです。

``` Swift
class Song : Codable {
    var events : [SequenceEvent] 
}

class SequenceEvent : Codable {
    var time : Double
}

class SequenceEventNote : SequenceEvent {
    var noteNo : Int
    var velocity : Float
    var duration : Float
}

class SequenceEventPitchBend : SequenceEvent {
    var depth : Float
}
```

で、こういうコードを追加してJSON化・保存するとどうなるか。

```Swift
class Song : Codable {
    var events : [SequenceEvent] 

    func save() {
        let encoder = JSONEncoder.init()
        let data = try? encoder.encode(self)
        if let d = data {
            try? d.write(to: Const.fileURL, options: [.atomic]);
        }
    }
}
```

eventsとして、SequenceEventNoteをいくつか追加、結果を見てみると

```JSON
{
  "events": [
        {
          "time": 0
        },
        {
          "time": 120
        },
        {
          "time": 240
        },
        ...
    ]
}
```

ノーーー！！！！ スーパークラスの情報しか入ってないじゃん！！！
そりゃねえよ・・・。

もちろん何か解決策はあるだろう、と調べます。するとこういうのが出てきます。

http://benscheirman.com/2017/06/ultimate-guide-to-json-parsing-with-swift-4/

まじか・・・。スーパークラスとサブクラスにencode/decodeメソッドを書かなきゃいかんのか・・・。でもまあNSCodingよりはまだいいか・・・と思ってたらさらにこんな話が。

↓その対策をやったところで、それがアレイに入っていた場合ガン無視されるという問題の報告。
https://bugs.swift.org/browse/SR-5331

↓そして、それに対するコメント

> This is by design — if you need the dynamism required to do this, we recommend that you adopt NSSecureCoding and use NSKeyedArchiver/NSKeyedUnarchiver, which will allow you to decode based on the class found in the archive rather than what is requested at runtime. See https://developer.apple.com/documentation/foundation/nscoding and https://developer.apple.com/documentation/foundation/nssecurecoding for more info.

し・・・「仕様」・・・だと・・・！？

一応対策みたいのは提案されていて、unkeyed container から、まずサブクラスへのデコードを試みて、失敗したらスーパークラスにデコードするということらしい。
だが、これサブクラスごとに全部やるのか・・・。

> Alternatively, if you know the possible subclasses which can be decoded from the payload, you can get an unkeyed container (instead of requesting Array<Superclass>) and attempt to decode instances of the subclasses out of the container; if those fail, you can decode the superclass successfully.

やっぱNSCodingに戻そうかな・・・。それはそれで各データ要素ごとにencode/decode/JSON書き出しを実装しなきゃだし・・・。NSCodingを自動化するライブラリを今更入れるか・・・。

新機能はやはりリスクが高いな・・・。

#追記
逃げの対策を書きました
http://qiita.com/Yokemura/items/11440a9ab87183db3bb7
003-Googleスプレッドシートに用意したテンプレートシートをコピーして名前変えて「左から２枚目に移動」したい

#結論
[moveActiveSheet(Integer)](https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet#moveActiveSheet(Integer) "Class Spreadsheet | Apps Script | Google Developers")で移動先の位置を指定しましょう。


```js:sample-code1.gs

function copySheet(){
  //スプレッドシートを指定
  var ss = SpreadsheetApp.getActiveSpreadsheet();
    
  //  コピー元シートを指定
  var source = ss.getSheetByName("テンプレート");

  //  シートをコピー
  var newSheet = source.copyTo(ss);
  
  //　シート名を「hoge」に変更
  newSheet = newSheet.setName("hoge");

  //作成シートにカーソルをフォーカス
  ss.setActiveSheet(newSheet);

  //カーソルフォーカスされた作成シートを左から２番目に移動
  ss.moveActiveSheet(2);
    
}

```

#解説
「シートの作成を自動化できたはいいものの、ピンポイントに設置したい！なのにどうすればいいかMethodが見つからない」というお問い合わせをいただきました。

「シートを増やすんだから、使うClassはSheetだよね」という読みは大正解。
だけどもシート移動はSpreadsheet ClassのMethodを使うことになります。

「Classを探すなら、やりたいことの補語[^1]に該当するものを探せ」。

[^1]: 「テンプレートシートを”スプレッドシートに”コピーする」なので、ダブルクォートの部分は「補語」、だと思う…あれ？


なおmoveActiveSheetは
+ 今、カーソルが置いてある（Activeな）シートを
+ 指定された位置に移動する

というMethodのため、「動かしたいシート（＝たった今、スクリプトによって作成したシート）」を明示してあげる必要があります。
上記サンプルスクリプトではこれを[setActiveSheet(sheet)](https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet#setActiveSheet(Sheet) "Class Spreadsheet | Apps Script | Google Developers")で実現しました[^3]。

[^3]: 例によってやり方は色々あると思います。

## 蛇足
今回のお題であればコピーしたシートの名前は「hoge」ではなく日付にしてあげた方が良いでしょう。
これも諸説ありますが私が書くとこんな感じ（というのをsample-code2.gsに載せておきます）。

# 動作確認スクリプト

```js:sample-code2.gs

  //スプレッドシートを指定
  var ss = SpreadsheetApp.getActiveSpreadsheet();
    
  //  スプレッドシート内にある「テンプレート」シートをコピーし、
  //  「yyyy-MM-dd HH:mm」形式のシート名に変更したものを
  //  シートの一番右側に作成
  var newSheet = ss.getSheetByName("テンプレート").copyTo(ss).setName(Utilities.formatDate(new Date(), "Asia/Tokyo", "yyyy-MM-dd HH:mm"));

  //作成シートにカーソルをフォーカス
  ss.setActiveSheet(newSheet);

  //カーソルフォーカスされた作成シートを左から２番目に移動
  ss.moveActiveSheet(2);
}
```

## スクリプト補足1
sample-code1.gsの2〜4行目をまとめました（変数sourceの使い道が、変数newSheetの操作にしか使わなかったので）。

## スクリプト補足2
setActiveSheetの返り値はSheet Classなので、うっかり`setCativeSheet(newSheet).moveActiveSheet(2)`とかやると実行時に怒られます。
moveActiveSheetもSpreadsheet Classだからね！

# つぶやき１
「”〜に”の部分って目的語だっけ？補語だっけ？」と悩んで10分くらいGoogle検索に頼ってしまったのは内緒の話。
Swiftの広域変数


Swift初心者です。主にMac版のアプリケーションをつくり時々iOSなプチ開発者です。MacのAppStoreにひとつだけアプリを公開していて、なんとか中級者の域に進みたいと日々精進しています。

コードを書き始めてぶつかる課題の一つがクラス間での変数の共有でした。デフォルトのViewControllerにあるプロパティに他のクラスからアクセスするだけでも、解決するのに何時間もかかったりするビギナーです。Qiitaで見かけたAppDelegateに置いたプロパティを他のクラスで共有するTIPSは初めて見るテクニックで、「これだ」探していたものはと思って使い始めていました。（下記ひとつめの方法）

そんな中で、Swiftでもいわゆる広域変数のglobal的な変数が使えることを知り、クラス外に置いておくと簡単に異なるクラスの間で変数が共有できることを、今更ながら知ったわけです。しかし、Swiftに限らず広域変数を多用することはよろしくないことは理解しています。複数人数で開発しているときなどはその理由はぼんやり理解できます。しかし、私のように「ひとり開発者」の場合には、手っ取り早い広域変数にはつい手が伸びてしまうのです。

まず私が知り得たクラス間での変数の共有（今回はこの用途を広域変数と呼んでいます）を取り上げて、コメントにてなぜ広域変数はよろしくないのかを指導していただけるとうれしいです。

### AppDelegateに設置する方法
下記のように、デフォルトで作成されているAppDelegate.swiftの中に変数を置いて、他のクラスからはread/writeすることができました。

```AppDelegate.swift
import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

	var globalVar = "Hello"
	
    func applicationDidFinishLaunching(_ aNotification: Notification) {
    }
}
```

```ViewController.swift
import Cocoa

class ViewController: NSViewController {

	let fromAppDelegate: AppDelegate = NSApplication.shared().delegate as! AppDelegate
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        print(fromAppDelegate.globalVar)  // Helloと表示される

    }
}
```

### クラス外に設置する方法

初心者にはありがたいシンプルな記述で広域で変数を共有できます。コードの文字数だけ見るとこれが一番簡潔に使えるのですが、ネット上の情報ではあまり推奨されているとは言い難く、できれば使用しない方が良いとの雰囲気です。

```AppDelegate.swift
import Cocoa

var globalVar = "Hello"

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
	
    func applicationDidFinishLaunching(_ aNotification: Notification) {
    }
}
```

```ViewController.swift
import Cocoa

class ViewController: NSViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        print(globalVar)  // Helloと表示される
    }
}
```

### シングルトンを使った方法

直感的に、この方法がデザインパターンにもあるように「玄人受け」しそうな気がします。現状ではこのテクニックを使うのが中級者への道を最短で走れるような希望を描いています。

```AppDelegate.swift
import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    func applicationDidFinishLaunching(_ aNotification: Notification) {
    }
}

	
class GlobalVar {
    private init() {}
    static let shared = GlobalVar()

    var sampleString = "Hello"
}
```

```ViewController.swift
import Cocoa

class ViewController: NSViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        var myVar = GlobalVar.shared
        print(myVar.sampleString)  // Helloと表示される
    }
}
```

ほかにもいろいろテクニックはあるのでしょうが、今のところ自分の頭のなかで整理して実用性のある方法を3つ取り上げました。異なる継承のないクラス間で変数をread/writeして共有するテクニックについてのスマートなやり方を模索中です。アドバイスをいただけると幸いです。

ちなみにこのポストが今回Qiitaではじめてのものです。これまで数多くここで知識を吸収できたので、自分でも情報発信や知識の共有に貢献したい考えの第一歩です。
IntelliJでコード補完のショートカットをCtrl+Spaceから変更する

### 背景
デフォルトのキーだと全角半角の変換と重なるので、Shift+Spaceあたりに変えたい。

### 環境
 * Ubuntu 16.04.3
 * IDEA

### 手順
 * 下記をたどって変更する
    * File -> Settings -> Keymap -> Main Menu -> Code -> Completion -> Basic
    *
デベロッパーツールでcurlコマンドを楽ちんコピペ


# ChromeもSafariもほぼ同じ

- Chrome
![スクリーンショット 2017-08-13 10.29.18.png](https://qiita-image-store.s3.amazonaws.com/0/33176/103ba94c-fcde-5b12-fd6f-ebbc8d53295e.png "スクリーンショット 2017-08-13 10.29.18.png")


- Safari
![スクリーンショット 2017-08-13 10.31.21.png](https://qiita-image-store.s3.amazonaws.com/0/33176/f1c837a6-5ab7-ee89-a6bf-665b564b9692.png "スクリーンショット 2017-08-13 10.31.21.png")
Google Maps Directions API は国内の電車ルートを返さない

例えば東京駅から新宿駅までのルート

```
https://maps.googleapis.com/maps/api/directions/json?destination=%E6%9D%B1%E4%BA%AC%E9%A7%85&origin=%E6%96%B0%E5%AE%BF%E9%A7%85&departure_time=1502587174&mode=transit&key=[API_KEY]
```

は徒歩ルートを返す。`transit_routing_preference=less_walking`を指定するとバスルートを返すこともある。

2015年の4月にレポートされている: https://issuetracker.google.com/issues/35826181
こんな時はこうやってcurlする

基本的な使い方メモ
# cookieを保存したい

`curl -c cookieを保存するファイル名 url`

# 保存したcookieを使いたい

`curl -b cookieを保存したファイル名 url`

# Request Headerを設定したい

`curl -H 'name:value' url`

-Hは複数指定可能
`curl -H 'name:value' -H 'name:value' url`

# User Agentを変えたい

`curl -H 'User-Agent:ユーザーエージェント' url`

`curl -A "ユーザーエージェント" url`

# Response bodyをファイルに保存したい

`curl -o 保存ファイル名 url`

# Response bodyを表示したくない

/dev/nullを指定するとよい
`curl -o /dev/null url`

# Response body保存の進捗を表示したくない

-s をつける
`curl -o 保存ファイル名 -s url`
HashiCorp Vault の 機密情報 を PostgreSQL に保存する

# はじめに

HashiCopr VaultのチュートリアルはstorageにConsuleを利用する手順になってましたが、クラウドサービスやデータベースも利用可能なようです。今回は機密情報をPostgreSQLに保存させてみました。

# 参考
公式サイトにはS3やMySQLなど様々なサービスやデータベースをstorageに設定する方法について解説があります。

[Storage Backends \- Configuration \- Vault by HashiCorp](https://www.vaultproject.io/docs/configuration/storage/index.html)

# PostgreSQL

## URL

DBを作成して、URLを確認する

```
postgres://<username>:<password>@<host>:<port>/<database>
```

## TABLE / INDEX

Vaultで利用するTABLEとINDEXを作成する

```
CREATE TABLE vault_kv_store (
  parent_path TEXT COLLATE "C" NOT NULL,
  path        TEXT COLLATE "C",
  key         TEXT COLLATE "C",
  value       BYTEA,
  CONSTRAINT pkey PRIMARY KEY (path, key)
);
```

```
CREATE INDEX parent_path_idx ON vault_kv_store (parent_path);
```

補足：
TABLEの作成を忘れるとVault利用時エラーになる

```shell-session
$ vault init
Error initializing Vault: Error making API request.

URL: PUT http://127.0.0.1:8200/v1/sys/init
Code: 400. Errors:

* failed to check for initialization: pq: relation "vault_kv_store" does not exist
```

# Vault

## 設定ファイル

設定ファイルでstorageにPostgreSQLを利用するように指定します。

```text:posgre.hcl
storage "postgresql" {
  connection_url = "postgres://<username>:<password>@<host>:<port>/<database>"
}

listener "tcp" {
 address = "127.0.0.1:8200"
 tls_disable = 1
}

# mlockが利用できない環境ではコメントアウトを外す
# disable_mlock = 1
```

## 起動

PostgreSQLを利用するように指定した設定ファイルを利用してVaultを起動します。

```shell-session
$ vault server -config=posgre.hcl
```

## 実行

基本的な操作が行えることを確認します。

```shell-session
# 環境変数を設定
$ export VAULT_ADDR='http://127.0.0.1:8200'

# 初期化
$ vault init -key-shares=1 -key-threshold=1

# unseal
$ vault unseal <key>

# 認証
$ vault auth <token>

# 機密情報の書き込み
$ vault write secret/hello value=world

# 機密情報の読み込み
$ vault read secret/hello
```

# 補足

PostgreSQLのvault_kv_storeテーブルを確認すると暗号化されたデータが書き込まれてることがわかります。

```sql
select * from vault_kv_store;

parent_path | path          | key    | value
------------+---------------+--------+----------------
 /logical/  | /logical/.../ | hello  | \x0000000102...
```
Pentahoのインストールと基本設定

#目的
オープンソースのBIツール「Pentaho」のインストール手順と基本的な設定項目を整理する。

#注意点(2021/9/18追記)
本ページのPentahoインストール手順については少々古いため、2021年時点では、以下のページをご参照ください。
[Pentaho Data Integration のインストール (Version 9.2)](https://qiita.com/mik/items/b6227b26cbd5bc099206)

基本設定については、そのまま使えると思います。


#主な機能
Pentahoの主な機能は、

- ユーザやBIレポートを管理するプラットフォーム環境
- 日報や月報などフォーマットが固定化されている定形レポート機能(Pentaho Report Designer -> PRD)
- ROLAPエンジン(Mondrian)
- ダッシュボードおよびダッシュボード構築用機能(CTools)
- ETL機能(Pentaho Data Integration -> [PDI](http://qiita.com/mik/items/8a36e8efb06367c82b41))

です。

#今回の環境
PDI 7.1
Java Version 8 Update 131
※OSはJavaが動けばなんでも良い、またJavaはとりあえず最新版を入れておけば大丈夫

#Javaのダウンロードとインストール
Javaは以下からダウンロードしてメニューに従ってインストールしておく。
https://java.com/ja/download/

#PentahoServerのダウンロードとインストール
以下からダウンロードする。
http://community.pentaho.com/
![pdi_install_1.png](https://qiita-image-store.s3.amazonaws.com/0/186651/bf9f113c-8256-b4b8-dedb-49cd50180b6b.png)

"Download Section"をClickして、以下のへ移動し"Business Analytics Platform"からダウンロードする。
![Pentaho_Install_1.png](https://qiita-image-store.s3.amazonaws.com/0/186651/53ce4918-a474-8c1b-15e6-383c7047c45b.png)

ダウンロードしたZIPファイルを解凍してできる"pentaho-server"ディレクトリを適当な場所に配置して完了です。

#起動方法
Pentahoの起動は以下のように行ないます。

```
$ cd pentaho-server
$ ./start-pentaho.sh
```

Localhost環境であれば、ブラウザより"http\://localhost:8080/"へアクセスし、以下のように起動すればOKです。
![Pentaho_Install_2.png](https://qiita-image-store.s3.amazonaws.com/0/186651/250102e0-d36b-6f9f-06c7-2e0644f26fca.png)

デフォルトの管理ユーザ/パスワードは、"admin/password"です。
ログインボタン下の「評価者としてログイン」を押すと自動ログインボタンがあるので、そちらからでもログインできます。

#設定
##日本語化(言語設定)
ブラウザの言語設定により、自動的に言語タイプが選択されているはずですが、言語が英語のままだったりする場合は、以下のメニューから変更可能です。
![Pentaho_Install_3.png](https://qiita-image-store.s3.amazonaws.com/0/186651/f4a98807-1db2-696f-8137-a56ef03a5a3a.png)

##メモリの割り当て
start-pentaho.sh内の"-Xmx6144m"を変更してSpoonの再起動。

```
$ vim pentaho-server/start-pentaho.sh

if [ "$errCode" = 0 ]; then
  cd "$DIR/tomcat/bin"
  CATALINA_OPTS="-Xms2048m -Xmx6144m -XX:MaxPermSize=256m -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Dfile.encoding=utf8 -DDI_HOME=\"$DI_HOME\""
  export CATALINA_OPTS
  JAVA_HOME=$_PENTAHO_JAVA_HOME
  sh startup.sh
fi
```

##各種JDBCドライバの配置場所
以下にドライバを置いて、Pentahoの再起動。

```
pentaho-server/tomcat/lib/配下
```
ちょっとずつ読むドメイン駆動設計 MartinFowlerによる序文3

# モデルは常に変化する

> Ericの経験から導き出される教訓は、真に強力なドメインモデルは時間とともに進化するということ
>(序文より)

一発で完璧なモデルを構築することはまずできない。だから、モデルは変更が容易なものでなければならない。

ということは、ドメイン駆動設計を実践するには"オブジェクト指向の技術"と"リファクタリングの技術"、"アジャイルの技術"が非常に大事になってくると思う。

また、『Ericの経験』という言葉がいいですね。Eric自身、日本語版への序文にて

> ドメイン駆動設計が語っているのは、私の物語です。
> ...しかしこの物語は、厳しい現実の中でソフトウェア設計を習得しようと奮闘してきた、他の多くの人々の物語にも似ています。

と言っている。

物語であり、現実であり、実践のなかで培われたもので、現実は常に不完全であり、常に変化している。
その中で導き出された教訓はとても説得力のあるものだと思いました。

モデルは常に変化する。リリース後も。
JPEG クロマ・サブサンプリングを視覚的に理解する

# 90%

![444.jpg](https://qiita-image-store.s3.amazonaws.com/0/142575/941988f4-11e0-048e-bb67-8a3ed1c9e2b3.jpeg)
![422.jpg](https://qiita-image-store.s3.amazonaws.com/0/142575/fe745282-2eb3-c670-0864-b3c1167536b2.jpeg)
![420.jpg](https://qiita-image-store.s3.amazonaws.com/0/142575/092fbd99-27fd-ed08-5cf3-80b17b3f0e09.jpeg)
![411.jpg](https://qiita-image-store.s3.amazonaws.com/0/142575/e48cce75-0384-f8d3-efb4-5b2bf31c5cb9.jpeg)

## 70%
![444-70.jpg](https://qiita-image-store.s3.amazonaws.com/0/142575/a3e0e1d1-d72c-afd0-99e1-576bfa76f96d.jpeg)
![422-70.jpg](https://qiita-image-store.s3.amazonaws.com/0/142575/fe7db219-2b9a-b0a4-9cde-7f2712881d78.jpeg)
![420-70.jpg](https://qiita-image-store.s3.amazonaws.com/0/142575/d4593521-7d21-dcdd-652c-94cef5bcef8c.jpeg)
![411-70.jpg](https://qiita-image-store.s3.amazonaws.com/0/142575/a7a9ca99-b6ba-226a-fe26-02df7221a45d.jpeg)

### 拡大
![up.png](https://qiita-image-store.s3.amazonaws.com/0/142575/69f2c819-de03-2da5-69f1-3450f443f575.png)


# Photoshopでオリジナル画像と差分(Original vs 70%)
部屋を暗くして画面の輝度を最大限まで上げて、拡大してみてください。

![diff-444.png](https://qiita-image-store.s3.amazonaws.com/0/142575/1397a1df-f27f-b163-5d3c-0072142688ca.png)
![diff-422.png](https://qiita-image-store.s3.amazonaws.com/0/142575/b609ed15-da8e-67c7-1e4f-615821224712.png)
![diff-420.png](https://qiita-image-store.s3.amazonaws.com/0/142575/41b746db-14a6-aa9f-7157-f675706034dd.png)
![diff-411.png](https://qiita-image-store.s3.amazonaws.com/0/142575/2a255816-9db6-0d5b-6972-987639aea594.png)

4:4:4は最高画質。4:2:2は色情報に劣化があるものの、それほどひどいとは感じない。4:2:0だと横方向での劣化がみられる。4:1:1では縦方向に劣化がみられる。

なぜこうなるかは、このサイトが詳しい。
https://blog.awm.jp/2016/02/10/yuv/

# サイズ比較
| test vector | Size [bytes] |
|:-:|:-:|:-:|:-:|
| 444 90%  | 335410 | 100% |
| 422 90% | 276700 | 82% |
| 420 90% | 244207 | 73% |
| 411 90% | 241385 | 72% |
| 444 70% | 180114  | 54% |
| 422 70%  | 152459 | 45% |
| 420 70%  | 136995 | 41% |
| 411 70%  | 135835 | 40% |

﻿﻿﻿
![image.png](https://qiita-image-store.s3.amazonaws.com/0/142575/d1060d5f-f4b0-5bad-6e67-5f0b5f4c4c0a.png)

420, 411はデータをハブる方向性が異なるだけでハブる率は同じなので、だいたい同じような結果になる。
これでみると、ディテールをあまり犠牲にせずデータを削減する4:2:2がコスパよさそうにみえる。
RubyMine：Macで日本語対応



## 概要
RubyMineは、2017年3月から使い始めていますが、Railsでの開発において、非常に優秀です。

Railsで開発している方には、オススメのテキストエディタです。

ただデフォルトで英語なので、使うにあたっては日本語対応する必要があります。

手順は簡単なので、以下に掲載します。

## 参考
### [日本語化](http://www.willbrains.jp/page/4#step)

## 手順
### pleiadesの最新版をダウンロード
#### [Pleiades 日本語化プラグイン](http://mergedoc.osdn.jp/#pleiades.html)にアクセス

#### 以下の画面になります。

![スクリーンショット 2017-08-13 8.15.00.png](https://qiita-image-store.s3.amazonaws.com/0/142810/76803b26-7b10-1097-04f2-8c684af5e2ed.png "スクリーンショット 2017-08-13 8.15.00.png")

#### 画面下方に進むと、「最新版ダウンロード」がありますので、クリックします。


![スクリーンショット 2017-08-13 8.15.14.png](https://qiita-image-store.s3.amazonaws.com/0/142810/4f4cd26f-5a47-b703-6a92-087519aea00a.png "スクリーンショット 2017-08-13 8.15.14.png")

#### ダウンロードしたら、zipファイルを展開します。

![スクリーンショット 2017-08-13 8.35.52.png](https://qiita-image-store.s3.amazonaws.com/0/142810/52a96611-da12-4424-b13d-d2e0afea1529.png "スクリーンショット 2017-08-13 8.35.52.png")

#### jp.sourceforge.mergedoc.pleiadesフォルダをRubyMineのplugins配下に移動します。

```
$ mv /Users/ユーザー名/Downloads/pleiades/plugins/jp.sourceforge.mergedoc.pleiades /Applications/RubyMine.app/Contents/plugins/
```

### RubyMineの設定
#### RubyMineのHelpから「Edit Custom VM Options...」を開きます。

![スクリーンショット 2017-08-13 8.23.58.png](https://qiita-image-store.s3.amazonaws.com/0/142810/7f7b0214-c5b7-9fea-58a4-375aaeda00fa.png "スクリーンショット 2017-08-13 8.23.58.png")

#### 以下のファイルが開きます。

![スクリーンショット 2017-09-09 15.45.45.png](https://qiita-image-store.s3.amazonaws.com/0/142810/adaceea4-030b-aea7-1f6f-274df3f471c3.png "スクリーンショット 2017-09-09 15.45.45.png")

#### `-Xverify:none` が設定されているか確認します。
#### なかったら、追記します。

![スクリーンショット 2017-09-09 15.45.45.png](https://qiita-image-store.s3.amazonaws.com/0/142810/10b13d67-aa44-2154-b51a-0227ed9c8f8c.png "スクリーンショット 2017-09-09 15.45.45.png")

#### ファイルの末尾に `-javaagent:...` を追記します。

```
-javaagent:/Applications/RubyMine.app/Contents/plugins/jp.sourceforge.mergedoc.pleiades/pleiades.jar
```

![スクリーンショット 2017-09-09 15.47.42.png](https://qiita-image-store.s3.amazonaws.com/0/142810/e7240950-1aa1-d330-b3e8-da95d793c046.png "スクリーンショット 2017-09-09 15.47.42.png")

#### RubyMineを再起動します。
#### RubyMineが日本語化されています。

![スクリーンショット 2017-08-13 8.29.19.png](https://qiita-image-store.s3.amazonaws.com/0/142810/b99a59e3-f224-5ce4-60fb-6062bf2eba36.png "スクリーンショット 2017-08-13 8.29.19.png")

#### 以上で設定は完了です。
Python で、Watson の翻訳サービスを使う

Watson の翻訳サービスを、Python3 の　request で使う例と、SDK で使う例です。
username と password は変更して下さい。

request の　例

```py3:translate_request.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
#       translate_request.py
#
#                                       Aug/14/2017
# --------------------------------------------------------------------
import sys
import requests
# --------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
username="12346e5d-350f-4fa5-b991-8dc6bb578789"
password="AB7tL8knaOTZ"
url_v2="https://gateway.watsonplatform.net/language-translator/api/v2"
#
word_in = "I got up early today."
url_en_ja=url_v2 + "/translate?model_id=en-ja&text="
url_target = url_en_ja + word_in
rr=requests.get(url_target,auth=(username,password))
print(rr.text)
#
#
word_in = "今日は早起きした。"
url_ja_en=url_v2 + "/translate?model_id=ja-en&text="
url_target = url_ja_en + word_in
rr=requests.get(url_target,auth=(username,password))
print(rr.text)
#
sys.stderr.write("*** 終了 ***\n")
# --------------------------------------------------------------------

```

SDK の例

```py3:translate_sdk.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
#	translate_sdk.py
#
#						Aug/13/2017
#
# --------------------------------------------------------------------
import sys
import json
from watson_developer_cloud import LanguageTranslatorV2
# --------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
language_translator = LanguageTranslatorV2(
	username='12346e5d-350f-4fa5-b991-8dc6bb578789',
	password='AB7tL8knaOTZ')
#
result = language_translator.translate('I got up early today.', source='en',
		target='ja')
print(result)
#
result = language_translator.translate('今日は早起きした。', source='ja',
		target='en')
print(result)
#
sys.stderr.write("*** 終了 ***\n")
# --------------------------------------------------------------------
ubuntu LAMPサーバを あとから構築

ubuntu インストールするときに どんな機能を インストールするか きめるけど あとから その機能を使う手順を おぼえたので 書いておきます

それは tasksel

```
$ sudo tasksel
```

を 実行すると 追加できるパッケージが 一覧されて その中の LAMPサーバ を 選んで スペースで 選択 TABで OKを 選択する それだけで インストールできます。途中で mysql-serveの rootパスワードが 聞かれたりします。
psqlのデフォルト接続先を変更する

psqlでホスト名など何も入力しなかった場合、デフォルトではlocalhostに接続しに行きますが、ローカルではなくAmazon RDSなど外部のデータベースサーバーに接続する場合に毎回 `psql hogedb -h example.com -U hoge` などとするのは苦行ですね。

```
echo 'export PGHOST=yourhostname' >> ~/.bashrc
echo 'export PGPORT=5432' >> ~/.bashrc
echo 'export PGDATABASE=yourdatabasename' >> ~/.bashrc
echo 'export PGUSER=yourusername' >> ~/.bashrc

source ~/.bashrc
```
yourなんちゃらの部分は適宜変えて下さい。

## 参考
https://www.postgresql.jp/document/9.6/html/libpq-envars.html

環境変数で設定できるのは聞いたことあったんですが、長らくドキュメントを見つけられませんでした。psqlでなくlibpqの中に書いてあるとは思わなんだ…
キーバインド設定の書き方

# 課題

Mac 上の Emacs で `Ctrl+Cmd+↑` に `toggle-frame-fullscreen` を割り当てたかったが、 `global-set-key` の第一引数をどう指定すればいいのか分からなかった

# 解決方法

`Ctrl+h k` に続けて `Ctrl+Cmd+↑` を入力すると、

```
<C-s-up> is undefined
```

とエコーエリアに表示され、このキーバインドが未割り当てであることと、その表現が `<C-s-up>` であることがわかる(ちなみに `Ctrl+h k` 自体が何をしているかを知るには `Ctrl+h k Ctrl+h k` とすればよく、 `describe-key` 関数を呼んでいるとわかる)。

ここで得られた `"<C-s-up>"` をそのまま指定しても駄目

```
(global-set-key "<C-s-up>" 'toggle-frame-fullscreen)
=> Debugger entered--Lisp error: (error "Key sequence < C - s - u p > starts with non-prefix key <")
```

で、それを `kbd` 関数に渡した戻り値を使って

```
(global-set-key (kbd "<C-s-up>") 'toggle-frame-fullscreen)
``` 

とするとうまくいった。
metalinkを使ったubuntu isoダウンロード

xubuntuのisoをよくダウンロードするのだが、metalinkというのはなにかググってみたところ

aria2 や kget でダウンロードできることがわかった。

```bash
sudo apt install -y aria2

aria2c "http://ubuntutym2.u-toyama.ac.jp/xubuntu/17.04/release/xubuntu-17.04-desktop-amd64.metalink"
```

ダウンロードが完了したら`ctrl-d`で終わる。

![dd.png](https://qiita-image-store.s3.amazonaws.com/0/25728/ac5f5984-ed40-10b4-e0be-262c3d51017d.png)


![スクリーンショット_2017-08-13_06-00-47.png](https://qiita-image-store.s3.amazonaws.com/0/25728/3562b1b4-089c-5269-aac3-6e208f9214ca.png)
SimpleFormのエラー表示対応何点か【不満だったこと解消できた】

## はじめに
今まで知らなかったことを最近知って、おおって思ったので置いておきます。

## サンプルコード

以下のようなコードについて書いています。

```erb
<%= simple_form_for(project, html: { class: 'form-horizontal' }) do |f| %>
  <%= f.error_notification %>
  <%= f.full_error :owner_id %>
  <%= f.input :title %>
  <%= f.input :content %>
  <%= f.button :submit %>
<% end %>
```

## エラーメッセージに主語がない
https://suin.io/546
こちらを見たりすると良いですよ（良記事多謝）。

私は `simple_formの設定で対応する方法` でやっています。こちらの方が元々用意されていたものに乗っかる感じがして好きだからです。これで `full_error` というワードがあることを知りました。

## 画面に表示項目がない時にエラーメッセージが出せない
内部的に利用している情報が返すエラーについて握りつぶされてしまうと思っていました。ですがそれは間違いだと知りました。

https://github.com/plataformatec/simple_form/wiki/Errors-not-connected-with-visible-fields

ちゃんと用意されているんですよ。

```rb
= f.error :field_name
```

と書かれているのを見て、もしや...と思い

```rb
= f.full_error :field_name
```

としてみたら見事に主語のついた内容で表示できました。
WebAssembly導入メモ


## これはなに？

備忘録、とりあえず試してみた

## 試す前から希望がもてない

Chrome,FireFoxで導入され、Safariまで導入が決定し、注目度が高い。
しかしながら、最初の導入記事以降、次の記事はみないので、とってもシュール。

実際３倍速くなるとか書いてあるが、ブラウザで３倍速くなるからといってビルドが必要なコードをjavascriptを置き換えてまで使いたいのか？といった疑問。
「実際あまり速くない。読み込み部分が速くなるくらい」と書かれていたり。各ブラウザが導入しているのに残念感を拭えない。
ネイティブコードをブラウザで動かせるにしてもCで書かれてたコードの穴を埋める労力考えると公開することはまずしない。

本家の[Use Cases](https://github.com/WebAssembly/design/blob/master/UseCases.md)を見ても何か作りたいと、ときめいたりはしない。
きっと導入時期はイマじゃないのだろう。もっと使いたくなる子になったらまた思い出そう。


## wasm Install

```
$ wget https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz
$ tar xvzf emsdk-portable.tar.gz
$ cd emsdk-portable/

$ ./emsdk update
##-- install 2時間待ちました。。orz
$ ./emsdk install sdk-incoming-64bit
$ ./emsdk activate sdk-incoming-64bit
$ source ./emsdk_env.sh
```

## [Rust Platform Support](https://forge.rust-lang.org/platform-support.html)

asmjsとwasmサポートを導入

```
$ rustup target add asmjs-unknown-emscripten
$ rustup target add wasm32-unknown-emscripten
```

## Rust Install
```
$ https://www.rust-lang.org/en-US/install.html
curl https://sh.rustup.rs -sSf | sh
$ echo 'fn main() { println!("Hello, Emscripten!"); }' > hello.rs

source $HOME/.cargo/env
```

## wasm Build

情報通り初回ビルド遅い３分くらい待った。次回以降そんな待つことはない。

```
$ rustc --target=wasm32-unknown-emscripten hello.rs -o hello.html
$ python -m SimpleHTTPServer
http://localhost:8000/hello.html
```

## [rust-webplatform](https://github.com/rust-webplatform/rust-webplatform)

DOM操作ができると聞いてwktk

```rust:main.rs
extern crate webplatform;

fn main() {
    let document = webplatform::init();
    let body = document.element_query("body").unwrap();
    body.html_set("<h1>HELLO FROM RUST</h1> <button>CLICK ME</button>");
    let button = document.element_query("button").unwrap();
    button.on("click", |_| webplatform::alert("WITNESS ME"));
}
```

```Cargo.toml
[package]
name = "app"
version = "0.1.0"

[dependencies]
webplatform = { git = "https://github.com/tcr/rust-webplatform" }

[[bin]]
name = "webplatform-test"
```

```index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <title>App</title>
  </head>
  <body>
    <script src="webplatform-test.js"></script>
  </body>
</html>
```

```
$ cargo build --target asmjs-unknown-emscripten --release
$ cp target/asmjs-unknown-emscripten/release/webplatform-test.js .
```

なるほど、asm.jsでは動くがwasmでは動かないのね。
アセンブリから直接DOMを書き換える機構はないでいいのかな？
OpenCVでアニメの顔検出


https://github.com/opencv/opencv

## 下準備

・`import cv2`できるようにする
・特徴量ファイルを読み込めるようにする

こちら参照
[Mac OS X で OpenCV 3 + Python 2/3 の開発環境を整備する方法](https://blog.ymyzk.com/2015/07/os-x-opencv-3-python-2-3/)

## 分類器の作成と顔の位置検出

```python
import os
import cv2

# 特徴量ファイルをもとに分類器を作成
classifier = cv2.CascadeClassifier('lbpcascade_animeface.xml')

# 顔の検出
image = cv2.imread('newGame.jpg')
# グレースケールで処理を高速化
gray_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
faces = classifier.detectMultiScale(gray_image)
```

`print(faces)`で6人分の顔の位置と大きさが検出できたのを確認

```
[[485 148 134 134]
 [456 313 193 193]
 [380  58  98  98]
 [649 227 127 127]
 [373 245 108 108]
 [637  54 104 104]]
```

## 一人ずつ顔を切り抜く

```python
# ディレクトリを作成
output_dir = 'faces'
if not os.path.exists(output_dir):
    os.makedirs(output_dir)
    
for i, (x,y,w,h) in enumerate(faces):
    # 一人ずつ顔を切り抜く
    face_image = image[y:y+h, x:x+w]
    output_path = os.path.join(output_dir,'{0}.jpg'.format(i))
    cv2.imwrite(output_path,face_image)
    
cv2.imwrite('face.jpg',image)
```

![スクリーンショット 2017-08-13 3.33.43.png](https://qiita-image-store.s3.amazonaws.com/0/136286/dd859612-c411-fd80-9021-d3ab9ab3f744.png "スクリーンショット 2017-08-13 3.33.43.png")


## 顔を四角で囲う

```python
for x,y,w,h in faces:
    # 四角を描く
    cv2.rectangle(image, (x,y), (x+w,y+h), color=(0,0,255), thickness=3)
    
cv2.imwrite('faces.jpg',image)
```

![faces.jpg](https://qiita-image-store.s3.amazonaws.com/0/136286/50f6e4ce-8f87-a544-cfa3-fc4040ed13ca.jpeg "faces.jpg")



## 特徴量ファイル一覧

https://github.com/opencv/opencv/tree/master/data/haarcascades

haarcascade_eye.xml
haarcascade_eye_tree_eyeglasses.xml
haarcascade_frontalcatface.xml
haarcascade_frontalcatface_extended.xml
haarcascade_frontalface_alt.xml
haarcascade_frontalface_alt2.xml
haarcascade_frontalface_alt_tree.xml
haarcascade_frontalface_default.xml
haarcascade_fullbody.xml
haarcascade_lefteye_2splits.xml
haarcascade_licence_plate_rus_16stages.xml
haarcascade_lowerbody.xml
haarcascade_profileface.xml
haarcascade_righteye_2splits.xml
haarcascade_russian_plate_number.xml
haarcascade_smile.xml
haarcascade_upperbody.xml

今回使用したlbpcascade_animeface.xmlはこちら
https://github.com/nagadomi/lbpcascade_animeface

> 参考
http://gihyo.jp/book/2017/978-4-7741-8367-1
docker の MySQL イメージを導入してホスト( mac )から接続する


```bash
# MySQL を Docker イメージとしてインストール
$ docker run -p 5001:3306 --name some-mysql -e MYSQL_DATABASE=＜DB名＞ -e MYSQL_USER=root -e MYSQL_PASSWORD=password -e MYSQL_ROOT_PASSWORD=password -d mysql:latest

# MySQL の Docker コンテナへクライアントイメージから接続
$ docker run --link  some-mysql-createdb:mysql -it --rm mysql bash

># env
ここにMYSQL関連の環境変数が表示される

># mysql -u root -ppassword -h $MYSQL_PORT_3306_TCP_ADDR ＜DB名＞
>mysql> show tables;


# mac に mysql client インストール
$ brew update

# mysql クライアントをインストールしようとしたら下記エラーが出たので、再インストールした
# Error: /usr/local/opt/makedepend not present or broken
# Please reinstall makedepend. Sorry :(
$ brew unlink makedepend
$ brew install makedepend

# mysql クライアントをインストール
$ brew install mysql --client-only
$ mysql --version
mysql  Ver 14.14 Distrib 5.7.19, for osx10.11 (x86_64) using  EditLine wrapper

# 接続
$ mysql -u root -ppassword -P 5001 ＜DB名＞

# ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)

# -h を指定してみる
$ mysql -h 127.0.0.1 -u root -ppassword -P 5001 ＜DB名＞

```
三角比　三角関数　サイン　コサイン　タンジェント　コタンジェント　セカント　コセカント　アークサイン　アークコサイン　アークタンジェント　アークコタンジェント　アークセカント　アークコセカント　アークタンジェント２

http://math.warabenture.com/?p=1177
Mac版Google Driveの名称が「Googleのバックアップと同期」に変わったのでHomebrewでインストールした

# Mac版Google Driveのインストールに失敗(via Homebrew)

Macの環境構築中にGoogle Driveアプリケーションをインストールしようと下記のコマンドを実行したところ、「google-driveは見つかりませんでした」といったエラーが表示されました。

```bash
brew cask install google-drive
Error: Cask 'google-drive' is unavailable: No Cask with this name exists.
Error: Install incomplete.
```

# 原因を調査

むむ？と思ってGoogle Driveのダウンロードページを見てみると、どうやらアプリケーション名が変わっている模様？

![スクリーンショット 2017-08-13 2.35.30.png](https://qiita-image-store.s3.amazonaws.com/0/34795/da644d08-1978-881e-d174-a47f2c2aedcd.png)

そこで、アプリケーション名の文言をキーワードにHomebrewで検索をしてみました。

```bash
brew cask search backup
==> Partial Matches
backuploupe                           get-backup-pro                        google-photos-backup-and-sync         ibackupbot
borgbackup                            google-backup-and-sync                ibackup                               iphone-backup-extractor
==> Remote Matches
caskroom/drivers/synology-cloud-station-backup
```

すると、`google-backup-and-sync`というまさにそれっぽい名前のものが。

# google-backup-and-syncをインストール

```bash
brew cask install google-backup-and-sync
```

このコマンドを実行すると「Googleのバックアップと同期」というアプリケーションがインストールされました。

# Googleのバックアップと同期

どうやら、Mac版Google Driveは、「Googleのバックアップと同期」としてリニューアルされていたみたいです。

以前は、マイドライブしか同期できなかったのに対し、今回からは同期するローカルのフォルダを指定してGoogle ドライブにバックアップできるようになったようです。

![スクリーンショット 2017-08-13 2.48.51.png](https://qiita-image-store.s3.amazonaws.com/0/34795/96017254-fc29-43ba-47fc-2171d215ca41.png)

そして、この方法でバックアップしたデータは「パソコン」というタブに「マイ `デバイス名`」という形で整理されるようになったみたいです。

![スクリーンショット 2017-08-13 2.48.33.png](https://qiita-image-store.s3.amazonaws.com/0/34795/f40a1a19-2f5e-0cff-8275-07ea726a248b.png)


# 終わりに

以上、環境構築中に困ってしまったので、他にも同じようにつまづいている人がいたら...と思ってシェアさせていただきました。

おそらく、過去にMac版Google Driveをインストールしている場合は、特に問題が起こらないのでは??と思います。新しく環境構築をしたり、アプリケーションを入れ直したりする場合は、今回の情報をご参考ください。
【swift3】ボタンに透明のフィルターぽいものをつける


環境：swift3のはず

どう表現していいのか難しいけど、例えば下の画面で背景がbuttonになってて背景画像が変えれるとかそういう感じの機能について。背景にimageviewがあって上にbuttonを重ねるとかのイメージ。
![スクリーンショット 2017-08-13 1.43.32.png](https://qiita-image-store.s3.amazonaws.com/0/64334/4498cd0e-c5b8-de50-b8a3-57a975e68d5a.png)
http://kappdesign.blog.fc2.com/blog-entry-11.html

# 経緯

画像にグレーの透過を加えたかったので、グラデーションでいけないかと試したが諦めた。
最終的にはbuttonにbuttonを重ねた。重ねることによって困ったことが起きたのでそれについてもメモしとく。


# グラデーションについて

画像にフィルターがかかったぽくしたかったが、グラデーションってグラデーションぽくなっちゃう。ってそらそうかw
やりたかったのはこれではなかった。
http://tanihiro.hatenablog.com/entry/2016/05/25/201726

```swift:
let startColor = UIColor(white: 0, alpha: 0).CGColor
let endColor = UIColor(white: 0, alpha: 1).CGColor

let layer = CAGradientLayer()
layer.colors = [startColor, endColor]
layer.frame = view.bounds

view.layer.addSublayer(layer)
```


![スクリーンショット 2017-08-13 1.25.11.png](https://qiita-image-store.s3.amazonaws.com/0/64334/60bac876-f505-658c-8b92-cd868498518a.png)


だけどカッコいいUIを作るのに使えそうな気がしたので一旦メモだけしとく。

```swift:
//https://stackoverflow.com/questions/37849359/swift-adding-gradient-layer-to-button-layer-length-error
let loginButton = UIButton(frame: CGRect(x: 10, y: 50, width: 300, height: 30))
self.view.addSubview(loginButton)

let gradient:CAGradientLayer = CAGradientLayer()
let colorTop = UIColor(red: 112.0/255.0, green: 219.0/255.0, blue: 155.0/255.0, alpha: 1.0).CGColor
let colorBottom = UIColor(red: 86.0/255.0, green: 197.0/255.0, blue: 238.0/255.0, alpha: 1.0).CGColor

gradient.colors = [colorTop, colorBottom]
gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
gradient.frame = loginButton.bounds
gradient.cornerRadius = 5

loginButton.layer.addSublayer(gradient)
```


![スクリーンショット 2017-08-13 1.27.43.png](https://qiita-image-store.s3.amazonaws.com/0/64334/474c58ef-31f8-2e56-90c5-5d1dc34ac4e6.png)


別の書き方

```swift:
import UIKit

public class GradientButton: UIButton {

    override public func layoutSubviews() {
        super.layoutSubviews()
        layoutGradientButtonLayer()
    }

    // MARK: Private
    private func layoutGradientButtonLayer() {
        let gradientLayer = CAGradientLayer()
        let color1 = UIColor(red:0.05, green:0.29, blue:0.49, alpha: 1.0).cgColor as CGColor
        let color2 = UIColor(red:0.08, green:0.23, blue:0.39, alpha: 1.0).cgColor as CGColor
        gradientLayer.colors = [color1, color2]
        gradientLayer.locations = [0.0, 1.0]
        self.layer.addSublayer(gradientLayer)
    }
}
```


で自分の場合はbuttonにaddsubviewで透化したbuttonを乗せたんだけどイベントが効かなくなった。

#色一覧 UIColor
http://www.codingexplorer.com/create-uicolor-swift/

UIColorデフォで持ってるカラーの一覧参考までに。

![スクリーンショット 2017-08-13 1.47.59.png](https://qiita-image-store.s3.amazonaws.com/0/64334/707d5c4e-ebc1-f86a-7229-e60a1dfdeecb.png)


#userInteractionEnabledを変更する。

view1.userInteractionEnabled = YES;
に設定すれば動いた。

この辺も参考に。
http://qiita.com/ika_tarou/items/e411c37b064fdd514afb
http://kappdesign.blog.fc2.com/blog-entry-11.html
ProgressDialogの 表示開始時間 と 最低表示時間 を設定できるようにしてみた

私はAndroidのアプリで通信中にProgressDialogを表示する処理をしばしば実装します。

しかし個人的な感覚になりますが、表示してすぐに閉じてしまうProgressDialogがとても嫌いです。
そのような処理の場合は表示する必要がないと思います。

ダイアログの表示を開始したら一瞬で消えてしまうと、
なんのためのダイアログかわからないときがあります。
（ダイアログに”通信中”と書いている場合に、ユーザに通信中であることを伝えたい）

だらだらと書きましたがProgressDialogの表示開始時間と最低表示時間を操作したいということです。
例えば、処理が開始して200ミリ秒以内で終わる場合はダイアログを出さないという場合に有効です。

以上の不満からProgressDialogを継承したViewを作成しました。


```java


public class CustomProgDiag extends ProgressDialog {

    // start time
    private long mStartTime;
    // show at least milliseconds
    private long mDuration;
    // showing?
    private boolean isShowing;

    private Handler mHandler;
    private Runnable mRunnable;

    public CustomProgDiag(Context context) {
        super(context);
    }

    /**
     * ミリ単位ダイアログを表示する最低時間を指定
     *
     * @param duration
     */
    public void show(long duration) {
        show(duration, 0);
    }

    /**
     * @param duration 最低何秒間表示するか
     * @param start    何秒後からダイアログ表示
     */
    public void show(long duration, long start) {
        mDuration = duration;
        isShowing = false;

        if (start == 0) {
            showDiag();
            return;
        }

        mHandler = new Handler();
        mRunnable = new Runnable() {
            @Override
            public void run() {
                showDiag();
            }
        };
        mHandler.postDelayed(mRunnable, start);
    }

    public void dismiss(final Callback callback) {
        if (!isShowing) {
            isShowing = false;
            mHandler.removeCallbacks(mRunnable);
            callback.callback();
            return;
        }

        long endTime = System.currentTimeMillis();
        long diffTime = endTime - mStartTime;

        if (diffTime < mDuration) {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    CustomProgDiag.super.dismiss();
                    callback.callback();
                }
            }, mDuration - diffTime);
        } else {
            super.dismiss();
            callback.callback();
        }
    }

    /**
     * ダイアログ表示
     */
    private void showDiag() {
        isShowing = true;
        mStartTime = System.currentTimeMillis();
        show();
    }

    public interface Callback {
        void callback();
    }
}

```



使用するときは


```java

CustomProgDiag diag = new CustomProgDiag(getConstext());
diag.setMessage("通信中");  
diag.show(1000,250); 

```


上の例では
250ミリ秒後からダイアログを表示、表示した場合は最低1000ミリ秒間はダイアログを表示する
という事になります。


```java

CustomProgDiag diag = new CustomProgDiag(getConstext());
diag.setMessage("通信中");  
diag.show(1000); 

```
第一引数のみ指定すると最低1000ミリ秒間表示するという処理になります。

閉じるときは

```java
diag.dismiss(new CustomProgDiag.Callback() {
    @Override
    public void callback() {
    /* ダイアログが閉じられたあとに呼ばれる */

}

```

となります。

以上の処理を参考にすると様々なところで活かせると思います。
TensorFlow + Kerasでフレンズ識別する - その3: 分類編

学習済みのモデルを使って、未学習のファイルを分類させてみる。

## 分類

判定は、前述の通り「顔周辺」の画素を利用して行う。ただ、顔検出の部分から実装しはじめると本質的な部分に触れる前に処理が複雑になってしまう。そこで、**まずは「手動で顔周辺のみを切り出した画像」を与えて正しく分類できるかを見てみる。**

学習は「顔周辺」の情報だけを元に行なっているので、ここでいきなり全身が写った画像を入力して判定させてもいい結果は出ないので注意すること。

### ソースコード

分類のコードは非常に短いため、先にコード全体を提示しておく。

```
# -*- coding: utf-8 -*-
import argparse
import numpy as np
from keras.models import load_model
from PIL import Image

parser = argparse.ArgumentParser(description='Predict.')
parser.add_argument('src_file', type=str, help='Source images file.')
parser.add_argument('model_file', type=str, help='Model file.')
parser.add_argument('--size', type=int, help='Width of image of model file.', default=48)
args = parser.parse_args()

image_size = args.size
model = load_model(args.model_file)

image = Image.open(args.src_file)
image = image.convert("RGB").resize((image_size, image_size), Image.ANTIALIAS)
image = np.asarray(image, dtype=np.float32).reshape(image_size, image_size, 3)
image /= 255.0

result = model.predict(np.array([image]), 1)[0]
for i, score in enumerate(result):
    print("Category-%d: %.2f"%(i, score))
```

まず、処理の本質的な部分ではないが、`argparse`を使って入力画像(判定したい画像)のパスと、判定に使用する学習済みモデルのパス、オプションで学習済みモデルの入力層に渡す画像のサイズを取得するようにしている。

```
model = load_model(args.model_file)
```

Kerasでは、`load_model`メソッドを使って、学習済みモデルファイル(hdf5)から簡単にモデルを復元することができる。自分でソースコード上で学習時と同じモデル構造を再現し、そこに学習済みの重みをセットしていくのに比べて非常にコードがシンプルになる。別の構造を持ったモデルを使って推論をして、性能を比較したりしたい場合でも、ソースコードをいじることなく別のモデルを使用することができて非常に便利だ。

```
image = Image.open(args.src_file)
image = image.convert("RGB").resize((image_size, image_size), Image.ANTIALIAS)
```

入力画像は、ここではPillowを使って読み込み、3チャンネル化(グレースケールやアルファチャンネルが含まれている画像ファイルは、変換してやる必要がある)、入力層のサイズにあわせたリサイズを行っている。OpenCVを使っても実現は可能で、場合によってはOpenCVを使ったほうが良い場合(OpenCVの顔検出を使いたい、フィルターを適用したい、など)もあるが、必要がなければPython3系でも安定して使え、インストールが用意なPillowをお勧めしたい。

```
image = np.asarray(image, dtype=np.float32).reshape(image_size, image_size, 3)
image /= 255.0
```

その後、`NumPy`の機能を使って画像のピクセル配列をTensorFlowの入力層(image_size * image_size * 3チャンネル)に渡す用のfloat32の配列に変換する処理を行っている。同時に、正規化も行っている。`image /= 255.0`で配列の要素に対して一度に演算を行えるというのは、慣れないと不思議であると同時に便利だ。

学習時にはImageDataGeneratorがこの辺りの処理もやってくれていたが、今回は判定に使う一枚の画像をわかりやすく扱うため、ImageDataGeneratorを使わなかった。

```
result = model.predict(np.array([image]), 1)[0]
```

最後に、復元したモデルの`predict`メソッドを使って、入力画像の分類を行う。`predict`メソッドは、一度に複数のデータを判定できるような構造になっているため、今回のように一個のデータ(1枚の画像)を判定させたい場合でも、要素一つの配列として入力を与え、結果の配列の一つ目を取り出して利用する形になる。

結果の配列には、各カテゴリのスコアが含まれているので、デバッグ用にそれを表示している。

この結果を見るとわかるように、結果はただのスコアの配列になってしまう。この配列の並びは学習時のカテゴリの並びと同一となるのだが、ここの管理は非常に重要であると同時に、適用にやっていたりするとあとで混乱の原因になるので注意したい。

## 顔の検出へ
ある程度未学習のデータでも正しく判定できてそうだったら、次は全身が写った画像を入力した場合でも正しく判定をできるように、顔検出と組み合わせてみる。

[TensorFlow + Kerasでフレンズ識別する - その4: 顔周辺の切り出し編](http://qiita.com/croquette0212/items/22d034a3215285401353)