OmniAICreator/Qiita-1.07M huggingface dataset:
PayPalペイメント スタンダードのボタンを編集する方法を教えてください。

お客さまのECサイトで使用しているのが、サードパーティのショッピングカートなのか、PayPal決済ボタンなのかによって、商品情報を編集する方法は異なります。

- サードパーティのショッピングカート
サードパーティのショッピングカートを使用している場合は、カートがすべてのボタンや外観などを管理しているので、カートのマニュアルをご覧ください。  

- 暗号化されていないボタン
HTMLを使って作成された、暗号化されていないPayPal決済ボタンを使用している場合は、お客さまのウェブサイトのコードを開くと、以下のような項目が表示されるはずです。
```
<input type="hidden" name="business" value="email@emaildomain.com">
<input type="hidden" name="item_name" value="my test item">
<input type="hidden" name="amount" value="1">
```
このタイプのボタンは、値を変更するだけで編集できます。たとえば、請求額を1ドルから5ドルに増額する場合は、amount変数の値を「1」から「5」に変更し、コードの変更内容を保存します。  
  
- ホスト型ボタン  
PayPalのホスト型ボタンを使用されている場合は、以下の例のようなコード行が表示されるはずです。
```
<input type="hidden" name="hosted_button_id" value="FQCFAJW5BR9T4">
```

**ホスト型ボタンを編集するには**

