OmniAICreator/Qiita-1.07M huggingface dataset:
Pythonでのレコメンデーション実装についての備忘録

# はじめに

業務でレコメンデーションを使う必要があり、Pythonのレコメンデーションライブラリについて調査を行ったので備忘録としてまとめました。なお、ライブラリの簡単な紹介が主で、アルゴリズムの解説等については言及していませんので、そちらに関しては必要に応じて別資料を参照をお願いします。

レコメンド周りはこれまで扱ったことはなかったのですが、この辺りも、真剣に勉強しなければと切に感じる今日この頃です。。

# crab
HP: http://muricoca.github.io/crab/
GitHub: https://github.com/muricoca/crab

Pythonの協調フィルタリングの実装で最初に見つけたのがこのライブラリ。アイテムベースとユーザーベースの協調フィルタリングが計算できるとのことですが、GitHubのmasterの最終更新が4年前ということで、最近はあまり使われていないようです 。。他のライブラリの依存関係もあり、最近の環境ではうまく動きませんでした。

カンファレンスでの発表資料
http://conference.scipy.org/scipy2011/slides/caraciolo_crab_recommendation.pdf

# python-recsys
HP: http://ocelma.net/software/python-recsys/build/html/index.html
GitHub: https://github.com/ocelma/python-recsys

特異値分解と近傍アルゴリズムを使った協調フィルタリングが可能です。計算したモデルをファイルとして保存・再利用ができたり、評価に関してもメソッドが充実しているため、精度を追求するのでなければこちらが一番簡単に利用できる印象です。

ただし、近年の主流である Nonnegative Matrix Factorization (NMF) を使った手法には対応していないため、そちらを使いたい場合は下記のninfaを使って実装する必要があるかと思います。

ちなみに、私は今回アイテム同士の類似度の算出も必要だったため、こちらを採用しました。

# nimfa
HP: http://nimfa.biolab.si
GitHub: https://github.com/marinkaz/nimfa

