OmniAICreator/Qiita-1.07M huggingface dataset:
各種仮想スイッチのMACアドレス登録上限数を調べてみる

## OvS

ソースコードを見る限りデフォルトの上限は2048みたい。
https://github.com/osrg/openvswitch/blob/master/lib/mac-learning.h

```
#define MAC_DEFAULT_MAX 2048
```

## Cisco Nexus 1000v

やっぱり1000オーダ程度の様子。
http://www.cisco.com/cisco/web/support/JP/docs/SW/VirtualNWing/Nex1000VInterCloud/CG/003/b_Cisco_Nexus_1000V_InterCloud_Layer2_Config_Guide_Release_5_2_1_IC_1_1_1_chapter_01.html

```
VEM の各 VLAN に対するフォワーディング テーブルには、最高 4094 個の MAC アドレスを格納できます。
単一のインターフェイスで設定できるスタティック MAC アドレスの上限は 1024 です。
Cisco Nexus 1000V では、VSM でのユーザ設定のスタティック MAC アドレスが 2000 までサポートされます。
Cisco Nexus 1000V では、VSM でのプライベート VLAN MAC アドレスが 2000 までサポートされます。
```

## fd.io VPP

20kオーダくらいなら余裕らしい。実際測ってみたい。

![image](https://qiita-image-store.s3.amazonaws.com/0/133883/72dc8d6a-c8b8-70b6-e77b-f4e8f3403bdb.png)
https://dpdksummit.com/Archive/pdf/2016Germany/DPDK-2016-DPDK_FD_IO_Introduction.pdf

（あとで追記するかも）
javascriptの例外処理

想定外の例外的な事象が現れた時の対処法。

# errorオブジェクト

``` js
const error = new Error("エラーメッセージ");
```

# try...catch文
tryで何かしらの処理を実行して、そこで例外を吐き出した時にcatchがその例外をキャッチする。

```js
try {
  console.log("正常の動作"　);
} catch(error) {
  console.log("エラー内容："　+ error);
}
```

# 例外のスロー　
throwを呼び出すと実行中の関数は即座に停止される。

例)2つの値を足し合わせて100以上なら例外をスローする

``` js
const add = (a,b) => {
  const add = a + b;
  if (100 > add) {
    throw new Error("100以上なのでエラー");
  } else {
    cosole.log("100より下");
  }
};
```

# try...catch...finally
エラーであろうとなかろうがfinally構文に書いた処理は必ず実行される

```js
try {
  console.log("処理中・・・");
  throw new Error("エラーです");
  console.log("エラーが起こるとスローされてここまで処理が実行されない");
} catch(error) {
  console.log("エラーが起きた！！！！");
} finally {
  console.log("どのような結果であれ、必ず実行される。");
}
```
px -> vw 早見表

# px -> vw 早見表
|			|	640px幅デザイン時	|	750px幅デザイン時	|
|	------------:		|	------------:	|	------------:	|
|	10	px	|	1.57vw	|	1.34vw	|
|	11	px	|	1.72vw	|	1.47vw	|
|	12	px	|	1.88vw	|	1.6vw	|
|	13	px	|	2.04vw	|	1.74vw	|
|	14	px	|	2.19vw	|	1.87vw	|
|	15	px	|	2.35vw	|	2vw	|
|	16	px	|	2.5vw	|	2.14vw	|
|	17	px	|	2.66vw	|	2.27vw	|
|	18	px	|	2.82vw	|	2.4vw	|
|	19	px	|	2.97vw	|	2.54vw	|
|	20	px	|	3.13vw	|	2.67vw	|
|	21	px	|	3.29vw	|	2.8vw	|
|	22	px	|	3.44vw	|	2.94vw	|
|	23	px	|	3.6vw	|	3.07vw	|
|	24	px	|	3.75vw	|	3.2vw	|
|	25	px	|	3.91vw	|	3.34vw	|
|	26	px	|	4.07vw	|	3.47vw	|
|	27	px	|	4.22vw	|	3.6vw	|
|	28	px	|	4.38vw	|	3.74vw	|
|	29	px	|	4.54vw	|	3.87vw	|
|	30	px	|	4.69vw	|	4vw	|
|	31	px	|	4.85vw	|	4.14vw	|
|	32	px	|	5vw	|	4.27vw	|
|	33	px	|	5.16vw	|	4.4vw	|
|	34	px	|	5.32vw	|	4.54vw	|
|	35	px	|	5.47vw	|	4.67vw	|
|	36	px	|	5.63vw	|	4.8vw	|
|	37	px	|	5.79vw	|	4.94vw	|
|	38	px	|	5.94vw	|	5.07vw	|
|	39	px	|	6.1vw	|	5.2vw	|
|	40	px	|	6.25vw	|	5.34vw	|
|	41	px	|	6.41vw	|	5.47vw	|
|	42	px	|	6.57vw	|	5.6vw	|
|	43	px	|	6.72vw	|	5.74vw	|
|	44	px	|	6.88vw	|	5.87vw	|
|	45	px	|	7.04vw	|	6vw	|
|	46	px	|	7.19vw	|	6.14vw	|
|	47	px	|	7.35vw	|	6.27vw	|
|	48	px	|	7.5vw	|	6.4vw	|
|	49	px	|	7.66vw	|	6.54vw	|
|	50	px	|	7.82vw	|	6.67vw	|
|	51	px	|	7.97vw	|	6.8vw	|
|	52	px	|	8.13vw	|	6.94vw	|
|	53	px	|	8.29vw	|	7.07vw	|
|	54	px	|	8.44vw	|	7.2vw	|
|	55	px	|	8.6vw	|	7.34vw	|
|	56	px	|	8.75vw	|	7.47vw	|
|	57	px	|	8.91vw	|	7.6vw	|
|	58	px	|	9.07vw	|	7.74vw	|
|	59	px	|	9.22vw	|	7.87vw	|
|	60	px	|	9.38vw	|	8vw	|
|	61	px	|	9.54vw	|	8.14vw	|
|	62	px	|	9.69vw	|	8.27vw	|
|	63	px	|	9.85vw	|	8.4vw	|
|	64	px	|	10vw	|	8.54vw	|
|	65	px	|	10.16vw	|	8.67vw	|
|	66	px	|	10.32vw	|	8.8vw	|
|	67	px	|	10.47vw	|	8.94vw	|
|	68	px	|	10.63vw	|	9.07vw	|
|	69	px	|	10.79vw	|	9.2vw	|
|	70	px	|	10.94vw	|	9.34vw	|
|	71	px	|	11.1vw	|	9.47vw	|
|	72	px	|	11.25vw	|	9.6vw	|
|	73	px	|	11.41vw	|	9.74vw	|
|	74	px	|	11.57vw	|	9.87vw	|
|	75	px	|	11.72vw	|	10vw	|
|	76	px	|	11.88vw	|	10.14vw	|
|	77	px	|	12.04vw	|	10.27vw	|
|	78	px	|	12.19vw	|	10.4vw	|
|	79	px	|	12.35vw	|	10.54vw	|
|	80	px	|	12.5vw	|	10.67vw	|
|	81	px	|	12.66vw	|	10.8vw	|
|	82	px	|	12.82vw	|	10.94vw	|
|	83	px	|	12.97vw	|	11.07vw	|
|	84	px	|	13.13vw	|	11.2vw	|
|	85	px	|	13.29vw	|	11.34vw	|
|	86	px	|	13.44vw	|	11.47vw	|
|	87	px	|	13.6vw	|	11.6vw	|
|	88	px	|	13.75vw	|	11.74vw	|
|	89	px	|	13.91vw	|	11.87vw	|
|	90	px	|	14.07vw	|	12vw	|
|	91	px	|	14.22vw	|	12.14vw	|
|	92	px	|	14.38vw	|	12.27vw	|
|	93	px	|	14.54vw	|	12.4vw	|
|	94	px	|	14.69vw	|	12.54vw	|
|	95	px	|	14.85vw	|	12.67vw	|
|	96	px	|	15vw	|	12.8vw	|
|	97	px	|	15.16vw	|	12.94vw	|
|	98	px	|	15.32vw	|	13.07vw	|
|	99	px	|	15.47vw	|	13.2vw	|
|	100	px	|	15.63vw	|	13.34vw	|


# stylus mixin

```stylus:.styl
/*
 * font-size / view width
 * f-vieww (16/640); -> font-size : 2.5vw;
 */
f-vieww($decimal)
  font-size ( (ceil($decimal * 10000)) / 100 ) vw
```

とか、でやればええですけどね。
これにview sizeをデフォで入るようにしてやってもええですけどね。
今更聞けないクラウドセキュリティ設定 for Beginners

本稿ではクラウド利用初心者の方向けにクラウドセキュリティ設定について解説を行います。                            

#目次

- はじめに
- Port番号変更
- rootログイン禁止
- FIrewall設定
- 参考URL


#はじめに
ご自身でクラウドを構築した場合、サーバーのセキュリティはどのようにしていますか？
「まさか、そんな自分が狙われているはずがない」「ちょっと使うだけだから〜」
こんな風にセキュリティ設定がいい加減になっていませんか？
サーバーを立てたその瞬間から、世界中からネット経由であなたのクラウドは脅威に晒されています。
サーバーが乗っ取られ悪用、情報が抜き取られる可能性もあります。
後の様々なリスクを回避するためにも、サーバーの設定変更をお勧めします。

