OmniAICreator/Qiita-1.07M huggingface dataset:
sphinxでplantumlの図入り日本語テキストをlatexpdfjaでPDF化してみた

2014-05-24 18:40頃追記
<blockquote class="twitter-tweet" lang="ja"><p><a href="https://twitter.com/hnakamur2">@hnakamur2</a> plantuml_latex_output_format で eps か pdf を指定すれば上手く行くかもしれません。&#10;<a href="https://t.co/VuY328ZAIF">https://t.co/VuY328ZAIF</a></p>&mdash; Yuya Nishihara (@yujauja) <a href="https://twitter.com/yujauja/statuses/470131475585568768">2014, 5月 24</a></blockquote>
というご指摘を頂いて試したら、epsにしてみたらあっさり出来ました。ありがとうございます！

ということで下記は適宜編集しました。

rst2pdfを使って変換する方法は[sphinx, rst2pdf, plantumlでUMLのクラス図入り本文日本語テキストをpdfに変換してみた - Qiita](http://qiita.com/hnakamur/items/fb703b826927ab571b6a)に書きました。

* [Sphinx で日本語を含む PDF 出力をする - 憧れ駆動開発](http://atasatamatara.hatenablog.jp/entry/2013/03/16/204232)
* [SphinxでPDFファイル作成 — Python製ドキュメンテーションビルダー、Sphinxの日本ユーザ会](http://sphinx-users.jp/cookbook/pdf/)

を見るとLaTeX経由のほうが、「見た目の綺麗なPDFが作れる」らしいので試してみました。

https://github.com/hnakamur/sphinx-rst2pdf-plantuml-japanese-example
にサンプルソースを置いてあります。

サンプル出力結果はこちらです。
https://hnakamur.github.io/sphinx-rst2pdf-plantuml-japanese-example/sphinxrst2pdfexample.pdf

# セットアップ

[sphinx, rst2pdf, plantumlでUMLのクラス図入り本文日本語テキストをpdfに変換してみた - Qiita](http://qiita.com/hnakamur/items/fb703b826927ab571b6a)
と同じですが、以下の手順が追加で必要です。

## MacTeXをインストール

TeX Liveというのを使うらしいのですが、[MacWiki - TeX Live](http://macwiki.sourceforge.jp/wiki/index.php/TeX_Live)によるとOSXの場合は[MacTeX - TeX Users Group](http://tug.org/mactex/)らしいので、インストーラをダウンロードしてインストールしました。

### PATH環境変数を設定

bashを使っている場合は~/.bash_profile、zshを使っている場合は~/.zprofileに

```
# Add PATH for MacTeX TexLive
export PATH=$PATH:/usr/local/texlive/2013/bin/universal-darwin
```

を追加して

```shell-session
exec $SHELL -l
```

で有効にします。

## conf.pyに設定追加

conf.pyにplantumlの設定のところに、plantuml_latex_output_formatをepsに設定するのを追加します。

```
# -- Options for PlantUML --------------------------------------------------
plantuml = ['java', '-jar', '/usr/local/Cellar/plantuml/7994/plantuml.7994.jar']
plantuml_latex_output_format = 'eps'
```

https://pypi.python.org/pypi/sphinxcontrib-plantuml#configuration
に説明があります。

デフォルトはpngだそうです。pdfにするには[epstopdf](http://www.ctan.org/pkg/epstopdf)というPerlスクリプトが必要らしいです。今回はepsで動いたのでpdfは試してないです。

# PDF生成

```shell-session
make latexpdfja
```

# PDFファイル内のフォントを調べてみました

```shell-session
(env)% pdffonts _build/latex/sphinxrst2pdfexample.pdf
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
QBGDEF+NimbusSanL-Bold               Type 1C           WinAnsi          yes yes no       4  0
THCURT+NimbusSanL-BoldItal           Type 1C           WinAnsi          yes yes no       5  0
AHQWSO+NimbusRomNo9L-Regu            Type 1C           WinAnsi          yes yes no       6  0
MXFITE+NimbusRomNo9L-Medi            Type 1C           WinAnsi          yes yes no      14  0
Ryumin-Light-Identity-H              CID Type 0        Identity-H       no  no  no      22  0
PUIYBR+NimbusRomNo9L-ReguItal        Type 1C           WinAnsi          yes yes no      37  0
```
CentOSにApache Ant1.9.4をインストールする

``` Bash
> wget http://www.apache.org/dist/ant/binaries/apache-ant-1.9.7-bin.tar.gz
> tar zxvf apache-ant-1.9.7-bin.tar.gz
> mv apache-ant-1.9.7 /usr/share/ant
> ln -s /usr/share/ant/bin/ant /usr/bin/ant
> vi ~/.bash_profile
```

``` Bash:~/.bash_profile
export ANT_HOME=/usr/share/ant
```
Chrome extensionのcontent_scriptsにAjaxを対応してみた

したいこと：

ウェブページにある要素の前にリンクを付けたい。

最初のページは簡単ですが、でもその以降のデータ取得はAjaxでとっています（Ajax.onSuccess($('a').html(data))の形で）ので、新たに撮ったデータにリンクが付けられません。

解決策はDOM要素の`DOMSubtreeModified`イベントを利用しました。

```js
function addLinks(){
  $("div[class='question-box']").each(function(){
    // do something ...
  });
}

function DOMModificationHandler(){

  $(this).unbind('DOMSubtreeModified');
  setTimeout(function(){
      addLinks();
      $('.question-list').bind('DOMSubtreeModified',DOMModificationHandler);
  },1500);
}

// add links for first page(loaded not by Ajax).
addLinks();

//after document-load(for ajax response)
$('.question-list').bind('DOMSubtreeModified',DOMModificationHandler);

```
phpのバージョンをアップデートしたらmysqlでエラーがでた件の解決

owncloudを使っていたら，「phpのバージョンを5.3.8以上にしろ」みたいなことを言われていたので，なんとか頑張ってphp5.4を入れました．

そこまでは良かったのだけど，そうしたら以下のようなエラーが

```shell-session
[2002] SQLSTATE[HY000] [2002] Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
```

結論としては，mysqlの設定ファイルの一部を書き換える必要がありました．

/etc/my.cnfの内容を書き換えます

```zsh
sudo vim /etc/my.cnf
```

以下の行を書き換えました．

```
default-character-set=utf8
↓
character-set-server=utf8
```

これで解決しました．
サーバ関連コマンド(メモ)

<h4>php編集</h4>
```
emacs -nw /var/www/html/sample.php
```
<h4>cronログ表示</h4>
```
cat /var/log/cron
```
<h4>時刻設定</h4>
```
date -s "05/24 13:34 2014"
```
<h4>コマンド履歴表示</h4>
```
history
```
<h4>crontab再起動</h4>
```
/etc/rc.d/init.d/crond/ restart
```
<h4>crontab起動</h4>
```
/etc/rc.d/init.d/crond/ start
```
<h4>crontab停止</h4>
```
/etc/rd.d/init.d/crond/ stop
```
<h4>現在のSHELLの表示</h4>
```
echo $SHELL
```
<h4>crontabの編集</h4>
```
emacs -nw /etc/crontab
```
<h4>crontabの設定</h4>
```
crontab /etc/crontab
```
<h4>sendmail再起動</h4>
```
/etc/init.d/sendmail restart
```
<h4>sendmailログの確認</h4>
```
cat /var/log/maillog
```
<h4>コマンドラインでphp実行</h4>
```
/usr/bin/php /var/www/html/sample.php
```
<h4>sshd config 適用のための再起動</h4>
```
service sshd restart
```
<h4>サーバを日本標準時設定にする</h4>
```
cp /usr/share/zoneinfo/Japan /etc/localtime
```

<h4>SSH接続情報、ホスト鍵を消す</h4>
```
sed -i -e ‘/192.168.1.100/d’ ~/.ssh/known_hosts
```
Selenium Python Bindingsとpy.testでデータ駆動テストのさわりを試す

## 背景

Seleniumを使ってデータ駆動型テストを勉強してみたかったので、
pythonのテストフレームワークであるpy.testを使って書いてみた。

## スクリプトの概要

* スクリプトはGoogleさんのトップページから検索を行い、検索結果を確認する簡単なもの。
* py.testに組み込まれているpytest.mark.parametrize デコレータを使って、検索ボックスに入力する文字列と、検索後の文字列をinput, expectedで定義。

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

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import pytest
import time

@pytest.mark.parametrize(("input", "expected"), [
    ("red", "<em>RED</em>/レッド - Wikipedia"),
    ("青", "<em>青</em> - Wikipedia"),
    ("きいろ", "五丁目 千 <em>きいろ</em>"),
])

def test_search(input, expected):
    driver = webdriver.Chrome()
    driver.get("http://www.google.co.jp/")
    elem = driver.find_element_by_name("q")
    elem.send_keys(input)
    elem.send_keys(Keys.RETURN)
    time.sleep(1)
    assert expected in driver.page_source
    driver.close()
```

## テストの実行結果

* 1つのテストでもセットしたテストデータは3件なので、3件のテストがコレクトされていることがわかる。
* テスト自体は1つしか書いてないので、スクリプトの変更も楽。

```
# py.test -v -s pram_test.py
=========================================================== test session starts ============================================================
platform darwin -- Python 3.3.3 -- pytest-2.5.1 -- /Users/hoge/local/py3/bin/python
collected 3 items 

pram_test.py:8: test_search[red-<em>RED</em>/レッド - Wikipedia] PASSED
pram_test.py:8: test_search[青-<em>青</em> - Wikipedia] PASSED
pram_test.py:8: test_search[きいろ-五丁目 千 <em>きいろ</em>] PASSED

======================================================== 3 passed in 13.50 seconds =========================================================
```

* py.testは機能豊富っぽいので、今後もいろいろ試していきたい。
他のUSBデバイスがいるとrtlsdrがエラーになっちゃう件


RaspberryPiでWifiのUSBドングルと、RTLデバイスを同居させたときに、rtl_testでエラーになってしまう。

```bash::rtl_test
$ sudo rtl_test
Found 1 device(s):
  0:  Generic, RTL2832U, SN: XXXXXXXXXXXX

Using device 0: Generic RTL2832U

Kernel driver is active, or device is claimed by second instance of librtlsdr.
In the first case, please either detach or blacklist the kernel module
(dvb_usb_rtl28xxu), or enable automatic detaching at compile time.

usb_claim_interface error -6
Failed to open rtlsdr device #0.
```

エラーメッセージの通り、デバイスをブラックリストに入れて、libusbが扱えるようにする。

`/etc/modprobe.d`にrtlsdr-blacklist.confといった感じで以下の通り作成する。

```config:/etc/modprobe.d/rtlsdr-blacklist.conf
blacklist dvb_usb_rtl28xxu
blacklist rtl2830
blacklist dvb_usb_v2
blacklist dvb_core
```

あとはリブートしちゃいましょう。
Arch linuxでSDRする準備


# パッケージ追加
pacman -Sで以下追加

````:pacman
gcc
make
cmake
lib-usb
git
````
Pidoraの時と違って、libusbはdevも込みなんですね。
libusb-devとか探しても無い筈だ。

# ビルド、テスト
[ここ](http://qiita.com/fujiba/items/68858760dace376d0642)の通り、gitでソース引っ張ってきて、make。
/etc/ld.confに`/usr/local/lib`の追加も忘れずにしましょう。
Chef-Soloのインストールと簡単なもの実行テスト

#前提
vagrantがインストールされていること
➡参考http://qiita.com/pollseed/items/c469e2d53d7125594043
<pre>$ vagrant -v</pre>
#手順
##vagrant起動
<pre>$ vagrant halt && vagrant up 再起動します
$ vagrant ssh
</pre>
##chef-soloいんすとーる
<pre>$ curl -L https://www.opscode.com/chef/install.sh | sudo bash chefをカールします
$ chef-solo -v 一応確認
</pre>
##クックブック作成
<pre>$ sudo knife cookbook create sample -o /var/chef/cookbooks</pre>
/var/chef/cookbooks/sample/recipes/default.rbを編集して、レシピを書きます
個人的なおすすめですが、sudoeditを使うと設定ファイル反映されます
パッケージをインストールするように追記します

```rb:default.rb
package "sample" do
  action :install
end
```

## 実行します
<pre>$ sudo chef-solo -o sample
$ rpm -q sample</pre>
Vagrantにaddされているものによりますが、私の環境ではCentOS向けのパッケージがインストールされていますので、rpmで確認します
なお、chefで使うことになるこのレシピですが、毎回同じ結果を与える思想の元に動きますので、実行するたびに何かがかわることはありません
とはいえ、勿論rubyのソースがエラーになっていたら話はかわってきますが、そうでない限りConverging 〜 resourcesというメッセージの通り、レシピに定義された状態にノードを収束させることを保証してくれます
UnityChanの状態と振る舞いを分けて管理する


[前回](http://qiita.com/mokemokechicken/items/f0ee1ee7bcf8dca19ed0) からの続きです。
いろいろあって１ヶ月ほど着手できなかったのですが、やっと落ち着いてきたので、さあ再開しようと思ったら、
久しぶりに見るコードがなかなか雑然としていたので、少し整理しました。

結果、こうなっています。
https://gist.github.com/mokemokechicken/dedb0e31825915fe15e9

**PlayerState** というClassを追加して、UnityChanの内部状態をそこで管理するようにします。
このClassは、以下の様な特徴があります。

* イメージは StateMachine
* UnityChanの状態を管理するが、振る舞いは管理しない
* Key Eventや衝突Eventを受け取り、状態を変化させる
* Eventの種類によって、 UnityChanの Action を呼び出したりする

ただ、ちゃんとしたStateMachineを実装しようとすると結構面倒なので、なんちゃってな感じになっています。
現状だと、ロジックは同じで場所だけ移動した感じになっています。。。
でもまあ、ちょっとは関心事が分離できたような気がします。

`Animator`とこの `PlayerState` はかなり役割が似ていますが、Animatorが状態遷移時にActionを呼んでくれたりはしなさそうなので、微妙にやりたいことができない感じです。

座標的な移動とAnimatorの制御を今後もう少し頑張りたいと思います。
iframe

## iframeを複数利用する方法

IEでは複数iframeを表示できたが、なぜかfirefoxやchromeでは１つ目のiframeしか表示されない。

* [Firefoxで複数のiframeを表示させる：Web Tips：So-net blog](https://naoichigo.blog.so-net.ne.jp/2011-03-16)

```php:回避策
<!--[if IE]>
<iframe src="〜" width="250" height="170"></iframe>
<![endif]-->

<!--[if !IE]>
<object type="text/html" data="〜" width="250" height="170"></object>
<![endif]-->
```

## chrome35のバージョンアップにともなうiframeの動作変更(?)

```html:
<iframe name="iframe1">
</iframe>
```

この領域に以下で中身を替えていたが、chromeがバージョンアップにともない
以下書き方はできなくなった。

```html:以下は動かなくなった
<script>
iframe1.location.href = "/url1/index.html";
```

```html:以下は動く
<script>
iframe1.src = "/url1/index.html";
```

参考
[firefoxでiframeをlocation.hrefしたい - Gpso.info 開発ブログ](http://blog.gpso.info/2006/09/firefoxiframelocationhref.html)


## iframeのinnerHTML取得方法

IEでは以下のように取得できていたが、firefoxでは取得できないことがわかった。

```js:以下はIE以外には対応していない
form1.contents.value = frames.frame1.document.body.innerHTML;
```

* 参考: [Javascript Iframe innerHTML - Stack Overflow](https://stackoverflow.com/questions/139118/javascript-iframe-innerhtml)

```js:修正版
function getIframeInnerHTML() {
	var form1 = document.frm1;
	if (typeof(frames.frame1.document) !== "undefined") {
		// IE
		return frames.frame1.document.body.innerHTML;
	} else {
		// firefoxなど
		var x = document.getElementById("frame1");
		var y = (x.contentWindow || x.contentDocument);
		if (y.document) {
			y = y.document;
		}
		return y.body.innerHTML;
	}
}
form1.contents.value = getIframeInnerHTML();
```
[ObjC][Xcode5] 簡単！Keychain Sharingで異なるアプリ間のデータ共有


けっこう簡単にできたのでメモ。

**「（同じプロビジョニングを使用した）異なるアプリ間でデータ共有する方法」**です。
KeychainSharingを利用するので、アプリを削除してもデータは消えません。
この領域に保存されたものは暗号化される？のでパスワードなどの保存領域として利用するものらしい。


##データを保存する側のプロジェクト作成

まずはデータを保存する側のプロジェクトを適当に名前をつけて作成。

![0_project](https://dl.dropbox.com/s/wauoaggobe51k77/0_project.png)

##KeyChainGroupのIDをつける


次にKeychain のグループIDを付けます。任意でOKです。
※ここでは「`jp.itoz.sample.TestKeyChainSharing`」としました。

他のアプリでも同じものを使います。

![1_keyChainIdSet](https://dl.dropbox.com/s/mh31pjntj75zxwf/1_keyChainIdSet.png)
 
上記グループIDが設定されると、「.entitlements」ファイルが出来ています。
中を覗いてみると、先ほどのIDの前に、$(AppIdentifierPrefix)が付加されていますね。
※このファイルを直接書き換えるとなんかエラるので触らないほうが良いのかも？。(よくわからないだれか教えて。。)

![2_entitlement](https://dl.dropboxusercontent.com/u/958512/_blog/romatica/resource/Xcode5KeyChaingSharing/2_entitlement.png)

##データを保存してみる

さっそくデータ保存してみます。
今回は、NSUserDefaultsのようにKeychainのデータにアクセスできるというライブラリ、[LUKeychainAccess](https://github.com/TheLevelUp/LUKeychainAccess) をつかってみます。
 
cocoapodで提供されているので、普通にPodfileを作成して `$pod install`します。

![3_lukeychainaccess](https://dl.dropbox.com/s/cq0tdw9um824nc5/3_lukeychainaccess.png)



インストール完了したらXcodeをワークスペースから開き直して、適当にAppDelegateとかイニシャルViewControllerとかで下記のコードを実行。

```objc


#import "LUKeychainAccess.h"
NSString * const kKeyDic = @"KEY_CHAIN_SHARING_KEY_DIC";

(略)

//--------------------------
//　適当なNSDictionaryを作成
//--------------------------
NSDictionary *userDic = @{
			  @"userName":@"itoz"
			, @"password":@"aaaaaaaaaaaaa"
			};
			
//--------------------------
// 保存
//--------------------------
[[LUKeychainAccess standardKeychainAccess] setObject:userDic forKey:kKeyDic];

```


##他のアプリからデータを取得

先ほどと同じ手順で、取得がわの別アプリを作成します。
再度新規プロジェクト作成し、cocoapodでLUKyechainAccessをインストールし、同じKeychainグループIDをセットします。

取得コードはこんな感じ

```objc

#import "LUKeychainAccess.h"
NSString * const kKeyDic = @"KEY_CHAIN_SHARING_KEY_DIC";

(略)
//--------------------------
// 取得
//--------------------------
NSDictionary *userDic = [[LUKeychainAccess standardKeychainAccess] objectForKey:kKeyDic];
			
NSLog(@"%@",userDic);

```

とすると、先ほどのアプリで保存したデータが取得できているのが、出力で確認できます！
すごい簡単！

![4_nslog](https://dl.dropbox.com/s/ansa7hiw0vmav8c/4_nslog.png)





##注意

この方法で保存すると、意図的に消さない限りデータは残り続けるのでそのへんは気にした方がいいかも。


##最後に

違うよ！もっとこうした方がいいよ！
などありましたらコメントいただけると嬉しいです。
Vagrant Saharaのcommitせずoffしたら元に戻るという誤解


# Vagrant Saharaについて

saharaはvagrant上で使えるプラグインです。
ご存知の通りゲストOSの状態をお試し設定した後、元の状態にロールバックするっていうことが可能になります。

[jedi4ever/sahara](https://github.com/jedi4ever/sahara)


# CommitせずにOffったら元に戻るんでしょっていう誤解

saharaに関して知識もなかったので当然いろんな紹介記事をみて使ってみました。

Googleで検索したいくつかのサイトにcommitしていないものはoffした時点で消える
ような記述があったのでそれを鵜呑みにして以下のようにやってみました。

```
# sahara開始
host$ vagrant sandbox on

# 仮想マシン起動
host$ vagrant up

# 仮想マシン接続して色々設定
host$ vagrant ssh
guest$ touch hoge
guest$ ls
hoge
guest$ exit

# ここでcommitせずにoffすれば元の環境に戻ると思ってた
host$ vagrant off

# 結果を確認してみる
host$ vagrant ssh
guest$ ls
hoge
 
```

あっるぅぇぇ〜？
offしたあとで中を覗いてみるとバッチリ情報が残っていますね。

おかしい、Google上位サイトにいくつも記述があったのだから間違っていないはず
きっと何か操作抜け漏れや間違いがあったのかなと思っていろいろ調べても
よくわかんない。

でも[こんな記事](http://ri.hateblo.jp/entry/2013/10/29/013359)もありました。

>コミットせずにsandboxをoffにするとcommitされたことになるっぽい．


# なにが正しいのかわからなくなってきたのでソースを読んでみる。

## saharaのディレクトリ構造

saharaはこんな感じのシンプルな構造です。

```
$tree sahara
sahara
├── Gemfile
├── README.md
├── Rakefile
├── lib
│   ├── sahara
│   │   ├── command
│   │   │   ├── commit.rb
│   │   │   ├── off.rb
│   │   │   ├── on.rb
│   │   │   ├── rollback.rb
│   │   │   ├── root.rb
│   │   │   └── status.rb
│   │   ├── errors.rb
│   │   ├── session
│   │   │   ├── factory.rb
│   │   │   ├── libvirt.rb
│   │   │   ├── parallels.rb
│   │   │   ├── virtualbox.rb
│   │   │   └── vmware.rb
│   │   └── version.rb
│   └── sahara.rb
├── locales
│   └── en.yml
└── sahara.gemspec
```

どうもlib/sahara/sessionに仮想化ソフト毎の処理が記述されていて
それをlib/sahara/command内のコマンドが1枚ラッパーとしてかぶさって
仮想化ソフトの違いを意識することなくon/off/rollbackなどをできるようになるらしい。

## virtualboxでのoff時の挙動を見てみる

使っているのはvirtualboxだったのでlib/sahara/session/virtualbox.rbを覗いてみる

[ここ](https://github.com/jedi4ever/sahara/blob/master/lib/sahara/session/virtualbox.rb)から見れます

```
#大事なとこだけ抜粋
def off
  `#{@vboxcmd} snapshot "#{@instance_id}" delete "#{@sandboxname}" `
end

def on
  `#{@vboxcmd} snapshot "#{@instance_id}" take "#{@sandboxname}" --pause`
end

def commit
  `#{@vboxcmd} snapshot "#{@instance_id}" delete "#{@sandboxname}"`
  `#{@vboxcmd} snapshot "#{@instance_id}" take "#{@sandboxname}" --pause`
end
```


まとめると、
- onの時は特定のスナップショットを作成する
- offの時は特定のスナップショットを削除する
- commitの時は特定のスナップショットを削除した上で特定のスナップショットを作成する

commitはつまりoff+onということになりますね

commitの動作が状態を保存することだとすると、offかonかのどちらかで状態を保存しなければなりませんが、この場合どう考えてもoffでやっていると思われます。

つまりスナップショットを削除しても状態は保存されている！ということになります。

ということはこの時点でoffすると状態が元に戻るっていう諸説は間違っているということになりますね。

#### 解析結果：offするとcommit（off+on)時同様状態は保存されます。



## なんでこうなった！

実はvirtualboxでスナップショットを多用していたのでここはすんなり納得出来ました。

そもそもsaharaなど使わずvirtualboxで手動でスナップショットをとって、削除をしてみたらすぐわかります。

削除するとそのスナップショットだけが完全になくなるのではなく、前後（どちらか不明）のスナップショットに内容がマージされるのです。


それもそのはず。

スナップショットは毎回差分だけを持っていますが、複数スナップショットがあって途中のスナップショットが完全になくなってしまってはそれ以前のスナップショットが無駄になってしまいます。

そのため削除するときには前後のスナップショットどちらかに情報をマージした上で目的のスナップショットを削除しているのですね。

## 結論；元に戻したいならかならずrollbackしてからoffしましょう

ということでoffで状態は元に戻りません。

以下のようにoff前にrollbackを必ずやりましょう。

```
$ vagrant sandbox on
$ vagrant sandbox up
$ vagrant sandbox ssh
・・・
# ここ重要
$ vagrant sandbox rollback
$ vagrant sandbox off
```

逆に重要そうなcommitなんてoffで代用できるので使う機会が半減します。
なんかいもこまめにon/offを繰り返しながら状態保存する必要がある場合にはcommitを使ったらコマンド数削減には役立つかもしれません。
JavaScript の簡単☆単体テスト（grunt + qunit）


# 概要

Chrome Extention やWebページ用のJSのコード書くときに使う単体テスト環境をサクッと用意したいと思って色々試しました。
今のところこれが個人的なベストです。
「もっと良いやり方があるよ！」という方、是非教えてください。真似させていただきます。

ちなみにqunitの概要についてはこちらのQiita記事が詳しいです。

* [Qunitの概要](http://qiita.com/ledsun@github/items/dee1f8d342147b714f56)


# 完成図

```
/ (プロジェクトフォルダ)
├── Gruntfile.js
├── node_modules/
├── package.json
├── src (ソースコードを入れる)
│   └── aaa.js
└── test (テストコードを入れる)
    ├── aaa.test.js
    └── index.html
```


# テスト環境の構築

サクッとやります。

## 前提

* Mac
* node, npmはインストール済み

## 事前準備

`grunt-cli` が入っていない人は以下のコマンドでインストールしておきましょう。

```
$ npm install grunt-cli -g
```

## 手順

```
$ mkdir (プロジェクトフォルダ名)
$ cd (プロジェクトフォルダ名)
$ mkdir src
$ mkdir test
$ npm init

# ウィザードが始まるので適当に答える

$ npm install grunt qunitjs grunt-contrib-qunit grunt-contrib-watch --save-dev

$ vim Gruntfile.js

# Gruntfileのひな形は後述

$ vim test/index.html

# test/index.html についての注意事項は後述
```



`Gruntfile.js` はこんな感じにしておきます。
`default` のタスクはご自由にお使いください。プロダクションコードを生成するタスクを登録しておくのが良いのではないでしょうか。

```javascript:Gruntfile.js
module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON("package.json"),
        qunit: {
            all: ["test/*.html"]
        },
        watch: {
            files: [
                "Gruntfile.js",
                "src/*.js",
                "test/*.js",
                "test/*.html"
            ],
            tasks: ["qunit"]
        }
    });

    grunt.registerTask("test", ["qunit"]);

    grunt.loadNpmTasks('grunt-contrib-qunit');
    grunt.loadNpmTasks('grunt-contrib-watch');
};
```

`test/index.html` は以下のようにしておきます。
ファイルパスにだけ注意しておきましょう。npmでインストールした `qunitjs` のファイルを見に行っています。
qunitをnpmでインストールしたのは私の好みなので、余計なパッケージを入れたくない方は[qunitのサイト](http://qunitjs.com)から落として来て入れれば良いと思います。

```html:test/index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>QUnit</title>
  <link rel="stylesheet" href="../node_modules/qunitjs/qunit/qunit.css">
</head>
<body>
  <div id="qunit"></div>
  <div id="qunit-fixture"></div>
  <!-- 開発したソースコードをこの辺りに -->
  <script src="../src/aaa.js"></script>

  <script src="../node_modules/qunitjs/qunit/qunit.js"></script>
  <!-- テストコードをこの辺りに -->
  <script src="./aaa.test.js"></script>
</body>
</html>
```

# 環境が整ったら

あとは好きなようにコードを書いてテストしていきます。

```
$ grunt watch

# 後はお好きにコードを書いてください
# src/ または test/ 以下のjsファイルやhtmlファイルが変更されると、勝手にテストが走ります
# grunt watch の終了は Ctrl + C でどうぞ
```

それでは、快適なJSの単体テストライフを！
MacをAppleStoreに修理出して戻ってきたら、タイムゾーンが変わっていて焦った。

時折修理等出すと、修理から戻ってきた時にタイムゾーンがリセットされます（されることがあります）。

USキーボードのMacを使っているからか、アメリカ時間に設定され
Chromeから何を開こうとSSLエラーが起こりますが、

システム環境設定からタイムゾーンを'日本'にしてあげると
正常に動作します。

これはTipsなのでいざその時になったらこれを見つけることはできないと思いますが
あたまの片隅に入れておいてください。
cocos2d-x v3.0 公式版 開発環境整える(for Mac 10.9-)

アプリ作るもので選択したcocos2d-x

2014/04/25に、ベータ版からどうやら安定版になっているようなので開発環境だけ整えておこうと思う。
http://www.cocos2d-x.org/news/216
#前提
### IDE
1. Android : eclipse
2. iOS : Xcode

### TOOLS
1. cocos2d-x 3.0 
http://www.cocos2d-x.org/download
2. Android-NDK
http://developer.android.com/tools/sdk/ndk/index.html#Installing
3. Android-SDK
http://developer.android.com/sdk/index.html 

#パス設定をやってない人はこちら（Android周りのパスです）

/.bash_profile設定
<pre>ANDROID_NDK=個々のパス入れる/android-ndk-r9d
export PATH=$PATH:${ANDROID_NDK}

ANDROID_SDK=個々のパス入れる/adt-bundle-mac-x86_64-20140321/sdk
export PATH=$PATH:${ANDROID_SDK}

export NDK_ROOT="$ANDROID_NDK"
export SDK_ROOT="$ANDROID_SDK"</pre>
という形でやっておいて

<pre>$ source ~/.bash_profile</pre>
これで読み込みでおk

#cocos2d-xのインストール
1. eclipseにcocos2dxのパスを設定します/general/workspace
2. 同じようにAndroidの方も設定/C/C++/build/environment
3. sdk/tools/androidを実行しますとAndroid SDK マネージャを開けます

##必要なものは
1. setup.pyにあるパスが通っていること
2. sdk/ndkのrootパス
3. ant

そのあとは、コマンドをターミナルへ
<pre>$ cocos new MyGame -p com.your_company.mygame -l cpp -d NEW_PROJECTS_DIR
$ cd NEW_PROJECTS_DIR/MyGame
$ cocos run -p mac</pre>
後はeclipseにそのプロジェクト追加してAndroidのライブラリにcocos2dxを追加すればok

 

ect...
## メモ
基本の流れはver2.3とかと同じでただObjective-Cとの互換性を軽視している傾向があるみたい。個人的にはC++よりになってほしいのでこれはありがたいnewsだ

なお、Androidを開発する場合C++のコードはライブラリ化されていてブレークポイントはセットできませんのでデバッグが面倒

* 開発

Androidの場合は./ClassesにC++のファイルを追加していく 

* 注意点

Xcodeの場合は、ファイルを追加しないとディレクトリに入ってこない
最新のiTunesでTitanium のビルドの際に出来るipaファイルがインストール出来ない

Twitterにも書きましたが、ググっても全然情報が見つからずに途方にくれたのでシェアしておきます。

Titanium で開発していると Ad-Hoc の配布は簡単です。

Titanium Studio や CLI でターゲットデバイスのUUIDを含んだプロビジョニングプロファイルで手元の実機にビルドすると、以下のディレクトリにipaファイルが出来るから、それをシェアするだけで済みます。

```
YourProject/build/iphone/build/Debug-iphoneos/YourProject.ipa
```

通常はこの方法で問題無いのですが、先日こんなエラーが表示され、ipaをインストール出来なくなりました。

 「エラーが起きたため、App"YourPorject"を iTunes ライブラリ に追加できませんでした。 メモリが不足しています。」

![エラー.png](https://qiita-image-store.s3.amazonaws.com/0/27892/b7871986-ee95-6b95-0861-335123c05ac4.png)

勿論メモリもSSD/HDDにも余裕は有ります。

iTunesライブラリ削除、コンピュータの認証・AppleIDの認証を外す・入れるを、アンチウィルスソフトをオフ、別の実機、iTunes再インストールと色々試しましたが変わず。


原因の方は、最近のAppceleratorのブログで知りました。
[Device deployment broken by recent iTunes update 11.2](http://www.appcelerator.com/blog/2014/05/device-deployment-broken-by-recent-itunes-update-11-2/)


JIRAでチケットも切られてて、既にFixedな様です。次のマイナーバージョンアップで治る筈です。
[[TIMOB-16987] iTunes 11.2 (114) Shows an error when trying to copy the build app - Appcelerator JIRA](https://jira.appcelerator.org/browse/TIMOB-16987)



回避策としては、ターゲットデバイスの持ち主にiTunesのバージョンアップを自粛してもらう・・・ではなくて、ちゃんとAd-Hoc Distribution用のプロビジョニングプロファイルを作って、Titanium Studio で[プロジェクトを副クリック] - [Publish] - [Distribute Ad Hoc/Enterprise] からビルドすると大丈夫でした。

![スタジオ.png](https://qiita-image-store.s3.amazonaws.com/0/27892/57a7c755-53e1-e014-d5da-a2e11829b310.png)
JavaScriptライブラリSugar

## はじめに

ようやく業務アプリの制作環境が整ってきました。

フロントエンドは
メインが[AngularJS](https://angularjs.org/)
補助ライブラリに[Sugar](http://sugarjs.com/)

バックエンドは
メインがPHP
データベースがMySQL
フレームワークに[Slim](http://www.slimframework.com/)
データベースライブラリに[Idiorm](https://github.com/j4mie/idiorm)

この構成による[SPA](http://www.oreilly.co.jp/books/9784873116730/)です。
SPAいいですね。[Flex](http://www.adobe.com/jp/products/flex.html)が望んで叶えられなかった夢の到達点のような感じがします。

## Sugarとは

JavaScriptの弱い点である、文字列・配列・日時などの操作を強化するライブラリです。

同じようなライブラリに[Underscore.js](http://underscorejs.org/)がありますが、Sugarのほうが非常に直感的に使えてなじむ感じです。あと日本語にとても強いです。

## Sugarの使い方

実は[公式サイト](http://sugarjs.com/api)がおそろしく良く出来ているのでほとんど説明するところがありません。公式サイトで直接編集して実行することができます。

以下蛇足です。

## 曜日を表示

```js
Date.create('2014-05-24');
```

で指定された日付のDateオブジェクトを得ることができます。例えば曜日を出したい場合は

```js
Date.create('2014-05-24').format('{weekday}', 'ja');
```

```text:結果
土曜日
```

このような感じで日本語の曜日が出ます。文字列操作も格段にパワーアップしていますので、

```js
Date.create('2014-05-24').format('{weekday}', 'ja').first();
```

```text:結果
土
```

と切り出したりするのも簡単です。

## 配列を回す

みんなだいすきforeachも直感的に

```js
[1,2,3,4].each(function(n) {
  // n: 1, 2, 3, 4
});
```

## 二次元配列の表から指定されたIDの行を見つけ出す

```js
[
  {id:1, name:'鈴木'},
  {id:2, name:'山田'},
  {id:3, name:'勅使河原'}
].find(function(n) {return n['id'] == 2;});
// -> {id:2, name:'山田'}
```

これと日付操作のために導入しました。

## 注意点

そんなわけでSugarオススメですが、ネイティブオブジェクトを拡張しているので、他のライブラリとぶつからないように注意する必要はあります。
Vagrant セットしてみた

開発PCは OS X -v10.9.3です

お暇な方は見て行って下さい
今回は、環境構築と少しコマンドを紹介します
とはいえ説明も適当なんで参考程度にチラ見レベルでいいかと思います

# いんすとーる
VertualBox 4.3.12 
https://www.virtualbox.org/wiki/Downloads
Vagrant 1.6.2
http://www.vagrantup.com/downloads.html

# Vagrantとは
簡単に言えば、単純コマンドの発行で、仮想サーバを立ち上げて、要らなくなったら壊して、また必要時に作って、と言った用途で使うらしいです
あ、一応読み方は(べいぐらんと)です
こんな用途で自分のサービスにも適用しようかなと思い立ち使ってみることにしましたとさ
なお、環境構築は普段エンジニアやってれば迷うことなくできるはずです
#実際にやってみる
それでは、VertualBoxで監視しながらコンソールにかたかたと打ち込みます
## 仮想イメージの取得
<pre>$ vagrant box add opscode-centos-6.5 http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5_chef-provisionerless.box</pre>
数分かかりますが、気長に待ちましょう
git からcloneしてくるのも時間かかりますねOSのイメージファイルなんで
##仮想サーバ起動・ログイン
<pre>$ vagrant init opscode-centos-6.5 ➡ Vagrantfileを作成します ➡ Vagrantfileを編集してprivate-ipを変更することも可能
$ vagrant up
$ vagrant ssh-config --host 「hostname」 >> ~/.ssh/config
$ vagrant ssh「hostname」</pre>
## 仮想イメージの停止・破棄
<pre>$ vagrant halt  ➡ この後 $ vagrant up で再起動
$ vagrant destroy</pre>


Vagrantオンリーだとあまり恩恵がないので、次は何かと組み合わせて紹介します

キーマップ系変更

```
$ sudo loadkeys jp106
Loading /usr/share/keymaps/i386/qwerty/jp106.kmap.gz
$ sudo loadkeys us
Loading /usr/share/keymaps/i386/qwerty/us.kmap.gz
```
Clojureのvectorに対するlastは遅い

ので、vectorだとわかっている場合はpeekを使うといい

```vector_peek.clj
(def s (doall (range 2000000)))
(def v (vec s))
(def l (apply list s))

(time (first s))
(time (first v))
(time (first l))
(time (last s))
(time (last v))
(time (last l))
(time (nth s (dec (count s))))
(time (nth v (dec (count v))))
(time (nth l (dec (count l))))
(time (get v (dec (count v))))
(time (peek v))
```

```
Elapsed time: 0.007123 msecs
Elapsed time: 0.005308 msecs
Elapsed time: 0.003352 msecs
Elapsed time: 191.406869 msecs
Elapsed time: 129.120391 msecs
Elapsed time: 77.368283 msecs
Elapsed time: 243.091859 msecs
Elapsed time: 0.006216 msecs
Elapsed time: 29.659985 msecs
Elapsed time: 0.093308 msecs
Elapsed time: 0.006775 msecs
```
PHPで壊れたHTMLを整形する

# **整形したいデータ**

以下の壊れたHTMLが `$html` に代入されているとします。

```html:テストデータ
<html>
<p>
<a href="http://google.com/?q=あいうえお">あいうえおで検索</a>
<br>
<img src="hoge.jpg" alt="<'あいうえお'>">
A & B ><
<p></p>
```

# **整形する方法**

## **[Tidy](http://www.php.net/manual/ja/book.tidy.php)** を使う

最も「イイカンジ」に整形してくれて尚且つ実行速度も速いものはこれだと思います。但し、環境によっては拡張インストールが必要です。

```php:テストコード
echo tidy_repair_string($html, ['indent' => true], 'utf8');
```

```html:出力結果

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
  <head>
    <title></title>
  </head>
  <body>
    <p>
      <a href=
      "http://google.com/?q=%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A">
      あいうえおで検索</a><br>
      <img src="hoge.jpg" alt="&lt;'あいうえお'&gt;"> A &amp; B &gt;&lt;
    </p>
  </body>
</html>
```

何で `indent-attributes` 有効化してないのに `href` の後で改行されてるんですかねぇ(憤怒
 
## **[HTML Purifier](http://htmlpurifier.org/)** を使う

ホワイトリスト方針のため、XSS防止における信頼性は抜群です。但し、ライブラリの設置が必要です。

```php:テストコード
使った事が無くて最適なオプションを設定できる自信がないので誰か編集リクエストお願いします
```

```html:出力結果
使った事が無くて最適なオプションを設定できる自信がないので誰か編集リクエストお願いします
```

## **[DOM](http://www.php.net/manual/ja/book.dom.php)** を使う

インデントを整えられないなど動作にやや不十分な点がありますが、拡張インストールやライブラリ無しで使えるメリットは大きいでしょう。

```php:関数定義
function dom_repair_string($html) {
    static $dom;
    static $conv;
    static $rev;
    if ($dom === null) {
        $dom = new DOMDocument;
        $conv = function ($html) {
            return mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');
        };
        $rev = function ($matches) {
            return mb_convert_encoding($matches[0], 'UTF-8', 'HTML-ENTITIES');
        };
    }
    @$dom->loadHTML($conv($html));
    return preg_replace_callback('/(?:&#\d++;)++/', $rev, $dom->saveHTML());
}
```

```php:テストコード
echo dom_repair_string($html);
```

```html:出力結果
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p>
<a href="http://google.com/?q=%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A">あいうえおで検索</a>
<br><img src="hoge.jpg" alt="&lt;'あいうえお'&gt;">
A &amp; B &gt;</p></body></html>
```
VBAマクロ不要! excelのREPT関数で簡易ガントチャート

##![無題.png](https://qiita-image-store.s3.amazonaws.com/0/2639/17fae0da-e2dd-37d3-3bef-93002ea02b26.png)

#ポイント
##Excelでは日付や時刻はシリアル値で処理されます。
|型|例|
|----|------------------------------------------|
|日付|1900年1月1日=「1」,1900年1月2日=「2」        |
|時刻|「24:00」=「1」、12:00=「0.5」、6:00=「0.25」|

##REPT()関数
```
=REPT(" ",A1*24*2)&IF(A1=B1,"|",REPT("|",(B1-A1)*24*2))
```
「プログラムでシダを描画する」をGoで描画する

「プログラムでシダを描画する」記事たちに触発されて、Goで書いてみました。

* [プログラムでシダを描画する - 強火で進め](http://d.hatena.ne.jp/nakamura001/20140505/1399316565)
* [「プログラムでシダを描画する」をDartで描画する - Qiita](http://qiita.com/zukkun/items/08b72c9934d3c0c09936)

**ファイル「shida.png」に出力した結果**

![shida.png](https://qiita-image-store.s3.amazonaws.com/0/31857/814556d9-4af3-897a-946e-159e289d0ce6.png)

**ソースコード**

* 変数については、見やすさを重視して型を表記しました。
* 変数 `N` は、オリジナルを踏襲して大文字のままにしています。
* 乱数は `rand.Float64()` としました。

```go:shida.go
package main

import (
	"image"
	"image/color"
	"image/draw"
	"image/png"
	"log"
	"math/rand"
	"os"
	"time"
)

var (
	N  int     = 20
	xm float64 = 0.0
	ym float64 = 0.5
	h  float64 = 0.6
)

var (
	width    int    = 500
	height   int    = 500
	filename string = "shida.png"
)

var (
	bgcolor   color.Color = color.RGBA{255, 255, 255, 255}
	linecolor color.Color = color.RGBA{0, 128, 0, 255}
)

func W1x(x, y float64) float64 {
	return 0.836*x + 0.044*y
}

func W1y(x, y float64) float64 {
	return -0.044*x + 0.836*y + 0.169
}

func W2x(x, y float64) float64 {
	return -0.141*x + 0.302*y
}

func W2y(x, y float64) float64 {
	return 0.302*x + 0.141*y + 0.127
}

func W3x(x, y float64) float64 {
	return 0.141*x - 0.302*y
}

func W3y(x, y float64) float64 {
	return 0.302*x + 0.141*y + 0.169
}

func W4x(x, y float64) float64 {
	return 0
}

func W4y(x, y float64) float64 {
	return 0.175337 * y
}

func f(m *image.RGBA, k int, x, y float64) {
	if 0 < k {
		f(m, k-1, W1x(x, y), W1y(x, y))
		if rand.Float64() < 0.3 {
			f(m, k-1, W2x(x, y), W2y(x, y))
		}
		if rand.Float64() < 0.3 {
			f(m, k-1, W2x(x, y), W2y(x, y))
		}
		if rand.Float64() < 0.3 {
			f(m, k-1, W3x(x, y), W3y(x, y))
		}
		if rand.Float64() < 0.3 {
			f(m, k-1, W4x(x, y), W4y(x, y))
		}
	} else {
		var s float64 = 490.0
		m.Set(int(x*s+float64(width)*0.5), int(float64(height)-y*s), linecolor)
	}
}

func main() {
	rand.Seed(time.Now().Unix())

	m := image.NewRGBA(image.Rect(0, 0, width, height))
	draw.Draw(m, m.Bounds(), &image.Uniform{bgcolor}, image.ZP, draw.Src)

	f(m, N, 0, 0)

	file, err := os.Create(filename)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	err = png.Encode(file, m)
	if err != nil {
		log.Fatal(err)
	}
}
```

**pngファイルを作成する際に参照したサイト**

* [Golang Cafe #10 まとめ imageパッケージをみる - taknb2nchのメモ](http://d.hatena.ne.jp/taknb2nch/20131231/1388500659)
* [image/draw/main.go at master · golang-samples/image · GitHub](https://github.com/golang-samples/image/blob/master/draw/main.go)
* [The Go image/draw package - The Go Blog](http://blog.golang.org/go-imagedraw-package)
* [raytrace-etude/msx at master · koron/raytrace-etude · GitHub](https://github.com/koron/raytrace-etude/tree/master/msx)
iOS7でセクションインデックスを設定すると編集モードの削除ボタンの表示が乱れる


#現象
セクションインデックスを指定して編集モードにして削除しようとすると下記画像のようにセクションインデックスの下に描画されてしまいます。

![20140524-1_convert_20140524015323.png](https://qiita-image-store.s3.amazonaws.com/0/37947/340b8e61-7a88-e6d6-66b6-cb0f13cc07c5.png "20140524-1_convert_20140524015323.png")

いい解決策が見つからなかったのでとりあえず編集モード時はセクションインデックスを表示しないようにしました。
解決策が判明次第、記事を更新したいと思います。

```
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
    [super setEditing:editing animated:animated];
    [self.tableView reloadSectionIndexTitles];
}

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
    if (self.editing) {
        return nil;
    }
    return @[@"あ", @"か", @"さ", @"た", @"な", @"は", @"ま", @"や", @"ら", @"わ"];
}
```

#追記
セクションインデックスの背景色を透明にする方法もありますが、データがある行の罫線がセクションインデックスのある部分で表示されなくなってしまいます。

```self.tableView.sectionIndexBackgroundColor = [UIColor clearColor];```

![20140524-2_convert_20140524234627.png](https://qiita-image-store.s3.amazonaws.com/0/37947/88c37702-e04f-aaba-ddea-564f083b3ac6.png "20140524-2_convert_20140524234627.png")

#解決
追記の対応（セクションインデックスの背景色を透明にする）＋
セル罫線のインデントをなくす事で正常に表示されるようになりました。やれやれです(^^;

```[UITableViewCell appearance].separatorInset = UIEdgeInsetsZero;```

![2014-05-25-1_convert_20140525223910.png](https://qiita-image-store.s3.amazonaws.com/0/37947/0fe44c81-7432-77ba-6696-364392406c66.png "2014-05-25-1_convert_20140525223910.png")
Fortran2003 Cheat Sheet

![fort03_01.png](https://qiita-image-store.s3.amazonaws.com/0/44522/0aef6089-1469-c8ff-5e92-cd798e8920d8.png)
![fort03_02.png](https://qiita-image-store.s3.amazonaws.com/0/44522/63c0f447-fb3c-ce0c-c0c6-9881b94dca41.png)
![fort03_03.png](https://qiita-image-store.s3.amazonaws.com/0/44522/aa5116af-4d25-bfa5-6369-0be94515c3ed.png)
![fort03_04.png](https://qiita-image-store.s3.amazonaws.com/0/44522/12b7efc0-92cc-52b7-10bc-42ea534f830a.png)

豆本となります。下図参照。
![9ba82789.jpg](https://qiita-image-store.s3.amazonaws.com/0/44522/75624893-6dd2-e3c0-ce7d-26d4d628e6d6.jpeg)
イメージを勝手ながらお借りしました。感謝。
http://blog.livedoor.jp/m_kanata/archives/51169763.html
【Sublime Text 2】プロジェクト内の特定ファイルを常に実行する

Sublime Text 2で作成したプロジェクト内の特定ファイルを実行する方法です。（設定なしで Command+B だと開いているファイルを常に実行してしまう）

メニューから「Project > Edit Project」で、"build_systems"を以下のように設定すると、常にプロジェクトのルートにある「app.py」を実行します。そしてプロジェクトファイルをルートディレクトリとします。

## 設定ファイル

```
{
	"folders":
	[
		{
			// 名前
			"name": "stg001",
			// プロジェクトに含めるディレクトリ
			"path": ".",
			// 除外するディレクトリ
			"folder_exclude_patterns": [".ropeproject"],
			// 除外するファイル
			"file_exclude_patterns": ["*.bmp", "*.png", "*.wav", "*.ogg", "*.sublime*"]
		}
	],
	// プロジェクト固有の設定
	"settings":
	{
		"tab_size": 4
	},
	// プロジェクト固有のビルド設定
	// 参考(http://y-anz-m.blogspot.jp/2012/11/sublime-text-2-typescript.html)
	"build_systems":
	[
		{
			"name": "stg001",
			// app.py を常に実行
			"cmd": ["python", "-u", "$project_path/app.py"],
			// プロジェクトファイルがあるフォルダをルートにする
			"working_dir": "$project_path",
			"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
			"selector": "source.python"
		}
	]
}
```

## 参考

Sublime Text 2 で TypeScript をビルドする
* http://y-anz-m.blogspot.jp/2012/11/sublime-text-2-typescript.html
Codereterat参加者のみなさまへ


このドキュメントはCoderetreatの参加者の皆様にお伝えしておきたい持ち物や開発環境の整え方をまとめたページです。

## 当日の持ち物

- (開発環境入り)ノートPC
- ACアダプタ

## ユニットテスト環境の構築メモ

プログラミング言語の実行環境以外に、ユニットテストができる環境を整えておくと開発が捗ります。各言語ごとにまとめました。もっと良いページがあれば、コメントをおねがいします。

| 言語 | ライブラリ | 参考ページ |
|--------|--------|--------|
| Java | JUnit/Eclipse | http://qiita.com/y-matsuda/private/c5cee6cc1b368a01cc9f |
| PHP  | PHPUnit | http://qiita.com/d9magai@github/items/026380f99cd17306d23c |
| Ruby | RSpec   | http://qiita.com/luckypool/items/e3662170033347510c3c |
| Python | unittest   | http://momijiame.tumblr.com/post/19516096498/python |
| Python | nose   | http://momijiame.tumblr.com/post/23042509434/python-nose |
| JavaScript | jasmine   | http://qiita.com/d9magai@github/items/b7f2b6df7c9ba3c418d1 |
| JavaScript | mocha   | http://tmlife.net/programming/javascript/javascript-test-framework-mocha-usage.html |
| C    | CUnit | http://codezine.jp/article/detail/1075 |
| C++    | GoogleTest | http://qiita.com/kuchida1981/items/9bb8fa4cc04635e7e909 |
| C#    | Visual Studioに付属 | http://www.tdd-net.jp/2013/12/tdd-c-tddadvent.html |
| Delphi    | DUnit | http://www.gesource.jp/weblog/?p=4673 |
| Perl    | CUnit | http://gihyo.jp/dev/feature/01/test-perl/0001 |
標準出力を受けて保存するファイル名に日付や時刻を含める

`date`コマンドの`+`以降に出力フォーマットを指定します。
このdateコマンドをバッククオート\`\`内に入れれば、dateコマンドの実行結果が引き継がれます。
##`result月日時分.txt`
例えば`test.rb`の実行結果を`result月日時分.txt`（月日時分は各2桁）という形式のファイル名で保存する場合には

```
$ ruby test.rb > result`date +%m%d%H%M`.txt
```
とします。
##参考
* [Man page of DATE](http://linuxjm.sourceforge.jp/html/GNU_coreutils/man1/date.1.html)
* [Amazon.co.jp： シェルの基本テクニック <ホップ・ステップ・ジャンプ> Linux world favorite series: 西村 めぐみ: 本](http://www.amazon.co.jp/dp/487280225X)
rescue_fromの走査は下から上だった。

どうも思った通りにrescue_fromが例外を捕まえないと思ったら、下記だった。

http://api.rubyonrails.org/classes/ActiveSupport/Rescuable/ClassMethods.html
> They are searched from right to left, from bottom to top, and up the hierarchy. 

> 右から左、下から上へ、そして継承を遡って検索される。

ずっとこの辺りのコードを弄っていなかったのだが、なぜ今まで想定通りに動いていたのだろうか…謎だ。


```rb
class ApplicationController < ActionController::Base

  # ...

  # ハンドルしきれなかったエラーは500エラー扱い
  # 評価は右から左、下から上へなされるのでこの場所で良い。
  # @see http://api.rubyonrails.org/classes/ActiveSupport/Rescuable/ClassMethods.html
  rescue_from Exception, :with => :render_500

  # その他細々したエラーをハンドル
  rescue_from ActionController::RoutingError, ActiveRecord::RecordNotFound, :with => :render_404
  rescue_from ActiveRecord::RecordNotUnique, :with => :render_409
  rescue_from UnauthorizedError, :with => :render_401
  rescue_from IllegalAccessError, :with => :render_403

  # 500エラーのハンドラ
  def render_500(exception = nil)
    handle_error(exception , 500)
  end

  # ... 他のエラーのハンドラも作る

end
```
Androidのエミュレータが遅い時は


IntelHAXMをインストールしてお試しください。

まずはAndroid SDKを起動しましょう。
Android Studioならこんなアイコンです。

![スクリーンショット 2014-05-23 23.37.55.png](https://qiita-image-store.s3.amazonaws.com/0/6061/29fe89f1-a3eb-2d57-00f4-01f757a518c3.png "スクリーンショット 2014-05-23 23.37.55.png")

Android SDK Managerが起動したら（おそらく一番下に位置している）`Intel x86 Emulator Accelarator (HAXM)`
を選択してインストールしましょう。
![スクリーンショット 2014-05-23 23.37.50.png](https://qiita-image-store.s3.amazonaws.com/0/6061/f7b216dd-7fc5-f84f-1e0f-357abb3020a3.png "スクリーンショット 2014-05-23 23.37.50.png")

インストールできたらディレクトリを開きます。
先ほどのAndroid SDK Managerに`SDK Path`が載っていますので、まずはこのディレクトリに移動します。

```
$ cd {ANDROID_SDK_PATH}
#上記画像なら→ $ cd /Applications/Android\ Studio.app/sdk/
```

ディレクトリに移動したら`IntelHAXM`をインストールしていきます。（Android SDKでのインストールは「インストーラの準備」だけのようです…）

```
$ open extras/intel/Hardware_Accelerated_Execution_Manager/IntelHAXM_1.0.8.dmg
```

以下のようにインストーラが開くと思います。

![スクリーンショット 2014-05-23 23.49.44.png](https://qiita-image-store.s3.amazonaws.com/0/6061/8ac4e1e7-682e-8261-f2bd-519874f955bc.png "スクリーンショット 2014-05-23 23.49.44.png")

上記インストールが終了したら対応するAndroidエミュレータを作成して実行します。
ここで言う「対応する」とはAndroidエミュレータのCPUを以下の画像のようにIntelにするだけです。（Android SDK Managerで`Intel x86 ...`というイメージをダウンロード済みでないと設定できないです）

![スクリーンショット 2014-05-23 23.51.11.png](https://qiita-image-store.s3.amazonaws.com/0/6061/987ab7d5-5457-da2c-6de5-db23b94eeec4.png "スクリーンショット 2014-05-23 23.51.11.png")

あとは実行するだけです！
実行時に以下のログが表示されていれば成功です。おそらくかなりサクサク動作するようになるはずです！

```
HAX is working and emulator runs in fast virt mode
```

以上です。
Goutteでスクレイピングする方法めも


単にスクレイピングするだけならSymfony2の機能テストと基本的に同じ

直接URLにアクセスする
---------------

```php
$client = new \Goutte\Client();

// GET
$client->request('GET', 'http://example.com/some/url');

// POST
$client->request('POST', 'http://exmaple.com/some/post/url', ['foo' => 'bar'], ['image' => '/var/www/myimage.jpg']);
```

アクセス先の特定のタグの内容・属性を取得する
-----------------------------------

```php

$client = new \Goutte\Client();

// $crawlerは\Symfony\Component\DomCrawler\Crawler
$crawler = $client->request('GET', 'http://example.com/some/url');

// <h1>this is header!</h1>タグの内容
$crawler->filter('h1')->text(); // →this is header!

// <h2><a href="./subpage.html">サブタイトル</a></h2>タグのhref属性
$crawler->filter('h2 a')->attr('href'); // →./subpage.html

// <ul><li>test1</li><li>test2</li></ul> 全部のliタグの内容
$lists = $crawler->filter('ul li')->each(function(Crawler $node){
    return $node->text();
});
// → $listsは['test1', 'test2']

// 取得したHTML全体
$crawler->html();

```

アクセス先にあるリンクをクリックする
-----------------------------------

```php
$client = new \Goutte\Client();

// まずリンクのあるURLにアクセス
$crawler = $client->request('GET', 'http://example.com/some/url');

// 「ここをクリック」をクリックしてリンク先に遷移
$client->click($crawler->selectLink('ここをクリック')->link());

```

アクセス先にあるフォームを送信する
--------------------------------

```php
$client = new \Goutte\Client();

// まずフォームのあるURLにアクセス
$crawler = $client->request('GET', 'http://example.com/some/form');

// 「ログイン」というボタンクリックで送信されるフォームを選択
$form = $crawler->selectButton('ログイン')->form();
$form['username'] = 'testuser';
$form['password'] = 'mypassword';
$crawler->submit($form);

```

URLにアクセスしてステータスコードを調べる
----------------------------

```php
$client = new \Goutte\Client();

$client->request('GET', 'http://example.com/good/url');
$client->getResponse()->getStatus(); // →200

$client->request('GET', 'http://example.com/bad/url');
$client->getResponse()->getStatus(); // →404

// $client->getResponse()は\Symfony\Component\BrowserKit\Response
```

アクセス時に使うUserAgentを設定する
-------------------------

```php
$client = new \Goutte\Client();

// UserAgentを"MyCrawler 1.0"に設定
$client->setHeader('User-Agent', 'MyCrawler 1.0');

$client->request('GET', '...'); // MyCrawler 1.0としてアクセス
$client->request('POST', '...'); // MyCrawler 1.0としてアクセス

// 以後、再度setHeader('User-Agent')で何か違うUAを設定するまでずっとこのまま
```
使用可能Bluetooth一覧を取得

## Bluetoothデバイスを一覧取得

使用可能なBluetoothが見つかった場合、ListViewにaddしていく

見つかり次第
adapter.notifyDataSetChanged();	listview.smoothScrollToPosition(adapter.getCount());
でListViewの更新と一番下まで自動でスクロールしている。

```java:MainActivity.java
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
 
public class MainActivity extends Activity {
 
	private ListView mListView;
	private ArrayAdapter<String> mAdapter;
	private BluetoothAdapter mBluetoothAdapter;
	private BroadcastReceiver mBluetoothSearchReceiver = new BroadcastReceiver(){
		@Override
		public void onReceive(Context context, Intent intent) {
			if(BluetoothDevice.ACTION_FOUND.equals(intent.getAction())){
				// 取得したbluetooth情報を取得
				BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);				
				mAdapter.add(device.getAddress());
				mAdapter.notifyDataSetChanged();
				mListView.smoothScrollToPosition(mAdapter.getCount());
			}
		}
	};
 
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		mListView = (ListView)findViewById(R.id.listView);
		mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
		mListView.setAdapter(mAdapter);
		mListView.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view,int position, long id) {				
			}
		});
		
		IntentFilter bluetoothFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
		registerReceiver(mBluetoothSearchReceiver, bluetoothFilter);
		
		mBluetoothAdapter = mBluetoothAdapter.getDefaultAdapter();
		mBluetoothAdapter.startDiscovery(); //検索開始
	}
	
	@Override
	protected void onDestroy(){
		super.onDestroy();
		mBluetoothAdapter.cancelDiscovery(); //検索キャンセル
		unregisterReceiver(mBluetoothSearchReceiver); //filter解除
	}
}
```
「第20回オフラインリアルタイムどう書くの問題」をPHPで解く

http://qiita.com/Nabetani/items/5791f8ae1bb5d069a49b
http://nabetani.sakura.ne.jp/hena/ord20meetime/

会議に都合のいい時間を探します。

```php
<?php

	class MEETING{
		/**
		* ミーティングの時間
		* @param String 「A1000-1130,B1230-1800,Z0800-2200」みたいな文字列
		* @return String 「1130-1230」みたいな文字列
		*/
		public function get($input){
			// 初期値
			$all1 = str_repeat('1', 480);
			$freetime = ['A'=>$all1, 'B'=>$all1, 'I'=>$all1, 'J'=>$all1, 'Z'=>$all1];
			$starttime = mktime(10, 0, 0);
			
			// 入力値を整形
			$input = explode(',', $input);
			
			// 都合の悪い時間帯は0にする
			foreach($input as $val){
				$start = (mktime(substr($val, 1, 2), substr($val, 3, 2), 0) - $starttime)/60;
				$end   = (mktime(substr($val, 6, 2), substr($val, 8, 2), 0) - $starttime)/60;
				if($start < 0){ $start = 0; }elseif($start>480){ $start=480; }
				if($end < 0){ $end = 0; }elseif($end>480){ $end=480; }
				for($i=$start; $i<$end; $i++){
					$freetime[$val[0]][$i] = 0;
				}
			}
			
			// GMPにする
			foreach($freetime as $key=>$val){
				$freetime[$key] = gmp_init($val, 2);
				// Zのみビット反転
				if($key==='Z'){
					$freetime[$key] = gmp_xor($freetime[$key], gmp_init($all1, 2));
				}
			}
			
			// 全員'1'が60回続く箇所を見つける
				// ABIZで一番早い時間
				$andi = sprintf('%0480s', gmp_strval(gmp_and(
					gmp_and($freetime['A'], $freetime['B']),
					gmp_and($freetime['I'], $freetime['Z']) ), 2));
				$starti = strpos($andi, str_repeat('1', 60));
				// ABJZで一番早い時間
				$andj = sprintf('%0480s', gmp_strval(gmp_and(
					gmp_and($freetime['A'], $freetime['B']),
					gmp_and($freetime['J'], $freetime['Z']) ), 2));
				$startj = strpos($andj, str_repeat('1', 60));
				// どっちも無ければ解なし
				if($starti === false && $startj === false){ return '-'; }
			
			// 整形して返却
				$start = $starti===false ? $startj : ( $startj===false ? $starti : min($starti, $startj));
				$return date('Hi', $starttime + $start*60) . '-' . date('Hi', $starttime + $start*60+3600);
		}
		
	}
	
	// 以下はテスト
	$test = [
		['A1050-1130,B1400-1415,I1000-1400,I1600-1800,J1100-1745,Z1400-1421,Z1425-1800', '1425-1525'],
		['A1000-1200,B1300-1800,Z1000-1215,Z1230-1800', '-'],
		/* 省略 */
	];

	$meeting = new MEETING();
	foreach($test as $key=>$data){
		$answer = $meeting->get($data[0]);
		if($answer !== $data[1]){
			print('えらー');
		}
	}
