OmniAICreator/Qiita-1.07M huggingface dataset:
private な interface を引数にもつ private なメソッドをテストした話

# 前提
- Java 8
- 自分はJava初心者

コメント欄にてこういうもっといい方法があるよ、などのご報告お待ちしてます。

# privateなメソッドのテストはつらい
```java
/*
例えばHogeというクラスに
int foo(int i) {
  return i+i;
}
という関数があったとする
*/

Hoge hoge = new Hoge();
Method m = Hoge.class.getDeclaredMethod("foo", int.class);
m.setAccessible(true);
int ret = (int)m.invoke(hoge, 10); // -> ret == 20
```
でもこれだけなら各ライブラリのお世話になるなどすれば大した事がない（気がする）。

# privateなメソッドの引数がprivateなinterfaceだったらもっとつらい
こちらのページが近い事をしていたので大変参考になった。→[技術見聞録 - 外部提供のInterfaceをインスタンス化する](http://www18.atwiki.jp/bovecrach/pages/55.html)

以下のようなクラスがある事にする。
（今回の例のインタフェースは関数型インタフェース）

```java
public class Hoge {
  // クラス内からはこのようにアクセス可能
  public int boo(int i) {
    return foo(i, (int i) -> i+i);
  }

  private int foo(int i, InnerInterface innerInterfaceInstance) {
    return innerInterfaceInstance.apply(i);
  }

　@FunctionalInterface // なくてもいいけど
  private interface InnerInterface {
    int apply(int i);
  }
 
}
```
もしインナークラスなら、getDeclaredConstructorからのnewInstanceとかやっちゃうことが一応可能なのですが、インナーインタフェース（？）だと難しい。

これをテストするコードが以下。
これに至るまで失敗が無限にありましたが注意点は後述。

```java
@Test
public void testFoo() throws Exception {
  Hoge hoge = new Hoge();

  // Interface内部の処理を移譲されるcallback
  class InterfaceHandler implements InvocationHandler {
    @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String name = method.getName();
        return getClass().getMethod(name, method.getParameterTypes()).invoke(this, args);
    
    public int apply(int i) {
      // apply()にしてほしい内容を書く
      // 例：
      return i * i;
    }
  }

  // パラメータの型の指定が大変なのでforループで名前から探す
  Method fooDummy = null;
  for (Method m : Hoge.class.getDeclaredMethods()) {
    if (m.getName().equals("foo")) {
      fooDummy = m;
    }
  }

  // 黒魔術的設定
  Class<?> interfaceClass = foo.getParameterTypes()[1]; // 2個目の引数
  ClassLoader loader = interfaceClass.getClassLoader();
  Class<?>[] interfaces = new Class<?>[] {interfaceClass};
  InvocationHandler handler = new InterfaceHandler();
  Object proxyInstance = Proxy.newProxyInstance(loader, interfaces, handler);

  fooDummy.setAccessible(true);
  
  // 実行！
  int ret = (int)fooDummy.invoke(hoge, 10, proxyInstance);

  assertEquals(ret, 100) // -> passed

}
```

java.lang.reflect.InvocationHanlder
java.lang.reflect.Proxy
の２つを利用して、interfaceの関数をこっちで指定してやる感じですね。

# 注意点
- インタフェースの型が必要になるのでforループ使って名前でmethodを取り出す。（もっといい方法もあるかもしれない）
- ちなみにHoge#boo()みたいにラムダ渡すと怒られます。invokeの引数がObjectを要求しているからでしょうか？

# 結論
package privateにしような

どうやら、AOP（アスペクト指向プログラミング）の実現のために使われるるらしい（下記参照）

# その他の参考になるサイト
[動的プロキシによるアスペクトとしての実装](http://ffy.afy-system.jp/tips/t_004.html)
[java.lang.reflect.Proxyの使い方（１）](http://qiita.com/obaQ/items/e401d41059d81149da52)
JETSON TX1が来てやったこと（４日目）

#本日の目標
カメラモジュールをV4L2へ置き換えます。
と言っても、やはりよく分からないので
Development Guide「Video for Linux User Guide」の章を上から順に舐めていきます。

#テストパターン
どうやらサンプルで、テストパターン画像を生成する擬似デバイス（カメラの制御は行わない）が入っているようです。
起動の流れをざっくり書くと
1. 既存のモジュール（GStreamer？）を停止する
2. V4L2ドライバをインストールする
3. V4L2制御用ソフト（Yavta ---- Windowsで言うところのamcapみたいなもの？）で画像をキャプチャする。
という流れのようです。
ここだけ見ると、別にV4L2ドライバのためにカーネル再ビルドする必要ないんじゃね？と思えてくるんだけどね……
基本的にはガイド通りに進めれば良いので、書かれてないことだけ捕捉します。

<dl>
<dt>Yavtaのインストール</dt>
<dd>
V4L2デバイスから画像を取得するために必要なソフトのようです。<br>
パッケージで配布されてないようなので (apt-getでインストールできない)<br>
Gitで引っ張ってくる必要があります。<br>
以下のコマンドを打つと、Yavtaが使えるようになります。<br>
<code>
$ sudo apt-get update<br>
$ sudo apt-get install git<br>
$ git clone git://git.ideasonboard.org/yavta.git<br>
$ cd yavta<br>
$ make
</code><br>
<br>
</dd>
<dt>ImageMagickのインストール</dt>
<dd>
Yavtaでキャプチャした画像を表示するために必要なソフトのようです。<br>
こちらはパッケージで配布されているので、以下のコマンドでインストールできます。<br>
<code>$ sudo apt-get install imagemagick</code>
</dl>

上手く行くと、彩りタイル画像が表示されます。
`modprobe tegra_camera`した時点で、`/dev/video0`というデバイスが見えるようになります。
当然なのかどうなのか、Gstreamerで画像取得は出来なくなっています。
引数らしき`tpg_mode=2`の数字を1とか3とかに変えても大きな変化なし、つまらん。

#OV5693_V4L2ドライバのインストール
ここからは、Gitの使い方も知らないズブの素人による悪戦苦闘の記録になります。
手順書によると、まずカーネルのソースコードにパッチを当てる必要がありそうです。
ところで、パッチについてはL4Tのバージョン`R23.1`と`R23.2`に限定するような記述ですね。
今日時点、Gitから取得できる最新のバージョンは`R24.1`です。
意味は気にせず`git checkout tegra-l4t-r24.1`と打ち込んでいたので、多分バージョンがズレてると怒られます。
というわけで、ひとまずバージョンを`R23.2`に戻すことにします。
`git checkout .`
`git checkout tegra-l4t-r23.2`
これでバージョン`R23.2`の状態に戻り、パッチが当てられるようになったはずです。

##パッチを当てる
`git am 0001-ARM64-adding-OV5693-V4L2-on-E3326-jetson_cv.patch`
手順書通りに上記コマンドを打ち込むと、gitから「お前ドコ中出身だオラ？」みたいな警告出てきます。
いや別にリポジトリ汚染する気はこれっぽっちもないんですローカル更新したいだけなんです……
多分、使い方を間違えてるんだろうな。あと引数で指定してるっぽい`*.patch`ってのも実体がどこにあるのか全くの不明
分からないことはフォーラムで検索します、そして行き当たったのが[こちらの記事](https://devtalk.nvidia.com/default/topic/920739/?comment=4824232)
要約すると
「パッチはどこからダウンロードすればいいんでうｓか？」
「コレがパッチだくれてやるよ（テキストべた貼り）」
って事なんですかね？
まさかそんな……と思いながらも、他にやり方が思いつかないので泣きながらコピペして`*.patch`ファイルとして保存。
gitも、`git am`だとやっぱり同じように上手く行かないので`git apply`でぶち込みました。

##configを書き換える
どうにかこうにかパッチを当てたと思ったら次は「設定ファイルを書き換えろよボーイ」と来たもんだ。
この設定値がどこにあるのか全く見当が付かないので、例によってgrepで当たりを付ける。
多分`arch/arm64/configs/tegra21_defconfig`ってやつだな……というわけで、こいつを書き換えます。
あとは[前回の記事](http://qiita.com/threecups/items/88f9b1afc6b98712ac0f)同様に、カーネルを再コンパイルします。
ソースコードは再度修正しないと、またエラーで止まるからね！

#ビルド結果をTX1に転送する
いよいよ最終段階、前回端折った所まで来ました。
（転送しても同じカーネルが上書きされるだけで意味が無いと思い、飛ばしたところ）
よく分からないので、それっぽいファイルは全てコピーします。
`Image`と`zImage`を、カーネルビルド出力先の`arch/arm64/boot/`から`kernel/`に上書きコピー
`module_install`の出力先の`lib`ディレクトリを全て`rootfs/lib`に上書きコピー
あとはデバイスツリーなんだけど、ビルド先に出来たのは`dts`フォルダで、カーネルに置くべきは`dtb`っぽいぞ
これどうやって変換するんだ……と悩むこと数十分
`dts`フォルダの中身、拡張子が`dtb`やないか！！クソ、時間返せ！！
一応、元の`dtb`フォルダの中身は全部消してから`dts`フォルダの中身を全コピーします。
これで動くやろ、`./flash.sh`を走らせて待機。

#結果
TX1再起動！またgitとYavtaインストール！めんどい！
ガイド通りにコマンドどーん！！rawファイル保存できた！！
`raw2bmp`って何だよ、分からないからUSBメモリにどーん！！
Windows上のRawビューワーで、カメラ画像っぽいのが撮れてる事が確認できました。
Gstreamerで画像取得した時との違いは
* 画像サイズが違う（リサイズなのか切り出しなのかは不明）
* ベイヤー配列で出てきてるっぽい（画処理されてない）
* 画像がひっくり返ってる

#まとめ
GstreamerからV4L2ドライバに置き換え、ソースコード弄れそうなところまでこぎ着けました。
バッチファイルの中を見れば、大体どこを弄れば良いか当たりが付けられそうだし
ガイドもまだまだ続きがあるので、画像サイズとか映像フォーマットとか調整できそうな気がします。
今日はここまでということで。
Nightmarejsでセッションを維持しない

```js
var Nightmare = require('nightmare');
var nightmare = Nightmare({ show: true , webPreferences:{ partition: 'nopersist' }});
```
Erectronのドキュメントより
https://github.com/electron/electron/blob/master/docs/api/browser-window.md#new-browserwindowoptions

↓のoption名 'web-preferences'は古いものなようでハマった・・・
http://stackoverflow.com/questions/33944837/clear-cache-in-nightmare-js-electron
私用Twicliスタイルシート（Vivaldi対象）　※2016/08/21追記あり

Vivaldiを最近インストールしまして、パネルに表示するようになりました。
そのときにメイリオ表示がほしくなって、色々いじった産物を投稿します。


```css:vivaldi_twicli.css
.tw{font-size:85%;
line-height:120%;
font-family:"メイリオ"}
#menu{top:28px;}
#menu2 a{font-family:"メイリオ";
line-heigth:110%;}
textarea#fst{font-family:"メイリオ";
font-size:80%;
height:26px;}
#control{height:48px;}
img.uicon{padding:3px;}
.tw{top:49px;}
```

ほんとにメイリオ表示して、それなりに体裁を整えただけです。
もうちょっといい書き方もあるかもですが…。

2016/08/21に!important表記を消しました。色々やってみたところ、そちらの方が便利だったので。
[Android]簡単！お手軽！タイマー

クイズアプリを作成中ではあるが、
どうせならタイムを計って個人の端末内でランキングをつけたいと思い、
タイマーをつけることにした。

そこで、非常に簡単にお手軽に設置できるタイマーを紹介する。

**Chronometer（クロノメーター）**である！

アプリの全体は映せませんが、
以下がイメージとなります。

![timer.png](https://qiita-image-store.s3.amazonaws.com/0/129169/acefc8a5-ef92-9e12-172e-198817f296d2.png)

シンプルではありますが、タイマーとして十分！

## 1.個別IDを取得

```activity_main.xml
<Chronometer
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/timer" />
```

```MainActivity.java
Chronometer timer = (Chronometer) findViewById(R.id.timer);
```

## 2.表示形式を設定

```MainActivity.java
timer.setFormat("%s");
```

今回はクイズアプリでそれほど時間のかかるものを想定していなく、
分秒単位で図れればいいので"%s"を設定。（画像と同じ）

~~ちなみに、~~
~~時単位でも図りたい場合は、"H:MM:SS"と記述すればいいはず。。。~~
（2016/06/16修正）
"%s"を指定すれば、経過時間次第で"MM:SS"や"H:MM:SS"という形式になる。

## 3.タイマー開始

```MainActivity.java
timer.start();
```

単純ですね！
クイズアプリだとスタートボタン押された時ですかね。

## 4.タイマー終了


```MainActivity.java
timer.stop();
```

こちらも単純ですね！
問題数が規定の回数に達したら止めてあげればいいですね。

デザインは非常に簡素なので、
デザインにもこだわりたい場合はあまりおすすめできないんでしょうかね...


以上です。
【CSS】CSSのみで五角形スライドアニメーション

![test2.gif](https://qiita-image-store.s3.amazonaws.com/0/42231/3410e198-ff3a-054c-2bda-bd53702b7ef6.gif)

本当は [HUMAAN](http://humaan.com/) の下部メニューのようにクリックすると回転して表示されるような超クールなものを作りたかったけど、五角形を回転させたところで飽きちゃった。

No Life, No Pentagon にっては完成形かもしれませんが、それ以外の方にとっては五角形が回転しているだけの意味のない代物です。

ただ、JavaScriptを習得しているスーパーえんじにあなら、超クールなものに変身できると思います。

私はJavaScriptさっぱりです┐(ﾟ～ﾟ)┌

超モダンブラウザが対象ですが、誰かしらの何かの参考になれば幸いです。

**追記：五角形の計算**

私のように五角形の計算がわからない方は少数かと思いますが、下記の質問のベスアンが参考になります。

+ [JavaScript - 算数（五角形の計算）について教えてください。(16261)｜teratail](https://teratail.com/questions/16261)

また、これを作るときの計算式が残ってたので晒します。

![p.png](https://qiita-image-store.s3.amazonaws.com/0/42231/d52c30ef-dd6e-b56d-2af2-a1b4e1d7f93a.png)

たぶん、あってるはず（おいっ

最初のアニメーションのコードは下記です。

```html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS</title>
<style type="text/css">

* { padding:0; margin:0; }

#drawing {
	width:1500px;
	height:600px;
	background:#000;
	perspective:1000px;
	margin:100px auto 0 auto;
}

.scale {
	transform:translateZ(-1000px) rotateY(-89deg);
	transform-style:preserve-3d;
	animation:rotation 8s linear infinite;
}

.cube {
	position:relative;
	width:1500px;
	height:600px;
	transform-style:preserve-3d;
}

.cube-panel {
	width:100%;
	height:600px;
	position:absolute;
	box-sizing:border-box;
	font-size:24px;
	line-height:1.5;
}

/* 1.正面 */
.cube-panel-pt01 {
	background:rgba(243,183,0,0.7);
	background-size:cover;
	transform:translateZ(412.91457614136px)
}

/* 2.左上 */
.cube-panel-pt02 {
	background:rgba(155,89,182,0.7);
	background-size:cover;
	transform:translateZ(127.5976212528095px) translateY(-392.7050983124903px) rotateX(72deg);
}

/* 3.右上 */
.cube-panel-pt03 {
	background:rgba(60,180,210,0.7);
	background-size:cover;
	transform:translateZ(-334.0549093234895px) translateY(-242.7050983124876px) rotateX(144deg);
}

/* 4.右下 */
.cube-panel-pt04 {
	background:rgba(231,60,140,0.7);
	background-size:cover;
	transform:translateZ(-334.0549093234895px) translateY(242.7050983124876px) rotateX(216deg);
}

/* 5.左下 */
.cube-panel-pt05 {
	background:rgba(228,0,0,0.7);
	background-size:cover;
	transform:translateZ(127.5976212528095px) translateY(392.7050983124903px) rotateX(288deg);
}

@keyframes rotation {

  from {
    transform: translateZ(-1000px) rotateX(0);
  }

  to {
    transform: translateZ(-1000px) rotateX(-360deg);
  }

}

</style>
</head>
<body>

<div id="drawing">
	<div class="scale">
		<div class="cube">
			<div class="cube-panel cube-panel-pt01">1.正面</div>
			<div class="cube-panel cube-panel-pt02">2.左上</div>
			<div class="cube-panel cube-panel-pt03">3.右上</div>
			<div class="cube-panel cube-panel-pt04">4.右下 </div>
			<div class="cube-panel cube-panel-pt05">5.左下</div>
		</div>
	</div>
</div>

</body>
</html>
```
UAC(権限)のエラー

# UACのエラー(権限に関するエラー)
gitを使っていたら急にブランチの切り替えができなくなった．
エラーから，あるファイルにアクセスする権限がないことが原因と推定．
ファイルを管理者権限で削除しようとしたが，エラーが出て削除できなかった．

いろいろ調べている内に以下の方法で解決した．

1. コントロールパネルを開く．
2. 「ユーザーアカウントと家族のための安全設定」-> 「ユーザーアカウント」
3. 「ユーザーアカウント制御設定の変更」
4. 最下位レベルの「通知しない」に設定．

UACに関する詳しい情報は以下のURLに載っている．
http://www.trycut.com/uac.htm
iOS 複数動画同時再生


複数動画再生には複数のAVPlayerとAVPlayerLayerを使います。

イメージは以下の通りです
![Screen Shot 2016-06-10 at 4.05.49 PM.png](https://qiita-image-store.s3.amazonaws.com/0/4537/b064eb45-7bcf-90ef-b979-e3658685f779.png)

次はコードです。

``` player.swift
/// プレイヤーを用意
let player1 = AVPlayer(URL: url1) 
let player2 = AVPlayer(URL: url2)
let player3 = AVPlayer(URL: url3)
let player4 = AVPlayer(URL: url4)

/// 各レイヤーにプレイヤーを関連付ける
let playerLayer1 = AVPlayerLayer(player: player1)
let playerLayer2 = AVPlayerLayer(player: player2)
let playerLayer3 = AVPlayerLayer(player: player3)
let playerLayer4 = AVPlayerLayer(player: player4)

/// 各レイヤーの位置・サイズをつけ貼り付け
playerLayer1.frame = CGRectMake(0,0,200,50)
playerLayer2.frame = CGRectMake(200,0,200,50)
playerLayer3.frame = CGRectMake(0,50,200,50)
playerLayer4.frame = CGRectMake(200,50,200,50)
self.view.layer.addSublayer(playerLayer1)
self.view.layer.addSublayer(playerLayer2)
self.view.layer.addSublayer(playerLayer3)
self.view.layer.addSublayer(playerLayer4)
```
別に1プレイヤー１レイヤーである必要はありません。
以下のイメージで作ってもいいです。

<img width="958" alt="Screen Shot 2016-06-10 at 4.14.27 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/4537/a64691d3-f18c-d529-6ebe-34b44328fefc.png">

``` player.swift
/// プレイヤーを用意
let player1 = AVPlayer(URL: url1) 

/// 各レイヤーにプレイヤーを関連付ける
/// 今回は全てプレイヤー1
let playerLayer1 = AVPlayerLayer(player: player1)
let playerLayer2 = AVPlayerLayer(player: player1)
let playerLayer3 = AVPlayerLayer(player: player1)
let playerLayer4 = AVPlayerLayer(player: player1)

/// 各レイヤーの位置・サイズをつけ貼り付け
playerLayer1.frame = CGRectMake(0,0,200,50)
playerLayer2.frame = CGRectMake(200,0,200,50)
playerLayer3.frame = CGRectMake(0,50,200,50)
playerLayer4.frame = CGRectMake(200,50,200,50)
self.view.layer.addSublayer(playerLayer1)
self.view.layer.addSublayer(playerLayer2)
self.view.layer.addSublayer(playerLayer3)
self.view.layer.addSublayer(playerLayer4)
```

あるアプリ開発では
以下のように、画面下部にサムネイルのように動画を再生させ、
タッチ操作などで、上部のメインのレイヤーに関連付けるプレイヤーを
切り替えいる方法を行いました。

<img width="973" alt="Screen Shot 2016-06-10 at 4.19.55 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/4537/d3820882-61d7-680e-5864-4c14b021b696.png">

端末によって同時再生数が決まっています。
僕が試している限りではiPhone6, iPad Pro などは16です。
また、AVPlayerの動画との紐付けを解放しないと、4つ再生した後に、その画面のコントローラを解放した後にまた4つ、次もまた4つと再生し、同時再生数の上限に達した時に動画が再生できなくなります。

なのでAVPlayerが必要なくなった時は必ず

```
self.player.replaceCurrentItemWithPlayerItem(nil)
```

を行ってください。
Microsoft Azure 上で sinatra アプリケーションを動作させる

クラウド上にデモアプリケーションを配備し何らかのデモやサービスのプロトタイプを立ち上げるといたシチュエーションを想定します。

Microsoft Azure は一ヶ月、開発者プログラム特典では一年間の無料枠があります。ちなみに、競合の Amazon Web Service にも同様に一年間の無料枠があります。

## アプリケーションの開発

以下の記事が良いでしょう。
[sinatraで一からwebアプリケーションを構築する](http://qiita.com/kazuhiro4949/items/606c1d58afcfb06f14c4)

ある程度の規模のアプリケーションを作るにあたり、ビューとモデルとコントローラーの分離、回帰テスト (RSpec) を実行をするといったことは必須かと思います。また haml, sass, coffeescript は使ったほうが良いでしょう。

## Microsoft Azure アカウントの取得

Microsoft アカウントを取得し、サインアップします。
[Microsoft Azure](http://azure.microsoft.com)

クレジットカード、電話番号の認証をすることになります。

## 仮想マシンの起動

Azure にログインしたら Virtual machines - Add を選択し仮想マシンを追加します。ここでは Ubuntu 16.06 LTS を選択したものとします。

### ドメイン

VM の Essentials の中に Public IP address/DNS name label 欄があります。これをクリックして命名することにより、ドメイン名が割り当てられます。

現在ですと Tokyo/East を選択すると xxx.japaneast.cloudapp.azure.com のような名前が割り当てられるようです。少々長くなってしまいますね。

### ポートの開放

Resource groups で設定します。 Network security group (盾のアイコン) をクリックすると Inbound security rules/Outbound security rules が見えてきますので、ここでルールを設定します。

## Ubuntu の設定

仮想マシンにログインすればあとはいつもの GNU/Linux 環境なのですが、忘れやすいところをメモしていきます。

### localtime の変更

Azure の時刻設定が UTC になっています。以下の記事を参考に JST に変更します。

[localtime を日本標準時間(JST)に変更](http://cameong.hatenablog.com/entry/20141012/1413114360)

### ファイアウォール

最近の Ubuntu では ufw という iptables のラッパーが用意されており、これを利用して設定します。

[ufwを使って簡単にファイアウォールを設定する](http://qiita.com/yoh-nak/items/46935af3c5c4036e93b3)

昔ながらの人は ufw を無効化した上で iptables を利用してもより細かい設定ができますので良いかもしれません。

### openssl のビルドに失敗する

Ruby の ext/openssl でビルドが失敗することがあります。このような場合は Makefile に一行追加しソースの場所を明示するとビルドが通ります。

```
top_srcdir = /usr/local/src/ruby/ruby-2.3.1
```

## まとめ

sinatra はちょっとしたアプリケーションを簡単に作って動かすことができますし、 Microsoft Azure などの IaaS を使うと、ほとんどハマりどころもなくクラウド上にアプリケーションの動作環境が構築できるので便利ですね。以上でこの話はおしまいです。
pyinstallerとHomebrewは共存しないで。。。

何時からか分かりませんがpyinstallerでMacOSのアプリを作って駆動して見ると

”Crash”
が発生してメモリ問題みたいなログが上がってしまいました。

```
Process:               test-gui [3465]
Path:                  /Users/USER/Documents/*/test-gui.app/Contents/MacOS/test-gui
Identifier:            test-gui
Version:               0.0.0 (???)
Code Type:             X86-64 (Native)
Parent Process:        test-gui [3463]
Responsible:           test-gui [3463]
User ID:               501

Date/Time:             2015-09-07 17:40:28.796 +1000
OS Version:            Mac OS X 10.10.5 (14F27)
Report Version:        11
Anonymous UUID:        7267BA3C-1EDF-8AD3-E3CD-905E8385C51C


Time Awake Since Boot: 310 seconds

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000

Application Specific Information:
abort() called

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib          0x00007fff91dd1286 __pthread_kill + 10
1   libsystem_c.dylib               0x00007fff87c529b3 abort + 129
2   libtcl8.6.dylib                 0x0000000106288633 Tcl_PanicVA + 428
3   libtcl8.6.dylib                 0x00000001062886c7 Tcl_Panic + 148
4   libtcl8.6.dylib                 0x00000001061d5dc1 DeleteInterpProc + 53
5   libtk8.6.dylib                  0x000000010609205a Tk_CreateConsoleWindow + 936
6   libtk8.6.dylib                  0x000000010613d73b TkpInit + 979
... (中略)
```

最初にはこれがwxPythonのバージョン・アップ問題かと思いました。結果的に一部は正しいでした。 HomeBrewを通じてinstallしたwxPythonが原因でした。

グーグル神様に熱心に問いましたが効果的な答えはありませんでした。wxPythonの再installのみ繰り返すだけ。

ですけどこの間、もう一度グーグル様に問いましたが「brewの問題」というのが書いているサイトを見つけました。

```
I had the same issue - my setup was python3 and pyqt4, both installed via brew. First I completely removed brew:

cd `brew --prefix`
rm -rf Cellar
brew prune
rm -rf Library .git .gitignore bin/brew README.md share/man/man1/brew
rm -rf ~/Library/Caches/Homebrew

- See more at: http://www.qhmfx.com/article/cgiaicgf-pyqt4-py2app-and-pyinstaller-crash-when-moving-app-to-another-machine.html#sthash.AZGiyyID.dpuf

```

それでHomebrewをuninstallしてみました。上のようにしてもいいし、スクリプトを提供するサイトもあります。
```/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)"
```

それでbrew+wxPythonを一気に削除され、brewを通じなくてwxPythonをinstallしてpyinstallerを駆動しました。

結果はSucceeded~

MacOSで公式にHomeBrewを支援しない理由を分かるようになりました。
xlwingsでExcel VBAからPythonを実行＆チュートリアルの補足


Qiitaでxmlwingsというライブラリを使ってExcel VBAでPythonを動かすことができるという記事を見て、Quick Start + 補足をちょっと書いてみる
普段ブログで書いてるのでQiitaの方で補足書いてみるのも良いかなということで

xlwingsがv0.9以降で大きく変更が入っていたようで、現状のコードで動かないためv0.9以降について追記

# 開発環境
- Windows 7 (32-bit)
- Office 2010 SP-2

# インストール
特に特殊なことはなくてpipでインストールするだけ
```
pip install xlwings
```
私の環境では下記の場所にインストールされる。後でExcel側からファイルをインポートする際に参照する場所
C:\Python27\Lib\site-packages\xlwings

# サンプルを実行
## サンプルコード
Excelから呼び出すpythonモジュール

* xlwings v0.9以前

```python:mymodule.py
import numpy as np
from xlwings import Workbook, Range

def rand_numbers():
    """ produces standard normally distributed random numbers with shape (n,n)"""
    wb = Workbook.caller()  # Creates a reference to the calling Excel file
    n = int(Range('Sheet1', 'B1').value)  # Write desired dimensions into Cell B1
    rand_num = np.random.randn(n, n)
    Range('Sheet1', 'C3').value = rand_num
```

* xlwings v0.9以降

参考：https://docs.xlwings.org/en/stable/migrate_to_0.9.html

```python:mymodule.py
import numpy as np
import xlwings as xw

def rand_numbers():
    """ produces standard normally distributed random numbers with shape (n,n)"""
    wb = xw.Book.caller()  # Creates a reference to the calling Excel file
    n = int(wb.sheets['Sheet1'].range('B1').value)  # Write desired dimensions into Cell B1
    rand_num = np.random.randn(n, n)
    wb.sheets['Sheet1'].range('C3').value = rand_num
```

Excel側にで書くVBAコード

v0.9以前はRAW文字列じゃない場合でも使用できていたが、現在のv0.9以降現在の版数では`\`を使用する場合はRAW文字列にするかパス区切り文字を`/`にしないとエラーするようになっている。

* v0.9以前

```vb:ExcelVBA
Sub RandomNumbers()
    RunPython ("sys.path.append('C:\Temp'); import mymodule; mymodule.rand_numbers()")
End Sub
```

* v0.9以降

```vb:ExcelVBA
Sub RundomNumbers()
    RunPython ("sys.path.append(r'C:\Temp'); import mymodule; mymodule.rand_numbers()")
'    RunPython ("sys.path.append('C:/Temp'); import mymodule; mymodule.rand_numbers()")
End Sub
```

このVBAのコードサンプルでは
`RunPython ("import mymodule; mymodule.rand_numbers()")`となっているのだがこれがチュートリアルのちょっとしたトラップなのかなと
mymodule.pyというファイルをどこに置けば良いのかというようなことが書かれているのだが、`RunPython`の`import`の前に任意のパスを追加すればどこに置いても構わない。
今回はパスを通していない`C:\Temp`に`mymodule.py`を置いてみた。
Excel自体は、`C:\Users\h_oki\Documents\book`に`test.xlsm`で保存しておいて、モジュールは別の場所にまとめておきたかったけどテスト用にどこからでも読み込めるか確認したかったため上記のとおりとした。

## 補足
VBAとかExcelとかは関係なく、あくまでPythonのコードを実行しているだけなので、その後にパスを設定してあげることで任意の場所に置いてあるモジュールでも読み込める。
`import sys`はxlwingsの中で勝手に読み込まれるため特に記入する必要はない。
サンプルコードではパスの通った場所か直下に置かないと読み込めないが任意のパスに置きたい場合は、`sys.path.append('/your/to/path')`を`import mymodule`の前に書いてあげるだけで良い。
また、`sys.path.append('/your/to/path')`を追加しなくても環境変数`PYTHONPATH`に設定してある場所であれば問題はなさそう。

# 実行結果
なぜか画像がアップロードできなかったため省略させてください。
ただ、任意の場所に置いた`mymodule.py`(クイックスタートのコードそのもの)は実行できました。

# 参考記事
## 関連記事
[xlwingsを使うぜ](http://qiita.com/shinriyo@github/items/1c38f5412e97d1a24c06)
[ExcelからPythonスクリプトを実行し、結果をExcelにグラフ表示できるxlwingsで遊んでみた。](http://qiita.com/mtb_beta/items/96628a19e3c94cea4c24)

## 公式
[xlwings公式](http://xlwings.org/)
[Quickstart](http://docs.xlwings.org/en/stable/quickstart.html)
htmlタグを消去する方法&それをmailerのviewで使う方法


####管理者からユーザーに宿題を出す
管理者画面でタグを直打ち入力すると、ユーザー画面ではタグを認識して、いい感じで表示される実装。
直打ちしているので、`strig_tags`メソッドは適用されない。（エディタのgemを使っている場合はこのメソッドが使える？）
しかし、mailerでメール送信をしてもタグを認識しないので、メールではタグを消去したい場合。

viewなので、application_helperに`<>`と`<>`で囲んだ文字を空文字にする正規表現を記述。

```rb:application_helper.rb
module ApplicationHelper
  def rm_html_tag(str)
    str.sub!(/<[^<>]*>/,"") while /<[^<>]*>/ =~ str
    str
  end
end

```

`views/mailers/該当ファイル.rb`で`rm_html_tag(str)`でいけるじゃんと思ったのですが、そんな「アクションがないよ」と怒られます。
mailerでapplication_helperを呼び出す必要があります。

```rb:mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
  add_template_helper(ApplicationHelper)
end
```

これで晴れてmailerのviewから定義した`rm_html_tag(str)`メソッドを呼び出すことができます。

```rb:views/activity_mailer/_hoge.text.erb
<%= rm_html_tag(object.body) %>
```

これで`<>`と`<>`で囲まれた文字はすべて空文字に変換される＝表示されなくなります。
htmlタグ=`<>`は消去されますが、htmlタグ以外の`<>`も消去されることになるのですが、管理者側の問題なので（管理者が気をつければいい）、今回はこのような実装にしました。
他にも良い実装方法をご存知の方がいれば教えて下さい！
CloudFormationでストリーム名を指定してKinesisストリームを作成できるようになった！

2016/06/09のアップデートでストリーム名を指定してKinesisストリームを作成することができるようになりました！

https://aws.amazon.com/about-aws/whats-new/2016/06/aws-cloudformation-adds-support-for-amazon-vpc-flow-logs-amazon-kinesis-firehose-streams-and-other-updates/

詳しい方法は下記をご参照ください。
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesis-stream.html

ここでは簡単にCloudFormationに用いるJsonをご紹介します。
と言ってもかなり直感的で、Nameを指定してあげたらいけます。

```json:sample
{
  "AWSTemplateFormatVersion" : "2010-09-09",

  "Resources" : {
    "KinesisSample": {
       "Type" : "AWS::Kinesis::Stream",
       "Properties" : {
          "Name" : "Kinesisストリーム名",
          "ShardCount" : シャード数
       }
    }
  }
}
```

ストリーム名を指定するために、わざわざKinesisストリームを別の手段で作成していたケースにおいて、CloudFormationに集約することができるようになりました！
Mac で go を使う


brew でインストール。
バイナリパッケージなら cask を使います。

``` sh
$ brew cask install go
```

ホームフォルダの .bashrc を編集。

テキストエディットなどのエディタで編集するのですが、通常は不可視ファイルなのでファイルダイアログで `command` + `shift` + `.` を押して .bashrc を表示させます。

.bashrc に次の内容を追記。

``` $HOME/.bashrc
export GOPATH="${HOME}/.go"
export GOROOT="$(brew --prefix)/go"
export PATH="$PATH:${GOPATH}/bin:${GOROOT}/bin"

test -d "${GOPATH}" || mkdir "${GOPATH}"
test -d "${GOPATH}/src/github.com" || mkdir -p "${GOPATH}/src/github.com"
```

ファイルを保存したら、保存した直後だけは

``` sh
$ . ~/.bashrc
```

を実行。普段はターミナルを開けば自動で設定は読み込まれます。

``` sh
$ go version
go version go1.6.2 darwin/amd64
```

go のバージョンを表示させてみて動作を確認。

出典：[Install go with brew, and running the gotour](http://stackoverflow.com/questions/12843063/install-go-with-brew-and-running-the-gotour)

※GOROOT の PATH が環境によって違うかも。出典では `/usr/local/Celler/go/libexec` (`$(brew --prefix golang)/libexec`) となっていたけど自分の環境では `/usr/local/go` みたいなので。
Photoshopでカラコレ用のLUTテクスチャを作る


すごい簡単なんだけど、
UnityとかUEとかoFとかで使うエンジニアが、
デザイナーの方に伝えるとき用に書きました。

## 0. LUTテクスチャ？

UnrealEngineのドキュメントにわかりやすい説明が載ってます。
https://docs.unrealengine.com/latest/JPN/Engine/Rendering/PostProcessEffects/ColorGrading/index.html


## 1. Photoshopに補正前LUTテクステャを入れる

どの大きさのLUTがいるかは、プロジェクトによるので、確認してください。

__LUT 256x16.png__
![lut256x16.png](https://qiita-image-store.s3.amazonaws.com/0/14330/a28b6947-ad61-29b4-1fa0-ba492afa0d1c.png "lut256x16.png")

__LUT 1024x32.png__
![lut1024x32.png](https://qiita-image-store.s3.amazonaws.com/0/14330/349bce8b-7402-f1f3-9978-43fd2689f409.png "lut1024x32.png")

__LUT 512x512__
![lut512x512.png](https://qiita-image-store.s3.amazonaws.com/0/14330/3d570c31-47f5-840d-0ee8-6e6bb23cf174.png "lut512x512.png")


プログラマー向け。大体いつも忘れるので、LUT生成用のコマンドをつくりました。
https://gist.github.com/asus4/09b1f5403c63ceab5ae34710cbe2809e


## 2. Photoshop好きな画像で色補正する

使う、ゲームなりのキャプチャ画像を下におく。
調整レイヤーでいい感じになるように色補正する。

元画像
![before.jpg](https://qiita-image-store.s3.amazonaws.com/0/14330/bc8a8281-0add-ca93-cc62-b5805ba4af19.jpeg "before.jpg")

適当補正後画像
![after.jpg](https://qiita-image-store.s3.amazonaws.com/0/14330/6f99e9b0-07d5-b295-17ca-be115b722839.jpeg "after.jpg")



## 3. 色補正がのったLUTテクスチャだけ書き出す

![out.jpg](https://qiita-image-store.s3.amazonaws.com/0/14330/6ea5c210-340c-96e9-d2b9-2a40445ef68b.jpeg "out.jpg")


→ これ貰えれば同じ色補正出来ます！
[Android]複数ボタンの同時押し対処

現在４択のクイズアプリを作成しているが、
ボタンを同時（Androidでは多少の誤差でも判別するため、厳密には違う）に２つ押された際に、意図しない挙動をしていることが分かった。


その事象は、
「その問題の判定には問題なかったが、次の問題の判定において、後に押された方の解答が適用される」
といったものだった。

アプリ開発初心者のため、ボタンが同時に押されることまで頭がまわらなかったので、
とりあえず検索した。

すると、簡単に制御できる方法があったので以下に記す。

```activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:splitMotionEvents="false">

    <Button
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:id="@+id/Button1" />

    <Button
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:id="@+id/Button2" />
</RelativeLayout>
```

**android:splitMotionEvents="false"**の部分である。

ただし、同時に押されるであろうボタン群を、
android:splitMotionEvents="false"を適用したレイアウトに配置していないと効果がないようだ。

以上です。
Content-Typeの一覧

# Content-Type List

自分が使いそうなとこだけピックアップ

|Content-Type | Kind |
|:--|:--|
|text/plain  | テキストファイル  |
| text/csv  | CSVファイル  |
| text/html  | HTMLファイル  |
| text/css  | CSSファイル  |
| text/javascript  | JavaScriptファイル  |
| application/octet-stream  | EXEファイルなどの実行ファイル  |
| application/json  | JSONファイル  |
| application/pdf  | PDFファイル  |
| application/vnd.ms-excel  | EXCELファイル( `.xls` OFFICE 2007より過去)  |
| application/vnd.openxmlformats-officedocument.spreadsheetml.sheet  | EXCELファイル( `.xlsx` OFFICE 2007以降)  |
| application/vnd.ms-powerpoint  | PowerPointファイル( `.ppt` OFFICE 2007より過去)  |
| application/vnd.openxmlformats-officedocument.presentationml.presentation  | PowerPointファイル( `.pptx` OFFICE 2007以降)  |
| application/msword  | WORDファイル( `.doc` OFFICE 2007より過去)  |
| application/vnd.openxmlformats-officedocument.wordprocessingml.document  | WORDファイル(`.docx` OFFICE 2007以降)  |
| image/jpeg | JPEGファイル(.jpg, .jpeg)  |
| image/png  | PNGファイル  |
| image/gif  | GIFファイル  |
| image/bmp  | 汎用Bitmapファイル  |
| image/x-ms-bmp  | Microsoft Bitmapファイル  |
| image/svg+xml | SVGファイル |
| application/zip  | Zipファイル  |
| application/x-lzh  | LZHファイル  |
| application/x-tar  | tarファイル/tar&gzipファイル  |
| audio/mpeg  | MP3ファイル  |
| video/mp4  | MP4ファイル  |
| video/mpeg  | MPEGファイル（動画）  |
難しいと思ってたRailsのパフォーマンス・チューニングがちょっとしたことで劇的に改善できた話

前から任されたら嫌だなーと思っていたパフォーマンス・チューニングのタスクがまわってきて「ついに来たー！イヤー！」と思ったのに、ちょっとしたことで劇的にパフォーマンスが改善して一瞬で終わりましたよ、でも大して自慢にならんね、という話。

そのプロジェクトは全部で１２カ国にまたがるウェブサービスを展開していて、問題になっていたのは定期的に出してたレポートの出力パフォーマンスだった。財務諸表のフォーマットに沿ったレポートでしかも統一されたモノではなく、各国の会計基準に合わせたフォーマットになっていた。それはほぼ９種類。もちろん通貨は異なるし、それぞれの国で独自でユーザーに無料特典とかを実施していたので、その会計のルールでは無料特典の扱いが国によって異なるから、ユーザー毎に無料特典分と本当にお金を支払ってサービス利用した分とかを集計したり、結果をchart.jsに渡してグラフ表示が必要な国と不要な国があったりと、とにかくややこしかった。

最初このレポート機能を実装した時はだいたい１，２分で全世界分のレポートが出力できていたらしい。ところが月日が経ってデータ量も肥大化し今ではボタンを押して全てのレポートが出るまで１４分もかかっていた。いくらなんでも１４分は無いわ、ということで担当エンジニアであるロンドンオフィスのイギリス人エンジニアPがチューニングをしていた。
しかしPは他にいい転職先が見つかったらしく、もうすぐ退職の予定でその最終出社日が間近に迫っていた。もしPが退職までにこれを完了させなければ、私にこの仕事がまわってきそうな、いやーな予感がしていた。ちょくちょくPにチャットで「やっとるか？」と進行状況を聞いていた。Pからは妙にガンバってる風な返信が来るのだが「実はそこまでやる気ない」というPの密かな思いをヒシヒシと感じていた。

で、いよいよデッドラインが近くなって私に声がかかった。「ついに来たか。。。」と暗雲たる気持ちでPから大量の国際会計ルールのドキュメントやらが送らてきたのを眺めていた。そして１時間ほどPとスカイプ会議をした。会議で説明を聞きながらPがハマるのも理解できた。あまりに細かいルールがあり過ぎるのだ。しかもコードはところどころが生SQLで別のところはActiveRecord（ORM）を使っている。
「なんでこんなに統一性が無いんだよ？」と聞くと、あまりに会計ルールが分からなさすぎて、泥縄式に統一感なく完成させたから、ということだった。スパゲッティ・コードもさることながら国際会計ルールも頭痛の種だった。そんな英語聞いたことない、というような会計用語をPのブリティッシュ訛りの英語でガンガン言われてストレスがマックスだった。「まだよく分からないけど今日はここまでにしよう。次回は２日後で」と言ってスカイプ会議を終了した。
会議が終わったついでに、なにげにレポート出力ボタンを押すと過去４年分のデータを１４分かけて計算していて「こんなもん知るか」と、かなり投げやりな気持ちになっていた。

ミッションはこの１４分かかっている出力パフォーマンスをせめて３分以内にすること。
ありがちなN+1問題とかインデックス張ってないとかの初歩的な部分は全てPがチェック済みだった。もうここまで来たら、データベース設計からコードまで根本的に見直す必要があるかも、と思っていた。

しかしあることに気がついてちょっとコードを変更して、やってみたら１秒足らずのレンダリング時間でレポートが出力されたのだ。
面白いから次回のPとのスカイプ会議まで黙っておいて、会議でPに「ちょっとレポートボタン押してみて」と言った。「え？今？１４分かかるけどいいの？」と言いながらPが押すと１秒でレポートが出た。Pは例の放送禁止用語を連発して私に絶賛と罵倒を交互にシャウトした。

もうここまで書いて勘の鋭い方はお気付きかもしれない。
私がやったことは極めて単純。過去の売上確定分の計算処理は最初の１回だけにして、その計算結果はデータに保存しておく。そしてボタンを押したら前回計算して保存しておいたところからの差分だけを処理してレポートに足したのだ。なんで今までバカみたいに過去４年分のしかも全ユーザー分を国別にゴリゴリ計算してたんだよ、と。

まーこの改善策はあまりに基本的過ぎて、声高らかに「１秒にしたんだぜ！」などと自慢できるような話ではない。そして案外こういう基本的なことが抜け落ちているのは誰にでもあること。

この件について別にPがマヌケで私がセンスいい、とか思っていない。逆の立場であれば私もPと同じ状況に陥っていたことは想像に難くない。どんなエンジニアでも「国際会計のルールを全部把握しろ！」「１２カ国分の会計レポート出せ！」「ハヨしろ！ハヨしろ！」とやられると目の前のタスクの巨大さから、ついつい近視眼的になってしまう。近視眼的にやらなければややこしい会計ルールをコードに落とし込めない。そうするうちに基本的なことを見落としてしまうのだ。

今回の件ではオイシイところだけ私が奪ってしまったようだが、なかなかに教訓になる出来事だなと感じた。
事情を知らない人は、なんか私がすごい改善をして内容も全部理解してるように見えるようだが、結局私は今でも国際会計ルールは把握できていないし、あのコードのメンテナンスなんてできないし、やりたくもない。

# エンジニアの皆様へ
「[ほとんどのエンジニアには解けるが、下位10％のダメなエンジニアにだけ解けないパズル?](http://tango-ruby.hatenablog.com/entry/2015/11/30/122814)」なるものをシリーズ化してパズル１から８まで作成した。もしご興味あれば解いてみてください。
http://tango-ruby.hatenablog.com/entry/2015/11/30/122814
Firebase Analytics、実際触ってみた。

#Firebase Analytics超便利そう！

カスタムイベントも発行出来るし実装簡単だし、コホート分析出来るし最高じゃん！使お！

#現実

##コホート分析
コホート分析はイベント事に区切ることは出来ない上に、恐らくセッションが繋がっていれば分析対象となるっぽい。
つまり、「チュートリアルを終えたユーザーのコホート分析」のような条件付けはできない。

##カスタムイベント
カスタムイベントにはイベント名とパラメータを付けることが出来るが、カスタムイベントのパラメータを**見ることは出来ない**
つまり、同じ「post」というイベントで「Twitterにも同時送信したフラッグ」のようなものを送っても**何も出来ない**

##プリセットイベント
Firebaseにはプリセットのイベントとパラメータがあって、実はこれを使うとイベントの欄にグラフで表示したり出来る。
が、どうもプリセットイベントとパラメータには関連付けがあるらしく例えば

```
FirebaseAnalytics.Event.APP_OPEN
```
のイベントに対して

```
FirebaseAnalytics.Param.ITEM_NAME
```
のパラメータを付けてもイベントには**何も表示されない**

##反映
４時間くらいかかる。

#まとめ

Firebaseはユーザーの行動や行動数を定量的に分析出来るツールであって、それ以上の事は出来ない…気がする。
なおBigQueryに接続すれば生データをエクスポート出来るが、デイリーでのエクスポートになり１日かかります。
正直カスタムイベント周りで見れないデータ多すぎて萎えた。

３日くらい触ってみての感想なので実際はそうでないかもしれないので、もしそういうことを知っている人がいれば教えて下さい…。
収益やユーザー数を見る人には向いてそう。ユーザーを見たい人には向かないのかな…。

#対策
イベントは５００個まで作れるのでイベントを詳細に分けるのが良い。
パラメータはあてにならないので、post_with_twitter/post/post_with_instagramなど
ディレクトリ毎に別ユーザ名のBASIC認証をかけられるようにする(縛りアリ)

色々出来ることに制限のある環境で以下のような要件を満たす httpd.conf の設定を編み出したメモ。

まず httpd-2.2 でほぼ静的な設定の既存WEBサーバ環境があった。で、そこの一部ディレクトリにBASIC認証をかけたいという依頼を受けた。しかし色々縛りがあって以外に大変だったわ…というネタ。

ちなみに結構変態に分類される設定だと思うが、単に縛りの中で頑張ったら出来ましたってだけの設定を吐き出してるだけなので、他の誰の参考にもならない気がする。`.htaccess` が使えるなら使えば良いし、`httpd-2.2` 以外にして良いとか、間に別のProxy挟んで良いとか、他のモジュール入れて良いとか、他の手段が選べるならもっと楽で真っ当な方法を検討したほうが良い。

# 要件
- 要求
    - /secret/ 以下にBASIC認証をかけたい
    - /secret/foo と /secret/bar はそれぞれ別のID/PASSにしたい。
    - /secret/ 以下のディレクトリ名は不定（依頼者が新しく任意のディレクトリを作って、ID/PASSを発行する）
    - パスワードの発行管理は依頼者自身が行えるようにしたい。（ /secret/.htpasswd の編集で完結させる）。
- 制限事項
    - httpd のバージョンは 2.2 系（2.4ではない）
    - .htaccess は使わせられない（`AllowOverride None`）
    - /secret/ 以下に新しいディレクトリを作る毎に面倒は見れない
    - 依頼者は新規ディレクトリの作成とパスワードファイルの編集のみ自由にできる。
- やっかないなポイント
    - .htaccess は有効化出来ず、httpd.conf に初回に1度設定追加を行うことしか出来ない。
        - ないのでBASIC認証の設定が出来るのは /secret ディレクトリに対する1つだけ
    - `require valid-user` だけじゃ駄目なのは明らか（ディレクトリ毎に別ユーザに出来ない）
    - `AuthGroupfile` のグループ制御でどうにか出来んか？とも思ったけど `require group xxx` を自由に変えられない（htaccessが使えない）ので駄目
    - `httpd-2.4` なら require で env を見たり式が使えたりするのでなんとでもなりそうだが…。

# 出来た

色々試行錯誤した経緯を端折って結果だけ書くと以下の様な設定で実現できた。

```/etc/httpd/conf/httpd.conf
<Location /secret/>
    # とりあえず普通のBASIC認証設定
    AuthUserfile /path/to/docroot/secret/.htpasswd
    AuthGroupfile /dev/null
    AuthName "Secret"
    AuthType "Basic"
    require valid-user
    # ユーザ名と同名のディレクトリのみを許可する（ただしadminユーザは全てのディレクトリを閲覧可）
    RewriteEngine on
    RewriteCond %{REMOTE_USER},%{REQUEST_URI} !^([A-Za-z0-9_-]+),/secret/\1/
    RewriteCond %{REMOTE_USER} !=admin
    RewriteRule . - [F,E=retry_basic]
    Header set WWW-Authenticate "Basic realm=\"Secret\"" env=retry_basic
</Location>
```

制限事項が１つあり、ディレクトリ毎のユーザ名はディレクトリ名と同名のユーザ名が強制される。
その点さえ目をつぶれば、新規ディレクトリを作ったら .htpasswd にディレクトリ名と同じユーザとパスワードを追加するだけで良い。また、管理者はディレクトリ毎にユーザ名を変えてみるのは面倒だと思うので admin というユーザ名はディレクトリ名の縛りが効かないようにした。

## 力技ポイント

### valid-user が通ったユーザに対して改めてBASIC認証をやり直させる方法

- `require valid-user` が通ったユーザに対して、mod_rewrite で改めてユーザ名とディレクトリ名の不一致をチェックして強制的に `403 Forbidden` を返す。
- また `F` と同時に環境変数を介して `Header set` と連携し、単に 403 にするだけでなく、BASIC認証の要求ヘッダを出力する。
- これにより `valid-user` であるにも関わらず、ブラウザには改めてBASIC認証の入力ダイアログが表示されることになる。



### 地味に面倒だった 『ディレクトリ名とユーザ名の一致チェック』

- `RewriteCond %{REQUEST_URI} ^/secret/%{REMOTE_USER}/` とかどうだ？
    - → `%{REMOTE_USER}` の `{` と `}` の部分が正規表現エラー。まぁそうよね…。
- `RewriteCond %{REQUEST_URI} ^/secret/%\{REMOTE_USER\}/` だと？
    - → `%{REMOTE_USER}` っていう文字列そのままの名前のディレクトリにマッチしちゃう。ですよねー…。
- `RewriteCond %{REQUEST_URI} ^/secret/([^/]+)` して更に `RewriteCond %{REMOTE_USER} %1` とか後方参照で分けたらどうよ！？
    - → ちょっと期待してたんだが `%1` ていう2文字の名前のBASIC認証ユーザ名が通るようになったよ！ 
    - つまり第2引数に変数入れられないってことなんだな…。しかしそれだと REQUEST_URI と REMOTE_USER を比較する方法ってあるんか？

💡 ピコーン！ そういえば `RewriteCond` の第1引数って単なる文字列だから変数2つとも突っ込んで、1個の正規表現の中で後方参照使って2箇所に分かれた部分文字列の一致チェックをすればいいんじゃね！？
ってことで ↓ この1行マッチが生まれた。

```
RewriteCond %{REMOTE_USER},%{REQUEST_URI} !^([A-Za-z0-9_-]+),/secret/\1/
```

結果は見事成功。やったね！ 🎉
BigQuery | bq load --nosync オプションをつけると --max_bad_records に意味がなくなる

かもしれない。

`--nosync` をつけた時点で、 `bq load --max_bad_records=無限`

みたいな扱いになり、リソースとスキーマに食い違いがあっても、暗黙にロード自体は成功する。エラーが起きない。

# 環境

- This is BigQuery CLI 2.0.24



<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# メンター受付


https://menta.work/user/5694

<!-- Update From Qiita API -->
Zabbix3.xで通信暗号化時の zabbix_getコマンド

## 概要
Zabbix3.0以降で通信が暗号化出来るようになりました。 
暗号化を利用すると、`zabbix_get` コマンドが今まで通り使えなくなります。 
オプションで暗号化の設定を記述しておく必要があるので、
.bashrc 等に aliasを記述しておくと便利です。

### 参考
```

alias zabbix_get="zabbix_get --tls-connect=psk --tls-psk-identity=HOGEHOGE  --tls-psk-file=/etc/zabbix/zabbix_agentd.psk"

```

上記で、今までと同じような感覚で`zabbix_get`コマンドが利用できます。

※.bashrc に追加したら、`source .bashrc` を忘れずに。
Chef リポジトリ作成

Chef リポジトリ作成
============

ワークステーションにて「chef generate repo」コマンドで [chef-repo](https://docs.chef.io/chef_repo.html) を作成し、以降の作業ディレクトリとします。

```bash
$ chef generate repo chef-repo
```

chef-repo を生成すると下記のようなディレクトリ構成になります。

```
chef-repo
├── .gitignore
├── LICENSE
├── README.md
├── chefignore
├── cookbooks
│   └── README.md
├── data_bags
│   └── README.md
├── environments
│   └── README.md
└── roles
    └── README.md
```

git init されている状態なのでコミットをしておきましょう。

```bash
$ git add .
$ git commit -m 'initial commit'
```

Knife Zero の設定ファイル作成
==================

chef-repo 直下に knife.rb を配置します。

```ruby
local_mode true
chef_repo_path File.expand_path('../', __FILE__)

knife[:ssh_attribute] = "knife_zero.host"
knife[:use_sudo] = true

knife[:automatic_attribute_whitelist] = %w[
  chef_packages
  hostname
  ipaddress
  os
  os_version
  platform
  platform_version
]
```
ターミナルでprologのプログラムファイルの読み込み

うん，前回の記事に引き続き，prologの課題をやっています．

課題のマニュアルはウィンドウズの方で，コマンドでどうやるか．．．．なんと書いてくれてない！！！！！！！
（まあそれは置いといて）

インストールして，課題通り`parents.pl`のプログラムをsublで作成しました．

ターミナル開いて

`gprolog`
を実行して

パスを含めたファイル名を以下のように書いてあげます．
自分のファイルのパスを使ってね（バカにしてないです）

```
| ?- ['/Users/bijin/Desktop/parents.pl']. 
compiling /Users/bijin/Desktop/parents.pl for byte code...
/Users/bijin/Desktop/parents.pl compiled, 6 lines read - 679 bytes written, 8 ms

(1 ms) yes
```
失敗したら変な空白とか入っていないかどうかを確認しましょう！
あと，バージョンによって書き方が違うから気を付けましょう．
`yes`って言われたら勝ち組です．

うん，次に`listing.`を入力したら，先ほど読み込んだプログラムの内容が表示されます．


```
| ?- listing.

% file: /Users/bijin/Desktop/parents.pl

parent(pam, bob).
parent(tom, bob).
parent(tom, liz).
parent(bob, ann).
parent(bob, pat).
parent(pat, jim).

(1 ms) yes
```

表示された！よし，正しくプログラム読み込み済み！
以上！

ちなみにちょっとQiitaの使い方わかってきた！良い！
Chef クックブックの作成

Chef クックブックの作成
============

Chef では Cookbook という単位で開発していきます。Rubygems で言う gem が cookbook にあたります。
今回は myweb というクックブックを作成します。

```bash
$ chef generate cookbook myweb
$ cd myweb
```

chef コマンドには generate サブコマンドがあり、cookbook の雛形を生成できます。
cookbook だけでなく recipe や template なども雛形が作成できます。
cookbook を生成すると下記のようなディレクトリ構成になります。

```
.
├── .gitignore
├── .kitchen.yml
├── Berksfile
├── README.md
├── chefignore
├── metadata.rb
├── recipes
│   └── default.rb
├── spec
│   ├── spec_helper.rb
│   └── unit
│       └── recipes
│           └── default_spec.rb
└── test
    └── integration
        └── default
            └── serverspec
                ├── default_spec.rb
                └── spec_helper.rb
```

metadata.rb には cookbook のメタ情報を記述します。
chefignore には cookbook を配布する際に含めないファイルを記述します。
.kitchen.yml は Test Kitchen の設定ファイルです。
他にもレシピファイル、インテグレーションテストのファイルやユニットテストファイルが生成されています。

Windows で生成した際には、改行コードが CRLF なので、LF に直します。(任意)

```bash
$ find -name .git -prune -o -type f -exec sed -i -e 's/\r//g' {} \;
```

git init されている状態なのでコミットをしておきましょう。

```bash
$ git add .
$ git commit -m 'initial commit'
```
Raspberry Pi 2 + USB WiFiドングル２個で、Wi-Fi 中継器 

## 概要
- キホン、[Raspberry Pi 3 + USB WiFiドングルで、Wi-Fi 中継器](http://qiita.com/mt08/items/a00417d877836744c65c)

## 環境
- Raspberry Pi 2
- USB WiFiドングル(RTL8188CUS) : 2個

## 手順
1. アクセスポイントの設定 [\[メモ\] Raspberry Pi 3で、Wi-Fi アクセスポイントルータ](http://qiita.com/mt08/items/f2e4f9d3b1ed00849e23)
2. iptablesの設定で `eth0`のかわりに、`wlan1`にする
3. RTL8188CUS向け、`hostapd`を入れ替え [(参考)](http://qiita.com/mt08/items/f2e4f9d3b1ed00849e23#%E3%81%9D%E3%81%AE%E4%BB%96)

    ```
#コマンドラインへこぴぺ
wget https://raw.githubusercontent.com/mt08xx/vgc/master/bin/hostapd_v2.5-rtl871xdrv.zip
unzip hostapd_v2.5-rtl871xdrv.zip
sudo mv -i /usr/sbin/hostapd /usr/sbin/hostapd.ORIG
sudo mv -i hostapd /usr/sbin
sudo chmod 755 /usr/sbin/hostapd
```
4. `sudo vi /etc/hostapd/hostapd.conf`

    ```txt:/etc/hostapd/hostapd.conf
...
# driver=nl80211
driver=rtl871xdrv
...
```

5. `sudo reboot`
フォーカス時かつトレイクリックができない

できなかった宣言

# <i class="fa fa-cubes" aria-hidden="true"></i> やりたかったこと

トレイアイコンクリック時の動作をウインドウの状態で変化させたい
(良し悪しは別にして)

| ウインドウ状態 | トレイクリック時 | 
|:-----------|------------:|
| 非フォーカス       |     フォーカス |
| フォーカス     |      トレイに最小化(非表示) |
| トレイに最小化   | フォーカス(表示)|

# <i class="fa fa-cogs" aria-hidden="true"></i> 環境

* Electron 0.37.2
* Windows 7

# <i class="fa fa-code" aria-hidden="true"></i> 書いてみたコード

```js

	var Tray = require('tray');
	var tray = new Tray('アイコン');

	tray.on('click', function() {
		if (mainWindow.isFocused()) {
			mainWindow.hide()
		} else if (mainWindow.isVisible()) {
			mainWindow.focus()
		} else {
			mainWindow.show()
		}
		
	})

	mainWindow = new BrowserWindow({hogehoge});
```

# <i class="fa fa-graduation-cap" aria-hidden="true"></i> 結果

当たり前だが、トレイクリック時点でウインドウのフォーカスがはずれていると思われる。
状態は表示かつ非フォーカスになるので、トレイクリックの結果は常にフォーカスになる。

もっとjs側でフラグ管理とかしないといけないのだろう。
さして必須ではないので今は

```js
		if (mainWindow.isVisible()) {
			mainWindow.hide()
		} else {
			mainWindow.show()
		}
```

にしている。
Raspberry Pi 3 + USB WiFiドングルで、Wi-Fi 中継器



## 概要
- `PC <--> [wlan0(本体) - ラズパイ3 - (USB)wlan1] <-> Wifiルータ <->Internet` みたいな感じ
- キホン、[\[メモ\] Raspberry Pi 3で、Wi-Fi アクセスポイントルータ](http://qiita.com/mt08/items/f2e4f9d3b1ed00849e23)
- iptablesの設定で、`eth0`のかわりに、`wlan1`(USB WiFiドングル)にする。

## 環境
- Raspberry Pi 3 + USB WiFiドングル(RTL8188CUS)

## 手順
1. [↑のリンク](http://qiita.com/mt08/items/f2e4f9d3b1ed00849e23)のアクセスポイントの設定を行う。
2. iptablesの設定で
    1. `eth0`のかわりに、`wlan1`にする
    <br>または
    2. 以下のスクリプト使用([VPNGate](http://qiita.com/mt08/items/01f57f8a6658922755b3#_reference-7dc28db6b2007e8d8f91)のとこで使ったやつ)

        ```
wget https://raw.githubusercontent.com/mt08xx/vgc/master/chif -O ./chif
chmod +x ./chif
./chif wlan1
sudo mv -i /etc/iptables.ipv4.nat /etc/iptables.ipv4.nat.bak
sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"
```
3. `sudo reboot`

## その他
- ネットワークIntefaceを入れ替えればいろいろできるので、<font color='red'>**有線LANの機器へ中継**</font>、なんてのもできる。
    - `PC(有線LAN) <--> [eth0 - ラズパイ - wlan0] <-> Wifiルータ <->Internet`
    - chifスクリプト内の `IF_from=wlan0`を書き換えればラク?
yumの扱い注意

###何回注意しても職場の方がやらかすので。

##Yum
yumは便利である。インストール/アンインストール時に、関連するパッケージも同時にインストール/アンインストールしてくれる。

##Yum注意事項
ただし、万能では無い。頼り切っていると、システムを破壊する事もある。
先日も発生。対策。必ず標準出力は見ながら実施する事、-yオプションは使わない事。-y使っていいのは、何回も試した後です。
また、何かしらのパッケージを入れ直す時、まずはアップデートを試す、それが出来なければ新パッケージのインストール後に旧パッケージのアンインストールを試す。
まずは旧パッケージをアンインストールして新パッケージのインストール、は最後の手段にする事。

##Yumの失敗事例
先日やらかしたのは、AWS上に構築したサーバで、
Java古いとか言い出して、yum --delete jdkのパッケージ、とかやってくれました。
その後、AWSのAPIコマンド群が無くなったとか騒いでましたが、Javaに頼ってるんだから、そりゃJava外せばAWSのコマンドも道連れでしょうよ…

##Yum、普通はトラブル避けるタイミング
この場合、Javaが何に使われてるか把握してれば、そんな事はしなかった。コマンドを実行する前に確認を行っていれば、事態に気づいていた。標準出力を見ていればコマンド実行前に気づくし、もし実行してしまったとしても原因は即わかった筈。

##Yum、仕方ないので復旧方法
そちら方面には、/var/log/yum.log見ながら復旧させました。

##補足

###インストール/アンインストールにおける理想論、ただし仕事においては当たり前と思う話

まずは検証する事。手順をテキストエディタでも手書きでもいいから事前に書き出す。書きだした通りに入力する。結果をもって最初の手順にフィードバックする。成功するまで繰り返す。

また、インストール/アンインストール前後で変更になったパッケージは記録または記憶しておく事。それこそrpm -qa等。

上記を軽く見ると、いずれ痛い目見ます…
面倒とか言う輩に限って検証もしないで自動化がどうとか言って大コケしてるし…
略していいのは、スキルと計画が十分になってから。

###インストール/アンインストールにおける注意事項

rpmコマンドでもyumコマンドでも同じです。
forceインストールや、-yを避ける理由もここにありますが。
rpm/yumコマンドは、ユーザが意図したパッケージのインストール/アンインストールに伴い影響を受けるパッケージを画面に出力します。
rpm/yumコマンドがこのパッケージをインストールしたら他にどのパッケージが必要で競合でこのパッケージが削除されます、とか、このパッケージをアンインストールしたら依存関係でどれどれのパッケージが削除されます、と教えてくれます。
せっかくrpm/yumコマンドが親切にも表示してくれてるのに見ないで、パッケージが消えたと大騒ぎするご主人様が多い、の話です。
なお、yum で-yすると、親切に教えてくれるのですが、無しの場合と違って表示だけして最後まで実行してしまうので、追跡は出来ますがコトが済んだ後です。
もっともyumの報告を見る人は残念ながら少数派とは捉えていますが。
gnu-prologをbrewでインストールした

大学の授業でPrologで推論を行ってみました．

今度はそのインストール編です．

ウェブページからパーケッジをダウロードするURLは
http://www.gprolog.org/
です．

ですが，そっちでダウロードすると，gprologのコマンド画面をいちいち開かないといかない．．．です．

macのターミナルで普通に使いたいから，brewで再インストールすることにしました．

とても簡単です．

まずbrewをアプデートする（もちろんhomebrewがインストールされたことは前提条件だよん）
`$brew update`

そして，gnu-prologのインストールです．
```$brew install gnu-prolog
==> Downloading
https://homebrew.bintray.com/bottles/gnu-prolog-1.4.4.el_capitan```
```######################################################################## 100.0%
==> Pouring gnu-prolog
1.4.4.el_capitan.bottle.1.tar.gz
🍺  /usr/local/Cellar/gnu-prolog/1.4.4: 190 files, 12.2M
```

これで完成です！！簡単でしょう！

ちなみに
`$gprolog`
で打つと実行が始まります！

`halt`
で終了
楽しんでください

引き続きはこちら：
http://qiita.com/liupeijie/items/a85ec3cd922c93057a71
kitchen & berks の不具合対応

環境
====

* Windows 10
* ChefDK 0.13.21

現象
===

Windows 環境で berks コマンドを実行すると内部エラーが発生する。

```
`split' invalid byte sequence in Windows-31J (ArgumentError)
```

文字コード絡みのようだ。

対策
===

* C:\opscode\chefdk\bin\berks
* C:\opscode\chefdk\bin\kitchen  (内部的に berks を利用時)
* C:\opscode\chefdk\embedded\bin\berks
* C:\opscode\chefdk\embedded\bin\kitchen (内部的に berks を利用時)

の 2行目に

```ruby
Encoding.default_external = 'utf-8'
```
を追加する。
Androidの標準ブラウザでbase64の画像を保存しようとすると落ちる問題


base64はURLが長すぎるので、一部Androidの標準ブラウザでは画像を長押し保存できない(2016年6月現在)。これはURLの文字数制限にひっかかるのが原因で、画像のサイズは関係なし。
（aタグにtarget="_blank"つけて別タブで開いても、download属性を使ってみても、画像は保存できない。）

検証はしていないが、考えられるのはblobへ変換する方法
[canvasで描画したデータをtoDataURL()メソッドで<img>のsrc属性に指定後、画像の保存ができない！](https://teratail.com/questions/11183)

これでできなければ対処法はないので、標準ブラウザを使えない旨を明記する。Dにはこんな感じの説明を添えて。
> Android端末は「Chrome」でのみ検証する。なぜならGoogleが「標準ブラウザ」のサポートを終了しているから。標準ブラウザのアップデートをしてくれないということは、バグが発生した時に対応できない。さらにアクセス解析では「Chrome」のシェアが「標準ブラウザ」を上回っている。

結論、サーバーサイドでjpeg/pngをつくるのが確実。
Fastly から流れてくるログを基に、Papertrail から Slack へ通知する

[Fastly のログを Papertrail にストリーミングする](http://qiita.com/gundammkv/items/843e4fa52283b3cf6cae) にて、Papertrail で Fastly のログを受け取ることができるようになりました。次はそのログを使って何をするか、ということになりますが、まずは特定のレスポンスコード（例：404 とか)を検知した時に、Slack へ通知を投げるということをやってみたいと思います。

# 下準備

Fastly のログを Papertrail にストリーミングしている状態であることを前提としています。もしまだ設定がない場合は、[Fastly のログを Papertrail にストリーミングする](http://qiita.com/gundammkv/items/843e4fa52283b3cf6cae) を参考に設定を作ってください。

通知を受ける Slack アカウントが必要です。新規作成される方は、[Slackを導入する方法](http://qiita.com/hhyuga201515/items/d072b886dd914d4a2a4a)という良記事がありますので参考にしつつ Slack アカウントを作成してください。

# Slack の設定

受け取る側の Slack では、どのユーザまたはチャンネルで受け取るかを指定します。Slack の App Directory で Papertrail を検索するか、[slack.com - New Papertrail Integration](https://my.slack.com/services/new/papertrail) に行くと、Slack の Papertrail 設定追加画面が表示されます。

![slack-1.png](https://qiita-image-store.s3.amazonaws.com/0/39350/3dba4eaf-6ad0-36bf-41e6-697bce19ccbe.png)

通知を受け取る Channel を指定するか、新規作成します。
作成すると、Webhook URL が生成されますので、これを次のステップで使います。

![slack-2.png](https://qiita-image-store.s3.amazonaws.com/0/39350/e20064f7-5e50-13f2-1259-fc1848bed120.png)

# Papertrail の設定

Papertrail から Slack へ通知を送る際には、そのきっかけとなるイベントを作る必要があります。そのためには、Event Viewer から Search を作成し、Alert を関連付けます。Search を作ることで特定の条件を指定（例：HTTP エラー 404 を検知する）し、Alert で通知を投げる（今回は Slack の Webhook URL に投げる）、という流れです。

Search を使うと任意の条件を基にログを検索することができますが、今回は、ログに 404 という文字列があったらという条件を作ってみます。敢えて 404 が出るようなリクエストを発行して事前にログに 404 を残しておくとわかりやすいと思います。

Event Viewer の画面に行くと、画面下の方に検索バーがあります。ここに 404 と入力し、「Search」してみましょう。

![papertail-search-1.png](https://qiita-image-store.s3.amazonaws.com/0/39350/215a67f7-7965-3dff-896c-cf9875508fcb.png)

検索バー右側にある「Save Search」をクリックして、検索条件を保存しましょう。今回は「404 - Errors」としました。保存した検索条件は検索バーの真ん中辺にある、「All Systems」とあるところの右側にある小さなボタンをクリックすると見ることができます。

![papertail-search-3.png](https://qiita-image-store.s3.amazonaws.com/0/39350/6a867f3a-b9c0-9fa0-1e5d-f9358f335721.png)

保存された検索条件を選択すると、検索バーの一番右の方に「Create Alert」というボタンが表示されますので、これをクリックします。

![papertail-search-2.png](https://qiita-image-store.s3.amazonaws.com/0/39350/11c58cd7-f5c8-0fe0-fe0b-fa71a2d64ac3.png)

「Create an Alert」画面が表示されます。Slack は右側の「Chat」のところにありますので、これをクリックします。

![papertail-alert-1.png](https://qiita-image-store.s3.amazonaws.com/0/39350/401f4d9a-b6a6-e890-7652-ec17c8297d87.png)

Alert 設定画面が表示されます。「Slack Details」の「Integration's URL for Webhook URL」に、先ほど Slack で作った「Webhook URL」を入力して「Create Alert」をクリックします。これで設定は完了です。「Alert Details」で検索頻度、しきい値、タイムスタンプだったりを設定できます。

![papertail-alert-2.png](https://qiita-image-store.s3.amazonaws.com/0/39350/ca637d27-2949-14e3-f935-6e0c2e672163.png)

# 404 エラーが発生すると、Slack にメッセージが届く

設定を確認するために、あえて 404 を発生する URL を叩いてみました。頻度を10分にしちゃったので、ちょっと時間がかかりましたが、Slack に Alert を送ることができました。

![slack-message-2.png](https://qiita-image-store.s3.amazonaws.com/0/39350/ae99b117-9f7b-0eeb-3b56-709720215790.png)

このように Papertrail を活用して、ログを使ったアラートシステムを構築することも可能です。Papertrail は他にも色々なアプリケーションと連携ができるので、想像が膨らみますね。Amazon SNS とも連携できるようですよ。

# 参照

Slack integration guide for Papertrail：http://help.papertrailapp.com/kb/integrations/slack/
OpenStack関連コマンドでEndpointのタイプを指定して接続する方法

OpenStack Keystone には、Public、Internal、Adminの３種類の URL を登録するようになっている。

この3タイプを使い分けることによって、たとえば Public だけ Disable にしておけば、管理者にだけ使えるコンポーネントを作ることが可能である。

OpenStack 関連コマンドのデフォルトでは、Endpoint タイプは、PublicURL を指定して接続を試みようとする。InternalURL を指定して接続したい場合には、以下のようなオプションを入れて実行するとコマンドが実行可能である。

```shell-session
$ swift --os-endpoint-type internal list
test_container
```
Git-svnでSubversionからGitに移行しよう。

# はじめに

Subversionのリポジトリからcommitログを引き継いだ形でGitへ移行した際の手順です。
また本番環境でのgitへの切替も含んでます。

[ブログ](https://www.yoshikinoue.net/2018-09-21-subversion-git-gitsvn/) に転記済みです。
よろしければ↑をどうぞ。

## 注意点
一度、自分の手元のPCで作業用のディレクトリを作成して作業することをおすすめします。
間違ってもいきなり本番環境などでは作業しないように…。

# SVNからGitへの移行作業

## 標準的なリポジトリ構造なら下記コマンドの実行でスムーズに行きます。

一連の作業は`git svn` コマンドで作業していきます。

```
git svn clone -s --prefix=svn/ svn+ssh://svnserve@hogehoge.com/hoge

標準的な構成
trunk
branches/hoge
branches/hugahuga2
tags
```

## リポジトリが変則的な場合

Subversionのリポジトリ構成が変則的な場合、`git svn clone`（内部で行っている事）を手動で行うことで対応出来る。

- `git svn init` で初期化
- `.git/config` を編集し、リポジトリ構成を明示しておく
- `git svn fetch` で取得

```
git svn init -s --prefix=svn/ svn+ssh://svnserve@hogehoge.com/hoge

/* .git/configを編集 */
vim .git/config

------------------------------------------------------
[svn-remote "svn"]
        url = svn+ssh://svnserve@hogehoge.com/hoge
        fetch = trunk:refs/remotes/svn/trunk
        fetch = dev:refs/remotes/svn/dev　　//追記部分
        branches = branches/*:refs/remotes/svn/*
        tags = tags/*:refs/remotes/svn/tags/*
------------------------------------------------------

git svn fetch
```


## ブランチの確認

```
git branch -a

  remotes/svn/dev
  remotes/svn/trunk
```

### ブランチを作る

```
git checkout -b svn/trunk
git checkout -b develop svn/dev
```

### 除外ファイル

```
git svn show-ignore >> .gitignore
```

# 予め用意しておいた空のリモートリポジトリを追加＆push

```
git remote add origin ssh://git@hogehoge.com/hoge

git push -u origin --all
```


# 既存のディレクトリへの反映

さて、無事VCSをGitに移行出来たら、開発環境や本番環境もGitに変更しましょう。

```
git init
git remote add origin ssh://git@hogehoge.com/hoge
git checkout -b svn-to-git
git fetch origin
git checkout origin/master -- .gitignore //監視除外の為リモートから取得する。
git reset --hard origin/master
```

### リモートをブランチをローカルに作成

```
git checkout -b master origin/master
git checkout -b develop origin/develop
```

### 仮に作ったブランチを削除

```
git branch -d svn-to-git
SVN使わないから削除
rm -rf .svn
SVNのバージョンが古い場合各ディレクトリに.svnが存在するので下記で対応
find . -name .svn | xargs rm -rf
```

## 参考情報
- [仕事で使ってる巨大SVNレポジトリをGithubに移管するためにやったことまとめ · DQNEO起業日記](http://dqn.sakusakutto.jp/2012/10/svn-git-github-migration.html)
- [git-svnでSVN→Gitへの移行をやってみたログ](http://qiita.com/hidekuro/items/4727715fbda8f10b6b11)