OmniAICreator/Qiita-1.07M huggingface dataset:
Windows 10 Fall Creator Updateを適用するとSysprepが落ちる件と対処方法

Fall Cretor Updateを適用すると、sysprepが通らなくなるようです。（2017/11/01現在）
エラーコード自体はWin10でsysprepを実行した人にはおなじみ、パッケージを削除したマシンでsysprep実行した場合に出る下記のエラーなのですが、

エラーコード：0x80073cf2　
エラーメッセージ：（前略）Package \<PackageFullname\> was installed for a user, but not provisioned for all users.（後略）

今回は原因と対処法が異なったのでセルクマ用にメモ。




原因：アップデート以前に存在したC:\Windows\MiracastViewディレクトリがFall Creator Updateで消えるため、sysprep時に見つからずエラーとなる
対応：アップデート前の当該パッケージのフォルダC:\Windows\MiracastViewフォルダをC:\Windows直下にコピーしてからsysprepを実行する。

手順
1.C:\Windows.old\Windowsディレクトリをエクスプローラで開く。
2.アップデート前の当該パッケージディレクトリC:\Windows.old\Windows\MiracastViewが存在するので、MiracastViewフォルダをコピー
3.C:\Windows直下へペースト
4.sysprepを実行

以上

参考：[Unable to Sysprep after Fall Creator Update Due To Miracast](https://social.technet.microsoft.com/Forums/windows/en-US/e610f718-b2d4-45a2-b4ff-ded8c755bdbb/unable-to-sysprep-after-fall-creator-update-due-to-miracast?forum=win10itprosetup)
XAMPPをインストール・スタートする際の注意点

#XAMPPを自分でインストールする際の注意点

##今回の動作環境
windows10

##注意点
XAMPPのインストールをが終わったあと、スタートする画面にいく。
そこで基本は「start」をクリックしていけばいいが、『Skype』がインストールされている場合”Apache”でエラーが出る。
その際は、Skype画面（最新バージョンでは見当たらなかったので旧バージョンで）の
`「ツール」→「設定」画面での、「接続」の『上記のポートに変わり、ポート80と443を使用』のチェックを外し保存`
Skype再起動後XAMPPを再起動して、Apache起動して実行。


まさか、Skypeに原因があったなんて。。。。
【翻訳】"Factory Girl"が"Factory Bot"に変わった理由（と移行手順）


2017年10月に、Rubyのライブラリ(gem)である"Factory Girl"が"Factory Bot"に変わりました。

名前が変わった理由が以下のページに記載されていたので、翻訳してみます。

https://github.com/thoughtbot/factory_bot/blob/master/NAME.md

## プロジェクト名の歴史

### Factory Girl

このライブラリはもともと2008年に"Factory Girl"という名前でリリースされました。

この名前を選んだ理由は書籍「デザインパターン」に載っていたファクトリメソッドパターンとオブジェクトの母（Object Mother）パターンに従っていたことと、ローリング・ストーンズに同じ名前の曲があったためです。

### Factory Bot

"Factory Girl"という名前はこのライブラリの存在を知った一部の開発者を混乱させました。また、不快で問題があるように感じる人々もいました。そのため、2017年10月に私たちはこのライブラリの名前を"Factory Bot"に変更しました。

（翻訳ここまで）

名前が変更される詳しい経緯については以下のissueも参考になります。

- [Repository Name · Issue \#921 · thoughtbot/factory\_bot](https://github.com/thoughtbot/factory_bot/issues/921)

## 参考：Factory GirlからFactory Botへ移行する方法

Factory BotとFactory Girlは名前が違うだけで基本的に同じものです。
Railsプロジェクトの場合、移行したい場合は次のようにします。

### 1. Gemfileを更新してbundle install

```diff:Gemfile 
- gem 'factory_girl_rails'
+ gem 'factory_bot_rails'
```

```
$ bundle install
```

### 2. プロジェクト内のFactoryGirlをFactoryBotに置換

```diff:spec/factories/users.rb
- FactoryGirl.define do
+ FactoryBot.define do
```

[UPGRADE_FROM_FACTORY_GIRL.md](https://github.com/thoughtbot/factory_bot/blob/4-9-0-stable/UPGRADE_FROM_FACTORY_GIRL.md) にある通り、Railsのプロジェクトルートディレクトリ内で、下記コマンドを打つのが楽です。

```shell
grep -e FactoryGirl **/*.rake **/*.rb -s -l | xargs sed -i "" "s|FactoryGirl|FactoryBot|"
```

### 3. プロジェクト内のfactory_girlをfactory_botに置換

```diff
- g.fixture_replacement :factory_girl, dir: "spec/factories"
+ g.fixture_replacement :factory_bot, dir: "spec/factories"
```

こちらも下記コマンドが楽です。

```shell
grep -e factory_girl **/*.rake **/*.rb -s -l | xargs sed -i "" "s|factory_girl|factory_bot|"
```

### 4. テストがすべてパスすることを確認

```
$ rails spec
```
java基本知識メモ

開発現場の個人経験からまとめたものであり、あくまでも参考までに読んでください。



#javaとは
 「javaとは」でgoogleなどで検索してみたら、いっぱい説明が出てくると思います。
　要するに、javaは、数多くの「プログラミング言語」の中の1つです。
　そもそも、プログラミング言語とは、コンピューターと会話できる言語です。当然、日本語を書いても、コンピューターには通じません。プログラミング言語で書いた言葉でコンピューターに指令を出したり、コンピューターの回答をもらったりできるのです。

　**ここは、もっときれいな絵があるといいね。。。（★TODO）**
　![image.png](https://qiita-image-store.s3.amazonaws.com/0/210895/7dfdac54-49f9-d5ba-7d4d-1cf7d7c96a24.png)


#javaでどんなことが得意？
  まあ、いろいろあるけど、代表的なところは、Androidスマートフォンのアプリを作成したり、
Webサイトを構築したり・・・
　
　詳しくは検索どうぞ：*java 得意*　

#さあ、javaを始めてみよう
　javaを書くには、いくつかの基本条件がある。

  - パソコン
　　　当然スベックが高いほどいいけど、メモリが4G以上は望ましい。　　　　　

  - インタネット接続
　　　せめて最初の環境構築時には、インタネット接続が必要です。
　　　インストール資材をインタネットからダウンロードする必要があるため

  - Ｊａｖａ書く流れ
　　１）Ｊａｖａの環境構築
　　　・Ｊｄｋインストール
　　　・ＩＤＥインストール
　　２）ＪａｖａのＣｏｄｅを書く
　　３）ＪａｖａのＣｏｄｅを実行

| コラム １|
|:-----------|
| jdkとはなんですか、なんでjdkをインストール必要？|

| コラム ２|
|:-----------|
| ＩＤＥとはなんですか、なんでIDEをインストール必要？|

　
#環境構築
  - jdkインストール　（★ＴＯＤＯ）
 
　　検索：*jdk インストール windows*
　　検索：*jdk インストール mac*
　
　　

| コラム ３|
|:-----------|
| jdk種類と選別方法について|

  

  - sts (eclipse）をインストール（★ＴＯＤＯ）

| コラム ４|
|:-----------|
| 主なＩＤＥ種類について|


#JavaのCodeを書こう！
 以下、Spring Tool Suite(略してSTS)にて、java codeを書くイメージとなります。

 - **STEP1 STSを起動する**

　パソコンにある「STS - ショートカット」アイコンをダブルクリックして、STSを起動する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/210895/ad2abb3b-6656-c9c1-7c31-9f4e84cfce0b.png)

　STS起動中・・・
![image.png](https://qiita-image-store.s3.amazonaws.com/0/210895/3be3fa30-51ff-87d2-f1a9-9a3724af5e0b.png)

　これから作業するファイルを保存するディレクトリを指定します。
　好きな場所を指定していいです。こだわりがないなら、何も変更せず、Launchボタンをクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/210895/11d84653-fc61-5685-d1ac-cb50d90dd559.png)
　
　しばらくすると、このような画面が表示されます。これでSTSは起動完了です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/210895/be27188b-1694-e2d5-1ac5-235447c164f9.png)

 - **STEP2 java projectを作成する**

ちょっと待った。java projectとはなにものじゃ？
　 java projectとは、いくつかのJavaプログラムを一機能やアプリケーションとしてまとめたものです。
　ここは概念がすぐ理解できなくて、徐々になれるので、まず、java codeを作成する場合は、いきなりjava codeを書くのではなく、まず、java projectを作成しておく必要ということだけを覚えておきましょう。

STS画面にて「file」メニューをクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/210895/904b9764-5110-7df8-224f-523693efbe6a.png)

メニューにて「New」をクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/210895/90843bae-21cc-4dcb-410a-c8da493c8b80.png)

メニューにて「Java project」をクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/210895/ce3bec43-4a95-59c6-8e52-34824f618704.png)

「New Java Project」画面にて好きな名称を入力し、「Finish」クリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/210895/fa094c0a-3d25-2e44-babd-1fef2a1fbe35.png)
　
STS画面の左上に作成されたprojetが見える。これでjava projectは作成完了です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/210895/5baed352-3c0e-7d41-2aac-29f5593de5be.png)

 - **STEP3   java codeを格納するfileを作成する**

java codeは、class単位で書くので、専門用語ではjava codeファイルは、classファイルといいます。classとはなんでしょうか？
　★ＴＯＤＯ




  
```java
package sample;

public class Main {

	public static void main(String[] args) {
		System.out.println("Hello World!");
	}

}
```


#javaのcodeを実行しよう！