```

いやあ……なんだこれ。

暇な時間は1、用事があれば0を入れたビット列を作り、1が60回続くところを探しています。
発想は簡単ですが、文字列に対して論理演算を使うと想定外の結果になるので[ビット操作](http://www.php.net/manual/ja/language.operators.bitwise.php)が面倒なことになっていたり、日付を文字列にするところが妙にややこしかったり、あと最後の三項演算子は絶対もっと簡単な書き方があるだろ。

なんともすっきりしない解答。
時間も無駄にかかっていて3時間くらい。
何故か日時をDateTimeにしようとしたり文字列のまま処理しようとしたりで大混乱。
RailsでFacebook認証を使う方法．(omniauth-facebookを使って)


Facebook認証をRailsアプリに使う方法を簡単にまとめたいと思います．
使うgemは __omniauth-facebook__です．

# 開発環境
* Rails
 * 4.1.0
* Ruby
 * 2.0.0
* omniauth-facebook
 * 1.6.0

# それでは書いていきましょう!

## Gemfileにgemを記載する．

```Gemfile
gem 'omniauth-facebook'
```
```
$ bundle install
```

## モデルを作ります!
モデルを作って，メソッド書きます．

```
$ rails g model User provider uid name token
$ rake db:migrate
```

```models/user.rb
def self.create_omniauth(auth)
	where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
		user.provider = auth.provider
		user.uid = auth.uid
		user.name = auth.info.name
		user.token = auth.credentials.token
		user.save!
