OmniAICreator/Qiita-1.07M huggingface dataset:
GitタグのpushでCircleCI 2.0のビルドを実行する

Gitでタグを打ったときに自動的にCircleCIのビルドを実行しようとして盛大にハマったので、情報を残しておきます。CircleCIは、バージョン1.0ではなくバージョン2.0の想定です。

ここでは、次の条件でビルドを開始するジョブを作ります。

* Gitの任意のブランチ＆タグをpushすると、ビルド処理を実行する
* Gitのタグ (`v〇〇`) または `master` ブランチをpushすると、デプロイ処理も実行する

## ビルドとデプロイのジョブを分けない方法

あまり格好よくないですが、こちらの方がシンプルで簡単です。ポイントは次の2点です。

* `filters/tags/only` を指定し、Gitタグをpushした場合もジョブが開始されるようにする
* `deploy` ステップの中でpushされたGitタグまたはブランチを特定し、デプロイ処理も実行するかどうかを判定する

```yaml:.circleci/config.yml
version: 2
jobs:
  build:
    docker:
      - image: circleci/golang:latest
    steps:
      - checkout
      - run: echo "Hello, World"
      - deploy:
          name: deploy build artifact
          command: |
            if [ "${CIRCLE_TAG}" != "" -o "${CIRCLE_BRANCH}" == "master" ]; then
              [ "${CIRCLE_TAG}" != "" ] && TAG=${CIRCLE_TAG} || TAG=latest
              echo "Deploy! ${TAG}"
            fi
workflows:
  version: 2
  build-and-deploy:
    jobs:
      - build:
          filters:
            tags:
              only: /v.*/
```

## ビルドとデプロイのジョブを分ける方法

Workflowらしく2つのジョブを使って実現する方法はこちらです。ポイントは、次の1点につきます。仕様が分かりづら過ぎます :angry: 

* `deploy` ジョブだけでなく `build` ジョブにも `filters/tags/only` を指定する

```yaml:.circleci/config.yml
version: 2
jobs:
  build:
    docker:
      - image: circleci/golang:latest
    steps:
      - checkout
      - run: echo "Hello, World"
  deploy:
    docker:
      - image: circleci/golang:latest
    steps:
      - checkout
      - run:
          name: deploy
          command: |
            [ "${CIRCLE_TAG}" != "" ] && TAG=${CIRCLE_TAG} || TAG=latest
            echo "Deploy! ${TAG}"
workflows:
  version: 2
  build-and-deploy:
    jobs:
      - build:
          filters:
            tags:
              only: /v.*/
      - deploy:
          requires:
            - build
          filters:
            tags:
              only: /v.*/
            branches:
              only: master
```

1つ目の方法とは違ってジョブが2つに別れているため、ビルドジョブの出力をデプロイジョブで使い回したい場合は注意が必要です。 `persist_to_workspace`, `attach_workspace` などを使って、ジョブからジョブへ成果物を受け渡す必要があるでしょう。

```yaml:.circleci/config.yml
jobs:
  build:
    steps:
      - ...
      - persist_to_workspace:
          root: /tmp/workspace
          paths:
            - build/*
  deploy:
    steps:
      - ...
      - attach_workspace:
          at: /tmp/workspace
      - run: cat /tmp/workspace/build/output.txt
```
GitHub事始め

GitHub導入の覚書として。概要のみで具体的ではありませんがご容赦ください。
#環境
Windows10+SourceTree+GitHub

#Gitのローカル環境を構築する
##SourceTreeをインストールする
###SourceTree ダウンロード
https://ja.atlassian.com/software/sourcetree
###メモ
・ATLASIANアカウントにログインする際に、Googleアカウントを使いました。
・Mercurialのインストールを同時に行うこともできますが、今回は行いませんでした。（インストーラーでチェックを外しました）。

#GitHubのアカウントを取得する
##GitHubのサイトにアクセスし、アカウントを作成する。
https://github.com/

#GitHubにあるリソース（リポジトリ）をローカル環境へコピーする（クローン）
##GitHubでリポジトリを作成またはフォークする。それをSouceTreeでクローンを作成することでコピーする。

#参考文献
湊川あい著「わかばちゃんと学ぶ　Git使い方入門」C&R研究所
Django girls でHerokuにpushできなかった時の話

Django girlsをやってたところ、デプロイ！のHerokuにアップする時少しつまづいたのでメモ
>https://djangogirlsjapan.gitbooks.io/workshop_tutorialjp/content/deploy/

#【事象】
Django girlsチュートリアルの手順に則り、以下コマンドでHerokuにアップロードしようとしたところ..

```
git push heroku master
```

Pushに失敗

```
remote: ! Push rejected, failed to compile Python app.
remote: 
remote: ! Push failed
remote: Verifying deploy...
remote: 
remote: !	Push rejected to mokumoku-blog-20180630.
```

#【原因】
原因は2つ
①Django girlsチュートリアルの「runtime.txt」に記載していたPythonのバージョンと、自分のPCに導入していたPythonのバージョンが異なっていた。

```
(myenv) TakunoMacBook-Pro:djangogirls2 taku$ python --version
Python 3.6.5
```

>The runtime.txt file
>Herokuに使っているPythonのバージョンを伝えなければいけません。djangogirlsディレクトリにruntime.txt ファイルを作ってその中に書きます。エディタで新規ファイルを作成して、次のように書いてください:

```
python-3.5.2
```

※事前にPythonを導入しており、以下手順はスキップしていた。（3.6.5をインストール）

>https://djangogirlsjapan.gitbooks.io/workshop_tutorialjp/content/python_installation/

=>これも3.6.2でruntime.txtで記載してみようとされていたバージョンと違うのだが・・

②psycopg2のバージョンが古い
チュートリアルの手順だと、必要なバージョンが導入されないらしい。

psycopg2のアップデートが必要

#【解決策】
①runtime.txtの記載を修正

>runtime.txt

```
python-3.6.5
```

修正後、以下コマンドで設定を反映

```
$ pip freeze > requirements.txt
```

②psycopg2のアップデート
以下コマンドを実行

```
pip install --upgrade psycopg2
```

###　(参考)
>Djangoでherokuを使おうとした時, git push heroku master ができなかった話
>https://qiita.com/rym903/items/14571f056463e924f742

①、②を実行後、次のコマンドで反映

```
$ git add -A .
$ git commit -m "My Django Girls app"
```

反映後、git push すると、git(Heroku)へのアップロードは成功

```
remote: -----> Launching...
remote: Released v4
remote: https://mokumoku-blog-20180630.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/mokumoku-blog-20180630.git
* [new branch] master -> master
```
Flutterでネイティブで作ったViewControllerを呼び出す

Flutterではチャンネルという概念を用いてネイティブAPIやネイティブコードを呼び出すことができます。

今回はXcode上で作ったViewControllerをFlutterから呼び出してみたいと思います。

公式ドキュメントではバッテリー情報を取得しています。
https://flutter.io/platform-channels/


## チャンネルを設定

まずはFlutter側の設定を書いていきます。

```dart

MethodChannel channel =
      const MethodChannel('jp.groupsnap/SandBoxViewController');

```

設定はこんな感じ。
`jp.group....` のところはiOSのネイティブ側と同じ文字列を設定する必要があります。

## ネイティブコードを呼ぶ

チャンネルを設定したら呼び出したい箇所で下記のコードを実行します

```dart
_callViewController() async {
    try {
      await channel.invokeMethod('callViewController');
    } on PlatformException catch (e) {
      print(e);
    }
  }
```

`callViewController` はプラットフォーム側にメッセージを渡せます。
 渡すことはなくてもとりあえずなにからテキストを設定しないといけないっぽいです。(?)
(ここの真相はよくわからないのでわかる方教えてください、、、)


## AppDelegateにChannelを設定する

```swift
import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    
    // Channelの設定
    setiOSChannel()
    
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
```

こんなコードを書いて、 `setiOSChannel` にチャンネル設定の実装を書いていきます。

```swift

    func setiOSChannel() {
        // iosチャンネル
        let controller : FlutterViewController = window?.rootViewController as! FlutterViewController;
        
        // SandboxViewController
        let callSandboxChannel = FlutterMethodChannel.init(name: "jp.groupsnap/SandBoxViewController", binaryMessenger: controller)
        callSandboxChannel.setMethodCallHandler({
            (call, result) -> Void in
            
            let next = controller.storyboard?.instantiateViewController(withIdentifier: "SandboxViewController")
            controller.present(next!,animated: true, completion: nil)
        })
    }
```

あとは　`setMethodCallHandler` の中でiOSの画面遷移の実装にしたがって実装を書いていきます。
NavigationControllerで使っていろいろしたりしたかったら `window?.rootViewController` とかからNavigationControllerを取得(？)してPushViewControllerとかしてください。

## 雑談

今回はiOSの方を書いていきましたが、Androidの方だとたぶん `Intent` 投げたりするのかも。
たぶん実装方法はあまり変わらないと思います。
CIでも可愛い子に叱られたい ~Google Apps Scriptを添えて~

 最近ちょいちょいと個人的な日曜プロジェクトでCircleCIを導入しているのですが、標準のSlackBOTでは味気がなくただただビルドが失敗したという事実しか通知してくれません。  

