OmniAICreator/Qiita-1.07M huggingface dataset:
Google Recaptcha

[![Build Status](https://travis-ci.org/crabstudio/Recaptcha.svg?branch=master)](https://travis-ci.org/crabstudio/Recaptcha) [![Latest Stable Version](https://poser.pugx.org/crabstudio/recaptcha/v/stable)](https://packagist.org/packages/crabstudio/recaptcha) [![Total Downloads](https://poser.pugx.org/crabstudio/recaptcha/downloads)](https://packagist.org/packages/crabstudio/recaptcha) [![Latest Unstable Version](https://poser.pugx.org/crabstudio/recaptcha/v/unstable)](https://packagist.org/packages/crabstudio/recaptcha) [![License](https://poser.pugx.org/crabstudio/recaptcha/license)](https://packagist.org/packages/crabstudio/recaptcha)
# CakePHP 3: Integrate Google Recaptcha v2

## Introduction

Integrate Google Recaptcha v2 to your CakePHP v3.x project

## Donate

Buy me a cup of coffee [![paypal](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=anhtuank7c%40hotmail%2ecom&lc=US&item_name=Crabstudio%20CakePHP%203%20%2d%20FlatAdmin%20Skeleton&item_number=crabstudio%2dcakephp%2dskeleton&no_note=0&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHostedGuest)

## Installation

You can install this plugin into your CakePHP application using [composer](http://getcomposer.org).

The recommended way to install composer packages is:

```
composer require crabstudio/recaptcha
```
Or add the following lines to your application's **composer.json**:

```
"require": {
    "crabstudio/recaptcha": "^1.0"
}
```
followed by the command:

```
composer update
```

## Load plugin

Add this line to **Your_project\config\bootstrap.php**
```
Plugin::load('Recaptcha', ['bootstrap' => true]);
```

## Configure

Write to your configure:
```
$recaptcha = [
    'Recaptcha' => [
        'type' => 'image',  //available image/audio
        'theme' => 'light', //available light/dark
        'lang' => 'vi',      //if not exist, plugin in will use your default locale
        'enable' => true,     //available true/false
        'sitekey' => 'your_site_key', //if you don't have, get one: https://www.google.com/recaptcha/intro/index.html
        'secret' => 'your_secret',
    ]
];
Cake\Core\Configure::write($recaptcha);
```

## Load component

In your controller initialize function
```
// Example, i just use recaptcha for function forgotPassword
if($this->request->action === 'forgotPassword') {
    $this->loadComponent('Recaptcha.Recaptcha');
}
```

## Usage

Display recaptcha in your view:
```
    <?= $this->Form->create()?>
    <?= $this->Form->input('email')?>
    <?= $this->Recaptcha->display()?>  // Display recaptcha box in your view, if configure enable = false, nothing display here
    <?= $this->Form->submit()?>
    <?= $this->Form->end()?>
```

Verify in your controller function

```
    public function forgotPassword() {
        if($this->request->is('post')){
            if($this->Recaptcha->verify()) { // if configure enable = false, always return true
                //do something here
            }
            $this->Flash->error(__('Please pass Google Recaptcha first'));
        }
    }
```

Done
ubuntu15.10使っていてアップデート後にfcitxが起動しなくなった場合

ubuntuのアップデート通知が出たのでアップデートし、
OS再起動したところfcitxが起動しなくなった。

im-configで再設定をして再起動したら治った。

```bash:
im-config
```

![スクリーンショット_2015-10-14_16-44-29.png](https://qiita-image-store.s3.amazonaws.com/0/25728/abe8f0f6-f75b-fc4d-6cea-e4e990150503.png)

![スクリーンショット_2015-10-14_16-44-37.png](https://qiita-image-store.s3.amazonaws.com/0/25728/28d212b5-b419-2900-f4fb-d019fc6f6f32.png)

![スクリーンショット_2015-10-14_16-44-46.png](https://qiita-image-store.s3.amazonaws.com/0/25728/7cf3c5c4-9f8f-6a60-5aa6-3bda62bf1c93.png)

![スクリーンショット_2015-10-14_16-44-54.png](https://qiita-image-store.s3.amazonaws.com/0/25728/d52952d4-5571-fd5b-a7f9-e3b47ca2241f.png)
google analytics の資格取得に向けて勉強してみた。

中途半端な情報だけですが、google analyticsについてのメモです。

公式サイトの動画を全部見て、
知らない言葉をここでメモして、
google analyticsの試験受けたら、
合格しました。

勉強時間は12時間くらいで、
analyticsは一応触ったことがあるので、抵抗はない状態でのスタートでした。

## analyticsで初めて聞いた、キーワードまとめ

各キーワードはanalyticsをどのように使用するかによって、意味が違ってきますが、ここでは、webサイトの分析に使用することを想定しています。

### コンバージョン

Webサイト上で獲得できる最終的な成果のこと。

#### マクロコンバーション

ユーザーがビジネス上の価値が高い操作を完了したときに発生します。e コマース ビジネスの場合、一般的には取引の完了が最も重要なマクロ コンバージョンです。

#### マイクロコンバーション

通常はユーザーがマクロ コンバージョンに近づいたことを示す指標となります

### アトリビューション
コンバージョンに対する貢献度を割り当てることを指します。

### KPI (Key Performance Indicators)
google analyticsでは目標値に対する状況を示す指数の事。
公式サイトの日本語約では、主要業績評価指標と訳されている。

### セグメント化
ビジネス目標を促進するうえで効果的なセグメント化の方法としての例
- サイトを初めて訪れたユーザーとリピーター 
- 初めて商品を購入するユーザーと、商品購入経験のあるユーザー 

### ディメンション
analyticsのレポートには必ず「ディメンション」と「指標」のふたつが含まれる。
ディメンションはユーザー、セッション、ユーザーの操作の性質を表します。

### 指標 (Metrics)
指標はユーザー、セッション、ユーザーの操作を数値的に測定したもので、数値データとなります。

### ユーザー

### セッション
gogole analyticsの初期設定ではセッションの期間は30分に設定されている。
30分を超えるとセッション数が１つ余計にカウントされてしまうので、サイトに応じて適切なセッションの設定が必要である。

### 直帰率
サイトを訪れたユーザーが 1 ページのみ閲覧し、サイトで以降の接点がなく離脱したセッション数の割合 

## 自動的にトラッキングされるトラフィックメディア

### organic
有料ではない検索結果から

### cpc
有料の検索から

### referral
検索エンジン以外のサイト上のリンクから

### none
リファラーがついていない場合。
MySQLでデータベースとユーザを作成するコマンド

MySQLのDBとユーザの作成コマンドです。

```sql
/* DBを作成 */
CREATE DATABASE _DB_NAME_ DEFAULT CHARACTER SET utf8;
/* ユーザを作成 */
CREATE USER _USER_ IDENTIFIED BY '_PASSWORD_';
/* 権限を付与 */
GRANT ALL PRIVILEGES ON _DB_NAME_.* TO _USER_@localhost IDENTIFIED BY '_PASSWORD_';
```

`_DB_NAME_` をデータベース名に置換します。
`_USER_` をユーザ名に置換します。
`_PASSWORD_` をユーザに設定するパスワードに置換します。

localhostになってますので、DBのホストが違う場合はこれも変更します。
データベース名にハイフンを付けたい場合はバッククオート（`）で囲む必要があります。
Rubyのstack level too deep回避をファイル内で完結させる


競技プログラミングでは、深すぎる再帰がしばしば問題になる。
キューや(データ構造の)スタックを使ってコーディングすれば防げるが、やはり再帰は便利である。

[AtCoder Regular Contest 045 C エックスオア多橋君](http://arc045.contest.atcoder.jp/tasks/arc045_c)を例に取る。

再帰が深すぎる場合、Pythonでは、sys.setrecursionlimit()により再帰の深さを変更できる。
cf: http://arc045.contest.atcoder.jp/submissions/526958

Rubyには同様の機能として、RUBY_THREAD_VM_STACK_SIZE環境変数がある。しかし、この値自体をプログラム中から変更しても、挙動を変更することはできない。
オンラインジャッジには単一のファイルしか提出できないため、通常の方法ではスタック拡張は困難ということになる。

今回は、環境変数を設定しつつ自分を実行し直すことで、当該ファイル内で完結させることができた。
cf: http://arc045.contest.atcoder.jp/submissions/526902

```rb
if !ENV['RUBY_THREAD_VM_STACK_SIZE']
	#Rubyパスを取得するには、rbconfigかrubygemsを使う。AtCoderでは--disable-gemsされているので、require 'rubygems'は必須である。
	#require 'rbconfig';RUBY=File.join(RbConfig::CONFIG['bindir'],RbConfig::CONFIG['ruby_install_name'])
	require 'rubygems';RUBY=Gem.ruby
	exec({'RUBY_THREAD_VM_STACK_SIZE'=>'100000000'},RUBY,$0) #100MB
end
```

ただし、binディレクトリは移動可能(librubyはRPATHから拾える)なので、その場合には対応できないことは留意。
ActiveAdmin で「検索状態」（Current Filters）を非表示にする設定

ActiveAdmin の一覧画面のサイドバーには、指定した検索条件が表示される欄がある。

検索項目(filter)や範囲(scope)のラベルは I18n で多言語化が可能だが、「検索状態」の範囲の値は I18n に対応していない。無理やり対応させることも難しそう。

であれば、いっそのこと「検索状態」自体を非表示にしてしまう。

```rb:config/initializers/active_admin.rb
ActiveAdmin.setup do |config|
  # Whether to display 'Current Filters' on search screen
  # config.current_filters = true
  config.current_filters = false
end
```
【Android】今更だけど手元のNexus6にマシュマロ焼いてみた

Android6.0 通称マシュマロが正式に発表され、Nexus5ではOTAも始まったと聞いていたのだけど、自分のNexus6には一向にアップデート通知がこないので、手作業でイメージファイル落としてAndroid6.0をインストールしてみた。

Android6.0以外にも、例えばAndroid4.xにダウングレードしたいとかでも使える手順だと思うのでメモ。

# 参考
**基本的な手順**
[How to install Android 6.0 Marshmallow on your Nexus phone or tablet](https://www.androidpit.com/how-to-get-android-m-preview)

**BootloaderのUnlockの手順**
[How to: Unlock the Nexus 6 Bootloader (Nexus 9 Too)](http://www.droid-life.com/2014/11/21/how-to-unlock-the-nexus-6-bootloader/)

**"boot.sig", "recovery.sig"がないって言われる場合の対処法**
[Nexus ファクリーイメージ flash-all.batエラー not contain ‘boot.sig’ ‘recovery.sig’ の対処法。](http://usagisaigon.com/nexus-5/nexus-%E3%83%95%E3%82%A1%E3%82%AF%E3%83%AA%E3%83%BC%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8-flash-all-bat%E3%82%A8%E3%83%A9%E3%83%BC-not-contain-boot-sig-recovery-sig-%E3%81%AE%E5%AF%BE%E5%87%A6/)

# 手順まとめ
1. 端末の「設定」＞「開発者向けオプション」＞「OEMロック解除」をオンにしておく
2. 端末の電源を落とし、ブートローダーを起動する（電源ボタンと音量減ボタン長押し）
3. PCとケーブルでつなぐ
4. 「BootloaderのUnlockの手順」の参考ページを参考に、bootloaderのロックを解除する
5. 「基本的な手順」の参考ページの"Prerequisites"にリンクがあるので、端末に合ったzipファイルを落としてくる。＆解凍する（解凍後のフォルダにもさらにzipがあるのでそれも解凍する。
6. adbのplatform-toolディレクトリにパスを通す（platform-toolディレクトリにあるfastbootが使えるように）
7. flash-all.bat（Macの場合はflash-all.sh）を実行する
8. 端末が自動的に再起動し、Android6.0が使えるようになる。

# ハマりポイントメモ
- まずOEMロック解除が必要。手順1と手順4を忘れずに。
    - **OEMロック解除すると、一旦端末を出荷状態に戻さなければならないので、バックアップを忘れずに！**
    - 以下のエラーが出たら解除できていないことを疑う。

```
(bootloader) Unlock before flashing
```

- 手順3でPCと端末をつなぐ際、USBポートによってはflash-all.batでエラーが出る。その場合はUSBを刺す場所を変えてみる。

```
$ ./flash-all.sh 
ERROR: could not get pipe properties
```

- 手順7で以下のエラーが出る場合は、「"boot.sig", "recovery.sig"がないって言われる場合の対処法」の参考ページを参考に、一つずつflashしてみる

```
archive does not contain 'boot.sig'
archive does not contain 'recovery.sig'
```
- 作業中はいつ端末が動かなくなるか分からない恐怖に襲われるけど、落ち着いてググりながら作業する。


以上
anemone.crawl内での、変数のスコープのわけがわからなかった話

まず、本文に入る前に、僕のコードを修正してくださった[riocampos](http://qiita.com/riocampos)様に感謝の旨を伝えたいと思います。ありがとうございました。



すぐ下にに掲載したのが、[riocampos様](http://qiita.com/riocampos)が修正してくれた一番簡潔に動くコードです。こちらを参考にしていただければと思います。

```rb

require 'nokogiri'
require 'open-uri'

URL = "http://iyashitour.com/meigen/greatman"
sets = []

doc = Nokogiri::HTML.parse(open(URL))
doc.xpath('//div[contains(@class,"one_half")]/a[2]')[1..-1].each do |b|
  sets << [b['title'], b['href']]
end
p sets


```

[Nokogiriについてのわかりやすい解説サイト](http://d.hatena.ne.jp/otn/20090509/p1)

[XPathについてのわかりやすい解説サイト](https://sites.google.com/site/shin1ogawa/xsl/xpath)

***
ここから下は、僕が頭を悩ませていた修正していただく前のコードです。再起動せず、メモリ周りがぐちゃぐちゃしていたことが、以下の問題が起こった原因だそうです。原因不明の現象が起こったら、次からはまず再起動するようにしたいと思います。

```ruby
body = nil
URL = "http://iyashitour.com/meigen/greatman"
sets = []

Anemone.crawl(URL, :depth_limit => 0) do |anemone|
	#クロールしたいURLの取得完了
	p anemone
	anemone.on_every_page do |page|
		doc = Nokogiri::HTML.parse(page.body)
		body = doc.xpath(%Q[//*[@id="wrap"]/*[@id="content"]//*[@class="entry-content"]/*[@class="one_half"]/a[2]])
		body.each do |b|
			set = []
			set << b.attributes['title'].value
			set <<  b.attributes['href'].value
			sets << set
            p sets 
            #ここで呼び出した場合、body.each内のsetsにはアクセスできる
		end
		
	p sets 
        #ここで呼び出した場合、body.each内はアクセスできないし、body.eachで作ったリストの結果も反映されない
	end
end
p sets
#ここで呼び出した場合、グローバル変数のsetsのリストに、body.each内で追加したものが反映されて返ってくる
```

なんでかわからないけど、anemone.crawlを実行したときにスコープの範囲が通常指定するやり方とは乖離していた。

とりあえず、anemone.crawlの外側で変数を初期化しておけば、anemone.crawlの外側からでも参照できるので、そうしておけば問題ない。
RaspberryPiで脈拍データをCSV出力(アナログ入力をpythonで確認)

#手順とリンク
1.準備と基礎編
http://qiita.com/tkyko13/items/62ff91bce7d9e555c434
2.アナログ入力確認編
http://qiita.com/tkyko13/items/981989a006a95821ccde
3.pythonで確認
ここ
4.脈拍センサ
http://qiita.com/tkyko13/items/e4afc73add81d7bbb426
5.csv出力
http://qiita.com/tkyko13/items/9c0eb46c1b65129d2556

#環境
ラズパイでどのようにpythonコードを書くのかのメモ
・ラズパイのデスクトップでIDLEで作成
（ディスプレイやキーボードが必要）
・ラズパイでviコマンド
（ディスプレイやキーボードが必要、マウスはなくてもよくなる）
・ラズパイにリモートデスクトップ、IDLEで作成
（ラズパイのネット接続とIPを確認出来る手段が必要）
・ラズパイにssh接続からvi
（ネット接続とIP確認できたら）
・ラズパイにftpでpythonファイル送信
（ネット接続とIP確認できたら
あと、自分のPCの開発環境で書けるよ、sublime textなど）

自分は臨機応変に使い分けています
基本はリモート接続しています
IP確認できる手段として同じネットワーク内から「arp -a」コマンドなどある
macのftpソフトはあまり使ってないですが、いいがない気がしますね
winの時はwinscp+puttyがすごくいい感じで、teratermも好きだったんですがね
ターミナルは好きです

#サンプルコードその1
とりあえず最もシンプルなコードの一つを乗せます
前回の「アナログ入力確認編」でのI2Cのアドレスを使用しています
まずは実行するたびに値を見ています

```sample1.py
import smbus

I2C_ADDRESS = 0x48
bus = smbus.SMBus(1)

bus.write_byte(I2C_ADDRESS, 0xFF)
value=bus.read_byte(I2C_ADDRESS)
print value
```

#サンプルコードその2
繰り返し文で常に見れるようにします

```sample2.py
import smbus
import time

I2C_ADDRESS = 0x48

bus = smbus.SMBus(1)

while True:
  bus.write_byte(I2C_ADDRESS, 0xFF)
  value=bus.read_byte(I2C_ADDRESS)
  print value
  time.sleep(0.1)
```

#サンプルコードその3
最終的に脈拍を取る目的なので、スレッドを利用し1ミリ秒ごとの処理にします

```sample3.py
import threading
import smbus
import time

I2C_ADDRESS = 0x48

bus = smbus.SMBus(1)

def loop():
	bus.write_byte(I2C_ADDRESS, 0xFF)
	value=bus.read_byte(I2C_ADDRESS)
	print value
	t=threading.Timer(0.1, loop)
	t.start()

t=threading.Thread(target=loop)
t.start()
```

#サンプルコードその4(追記)
今回は10秒間だけ測って終了にしたいので、100回スレッドが実行されたら終わる処理を書きます。
スレッドの引数に与える値がどんどん増えていくようにしました。
もっと単純にできるやり方を考えたのですが、思いつかなかった。
何か存じていたらコメントお願いします。
(のちにファイル操作も行うので処理終了時にファイルを閉じる処理を行う必要があり、追記させて頂きました)

```sample4.py
import smbus
import time
import threading
import csv

I2C_ADDRESS = 0x48

bus = smbus.SMBus(1)
f = open('data.csv', 'w')

def loop(count):

    # count = count+1
    bus.write_byte(I2C_ADDRESS, 0xFF)
    value = bus.read_byte(I2C_ADDRESS)
    print value

    writer = csv.writer(f, lineterminator='\n')
    writer.writerow([value])

    if count < 100 :
        t = threading.Timer(0.1, loop, [count])
        t.start()
    else :
        f.close()
        print 'finish'

t = threading.Thread(target=loop, args=(0,))
t.start()
```


次回は最後のサンプルコードを利用していきます
WordPress 使ったプラグイン


#**Ktai Entry**
![image](https://qiita-image-store.s3.amazonaws.com/0/94475/2ae65de7-1c6f-1f37-5233-f36cf06c51ee.png)

##内容
メール投稿を反映させる

##設定について
1.「Bad Gateway」でエラー
　環境）投稿用メアドにgmailを利用
　原因）メーラ側で接続フィルタがかっていた。
　対応）接続済みのアプリとサイト→安全性の低いアプリの許可「有効」にする

Googleのアカウント設定
https://myaccount.google.com/?hl=ja

#**User Role Editor**
![image](https://qiita-image-store.s3.amazonaws.com/0/94475/f013f4ff-30f0-f5dc-7683-68f79ddc0d3c.png)

##内容
ユーザーの権限ごとに利用できる範囲を設定する
meteor deploy で SSL (https) を有効にする方法


Meteor はインターネット上での簡単な動作確認のためのデプロイコマンドが用意されています。

```bash
meteor deploy <YOUR_APP_NAME>.meteor.com
```

上記コマンドで Meteor が用意しているサーバーにデプロイすると、

```bash
http://<YOUR_APP_NAME>.meteor.com
```

という URL 上でアプリが動かすことができますが、
ログイン機能などを実装したアプリを動かす時に平文でパスワード送られるのがなんだかいやですよね。


そこで SSL を有効化する方法です。

```bash
http://<YOUR_APP_NAME>.meteor.com
↓
https://<YOUR_APP_NAME>.meteor.com
```

と http の部分を https に変更してください。
これで SSL が有効化されます！なんとこれだけ！

簡単ですね！ :-P
UnityでAndroidのネイティブプラグインを使用する3つの方法

・・・と思ったら詳しい説明がすでにあった(笑)
詳細を確認したい方は以下参考。

[Androidネイティブ開発のすすめ](http://qiita.com/relzx/items/a35f7ab6dbacb48f7e26)
[Unity公式:Android 用のプラグインをビルド](http://docs.unity3d.com/ja/current/Manual/PluginsForAndroid.html)

ここでは情報整理がてら簡単にまとめ。

```lang:方法1/UnityPlayerActivityを継承する方法
// Android
public class AndroidPlugin extends UnityPlayerActivity {
	public static final String TAG = AndroidPlugin.class.getSimpleName();

	public void log(String mes) {
		Log.d(TAG, mes);
	}
}
----------------------------
// Unity
public static class AppUtil
{
    public static void Log()
    {
#if UNITY_ANDROID
        using (AndroidJavaClass c = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        using (AndroidJavaObject o = c.GetStatic<AndroidJavaObject>("currentActivity"))
        {
            o.Call("log", "お前は、無力だ。");
        }
#endif
    }
}
```

```lang:方法2/JavaのClassファイルを直接呼ぶ方法
// Android
package com.tempura;

public class AndroidPlugin {
	public static final String TAG = AndroidPlugin.class.getSimpleName();
	
	public void log(String mes) {
		Log.d(TAG, mes);
	}
}
----------------------------
// Unity
public static class AppUtil
{
    public static void Log()
    {
#if UNITY_ANDROID
        using (AndroidJavaObject o = new AndroidJavaObject("com.tempura.AndroidPlugin"))
        {
            o.Call("log", "お前は、無力だ。");
        }
#endif
    }
}
```

```lang:方法3/Unityから直接Javaコードを呼ぶ方法
// Unity
public static class AppUtil
{
    public static readonly string Tag = typeof(AppUtil).Name;

    public static void Log()
    {
        using (AndroidJavaClass c = new AndroidJavaClass("android.util.Log"))
        {
            c.CallStatic("d", Tag, "お前は、無力だ。");
        } 
    }
}
```

方法1は UnityPlayerActivity を継承したクラスを作成して呼ぶ方法。
メリットとしては、方法2と違いクラス名を汎用的に記述出来るので、プログラムの変更に強い。また、UnityPlayerActivity を継承してるクラス=ネイティブプラグイン の図式が成り立つので、パッと見分かりやすい。
デメリットとしては、UnityPlayerActivity を継承してるので他のクラスを継承できない。

方法2は普通にJavaで定義したクラスを呼ぶ方法。
メリットとしては、UnityPlayerActivity を継承しないので、他のクラスを継承可能。あと単純に UnityPlayerActivity を継承してないので利用が手軽。
デメリットとしてはUnity側で使用する際にパッケージ名の指定が必要になるので、プログラムの変更に弱い。

方法3はUnityから直接Javaコードを呼ぶ方法。
メリットとしては、Javaのコードを書く必要がない(全てC#で完結！)。
デメリットとしては可読性が悪くなる。そもそもJavaのコードをC#で無理やり記述してるからね。。


自分が開発する時は、そのプロジェクト内で使用する個人のネイティブプラグインは方法1を使用して、ライブラリ群を作成する際は方法2を使用している。方法3は基本的に使用しない。理由としては、UnityPlayerActivity は1プロジェクトに1つしか継承出来ない代わりに、目印としては分かりやすく(主に他の人が見た時に)、そもそも個人のネイティブプラグインの量は多くないから1クラスにまとめるため。逆にライブラリ群を作成する際は、がっつりネイティブプラグインを作るし、UnityPlayerActivity はメインプロジェクトの方で使用する可能性があるので。方法3は可読性が悪くなっちゃうので、基本、方法1で処理してる。
最近知って改めてS3を好きになった機能！コンテンツ配信をセキュア化する「PresignedURL」

AWSのS3にはPresignedURLという、コンテンツを限定的に公開するための機能があります。
S3を使ってコンテンツ配信を行っている人は是非とも押させておくべき機能です。
PresignedURLの概要から利用シーン、具体的な使い方をまとめます。

## PresignedURLとは
S3にアップロードされたコンテンツを制限時間付きで公開する機能です。
指定した時間内のみ有効なURLを動的に生成することができ、そのURLにアクセスすることでコンテンツにアクセスできます。
URLの生成にはアクセスキーとシークレットキーが必要です。
オブジェクトのアクセス権を持つ者が、アクセス権を持たない者に制限時間付きでコンテンツを公開できる機能なのです。

## PresignedURLを使うとどんな嬉しいことがあるのか
「制限時間付きで公開できて嬉しいの？」
「API使って、時間がきたらコンテンツ削除すれば良いじゃん！」
と最初は思ったのですが、PresignedURLの想定利用シーンは、以下のようなシーンです。

WebアプリケーションサーバーのコンテンツをS3に配置して、Webアプリケーションサーバーの負荷軽減を行うとします。

下記の構成を実現することで、コンテンツをWebアプリケーションサーバーに配置した場合と比較して、Webアプリケーションサーバーの負荷を下げる事ができます。

![スライド1.JPG](https://qiita-image-store.s3.amazonaws.com/0/20223/00170ad6-5bc6-a0d4-482b-49363e9b75ea.jpeg)


ただし、上記の構成を実現するためには、S3にアップロードしたコンテンツをどこからでもアクセス可能なように設定する必要があります。
つまり、Webアプリ関係なく、コンテンツが利用される可能性があるわけです。

そこで、PresignedURLの出番です！
Webアプリケーションサーバーで、一時的に有効なURLを動的に生成し、そのURLをブラウザに渡してやることで、コンテンツの全公開をする必要がなくなります。
生成されたURLもすぐに無効になるため、自由にそのコンテンツにアクセスできるという事は無くなります。
具体的には下記のイメージです。

![スライド2.JPG](https://qiita-image-store.s3.amazonaws.com/0/20223/772499c8-1c62-be93-76ff-a07d48cd13e5.jpeg)


PresignedURLの機能は、時間を限定してコンテンツの公開ができて嬉しいというよりは、
「動的に」時間制限ありのコンテンツ公開ができるのが嬉しいのです。


## 実際にPresignedURLを生成してみる
実際にPresignedURLの生成をしてみます。

AWSから提供されているSDKを利用することで、簡単にPresignedURLを生成することができます。

以下は、PresignedURLの生成をJavaで実装してみたコードです。

```java

	private static URL createPreSignedUrl(String accessKey, String secretKey, String bucketName, String objectName){
	    AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
	    AmazonS3 s3Client = new AmazonS3Client(credentials);
		
		Date expiration = new Date();
		long msec = expiration.getTime();
		msec += 1000 * 60; // 1分だけ有効なURLを生成する
		expiration.setTime(msec);
		
		GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, objectName);
		generatePresignedUrlRequest.setMethod(HttpMethod.GET); 
		generatePresignedUrlRequest.setExpiration(expiration);
		             
		return s3Client.generatePresignedUrl(generatePresignedUrlRequest); 
	}

```

上記を使って、"wakamatsu-test"という名前のバケットに作成したtest.txtを1分間だけ公開します。

![s3ob.png](https://qiita-image-store.s3.amazonaws.com/0/20223/aea98256-2b51-8574-b8e9-d3d583018171.png)

アクセスを許可していないので、以下の「リンク」にアクセスしても、Access Deniedが出てしまいます。

![access.png](https://qiita-image-store.s3.amazonaws.com/0/20223/730b7c51-323c-a979-49a8-abe1c046f6d9.png)

![dn.png](https://qiita-image-store.s3.amazonaws.com/0/20223/381d87b4-459d-1750-3d4e-880e0ab68e59.png)

先ほどのJavaプログラムを使ってPresignedURLを生成します。
以下が生成されたURLです。

```
https://wakamatsu-test.s3.amazonaws.com/test.txt?AWSAccessKeyId=AKIAI2HC6MLP22MJDT2Q&Expires=1444751266&Signature=a97izpIZGlL%2F3ba%2BsjyKiVFJDk0%3D
```

ブラウザで上記のURLを開いてみます。

![succ.png](https://qiita-image-store.s3.amazonaws.com/0/20223/8376f116-18c1-19d7-f04e-ec264e585edf.png)

全公開していないコンテンツにアクセスすることができました！

ちなみに、1分後にアクセスしてみると、、、

![expire.png](https://qiita-image-store.s3.amazonaws.com/0/20223/b245a669-9da0-d929-57f6-2130d7a02b1f.png)

"Request has expired"となり
ちゃんとアクセスできないようになっています！

## まとめ
PresignedURLを使う事で、セキュアなコンテンツ公開を実現する事ができます。
PresignedURLの生成はSDKを使う事で簡単に生成できますので、ぜひ使ってみてください。
Siegeを使ってカジュアルWeb負荷テスト

## インストール
```
sudo yum -y update
sudo yum install gcc make openssl-devel
wget http://download.joedog.org/siege/siege-latest.tar.gz
tar zxvf ./siege-latest.tar.gz
rm -f siege-latest.tar.gz
cd siege-3.1.2/
./configure && make
sudo make install
cp doc/siegerc ~/.siegerc
```

## 実行
### urls.txtからランダムにURLを抽出して、10秒間300同時接続でアクセスをする
```siege -c 300 -t 10S -b -i --log=/tmp/siege.log -f /usr/local/etc/urls.txt```

### sample.jp に対して、同時ユーザー数は30でリクエスト数5で10秒間の連続負荷を掛けたい
```siege -c 30 -r 5 --time=10S --log=/tmp/siege.log http://sample.jp```

## fileから読み込み
```urls.txt
https://sample.jp
https://sample.jp/search/tag
https://sample.jp/id/test
```


## 実行オプション
| オプション | 意味 |
|--------|--------|
|-V, –version|バージョン表示|
|-h, –help|ヘルプ表示|
|-C, –config|コンフィグファイルを指定|
|-v, –verbose|アクセスの状態を標準出力に表示|
|-q, –quiet|verboseをオフにしてテスト出力を抑制|
|-g, –get|HTTP リクエストの GET メソッドを利用して、HTTP ヘッダを取得してトランザクションを表示する|
|-c, –concurrent=NUM|同時接続ユーザーを指定でデフォルトは10|
|-i, –internet|INTERNET ユーザーモードで URL のリストからランダムにアクセスする|
|-b, –benchmark|ベンチマークモードでリクエスト間隔を置かない（デフォルトは 1 秒間のリクエスト間隔を置く）|
|-t, –time=NUMm|テストの時間を指定（S = 秒、M = 分、H = 時間）|
|-r, –reps=NUM|テストにおける毎秒のリクエスト数|
|-f, –file=FILE|URL のリストファイルを指定|
|-R, –rc=FILE|siegerc ファイルを指定（デフォルトは ~/.siegerc）|
|-l, –log[=FILE]|ログファイルのパスを指定する（指定が無い場合には PREFIX/var/siege.log）|
|-m, –mark=”text”|ログファイル内にマーキング（区切り）文字を入れることが出来る|
|-d, –delay=NUM|リクエスト間の間隔を指定（デフォルトは 1 秒）|
|-H, –header=”text”|リクエストヘッダを付与することが出来る|
|-A, –user-agent=”text”|User-Agent の指定|
|-T, –content-type=”text”|Content-Type の指定も可能|


## 実行結果の見方
| 項目 | 意味 | 出力例 |
|--------|--------|--------|
|Transactions|リクエスト数|506 hits|
|Availability|成功率|100.00 %|
|Elapsed time|処理時間|9.51 secs|
|Data transferred|転送量|0.13 MB|
|Response time|平均のレスポンス時間|0.01 secs|
|Transaction rate|毎秒のリクエスト数|53.21 trans/sec|
|Throughput|スループット|0.01 MB/sec|
|Concurrency|平均の同時接続数|0.48|
|Successful transactions|成功したリクエスト数|506|
|Failed transactions|失敗したリクエスト数|0|
|Longest transaction|1リクエスト当たりの最長秒数|0.02|
|Shortest transactio|	1リクエスト当たりの最短秒数|0.00|


## 参考リンク
- [負荷テストが気軽に行えるsiegeでちょっとハマった](http://blog.kenjiskywalker.org/blog/2015/02/13/siege/)
- [Siege でお手軽 Web 負荷テスト - Qiita
](http://qiita.com/inokappa/items/84f42dbd718a8070bd1d)
- [Siege でお手軽 Web 負荷テスト](http://blog.cloudpack.jp/2014/08/25/easy-web-load-test-with-using-siege/)
- [サーバのパフォーマンスが気になる人に嬉しいツール2つ](http://tech.vasily.jp/siege_and_httping/)
- [siegeでお手軽にストレステスト](http://qiita.com/biatunky/items/4412d0deb3075293da98)
RetrofitのJSONライブラリを使うときにしっておきたいこと

# 前置き

使い方とか詳しい話はzakiさんのスライドとかみるとよさそう

- [RealmとJSONライブラリ](https://speakerdeck.com/zaki50/realmtojsonraiburari)

現状だとRetrofitで対応しているConverterは下記3つの選択肢がある

- gson
- jackson
- moshi

# メソッド数

| Name                         | method count |
|------------------------------|--------------|
| gson-2.4.jar                 | 1242         |
| jackson-databind-2.6.3.jar   | 8019         |
| jackson-core-2.6.3.jar       | 2192         |
| jackson-annotation-2.6.3.jar | 248          |
| moshi-1.0.0.jar              | 609          |

あんまり言及されないが、Androidは65K問題とかあるので気にしたい点。
jacksonは早いのだけれど、10Kのmethod数を持っていかれるのでデカいアプリやGooglePlayServicesを利用するアプリは注意しておいたほうがいい。

# JSONのfield存在チェック

例えば `{"hoge":"fuga"}` ってjsonが来た時に `{"piyo":""}`ってfieldが存在することを保証したい。
これを例外として扱う仕組みをライブラリ側でサポートしてるかどうか

Gson

- [Gson optional and required fields](http://stackoverflow.com/questions/21626690/gson-optional-and-required-fields)
- できるにはできるがクラスごとにDeserializerを設定しなくちゃならないのがツライところ

Jackson

- [Jackson 2.6.0 から parse時のrequired fieldをチェックできるようになった。](http://qiita.com/mattak@github/items/1be9ef9af790f31c9100)

Moshi

- ドキュメントがあんまりなくて不明...
- 誰か知ってたら教えて下さい

# 個人的な感想

Jackson

- 早くてよい
- method数がでかすぎてAndroidで利用するには要注意

Gson

- 安定していて良い
- PerformanceとRequiredFieldチェックが効かないのが残念.

Moshi

- 1.0.0が出たばかりでまだ若い
- だがシンプルで軽量でよさそうな感じ
- パフォーマンスもこれからに期待
SurfaceTextureとは

※[SurfaceTexture](http://developer.android.com/intl/ja/reference/android/graphics/SurfaceTexture.html)のClass Overviewを日本語訳してみました。

OpenGL ESテクスチャーとしてのイメージストリームからのキャプチャーフレームです。

イメージストリームはカメラプレビューやビデオデコードから来ます。SurfaceTextureから作られた[Surface](http://developer.android.com/reference/android/view/Surface.html)は[android.hardware.camera2](http://developer.android.com/reference/android/hardware/camera2/package-summary.html), [MediaCodec](http://developer.android.com/reference/android/media/MediaCodec.html), [MediaPlayer](http://developer.android.com/reference/android/media/MediaPlayer.html), [Allocation](http://developer.android.com/reference/android/renderscript/Allocation.html)等のAPIからの出力先として使用することができます。
[updateTexImage()](http://developer.android.com/reference/android/graphics/SurfaceTexture.html#updateTexImage())が呼ばれると、SurfaceTextureを作成するときに指定されたテクスチャーの内容がイメージストリームからの最新の画像に更新されます。これによりいくつかのフレームがスキップされることがあります。

SurfaceTextureは古い[Camera](http://developer.android.com/reference/android/hardware/Camera.html) APIでのSurfaceHolderとして使うこともできます。こうすることでデバイスのディスプレイの代わりに全てのイメージストリームがSurfaceTextureに送られるようになります。

テクスチャーからのサンプリングをする場合は、まずテクスチャー座標を変換するための行列を[getTransformMatrix(float[])](http://developer.android.com/reference/android/graphics/SurfaceTexture.html#getTransformMatrix(float[]))で取得します。変換行列は[updateTexImage()](http://developer.android.com/reference/android/graphics/SurfaceTexture.html#updateTexImage())が呼ばれるたびに変化するので、テクスチャーイメージが更新される度に再取得されるべきです。この行列は伝統的な2D OpenGL ESテクスチャー座標ベクトルを変換します。ベクトルは`(s, t, 0, 1)`の形式で`s`と`t`は0以上、1以下で、サンプリング位置を表します。この変換によって異なるソースのイメージストリームを統一的に扱えるようになります。たとえば、画像の左下の隅は変換行列によってベクトル(0, 0, 0, 1)になり、画像の右上の隅はベクトル(1, 1, 0, 1)になります。

テクスチャーオブジェクトは`GL_TEXTURE_EXTERNAL_OES`テクスチャーターゲットを使用します。これは[GL_OES_EGL_image_external](http://www.khronos.org/registry/gles/extensions/OES/OES_EGL_image_external.txt) OpenGL ES 拡張で定義されています。これはテクスチャーがどのように使われるかを制限します。テクスチャーは`GL_TEXTURE_2D`ではなく`GL_TEXTURE_EXTERNAL_OES`ターゲットにバウンドされなければいけません。さらに、このテクスチャーからサンプリングを行う全てのOpenGL ES 2.0シェーダーはこの拡張を使用する宣言を行う必要があります。たとえば、`"#extension GL_OES_EGL_image_external : require"`ディレクティブです。このようなシェーダーは`samplerExternalOES`GLSLサンプラータイプを使ってテクスチャーにアクセスする必要があります。

SurfaceTextureオブジェクトはどんなスレッドでも作成することができます。[updateTexImage()](http://developer.android.com/reference/android/graphics/SurfaceTexture.html#updateTexImage())はテクスチャーオブジェクトを持つOpenGL ESコンテキストのスレッドからしか呼べません。フレーム利用可能コールバックは任意のスレッドから呼ばれるので、[updateTexImage()](http://developer.android.com/reference/android/graphics/SurfaceTexture.html#updateTexImage())はこのコールバックから直接呼ばれるべきではありません。

---

…うーん、わかったようなわからないような…
Google App Engineを触ってみた

環境導入からサンプルを動かすところまでやってみました

#環境導入
以下のURLからGoogle App Engine SDKをダウンロードしてインストールします。
https://cloud.google.com/appengine/downloads
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/e79437e9-5e3e-57e1-e542-0c88442a478b.png)
今回はPythonを使いたかったのでGoogleApp Engine SDK for PythonをDLしてインストールしました。

#Google App Engine Launcherを起動する
インストールが終わるとデスクトップに以下のアイコンが追加されるのでこれをダブルクリックしてLauncherを起動します。
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/3bb7737f-d355-484f-434d-ed4c2a5517af.png)

#Google App Engine Launcherにサンプルを追加してみる
File -> Add Demo Application -> guestbook
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/cff84736-bdcf-779f-a27d-7fd679356c1f.png)

#サンプルを表示してみる
1.Runを押す
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/619646ea-5a5b-5813-290b-f23265f4e76f.png)

2.Browseを押す
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/97e709c1-9b74-3047-9003-9f333187f682.png)

3.ブラウザが立ち上がりサンプルが表示されます
![image](https://qiita-image-store.s3.amazonaws.com/0/44288/336337c2-5fa4-bd60-287c-6e84d5b0c70f.png)

#参考
一番かんたんなGoogle App Engineの使い方
http://gihyo.jp/dev/serial/01/gae/0001
nginxでredmineにBasic認証をかける

## nginxでrailsアプリにBasic認証をかける

* http://localhost:8080 にアクセスしたら http://localhost:3000 の内容を返してほしい。

```bash:./nginx/htpasswdを生成
htpasswd -c htpasswd ユーザ名
```

パスワードは平文でも書くこと可能。

```bash:./nginx/htpasswd
user1:{PLAIN}passhogehoge
```

----

```bash:./nginx/proxy
server {
        # port番号を変更したい場合はここで変更
        listen 8080;
        location / {
                # Basic認証
                auth_basic "Basic Auth";
                auth_basic_user_file /etc/nginx/htpasswd;

                proxy_pass http://外向けのIPアドレス:3000;
                break;
        }
}
```

```bash:docker-compose.yml
nginx:
  image: nginx
  restart: always
  environment:
    - TZ=Asia/Tokyo
  volumes:
    - ./nginx/htpasswd:/etc/nginx/htpasswd
    - ./nginx/proxy:/etc/nginx/conf.d/default.conf
  ports:
    - "8080:8080"
```
Vimでreactのjsフォーマッティング


vimでjsフォーマッティングは[vim-jsbeautify](https://github.com/maksimr/vim-jsbeautify)を使っているのですが、reactを使い始めてからまともに使えなくなってしまって、放置していましたが、久しぶりに見たらなんとなく対応できてました。

ポイントとしてはver1.0から対応した`.editorconfig`を書くこと。
以下のように書いて`.vim/.editorconfig`においてます。

```
[**.js]
e4x = true
indent_style = space
indent_size = 2

[**.jsx]
e4x = true
indent_style = space
indent_size = 2
```

## 別の選択肢 esformatter + esformatter-jsx

jsbeautifyでもいいのですが、[esformatter-jsx](https://github.com/royriojas/esformatter-jsx)ならjsxをもっと綺麗に整形してくれるようです。

#### インストール

別途esformatter達を入れます。

```
npm install -g esformatter esformatter-jsx
```

余談ですが、vim-jsbeautifyの場合はvimプラグインリポジトリから[js-beautify](https://github.com/beautify-web/js-beautify)をsubmodule参照してるんですね。

vim側は[vim-esformatter](https://github.com/millermedeiros/vim-esformatter)をインストールします。
NeoBundleなりで入れてください。

#### キーバインド参考

```
nnoremap <silent> <leader>es :Esformatter<CR>
vnoremap <silent> <leader>es :EsformatterVisual<CR>
```

例えば以下のようなjsxが、

```
render() {
  return (
    <div>{this.props.text}</div>
  );
}
```

このようにフォーマットされます。great!!

```
render() {
  return (
    <div>
      {this.props.text}
    </div>
    );
}
```
【CoreData】あるEntityのあるPropertyの最大値、最小値を取得するのSwift版


[Objective-C - 【CoreData】あるEntityのあるPropertyの最大値、最小値を取得する - Qiita](http://qiita.com/ryokosuge/items/95577cbdd9df80d1dcaa)のSwift2.0版です。

簡単なソースコードだけ。

```swift:Persion.swift
import Foundation
import CoreData

class Person: NSManagedObject {

// Insert code here to add functionality to your managed object subclass

}
```

```swift:Person+CoreDataProperties.swift
import Foundation
import CoreData

extension Person {

    @NSManaged var age: NSNumber?
    @NSManaged var name: String?
    
}
```

```swift:Test.swift
for num in 0...10 {
	if let person = NSEntityDescription.insertNewObjectForEntityForName("Person", inManagedObjectContext: managedObjectContext) as? Person {
		let age = num * 5
		let name = "name_\(num)"
		person.age = age
		person.name = name
	}
}
/// 保存処理        
saveContext()
        
/// ここからが最大値の取得方法
let expressionAgeName = "maxAge"

/// fetchRequestの生成
let fetchRequest = NSFetchRequest()

/// EntityDescriptionの生成
let entityDescription = NSEntityDescription.entityForName("Person", inManagedObjectContext: managedObjectContext)
fetchRequest.entity = entityDescription
        
let keyPathExpression = NSExpression(forKeyPath: "age")
let expression = NSExpression(forFunction: "max:", arguments: [keyPathExpression])
let expressionDescription = NSExpressionDescription()
expressionDescription.name = expressionAgeName
expressionDescription.expression = expression
expressionDescription.expressionResultType = NSAttributeType.Integer16AttributeType
        
fetchRequest.resultType = NSFetchRequestResultType.DictionaryResultType
fetchRequest.propertiesToFetch = [expressionDescription]
        
do {
	let results = try managedObjectContext.executeFetchRequest(fetchRequest)
	if let maxAge = results.first?.valueForKey(expressionAgeName) as? Int {
		print("maxAge = \(maxAge)")
	}
} catch let error {
	print(error)
}
```

こんな感じで取得できました。

## 補足

最小値が欲しい場合は

```swift:
let expression = NSExpression(forFunction: "max:", arguments: [keyPathExpression])
```

の部分を

```swift:
let expression = NSExpression(forFunction: "min:", arguments: [keyPathExpression])
```

にすれば良いです。

他にも平均値の`avarage:`や合計の`sum:`、数の`count:`と指定できる値があります。

## 終わりに

やはり僕は`Swift`の方が好きです。
MSYS2でディレクトリのシンボリックリンクを作成する方法

Windowsでは、一般ユーザでシンボリックリンクの作成はできません。

```
$ ln -s /c/Users/kunst/Documents
ln: シンボリックリンク `./Documents' の作成に失敗しました: Permission denied
```

ディレクトリのリンクを作成したい場合は、cmd.exe組み込みの「mklink」コマンドを使用して、ジャンクションとして作成しましょう！

## mklinkコマンドについて

コマンドプロンプト(cmd.exe)から、ヘルプを参照してみましょう。

```
C:\usr\home\test>mklink /?
シンボリック リンクを作成します。

MKLINK [[/D] | [/H] | [/J]] リンク ターゲット

        /D          ディレクトリのシンボリック リンクを作成します。既定では、
                    ファイルのシンボリック リンクが作成されます。
        /H          シンボリック リンクではなく、ハード リンクを作成します。
        /J          ディレクトリ ジャンクションを作成します。
        リンク      新しいシンボリック リンク名を指定します。
        ターゲット  新しいリンクが参照するパス (相対または絶対)
                    を指定します。
```

※引数のsourceとdestの順番がlnコマンドと逆なので注意しましょう


## mklinkコマンドを使ってジャンクションを作成する

### コマンドプロンプト(cmd.exe)から作成する場合

```
C:\usr\home\test>mklink /j Documents C:\Users\kunst\Documents
Documents <<===>> C:\Users\kunst\Documents のジャンクションが作成されました

C:\usr\home\test>dir
 ドライブ C のボリューム ラベルは Windows です
 ボリューム シリアル番号は 66AD-860B です

 C:\usr\home\test のディレクトリ

2015/10/14  12:44    <DIR>          .
2015/10/14  12:44    <DIR>          ..
2015/10/14  12:44    <JUNCTION>     Documents [C:\Users\kunst\Documents]
               0 個のファイル                   0 バイト
               3 個のディレクトリ  161,501,753,344 バイトの空き領域
```

### msys2のbashから作成する場合
cmd.exeを起動して、実行するコマンドを引数に渡します。
パスの書き方がWindowsの書き方になるので注意

```
$ cmd.exe /c "mklink /j Documents C:\Users\kunst\Documents"
Documents <<===>> C:\Users\kunst\Documents ▒̃W▒▒▒▒▒N▒V▒▒▒▒▒▒▒쐬▒▒▒▒܂▒▒▒

$ ls -l
合計 0
lrwxrwxrwx 1 kunst なし 24 10月 14 12:45 Documents -> /c/Users/kunst/Documents/
```

## ジャンクションの消し方
消すときはunlinkコマンドで問題ありません。

```
$ unlink Documents

$ ls
```
Windows+openFrameworksでboostを使うときの罠

openFrameworksでboostを使うときは、POCO_NO_WINDOWSというマクロを定義しなければ、CreateEventがglobal namescopeではないといったエラーによりコンパイルが通らない。

boostをNuGetで入れてもこのフラグはつかないので、自分で定義してあげる必要がある。

プロジェクトのプロパティから、プリプロセッサの定義をすれば良い。

また、openFrameworksではshared_ptrをnamespaceをつけずに使用している部分が存在する。
そのため、boostのshared_ptrとstdのshared_ptrが重複してビルドできないことがある。
これは、namespaceを追記してopenFrameworks自体に修正を入れなければならない。

再現したの環境↓

- openFrameworks(0.8.4)
- Visual Studio 2013 Update5
- Windows8
新conoha (cloud) で追加ディスクをマウントする方法

# 新conoha (cloud) で追加ディスクを認識させる方法

conohaのVPSで毎回毎回設定する途中で、ん？なんで追加ディスクが認識されてされていないんだっけ？と悩むので、次回そのようなことがないように
メモ。衝撃的なことも何もありません。本当に単なるメモです

## vdbをフォーマット

たぶん、追加ディスクは、vdbだと思うのですが、誤って異なるディスクをフォーマットしちゃわないように、fdisk -l で確認しておいたほうがいいよ

```
mkfs.ext4 /dev/vdb
```

## マウント

```
mkdir /data
mount /dev/vdb /data/
```

## アンマウント

```
umount /data
```
## blkid の取得

```
blkid
-----------------------------------------------------------------------------------------------
/dev/sr1: LABEL="config-2" TYPE="iso9660" 
/dev/vda1: UUID="3cdd9ce3-7cf8-41de-80bf-3fd2e000cbf2" TYPE="ext4" 
/dev/vda2: UUID="mH9J8u-cBzz-Zwge-d9EH-0AuW-r4MO-UCpd7e" TYPE="LVM2_member" 
/dev/mapper/VolGroup-lv_root: UUID="a9bff0a7-acd3-4359-962d-aaee24064e99" TYPE="ext4" 
/dev/mapper/VolGroup-lv_swap: UUID="7768ac60-723f-4221-9484-3450a8963d49" TYPE="swap" 
/dev/vdb: UUID="13686500-c619-44a0-8e05-7da3632a1d9e" TYPE="ext4"
```

## fstabの編集

上記にて、フォーマットした

```
cp -a /etc/fstab /etc/fstab.bak
cat << '_EOT_' >> /etc/fstab
UUID=13686500-c619-44a0-8e05-7da3632a1d9e       /data           ext4    defaults        1       2
_EOT_
```

## diskのマウント

```
mount /data
```

## マウントされたか確認

```
df -h                                                   
-----------------------------------------------------------------------------------------------
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root
                       47G  1.2G   44G   3% /
tmpfs                 1.9G     0  1.9G   0% /dev/shm
/dev/vda1             477M  106M  347M  24% /boot
/dev/vdb              197G   60M  187G   1% /data
```
Underscore.js(Backbone.js)のtemplateで削除されるコメントを書く

htmlのコメントアウトを直接利用したら表示されてしまう。

```js
console.log(_.template('<!-- comment -->', {}));
// -> '<!-- comment -->'
```

以下の方法だと削除される。

```js
console.log(_.template('<%// comment %>', {}));
// -> ''
```

もしもっと良い方法あれば教えていただきたいです。
LinuxでTimeCapsuleのHDDをマウント

## 参考

* [linux - mount error 13 = Permission denied - Unix & Linux Stack Exchange](http://unix.stackexchange.com/questions/124342/mount-error-13-permission-denied)
* [PCと戯れる日々（備忘録）:mlocateのデータベース更新で特定のディレクトリを除外する](http://blog.minomushi.com/archives/1587265.html)

## timecapsuleのマウント

```bash:
sudo mount -t cifs "//192.168.1.1/Time Capsule" /mnt \
 -o password=装置パスワード,sec=ntlm,uid=1000,gid=1000
```

* sec=ntlm をつけるのが必要。

## mlocateからtimecapsuleを除外

```diff:/etc/updatedb.conf
- PRUNEPATHS="/tmp /var/spool /media /home/.ecryptfs /var/lib/schroot"
+ PRUNEPATHS="/tmp /var/spool /media /home/.ecryptfs /var/lib/schroot /mnt"
```

* こうしておかないと、毎分HDDが「ウィーン」と回り出す。
dirname、basenameは「%/*」と「##*/」で書くと処理速度が早くなる

さっきの記事を書いているときに面白いものを見つけた。
> [bash では basename や dirname を使うより ${0##*/} や ${0%/*} を使ったほうが速い？](http://mattintosh.blog.so-net.ne.jp/56908902)

dirnameで行えることを変数内（${}）で行ってしまおうというもの。
しかもこれで行うと処理速度が早いらしいので実際やってみた。

# 実際に実行してみる
```sh:hoge.sh
#!/bin/bash
DIR="/home/hoge/bin"
echo 0.DIR:${DIR}
echo
echo 1.dir:$(dirname ${DIR})
echo 2.base:$(basename ${DIR})
echo
echo 3.dir:${DIR%/*}   # 変数に対してdirnameを行う
echo 4.base:${DIR##*/} # 変数に対してbasenameを行う
```

```:結果
$ ./hoge.sh
0.DIR:/home/hoge/bin

1.dir:/home/hoge
2.base:bin

3.dir:/home/hoge
4.base:bin
```

すごい。本当になっている。
`${DIR%/*}`と`${DIR##*/}`の部分は何を行っているのかは引用で説明させてもらう。

- `${DIR%/*}`
> 変数内文字列置換の方は % で後方から最短一致で最初のスラッシュまでを削除する。

- `${DIR##*/}`
> ${} 内の ## というのは この記事 でもちょっと書いたけど、変数内の文字列を先頭から最長一致で取り除く bash の機能。つまり、##*/ と書けば先頭から最後のスラッシュまでを取り除く。

早さもチェック。

# 負荷テスト

```sh:stress_test.sh
#!/bin/bash
DIR="/home/hoge/bin"

printf dirname、basename
time for ((i=0;i<=1000;i++))
do
  echo $(dirname ${DIR})  >/dev/null
  echo $(basename ${DIR}) >/dev/null
done

echo
printf %%/*、##*/
time for ((i=0;i<=1000;i++))
do
  echo ${DIR%/*}  >/dev/null  # dirname
  echo ${DIR##*/} >/dev/null  # basename
done
```

```:結果
$ ./stress_test.sh
dirname、basename
real    0m2.416s
user    0m0.505s
sys     0m1.866s

%/*、##*/
real    0m0.036s
user    0m0.024s
sys     0m0.012s
```

あまりにも早すぎて驚いた。
シェルの中にdirnameとbasenameを多用している人は置き換えた方がいいかも。

# 問題点
使っている時に気づいた問題点を上げる。

- パスの最後に「/」がある場合、basenameが表示できない。

- 可読性が悪い。コメントを付けないと何をしているかわからない。

とりあえずこのくらいかな？
特にbasenameでは最後に「/」があっても認識してくれるのに、「##*/」だとしてくれない。
こういう方法もあるよという知識として。
[JavaScript] 特定の文字数をカウント

**文字列中に特定の文字が何回出現するかを数える自作関数です。正規表現に変数を使えるよう、RegExp を利用します。**

### ![yotsuba_s.jpg](https://qiita-image-store.s3.amazonaws.com/0/36751/ba04f0f8-9c02-ffc6-0603-467f65afd633.jpeg) サンプルコード

```js:JavaScript
var all = "aaa\naaaa\nbbc";
alert(str_count(all, "\n")); // 2
alert(str_count(all, "aa")); // 3

// all の中に part が出現する回数を取得
function str_count(all, part) {
	return (all.match(new RegExp(part, "g")) || []).length;
}
```

### ![yotsuba_s.jpg](https://qiita-image-store.s3.amazonaws.com/0/36751/ba04f0f8-9c02-ffc6-0603-467f65afd633.jpeg) デモはこちら

http://jsfiddle.net/yasumodev/fLbw63cn/1/

(･o･ゞ いじょー。
processingで透過画像を作る

```processing
size(64,64);
PGraphics g = createGraphics(64, 64, JAVA2D);

g.beginDraw();
g.noStroke();
g.background(255,255,255,0);
g.ellipse(32, 32, 64, 64);
//g.rect(0, 0, 64, 64);
g.endDraw();

image(g, 0, 0);

g.save("circle.png");

```
c++ builder XE4, 10.2 Tokyo > プロジェクトごとにビルドを変える > C++(共有オプション) > 条件定義 > _USE_XXX;_DEBUG

```txt:動作確認
C++ Builder XE4
Rad Studio 10.2 Tokyo Update 2 (追記: 2017/12/27)
```

プロジェクトを複数持つ場合、同じUnitファイルでビルドすると同じ振る舞いとなる。
プロジェクトAとプロジェクトBで同じUnitファイルを使いながら、異なる動作にするために「条件定義」を使う。

![project.png](https://qiita-image-store.s3.amazonaws.com/0/32870/b349026d-993e-7777-ec24-c8c329ffc893.png)

例として、上記のプロジェクト２つがあるとする。
Unit1.cppをそれぞれのプロジェクトが含んでいる。

`プロジェクト > オプション`で「C++(共有オプション)」の「条件定義」を以下のように`_USE_XXX`を追加。(`_DEBUG`はもともとあったもの)。

![setting.png](https://qiita-image-store.s3.amazonaws.com/0/32870/33d139f3-1a2f-d446-9c1a-a5d26a5a465c.png)

Unit1.cppのコードは以下。

```cpp
void __fastcall TForm1::Button1Click(TObject *Sender)
{

#ifdef _USE_XXX
	ShowMessage(L"USE XXX");
#else
	ShowMessage(L"TEST");
#endif
}
```

プロジェクトのオプションにて`_USE_XXX`を定義した方だけメッセージが`USE XXX`となる。


参考: [ゆるいSEの小ネタ集](http://yuruse.tou3.com/delphi/-delphi-%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%E3%83%BB%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E5%86%8D%E6%A7%8B%E7%AF%89)
iTunes Connect でビルドを選択するときに "Toolchain が無効です。" と言われる件について


# 概要

2015年10月13日に iTunes Connect に Submit してあったビルドを申請しようと思ってポチポチ押していたら「Toolchain が無効です。新規 App および App アップデートは Xcode 6 以降の公開 (GM) バージョン、および iOS 8 SDK 以降を使ってビルドする必要があります。ベータ版ソフトウェアを使ってビルドした App は送信しないでください。」と言われた。

環境としては Xcode 7.0.1 でビルドしていたので、「なんでやねんっ！」となって調べた。

# 原因

どうやら、Xcode の方ではなく OS X のバージョンが Beta であったコトが原因のようだ。

その時点で `OS X 10.11.1 Beta` だったので、その上で動く Xcode からビルドするとダメらしい。

# 対策

OS X をダウングレード (というか、Beta を外す) するコトで対応した。

やり方は以下の通り

1. [ココ](https://beta.apple.com/sp/ja/betaprogram/unenroll?locale=ja) に書いてある方法で Beta プログラムの登録解除を行う
1. 普通に App Store から最新の El Capitan をダウンロードしてインストール
1. いつも通りの手順で Submit

これで、無事に登録できた！！
[python] sorted のkeyってなんぞ


# sorted , list.sort()

pythonの組み込み関数で、listをソートしてくれるこの2つ。
1次元配列なら別にあんまり考える事ないからいいけど、多次になってくるとめんどくさい。
で、多次になってる時の方法として説明されていたのがこちら

```python:sorted
	a = [
      [1,7,'z'],
      [3,2,'x'],
      [1,8,'r'],
      [2,2,'s'],
      [1,9,'b'],
      [2,2,'a']
    ]
    print sorted(a, key=lambda x:x[2])
```

この`key=lambda x:x[2]`を書くと、リストをindex=2, ここでは文字でソートしてくれるという。
しかし、いまいちこのlambda関数を渡すとうまく動くのかよくわからなかった。
どうやら僕は未だに古めかしい関数の名前を変更できない言語にとらわれていたらしい。

```python:example
	def f1(data,function):
		p = []
		for i in data:
			p.append(function(i))
		return p
	
	def f2(num):
		return num/2.
		
	a = f1  # 関数f1を意味する変数a
	b = f2  # 関数f2を意味する変数b

    print f1(3,f2)    # この結果と
	print a(3,b)      # この結果は同じ
```

つまりsortedでは、keyは2番めの要素を比較するように指定をうけたのではなく、
比較するべき要素を返す関数を指定されていたということになる。

```python:sorted
	sort(a,key=str.lower)
	sort(a,key=lambda x:x[2])
	    # for i in a:
	    #     key(i) => 比較要素
```

ということは、これは自作の凝った関数を放り込むことだってできる。

```python:function_x
	def function_x(something):
		'''
		とても凝った予想外の結果を返すなにか
		'''
		return result
		
	a = [
      [1,7,'z'],
      [3,2,'x'],
      [1,8,'r'],
      [2,2,'s'],
      [1,9,'b'],
      [2,2,'a']
    ]
    print sorted(a,key=function_x)
```

例えば、国名を投げたらサッカーのワールドランキングを返すfunctionを作ってソートすれば、
国名からサッカーのランキング順にソートできる。（需要はしらない）
これは案外いろいろ使えて便利かもしれない。
CodeDeploy 困った4

<追記>
あれこれやった結果もうちょっとわかるようになったので、こちらの方にまとめ直しました。

http://qiita.com/ma2saka/items/8e20b5df52da3c96ee0e
</追記>

AWS初心者の私が、東京にCodeDeploy がやってきたということで少し試して順当に困ったことを記録しておきます。

# こまったリスト
## こまった1　DownloadBundleした時のファイルの場所がわからない・・・

deployした元のファイルは以下の場所に展開されている。

```
/opt/codedeploy-agent/deployment-root/
|-- 0XXXXeea-XXXX-YYYY-ZZZZ-FFFFFFFFFe64
|   |-- d-50QKXXXXX
|   |-- d-XXXXX8FUNB
|   |-- d-XXXXX9TNB
|   |-- d-XXXXXWSNB
|   `-- d-XXXXXDPNB
`-- deployment-instructions
    |-- 0XXXXeea-XXXX-YYYY-ZZZZ-FFFFFFFFFe64-cleanup
    |-- 0XXXXeea-XXXX-YYYY-ZZZZ-FFFFFFFFFe64-install.json
    `-- 0XXXXeea-XXXX-YYYY-ZZZZ-FFFFFFFFFe64_last_successful_install
```

ぱっと見て「前回の成功したインストール」とかその種の情報が保存されているのがわかる。

`XXXXXX-cleanup` ファイルには、インストール時に作ったファイルが(たぶん appspec.yml の file エントリで置かれたファイル)が記述されている。これは次回のインストール時にクリアされる対象だということなんだろう。


## こまった2 ログの出力がしょぼすぎるのでは

実際問題、マネジメントコンソールからも情報が少なすぎてうまく動作しないときのトレースがやりづらい。

`/etc/codedeploy-agent/conf/codedeployagent.yml` verbose を true に設定して codedeploy-agent サービスを再起動しよう。 

```
$ cat /etc/codedeploy-agent/conf/codedeployagent.yml
---
:log_aws_wire: false
:log_dir: '/var/log/aws/codedeploy-agent/'
:pid_dir: '/opt/codedeploy-agent/state/.pid/'
:program_name: codedeploy-agent
:root_dir: '/opt/codedeploy-agent/deployment-root'
:verbose: false
:wait_between_runs: 1
```

そうするとけっこうドバドバとログがでる。

ちなみにログを眺めていると、ああ codedeploy というのはつまり1分バッチで更新情報を取得するプル型のアーキテクチャなんだなーとわかる。

## こまった3 ApplicationStopが古いものが実行されている?

ある時、ApplicationStop のスクリプトがこけてしまい、どうしてもデプロイが進まなくなった。appspec.yml から該当のフックを削除しても、全く同じく ApplicationStop の失敗でデプロイがこける。

これは自分が勘違いしていて、そもそも ApplicationStop は「前回デプロイが成功した時のリビジョンの appspec.yml のフックが実行される」動作をする。これは理にかなった設計だが罠だと思った。

つまり、**前回デプロイ成功したリビジョンに必ず失敗する ApplicationStop フックがあった場合**、死ぬ。新規リビジョンのデプロイはそのサーバにはできない。と思う。

## こまった4　対象サーバによって処理を分けたい / Web起動するとかCronを切り替えるとかデバッグモードにするとか

できない。現時点ではフック側やAWSのサービス側からデプロイプロセスに環境変数などを渡す方法はないっぽい。

サーバに環境情報は用意しよう。もしくはフックのシェルスクリプトでがんばる。

フックは実行権限さえあれば python だろうが ruby だろうが突っ込める。自分自身の情報を awscli 経由で持ってくるか、予め環境情報を `/etc/myapp.env` などに置いてがんばることもできる。でもつらいのでサーバ側に環境情報は配置した方がいいかなぁ。

# ということで

なんとなく、使いたい用途には十分かなという気がしてきました。
【appium】send_keysで日本語入力するtips

# 1. はじめに
appiumを使ったモバイル端末テスト自動化に取り組んで、
日本語の情報源が少なそうだった表題のケースについて投稿します。

# 2. send_keysで日本語入力できない
```ruby:日本語入力サンプル
 find_element(:name, "本文").send_keys "テストの鬼"
```

と書いても日本語入力されないのはsend_keysで
unicodeキーボードのエミュレーションができてないから、だそうです。

# 3. 解決法
capabilitiesでunicodeKeyboard入力を有効にしてあげればよい。

```ruby:capabilitiesサンプル
describe 'test_sample' do
  def desired_caps
    {
      caps:       {
        (中略)
        unicodeKeyboard:  'true'
        (中略)
      }
    }
  end
```
# 4. 補足
http://appium.io/slate/en/v1.4.8/?ruby#android-only
appiumページのドキュメントによると、Android-onlyのcapabilityなので
iOSではこのtipsは使えません。
まだ、iOSの日本語入力は試してないです。
gvimの初期設定

# 目的
Windowsでの快適なvim環境を構築する

# 参考サイト
[Windowsでgvimを使う(neobundleのインストール)](http://ylgbk.hatenablog.com/entry/2015/01/07/120000)
[VimとUTF-8](https://sites.google.com/site/fudist/Home/vim-nihongo-ban)

# インストール
Windows向けにコンパイルされたバイナリをダウンロードし、解凍するだけ。
[KaoriYa](http://www.kaoriya.net/software/vim/)

# NeoBundleのインストール
予めgitをインストールしておく必要がある。
[git for windows](https://git-for-windows.github.io/)からインストーラをダウンロードして、インストールする

コマンドプロンプトからgitを実行できるように、環境変数のPATHにgit.exeにパスを通しておく
コマンドプロンプトで、以下を実行してバージョン情報が表示されればok

```bash
git --version
```

コマンドプロンプトで、neobundleをクローンする

```bash
mkdir %userprofile%\.vim\bundle
cd %userprofile%\.vim\bundle
git clone git://github.com/Shougo/neobundle.vim
```

# NeoBundleの設定
以下の内容で%userprofile%\_vimrcを作成する
vim起動時のエラーを回避するため、参考サイトとneobundle#end()の位置が異なっている。

```text:_vimrc
" vim起動時のみruntimepathにneobundle.vimを追加
if has('vim_starting')
  set nocompatible
  set runtimepath+=~/.vim/bundle/neobundle.vim
endif

call neobundle#begin(expand('~/.vim/bundle'))
  " neobundle.vimの初期化 
  " NeoBundleを更新するための設定
  NeoBundleFetch 'Shougo/neobundle.vim'

  " 読み込むプラグインを記載
  NeoBundle 'Shougo/unite.vim'
  NeoBundle 'itchyny/lightline.vim'

  " 読み込んだプラグインも含め、ファイルタイプの検出、ファイルタイプ別プラグイン/インデントを有効化する
  filetype plugin indent on

  " インストールのチェック
  NeoBundleCheck
call neobundle#end()
```

# 内部エンコードをUTF-8に変更
デフォルトの内部エンコードがCP932になっている。
テキストエディタとして問題があるわけではないが、UTF-8に変更する
%VIM_HOME%/switches/catalog/utf-8.vimを%VIM_HOME%/switches/enabledにコピーすることで、UTF-8に内部エンコードが変更される。
ログローテーションするためのlogrotate設定とちょっとしたtips



# 概要
Linuxの場合ログローテーションは`logrotate`というrpmを用います
だいたいのディストリビューションには最初から入っているはずです。

設定もとても簡単で、ローテーションしたいファイルの指定と、
ローテーションする際の設定を数行書けば完了です。


# 準備
ログローテーションにはcronを用いてるため
crondが動いているかどうか確認

```bash
$ service crond status
```


# ローテーション設定
`/etc/logrotate.conf`と`/etc/logrotate.d/`配下のファイルによって設定します。
おそらく`/etc/logrotate.d/`配下に最初から幾つか設定ファイルがあるのでそれらも参考にすると良いでしょう。

例えばnginxの各種ログファイルのローテーション設定は

```
/var/log/nginx/*log {
    create 0644 nginx nginx
    daily
    rotate 10
    missingok
    notifempty
    compress
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
    endscript
}
```

みたいな感じで設定できます。

### 使用できる主なコマンド

- `weekly` 	ログローテーションを週毎に行う。
- `rotate 4` 	ログローテーションの世代数を４個に設定。
- `missingok` 	指定のログファイルが実在しなかったとしてもエラーを出さずに処理続行。
- `notifempty` 	ログファイルが空ならローテーションしない。
- `copytruncate` 	copy の動作を行った後、元のログファイルの内容を消去する。
- `create 0644 fuga fuga` 	ローテーションを行った後、代わりに空の新規ログファイルを作る。権限・グループ・ユーザを指定可能
- `postrotate～endscript` postrotateとendscriptの間に記述されたコマンドをログローテーション後に実行
- `size ファイルサイズ` ログファイルが指定したファイルサイズ以上になったらローテーションする

その他設定項目は→[＠IT：logrotateの設定ファイルで指定できる主なコマンド](http://www.atmarkit.co.jp/flinux/rensai/linuxtips/747logrotatecmd.html)



# logrotateの動作確認
[ShellScript - logrotateを手動実行 - Qiita](http://qiita.com/iktakahiro/items/e44c9b9c80be30da7c97)

```bash
# デバッグ
/usr/sbin/logrotate -fd /etc/logrotate.d/nginx

# 実行
/usr/sbin/logrotate -f /etc/logrotate.d/nginx
```



# TIPS
## ログを扱うアプリケーション側でログファイルを再openできない・するのが面倒
`logrotate`の通常の動作としては

```
hoge.log
```
があった場合、これをローテーションさせるには
`hoge.log.1`にリネームし、新たに`hoge.log`を生成します。

ただしデーモンで動作しているアプリケーション等の場合、開いているファイルは`hoge.log.1`なので、
`hoge.log`を再openしてあげる必要があります。

例えばUnicornの場合USR1シグナルを送信するとログファイルを再度openしてくれますが、
こういった便利なシグナルやコマンドが用意されていない場合は`copytruncate`を用います。

`copytruncate`を記述しておくと
`hoge.log`があった場合に、これをコピーしたものをローテーションのファイル`hoge.log.1`とし、
オリジナル(`hoge.log`)の中身を削除します。
つまり`hoge.log`を開きっぱなしにしておけばokということです！



# 参考
[Nginx - ログローテーション設定！ - mk-mode BLOG](http://www.mk-mode.com/octopress/2013/02/17/nginx-logrotation/)
[Ruby on Rails - Unicorn のログローテーション！ - mk-mode BLOG](http://www.mk-mode.com/octopress/2014/02/02/unicorn-logrotation/)
サービスのレビュー

# これを読んでこの記事を書いた
あなたのおっしゃるレビューってどのことかしら？
http://qiita.com/mima_ita/items/c3490ad1ccc12ad853f1

# 種本
アジャイルレトロスペクティブ
http://www.amazon.co.jp/dp/4274066983/

# 本題
上のレビューだとソフトウェアしかレビューの対象としていないが、アジャイルレトロスペクティブでは「レビュー」をプロダクト(orサービス)のマーケットや事業計画における振り返りとしている。

KPIの確認や対象セグメントの占有状況、計画における進捗状況の確認や市場状態の変化などを行なう。
種本では参加者は「開発チーム全員ではない」「チーム外のステークホルダーも出席する」とある。
平鍋さんのいう「アジャイルの両翼」の左翼側をレビューする。

# アジャイルにおけるレビューなので
## プロセスの定義が(あんまり)ない。
目的と獲得したい利益は大体書いてある。

## 正解の方も変化する
レビューって開発標準みたいな１つの解答集にもとづいて答え合わせをする系のイメージが(SIerとかだと)あるが、そういうのは一重学習ループという。
アジャイルは野中郁次郎さんのいう二重学習ループに基づいているので、市場に対してアクションをとった結果を見て、正解の方が変化する。
正解の方が変化する以上、レビュー結果を見て「~~の仮説でうまくいくかと思ったら全くの勘違いでした」みたいな感じの結果を踏まえ、事業計画の方も変化する。

# 結論？
コードだけではなくサービスもレビューされるものだよ、っていう話でした。
illustratorCCで文字に輪郭をつける方法

①文字ツールで文字を書く。
:bell:（ここです） ②選択ツールに切り替えて文字を選択
③「表示」からアピアランスを選択
④アピアランスのパレットから左下の「新規線を追加」をクリック
（文字ツールのままだと「新規線を追加」を選択できない仕様らしい、、、不便！）
⑤「：塗り」をドラッグして「：線」より上に
これにより文字の外側に輪郭がつけられる。デフォルトは
文字の内側に輪郭なので自由に輪郭がつけられない。

後は色を文字パレットなどから選択
「：線」が輪郭にあたるので太さを調節し完成。

![sample.jpg](https://qiita-image-store.s3.amazonaws.com/0/87543/3ae2257e-36fc-bf7d-29a6-61607cfe3999.jpeg)


文字ツールから選択ツールに持ちかえる作業が余分な
気がします。文字ツールからでも「新規線の追加」が選択
できるようにバージョン修正してもらいたいところです。