end
```

## セッションを管理するコントローラを作る

```
$ rails g controller Sessions
```

## ルーティング！

```config.routes.rb
get 'auth/:provider/callback', to: 'sessions#create'
get 'auth/failure', to: redirect('/')
get 'signout', to: 'sessiongs#destroy', as: 'signout'
```

## sessionsコントローラにcreateメソッドとdestroyメソッドを追加する

```sessions_controller.rb
def create
	user = User.create_omniauth(env['omniauth.auth'])
	session[:user_id] = user.id
	redirect_to root_url
end

def destroy
	session[:user_id] = nil
	redirect_to root_url
end
```

## ログイン中のユーザの情報を取れるように...

```application_controller.rb
helper_method :current_user

private
def current_user
	@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
```

## サインインとサインアウトリンクをビューに表示させる

```layouts/application.html.erb
<% if current_user %>
	<%= link_to 'Sign out,', signout_path %>
<% else %>
	<%= link_to 'Sign in with Facebook', '/auth/facebook' %>
<% end %>
```

## 終わり
これでRailsアプリにFacebook認証でログインさせる事が出来ます．
ただこれだとログインしていなくてもログイン後に表示させたいページも見れるようになってるので気を付けてください．
その方法に関してはまた別の機会にでも書こうかと思います!
[Rails]既存サービスにhas_oneなModelを新規追加した際のデータハンドリング


##困った
既に動いているサービスに新しく機能を追加する際に、
1対1のリレーションシップを持たせたテーブルを追加する必要がありました。
例えば、usersテーブルにuser_settingsテーブルを1対1の関係で追加するってイメージです。
※usersにカラム追加すればいいじゃんってのは別の話で。

ここで困ったのが、新しく追加したテーブルへのデータ追加方法です。
考えられる方法として、
1.デプロイする際にバッチで一気にデータ投入する
2.新規追加したmodelを使う際にnullチェックをしてnullならば作成

の2パターンなんですが、
1だとデータ量が多くなっている場合にシビアになってくるので2で考えました。

しかし毎度modelを呼び出すところでnullチェックするのもめんどくさい。。

##こんな実装がしたい

```user.rb
#既存でデータが入っているモデルクラス
class User << ActiveRecord::Base
  has_one :user_setting