近年の流行りであるNMF を使った手法は、レコメンデーションのライブラリとしては存在しないようですが、実装において肝になる行列の演算はライブラリとして提供されているので、こちらを使うことでそれほど困難なく実装は実現できそうです。実装アルゴリズムはかなり豊富で、Factorizationの実装だけでも10種類以上ありました。違いが。。 (ry

**NMFに関する参考資料**
[Matrix Factorization Techniques for Recommender Systems]
(http://www2.research.att.com/~volinsky/papers/ieeecomputer.pdf)
[非負値行列因子分解 NMF の基礎とデータ／信号解析への応用]
(http://www.kecl.ntt.co.jp/icl/signal/sawada/mypaper/829-833_9_02.pdf)
[Non-negative Matrix Factorization（非負値行列因子分解）]
(http://d.hatena.ne.jp/a_bicky/20100325/1269479839)

# Spark + MLlib

[MLlib - Collaborative Filtering](
http://spark.apache.org/docs/latest/mllib-collaborative-filtering.html)

Spark + MLlib にもレコーメンデーションの実装はあるので、スケールアップで対応できない量のデータを分散処理をする場合はこちらを使うのがよいと思います。なお、MLlibでは Alternate Least Square という手法を使ってMatrix Factorizationが実装されており、PythonのAPIも提供されています。

**参考資料**
[Spark and Matrix Factorization]
(http://stanford.edu/~rezab/slides/reza_codeneuro.pdf)

[Spark の MLlib を使った Dataproc でのレコメンドシステムの実装]
(http://qiita.com/kndt84/items/b975ac9e6552f5289ec9)

# まとめ

Pythonでレコメンデーションを実装する場合、手軽に利用したいたいということであれば、python-recsysを使うのが一番手っ取り早いかと思います。ただし、最近の流行りであるNMFには対応していないので、NMFを使いたい場合は、nimfaを使うことで実装するのがよいかと思います。

また、スケールアップで対応できない量のデータを扱う場合は、Spark + MLlibにレコーメンデーションの実装があり、PythonのAPIも提供されているので、こちらを使うのがよいと思います。こちらに関しては、別途検証を行っていますので、また別記事で紹介予定です。
YOU'RE NOT AUTHORIZED TO LOG ON THE STORE


同一アカウントでもう一台のpepperにログイン後
ストアにアクセスするとこの画面に。

アカウントを新しく作成してから同様にストアを開きましたが、同じくこの画面からログインする事が出来ず。

初期化する方法がChoregraphの2.3で提供されていますが、
最新のNaoqiが入手出来ないと初期化出来ないのか
初期化は現在出来ていない。

設定にて登録してあるアカウントは
Ｗｅｂサイトからアクセスするとログイン出来、
ストアでソフトウェアをダウンロードする選択までは可能。

しかしアプリケーションはダウンロードされず。
Ｐｅｐｐｅｒ本体にキャッシュが残っている可能性を調べる予定。

![IMG_5939.png](https://qiita-image-store.s3.amazonaws.com/0/58501/6c411ddf-cb9f-0631-98c7-0d78f65c8870.png "IMG_5939.png")
docker-composeで複数のコンテナをyamlファイルで管理し、最後にcowsayする

docker-composeで複数のコンテナをyamlファイルで管理、最後にcowsayします。

## <i class="fa fa-cloud-download" style="font-size:1em;"></i> インストール
```bash
$ curl -L https://github.com/docker/compose/releases/download/1.3.2/docker-compose-`uname -s`-`uname -m` > docker-compose
$ sudo cp docker-compose /usr/local/bin/
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose -v
docker-compose version: 1.3.2
CPython version: 2.7.9
OpenSSL version: OpenSSL 1.0.1e 11 Feb 2013
```

## <i class="fa fa-file-text" style="font-size:1em;"></i> docker-compose.yml
```yaml
cowsay:
  build: ./cowsay
  command: cowsay hoge
figlet:
  build: ./figlet
  command: figlet hoge
```

## <i class="fa fa-cube" style="font-size:1em;"></i> cowsay/Dockerfile 
```
FROM ubuntu:trusty
MAINTAINER tbpgr <tbpgr@tbpgr.jp>
RUN apt-get update
RUN apt-get install cowsay
```

## <i class="fa fa-cube" style="font-size:1em;"></i> figlet/Dockerfile 
```
FROM ubuntu:trusty
MAINTAINER tbpgr <tbpgr@tbpgr.jp>
RUN apt-get update
RUN apt-get install figlet
```

## <i class="fa fa-child" style="font-size:1em;"></i> docker-compose で一括build
```bash
$ docker-compose build
$ docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
testdockercompose_figlet   latest              154d5860affc        26 seconds ago      211.2 MB
testdockercompose_cowsay   latest              8766e33b7dd5        30 seconds ago      210.5 MB
```

## <i class="fa fa-child" style="font-size:1em;"></i> docker-compose で実行
```bash
$ docker-compose run cowsay
 ______
< hoge >
 ------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

```

## <i class="fa fa-book" style="font-size:1em;"></i> 外部資料
* <i class="fa fa-external-link" style="font-size:1em;"></i> [docker/compose - GitHub](https://github.com/docker/compose)
* <i class="fa fa-external-link" style="font-size:1em;"></i> [docker/compose - Docs](http://docs.docker.com/compose/)
* <i class="fa fa-external-link" style="font-size:1em;"></i> [Dockerのキホンその２ Docker Compose Swarm Machine 利用編](http://www.slideshare.net/ngzm/so-50778247)
WerckerでRailsのCIを回す

# Werkerとは

CIサービスはいろいろとあるんですが、BitbucketのPrivateリポジトリで無料でCIを回したくてWerckerを使ってみることにしました。

- http://blog.wercker.com/

ymlに設定を書くんですが、書き方がちょっと前に変わったらしく、調べても古い情報と新しい情報が混在していてなかなかに苦戦したのでメモ程度ですが書き残しておきます。

# 最終的な動作環境

早速ですがまず最終的な設定を晒しておきます。
今回使ったデータベースはMySQLです。

## 設定ファイル

以下の設定で動きました。（mysqlの環境変数は適当です）

```
box: phusion/passenger-ruby22
services:
  - id: mysql
    env:
      MYSQL_ROOT_PASSWORD: root_password
      MYSQL_USER: test_user
      MYSQL_PASSWORD: test_password
      MYSQL_DATABASE: test_database
build:
  steps:
    - bundle-install
    - rails-database-yml
    - script:
        name: rspec
        code: bundle exec rspec
```

## 環境変数

Werckerでは、Applicationの設定から環境変数を設定出来ます。
僕の環境でCIを回すにあたって必要だった環境変数は以下のみでした。

```
WERCKER_BUNDLE_INSTALL_WITHOUT: development production
```

`bundle install` に `--without development production` を付けるための環境変数です。

必要かどうかはprojectで使っているgemによりますが、僕の場合 development,production では sql-server を使い、test では mysql を使いたかったため、 sql-server関連のgemを避けないとfailするという問題があったため必要でした。

基本的なプロジェクトでは必要ないと思います。

ちなみにソースは以下の部分です

- https://github.com/wercker/step-bundle-install/blob/master/run.sh#L15

# 設定ファイルの項目について

## box

Rubyのdockerイメージを選択します。
これはwerckerのREADMEで使われているものをそのまま使用しました。

- http://devcenter.wercker.com/quickstarts/building/ruby.html

## service

データベースを使う場合、serviceにデータベース用のdockerイメージを選択します。
また、データベースの設定はenvオプションに書きます。

- MYSQL_ROOT_PASSWORD
    - mysqlのrootユーザのpasswordです。コンテナを作る際に必要です。
- MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE
    - `rails-database-yml`のstepでテスト用のdatabase.ymlを作る際に必要です。以下ソースです。
        - https://github.com/wercker/step-rails-database-yml/blob/master/run.sh

## bundle-install

railsプロジェクトの依存ライブラリのインストールします。普通の`bundle install`です。

## rails-database-yml

serviceで設定したenvを元にdatabase.ymlを生成します。
これがないとmysqlに接続出来なくてfailします。

## rspec

最後に、scriptでrspecを実行します。

# 上記の設定で失敗する場合

上の設定で何度か成功したのですが、急にmysqlに接続できなくなってfailするようになりました。
以下の設定を`bundle-install`の前に入れることで動くようになりました。

```
- script:
  name: delete docker images cache
  code: |
    rm -rf $WERCKER_CACHE_DIR
```

詳細分かりませんが、キャッシュが悪さをしていたようです。
Packer buildでDocker HubにDocker Imageを保存するやいなやpullしてcowsayする

Packer buildでDocker HubにDocker Imageを保存するやいなやpullしてcowsayします
## <i class="fa fa-flask" style="font-size:1em;"></i> サンプル
### <i class="fa fa-file-text" style="font-size:1em;"></i> 仕様
Base Image: [ubuntu:trusty - Docker Hub](https://hub.docker.com/_/ubuntu/)

### <i class="fa fa-download" style="font-size:1em;"></i> Base Imageをpullする

```bash
$ docker pull ubuntu:trusty
```
### <i class="fa fa-file-text" style="font-size:1em;"></i> template.json
```bash
{
    "builders":[{
        "type": "docker",
        "image": "ubuntu:trusty",
        "commit": true
    }],

    "provisioners":[
    {
        "type": "shell",
        "inline": [
            "apt-get -y update",
            "apt-get install -y cowsay"
        ]
    }
    ],

    "post-processors": [
        [
            {
                "type": "docker-tag",
                "repository": "tbpgr/cowsay",
                "tag": "0.0.1"
            },
            "docker-push"
        ]
    ]
}
```

### <i class="fa fa-cloud-upload" style="font-size:1em;"></i> Packer buildでDocker HubにImageをpush
```bash
$ packer build template.json
```

### <i class="fa fa-desktop" style="font-size:1em;"></i> pushされたImageをDocker Hub上で確認
![packer_docker1.png](https://qiita-image-store.s3.amazonaws.com/0/43480/723eb0f8-6391-0567-3116-c7b85074be29.png)

### <i class="fa fa-search-plus" style="font-size:1em;"></i> Docker Hubに保存したImageを検索します
```bash
$ docker search tbpgr/cowsay
NAME            DESCRIPTION   STARS     OFFICIAL   AUTOMATED
tbpgr/cowsay                 0   
```

### <i class="fa fa-trash" style="font-size:1em;"></i> ローカル環境のDocker Imageを一度削除します
pullの検証をするため、Docker Imageを1回削除します

```bash
$ docker rmi tbpgr/cowsay:0.0.1
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
```

### <i class="fa fa-cloud-download" style="font-size:1em;"></i> Docker Hubに保存したImageをpullします
```bash
$ docker pull tbpgr/cowsay:0.0.1
0.0.1: Pulling from tbpgr/cowsay
# 中略
Status: Downloaded newer image for tbpgr/cowsay:0.0.1
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
tbpgr/cowsay       0.0.1               8cb354c0a903        12 minutes ago      210.5 MB
```

### <i class="fa fa-child" style="font-size:1em;"></i> Docker Hubから取得した自作Docker Imageを実行します
```bash
$ docker run -i -t tbpgr/cowsay:0.0.1 /usr/games/cowsay hoge ______
< hoge >
 ------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
```
bashで始めるEmacsキーバインド


#動機

+ 一流のエンジニアはvi(m)もemacsも使えるような気がする
+ Emacsを使ってLispを勉強したい
+ 思い切ってviキーバインドを封印したいが、仕事の効率が落ちるためできない
+ bashでemacsのキーバインドを使い始めたら結構いい感じ

#Emacsのキーバインドが使えるところ
MacOSでは標準でEmacsライクなキーバインドがされていて、いろんなアプリケーションで使用できますし、
Windowsであれば[keyhac](https://sites.google.com/site/craftware/keyhac "keyhac")というツールとこの[スクリプト](http://www49.atwiki.jp/ntemacs/pages/25.html "スクリプト")を使うことで簡単にEmacsライクなキーバインドに変更することができます。
また大抵の高性能EditorやIDEにはプラグインでEmacsのキーバインドを使用できます。

以降、emacsのキーバインドをを学ぶのになぜbashが始めやすいのかを説明していきたいます。

#bashで始めるのかなぜか？

##1. 覚えやすいキーバインドしか必要としない
emacsでは`<C-x><C-c>`や`<C-x>k`などキーを複合させて使いうことが多いです。
Undo、Redo、切り取り、バッファのセーブ、バッファを閉じるなどの基本的なコマンドも複合キーによって実行され、
そう簡単には実行させてもらえません。
Emacsのテキスト入力系のキーバインドはが単一キーが多く使用されているので、比較的覚えやすいです。

##2. bashの標準のキーバインドがemacsのキーバインド
Emacsのキーバインドを学びたいと思ったらEmacsエディタを使うかOSなりEditorなりのキーバインドを変更しなければいけませんが、bashでは設定が必要ありません。

##3.　キーバインドを覚えていなくてもたいして困ることがない
１．でも述べたようにEmacsのキーバインドで基本的な操作が複合キーになっていて少し覚えにくいです。
今までbashの標準のキーバインドがemacsのそれと知らずに使っていたとしても困ったことはあまりないはずです。


#３つのキーを封印する
Emacsキーバインドに慣れるには以下のキーを封印しましょう。

##1. 矢印キーを封印
思いの外すぐに慣れます。

- ctrl+f １文字右に移動
- ctrl+b １行下に移動
- ctrl+n １行上に移動
- ctrl+p １行下に移動
- ctrl+a 行頭に移動
- ctrl+e 行末に移動

##2. Enterキーを封印
慣れるとEnterがずいぶん遠く感じます。

- ctrl+m Enterキーと同じ
- ctrl+j Enterキーと同じ

##3. Deleteキーを封印
結構意識していないと、いつのまにか薬指がDeleteボタンにいっています。

- ctrl+h 一文字前を削除
- ctrl+d 一文字後ろを削除
- ctrl+u カーソルから行頭まで削除
- ctrl+k カーソルから行末まで削除

#まとめ
慣れないエディタで作業しようと思ったら初期コストがかかります。しかしそれは一気に学ぼうとするからで、
重要な事はできるだけ負荷を分散させることかなと思います。

ついつい封印したキーを押しそうになりますが押さないように努力しましょう。
初めの方は多少イライラしますが、少しするとゲーム感覚でできるようにります。

私はEmacsは冒頭でも述べた通り数時間しか触っていませんが、Emacsのキーバインドはなかなか楽しいです。

#謝辞
最後まで読んでいただき、誠にありがとうございます。
Brunchでフロントエンド開発

知人からgulpでもなくgruntでもなく、Brunchが良いといわれ、ならばどのようなビルドツールなのか気になって調べてみた。

# Brunch
* github - https://github.com/brunch/brunch
* 公式サイト - http://brunch.io/

初コミットは2011年9月のよう。実はGruntと同じころに開発がスタートしている。

> Brunch is an ultra-fast HTML5 build tool


超高速html5ビルドツールとのこと。
GruntやGulpよりもビルドが早いそうだ。

## 特徴
* 変更があったファイルのみをビルドしてくれる
* bowerとの連携が良い
* BrunchだけでliveReloadしてくれる
* 設定ファイルが書きやすい
* http://brunch.io/examples.html をみてみると、ゲーム開発などでも選ばれているよう

### Skelton
「Skelton」も特徴の一つのようで、

```
# Example from a full URL
brunch new https://github.com/scotch/angular-brunch-seed
```
↑こういったコマンドを打つだけで、yeomanのようにプロジェクトの雛形のアプリケーションテンプレートを作成してくれるそうだ。

* Skelton一覧 - http://brunch.io/skeletons.html
        
 　

まあさわってみないと何も分からないので、
https://github.com/yhikishima/Brunch-env
ここで開発してみたいと思う。
　
随時内容を更新していきたい。
[短文メモ]matplotlibで、showしても何も表示されない→backend設定を確認

backendがGUIのものになっていない可能性がある。

```python:
import matplotlib as mpl
mpl.use('tkagg')
```
を、import matplotlib.pyplot`よりも先に評価する(上の行に書く)。

**`ImportError: No module named backend_tkagg.py`と表示される場合:**
バックエンドがインストールされていないっぽい。apt-getなりyumなりでインストールが必要。
SUSEの場合は、
`sudo zypper in python-matplotlib-tk` (Python3の場合は python3-matplotlib-tk)

**できるようになったけど毎回これやるの面倒**
matplotlibrcファイルに記述する。

```text:~/.config/matplotlib/matplotlibrc
backend : tkagg
```

Linuxの場合は、`.config/matplotlib/matplotlibrc`
その他のプラットホームでは、`.matplotlib/matplotlibrc`
分からなければ

```py:
import matplotlib as mpl
print(mpl.get_configdir() + '/matplotlibrc')
```



#参考
http://python.dogrow.net/?p=186
http://matplotlib.org/users/customizing.html
Python基礎学習

#print文，四則演算，list，tuple

とりあえず恒例の（？）"Helo world"から

```py:print()
x="Helo world"
print x
```

Python2とPython3は何か違うらしく，Python3では括弧をつける必要があるようだ．

```py3:print()
x="Helo world"
print(x)
```

```py3:四則演算
x = 3 + 1
print(x)

y = 8 - 3
print(y)

i = x * y
print(i)

j = i / 2
print(j)
```

```py3:実行結果
4
5
20
10.0
```

リスト型はシーケンス型の一つ．複数の要素から構成され，要素が順に並んでいるもの．
listは配列のようなものなのかな？

```py3:list
list_a = ['aaa', 'bbb', 'ccc', 'ddd']
list_b = ['1', '3', '4', '2']
print(list_a)
print(list_b)

print(list_a[2])
print(list_b[1])
```

```py3:実行結果
['aaa', 'bbb', 'ccc', 'ddd']
['1', '3', '4', '2']
ccc
3
```

タプル型もシーケンス型の一つで，リスト型との違いは要素の書き換えができないこと．

```py3:tuple
tuple_a = ('aaa', 'bbb', 'ccc', 'ddd')
tuple_b = ('1', '3', '4', '2')
print(tuple_a)
print(tuple_b)

print(tuple_a[2])
print(tuple_b[1])
```

```py3:実行結果
['aaa', 'bbb', 'ccc', 'ddd']
['1', '3', '4', '2']
ccc
3
```

#条件分岐　if文
```py3:if文
#input():キーボードからの入力を受け付ける．入力は文字型．
#int():（）内を整数型にする．

x = int(input("入力："))
if x == 0:
  print("false!")
elif x == 1:
  print("true!")
else:
  print("nill")
```

```py3:実行結果
入力：1
true!

入力：0
false!

入力：5
nill
```

#繰り返し文　for文，while文
```py3:for文
list_a = ["taro", "tomo", "msds", "kumi"]
for i in list_a:
  print(i)
```


```py3:実行結果
taro
tomo
msds
kumi
```

```py3:while文
i = 0
while i < 10:
  print(i)
  i += 1 
```


```py3:実行結果
0
1
2
3
4
5
6
7
8
9
```

#関数の定義
```py3:関数
#funcは関数名
#defの中のxは引数
#return xは返り値
def func(x):
  x += 5
  return x

x = func(2)
print(x)
```

```py3:実行結果
7
```

#モジュールの使い方
モジュールは関数や変数をひとまとめにしたもの．
必要な関数を使うには，その関数が所属しているモジュールをimportする必要がある．
試しに，時間を扱うモジュールである”time”を使ってみる．

```py3:関数の使い方
import time
print(time.asctime())
```

```py3:実行結果
Thu Sep 10 00:31:51 2015
```
Swiftの関数名と外部引数名の付け方メモ


Swiftの関数名（メソッド名）ってどうやってつけてますか？　と聞かれた時に話したメモ。ふたりとも同じようにつけていたので、おそらく無難な付け方。

以下はSwift 1.2を対象として **関数** で説明しています。


**メソッド（クラス内の関数）とinit（イニシャライザ）では `#` の使い方が異なりますのでご注意ください。**

内部引数名を外部引数名にも使う場合、メソッドなら第一引数に`#`を付けます（第二引数以降は自動で使われる）。
initなら`#`は全て不要となります（全て自動で使われる）。



関数名だけで機能を説明する
----------------------

**OK**

```swift
func setSize(size: CGSize) {
}
setSize(size)
```

**NG**

```swift
// 関数名 + 外部引数名で機能がわかるような付け方はしない
func set(#size: CGSize) {
}
set(size: size)
```


追加要素には外部引数名をつける
-------------------------

**OK**

```swift
func setSize(size: CGSize, #animated: Bool) {
}
setSize(size, animated: true)
```



関数名と引数が1対1で対応しない場合、外部引数名を使用する
----------------------------------------------

**OK**

```swift
func setSize(#width: CGFloat, #height: CGFloat) {
}
setSize(width: 640, height: 480)
```

**NG**

```swift
// 内部引数名で意図がわかるとしても、内部引数名だけにはしない
func setSize(width: CGFloat, height: CGFloat) {
}
setSize(800, 600)
```

**NG**

```swift
// Objective-Cっぽくしない
func setSizeWithWidth(width: CGFloat, #height: CGFloat) {
}
setSizeWithWidth(320, height: 240)
```

Swift 2では第一引数に `#` が使えないらしいとか、Objective-Cっぽい名前を目指している？　といった情報がありました。
[第２回目の Swift 2 シンポジウムも沢山の学びが得られる良い会でした。](http://ez-net.jp/article/0F/43I55KdO/QYmgZh-oK5bh/)

こちらを読ませていただくと、上記の名前の付け方でいいか考えちゃいますね。とても参考になりました。
UIDatePickerから時分を取得する

時間と分をセットしたくてUIDatePickerから取得してみた。
NSDateFormatterで取得するのもいいけど、いっぺんにやりたかったので、NSDateComponentsを使ってみた。いつも思うけど、カレンダー周りはもう少しスッキリしてほしい。

```lang:datePicker
- (IBAction)datePicker_ValueChanged:(id)sender
{
    UIDatePicker *picker = ( UIDatePicker *)sender;

    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSUInteger flags;
    NSDateComponents *comps;
    
    flags = NSCalendarUnitHour | NSCalendarUnitMinute;
    comps = [calendar components:flags fromDate:picker.date];

    NSInteger hour = comps.hour;
    NSInteger minute = comps.minute;
    
    NSLog( @"%ld:%ld", hour, minute );
}
```
Panther: Fast Top-k Similarity Search on Large Networks読んだ

# KDD2015 Panther: Fast Top-k Similarity Search on Large Networks読んだ
## どんなもの？
ネットワーク上の類似ノードTop Kを高速に検索する手法を提案

## 先行研究と比べると？
300倍早くなった

## 技術や手法のキモはどこ？
- サンプリングで近似してやることで高速化した
- random pathという考え方に基づいている
	R回長さTのランダムウォークを行う。もし二つの接点が似ているなら同一のパスに出てくる確率が高くなるはず、というアイデア

## どうやって有効だと検証した？
- R,T,エラーのバウンド,信頼水準の関係を導出した
- マイクロブログと共著ネットワークで速度・精度を比較


## ref 
http://dl.acm.org/citation.cfm?id=2783258.2783267

## メモ
https://research.preferred.jp/2011/08/nearest_neighbor_search2011/
Efficient K-Nearest Neighbor Graph Construction for Generic Similarity Measuresとやってることは同じっぽい
AtomのPackageなどなど

# はじめに
GitHub製のAtomをインストールしたので、追加したPackageなどを残してみる。
全然使いこなしていないので、ほんの少しになりますが。。。

# フォント
いきなりPackageから離れますが、フォントについて見直してみました。

以前この[記事](http://ics-web.jp/lab/archives/7010)を見てから、コーディングの為のフォントを選ぶのもアリだなぁと思っていました。
初めは記事に書いてるSource Han Code JPを使用しようかと考えましたが、このフォントは半角全角の横幅比が2:3で違和感を感じたので、RictyDiminishedを使用する事にしました。

どちらも、「O(オー)/0(ゼロ)」や「I(大文字アイ)/l(小文字エル)/1(数字の一)」などの見間違えないように配慮されていていいですね。

- [Source Han Code JP](https://github.com/adobe-fonts/source-han-code-jp)

- [RictyDiminished](https://github.com/yascentur/RictyDiminished)

# install Package
## [japanese-wrap](https://atom.io/packages/japanese-wrap)
自動折り返しを使用する際に日本語を意識。
[Atom:1.2]標準で折り返しできるようになりました。このPackageを有効にしていると、折り返しがおかしくなります。無効またはアンインストールする必要があります。

## [show-ideographic-space](https://atom.io/packages/show-ideographic-space)
全角スペースの可視化。

## [highlight-selected](https://atom.io/packages/highlight-selected)
選択しているワードと同一ワードをハイライト表示。

## [highlight-column](https://atom.io/packages/highlight-column)
カーソル列の縦軸をハイライト表示。

## [highlight-line](https://atom.io/packages/highlight-line)
カーソル行のハイライト表示。

## [file-icons](https://atom.io/packages/file-icons)
アイコンがかわいい表示に。
目的のハッシュタグを含むツイートを取得する

[Player!](https://itunes.apple.com/jp/app/player!-your-sports-news-curator/id897872395)は、twitterに同時投稿した際に`#playerapp`がつきます。
そのため、どんな投稿がされているのかなというのが気になったときに、使えるもの書きました。

`gem install twitter'としてgemをインストール

```twitter.rb

require "twitter"

# Twitter APIによるリクエスト
client = Twitter::REST::Client.new do |config|
  config.consumer_key        = "CONSUMER_KEY"
  config.consumer_secret     = "CONSUMER_SECRET"
  config.access_token        = "ACCESS_TOKEN"
  config.access_token_secret = "ACCESS_TOKEN_SECRET"
end

# 取得するツイートの上限数
limit   = 10

# 欲しいハッシュタグのキーワード
tag = "playerapp"

# ここでツイートを取得
client.search("##{tag}", lang: 'ja', result_type: 'recent', count: 1).take(limit).map do |tweet|
  puts "#{tweet.user.name}: #{tweet.text}"
end
```



[Twitterで指定のusernameのツイートを取得する](http://qiita.com/abe-perorist/items/c598f6338060b7d04a61)ではなく、こっちが欲しかったやつでした


あと、TwitterのDocumentにサンプルが皆無で心底読みづらかったので、お気をつけください
SourceTreeでコミット間の差分ファイル一覧をテキストファイルに出力する方法

SourceTreeの「カスタムアクション」を使って、コミットの履歴から差分ファイルを抽出する方法は、以下のエントリーで紹介しました。

- [Git - SourceTreeでコミット間の差分ファイルを圧縮しないで取り出す方法 - Qiita](http://qiita.com/youthkee/items/8579c7a963c24bd4e655)

ただし、納品ファイルとして提出する際には、同時に差分のファイルリストを求められるケースも多いでしょう。

そこで、今回は同様にSourceTreeの「カスタムアクション」を使って、変更した差分ファイルの一覧を作成する方法を紹介します。
（下記の説明はMac OS 10.10.4での操作を前提としています）

# バッチファイルの作成

差分を表示するには [git diff](http://git-scm.com/docs/git-diff) コマンドを使いますが、以下のように `--name-status` オプションを付けると、変更されたファイルの名前とステータスだけを抽出することができます。

さらに、 `>` に続けてファイル名を指定することで、コマンドの表示結果をテキストファイルなどに書き出して保存することができます。

```list_diff.sh
#!/bin/sh
git diff --stat --name-status $2 $1 > filelist.txt
```

# カスタムアクションの登録

上記テキストファイルを `list_diff.sh` 等のファイル名で保存し、「指定された差分でファイルリスト作成」という名前でカスタムアクションとして登録しました。
（パラメータには `$SHA` を入力）

また、作成したシェルスクリプトに実行権限を追加しないと、カスタムアクションの実行時に「launch path not accessible」というエラーが発生してしまうので、ターミナルから以下のコマンドを実行しておきます。

```
chmod +x list_diff.sh
```

# カスタムアクションの実行

SourceTreeの「ログ表示」画面で、Commandキーを押しながら2つのリビジョンを選択し、右クリックから「カスタムアクション」→「指定された差分でファイルリスト作成」を実行します。

すると、プロジェクトのルートディレクトリに `filelist.txt` というファイルが作成され、変更されたファイル名とステータスの一覧が書き出されます。

# ファイルリストの加工・編集

`filelist.txt` に保存されたファイルリストの形式は、以下のような形になります。

```filelist.txt
M	common/img/img01.jpg
A	img/banner_a.png
D	index.html
```

M=変更ファイル、A=追加ファイル、D=削除ファイル、と覚えておけばいいでしょう。

このままだと、さすがにちょっと味気ないので、EXCELやCSVに加工して適宜編集して使用します。

置換やソート機能を使って加工すれば、好みに合わせて見やすいリストを作成できると思います。

`git diff` コマンドで書き出したファイルリストは、タブ区切りテキストになっているので、EXCEL等にコピー&ペーストする分にも問題ありません。

# 応用

こちらのカスタムアクションも、シェルスクリプトを書き換えることで様々な応用が可能です。

[前回](http://qiita.com/youthkee/items/8579c7a963c24bd4e655#%E3%81%BE%E3%81%A8%E3%82%81%E5%BF%9C%E7%94%A8)と同じように、gitの管理下にならない上階層にフォルダを作って、その都度日付名を付けてリストを保存するようにしたサンプルは以下になります。

他にもシェルスクリプトを使えば、プロジェクトごとにフォルダやファイル名を振り分けることなども可能なので、ニーズに応じて色々とアレンジしてみてください。

## 一階層上の/archive/ディレクトリに日付名でファイルリストを作って書き出す場合

```list_diff2.sh
#!/bin/sh
today=`date +"%Y%m%d"`
git diff --stat --name-status $2 $1 > ../archive/$today.txt
```
APIGatewayでIAM認証を使う


APIGatewayで定義したメソッドに対しIAMによる認証ができる。

IAMでの認証ってどういうことかというと、AWS SDKの内部で行っている署名をもって定義したメソッドのエンドポイントにリクエストを送ると他のサービスと同様にIAMユーザーで認証が行える。

つまりCognitoから振り出されたIAMなんかでAPIGatewayを使うことが出来る。
そのIAMで直接dynamodbもSNSも叩けるしAPIGateway使うケースあるのかな…？
 rubyでリクエストつくろうとしたら躓いたのでメモを残しておく


## IAMロールを作成

APIを叩く際、サービス名はapigatewayではなくexecute-apiである。利用するIAMのroleで`execute-api:Invoke`の権限が必要になる

```role
{
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:Invoke"
      ],
      "Resource": "arn:aws:execute-api:*:*:*"
    }
  ]
}
```

## メソッドを作成

対象のメソッドのMethod RequestでAuthrization type:AWS_IAMを指定。（✔を押さないと適用されない。APIGatewayのGUIはどうにも独特すぎて分かりにくい）
外から叩くのでDeploy APIで適当なステージにデプロイしておく

![Kobito.mp8wkq.png](https://qiita-image-store.s3.amazonaws.com/0/3181/a8bd2aa3-4233-5aaa-73fa-c2e0deee9b13.png "Kobito.mp8wkq.png")


## 署名したリクエストを作成
署名を作るの面倒くさいのでGEMを利用する。rubygemsで探すとaws4とaws4_signerの２つが見つかるがどちらもそのまま使おうとするとハマる。特にaws4はホスト名からサービス名を取り出して利用するのだが、APIGatewayのエンドポイントになるホスト名は他のサービスとルールが違うため正しい署名を作ることが出来ない。のでaws4_signerを使う。

```ruby
require "aws_signer"

signer = Aws4Signer.new(ENV["AWS_ACCESS_KEY_ID"], ENV["AWS_ACCESS_SECRET_KEY"], 'us-east-1', 'execute-api')

# GETの場合
uri = URI("https://xxxxxx.execute-api.us-east-1.amazonaws.com/xxxxx/resource")
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
  request = Net::HTTP::Get.new(uri,
    'Accept-Encoding'=>"identity" #identity or gzip
  )
  signer.sign_http_request(request)

  response = http.request(req)
  puts response.body
end
```


`Net::HTTP::Get` でリクエストを作る場合、デフォルトでリクエストヘッダに `accept-encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3` が設定される。
が、Accept-Encodingに`gzip`か`identity`の値が入っていると署名が一致せず認証エラーになる。S3などはデフォルトの値でも通ったのでAPIGatewayだけの仕様？情報求む。

## リクエスト時のIAMでLambdaを実行

通常、APIGatewayのメソッドに紐付けたLambdaFunctionはLambda側で設定されたロールで実行されるが、Integration Requestの`Invoke with caller credentials` にチェックを入れると、リクエスト時のIAMでLambdaを実行することができる。（lambdaの実行権限を持ってないと503になる）


![Kobito.AUjFlm.png](https://qiita-image-store.s3.amazonaws.com/0/3181/9057955c-b091-3751-88e9-e226f1bc6021.png "Kobito.AUjFlm.png")

ただしこの設定をするとコンソール画面からのテストが利用できなくなる

## 未来を感じる
IAMで認証できるしCognitoと外部OAuthプロバイダでがしがしユーザ発行できるのでログインが必要なAPIもこれでいけるかもしれないが死ぬほど面倒くさそう。

現状設定がやたら面倒くさいしコンソール使いにくいし動的にヘッダ吐きだせないしlambdaもデバッグしんどいしログ見難いし辛いことはいっぱいあるけどAPIGatewayでEC2にサヨナラを告げられるかもしれないので期待してる。


## 参考
* [署名バージョン 4 を使用して AWS リクエストに署名する](http://docs.aws.amazon.com/ja_jp/general/latest/gr/sigv4_signing.html)
* [API Gatewayへの入力値にLambdaからアクセスする](http://qiita.com/r7kamura/items/6420538789da95cd2f47)
Twitterで指定のusernameのツイートを取得する

`gem install twitter'としてgemをインストール


```twitter.rb
require "twitter"

client = Twitter::REST::Client.new do |config|
  config.consumer_key        = "CONSUMER_KEY" # ①
  config.consumer_secret     = "CONSUMER_SECRET" # ①
  config.access_token        = "ACCESS_TOKEN" # ①
  config.access_token_secret = "ACCESS_TOKEN_SECRET" # ①
end

client.user_timeline("②", { count: ③ } ).each do |timeline|
  tweet = client.status(timeline.id)
  puts tweet.created_at
  puts tweet.text
end
```

それぞれを説明すると、
① - Twitter Applicationを作り、取得した値を入れてください
② - 取得したいusername(@の後ろの箇所)を入れてください
③ - 取得したいツイートの数を入れてください

本当は、特定のハッシュタグのついた投稿を取得したかったのですが、なんかこっちが先に出来たので投稿
AppleSpecialEvent視聴方法

## AppleSpecialEventを夜更かしして見る方法まとめ

### apple公式サイト
http://www.apple.com/apple-events/september-2015/

※注意書きの通り、OSX10.8以降のMacまたは
iOS7以降のiPhoneのSafariでないと見れないそうです
![Apple Events - Special Event September 2015 - Apple.png](https://qiita-image-store.s3.amazonaws.com/0/91606/53de788a-6209-7cda-1f90-1315fb5797f0.png)

### macwebcaster
http://www.macwebcaster.com/
日本語の同時通訳が放送される予定です
![macwebcaster.com | Streaming Info & Keynote in Japanese.png](https://qiita-image-store.s3.amazonaws.com/0/91606/9243908f-4b3d-21cd-73b6-ff0085b2ed48.png)

macwebcasterさんのニコ生はこちら
http://live.nicovideo.jp/watch/lv234098395

### engadget
http://www.engadget.com/2015/09/08/apple-iphone-liveblog-teaser/
英語でのテキスト速報

### engadget日本版
http://japanese.engadget.com/2015/09/09/iphone-6s-6s-plus-9-9/
日本語でのテキスト速報

### 週刊アスキー（ニコ生）
http://live.nicovideo.jp/watch/lv233643058
※こちらは会場の映像と音声は放送されないようです





いよいよ後3時間ですね。発表まで待ち遠しいです！
Dockerコンテナ内のnet.core.somaxconnをいじる方法

結論
----

Docker 1.12 から `--sysctl` オプションが指定できるようになり、本TIPS(もはやBK)はObsoluteです<8/18追記>

```bash
$ docker run -it --rm alpine sysctl net.core.somaxconn
net.core.somaxconn = 128

$ docker run -it --rm --sysctl net.core.somaxconn=65535 alpine sysctl net.core.somaxconn
net.core.somaxconn = 65535
```

`--sysctl` は複数回指定可能です

```bash
$ docker run -it --rm --sysctl net.core.somaxconn=65535 \
  --sysctl "net.ipv4.ip_local_port_range=10000 65000" alpine true
```

1.12以前の方は `/proc` をマウントしてコンテナ内でいじってください

```bash
$ docker run --rm -it -v /proc:/wproc debian /bin/bash
root@9a1da1651135:/# echo 1024 > /wproc/sys/net/core/somaxconn
```

### 情報源 ###

[Refresh net.core.somaxcomm (or any sysctl property) for docker containers](http://stackoverflow.com/questions/26177059/refresh-net-core-somaxcomm-or-any-sysctl-property-for-docker-containers)

解説
----

### somaxconn ###

WEBサーバ等、大量コネクションを必要とするサーバ設定の定番チューニングは `net.core.somaxconn` の調整です

somaxconnの概要は下記URLで見てください

* [DSAS開発者の部屋:高負荷サイトのボトルネックを見つけるには](http://dsas.blog.klab.org/archives/51977201.html)
* [Webサーバの性能を測る | 最新の技術・取り組み | IIJ](http://www.iij.ad.jp/company/development/tech/activities/weighttp/)
* [Linux - Listen backlog - Qiita](http://qiita.com/nk_yohn3301/items/515733ed244ee3f35522)

### Dockerコンテナ内のsomaxconnのデフォルト ###

一方、Dockerコンテナ内主要なimageのsomaxconnは128となっており、とても本番に投入できる状況ではありません

```bash
$ docker run --rm ubuntu sysctl net.core.somaxconn
net.core.somaxconn = 128
$ docker run --rm debian sysctl net.core.somaxconn
net.core.somaxconn = 128
```

### Read-only file system ###

`/proc/sys/net/core/somaxconn` に書き込もうとしても `Read-only file system` とつれないメッセージが返り、書込みできません

```bash
$ docker run --rm -it debian /bin/bash
root@0dab1a51c6b2:/# echo 1024 > /proc/sys/net/core/somaxconn
bash: /proc/sys/net/core/somaxconn: Read-only file system
```

冒頭で紹介した方法は `/proc` を volume でコンテナ内に渡して書き込めるようにする方法です

```bash
$ docker run --rm -it -v /proc:/wproc debian /bin/bash
root@9a1da1651135:/# sysctl net.core.somaxconn
net.core.somaxconn = 128
root@9a1da1651135:/# echo 1024 > /wproc/sys/net/core/somaxconn
root@9a1da1651135:/# sysctl net.core.somaxconn
net.core.somaxconn = 1024
```

これを行っても host 側の net.core.somaxconn が変更されることはなく、思い切って変更が出来ます

また、somaxconnに限らず、他のパラメータも調整できるようになりますので、sysctlをいじる必要が出てきたら、覚えておきたい方法です


Docker entrypoint
-----------------

このような `entrypoint.sh` を作って `/wproc` が存在したら `somaxconn` の調整を行うようにするのがよろしいでしょう

※ついでに `ip_local_port_range` もいじっています


```:/entrypoint.sh
#!/bin/sh

PROCFS=${1:-"/wproc"}
if [ -d ${PROCFS} ]; then
	echo -n "Tune of linux kernel params for "
	echo 65535        > ${PROCFS}/sys/net/core/somaxconn
	echo "1024 65535" > ${PROCFS}/sys/net/ipv4/ip_local_port_range
	#net.unix.max_dgram_qlen = 10
	;;
else
	cat <<-EOT
WARN: Not found ${PROCFS} on this system
May be max concurrency is 100, due to somaxconn=128
please re-run "docker run -v /proc:/wproc"
	EOT
fi

exec /usr/local/bin/supervisord -n -c /etc/supervisord/supervisord.conf
```

あとがき
--------

こういうこと、やってくれる人、マジ募集
LabVIEWとDAQMX

|DAQmx|8.6  |2009 |2010 |2011 |2012 |2013 |2014 |2015 |備考|
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|-----|
|15.1 |     |     |     |     |2012 |2013 |2014 |2015 ||
|15.0.1|     |     |     |     |2012 |2013 |2014 |2015 ||
|14.5.1|     |     |     |2011 |2012 |2013 |2014 |     ||
|14.5 |     |     |     |2011 |2012 |2013 |2014 |     ||
|14.2 |     |     |     |2011 |2012 |2013 |2014 |     ||
|14.1 |     |     |     |2011 |2012 |2013 |2014 |     ||
|14.0 |     |     |     |2011 |2012 |2013 |2014 |     ||
|9.7.5|     |     |2010 |2011 |2012 |2013 |     |     |2013のサポート開始|
|9.7  |     |2009 |2010 |2011 |2012 |     |     |     ||
|9.6.2|     |2009 |2010 |2011 |2012 |     |     |     ||
|9.6.1|     |2009 |2010 |2011 |2012 |     |     |     ||
|9.6  |     |2009 |2010 |2011 |2012 |     |     |     ||
|9.5.5|     |2009 |2010 |2011 |2012 |     |     |     |2009以降 2012のサポート開始|
|9.5.1|8.6.x|2009 |2010 |     |     |     |     |     |8.6.x以降(2009以降を含む)|
|9.5  |8.6.x|2009 |2010 |     |     |     |     |     |8.6.x以降(2009以降を含む)|
|9.4  |8.6.x|2009 |2010 |     |     |     |     |     |8.6.x(2009以降を含む)|
|9.3  |8.6.x|2009 |2010 |     |     |     |     |     ||
|9.2.3|8.6.x|2009 |2010 |     |     |     |     |     ||
|9.2.2|8.6.x|2009 |2010 |     |     |     |     |     ||
|9.1.7|8.6.x|2009 |2010 |     |     |     |     |     ||
|9.1.1|8.6.x|2009 |     |     |     |     |     |     |Windows2000はここまで|
|9.1  |8.6.x|2009 |     |     |     |     |     |     ||
|9.0.2|8.6.x|2009 |     |     |     |     |     |     ||
|9.0  |8.6.x|2009 |     |     |     |     |     |     ||
|8.9.5|8.6.x|2009 |     |     |     |     |     |     ||
|8.9  |8.6  |     |     |     |     |     |     |     ||
|8.8  |8.6  |     |     |     |     |     |     |     ||
|8.7.2|8.6  |     |     |     |     |     |     |     ||
|8.7.1|     |     |     |     |     |     |     |     ||
|8.6.1|     |     |     |     |     |     |     |     ||
コマンド名: command not foundと言われたのでwhereisコマンドでしらべました。

コマンドを叩いた時に`command not found`と言われて困る時があります。

今回の例では`useradd`コマンドを実行したところエラーが出ました。

```bash:useraddコマンドが見つからない
useradd pugi_user
-bash: useradd: command not found
```
`useradd`コマンドが無いと言われています。pugi_userを追加しようとして失敗しました。

# whereisコマンドでコマンドを調べる
コマンドが本当に無いか`whereis`コマンドで調べます。

```bash:whereisコマンドでuseraddコマンドを調べる
whereis useradd

useradd: /usr/sbin/useradd /usr/share/man/man8/useradd.8.gz
```
`/usr/sbin/useradd`に`useradd`があるとわかりました。

# コマンドをパス付きで実行
パス付きでコマンドを実行してみます。

```bash:パスを指定してコマンドを実行
/usr/sbin/useradd pugi_user
```
今度はpugi_userが追加できました。
XAMLの基本プロパティ

以下２例は同じ意味です。

属性として記述すると

```xaml
<MyObject
xmlns= "clr-namespace:Sample;assembly=samples"
MyProperty="1"
OnChange="ObjectChange"/>
```

子要素として記述すると

```xaml
<MyObject
xmlns= "clr-namespace:Sample;assembly=samples">
<MyObject.MyProperty>
1
</MyObject.MyProperty>
</MyObject>
```
Facebook広告の入札方法が突如変更しCPCが5~10倍に急騰中

# TL;DR

- 20150909 21:00時点で確認、Facebook広告の入札仕様変更が確認された。
- Webクリック広告のフォーマットについて、従来の入札単価に対し、現入札単価が筆者運用アカウントでは5~10倍へ急騰している。


# 確認方法

- 新たに広告を作成し、広告セットの入札欄を確認する。
- 下記の違いを比較、新仕様となっている場合、アカウントが同様の影響を受けている可能性あり。

旧仕様：入札が`レガシーCPC`となっている
![image](https://qiita-image-store.s3.amazonaws.com/0/83135/b2dc90f4-0c69-1c3c-ae2c-732ba74b5961.png)


新仕様：入札が`CPC`となっている
![image](https://qiita-image-store.s3.amazonaws.com/0/83135/9da18f8f-cd42-5650-22d9-077c9737af8b.png)


# コメント

- こういった突然の仕様変更はプラットフォームであればよくあることなのですが、Facebookの嫌なところはリリースも出さずにしれっと大きな変更を加えてくる所ですね（たまたまABテストアカウントとして抽出されただけ、という可能性はなきにしもあらずですが）。
- 最終的な広告成果やCPAがどう推移していくかは運用をしてみないとわからないので、新仕様での運用を一晩試してみますが、Facebook広告を常用する広告主からするとビジネスへのネガティブインパクトが大きそうな今回の仕様変更です。

# 一晩運用してみて 20150910追記

![image](https://qiita-image-store.s3.amazonaws.com/0/83135/6f8d6fea-a9ec-82ca-c098-f99b93be5130.png)

- CPCは落ち着いたものの、旧仕様運用時の平均CPCから2.5倍ほど上振れする結果に。これは今後のFacebook広告運用に大きく影響がある。少なくとも予算比率を下げざるを得ないと思いました。

# 5日間経過して

- FB広告は単価が上がりきったまま戻らないので標準仕様とする模様。
- まだまだ割安感のある広告とはいえ、ROAS確保できる商材じゃないと出稿しにくい環境になりました。
- 来月始まるInstagram広告も、プロダクトの特性から決して安価になるとは考えずらい（エンゲージよりはブランディング・imp重視になるのではないか）。
- Twitterランドの広告に頑張ってもらいたい。広告主がインハウス運用できる環境に変えて欲しいっすね。
Yahoo!ID連携がうまく行かない。サンプル通りだがエラーになる。

お世話になっております。
Yahoo!ID連携の構築について質問です。

■SDKを利用したPHPによる導入方法
http://developer.yahoo.co.jp/yconnect/server_app/php/

記述通り行っているのですが、ログインボタン押下後、callback.phpにリダイレクトされ
Authorization Codeを取得を取得とありますが、エラーで取得ができません。
下記にコードを記載しますので、お分かりの方がいらっしゃいましたら修正点をお願いします。

```エラー内容
Notice: Undefined variable: state in /var/www/html/fmit-kk.com/admin/callback.php on line 18
Fatal error: Uncaught YConnect\Exception\TokenException: not_matched_state ( the state did not match ) thrown in /var/www/html/fmit-kk.com/admin/vendor/yahoojapan/yconnect-php-sdk/lib/YConnect/YConnectClient.php on line 188
```

```php:admin_header.php
<span class="yconnectLogin"></span>
<script type="text/javascript">
	window.yconnectInit = function() {
		YAHOO.JP.yconnect.Authorization.init({
			button: {
				format: "image",
				type: "a",
				width: 64,
				height: 36,
				className: "yconnectLogin"
			},
			authorization: {
				clientId: "app_id",
				redirectUri: "http://fmit-kk.com/admin/callback.php",
				scope: "openid",
				state: "44Oq44Ki5YWF44Gr5L+644Gv44Gq44KL77yB",
				nonce: "5YOV44Go5aWR57SE44GX44GmSUTljqjjgavjgarjgaPjgabjgog="
			},
			onError: function(res) {
				// エラー発生時のコールバック関数
			},
			onCancel: function(res) {
				// 同意キャンセルされた時のコールバック関数
			}
		});
	};
	(function(){
	var fs = document.getElementsByTagName("script")[0], s = document.createElement("script");
	s.setAttribute("src", "https://s.yimg.jp/images/login/yconnect/auth/1.0.0/auth-min.js");
	fs.parentNode.insertBefore(s, fs);
	})();
</script>
```
```php:callback.php
<?php
ini_set( 'display_errors', 1 );
require './vendor/autoload.php';

use YConnect\Credential\ClientCredential;
use YConnect\YConnectClient;
 
// アプリケーションID, シークレッvト
$client_id     = "app_id";
$client_secret = "シークレット";
$redirect_uri  = "http://fmit-kk.com/admin/ys_index.php";
 
$cred = new ClientCredential( $client_id, $client_secret );
$client = new YConnectClient( $cred );
 
try {
    // Authorization Codeを取得
    $code_result = $client->getAuthorizationCode( $state );

    // Tokenエンドポイントにリクエスト
    $client->requestAccessToken( $redirect_uri, $code_result );
 
    // アクセストークン, リフレッシュトークンを取得
    $access_token  = $client->getAccessToken();
    $refresh_token = $client->getRefreshToken();
 
} catch ( TokenException $e ) {
    // 再度ログインして認可コードを発行してください
}
echo $access_tokene;
echo $refresh_token;
```
XAMPPでPHP7.0.0 RC1が動かない

XAMPPにPHP7を入れて遊んでいたわけですが、[前書いた手順](http://qiita.com/rana_kualu/items/447995347acb2f8997a3)では、PHP7.0.0RC1は動作しません。

手順に従ってPHPを起動しようとすると、
「序数387がダイナミックライブラリSSLEAY32.dllから見つかりませんでした」
という謎のエラーが発生して起動できません。
きっとみんな困ってるだろうなと「[xampp PHP7 SSLEAY32.dll](https://www.google.co.jp/search?q=xampp+PHP7+SSLEAY32.dll&lr=lang_ja)」とかで検索してみても同様の事例が全く見当たらない。
どういうことだ？みんなWindowsでPHP7使ってないのか？

まずは原因調査。
php.iniの`extension=***.dll`の行を全てコメントアウトしてからXAMPPを起動してみます。
これであれば動作するはずです。
動かなかったら知らん。
次に`extension=php_curl.dll`の行を有効にしてXAMPPを起動。
これでエラーが出るようであれば、原因はOpenSSLのバージョンです。

2015/09/09時点でのXAMPP最新バージョン[XAMPP5.6.12](https://www.apachefriends.org/jp/index.html)に入っているOpenSSLのバージョンは1.0.1です。

一方[PHP7](https://github.com/php/php-src/blob/php-7.0.0RC1/NEWS)ではOpenSSL1.0.2以降のバージョンが要求されています。
実際はβ1の時点から要求されていますが、これまではたまたま新機能を使っていなかったようで、エラーは発生していませんでした。

ということでOpenSSLの新バージョンをインストールしましょう。
[公式](https://www.openssl.org/)にはソースしかないので、[Windows版を配布しているサイト](http://slproweb.com/products/Win32OpenSSL.html)から持ってきます。
今回は「Win32 OpenSSL v1.0.2d」を選択。
インストール後、インストールディレクトリの中から「libeay32.dll」「ssleay32.dll」のふたつを取り出して、
`XAMPP/apache/bin/`以下にある同名ファイルを置き換えます。
というかこの2ファイル以外要らないので、インストーラじゃなくてzipでほしかった。
手元環境が32ビットなので32ですが、64ビットの場合は「Win64 OpenSSL v1.0.2d」になると思います。
試してないのでわかりませんが。

これでSSLを使うextensionをロードしても怒られなくなったはずです。
めでたし。

なお、「[ダイナミックライブラリSSLEAY32.dllから見つかりませんでした](https://www.google.co.jp/search?q=ダイナミックライブラリSSLEAY32.dllから見つかりませんでした&lr=lang_ja)」で検索すると一発で解決策が見つかる模様。
Lambda を cron 的に使う Ver 2015.09


先日の "JAWS-UG 千葉支部 Vol.5 ～秋のAWS Lambda & API Gateway 祭り！！～" の懇親会で飛び入りLTさせて頂いた内容です。

## これまでのLambda を cron 的に使う試み

### ■[AWS Lambdaをcronの代わりに使ってみるよ](http://qiita.com/toritori0318/items/3ab95e94c5fc47530447)  
S3のEventから起動され、S3のobjectを作成する事でループする手法  
![s3-lambda-s3](http://j3tm0t0-img.s3-ap-northeast-1.amazonaws.com/s3-lambda-s3.png)

もしLambdaからS3にobjectを入れるのに失敗すると、そこでループが途切れてしまう、また頻度は最長でも１分に１回程度

### ■[Azure Job Scheduler + AWS Lambdaで夢のサーバレス定期ジョブを実現する](http://marcy.hatenablog.com/entry/2015/01/17/005502)

![azure-s3-lambda](http://j3tm0t0-img.s3-ap-northeast-1.amazonaws.com/azure-s3-lambda.png)

自分もこの記事を見て、同じ形で長らく使っていました(無料枠でも１時間に１度なら使用できます)。

## どうにかしてAWSのサービスのみで実装できないだろうか？

### ■ 実験１ Dead Dead Queue DeDeDeDe-Destruction パティーン
最初はSQSを２つ作って Dead Queue として指定したらお互いにメッセージを投げ合えないだろうか？と考えてみました。

![sqs-sqs](http://j3tm0t0-img.s3-ap-northeast-1.amazonaws.com/sqs-sqs.png)

→ 一度も受信されなかったメッセージは Dead Queue には入らなかった...  
＃LambdaでSQSを読み捨てするのもアリかと思ったけど、失敗した時に途切れるのでボツ

### ■ 実験２　Return to myself パティーン
Alarm を設定しているうちに、ふと SQS は SNS Topic を Subscribe できる事に気付いたので、以下の手順で定期的に SNS Alarm を鳴らす事に成功した。

1. SQS のキューを作成する(その際にメッセージ保持期間を繰り返したい時間-5分とかに設定する)
2. SQSにメッセージがない状態(ApproximateNumberOfMessagesVisible<=0)が一定時間(５分)続いたら、CloudWatch Alarm から SNS Topic へアラートを送る
3. 上記 SNS Topic には 上記の SQS Queue を Subscribe させておく

これによって、メッセージがないというアラートがSQSメッセージとして同じキューに届き、メッセージ保持期間を過ぎたらまたアラートが飛んでメッセージが届く、というループ状態になる。

これを使用して、SNS Topic に Lambda function を指定しておくと、一定時間に１度 Lambda function が実行される状態となる。

![sqs-sns-lambda](http://j3tm0t0-img.s3-ap-northeast-1.amazonaws.com/sqs-sns-lambda.png)

SNS から SQS へのアラートが失敗する事はリスクとして存在するが、例えば１時間以上０が続いたらアラートが鳴るような設定を追加する事で、何か問題が発生しても１時間でリトライがかかるようになる。

ただ、SQS の ApproximateNumberOfMessagesVisible メトリックはメッセージが入れられてから数字が検知されるまでに間があるので、メッセージ保持期間は10分未満には設定しない方がよいと思われる。

## まとめ

汎用のスケジューラ( REST の URL や AWS の API コールが行えるもの)があるといいのですが！
Raspberry Pi に高精細IGZOパネルを繋げてみた。


2015年8月1,2日に東京ビックサイトで開催されたMaker Faire Tokyo 2015で、Raspberry Pi向け高精細IGZOパネルを購入しました。

- [商品探求　Raspberry Pi向け液晶パネル　高精細IGZO](http://ameblo.jp/motohide-shirasuna/entry-12057065296.html)
- [商品探求　Raspberry Pi向け液晶パネル　高精細IGZO　メイキング](http://ameblo.jp/motohide-shirasuna/entry-12057241954.html)

#Raspberry Pi用IGZOディスプレイパネル
7インチのWUXGA(1200×1920ピクセル)ディスプレイです。デフォルトでは縦長(Portrait)、設定によって横長(Landscape)に変更できます。
ただタブレット端末のようにon-the-flyで画面の縦横を変えられず、Raspbian起動時に読み込まれるconfig.txtファイルを書き換える必要があります。またEDIDによる自動判別に対応していません。

これのconfig.txtの書き換えが面倒なのでシェルスクリプトを書きました。

#config.txtの編集
config.txtは `/boot` ディレクトリにあります。
まずオリジナルを複数コピーします。

```bash
$ cd /boot/
$ sudo cp config.txt config.txt.original
$ sudo cp config.txt config.txt.IGZO_0
$ sudo cp config.txt config.txt.IGZO_1
$ sudo cp sonfig.txt config.txt.IGZO_2
$ sudo cp sonfig.txt config.txt.IGZO_3
```

次に `config.txt.IGZO_0` 〜 `config.txt.IGZO_3` に下記の記述を追加します。

```bash:config.txt.IGZO_0
hdmi_pixel_freq_limit=200000000
hdmi_timings=1200 0 164 8 32 1920 0 12 2 6 0 0 0 60 0 163430000 0
hdmi_drive=2
disable_overscam=1
max_framebuffer_width=1920
max_framebuffer_height=1920

# Portrate
display_rotate=0
framebuffer_width=1200
framebuffer_height=1920
```

```bash:config.txt.IGZO_1
hdmi_pixel_freq_limit=200000000
hdmi_timings=1200 0 164 8 32 1920 0 12 2 6 0 0 0 60 0 163430000 0
hdmi_drive=2
disable_overscam=1
max_framebuffer_width=1920
max_framebuffer_height=1920

# Landscape
display_rotate=1
framebuffer_width=1920
framebuffer_height=1200
```

```bash:config.txt.IGZO_2
hdmi_pixel_freq_limit=200000000
hdmi_timings=1200 0 164 8 32 1920 0 12 2 6 0 0 0 60 0 163430000 0
hdmi_drive=2
disable_overscam=1
max_framebuffer_width=1920
max_framebuffer_height=1920

# Portrate
display_rotate=2
framebuffer_width=1200
framebuffer_height=1920
```

```bash:config.txt.IGZO_3
hdmi_pixel_freq_limit=200000000
hdmi_timings=1200 0 164 8 32 1920 0 12 2 6 0 0 0 60 0 163430000 0
hdmi_drive=2
disable_overscam=1
max_framebuffer_width=1920
max_framebuffer_height=1920

# Landscape
display_rotate=3
framebuffer_width=1920
framebuffer_height=1200
```

#シェルスクリプトの作成
ホームディレクトリに戻って次のシェルスクリプトを作成します。スクリプト名は `IGZO.sh` です。

```bash:IGZO.sh
#!/bin/bash

case $1 in
    0) sudo cp /boot/config.txt.IGZO_0 /boot/config.txt;;
    1) sudo cp /boot/config.txt.IGZO_1 /boot/config.txt;;
    2) sudo cp /boot/config.txt.IGZO_2 /boot/config.txt;;
    3) sudo cp /boot/config.txt.IGZO_3 /boot/config.txt;;
    9) sudo cp /boot/config.txt.original /boot/config.txt;;
esac

case $2 in
    "r" ) sudo reboot;;
    "h" ) sudo halt;;
esac
```

次に実行権限を与えます。

```bash
$ chmod +x IGZO.sh
```

#使い方
コマンド `IGZO.sh` の最初の引数(0,1,2,3,9)で `config.txt` を書き換え、2番目の引数(r,h)で再起動かシャットダウンかを選択します。

例1) ポートレート画面で再起動。

```bash
$ ./IGZO.sh 0 r
```

例2) 標準設定に戻してシャットダウン。

```bash
$ ./IZGO.sh 9 h
```
linux > 5秒ごとにUDPで文字列を送信するbashスクリプト (不完全版)

```txt:動作確認
CentOS 6.5 (32bit)
```

やりたいこと
"時:分,データ"の形式 (例 "02:10,-0.9")を5秒ごとに送信したい。

やっつけ仕事的に以下で実装した。

```bash:udpSend-exec
#!/bin/env bash

for data in \
"00:00,0.2" "02:10,-0.9" "03:40,0.3" \
"05:30,-0.9" "09:30,0.2" "11:30,0.4" \
"13:30,0.1" "16:30,0.5" "18:30,0.9" "22:00,-0.9";do
  sleep 4
##  echo $data | nc -u 192.168.10.3 6000 &
  echo $data | nc -w 1 -u 192.168.10.3 6000 &
done
```

[追記 2015/09/10] 上記ncの使用について訂正した。

```txt:結果
$ bash udpSend-exec 
00:00,0.2
02:10,-0.9
03:40,0.3
05:30,-0.9
09:30,0.2
11:30,0.4
13:30,0.1
16:30,0.5
18:30,0.9
[tmp]$ 22:00,-0.9
```

5秒ごとに 192.168.10.3(ポート6000)へ送信できた。

##不完全というタイトルの理由1

~~上記スクリプトにて ncに&をつけないと処理がhaltしている感じだった。
送信のブロッキングになってしまったのか未調査。
&をつけて実行できたが、本来のやり方ではないかもしれない。（が、今必要な処理としてはとりあえず使える).~~

[追記 2015/09/10] `-w 1`にて1秒でタイムアウトするようにした。

##不完全の理由2
http://qiita.com/7of9/items/6a19c036ada7af01078a
あたりで教えていただいたファイル読込み処理をやれば、もっと綺麗なコードができるはず。
Nginxで適当なfaviconを設定する

faviconがどうでもいいサービスなのにfavicon.icoにアクセスされるのは気持ちのいいものではないです。
というわけで以下の様な設定をしていました。

```nginx
location = /favicon.ico {
  access_log off;
  return 200;
}
```

まあこれでも困ることってないと思うのですが、以下の様な需要があるかもしれません。

  * 一応適当な画像を返したい
  * キャッシュして欲しい

そういう場合は以下の様な設定が良さそうです。

```nginx

location = /favicon.ico {
  access_log off;
  empty_gif;
  expires 30d;
}
```

`empty_gif`で1px四方の透明なGIF画像を返してくれるらしいです。便利。
Wildcard SSL certificate for sub sub-domain

# やりたいこと
example.com
www.example.com
sub1.example.com
sub2.sub1.example.com
sub3.sub2.sub1.example.com
を一枚のSSL証明書でまかないたい。
# 回答
```*.example.com``` というWildcard SSLを取得して、
```*.*.example.com``` と ```*.*.*.example.com``` をSANとして申請することは出来ない。
要するにSANには「*（アスタリスク）」を含めることができないということらしい。
なので、やりたい放題の証明書を簡単につくることは不可能。
# よくある解決法
勧められたのは、Wildcard SSL証明書に、実際のホストネームをいっこずつSANとして登録するやり方。
「*.example.com」 というWildcard SSLを申請して、
「sub1.example.com」
「sub2.sub1.example.com」
「sub3.sub2.sub1.example.com」
.
.
.
と必要なだけ（一枚の証明書には上限10）SANを追加していく。
ネイキッドドメイン「example.com」も追加可能。
SANの追加は無料です。

詳しくはここで。
https://www.digicert.com/ssl-support/wildcard-san-names.htm
彼よりワイルドだぜ。
Vimのカラースキームを設定できない問題


## 問題

VimのカラースキームをSolarizedに設定しようとして、.vimrcに以下のように書いて

```.vimrc
NeoBundle 'altercation/vim-colors-solarized'
syntax enable
set background=dark
colorscheme solarized
```

何かファイルを開こうとすると、以下の **Cannot find color scheme** のエラーが出てカラースキームが設定されない。

```
$ vim .vimrc
Error detected while processing /Users/user/.vimrc:
line  100:
E185: Cannot find color scheme 'solarized'
Press ENTER or type command to continue
```


## 解決方法

[Cannot find color scheme solarized · Issue #104 · altercation/vim-colors-solarized](https://github.com/altercation/vim-colors-solarized/issues/104#issuecomment-71037368)

によると、 `colorscheme solarized` は `call vundle#end()` の後に書けとのこと。

というわけで、.vimrcを

```.vimrc
·
·
·
NeoBundle 'altercation/vim-colors-solarized'
·
·
·
call neobundle#end()
·
·
·
syntax enable
set background=dark
colorscheme solarized
```

と書くようにしたら、エラーを解消してカラースキームの設定をすることができた。
unity > time > System.DateTime.Parse("12:30"); > 12時30分になる

```txt:動作確認
Unity 5.1.2-f1 on MacOS X 10.8.5
```

```sample.cs
	void Test_timeCsvRead(string line) {
		System.DateTime dt = System.DateTime.Parse (line);
		Debug.Log (dt.ToString ());
	}

	void Start () {
		Test_timeCsvRead ("12:30");
		Test_timeCsvRead ("10:10");
		Test_timeCsvRead ("23:45");
	}
```

上記の結果

![Main_unity_-_150908-udpTimeGraph_-_PC__Mac___Linux_Standalone__Personal_.jpg](https://qiita-image-store.s3.amazonaws.com/0/32870/7f345d44-4b69-c779-7d1f-11875c093684.jpeg)

本日の時分として認識されるようだ。

時系列グラフ描画に使える。
サポートブラウザの選定案（スマホ）

※ これはあくまでも案です

# スマホは4年以上使わないと仮定した場合。

- サポートする対象は、4年以内に発売された端末（※1）が、デフォルトで搭載している OS 以降とする（※2）。
- 実機確認が必要な以上、古い端末の手配・管理にも限界があるので、それを考慮してもデバイスの発売日を軸にしたサポートブラウザ対象の選定は妥当と思える。

#### 各社スマホの保証の実態もろもろ（ググって出て来た順にピックアップ）
+ [K's デンキ](http://www.ksdenki.com/ec/inc/topics/special/special_2837.html) - 1,5,10 年保証はスマホは除く
+ [biccamera](http://www.biccamera.com/bc/c/info/guarantee/index.jsp) - 1,5,10 年保証はスマホは除く
+ [softbank](http://www.softbank.jp/mobile/service/anshinpack/plus/) - 安心保証パックは無期限だけど、代替機種になる可能性がある
+ [Apple](http://www.apple.com/jp/support/products/iphone.html) - Apple は、拡張しても2年

（※1）4年以内に販売ではなく、「最終発売日」もしくは「発売日から1年」等も検討の余地がある

（※2）発売は4年以内だが、すごく古い OS が搭載されていて、ただとてもマイナーな端末（サイトのアクセスがないとか一桁台とか）であったりする場合はサポートしない、例外を設けても良いと思われる


## で、過去4年に販売が開始された端末のデフォルトOSはどうなのかというと

2011 年 9 月以降発売の、
　- 最低 Android バージョン Android 2.3
　- 最低 iOS バージョン iOS 5
因に、上に 4 年と書いたけど、 3 年にすると…
2012 年 9 月以降発売の、
　- 最低 Android バージョン Android 4
　- 最低 iOS バージョン iOS 6


#### 参考

[smartphone.ultra-zone.net](http://smartphone.ultra-zone.net/)
[hot-topic-news.com](http://hot-topic-news.com/iphone-history)


## サポート対象ブラウザを引き上げる際

ユーザも、好きで古い端末・OS を使っているわけではないかもしれなく、変える必要・必然がないから変えてないだけで、不都合を感じたりする事があれば買い替えるかもしれない。
サポート対象を引き上げる際、昔の Web サイトではよく利用されていた、「お使いのブラウザでは、Webサイトを正しく利用ごにょごにょ」的な表記を出すようにする事で、買い替え・アップデートが必要ないと思っているユーザに対して、啓蒙できる可能性がある。

また、一貫して上の表記を出すのではなく、何らかの理由で規定のバージョンよりもサポート対象を引き上げたい場合に限り表記するような事も考えられる。
IPv6を省略形に変換する


```cpp:test.cpp

#include <stdio.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>

#include <string>

std::string compress_ipv6( std::string ip ) {
	
	if( ip.empty() ) {
		
		return( "" );
		
	}
	
	unsigned char buf[sizeof(struct in6_addr)] = "";
	int domain;
	int s;
	char str[INET6_ADDRSTRLEN] = "";

	domain = AF_INET6;

	s = inet_pton( domain, ip.c_str(), buf );
	
	if( s <= 0 ) {
		
		if( s == 0 ) {
			
			fprintf( stderr, "Not in presentation format. %s\n", ip.c_str() );
			return( "" );
			
		} else {
			
			fprintf( stderr, "inet_pton failed. %s\n", strerror( errno ) );
			return( "" );
			
		}
		
	}
	
	if( inet_ntop( domain, buf, str, INET6_ADDRSTRLEN ) == NULL ) {
		
		fprintf( stderr, "inet_ntop failed. %s\n", strerror( errno ) );
		return( "" );
		
	}
	
	return( str );
	
}

int main( int argc, char **argv ) {
	
	if( argc != 2 ) {
		
		return( 1 );
		
	}
	
	std::string ret = compress_ipv6( argv[1] );
	
	if( ! ret.empty() ) {
		
		printf( "%s\n", ret.c_str() );
		
	}
	
	return( 0 );
	
}

```

<pre>
コンパイル
[todanano@localhost test]$ g++ -o test.o test.cpp

実行
[todanano@localhost test]$ ./test.o 2001:0db8:0020:0003:1000:0100:0020:0003
2001:db8:20:3:1000:100:20:3
[todanano@localhost test]$
[todanano@localhost test]$ ./test.o aaaa
Not in presentation format. aaaa
[todanano@localhost test]$
[todanano@localhost test]$
</pre>
Scratch公式サイトのプロジェクトをPyonkee (ピョンキー)2.1から簡単に開くブックマークレット

# Pyonkeeとは
[Pyonkee](http://www.softumeya.com/pyonkee/ja/index.html)はMITメディアラボのScratchを基に開発されたiPadで動くビジュアルプログラミング環境です。
Scratch1.4プロジェクトとの互換性があります。

# Scratch公式サイトプロジェクトについて
PC、Mac、Raspberry Piなどで動くScratch1.4で作成されたプロジェクトは、メニューの【共有】ー【ネットワーク上でこのプロジェクトを共有】を選択することでScratch公式サイトへアップロードすることが可能です。

この記事で対象とするScratchプロジェクトは、このScratch1.4で作成されてアップロードされたものが対象となります（Scratch2.0のプロジェクトはPyonkeeでは開けません）。

# プロジェクトファイル取り込み方法
プロジェクトファイルの取り込み方法の詳細手順は以下のサイトに解説があります。
[Scratch公式サイトのプロジェクトをPyonkee(ピョンキー)から開く方法](http://swikis.ddo.jp/abee/81)
こちらの解説にあるように、プロジェクトのURLの一部を置き換えることで公式サイトにあるプロジェクトファイルがダウンロード可能になります（Scratch1.4プロジェクト限定）。

# Safariブックマークレット
ブックマークレットはWebブラウザのブックマークに登録されたJavaScriptで書かれた簡易なプログラムで、ブラウザ上で簡単な処理を行うものを言います。

今回の事例では現在開いているWebサイトのURLの一部を置き換えるという処理ですので、ブックマークレットの得意とする部分です。

iPadのSafariでScratch公式サイトを開き、目的とするプロジェクトのURLを開きます。その状態で以下のブックマークレットを実行することで

javascript:location.href=document.URL.replace(/projects/,'services/download');

解説サイトのURL置き換え手順である

>URLを変更する
>アドレス欄をタップし、URLを表示させます。URLは以下の形式になっています。
>https://scratch.mit.edu/projects/プロジェクト番号/
>これを次のように書き換え、「Go」ボタンをタップします。
>https://scratch.mit.edu/services/download/プロジェクト番号/

という部分を自動的に処理することになります。

# ブックマークレット登録手順

具体的な手順は以下のブログエントリに記載したのでご参照ください。
[Pyonkeeのプロジェクトファイル取り込みが便利になった話](http://nasu-lab.blogspot.jp/2015/09/pyonkee.html)