#Java Codeの基本構成
  - パッケージ
  - クラス
  - メソッド
  - 変数

　まだ途中です。時間があったら、また編集します。:fist:

#java Codeの基本文法
- ループ
- 条件判定
- 処理中断
- 異常中断
Visual Studio for Macのインストール時に接続エラーとなる場合の対処

Visual Studio for Macをインストールしようとしていて、以下のエラーが出た場合の対処を記載します。社外へのアクセスに認証プロキシを必須とするような会社で、Visual Studio for Macをインストールしようとしている方に役立つかもしれません。

```
System.InvalidOperationException: Android SDK was detected for update, but list of installed SDKs was empty.
Please check your internet connection and run the installer again. If it fails, file a bug report: https://go.microsoft.com/fwlink?linkid=852416
```

# 原因
詳細は不明ですが、インストーラの処理に認証プロキシを介すとうまく動作しない個所があるのではないかと思われます。

# 対処
認証プロキシの前段に、認証を行わない別のプロキシサーバを設置します。
認証プロキシ側の認証は、追加したプロキシサーバ側で代行します。

## 対処方法のイメージ
[Mac] --1-- [追加プロキシ] --2-- [会社の認証プロキシ]

1では認証不要
2で認証

# 対処方法の実施例
1. homebrewをインストールします。  
以下のページを参照してhomebrewをインストールします。  
https://brew.sh/index_ja.html
2. squidをインストールします。  
brew install squid
3. squidを設定します。  
対象ファイル：```/usr/local/etc/squid.conf```  
**○以下の設定を追加**  
```cache_peer <プロキシサーバのIPアドレス> parent <プロキシサーバのポート> 0 no-query login=<プロキシID>:<プロキシPW> （会社の認証プロキシに転送するための設定）   
例： cache_peer 10.10.10.10 parent 8080 0 no-query login=user:password```  
```never_direct allow all （追加したプロキシサーバを必ず経由させる設定）```  
```never_direct allow CONNECT （SSLの接続も追加したプロキシサーバを必ず経由させる設定）```  
**○以下の設定を必要に応じて変更**  
```http_port 3128 ＜－ お好みのポートに変更```


4. システムのプロキシ設定を変更します。  
設定先： システム環境設定　＞　ネットワーク　＞　詳細　＞　プロキシ  
HTTPSのWebプロキシサーバの情報をsquidをインストールしたサーバのアドレスとポートにします。  
5. squidを起動します。  
```/usr/local/opt/squid/sbin/squid -N -d 1```
6. Visual Studio for Macのインストーラを起動してインストールを実施します。

インストールが済んだらプロキシの設定を元に戻します。
インストール後はシステム環境設定のところでプロキシ設定をすれば問題無く利用できます。
ハッシュ関数

#ハッシュ関数ってなんぞや

 

ブロックチェーン技術には欠かせないのがハッシュ関数です。

 

これは、暗号化分野でよく使われている関数のようで、その出力した値（情報）に対して、唯一無二のハッシュ値を返すというものです。このハッシュ値から参照することで、元のデータが改ざんされていないか、または、すり替えられていないかを検証することができます。

 

少々複雑なので簡単に図で説明します。

1. 値を入れる

2. ハッシュ関数が処理

3. ハッシュ値が出来上がる

 
<img width="747" alt="スクリーンショット 2017-11-01 7.43.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/161691/766b524e-8595-470d-0109-e8b4b50b254d.png">


例えば、木村さんが鈴木さんにデータを送ろうとしています。

 

木村さんが値A をハッシュ関数で処理し、ハッシュ値 Z を作成したとします。

このハッシュ値 Z は、唯一無二であるので、たとえ、鈴木さんが同じ値A をハッシュ関数で処理しても、ハッシュ値 Z が求められるはずなのです。

これで、

鈴木さんが求めたハッシュ値 = 木村さんが求めたハッシュ値 Z

であれば問題ないのですが、もし

鈴木さんが求めたハッシュ値 ≠ 木村さんが求めたハッシュ値 Z

となると木村さんの元の値A は変更されていると証明できるのです。

 

 

#ハッシュ関数の特徴

 

・長さの違う値でも、常に一定の桁数のハッシュ値が作成される。

・一つの値に対して、常に唯一無二のハッシュ値が作成される

・入力する値は、数値、テキスト、ファイル形式でも可能

・ハッシュ関数を使うことで、その情報が原本と同じであること、改ざんされていないことを保証できる

 

 

#ハッシュ関数の衝突問題

 

ハッシュ関数の最大の特徴は、一つの値に対して唯一無二のハッシュ値が作成されることだと記述しました。

しかし、ごく稀に、本当にごく稀に違う値で同じハッシュ値が作成されてしまうことがあり、それはハッシュ関数の衝突問題と呼ばれています。

 

図にすると、下記のようになります。

異なる値、ABCとBCAを入力した際に、同じハッシュ値 Z が作成されてしまっています。

 
<img width="734" alt="スクリーンショット 2017-11-01 8.07.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/161691/49c6d871-6a32-f0aa-b143-a0ce1fea7712.png">


 

しかし、これは実際に起きる確率は非常に、非常に低く、故意に起こすことはほぼ不可能です。

1995年にできたハッシュ関数である、"SHA1"というハッシュ関数は、2017年2月にグーグルによって初の衝突が確認されました。しかし、その衝突を発見するのに、グーグルは900京回以上という途方も無い計算を行いました。これは、"SHA1"というハッシュ関数が世に出てから22年後の出来事なのです。

 

よって、衝突問題は、可能性としては起こりうる問題ではありますが、実際にはそこまで危惧する必要も無い問題のように感じられます。

 

 

 

#まとめ

 

このように、ブロックチェーン技術は、改ざんなどをはじめとする不正に対抗することのできるハッシュ関数により支えられており、今後も、それら不正のない信頼できる取引技術として注目していきたい次第です。

ブロックチェーンに関するブログも運営しておりますので、もしよろしければ、こちらもよろしくおねがいいたします。

