OmniAICreator/Qiita-1.07M huggingface dataset:
PHPで簡単にOAuth認証を実装するサンプル（例：GitHubログイン）

ふとGitHubログインを実装しようとしたのだが、調べてもあまり使いやすそうなライブラリがない。

OpauthやHybridAuthなどの記事が多かったが、Opauthは既に開発が止まっているみたいだし、HybridAuthも2系はcomposer使うと非常に面倒くさく、3系はまだ開発中。

そこで**league/oauth2-client**というよさそうなライブラリを発見したので、これで実装することに。ついでにサンプルも作ってみた。

> thephpleague/oauth2-github
> https://github.com/thephpleague/oauth2-github

ドキュメントページもちゃんとあります。

> OAuth 2 Client - Easy integration with OAuth2 service providers
> http://oauth2-client.thephpleague.com/

## インストールと設定

はじめにGitHubの[ここ](https://github.com/settings/developers)でApplicationをregisterしてClient IDとClient Secretを取得しておきましょう。callbackのurlはここでは`/callback.php`とします。

composerで入れます。

```
$ composer require league/oauth2-client league/oauth2-github
```

oauth2-clientはproviderごとのpackageも別にインストールする形になっています。
今回はGitHubログインなのでこれも入れる。GitHubは公式のプロバイダとなっているので安心できる。

あとautoloadやその他設定をまとめるファイルを作っておきます。

```_config.php
<?php
require_once './vendor/autoload.php';
session_start();
$github_keys = require('./github-app-keys.php');
$provider = new League\OAuth2\Client\Provider\Github([
    'clientId'          => $github_keys['clientId'],
    'clientSecret'      => $github_keys['clientSecret'],
]);

$title = "PHP GitHub Login Sample";
```

GitHubのclientIdとclientSecretはさっき作成したものを入れておきます。`github-app-keys.php`は必ずgitignoreしておくこと。

```github-app-keys.php
<?php
return [
    'clientId'          => 'asdfasdfasdfasdfasdfasdf',
    'clientSecret'      => 'asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf'
];
```

（HybridAuth2系みたいに`vendor/hybridauth/hybridauth/hybridauth/...`となんども同じことを書かなくて良いのが楽ですね。）

## OAuth認証してみる

`/login.php`をログインページのURLとして、以下のように書きます。

```login.php
<?php
require_once '_config.php';

// GitHubの認証画面へリダイレクトするURL取得
$authUrl = $provider->getAuthorizationUrl();

// CSRF対策のためにいまの状態を入れておく
$_SESSION['oauth2state'] = $provider->getState();

header('Location: '.$authUrl);
exit;

```

```callback.php
<?php
require_once '_config.php';

// ちゃんとlogin.phpからきたかどうか確認
if (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
    unset($_SESSION['oauth2state']);
    exit('Invalid state');
}

// 認証コードからアクセストークンを取得
$token = $provider->getAccessToken('authorization_code', [
    'code' => $_GET['code']
]);

echo $token.'\n';
echo 'Successfully callbacked!!'.'\n';

// トークン使って認可した情報を取得できる
$user = $provider->getResourceOwner($token);

echo '<pre>';
var_dump($user);
echo '</pre>';
```

## おわりに

いいライブラリあると結構楽ですね。
ここで書いたコードはGitHubにも上げておきました。

> ikuwow/php-github-login
> https://github.com/ikuwow/php-github-login
Deisインストール職人が朝早起きしなくても済むTipsいくつか(Azure編)

注意
===
本記事は Deis v1.x について書いています。
最新の Deis は v2.0.1 で、基盤が Fleet から Kubernetes になるなど大きな変更がありましたので、本記事は参考になりません。

この記事の目的
===========

Engine Yard さんが主導して開発を進めている Micro PaaS 実装の [Deis](http://deis.io/) は，類似実装よりも安定して稼働します．
大人の事情で Heroku が使えない職場でも，Hubot や，ちょっとした業務改善 Rails アプリをお気軽にデプロイできるようになるので，かなりオススメです．

しかし，日本語でも英語でも情報が断片的で，最初はインストールでハマります．…というか，私は大いにハマりました．ので，メモ．

(コンテナデプロイ中の暇な時に，加筆していきます．)

Azure の記事の内容を鵜呑みにしてはいけない
================================

ググると，[Deis 本家の情報](http://docs.deis.io/en/latest/installing_deis/azure/)よりも上位に Azure の記事が出る場合があります．Azure の記事は[日本語版](https://azure.microsoft.com/ja-jp/documentation/articles/virtual-machines-deis-cluster/) もあり，つい頼りたくなりますが，本稿執筆時点ではお勧めしません．
記述の内容と，Azure が github.com で公開しているスクリプトの内容とが一致しない上に，かなり古いバージョンの CoreOS がインストールされるため，一手間かけないと DockerHub からコンテナをデプロイできません．

どう一手間をかければよいのかは，私が [Deis の issue に残してあります](https://github.com/deis/deis/issues/4806)が，本家の情報に従ったほうが確実です．

ただし，本家の情報もいろいろ足りていないところがあるので，一読しておくことは無駄ではありません．

再デプロイ時には，create-azure-user-data の再実行を忘れない
=======================================================

最初の頃は，いろいろと設定に失敗して，Azure のリソースグループの削除と再デプロイを行うことになると思います．
その際，は，他の設定はそのままでも `create-azure-user-data` の再実行は忘れずに行わなければなりません．

```shell-session
$ ./create-azure-user-data $(curl -s https://discovery.etcd.io/new)
```

これを忘れると，[issue に上がっているようなエラー](https://github.com/deis/deis/issues/3304) で先に進めなくなります．

加えて，azure-user-data が書き換わったわけですから，BASE64 化して， parameter.json の書き換えすることもお忘れなく．

parameter.json に記入する公開鍵は空パスワードで作る
==============================================

これを忘れるとどういうエラーになるのかは忘れましたが，うまく行きません．
この公開鍵に対応する秘密鍵はあとで deisctl コマンドでインストールしますが，
その後の運用では登場しません．

platform のインストール完了後に deis コマンドで(ユーザや管理者が)使う鍵ペアはこれとは別に管理されますし，むしろ一緒にしないようがセキュリティ上も宜しいかと思います．

Azure へのリソースデプロイ時の進捗確認や失敗原因分析
==============================================

Deis のデプロイに限らないので，[別の記事](http://qiita.com/monamour555/items/950975b263f7814fb615)にしました．

バージョン不一致に注意する
=======================

これは，何ヶ月か前にデプロイを経験したインストール職人が陥りやすい罠です．
Deis は下記の3つの要素から成り立っています．

* platform (CoreOS 上にある)
* deisctl コマンド (クライアント側にある)
* deis コマンド (クライアント側にある)

これらのバージョンは，必ず一致させてください．
不一致な場合でも，運が良ければ動きます．でも大抵の場合，よくわからない 500 エラーなどが出て悩まされます．
「マイナーバージョンが上がった場合，互換性はほぼ無い」くらいに思っておいたほうが安全です．


DNS の設定は，秘密鍵のインストール後にする
=====================================

DNS の設定が伝搬されるには，それなりの時間がかかります．
そして，インストールに失敗して Azure への再デプロイをした場合には IP アドレスは変わります．
よって，ほぼ失敗は無いという確証が得られるまで， DNS の設定は遅延させたほうがトラブルが少なくなります．
また，下記列挙のようなことも考慮すると良いと思います．

* ワイルドカードのレコードは A ではなく CNAME にする
* A レコードの TTL は可能な限り短くしておく
* Route53 や AzureDNS など，クラウドとの親和性の高い(伝搬の早い) DNS サービスを選ぶ
Macでgo-qmlの環境構築からHello Worldの表示まで

「[Goとキュートな日々 | Macでgo-qmlの環境構築からHello Worldの表示まで](http://miyabishi.hatenablog.com/entry/2015/12/27/095210)」からの転載。

環境

* OS X EI Capitan バージョン10.11.2

* go version go1.5.2 darwin/amd64

[go-qml/qml · GitHub](https://github.com/go-qml/qml) を参考にシェルを開き、以下を実行してみる。

```
$ go get gopkg.in/qml.v1
```
そしたら、以下のように怒られた。

```
# pkg-config --cflags Qt5Core Qt5Widgets Qt5Quick
pkg-config: exec: "pkg-config": executable file not found in $PATH
```

よく読むと[go-qml/qml · GitHub](https://github.com/go-qml/qml)の下の方に<b>Requirements on Mac OS X</b>の項目があったので読んでみる。

[Homebrew](http://brew.sh/)にアクセスしてHomebrewをインストールし、qt5とpkg-configをインストールする必要があるらしい。
Homebrewインストール後以下のコマンドを実行する。

```
$ brew install qt5 pkg-config
```

無事インストールが終わったのでqt5を有効にする。

```
$ brew link --force qt5
```

再度以下を実行

```
$ go get gopkg.in/qml.v1
```

うまく通ったみたい。

[qml - GoDoc](https://godoc.org/gopkg.in/qml.v1)を見ながらポチポチコードを打ち込んでみる。

goのソースコードは以下。

```go:goqml.go
package main
import (
	"gopkg.in/qml.v1"
	"fmt"
)

func main() {
	err := qml.Run(run)
	if nil != err {
		fmt.Println(err)
	}
}

func run() error {
	engine := qml.NewEngine()
	component, err := engine.LoadFile("goqml.qml")
	if err != nil {
		return err
	}
	win := component.CreateWindow(nil)
	win.Show()
	win.Wait()
	return nil			
}
```

qmlは[QML Tutorial 1 - Basic Types | Qt Quick 5.5](http://doc.qt.io/qt-5/qml-tutorial1.html:title)から持ってきた。

```qml:goqml.qml
import QtQuick 2.0

Rectangle {
    id: page
    width: 320; height: 480
    color: "lightgray"

    Text {
        id: helloText
        text: "Hello world!"
        y: 30
        anchors.horizontalCenter: page.horizontalCenter
        font.pointSize: 24; font.bold: true
    }
}
```

`go run goqml.go`を実行すると以下のウインドウが開く。ちゃんと動いているっぽい。
![screenShot.png](https://qiita-image-store.s3.amazonaws.com/0/107186/edd7ef05-14c4-eed5-b72c-cc36d3ddfd0d.png)

以上です。
tcpdumpの使い方

Wiresharkの方が新しく強力なイメージがあるが、tcpdumpも開発が続いているし機能面では負けていない印象。

# 使い方例

全ての通信をキャプチャ。

```
# tcpdump
```

ポート80への送受信のみキャプチャ。

```
# tcpdump port 80
```

ポート22（ssh）以外への送受信をキャプチャ。

```
# tcpdump port not 22
```

ポート80番への受信パケットだけを表示する

```
tcpdump dst port 80
```

ポート80番からの送信パケットだけを表示する

```
# tcpdump src port 80
```

`-nn` をつけるとアドレスやポート番号を名前に変換しない（No Nameの略か？）。基本的につけた方が見やすいと思う。
`-X` をつけるとパケットの中身（HTTPならリクエストやレスポンス）も表示。 
`-A` をつけると16進ダンプでなくテキストのみ表示。

```
# tcpdump -nn -X dst port 80
```

宛先IPアドレス 1.2.3.4 のみキャプチャ。

```
# tcpdump -nn -X host 1.2.3.4
```

条件のAND指定

```
# tcpdump -nn 'src host xx.xx.xx.xx and dst port 80'
```

宛先port 80かつSYNフラグのたったパケットだけ。

```
# tcpdump -nn dst port 80 and '(tcp[tcpflags] & tcp-syn)' != 0
```

Macでローカルホスト同士の通信を見る場合は`-i lo0`をつける。`-i all`でもいいかもしれない。

```
# tcpdump -i lo0
```


ICMPをキャプチャ

```
# tcpdump -nn icmp
```

## 指定できるプロトコルのリスト

ether fddi mopdl ip ip6 arp rarp decnet lat sca moprc icmp icmp6 tcp udp


# よく使うオプション

```
表示形式
-nn      アドレスやポート番号を名前に変換しないで表示します。
-X       16進とASCII文字で表示を行います。
-A       ASCII文字で表示を行います。
-ttttt   最初に表示したパケットからの経過時間（delta）を表示
-vvv     詳細を出力します。

キャプチャ
-i       キャプチャするインターフェースを指定します。-iオプションを指定しない場合はループバックを除いた一番小さいインターフェースが指定されます。（大体の場合はeth0ですね。）
-s       キャプチャするサイズを指定します。-s0ですべてキャプチャします。デフォルトは65535

ファイルへの入出力
-w <ファイル名>      生データをそのままファイルに書き込みます。WireSharkやEtherealで開く場合に便利です。
-r <ファイル名>      -wで書き込んだファイルを読み込んで表示する
```

* -nn（アドレスやポートを名前でなく番号で表示）はつけた方がよい
* HTTPのように中身をテキストでちゃんと見たいというときだけ -A をつけるとよい
* 中身に興味がなければ-X、-A どちらもつけないのが見やすい

# 出力の見方

形式

```
src > dst: flags data-seqno ack window urgent options
```

フラグの意味

```
S (SYN)
F (FIN)
P (PUSH)
R (RST)
W (ECN CWR)
E (ECN-Echo)
. (フラグなし）

URG, ACK は urg, ack という文字列で表示される
```

TCPヘッダの構造
![TCPヘッダ.png](https://qiita-image-store.s3.amazonaws.com/0/79394/7844c3d2-e07e-f048-cac8-f1eb80ee9038.png)

ECE ECN-Echo (`ECE`) フラグは TCP ピアが TCP 3-way ハンドシェイク間に ECN 対応であることを示すために、また TCP セグメントが 11 に設定されている IP ヘッダーの ECN フィールドとの接続で受け取られたことを示すために使用されます。TCP 3-way ハンドシェイクに関する情報は RFC 793 をご覧ください。
CWR Congestion Window Reduced (`CWR`) フラグが送信ホストにより設定され、ECE フラグ セットと TCP セグメントを受信したことを示します。輻輳ウィンドウは TCP により保持される内部の変数で、送信ウィンドウのサイズを管理します。

```
19:24:49.347860 IP 13.113.156.215.40206 > 10.4.3.221.d-s-n: Flags [P.], seq 266:297, ack 1, win 211, options [nop,nop,TS val 852763 ecr 854483], length 31
        0x0000:  4500 0053 908d 4000 fe06 33ee 0d71 9cd7
        0x0010:  0a04 03dd 9d0e 1f96 9c50 949a eba9 fc37
        0x0020:  8018 00d3 90c8 0000 0101 080a 000d 031b
        0x0030:  000d 09d3 666f 6f62 6172 2076 616c 7565
        0x0040:  3d30 2e39 3935 3732 3230 3032 3833 3330
        0x0050:  3935 39
```



```
4 = IPのバージョン番号（4はIPv4を表す）
5 = IPヘッダの長さ（4 * 5 = 20バイト）
00 = サービスタイプ
0053 = IPヘッダを含むパケットの全長。0x0050の3バイト目が終端になっていることに注目。
（中略）
0d71 9cd7 = 13.113.156.215。送信元IPアドレス
0a04 03dd = 10.4.3.221。受信IPアドレス
ここからTCPヘッダ
9d0e = 40206。送信元ポート
1f96 = 8086。受信ポート
0x20の行の最初にある8（4ビット）がTCPヘッダのサイズ。8→32バイト。
```
[Django] Generic editing viewsについて [2]

# はじめに
[\[Django\] Generic editing viewsについて \[1\]](http://qiita.com/KamekoKameKame/items/dbc4168581341897ec78)の続きです。

## UpdateView

更新です。

```django:polls/view.py
from django.views.generic.edit import UpdateView

class UpdateQuestionView(UpdateView):

    model = Question
    fields = ['question_text', 'pub_date']
```

templateは新規追加と同じquestion_form.htmlを利用します。

urls.pyに追加します。更新の場合はpkを指定する必要があります。

```django:polls/urls.py
urlpatterns = [
    url(r'^(?P<pk>[0-9]+)/update/$', views.UpdateQuestionView.as_view(), name='update'),
]
```

[http://127.0.0.1:8000/polls/1/update/](1)　にアクセスします。pk=1の情報が表示されているので更新して、Createボタンを押します。

![update2.png](https://qiita-image-store.s3.amazonaws.com/0/21492/01884a29-7f0a-8c88-082f-4a53bc8c4e2d.png)

Detail画面が表示されます。

![update3.png](https://qiita-image-store.s3.amazonaws.com/0/21492/8f29952c-61c3-60cb-93df-b3c8c6653503.png)

## DeleteView

最後に削除です。

まずはview.pyです。削除が成功した場合に移動するviewを指定します。

```django:polls/view.py
from django.core.urlresolvers import reverse_lazy
from django.views.generic.edit import DeleteView

class DeleteQuestionView(DeleteView):

    model = Question
    success_url = reverse_lazy('polls:index')
```

削除をしてよいか確認するためのtemplateを用意します。これも名前を指定しないなら、[model名]__confirm_delete.htmlという名前にします。

```django:templates/polls/question_confirm_delete.html
<form action="" method="post">{% csrf_token %}
    <p>Are you sure you want to delete "{{ object }}"?</p>
    <input type="submit" value="Confirm" />
</form>
```

urls.pyにも追加します。

```django:polls/urls.py
from django.conf.urls import url

from . import views

app_name = 'polls'
urlpatterns = [
    url(r'^$', views.IndexView.as_view(), name='index'),
    url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
    url(r'^add$', views.CreateQuestionView.as_view(), name='add'),
    url(r'^(?P<pk>[0-9]+)/update/$', views.UpdateQuestionView.as_view(), name='update'),
    url(r'^(?P<pk>[0-9]+)/delete/$', views.DeleteQuestionView.as_view(), name='delete'),
]
```

[http://127.0.0.1:8000/polls/3/delete/](http://127.0.0.1:8000/polls/3/delete/)にアクセスします。確認用の画面が表示されますので、Confirmボタンを押します。

![delete1.png](https://qiita-image-store.s3.amazonaws.com/0/21492/f5e2d772-36c7-4fad-e91f-9ab1de62d44c.png)

view.pyで指定した一覧画面にpk=3のデータが消えた状態で遷移します。

![delete2.png](https://qiita-image-store.s3.amazonaws.com/0/21492/cc23a661-ddd4-d33b-542d-9ea22995ceaf.png)

# まとめ
modelの指定だけでSQLやORMの記述等は必要なく簡単に更新系の処理も作れました。プロトタイプなどを素早く作りたい場合などにとても役に立つのではないでしょうか。

## 最後に
これは[2015 tech-yuruyuru アドベントカレンダー](http://connpass.com/event/22759/)の11日目の記事です。
Windows Server 2012 R2のリモートデスクトップ設定

# 概要
Windows Server 2012 R2にリモートデスクトップで接続するための設定手順を記載する。

# リモートデスクトップの設定
1. 自動起動する「サーバーマネージャー」画面
「ローカルサーバー」を選択し、「プロパティ」の「リモートデスクトップ」をクリックする。

1. 「システムのプロパティ」画面
「このコンピューターへのリモート接続を許可する」ラジオボックスを選択し、「OK」ボタンをクリックする。
![.1449361706562.png](https://qiita-image-store.s3.amazonaws.com/0/106250/2b49f227-6090-c941-3674-8ddd19743145.png)
　
以下の画面が表示された場合は、「OK」ボタンをクリックする。
![.1449395763048.png](https://qiita-image-store.s3.amazonaws.com/0/106250/41ce7300-ba8a-6478-c2d6-04e856c6ff08.png)

# Windowsファイアウォールの設定
これまでの設定で、外部端末からリモートデスクトップ接続できない場合は、ファイアウォールの設定を変更する。

1. 自動起動する「サーバーマネージャー」画面
「Windows ファイアウォール」を選択する。

1. 「Windows ファイアウォール」画面
「詳細設定」をクリックする。
![.1449394402475.png](https://qiita-image-store.s3.amazonaws.com/0/106250/58e17609-c199-fb3e-0c16-c2296d64dd27.png)
　
1. セキュリティが強化された Windows ファイアウォール」画面
「ローカルコンピューターのセキュリティが強化された Windows ファイアウォール」を選択し、「受信の規則」を選択する。
以下の名前のネットワーク接続について「規則を有効化」する。
※「ネットワークアダプタの種別」が「パブリック」の場合、無効となっている。
 * リモート デスクトップ - シャドウ (TCP 受信)
 * リモート デスクトップ - ユーザー モード (TCP 受信)
 * リモート デスクトップ - ユーザー モード (UDP 受信)
![.1449362015057.png](https://qiita-image-store.s3.amazonaws.com/0/106250/5a08542b-3df9-94e2-a17c-9f4dc013abf9.png)

# 動作確認
1. 実際に他の端末から、リモートデスクトップ接続できることを確認する。**以下はサンプルです**
![image](https://qiita-image-store.s3.amazonaws.com/0/106250/28cfe1da-d456-64ba-80af-23dbbaf4279d.png)


以上
mythingsのアクションをsangoで受ける

#概要
mythingsのアクションをnode-redでブリッヂして、sangoで受ける。
#写真
![sango.JPG](https://qiita-image-store.s3.amazonaws.com/0/18104/8408586a-2226-7471-3a84-300d6c4b0407.jpeg)

#sango設定
```
url: lite.mqtt.shiguredo.jp
port: 1883
user: you @github
pass: you pass
topic: you @github/test0
```
#meshblu設定
```
url: you .jp-east.compute.idcfcloud.com
port: 1883
user: action-1 uuid
pass: action-1 token
topic: action-1 uuid
```
Tclで文字列置換

いざ使おうとすると忘れてることが多いので。

#対応バージョン

Tcl 8.4.1

#正規表現(regsub)による置換

``regsub ?オプション? パターン 元の文字列 置換後の文字列``

##よく使うオプション

| オプション |内容                | 
|:---------|:-------------------|
| -all     | マッチした部分全て置換 |
| -nocase  | 大文字小文字を無視    |
| -line    | 改行コードを認識する  |

##応用

置換後の文字列に、パターンでマッチした文字を使用した場合、``¥+数字`` (¥1等)が利用出来る

例えば、"ping \<10.0.0.1-10.255.255.254\>"を"ping 10.0.0.1"に置き換えたい場合は、下記のようにする。[^1]

```
regsub {<((¥d{1,3}¥.){3}¥d{1,3})-(¥d{1,3}¥.){3}¥d{1,3}>} "ping <10.0.0.1-10.255.255.254>" {¥1}
```

[^1]: ¥0はマッチした部分全体が入ることに注意

#stringによる置換(位置指定)

``string replace 元の文字列 開始位置 終了位置 置換後の文字列``

開始位置から終了位置までの部分を「置換後の文字列」で置き換える。

#stringによる置換(複数箇所)

stirngを使って、複数の文字列を置換することもできる。

``string map 置換する文字の配列 元の文字列``

「置換する文字の配列」は、置換対象の文字列をキー、置換後の文字列を値とするKey-Valueペア。

例えば、「2015」を「2016」に、「Summer」を「Spring」に置き換える場合は、以下のようになる。

``string map {2015 2016 Summer Spring} "ABC 2015 Summer coming soon."``

とりあえず、この3種類を押さえておけば、大抵なんとかなる。

しかし、Tclの配列だろうと、文字列だろうと、表現がほぼ同じってのは便利なんだか、不便なんだか。。。
Petalinux > Link > Zedboardでの導入メモ

[ZedboardでのPetalinuxの導入メモ](http://blog.livedoor.jp/yhmtmt/archives/30554806.html?1403835700)

環境
> petalinux v2013.04、ISE14.6
ISE、XPSはWindows 7 64bitで動作
XSDK,Petalinux SDKはCentOS 6.4 32bitで動作

Vivadoではないが色々参考になった
Zybo > Link > Zynq Releases / Errata Work-around Soluations

Zynq Releases
http://www.wiki.xilinx.com/Zynq+Releases
FSBL / U-Boot / Linux / Device-tree Generator

Errata Work-around Soluations
http://www.xilinx.com/support/answers/55539.html


Petalinux使う時、こちらは使わなかったかもしれないが、後々の参照のため記載。
技術英語 > it's sure to affect historical parks around the country [for years to come]. / for coming two decades

@ LOE > August 31, 2012

http://loe.org/shows/shows.html?programID=12-P13-00035
> it's sure to affect historical parks around the country for years to come.

http://eow.alc.co.jp/search?q=for+years+to+come
> 《for （the） years to come》この先何年も、今後数年間、この先ずっと、後世

<hr>
関連して思い出したのは

> for coming two decades
Bootstrap3のグリッドシステムの概念を理解して使えるようになる

## グリッドシステムとは何か
* 可変グリッドレイアウトを実現するためのBootstrapのCSSの機能

### そもそもグリッドレイアウトとは
* Webデザインに使われるレイアウトの手法の一つ

* 「グリッド（grid）」とは方眼(状のもの)という意味で、グリッドレイアウトは画面やページを縦横に分断する直線で格子状に分割し、ブロックを組み合わせて各要素の大きさや配置、余白などの画面構成を決定していく手法のこと

* グリッドは縦を「カラム(column)」、横を「ロウ(row)」で表現する

* グリッドレイアウト用のテンプレートとして有名なサービスに「960 GRID GYSTEM」がある
* http://960.gs/

### 可変グリッドレイアウトとは
* Webページのレイアウトは「カラム数」と「固定か可変」を組み合わせて決定していく

* 可変レイアウトの代表として、リキットレイアウト(Liquid Layout)とレスポンシブWebデザイン(Responsive Web Design)がある

#### リキッドレイアウト
* 要素の単位を%で指定することにより、ブラウザの幅に合わせてコンテンツの幅・位置が相対的に変化するレイアウトのこと

* デメリットとして、無制限に可変すると解像度が異常に高いディスプレイの場合は横幅が広がりすぎてしまう
* http://design1.chu.jp/setucocms-pjt/wp-content/uploads/2011/09/index.html

#### レスポンシブデザイン
* ブラウザの幅に応じてコンテンツの幅が変化するのはリキッドレイアウトと同じ
* ただ、画面サイズに応じて一部のコンテンツを表示したり、消したりなどサイズだけでなく位置や要素そのものも変化する
* http://products.comnico.jp/cms/jp

#### 可変グリッドレイアウト
* 上記の可変レイアウト(リキッドレイアウト・レスポンシブデザイン)にグリッド線に沿って画像や文字を配置するグリッドレイアウトを合わせたのがもののこと

## Bootstrapのグリッドシステムの仕組み
* Bootstrapのグリッドシステムは12列のカラムで分割するようにする
* .container or .container-fluid > .row > .colの順番でコーディングしていく

### containerとは
* 固定長を指定し、要素をセンタリングさせる

* ウィンドウサイズに応じて固定長サイズが変わる

* containerには左右に15pxのpaddingが設定されており、スマホサイズで画面いっぱいになった時に見た目が綺麗になる

* サイズが変わるポイントをブレイクポイントと呼ぶ

### ブレイクポイントについて
* 768px, 992px, 1200pxをそれぞれブレイクポイントと呼ぶ

```
1200px >= の場合:               高解像度PC用
992px <= && <= 1199pxの場合:    PC用
768px <= && <= 991pxの場合:     タブレット用
767px以下の場合:                 スマホ用
```

* 上記のようになっており、ブレイクポイントに応じて対応するデバイスが変わる

### rowとは
* カラムの区切りを明確にするために設定する
* またcontainerは左右にpaddingを15px設定するため、そのままだと分割できる幅が30px減ってしまう
* そのためrowにネガティブマージンを左右に15px設定することでcontainerの長さと分割できる幅を一致させている

### colとは
* 実際に画面幅をグリッドとして分割するために必要なクラス
* 各ブレイクポイント用に利用するクラス名は下記のようになる

```
1200px >= の場合:               col-lg-*
992px <= && <= 1199pxの場合:    col-md-*
768px <= && <= 991pxの場合:     col-sm-*
767px以下の場合:                 col-xs-*
```

* スマホとスマホ以外のデバイスで分けたい時はcol-sm-*を使う

## 試しに作ってみよう
http://designup.jp/demo/boot-web/
Custom Keyboardでオートレイアウトするとき、Verticalの上を設定したらぺたんこになった

~~未だ正解を知らず。~~

**更新:** ここに書いてある記事は不完全。下記の記事で高さを設定することができた。
[Custom Keyboard の高さは viewWillAppear:animated で設定する](http://qiita.com/ichiroc@github/items/9ed1d69b69113d79b4cf)



## 1. NGだったケース ``V:|-[hoge]-[fuga]-|``

```swift
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[hoge]-[fuga]-5-|", options: NSLayoutFormatOptions(rawValue: 0) , metrics: nil, views: views))

```
上記のように指定すると一番下にぺたんこに表示されてしまった。

## 2. ~~NG~~ OKと思われるケース ``V:|-[hoge(300)]-[fuga]-|``

```swift
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[hoge(100)]-[fuga]-5-|", options: NSLayoutFormatOptions(rawValue: 0) , metrics: nil, views: views))

```

高さは指定できたけど、キーボードのあるべき高さ以上に指定できるので、~~間違いなくAppStoreのレビューで却下されてしまうだろう。~~

**更新:** どうも iOS8 から自由に高さを設定して良いらしい。明確な基準は示されてないけど、常識的な高さなら審査は通ると言うことだろうか。

[Custom Keyboard](https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/Keyboard.html)

>You can adjust the height of your custom keyboard’s primary view using Auto Layout. By default, a custom keyboard is sized to match the system keyboard, according to screen size and device orientation. A custom keyboard’s width is always set by the system to equal the current screen width. To adjust a custom keyboard’s height, change its primary view's height constraint. 

**更新:** この ``Constarint`` を ``viewWillAppear:animated`` で設定すれば高さはきちんと設定される。 ``viewDidLoad`` ではNG。

## 3. ~~OK~~ NGだったケース ``[hoge(300)]-[fuga]-|``

```swift
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[hoge(200)]-[fuga]-5-|", options: NSLayoutFormatOptions(rawValue: 0) , metrics: nil, views: views))

```

~~高さが自動で設定されて、適切な高さになった。~~

適切な高さではあるけど、 ``(200)`` を増やすと view の高さを超えて、不可視領域に描画されるのでNG。

結局キーボードの高さを自分で決めてやるのが正解なのかな？するとこうなるはず。



## 残る疑問
通常の View が Super View になっていたら、そのビューの高さに合わせて高さが設定されると思うのだけど、キーボードの View の高さは設定されていないのだろうか？
Emacs メジャーモードの elisp を直に記述する場合の keybind の設定の行い方、まとめ

# 目的

Emacs のメジャーモードのキーマップの設定方法が、 hook の中で define key したりそうでなかったりなど、検索するといくつかの方法が Hit するので、何が適切なのかを少ししらべてみた。

(タイトル編集@12/29)
@tadsan から[ライブラリの紹介](https://github.com/jwiegley/use-package)があって、まだ試していないですが、このライブラリを使うとメリット出そうなので、そのようなパッケージを使わずに elisp で直接設定するケースについてフォーカスした記事、ということでタイトルを変更しました。そんなケースがあるのか、という疑問は若干ありますが、あるかもしれないしないかもしれないので、気にしないことにします。

# 良さそうな方法: eval-after-load + define-key

まず、一番筋が良さそうなのは、次のように `eval-after-load` 関数で、対象のメジャーモードが読み込まれた直後に、対象モードの keymap に `define-key` を行う方法。詳細は関数の help を参照。簡単以下のコードだと、 `latex` を provide している .el ファイルが、読み込まれた直後に１回だけ、 `define-key` が実行され、メジャーモード用の map が更新される。

```el
(eval-after-load 'latex 
                    '(define-key LaTeX-mode-map [(tab)] 'outline-cycle))
```

# よくあるパターン1: hook で define-key

そうではないパターンでよく見かけるのが、`add-hook` によって、各メジャーモードが実際に実行された直後に、毎回 `define-key` なりを行う方法。これだと、新しくメジャーモードでバッファを開くたびに、フックの内容が実行されることになると思われる。これでも正しく動作はするだろうが、やりたいこと的に、正しくはそこで実行するべきではない、と思われる。

```el
(add-hook 'LaTeX-mode-hook
          (lambda () (local-set-key (kbd "C-0") #'run-latexmk)))
```

# よくあるパターン2: require してから define-key

```el
(require 'latex)
(define-key LaTeX-mode-map [(tab)] 'outline-cycle)
```

対象の el ファイルを読み込んでしまえば、対象メジャーモードの map が存在するようになるから、`define-key` が行えるようになる、という方法。

ただ、これを `init.el` に入れてしまうと、使わないメジャーモードまで毎回毎回起動時に読み込むことになる。AUCTeX とか、重たい el ファイルだと、それはあまり喜ばしくないと考えられる。(常時サーバーとして起動させておくのが、 emacs の使い方だよ、と言われれば、その通りですとなってしまいますが。)


# 参考リンク

http://stackoverflow.com/q/5500035/3090068
【自分用メモ】Rubyのメモ

初心者が書いているメモです。

#Homebrewを入れる
Homebrewはmacの開発環境を整えるツール。gemはrubyのライブラリを入れるツール。
http://qiita.com/issobero/items/e0443b79da117ed48294

#gemのインストール先のパスを調べる

```
gem environment
```
rubyのバージョン管理ツールのrbenvを入れている場合はrbenvの方を見ること。

```
- GEM PATHS:
     - /home/hoge/.rbenv/versions/2.0.0-p576/lib/ruby/gems/2.0.0
     - /home/hoge/.gem/ruby/2.0.0
```

#特定のgemのインストール先のパスを調べる
```
gem which nokogiri
```

#アップデート時
macの場合

```
brew update
```

ubuntu,debian系

```
apt-get update
```



gemをアップデート

```
gem update
```



```
brew upgrade ruby-build
```

インストール出来るもの一覧
```
rbenv install --list
```

```
rbenv install 2.3.0
```

```
rbenv global 2.3.0
```

インストールされているrubyバージョン一覧

```
rbenv versions
```

アンインストール

```
rbenv uninstall 2.1.2
```

--------------
ライブラリ

rmagickでのエラーはまり
http://yatta47.hateblo.jp/entry/2015/05/11/080000

--------------
ubuntuの場合
http://qiita.com/kazoo04/items/7056704efee66f323ddb

参考
gem
https://rubygems.org/gems
ElasticSearchでSynonymTokenFilterを設定してみる

# 概要・背景
最近の若者は、本田翼をばっさーとかって略すらしい。
ホンツバとかって略したくなるのは自分だけでしょうか？

どっちでもいいですが、検索エンジン的には、
本田翼も、ホンツバも、ばっさーも、同じ結果を返して欲しいですよね？
もちろん、検索システムを含むサービスの運営側としては、同じ結果を返したいですよね？

[ジョブメドレー](https://job-medley.com/?force=1)では[Elasticsearch](https://www.elastic.co/jp/)を使っているので、それをうまくチューニングしたというお話。

# ElasticSearchについて理解する
Elasticsearchについて無知過ぎたので、そもそもまずは概形を学ぶところからスタート。
以下は、勉強に使った一部の資料。
 - http://code46.hatenablog.com/entry/2014/01/21/115620
 - http://blog.shibayu36.org/entry/2015/07/08/095838
 - https://medium.com/hello-elasticsearch/elasticsearch-6d69b6ff5c26#.tf71jaycs



## わかったこと（今回はこれだけ知っていれば、行ける）
 - データからインデックスを作成して、検索時にクエリを発行して検索する
 - アナライザーは、Toknizerでパースされ、Filterで整理される
 - アナライザーは、インデックス作成用と検索用がある

# Ruby on Railsに組み込む
今回、組み込むにあたり、「辞書は定期的にいれかえる必要がある」という要件があった。
そのため、辞書更新の度に、インデックスをすべて更新するのはコストが高いので検索時のanalyzerだけ設定することにした。

## 辞書ファイルの作成
辞書ファイルの書き方は、大まかに3種類ある。

https://www.elastic.co/guide/en/elasticsearch/reference/1.4/analysis-synonym-tokenfilter.html
を参考に


```config/search.txt
# 下記の用に=>を使うとマッピングされ
# ばっさーと検索すると、本田翼の結果が引っかかる
# ※「ばっさー」の結果は引っかからない
ばっさー => 本田翼

# 下記のようにカンマ(,)でつなげると
# 本田翼やばっさーで、検索すると
# 本田翼とばっさーとほんつばで検索した結果がすべて出る
ばっさー,本田翼,ほんつば

# 複数指定もできる
ばっさー=>ほんつば,本田翼

# 上書き方式ではなく、追加方式
# 下記の例は ばっさー=>ほんつば,本田翼と同じ
ばっさー=>ほんつば
ばっさー=> 本田翼
```

※追加終わったら、elasticsearchを再起動する

## Elasticsearch-inquisitorを使って、実際できているかを見る
http://blog.johtani.info/blog/2013/09/23/intro-elasticsearch-inquisitor/
で紹介されているElasticsearch-inquisitorを使い、実際に検索クエリの単語がうまく解釈されているかを確認する。
※Elasticsearchがきちんと再起動されていることを確認する

## 検索側のクエリにanalyzerを指定する
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html
を見ると```analyzer: The analyzer name used to analyze the query string.```というのがあるので、

```sample_search_query
{
    'query_string' : {
        'default_field' : 'content',
        'default_operator': 'AND',
        'query' : 'ばっさー',
        'analyzer' : 'search_analyzer',
    }
}
```
これで検索できる

# まとめ
 - elasticsearchで類似語検索する場合は、[Synonym Token Filter](https://www.elastic.co/guide/en/elasticsearch/reference/1.4/analysis-synonym-tokenfilter.html)を使う
 - 基本的には、filterを設定しanalyzerを書いて、elasticsearchを再起動する
 - [query string query](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#query-dsl-query-string-query)を使い、analyzerを設定し検索する

以上
Electronでズームを禁止する

Macとかだとピンチインやピンチアウトでページを拡大したり、縮小したりできますよね。
Electronではこれを制御することができるようです。

```js
var webFrame = require('web-frame');
webFrame.setZoomLevelLimits(1, 1);
```

このコードは描画側で呼ぶ必要があるようです。
詳しい使い方はドキュメントを見るほうがいいでしょう

参考: [web-frame](https://github.com/atom/electron/blob/master/docs/api/web-frame.md)
neovimのterminalモードマッピングの有効/無効をコマンドから切り替える

ぶっちゃけなんで作ったのか思い出せないけど、なんか便利そうだから置いておく
確か、terminalモードでマップすると入力がめんどいから一瞬だけデフォルトに戻すかみたいな思惑で作った気がする.

```vim
" Copy and modify from mapping source in unite.vim
function! s:get_mapping_list(map_cmd) abort
    redir => mapping_str
    silent! execute a:map_cmd
    redir END

    let mapping_list = []
    let mapping_lines = split(mapping_str, '\n')
    let mapping_lines = filter(copy(mapping_lines), "v:val =~ '\\s\\+\\*\\?@'") + filter(copy(mapping_lines), "v:val !~ '\\s\\+\\*\\?@'")
    for line in map(mapping_lines, "substitute(v:val, '<NL>', '<C-J>', 'g')")
        " attribute
        let attr = ''

        " right
        let map_rhs = matchstr(line, '^\a*\s*\S\+\s*\zs.*\ze\s*')
        if map_rhs =~ '^\*\s.*'
            let map_rhs = map_rhs[2:]
            let attr = '*'
        endif

        " left
        let map_lhs = matchstr(line, '^\a*\s*\zs\S\+')
        if map_lhs =~ '^<SNR>' || map_lhs =~ '^<Plug>'
            continue
        endif
        let map_lhs = substitute(map_lhs, '<NL>', '<C-j>', 'g')
        let map_lhs = substitute(map_lhs, '\(<.*>\)', '\1', 'g')

        call add(mapping_list, [map_lhs, map_rhs, attr])
    endfor

    return mapping_list
endfunction

let s:is_term_map_enable = 1
function! s:toggle_terminal_map() abort
    if s:is_term_map_enable == 1
        let g:toggle_mapinfo_list = <SID>get_mapping_list('tmap')
        " Disable
        for mapinfo in g:toggle_mapinfo_list
            echo mapinfo[0]
            execute 'tunmap' mapinfo[0]
        endfor
        let s:is_term_map_enable = 0
    else
        " Enable
        for mapinfo in g:toggle_mapinfo_list
            let map_cmd = (mapinfo[2] == '*') ? ('tnoremap') : ('tmap')
            execute map_cmd mapinfo[0] mapinfo[1]
        endfor
        let s:is_term_map_enable = 1
    endif
endfunction

command! -nargs=0 ToggleTerminaMap call <SID>toggle_terminal_map()
```

こんな感じのマッピングの有効/無効を切り替えられるはず

```vim
tnoremap <ESC> <C-\><C-n>
tnoremap <C-w>h <C-\><C-n><C-w>h
tnoremap <C-w>j <C-\><C-n><C-w>j
tnoremap <C-w>k <C-\><C-n><C-w>k
tnoremap <C-w>l <C-\><C-n><C-w>l
```

もっと簡単な方法があればぜひ教えてください.
Pyramid導入

PythonのWebフレームワークであるPyramidをインストールして、起動させるまでの導入記事です。

# 開発環境

  - CentOS 7
  - Python 3.5
  - Maria DB
  - PyMySQL

# インストール
pipを使うだけです。とても簡単ですね。

```
$ pip pyramid
```

# プロジェクト作成

Pyramidのプロジェクトを作成します。
今回の例では、 **my-app**を作成します。

```
$ pcreate -s alchemy my-app
```

alchemyを指定することで、SQLAlchemyを使用する設定でプロジェクトを作成します。

# 設定変更

デフォルトではDBにSQLiteを使用する設定です。
今回はMariaDBを使用するため、DB接続設定を変更します。

```development.ini
sqlalchemy.url = mysql+pymysql://pyramid_user:pyramid_password@localhost:3306/pyramid_db?charset=utf8&use_unicode=1
```

## 補足
pyramid_user、pyramid_password、pyramid_dbは適宜、置き換えてください。

# 起動

デフォルトではwaitressというWSGIサーバを使う設定です。
今回は変更せず、デフォルト設定のまま起動させます。
設定は、development.ini／production.iniに記述されています。

```
$ pserve development.ini
```

これでWebサーバが動くので、開発を進められるようになりました。
Ruby 2.3.0がrbenvに表示されない時にやったこと

12月25日に Ruby 2.3.0 がリリースされました:tada:

まずは

```
$ brew update
$ brew upgrade rbenv ruby-build # updateしたら私の環境ではupgradeできたのでやりました
```

上記を行って、rbenv, ruby-build を最新の状態にします。
しかし、

```
$ rbenv install -l
(略)
  2.2.2
  2.2.3
  2.3.0-dev
  jruby-master+graal-dev
  jruby-1.5.6
(略)
```

2.3.0 の正式版がない。。

ここからが本題で、Ruby2.3.0 をインストールするためには、rbenv を最新の状態にしてあげればよいです。

```
$ cd ~/.rbenv/plugins/ruby-build
$ git pull
```

これで rbenv が最新の状態になり、Ruby 2.3.0 が表示されるようになったはずです。

```
$ rbenv install -l
(略)
  2.2.2
  2.2.3
  2.2.4
  2.3.0-dev
  2.3.0-preview1
  2.3.0-preview2
  2.3.0
  2.4.0-dev
  jruby-master+graal-dev
  jruby-1.5.6
(略)
```

ちゃんと新しいバージョンも表示されていました。なんなら 2.4.0-dev もあります。
今回の目的は Ruby 2.3.0 をインストールすることなので、さっさとインストールしてしまいます。

```
$ rbenv install 2.3.0
```

あとはお好みで `rbenv global 2.3.0` するなり `rbenv local 2.3.0` するなりして、 `rbenv rehash` しておけば大丈夫ですね。

なんか Ruby のバージョン新しいの出るたびに同じことしてる気がする僕。。

#### 追記
`rbenv rehash` は不要になったようです:bow:
https://github.com/rbenv/rbenv/pull/638
zfコマンドを有効にする

#zfコマンドを使えるようになる

ZendFrameworkで空のプロジェクトを作る際などに便利な **zf** コマンドについて調べてみました．

環境：CentOS6.6

##zfコマンドを有効にする
まずはZendFramework関係のものをインストール

```bash
$ yum install php-ZendFramework*
```

このままの状態だとzfコマンドは有効になっていない．

```bash
$ zf show version
-bash: zf: コマンドが見つかりません
```

そこで，コマンドを使えるようにパスを通す．

```bash
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
$ cd /usr/local/bin/
$ cp /usr/share/php/Zend/zf* ./
$ mv zf.sh zf
# もし/usr/share/php/Zend/配下にzf.shなどが存在しなかったら，
# /usr/share/php/Zend1/配下にあるかもしれない．
```

これでzfコマンドが使えるようになっているはず．

```bash
$ zf show version
Zend Framework Version: 1.12.3
```
プラグインできるタイプの実装が作りたい


ルールに従い判定を行うスクリプトを作成時

ルールは追加できるようにしたかったので作成

Personを継承したクラスをclassesの中に作ることで実行できるようにしました

```
.
├── Main.py
└── classes
    ├── Person.py
    ├── Taro.py
    └── Tom.py
```

```Python:Main.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# from os.path import join, relpath, splitext
from os import path
from glob import glob
import re
import sys

def main():
    """ Run from Here. """
    dir = "classes"
    exception_file = ["__pycache__", "Person.py"]
    extention = ".py"
    reg = re.compile('.+\\' +extention)

    sys.path.append(dir) # path の追加 
    files = [path.relpath(x, dir) for x in glob(path.join(dir, '*'))]
    files = list(set(files) - set(exception_file))

    objs = []
    for x in files:
        if reg.match(x):
            name = x.replace(".py", "")
            # ここでクラスの読み込み
            m = __import__(name, globals(), locals(), [name], 0 )
            o = eval("m."+name+"()")
            objs.append(o)

    for obj in objs:
        obj.say()

if __name__=="__main__":
    main()
```

```Python:Person.py
from abc import ABCMeta
from abc import abstractmethod

class Person(metaclass=ABCMeta):

    @abstractmethod
    def say(self):
        raise NotImplementedError
```

```Python:Taro.py
from Person import Person

class Taro(Person):
    def say(self):
        print("Hello, this is Taro.")
```

```Python:Tom.py
from Person import Person

class Tom(Person):
    def say(self):
        print("Hello, this is Tom.")
```

```Bash:out
$ python Main.py 
Hello, this is Taro.
Hello, this is Tom.
```

## 分からない点

プログラムを書き換えること無くスクリプトを追加できる実装は危険なのか

もっとスマートにかける方法ないのか

教えて下さい
nanogui.goの進捗を記録するスレ

もろもろ細かいレベルで元のnanoguiから手を加えているので、それを淡々と記録していく。目標としては、Qtなどの既存のGUIフレームワークを使ったことがある人が違和感を感じるようなところを無くす。

Screen/Window/Widgetまわり
------------------------

* Screen内にレイアウトを設定してWindowを複数並べたりできるようにした
* Widgetを置いて、その中にWindowを複数並べられるようにした
* デバッグでツリー構造を表示する機能をつけた(Screen.DebugPrint())
* 子要素の表示順序
   * Z値を持たせて、それに応じてソートして表示する。ただし、現状はZ値を持っているのはウインドウの子クラス(Window, Popup)のみ。
* クリッピング
    * 親要素の範囲外のものは描画しなようにした。大量にあるデータをVScrollPanelで表示しても、表示領域にあるものしかOpenGL命令は呼ばない。
    * ついでに、NanoVGoのテキストをTRIANGLESからTRIANGLE_STRIPにして頂点数を減らした

基本ウィジェット
------------------------

* TextBox
    * 編集中文字列の長さでセンタリングされるようにした。オリジナルはコミット後文字列
    * MacOS Xと同じEmacsキーバインドを追加
    * IMEサポート
    * テーマのフォントを使わずに固有のフォントを設定するメソッドを追加した(FontFace/SetFontFace)
* VScrollPanel
   * スクロール量を取得設定するメソッド(Scroll/SetScroll)を追加
   * スクロールが不要な時はスクロールバーを非表示に。小さすぎるときは最低20px表示するように。
   * スクロール値(0.0-1.0)だけを保持していたが、絶対座標を持つようにして、そこからスクロール値を計算するようにした。今まではスクロール値への変換を何度も行うことで誤差が拡大してスクロールがなめらかに行えなかった。
* Popup
   * 子要素が大きかった時にスクロールバーを出すようにした。VScrollはクセが強いのでなんとかしたい。
   * まだ完全ではない。ポップアップが画面からはみ出すかどうかでサイズの調整を自動にしたりしたい。
* Label
    * SetWrap(bool)でラップの設定を行う。デフォルトはON。falseにすると、nanoguiext.ExpandListLayout()でも、折り曲げられないで表示される。

基本レイアウト
-----------------------

* BoxLayout(horizontal)
   * ウインドウに対してレイアウトを設定するとおかしくなる。本家にもPR出した。

追加ウィジェット
------------------------

* nanoguiext.Spinner
    * スピナー。表示中はイベントハンドラをブロックする。設置されたところから一番近い親のウインドウ、もしくはスクリーンを覆う。
    * スピナー自身はサイズゼロの要素で、別に全体を覆うフィルターコンポーネントを内部で作る。
    * サイズや回転速度やらはパラメータで変更できる

追加レイアウト
------------------------

オリジナルはボトムアップで大きさを決めていくレイアウトしかなかったので、親要素のサイズからトップダウンで決めていくものを追加した。ウインドウ全体に対して覆うようなレイアウトを実現する。

* nanoguiext.ExpandBoxLayout
    * Boxレイアウトのトップダウン型。500のスペースがあって、ウィジェットが2つあれば250pxずつボックスを作って配置する。
    * Clamp()が設定されている場合や、FixedSize()が設定された場合は、スペースを延長せずに並べる。残った空間が、他のウィジェットで等分されて配置される。
* nanoguiext.ExpandListLayout
    * リスト型のテーブルを実現する。各カラムのベースの大きさと、スペースが余った時の戦略を設定する。
    * スペースが余った時の戦略は、すべてのカラムに等分で配分(ExpandAll=default)と、最後のカラムにすべて配分(ExpandLast)と、個別指定がある。
    * 個別指定はSetStretches()を呼ぶ。この数値の大きさで配分する。{0.5, 1.0}なら、1:2に配分される。全部ゼロの場合はExpandAll/ExpandLastが使われる
    * ヘッダが固定長で、各項目が残りすべて、みたいな用途で使う。ラベルのように幅が決まってから高さが決まる要素で正しくレイアウトするのがこのレイアウトの目的
    * SetColumnWidth()を持っているウィジェットには、これを内部で呼び出して、コンテンツの幅を設定する。ラベルのように幅によって高さが変わるウィジェットで、PreferredSize()メソッドが正しいサイズを返すために、期待する幅を設定する。

困りごと/追加したい機能
------------------------

* VScrollPanel
   * スクロールされる子もコンポーネント内で面倒みるようにしたい
* トップレベルのウィジェット
   * [Material Design LiteのLayout](http://www.getmdl.io/components/index.html#layout-section)あたりを実現したい。
* ボタンのラベル
    * 長過ぎる時に三点リーダを使って省略というのをやりたい
* 自動レイアウト
    * 今は自分でScreen.PerformLayout()を呼び出さないとレイアウトが実行されない。dirtyフラグを付けて、描画のコールバック内で自動で再レイアウトするようにしたい
[baserCMS] メールフォームで郵便番号を2つに分けた際も住所補完機能を利用する

baserCMSのメールフォーム機能には、郵便番号での住所補完機能があります。
フォーム制作時、郵便番号を2つの入力欄に分けたい場合がありますが、その際にはこの住所補完が効きません。
それを可能にするちょっとしたTipsです。


## 想定している対象者
- baserCMSでウェブサイトを制作をしている方
- baserCMSでメールフォームを制作している方


## フィールドを作る

※住所補完が効くフィールドは「都道府県: address_1、住所テキスト: address_2」を前提とした内容です。

- 郵便番号の前半用
  - フィールド名: zip
  - タイプ: テキスト
  - 最大値: 4文字
  - 拡張入力チェック: グループチェック
  - グループ名: postal_code
  - グループ入力チェック: postal_code
  - 自動変換: 半角変換
- 郵便番号の後半用
  - フィールド名: zip_2
  - タイプ: テキスト
  - 最大値: 4文字
  - 拡張入力チェック: グループチェック
  - グループ名: postal_code
  - グループ入力チェック: postal_code
  - オプション: ```onKeyUp|AjaxZip3.zip2addr('data[MailMessage][zip]','data[MailMessage][zip_2]','data[MailMessage][address_1]','data[MailMessage][address_2]');```
  - （旧）オプション: ```onKeyUp|AjaxZip3.zip2addr('data[Message][zip]','data[Message][zip_2]','data[Message][address_1]','data[Message][address_2]');```
  - 自動変換: 半角変換
- 都道府県リスト
  - フィールド名: address_1
  - タイプ: 都道府県リスト
- 住所
  - フィールド名: address_2
  - タイプ: テキスト

▼ 追記
※オプションに設定する内容の「Message」→「MailMessage」に変わっていたので両方載せてみた。


## メールフォーム用ビューの調整

■ ajaxzip3.js をフォーム用のビューに読み込む
/theme/YOUR_THEME/Elements/mail_form.php

```
$this->BcBaser->js('admin/ajaxzip3', false);
```

以上で完了です。
文字を長体に変形して指定幅に詰めるjQuery拡張

# tume.js
所定の幅に収まるように長体にして文字を詰めるjQuery拡張。
widthを指定したブロック要素に対して使う。
##使い方

    $(hoge).tume() innerHTMLの内容を詰める
    $(hoge).tume(str) strを詰めて設定
    $(hoge).tume(str,true) widthに満たない場合は広げる

##サンプル

表示例: 
![表示例画像](http://wakufactory.jp/html5/kumi/tume/tume.png)

[実働サンプル](http://wakufactory.jp/html5/kumi/tume/tume_sample.html)

実際の使用例: [書誌ガチャ](http://wakufactory.jp/misc/handot/gacha.html) タイトル等を１行に収めるために使用。

##仕組み

隠しdevエレメントに一旦文字を表示し、幅を測った上で、所定のサイズに収まるように、css::transformで変換をかけている。

##リソース

[github](https://github.com/wakufactory/tume)
ファイルサイズを取得する！

#ファイルサイズを取得する！

これは [Delphi Advent Calendar](http://qiita.com/advent-calendar/2015/delphi) 補欠の記事です。

実は Delphi にはプラットフォーム関係なく[ファイルサイズを取得する関数やメソッドはありません](http://stackoverflow.com/questions/1642220/getting-size-of-a-file-in-delphi-2010-or-later)。

ただ、Indy にはあります。
IdGlobalProtocols ユニットに宣言されている FileSizeByName 関数です。

でも、Indy を uses すると色々なユニットが含まれてしまうので、コードが少し大きくなってしまいます。
それは避けたいところです。

そこで、作りました。

# TFileHelper

TFile に、GetSize メソッドを１個だけ追加するヘルパクラスです！！
[ソースはこちら](https://gist.github.com/freeonterminate/e2316f0f829115851358)。

また１個だけ追加するヘルパを作ってしまった…

このユニット System.IOUtils.Files は System.IOUtils.TFile を System.IOUtils.Files.TFile としてエイリアスしているので、System.IOUtils.Files だけを uses すれば TFile が使えます。

使い方は簡単。
TFile.GetSize を呼ぶだけです。

```delphi
implementation

uses
  System.IOUtils.Files
  , FMX.ApplicationHelper // 「Application.ExeName 作ったよ」参照
  ;

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(TFile.GetSize(Application.ExeName).ToString);
end;
```

#発展
多分、@ht_deko 氏が、[uIOUtilsEx.TFileEx](http://ht-deko.com/delphiforum/?vasthtmlaction=viewtopic&t=1431) に追加してくれるはず…

#追記
2016/01/05 追記
追加して貰えました！！
https://twitter.com/ht_deko/status/683982584393515009
Application.ExeName 作ったよ

#TApplication.ExeName

これは [Delphi Advent Calendar](http://qiita.com/advent-calendar/2015/delphi) 補欠の記事です。


VCL でおなじみの [Application.ExeName](http://docwiki.embarcadero.com/Libraries/Seattle/ja/Vcl.Forms.TApplication.ExeName) は FMX には存在しません。
[同じ効果を持つものとして ParamStr(0) を使う](http://stackoverflow.com/questions/15218979/getting-application-path-in-firemonkey)と、言われてきました。
これで、確かに Windows や OS X では正しく動作するのです。

##しかし！！
Android では、正しく動作しません。
でも、そもそも Android では、何を返すべきなのでしょうか…？
apk のパス？ classes.dex のパス？？
…何が正解か判らないから ParamStr(0) は値を返さないのかもしれません。

今回はアプリの全てが含まれる apk が一番近いかなあと思い「ExeName は apk のパスを返す」と規定しました。

apk のパスは [Context.getPackageCodePath](https://developer.android.com/reference/android/content/Context.html#getPackageCodePath()) で取得できます。
（[ApplicationInfo](http://developer.android.com/reference/android/content/pm/ApplicationInfo.html#sourceDir) などからも取得できます）。

```delphi
// Application(apk) のパスが返る
TAndroidHelper.Context.getPackageCodePath;
```

#TApplicationHelper
これをラッピングした TApplication のヘルパクラスを作りました。

[ソースはこちら](https://gist.github.com/freeonterminate/2f7b2e29e40fa30ed3c4)。
※コードの使用や改変はご自由にどうぞ

これを uses すれば、こんな風に ExeName が使えるようになります。

```delphi
implementation

{$R *.fmx}

uses
  FMX.ApplicationHelper;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(Application.ExeName);
end;
```

#取れる値の例

- Windows
> C:\Source\Delphi\ExeName\Win32\Debug\Project1.exe

- OSX
> /Users/UserName/PAServer/scratch-dir/SDKVersion/Project1.app/Contents/MacOS/Project1

- iOS
> /var/mobile/Containers/Bundle/Application/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA/Project1.app/Project1

- Android
> /data/app/com.embarcadero.Project1.apk

#まとめ
Android の ExeName って結局何を返すのが正解なんでしょうね！？
あと、TApplicationHelper と言いながら１個しか機能が追加されないし、TApplication に依拠してるわけでもないので、普通の関数にしたほうが良いかもしれませんね！
sinatraでfitbitのデータを利用する

# はじめに
消費カロリーや心拍数を集計する仕組みを作りたい。ということで
[Fitbit](https://www.fitbit.com/)のデータを取得してWebアプリから使用するための準備を行う。

# Developer登録
Fitbit API をhttps://dev.fitbit.com/jp から、Developer登録を行う。

# アプリを登録
必要事項を記載して、登録する。callback URLは、実際のCallback先でないと、リクエスト時に蹴られるので注意
`http://localhost:3000/auth/fitbit_oauth2/callback`
のように登録した

# sinatraの準備
省略

# Gemfile作成
`bundle init`
して、ひな形を作った後

```
gem 'sinatra'
gem 'omniauth'
gem 'omniauth-oauth2'
gem 'omniauth-fitbit-oauth2'
gem 'multi_json'
gem 'rest-client'
```
を追加。OAuthライブラリとしてomniauthを使う。便利。
`bundle install`
を実行

# アプリ作成
こんな感じ

```rb
require 'rubygems'
require 'bundler'
Bundler.require

class HRMonitorApp < Sinatra::Base
  configure do
    use OmniAuth::Builder do
      provider :fitbit_oauth2, '#{OAuth 2.0 Client ID}','#{Client (Consumer) Secret}',
      scope: 'profile',
      expires_in: '2592000'
    end
    enable :sessions
    enable :inline_templates
    set :bind, '0.0.0.0'
    set :port, 3000
  end
  
  helpers do
    def get_profile
      res = JSON.parse RestClient.get "https://api.fitbit.com/1/user/-/profile.json", Authorization: "Bearer #{session[:token]}"
      warn "#{res}"
      "<body><h1><code>#{res}</code></h1></body>"
    rescue => e
      warn e
    end
  end
  
  get '/' do
    if session[:token]
      get_profile
    else
      redirect to '/auth/fitbit_oauth2'
    end
  end
  
  get '/auth/fitbit_oauth2/callback' do
    session[:token] = env['omniauth.auth']['credentials'].token
    redirect to '/'
  end
end

HRMonitorApp.run!
```
## はまったポイント

1. configureブロックで、`enable :sessions`をやらないと、セッションがないとOmniAuthに怒られる
2. `HRMonitor.App.run!` runにしてた。
3. OmniAuthを使う場合、認証用のURLは固定。omniauth-*(今回はomniauth-fitbit-oauth2)で定義されている:nameを使った /auth/:name が認証用のURLとなる。 
- https://github.com/codebender/omniauth-fitbit-oauth2/tree/master/lib/omniauth/strategies/fitbit_oauth2.rb
だと、:name => fitbit_oauth2 なので /auth/fitbit_oauth2 に飛ばす必要がある。コールバックはこれに/callbackをつけたもの。なので、結局アプリ登録する際に指定するべきコールバックURLは自動的に決まる。
4. スコープは https://dev.fitbit.com/docs/oauth2/#scope を参照

# 今後の予定
心拍数が一定以上になっている時間を列挙したり、睡眠時間を管理したり
Qiitaのストックとはてなブックマークの追加を同時に実行するChromeエクステンション



Qiitaにストックするか、はてなブックマークに追加するか迷ったあげく、どっちにも保存するという、面倒なことをすることがあったりするので、この作業めいたことを簡略化するため、Chromeのエクステンションを書いてみました。↓

[Github:high5/qbta](https://github.com/high5/qbta) 


このエクステンションは, Qiitaのストックボタンを押すと、はてなのブックマークレットをたちあげ、Qiitaの対象の投稿記事についたタグをはてぶコメント欄にタグとして挿入して、追加ボタンをクリックするというのを自動的にやってくれます。はてブのほうの追加ボタンが自動でクリックされるかはオプションで選択できるようになってます。Qiitaのタグの他にコメントを残したいような人はこのオプションをオフにしてください。
広告用のバナー領域をAutoLayoutを使って確保する


無料アプリには、画面の下に広告バナーを表示するものがあります。このバナーは画面の向きが縦の時と横の時で高さが異なることがあります。そんな広告用のバナー領域をAutoLayoutを使って実現する方法について説明します。

# 完成イメージ

今回は高さの違う二つのバナーをViewで用意しています基本的には緑色のバナー（height=50）が表示されます。ただし、iPhone（ただしiPhone 6plusをのぞく）を横に向けた時は、青いバナー（height=33）が表示されます。iPadなど画面が十分に大きい端末の時には、縦横問わず緑色のバナーが表示されます。

![BannerSample.gif](https://qiita-image-store.s3.amazonaws.com/0/75307/d7cecd43-4dad-c25d-4788-f4992b9c1492.gif "BannerSample.gif")

# Autolayoutの共通的な設定を行う

まずはAutolayoutを使って縦横共通となる設定を行います。設定している項目は次の通りです。

* TableViewの上下左右のマージン
* 緑色のバナーの下と左右のマージン、height=50
* 青色のバナーの下と左右のマージン、height=33

TableViewの下のマージンは-50としていますが、これは緑色のバナーの高さ分です。

![BannerSample1.gif](https://qiita-image-store.s3.amazonaws.com/0/75307/0a73da8f-cc18-1dfb-f42d-384cbcae373e.gif "BannerSample1.gif")

# バナー用のViewを出し分ける

ここでは、基本的には緑色のバナーを表示しつつ、iPhoneの横画面のときには青色のバナーを表示する処理を行っています。
対象となるビューを選び、ユーティリティエリアのAttributeを選択します。Viewカテゴリの一番下に"Installed"というカテゴリがあるので、ここで共通設定と個別設定を行います。今回は、緑色のバナーについては共通はチェックが入り、任意のwidthでheightがCompactの場合のみチェックが入らない設定を行います。そして青色のバナーについては、その逆の設定を行います。

ストーリーボード上で、widthとheightを切り替えたときに正しくバナー表示が切り替わっていることを確認します。

![BannerSample2.gif](https://qiita-image-store.s3.amazonaws.com/0/75307/578af139-9e90-f585-128a-db7174f851f1.gif "BannerSample2.gif")

# TableViewの下のマージンを設定する

次に、バナーが切り替わったときにTableViewの下につけたマージンの幅を変更します。これは、ストーリーボード上でheightを切り替えた状態で、Constraintの値を直接変更します。
ここでは、任意のwidthでheightがCompactの場合のみ、TableViewの下のマージンを-33としています。

![BannerSample3.gif](https://qiita-image-store.s3.amazonaws.com/0/75307/ddca4aa0-52ad-aa35-8ba9-ab83d731bd0e.gif "BannerSample3.gif")

# サンプルソース

https://github.com/nakaken0629/BannerSample
『あなたのチームは、機能してますか？』を読んだ

※本の内容を紹介しており、ネタバレします

[あなたのチームは、機能してますか？](http://www.amazon.co.jp/gp/product/4798103683/ref=as_li_ss_il?ie=UTF8&camp=247&creative=7399&creativeASIN=4798103683&linkCode=as2&tag=neira-22)
![41yXPrx75dL.jpg](https://qiita-image-store.s3.amazonaws.com/0/4107/ade93aed-a077-fbfd-acd7-eda84ade1d6d.jpeg "41yXPrx75dL.jpg")


11月の始めくらいに読んだ書籍なんだけど、ずっとまとめてなかったので記載した。

## 書籍の内容構成
物語形式（ビジネス・フィクション）で進む200ページの中で「チームづくり」をテーマに話しが進む。
舞台はシリコンバレーの新興ハイテク企業、そこにブルーカラー企業出身の「キャサリン」がCEOに就任し、経営陣チームの健全化までの道のりを描いている。
また、他30ページ超で、書籍内で出てきた「モデル」について、解説があり、非常に親切な作りになっている。

## モデル

下記の機能不全は、 _「5つのまったく異なる問題で、個別に対処できるかのように誤解されるかもしれない。しかし実際には、これらは相互に関係しており、5つのうちの一つでももろい部分があれば、チームの成功は絶望的になる可能性さえある。」_ と書籍内で説明のある通り、1つでも無視のできるものではない。

1. 信頼の欠如（互いを信頼する）
2. 衝突の恐怖（アイデアをめぐって遠慮なく衝突する）
3. 責任感の不足（決定や行動計画に責任感をもって取り組む）
4. 説明責任の回避（計画を守らなかった場合、互いの責任を追求する）
5. 結果への無関心（チーム全体の結果を達成することを重視する）

結束の固いチームでは 1.から順にカッコ内に記載したとおりの内容を解消しているはず。

## モデルに対しての所感

僕の個人的な感覚では、多くのチームは中身を伴わない、上辺だけのつながりが多く「1. 信頼の欠如（互いを信頼する）」がそもそも満たせていない気がする。
よって「2. 衝突の恐怖（アイデアをめぐって遠慮なく衝突する）」もそうだが、そもそも衝突すら無意味だと感じている方もいるのかもしれない。

結果として3. 4.を経由しているので、「5. 結果への無関心（チーム全体の結果を達成することを重視する）」が多発しているのかもしれない。
また、 __強いリーダー（声の大きなうるさいリーダーも同意）__は「4. 説明責任の回避（計画を守らなかった場合、互いの責任を追求する）」をメンバー間で追求させ、自分はフォローにまわるという動きができないので、自分で解決に翻弄されている。

まさに愚の骨頂。
Swift で簡単なシングルトンの実装方法

Swift で マネージャー系のコードを書く時にはシングルトンの実装を迫られる場合があります。インスタンスとしていくつも存在されても困る場合があるからです。そんな時に便利な二つのイディオムを紹介します。

## 通常のシングルトン

```.swift
class Manager {
	static let sharedManager = Manager()
	private init() {
	}
}
```
* `static let` の構文
* `init` を `private` にする
* 初期化がインスタンスの生成がシンプルな場合に便利

## クロージャーを使ったシングルトン

```.swift
class Manager {
	static var sharedManager: Manager = {
		return Manager()
	}()
	private init() {
	}
}
```
* `static var` の構文
* `init` を `private` にする
* インスタンスはクーロージャ内 `{` `}` で生成して、`return` 文で戻す
* クロージャーの最後の `()` を忘れないで
* インスタンスの生成の為に、ファイルやリソースを用意したりなど、いくつかステップを踏む必要がある場合に便利

（EDIT: 表現を変更しました）

## どちらでも、シングルトンのオブジェクトを生成します

```.swift
var manager1 = Manager.sharedManager
var manager2 = Manager.sharedManager
manager1 === manager2 // true
```

`init` に `private` が付いているので、基本的には直接生成はできません。ただし、同じソースファイルから呼び出す場合はその限りではありません。Playground で試す場合は要注意ですね。

---

【参考情報】
Swiftでシングルトンパターンを実装する３つの方法
http://qiita.com/susieyy/items/acb3bc80a1dafe64cffd
underscoreコードリーディング（partition）



underscoreに詳しくないので、勉強半分でソースコードを読む。


##利用するバージョン
[underscore.js(v1.8.3)](https://github.com/jashkenas/underscore/tree/1.8.3)


##partitionとは


###[underscorejs.orgのpartition](http://underscorejs.org/#partition)

こんな説明。
>####_.partition(array, predicate) 
Split array into two arrays: one whose elements all satisfy predicate and one whose elements all do not satisfy predicate.



```javascript

_.partition([0, 1, 2, 3, 4, 5], isOdd);
=> [[1, 3, 5], [0, 2, 4]]

```

------------- 

配列を2つの配列に分割します。
1つはpredicateで指定されたものをすべて満たす配列、もう1つはそれをすべて満たさない配列です。

###[underscore.partition](https://github.com/jashkenas/underscore/blob/1.8.3/underscore.js#L439)

コード的にはこのあたり。


```javascript

 // Split a collection into two arrays: one whose elements all satisfy the given
  // predicate, and one whose elements all do not satisfy the predicate.
  _.partition = function(obj, predicate, context) {
    predicate = cb(predicate, context);
    var pass = [], fail = [];
    _.each(obj, function(value, key, obj) {
      (predicate(value, key, obj) ? pass : fail).push(value);
    });
    return [pass, fail];
  };

```

2つめの引数をcbに渡す。functionだった場合はそのまま利用する。
分割する配列のpassとfailを宣言する。
objに対して_.eachを利用し、objの値をpredicateに渡し、passとfailの配列に振り分ける。
その後、passをfailをひとつの配列にまとめ、返す。
1時間で作ったRPGツクールMV作品を楽しんでもらった、という話

この記事は[RPGツクールMV(なんでもあり) Advent Calendar 2015](http://www.adventar.org/calendars/1119)の12月25日に投稿する・・・予定だったものがちょっと遅くなってしまったなり。


それはさておき。

本当はクリスマスにちなんだRPGツクールMV作品を作ろうと思っていたのですが、いろいろ忙しくて時間が取れず・・・。

とはいえ、時間が無い時には無いなりに作ってゲーム公開しても体裁が付くのが、この度発売となった[RPGツクールMV](https://tkool.jp/mv/)の良いところ。

たとえば、こんな感じ。
![スクリーンショット 2015-12-26 21.10.49.png](https://qiita-image-store.s3.amazonaws.com/0/107160/c397301f-8454-18d8-8484-940d373c1789.png)
[プレイはこちら](https://dl.dropboxusercontent.com/u/17244244/gakenama/index.html)

[「崖生の1日」](https://dl.dropboxusercontent.com/u/17244244/gakenama/index.html)というタイトルのゲームを制作時間：1時間ほどで作ってみました。ゲーム自体は1分程度のストーリーが未完で終了します。

これは、私が配信をお手伝いしているニコニコ生放送(ユーザー放送)[「崖の上の生放送」](http://com.nicovideo.jp/community/co2688681)を舞台にしています。

通称「崖生」と呼んでいるこの放送、メイン司会は週刊ファミ通の元編集長・[バカタール加藤](https://twitter.com/bakataal)さん。この他、ぐれキャラの[カニ巫女](https://twitter.com/yudashio)さん、謎の美女[こっこ](https://twitter.com/kokko919)さん、映画・特撮ライターの[アップル大谷](https://twitter.com/applebigvalley)さんが出演し、毎回自由奔放に放送をし続けております。

ゲームは、放送現場を舞台に「とある事件」が起こる・・・という導入部分までをサクッと描いております。

1時間でサクッと作った後、出演者にゲームURLを(LINEグループで)伝えたら、みんな驚きと共に喜んでくれまして。バカタール加藤さんからは「この続き、一緒に作ろうよ！」とやる気満々。

まあ、ゲーム自体は従来のツクールでも同様のものはできますが、ゲームをPCブラウザでもスマホブラウザでも遊べるようにすると、遊ぶ側の手間が少ないので遊んでもらいやすいです。今ではスマホを持っていない人は少数派だと思うので、友達や身内にちょっと楽しんでもらう用途に・・・みたいな部分はRPGツクールMVならではだと思うのです。

なお、12月20日の生放送内でもこのゲームを紹介し、出演者にゲーム内をセリフをアテレコしてもらうみたいな楽しみ方もしました。
![スクリーンショット 2015-12-26 21.32.34.png](https://qiita-image-store.s3.amazonaws.com/0/107160/70e680e4-9e25-90f6-9ef7-836148e90fce.png)

こんな感じで「短時間で作ったものでも公開することをオススメするよ！」ということを伝えたいなぁと思い、こんな記事を書いてみました。

ちなみに短時間で作るコツは、作りきれない部分はすべてこうしておくことです。w
![スクリーンショット 2015-12-26 21.56.13.png](https://qiita-image-store.s3.amazonaws.com/0/107160/9a417874-a4a8-eb25-09e6-b1afacb3ba5f.png)

それではみなさん、よいツクラー生活を！