1. [ここ](https://www.paypal.com/)をクリックしてPayPalアカウントを開きます。
2. **[ツール]**をクリックします。
3. **[PayPal決済ボタン]**をクリックします。
4.**[保存したボタン]**を選択します。
5. ボタンの一覧から変更するボタンを選択し、**[アクション]**ドロップダウンメニューで**[ボタンの編集]**をクリックします。

注: ホスト型ボタンのドロップダウンメニューまたはテキストボックスを編集した場合は必ず、変更内容を保存した後に、変更したHTMLコードをお客さまのECサイトに貼り付けてください。新しく更新されたボタンのソースコードを使用して更新しないと、変更が本番サイトに反映されません。

PayPalではテクニカルサポートの部署がありますので、何かPayPal実装関連の質問や技術的な質問がありましたら、下記URLで記事を検索してみてください。
https://jp.paypal-techsupport.com/
上記URLの一番下の「お問い合わせ」リンクをクリックしてまたは下記URLをアクセスして質問を送信してください。
https://jp.paypal-techsupport.com/app/ask
【Interface】オブジェクト指向の「インターフェイス」をなんとなく理解してみる（PHP）

# はじめに
N88BASICを中学校のときに触りまくってしまったせいで、2X歳になった今年でも未だにすべてを[手続き型](http://tsumari.zapto.org/detail.php?id=79)で書いてしまう私が、
とうとう[オブジェクト指向](http://tsumari.zapto.org/detail.php?id=80)の勉強をはじめました。

その中で、「インターフェイス」というわけのわからないものに出会ったので、備忘録がてら書いてみたいと思います。
間違っていたらご指摘ください。



# そもそもインターフェイスとはなんぞや？
「インターフェース」か「インターフェイス」かわかりませんが、私はインターフェース派です。
しかし、教わった方がインターフェイスとおっしゃってたので、そっちが正しいのかな？と思っていたり。

で、何するやつかということを、すっっっっっっっごく噛み砕いて言うと、
**定義したメソッドを使うことができるよ！**
ってことだそうです。

……は？

そんな反応になりますよね。僕もそうです。

ようは、先にメソッド名を宣言しておいて、その中身をclassの中で定義していく……という風に使うんですって。
なんじゃそりゃ。
とりあえず、[詳しい解説みたい人はPHPのリファレンス](http://php.net/manual/ja/language.oop5.interfaces.php)へ。。。



# とりあえずやってみる
まあ、兎にも角にも、コードを書いてみなければわかりません。

処理の内容としては、
1. Hdmiというインターフェースにconnect（接続する）というメソッドを宣言しておきます。
2. Displayというクラスで、Hdmiインタフェースをimplements（実装）します。
3. connectメソッドの中身をDisplayクラスの中で定義します。
4. 実際にDisplayオブジェクトを作成し、connectメソッドを実行してみます。

```PHP
<?php

# インタフェースの定義
interface Hdmi{
    # connectメソッドの宣言
    public function connect();
}



# Displayクラスの定義
class Display implements Hdmi{
    
    # connectメソッドの定義
    public function connect(){
        echo '接続しました';
    }
    
}


# なんとなくHdmi型のオブジェクトを渡す関数で実行してみる
function hdmiConnect(Hdmi $obj){
    $obj->connect();
}


# 実際にインスタンスを作って実行してみる
$display = new Display();
hdmiConnect($display);
```

↓　実行結果

```
接続しました
```

こんな感じですね。
……あんまり意味がない……と思えがちですが、

例えば
`キメラclass`と言うものを創るときに、`獅子class`、`山羊class`、`毒蛇class`のそれぞれのメソッドを継承したい。
そしてそれぞれのメソッドの中身が、元の各動物のクラスと、キメラのクラスでは違ってくる……
そんなときに使える！…………そうです（


>プレイヤーには再生ボタン(Playableインターフェース)が付いてる。
再生ボタンを押すと、CDプレイヤーは音が鳴り、DVDプレイヤーは音と映像が流れる。
DVDレコーダーはRecordableインターフェースとPlayableインターフェースの両方をそなえている。
クラスは本体(機種)、インターフェースは側面(役割、操作部、接続部)。
DVDプレイヤーのインターフェースは前面と背面に付いてるけど。
本体内部は、小さな機能を持った部品を組み合わせて様々な機能が実装されてるけど、ユーザが使えるのはインターフェスのみ。
その小さな部品にも様々な回路が内蔵されてるけど、外から使えるのは側面や下面にある端子(インターフェース)のみ。

@shiracamus さんがわかりやすい解説をコメントしてくださりましたので、引用させていただきます！
ありがとうございます！！

私もまだ勉強途中なので、「へ〜、こんなのがあるんだ」くらいの認識ですが、同じ困っている仲間がいそうだったので書いてみました。
また知識が増えたら共有していきたいと思います。


# 参考
- [http://php.net/manual/ja/language.oop5.interfaces.php](http://php.net/manual/ja/language.oop5.interfaces.php)
- [http://tsumari.zapto.org/](http://tsumari.zapto.org/)
情シス(コーポレートエンジニア)で大切なこと

- 結論
    - 自由なIT環境をつくること 

- 従来型の企業文化
    - トップダウン型
    - 数値、お金目線
    - 何をいうかより、誰がいうか 

- 次世代型の企業文化
    - ボトムアップ型
    - 全社員がプロダクト(サービス、事業)目線
    - 誰がいうかより、何をいうか 

- 企業でいちばん大切なこと
    - いいプロダクトを作ること
        - プロダクトとは、サービス、製品、事業のこと
        - 世の中は非常に多くのプロダクトで溢れている
        - ユーザには選ぶ権利があり、レビューをつけられる世の中 
    - いいプロダクトを作るには、スゴい人たちが必要
        - スゴい人たちとは、優秀な人という意味
        - 優秀な人たちを獲得する仕組みが必要 
    - スゴい人たちは、自由な環境に惹かれる
        - 自由な環境とは、
            - 裁量が大きい
            - 制約(ルール)が少ない
            - 細かい管理をされない
            - 成長(チャレンジ)の機会がある
            - 失敗に対して寛容 

- 情シスでできること
    - 自由なIT環境をつくる
        - 例）
            - 社員が使いたいツールを使う
            - 新しいツール、仕組みを常に検討し、生産性を向上させる
実装環境で無効なデータがPayPalに送信されていることを確認しました。どうすればよいですか。

質問：  
PayPalウェブ ペイメント スタンダードまたはHTMLボタンが関わる取引が処理されていないため、次のようなエラーメッセージが表示されています。
日本語：  申し訳ありませんが、現在問題が起きているようです。しばらくしてから再実行してください。
英語：  Things don’t appear to be working at the moment. Please try again later.


  
回答：
2017年3月29日に、PayPalの決済処理が更新されました。
大半の実装環境では、新しいPayPal決済の処理が自動的に動作します。ただし、一部の実装環境では問題が発生し、ユーザーの操作が失敗する場合があります。検証確認が失敗する最も一般的な理由は次のとおりです。

- 「\$」「£」などの通貨記号または1、2、3などの整数および小数点(「.」)以外の値を金額フィールドで送信している。たとえば、「1234.50」は正しく処理されますが「$1,234.50」は許可されていません。
- 国コードで3文字以上の値を送信している。たとえば、「FR」は正しく処理されますが「フランス」または「fr_FR」は許可されていません。
- item_numberフィールドで128文字以上の文字を送信している。「買い手へのメッセージ」などの入力に、item_numberフィールドを使用しないでください。
- オプションフィールド(on0、on1など)で65文字以上の文字を送信している。
- 重複する空のパラメータを送信している。
- 住所を送信せずに address_override=1を送信している。

解決方法の詳細につきましては下記URLをご参考ください。
https://www.paypal-knowledge.com/infocenter/index?page=content&id=FAQ2067&pmv=print&impressions=false&viewlocale=ja_JP


  
PayPalではテクニカルサポートの部署がありますので、何かPayPal実装関連の質問や技術的な質問がありましたら、下記URLで記事を検索してみてください。
https://jp.paypal-techsupport.com/
上記URLの一番下の「お問い合わせ」リンクをクリックしてまたは下記URLをアクセスして質問を送信してください。
https://jp.paypal-techsupport.com/app/ask
最初のPayPal決済ボタンは機能するのに、それ以降のボタンが機能しないのはなぜですか?

PayPal決済ボタンのソースコードを調べる場合、変数に数字が付加されているかどうかを確認します(例: 'cmd2'、'business2'、'item_name2'、'submit2' など)。これは列挙と呼ばれ、ウェブエディタによって発生したと思われます。
お客さまの設定に応じて、一部のエディタ(特にDreamweaverおよびFrontPage 2003)は、HTMLコードのform変数を自動的に列挙します。弊社のサーバーがこれらの変更された変数を認識しないため、ボタンが正しく機能しません。このため、ボタンが、PayPalの決済ページではなく、PayPalのホームページにアクセスします。

HTMLコードを修正し、各変数の後の数字を削除する必要があります。

また、以下の手順で、Dreamweaverの変数列挙を無効にすることもできます。
1.	Dreamweaverで、[編集]をクリックします。
2.	[環境設定]をクリックします。
3.	[一般]の下で、\[ペーストするときにフォームアイテムの名前を変更\] (Dreamweaver MXの場合、このオプションは[コードの書き換え]の下にあります)の選択を解除します。

また、以下の手順で、FrontPage 2003の変数列挙を無効にすることもできます。
1.	FrontPage 2003で、[ツール]をクリックします。
2.	[ページのオプション]をクリックします。
3.	選択されていない場合は[全般]] タブを選択します。
4.	[Make ID Unique on Paste(貼り付け時にIDを一意にする)]の横のチェックボックスをオフにします。
5.	[OK]をクリックして変更内容を保存します。

注: DreamweaverまたはFrontPage 2003を使用していない場合は、エディタのヘルプで、この設定を無効にする方法を確認していただく必要があります。または、HTMLソースコードの変数名から追加された番号を手動で削除してください。



PayPalではテクニカルサポートの部署がありますので、何かPayPal実装関連の質問や技術的な質問がありましたら、下記URLで記事を検索してみてください。
https://jp.paypal-techsupport.com/
上記URLの一番下の「お問い合わせ」リンクをクリックしてまたは下記URLをアクセスして質問を送信してください。
https://jp.paypal-techsupport.com/app/ask
Google Analytics 用語メモ

# はじめに
この記事は、最近Google Analyticsを使い始めた素人エンジニアが色々調べた単語についてのまとめメモです。
間違っていたらご指摘いただけるとありがたいです。


# 用語集
語句とその意味一覧。


## セッション
ユーザの**訪問から離脱までの流れ**を指します。

つまり、**<font color="HotPink">一度訪れた同サイト中のどのページに何回訪れてもセッション数は1</font>**となります。

ただし、[有効期限](http://tsumari.zapto.org/detail.php?id=78)は30分らしく、30分を超えるとセッションがリセットされ、リセット後にサイトを訪れると、更にセッション数が1加算されます。


## ユーザ
**サイトを訪れた人の数**。
セッションとは違い、30分経って再度訪れてきてもカウントされません。
情報は2年間保持され、毎日来てくれても数値は加算されませんが、「Returning Visitor」の値が増える……ということですかね？（謎

逆に初めてサイトに訪れ他人に対しては、ユーザの数は1加算され、「New Visitor」の方にも1加算される……ということですかね？（謎


## ページビュー数（PV数）
**ページの読まれた数**。
**<font color="HotPink">誰が何回アクセスしようが、1加算</font>**されます。


## ページ/セッション
普通に割り算。
ページ/セッション = ページ ÷ セッション


## 平均セッション時間
サイトを訪問した人が、サイトに滞在してくれている平均時間。


## New Visitor
レポート期間中に、どれだけ初めての訪問者が来たかの割合。
レポート期間中ってのは、↓コレの事っぽい
<img width="715" alt="スクリーンショット 2017-05-17 15.09.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/63338/5857db3d-37b4-bdde-53e1-d80f80aea2c5.png">



## Returning Visitor
レポート期間中に、2回以上サイトに来てくれた人の割合。
レポート期間中ってのは、↓コレの事っぽい
<img width="715" alt="スクリーンショット 2017-05-17 15.09.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/63338/5857db3d-37b4-bdde-53e1-d80f80aea2c5.png">


## 新規セッション率
レポート期間内に、あなたのサイトを初めて訪れるユーザーの割合
レポート期間中ってのは、↓コレの事っぽい
<img width="715" alt="スクリーンショット 2017-05-17 15.09.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/63338/5857db3d-37b4-bdde-53e1-d80f80aea2c5.png">


## 直帰率
サイトに訪問してきて、**<font color="HotPink">1ページだけ読んで他のサイトに行く、または[ブラウザ](http://tsumari.zapto.org/detail.php?id=15)を閉じた人</font>**の人数。


とりあえず、ここまで。



# 参考
- [ひびの備忘録](http://www.h-nanae.com/analytics/googleanalytics/entry-143.html)
- [つまり？](http://tsumari.zapto.org/)
- [ まるで教科書！初心者のためのGoogleアナリティクスの使い方【絶対保存版】](https://junichi-manga.com/google-analytics/)
SELinuxを有効にした状態で、ドキュメントルートを変更

SELinuxを有効にした状態で、ドキュメントルートを変更

/httpd.confのDocumentRootを
/home/hoge/public_html 
と書き換えて、ドキュメントルートを変更した。

以前、ユーザディレクトリをSELinuxを有効にした状態で公開したときの
コマンドを実行した。

```
# chcon -R -t httpd_user_content_t /home/hoge/public_html
```


しかし、何の変化も起きない。

もしやと思って、

```
# chcon -R -t httpd_sys_content_t /home/labpress/public_html
```

と実行すると、表示できた。
/homeの下であっても、「httpd_sys_content_t」なんですね。
当たり前といえば当たり前、何も考えず流れでコマンドを打ったことを反省。
回線の種類と選び方


## 回線の種類
1. ベストエフォート型
    1. 通信の品質（帯域）が保証されていない回線サービス
1. ギャランティ型
    1. 通信の品質が保証されている回線サービス
1. バースト型
    1. 一定の帯域を確保し、通常はその帯域内で通信するが、一時的なデータ量増加に対しては、確保した帯域以上の速度が利用できる。

## 回線の選ぶポイント
1. 速度
1. SLA
1. サポート体制
    1. 問い合わせ対応時間、問い合わせ方法など
1. 個人的な経験則
    1. Nuro光、USENを使っていることが多い
    1. トラフィック量にもよるが、数百名規模の会社であれば、上記で基本的に問題なし
    1. 1拠点で1000名を超える場合は、どのような回線を使用しているのか不明


## 回線の変更の目安
1. 回線使用量の把握
    1. 現在回線の帯域幅のうち、どの程度使用しているのか確認する
    1. データの取得方法は、回線接続されている機器(UTM、ルータなど)のコマンド、SNMPで取得できることがある。対応していない機器では取得できない。
    1. Cactiなどで常日頃から平均値を取得しておき、平均使用量が上がったタイミングで回線の変更を検討をする。
Call to undefined function posix_getuid()解消

# はじめに

CentOS7-minimalから環境構築を始めて、標準リポジトリでhttpd, php5と入れていって、その後は特に何もせずに実行できると思っていたposix_getuid()が実行出来なくて３時間もハマったのでメモ

# 結論

```
yum install -y php-process
```

入れれば`posix_getuid()`は実行可能になる。多分、`posix_*`系の関数も使えるんじゃないかと思う。ちなみに、入れればphpinfo()にもPOSIXのエントリが追加される。

# php.netを見ても・・

> POSIX 関数は、デフォルトで有効となっています。POSIX 互換関数を --disable-posix により無効にする ことができます。
https://secure.php.net/manual/ja/posix.installation.php

わざわざ`--disable-posix`なんてしてインストールしてないので標準で入ってるものだと思いこんでた。

# ググっても

知恵袋みたいなところで`windows環境じゃ実行できないよ`的な答しか見つからず。
無線LANの設計ポイント


* 極力、5GHz帯を使用する
    * 5GHz帯を使用するには、PCの無線モジュールとAPが5GHzに対応している必要がある
    * 2.4GHzの方が最大速度が低く、使えるチャンネルが少ないため、電波干渉が起きやすい
* SSIDは、5GHz帯と2.4GHz帯で分ける
    * どちらにつながっているかすぐに分かるようにするため
    * PCから見た場合
        * 2.4GHzのみの対応PCは、2.4GHzのSSIDだけが見える
        * 5GHz対応のPCからは、2.4GHzと5GHzのSSIDが見える
* チャンネル設計
    * 2.4GHzの場合、隣接AP間は1ch,6ch,11chで構成する
        * 電波干渉による速度低下、接続しずらい状況を回避するため
    * 5GHzの場合、できればW52のみで構成する
        * W53、W56はDFSの影響を受けるため
        * チャンネルがW52に自動変更されると電波干渉が起きる
        * 天気レーダー、ヘリや飛行機など。。。
* セル、配置設計
    * クライアント端末数やユーザ数、場所で配置場所を決める
        * 1APあたりの最大接続数を考慮
        * ユーザが密集しているところの天井とかに配置
        * チャネルが隣接するAPは最低20mほど離して設置することを推奨
            * 36chと40chとか
    * 場所
        * 電波が減衰しそうな壁などを考慮する
        * スチール性のパーティションは、電波を反射して通りにくい
        * ガラスや木材は、電波を通りやすい
    * レイアウト図を元にバランス良く配置はNG
* 電波品質
    * SNRを計算する
        * -60dBm以下は、無線接続が不安定といえる
            * マイナスの値なので数値が小さいほうがよい
        * SNR = (RSSI) - (ノイズ)で計算される
jqでjson形式の行だけ抽出する

以下のようにjson形式の行とそうでない行が混在しているファイルにjqを実行してもparseエラーになってしまう。

```
php
java
{"lang": "go"}
ruby
{"lang": "perl"}
```

次のようなコマンドでjson形式の行だけ抽出することができた。

```
$ cat lang.json | jq -R 'fromjson? | select(type == "object")'

{
  "lang": "go"
}
{
  "lang": "perl"
}
```
VPCのネットワークまわりをもう一度

# VPCまわりって、ややこしいよね

---

- VPC
- サブネット
- IGW・VGW
- NATインスタンス・ゲートウェイ
- セキュリティグループ
- ネットワークACL
- VPCピア接続

---

# 😂

---

今日はこのへん話します

- VPC
- サブネット
- IGW
- NATインスタンス

---

ひとつずつ、思い出してみよう
(知らない人はこれを機にそんなもんがあるのかと思ってみよう)

---

# VPC(Virtual Private Cloud)

---

# VPCとは

利用者ごとのプライベートなネットワーク空間のこと

クラスA〜Cのプライベートネットワークのいずれかの値を使用します

---

# Q. aとbどちらが正しいでしょう

a. VPCはリージョン内でAZ(アベイラビリティゾーン)をまたげる
b. VPCはリージョン内でAZ(アベイラビリティゾーン)をまたげない

---

# 答え

a. VPCはリージョン内でAZ(アベイラビリティゾーン)をまたげる

---

![AWS Design Simple AZ:Untitled - Cacoo 2017-05-17 11-07-07.png](https://qiita-image-store.s3.amazonaws.com/0/37036/c6175960-be60-f152-18fe-cd774cdde16c.png)

---

# サブネット

---

# サブネットとは

大きなネットワークの中の小さなネットワーク

役割に応じてWeb用、DB用と作られる。これによって、インターネットからのアクセス制限をかけられたりする

---

# Q. aとbどちらが正しいでしょう

a. サブネットはリージョン内でAZ(アベイラビリティゾーン)をまたげる
b. サブネットはリージョン内でAZ(アベイラビリティゾーン)をまたげない

---

# 答え

b. サブネットはリージョン内でAZ(アベイラビリティゾーン)をまたげない

---

![AWS Design Simple subnet:Untitled - Cacoo 2017-05-17 11-12-13.png](https://qiita-image-store.s3.amazonaws.com/0/37036/2d5c4fbc-78eb-0a76-6f38-be199361b9bc.png)

---

# IGW(Internet Gate way)

---

# IGWとは

VPCと外部ネットワークの間で通信を行うための出入り口。こいつをVPCにアタッチしてインターをネットする

---

# サブネットでネット制限

- インターネットとのアクセスを許可するサブネット: **パブリックサブネット**
- インターネットとのアクセスを許可しないサブネット: **プライベートサブネット**

---

ルートテーブルの設定によってパブリック/プライベートが決まる。
ルートテーブルでIGWをターゲットに設定するとパブリックになる。

---

![AWS Design Simple:Untitled - Cacoo 2017-05-17 11-15-36.png](https://qiita-image-store.s3.amazonaws.com/0/37036/13b3d865-b70d-497c-3a62-dc7527d37c20.png)

---

でもこのままだとプライベートサブネット孤立問題が起こる

- パッチなどをダウンロードしたいときインターネットにアクセスできない
- DynamoDBなど他のリージョンサービスにアクセスできない

---

そこで

# NAT(Network Address Translation)

が登場します

---

NATを使うことで、インターネットからのアクセスを受け付けないまま、インターネットやDynamoDBなどのリージョンサービスにアクセス可能に

---

![nat-gateway-diagram.png](https://qiita-image-store.s3.amazonaws.com/0/37036/47d3db24-c676-d87a-ec05-0371cc0dc6d8.png)

---

# ルーターとは

サブネットを相互接続し、インターネットゲートウェイ、仮想プライベートゲートウェイ、NAT ゲートウェイ、およびサブネットの間でトラフィックを正しい宛先に送る機能。

---

# ありがとうございました
Cognos レポートでY軸の最大値をデータが無くても固定したい

##概要
またも昔やった小ネタを投稿します。

下図のように、Y軸の最大値、最小値をテキストのプロンプトで指定できるレポートを作成した場合に、Y軸の最大値を12に指定した時に、12に近い値が無い場合は、デフォルトで左側のグラフのように最大の値がぎりぎり表示されるレベルのY軸になってしまいますが、右側のグラフのように、Y軸の最大値に指定した値にしっかり固定する方法です。
![001.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/24b00836-6e42-13a0-f3fa-c832a4451641.png)

##実装
レポートの定義です。
右側のグラフで、棒グラフではなく、複合グラフにしておいて、COL3というアイテムを折れ線グラフに指定しています。
![002.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/e60ce4f0-8d6b-25c3-5683-d4f2c03bd67f.png)

COL3の中身はこちらです。
?pYH?は、Y軸の最大値に入力された値を拾うパラメーターです。
最大値よりほんの少しだけ小さい値をCOL3が持つようにします。
![003.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/e1ed492b-40d7-0a80-eec4-93ff032d60a1.png)

そのCOL3を折れ線で表現するときに、グリッド線の色と同じ色を指定すると、Y軸の12のグリッド線と、COL3の折れ線がほぼ重なって、見えなくなる、というカラクリです。
![004.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/cc01de3f-2c77-87ac-a0f0-2c00904eafd5.png)

またも苦肉の策ですが、こんなやり方もあるよという例でした。
Vagrantで立ち上げた仮想環境にIPアドレスを振ってsshでログインする

この記事はMac向けです。他のOSの場合は、sshコマンド等別途準備してください。

## 事前準備

### VirtualBoxのインストール
- VirtualBox https://www.virtualbox.org/

インストール後、起動してください。

### Vagrantのインストール
- Vagrant https://www.vagrantup.com/

インストール後、vagrantコマンドが使えるようになります。

```bash
$ vagrant --version
Vagrant 1.9.4
```

## Vagrantプロジェクトの初期化からVM起動まで

適当な場所に作業ディレクトリを作成。場所と名前はどこでも可です。以下の説明は適当に読み替えてください。
今回の説明では、VMのOSにCentOS7を使います。他のOSを使う場合は[ここ](https://atlas.hashicorp.com/boxes/search)で探して下さい。


```bash
$ mkdir -p /your/directory/vm1
$ cd /your/directory/vm1
```

initコマンドで初期化します。Vagrantfileが作成されます。

```bash
$ vagrant init centos/7
```

VirtualBoxにVMを起動

```bash
$ vagrant up
```

![スクリーンショット 2017-05-17 14.50.20.png](https://qiita-image-store.s3.amazonaws.com/0/88743/7f234686-38cb-befc-f849-297ce62d2a0b.png)



無事立ち上がったら、VMにvagrant sshでログインできます。ログアウトはexitです。

```bash
$ vagrant ssh
```


destroyコマンドで、VirtualBoxのVMを停止・削除できます。vm内での変更は破棄されます。


```bash
$ vagrant destroy
```


## Vagrantで立ち上げたVMにディフォルト設定でsshでログイン

vagrant sshではなく、通常のsshコマンドでログインしてみます。

ssh-configコマンドで、SSH接続情報を確認できます。


```bash
$ vagrant ssh-config
Host default
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /your/directory/vm1/.vagrant/machines/default/virtualbox/private_key
  IdentitiesOnly yes
  LogLevel FATAL
```

ディフォルトでは、ホストOSのport 2222に、VMのport 22がフォワードされています。このため、localhostのport 2222に対してsshでログインできます。選んだOSによってはUserがvagrant以外になっているかもしれません。


```bash
$ ssh -i /your/directory/vm1/.vagrant/machines/default/virtualbox/private_key -p 2222 vagrant@127.0.0.1
とか
$ ssh -i /your/directory/vm1/.vagrant/machines/default/virtualbox/private_key -p 2222 vagrant@localhost

[vagrant@localhost ~]$ 
```

**su -でrootになる場合、パスワードはvagrantです。**


## VMに接続するポートを変えてsshログイン
ディフォルトの設定のままで2台目のVMを起動させると、port 2222にフォワードしようとして失敗するため、2223を割り振ってみます。
新しい作業ディレクトリを作って、vagrant initコマンドを実行し、作成されたVagrantfileをテキストエディタで開きます。

```bash
$ mkdir -p /your/directory/vm2
$ cd /your/directory/vm2
$ vagrant init centos/7
$ vi Vagrantfile
```

Vagrantfileに１行追加

```bash
config.vm.network "forwarded_port", guest: 22, host: 2223, id: "ssh"
```


vagrant upでVMを起動して、vagrant ssh-configで接続情報を確認すると、ポートが2223に変わっています。

```bash
$ vagrant up
$ vagrant ssh-config
Host default
  HostName 127.0.0.1
  User vagrant
  Port 2223
以下略
```

port 2223でsshログインできます。

```bash
$ ssh -i /your/directory/vm2/.vagrant/machines/default/virtualbox/private_key -p 2223 vagrant@localhost
[vagrant@xxx ~]$ 
```

## VMにIPアドレスを振ってsshログイン
今度はVMにホストOSとは別の、IPアドレス割り振って、ホストOSからssh接続してみます。
また新しい作業ディレクトリを作成して、init後、Vagrantfileに1行追加します。


```bash
$ mkdir -p /your/directory/vm3
& cd /your/directory/vm3
$ vagrant init centos/7
$ vi Vagrantfile
```

Vagrantfileに１行追加します。192.168.10.2の所は環境に応じてかえてください。

```bash
config.vm.network "private_network", ip: "192.168.10.2"
```

VMに対してホストOSとは別のIPで、sshでログインできるようになりました。

```bash
$ vagrant up
$ ssh -i /your/directory/vm3/.vagrant/machines/default/virtualbox/private_key vagrant@192.168.10.2
[vagrant@xxx ~]$ 
```
先に記入させて後からログインさせる(Gradual Engagement)の話

渋谷.rb[:20170517]のLT資料です。
スライドモードで見ることを想定しています。

---

# 今日話すこと
- 先に記入させて後からログインさせる(Gradual Engagement)の話
- 設計の話でRubyあんま関係ない、ごめん :tired_face: 
- Railsの実装例も紹介
- 実例

---

# Who
- kaiba
- 最近は RailsとiOS
- 無法地帯改善! テストも書き始めた :muscle: 

---

# とあるウェブサービスで…
1. ほほう、おもしろそうだな。ポチ。 
1. 会員登録が必要です
1. めんど、やめよ

---

# そこでこうしたい
1. ほほう、おもしろそうだな。ポチ。
1. どうぞ! 使ってください!
1. それ! なるほど、こういうことができるのか! 使ってみよう!
1. 会員登録が必要です
1. **しょうがないにゃあ、いいよ** :cat: 
1. **WIN! WIN!**

---

# Gradual Engagement
日本語にすると**段階的な関与**

- 何ができるのかを最初に見せることができる
- そのために会員登録が必要なことも理解しやすい
- **会員登録してもらいやすい！**

---

# 実装を考える :thinking: 
- 今までログインありきだったのをログインなしで使えるようにしないといけない
- 入力情報を input type=hidden でパラメータを引きずり回して、会員登録時にどーん！して紐付けてやる…?
- つらい
- やめない…?

---

![image.png](https://qiita-image-store.s3.amazonaws.com/0/21799/81accfbc-41dc-996c-6cab-cd41b40978d9.png)

---

# そこで、こうやって、こうじゃ
- Guestsテーブルを作成
- Guestsテーブルはtokenを持ち、cookieにも保持させる
- Guestsテーブルと作成したデータ(今回はPosts)を紐付ける
- 会員登録したらUserテーブルと作成したデータを紐付けてやる

---


![image.png](https://qiita-image-store.s3.amazonaws.com/0/21799/313dd3bd-4d0e-1c12-9f5e-6c8410021457.png)

---

# 注釈

※ 最初からこの仕様がわかっているなら Posts と Users/Guests間に関連テーブルを作るとかしたほうが美しい/使いやすい

---

# Railsの例
- こんなかんじ? を書いただけで動く補償はないです :smiling_imp: 
- 処理の流れを追うためにベタッと書いてます。

---

# Posts作成時に認証を不要にして、Guestと紐付ける
```ruby
# posts_controller.rb
skip_before_action :authenticate_user!
def create
  session[:guest_token] ||= SecureRandom.uuid
  guest = Guest.where(token: session[:guest_token]).first_or_create
  Post.create(msg: msg, guest: guest)
end
```

---

# 会員登録後にPostと紐付ける
```ruby
# users_controller.rb
def create
  user = User.create(params)
  guest = Guest.find_by(token: session[:guest_token])
  Post.where(guest: guest).update(user: user)
end
```

---

# やった！
- ログイン前に作った情報がログイン後にユーザに紐付いた!
- input type=hiddenなんて要らなかったんや!
- 参考文献: http://nithinbekal.com/posts/gradual-engagement-rails/

---

# おわり
- **せっかくなので未リリースの機能を実演させてください** :bow: 

---

# 発表後にいただいた意見

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">user_id, guest_id カラムを作ってどちらかが必須 -&gt; Polymorphic association (owner_type, owner_id) で NOT NULL 制約かけよう -&gt; 外部キーを設定できないので関連テーブルを作るべき <a href="https://twitter.com/hashtag/shibuyarb?src=hash">#shibuyarb</a></p>&mdash; Takafumi ONAKA (@onk) <a href="https://twitter.com/onk/status/864805361659793408">2017年5月17日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

not nullにできて、Railsの機能で使いやすい。
ただpreloadするときに困るケースがある。
爆速！サーバにSSHでログインがあった時にLINEで通知する

LINEでサクっと通知が受け取れると便利ですよね。爆速で設定しましょう。

## LINE Notifyのトークンを取得する

Botのように相互にやりとりをするのではなく一方的に通知をするだけであればLINE Notifyが便利です。

Messaging APIと異なり基本的にずっと無料で、設定が簡単なのも利点です。今回はこれを使うことにします。

まずはLINE Notifyのサイトでトークンを取得しましょう。

[https://notify-bot.line.me/](https://notify-bot.line.me/)

![](https://qiita-image-store.s3.amazonaws.com/0/28762/596136e4-bd0b-84a7-cf6e-43235c1610bb.png)

右上のログインを押して、普通にLINEアカウントでログインします。

ログインの表記がアカウント名に変わるので、そこから**マイページ**をクリックします。

![](https://qiita-image-store.s3.amazonaws.com/0/28762/70046e49-e2d7-939a-a2ce-0448473eec93.png)

こんな感じの画面になるので、**トークンを発行する**ボタンを押します。

トークン名は通知の際に表示されるので、「SSH通知」や「ログイン通知」などわかりやすいものにしておきます。

送付先のメッセージルームは通知をチームで共有したいならそこを、個人的なものなら1:1で通知を受け取るを選びます。

入力が終わり、**発行する**ボタンを押すとトークンが表示されます。

このトークンはこの画面以外では表示できず、紛失してしまうと再度発行し直しになるのでしっかりコピーしておきましょう。

以上でトークンの取得は完了です。

## トークンを試す

きちんとNotifyで通知が送れるか試してみます。

以下のコマンドをターミナルで実行してみてください。

```bash
curl -X POST -H 'Authorization: Bearer <取得したLINE Notifyのトークン>' -F 'message=Notifyのテスト' https://notify-api.line.me/api/notify
```

無事にLINEで通知が届いていればOKです。

## sshrcを設定する

あとはサーバ側でユーザがsshログインしてきた時に実行されるsshrcに通知用のスクリプトを書くだけです。

`/etc/ssh/sshrc`に下記のスクリプトを書いておきます。

```bash:/etc/ssh/sshrc
message='SSH Login / User: '$USER' / Client: '$SSH_CLIENT

curl -sS -X POST -H 'Authorization: Bearer <取得したLINE Notifyのトークン>' -F message="$message" https://notify-api.line.me/api/notify > /dev/null
```
これでサーバにログインがあった時はLINEに通知が届くようになりました。

curlでサクッと通知を送れるのでとても楽ですね。

ちなみにcurlの-sオプションはプログレスバーを表示しないようにするもの、-Sオプションはエラー時だけ表示するようにするものです。

これを設定しておかないとログインの度にcurlの進捗が出てしまってうっとうしいのでこうしてあります。

## 最後に

LINE Notify、いまいちマイナーですけど普段使っているチャットアプリにサクっと通知を送れるのはすごく便利ですね。

筆者はTwitterで日々技術情報もろもろの投稿をしているので良かったらフォローしてもらえると嬉しいです。

https://twitter.com/YuhsakInoue
UTM製品の選び方

## UTMとは
* 次世代ファイアウォール製品のこと
* ファイアウォール製品より、豊富なセキュリティ機能が搭載されている

## 選び方の鉄則
* どのセキュリティ機能を使用するか見極める
* 一部のセキュリティ機能については、アプライアンスとの併用を考える
* できる範囲で、導入前に社内でテストする
    * 時間、人
    * 検証機が無料か有料か

## セキュリティ機能
1. ファイアウォール
    1. パケットフィルタリング
        1. 宛先や送信元IPアドレスやポート番号などをチェックして、通信を制御する機能
    1. ステートフルインスペクション
        1. 通信プロトコルを利用して、「ありえない応答」を拒否する機能
        1. 偽装された通信をブロックできる
    1. Webアプリケーション制御
        1. どのWebアプリケーションを利用しているのかチェックして、通信を制御する機能
        1. IPヘッダだけでなくデータの中身まで読み出してアプリケーションを特定する
1. VPN
    1. インターネット上に暗号化されたセキュアな通信を実現する
    1. 使い方としては、拠点間VPN接続とリモートアクセスVPNの2種類がある
1. IPS
    1. シグネチャを使って、既知の脆弱性を突く攻撃コードを遮断する
1. URLフィルタ
1. ウイルスゲートウェイ
1. メールゲートウェイ
1. DLP
リンクアグリゲーションとは

# この記事について
この記事は、ネットワークのリンクアグリゲーションのメリットやデメリットなどについて書いたものです。

## リンクアグリゲーションとは
物理ポートおよび物理リンクをひとつの論理リンクにまとめる技術
LAG(ラグ)とも呼ばれる。

## メリット
ひとつの論理リンクにまとめることで、帯域拡張と冗長化を確保できる

## デメリット
物理ポートを多く使用する

## 3つの構成方法
1. 静的
    - 各ポートごとに静的にリンクアグリゲーションを設定

2. PAgP
    - リンクアグリゲーションを自動構成するためのプロトコル
    - Cisco独自のプロトコル
    - Ciscoのみのネットワーク環境であれば推奨
    - "Desirable"と"Auto"の2種類のモードがある
    -  Desirableは、自分でPAgPを送信して積極的に論理リンクを作ろうとする
    -  Autoは、LACPを送信せず、PAgPを受け取ったら論理リンクを作る
    - 一般的なネットワーク設計では、設定を統一するために"Desirable"にすることが多い

3. LACP
    - リンクアグリゲーションを自動構成するためのプロトコル
    - 802.1adで規格化されているのため、複数ベンダーが混在したネットワーク環境でも使用可能
    - "Active"と"Passive"の2種類のモードがある
    - Activeは、自分でLACPを送信して積極的に論理リンクを作ろうとする
    - Passiveは、LACPを送信せず、LACPを受け取ったら論理リンクを作る
    - 一般的なネットワーク設計では、設定を統一するために"Active"にすることが多い

## 重要なポイントは負荷分散方式
1. 帯域拡張は、複数の物理リンクに対して負荷分散を行って、拡張を図っている
1. 誤った負荷分散方式を選択すると、使用する物理リンクに偏りが出る
1. 機器によって対応している負荷分散方式は違う
  - 送信元 / 宛先MACアドレス
  - 送信元 / 宛先ポート番号
  - 送信元 / 宛先IPアドレス
  - などなど
1. どの方式がよいかはネットワーク構成によって異なる

## 事例
* L2スイッチとコアL3スイッチ間
* コアL3スイッチとUTM間
Selenium2のWebDriverでIEを操作したときの問題と対応まとめ


出向している現場のチームが画面上で手動でテストデータ作成していたのでSeleniumを導入しました。
担当しているシステムはIEでしか動かないのでIDEでテストケースは作らず
WebDriverを利用してjavaでケースを実装し、ブラウザ操作を行いました。
備忘録を兼ねて問題や使い方をまとめます。

##環境
windows10 64bit
IE11
java 1.8.0_121
eclipse Neon.2 Release (4.6.2)
selenium 2.53.1

##設定
1.eclipseで新規mavenプロジェクトを作成する
作成時に「シンプルなプロジェクトの作成」にチェックします

2.pom.xmlを修正

```html:pom.xml抜粋
<dependencies>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>2.53.1</version>
    </dependency>
</dependencies>
```

3.IEDriverServerをダウンロード
<a href="http://selenium-release.storage.googleapis.com/index.html">
こちらから
</a>

※僕はWindows64bitを利用していますが
IEDriverServerは32bit版をダウンロードしました。
64版だとうまく動かないシーンがあります。後述の「問題と対応 2」をご覧ください。

4.Java実装へ
3で取得したDriverServierのパスをsetPropertyする必要があります。

```html:IEDriver初期設定の書き方
System.setProperty("webdriver.ie.driver","C:\\任意の場所\\IEDriverServer.exe");
WebDriver driver = new InternetExplorerDriver();
```

<a href="https://donow.jp/skillup/?p=776#i-7">
driverの使い方はこちらが参考になります
</a>

#問題と対応

##1.Selenium起動時エラー

```html:
Unexpected error launching Internet Explorer. 
Protected Mode must be set to the same value (enabled or disabled) for all zones.
```

IEブラウザの
インターネットオプション→セキュリティタブの設定
→すべてのゾーンで保護モードの設定を同じにする

##2.sendKeysがめっちゃ遅い
ブラウザのテキストを入力するsendkeysが異常な遅さで使えません
詳細原因は追究してませんが、64bit版のIEDriverServerを利用するとそうなるようです。

##3.クリック操作しても発火しない
IEだとたまに発生するようです。
以下の記述で回避できました。

```html:
WebElement element = driver.findElement(clickTarget);
element.sendKeys(Keys.CONTROL);
element.click();
もしくは
new Actions(driver).click(element).build().perform();
```

##4.ファイルダウンロードポップアップが表示されると停止する
IEでファイルをダウンロードしたときに出るポップアップ（通知バー)
あれが出るとseleniumは停止します。
手動でぽちりしても動きません。
IE11だとブラウザから設定変更もできませんでした。
よって子スレッドを作ってダウンロード処理はそちらに任せて
親スレッドが本筋の処理を継続させるよう苦肉の対応を行っています。


#Tips
##ブラウザの子画面を操作したい
親画面がJSで子画面を生み出した場合
子画面にフォーカスして操作したいときのやりかた。

```html:
// 親ウィンドウ情報を保持
String currentHandle = driver.getWindowHandle();

// 子ウィンドウにフォーカスを切り替える
Set<String> windowHandles = driver.getWindowHandles();
　　for (String handle : windowHandles) {
　　　　if (!handle.equals(currentHandle)) {
　　　　　　driver.switchTo().window(handle);
　　　　}
}

// 子ウィンドウ処理が終わったら親に戻す
driver.switchTo().window(currentHandle);
```
##ブラウザの処理が終わるまで待機したい
Seleniumで操作を命令した後、それが終わるまで待機したい。
例えば、検索のした後に、検索終わって一覧が出てから次の操作を行いたい。
以下のソースは、idがlistのエレメントが画面に表示されるまで待機する。
タイムアウトは10秒、超えると例外発生。

```html:
// 待機用オブジェクト
WebDriverWait wait = new WebDriverWait(driver, 10);

wait.until(
  ExpectedConditions.presenceOfElementLocated(
    By.id("list")
  )
);
```
##ファイルをアップロードしたい

```html:
WebElement element = driver.findElement(By.xpath("//input[@type='file']"));
element.sendKeys("./ファイル.txt");
```

#参考文献
https://donow.jp/skillup/?p=776#i-7
http://qiita.com/tukiyo3/items/44f5b64cf222d9da1b5b
http://bokuibi.blogspot.jp/2012/05/selenium-2.html
http://qiita.com/nkns165/items/53d1afc17023d9ae3ebd
amazon-cognito-identity-jsがセッション情報をsessionStorageに保存できるようになった

　Amazon Cognito User Poolsをjavascriptで扱うための公式パッケージ[amazon-cognito-identity-js](https://github.com/aws/amazon-cognito-identity-js)が2017/5/12に更新され1.17.0になった。

　これまでは認証後のセッション情報は自動的にローカルストレージに保存される仕様であったたため、明示的にclearCachedTokensまたはsignOut, globalSignOutを実行しない限りセッション情報が端末に残ることとなっていた。  
　ローカルストレージはドメイン毎の情報を端末に永続保存するための場所なので、共用パソコンなどでログアウトを忘れると、なりすましのリスクがあった。モバイルアプリの場合は問題にならないがWebアプリケーションの場合は注意しないといけない。
　具体的には、id tokenやsession tokenは1時間で期限切れにより使えなくなるが、refresh tokenの有効期限(デフォルト30日、設定により1-3650日)までの間はid token/session tokenを再取得できるため、ブラウザを閉じても簡単にセッションが復活できてしまう。 
　これまでにとれた回避策は、コード改変をするか、ローカルストレージに保存されるアクションの度にclearCachedTokensを実行するという方法くらいのようである。

　今回のバージョンアップでCognitoUserPoolおよびCognitoUserのconstractorにStorageオプションが追加されたので、ここにセッションストレージを指定することでブラウザを閉じた時に情報を削除させることができるようになった。

```javascript:cognitoUserの作成
import { CognitoUserPool, CognitoUser } from 'amazon-cognito-identity-js';

const cognitoUserPool = new CognitoUserPool( {
  UserPoolId: <<userPoolId>>,
  ClientId: <<clientId>>,
  Storage: sessionStorage
});

const cognitoUser = new CognitoUser({
  Username: <<userName>>,
  Pool: cognitoUserPool,
  Storage: sessionStorage
});
```

　現時点ではCognitoUserのコンストラクタはStorageを指定したCognitoUserPoolを引数にしてもローカルストレージが使われるため、
CognitoUserPoolおよびCognitoUserどちらも明示的にStorageを指定しないと期待した動きにならない。（修正を提案中）

　よいUXのためには、デフォルトではセッションストレージを使うようにしておき、ユーザがオプトアウトした場合のみローカルストレージで長期保存するように作るのがいいだろう。
　Cognitoはログインしたデバイスを認識できるので、設定したデバイスでだけログインし続けるように作ることもできるはず。
[Unity] CanvasGroupの影響を受けない子要素を作る

## 実行環境
- Unity5.5.2f1

## 概要
- CanvasGroupを使用してUI群のアルファ値を一括で操作したいケースはよくある
- その際、一部のUI要素のみアルファ値の操作の影響下から外したい

## Ignore Parent Groups
- https://docs.unity3d.com/ja/540/Manual/class-CanvasGroup.html
- CanvasGroup の Insepector上で設定できる項目にの1つ
- Ignore Parent Groupsを有効にした場合、アタッチされたGameObjectと子要素が、親要素の Canvas Group の影響を受けなくなる
- スクリプトから変更する場合、以下のように記載する

```
CanvasGroup canvasGroup = GetComponent<CanvasGroup>();
canvasGroup.ignoreParentGroups = true;
```

## 対応
- 1) 親要素にCanvasGroupをアタッチする
- 2) 子要素にもCanvasGroupをアタッチする
- 3) 子要素のCanvasGroupのIgnore Parent Groupsを有効にする
- 4) 親要素のCanvasGroupのアルファを変更する

![ignore_parent_group.gif](https://qiita-image-store.s3.amazonaws.com/0/102664/ede76785-e112-e2d0-85de-1d6427148365.gif)
GitHub PagesとGitLab Pagesの比較

(2017/06/29 追記) 後半は利用可能なデプロイツールの比較になってますね。

||GitHub|GitLab|
|---|---|---|
|SSL|対応|対応|
|独自ドメインSSL|非対応|対応|
|デプロイツール|Circle CI, Travis CI, ...|GitLab CI|
|デプロイ方法|`gh-pages` にプッシュ|tarをアップロード|
|環境変数の隠蔽|ペアリング暗号|GUIで設定|

# GitLab CI設定ファイル
詰まったところを交えつつ書いていきます。

```yaml:.gitlab-ci.yml
image: node:latest
stages:
  - deploy
cache:
  # NPMに関連するディレクトリをキャッシュすることでインストールを高速化
  paths:
    - node_modules/
    - .yarn/
pages:
  stage: deploy
  # masterブランチにプッシュされた時のみ実行
  only:
    - master
  before_script:
    # Yarnのキャッシュディレクトリを .yarn に
    - 'yarn config set cache-folder .yarn'
    - 'yarn install'
  script:
    # スクリプトで gulp タスクを回しビルドを実行
    - 'yarn run build'
    # どうやらアップロードするディレクトリは public という名前である必要がある
    - 'cp -pr build public'
  after_script:
    # デプロイ後にCloudFlareのキャッシュを消去
    - './cf-cache-flush.sh'
  artifacts:
    paths:
      - public
variables:
  # shallow cloneすることによりダウンロードを高速化
  GIT_DEPTH: '1'
  CF_ZONE_ID: '26c20487321750ddce766cc1a83a6afa'
```
```bash:cf-cache-flush.sh
#!/bin/sh

# CloudFlareのキャッシュを削除
# $CF_API_KEY は隠蔽する必要があるので、GUIの Secret Variables で定義する
curl -X DELETE "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/purge_cache" \
  -H "X-Auth-Email: sei40kr@gmail.com" \
  -H "X-Auth-Key: ${CF_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"purge_everything":true}'
```
# こちらもどうぞ
* [GitLab CIの設定ファイルを手元でLintする](http://qiita.com/sei40kr/items/407e08cc45f218738d4c)
Javaの勉強 - 8

# ifの条件式で文字列を比較する
数値の時に使っていた「==」は文字列の比較では使えない。
文字列の時は「**equals**」を使う。

書き方は「==」のときと少し違っていて

```
変数a.equals(変数b)
```

と書くっぽい。
ifで変数s1とs2を比較したいときは、こんな感じで使う↓

```java
String s1 = "tomato", s2 = "tomato";

if (s1.equals(s2)){
	System.out.println("一致");
}
```

これ↑はs1、s2が一致するとき、if内を実行されるが
『文字列が一致しないとき』にしたい場合は
条件式の前後を「( )」で囲んで、前に「!」をつける。

```
!(変数a.equals(変数b))
```

変数s1とs2が異なるときに、if内を実行するのは↓

```java
String s1 = "tomato", s2 = "potato";

if (!(s1.equals(s2))){
	System.out.println("不一致");
}
```

「!」が否定のために使われることに慣れてきた感。

# if内で変数に代入してエラーになった
変数に初めて値を入れるのがif内で、
その変数の値をその後の処理で使おうとしたらエラーになった。

何が言いたいのか分からないかもしれないけれど
書いている方も「ん？ん？」そうなのか？
な感覚なので気にしないでもらいたい。

エラーになったのは↓のとき

```java:Yomogi.java
public class Yomogi{
	public static void main(String[] args){
		int a, b;
		a = 1;
		
		if (a == 1){
			b = 1;  // これと
		}	
		System.out.println("b = " + b);  // この関係がダメ
	}
}
```

変数aには1が入るんだから、ifは100%trueになって
if内部の処理が実行されるからこれでいいだろう。
と思っていたけど、ダメでした。

if内で初めて値が入る、と言うのが問題だったみたい。
なので、事前に変数bに適当な値を入れておく。

```java:Yomogi.java
public class Yomogi{
	public static void main(String[] args){
		int a, b;
		a = 1;
		b = 0;  // 事前に0で初期化
		
		if (a == 1){
			b = 1;
		}
		System.out.println("b = " + b);
	}
}
```

こうしたら上手く動いてくれた。
なるほど、javaってそういう仕様なのね。

と、理解したところで。

変数に初めて代入するのがif内であっても、
その変数をif内だけで使うのはOKだったので覚えとくことにした。

```java:Yomogi.java
public class Yomogi{
	public static void main(String[] args){
		int a, b;
		a = 1;
		
		if (a == 1){
			b = 1;
			System.out.println("b = " + b);  // if内だけで使うのはOK
		}
	}
}
```

ifを使うとき、変数に代入するタイミングは気を付けないとな。
と思ったエラーとの遭遇でした。
Enterprise program In-House配布時にダウンロードできない際のチェック項目

大抵の場合「現在ダウンロードできません。」といったダイヤログが表示されますが、それだけだと情報が少なすぎるのでよくある原因を挙げてみました。

## チェック項目
### OSバージョン

* アプリがサポートする最低OSバージョンを満たしているか
-> iOS9以上が対象のアプリをiOS8の端末にインストールしようとしている場合など。

* インストールしようとしている端末のOSが最新で、かつOSのアップデート直後ではないか
-> 最新OSになったことでエンタープライズApp関連の仕様が変更された可能性があるので、調査する。過去には設定から企業を信頼（許可）しないと起動できなくなるといったことがあった。また、iOSのバグで以前のOSで一度インストールしたことがあるBundleIDのアプリがインストールできなくなるということもあったので、TwitterなどのSNSでの検索もした方が良い。

### 端末

* iPad専用アプリをiPhoneでダウンロードしようとしていないか

### Provisioning Profile

* プロファイルに必要な設定が入っているか
-> アプリによってはプロファイル側で設定が必要な機能を利用している場合がある。（iCloudなど。XcodeではTargetのCapabilitiesから設定）
このように設定されたプロファイルが必要なアプリに対して、ワイルドカードのプロファイルを使っているとダウンロードが失敗する。

* プロファイルの期限は切れていないか
-> プロファイルの期限は作成から1年（2017/5現在）で切れるため、切れていた場合は更新してセットし直す。この場合は同じプロファイルで入れたアプリの起動もできなくなりますが、切れたらすぐ起動ができなくなるというわけではなく、少し時間が経ってから起動できなくなるようです。

### 証明書

* 証明書の期限は切れていないか  
-> AppStoreへの提出用の証明書と異なり、エンタープライズ配布の証明書では期限が切れるとダウンロードできなくなります。この場合は同じ証明書と紐付いたプロファイルで入れたアプリの起動もできなくなりますが、こちらも切れたらすぐ起動ができなくなるわけでは無いようです。

### manifest.plist

* manifestに定義するBundleIDがアプリのBundleIDと一致しているか  
-> 経験上、一度でも同じBundleIDでインストールしたことがあればその後は一致していなくてもダウンロードに成功してしまっている気がするので、新しい端末に入れる時に突然発生する印象です。

### その他

* 3Gで接続しているなど、通信が不安定な場合にインストール失敗になることもありました。
* CLIからビルドしている場合は、XcodeからArchiveしてみるとエラーが表示されることもあります。
* インストール失敗する端末をMacに接続して Xcode -> Window -> Devices からログを確認できます。
ブラウザ経由でsudoの必要なrsyncスクリプトが動かなかった件

WEBデザイナさんたちのために、
rsyncで開発サーバから本番サーバへ一発送信のスクリプトファイルを書いたのだけど、
「黒い画面（コンソールのことか…）はこわい」とおっしゃるので
一枚物のWEB画面をPHPで書いて、
そこにボタンを置いてキックする形にしようとして書いたんだけど
sudoが通らなくてはまっちまって1日無駄にした挙句
他の人の手も煩わせたのでメモしとく。
っていうか日本語の記述なかった。
参考：http://stackoverflow.com/questions/19608431/php-fpm-d-with-nginx-how-to-run-sudo-at-shell-exec

##環境：
AWS 
nginx
PHP
だけどバージョンとかWEBサーバの種類とか関係ないです、これ。

##実現したいこと：
WEB画面からPHPでスクリプトファイルをキック
（ユーザ：nginx）
　　　　↓
nginxユーザはコンソールが無いので
sudoで「soushin」ユーザに切り替えて
スクリプトファイル中のrsyncをsshで実行
　　　　↓
画面に実行結果を返す

##やったこと：
visudoでnginxにrsyncのパスワードなしでの実行権限を付与

```bash:visudo
%nginx ALL=(soushin) NOPASSWD:/usr/bin/rsync
```
ALL=(all)ってなってることが多いのに(soushin)とした理由は
allにしたらrootにもなれちゃうでしょ！危ないでしょ！ということ。

20170518追記：
実際にはrsyncなんていう恐いコマンドを許可せずに
（soushinユーザで何でもかんでもrsyncできるようになってしまう）
スクリプトファイルの方を許可するのが良かとですが
なにしろ開発サーバと同期する先が本当は20か所ぐらいあるので
こうしてしまった…
（スクリプトファイルの設計で何とかしろよというツッコミは甘受）

##結果：
コンソールからPHPを実行 → 成功
WEBブラウザからPHPを実行 → エラー
###エラー内容
sudoをつけない → sshの秘密鍵のパスが通らないのでネットワーク系のエラー番号12が出る → logにはその旨出力される
sudoをつける → そもそもsudoが実行できない → rsyncのエラーではないのでrsyncのlogにはエラー出力されない

##原因：
nginxユーザにそもそも端末がないため。
コンソール上で曲がりなりにも成功したのは、
コンソール自体がnginxの疑似端末として機能したから。
WEBサーバ経由では端末が無いので失敗する。

##対策：
sshを通すだけなら -t オプションをつけることで
端末があるように見せかけることができるのだが、
rsync内でsshを走らせているのでこの方法では成功しなかった
（だからハマったのだが）。

よって、sudo visudoにて

```bash:visudo
 Defaults:nginx　　!requiretty
```
の1行を追加。
これで
端末のないnginxユーザに疑似端末が付与される

端末のないnginxユーザでもsudoできるようになる。
(rryuさま、ご指摘ありがとうございます)

ちなみにスクリプトファイルにSUIDの付与では上手くいかなかった。

##おまけ
PHP上でシェルスクリプトを動かすなら、
shell_exec()、exec()、passthru()といろいろあるが
得られる出力結果がちょっとずつ違うので必要に応じてお好みで。
あと、rsyncをお試しになるときは
--dry-run(-n)オプションが疑似実行結果を返してくれるだけなので
いきなりrsyncが走り出すこともなくて便利。
SublimeText3でいきなりCPU100%

# 環境
MacOS Sierra 10.12.5
SublimeText3 build 3126

# 起こったこと
CPU100%超え。再起動しても、プラグイン消しても治らず。。。

# 起こったタイミング
どのタイミングでなったのか定かではないが、composerでいれたvendor内のファイルを開いた時？

# 調査
Console.appを開いて何かヒントがないか一応見た。が「... thread 34986 caught burning CPU! ....」以外の手がかり無し？
ちなみにこんなのもでていた「Updating RESOURCE_NOTIFY report statistics for RESOURCE_NOTIFY : EXC_CPU_USAGE : NON-FATAL : Sublime Text」

# 対応
一時しのぎだが「Preferences > Settings」に「"index_files": false」を追加。

# 所感
[index_files](http://qiita.com/lunatea/items/7101572e159f98369bc9#index_files "index_files")にfalseとするよりも、該当ディレクトリを特定し、index_exclude_patternsで除外した方がよい。

# 参考
[PHP 100% CPU usage with Sublime Text 3](http://stackoverflow.com/questions/28644612/php-100-cpu-usage-with-sublime-text-3#answer-33843873)
[Sublime Text 3 File Indexing](https://www.sublimetext.com/blog/articles/file-indexing)
[How can I exclude a folder from indexing in Sublime Text, while still showing it in the sidebar?](http://stackoverflow.com/questions/30954728/how-can-i-exclude-a-folder-from-indexing-in-sublime-text-while-still-showing-it)
素人の覚書：ファイルを開く方法(GetOpenFileName)

##
Excelシートに他のブックやCSVのデータを取り込む方法ってたくさんあるわけで、一番初歩的な手順だと**外部データの取込**の手順をマクロで設定する。という手順でしょうか。さらに原始的なら、データを**全コピー -> ここに貼り付ける**とか位置指定のあるシートとかも見たことがあります。文字列にしないと作った人にえらい怒られるという理不尽に耐え、いくつか解決策を考えてみました

###最初に知った方法###

```vbnet:Excel.vba
dim varFileName

varFileName = Application.GetOpenFilename(FileFilter:="CSVファイル(*.csv),*.csv", _
          Title:="CSVファイルの選択")
    If varFileName = False Then
        Exit Sub '存在しなかったらプロシージャ終了
    End If
```
最初はこれをボタンとかに設定して、ファイルを開くようにしてました
あとあと思ったのですが、ファイルを指定したのに「存在しなかったら」って過程は必要なのかと

###FSOを使ってみた###

```vbnet:Excel.vba
Dim FSO As Object
Dim book
Dim Path
Dim pbx as workbook

Set FSO = CreateObject("Scripting.FileSystemObject")
Set Path = Cells(3, 8) 'フォルダまでの絶対パスを突っ込んだりするのですが、これって何なんですかね？
If FSO.FolderExists(Path) Then
Else
MsgBox "処理停止：フォルダが存在しません"
Exit Sub
End If
    If Dir(Path & "*") <> "" Then
    pbx = Application.GetOpenFilename("book, *xls?")
        Workbooks.Open pbx
        pbx = Dir(pbx)
     Else
     MsgBox "処理停止：ファイルが存在しません"
     Exit Sub
     End If
```

なんとなくFSOとか呼び出したらかっこよく見えたので、どこかのサイトからいただいて、自分用に少し改造しています。かっこつけなので、Pathの必要性とかが分かってません(入れないとエラーになる)

##原点回帰##
結局ファイル開くだけなので一緒じゃね？と思い、原点回帰します

```vbnet:Excel.VBA
Dim md
Dim wbs As Workbook
md = Application.GetOpenFilename("book, *xls?") '展開するファイルを選択
md = Dir(md)
    '既に開いていないかチェック
For Each wbs In Workbooks
    If wbs.Name = md Then
        md = wbs.Name'既に開いてるときはファイル名を変数に格納
        GoTo jumpin
    Else: End If
Next wbs
Workbooks.Open md
jumpin:
'以下開いた後のあれこれ
```

自分なりに工夫したのは、***既に開いてるファイルの時どうするか？***ってこと
この処理を入れないと、「2重に開いています」となるわけで、そうならないようにどうするかを考えて、***指定したファイルが既に開かれているときはファイル名を取得し、オープン処理をジャンプさせる***というアイデアでした
RからExcelで文字化けしないCSVを出力する

とりあえずMacでしか確認してません。

# ExcelでUTF-8のCSVを開くと文字化けする

例えば次のようなデータフレームをCSV出力したいとする。

```r
df <- data.frame(a = letters[1:3],
                 b = c("あ", "い", "う"))
```

これをそのまま`write.csv()`で出力するとUTF-8のCSVになるので、Excelで開くと文字化けする。

```r 
write.csv(df, "test.csv")
```

![スクリーンショット 2017-05-17 12.38.23.png](https://qiita-image-store.s3.amazonaws.com/0/109348/c60ff178-cf11-d4ce-92f5-7253445e90ed.png)

ExcelはUTF-8のCSVをそのままでは開けない。

# 対策

## Shift-JISで出力する

### 書き込み

```r 
write.csv(df, "test.csv", fileEncoding = "CP932")
```

なんだか負けたような気がするがとりあえずExcelで開いても文字化けしない。

### 読み込み時の注意

ただし読み込むときに再びエンコーディングを指定する必要がある。

```r 
read.csv("test.csv", fileEncoding = "CP932")
```

`readr::read_csv`でもエンコーディングの指定ができるけど少しやり方が異なるので注意。

```r 
readr::read_csv("test.csv", locale=readr::locale(encoding="CP932"))
```

## BOM付きのCSVを出力する

### 書き込み

これもなんだか負けたような気がするけど扱いは多少楽になる。

`readr::write_excel_csv()`で出力すれば自動的にBOM(Byte Order Mark)付きのUTF-8で出力される。

```r 
readr::write_excel_csv(df, "test.csv")
```

### 読み込み

R 3.0.0からはBOM付きUTF-8でも普通に読めるので、`read.csv()`、`read_csv()`ともにエンコーディング指定なしで特に問題は発生しない。確実にBOM殺したかったら`UTF-8-BOM`を指定するという手段もある様子(cf. [R 3.0.0の大事な変更点 - Qiita](http://qiita.com/kohske/items/2d21344ba11d030c3cf0))。
HTMLで引用文を書くいい方法ないかな　～blockquote要素にセクショニング・ルートの小話を添えて～

#引用文を書きたい気分の時もある
そんなときに、今まではこう書いていました。

```html:今まで書いていたコード
<body>
<div class="article">
  <h1>フエキ糊について</h1>
  <p>不易糊工業株式会社より公式の説明文。</p>
  <div id="quote">
    <h2>フエキでんぷんのり</h2>
      <h3>主原料がとうもろこしでんぷん100％でできています。</h3>
        <p>
        園児や学童に安心して使ってもらえる、主原料とうもろこしでんぷん１００％。<br>
        ホルマリンは一切使用しておりません。<br>
        強力な初期粘着性、すぐれた塗布性、長期にわたり安定した品質。高品質なでんぷんのりです。
        </p>
  </div>
  <h2>フエキ糊のヘラについて</h2>
  <p>160g入りのみに付属。60g入りには付属していない。</p>
</div>
</body>
```

お恥ずかしながら、とりあえずdivで囲っておけ精神でコードを書いていたのでこんなことに…。
そこで、引用文を示す**\<blockquote>**という要素があります。

##blockquote要素
[MDNの説明ではこうあります。](https://developer.mozilla.org/ja/docs/Web/HTML/Element/blockquote)
>HTML \<blockquote> 要素 (HTML ブロック引用要素) は、内包する要素のテキストが引用文である事を示します。通常、字下げを伴ってレンダリングされます (成形方法については「注意」の項を参照して下さい)。cite 属性により引用元の文書の URL を、\<cite> 要素により引用元の文書のタイトルなどを明示可能です。

早速、blockquoteを適用してみましょう。

```html:blockquoteを適用したコード
<body>
<div class="article">
  <h1>フエキ糊について</h1>
  <p>不易糊工業株式会社より公式の説明文。</p>
  <blockquote>
    <h2>フエキでんぷんのり</h2>
      <h3>主原料がとうもろこしでんぷん100％でできています。</h3>
        <p>
        園児や学童に安心して使ってもらえる、主原料とうもろこしでんぷん１００％。<br>
        ホルマリンは一切使用しておりません。<br>
        強力な初期粘着性、すぐれた塗布性、長期にわたり安定した品質。高品質なでんぷんのりです。
        </p>
  </blockquote>
  <h2>フエキ糊のヘラについて</h2>
  <p>160g入りのみに付属。60g入りには付属していない。</p>
</div>
</body>
```

わざわざdivにidを付けて区別する必要もなく、さらには表示の際に字下げをしてくれます。
もちろんCSSによる装飾の変更も可能です。

HTML5に基準するのであれば、\<div class="article">もセクション要素\<article>と変えられるのでこうなります。

```html:blockquoteを適用しHTML5基準にしたコード
<body>
<article>
  <h1>フエキ糊について</h1>
  <p>不易糊工業株式会社より公式の説明文。</p>
  <blockquote>
    <h2>フエキでんぷんのり</h2>
      <h3>主原料がとうもろこしでんぷん100％でできています。</h3>
        <p>
        園児や学童に安心して使ってもらえる、主原料とうもろこしでんぷん１００％。<br>
        ホルマリンは一切使用しておりません。<br>
        強力な初期粘着性、すぐれた塗布性、長期にわたり安定した品質。高品質なでんぷんのりです。
        </p>
  </blockquote>
  <h2>フエキ糊のヘラについて</h2>
  <p>160g入りのみに付属。60g入りには付属していない。</p>
</article>
</body>
```

#blockquoteはセクショニング・ルート
内容のセクションや見出しがアウトラインに一切影響を与えない要素を**セクショニング・ルート**と呼ばれます。
blockquoteを含めた、次の5つの要素が**セクショニング・ルート**として定義されています。

- body要素
- blockquote要素
- fieldset要素
- figure要素
- td要素

**引用**を示すblockquote要素は、**内容のセクション・見出しは引用された文**であり、**元のアウトラインとは関係が無い**ため、**セクショニング・ルート**として扱われるのですね。

##となるとアウトラインはどうなる？
このコードのアウトラインはどうなるのでしょうか？

```HTML:
<body>
<article>
  <h1>フエキ糊について</h1>
  <p>不易糊工業株式会社より公式の説明文。</p>
  <blockquote>
    <h2>フエキでんぷんのり</h2>
      <h3>主原料がとうもろこしでんぷん100％でできています。</h3>
        <p>
        園児や学童に安心して使ってもらえる、主原料とうもろこしでんぷん１００％。<br>
        ホルマリンは一切使用しておりません。<br>
        強力な初期粘着性、すぐれた塗布性、長期にわたり安定した品質。高品質なでんぷんのりです。
        </p>
  </blockquote>
  <h2>フエキ糊のヘラについて</h2>
  <p>160g入りのみに付属。60g入りには付属していない。</p>
</article>
<body>
```

この部分は、blockquote要素で囲まれているため、**アウトラインには影響しない見出しです。**

```HTML:
<h2>フエキでんぷんのり</h2>
 <h3>主原料がとうもろこしでんぷん100％でできています。</h3>
```

また、body要素もセクショニング・ルートのため、アウトラインに影響されません。
なので、アウトラインはこうなります。

```
1.フエキ糊について
　1.フエキ糊のヘラについて
```
git reset を取り消す


```
git reset --soft abac987
```

でファイルを戻そうとすると、戻すべき場所を間違えた。
なので `git reset` をなかったことにする。

# `git reflog`

![スクリーンショット 2017-05-17 12.38.50.png](https://qiita-image-store.s3.amazonaws.com/0/109241/d1bbcea0-b590-ad49-7c1b-042635b034b1.png "スクリーンショット 2017-05-17 12.38.50.png")

これで戻したいところの場所を調べて

```
git reset --soft HEAD@{1}
```
Dockerfileのアンチパターンと軽量化方法

# 前書き
Dockerfileとして基本的な部分も守らずchefからそのまま移行したようなDockerfileでDockerImageを作成している案件があった。その案件で使用しているDockerImageのサイズが約3GBと肥大化していた。

基本的な変更で約30%軽量化できたため備忘録としてやったことを記載する。

# 対象とする環境
CentOS6+PHP7+apache2.2　という構成

# yumのcacheを削除する。

Dockerfileで yum install時には以下のようになっていた

```
yum install -y wget vim ....
```

これは単純に

```
yum install -y wget vim ... \
  && rm -rf /var/cache/yum/* \
  && yum clean all
```

でyum のcacheを消してあげれば良い。

# ソースインストール時の中間ファイルを削除する

なぜかソースインストールでgitをインストールしていた。
(しかも1.9.0 2014年のものである...)

```
 RUN cd /usr/local/src \
     && wget "https://www.kernel.org/pub/software/scm/git/git-1.9.0.tar.gz" \
     && tar zxf /usr/local/src/git-1.9.0.tar.gz \
     && cd /usr/local/src/git-1.9.0.tar.gz}/ \
     && ./configure \
     && make && make install \
```

dockerなので make uninstallとかもしないし make cleanで中間ファイルを削除してあげればいい


```
 RUN cd /usr/local/src \
     && wget "https://www.kernel.org/pub/software/scm/git/git-1.9.0.tar.gz" \
     && tar zxf /usr/local/src/git-1.9.0.tar.gz \
     && cd /usr/local/src/git-1.9.0.tar.gz}/ \
     && ./configure \
     && make && make install && make clean \
```

# 不要なtar.gzとかの削除
お気付きだろうか。上記で落としてきたgit.tar.gzを削除していないことを


```
 RUN cd /usr/local/src \
     && wget "https://www.kernel.org/pub/software/scm/git/git-1.9.0.tar.gz" \
     && tar zxf /usr/local/src/git-1.9.0.tar.gz \
     && cd /usr/local/src/git-1.9.0.tar.gz/ \
     && ./configure \
     && make && make install && make clean \
     && rm /usr/local/src/git-1.9.0.tar.gz
```

のように削除する。
気をつけないと行けないのは同一レイヤで行うこと。
別レイヤで行うと削除した。というレイヤが作られるので逆にサイズが増加する。

# レイヤの結合
Dockerfileの可読性とのトレードオフだがレイヤ結合出来るものは 
``` \ ``` と　``` && ```　で結合すればよい。

# サイズの削減
上記を行っただけで 3GB -> 2.1GBと約30%削減できた。  
(それでも大きい)
理由としてはchef時代のものを精査せず 不要なパッケージやライブラリまでインストールしているため。
現行で動作しているコンテナなので削除できるかどうかの判断ができずかなりつらい所

# アンチパターンまとめ
1. cacheを削除しない
2. 中間ファイル削除しない
3. レイヤ結合しない
4. chefなど昔の資産に引っ張られてライブラリの精査をしない

# その他
たとえばalpineなど軽量のイメージを使用して、必要のあるパッケージだけ使用すればかなり軽量化はできると思われるが、それを良しとしない人間が多いと推し進めていくのは大変である。
どんな技術でもそうだが本質を見失ってとりあえず使えればいいやで導入すると後からメンテナンスする人が困る。
新しい技術を導入するのもいいが、本質を理解した上で適切に使用していく必要がある

# 参考文献
[軽量なDockerイメージで CIのビルド時間を短くしてみる // Speaker Deck](https://speakerdeck.com/horie1024/qing-liang-nadockerimezide-cifalsebirudoshi-jian-woduan-kusitemiru)
[Dockerイメージの最適化 - ワザノバ | wazanova](http://wazanova.jp/items/1454)
[Dockerイメージのレイヤー構造について - めもめも](http://enakai00.hatenablog.com/entry/20140802/1406958412)
SQL Serverでバックアップを復元したときにログインできなくなった

SQL Serverで他のサーバーのバックアップを復元したとき、ログインできなくなった

復元したデータベースのユーザーとサーバーのログインのユーザーのマッピングが不整合となっているため

ログインでユーザーマッピングを行おうとしても
「ユーザー、グループ、またはロールは現在のデータベースに既に存在します。」
というメッセージが表示されマッピングできない

不整合のあるユーザーの調べ方

```
Use [データベース名]
EXEC sp_change_users_login 'Report'
```

修正方法

```
Use [データベース名]
EXEC sp_change_users_login 'Update_One', 'データベースのユーザー名', 'ログインユーザー名'
```

上記方法は将来サポートされなくなるようです。以下の方法で修復可能です。

```
Use [データベース名]
ALTER USER データベースのユーザー名 WITH LOGIN = ログインユーザー名
```
Goでpkg/errorsを使ってスタックトレースを残しつつエラーハンドリングもする


[github.com/pkg/errors](https://github.com/pkg/errors)を使うと、errorオブジェクトをラップすることでスタックトレースを付加できるので便利です。

errorの中のスタックトレースは、 `"%+v"` フォーマット指定で出力できます。

また、errors.Causeを使ってエラー原因を取り出すことができるので、これを利用して関数の呼び出し側からエラー原因による分岐を行うことができます。

#エラーを投げる側

```go
package piyo

import (
	"github.com/pkg/errors"
	"strings"
)

var (
	// エラー定義
	NotFound = errors.New("not found")
	UnexpectedID = errors.New("unexpected id")
)

func Find(id string) ([]Piyo, error) {
	n, err := strings.Atoi(id)
	if err != nil {
		return nil, errors.WithStack(UnexpectedID)
	}
	p, err := fetch(n)
	if err != nil {
		return nil, errors.WithStack(NotFound)
	}
	return p, nil
}
```

#エラーを受ける側

```go
package main

import (
	"fmt"
	"os"
	"github.com/kaizoa/piyo"
	"github.com/pkg/errors"
)

func main() {
	piyos, err := piyo.Find("foo")
	// エラーに応じてメッセージ変える
	if err != nil {
		switch errors.Cause(err) {
		case piyo.NotFound:
			fmt.Fprintln(os.Stderr, "Piyoはみつかりません")
		case piyo.UnexpectedID:
			fmt.Fprintln(os.Stderr, "PiyoのIDが間違ってます")
		default:
			fmt.Fprintln(os.Stderr, "不明なエラーが発生しました")
		}
		panic(err)
	}
	for _, p := range piyos {
		fmt.Printf("%+v", p)
	}
}
```

これでjavaのtry~catchのようにswitch文を使ってエラー分岐ができます。
sample関数の再確認

昔自分用にメモったのを修正して公開メモに。

ヘルプの概略
------------

### Usage

``` r
sample(x, size, replace = FALSE, prob = NULL)
```

### Arguments

`x`: サンプリング元のデータ。長さが1もしくはそれ以上のベクトル。詳細は後述。

`size`: サンプリング回数。非負の整数で指定。

`replace`: サンプリングする際，同一の要素を繰り返しサンプリングするのを許容するかどうか。論理値で指定。

`prob`: サンプリング元のデータについて，サンプリングする際の重み付けを確率のベクトルで指定。

### Details (気になるところだけ)

-   `x`の長さが1で，かつそれが1以上の数値の場合，サンプリングは`1:x`から実施される
-   `size`を指定しないと，`length(x)`回サンプリングする
-   `x`に正の非整数が使われると端数を切り捨てる。ただし，`.Machine$integer.max`を超えない整数とする
-   `prob`はサンプリングする際の重み付けを確率で指定
    -   別に合計が1にならなくてもOK
    -   ただし非負かつ全てが0ではないこと
    -   `replase = TRUE`を指定すると，Walker's alias methodを使用するとのこと。

いろいろやってみる
------------------

以下，適当に色々やってみます。seedを固定します:

``` r
set.seed(57)
```

### 1:6からサンプリング

``` r
sample(1:6)
#>  [1] 2 3 1 4 6 5
sample(6)
#>  [1] 6 2 3 1 5 4
```

上述のとおり，これは同値。

### 固定範囲からサンプリング

``` r
sample(3:8)
#>  [1] 8 5 3 4 6 7
```

### 非整数の場合

``` r
sample(6.8)
#>  [1] 5 4 6 2 3 1
sample(2.6:7.4)
#>  [1] 2.6 6.6 3.6 4.6 5.6
```

非整数を`x`に指定した場合はこのようになります。まず，`length(x) = 1`のとき，端数を切り捨てた整数値として振る舞います。しかし，`2.6:7.4`のようにすると，最初の値から1ずつ増加していった値からサンプリングしてきます。これはどちらかというと`:`の仕様です:

``` r
2.6:7.4
#>  [1] 2.6 3.6 4.6 5.6 6.6
```

詳しくは`:`のヘルプを参照してください。

### サンプリングする数を指定

``` r
sample(1:100, 10)
#>   [1] 99 21 96  1 94  3 68 58 60 88
```

そのままです。なお，`replace`には何も指定していないのでデフォルト値の`FALSE`で実行されます。そのため`x`の長さが`size`の値より小さいとエラーが返ってきます。

### replaceを許容する

``` r
sample(1:6, replace = TRUE)
#>  [1] 5 1 2 6 5 2
sample(0:1, 100, replace = TRUE)
#>    [1] 0 0 1 1 0 0 1 1 0 1 1 1 0 1 0 1 1 0 0 0 0 1 1 0 1 1 0 1 0 1 1 0 0 0 0
#>   [36] 0 0 0 0 1 0 0 1 0 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 0 1 1 0 0 1 1 1
#>   [71] 0 0 1 1 1 1 1 0 0 1 0 0 1 0 0 0 1 1 1 0 0 0 0 1 1 1 1 0 1 0
```

そのままです。

### 確率で重み付けをする

``` r
kosaki <- sample(1:3, 100, replace = TRUE, prob = c(0.5, 0.25, 0.25))
kosaki
#>    [1] 2 3 1 2 2 1 1 1 1 3 1 3 3 1 3 1 2 2 3 3 1 1 2 3 1 1 1 2 2 2 2 2 1 3 2
#>   [36] 1 3 1 2 1 1 3 1 1 2 1 3 1 2 3 1 1 1 1 3 1 3 3 3 1 3 2 2 2 1 1 3 1 2 3
#>   [71] 1 1 3 3 1 1 1 1 2 1 3 3 1 1 1 3 2 1 1 1 3 2 1 2 3 1 2 1 3 1
table(kosaki)
#>  kosaki
#>   1  2  3 
#>  48 24 28
```

このように重み付けできます。あと上述のように，`prob`は別に合計が1にならなくてもOKです:

``` r
kutori <- sample(1:3, 100, replace = TRUE, prob = c(50, 25, 25))
kutori
#>    [1] 1 3 1 2 1 3 2 3 1 3 2 2 1 3 3 1 3 1 2 2 2 3 1 1 1 1 1 1 1 2 1 3 3 3 3
#>   [36] 1 1 1 1 1 2 1 2 2 2 1 2 2 1 3 3 3 1 3 1 2 2 1 1 2 3 2 2 1 2 1 2 1 2 1
#>   [71] 1 2 1 1 1 1 3 1 3 3 3 1 2 1 1 1 1 1 3 1 1 1 2 1 2 1 1 2 1 3
table(kutori)
#>  kutori
#>   1  2  3 
#>  50 27 23
```

なお，`length(x)`と`length(prob)`が一致しないとエラーを返しますので注意してください。

**Enjoy!**
上限付きデータの平均推定

# 問題設定
- センサーである時間を何個も測定している
- この時間は、指数分布に従うことが分かっている
- センサーの不具合で、正しい時間より短い時間を返すことがある。ただし、不具合が発生したかどうかはわかる
- 測定値から元の時間の平均を知りたい

# 計算式
その推定値となる確率が最大となるように求めればよい。具体的には、次式。ただし、不具合の場合、上限に達したとみなす。

> $ 元の平均 = \frac{全データの合計}{データ数 － 上限に達した数} $

# Python で確認

```py3:python3
import numpy as np
np.random.seed(1)
n = 100000 # データ数
a = np.random.exponential(3, n) # 元の分布
print('元の分布の平均 %.3f'%a.mean())
b = np.random.uniform(2, 10, n) # 上限
c = np.min((a, b), 0) # 上限ありの分布
nn = (c==b).sum() # 上限に達した数
print('元の分布の推定平均 %.3f'%(c.sum()/(n-nn)))
>>>
元の分布の平均 2.996
元の分布の推定平均 2.996
```

以上