最低限次の3項目は押さえて！

- **Port番号変更**
- **rootログイン禁止**
- **Firewall設定**

#Port番号変更
**1. 既存のconfig fileのバックアップ**
これから行う様々な設定変更を行う前に既存のconfig fileをバックアップしておきます。
``$ cp /etc/ssh/sshd_config /etc/ssh/sshd_config.old``

**2. viコマンドによるPort変更**
config fileを編集します。既存設定でport22となっていますがこれを任意のポート番号に変更しましょう。
``$ vi /etc/ssh/sshd_config``
viエディタの設定変更の仕方→port項目が探すことができれば``i``(insert)で入力、見つけられなければ``/``(search)でportを入力してみてください。22番ポートから任意のportに変更できれば、``:wq``で保存します。

**3. 再起動(変更の反映)**
``$ /etc/init.d/ssh restart``で再起動させてください。

**4. 変更の確認**
今まで通りに``$ ssh root@xxx.xxx.xx.xx``でログインを試してみてください。
``$ ssh: connect to host 161.202.86.30 port 22: Connection refused``となればportが変更できています。
port変更後は``$ ssh -p(ポート指定) zzzz(任意ポート) root@xxx.xxx.xx.xx``でアクセスしてください。


#rootログイン禁止
先ほどまでは管理者アカウントであるrootからログインを行なっていました。これではrootとIPアドレスさえ判明すればログインができてしまいます。なのでここで任意のユーザーを作成し、rootでアクセスできないようにします。
**1. 新規ユーザーの追加**
``$ useradd abcde(任意の名前)``

**2. パスワード設定**

```
$ passwd abcde(新規ユーザー名)
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully
```
ここで任意のパスワードを設定します。

**3. rootログイン禁止**
ここまでできれば、新規ユーザー名と設定したパスワードでサーバーにアクセスすることができるのでrootログインを禁止します。rootログイン設定は先ほどのconfig file上にあるので、先ほどport番号を変更した手順を参考にしてください。
( ``$ vi /etc/ssh/sshd_config``でviエディタを開き、``PermitRootLogin ___`` 項目を探し、``PermitRootLogin yes``と入力、``$ /etc/init.d/ssh restart``で再起動させてください。)

**4. 変更の確認**
一度ログアウトし、新規ユーザー名とパスワードでアクセスしてみましょう！
``ssh -p(ポート指定) zzzz(任意ポート) abcde(名前)@xxx.xxx.xx.xx``
パスワードの入力が求められるので、先ほどご自身で設定したパスワードを入力してください。


#Firewall設定
ポート番号の変更・rootユーザーでのログインをしてきましたが、最後にFirewallを設定します。
Firewallを設定することで使用するポートの制限などよりサーバーの安全性を高めます。
ufw(Uncomplicated Firewall)というpythonで実装されているfirewallを今回は使用します。

**1. ufwのインストール**
``$ sudo apt-get install ufw`` (もともとufwが入っていない場合インストール。)

**2. 指定ポート開放**
使用するポートを解放する。例えばHTTP(80), HTTPS(443)など。

```
$ ufw allow 80
Rules updated
$ ufw allow 443
Rules updated
```

**3. 指定ポート以外を閉鎖**
デフォルトで通信が許可されていないポートは閉鎖、変更設定を有効にする。

```
$ ufw default deny
Default incoming policy changed to 'deny'
(be sure to update your rules accordingly)

$ ufw enable 
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
```
**4. Firewall設定の確認**
今回行ったFirewallの設定が有効化されているかステータスを確認する。

```
$ ufw status
Status: active
To                         Action      From
--                         ------      ----                 
80                         ALLOW       Anywhere                  
443                        ALLOW       Anywhere                   
```

これで基本的な設定はできました。
Have a great cloud life :) 



####参考URL
__________________
vi エディタコマンド集：http://net-newbie.com/linux/commands/vi.html
代表的なポート番号：http://eng-entrance.com/network-port
Ubuntu ufw設定：http://exoself.hatenablog.com/entry/2013/04/24/170540
browserifyでjqueryを読み込むときに詰まったポイント

browserifyでjqueryを読み込むときにだいぶ、苦労したのでメモしておきます。
詰まったポイント


browserify公式ページ
http://browserify.org/#install

1.テスト用のディレクトリを作る。
```$ mkdir test```

その中に移動して、

2. package.json作成
```$ npm init```

下のindex.htmlを作成
```
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src="./bundle.js"></script>
</body>
</html>
```

3.jquery をインストール
```npm install jquery --save```

4.テスト用スクリプトを書く（main.js）。

```
var $ = require('jquery');
 
$(function () {
  alert("ok")
});
```

ここ↑で詰まりました。

#####詰まったポイント

1.jqueryの場合は、「$]にjqueryモジュールを代入しないと、
その後、jqueryとして使えない。

2.javascriptは、このmain.jsの中に書く。
勘違いして、index.htmlの中に書いていました。


5.browserifyをインストール
npm install browserify --save

6.browserify実行。(bundle.js作成)
./node_modules/.bin/browserify main.js -o bundle.js

※グローバールインストールしていないため、直接node_modulesの中に、
browserifyを呼びにいく。

7.下の一文をindex.htmlで読み込むと、jqueryが使えるようになる。
<script src="bundle.js"></script>















参考にさせて頂いた記事
npmとBrowserifyでjQueryを管理する（to-R様）
http://blog.webcreativepark.net/2015/12/24-221725.html
SurfaceView で描画されないとき

ゲームプログラミングなどで SurfaceView に描画すると早いと思って、使ったは良いがなぜか描画されず、ネットで記事を検索してもうまく行かなかくてハマった。
これはその問題を解決するまでのドラマである。

ｗ

まず、考えておくこととして、ゲームプログラミングの本を買った方が良い（もしくはスクール、セミナー受講）。体系的に書いてあるし、動くコードが掲載されている。ゲームプログラミングとアンドロドアプリ特有の事情が絡んでいるので、初学者には難しい。

最初のハマりポイント。

Q. SurfaceView が 再描画イベントを感知しないので、描画できません！

A. まず、Android OS は UIスレッドの中で再描画しません。別スレッドをおこしてください。

そもそも、SurfaceView はゲームなどの高速描画を行うための View なので、わざわざ invalidate() をしたりして、 UI イベントを送って再描画するような使い方は通常はしないと思います。

なぜなら、UI イベントを送るというお行儀の良いやり方は、「システムの都合の良いときに描いてくれればあり難き幸せ」と言っているのと同じで、速度が犠牲になっているからです。
なので、ゲームでもそれほど速度が重要でないチェスや将棋のようなゲームにはそのような描画の仕方で良いといえます。その場合は、通常の View を使うはずです。

それでも、なんらかの事情で SurfaceView を使って UI イベントを送って描画させたいケースがあるとすれば、SurfaceView のサブクラスで setWillNotDraw(false); としなければなりません。
その後は、普通にスレッドを起こしてループを書き、そのなかで invalidate()　を呼び出して、SurfaceView のサブクラスのOnDraw()を呼び出すようにしてください。

もちろん、この描画の方法は、SurfaceView を使っているからといって速くなりません。

Q. SurfaceView で描画専用のスレッドを起こして、unlockCanvasAndPost() を呼び出したのに、まだ実行できません！

A. これにはいくつかの原因があります。

1. まず、SurfaceView のサブクラスに SurfaceHolder.Callback というインターフェースを継承し、surfaceChangedというメソッドから描画スレッドを開始すること。
2. Thread を開始するときに呼び出すのは run() ではありません。start() にしないと非同期になりません！
3. lockCanvas -> 描画 -> unlockCanvasAndPost を行って描画する。

ちなみに、SurfaceView を使って描画イベントすっ飛ばして自分で描画してみたところ、ゲームの動きが非常にスムーズになりました。
Oracle Database 11.2, 12.1, 12.2の簡易セットアップ

Oracle Database 12c Release 2がついに出ました。

[Oracle Database Software Downloads | Oracle Technology Network | Oracle](http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html)

手元のPC上のVirtualBoxでサクッとセットアップする手順を自動化したので公開します。Oracle Database 12.2だけではなく、12.1や11.2用の手順も作成しました。