これは由々しき事態です。  
また、Slack以外のChatworkなどの公式対応がないツールや別ツールと連携できるようにWebhookの仕組みとGoogleAppsScript(以下GAS)を使って通知をできるようにします。

## SlackのAPI トークンを取得する
まずはSlack APIのページにアクセスして```start build```を押します。  
[https://api.slack.com/](https://api.slack.com/)  
サービス名とインストール先を入力します。  
```Add features and functionality > OAuth & Permissions > Scopes```でサービスに対して権限を付与します。  
今回はチャンネルにポストするための権限を付与します。  
saveしたら```Install App to Workspace``` を押して対象ワークスペースにアプリケーションを適用します。  
インストール後にはOAuth Access Tokenが発行されます。このアクセストークンはSlackにポストする際に使用します。

アイコンなどはここで合わせて設定しましょう。

# とりあえずソースコード

GASでは公開ウェブアプリケーションとして公開すると ```doPost()``` でPOSTメゾットを扱うことができます。  
今回はSlackにPostするにあたって [Qiita | Slack BotをGASでいい感じで書くためのライブラリを作った
](https://qiita.com/soundTricker/items/43267609a870fc9c7453)をお借りしました。



```js
function doPost(e) {
  var json = JSON.parse(e.postData.getDataAsString());
  var msg = ""
  var icon = null
  msg += "circleCIが起動したよ！\n"
  
  if(json.payload.status == "success"){
    msg += ":success_circleci: テストは成功したみたいだよ！ \n"
  }else{
    msg += ":failed_circleci: テスト失敗しちゃった… \n"
  }
  msg += "ブランチ名:" + json.payload.branch + "\n" + json.payload.build_url
  postSlackMessage(msg)
}

// メッセージを投げる
function postSlackMessage(msg) {
  var token = ”Slack Tokenをここにはる";
  var slackApp = SlackApp.create(token); //SlackApp インスタンスの取得
  var options = {
    channelId: "#hoge", //チャンネル名
    userName: "ユニティちゃん", //投稿するbotの名前
    message: msg //投稿するメッセージ
  };
  Logger.log(slackApp.postMessage(options.channelId, options.message, {username: options.userName, icon_url: options.icon_url}));
}


```

## CircleCIのWebhookを追加する
まずはテストが回ったあとにPOSTする先を取得します。  
Googleの上部メニューバーの公開>ウェブアプリケーションとして公開を押します。  
そうするとモーダルウィンドウでURLとアプリケーションにアクセスできるユーザー、アプリケーション実行するユーザーなどが設定できます。  
<img width="428" alt="スクリーンショット 2018-07-01 21.59.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/77203/36f6f1aa-7f6c-ba3f-d9e5-19263b9a00a0.png">

今回はアプリケーションにアクセスできるユーザーは全員にします。  
更新を押すとURLが生成されるので控えておきます。

URLを控えたら対象とするプロジェクトの```.circleci/config.yml```を開きます。  
Yamlの中に以下の文を書きます。  
```yml
notify:
  webhooks:
    # A list of hook hashes, containing the URL field
    - url: 生成されたGASURL
```



## 僕たちが得たもの
<img width="607" alt="スクリーンショット 2018-07-01 22.36.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/77203/6853c317-96cb-1cb1-44b5-e72dfb23e048.png">


参考

* [CircleCi Document](https://circleci.com/docs/configuration#notify)

## ライセンス
このコンテンツの一部にユニティちゃんを使用しています  
© Unity Technologies Japan/UCL
いつもお世話になってます!
未来志向の方策ベースの学習アルゴリズム

アルゴリズム モンテカルロ木探索 コンピュータ囲碁 コンピュータ将棋 機械学習

# はじめに
モンテカルロ木探索と先読みを利用した、方策ベースの学習アルゴリズムに関するアイデアです。

# アルゴリズム
モンテカルロ木探索で、方策を取得したい場合の「学習の一サイクル」は、以下のようになります。

1. 乱数、既存の方策などを利用して、多数の状態を作成

1. 作成した各々の状態から、モンテカルロ木探索を実行

1. モンテカルロ木探索で得られた結果(取り得る行動に対する分布)で、方策を学習

この際、モンテカルロ木探索は、探索木の子節点(スタートの状態から、ある行動を選んだ次の状態)から開始されますが、この開始時の子節点を「未来に進めてしまう」というアイデアです。
具体的には、全ての子節点に対し、既存の方策を使用して(場合によっては乱数も使用して)先の状態に進めます。
それによって得られた「先の状態」の節点を、モンテカルロ木探索を開始するときの子節点とみなして探索を実行するというものです。
どれくらい先の状態に進めるかを意味する「深さ」は、学習のサイクルごとに大きくしていく方式が考えられます。
例えば、方策が得られていない最初のサイクルは深さ0で実施し、次のサイクルでは前サイクルの方策を使用して深さ1で実施、その次は一つ前のサイクルの方策を使用して深さ2(または深さ3)で実施、といったように次第に深くしていきます。
このアイデア自体は、コンピュータ将棋の「雑巾絞り」から思い浮かびましたが、方向性としては、強化学習におけるTDLeaf(λ)と同様のように思われます。

# メリットとデメリット
未来に進めてから探索することにより、効率よく将来の状況を見通して学習できる(可能性がある)というメリットが考えられます。
その一方、既存の方策に基づく先読みであり、特定の状態に決め打ちしてからの探索となってしまうため、学習が片寄るデメリットも考えられます。
メソッドの再利用性を高めるためeventを活用した

#やりたいこと
ある処理をクラス化する場合、クラスのコードをべた書きすると当然逐次処理となる。
べた書きの場合、ある処理の一部を少しだけ変えて処理をしたい場合は別クラスを作成するか、その部分のクラス化をあきらめるかしないといけない。
それを回避するためにeventを活用しクラスに汎用性を持たし再利用性を高めることにした。

#やったこと

##登場人物

|クラス|概要|
|:--|:--|
|SomeProcessExecutor|ある処理を実行するクラス（ここがメイン）|
|GenericEventArgs&lt;T&gt;|イベント引数。SomeProcessExecutorのイベント発生時に呼び出し元クラスが特定の値を受け取る。<br />EventArgsクラスを継承|
|Form1|SomeProcessExecutorを呼び出すクラス|

##クラスの内容

```c#:GenericEventArgs&lt;T&gt;
    public class GenericEventArgs<T> : EventArgs
    {
        public T EventData { get; set; }
        
        public GenericEventArgs(T evenData)
        {
            EventData = evenData;
        }
    }
```
ジェネリクスを使用し、処理に応じて呼び出し元に引き渡す型を変えられるようにした。ここでは引き渡しは１つにしてある。



```c#:SomeProcessExecutor
    public class SomeProcessExecutor
    {
        public event EventHandler<GenericEventArgs<string>> MainProcessHandler;
        public event EventHandler<GenericEventArgs<Exception>> ExceptionHandler;

        public void Execute()
        {
            try
            {
                //共通の前処理の実施

                //（イベント発生】呼び出し元個別の処理
                //呼び出し元でイベント発生時の処理を記述
                ExecuteMainProcessHandler(new GenericEventArgs<string>("Hello World!"));

                //共通の後処理を実施

            }
            catch(Exception e)
            {
                //呼び出し元でイベント発生時の処理を記述
                ExecuteExceptionHandler(new GenericEventArgs<Exception>(e));
            }
        }

        private void ExecuteMainProcessHandler(GenericEventArgs<string> arg)
        {
            //イベントが呼び出し元で定義されている場合のみイベント処理を実施
            EventHandler<GenericEventArgs<string>> handler = this.MainProcessHandler;
            if (handler != null)
            {
                handler(this, arg);
            }
        }

        private void ExecuteExceptionHandler(GenericEventArgs<Exception> arg)
        {
            //イベントが呼び出し元で定義されている場合のみイベント処理を実施
            EventHandler<GenericEventArgs<Exception>> handler = this.ExceptionHandler;
            if (handler != null)
            {
                handler(this, arg);
            }
        }
    }
```
呼び出し元個別に処理を定義したい箇所でイベントを定義


```C#:Form1
        private void button1_Click(object sender, EventArgs e)
        {
            //ある処理のインスタンスを生成し、イベントの処理を定義
            SomeProcessExecutor executor = new SomeProcessExecutor();
            executor.MainProcessHandler += Execute;
            executor.ExceptionHandler += handleException;

            //ある処理を実行する処理を実行
            executor.Execute();

        }

        private void Execute(object sender, GenericEventArgs<string> args)
        {
            //呼び出し元個別の処理を定義
            MessageBox.Show(args.EventData);
        }

        private void handleException(object sender, GenericEventArgs<Exception> args)
        {
            //呼び出し元個別の処理を定義（例外発生時）
            MessageBox.Show(args.EventData.ToString());
        }
```
イベントそれぞれに個別処理を定義し、処理を実行。


以上
RaspberryPiでLチカ

# はじめに
ずっとやってみたいと思っていたRaspberryPiでの電子工作。
臨時収入があったので、一通りの機材を買い揃えました。
まずは、電子工作のHelloWorldと言われているLED点滅に挑戦してみたいと思います。

# 今回の目標
3つのLEDを順番に高速点滅させたい

# 使った部品
  RaspberryPi 3 Model B
  1kΩ抵抗 x 1
  赤色LED x 1
  黄色LED x 1
  緑色LED x 1
  ブレッドボード x 1
  ジャンパーワイヤー x 4

# 作った回路
<img width="464" alt="ledtest.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/246683/6d52dbc9-54bb-bf70-a606-d5c9c213c0dc.png">

- 使用したGPIO
    - GND(6番) -> 1kΩ抵抗へ
    - GPIO4(7番) -> 緑色LEDのアノードへ
    - GPIO17(11番) -> 黄色LEDのアノードへ
    - GPIO27(13番) -> 赤色LEDのアノードへ

# 制御プログラム(Python3)
[GitHubにもアップしてます](https://github.com/horus19761108/raspi/blob/master/ledtest.py)

```Python3:ledtest.py
#!/usr/bin/env python3

import RPi.GPIO as GPIO
import time

#GPIOのセットアップ
GPIO.setmode(GPIO.BCM)		# GPIOモードのセット
GPIO.setup(4, GPIO.OUT)	 	# GPIO4を出力に使用(緑色LED用)
GPIO.setup(17, GPIO.OUT)	# GPIO17を出力に使用(黄色LED用)
GPIO.setup(27, GPIO.OUT)	# GPIO27を出力に使用(赤色LED用)

# LEDを順番に光らせる
i=0
pin=[4, 17, 27]	# GPIOのIDを配列にセット
while i<50:
	# 緑->黄色->赤の順にLEDを点灯させる
	for p in pin:
		GPIO.output(p, GPIO.HIGH)	# HIGHで電圧がかかる(LEDが光る)
		time.sleep(0.1)
		GPIO.output(p, GPIO.LOW)	# LOWで電圧がなくなる(LEDが消える)
	i += 1

GPIO.cleanup()	# 使ったGPIOの解放
```
# 感想
結構簡単にできました。
電子工作自体が初めてなので、セオリーとかよくわからず作りました。
とりあえず目的通りに動いたので間違ってないのかな？
「こういった回路は一般的にはこうやるよ」みたいなアドバイスあればコメントお願いします。
Arduino で取得したセンサーの値を Raspberry Pi で受け取る

使用したのは温湿度センサーです。

# 参考
[Arduinoで温湿度センサ(DHT11)を使う (shangtian’s blog)] (http://www.shangtian.tokyo/entry/2017/04/09/212730)

# 環境
* Raspberry Pi 3 Model B+
* Raspbian 9.4 (Stretch)
* platformio
* Arduino 互換機
* 温湿度センサー DHT11
* Python 2.7.13

# スケッチ
参考ほぼそのままですが、platformio でコンパイルするには Adafruit_Sensor.h の宣言が必要でしたので追加しています。
もちろん、ライブラリの追加も必要ですよ。

※スケッチの記述、Arduino への書き込みは Mac や Windows で作業したほうが早そうだなと思い始めました。

~~~c
#include <Adafruit_Sensor.h>
#include <DHT.h>

const int PIN_DHT = 8;
DHT dht(PIN_DHT, DHT11);

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("Start");
  dht.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(3000);
  float humidity = dht.readHumidity();
  float temperature = dht.readTemperature();

  Serial.println("Humidity: ");
  Serial.println(humidity);
  Serial.println("%");
  Serial.println("<--EOL-->");
  Serial.println("Temperature: ");
  Serial.println(temperature);
  Serial.println("*C");
  Serial.println("<--EOL-->");
}
~~~

# 受信プログラム
Python で受信プログラムを書きました。
Raspberry Pi 上で動かします。

~~~python
# -*- coding: utf-8 -*-
import serial

start = 'Start'
line_separator = '<--EOL-->'
output = ''

s = serial.Serial('/dev/ttyACM0', 9600)

# Arduino との接続前に受け取ったデータは破棄する
while True:
    output = output + str(s.read())

    if (start in output):
        output = ''
        break

# 行ごとに出力する
while True:
    output = output + str(s.read())

    if (line_separator in output):
        output = output.replace(line_separator, '')
        output = output.replace("\r\n", '')
        print(output)
        output = ''
~~~

# 動かしてみる
無事動きました。
暑そうなところで作業してるようですね。

~~~
pi@raspberrypi:~/Arduino/DHT11 $ python receiver.py 
Humidity: 57.00%
Temperature: 29.00*C
Humidity: 59.00%
Temperature: 29.00*C
Humidity: 65.00%
Temperature: 29.00*C
Humidity: 70.00%
Temperature: 29.00*C
Humidity: 72.00%
Temperature: 29.00*C
Humidity: 74.00%
Temperature: 29.00*C
Humidity: 69.00%
Temperature: 29.00*C
~~~

# まとめ
ひとまずこれでやりたいことの下地はできました。
Python で値が受け取れてしまえば、あとは表示するなりデータベースに保存するなり何でもできるようになりますね。
【Python】crontabで、ファイルを読み込むスクリプトを動かす時にpathlibを使うと楽だった

## crontabで設定ファイルが読み込まれない
普段はpythonで仮想通貨の自動取引Botを作ったりしているのですが、息抜きに全く関係ない大学用のTwitterBotを作りました。

[KU休講情報Bot](https://twitter.com/KUBotver2)

このBotは講義が終わるたびにその日の休講情報を呟くものです。
これをcrontabで定期実行させようと考えました。

しかし、設定をしても同じディレクトリにあるアクセストークン等が書かれたjsonファイルが読み込まれない。おかしいと思いログをあさってみると、`No such file or directory`。

調べてみるとcrontabのカレントディレクトリがホームディレクトリにあることが原因でした。
##解決法
先に解決法を書いておきます。以下のようにコードを変更しました。

* **変更前**

```python
f = open("./hoge.json","r") #相対パスでは読み込まれずエラーが起きる
```

* **変更後**

```python
from pathlib import Path
path = Path.cwd() / Path(__file__).parents[0] / "hoge.json"
f = open(path,"r")
```
#原因
##crontabのカレントディレクトリはホームディレクトリ
crontabのカレントディレクトリはホームディレクトリであり、スクリプトがあるディレクトリではありません。よって、`./hoge.json`のように書くとファイルが読み込まれません。

#なぜ[pathlib](https://docs.python.jp/3/library/pathlib.html)を使うのか
## 異なる環境でも動作する
相対パスでエラーが起きてしまう場合、絶対パスでファイルを参照したりしますが、それだと別の環境下(WindowsとLinuxなど)で使えません。引数でファイルパスを設定するのもありですが、毎回するのは面倒くさいです。

そんな時に[pathlib](https://docs.python.jp/3/library/pathlib.html)は効果を発揮します。[pathlib](https://docs.python.jp/3/library/pathlib.html)はPython3.4で追加された公式のモジュールです。

[pathlib](https://docs.python.jp/3/library/pathlib.html)はパスを表すクラスを提供し、パス通しの連結を`/`で行います。

```python
from pathlib import Path
hoge = Path("hoge")
fuga = Path("fuga.py")
print(hoge / fuga)

# > hoge/fuga.py (Linux)
# > hoge\fuga.py(Windows)
```
パス通しの連結の際に自動的にOSに準拠した表記になり、異なる環境でも動作します。

## 上位パスにアクセスしやすい
[pathlib](https://docs.python.jp/3/library/pathlib.html)は上位パスを`parents[n]`で取得できます。

```python
from pathlib import Path
path = Path("aaa/bbb/ccc/ddd")
print(path)
print(path.parents[0])
print(path.parents[1])

# > aaa/bbb/ccc/ddd
# > aaa/bbb/ccc
# > aaa/bbb
```

## `open()`の引数に使える
pythonでファイルを読み込む場合、大抵`open()`が使われますが、この引数に`Path()`を使うことができます。(Pytho3.6から)

##後は目的のディレクトリまでパスをつなげるだけ
これらを用いれば先に書いたようにパスを指定できます。

```python
path = Path.cwd() / Path(__file__).parents[0] / "hoge.json"
```
`Path.cwd()`はカレントディレクトリを返すクラスメソッドです。
また`__file__ `はスクリプトの絶対パスを表します。よって、スクリプトと同じ階層にあるファイルを読み込む場合は、`Path(__file__).parents[0]`と一つ上の階層のパスを用います。

#参考
1. [11.1. pathlib — オブジェクト指向のファイルシステムパス](https://docs.python.jp/3/library/pathlib.html)
2. [Python3.4以降ならos.pathはさっさと捨ててpathlibを使うべき](https://qiita.com/tag1216/items/29bf3b9c3c4b563ff0fe)
3. [cronの設定方法](https://qiita.com/hikouki/items/e744b3a4d356d2af12cf)
【しずおかアプリ部】活動ログ　第51回

![しずおかアプリ部2.jpg](https://qiita-image-store.s3.amazonaws.com/0/88105/ee800648-fa25-1829-20c3-bad9c2055d35.jpeg)

##■公式サイト##
[http://monolizm.com/shizuoka-app](http://monolizm.com/shizuoka-app)
「Slack」も利用しています。 shizuapp で検索し、ご参加ください。

##◾️参加申し込み##
しずおかアプリ部への参加申し込みは[こちら](https://shizuoka-app.connpass.com/)から

##■タイトル##
第５１回


##■開催日##
２０１８年６月２１日（土）　１６：００～１８：００


##■参加者##
１３名


##■活動内容（概要）##
・菅原プレゼン「Unity始めるよ 〜初心者向け講座！簡易レースゲーム制作でUnityを覚えよう２〜」
　　　　　　　「Unity始めるよ 〜スクリプタブルレンダーパイプラインを試してみた〜」
・部員さん： OpenSiv3Dについて
・雑談

　![IMG_0075.JPG](https://qiita-image-store.s3.amazonaws.com/0/88105/cd09f729-f2d7-f63e-2124-f239a4188abf.jpeg)


##■活動内容（詳細）##

【実演・プレゼン】



**・菅原プレゼン　「Unity始めるよ 〜スクリプタブルレンダーパイプラインを試してみた〜」**

　レンダーパイプラインとは、※レンダリングパイプライン、グラフィックパイプラインともいう
　オブジェクトを画面に描画するまでの様々な工程（カリング、各種座標変換、陰影計算、ラスタライズなど）を表す言葉。
　Unityではレンダーパイプラインがブラックボックスだったが、
　Unity5から試験的に開発者がコントロールできる機能を提供し始め、
　Unity2018で正式なものとなった。

　メリット
　　表現力と処理速度の天秤を、
　　開発者がコントロールできるようになった。

　デメリット
　　学習コストが高い（つまり難しい）

　Unityがデモプロジェクトを用意してくれている
　https://github.com/stramit/SRPBlog/tree/master/SRP-Demo

　導入するにはそれなりの手間がかかった。
　また自作のシェーダーは自分で対応する必要がある。

　でもLWRPは確かに軽かった！
　![スクリーンショット 2018-07-01 22.07.47.png](https://qiita-image-store.s3.amazonaws.com/0/88105/1e1df82e-072e-6676-962a-46bb8724d57f.png)



　実際に調べて見ての感想
　調べてみるまでは、正直もっと手軽なものだと思っていた。
　現時点ではまだまだ情報が少ないと感じる。構造の難しさだけじゃなくて調べるコストも大きい。
　進化速度が速いのか（すぐに情報が古くなる）、調べた通りにやってもうまく動かなかったりと、一筋縄じゃいかない。
　もう少し情報が出揃ってくるまでは、手を出すのに覚悟がいる。
　ただ、モバイル開発者には美味しい話ではある。



　 [資料](http://monolizm.com/sab/pdf/第51回_プレゼン資料(〜Unity2018のスクリプタブルレンダーパイプラインを試してみた〜) .pdf)　

<hr>
**・部員さんプレゼン　「OpenSiv3Dについて」**

　OpenSiv3Dという3Dフレームワークの紹介。
　グラフィカルなアプリケーションを簡単に素早く開発できる C++用フレームワーク。
　日本の方が作ったフレームワークで、
　Siv3Dというプロジェクトを、よりモダンなコードが書けるように、
　再構築＆オープン化したもの。
　WindowsならVisualStudio、
　MacならXcodeで開発可能。

　かなり短いコードでいろいろなことができるのが特徴。
　ブロック崩しはなんとたったの４７行！
![スクリーンショット 2018-06-30 17.03.04.png](https://qiita-image-store.s3.amazonaws.com/0/88105/3df667db-bcc1-8309-c7c5-a20d3c983293.png)



　ただまだ3Dには対応していないとのこと。（旧版のSiv3Dは対応していた）

　 [資料](http://monolizm.com/sab/pdf/http://monolizm.com/sab/pdf/第51回_プレゼン資料(OpenSiv3Dの紹介).pdf)
<hr>
**・菅原プレゼン　「Unity始めるよ 〜初心者向け講座！簡易レースゲーム制作でUnityを覚えよう２〜」**

　ゲームを作ったことがない人向けに、考え方、やること、作り方をまとめた。
　まとめはじめたら、とても１回のプレゼンじゃ収まりきらない内容になってしまったため、
　何回かに分けて発表する。

　今回は第２回として、車を制御するプログラム、ユーザー操作、敵AIを取り上げた。
　なるべく少ないスクリプトで、それっぽい動きができるように組んでみた。
　計算が面倒くさい処理も、Unityが用意してくれている関数を使えば、すっきりと書くことができる。
　Mathf.Lerp
　Mathf.Clamp
　Vector3.Cross
　Vector3.Angle
　を使って簡潔にした。

　![スクリーンショット 2018-06-24 19.28.20.png](https://qiita-image-store.s3.amazonaws.com/0/88105/752b3962-d647-6f4c-a205-d91ad507e388.png)

　ドリフト挙動も含めて、　敵AIも想定した通りに動いてくれている。
　ただ、特殊な状況には対応していないので、クラッシュした後はコースに復帰できない場合も。

　 [資料](http://monolizm.com/sab/pdf/第51回_プレゼン資料(〜初心者向け講座！簡易レースゲーム制作でUnityを覚えよう2〜).pdf)　
　 [プロジェクト一式](http://monolizm.com/sab/src/RaceGame.zip)　



<hr>


**・　雑談**

・OculusGO体験
　本日も部員さんがOculusGOを持って来てくれました。
　ヘンリーというソフトを体験させてもらいましたが、
　高クオリティグラフィックと高解像度ディスプレイのおかげで、
　かなりの没入感でした。

・その他、部員さん自作のVRマシンが、3Dプリンタを駆使しでクオリティアップを目指しているとのこと。
　８月４日５日開催のMaker Fair Tokyoに出展とのこと。

・Unity軽量ランタイム　http://ruccho.hateblo.jp/entry/2018/06/09/192033
・Unet http://nn-hokuson.hatenablog.com/entry/2018/06/19/200334
などなど
memo1

```html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>CSS overflow</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  </head>
  <body>
  
  <div id="slide1">
    <div style="1200px; overflow: hidden;">
    <ul id="list1" style="list-style: none; display: flex; overflow: scroll; width:500px">
      <li><img src="https://chokaigi.jp/2018/common/uploads/artist_katojunichi.jpg" width="320" height="213" alt="" /></li>
      <li><img src="http://youtuberch.com/wp-content/uploads/2017/10/24b308e8d9e3a6807cddf8c6638375d6.png" width="320" height="213" alt="" /></li>
      <li><img src="http://nancreator.com/wp-content/uploads/2017/06/%E3%81%86%E3%82%93%E3%81%93%E3%81%A1%E3%82%83%E3%82%93%EF%BC%88%E5%8A%A0%E8%97%A4%E7%B4%94%E4%B8%80%EF%BC%89-300x300.png" width="320" height="213" alt="" /></li>
      <li><img src="http://chokaigi.jp/2017/common/uploads/artist_katojunichi.jpg" width="320" height="213" alt="" /></li>

    </ul>
  </div>

  <button id="btn">button</button>
  <script type="text/javascript">
    $('#btn').click(function () {
    var slide = $('#slide1 ul li');
    var slide_sheets = slide.length;
    var slide_width = slide.width();
    //var wid_max = slide_sheets * wid + 'px';

var ttt = $('#list1 li').clone(true);
var limit_width = slide_width;
var x = 1;
var slide_cnt = 0;

loopMove();
 function loopMove(){
    $('#slide1 ul').animate({
    scrollLeft: '+=10px'},100,
    function(){
      loopMove();
      console.log($('#slide1 ul').scrollLeft());
      
      if($('#slide1 ul').scrollLeft() >= limit_width){
         var tes = $('#slide1 ul').scrollLeft();
         console.log($('#slide1 ul').scrollLeft());
         //var copy_sheet = $('#list1 li:eq(' + slide_cnt +')').clone(true);
         var copy_sheet = $('#list1 li:first').clone(true);
         $('#list1').append(copy_sheet);
         //limit_width = limit_width + slide_width;
         $('#list1 li:first').remove();
         slide_cnt++;
         
         ($('#slide1 ul').scrollLeft(0));


      }
    });
    
  };

    });


  </script>
  </body>
</html> 


```

[CSSのdisplay-tableで参考にさせていただいた記事](http://taneppa.net/display_other02/)
シンプルなreact-reduxのconnectの書き方

react-reduxのconnect関数は、いろいろな書き方ができることで知られています。
 (参考：[ReactとReduxを結ぶパッケージ「react-redux」についてconnectの実装パターンを試す](https://qiita.com/MegaBlackLabel/items/df868e734d199071b883))

その柔軟さゆえ、実際にアプリケーションの中で書く場合にどのパターンを選ぶか悩むことが多いのではないでしょうか。今回は自分の気に入っている書き方を紹介します。

## 最もシンプルな書き方

```react
import { connect } from 'react-redux'
import MyComponent from './my-component'
import { actionCreatorA, actionCreatorB } from './my-module'

export default connect(
  ({users, todos}) => ({users, todos}),
  {
    actionCreatorA,
    actionCreatorB
  }
)(MyComponent)
```

これだけです。stateを特にいじらずにconnectしたいときはこれで十分です。action creatorsは、rest spread operatorでまるっと渡してしまっても良いです。

## reselectとか使うなら
```react
import { connect } from 'react-redux'
import MyComponent from './my-component'
import { actionCreatorA, actionCreatorB } from './my-module'
import { mySelector } from './selectors'

export default connect(
  state => ({
    todos: mySelector(state)
  }),
  {
    actionCreatorA,
    actionCreatorB
  }
)(MyComponent)
```

reselectを使ったり、stateのconnectの仕方に工夫がいる場合はこのように書きます。

## actionCreatorsをactionsでまとめたい時
```react
import { connect } from 'react-redux'
import MyComponent from './my-component'
import { actionCreatorA, actionCreatorB } from './my-module'

export default connect(
  ({users, todos}) => ({users, todos}),
  dispatch => ({
    actions: {
      actionCreatorA: () => dispatch(actionCreatorA()),
      actionCreatorB: () => dispatch(actionCreatorB())
    }
  })
)(MyComponent)
```

## よくある書き方と比べると

```react
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import MyComponent from './my-component'
import { actionCreatorA, actionCreatorB } from './my-module'

function mapStateToProps(state) {
  return { 
    users: state.users 
    todos: state.todos
  }
}

function mapDispatchToProps(dispatch) {
  return { actions: bindActionCreators(actionCreators, dispatch) }
}

export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)
```

やっていることは紹介したシンプルな書き方と同じことですが、かなり冗長に見えます。

## 解説
キモは、mapStateToProps、mapDispatchToPropsを定義していないところです。特に再利用するものでもないですし、直接書いたほうが読みやすいと思います。

### mapSteteToProps
connectの第一引数、即ちmapStateToPropsは、stateを引数に取り、Objectを返すただの関数です。
これは、stateをDestructuringしてアロー関数にしてconnectに直接渡してあげればシンプルに書けるということですね。

### mapDispatchToProps
これはややこしいです。そもそも `bindActionCreators`はどこに行ったのでしょうか。
`bindActionCreators` の役割は、Store#dispatchで関数をラップすることです。簡易的に書くと、以下のようなobjectを返してくれます。

```js
{
  actionCreatorA: () => {
    dispatch(actionCreatorA())
  },
  actionCreatorB: (foo) => {
    dispatch(actionCreatorB(foo))
  }
}
```

こうすることで、Store#dispatchを書かずに直接呼び出せるということです。

**実はconnect関数も同じことをやってくれます。** 正確に言うと、connect関数の第２引数は関数かobjectを取ることができて、オブジェクトが渡された場合はbindActionCreatorsと同じように、object内の各関数をdispatchでラップしてくれます。

この特性を利用すると、紹介したような書き方が実現できます。

```js
export default connect(
  state => ({
    todos: mySelector(state)
  }),
  {
    actionCreatorA,  // dipatchでラップされる
    actionCreatorB  // dispatchでラップされる
  }
)(MyComponent)
```

以上です。
おかしなところがあればご指摘いただければと思いますmm
4日目　ニューラルネットワークをChainerに変換しながら学ぶ（その2）

今回は前回つくったニューラルネットワークを、Chainerに変換していきます。
今回もお世話になったのは、この[ページ](https://orizuru.io/blog/machine-learning/deeplearning_chainer-01/)です。ありがとうございます。

#Chainer.Variableの導入

前日つくったNumpyのニューラルネットワークのうち、重み付けのWの微分計算をする部分をVariableでつくります。
このとき、関数はFunctionをつかって定義します。

Variable：データを取り扱う部分。関数である変数。
Function：Variableを変数として扱う関数。

Functionを用いるときは、データ（変数）を必ずVariableとして定義する必要がある。

ここで、Variableを使うことによって、誤差逆伝搬の式がbackwordを使うだけですむ、というのが特徴かと思いました。

それぞれ比べます。

Numpy記述

```
x = X
y = Y

w1 = W1
w2 = W2
```

Chainer記述

```
x = Variable(X)
y = Variable(Y)
 
w1 = Variable(W1)
w2 = Variable(W2)
```
np.random.randnで定義した変数をVariableの変数としてセットします。

次に順方向計算です。

Numply記述

```
h = x.dot(w1)
h_r = np.maximum(h, 0)
y_p = h_r.dot(w2)
 
```
Chainer記述

```
h = F.matmul(x, w1)
h_r = F.relu(h)
y_p = F.matmul(h_r, w2)
```
内積のdotがmatmulになります。
np,maxmum(h,0)としていたLeRUがleruそのままとなって、記述がはっきりしました。

### 2乗の差分のルートである、誤差計算

Numpy記述

```
loss = np.square(y_p - y).sum() / y_size
print(loss)
```

Chainer記述

```
loss = F.mean_squared_error(y_p, y)
print(loss.data)
```
単純に、mean_squared_errorとなりました。
記述そのままです。


### 重みの微分計算

Numpy記述

```
grad_y_p = 2.0 * (y_p - y) / y_size
grad_w2 = h_r.T.dot(grad_y_p)
 
grad_h_r = grad_y_p.dot(w2.T)
grad_h = grad_h_r
grad_h[h < 0] = 0
grad_w1 = x.T.dot(grad_h)
```

Chainer記述

```
w1.zerograd()
w2.zerograd()
 
loss.backward()
```
こんなに記述が簡単になるのは、びっくりです。
3行ですみますので。

微分値より重み付けを更新するのは同じです。

では、全体の記述になります。

```nm_train6.py
# -*- coding: utf-8 -*-

import numpy as np
import chainer.functions as F
from chainer import Variable

EPOCHS = 300
M = 2
N_I = 3
N_H = 2
N_O = 3
LEARNING_RATE = 1.0e-04


np.random.seed(1)

X = np.random.randn(M, N_I).astype(np.float32)
Y = np.random.randn(M, N_O).astype(np.float32)
W1 = np.random.randn(N_I, N_H).astype(np.float32)
W2 = np.random.randn(N_H, N_O).astype(np.float32)


def sample_2():

    x = Variable(X)
    y = Variable(Y)

    w1 = Variable(W1)
    w2 = Variable(W2)

    for t in range(EPOCHS):

        h = F.matmul(x, w1)
        h_r = F.relu(h)
        y_p = F.matmul(h_r, w2)

        loss = F.mean_squared_error(y_p, y)
        print(loss.data)

        w1.zerograd()
        w2.zerograd()

        loss.backward()

        w1.data -= LEARNING_RATE * w1.grad
        w2.data -= LEARNING_RATE * w2.grad


if __name__ == '__main__':
    sample_2()
```

300回計算させた結果、
lossが1.417から1.095まで減少したのを確認しました。

コード自体もシンプルになりましたし、また直接コードの表記から意味がわかります。
Numpyで作るとなると、式そのものを記述するため、それを導出する必要があります。
Chainerが直感的と言われる所以をしりました。

次は、Function,Variableだけでなく、ChainやOptimizerを使って記述してみます。
UWP開発で Project ... is not compatible with uap10.0 (UAP,Version=v10.0.XXXXX). Project ... supports: uap10.0.10586 (UAP,Version=v10.0.YYYYY)

って出たときの解決方法
# 解決方法
プロジェクトの設定→アプリケーション→最小バージョンを、参照しているプロジェクト間で一致させる。

# 環境
VS15.7.4

# こんなメッセージ（検索用）
```
"Project RuntimeComponent1 is not compatible with uap10.0 (UAP,Version=v10.0). Project RuntimeComponent1 supports: uap10.0.10586 (UAP,Version=v10.0.10586)"
```

```
NU1201	プロジェクト Project は uap10.0.15063 (UAP,Version=v10.0.15063) と互換性がありません。 プロジェクト Project がサポートするもの: uap10.0.16299 (UAP,Version=v10.0.16299)				
```

# メモ
参照元が参照先よりターゲット最小バージョンが低いとこのパターンになるらしい。メッセージをよく読んで考えればああそうかってなるけど、パッと見ただけだとハマった。
[Blog OS]panic_implementation unknownの解決方法

# はじめに

ちょんぼでハマってしまったので、同じ過ちを他の人が繰り返さないための情報です。
Rustのツールチェーンが1ヶ月分古かったせいで、最新機能である`panic_implementation`がコンパイルできなかった、という内容です。

# Blog OS

[Writing an OS in Rust (Second Edition)](https://os.phil-opp.com/)

Rustで小さなOSを作るチュートリアルです。OSの名前がBlog OSです。
2nd Editionになっており、継続的にコンテンツが更新されています(2018年7月現在)。

こういうコンテンツがあるおかげで、私のような凡人でもRustでOS作ってみよう！となれるので、本当にありがたいです。

# 発生した問題

[A Freestanding Rust Binary](https://os.phil-opp.com/freestanding-rust-binary/)

最初のコンテンツ、ベアメタルでRustバイナリを作るチュートリアルです。
ここで、panic時のハンドラを実装します。

```rust
// in main.rs

use core::panic::PanicInfo;

/// This function is called on panic.
#[panic_implementation]
#[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! {
    loop {}
}
```

上記コードをnightly Rustでビルドしたところ、panic_implementationが`unstable`となるはずが、`unknown`のエラーが出力されました。
[A Freestanding Rust Binary](https://os.phil-opp.com/freestanding-rust-binary/)の記事が書かれたのが、2018年2月のようだったので(ページ最上部情報)、2018年5月のnightly Rustでビルドできないのはなんでだ？となりました。

# 調査

https://github.com/phil-opp/blog_os/pull/435/commits/4effb4d0f67a8b11b26ec542964fdf4b0df3560d

記事のBlameを辿ると、panic_implementationの部分は、2018年6月4日に修正が入っていました。
ムムっと思って、Rustのツールチェーンを更新したところ、無事、ビルドが通るようになりました。

```
$ rustup update
$ rustup override add nightly.
$ rustc --version
rustc 1.28.0-nightly (e3bf634e0 2018-06-28)
```

うろ覚えですが、ビルド通らなかった時は、1.27.0-nightlyだったはずです。
(エラーログ残してなかった。不覚…)

## panic_implementation

そもそもpanic_implementationとはなんぞや？となります。

https://users.rust-lang.org/t/psa-breaking-change-panic-fmt-language-item-removed-in-favor-of-panic-implementation/17875

これも、2018年6月4日に言及があり、

>  As of the **latest nightly** this language item has been removed in favor of the #[panic_implementation] attribute which offers a type checked way of declaring the behavior of panic!.

この時点で最新のnightly Rustにpanic_implementationが入ったであろうことが判明しました。

これは*breaking-change*であるため、これまでpanic_fmtで書かれていたcrateは修正が必要になる、とのことです。

現時点では、ベアメタルでRustを動作させる記事の多くがpanic_fmtを利用したコードサンプルになっていると思うので、今後、ベアメタルでRustを書く方は注意が必要です。
近い将来、panic_fmtが利用できなくなるはずです。

# おわりに

ということで、かなりしょうもないハマり方をしてしまいましたが、今後も使う機能のbreak-changeが学べたので良かったです。
皆様もお気をつけ下さい。
[HTML5]標準draggableについて

### HTML5のdraggable属性

html5の標準機能でDOMをドラッグ&ドロップできるのを初めて知りました。主要ブラウザでは既にサポートされているようです。

### HTMLサンプル

```HTML:html
<div draggable="true">draggable</div>
```
draggable="true"とするだけでその要素をドラッグできるようになります。
但し、一部のブラウザではこれだけでは機能しないようです。
有名なところでFireFoxでは動きません(恐らくMozillaの派生ブラウザも)。
FireFoxの場合、JavaScriptでondragstartイベントに登録する必要があります。

選択中のテキスト、href属性が指定されたa要素、src属性が指定されたimg要素は、デフォルトでdraggable=trueとなっています。

```HTML:ForFireFox
<div draggable="true" ondragstart="event.dataTransfer.setData('text', '今日も一日がんばるぞい')">
  今日も一日がんばるぞい
</div>
```

[ドラッグ操作](https://developer.mozilla.org/ja/docs/DragDrop/Drag_Operations)

### dataTransferとは？

> DataTransferオブジェクトは、ドラッグ＆ドロップ操作の実行中、ドラッグされているデータを保持するために使われます。データトランスファーは1つ以上の項目を保持し、それぞれの項目は1つ以上のデータ型を保持します。

連想配列のDTOです。キーとバリューをセットします。使用できるキーは決まりがあり、text、text/plain、text/htmlのどれかです。ですがブラウザによってバラバラです。例えば、FireFoxとChromは「myKey」とか任意の名前でできました。逆にIE11だとtext以外動きませんでした。
頭が真っ白の人にお送りする,JavaScriptを使用して経過時間表示

####setIntervalのみ使った完成図
```javascript
var i= 1;
var countup=function(){
 var x = i++;
 var count=document.getElementById(‘count’).innerHTML=Math.floor(x/60)+“分”+(x%60)+“秒経過“;
};
 setInterval(countup, 1000);
```



Webで検索をかけるとnew Dateを用いた経過表示や、ボタンを押したタイミングからカウントを開始するものがヒットしたが、setIntervalのみで分秒経過表示を記載しているサイトに巡り合わなかったので一筆。下記にはコード完成までにぶつかった壁の対処を順列。

#####疑問1　そもそもどうやってHTML上に表示させればいいのか
```javascript
var count = 0;
  var countup = function(){
    console.log(count++);
  } 
  setInterval(countup, 1000);
```
手持ちのコードは一秒毎にカウントした数値をconsoleに表示するもの。
とりあえずHTMLにdivタグとIdを記述して、document.getElementByIdにてIdを取得した後、var countとして変数に変えてみる。「要素の中身変更　js」でググって出てきた.innerHTMLを足すと以下のようになる。申し訳程度に数字だけ表示されるコードの完成である。

```javascript
var i= 0;
var countup=function(){
 var count=document.getElementById(‘count’).innerHTML=(i++);
}
setInterval(countup, 1000);
```

#####疑問1　そもそも分と秒をどう設定すればいいのか
```javascript
var x=i++ 
省略.innerHTML=x%60+"秒経過";
```
i++のまま弄るのは分かりづらいのでi++=xと変更。xのまま秒表示させると６０を超えてもカウントが続いてしまう。
そこで「x%60」。実際にグーグル検索で適当な数値を代入して気づいたのが、xが６０を越えるまでは割り切れない(=0.小数点となる)為、１〜５９までを表示してくれるのだ。

#####疑問2　if文を用いて秒を分に変えれば良いのでは
```javascript
if(x>60){
省略.innerHTML=(x%60)+"分";
};
```
一見問題なさそうに動くと思われたが、if文を抜けた後にsetIntervalによる処理が実行されていたことを見落とし、一秒毎に、１,２分と処理されてしまったのでアウト。一行で分秒表示させるコードを書く以外ではダメそうなので却下。

#####疑問３　分をどう表示すればいいのか
```javascript
省略.innerHTML=(x/60)+"分";
```
（文系脳）秒数から60を引いた数値にxを掛けた後に６０で割った数値を記述すればいいのだ・・・と試行錯誤を繰り返して期待結果にならない作業を延々と繰り返した後に閃いた答えがこれ。
xが６０を越えてからの計算処理にこだわらずに、秒数を６０で割れば分が出るという当たり前なことでした。
このままでは小数点まで表示されてしまうので

```javascript
=Math.floor(x/60)
```
Math.floorを使って小数点を省いて表示するとあら不思議。カウント60毎に無事「分」が表示されるようになりました。

######感想
タイマー表示なんか楽だろうとタカを括っていざコード記述に至ると、頭が真っ白、何から手をつければいいかすら思い浮かびませんでした。各問題点を理解した後、原因を分析ー原因を仮定ー仮定案を実行をループにしてコードを書く基本が身についたので、ヨシ。
以下参考リンク
[setIntervalとは](https://techacademy.jp/magazine/5537)
[経過時間（秒数）をリアルタイムに表示する方法](https://www.nishishi.com/javascript-tips/setinterval-passage.html)
[経過時間を表示する（1）](https://www.tagindex.com/javascript/time/timer1.html)
[経過時間の測定](http://park6.wakwak.com/~wmasa/prog/srclib/0003.htm)
[JavaScript【 Date 】４ ～ setIntervalでリアルタイム表示](http://www.recipi.jp/7445)
vgo requires Go 1.10 but VGOROOT is not a Go 1.10 source tree

# 環境
Go 1.10.3

# エラー
`vgo`を使おうとすると
`vgo requires Go 1.10 but VGOROOT is not a Go 1.10 source tree`
と表示される

# 原因
`vgo`はGoのバージョンが1.10かどうかを
`$GOROOT/api/go1.10.txt`
が存在するかで判断する

`go1.10.txt`は
パッケージには含まれないので (ソースからインストールすれば手に入る)
パッケージマネージャーを使ってGoをインストールした場合
`vgo`はファイルを見つけられずに
エラーになる

# 解決策
2通りある

- Goをソースからインストールする
- `$GOROOT/api/`に`go1.10.txt`を作る

私は後者で解決しました
`sudo touch $GOROOT/api/go1.10.txt`

`vgo`はファイルが存在するかではなく
`go version`の結果でGoのバージョンを判断するべきですね〜

# 参考
https://github.com/golang/go/issues/24773
Hyperで新しいタブを現在のディレクトリで開く方法

# Hyperだと、新しいタブを開くとホームディレクトリに戻ってしまう

最近は、流行りに乗ってHyperを使っています。
新しいタブを開く時、ホームディレクトリになってしまい、いちいちワーキングディレクトリを開くのがめんどくさいです。
今頃ですが、terminal.appのように新しいタブを現在のディレクトリで開けるようにします。

# Hyperで新しいタブを現在のディレクトリで開く方法

## Hypercwdを導入するだけ。

```js:.hyper.js
module.exports = {
  plugins: [
    'hypercwd'
  ]
}
```
`plugins`　に`hypercwd`を追加するだけ。

## Hyperを起動した時のディレクトリも設定できる

```js:.hyper.js
module.exports = {
  config: {
    hypercwd: {
      initialWorkingDirectory: '~/projects'
    }
  },
  plugins: [
    'hypercwd'
  ]
}
```
ちょっとした技術メモ(ソフトウェア編)

# git

- [Git submodule の基礎](https://qiita.com/sotarok/items/0d525e568a6088f6f6bb)

# VisualStudio2017

- TypeScript開発環境
    - http://takachan.hatenablog.com/entry/2018/03/09/002412
- 使用するnodejsのバージョン
    - https://stackoverflow.com/questions/43849585/update-node-version-in-visual-studio-2017

# VisualStudioCode

## Markdownファイルの改行方式設定

デフォルトのテキストエディタ設定で指定した改行処理方式がMarkdownファイルの設定で上書きされるため、
下記の設定を記述してMarkdownファイルでもwordwrapが働かないように設定する。

```json
"[markdown]": {
  "editor.wordWrap": "off"
}
```

# yum

Openshift関連で、インハウスyumサーバを立てる場合など。

- [yumリポジトリサーバの構築方法](https://qiita.com/hana_shin/items/f714376d041941320290)


# 仮想化技術

- [OpenShift Origin v3 on Kubernetes - Part2: Ubuntuにインストール](http://masato.github.io/2014/09/13/openshift-origin-3-on-kubernetes-on-ubuntu/)

- [Docker（コンテナ型仮想化）と Kubernetes についての簡単な紹介](https://ubiteku.oinker.me/2017/02/21/docker-and-kubernetes-intro/#what-is-kubernetes)
    - OpenShiftOriginV3の基礎技術であるKubernetesについてわかりやすい解説

# Openshift Origin

[Github](https://github.com/openshift/origin/releases/tag/v3.7.1)からバイナリファイル`openshift-origin-server-v3.7.1-ab0f056-linux-64bit.tar.gz`を取得し、インストールを行う。

## Ansible

- [openshift-ansble - github](https://github.com/openshift/openshift-ansible)

# Docker

- [効率的に安全な Dockerfile を作るには](https://qiita.com/pottava/items/452bf80e334bc1fee69a)

# VMWare

- [今どきVMwareでゲストOSを入れたら、VMware Toolsじゃくてopen-vm-toolsらしい。](https://qiita.com/y_minowa/items/8032a80b02432db0f5c2)
    - VMWareにUbuntu17.10を入れたら同様のメッセージが出たのでメモ。
C#でFirebase - 匿名認証編

皆さんこんにちは。

私はよくスマホのアプリを作るときにFirebaseを利用するのですが
今回久しぶりにWindowsのデスクトップアプリを作る機会を頂いたので
WindowsアプリでFirebaseを使う手順を共有したいと思います。

#環境
この記事を書くにあたり利用した環境は以下です。
Windows10
Visual Studio Community 2017 Version 15.7.2
プロジェクトはC#のWPFアプリで作成しました。
.NET Framework 4.6.1

#Firebaseの準備
まずは↓のURLからFirebaseコンソールにログインします。
https://console.firebase.google.com

1. プロジェクト名を入力してプロジェクトを作成します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/151376/76e79232-b2e5-1bbd-cd3f-cdc698097340.png" width="320">

2. 次に「ウェブアプリにFirebaseを追加」をクリックします。
<img src="https://qiita-image-store.s3.amazonaws.com/0/151376/05cc5340-5f72-1b33-abe1-edb5c43f60f1.png" width="320">
その時に表示される**apiKey**をコピーしておいてください。
後で利用します。

3. 次にFirebaseで匿名認証を有効にします。
<img src="https://qiita-image-store.s3.amazonaws.com/0/151376/0c8adb4f-c40b-2f09-67a6-3899e849f0a8.png" width="320">
Authenticationで**匿名認証**を有効にして保存してください。

以上でFirebase側の設定は完了です。

#WPFアプリの準備
1. WPFアプリを作成
2. NuGetパッケージマネージャーで**FirebaseAuthentication.net**をインストールする。
3. ↓のコードで匿名認証が行えます。
*FIREBASE_API_KEY*は、さきほどコピーした**apiKey**を入れてください。

```c#
    async Task Authenticate()
    {
      try
      {
        var authProvider = new FirebaseAuthProvider(new FirebaseConfig(FIREBASE_API_KEY));

        var auth = await authProvider.SignInAnonymouslyAsync();
      }
      catch(FirebaseAuthException ex)
      {
        Console.Error.WriteLine(ex.Message);
      }
    }
```

以上です。
実行してみるとFirebaseのAuthenticationのユーザーに追加されているのが確認できると思います。
Rails チュートリアル メモ 第13章

# メモ

## 14.1.1 データモデルの設計

* 関係性を表現するために、1つのテーブルを用意する。
* テーブルには follower_id と followed_id というカラムがある。
* 「ユーザー 1 がユーザー 2 をフォローする」とは、このテーブルに「follower_id: 1, followed_id: 2」というカラムが1行追加される、ということである。

という設計。シンプルで素晴らしい。

## 14.1.2 やりたいこと

* Relationship のインスタンスを r とすると
    * r.follower で、フォロー元のユーザーの id を返す
    * r.followed で、フォロー先のユーザーの id を返す

* User のインスタンスを u とすると、
    * u.active_relationships.create（または build）すると、あらかじめ follower_id に u.id がセットされた状態で Relationship のインスタンスを保存（または 作成）する

上記における課題は、属性名とクラス名が異なる点。例えば Micropost の場合は、micropost.user というメソッドで、その micropost を所有する User を取得できた（属性名とクラスが一致している）。しかし、今回は r.follower というメソッドで、（Follower ではなく）User を取得できる必要がある。User 目線でも、u.active_relationships で（ActiveRelation ではなく）Relationships を扱える必要がある。

そこで、以下のような定義をする。

```ruby
class Relationship < ApplicationRecord
  belongs_to :follower, class_name: 'User'
end
```

* r.follower のように呼び出すけど、その follower の実体は User クラスだよ

といった設定をしている。同様に User 側についても、

```ruby
class User < ApplicationRecord
  has_many :active_relationships, {
             class_name: "Relationship",
             foreign_key: "follower_id",
             dependent: :destroy
           }
```

* user.active_relationships のように呼び出すけど、その実体は Relationship クラスだよ
* Relationship クラスの follower_id と外部キーで結びつくよ
    * 所有側で設定することに注意

といった設定をしている。

## 14.2.2 member

```
  resources :users do
    member do
      get :following, :followers
    end
  end
```

こんなルーティングを定義すると、/users/1/following/ のようなルートが有効になる。対応するアクションは users#following 。

## 14.2.5 Ajax

* form_for に remote: true オプションを追加することで、Ajax が使われるようになる
* コントローラ側で respond_to を使うと、要求されたフォーマットごとに何を返すかを決められる
    * 書式がわかりづらいので注意。case 文だと思ってしまうと楽
* 例えば user#show アクションの場合、フォーマットが html なら view/user/show.html.erb が描画に使われる。そのアナロジーで、フォーマットが js の場合は view/user/show.js.erb がブラウザで評価される。

それ以外のことはよくわからん・・・。

## 14.3.3 サブセレクト

適当にコードを書くと、

* フォローしているユーザー達の ID を取得するのに SELECT 1回
* それらの ID それぞれに対して microposts を取得するのに SELECT 1回

が発生してしまい、数が増えたときに重くなる。そこで、サブクエリを使って1回の問い合わせで済むようにする。

せっかく ActiveRecord がいろいろやってくれるのに、パフォーマンスを考えると結局 SQL 書かなきゃいけないのか・・・。
AWS 誤ってファイルを削除してしまったら・・

#####ファイル復元
１: 消してしまったファイル名を空のまま作成。
２: 空のファイルをダブルクリックで表示。
３： 上部メニュータブより「File」→「Show File Revision History」を選択。
４： 再生ボタンと共にファイルの変更内容が、最初から削除するまでの期間で表示されるので任意の位置で復元。
５: ファイル復元完了！！

*ファイルパスが指定されているファイルの場合は、フォルダも作成する必要有り。

参考サイト
https://community.c9.io/t/how-do-i-recover-a-deleted-file/17
【Bash】画像ファイルとかzipファイルとかが破損してるかチェックする

# 画像 (JPG, PNG, GIF, ...)

要: [Image magick](https://www.imagemagick.org/script/index.php)

```bash
identify foo.jpg >/dev/null 2>&1 && echo ok || echo error
```

# zip

```bash
zip -T foo.zip >/dev/null 2>&1 && echo ok || echo error
```

# JSON

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

```bash
jq '' foo.json >/dev/null 2>&1 && echo ok || echo error
```

# おわりに
他にもあればコメントしていただけると助かります。
Settingslogicの設定値を、テストの時だけ変更する

# やりたいこと

gem `settingslogic` で定義された設定値をテストの時だけ変えたい


# やりかた

２種類の方法があります。

## 方法１：test用のネームスペースに値を記述する

yamlにtest用のネームスペースがあると思いますので、そこに記述します。

```yaml
# config/application.yml
defaults: &defaults
  parent:
    child1: default_value1
    child2: default_value2
  awesome_setting: 800

development:
  <<: *defaults

test:
  <<: *defaults
  parent:
    child1: value1 # 特定のキーだけ上書き
    child2: value2

production:
  <<: *defaults
```

## 方法２：stub_const などrspecの機能を利用する

テストフレームワークにrspecを採用している場合、以下のテストコードでstubできます。

```rb
let(:fake_settings) do
  obj = double("Settings")
  allow(obj).to receive_message_chain(:parent, :child1).and_return('value1')
  allow(obj).to receive_message_chain(:parent, :child2).and_return('value2')
  obj
end

before do
  stub_const("Settings", fake_settings)
end
```

「方法１」とくらべ、柔軟に値を変更できるので、「設定値がAならこう、Bならこう」といったテストをしたい場合は、こちらの方法がおすすめです。

# 参考URL

* https://github.com/binarylogic/settingslogic
* https://relishapp.com/rspec/rspec-mocks/docs/working-with-legacy-code/message-chains
【Elixir】ディスプレイ下に置いてある付箋メモを残す


## 内容
　Elixir初心者の私が付箋に残したメモたちです。
　書籍「プログラミングElixir」や公式サイトを見ながら独学で勉強しています。そんな中で「あれ、これなんだっけ？」ってなることが多々ありました。一々調べるのが面倒だったのでディスプレイ下に付箋メモを残しておきました。ですが、鬱陶しくなったのでここに残しておきます。

<hr>
### 付箋たち
付箋１　拡張子
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
.ex 　⇒　バイトコードにコンパイルして実行
.exs　⇒　スクリプト実行（テストコードをコンパイルして実行する必要なし）
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

付箋２　Atomの宣言
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
「:」で始まる語　⇒　Atom
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

付箋３　文字のリストと文字列
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
シングルクォーテーションで囲む　⇒　文字のリスト
ダブルクォーテーションで囲む　　⇒　文字列
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

付箋４　プロセス
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
１度receiveすると、そのプロセスは終了する
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

付箋５　コレクション
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
{}　　⇒　タプル
[]　　⇒　リスト
%{} 　⇒　マップ
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

付箋６　実行
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
iex -S mix　⇒　インタラクティブモードに入る前にmixを実行
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

付箋７　「!」例外
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
functionA!()　⇒　エラー時に例外を発生させる
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

<hr>
Node.js基礎ーモジュールのエクスポート

# 初めに
Node.jsではrequireやimportな文法を使って既存のコードの入を行います。
そもそもなぜrequireだけで機能拡張実現できるのかはよく分からないので、今回はモジュールのインポートの流れを整理してみます。

# モジュールのインポートの例

先ず、**呼べれる関数**myfunction.jsを作成します：

```javascript
function MyFunction() {
    console.log('Hello World!');
}

module.exports = MyFunction;
```
 **呼ぶ側**も作成してみよう：

```javascript
var MyFunction = require('./myfunction');

MyFunction(); // Hello World!
```

##　要するに
モジュールのエクスポート：

```javascript
module.exports = variable_name;
```

モジュールのインポート：

```javascript
var foo = require('module_path');
```
# なぜ'module.exports'だけでできるの
それは、jsファイルがNodeにロードされる前に、Node側はあらかじめ*module*という変数を用意します。

```javascript
// module変数を用意
var module = {
    id: 'myfunction',
    exports: {}
};
var load = function (module) {
    // 元々のコード:
    function MyFunction() {
        console.log('Hello World!');
    }

    module.exports = MyFunction;
    return module.exports;
};
var exported = load(module);
// module保存
save(module, exported);
```
上記のように、Nodeは全てのエクスポートを記載している*module変数*を保管しているから、他のモジュールに導入の時に*module変数*をチェックすれば機能拡張を実現できます。

# 終わり
今回はモジュールのエクスポートの流れを整理してみまました。なんかDIっぽい気がします。
ちなみに、今回はCommonJSで整理しましたが、ES6標準に合わせるため、*require*ではなくて、*import*を使用した方がいいと思われます。
Xcodeで簡易トレース

WWDC 2018の[Advanced Debugging with Xcode and LLDB](https://developer.apple.com/videos/play/wwdc2018/412/)のセッションがとても良かったので、コマンドを作ってみた。

デバッグ時、ある関数を通ったかどうか知るためにNSLogとかprintとかを書いたりするが、リポジトリには入れたくないし、消すのが面倒である。
そこでLLDBのスクリプト機能を使って簡易トレースしてみた。
使い方は、

1. Xcode上で、トレースしたい関数にブレークポイントを貼る
2. アプリケーションの先頭 (application:didFinishLaunchingWithOptionsなど)にブレークポイントを貼る
3. 実行するとアプリケーションの先頭で止まる
4. LLDBコマンドプロンプトでtraceコマンドを実行
5. 実行を続行する

という感じ。トレースが不要になったらブレークポイントをすべて削除すればよい。

![demo.png](https://qiita-image-store.s3.amazonaws.com/0/20902/e522a6e8-b0fe-90c9-1308-6e1fba1e2581.png)

XcodeはデバッガとしてLLDBを使っている。LLDBは~/.lldbinitというファイルを用意しておくと、デバッグの起動時に読み込んでくれる。このファイル中は(Pythonではなく)LLDBのコマンドだけが実行できる。その中でPythonスクリプトを読み込むことができる。

```bash:.lldbinit
command script import ~/bin/lldbutils.py
```

スクリプトの中でコマンドや、コマンドで使うクラスを定義する。コマンドを追加するには、クラスを定義してもよいし、関数だけでも実装できる。(WWDCのセッションのサンプルだと、引数をきちんとパースしている)

```python:lldbutils.py
import lldb

class TraceCommand:
    def trace(self, target, debugger, result):
        for breakpoint in target.breakpoint_iter():
            debugger.HandleCommand("br command add -F lldbutils.show_function_name %d" % breakpoint.id)
        return None

    def get_short_help(self):
        return "Change all breakpoints into trace points."

    def get_long_help(self):
        return self.get_short_help()

    def __init__(self, debugger, unused):
        return

    def __call__(self, debugger, command, exe_ctx, result):
        self.trace(exe_ctx.target, debugger, result)

def show_function_name(frame, bp_loc, dict):
    thread = frame.GetThread()
    debugger = thread.GetProcess().GetTarget().GetDebugger()
    lineEntry = frame.GetLineEntry()
    options = lldb.SBExpressionOptions()
    reg = frame.EvaluateExpression("self", options)
    print('%s %s : %d' % (str(reg.GetValue() or ''), frame.GetFunctionName(), lineEntry.GetLine()))
    return False

def __lldb_init_module(debugger, dict):
    debugger.HandleCommand('command script add -c lldbutils.TraceCommand trace')
```

traceコマンドでは、全てのブレークポイントを列挙して、show_function_name関数を実行するようにしている。show_function_nameの中では関数名と行番号をprintする。ブレークポイントで呼び出された関数にてFalseを返すと、(コマンドプロンプトを表示せずに)実行を継続するという仕様になっている。(詳細はhelp br command addに書いてある)
ブレークしたときのコマンドやauto-continueなどの属性をPythonのオブジェクトで直接設定する方法がわからなかったので、デバッガ経由でコマンド実行して設定している。

微妙なのは、デバッガインスタンスはデバッグを開始したあとに作成される点である。どうやら、Xcode上で設定したブレークポイントはXcodeが管理していて、デバッグを開始した時点でLLDBに伝えるようになっているようだ。LLDBのコマンドプロンプトで設定したブレークポイントの情報はXcodeには伝わらず、実行を停止してからもう一度実行すると、Xcode上で設定したブレークポイントだけが設定される。
jQueryのfilterメソッド

要素の絞り込み行うためのメソッド

```html
<ul>
  <li class="asia">Japan</li>
  <li class="america">USA</li>
  <li class="europe">France</li>
</ul>
```

```js
 console.log($('li').filter('.asia').html());
```

以下のように表示

```
Japan
```

## 参考
[【jQuery入門】filterメソッドの使い方まとめ]
(https://www.sejuku.net/blog/32325)

[jQueryでセレクタで指定するのとfilter()で絞るの、どっちがいいか。]
(http://www.tinybeans.net/blog/2011/10/17-220954.html)