[kibinag0.com](http://www.kibinag0.com/archive/category/%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E3%83%81%E3%82%A7%E3%83%BC%E3%83%B3)
docker-compose up するときに subnet を指定する

# 概要

アドレスを変えたかったので、やりかたを調べた

# まとめ

`docker-compose.yml` に、書く。

`192.168.210.0/24` を使いたいときは、以下のような感じ。
具体的には、`networks` のところを追加した。

```
version: "2"
services:
  mongo:
    image: mongo
    volumes:
      - /home/vagrant/work/github/togelack/datadir:/data/db
    restart: always
  app:
    build: .
    ports:
      - 3000:3000
    environment:
      SECRET_KEY_BASE: xxxxx
      RAILS_ENV: production
      MONGOID_ENV: production
      SLACK_TOKEN: xoxp-xxxxx
      SLACK_CLIENT_ID: 'xxxx.xxxxx'
      SLACK_CLIENT_SECRET: xxxxxxx
      SLACK_TEAM_ID: xxxxxx
      SLACK_TEAM_NAME: xxxxxx
      MONGO_URL: mongodb://mongo:27017/togelack
    restart: always
networks:
  default:
    ipam:
      config:
        - subnet: 192.168.210.0/24

```
TypeScriptでnpmパッケージを記述する(最小構成）


はこです。こんにちわ。

何か小さなnpmパッケージを作って公開したい時、TypeScriptを使えば型安全が手に入るし、Decorator等のイケてる機能も手に入るます。


### typescriptのパッケージ作成

```console:

# npm 初期化
npm init パッケージ名

# git初期化
git init パッケージ名

# TypeScript導入
npm install -S typescript 

# tsconfig.json生成
npx tsc --init

```



あとはtsconfig.jsonを好み合わせて変更すればOKです。



なお、ビルドした結果をgitに含めたくないので、postinstallでインストール後にユーザ環境でビルドを行うようにしています。

```package.json
{
  "name": "small-npm-pkg",
  "main": "dist/index.js",
  "scripts": {
    "build": "tsc",
    "postinstall": "postinstall-build dist"
  },
  "devDependencies": {
    "typescript": "^2.6.1"
  },
  "dependencies": {
    "postinstall-build": "^5.0.1"
  } 
}

```


通常、postinstallではdevDependenciesを取得してくれません。

コレを回避する方法として、 [postinstall-build](https://www.npmjs.com/package/postinstall-build) のnpmパッケージを利用しています。





### postinstall-build

一言で言えば「devDependenciesのファイルもインストールしてくれるやつ」です。
 
 ```sh:
 "postinstall-build 出力先ディレクトリ名(必須) 実行コマンド(省略時はnpm buildを実行)"
 ``` 
 
 
 コレのお陰で、devDependenciesを分離できます。
Jupyter でライブラリの API を確認する

# Jupyter Notebook
Python を使ってデータ分析をする場合，インタラクティブにやりたいなと思った場合，
よく Jupyter Notebook が使われます．
Cell と呼ばれる単位でコードを実行できるので，
自分が思っている挙動になっているか，あるいは都度分布を確認するというのがやりやすいです．
Jupyter Notebook については，[記事](https://qiita.com/taka4sato/items/2c3397ff34c440044978)を参考にしてください．

# Python っていいよね！
Python はすごく使いやすいと思います．
そして，書き方を忘れることもよくあるかと思います．
（これは他の言語でもそうだと思います）

そんなときは，ググって...とやる前にやることが一つあるのです．
Jupyterの場合， __APIをJupyter内で調べられる__ のです．

# Jupyter での API の調べ方
例えば， numpy の array の使い方を忘れたとします．
その場合はセル内で，

```python
np.array?
```

としてやればいいです．
こんな具合に...
![スクリーンショット 2017-11-01 16.25.06.png](https://qiita-image-store.s3.amazonaws.com/0/47270/6b0acd74-7927-26b1-ce25-512c2c4c8f16.png)

そうすると画面の下に何やら説明がずらずらと出てきます．
これが API の説明になっています．
API の説明の右上に別タブにするボタンがあるので，それをクリックすると，
![スクリーンショット 2017-11-01 16.28.55.png](https://qiita-image-store.s3.amazonaws.com/0/47270/57f47a4b-1716-e160-d409-40c45e69d632.png)
このような形式で表示されます．

Jupyterって便利！
MOVERIO BT-300 のサンプル一覧

## 目的

どんなサンプルかすぐ忘れてしまうのでスクショ付きでメモします。

## サンプル一覧

| プロジェクト名 | 概要 |  
|:----------------------|:-----------------------------------------|
| SampleCameraPreview   | カメラの映像を表示する                     |  
| SampleControllerGyro  | コントローラのジャイロセンサを扱う           |  
| SampleDisplayControl  | ディスプレイ関連の機能を制御する             |  
| SampleHeadsetGyro     | ヘッドセットのジャイロセンサを扱う           |  
| SampleHWKey           | コントローラの左右のキー入力を扱う           |  
| SampleShowBatteryInfo | バッテリーの情報を出力する                  |  
| SampleTapMute         | ヘッドセットをタップすると画面がミュートになる |  


## SampleCameraPreview
<img src="https://qiita-image-store.s3.amazonaws.com/0/61622/6f9bd5b3-b830-c95c-eb7f-cced519f09e2.png" width=50%>

カメラの映像をリアルタイムで表示する


## SampleControllerGyro
<img src="https://qiita-image-store.s3.amazonaws.com/0/61622/a9f43ad9-10f2-a3fb-a05e-54dfb3f42417.png" width=50%>

コントローラのジャイロセンサの値をリアルタイムで表示する
コントローラの左右の振りを認識し、画像の色を切り替える


## SampleDisplayControl
<img src="https://qiita-image-store.s3.amazonaws.com/0/61622/06d5e724-efbd-8652-5498-310760e5af20.png" width=50%>

2D/3Dを切り替える
ディスプレイを3秒間ミュート状態にする
ディスプレイの明るさを変える

## SampleHeadsetGyro 
<img src="https://qiita-image-store.s3.amazonaws.com/0/61622/2c50f7da-2dbe-1f2a-c146-296659fa3d12.png" width=50%>

ヘッドセットのジャイロセンサをリアルタイムで表示する
ヘッドセットを左右に向けることで、画像の色を切り替える


## SampleHWKey 
<img src="https://qiita-image-store.s3.amazonaws.com/0/61622/60a965a2-631a-1f5f-cd1d-37b010105537.png" width=50%>

コントローラの左右のキー入力で画像を切り替える

## SampleShowBatteryInfo   
<img src="https://qiita-image-store.s3.amazonaws.com/0/61622/26f78cce-f6d1-15e0-ffe0-887664c45624.png" width=50%>

バッテリーの状態をリアルタイムで表示する

## SampleTapMute 
<img src="https://qiita-image-store.s3.amazonaws.com/0/61622/6759a5b1-f4ec-1794-4827-27f58609327a.png" width=50%>

ヘッドセットをタップすることで、ディスプレイをミュート状態にする

## 参考
+ [MOVERIOBT-300 SDK & サンプルプロジェクト] (https://tech.moverio.epson.com/ja/bt-300/sdk_download.html)
kippoを設置する(Cent OS 7)

## kippo導入のためのライブラリ
まずはkippoに必要なライブラリをインストール

```
yum install -y gcc python-devel python-setuptools
easy_install pip
pip install pyasn1 pycrypto
pip install twisted==15.2.0
```

## SSHポート番号を変更

- ポート番号10022への許可

```
cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/service/ssh_2.xml
```
```
vi ssh_2.xml
```

```
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>SSH</short>
  <description>Secure Shell (SSH) is a protocol for logging into and executing commands on remote machines. It provides secure encrypted communications. If you plan on accessing your machine remotely via SSH over a firewalled interface, enable this option. You need the openssh-server package installed for this option to be useful.</description>
  <port protocol="tcp" port="10022"/>　←　ココを22から10022に変更
</service>
```



```
firewalld-cmd --reload
```

```
firewall-cmd --permanent --add-service=ssh_2
```


- SSHのポート変更

```
vi /etc/ssh/sshd_config
```


```
#Port 22 
↓
Port 10022
```

## SELinuxの変更
```
yum install policycoreutils-python
```

```
semanage port -a -t ssh_port_t -p tcp 10022
```

## sshdの再起動

```
systemctl restart sshd
```


## kippo用ユーザーを作成

```
useradd kippo
```

```
su kippo
cd
git clone https://github.com/desaster/kippo.git
cd kippo
cp kippo.cfg.dist kippo.cfg
```


## 起動する

```
./start.sh
```

## 22番ポートへのアクセスを10022番ポートへ
- これをkippo起動前に行うと，Teratermなどで設定している場合はTeratermが落ちます．
- もしかしたらSSHポート番号を変更して再起動した時点で落ちたかも

```
firewall-cmd --permanent --add-forward-port="port=22:proto=tcp:toport=2222"
```

## 使ってみた結果
* [kippoの収集記録](https://qiita.com/nekkoneko/items/db3c29a8ffa860ffae97)
Spring Data JPA において、複数エンティティから参照された際に予期せぬ SQL が実行されて EntityNotFoundException が発生する

#概要
複数のエンティティから参照されるエンティティに JPQL にて結合を
実施した際、予期せぬ SQL が実行されて EntityNotFoundException が発生しました。
具体的には、JPQL 実行後に、参照されているエンティティの情報を元に、2 つのエンティティのうち、データが存在しないエンティティに対して SQL が実行されるため、結果としてデータが見つからない動作となります。
下記の例だと、RecordCompany に存在し、Office に存在しない ID で Office のデータを検索しようとする動作になります。
現象としては [こちらの内容](https://stackoverflow.com/questions/28862986/javax-persistence-entitynotfoundexception-unable-to-find-object-with-id-x) に類似していると判断しております。

```Artist.java
@Entity
@Getter
public class Artist {
  @Id
  private int Id;

  @ManyToOne
  @JoinColumn(name = "record_company_id")
  private RecordCompany recordCompany;

  @ManyToOne
  @JoinColumn(name = "office_id")
  private Office office;
}
```
```RecordCompany.java
@Entity
@Getter
public RecordCompany {
   @Id
   private int id;
   
   @OneToMany(mappedBy = "recordCompany")
   private Set<Artist> artists;
}
```
```Office.java
@Entity
@Getter
public Office {
   @Id
   private int id;
   
   @OneToMany(mappedBy = "office")
   private Set<Artist> artists;
}
```
*JPQL*

```.sql
select x from RecordCompany x left join fetch Artist left join fetch Office where ...
```

*SQLイメージ*

```.sql
-- 想定通りの 1度目の SQL
select ... 
    from 
record_artist a 
    left join record_company b 
on a.record_company_id = b.id 
    left join office c
on a.office_id = b.id 

-- 予期せぬ 2度目の SQL id = 1 は Office に存在しない。
select ... 
    from 
artist a 
    left join office b 
on a.office_id = b.id 
where
    b.id = 1;
```   

#回避策

幸いにドメインモデルが継承戦略を適用するにふさわしいモデルであったため、SINGLE_TABLE の継承戦略を適用することで回避できました。
2 つ以上のエンティティから参照される際、参照元のエンティティの ID は参照先のテーブルに格納されている必要があるようです。
上記例では、Affiliation クラスを用意して、affiliation テーブルに、RecordCompany と Office のレコードを格納して回避しました。

```Affiliation.java
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Getter
public abstract class Affiliation {
   @Id
   private int id;
}

```
```RecordCompany.java
@Entity
@Getter
@DiscriminatorVaue("record")
public RecordCompany extends Affiliation {
   @OneToMany(mappedBy = "recordCompany")
   private Set<Artist> artists;
}
```
```Office.java
@Entity
@Getter
@DiscriminatorVaue("office")
public Office extends Affiliation {
   @OneToMany(mappedBy = "office")
   private Set<Artist> artists;
}
```
```Artist.java
@Entity
@Getter
public class Artist {
  @Id
  private int Id;

  @ManyToOne
  @JoinColumn(name = "record_company_id")
  private Affiliation recordCompany;

  @ManyToOne
  @JoinColumn(name = "office_id")
  private Affiliation office;
}
```

##補足

targetEntity 属性を使うことで [こちらのページ](https://gist.github.com/momotar/0f168cb5d953d519017a) にあるような関連テーブルで解決できる可能性もございましたが、SINGLE_TABLE のシンプルさが有効であると判断したため、上記対処策を実施いたしました。
redashビルドとエラー対応（2017/11 時点）

# Redashのリビルド

Ubuntu16にbootstrap.shで直インストールしたredashをちょっと手直ししたく、ソースをいじってみましたが、
nodeとかwebpackとかよく知らないですが、buildしないと反映されないんですね。
無知すぎていろいろ手こずったのでメモを残します。


## npm周りをインストールし、nodeバージョンを指定
nodeのバージョンが新しすぎても古くても問題が発生したので、npmバージョン管理ツールのnvmを使って指定しておきます。

```shell-session
$ apt install npm
$ git clone git://github.com/creationix/nvm.git ~/.nvm
$ source ~/.nvm/nvm.sh
$ nvm install v8.9.0
```

## npm install、npm run build
本来は`/opt/redash/redash.x.xxx/`でinstallとrun buildすれば動作するはずなんですが、
現時点では`npm run build`の時点でエラーを吐きます。
同じ問題にぶち当たってる人はそこそこいる様子？

500 error post setup on docker install
[https://github.com/getredash/redash/issues/1578#issuecomment-326128982](https://github.com/getredash/redash/issues/1578#issuecomment-326128982)

```shell-session
ERROR in ./client/app/index.js
Module build failed: TypeError: Cannot read property 'length' of undefined
    at Traverser.traverse (/opt/redash/redash.2.0.1.b3080/node_modules/estraverse/estraverse.js:411:37)
    at Traverser.traverse (/opt/redash/redash.2.0.1.b3080/node_modules/eslint/lib/util/traverser.js:31:22)
    at EventEmitter.module.exports.api.verify (/opt/redash/redash.2.0.1.b3080/node_modules/eslint/lib/eslint.js:926:23)
    at processText (/opt/redash/redash.2.0.1.b3080/node_modules/eslint/lib/cli-engine.js:264:31)
    at CLIEngine.executeOnText (/opt/redash/redash.2.0.1.b3080/node_modules/eslint/lib/cli-engine.js:754:26)
    at lint (/opt/redash/redash.2.0.1.b3080/node_modules/eslint-loader/index.js:218:17)
    at Object.module.exports (/opt/redash/redash.2.0.1.b3080/node_modules/eslint-loader/index.js:213:21)
```
エラーの内容を見るに３つほどのモジュールでobjectタイプを判別できていないのだろうか。

## 場当たり対処

`/opt/redash/redash.x.xxx/`でエラー対象のモジュールを再インストールすると…`npm run build`が通りました。

```shell-session
$ npm install estraverse
$ npm install eslint
$ npm install eslint-loader
```
動的メモリ確保なしで派生クラスを格納する`base_storage`クラスを作った

# tl;dr

最大サイズを決めておくことで、それ以下の大きさなら動的メモリ確保なしで格納でき、BaseクラスへのポインタとRTTIを取り出せるクラスを作った。

https://github.com/ToruNiina/base_storage

# 背景

C++で、特定の文脈では同様の意味を持つものの、実装の詳細は異なる複数の型を統一的に扱いたい場合、選択肢はいくつかあります。

一つは、派生クラスです。`Base`クラスに共通のインターフェースを定義し、そのポインタを経由することで、それぞれの型に特異的なメンバを呼び出すことができます。

別の選択肢として、`(std|boost)::variant`があります。これは型安全な`union`で、先に指定しておいた型の集合に含まれるどれか一つの型を格納することができ、その時点で格納している型を調べたり、ある型に変換して取り出したり、それぞれの型に対応する`visitor`を用意することで、自動的に適切な関数を選んで実行できます。

これは速度の面で優れています。`variant`は最初に、入る可能性のある型のリストを受け取れるので、その中で最も大きなサイズの型を格納できるだけの領域を確保すれば、入りうる全ての型をその中に収めることができます。なので、メモリ確保は静的に行うことが出来、コストの高い処理である動的メモリ確保を行う必要がありません。また、都度`new`する場合と異なり、配列を作った時もオブジェクトをメモリ上に隣接して配置できるので、キャッシュヒット率の向上も期待されます。ただし、型が増えてくると書くのが面倒です（それは設計の問題という可能性はありますが）。また、入りうる全ての型を具体的に知っていなければなりません。メモリ消費の点からは、型の一つだけが非常に大きいと非効率的になるでしょう。

[boostjp - Boost.Variant (日本語)](https://boostjp.github.io/tips/variant.html)
[boost.org - Boost.Variant (English)](http://www.boost.org/doc/libs/1_65_1/doc/html/variant.html)
[cppreference.com - std::variant (English)](http://en.cppreference.com/w/cpp/utility/variant)

さらに別の選択肢として、`(std|boost)::any`もあるでしょう。これは動的型で、値を格納するときにメモリをその都度確保してどんな型でも保持する型です。これは任意の型を代入できるので非常に柔軟ですが、内部ストレージ確保のための実行時オーバーヘッドが発生します。また、内部の型に対してどんな前提もおけないので、毎回型情報を見て変換しなければなりません。

[boostjp - Boost.Any (日本語)](https://boostjp.github.io/tips/dynamic_type.html)
[boost.org - Boost.Any (English)](http://www.boost.org/doc/libs/1_65_1/doc/html/any.html)
[cppreference.com - std::any (English)](http://en.cppreference.com/w/cpp/utility/any)

変わり種ですが、`static_any`なるものを作った人がいます。これは`any`の柔軟性と`variant`の速度を混ぜあわせたようなクラスで、最初に`any`に入れられる最大サイズを決めておき、`variant`と同様に静的にその分のメモリを確保し、`any`の内部ストレージとしてその領域を使うというものです。 _最大サイズを超えない限り_ どんな型でも入れられる、と少し制約は付きますが、速度向上がそれを補っているでしょう。ただし、`variant`と同様、最大サイズを大きくし過ぎるとメモリの浪費が激しくなります。

[github - david-grs/static_any](https://github.com/david-grs/static_any)

この発想は面白いと感じました。これと同様の戦略が、継承による解決の高速化に使えるのではないでしょうか。

# 今回作ったもの

というわけで、`static_any`のアイデアを元に、表題の`base_storage`クラスを作りました。

```cpp
template<typename Base, std::size_t Size>
class base_storage;
```

基本的には、中に入っているものは全て`Base`クラスから派生しているという前提を置いた`static_any`です。例えば、`Base`クラスから`Derived`クラスが派生しており、`void dosomething()`なる関数を`override`しているとしましょう。何らかの方法で、`MaxSize`が決定できたとします。実際、入れるべき型が決まっていればちょっとした`constexpr`関数かTMPによってこれは計算できます。

```cpp
base_storage<Base, MaxSize> storage(Derived());
assert(std::type_index(storage.type()) == std::type_index(typeid(Derived)));
storage.base_ptr()->dosomething(); // Derived::dosomethingが呼ばれる
```

`Base`から派生しているもの以外は受け付けない点については、コンストラクタや`operator=`で代入しようとした型が正しいかどうか判定して、違った場合は`std::enable_if`によって抑制できます（`std::is_base_of`が`private`などの指定を無視する点は少し困りものですが）。また、`static_assert(sizeof(T) <= capacity);`のようにして、最大サイズを超えるものを格納しようとした時にコンパイルエラーにできます。

`static_any`との比較ですが、無条件に`Base*`を取れるので`any_cast`に相当するチェックなしで仮想関数呼び出しができます。

`operator->`をオーバーロードすることでコードを書く上での少し利便性が高まりそうですが、これは意味的にはポインタではないので悩みどころでしょう。

実装やサンプルコードに関しては、[githubレポジトリ](https://github.com/ToruNiina/base_storage)をご覧ください。
new DateTime('yesterday')とnew DateTime('-1 day')の違い

## 経緯

UTCで動いているサーバで、

1. UTCで入っている現在時刻をJSTに変換
1. 実行日の前日の日付を取得
1. 前日データをうんぬんかんぬん

というバッチを日本時間の朝7時に毎日回す想定で、PHPでこんなコードを書いた。

```php:前日日付を8ケタで返すコード？
$y = new DateTime('yesterday');
$y->setTimezone(new DateTimeZone('Asia/Tokyo'));
$yesterday = $y->format('Ymd');
```

ところが、これで取得した8ケタの日付が前日でなく前々日だったという…。

## `yesterday` ≠ `-1 day`だった

var_dumpを張ってみて発覚。`new DateTime('yesterday');`の認識が誤っていた。
てっきりちょうど1日前の日時を返してくれるものだと思っていたら…

```php:実験1
$y = new DateTime('yesterday');
var_dump($y);
```

```:出力1
object(DateTime)#126 (3) {
  ["date"]=>
  string(26) "2017-10-31 00:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(3) "UTC"
}
```

`$y`には前日の00:00:00が格納されていた。
つまりJSTの7時（UTCの22時）にこのコードを動かすと、`$y`には22+24=46時間だけ遡った時刻が格納されてしまう。
そのために、実行した日本時間7時の46時間前、つまり前々日ぶんのデータをうんぬんかんぬんしていたご様子。

「昨日」でなく、「昨日の今」まで取得したいなら、こうでした。

```php:実験2
$y = new DateTime('-1 day');
var_dump($y);
```

```:出力2
object(DateTime)#126 (3) {
  ["date"]=>
  string(26) "2017-10-31 04:54:02.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(3) "UTC"
}
```
これでピッタリ24時間前。

## まとめ
昨日の日付のみが欲しいのであれば`'yesterday'`
時刻まで込みで欲しいのであれば`'-1 day'`

毎日決まった時刻に動くバッチを実装する際、昨日の日付が欲しくなったときは、相対日付は`'yesterday'`でなく`'-1 day'`を選んだ方が無難そうです。

## 実は公式ドキュメントにも説明がありました
http://php.net/manual/ja/datetime.formats.relative.php#datetime.formats.relative
Leaflet と OpenStreetMap で伊能忠敬の古地図を表示してみよう

[OpenStreetMap Advent Calendar 2017](https://qiita.com/advent-calendar/2017/osmjp) へ投稿の記事です

# Leaflet.js 

ブラウザで地図を表示するためのオープンソースクライアントライブラリです。
Google Maps に近いものですが、表示する地図を OSM や国土地理院の地図などユーザの任意の地図にできます。

今回はこの Leaflet.js に OSM の地図を表示して、なおかつ古地図画像をプロットしてみたいと思います。
地図にプロットする古地図は国土地理院の「[古地図コレクション](https://kochizu.gsi.go.jp/)」を引用します。

引用する古地図画像は、正確無比と名高いかの伊能忠敬の[越中　能登　能登島](https://kochizu.gsi.go.jp/items/377?from=category,14,index-table)の図にしました。

まずは地図を作成するHTMLとCSSを用意します。

```html
<div id="map"></div>
```

```css
html, body {
  height: 100%;
}
#map {
  position: relative;
  width: 100%;
  height: auto;
  min-height: 100%;
  background-color: #ddd;
}

.leaflet-tile-pane > .leaflet-layer {
    opacity: 0 !important;
}
```

次に Leaflet.js を使って地図を作成します。

```js
var map = L.map('map', {
  attribution : '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
  center: [37.33522435930641, 136.74133300781253],
  zoom: 9
});
```

Leaflet.js では、ここに独自に画像を表示し WEB 地図のように拡大やドラッグ移動などできるようにすることもできるのですが、今回は OSM のタイルサーバから世界地図を読み込むようにしました。

```js
const layerUrl = 'http://{s}.tile.osm.org/{z}/{x}/{y}.png';
var tileLayer = L.tileLayer(layerUrl).addTo(map);
```


## 画像をプロットする

地図に画像をプロットします。
プロットする時は、座標系での数値していになります。
Leaflet.js には画面のピクセルと座標系を相互変換できる関数も用意されていますが、今回は適当に配置 笑

```js
let ne = { lat: 36.5, lng: 136 };
let imageUrl = "http://kochizu.gsi.go.jp/map-thumbnails/inouzu-saisyokuzu/i084.jpg",
imageBounds = new L.LatLngBounds(
  [ne.lat, ne.lng],
  [ne.lat + 0.75, ne.lng + 1.5]
 );
L.imageOverlay(imageUrl, imageBounds).addTo(map);
```

## 結果

このように地図がクライアントに表示されました。
OSM のタイル画像が読み込まれるコンテナを CSS で `opacity: 0 !important;` として背景を透過しています。

![越中　能登　能登島](https://qiita-image-store.s3.amazonaws.com/0/208400/dafb41d3-06f4-b59a-3912-9f3852be9048.png)

OSM の座標を利用して実際の座標に合わせてプロットしたかったのですが時間がなくて断念しました。笑
実際は以下の画像のようにプロットされています。

![透過していない場合](https://qiita-image-store.s3.amazonaws.com/0/208400/ef68c954-1d20-f253-acab-efb51453736d.png)
Google URL Shortenerで短縮URL生成

# 追記

Google URL Shortenerでの短縮URL生成は2019/03/30にサービス終了しました。

----

# 手軽に生成したい場合

- 以下を利用すればOK
 - [https://goo.gl/](https://goo.gl/)

- でも、複数生成したい場合は都度reCAPTCHAしなければならず非常に面倒

# reCAPTHA回避して複数生成したい場合

- curlでAPIにリクエスト投げましょう

```sh:shortener.sh
#!/bin/bash

api_key="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
url=$1

curl -s -X POST \
    -H 'Content-Type: application/json' \
    -d "{\"longUrl\": \"${url}\"}" \
    "https://www.googleapis.com/urlshortener/v1/url?key=${api_key}" | jq -r '.id'
```

- APIキーは以下から取得してください
 - https://developers.google.com/url-shortener/v1/getting_started#APIKey

# 参考

https://developers.google.com/url-shortener/v1/getting_started
IBM Cloudの試用


IBM Cloudに無料アカウントができたと聞いて、早速使ってみることにした。
- https://www.ibm.com/cloud-computing/jp/ja/bluemix/lite-account/

IBMのサイトにおいても、ライト・アカウントと書かれていたり、標準アカウントと書かれていたりで、正直なところ、メールアドレスと姓名と電話番号を登録して作成したアカウントが権限も含めてどうなっているのか分かりづらい。

さて、Bluemixに関して検索すると、いろいろな情報が得られるのだけれど、2016年頃の情報がすでに古くなっているようで、正直なところ、アカウント作成後は何から始めたらよいのか、イマイチ分かりづらい。

ということで、2017年11月時点での、自分用の備忘録も兼ねて。

## アカウント作成
[IBM Cloudの試用](https://www.ibm.com/cloud-computing/jp/ja/bluemix/lite-account/)のWebページを開いて、[ライト・アカウントを今すぐ登録](https://console.bluemix.net/registration/)というリンクを開くと、登録画面になる。

この画面では、メールアドレス(IBM IDになる)と、姓名とパスワード、国、電話番号を登録する。会社名の入力欄もあるが、それは任意だ。

最後に「アカウント作成」のボタンを押すと、登録したメールアドレス宛に確認メールが届くので、そのメールに書いてあるURLにアクセスすることで、アカウントがアクティベートされる。

このプロセスには、特に何の疑問もない。

## ダッシュボード
初めてログインすると、ダッシュボードの画面になる。

### 組織とスペース
IBM Cloud(Bluemix)は、PaaSなので、クラウド上に自分用の環境が作成されるのだけれど、その際の「組織」「スペース」などを聞かれる画面に飛ばされるときもあるし、自動で「米国南部」にIBM IDと同じ名前の「組織」が作成されて、その下に「dev」というスペースが作成される場合もある。

自分で組織の設定をすることを求められた場合は、「組織？スペース？なんのこっちゃ？」と思ったりもするけれど、組織名もスペース名もサジェストされるので、IBM Cloudと同じ組織名でtestとかdevとかいう名前のスペースを作ることになると思う。

### カタログ
では、Cloud上に作成する自分のアプリケーション用のプラットフォームを作成することになる。この際には、カタログのページから、テンプレートを選択することになる。
IBMいわく、「30秒で設定完了」とのことだけれど、例えば、Node.jsのカタログを選択したりすると、本当に30秒程度で「Hello World」が表示されるだけのWebアプリケーションが稼働するようになる。

ライト・アカウントの場合は、このカタログで選択可能なテンプレートに制限がある。制限があるが、そもそも無料アカウントで何か試してみようという目的からしたら、十分な種類と量のテンプレートが表示される。

### Cloud Foundry Command Line Interfaceの入手
さて、Bluemix環境で何らかのアプリケーションを開発した場合に、[Cloud Foundry](https://www.cloudfoundry.org/)の配布するソフトウェアを使う必要がある場合がある。

http://docs.cloudfoundry.org/cf-cli/install-go-cli.html によると、Mac版の場合は以下の様にインストールできるようだ。

```
$ brew tap cloudfoundry/tap
$ brew install cf-cli
```

### bluemix Command Line Interfaceの入手
Bluemix 上のアプリケーションをローカルのマシンで修正して、Bluemixにデプロイするために使うコマンドラインツールとして、Bluemix Command Line Interfaceも必要になる。これは、
https://console.bluemix.net/docs/cli/reference/bluemix_cli/get_started.html#getting-started から、binary形式のものをダウンロードして、インストールする。

----

## チュートリアルの実行
以上の準備ができたところで、ようやくチュートリアルを実行可能になる。
試しに、[SDK for Node.JSの入門チュートリアル](https://console.bluemix.net/docs/runtimes/nodejs/getting-started.html)を実施してみる。

### コードのダウンロード

```
git clone https://github.com/IBM-Bluemix/get-started-node
```

カレントフォルダに、```get-started-node``` というフォルダができる。

### アプリケーションの実行
ローカルの環境で実行してみる。

```
cd get-started-node
npm install
npm start
open http://localhost:3000/
```

簡単な、Hello WorldのWeb Applicationが起動することが確認できた。

![20171101_01.png](https://qiita-image-store.s3.amazonaws.com/0/15553/b69238d0-0ea9-8ed3-3a7c-b631618a3636.png "20171101_01.png")

```What is your name?```に答えると、```Hello <名前>```と表示してくれる。

### アプリケーショのデプロイ
ローカルの環境で動くことが確認できたので、これをBluemix環境にデプロイする。

```
cf api https://api.ng.bluemix.net
cf login
cf push
```

cf pushした時に表示されるURLにアクセスすると、先程localhostで動作していたのと同じWeb Application (Hello World)が、Bluemixの環境上で動作していることが分かった。

----
## 本日のまとめ
- IBMのCloud環境が無償化されたのを受けて、アカウントを作成してみた
- コマンドラインツールなどをインストールして利用環境を作成した
- Node.jsの入門チュートリアルを実施してみた
Androidで署名付きapkを作成する


今更なんですが、最近Androidを始めたのと既存のKeyStoreの場合にどうするかちょっと迷ってしまったので、個人的なメモとして残しておきます。

# 環境

- Mac : MacBook Pro (Retina, 15-inch, Mid 2015)
- OS : 10.12.6
- Android Studio : 2.3.3 (すいません3.0ではないです><)

# ユースケース

1. 新規で作成
2. 既存ので作成

# 手順

## 1. 新規で作成する場合

### メニューから ```Build``` -> ```Build APK``` を選択する

![スクリーンショット 2017-11-01 12.50.31.png](https://qiita-image-store.s3.amazonaws.com/0/25250/4fd43a67-05ed-1278-62b6-800ae0522956.png "スクリーンショット 2017-11-01 12.50.31.png")

### 下記のWindowが表示される

![スクリーンショット 2017-11-01 12.50.55.png](https://qiita-image-store.s3.amazonaws.com/0/25250/b9fffd66-44e5-ea9e-163b-1402089c0a36.png "スクリーンショット 2017-11-01 12.50.55.png")


### ```Create new...``` を選択する

![スクリーンショット 2017-11-01 12.50.55.png](https://qiita-image-store.s3.amazonaws.com/0/25250/b9fffd66-44e5-ea9e-163b-1402089c0a36.png "スクリーンショット 2017-11-01 12.50.55.png")

### ```Generate Signed APK``` という別Windowが開かれます

![スクリーンショット 2017-11-01 15.17.22.png](https://qiita-image-store.s3.amazonaws.com/0/25250/2e4889b8-5fc9-c05b-e7ad-1bbf42a95e69.png "スクリーンショット 2017-11-01 15.17.22.png")


### 設定する項目
- Key store path
	- key storeの保存場所
- Password（Confirm）
	- Key storeのPassword（以降でてくるkeyのPasswordとは別物）
- KeyのAlias
	- 任意のラベル（わかり易い名前で）
- Password（Confirm）
	- KeyのPassword
- Certificate
	- 証明書の情報（Nameだけ入力すればとりあえず動きます）

### ```OK``` を押下すると設定が反映される

![スクリーンショット 2017-11-01 14.46.06.png](https://qiita-image-store.s3.amazonaws.com/0/25250/52d1fd33-bcd8-b847-27a9-56847de31c82.png "スクリーンショット 2017-11-01 14.46.06.png")

### ```Next``` を押下すると以下に遷移する

![スクリーンショット 2017-11-01 14.49.13.png](https://qiita-image-store.s3.amazonaws.com/0/25250/ab078c8f-dbd4-b8d5-c602-8d82ec192505.png "スクリーンショット 2017-11-01 14.49.13.png")


### 設定項目

- APK Destination Folder
	- apkが格納されるDirectory
- Build Type
	- 該当のも
- Flavors
	- 該当のもの
- Signature Versions
	- 両方ともにチェックを入れる（詳しくは[こちら](https://developer.android.com/about/versions/nougat/android-7.0.html#apk_signature_v2)）

### ```Finish``` を押下、設定している項目が正しければ、apkのビルドが始まります

## 2. 既存のKeyStoreで作成する場合

### メニューから ```Build``` -> ```Build APK``` を選択する

ここまでは一緒です

### ```Choose existing...``` を押下する

![スクリーンショット 2017-11-01 12.50.55.png](https://qiita-image-store.s3.amazonaws.com/0/25250/b9fffd66-44e5-ea9e-163b-1402089c0a36.png "スクリーンショット 2017-11-01 12.50.55.png")

- Key store path
	- 既に作成した、もしくはメンバーが既に作成した拡張子 ```.jks``` ファイルのpathを選択します
- Key store path
	- 既存のKey storeのPasswordを入力します
- Key alias
	- Passwordを入力すると ```...``` 押下で設定されているエイリアスが選択できるようになります（Passwordがあっていれば）
- Key password
	- Keyに設定されているPasswordを入力します

### ```Next``` 以降は新規作成と手順が一緒です

### 注意点

アプリ公開用のKey storeをなくしてしまうと、新たにPackage Nameを変更する必要があり、別アプリ扱いにしないといけないので管理には注意です。

### 最後に

既存のKey Storeを扱う際にGUI的に迷ってしまったのでメモしました。今年のGoole I/Oでは[Google Play App Signing](https://support.google.com/googleplay/android-developer/answer/7384423?hl=ja)というものが発表されたようです。

### :paperclip: Refs

- [Android Studioでアプリ公開用KeyStoreを作成して本番ビルドする](https://qiita.com/konifar/items/6c6b73deae9085a69666)
- [【Android】Google Play App Signingのススメ](https://qiita.com/rkowase/items/90cdc4e8c6fc449d8276)
新しいIBM Cloud（Bluemix）の無料アカウントを申し込んでみる

#背景
日経には、だいぶキャッチーな表現で紹介されていますが、Bluemix改め、IBM Cloudの無料アカウントの体系が本日からかわり、ライトアカウントというものが使えるようになりました。

> 米IBM、AI「ワトソン」無料に　アマゾンに対抗
> https://www.nikkei.com/article/DGXMZO22747480W7A021C1MM8000/

ということで、早速アカウントを作ってみましたので、簡単にその内容を。
また、アカウント作成自体は簡単ですので、補足やいままでのアカウントとの違いなども。


#いままでの無料アカウントとの違い
いままでの無料アカウントを「フリートライアル」、新しいものを「ライトプラン」と呼ぶようですが、以下のような違いとなっています。

| 項目      　　　　　 |旧　フリートライアル | 新　ライトプラン    |
|:--------------------|:------------------:|:------------------:|
| 無料期間            |30日間 |        期限無し（※1）       |
| クレジットカード情報 |                 必要|               不要|
| メモリ                |             2G |        256M       |
| 利用可能サービス種類     |             ほぼ全て |         PaaSやWatsonなど（※2） |
| 利用可能サービス数     |            同時に4つまで |        制限無し |


※1 一定期間利用無しで削除されるようです（10日間利用無しでアプリ停止、30日間利用無しで削除）

※2 全部で現在は40種類ほどを利用可能で、Java、PHPなどの主要アプリや、WatsonもDiscoveryやConversationなどの主要どころは乗っています。(11/2に早速watsonのtext to speech、speech to textも追加されてました。今後も拡張されていくのではないでしょうか) ~~一方で、NodeRedがないのが個人的には残念。。。。~~ →「Internet of Things Platform Starter」を使用すれば、node-redが同梱されているので、ライトアカウントでもnode-redが使用可能でした。asmanabuさん、ご指摘ありがとうございます。


クレジットカードの入力が不要になったことと、30日間の利用制限がなくなったことで、よりお気軽に使えるようになっています。

あと、個人的にライトアカウントになってうれしいのは、同時利用サービス数の制限が4個から10個に拡張されたことです。特にWatson系のサンプルアプリを作っていると、複数サービスを組み合わせたくなるのですが、このときにすぐに4つに達してしまうため、いままでは削除しては追加を組み合わせていましたが、これが不要になります。

いっぽうで、メモリ量や使用可能サービス種類は狭まっていますので、いままでの無料アカウントを持っている方はそのまま持っておき、別アカウントとしてライトアカウントを作成したほうがよいと思います。（申し込み時に使用するメールアドレスを別のものにすることで、別アカウント作成が可能でした）



#ライトアカウント作成方法
３ステップで終わります。
迷う入力項目もないのではないでしょうか。

①Bluemixページにすすんで、上のほうにある「無料トライアル」ボタンを押す
> Bluemixページ(IBM)
> https://www.ibm.com/cloud-computing/bluemix/ja

②登録情報を入力
メールアドレス、氏名、パスワードなどを入力し、アカウントを作成ボタンを押します。

③メールのリンクをクリック
登録情報として入力したメールアドレスに確認メールが飛んできますので、メール本文内のリンクをクリックします。

メールタイトルはこんな感じでした。「Action required: Confirm your IBM Cloud account」


#（参考）ライトアカウントのカタログ

いま使えるサービスの一覧をキャプチャしてみました。

![Screenshot-2017-11-1 カタログ - IBM Bluemix(1).png](https://qiita-image-store.s3.amazonaws.com/0/176688/0083ba39-0200-4e20-09e5-04eeca69f606.png)
BootStrapのドロップダウンメニューを閉じないようにする


今更BootStrap感あるけど。

## 概要
https://getbootstrap.com/docs/3.3/components/#btn-dropdowns
このメニューの中チェックボックス入れた時に、ラベルクリックすると閉じちゃうのを止めたかった

こんなHTML

```haml
.btn-group
  %button.btn.btn-default.dropdown-toggle{ 'data-toggle': 'dropdown' }
    Action
    %span.caret
    %ul.dropdown-menu.dropdown-menu-right
      %li
        .checkbox
          %label
            %input{ type: :checkbox }
            Action
```

## 対応

BootStrapで、以下のようにページ全体でクリックイベント待ち受けしてメニューを閉じているので

```js
$(document).on('click.bs.dropdown.data-api', clearMenus)
```

チェックボックスの親も含めて、クリックしてもイベントを伝播しないようにした。

```js
$('.checkbox').on('click.bs.dropdown.data-api', (event) => event.stopPropagation())
```

メニュー閉じる動作は、ブラウザのネイティブなものではないので `event. preventDefault()` だと効かないのに注意。
よく使うEclipseショートカットキーまとめ


###必須ショートカットたち

- 補完機能  
変数名やメソッド名、クラス名等を途中まで入力していれば自動で入力補完してくれる

```
Ctrl + Space
```

- 戻る/進む  
直前、直後に開いたソースに移動する

```
Alt + ← / Alt + →
```

- 呼び出し元階層を開く  
クラス名、メソッド名にカーソルを置いて検索ができる

```
Ctrl + Alt + h
```

- インデントの整形  
フォーマットを自動で整えてくれる

```
Ctrl + shift + f
```

- コメントアウト  
カーソルのある行をコメントアウトできる

```
Ctrl + /
```

###作業が早くなる知っておきたいショートカット

- 行削除  
カーソルのある行が削除できる

```
Ctrl + d
```

- メソッド名の変更  
変数名やメソッド名を一括変更できる

```
Alt + Shft + r
```

- import文の一括編成  
必要/不要なimport文を一括で編成してくれる

```
Ctrl + Shift + o
```

- 対応するかっこに移動  
if文がいくつも入れ子になっている場合などに便利

```
Ctrl + Shift + p
```

- Javadocコメントの追加  
これで一発です

```
Alt + Shift + j
```
Google Cloud SDKをpyenvのpythonでinstallする


## python2系インストール
python3系でインストールしようとするとエラーになった
仕方ないので、2系をインストール

```
pyenv install 2.7.10
pyenv global 2.7.10
```

## オプションをつけて実行


指示通りにやるとplatformがないと怒られた

```
$ ./google-cloud-sdk/install.sh

Welcome to the Google Cloud SDK!
Traceback (most recent call last):
  File "~/Downloads/google-cloud-sdk/bin/bootstrapping/install.py", line 8, in <module>
    import bootstrapping
  File "~/Downloads/google-cloud-sdk/bin/bootstrapping/bootstrapping.py", line 9, in <module>
    import setup
  File "~/Downloads/google-cloud-sdk/bin/bootstrapping/setup.py", line 27, in <module>
    from googlecloudsdk.core.util import platforms
  File "~/Downloads/google-cloud-sdk/lib/googlecloudsdk/core/util/platforms.py", line 18, in <module>
    import platform
ImportError: No module named platform
```

なのでオプションをつけて実行


```
CLOUDSDK_PYTHON_SITEPACKAGES=1 ./install.sh
```

## zshrcの設定

```
export CLOUDSDK_PYTHON_SITEPACKAGES=1
source 'PATHTO/google-cloud-sdk/path.zsh.inc'
source 'PATHTO/google-cloud-sdk/completion.zsh.inc'
```
AndroidアプリのURLスキームのテストをadbから実行する

AndroidでURLスキーム（sample:// のようなやつ）をテストしたい時、わざわざテキストに書いて端末に保存しておくのは面倒ですよね。

adbから直接Intentを投げることでテストすることが可能です。

# 簡単に言うと
1. `adb shell`で端末に入って
* コンソールからIntentを投げる


です。

# 前準備
テストしたい端末（or エミュレータ）にshellで入ります。

```
$ adb shell
```

# adbからIntentを投げる
下記コマンドのように投げます。

```
am start -a android.intent.action.VIEW -d "sample://"
```
`sample://`には任意のURLを入れてください。
これらをどこかテキストとして置いておいて、必要に応じてコピペする等したら便利かもしれませんね。

以上です。
Heroku上のLaravel 5.5でHTTPSを有効にする

HerokuにLaravelをデプロイした際、そのままではroute()、asset()等のヘルパーで出力されるスキームが`http`になります。
これはアクセスする際にHeroku側のロードバランサによってフォワードされ、リクエストのスキームが消えてしまうことが原因です。

## 対応策

[Laravel 5.5ではTrustProxiesというミドルウェアが追加されています。](https://github.com/laravel/laravel/releases/tag/v5.5.0)
通常、`$proxies`にロードバランサのIPアドレスを追加することでLaravelにリクエスト元のスキームを正しく伝えることができます。

しかしHeroku上のロードバランサはIPアドレスがアクセスのたびに変わるため、指定するべきIPアドレスを特定することができません。
この場合は以下のようにワイルドカードを設定することができます。

```php:app/Http/Middleware/TrustProxies.php
     /**
     * The trusted proxies for this application.
     *
     * @var array
     */
    protected $proxies = '**';
```

## 参考資料

[HTTP Requests - Laravel](https://laravel.com/docs/5.5/requests#configuring-trusted-proxies)
CPS変換風のやり方で NNF(否定標準形) を DNF(選言標準形) に変換する


NNF: 否定(¬) が葉ノードにだけついている、∧ と ∨ で表現された論理式。
DNF: NNFのうち、root ノードが ∨ であり、それぞれの節が ∧ だけで出来ている論理式。

例: 以下のNNFを

```lisp
(and (or (and x (not z)) y)
     c
     (or a b))
```

DNFに変換したい。

```lisp
(or (and x (not z) c a)
    (and x (not z) c b)
    (and y c a)
    (and y c b))
```

べつにこれを実装するのにCPS変換の知識が必須というわけではない。
しかし、イテレータみたいなものを実装しようとすると、必然的にCPS変換っぽくなるのだ。


```lisp

(ql:quickload '(:trivia :trivia.quasiquote))
(use-package :trivia) ; パターンマッチ用マクロ
(named-readtables:in-readtable :fare-quasiquote) ; パターンにquasiquote ` を使える

(defun NNF-DNF (condition)
  ;; 論理式をとって、継続渡しスタイル(cps)の関数を返す。
  ;; OR 節はイテレータになる。
  (ematch condition
    (`(or ,@rest)                             ; list の 最初の要素がorのとき
      (let ((restk (mapcar #'NNF-DNF rest)))  ; 要素ごとにcps関数を作って
        (lambda (k)                    ; 関数自体もcps関数を返す
          ;; calls k for each element
          (dolist (nowk restk)         ; イテレータ
            (funcall nowk k)))))       ; それぞれのcps関数に継続(残りの計算)を渡す

    (`(,first ,@rest)                 ; or 以外の場合
     (let ((firstk (NNF-DNF first))   ; first と rest のcps関数を作って
           (restk  (NNF-DNF rest)))
       (lambda (k)
         (funcall firstk              ; first を評価
                  (lambda (result)    ; 結果が継続に渡されて
                    (funcall restk    ; rest も評価
                             (lambda (result2) ; 結果が帰ってきて
                               ;; 2つをconsで渡して 継続(残りの計算) に渡す
                               (funcall k (cons result result2)))))))))

    (_ ; list じゃない場合は そのまま現在の値を継続に渡す
     (lambda (k) (funcall k condition)))))
```

これだけだと結果を取り出す方法を書いてないので

```lisp
(defun use-expander (condition)
  (let (acc)
    (funcall (NNF-DNF condition)
             (lambda (result)      ; 最後のコールバックとしてaccに貯める関数を指定
               (push result acc)))
    (print acc)))
```

結果確認。

```lisp
(use-expander 'a)
(use-expander '(or a b))
(use-expander '(or a b c (or d e)))
(use-expander '(and x (or a b)))
(use-expander '(and (or x y) (or a b)))
(use-expander '(and (or x y) c (or a b)))
(use-expander '(and (or (and x z) y) c (or a b)))
(use-expander '(or (and x (or w z)) y))

(A) 
(B A) 
(E D C B A) 
((AND X B) (AND X A)) 
((AND Y B) (AND Y A) (AND X B) (AND X A)) 
((AND Y C B) (AND Y C A) (AND X C B) (AND X C A)) 
((AND Y C B) (AND Y C A) (AND (AND X Z) C B) (AND (AND X Z) C A)) 
(Y (AND X Z) (AND X W)) 
```

動いてるっぽい。
Google Assistant SDKのサンプル利用

Google Assitant SDKを利用した検証を実施したので、メモ。

#環境：
DELL　LATITUDE D430 (Mdel No.PP09S)
OS　ubuntu 16.04
USBマイク　SANWA SUPPLY MM-MCUSB16 USBマイクロホン

#手順：
以下の手順に従って実施すればおおむね成功するが、念のため実施した内容を手順として記録します。
https://developers.google.com/assistant/sdk/develop/python/

①ubuntuのイメージを入手
https://www.ubuntulinux.jp/

②DVDに焼いて、インストール対象（今回はDELLのノートPC）にDVDドライブ
をUSB接続して電源ON
念のため。。。BOOTの優先順位がHDDからになっているはずなので、BIOS起動直後（DELLのロゴマークが表示されたとき）に[F12]を押してBIOSの設定画面からどこからBOOTするのかを選択します。

③インストーラーに従ってOSをインストールします。

④インストールが無事終了！！
したと思ったら思わぬ落とし穴が。。。WiFiがOSに認識されてない・・・
ネットワークの設定からWiFiが選択できない状態になっています。
VPNしか設定ができない。。。
![Screenshot from 2017-11-01 12-04-29.png](https://qiita-image-store.s3.amazonaws.com/0/208434/b6280ea6-c8f2-0860-4ba8-dbb65478e781.png)

⑤まずは、WiFiで接続できるようにします。
⑤-1　ubuntuにログインしてデスクトップで右クリックを押下し、[端末を開く]を選択します。
⑤-2　Terminal上で以下コマンドを実行します。　
` #$lspci -vvnn | grep 14e4`

⑤-3　パッケージの再インストール
` #sudo apt-get update` 
` #sudo apt-get --reinstall install bcmwl-kernel-source` 

⑤-4　カーネルのモジュールをいったんアンロードしてから、wlのモジュールを読み込む
` #sudo modprobe -r b43 ssb wl brcmfmac brcmsmac bcma` 
` #sudo modprobe wl` 

⑤-5　少しまって、右上のネットワーク部分にWifiが出てくれば成功
出てこない場合、以下のコマンドを実施してモジュールのアンロード/ロードを実施するとうまくいく
` #sudo modprobe -r b43 ssb wl brcmfmac brcmsmac bcma` 
` #sudo modprobe b43` 
` #sudo modprobe ssb`
` #sudo modprobe wl`
 
（OS起動時にはいつもこれをしないとWifiを認識しない・・・ので、
/etc/rc.localに起動時に実行するスクリプトとして追加したほうがいいかも。。。）
スクリプトとして追記する場合、sudoの実行には、
以下のようにechoで渡してあげれば実行できます。
` echo パスワード | sudo コマンド` 
以下の表示なれば接続できます。
![Screenshot from 2017-11-01 13-01-44.png](https://qiita-image-store.s3.amazonaws.com/0/208434/c73b99b4-1a8e-b5c6-33f3-3ccbaee3ed82.png)

上記でもWifi接続ができない場合は、ノートPCの横のWifiスイッチ（スライド式）が手前に引かれた状態になっているかご確認を。

⑥　後は、Googleのガイドに従って実施すればできる。
https://developers.google.com/assistant/sdk/develop/python/

#動作確認
どうなっていれば、Google Assistant SDKが利用できているのかをGoogleのサンプルを使って確認。
① Pythonを起動する
` #source env/bin/activate` 

② 以下コマンドでサンプルを実行する
` #google-assistant-demo` 

③ 以下のコマンド”ON_START＿FINISHED”がでると”OK Google”の音声入力を待機
![WS000843.JPG](https://qiita-image-store.s3.amazonaws.com/0/208434/34563931-711f-c486-f7e6-7e3b91007759.jpeg)

④ ”OK Google”という単語を認識すると”ON_CONVERSATION_TERN_STARTED”が表示され、
何ををしゃべると認識することができる。また、認識した言葉は、”ON_RECOGNIZING_SPEECH_FINISHED”にて出力される。
今回は”What is Google”と発言しました。
![WS000844.JPG](https://qiita-image-store.s3.amazonaws.com/0/208434/76396c0b-9366-3b55-51bb-7a72f6e46b15.jpeg)

英語音声で返答してくれます（ON_RESPONSE_STARTED表示時？に音声が再生されます）
”ON_CONVERSATION_TERN_FINISHED”の後にも続けたい場合は、
再度”OK Google”とお話すれば会話が実施できます。

⑤ 日本語で”こんにちわ”というと、ローマ字変換”konichiwa”になる。
英語未対応のため、日本語として認識していませんが、
英語でここまで認識するとは恐るべし。。。
![WS000845.JPG](https://qiita-image-store.s3.amazonaws.com/0/208434/f22209bf-8d88-252f-4fc2-8fa2d952ddd0.jpeg)
Debian apt系コマンドTips


apt系コマンドのTips。インストールとか基本的な使い方は知ってる前提

# スーパー牛さんパワー

```bash
$ apt moo
$ apt moo moo
$ apt moo moo moo
# 4つめ以降は上の３つがランダムで出現
```

# インストール可能なバージョンが知りたい

`apt list -a`を使う

```bash
$ apt list -a weston
一覧表示... 完了
weston/testing,unstable 3.0.0-1 amd64 [1.12.0-3 からアップグレード可]
weston/now 1.12.0-3 amd64 [インストール済み、3.0.0-1 にアップグレード可]
```

globパターンが使用可能

```bash
$ apt list -a 'libwayland*'
一覧表示... 完了
libwayland-bin/testing,unstable,now 1.14.0-1 amd64 [インストール済み、自動]

libwayland-client0/testing,unstable,now 1.14.0-1 amd64 [インストール済み、自動]
libwayland-client0/不明 1.6.0-2 amd64

libwayland-cursor0/testing,unstable,now 1.14.0-1 amd64 [インストール済み、自動]
libwayland-cursor0/不明 1.6.0-2 amd64
# 以下省略
```

# 特定のバージョンをインストールしたい

```bash
$ apt list -a weston
一覧表示... 完了
weston/testing,unstable 3.0.0-1 amd64 [1.12.0-3 からアップグレード可]
weston/now 1.12.0-3 amd64 [インストール済み、3.0.0-1 にアップグレード可]
```

となっている場合

```bash
$ sudo apt install weston/testing
```

または

```bash
$ sudo apt install weston=3.0.0-1
```

としてバージョンの指定が可能

# ファイルがどのパッケージに含まれているか調べる

`apt-file`を使う

```bash
$ apt-file search weston.ini
weston: /usr/share/doc/weston/examples/weston.ini
weston: /usr/share/man/man5/weston.ini.5.gz
```

`-x`で正規表現も使える

```bash
$ apt-file search -x 'weston\.ini\.[0-9]'
weston: /usr/share/man/man5/weston.ini.5.gz
```

# パッケージの被依存関係を表示

`apt rdepends`を使う

```bash
$ apt rdepends libwayland-client0
libwayland-client0
Reverse Depends:
  依存: libweston-3-0 (>= 1.11.91)
  依存: libegl1-mesa (>= 1.9.91)
  依存: libmutter0f (>= 1.5.90)
  依存: mpv (>= 1.9.91)
  依存: xwayland (>= 1.9.91)
  依存: gstreamer1.0-vaapi (>= 1.9.91)
# 以下省略
```

# `apt search`をパッケージ名のみにヒットさせる

`apt search`はデフォルトでは説明文まで検索してしまう。
これを止めさせるには`--names-only`を付ければよい。

```bash
$ apt search --names-only compositor
# 以下省略
```

# パッケージが持ってるファイルを知りたい

`dpkg -L`を使用する

```bash
$ dpkg -L libdrm-dev
/.
/usr
/usr/include
/usr/include/libdrm
/usr/include/libdrm/amdgpu.h
/usr/include/libdrm/amdgpu_drm.h
/usr/include/libdrm/drm.h
# 以下省略
```

# `apt`をスクリプトで使うのは良くない？！

`apt`の出力をパイプで繋いだりすると

```
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
```

と警告される
dig結果からANSWERをひとつ取り出すメモ

### digからANSWER（AレコードとPTRレコード）をひとつ取り出したい

正・逆引きをひたすらやって、その結果をサマリする必要があったので、
無理やりawkとsedを使って取り出してみました。

```:Aレコードを取り出す
dig ... | awk '/;; ANSWER SECTION:/,/^$/' | sed -e '/^$/d' -e '1d' | awk '$4 == "A" {print $NF}' | sed -n 1p
```
1. 「ANSWER SECTIONから空白行まで」のかたまりにする
2. その一行目を消す
3. 4フィールド目が「A」である場合に、その末尾のフィールドを取り出す
4. 一行目だけにする


### レコード数も取り出したい

レコードをひとつだけ取り出した手前、「実際にはいくつ引けているのか」が分からないので、
Aレコードの数をHEADER？部分から取り出します。

```:ANSWERの数を取り出す
dig ... | awk -F ':' '{if($3 ~ "ANSWER") print $4}' | sed -e 's/, AUTHORITY//' -e 's/ //'
```

1. ":"（コロン）を区切りに指定して、3フィールド目が「ANSWER」である場合に、4フィールド目を取り出す
2. 「, AUTHORITY」を消去して、4フィールド目のアタマの数字部分だけにする



awkの「○フィールド目が□だった場合、△フィールドを取り出す」というやり方を覚えました。
Rubyで日付取得

毎回忘れるので・・

```Ruby
require 'date'
date = DateTime.now
date.strftime("%Y%m%d_%H%M%S") #=> "20171101_142504"
```
日付と時間を取るだけであれば、dateライブラリをrequireしなくてもTimeで可能です！

```Ruby
time = Time.now
date.strftime("%Y%m%d_%H%M%S")
```
GitlabがFobbiden表示で見られなくなったら

証拠画像と残念な雰囲気の絵文字が同僚から飛んできて確認したら本当だったので
いそいで"gitlab Fobbiden"で検索したら下記参考サイトが出てきました。

DoS攻撃対策の効きすぎらしくホワイトリストにアクセス元IPを追加/反映するとなおりました。

書いてあるとおりアクセス元のGIPを`/etc/gitlab/gitlab.rb`の、
`rack_attack_git_basic_auth`の`ip_whitelist`の配列に追加してコメント符号を設定セクションまるっと外して
`gitlab-ctl reconfigure`すると直ります。

```
# diff gitlab.rb{,.$(date +%Y%m%d)}
243,249c243,249
< gitlab_rails['rack_attack_git_basic_auth'] = {
<   'enabled' => true,
<   'ip_whitelist' => ["127.0.0.1", '送信元GIP'],
<   'maxretry' => 10,
<   'findtime' => 60,
<   'bantime' => 3600
<  }
---
> # gitlab_rails['rack_attack_git_basic_auth'] = {
> #   'enabled' => true,
> #   'ip_whitelist' => ["127.0.0.1"],
> #   'maxretry' => 10,
> #   'findtime' => 60,
> #   'bantime' => 3600
> # }
```

アクセス元のGIPの調べ方は"確認君"とか"UGTOP"とかで検索すると出てきます。以下のようにしても出てくると思います。

```
mygip=$(wget -q -O - http://taruo.net/ip/?raw)
echo $mygip
```

（[プライベートIP](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%A9%E3%82%A4%E3%83%99%E3%83%BC%E3%83%88%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF)を設定してもVPNやSSHトンネリング接続でない限りアクセス許可されないです）

[Rack attack · Security · Help · GitLab](https://gitlab.com/help/security/rack_attack.md)
上記ヘルプ一応見ると以下をみろと書いてあった。
設定例の見た目と[使ってる人の記事](https://qiita.com/patorash/items/57f9f70ca00952e39f37)をみた限りはIPレンジで許可はそのままでは無理そげな気がしました。
[rack-attack/README.md at master · kickstarter/rack-attack](https://github.com/kickstarter/rack-attack/blob/master/README.md)


参考
[GitlabでForbiddenが表示された場合の対処方法 - Qiita](https://qiita.com/copei/items/59a6818dc24b20c5917a)
[rack-contribをやめてrack-attackに乗り換えた - Qiita](https://qiita.com/patorash/items/57f9f70ca00952e39f37)
[wgetコマンドで覚えておきたい使い方16個(+1個) | 俺的備忘録 〜なんかいろいろ〜](https://orebibou.com/2016/03/wget%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%A7%E8%A6%9A%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84%E4%BD%BF%E3%81%84%E6%96%B916%E5%80%8B/)