* [shakiyam/vagrant-oracle12.2: Vagrant + Oracle Linux 7 + Oracle Database 12c Release 2 (12.2.0.1) シングル環境の簡易セットアップ](https://github.com/shakiyam/vagrant-oracle12.2)
* [shakiyam/vagrant-oracle12.1: Vagrant + Oracle Linux 7 + Oracle Database 12c Release 1 (12.1.0.2) Enterprise Editionシングル環境の簡易セットアップ](https://github.com/shakiyam/vagrant-oracle12.1)
* [shakiyam/vagrant-oracle11.2: Vagrant + Oracle Linux 7.4 + Oracle Database 11g Release 2 (11.2.0.1) Enterprise Editionシングル環境の簡易セットアップ](https://github.com/shakiyam/vagrant-oracle11.2)
Rails Bootstrap3 ToolTipsが動かない時の対処法

ヘルプメッセージ等を表示する際に、tooltipを使われているサービスをよく拝見します。
同じように該当部分をホバーすると、ヘルプメッセージを表示するという用途でBootstrapのtooltipを使用したのですが、動かず...
原因を調べたらなんと、**jQuery-uiのtooltipとのコンフリクト**　。
普通に知らねーよとは思いつつも、以下に対処法をまとめました。

## jsマニフェストファイルにて、bootstrapとjquery-uiの読み込む順番を変えてあげる
```application.js
//= require jquery
//= require jquery_ujs
//= require jquery.turbolinks
//= require jquery-ui
//= require bootstrap-sprockets
//= require ckeditor/init
//= require moment
//= require bootstrap-datetimepicker
//= require fullcalendar
//= require fullcalendar/lang/ja
//= require knockout
//= require bootstrap-colorpicker.min
//= require turbolinks
//= require_tree .
```

これだけです。

中には以下のように対処されている方もいるかと思いますが、僕の場合動かなかったので読み込む順番を変えることで対応しました。

``` tooltipの初期化設定を書くファイル.js
// ui-tooltipとbootstrapのtooltipが競合して動かなくなるのを防ぐため
        $.widget.bridge('uibutton', $.ui.button);
        $.widget.bridge('uitooltip', $.ui.tooltip);
```

以上です。
プラグインのコンフリクトは見えにくいところなので、気をつけていきましょー
Javaにおける日付の期間内判定の実装のあれこれ

# これは何？
* Javaにおける日付範囲（Between）の判定する実装について考えたページ

# お題目

与えられたある2つの期間（日付）に対して、ある日付が含む又は含まれないかどうかを判定したい。
たとえば、7月20日～7月30日に対して、「8月1日は含まれない」、「7月20日、7月25日、7月30日」は含まれるものとする。
線でたとえると…

```
---●---------------------●------
   7/20                 7/30

●は、その日を含むという意味を表すことにする。
```

# 実装のやり方

## その1

```java
boolean between(LocalDate date){
  return (startDate.isBefore(date) && endDate.isAfter(date)) || startDate.equals(date) || endDate.equals(date);
}
```

## その2（よりスマート）

```java
boolean between(LocalDate date){
  return !(startDate.isAfter(date) || endDate.isBefore(date));
}
```

# 番外編

```
---○---------------------○------
   7/20                 7/30

○は、その日を「含まない」という意味を表すことにする。
```

## その1

```java
boolean between(LocalDate date){
  return (startDate.isBefore(date) && endDate.isAfter(date));
}

boolean between(LocalDate date){
  // 外からくる値をベースに考えるべきではないがシンプル
  return date.isAfter(startDate) && date.isBefore(endDate);
}
```

## その2（よりスマート？）

```java
boolean between(LocalDate date){
  return startDate.compareTo(date) * endDate.compareTo(date) < 0;
}

boolean between(LocalDate date){
  // // 外からくる値をベースに考えるべきではないがパターンとして
  return startDate.compareTo(date) * date.compareTo(endDate) > 0;
}
```

※ 元々のお題目通り（●にする）にしたければ、 ```>=``` や ```<=``` としてあげれば良い。

# 感想

* 地頭の良さがモロに出てしまうお題目。スマートな実装をできる自分になりたい。
* とはいえ、可読性が下がってしまう点はトレードオフ。（直感的な実装ではないので、読み手を「？」な状態にしてしまう）
* ある意味定番プログラムなのかもしれませんが。```java.awt.Rectangle#intersects```や```java.awt.Rectangle#intersection```などのいわゆる「あたり判定」系のロジックも同じ事が言える気がします。
C++ Builder XE4, 10.2 Tokyo > Formを名前から探す > frmPtr = (TForm *)Application->FindComponent(L"Form2");

```txt:動作環境
C++ Builder XE4
RAD Studio 10.2 Tokyo Update 2 (追記: 2017/12/28)
```

現在実装を検討している処理にて、Formの名前(String型)からTForm*ポインタを取得する必要がありそうなため方法を調べた。

- プロジェクトの構成
  - Form1 (Unit1.cpp)
  - Form2 (Unit2.cpp)
     - Caption: L"Form2"

参考 http://stackoverflow.com/questions/25610673/delphi-find-form-by-name


```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	TForm *frmPtr;

	frmPtr = (TForm *)Application->FindComponent(L"Form2");
	if (frmPtr == NULL) {
		return; // not found
	}

	OutputDebugString(frmPtr->Caption.c_str());
}
//---------------------------------------------------------------------------
```

```txt:結果
デバッグ出力: Form2 プロセス Project1.exe (5808)
```
今風のデザインのメモ

ディスプレイ：机
ウィンドウ：机の上に置いた紙
とした場合
・フラットデザイン：紙に直接書く
・マテリアルデザイン：付箋に書いて紙に貼り付ける
　※付箋の素材は紙とは限らない
　※付箋の形は四角形とは限らない
　※付箋をめくると別の付箋があるかもしれない
　※水の付箋の場合触ると波紋が広がり、薄いセロハンなら吸いつく
bashでリトライ処理(だんだんsleep時間を増やす)

```
#!/bin/bash

retry_count=5
retry_interval_seconds=10

count=1
while :
do
  command
  status=$?
  if [ ${status} -eq 0 ]; then
    exit 0
  fi
  if [ ${count} -eq ${retry_count} ]; then
    break
  fi
  sleep_seconds=$((count * retry_interval_seconds))
  count=$((count + 1))
  echo Retry after ${sleep_seconds} seconds, next count is ${count}
  sleep ${sleep_seconds}
done

echo Retry over
exit 1
```

厳密なExponential Backoffではない
【Django】外部ファイルに定義した変数/定数を読み込む方法

メモです
まず、consts.pyというファイル名で、変数/定数を定義します
ここではconsts.pyはアプリケーションディレクトリの直下に配置するものとします

```python:project/application/consts.py
PREF_CHOICE = (
    ('', '都道府県'),
    ('1', '北海道'),
    ('2', '青森県'),
    ('3', '岩手県'),
    ('4', '宮城県'),
    ('5', '秋田県'),
    ('6', '山形県'),
    ('7', '福島県'),
    ('8', '茨城県'),
    ('9', '栃木県'),
    ('10', '群馬県'),
    ('11', '埼玉県'),
    ('12', '千葉県'),
    ('13', '東京都'),
    ('14', '神奈川県'),
    ('15', '新潟県'),
    ('16', '富山県'),
    ('17', '石川県'),
    ('18', '福井県'),
    ('19', '山梨県'),
    ('20', '長野県'),
    ('21', '岐阜県'),
    ('22', '静岡県'),
    ('23', '愛知県'),
    ('24', '三重県'),
    ('25', '滋賀県'),
    ('26', '京都府'),
    ('27', '大阪県'),
    ('28', '兵庫県'),
    ('29', '奈良県'),
    ('30', '和歌山県'),
    ('31', '鳥取県'),
    ('32', '島根県'),
    ('33', '岡山県'),
    ('34', '広島県'),
    ('35', '山口県'),
    ('36', '徳島県'),
    ('37', '香川県'),
    ('38', '愛媛県'),
    ('39', '高知県'),
    ('40', '福岡県'),
    ('41', '佐賀県'),
    ('42', '長崎県'),
    ('43', '熊本県'),
    ('44', '大分県'),
    ('45', '宮崎県'),
    ('46', '鹿児島'),
    ('47', '沖縄県'),
)


```
<br>
これをviews.pyやforms.pyで以下のように読み込みます

```python:project/application/views.py
from .consts import PREF_CHOICE

....
```

これでconsts.pyに定義した変数/定数が利用できます
仮にconsts.pyに複数の変数/定数を定義しており、全てをviews.pyやforms.pyで利用したい場合は`from .consts import *`で利用することができます
スマホアプリの公開テスト配布をしてみた感想

#はじめに
どうも、個人でスマホアプリを開発している青木そらす（@open_sorasu）です。
皆さん、スマホ向けにアプリを作った時、ちゃんとデバッグやユーザーテストをしていますか？

#そもそもテストをする理由
アプリストアに並ぶという事は、<b>お客さんの目に触れる</b>わけです。
そのアプリに重大なバグがあると言うのは<b>大問題</b>なわけです。
なので、事前に<b>「話しが通じる開発者」</b>や<b>「ベータテストだと分かってる人」</b>向けにテスト配信をして
お客さんに対してストレスを与えない状況を作るべきだと考えています。
そもそも、製品として完成されてないモノです！って言いきれば
「完成してから遊ぶ人」「未完成でも触りたい人」で分類できます。

そもそも動かないモノをストアに上げてしまうと、低評価レビューが付いて印象も悪くなります。
こうなると、本来取得できたであろう顧客を逃します。
ファーストインプレッション、コアユーザーの育成、とても大事です。

と言うわけで、アプリを正式配布する前に「テスト配信」をしましょう！と言う感じで
私が実際に使用したサービスの所感をまとめていきたいと思います。

#使ったサービス
1. DeployGate（Android/iOS）
2. GooglePlayのテスト配信機能（Android）
3. Testflight（iOS）

#共通項目
1. 外部テスター、内部テスターの登録が出来る
2. 配布制限が出来る（100端末限定とか）
3. どの端末が、どのバージョンをインストールしているか分かる
4. バグ報告機能がある
5. クラッシュレポートが届く

#DeployGate
GooglePlayのテスト配信機能が入る前にお世話になっていたサービスです。
GooglePlay、AppStoreにて配布されているDeployGateアプリをインストールすることで
テストアプリのダウンロードと不具合報告が出来ます

1. 利点
 1. APKをアップロードするだけでプッシュ通知が飛ぶので分かりやすい
 2. APKのインストールを自動で行ってくれる
 3. ユーザーコメントを1か所にまとめられるので色々と楽
 4. APKページにメモ欄があるのでバグとかの管理も楽
 5. ログを仕込めば、どの端末が何でどうクラッシュしたかも取れる（リモートLogcat機能はかなり便利）
2. 欠点
 1. 色々と制限がある（有料プランで増やせる）
 2. 提供元不明アプリをインストールするので、信頼できないアプリは怖い
 3. iOSはUUIDを登録したプロビジョニングファイルが必要（エンタープライズでは出来ない、iOSユーザーからUUIDの提供が必要）
 4. DeployGateのアプリをインストールしてもらう必要がある
 5. 海外対応が不明（なんとか突破してインストールする人は沢山いたが…）
 6. 色々とリスト化されていない（端末で絞るとか、バージョンで絞るとか…昔使ってた時は無かったです）

開発者向けの機能なので、デバッグに向いていると思います。
ただし、開発者よりではない人には、少々難しい操作を要求する個所もあるので、適材適所な感じがします。

#GooglePlayのテスト配信機能
GooglePlayが提供しているテスト配信機能です。DeveloperConsoleから配布が出来ます。

1. 利点
 1. GooglePlayからダウンロードするので、安心感がある（署名は必要）
 2. フローとしては本番へのアップロードと変わらないので練習になる。
 3. そこそこ詳細なレポートを端末やバージョンによって分類することが出来る。
 4. 外国語を勝手に変換してくれるので、そこそこ読める
 5. マーケットを限定しなければ、いろんな国からレポートが飛んでくる
 6. レポート等を受け取った時に指定のメールアドレスに対して通知を送る機能などがある
2. 欠点
 1. テスター登録が必要なので、Googleアカウントが必要
 2. テスター登録の反映に1時間ぐらい掛かるので、たまにお問い合わせがくる

幅広い層にリーチするので大規模テストの場合はコチラがオススメな気がします。

#Testflight
Appleが提供するテスト配信機能です。iTunesConnectから操作できます。

1. 利点
 1. 色々な制約を無視して大勢にアプリのテストをしてもらうことが出来る（ipaをitunes越しにインストールとか、エンタープライズとか、UUIDとか、そう言うのを全部無視できる）
  1. iOSのバージョン、機種による依存を洗い出すためには必須だと思います
2. 欠点
    1. 公開したアプリには1ヵ月の起動制限が付く（過ぎるとアプリが起動しない）
    2. 外部テスターは1000人の制限がある（1アカウントに対してインストール制限はない模様）
    3. 初回アップロード時にはTestflightの審査が入る（もちろん、リジェクトあり）
        1. 審査が通った後は、任意で再審査してもらうか決められる。
        2. 大型アップデートを入れて、その内容がリジェクト対象かもしれないと思った場合は見てもらうべし
    4. 外部テスターは、認証後にTestflightのアプリを入れてもらう必要がある

iOSでテスト配信するならこれしかない！と思います。

#と言うわけで…
こう言うオープンデバッグやユーザーテストを行った結果が[「みくちゃ」](https://play.google.com/store/apps/details?id=com.sorasu.armiku&hl=ja)になります。
何をどうしたらこうなったのかは、DeployGateの藤崎さんが下記スライドでまとめてくださったので併せて見て頂ければと思います。

[DeployGateで実践！モチベーション高くヒットアプリを作る方法](https://speakerdeck.com/tnj/deploygatedeshi-jian-motibesiyongao-kuhitutoapuriwozuo-rufang-fa)

皆様の参考になれば幸いです。
[AWS] Amazon Linux の Timezone を日本標準(JST)に変更

Amazon Linux を Tokyo Region にたてるとまずはこれ。

# 1. /etc/sysconfig/clock 変更
- vi で編集

```
$ sudo vi /etc/sysconfig/clock
```
- 編集内容

```
#ZONE="UTC"             >>>コメントアウト
ZONE="Asia/Tokyo"       >>>追加
UTC=true
```


#2. シムリンク追加
- 追加

```
$ sudo ln -sf /usr/share/zoneinfo/Japan /etc/localtime
```

- これで日本時間に変わってるよ

#3. reboot
- ついでにパッケージアップデートをした方がいい (何度もreboot面倒いからね)

```
$ sudo yum update -y 
```
- reboot

```
$ sudo reboot
```


= 終 =
PHPでの画像認証にSecurimageではなく画像選択方式のreCapchaを使ってみよう

PHPのWEBアプリケーションの画像認証として[Securimage](https://www.phpcaptcha.org/)を使われている方が多いと思います。
この種の画像認証の課題として以下のようなものが挙げられています。

* 難読化されすぎていて、人が読めない
* 画像処理をすればコンピュータ（ロボット）でも突破できる

代替の手法として、パズル形式の[Capy Puzzle CAPTCHA](https://www.capy.me/)や、指定された画像を選択する[reCaptha](https://www.google.com/recaptcha/intro/)が存在します。
今回は、Googleが提供しているReCaptchaをPHPで利用する方法をまとめました。

すでにPHPでの利用方法をまとめてらっしゃる方がいましたので、そちらを参考にさせていただきました。
参考：[GoogleのreCAPTCHAをPHPで使う](http://qiita.com/koliainwiki/items/544fe01d8c964c1b99a0)


※[reCaptchaのAPIリファレンス](https://developers.google.com/recaptcha/docs/verify)によるとPOSTで送るように記載されてましたので、今回はPOSTとして作成しました。
※利用開始にはGoogleアカウントが必要です・

手順は以下の通りです。

1. reCapthaのページからキーを発行
2. クライアントのViewにHTMLタグを埋め込む
3. クライアントからPOSTされたデータをGoogleのAPI経由で検証

## reCapthaのページからキーを発行

[reCaptha](https://www.google.com/recaptcha/intro/)のGet reCAPTCHAボタンからキーの発行画面に移動します。

Label と Domains を入力するとキーが発行されます。

* Label: 管理用につけるラベルですので分かりやすい名前をつけてください

* Domains: 複数ドメインに対して同一のキーを割り当てることができます。
開発環境のドメインが別の場合などは複数行に渡ってドメインを記載してください

※G Suiteを使っている場合は、管理者アカウントでログインしたほうが良いかと思います。
※現時点では、このAPIはGoogle API Consoleでは管理されていないようです。

## クライアントのViewにHTMLタグを埋め込む

キーが入力されているHTMLタグも生成されますので、そのままコピペしていただければよいかと。

jsファイルの読み込みタグを追加します。

```html
<script src='https://www.google.com/recaptcha/api.js'></script>
```

reCaptchaを表示したい箇所に以下のタグを追加します。
XXXXXXXXXXXXX 部分は Site Key で置き換えてください。

```html
<div class="g-recaptcha" data-sitekey="XXXXXXXXXXXXX"></div>
```

このViewのFormからPOSTすると、g-recaptcha-responseというPOSTパラメータにハッシュ化された文字列が送られてきます。
その値をAPIのパラメータに渡してチェックする流れになります。

## クライアントからPOSTされたデータをGoogleのAPI経由で検証

お使いのWEBフレームワークに合わせてPOSTされたデータとクライアントのIPアドレスを取り出します。
※ELBがいる場合はELBのIPアドレスを取り出さないようにお気をつけください。

```php
$recaptha_response = $_POST['g-recaptcha-response'];
$remoteip = $_SERVER['REMOTE_ADDR'];
$check_result = checkReCaptha($recaptha_response, $remoteip); // checkReCapthaというfunctionがある前提で
```

チェック用の関数は素で書くとこのようになります。

```php
function checkReCaptha($recaptha_response, $remoteip) {
  $url = 'https://www.google.com/recaptcha/api/siteverify';

  $data = http_build_query([
      'secret' => 'XXXXXXXXXXXXX', // Secret Key を指定
      'response' => $recaptha_response,
      'remoteip' => $remoteip,
  ], '', '&');

  $header = implode("\r\n", [
      'Content-Type: application/x-www-form-urlencoded',
      'Content-Length: ' . strlen($data)
  ]);

  $context = [
      'http' => [
          'method' => 'POST',
          'header' => $header,
          'content' => $data,
      ]
  ];

  $json = json_decode(file_get_contents($url, false, stream_context_create($context)), true);
  return $json['success'] === true;
}
```

APIの応答はJSON形式です。
画像認証に成功した場合は success フイールドに true が入ります。
画像認証に失敗した場合や、キー情報が間違っている場合には error-codes フィールドに配列形式でエラーの理由が返却されます。
Azure Managed Disk を使ったマシン作成のテンプレートについて

# 概要

Azure Managed Disk を使うと色々便利そうだったが、
すでにあるイメージを使ってマシンを作る方法はいくつか見つかったが
ARM と azure-cli で、何もないところからマシンを作る方法がわからなかったので調べた

# 結論（になるはず）

一度 GUI で、ポチポチすると、最後に ARMのテンプレートや、azure-cliなどのファイルが
ダウンロードできるリンクがあることがわかった。

落としたテンプレートを使うとどうなるのか調べてみる

それを元にすればできるはず。

# 参考画像

ここにでているようなものがzipでまとまって、落とすことができる

![Screenshot from 2017-03-02 13-22-08.png](https://qiita-image-store.s3.amazonaws.com/0/82011/384e0c61-2727-a0cf-4837-7a0ec6e61614.png)



# 参考

* [3分でわかる Azure Managed Diskのしくみ](https://www.slideshare.net/ToruMakabe/3-azure-managed-disk)


* [Azure の Managed Disk のまとめ - Qiita](http://qiita.com/tsubasaxZZZ/items/7c0a15ce76d0b4d0b83f)

* [Azure Managed Disks(管理ディスク) でスナップショットを使ってみた - 世界のやまさ](http://blog.nnasaki.com/entry/2017/02/09/121432)


* [【Azure】 Managed Diskを使って仮想マシンをデプロイしてみた - マラソンランナーのITブログ](http://enjoymylife.hatenablog.com/entry/2017/02/11/131307)

* [Azure Premium および Standard 管理ディスクの概要 | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/storage/storage-managed-disks-overview)
*
neovimでreactを書くための開発環境

✳︎**追記: プラグイン入れ替えたので更新した**

neovimでreact書くとき、どのプラグイン入れたらいいかすげぇ悩んだ。
とりあえずこれで落ち着いたので、しばらくはこれで頑張ろうと思う。


```plugin.toml
[[plugins]]
repo = 'pangloss/vim-javascript'
on_ft = ['javascript', 'javascript.jsx']

[[plugins]]
repo = 'maxmellon/vim-jsx-pretty'
on_ft = ['javascript', 'javascript.jsx']

[[plugins]]
repo = 'alampros/vim-styled-jsx'
on_ft = ['javascript', 'javascript.jsx']

[[plugins]]
repo = 'moll/vim-node'
on_ft = ['javascript']

[[plugins]]
repo = 'w0rp/ale.git'
on_source = ['lightline.vim']
hook_add = '''
  let g:ale_statusline_format = ['⨉ %d', '⚠ %d', '']
  let g:ale_echo_msg_format = '[%linter%] %s'
  nmap <silent> <C-k> <Plug>(ale_previous_wrap)
  nmap <silent> <C-j> <Plug>(ale_next_wrap)
'''
```


![Imgur](http://i.imgur.com/5UJapYL.png)
Omniauth-google-auth2 だけで、DB に保存せず認証する

要件的に、「ユーザーデータを保存はしないけど Google 認証だけはしたい」という条件があって、巷では Devise を使った例しか見つからなかったので記事にしてみます。

環境: Ruby 2.3.1, Rails 4.2.6 / 5.0.1 [^1]

[^1]: Rails 4 系でこの実装をしたあとにおもむろに Rails のバージョンもあげてみたけど普通に動いてたので、たぶん大丈夫

# 事前準備
Google で client_id, client_secret を発行しておく。また、リダイレクト先の許可設定もしておく。リダイレクト先は `/auth/xxxx/callback` の形にしておくと、のちに困らないはず。今回は `xxxx` のところを
 `google_oauth` にして、 `/auth/google_oauth/callback` としてみます（*1）


# コーディング

## Gem 追加

```rb:Gemfile
gem "omniauth-google-oauth2"
```
を Gemfile に追記して、 bundle install をする

## ベースとなる Controller の実装

名前はなんでもいいのですが、ここでは LoginedApplicationController というのを用意して、ログイン状態で使う Controller は全てこれを継承するみたいな想定で作ります。

```rb
class LoginedApplicationController < ApplicationController
  before_action :authenticate

  def authenticate
    # session がなかったら
    # Google に redirect する
    # url は、 /auth/google_oauth (Google にリダイレクト先を登録したときの google_oauth 。 *1 参照) にすると、 OmniAuth が飛ばしてくれる
  end
end
```

## callback 先となる部分を用意する
名前はなんでもいいのですが、ここでは例として CallbacksController という名前にします (*2)。

メソッド名もなんでもいいのですが、ここでは omniauth_google という名前にしています (*3)。

```rb:app/controllers/callbacks_controller.rb
class CallbacksController < ApplicationController # *2
  #
  # 当たり前ですが LoginedApplicationController を継承してしまうと無限ループしちゃうので、 
  # Callback 用メソッドが呼ばれた時には authenticate メソッドが実行されないようにする
  #
  # この例では親クラスを分けることによってそれを実装している。
  # before_action に if 文を噛ませるなどの対応でも OK

  def omniauth_google # *3
    # session にセットして、アプリケーションの画面に redirect する
  end
end
```

```rb:config/routes.rb
  # callback を、さっき作った callback 先メソッドに流せるように書く
  # match のあとに書くのは *1、 actionとして書くのは *2 と *3
  match "/auth/google_oauth/callback" => "callbacks#omniauth_google", :via => [:get]
```

## omniauth の設定をしておく

```rb:config/initializer/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :google_oauth2, ENV['FOOBAR_GOOGLE_CLIENT_ID'], ENV['FOOBAR_GOOGLE_CLIENT_SECRET'],
    {name: "google_oauth", approval_prompt: ''}
    # name には、Google にリダイレクト先として登録したはずのパスの後半部分 (*1)
end
```
んで、環境変数として `FOOBAR_GOOGLE_CLIENT_ID` と `FOOBAR_GOOGLE_CLIENT_SECRET` に適切な値を入れる

これでよし

# Advanced
## ユーザーを取る
上記で説明した authenticate メソッドで

```rb
  def authenticate
    if request.env['omniauth.auth'].present? && request.env['omniauth.auth']["info"].present?
      session['google_data'] = request.env['omniauth.auth']["info"]
```

としておいて

```rb
 def current_user
   authenticate

   @current_user ||= session['google_data']
 end
```

## 


# Tips / Troubleshooting

## CookieOverflowError
Google から返却されたユーザーデータを全部 session に入れると、 CookieOverflowError に遭遇する。外部ストレージを検討するか、 session には必要なものだけを入れる
NiconicoAPIメモ(見よう見まね編)

#Niconico API ライブラリ

>https://github.com/fujiriko59/nico-api-client

にあるものを使ったが、Cookie関連とXMLのパース関連でエラーを吐きまくっていたので一から自分で作ることに。
AndroidでもGladleを用いていたので、プロジェクトはGladleで管理することに。
後日公開予定。

数時間右往左往していたが、
>https://teratail.com/questions/31972

を参考にしたらうまくいった
残念ながら筆者はHttp関連の知識が**皆無**である。

```java:Login
    public static void login_test_from_teratail(){
        try {
            URI uri = new URI("https://secure.nicovideo.jp/secure/login?site=niconico");
            String mail = "ここにメアド";
            String pass = "ここにパスワード";
            HttpPost httpPost = new HttpPost(uri);

            RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
            httpPost.setConfig(requestConfig);

            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("mail", mail));
            params.add(new BasicNameValuePair("password", pass));
            httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));

            HttpClient httpClient = HttpClientBuilder.create().build();
            HttpResponse httpResponse = httpClient.execute(httpPost);



            //POST結果
            String response1 = httpResponse.toString();
            String response2 ="";
            for (String str : response1.split(",",0)){
                response2 += str+"\n";
            }

            System.out.println(response2);

        }catch (Exception e){
            e.printStackTrace();
        }
    }
```

##HttpURLConnectionにシフト
コメントでApacheのHttpClientは非推奨というご指摘を頂いたので、自分でHttpURLConnectionを使ってCustomHttpClientを使うことに。
しかしここでも、クッキー関連の問題が多発。
調べたところ、こんな問題があるようだ。
- 地域ごとの時間設定によりクッキーの有効期限が0に(2017/03/02時点では解決)
- クッキーデータがスタックされて優先順位が逆に(未解決)

これにより、SessionIDが正しく取得できなくなる。
そこで以下のサイトのClassを使わせて頂くことに。
>http://tomott.cocolog-nifty.com/blog/files/CorrectedCookieManager.java

>引用: http://tomott.cocolog-nifty.com/blog/2010/09/javecookie5-5d9.html

前回の編集からだいぶ間が空いてしまった。
覚えていることを記述。

##動画データのダウンロードについて
クッキーの準備をして直接動画のURLをたたくと403が返されてしまう。
なのでその前に幾つかのURlにアクセスする必要がある。

##64K問題
合計のメソッドの数が64Kを超えるとビルドや実行に失敗する問題。

>https://developer.android.com/studio/build/multidex.html

##HttpのCookie等の概念の実態
いい記事があったので参考にします

>http://qiita.com/mogulla3/items/189c99c87a0fc827520e

##VideoViewでsetVideoUriでのクッキーの指定
>http://www.binzume.net/diary/2010-10-04:A1

に書いてあるように、Uriは指定できてもクッキーが指定できないから困ったと思いつつ、Android Developer サイトをみてたら、

```java:setVideoURI
void setVideoURI (Uri uri, Map<String, String> headers)
```
がAPI Level 21で追加されていた。これで解決できそう。
Python > update()でdictionaryの値を差し替える

@ Introducing Python: Modern Computing in Simple Packages by Bill Lubanovic
(No. 1593 / 12833)

> You can use the update() function to copy the keys and values of one dictionary into another.

本のコードを参考にサンプルを作ってみた。

http://ideone.com/uMxSqe

```py
equipment = { 'item1': 'double edged sword', 'item2': 'Korejanai Robo'}
print(equipment)
second = {'item2': 'Delta Flyer'}
equipment.update(second)
print(equipment)
```

```txt:結果
{'item2': 'Korejanai Robo', 'item1': 'double edged sword'}
{'item2': 'Delta Flyer', 'item1': 'double edged sword'}
```

[Korejanai Robo](http://www.zariganiworks.co.jp/korejanairobo/)
[Delta Flyer](http://ja.memory-alpha.wikia.com/wiki/%E3%83%87%E3%83%AB%E3%82%BF%E3%83%BB%E3%83%95%E3%83%A9%E3%82%A4%E3%83%A4%E3%83%BC)
PageMethodsの結果がHTMLになる事象

はまったのでメモ
※2017/9/6追記しました

## 事象
PageMethodsの呼び出し方はあっているはずなのに、
JavaScriptからPageMethodsの呼び出しを行うと結果値がHTMLになってしまう

正しくは、PageMethodsの結果がHTMLになっているわけではなく、
PageMethods自体が呼び出せていない
HTMLが返却されるのはASP.NET Friendly URLsによるもの

## 環境
- Visual Studio 2015
- ASP.NET Web Application(.NET Framework)のテンプレートで生成したプロジェクトを利用

## 原因
ASP.NET Friendly URLsを使用すると通常の方法でPageMethodsが呼び出せなくなる
Friendly URLsはASP.NETのテンプレートに含まれているので既定で使用状態となっている

Friendly URLsとは何か
http://aspnetfriendlyurls.codeplex.com/

具体的にはApp_Startの中にある `RouteConfig.cs` のコード

``` lang:C#
    public static void RegisterRoutes(RouteCollection routes)
    {
        var settings = new FriendlyUrlSettings();
        settings.AutoRedirectMode = RedirectMode.Permanent;
        routes.EnableFriendlyUrls(settings);
    }
```

## 原因詳細
Default.aspxにあるTestMethodというPageMethodsを呼び出す場合、
Default.aspx/TestMethodにアクセスする必要があるが、
ASP.NET Friendly URLsを使用していると
Default/TestMethodにアクセスされたことになり
DefaultのHTMLが返却される



## 解決方法（Friendly URLsを使わない場合）
上記の原因コード（RegisterRoutes）をまるっと削除すれば完了

## 解決方法（Friendly URLsを使う場合）
PageMethodsを使う前に下記のコードを実行する

```lang:JavaScript
PageMethods.set_path(PageMethods.get_path() + '.aspx');
```

ただ実用するにはMasterページなどに下記のコードを入れたほうがいい

```lang:JavaScript
<script type="text/javascript">
    $(document).ready(function () {
        if ("PageMethods" in window) {
            if (PageMethods.get_path().slice(-5) != '.aspx') {
                PageMethods.set_path(PageMethods.get_path() + '.aspx');
            }
        }
    });
</script>
```

この状態でPageMethodsを呼び出すと、
コンソールに下記のエラーが出て実行出来ないかもしれない

<font color="red">Failed to load resource: the server responded with a status of 401 (Unauthorized)</font>

上記のエラーを解消するには`RedirectMode.Permanent`から`RedirectMode.Off`に変更するのが簡単


``` lang:C#
    public static void RegisterRoutes(RouteCollection routes)
    {
        var settings = new FriendlyUrlSettings();
        settings.AutoRedirectMode = RedirectMode.Off;  //This one!
        routes.EnableFriendlyUrls(settings);
    }
```

その他の設定変更でも対応可能かもしれませんが調べていないです。

## 500エラーが返される場合
C#側ページメソッドの引数をstringにしていて、
JS側ページメソッドのパラメータにJavaScriptのオブジェクト（配列など）を入れた場合
500エラーが返される

JavaScriptのオブジェクトを渡す場合はJSON文字列にする必要がある
オブジェクトを送りつけたい場合は、JSON.stringify()を使ってJSON文字列に変換するとよい

なお単純な文字列を渡したい場合は500エラーは発生しない
Python > two value sequenceをdictionaryに変換

@ Introducing Python: Modern Computing in Simple Packages by Bill Lubanovic
(No. 1515 / 12833)

> You can use the dict() function to convert two-value sequences into a dictionary.

本のコードを元にサンプルを作ってみた。

http://ideone.com/HMftGs

```py
lol = [ [ 'pi', '3.1415'], ['napier', '2.71828'], ['avogadro', '6.022 x 10^23'] ]
print(lol)
 
mydict = dict(lol)
print(mydict['avogadro'])
```

```txt:結果
[['pi', '3.1415'], ['napier', '2.71828'], ['avogadro', '6.022 x 10^23']]
6.022 x 10^23
```

ファイル変換とかで使うだろうか。
Mac iTerm2 | option OR command + 左右キー で 単語を移動する設定

# 解決

Preference > Profiles > Keys

の設定を変える。

- ⌥← に `Send Escape Sequence` = `b` を設定する
- ⌥→ に `Send Escape Sequence` = `f` を設定する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89618/a990ddb8-1957-f705-2c15-3865362bfa69.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89618/aed9d119-8607-0778-cdd4-55933b33bbf6.png)

ちなみに最初はこんなのが登録されているかもしれないので、削除するか編集して上記設定に変える

![CleanShot 2024-08-28 at 10.13.48@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89618/17b55f2b-550a-31b1-d171-3a5b5a2bbc72.png)


# Commandキーの場合

同じ要領で設定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89618/fb2f8b37-461f-dd41-7cc3-e7f49ae8d104.png)


# 補足

- 同じ要領で他のキーにも適用できる。

# 環境

- iTerm2 3.0.12
- Mac OSX

# 3.3.4 のバージョンアップで使えなくなっているっぽい？

3.3.5 Beta では動いた

# 参考

- https://coderwall.com/p/h6yfda/use-and-to-jump-forwards-backwards-words-in-iterm-2-on-os-x








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
vagrantでWordPressを立ててAgular2でフロントエンド開発

#VagrantでWordPressを立てる
[virtualboxのインストール](
https://www.virtualbox.org/)
[Vagrantのインストール](
https://www.vagrantup.com/)

VCCW v3　をダウンロードする。
http://vccw.cc/

vagrant-hostsupdaterをインストールする。

```vagrant:vagrant
vagrant plugin install vagrant-hostsupdater
```

プラグインインストール後にupしてWordPressを立てる

```vagrant:cmd
cd vccw
vagrant up
```

#WordPressの設定
正常にupできていれば

* http://vccw.dev/
    * または　http://192.168.33.10/
* http://vccw.dev/wp-admin/
    * または　http://192.168.33.10/wp-admin/ 

にアクセスできる。

日本語とかにしとくと幸せになれる。
Wordpressは最新にしておく。

#Angular2のインストール
https://angular.io/docs/ts/latest/cli-quickstart.html
を参照

nodeとnpmをインストールする。
https://nodejs.org/en/

インストールが終わったらAngular2のCLIをインストールする。

```cmd:cmd
npm install -g @angular/cli
```

インストールが終わったらプロジェクトを作成する。

```cmd:cmd
ng new my-app
````

プロジェクトが作成されたら実行してみる。

```cmd:cmd
cd my-app
ng serve
```

http://localhost:4200/ にアクセスして
``app works!`` みたいなの出れば動いてる。

#Angular2をコンパイルしてVagrantで動かす

Angular2をbuildする

```cmd:cmd
ng build
```

終わると ``dist/`` というフォルダが生成されている。
``dist/`` を先程の``vccw/wordpress/`` にコピーする。
http://vccw.dev/dist/ にアクセスすると先程の``app works``が出る。

トップページごと変えたい場合は``dist/``の中の全部を``vccw/wordpress/``にぶち込む。


#最後に
最近（4.7から？）のWordPressもAPIが提供されているのでとりあえずローカルで試せる環境の構築をした。
WordPressの管理画面は使いたいけどPHPでデザインとかはやりたくないしフロントエンドでいろいろやったほうが楽だと思ってる。
とりあえず開発環境はできたので色々やりたい。
Python > Tuples versus Lists

### 参考1

@ Introducing Python: Modern Computing in Simple Packages by Bill Lubanovic
(No. 1466 / 12833)

> ..., but they have many fewer functions -- there is no append(), insert(), and so on -- because they can't be modified after creation.

listと比べてtupleを使う理由が記載されている。

- Tuples use less space.
- You can't clobber tuple items by mistake.
- You can use tuples as dictionary keys 
- Named tuples can be a simple alternative to objects.
- Function arguments are passed as tuples.

Named tuplesの例は以下。
http://stackoverflow.com/questions/2970608/what-are-named-tuples-in-python

Function argumentsへのtuples渡しは別途。

### 参考2

tupleとlistの違いについて
http://stackoverflow.com/questions/626759/whats-the-difference-between-lists-and-tuples

> Tuples have structure, lists have order.

など。
Zynq > BOOT.binの解析 > L. .elfファイルのstart addressを調べる > arm-xilinx-eabi-objdump --section=.text -h HellowWorld.elf | grep .text | cut -c29-36

```txt:動作環境
PetaLinux 2014.4
Vivado v2014.4
MicroZed
```

2014年頃のメモより。

linuxにて以下のコマンドでstart addressを調べることができる (bootgen.pyのコメントとして記載されていた)

```
$ arm-xilinx-eabi-objdump --section=.text -h HellowWorld.elf | grep .text | cut -c29-36
00100000
```
Zynq > BOOT.binの解析 > K. BitstreamのHEXの意味

```txt:動作環境
PetaLinux 2014.4
Vivado v2014.4
MicroZed
```

2014年頃のメモより。

ug470のp99のTable 5-18にbitstreamのHEXの例が記載されている。

| Configuration Data Word (hex) | Description |
|:-:|:-:|
| FFFFFFFF  | Dummy pad word  |
| ...  |   |
| 000000BB  | Bus width auto detect, word 1  |
|  11220044 |  Bus width auto detect, word 2 |
| ...  |   |
| AA995566  |  Sync word |
|  20000000 |  NOOP (no operationの意味か?) |
| 30022001  | Packet Type 1: Write TIMER register, WORD_COUNT=1  |
| ...  |   |
| 20000000  | NOOP (End of bitstream)  |
Zynq > BOOT.binの解析 > J. 各ファイルのアドレス対応表

```txt:動作環境
PetaLinux 2014.4
Vivado v2014.4
MicroZed
```

2014年頃のメモより。

Vivado, XSDKで作成したベアメタルアプリを含むBoot.binに関して、元ファイルとBoot.binの中身を比較して以下の情報を得た。

|  | 元ファイルのアドレス | Boot.bin内のアドレス | 備考 |
|:-:|:-:|:-:|:-:|
| FSBL  |  0x8000 から 0x2000B (サイズ 0x1800B | 0x1700 から 0x1970B (サイズ 0x1800B)  |   |
| bitstreamを変換した .bit.binファイル  | 0x3CD0D から 0x1FCB9B (サイズ 0x1BFE8E)  | 0x5644D から 0x2162DF (サイズ 0x1BFE92)  | endianを入れ替えている。 アルファ。 これらの処理はarm-xilinx-eabi-objcopy -O binaryで行っている。左記のサイズに4バイトの違いがある理由は不明 |
| HelloWorld  |  0x8000 から 0x1000B (サイズ 0x800B) |  0x216300 から 0x21E30B (サイズ 0x800B) |   |

[bootgen.py](https://github.com/ryos36/py_bootgen/blob/master/bootgen.py)の処理を見ている中で、bitstreamのバイナリ処理は以下のようにしていることがわかった。

- arm-xilinx-eabi-objcopy -O binary を用いて変換をしている
- 変換したものをboot.binに含めている

[arm-xilinx-eabi-objcopyの参考](http://d.hatena.ne.jp/ken_2501jp/20121107/1352311439)
CentOS7 コネクションネームが日本語で困った時の対処

コネクションを確認
`nmcli c s`
UUIDとデバイス名を確認する
コネクションを削除
```nmcli c delete [UUID]```
コネクション作成
```nmcli c add type eth ifname [デバイス名] con-name [デバイス名]```
これでデバイス名と同じコネクションネームになる
con-nameの次の[デバイス名]は任意の名前にしてもよい
[C++11] 生文字列リテラル(Raw String Literals)の使用方法メモ

生文字列リテラル(Raw String Literals)の使用方法メモ

コード見たほうが早いと思うのでサンプルコード載せます。（Qiitaのシンタックスハイライト対応してないですね・・・）

```cpp:test_raw_literals.cpp
#include <cstdio>

static const char* raw_string_literals1 = R"(hoge)";
static const char* raw_string_literals2 = R"("foo", "bar")";
static const char* raw_string_literals3 = R"({
    "object" : {
        "foo" : 1,
        "bar" : "hoge"
    }
})";
static const char* raw_string_literals4 = R"*("(cdr '(1 2 3 4))" => "(2 3 4)")*";

int main(int argc, char const* argv[])
{
	puts("case 1: 通常ケース");
	puts(raw_string_literals1);
	puts("case 2: ダブルコーテーションを含むケース");
	puts(raw_string_literals2);
	puts("case 3: 改行を含むケース");
	puts(raw_string_literals3);
	puts("case 4: 丸括弧とダブルコーテーションが隣接する文字があるケース");
	puts(raw_string_literals4);
	return 0;
}
```

```console:ビルドと実行例
$ g++ -std=c++11 test_raw_literals.cpp && ./a.out
case 1: 通常ケース
hoge
case 2: ダブルコーテーションを含むケース
"foo", "bar"
case 3: 改行を含むケース
{
    "object" : {
        "foo" : 1,
        "bar" : "hoge"
    }
}
case 4: 丸括弧とダブルコーテーションが隣接する文字があるケース
"(cdr '(1 2 3 4))" => "(2 3 4)"
```

シンタックスハイライトが分かりにくいのでVimでのキャプチャも載せます。

![無題.png](https://qiita-image-store.s3.amazonaws.com/0/37721/63617446-c1a8-5b37-3d8c-ed2dee6b3a63.png)


# 参考
[生文字列リテラル - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/lang/cpp11/raw_string_literals.html)
herokuのpostgresqlをアップグレードする



# 内容
herokuの無料プランから有料プランへアップグレード
pgのアップグレードは別のdbを作成して移行する流れになる



# フロー

1 有料プランのpgを作成する
2 無料プランから有料プランへデータをコピー

# 手順

 #{app_name}はアプリの名前

##0 現在の状況を確認

```
heroku pg:info -a #{app_name}
```

##1  pgのhobby-basicを追加

```bush
heroku addons:create heroku-postgresql:hobby-basic -a #{app_name}

# こんな感じの環境変数が生成される　=> HEROKU_POSTGRESQL_OLIVE_URL
```

##2 pgをwaitする

```
heroku pg:wait -a #{app_name}
```

##3 メンテナンスモードにする

```
heroku maintenance:on -a #{app_name}
```

##4 データをコピーする

この時に実行するか聞かれる

```
heroku pg:copy DATABASE_URL HEROKU_POSTGRESQL_OLIVE_URL -a #{app_name}
```

##5　dbの参照先を変更する

```
heroku pg:promote HEROKU_POSTGRESQL_OLIVE_URL -a #{app_name}
```

##6 変更されたか確認
DATABASE_URLがHobby-basicになっているか確認

```
heroku pg:info -a #{app_name}

=== DATABASE_URL, HEROKU_POSTGRESQL_OLIVE_URL
Plan:        Hobby-basic
Status:      Available
.
.
.

```

##7 メンテナンスモード解除

```
heroku maintenance:off -a #{app_name}
```

##8 定期的にバックアップを取るようにする

```
# 現在のバックアップの状況を確認。設定がない場合はこんな感じ
heroku pg:backups:schedules -a #{app_name}
 ▸    No backup schedules found on ⬢ #{app_name}
 ▸    Use heroku pg:backups:schedule to set one up

# スケジュールを設定
heroku pg:backups:schedule DATABASE_URL --at '4:00 Asia/Tokyo' -a #{app_name}
Scheduling automatic daily backups of postgresql-xxxxxxxx at 4:00 Asia/Tokyo... done

# スケジュール確認
heroku pg:backups:schedules -a #{app_name}
=== Backup Schedules
DATABASE_URL: daily at 4:00 Asia/Tokyo
```
LinuxMintから無線LAN環境（WPA2エンタープライズ）に証明書を使って接続する方法

何も知らずに設定していて、ドはまりして色々と調べたので整理します。試していた環境は、LinuxMint18.1ですが、Mintのバージョンが、ある程度古くても変わらないと思います。（MintはUbuntuの皮だけ変更なので、Ubuntuでも変わらないかもです。）

# 結論

メニューから、「設定 - ネットワーク - 非表示のネットワーク」と開いてWIFIで下記を設定していけた。（一覧に出てきていれば、それをクリックでいけます。SSIDがブロードキャストされていない場合は、非表示のネットワークから設定する必要があります。）

- セキュリティ: WPA & WPA2 Enterprise
- 認証: TLS
- Identity: 証明書のcnに書かれているID（なければ、証明書発行時に設定されたユーザID）
- ユーザ証明書: p12証明書ファイル(.pfx)から取り出した証明書を設定
- CA証明書: 設定しない（下にあるチェックボックス「No CA certificate is required」にチェックする）
- プライベートキー: p12証明書ファイルを設定（.p12）
- プライベートキーパスワード: p12証明書のパスワード

# 管理者から渡されたファイルと情報

- 「WPA2 Enterprise」で、「EAP-TLS」で証明書を使って接続してね。
- 証明書はこれだから「username.p12」（p12証明書ね）
- 証明書のパスワードは「hoge」ね。
- あと、手順書はこれね。（WindowsとMac用）

Windows版は、ほぼ手順書通り苦も無く成功。理由は簡単でp12証明書ファイルを認証センターに登録すれば、あとはGUIからポチポチで行けるようになっているためです。LinuxMintはそんなもの無いため、p12のファイルからOpenSSLのコマンドで証明書を取り出す必要がありました。

ざっくりと無線の種類については、こちらが参考になりました。

[無線LANの暗号化方式について整理してみた](http://security.nekotricolor.com/entry/difference-in-wireless-lan-protocol-wep-wpa-wpa2-tkip-ccmp-aes)

# WPA2 Enterpriseとは？

RADIUSサーバというものを使った認証方式らしいです。RADIUSサーバは、DBサーバと同じ抽象度での名称で、DBサーバのMysqlとかと同じく、RADIUSサーバのCisco ACSとかあるみたいです。下記記事が分かりやすかったです。

(RADIUSの仕組みと構築のポイント――第2部：RADIUSを使ったシステム構築のポイント (1/6))[http://www.itmedia.co.jp/enterprise/0307/14/epn08.html]

# 拡張子.p12とは

PKCS#12のファイルにつく拡張子です。.pfxもほぼ同じファイルだと思っていいみたいです。証明書周りは、crtとかpemとか分かりづらいですね。

# PKCS#12とは

PKCSは「Public Key Crypt Systems」の略で、秘密鍵と証明書を1つのファイルに格納する形式です。必ずしも両方を入れる必要は無いので、証明書が入ってない場合もあります。コマンド叩けば入っているものが見れます。中身は暗号化されているので、使う際はパスワードが必要です。

```bash
openssl pkcs12 -in username.P12 -noout -info
```

# p12ファイルから「証明書」を取り出す

証明書の取り出し

```bash
openssl pkcs12 -in username.P12 -clcerts -nokeys -out username.crt
```

ファイルの中身

```
ヘッダ情報
-----BEGIN CERTIFICATE-----
abcd...
-----END CERTIFICATE-----
```

中身は上記のようになっています。ヘッダ情報を消したほうが良いという情報もありましたが、僕の場合消さなくても大丈夫でした。初期の頃は消す必要があったのかもです。

# Identity項目を設定するためにcn情報が見たい

ユーザ証明書が作れれば、中身は平文テキストなので見れば分かります。余談ですが、Windows版の設定ではIdentity項目を設定しなくても通ります。なぜかというと、設定していない場合、自動でcn情報を見てくれるかららしいです。楽ですね(・∀・)

# LinuxMintではデフォルトでwpa_supplicantが入っています

WPA2エンタープライズで接続するためにLinux界隈で使われているらしいです。

# 調査時の見たところ

設定ファイルの位置（何が設定されているか見れる）

```
/etc/NetworkManager/system-connections
```

接続時のログ（syslog参照）

```
tail -f /var/log/syslog
```

# 最後に

なんかいろいろな理由で接続できなかったです。無知過ぎました。。。

[Linux の無線設定例](http://jimubu.adm.s.u-tokyo.ac.jp/public/index.php/Linux_%E3%81%AE%E7%84%A1%E7%B7%9A%E8%A8%AD%E5%AE%9A%E4%BE%8B)

こちらの設定もあって混乱したのも事実です。RADIUSサーバの設定によって、設定が変わるのかなぁと思います。同じようにハマる人がいれば、管理者の人に設定を聞いたほうが速いかもしれません。
boto3を使ってS3をごにょごにょする

# はじめに

IoT関係の案件で、ゲートウェイ(以下GW)からS3にあるファイルをダウンロードしたり、アップロードしたりする必要があったので、python(2.7)とboto3(AWS SDK for python)を使って実装してみました。その際の手順を備忘録的に残しておこうと思います。

# 最終目標

1. バケット内のファイルをダウンロードできるようになる
2. 特定のディレクトリへファイルをアップロードできるようになる

# さあ、はじめようか

## boto3のインストール

GWにssh接続でログインして、pipでboto3をインストールします。(GWはpython2.7 pipはインストール済み)

```
sudo pip install boto3
```

特定のバージョンを指定する場合は以下のようにインストールします。

```
sudo pip install boto3==1.0.0
```

## IAM作成

boto3を利用する際に、IAMにてポリシーを設定する必要があります。今回はS3FullAccessを設定したIAMユーザーを作成しました。
必要に応じて読み込みのみにしたり、アクセスできるバケットを絞ったりなど必要最低限のポリシーを設定するようにしましょう。
※この手順は省略します

## AWSCLI設定

先ほど作成したIAMユーザーのアクセスキー情報を設定します。

### AWSCLIのインストール

```
sudo pip install awscli
```

### Configure設定

```
aws configure
AWS Access Key ID: xxxxxxxxxxxxxxxxx
AWS Secret Access Key: xxxxxxxxxxxxxxxxx
Default region name: ap-northeast-1
Default output format:
```

これで設定完了です。設定した内容は、「~/.aws/credentials」と「~/.aws/config」で確認することができます。


## python内でboto3をimportする

bote3のimportしてS3のファイルをごにょごにょするためには、下記のように書き始めます。

```boto3_test.py
# -*- coding: utf-8 -*-

import boto3

s3 = boto3.resource('s3')

```

ほかのサービスを利用する場合は下記のように書きます。(DynamoDBの例)

```boto3_test.py
# -*- coding: utf-8 -*-

import boto3

# S3
s3 = boto3.resource('s3')

# DynamoDB
dynamo = bot3.resource('dynamodb')

```

## 実際にS3のファイルをごにょごにょする

### S3からのダウンロード

download_file()を使用します。バケット名hoge内のfuga.txtをダウンロードする場合は

```boto3_test.py
# -*- coding: utf-8 -*-

import boto3

s3 = boto3.resource('s3')

bucket = s3.Bucket('hoge')
bucket.download_file('fuga.txt', 'fuga.txt')

```

バケットは同じで、フォルダhogehoge内のfuga.txtをダウンロードする場合は

```boto3_test.py
#---省略---

bucket = s3.Bucket('hoge')
bucket.download_file('hogehoge/fuga.txt', 'fuga.txt')

```

### S3へのアップロード

upload_file()を使用します。バケット名hoge内にfuga.txtをアップロードする場合は

```boto3_test.py
#---省略---

bucket = s3.Bucket('hoge')
bucket.upload_file('fuga.txt', 'fuga.txt')

```

バケットは同じで、フォルダhogehoge内にfuga.txtをアップロードする場合は

```boto3_test.py
#---省略---

bucket = s3.Bucket('hoge')
bucket.upload_file('fuga.txt', 'hogehoge/fuga.txt')

```

これでS3内のファイルをダウンロードしたり、アップロードすることができるようになりました。
ちなみにバケット内の各オブジェクト情報を表示させるのは

```boto3_test.py
#---省略---

bucket = s3.Bucket('hoge')
print bucket.name

```

で一覧が表示されます。

## 最後に

boto3を使う以前にpython自体あまり触れたことがなかったので少し苦戦してしまいましたが、[公式ドキュメント](https://boto3.readthedocs.io/en/latest/)がかなり整っていたので助かりました。というか英語に対する拒否反応を示さない方は公式ドキュメントを読んでいただいたほうがいいと思います。汗
javascriptで一覧画面の明細をsortしたりfillterしたりするサンプル集め

やりたい事はこれ。
https://datatables.net/examples/plug-ins/range_filtering.html

# 参考になりそうなサイト
jquery入門
http://www.jquerystudy.info/reference/traversing/filter.html

buildinsider
http://www.buildinsider.net/web/jqueryref/013

Qiita
http://qiita.com/itagakishintaro/items/29e301f3125760b81302

自分で書いてみたら更新予定。
ローカルのフォルダをgitのremoteとして設定したい(windows)

自分のローカルにgitのremoteを設定して運用することになったのでメモ

普通だとgithubとかなんやら使うのに珍しいな...と思った

# 参考サイト様
参考サイト：[Windows PCをGitのリモートリポジトリとして使用する方法](http://d.hatena.ne.jp/MoonMtLab/20140314/1394807213)

この記事はほぼ参考サイト様の内容と同じです。
非常に助かりました。ありがとうございます。

# リモートの作成
なにはともあれ早速環境を構築

まずは、リモートなるファイルを作成する。(A)

その後、実際にリポジトリとして使用されるフォルダを作成する。(B)

大体↓の画像のイメージ
![image](https://qiita-image-store.s3.amazonaws.com/0/101848/577670ce-8e2c-cf27-ad65-3dd2123a3b10.png)


特に(B)はhogehoge.gitなど、最後に.gitがつくのが習慣なので、今回もそれに習っています。

後はコンソールを立ち上げて...

```
cd /
cd git_share/repo.git
git init --bare --shared=true # リポジトリの初期化
touch ./git-daemon-export-ok  # 公開用リポジトリに指定
git daemon --export-all --enable=receive-pack --base-path=/C/git_share # GITデーモンの起動
```

こうすることで、下記URLよりリモートリポジトリとしてアクセスできるらしい
`git://<リモートリポジトリを構築したPCのIPアドレス>/test_remote_repository.git`


# おまけ
私のローカルにGITのリモートを作成したので、私は直接リモートを設定しています
具体的には以下のような感じ


`git remote add origin /c/git_share/mine.git`

```
PS C:\hogehoge> git remote -v
origin  /c/git_share/repo.git (fetch)
origin  /c/git_share/repo.git (push)
```
[apt] パッケージの事前ダウンロードを行う

インストールは後で行いたいため、事前にパッケージだけダウンロードしておく方法のメモ。

`-d`, `--download-only` のオプションを使用すればよい。

```console:packageの事前ダウンロード
$ sudo apt-get -d install <package name>
or
$ sudo apt-get --download-only install <package name>
```

# 使用例

```console:パッケージの事前ダウンロード
$ sudo apt-get -d install gitlab-ce
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages will be upgraded:
  gitlab-ce
1 upgraded, 0 newly installed, 0 to remove and 161 not upgraded.
Need to get 270 MB of archives.
After this operation, 32.2 MB of additional disk space will be used.
Fetched 270 MB in 1min 14s (3,625 kB/s)
Download complete and in download only mode
$ ls /var/cache/apt/archives/
gitlab-ce_8.17.2-ce.0_amd64.deb  lock  partial
```

# 参考
[debian - How do I download a package from apt-get without installing it? - Stack Overflow](http://stackoverflow.com/questions/4419268/how-do-i-download-a-package-from-apt-get-without-installing-it)