OmniAICreator/Qiita-1.07M huggingface dataset:
GuzzleでTimeoutを1秒未満に設定する

Guzzleでタイムアウトを1秒未満に設定したい時に必要となる記述を残しておきます。

## 前提条件

- Guzzle 6系
- PHP 5.6系

## 解決方法

curlのオプション `CURLOPT_NOSIGNAL` を `true` にします。

```php
use GuzzleHttp\Client;

$request_params = ['hoge' => 'foo'];
$guzzle_client = new Client(['base_uri' => 'http://example.com/']);
$http_response = $guzzle_client->request(
    'POST',
    '/api',
    [
        'timeout' => 0.1,  // 100msec
        'curl'    => [CURLOPT_NOSIGNAL => true],   // これが要！
        'json'    => $request_params
    ]
);
var_dump($http_response->getBody());
```

## 背景説明

内部的には、Guzzle→PHP→libcurlという流れで実行されています。libcurlは(少なくとも)Linux環境において、ディストリビューションが提供する標準のものを利用すると、タイムアウトはカーネルが提供するシグナル `SIGALRM` を使います。

しかし、 `SIGALRM` は秒単位でしか設定できないことが、今回の問題のポイントです。ですので、1秒未満になると切り捨てられてまともに動きません。

そこで、libcurlにてシグナルを使わないよう設定をした上で、タイムアウトを設定すると、シグナルに頼らずタイムアウトを観測できるようになり、問題が解決します。

なお、Guzzleのタイムアウトの設定は `CURLOPT_TIMEOUT` ではなく `CURLOPT_TIMEOUT_MS` を使っていて、Guzzleとしては1秒未満の値を定義することはできます。ここ、私が勘違いしていたところでした。

## 謝辞

@do-aki@github さんに助言いただきました。どうもありがとうございました！

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr"><a href="https://twitter.com/koemu">@koemu</a> guzzle って、 CURLOPT_CONNECTTIMEOUT_MS 利用してません？</p>&mdash; どぅーあき (@do_aki) <a href="https://twitter.com/do_aki/status/829609990205771777">February 9, 2017</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

## 参考文献