end
```

```user_setting.rb
#新しく追加し、リレーションを組むモデルクラス
class UserSetting << ActiveRecord::Base
  belongs_to :user
  def hoge_user?
    return true
  end
end
```

```user_controller.rb
def test
  user = User.find(params[:user_id])
  if user.user_setting.hoge_user?
    p "hogehoge"
  end
end
```

ここで、user_settingsテーブルに指定のuser_idのデータが入ってないと、
user_controller.rbでhoge_user?呼んでるところでぬるぽります。


##そこでこんな実装をしてみた

```user.rb
#既存でデータが入っているモデルクラス
class User << ActiveRecord::Base
  has_one :user_setting

  # ここを追加
  def user_setting
    UserSetting.find_or_create_by(user_id: id)
  end
end
```

```user_setting.rb
#新しく追加し、リレーションを組むモデルクラス
class UserSetting << ActiveRecord::Base
  belongs_to :user
  def hoge_user?
    return true
  end
end
```

```user_controller.rb
def test

  user = User.find(params[:user_id])
  if user.user_setting.hoge_user?
   puts "hogehoge"
  end
end
```

user.rbでuser_settingというメソッドを実装（オーバーライド）して、
そこでfind_or_create_byという読み出し時にnullの場合はcreateしてからデータを返してくれるメソッドを使い、nullでもきちんと欲しいデータが作成され取得できるようにしてみました。
ここでこだわったのがコントローラー等からはいつもどおりの読み出しかたでそれを実現したところです。

初期値とか色々いじりたかったら実装したメソッドいじればいいんじゃないですかね。

これでコントローラーやビューでデータ取得時に毎度nullチェックして作成とか意味のわからない実装しなくて済む！！

##とはいえ
Railsさんなのでもうちょっと設定とかでできるんじゃねーのと思って探してて見つけれなかったのでこんな実装してみました。
これ以外にも絶対方法あると思うので誰か教えてください