- [php.net - curl_setopt](http://php.net/curl_setopt)
- [curl - CURLOPT_TIMEOUT_MS](https://curl.haxx.se/libcurl/c/CURLOPT_TIMEOUT_MS.html)
- [curl - CURLOPT_NOSIGNAL](https://curl.haxx.se/libcurl/c/CURLOPT_NOSIGNAL.html)
- [Linux man - SIGNAL](http://linuxjm.osdn.jp/html/LDP_man-pages/man7/signal.7.html)
- [Linux man - ALARM](http://linuxjm.osdn.jp/html/LDP_man-pages/man2/alarm.2.html)
- [Guzzle6 FAQ: How can I add custom cURL options?](http://docs.guzzlephp.org/en/latest/faq.html?highlight=curlopt#how-can-i-add-custom-curl-options)
Javaでシグナルを検知して処理する。

##結論
しない方が良い。

##そもそも「シグナル」とは
>シグナル（英: signal）とは、UNIXやUnix系などのPOSIX準拠OSにおける限定的なプロセス間通信の一形態。
>プロセス間あるいはスレッド間で非同期イベントの発生を伝える機構である。

例えば、プログラム実行中に`Ctrl+C`で停止できるが、
この時、OSに対してSIGINTが送信されており、killコマンドが発行され、停止している。

##Javaでシグナルを検知するには
sun.misc.{Signal,SignalHandler} というAPIのがあります。
ですがこのAPIは非サポートで、Java9で残るのか無くなるのかも定かではないです。
[https://blogs.oracle.com/java/get-ready-jdk9](https://blogs.oracle.com/java/get-ready-jdk9)
怖い。
とても怖い。

とりあえず、今回のまとめではこれを使っていきます。

##まず始めに、どのシグナルは使わないべきか調べよう。
VMが掴んだりしてるシグナルがあるので、そういうのは避けたいですね。
という事で。

###JVMが使用しているシグナル
[http://www.ibm.com/support/knowledgecenter/ja/SSYKE2_7.0.0/com.ibm.java.zos.71.doc/user/sighand.html](http://www.ibm.com/support/knowledgecenter/ja/SSYKE2_7.0.0/com.ibm.java.zos.71.doc/user/sighand.html)
ここに書かれてるように、主要なシグナルは結構使われてます。

###HotSpotVMが使用しているシグナル
[http://www.oracle.com/technetwork/java/javase/signals-139944.html](http://www.oracle.com/technetwork/java/javase/signals-139944.html)
これもまた、主要なシグナルは結構使われてます。( JVMと同じような感じだけど )

###ここまでで分かる事
- 主要のシグナルは検知しない方が無難（SIGINTとかSIGTERMとか）
- ユーザ定義(SIGUSR1/SIGUSR2)も使われてる

##だったら SIGRTMIN以降 を使おう！！！
というわけにもいかない。( ばっさり )

[http://d.hatena.ne.jp/Kazuhira/20150422/1429713440](http://d.hatena.ne.jp/Kazuhira/20150422/1429713440)
ここに書かれてるように、RTMIN以降は使えない。
悲しい。
とても悲しい。

##という事で
ここまでで丸一日費やして、結局別の方法を取る事にしました。
幸い、「シグナルを検知する」という要件ではなかったので、別の方法で何とかなりそうですが、
もし、**「シグナルを検知する」という要件**の場合にはお気を付け下さい。

<br />
**けど勉強にはなったから良し!!!**
<br />
以上。
行の始め全てに文字を追加する（＞返信用記号など）

正規表現でやった方が楽かと思ったのですが、うまくできなかったので改行コードごとに分けて１行ずつ追加しています。    

行の始めに>を追加する


```objc
// 最初に文字列全範囲を示すRangeを作成する
NSRange range, subRange;
range = NSMakeRange(0, self.replyBody.length);
NSString *line;
NSString *result = @"";

// １行ずつ読み出す
while (range.length > 0) {
    // １行分を示すRangeを取得します。
    subRange = [self.replyBody lineRangeForRange:NSMakeRange(range.location, 0)];
    // 1行分を示すRangeを用いて、文字列から１行抜き出す
    line = [self.replyBody substringWithRange:subRange];
    NSString *addLine = [@">" stringByAppendingString:line];
    result = [result stringByAppendingString:addLine];
    // 1行分を示すRangeの最終位置を、
    // 次の探索に使うRangeの最初として設定する
    range.location = NSMaxRange(subRange);
    // 文字列の終端を、次の探索に使うRangeの最終位置に登録します
    range.length -= subRange.length;
}
self.messageTextView.text = [NSString stringWithFormat:@"%@", result];
```

こちらを参考にしました
http://www.yoheim.net/blog.php?q=20120614
UnityでPVRTC画像に対応する

# 前置き

Unityでビルドしたときに、APKは50MB、IPAは250MBというとんでもないサイズの差が起きた。
調べてみると、ほとんどが画像リソースによるサイズ肥大化で画像を調整することでサイズが抑えられることを確認できた。
色々無知だったのでiOS用に画像用意するときに注意したことをメモ。

# 前提

Unityに配置する画像リソースは、そのままExportされない。
Platformに最適なフォーマットとして格納される。

- [ファイルサイズの削減](https://docs.unity3d.com/ja/current/Manual/ReducingFilesize.html)

```
Unity は、アセットを独自の内部フォーマットに変換してインポートするため、元となるアセットの種類はさほど関係ありません。
例えば、プロジェクトでマルチレイヤーの Photoshop のテクスチャを持っている場合、ビルドされる前に平坦化され、圧縮されます。
PNGファイルのテクスチャをエクスポートしても、ビルドサイズに違いはないので開発時に最も便利なフォーマットにするべきです。
```

iosでscene内で利用するSpriteについては、pngquantなどでいくら減色を頑張ってもあまり効果がない。

# PVRTC

iOSではPVRTCフォーマットに変換することで効率的にExport時のサイズ圧縮ができる。

- [PVRTCの圧縮アルゴリズムとは？](http://www.webtech.co.jp/blog/optpix_labs/format/4930/)

PVRTCのメリット

- メモリへの展開サイズが抑えられる. GPUが圧縮されたまま参照できる
- Export後の画像サイズが抑えられる (1/5くらいになったりする)

PVRTCのデメリット

- 画像の種類によっては劣化が見られる
- POT (Power Of Two: 2の累乗)サイズの画像しか扱えない (256x256, 512x512など)
- 正方形じゃなきゃ駄目

# PVRTC対応

SwitchPlatformでiOSを選択

<img width="626" alt="buildsettings.png" src="https://qiita-image-store.s3.amazonaws.com/0/15000/b47ec213-d5b9-0a8e-6b2c-3a04590c7795.png">

Inspectorで見たときに、PVRTCと表示されていれば対応OK

<img width="324" alt="pvrtc512.png" src="https://qiita-image-store.s3.amazonaws.com/0/15000/683e46ab-a013-d6a6-700b-9046e1275824.png">

逆に NPOT (NonPowerOfTwo) などと表示されていればPVRTC化はできていない.

<img width="340" alt="npot511.png" src="https://qiita-image-store.s3.amazonaws.com/0/15000/7dfa7227-343c-6d19-803f-a951d78ba6da.png">

サイズが2の累乗の正方形であれば、Spriteに関しては自動でPVRTCにしてくれる。

# 参考

もっと詳しく書かれていて、良記事でした

- http://developers.mobage.jp/blog/texture-compression
Androidアプリがエラーで非公開にできない場合の対処法

学生時代、いくつか androidアプリを作っていたのですが、それらに関してつい最近、以下のようなメールが Google から届きました。

> [要対応] Google Play デベロッパー ポリシー違反に関わる警告
>
> Google Play デベロッパー様
>
> お客様のアプリ 【アプリ名】（パッケージ名 【パッケージ名】）が、Google Play の個人情報や機密情報に関するユーザー データ ポリシーに違反していることが確認されました。
>
> （中略）
>
> 2017 年 3 月 15 日までにこの問題を解決いただくようお願いいたします。ご対応いただけない場合、Play ストアからの削除も含め、お客様のアプリの公開を制限する措置を取らせていただきます。恐れ入りますが、あらかじめご了承ください。Google Play のユーザー皆様にわかりやすく透明性の高いサービスを提供するため、ご協力いただけますと幸いです。

2012年くらいに作ったやつなので、それ以後にポリシー変更があったようなのですが、対応していなかったので怒られた、というものです。

単純にマーケットを荒らしている僕が悪いので、メンテナンスしていないものについては全て非公開にして対応しようとしたところ、

**「アプリを保存できませんでした。フォーム内のエラーを確認してください」**

というメッセージが表示され、保存できませんでした。
そこで、Google Support に連絡してみたところ、以下の返信をいただきました。

> お問い合わせいただきましたアプリを非公開にする件ですが、アプリを非公開にした後も、既存のユーザーに対してはPlayストアにてアプリが表示されるため、アプリを更新または非公開とするには、デベロッパーコンソール上のアラートが表示されているページの赤字箇所を完成させていただく必要がございます。
> ご指摘の通りスクリーンショットも含めご対応いただき、デベロッパーコンソールにアラートがなくなりましたら、アプリの公開を停止していただけます。

なるほど。
というわけで、非公開にするためにスクリーンショットを作成するという不毛な作業をすることになったのですが、よく見たら必要なのはスクリーンショットではなくてヘッダー画像（1024x500）だったので、全アプリに共通のヘッダーを作成してアップロードしました。

![not-maintenance.jpg](https://qiita-image-store.s3.amazonaws.com/0/52780/0ea37692-c615-cdc5-610f-70d80e1340d3.jpeg)

その他、Rating に関するアンケートに答えたり、プロモーション情報を入れるなどして、エラーがなくなったら、無事に非公開にできました。

アプリを非公開にしようとしている開発者にとって、あまり親切なエラーメッセージではないと思ったので、そんな方の役に立てればと思い、駄文ですがまとめました。

上の画像について著作権の一切の行使をしないので、自己責任にてご自由にお使いください。
Swift で Quadratic Bezier 曲線の長さを計算する

## ベジエ２次曲線の長さを計算

ベジエ曲線の長さを計算する必要が出てきました。誤差はあってもいいのですが、やはり小さい方がいいです。そこで良い記事を見つけました。

![quad_bez_curve.jpg](https://qiita-image-store.s3.amazonaws.com/0/65634/6db4c10a-d801-760d-8505-66ff8f6d05df.jpeg)

■ Quadratic Bezier curve length
http://www.malczak.linuxpl.com/blog/quadratic-bezier-curve-length/

この記事を参考に Swift で書き直して見ました。

```swift:quadraticBezierLength.swift
func quadraticBezierLength(_ p0: CGPoint, _ p1: CGPoint, _ p2: CGPoint) -> CGFloat {

	// cf. http://www.malczak.linuxpl.com/blog/quadratic-bezier-curve-length/

	let a = CGPoint(p0.x - 2 * p1.x + p2.x, p0.y - 2 * p1.y + p2.y)
	let b = CGPoint(2 * p1.x - 2 * p0.x, 2 * p1.y - 2 * p0.y)
	let A = 4 * (a.x * a.x + a.y * a.y)
	let B = 4 * (a.x * b.x + a.y * b.y)
	let C = b.x * b.x + b.y * b.y
	let Sabc = 2 * sqrt(A + B + C)
	let A_2 = sqrt(A)
	let A_32 = 2 * A * A_2
	let C_2 = 2 * sqrt(C)
	let BA = B / A_2
	let L = (A_32 * Sabc + A_2 * B * (Sabc - C_2) + (4 * C * A - B * B) * log((2 * A_2 + BA + Sabc) / (BA + C_2))) / (4 * A_32)
	return L
}
```

記事を疑うわけではありませんが、以前 Bezier曲線を計算する記事を元に。実際の曲線の点を細かくとってその点と点の距離の和を計算して、違いを計算して見ます。

http://qiita.com/codelynx/items/f7e6a844aac3746a6b79

```swift:approximateQuadraticBezierLength.swift
func approximateQuadraticBezierLength(_ p0: CGPoint, _ p1: CGPoint, _ p2: CGPoint) -> CGFloat {
	let m = 1
	let n = Int((p1 - p0).length + (p2 - p1).length) * m
	var length: CGFloat = 0
	var lastPt: CGPoint? = nil
	for i in 0 ..< n {
		let t = CGFloat(i) / CGFloat(n)

		let q1 = p0 + (p1 - p0) * t
		let q2 = p1 + (p2 - p1) * t

		let r = q1 + (q2 - q1) * t

		if let lastPt = lastPt {
			length += (lastPt - r).length
		}
		lastPt = r
	}
	return length
}
```

実際に計算してみるとこんな感じです。

```.swift
let p0 = CGPoint(0, 0)
let p1 = CGPoint(500, 0)
let p2 = CGPoint(500, 500)

approximateQuadraticBezierLength(p0, p1, p2) // 810.613036611711
quadraticBezierLength(p0, p1, p2) // 811.612620070115
```

どうでしょう。m の値を 10 と近似値の精度を上げる中間点を 10倍 に増やすと…

```.swift
approximateQuadraticBezierLength(p0, p1, p2) // 811.512624236657
quadraticBezierLength(p0, p1, p2) // 811.612620070115
```

計算結果に収束しているような気もするので、良しとします。

コードは gist からも入手できます。
https://gist.github.com/codelynx/0f88983c0ba3e52776d2adeac77cb4f9

## What's next?

ベジエの３次曲線の長さの計算ですね。ハードルはさらにたかそうです。

## 環境に関する表記

```.log
Xcode Version 8.2.1 (8C1002)
Apple Swift version 3.0.2 (swiftlang-800.0.63 clang-800.0.42.1)
```
Talend tXMLMap での XML 加工時のポイント


Talend (Open Studio利用) でよく利用する tXMLMap について、慣れるまでに苦労した点を、つらつらと記録します。

# 1. Create empty element

Create empty element を **false** にしても、XMLで確認すると空ノードが生成されてしまっている事が多かった。
不具合かと思っていたが、実は分かっていなかっただけだったのでメモ。

**値や属性が空文字の場合は、ノードが生成される。**
**値や属性が null の場合は、生成されない。**

そういう事だった。

![00_design.png](https://qiita-image-store.s3.amazonaws.com/0/146352/abf57d59-55c2-1d4c-9f3c-4b91b0fdb5dc.png)

![01_tXMLMap_cee_false.png](https://qiita-image-store.s3.amazonaws.com/0/146352/cd83f2a1-bfa1-5a80-eba2-981c48918bac.png)

上のように設定した場合に、出力される XML は以下のようになる。
（```null``` を直接代入するとコンパイルエラーになるので、上記設定では ```true ? null : ""``` としている。）

```xml
<root>
	<EmptyStringNode>
		<item></item> <!-- 値が空文字 -->
	</EmptyStringNode>
	<NullWithEmptyAttr dummy=""/> <!-- 属性が空文字 -->
</root>
```

Create empty element が **true** ならこうなる。比較すると一目瞭然：


```xml
<root>
	<EmptyStringNode>
		<item></item> <!-- 値が空文字 -->
	</EmptyStringNode>
	<NullNode>
		<item/> <!-- 値がnull -->
	</NullNode>
	<NullWithEmptyAttr dummy=""> <!-- 属性が空文字 -->
		<item/>
	</NullWithEmptyAttr>
	<NullWithNullAttr dummy=""> <!-- 属性がnull -->
		<item/>
	</NullWithNullAttr>
</root>
```


---
# 2. 複数loopとAll in one

XML から直接 XML へ値を移したい時は、loop element の位置と All in one の設定に注目する。

例えば次のような XML をまるごとコピーしたいと仮定する（実際のケースはもっと複雑だろうが）。

```xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <loop1> <!-- 親1に対して子３ -->
        <item>
            <A>A1</A>
            <B>B1</B>
        </item>
        <item>
            <A>A2</A>
            <B>B2</B>
        </item>
        <item>
            <A>A3</A>
            <B>B3</B>
        </item>
    </loop1>
    <loop2> <!-- 親1に対して子2 -->
        <item>
            <C>C1</C>
            <D>D1</D>
        </item>
        <item>
            <C>C2</C>
            <D>D2</D>
        </item>
    </loop2>
</root>
```

次のように設定してやれば、まるごとコピーできる。
必要となるループ回数は、3 + 2 で 5回。その結果を All in one でまとめる具合に。

![02_tXMLMap_multiloop.png](https://qiita-image-store.s3.amazonaws.com/0/146352/fb8fdb4d-3d5e-adff-1f8e-ea75d411a431.png)

試しに All in one を false にすると、5 rows 生成されることが確認できるはず。


---
# 3. ツリースキーマエディター

自分でもまったく愚かだったと思うのは、「ツリースキーマエディター」の存在にしばらく気づかなかった事。
それまで、XML の各ノードの型指定はできないものと思っていた。すべて文字列扱い？などと誤解していた。

![03_tXMLMap_treeschema.png](https://qiita-image-store.s3.amazonaws.com/0/146352/1f3a589a-1fa6-407f-52f7-1c23c0b06f6f.png)

例えば日付として認識できる値は、上図のように直接日付型として読み取れる。
わざわざ TalendDate.parseDate() を経由して加工する必要はない。（してました。）


---
# 4. おまけ：Document型とObject型の相互変換

例えば子ジョブに XML データを渡したいな、と考えても、context 経由では Document 型を渡せない。
でも、一度 Object 型に変換してやれば渡せる。

1. contexts に Object 型の項目を用意する。(この例では xmlDoc)
2. 子ジョブにも同じものを用意する。
3. 親ジョブ側では、tRunJob の手前に tJavaRow を加える。
4. tJavaRow で ```context.xmlDoc = input_row.payload;``` と代入する。(payload は Document型)
5. tRunJob で xmlDoc を子ジョブへ渡す。
6. 子ジョブの tJavaRow で ```output_row.payload = (Document)context.xmlDoc;``` でキャストして戻す。

親ジョブ：
![04_tJavaRow_Doc2Obj.png](https://qiita-image-store.s3.amazonaws.com/0/146352/4e6dbd41-2cfc-9cf8-0be5-09fdd3e10175.png)
 
子ジョブ：
![05_tJavaRow_Obj2Doc.png](https://qiita-image-store.s3.amazonaws.com/0/146352/49008523-3f42-8258-9945-703134bf81e2.png)

---
（以上）
ポップアップウィンドウで、メニューを無くす方法

詳細画面等をポップアップウィンドウにする場合に普通にVIEWを使ってしまうと、
メニューまでポップアップに表示されるので、できればポップアップウィンドウだけ
メニューは外す処理をしたほうが良い。

方法としては下記。


application_helper側で、popupかどうかの判定を入れる。

`app/helpers/application_helper.rb`

```rb
  def is_popup_window?
    case controller.controller_name
    when "diseases","interview_sheets"
      case controller.action_name
      when "show"
        return true
      end
    end
    return false
  end
```

その上でVIEW側、メニューのある部分を下記の通り。

```html

              <% if is_popup_window? %>
                <li><%= link_to "閉じる", '_self', :onclick => "window.close();" %></li>
              <% else %>
                <li><%= link_to "病気一覧" , diseases_path %></li>
                <li><%= link_to "症状検索" , disease_symptoms_path  %></li>
                <li><%= link_to "問診一覧", interview_sheets_path %></li>
                <li><%= link_to "問診画面", medical_interview_steps_path, :target=>["_blank"] %></li>
                
```
jumpy系プラグインメモ

## jumpyとは

エディタ内を自由に動きまわる為のショートカットを提供するプラグインです。
これを使い始めてマウス操作が格段に減りました。

## エディタ&IDE
- ATOM
  - https://atom.io/packages/jumpy

- VisualStudioCode
  - https://marketplace.visualstudio.com/items?itemName=wmaurer.vscode-jumpy
- VisualStudio
  - https://github.com/justRu/jumpy
- JetBrains
  - https://plugins.jetbrains.com/idea/plugin/7086-acejump

## メモ
VisualStudioのjumpyはVisualStudio2015にGitHubからクローンしてビルドをして導入しました。

JetBrainsのプラグインは、early buildのGoglandに導入しました。
The Basic - Comments, Semicolons


## 参考
The Swift Programming Language 3.0.1
 - The Basic - Comments
 - The Basic - Semicolons

## コメント
Swift ではコメントが2種類で書ける。

### 1行コメント
// を行頭に添えると、その行はコメントになる

```
// この行はコメント
```

### 複数行コメント
\*/ で始め、*/ で終了を示唆。

```
/* コメント開始
コメント行
*/ // コメント終了
```

## セミコロン
Swift では文の終了に ; を書かなくても良いが、
書いても良い。
逆に、; を添えると、1行に２つの文が書ける

```
let someConst = "sample"; let someConst2 = "aaa"
```

自分が使う言語では ; が不要なので、書かない方向で進める。
Vagrant+VirtualBoxで作成した仮想マシンにPHPライブラリテスト用環境を構築する【3】

[Vagrant+VirtualBoxで作成した仮想マシンにPHPライブラリテスト用環境を構築する【1】](http://qiita.com/ss_watanabe/items/4bb3b86951ca82d71815)
[Vagrant+VirtualBoxで作成した仮想マシンにPHPライブラリテスト用環境を構築する【2】](http://qiita.com/ss_watanabe/items/6b79dfc0362eb5c5c44b)
Vagrant+VirtualBoxで作成した仮想マシンにPHPライブラリテスト用環境を構築する【3】 ←イマココ
[Vagrant+VirtualBoxで構築した仮想マシンをBox化して復元する](http://qiita.com/ss_watanabe/items/d15f890af58fa16447f6)

# pearのインストール
ここめちゃくちゃ詰まった
まずphp-xmがないとうまいこと動かなかった

```
[vagrant@localhost ~]$ sudo yum --enablerepo=remi,remi-php56 install -y php-xml
```

pearのインストールもバージョンがあってないとちゃんと動かない。（当たり前か）

```
[vagrant@localhost ~]$ sudo yum update --enablerepo=remi-php56 php-pear
```

# ライブラリのインストール
```
[vagrant@localhost ~]$ sudo pear install channel://pear.php.net/Image_Barcode2-0.2.3
```

# 突貫だけど整った
使い勝手とかスマートさとかそんなものはどこにもないけどとりあえず整った。

```
equire_once('Image/Barcode2.php');
```

この行が動く環境ができた....

ワクワク

ポチー

<img width="245" alt="スクリーンショット 2017-02-09 17.37.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/147005/95dbd036-7d9b-f0fa-e77f-dcf3c88d38df.png">

で、できたー（一応加工してます）


# おわりに
実際に手を動かしながら記事を書いてみたけど、なかなかひどい。
とりあえず疑わしいものを全部やって確かめる方式で進めてきたので、書いてないこともいっぱいある。
内容は後々追加、修正していきます。すみませんでした。

全ての情報発信しているエンジニアに感謝

## 追記
Box化からの復元もやってみた
[Vagrant+VirtualBoxで構築した仮想マシンをBox化して復元する](http://qiita.com/ss_watanabe/items/d15f890af58fa16447f6)
SimpleFormでの入力項目のデフォルト値設定方法

SimpleFormを使っていて、入力項目のデフォルト値を設定したい時がありますが、「あれ？チェックボックスのデフォルトってどうやって設定するんだっけ？」とか毎回調べたりしてます。

毎回調べるのも面倒なので、まとめておきます。


バージョン: simple_form (3.3.1)


#テキストボックスの場合
```
f.input :field_name, as: :text, input_html: { value: 'デフォルト値' }
```

#テキストエリアの場合
テキストボックスの場合と同じですね。

```
f.input :field_name, as: :string, input_html: { value: 'デフォルト値' }
```

#セレクトボックスの場合
`青：blue`を選択した状態にします。

```
f.input :field_name, as: :select, collection: [ ['赤', 'red'],[ '青', 'blue'], [ '黃', 'yellow'] ],
    , selected: 'blue'
```

#ラジオボタンの場合
`青：blue`を選択した状態にします。

```
f.input :field_name, as: :radio_buttons, collection: [ ['赤', 'red'],[ '青', 'blue'], [ '黃', 'yellow'] ],
    , checked: 'blue'
```

#チェックボックスの場合
ラジオボタンの場合と同じですね。
`青：blue`を選択した状態にします。
複数選択した状態にしたい場合は、配列にしておけば良いです。

```
f.input :field_name, as: :check_boxes, collection: [ ['赤', 'red'],[ '青', 'blue'], [ '黃', 'yellow'] ],
    , checked: 'blue'
```
The Basic - Constants and Variables


## 参考
The Swift Programming Language 3.0.1
The Basic - Constants and Variables

## 定数と変数
Swift では値を格納する際 *定数(Constants)* か *変数(Variables)* を使う。

定数は、一度格納した値は変更できず、変数は何度でも変更できる。
プログラムを通して値の変更が無いことがわかっている場合は出来るだけ定数を使う。

## 定数・変数の命名規則
Swiftでは定数・変数名に記号、絵文字、全角文字が使えるが一般的に言って面倒の原因になるようなので、半角英数字を使う。
その上で自分流の規則は

* 最初の一文字目は英小文字
* 二文字目以降には半角数字が使える
* キャメルケースで記述する

## 宣言
定数・変数は利用する前に宣言しておく必要がある。それぞれにキーワードがあり、定数は *let* 変数は *var* で宣言する

```
// 定数の宣言
let sampleConstant = 1

// 変数の宣言
var sampleVariable = 2
```

カンマ区切りにすることで複数を1行で同時に宣言できる

```
let sampleA = 1, sampleB = 2
var sampleC = 3, sampleD = 4
```

## 型
Swift では値に *型(types)* の概念がある。
定数・変数はそれぞれが型を持ち、その型にあてはまる値しか格納できない。

### 型簡易一覧
Swift で使える型の簡易一覧。このほかにもあるらしい。

|型名 | 内容 |
|:---|:---|
|Int |整数、1, 2, 3, 10, 100, -1, -2, -100 など |
|Double |小数点、1.0, 3.14, -1.0, -3.14 など |
|String |文字列、" "でくくる。"yes", "hello"など |
|Bool |真偽、true もしくは false |

### 型推測
定数・変数を宣言する際にリテラル値をあてておくと、その値種類から自動的に型を推測して決めてくれる。

```
// sampleVariable の値が 1 であることから、自動的に型は Int となり、小数点や文字列は受け入れなくなる
var sampleVariable = 1
```

### 型の指定
型を明示的に指定したい場合は、定数・変数宣言時に型名を明示する。

```
let stringConstant: String = "abc"
```

### 型を指定しつつ複数の定数・変数を宣言する
同じ型ならば、定数・変数名をカンマで区切って一度に宣言できる。

```
var varA, varB, varC: String
```
RECRUIT Technologies NIGHT vol.3のセッション内容

[RECRUIT Technologies NIGHT vol.3](https://atnd.org/events/85028)に参加した際のセッションの内容を記録。

###イベント概要
---
1. CSPの代表的ディレクティブや、実際に収集されるレポートなどについての解説
2. 近年のWebブラウザに搭載されている技術を、その脆弱性とともに紹介

###目的
---
・webのセキュリティ技術の勉強会だっため、知らない技術の情報を得るため
・業務上などでも何か参考になる情報があると期待して

###CSPによる防御とリアルワールドレポート収集（Jxck氏）

登壇時のスライド：https://speakerdeck.com/jxck/csp-and-real-world-reporting

---
####CSP（Content Security Policy）とは？
セキュリティの観点から、コンテンツに対して許可することをポリシー定義することでセキュリティを向上することができる
・ クロスサイトスクリプティング (XSS)を軽減
　→インラインで埋め込まれたjavascriptを実行不可にすることが可能
　→iframeを埋め込み不可にすることが可能
　→mixed contentを不許可にすることが可能
・ パケット盗聴を軽減
　→あらゆるコンテンツのドメインを設定可能
　→全てのコンテンツをhttps通信をするように指定することが可能
･レポートを受け取ることができる（report-uri.io）

etc

####適用方法
・httpsヘッダにContent-Security-Policyを返すように記述する
・metaタグに記述する

####レポート
・report-onlyを指定することで、ポリシーを適用したままブロックせずにレポートを受け取ることが可能
・CSPポリシー違反が発生した場合、ブロックすることができ、またレポートを受け取ることが可能

※レポートは、どのポリシー違反が発生したのかは確認できるが、その発生理由は分からない
　攻撃なのかそうでないのか、ユーザーがどういう状態になったかなどは分からない

####ブログで検証した結果（レポートを収集し確認）
ブログ
　・静的サイトジェネレータを使用した静的なサイトでinputタグは使用していないため、xssは起きない想定

設定したポリシー
　・コンテンツのドメインを制限
　・アナリティクス、youtubeを許可
　・アンセーフインラインを指定していない（インラインスクリプトを全てブロック）

・Firefoxの「view-source:」をユーザーが使用する度にレポートが送信された
・テキスト、マークダウン、xmlも同様にレポートが送信された
　→ソースをhtmlに成型してブラウザに表示させる。そのhtmlにインラインスタイルが適用されるため
・何かしらの理由でabout:blankになった際にレポートが送信された
・ms-browser-extension（よくわからないがレポートが送信された）
･jQueryを埋め込もうとしてレポートが送信された

####総括
・レポートを確認しても何が起こっているのかよく分からない
・ポリシー違反が起きているということは分かるが、そもそも防げているのか分からない
・ブラウザをアレンジして使用いている人たちが不自由になっているだけではないのか
・サイトによって、xssを防ぐことに重きを置くのか、ユーザービリティーをとるのか考えるべき

###脆弱性発見者が注目する近年のWeb技術（西村 宗晃 氏）

登壇時のスライド：https://speakerdeck.com/nishimunea/cui-ruo-xing-fa-jian-zhe-kazhu-mu-surujin-nian-falsewebji-shu

---
脆弱性がいっぱい見つかるであろう技術を紹介
1. Server Push（multipart/x-mixed-replace）
2. Http/2
3. FlyWeb

####multipart/x-mixed-replaceに注目している理由
・セキュリティヘッダをよく無視するから
　例1. CSPでインラインスクリプトを無視するポリシーを定義しても無視する
　　　chrome、safariではポリシーに従うが、Firefoxは無視する（まだ直っていない脆弱性）

　例2. リファラーポリシーヘッダでリファラー送出を禁止にするも、リファラーが送られてしまう

新しいヘッダが登場する度に楽しめる

####HTTP/2はコネクションの管理が大変
1. 同じIPアドレス、同じ証明書のCN/SANが含まれているホストの通信であれば、HTTP/2のコネクションを共有してよい
例）google.comのサイトにアクセスして証明書を確認すると関連サイトのドメインが含まれており、その含まれているドメインのサイトであればコネクションを再利用して良い

2. 同じリソースを提供する代替サーバの使用をクライアントに提案する
例）～～.ukサーバーに繋いた際に、日本国内内にも同じサービスを提供しているサーバーがあるので、そのサーバーに接続してと提案する（alt-svc headerがクライアントに提案する）

　同じ証明書だからといって、同じ権利者とは限らない

####FlyWeb
・Mozillaが実施しているWebとデバイスの連携プロジェクトで、webコンテンツとそれにアクセスした人の近くにあるデバイスが連動する
・まだ、実験段階でFirefox Nightlyを使用しないと試すことができない

仕組みは、mDNSとbonjourを組み合わせて実装されている
1. 最初に、PCでサーバーに接続するとjavascriptが落ちてくる
2. Firefox上でmDNSサーバーとwebサーバーが起動する
3. 同じローカルネットワーク内のデバイスがFirefoxに接続することができる
4. webソケットで通信ができる

###考察
---
知らなかった技術や、既存の技術に様々な脆弱性が潜んでいることを知ることができた。
最新の技術をキャッチアップしていく必要性や、脆弱性についての知識の必要性を改めて実感できるイベントだった。
R6 クラスでのよくあるエラー

#R6 OOPライブラリ

Rでオブジェクト指向をするのに、他のOOP言語から来た方が一番とっつきやすいのが最新のR6ライブラリだと思います。（R6も慣れが必要だが、それ以前はもっとすごい）
以下など解説があります。
[R6パッケージの紹介―機能と実装](http://www.slideshare.net/__nakamichi__/r6-upload)

## はまりポイント１ Error: attempt to apply non-function

いろいろ使ってリファクタリングをしているうちに、奇妙なエラーに出くわしました。忘れてしまいそうなので、備忘録的に記しておきます。

```R
require(R6)

classA <- R6Class(
    classname = "classA",
    public = list(
        a = 10,
        f1 = function(x) { x + self$a },
        f2 = function(x) { x + self$b },
        f3 = function(x) { x + self$fp1(x) }
    ),
    private = list(
        b = 100,
        fp1 = function(x) { x+1 }
    )
)
```

このクラスでf3メソッドを呼ぶと、以下のように、関数でないものをコールしているぞと怒られます。

```R
> A$f3(2)
Error in A$f3(2) : attempt to apply non-function
```
ちゃんとR6の仕様を読んでいればわかるのですが、問題はselfという自オブジェクトの識別子はプライベートメンバには使用できず、privateという識別子を使う必要があるのです。

そもそもプライベートメンバにアクセスした場合R6はどのような挙動をしめすのでしょうか？

```R
> A$a
[1] 10
> A$f1(1)
[1] 11
> A$b
NULL
> A$fp1(1)
Error: attempt to apply non-function
```

オブジェクトを外部から呼び出した場合、プライベートプロパティはNULLを返し、メソッドは上記のエラーを吐くようです。ちなみにf2を呼ぶと 数値とNULLの足し算になるため以下のような結果になります。

```R
> A$f2(2)
numeric(0)
```

正しくは、self を privateに直せばOKでした。

## はまりポイント２   All elements of public, private, and active must be named.

こんなエラーにも遭遇しました。
慣れた人はこんなバカなことはしないと思いますが、以下のようなクラス定義で出ます。

```R
require(R6)

classA <- R6Class(
    classname = "classA",
    public = list(
        a <- 10,
        f1 <- function(x) { x + self$a }
    )
)
```

関数を f <- function()というのに慣れていると、ついついメソッドとしてそのままコピペしたりして、このようなエラーを招きます。

```R
Error in R6Class(classname = "classA", public = list(a <- 10, f1 <- function(x) { : 
  All elements of public, private, and active must be named.
```

メソッド定義はlistのメンバとして定義するので、listの名前付き要素指定のために <- ではなく = が必要です。

## はまりポイント３ cannot add bindings to a locked environment

もう一つ、もっと簡単なものですが、privateメンバ変数がらみで、このようなエラーが出ます。

```R
require(R6)

classA <- R6Class(
    classname = "classA",
    public = list(
        a = 10,
        f1 = function(x) { self$b <- x }
    ),
    private = list(
        b = 1
    )
)
```

```R
> A$f1(1)
Error in self$b <- 2 : cannot add bindings to a locked environment
```
locked environmentというのがよくわかりませんでしたが、R6のクラスは基本的には定義の変更がロックされた状態がunlockすると動的にメンバーの追加、削除ができるようです。privateメンバへのアクセス制御もこの仕組みが用いられているのかわかりませんが、このようなエラーはきっちりアクセス制御が効いている証拠ですね。
でも、やっぱりわかりにくい（泣）

ちゃんと読んでいればわかるものを、ついついはまってしまいました。
Amazon Cloud Drive をCentOS7 で使う

# 事の始まりと概要
[Amazon Cloud Drive Unlimited](https://www.amazon.co.jp/clouddrive/home)（以下ACD）という容量無制限・年間＄59.95　という超便利なサービスが、
[Foltia Anime Locker](https://foltia.com/ANILOC/support/releasenote/pressrelease20160721.html)と連携できるという話を聞いてから早半年。いい加減に導入しようと思いたち、
ついでにOwncloudなどの他のデータのバックアップもACDに取れないかと格闘したという履歴を残しておこうかと思った次第。

今回は検証環境での実験結果を残すだけにします。できたらまたどこかに公開でもしようかと。


# 構築したいもの
- CentOS 7 
    - acd_cli とこれに必要なソフトウェアの導入
    - 適当なところにマウント
- Foltia Anime Lokcer
    - unlimited movie works の構築

今回のメインは上。Foltia Anime Locker関連は省略。


# acd_cli インストール
## 必要なパッケージ
python関連のパッケージは空っぽなので、ゼロから入れることになります

参考サイト : http://christina04.hatenablog.com/entry/2016/01/27/015641

- epel-release
- python34
- python34-pip
- python34-setuptools
- python34-requests
- git
- fuse-python

以上をyum で入れます。
重要なのはfuse-python だと思います（おそらく）

```bash
$ sudo yum install epel-release
$ sudo yum install python34 python34-pip python34-setuptools python34-requests git fuse-python
$ sudo easy_install-3.4 pip
```

## acd_cli インストール
至ってシンプルなpip install 

```bash
$ sudo pip3 install --upgrade git+https://github.com/yadayada/acd_cli.git
```

# acd_cli 設定
## 初期設定
どういう動作をしているのかを理解していないので、なんとも言えないですが、
他の人柱様を参考にして

```bash
$ acd_cli -v init
```
画面の指示に従い、Webブラウザにてacd_cliのOAuth認証に必要なデータを取得し、`~/.cache/acd_cli/oauth_data`に取得データを置くなどの処理を行います。


設定完了後、同期を取ります

```bash
$ acdcli sync
```

## マウント
予め、マウントする先のディレクトリを作成しておき、マウントをしていきます

```bash
$ mkdir ~/acd_mount_point
$ acdcli mount ~/acd_mount_point 

$ df -h 
Filesystem               Size  Used Avail Use% Mounted on
（中略）
ACDFuse                  100T   0M  100T   0% /home/acd/acd_mount_point

```

あとは、通常と同じようにファイル作成・操作をすると、（ちょっと時間がかかりますが）ACDにファイルがしっかりとできています。これはすごい


# 詰まった点
- python3 をvirtualenv を使わずに共存させつつpipをする方法（結局よくわかってない）
- `acdcli mount` 実行時にマウントされてない原因が`fuse`と`fuse-python`がインストールされていない

```bash
$ acdcli mount ~/acd_mount_point 
(略)
    raise EnvironmentError('Unable to find libfuse')
OSError: Unable to find libfuse
```
Mosesの使い方

## 参考
[統計的機械学習システムMosesで遊ぶ](http://y-uti.hatenablog.jp/entry/2014/10/25/214843)

## 対話コーパスの準備
[田中コーパス](http://www.edrdg.org/wiki/index.php/Tanaka_Corpus)をダウンロードする

```
mkdir ~/workspace/smt/corpus
cd ~/workspace/smt/corpus
wget ftp://ftp.monash.edu.au/pub/nihongo/examples.utf.gz
```

ダウンロードしたgzファイルを解凍してtxtファイルに保存

```
gzip -dc examples.utf.gz > examples.txt
```

行頭に`A:`がある行は、日英対訳コーパスである。
`B:`行は表記ゆれなど、追加情報が記載されている。

```tanaka_corpus.txt
A: ムーリエルは２０歳になりました。     Muiriel is 20 now.#ID=1282_4707
B: は 二十歳(はたち){２０歳} になる[01]{になりました}
A: すぐに戻ります。     I will be back soon.#ID=1284_4709
B: 直ぐに{すぐに} 戻る{戻ります}
...
```

このファイルから必要な部分を切り出す

```
gzip -dc examples.utf.gz | grep ^A: | cut -f1 | sed 's/^A: //' | mecab -Owakati >tanaka.ja
gzip -dc examples.utf.gz | grep ^A: | cut -f2 | sed 's/#.*$//' >tanaka.en
```

|コマンド|説明|
|---|---|
|cut|タブ区切りになっているのでフィールド(列)ごとに分割できる|
|mecab|日本語文を単語に分割|
|grep ^A:|"A:"を含む行を検索し、その表の先頭を示す(^)|
|sed 's/^A: //'|行頭の"A:"を削除|
|sed 's/#.*$//'|"#"とその後に続く文字を削除|

## 言語モデルの学習
日本語側のファイルから言語モデルを学習する
言語モデル：ある単語の列を与えると、日本語としての流暢さによって得点をつけてくれる関数のようなもの
機械翻訳では言語モデルを利用することで翻訳候補の中から自然なものが選ばれるようにする

Mosesに同梱されている[KenLM](https://kheafield.com/code/kenlm/)を用いて言語モデルを学習する

KenLMでの言語モデル学習を行う

```
~/workspace/mosesdecorder/bin/lmplz -o 5 -S 80% -T /tmp < tanaka.ja >tanaka.ja.arpa
```

## 翻訳モデルの学習
日英の対訳コーパスから、翻訳モデルを学習する
翻訳モデル：英語と日本語の単語列を与えると、対訳の適切さによって得点をつけてくれる関数のようなもの

```
cd ~/workspace/smt
~/workspace/mosesdecorder/scripts/training/train-model.perl \
    --root-dir . \
    --corpus corpus/tanaka \
    --f en \
    --e ja \
    --lm 0:5:$HOME/smt/corpus/tanaka.ja.arpa \
    --external-bin-dir ./mosesdecoder/tools
```

|コマンド|説明|
|---|---|
|--corpus, --f, --e|--corpusの値に--fと--eの拡張子を追加したものを対訳コーパスの各言語側のファイルとして読み込む --fが翻訳元、--eが翻訳先|
|--lm|言語モデルの指定|
|--external-bin-dir|Moses以外のプログラムの実行ファイルが存在するパスを指定|

最終的な結果はmodel/phrase-table.gz

## 英和翻訳を試す
model/moses.iniの設定ファイルを編集
利用する言語モデルの種類をSRILM → KenLMに修正

```
SRILM name=LM0 factor=0 path=/home/y-uti/smt/corpus/tanaka.ja.arpa order=5
→
KENLM name=LM0 factor=0 path=/home/y-uti/smt/corpus/tanaka.ja.arpa order=5
```

プログラムを実行
-fオプションに設定ファイルを指定する
言語モデル、翻訳モデルの指定などは設定ファイルに書かれている

```
~/workspace/mosesdecoder/bin/moses -f model/moses.ini
```

言語モデル、翻訳モデルが読み込まれた後、入力モードになる
英語を入力すると翻訳された日本語が出力される
ヘッダ付きTSVの列・行をソート

`select * from tbl1`とかでテーブルの中身を抜いて期待結果ファイルとdiffを取りたいときに

```sort_tsv.rb
require 'csv'

infile  = ARGV[0]
outfile = ARGV[1]

incsv = CSV.read(infile, col_sep: "\t", headers: true)
cols = incsv.headers.sort

outdata = []
incsv.each do |inrow|
  outrow = []
  cols.each do |col|
    outrow << inrow[col]
  end
  outdata << outrow
end

CSV.open(outfile, 'w', col_sep: "\t", headers: cols, write_headers: true) do |outcsv|
  outdata.sort.each do |outrow|
    outcsv << outrow
  end
end
```

```shell-session
$ cat result.tsv
col2    col3    col1    col4    time
col2val6        col3val6        null    col4val6        1483455599
col2val2        col3val2        col1val2        null    1483282800
col2val3        col3val3        col1val3        null    1483282800
col2val4        col3val4        col1val4        null    1483369200
col2val5        col3val5        col1val5        null    1483369200
col2val6        col3val6        col1val6        col4val6        1483455600
col2val7        col3val7        col1val7        col4val7        1483455600
null    col3val8        col1val8        col4val8        1483542000
null    col3val9        col1val9        col4val9        1483542000
col2val1        col3val1        col1val1        null    1483282800
col2val6        col3val6        col1val6        col4val6        1483455599
$ ruby sort_tsv.rb result.tsv out.tsv
$ cat out.tsv
col1    col2    col3    col4    time
col1val1        col2val1        col3val1        null    1483282800
col1val2        col2val2        col3val2        null    1483282800
col1val3        col2val3        col3val3        null    1483282800
col1val4        col2val4        col3val4        null    1483369200
col1val5        col2val5        col3val5        null    1483369200
col1val6        col2val6        col3val6        col4val6        1483455599
col1val6        col2val6        col3val6        col4val6        1483455600
col1val7        col2val7        col3val7        col4val7        1483455600
col1val8        null    col3val8        col4val8        1483542000
col1val9        null    col3val9        col4val9        1483542000
null    col2val6        col3val6        col4val6        1483455599
```

もっと短く書けないかな
sphinx -> pdf で 「file://hogehoge」にハイパーリンク貼る方法

# `sphinx` のファイルに追記
- 場所：`Lib\site-packages\Sphinx-x.x.x-pyx.x.egg\sphinx\writers`
- ファイル名：`latex.py`
- 変更箇所：`visit_reference` メソッド（1729行目周辺）

# 以下を追記
```py
# python2.7.13
    elif uri.startswith('file:'):
        self.body.append('\\href{%s}{' % self.encode_uri(uri))
        self.context.append('}')
```
- 参考：[hyperlink to an external git repository in Sphinx PDF documentation](https://stackoverflow.com/questions/18560042/hyperlink-to-an-external-git-repository-in-sphinx-pdf-documentation)

# 課題：ファイルパスに日本語が入ると駄目・・・
Global IPを監視してRoute53を更新する

# 背景

自社開発サーバを建てたのは良かったのですが、実はOfficeのGlobal IPが固定されていないことがわかりました。これではやや面倒くさいのと、ISPさんに電話して固定IPの契約をすれば良い話なのですが、インフラのソフトウェア解決の文化を啓蒙したい想いもあって、とりいそぎRoute53を自動更新するShell ScriptをCronに登録しておこうというものです。

# こんなShell Scriptを書いたのです

仕組みとしてはGlobal IPを`gip.txt`というテキストファイルに記録しておいて、今のGlobal IPと比較して更新があればaws-cliでRoute53のRecordの更新をするというものです。

```bash:ip_watch.sh
#!/usr/bin/env bash

gip=`curl inet-ip.info`	# Global IPを取得
r53_hosted_id="********" # AWS Route53のHosted ID
r53_target_domain="my.host.domain.com" # 更新するドメイン(今回はA record)
gipfile="/path/to/gip.txt" # gip.txt出力先
outfile="/path/to/update.json" # JSON出力先
env_gip=`cat $gipfile` # 旧Global IP

# 以前環境変数に登録していた旧Global IPと現Global IPを比較
if [ "${gip}" != "${env_gip}" ]; then
	# aws-cli route53で渡すJSONファイル(update.json)を作成
	json="{\"Comment\" : \"\", \"Changes\" : [{\"Action\" : \"UPSERT\", \"ResourceRecordSet\" : {\"Name\" : \"${r53_target_domain}\", \"Type\" : \"A\", \"TTL\" : 300, \"ResourceRecords\" : [{\"Value\": \"${gip}\"}]}}]}"
	echo $json > $outfile
	# aws-cliでroute53のrecord set更新
	aws route53 change-resource-record-sets --hosted-zone-id $r53_hosted_id --change-batch file://$outfile
	# Slackにお知らせ。Incoming Webhook URLをご用意ください。
	curl -X POST --data-urlencode "payload={
		\"channel\": \"#infra\",
		\"username\": \"ip監視さん\",
		\"text\": \"updating global IP ${env_gip} -> ${gip}!!\", 
		\"icon_emoji\": \":elevennines:\"
	}" https://hooks.slack.com/services/******/*******/***************
	echo "${gip}" > $gipfile # Global IPをセット
fi
```

# 実行結果

コマンドライン上では以下の様になります。

```
[tokifuji@office ip_watch]$ ./ip_watch.sh 
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    15  100    15    0     0     36      0 --:--:-- --:--:-- --:--:--    36
{
    "ChangeInfo": {
        "Status": "PENDING", 
        "Comment": "", 
        "SubmittedAt": "2017-01-30T12:22:21.799Z", 
        "Id": "/change/***********"
    }
}
[tokifuji@office ip_watch]$
```

その後のステータス確認は以下です。Statusが`INSYNC`になったらOKです。

```
[tokifuji@office ip_watch]$ aws route53 get-change --id /change/***********
{
    "ChangeInfo": {
        "Status": "INSYNC", 
        "SubmittedAt": "2017-01-30T12:22:21.799Z", 
        "Id": "/change/***********"
    }
}
```

Slackにはこんなメッセージが飛びます。

![image](https://qiita-image-store.s3.amazonaws.com/0/38292/3df6f843-a5f3-0d6a-1fc2-4873baa3a4a2.png)


# CRONTABに設定

自分は５分置きに設定してますが、お好みで…

```
[tokifuji@office ip_watch]$ crontab -l
*/5 * * * * /path/to/ip_watch.sh
```

これであなたも快適Route53ライフ(？？)をエンジョイしてください。それではまた:raised_hand:
JavaScriptでユークリッド色差計算

[Color difference（wikipedia）](https://en.wikipedia.org/wiki/Color_difference#Euclidean)で公開されているユークリッドの色差計算式をJavaScriptで書いてみました。

wikipediaで公開されている計算式は以下のとおりです。
> ![Euclidean](https://wikimedia.org/api/rest_v1/media/math/render/svg/f959802c3c7352dbe9ae96468fb188e93de69ef7)
（「[Color difference](https://en.wikipedia.org/wiki/Color_difference#Euclidean)」（5 Feb 2017, at 02:30. UTC）『ウィキペディア』より引用）

この計算式は知らない記号もなくシンプルなので、そのまま書くことができます。

```js:euclidean
function euclidean(r1,g1,b1, r2,g2,b2) {
	return Math.sqrt(
			Math.pow(r2 - r1, 2) + 
			Math.pow(g2 - g1, 2) +
			Math.pow(b2 - b1, 2)
			);
}
```

## 関連リンク
- [色差アルゴリズムの違いをビジュアル化してみた](98c218bc5616eaaba9a0)
- [JavaScriptでCIEDE2000色差計算](860f061a2ab7a4f2d06f)
- [JavaScriptでCIE94色差計算](3488df50b7082d4fcffb)
- [JavaScriptでCIE76色差計算](cda9b95395468ee7e0f8)
- [JavaScriptでHSVからRGBに変換](633d1bf6baf008e82847)
- [JavaScriptでRGBからLab色空間への変換](09caabe6bec46a2a0858)
Python初心者が、PyPIに自作のパッケージを登録しようとしてハマったこと　２０１７年２月版

　先日、初めてPyPIに自作のパッケージを登録したときに苦労した内容を紹介します。
　ハマった点を先に挙げておくと、twineを使う必要がある、パッケージ名は適当ではだめ、です。


　当初、PyPIにパッケージを登録する方法を検索して調べたところ、多くのブログや記事で以下の手順が紹介されていました。


| no | work | 参考 url/command |
|:-:|:-:|:-:|
| 1 | ソースコード作成 |   |
| 2 | フォルダ構成を整える | [Python: 自作パッケージにデータファイルを含める](http://blog.amedama.jp/entry/2015/12/26/012332) |
| 3 | setup.pyを作成 | [PyPIデビューしたい人の為のPyPI登録の手順](http://qiita.com/kinpira/items/0a4e7c78fc5dd28bd695) |
| 4 | ディストリビューション構築 | >>python setup.py sdist |
| 5 | テストインストール | >>python setup.py install |
|   |   |
| 6 | test用のPyPIにアカウントを作成 | [登録先](https://testpypi.python.org/pypi?%3Aaction=register_form) |
| 7 | .pypircを作成 | [PyPIにパッケージ登録する](http://qiita.com/edvakf@github/items/d82cd7ab77ea2b88506c)  |
| 8 | パッケージ名を登録 | >>python setup.py register -r pypitest |
| 9 | パッケージをアップロード | >>python setup.py sdist upload -r pypitest |
|   |   |
| 10 | 本番用のPyPIにアカウントを作成  | [登録先](https://pypi.python.org/pypi?%3Aaction=register_form) |
| 11 | パッケージ名を登録 | >>twine register dist/* |
| 12 | パッケージをアップロード | >>twine upload dist/* |
|   |   |
| 13 | テストインストール | >>pip install パッケージ名 |

***
　twine、test用PyPi、「.pypirc」関連を補足しておきます。

・test用PyPiと本番用PyPiは、別々にアカウントを作成する必要があります。
・「.pypirc」は twineを使う場合は必要です。
・Windowsの場合、「.pypirc」を置く場所は環境変数で指定した場所(HOMEPATH=\Users\foo なら c:\Users\foo\\.pypirc)
・「.pypirc」でserverを定義している場合、python setup.py -r のurl指定では、「.pypirc」で定義したserver名を書く

```python:sample
file:.pypirc
        [distutils]
        index-servers =
            pypi
            pypitest

        [pypi]
        repository: https://pypi.python.org/pypi
        username: worst
        password: Salary_burglar

        [pypitest]
        repository: https://testpypi.python.org/pypi
        username: learner
        password: Being_late

# server定義がpypitestなら以下のように指定        

>>python setup.py register -r pypitest
>>python setup.py sdist upload -r pypitest
```

***
##ハマったところ　その１
　test用のPyPIに登録するところまでは、すんなりいきました。Python歴が長い人ならば５分とかからないでしょう。
PyPIの本番サーバーにパッケージ名を登録するところで、下記のエラーが出て止まりました。

**Server response (410): This API is no longer supported, instead simply upload the file.**

これは、python setup.py register ではなく、twine を使用するか、以下のurlで、直接PKG-INFOを登録すればいいそうです。

https://pypi.python.org/pypi?%3Aaction=submit_form

```python:sample
# 古い方法
python setup.py register
python setup.py sdist upload

# 新しい方法
pip install twine # 必要ならインストール
twine register dist/*
twine upload dist/*
```

この方法が推奨（no longer supportedだから今は必須）になったのが２０１４年ごろ？で、２０１４年までの記事には古いやり方で紹介されています。

そしてtest用PyPiでは古い方法で登録できてしまうのに、本番用のPyPiでは、新しい方法でないと登録できないのが、一番ハマりやすいところですね orz

***
##ハマったところ　その２
　こちらは単純です。
登録しようとしていたパッケージ名は、すでに他の方が使用されていました。
　レスポンスで、指定できないとあるのを、すでに使用されていますだったらすぐに気がついたんですが･･･とは後の祭りです。

使用済みの名前でWEBでPKG-INFOを登録しようとすると、以下のresponseが返ってきます。

**Forbidden
You are not allowed to store 'picker' package information**


twineを使用すると、以下のメッセージが出ます。

**HTTPError: 403 Client Error: You are not allowed to edit 'picker' package information for url: https://pypi.python.org/pypi**

バッティングの確認は、PyPiのサイトで検索して確認するか、

https://pypi.python.org/pypi

「pip search 使用したい名前」で検索しましょう。

どれもとられていたら、「pip search * > list.txt」で全リストを収得してにらめっこしてください。
BOAL - Beab Old Account List + BBEOS Code

Misuse prohibited.
Please avoid quoting.
This is my memorandum.

Hell Miner : BBS - AECS (High E)
└YouTube Subscribers : 34

Nest Xcet : Nood (SS) - Brabs (A)
└YouTube Subscribers : 4

Free Osuke : (BBEOS does not exist.)
└YouTube Subscribers : Null

Avel Xevaltion : (BBEOS does not exist.)
└YouTube Subscribers : Null

Flan Elevalion : CES - Elevalion (E & AO)
└YouTube Subscribers : 4

Elen Kearcdovar : Nood - Taix Code (AO)
└YouTube Subscribers : Null

Ubuntu Osuke : Linux - Ubuntu 15.10 (High E)
└YouTube Subscribers : Null

Kail Digraint : iOSB - Digraint (A)
└YouTube Subscribers : 4

Qalt Xeap : QX - Elebrine (E & AOS)
└YouTube Subscribers : 82

Walter Adel : WA - Xelabic (E & AOS)
└YouTube Subscribers : 25

Writer Myagsterang : Linux - Elebrain (NB)
└YouTube Subscribers : 18

YouTube Total Subscribers : 171
メモ

・clkinから抵抗をプラスに、コンデンサをマイナスにつなぐことでrc発振回路
・470kΩ　1000pfあたりで約800hz？
・発光ダイオードは抵抗を通して接続
・mclrは抵抗を通してプラスに接続
・pic vdd(+) vss(-)には電源と別にセラミックコンデンサも接続
・goto文につく$は自分自身のアドレスを指す。

goto $+2
A
B

はBにジャンプするということである。
・special function register(SFR)のgpioやporta,portb,trisio,trisa,trisbなどを書き換えることでピンから入出力をすることができる。
Googleフォームの自動返信メールのサンプルスクリプト

Googleフォームの自動返信スクリプトのサンプルです。

```js
function sendMailFromForm() {
    var title = "＊＊＊＊＊＊";    //メールタイトル
    var admin_name = "＊＊＊＊＊＊";　//送信者名
    //------------------------------------------------------------
    // 設定エリアここから
    //------------------------------------------------------------
    // 件名、本文、フッター
    var subject = "【" + title + "】控えメール";
    // メール送信先
    var admin = "";    // 管理者メールアドレス（必須）
    var cc    = "";    // Ccに入れるメールアドレス
    var bcc   = ""; // Bccに入れるメールアドレス:
    var reply = ""; // Reply-Toに入れるメールアドレス:
    var to    = "";    // To: （入力者のアドレスが自動で入ります）

    //------------------------------------------------------------
    // 設定エリアここまで
    //------------------------------------------------------------

    try{
        // スプレッドシートの操作
        var sh   = SpreadsheetApp.getActiveSheet();
        var rows = sh.getLastRow();
        var cols = sh.getLastColumn();
        var rg   = sh.getDataRange();

        var dataList = {};

        // メール件名・本文作成と送信先メールアドレス取得
        for (var j = 1; j <= cols; j++ ) {
            var col_name  = rg.getCell(1, j).getValue();    // カラム名
            var col_value = rg.getCell(rows, j).getValue(); // 入力値
            dataList[col_name] = col_value;
        }
        to = dataList["メールアドレス"];
        var sei = dataList["お名前（姓）"];

        var body
        = sei + "さん\n"

    body+= "\n"
        + "ここに本文を入力します。\n"
        + "ここに本文を入力します。\n"
        + "ここに本文を入力します。\n"
        + "===================================\n"
        + admin_name + "\n"
        + "\n"
        + "";

        // 送信先オプション
        var options = {};
        if ( cc )    options.cc      = cc;
        if ( bcc )   options.bcc     = bcc;
        if ( reply ) options.replyTo = reply;

        // メール送信
        if ( to ) {
            MailApp.sendEmail(to, subject, body, options);
        }else{
            MailApp.sendEmail(admin, "【失敗】Googleフォームにメールアドレスが指定されていません", body);
        }
    }catch(e){
        MailApp.sendEmail(admin, "【失敗】Googleフォームからメール送信中にエラーが発生", e.message);
    } 
}
```
Swift 3でUserDefaultsに保存したりしたオブジェクトをデシリアライズする

オブジェクトをUserDefaultsに保存したくなりました。

Swiftでは、UserDefaultsに保存できるオブジェクトはプリミティブな幾つかのものに限られていますが、
それ以外のオブジェクトでも、`Data`に変換することでUserDefaultsに保存することができます。

これを実現するために、UserDefaultsにとっておきたいクラスでシリアライズとデシリアライズをサポートする必要があります。

Swift 3で使えそうな例を載せておきます。

## 注意

もし **複雑なデータを永続化しようとしている** なら [Realm](https://realm.io) を検討するべきだと思います。認証用の文字列とかなら https://github.com/kishikawakatsumi/KeychainAccess がよいです。

## コード

### Class

```swift:Swift
class Hoge: NSObject, NSCoding {
	var name = ""
	var hoge = ""
	var fuga = ""
}
```

### Deserialize

```swift:Swift
required init(coder aDecoder: NSCoder) {
	self.name = aDecoder.decodeObject(forKey: "name") as! String
	self.hoge = aDecoder.decodeObject(forKey: "hoge") as! String
	self.fuga = aDecoder.decodeObject(forKey: "fuga") as! String
}
```

### Serialize

```swift:Swift
func encode(with aCoder: NSCoder) {
	aCoder.encode(self.name, forKey: "name")
	aCoder.encode(self.hoge, forKey: "hoge")
	aCoder.encode(self.fuga, forKey: "fuga")
}
```

# 参考

* [SwiftでオブジェクトをNSUserDefaultsに保存する - xykのブログ](http://xyk.hatenablog.com/entry/2015/12/25/190237)
* [Search · required init?(coder aDecoder: NSCoder) decodeObject(forKey](https://github.com/search?l=Swift&q=required+init%3F%28coder+aDecoder%3A+NSCoder%29+decodeObject%28forKey&ref=searchresults&type=Code&utf8=✓)
* [Search · aCoder.encode(](https://github.com/search?l=Swift&q=aCoder.encode%28&ref=searchresults&type=Code&utf8=✓)
LinuxからPHPでSQLServerに接続－様子を見つつ

# あらすじ
昨年5月ごろ、CentOS7+PHP5.6/7.0で簡単な社内用webアプリを作成したが、そのときはfreeTDSを導入し、unixODBC、PDO_ODBCを用いてMS-SQLServerに接続した。
時は過ぎ2017年2月、別件でweb検索の折、php7.0/7.1でphp-sqlsrvがリリースされていることを知った。（気が付くの遅せえ）

#やってみた
さっそくphp-sqlsrvをインストールし、PDOでデータ取得してみた。
接続成功！しかし思ったようにデータが取得できない。日本語とか。
あと接続できるインスタンスとできないインスタンスがある。

#githubを見た
[リンク先はこちら](https://github.com/Microsoft/msphpsql/)
LimitationsとKnown Issuesを見ると、まだ実用段階ではないようだ。
しかしREADMEから本気度が伝わってくる。
今後はまめにチェックしていこうと思う。

#最後に
役に立たない記事ですみません。ただfreeTDSを使うしかなかった状況がついに変わりそうなので、思わず書いてしまいました。
C# 4Kディスプレイの解像度を取得する

# C# 4Kディスプレイの解像度を取得する

## ディスプレイの解像度を取得するプログラム

画面の解像度が[3840x2160]なのに[2560x1440]を取得する。

```CSharp:Form.cs
using System;
using System.Drawing;
using System.Windows.Forms;

namespace Disp4KComfirm
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        private void button1_Click(object sender, EventArgs e)
        {
            Rectangle rc = Screen.PrimaryScreen.Bounds;

            textBox1.Text = string.Format("W: {0} h: {1}", rc.Width, rc.Height);
        }
    }
}

```


## フォームを作成する前に呼び出すようにProgram.csを修正


```CSharp:Program.cs
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Disp4KComfirm
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            SetDpiAwareness();
            Application.Run(new Form1());
        }

        private enum ProcessDPIAwareness
        {
            ProcessDPIUnaware = 0,
            ProcessSystemDPIAware = 1,
            ProcessPerMonitorDPIAware = 2
        }

        [DllImport("shcore.dll")]
        private static extern int SetProcessDpiAwareness(ProcessDPIAwareness value);

        private static void SetDpiAwareness()
        {
            if (Environment.OSVersion.Version.Major >= 6)
            {
                SetProcessDpiAwareness(ProcessDPIAwareness.ProcessPerMonitorDPIAware);
            }
        }

    }
}

```

## 参考URL

Problems with screen resolution displaying on 4K
http://stackoverflow.com/questions/36089452/problems-with-screen-resolution-displaying-on-4k

ClickOnceアプリケーションの高DPI対応方法について
https://social.msdn.microsoft.com/Forums/vstudio/ja-JP/5051d15c-6e2a-4fc8-aa26-df0f466caf64/clickoncedpi?forum=vsgeneralja
Ruby | シングルトンクラスを作る

include するだけで OK 。

```ｒb
require 'singleton'
```

```rb
class A
  include Singleton
end
```


# 検証

## 通常のクラス

当たり前だが、インスタンス生成のたびにオブジェクトIDは変わる。

```rb
class B
end
```

```rb
puts B.new.object_id # 70357495108880
puts B.new.object_id # 70357495108820
puts B.new.object_id # 70357495108760
```

## シングルトンクラス

何度呼び出してもオブジェクトIDは一緒だ。
`new` ではなく特異メソッドの `instance` を呼ぶ。

```rb
puts A.instance.object_id # 70357495109120
puts A.instance.object_id # 70357495109120
puts A.instance.object_id # 70357495109120
```

## 信憑性

他クラスのインスタンスから、シングルトンクラスのインスタンスを呼び出しても、オブジェクトIDは変わらない。

```rb
class A
  include Singleton
end
```

```rb
class B
  def call_singleton_instance
    A.instance.object_id
  end
end
```

```rb
puts A.instance.object_id # 70180072059980
puts A.instance.object_id # 70180072059980
puts A.instance.object_id # 70180072059980

puts B.new.call_singleton_instance # 70180072059980
puts B.new.call_singleton_instance # 70180072059980
puts B.new.call_singleton_instance # 70180072059980
```

## initialize

initialize も一度しかおこなわれない。

```rb
class A
  include Singleton

  def initialize
    puts 'initialized'
  end
end
```

```rb
A.instance # initialized
A.instance
A.instance
```

### 引数

initialize に引数を取ることはできないっぽい。
「世界にひとつのインスタンスを作るのに、引数なんか要らないよね」って理解した。

```rb
class A
  include Singleton

  def initialize(argument)
  end
end
```

特に親切なメッセージは出してくれないっぽい。

```rb
A.instance 'argument' # `instance': wrong number of arguments (given 1, expected 0) (ArgumentError)

A.instance # `instance': wrong number of arguments (given 1, expected 0) (ArgumentError)
```

# 環境

- ruby 2.3.1

# 参考

- https://ruby-doc.org/stdlib-1.9.3/libdoc/singleton/rdoc/Singleton.html
- http://stackoverflow.com/questions/4217968/a-problem-about-singleton-in-ruby








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Google BigQueryのCSVロードでMissing close double quote (") character.


S3にCSVファイルが置かれたら、ファイルをBigQueryにアップロードするタスクを仕掛けていたら、ある日を境にこけ始めた。

```
$ bq load --skip_leading_rows=1 --replace --sync --project_id mypj ...[以下省略]
Upload complete.
Waiting on bqjob_r42fb5f95fa2e4847_0000015a213d6a98_1 ... (89s) Current status: DONE   

BigQuery error in load operation: Error processing job 'amimoto-dashboard:bqjob_r42fb5f95fa2e4847_0000015a213d6a98_1': Too many errors encountered.
Failure details:
- /gzip/subrange/file-00000000: Error detected while parsing row
starting at position: 250878765. Error: Missing close double quote
(") character.
```

`Missing close double quote`。なんでやねんと思って調査。

## 改行。

csvファイルの行数は`1,117,796`、pandasでロードしたらレコード数は`1,117,768`。。。??

で、あるカラムに改行を発見。

```
"foobarstring\n"
```

なるほど。


## `--allow_quoted_newlines`をつけて対応できるケースだった

```
$ bq load --skip_leading_rows=1 --allow_quoted_newlines --replace --sync --project_id mypj ...[以下省略]

Upload complete.
Waiting on bqjob_r1680e9a9697238aa_0000015a214b406d_1 ... (168s) Current status: DONE  
```

ちなみに改行が混入したのはAWSの請求データで、`user:Name`とされているカラムでした。リソースタグに`\n`とか入れたら請求のCSVに記述されて、どこかで何かがこけちゃうぞ！