OmniAICreator/Qiita-1.07M huggingface dataset:
WinFormsのComboBoxでSelected Changedイベントが何回も発火するのが嫌なら

まずコード。
VB.NETで書いてあるやつを修正するとする。
すでに作成済のSelectedIndexChangedイベントの、Handles以降を消す。

```vb
Private Sub ComboBox1_Changed(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
```
を

```vb
Private Sub ComboBox1_Changed(sender As Object, e As EventArgs)
```
とする。

そして今回、私はLoadが終わったらイベントが発火していいので、Loadイベントの最後かShownイベントあたりで、

```vb
AddHandler ComboBox1.SelectedIndexChanged, AddressOf ComboBox1_Changed
```
としておく。

もしも、動的に行いたいのなら、イベントが発火してほしくないタイミングの前に

```vb
RemoveHandler ComboBox1.SelectedIndexChanged, AddressOf ComboBox1_Changed
```
でイベントをはがしておいて、後でまたAddHandlerすれば良い。


Formのロードイベントで、ComboBoxのItemsを設定しているような場合、何回もSelectedIndexChangedが動作しているようです。しかも、他のコントロールの影響で、コンボボックスのSelectedIndexが変わろうものなら、そこでまたSelectedIndexChangedが動作します。それが鬱陶しいと言われたので。
（バカみたいにステップ実行してるからじゃないか。。。とか思ったけど口には出さない）
（発火とかなんとかいまいち全体的に言葉が会ってるか自信ない）
Zabbix3.4 監視対象の設定

CentOS7を、Zabbix 3.4の監視対象とする為の設定方法です。
環境は次の通りです。

・Zabbix 3.4
・CentOS 7.5

Zabbix3.4 の yum リポジトリの登録

```
# rpm -ivh http://repo.zabbix.com/zabbix/3.4/rhel/7/x86_64/zabbix-release-3.4-1.el7.centos.noarch.rpm
```

#<b>Zabbix agentのインストール</b>

```
# yum -y install zabbix-agent
```

設定

```
# vi /etc/zabbix/zabbix_agentd.conf
Server=(Zabbix server IP)
ServerActive=(Zabbix server IP)
#Hostname=[Hostname] (コメントアウトもしくはZabbixで表示するホスト名を設定)
HostnameItem=system.hostname (Hostnameをコメントアウトする場合はコメントアウト外す)
```

Firewallの設定

```
# firewall-cmd --add-port=10050/tcp --permanent
```
サービスの起動

```
# systemctl enable zabbix-agent
# systemctl start zabbix-agent
```

#<b>Zabbixの監視設定</b>
「設定」> 「ホスト」> 「ホストの作成」で監視設定

・ホスト名、グループ名、IPアドレスを設定
![監視.JPG](https://qiita-image-store.s3.amazonaws.com/0/251519/0dfcf12d-cee2-e66a-43f8-b2654e6f3b5b.jpeg)


・テンプレートタブにて、監視対象テンプレートを追加
例）Template OS Linux、Template VM VMware、Template VM VMware Guestを選んで「追加」
![監視２.JPG](https://qiita-image-store.s3.amazonaws.com/0/251519/cdf01a21-27e8-a1b9-f366-611eb9863c82.jpeg)

#<b>監視動作の確認</b>
「監視データ」> 「最新データ」より、監視対象と項目を選んでグラフ形式で確認出来る

![監視４.JPG](https://qiita-image-store.s3.amazonaws.com/0/251519/a19cb6ae-09ba-f7d8-867e-98d48b033a6d.jpeg)



※8/1 誤字訂正いただきありがとうございました。
arduino unoの asm で serial.write (多分nanoもできる)

#環境/environment

arduinoのhardwareserialのコードをasembblyで描きたい

```
void setup() {
  asm(
    //baudrateの設定
    "ldi R16,0x00                     \n"
    "sts 0x00C5,R16                      \n"
    "ldi R16,0x07                        \n"
    "sts 0x00C4, R16                     \n"

//baudrateが300と57600の時は0b00000000をつかう
    "ldi R16,0b00000010                  \n"
    "sts 0x00C0, R16                     \n"

    "ldi R16,0b11001000                  \n"
    "sts 0x00C1, R16                     \n"


    "ldi R16,0b00000110                  \n"
    "sts 0x00C2, R16                     \n"
  );
  asm(
    "USART_Tx:                           \n"
    "LDS  R16,192                        \n"
    "SBRS R16, 5                         \n"
    "RJMP USART_Tx                       \n"

    //udrレジスタに書き込み
    "ldi R16,0x21                        \n"
    "sts 0x00C6, R16                     \n"

    //UCSR0B(0x00C1)UDRIE0(bit 5)をセット
    "lds  R16,0x00C1                     \n"
    "ori  R16,0b00100000                 \n"
    "sts  0x00C1, R16                    \n"

    
  );
}

void loop() {
}
```

#baudrateとUBRR0H、UBRR0Lのsetting
|baudrate|UBRR0H|UBRR0L|
|:---:|:---:|:---:|
|300|13|4|
|1200|6|130|
|2400|3|64|
|4800|1|160|
|9600|0|207|
|19200|0|103|
|38400|0|51|
|57600|0|16|
|74880|0|26|
|115200|0|16|
|230400|0|8|
|250000|0|7|
|500000|0|3|
|1000000|0|1|
|2000000|0|0|



# 引用
[シリアル通信関連のレジスタ](https://garretlab.web.fc2.com/arduino/inside/hardware/arduino/avr/cores/arduino/HardwareSerial.cpp/registers.html)
[](http://www.cs.shinshu-u.ac.jp/~haeiwa/m-com/instruction.html)
[ATMEGA328pの公式データシート](https://avr.jp/user/DS/PDF/mega328P.pdf)
[ATMELの8bitCPUの命令セットやレジスタ](https://docs-apac.rs-online.com/webdocs/0db4/0900766b80db4deb.pdf)
PythonでSSLでRESTを投げるときに、プロキシを通す方法


先日、っても1年以上まえですが、[JavaでSSLでRESTを投げるときに、プロキシを通す](https://qiita.com/masatomix/items/c1f8674213500f54df0f)という記事を書いたのですが、そのPythonバージョンです。

結論を言うと、requests.get メソッドの引き数に、

```python
r = requests.get(
    'https://qiita.com/api/v2/users/qiita/items',
    headers=headers,
    params=payload_obj,
    proxies=proxies,
    verify=False
)
```
って、

```python
proxies = {
    "http": "http://127.0.0.1:8888",
    "https":"http://127.0.0.1:8888"
}
verify = False
```

などを渡してあげればOKです。SSLの検証でエラーになるケースがあるので  verify = False を渡して検証を回避しています。

## コード全体。

アクセス先はQiitaのAPI

```bash
https://qiita.com/api/v2/users/qiita/items?per_page=1&page=4
```

を対象にしてみます。

###まずはcurlで
proxyはとおしてませんが、

```bash
curl 'https://qiita.com/api/v2/users/qiita/items' -d 'per_page=1' -d 'page=4' -G
```

なにかJSONが返ってきたと思います。

###Pythonで
つぎにPythonです。

あ、環境は

```bash
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.13.6
$ python -V
Python 3.6.6
```

OSは macOS High Sierra でやってます


```python:rest_sample001.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import requests
import json


def execute(args):

    headers = {
        "Accept": "application/json",
        "Content-type": "application/json"
    }

    payload_obj = {
        'per_page': '1',
        'page': '4'
    }

    proxies = get_proxy()

    r = requests.get(
        'https://qiita.com/api/v2/users/qiita/items',
        headers=headers,
        params=payload_obj,
        proxies=proxies,
        verify=False
    )
    print(r.url)
    print(r.json())


def get_proxy():
    proxy = 'http://127.0.0.1:8888'
    return {
        "http": proxy, "https": proxy
    }


if __name__ == "__main__":
    execute(sys.argv)


```

```bash
pip install requests -t ./
python rest_sample001.py
```

curlの場合と、おなじ結果が得られるはずです。おつかれさまでした。



##関連リンク
[JavaでSSLでRESTを投げるときに、プロキシを通す](https://qiita.com/masatomix/items/c1f8674213500f54df0f)
[サンプルソース](https://github.com/masatomix/python-samples/releases/tag/0.0.1_proxy)
Androidの自動UIテストでWebViewやScrollViewを座標指定でスワイプスクロールする

# 概要
Espressoの操作録画機能（Record Espresso Test）は便利ですが、残念ながら一部の操作は記録されないようです。
今回は、WebViewのスクロールが記録されなくて困ったので、座標指定でスクロールするコードで代用できないか調べました。
結果としては可能で、[UI Automator](https://developer.android.com/training/testing/ui-automator)の[UiDevice](https://developer.android.com/reference/android/support/test/uiautomator/UiDevice)を使います。

# 実装方法（例）
## build.gradle
```
dependencies {
    ・・・
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3'
　　　　　　　　・・・
}
```
## テストコード
```
// Initialize UiDevice instance (UI Automator)
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());

// 座標{80, 1000}から{80, 100}に1秒(第５引数かける5ミリ秒)かけてスワイプ
device.swipe(80, 1000, 80, 100, 200);
```

# 補足
以下調査中。もしわかる方いましたらコメント下さい。
- WebViewの最後までスクロールする
- WebViewの中で特定の文字列が見つかるまでスクロールする
Qiita—めちゃくちゃ細かな編集リクエストを送ってContributionを荒稼ぎする手法を見つけた


## ソーシャルの魔法は

こういう些細な部分から簡単に崩れ得るものだと思う。

ブランドバリューみたいに、元は形のないものに魔法の粉をふりかけているわけだから。

僕らはこの魔法に、できるだけ浸っていたい。



# 気付いたきっかけ

大量のいいねが同一アカウントからついた。
1分で5個とか、絶対読んでないスピード。

具体的なアカウントは伏せ。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/2ab072ca-d5b8-0d55-0d90-b34ab8573bc1.png)

# 加えて編集リクエスト

大量のいいねの最後だけ「編集リクエスト」になっていた。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/80155a94-d219-4212-fe81-a1b362753996.png)

いいねの狭間に編集リクエストが紛れ込んでいるパターンもあった。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/ba2dbf7d-a249-1560-b890-54a440010aea.png)



# アカウントを確認

アカウントを見ると大量のContributionsを獲得している。
(もしかしてすごいアカウントなのか！？)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/9ebe8be5-d066-6e82-560a-935a563b8997.png)

# ところでQiitaは今こういう仕様

>Contribution (コントリビューション) とは貢献度を意味し、投稿した記事がいいねされることや編集リクエストが受け入れられた記事がその後いいねされることで数値が上がっていきます。

[Contributionとは - Qiita:Support](https://help.qiita.com/ja/articles/qiita-contribution)

# 全ての Contributions が「編集リクエスト」経由

そもそもたくさんの「いいね」が付いている記事に対して、
「シンタックスハイライトの修正」とか「誤字の修正」とかを送って、Contributionsを稼いでいる様子。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/85fd88fe-a033-0f79-3466-bd14dc2cf58f.png)

---

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/e25c6500-2342-b574-6606-8870e0a2cd44.png)

---

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/ab264ada-752c-4c6b-769b-4ff4ad7e4ea2.png)

# 追記

そしてその後、この記事にさえ同一アカウントから「いいね」が付いたのだった。(あなたのことですよ‥！)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/b94d78ee-d72b-e3b3-a92a-955215559025.png)

(何らかの誤認や誤操作を狙っているのだろうか)

# 感想

編集リクエストを送るのはQiitaの仕様に則っているのでまあ良いとして、大量のいいねを付けるのはノイズになるのでやめてほしい。スパムだと思う。

## こんなContiributionsは要らない

突出してるのが本事案の発生日時。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/c0e9c9c1-51c4-16b8-19e5-5b36f2d9fe7d.png)











<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Firebase Cloud FunctionsでNode.js v8を使う

ローカルで

```bash
$ firebase serve --only hosting,functions
```
とかやると

> Warning: You're using Node.js v8.9.4 but Google Cloud Functions only supports v6.11.5.

上記のようなメッセージが出てしまいます。v6.11.5.しかサポートしていないんですね。

個人的には`async/await`を使いたくて、絶望していました。

しかし先日以下の記事を発見しました。

[The Node.js 8 Runtime  |  Cloud Functions Documentation  |  Google Cloud](https://cloud.google.com/functions/docs/concepts/nodejs-8-runtime)

Google Cloudではベータ版という位置づけでNode.js 8が使えるようです！

ということでGoogle Cloudの[コンソール画面](https://console.cloud.google.com/functions/list?_ga=2.134848753.-1667492651.1528118669)に行き、Firebaseで使っているfunctionsのRuntimeを`Node.js 8`にしたら…

```bash
$ firebase deploy --only hosting,functions
・
・
✔  functions[ssrapp(us-central1)]: Successful update operation.

✔  Deploy complete!
```

`async/await`を使用しているfunctionsのdeployが成功しました（以前は失敗していた）！
[Laravel 5.6] Laravel 開発で Javascript を書きたいとき（Laravel Mix の使い方とか）

# Laravel 開発で Javascript を書きたいけど...

Laravel 初心者としては Javasctipt を書きたいと思ったとき、どこにどうやって書いて管理していけばいいかわからないですよね。。（自分だけかもしれませんが。。）

決まった方法はないみたいですが、会社の先輩からのアドバイスなどを基に自分なりにまとめてみました。

#おおまかな流れ

1. npm をインストール

2. `resources/assets/js` 内に js ファイルを作成

3. `resources/assets/js/app.js` を編集

4. `npm run dev` コマンドで js ファイルをコンパイル 

#npm のインストール

Laravel Mix（ js ファイルをコンパイルしてくれるやつ）を使えるようにするために npm をインストールします。

ターミナルでプロジェクトのディレクトリに移動して以下のコマンドを実行。

```
$ npm install
```

ちなみに `package.json` が npm の設定ファイルになっています。

Laravel の一番上の階層ディレクトリに入ってます。

#resources/assets/js 内に js ファイルを作成

`resources/assets/js` に好きなファイル名の js ファイルを作成し、中身を書いていきます。

今回は以下のような簡単なサンプルを作成してみました。

```sample.js
$(function() {
    alert('sample');
});
```

#`resources/assets/js/app.js` を編集

Laravel の一番上の階層ディレクトリに入っている `webpack.mix.js` を見てみると、以下のようになっています。

```webpack.mix.js
mix.js('resources/assets/js/app.js', 'public/js')
   .sass('resources/assets/sass/app.scss', 'public/css');
```

Laravel Mix はこのファイルの中身を見てコンパイルを行ってます。

この場合 `app.js` と `app.scss` をコンパイルして、それぞれ `public/js` と `pulic/css` 内に保存するとの指示になっています。

ここに先ほど作った `sample.js` の項目を追加すればコンパイルしてくれます。

ただ、その場合 `public/js` に `sample.js` というファイルが作成されるため、これをビュー側で読み込ませる必要が出てきます。

作成する js ファイルが１つ２つなら問題ありませんが、数が多くなってくるとちょっとめんどくさいです。

なので `app.js` の中身を編集して、作成した js ファイルを require すれば、わざわざビュー側で js ファイルを読み込む必要がなくなります。

```resources/assets/js/app.js
require('./sample');  // 好きなところに行を追加
```

require でファイルを指定するときは、頭に `./` を付けた相対パスで、拡張子は付けません。

#`npm run dev` コマンドで js ファイルをコンパイル 

これで用意は整いました。

ターミナルで以下のコマンドを実行します。

```
$ npm run dev
```

これで自分が作成した js ファイルがコンパイルされ、その内容が `public/js/app.js` 内に確認できるかと思います。

`sample.js` もちゃんと実行されてます。

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/238891/67e73e50-5f14-41cb-748b-82a97c1a01bc.png)

なお、上記は開発環境用のコンパイルです。

本番環境用のコンパイルは `npm run prod` になります。

以上！
リアルと連動する糸通しゲームを作る

糸通しや，Flappy Birdのような迫りくる壁を回避するゲームをobnizで作りました
距離センサを使って入力しますので，より直感的な操作で遊べます

![20180731_124627.GIF](https://qiita-image-store.s3.amazonaws.com/0/227015/0d37ba08-eeb3-150d-01f0-0c039e1fc62f.gif)

[youtubeでみる] (https://www.youtube.com/embed/9OroMY-90xk)

## 材料

- [obniz](https://obniz.io)
- [距離センサ GP2Y0A21YK0F](https://obniz.io/sdk/parts/GP2Y0A21YK0F/README.md?iframe=false) 
- ブラウザが使えるPC/スマートフォン

## 作り方（ハードウェア）

obnizに距離センサをつなぐだけです．どこに挿してもいいですが，下記のようにつなぎました．

 - io0 : 信号線（黄色）
 - io1 : GND（黒）
 - io2 : VCC（赤）

![IMG_8313.JPG](https://qiita-image-store.s3.amazonaws.com/0/227015/df042e63-0a5b-1d0b-806e-c0056eaca58a.jpeg)


## 作り方（ソフトウェア）
全体のソースコードは[こちら](https://obniz.io/explore/35)にあります

### ハードウェアとの連携
距離センサからの入力はinputHeight変数に自動で入るように設定しておき，使いたいタイミングで使うようにします．

```javascript

  let inputHeight = 0;
  let obniz = new Obniz("OBNIZ_ID_HERE");
  obniz.onconnect = async function () {
    let sensor = obniz.wired("GP2Y0A21YK0F", {vcc: 2, gnd: 1, signal: 0});
    sensor.start(function (height) {
      inputHeight = height;
    })

  };
```


コードの中の`{vcc: 2, gnd: 1, signal: 0}`は距離センサを接続した場所によって変えます．「作り方（ハードウェア）」にて同じように接続していれば，そのままで大丈夫です．

ここでとった値は，毎フレーム内の処理の際に入力値として使っています

```javascript
   let input = (300 - inputHeight);
   input = Math.min(Math.max(0, input), canvas.height);
   dot.push(input);
```

### ゲームロジック
dot（糸）とbar（壁）の変数を作り，そこにそれぞれの値を入れていきます．
どちらも配列にしていて，複数個対応しています．

``` javascript
//新しい壁を追加
bars.push({x: canvas.width, y: Math.random() * 380 - 80, width: 16, height: 160});

//入力値に応じて糸を動かす
let input = (300 - inputHeight);
input = Math.min(Math.max(0, input), canvas.height);
dot.push(input);
dot.shift();
```

### 描画

HTML5のcanvasをゴリゴリ使っていきます

```html
<canvas id="field" width="300" height="300"/>
```

```javascript
  let canvas = document.getElementById('field');
  let ctx = canvas.getContext('2d');



  function drawDots() {
    ctx.strokeStyle = "white";
    ctx.lineWidth = 1;
    ctx.beginPath();

    for (let i = 0; i < dot.length - 1; i++) {

      if (dot[i] !== undefined && dot[i + 1] !== undefined) {

        ctx.moveTo(i, dot[i]);
        ctx.lineTo(i + 1, dot[i + 1]);
      }
    }
    ctx.closePath();
    ctx.stroke();


  }

  function drawBars() {
    ctx.fillStyle = "red";
    ctx.beginPath();

    for (let i = 0; i < bars.length; i++) {

      ctx.fillRect(bars[i].x, bars[i].y, bars[i].width, bars[i].height);
    }

  }
```


### 完成型

![20180731_124627.GIF](https://qiita-image-store.s3.amazonaws.com/0/227015/0d37ba08-eeb3-150d-01f0-0c039e1fc62f.gif)

## まとめ
物理的な動きで遊べるの結構楽しい！
リープモーション／キネクト等でも同じことができますがobnizも簡単でおすすめです
Firebaseからtimestampのカラムをbetween条件でクエリしてデータを表示する方法 on Vue.js 

[javascript \- Query Firebase Database with two between conditions \- Stack Overflow](https://stackoverflow.com/questions/42228445/query-firebase-database-with-two-between-conditions)

## 前提

- Firebaseはcloudfirestoreを使っています

- インストールパッケージ抜粋

```json

  "dependencies": {
    "firebase": "^5.2.0",
    "node-sass": "^4.9.0",
    "sass-loader": "^7.0.3",
    "view-router": "^0.2.3",
    "vue": "^2.5.2",
    "vue-firestore": "^0.2.9",
    "vue-router": "^3.0.1",
    "vuefire": "^2.0.0-alpha.12",
    "vuex": "^3.0.1"
  },
```

## createdAt(timestamp)が、6/1から6/30までのデータが欲しいよ！

playsのドキュメントの中には、音楽データのレファレンスが入っているので、途中でそのレファレンスから音楽データも取得しています


```javascript
<script>
    import playitem from './PlayItem';
    import db from '../../firebase/firebase';

    export default {
        components: {
            playitem
        },
        data() {
            return {
                plays: []
            };
        },
        created() {
            var startDate = new Date('June 1, 2018');
            var endDate = new Date('June 30, 2018');

            let items = [];
            db.collection('plays').orderBy('createdAt', 'asc').startAt(startDate).endAt(endDate).get().then((querySnapshot) => {
                querySnapshot.forEach(async(doc) => {
                const music = await doc.data().musicRef.get();

                let data = {
                    'id': doc.id,
                    'userId': doc.data().userId,
                    'postId': doc.data().postId,
                    'title': music.data().title,
                    'artist': music.data().artist,
                    'createdAt': doc.data().createdAt
                };

                this.plays.push(data);
                });
            });

        }
```

- テンプレート側抜粋

```html

            <playitem
            v-for="play in plays" :key="play.id" :play="play">
            </playitem>
```

- firebase.js

```javascript

import firebase from 'firebase/app';
import 'firebase/firestore';

firebase.initializeApp({
    databaseURL: 'https://xxxxxxxxxxxx.firebaseio.com',
    projectId: 'xxxxxxx'
});

const db = firebase.firestore();

const settings = { /* your settings... */
    timestampsInSnapshots: true
};
db.settings(settings);

export default db;
```
Flaskでページのリダイレクト＆Bootstrap4導入【「本棚自慢」サイト開発日誌#2】

# 環境

- 開発端末：Linux（Ubuntu 17.10）
- 言語：Python（v3.6.3）※ pip は v9.0.1
- Webフレームワーク：Flask（v1.0.2）
- CSSフレームワーク：Bootstrap（v4.0.1）

# 今日のお題

[前回](https://qiita.com/sky0621/items/1268d82b149eb0788f23)の続き。
実装中の最新ソースは、[ここ](https://github.com/sky0621/bicherregal-py)。

- ページのリダイレクトと404ページ追加
- CSSフレームワーク導入

## ■ページのリダイレクト

現状、トップページに表示するコンテンツを考えていないので、とりあえず本棚一覧ページにリダイレクトさせる。
<pre>
@app.route('/')
def index():
    return redirect(url_for('list'))
</pre>

あと、存在しないアドレスを指定された時用のページを用意。（実は前回の記事書いた時点で出来てた。）
<pre>
@app.errorhandler(404)
def page_not_found(error):
    return render_template('404.html'), 404
</pre>

![6nG6Be.png](https://qiita-image-store.s3.amazonaws.com/0/180599/d9b405e2-d832-a1d9-669f-1ae421a6e32b.png)

【参考】
　http://flask.pocoo.org/docs/1.0/quickstart/#redirects-and-errors

## ■CSSフレームワーク導入

べたにBootstrapを導入。と思ったけど、普及してるのは v3 で、今は **[v4](http://getbootstrap.com/)** が出ているようなので最新を採用。
ひとまず見た目をそれなりにするためなのでCDN使う。

本棚一覧ページに何となくのデザインを当ててみる。

![wPCjlg.png](https://qiita-image-store.s3.amazonaws.com/0/180599/940b4a60-e21f-02f4-b488-4e4ddca68656.png)

一応、レスポンシブ？。

![AahTdF.png](https://qiita-image-store.s3.amazonaws.com/0/180599/ead2889c-b222-7943-0cdf-5d84a7b09433.png)


HTMLソースは、[ここ](https://github.com/sky0621/bicherregal-py/blob/e867d749f292cc7dd4ef8cdf8915ea07f0f3c215/templates/list.html)。

【参考】
　http://getbootstrap.com/docs/4.1/layout/grid/
　http://getbootstrap.com/docs/4.1/components/carousel/
lazuriteでコンパス（方位磁石）

#概要
lazuriteでコンパス（方位磁石）やってみた。

#写真

![CIMG2671.JPG](https://qiita-image-store.s3.amazonaws.com/0/18104/f99d1bde-d158-33d3-a1e4-65e28da17e0a.jpeg)

#サンプルコード

```
#define M_PI 				3.1415926535897932384626433832795

void setup()
{
	byte rc;
	Serial.begin(115200);
	Wire.begin();
	rc = bm1422.init(0);
	hsv.init(1, 20000);
	hsv.attach(0, 5);
	hsv.write(0, 800);
	hsv.start();
	Serial.println("start");
}
void loop()
{
	int range;
	float heading;
	byte rc;
	float mag[3];
	float mx;
	float my;
	rc = bm1422.get_val(mag);
	if (rc == 0)
	{
		mx = mag[0];
		my = mag[1];
		Serial.print_long(mx, DEC);
		Serial.print(",");
		Serial.print_long(my, DEC);
		Serial.print(",");
		heading = atan2(mx, my) * 180.0 / M_PI + 45;
		Serial.println_long(heading, DEC);
		range = map(heading, 140, 220, 500, 2400);
		hsv.write(0, range);
		hsv.update();
	}
	delay(500);
}




```

以上。
ローカルからGoogle Cloud Datastoreを使う際に、複合インデックスを登録する方法

# 経緯
RaspberryPiのPHPから、Google Cloud Datastoreに繋いでクエリを発行するも、「no matching index found.」と返されて怒られる。
実行するクエリによって、複合インデックスを登録する必要があるが、調べてもGAE環境でしか見当たらず、困ったのでそのメモ。

# 環境
RaspberryPi3B
php7
gloudコマンドラインツール
サービスアカウントあり

### Datastoreのエンティティ
- door インデックス登録済み
- room インデックス登録済み
- timestamp インデックス登録済み

### 発行クエリ
```
$query = $datastore->gqlQuery('SELECT * FROM Rooms WHERE room = @room ORDER BY timestamp DESC LIMIT @limit', [
	'bindings' => [
		'room' => $room,
		'limit' => 1
	]
]);
```
### 実行結果
```
PHP Fatal error:  Uncaught Google\Cloud\Core\Exception\BadRequestException: {
  "error": {
    "code": 400,
    "message": "no matching index found. recommended index is:\n- kind: Rooms\n  properties:\n  - name: room\n  - name: timestamp\n    direction: desc\n",
    "status": "FAILED_PRECONDITION"
  }
}
```
# 対策
エラーに書いてある通り、マッチするインデックスが無いと言われるので、インデックスの設定を行う。
[インデックス設定](https://cloud.google.com/datastore/docs/tools/indexconfig)

recommended index is と書いてくれてるので、そのまま index.yaml に書く。

```index.yaml
indexes:

- kind: Rooms
  properties:
  - name: room
  - name: timestamp
    direction: desc
```
この内容を反映させる方法がこちら
[gcloud ツールを使用したアプリケーション テストとインデックス管理](https://cloud.google.com/datastore/docs/tools/#the_development_workflow_using_gcloud)

```
$ gcloud datastore create-indexes ./index.yaml
```
```
Configurations to update:

descriptor:      [./index.yaml]
type:            [datastore indexes]
target project:  [xxxxxxxxxxxxxx]


Do you want to continue (Y/n)?  y
```
これでOK。作成されるまでに時間がかかる。急いでクエリを実行すると、以下のように怒られる。

```
PHP Fatal error:  Uncaught Google\Cloud\Core\Exception\BadRequestException: {
  "error": {
    "code": 400,
    "message": "The index for this query is not ready to serve. See the Datastore Indexes page in the Admin Console.",
    "status": "FAILED_PRECONDITION"
  }
}
```
焦っちゃダメよ、管理画面を見てね。

# 結果
```
array(1) {
  [0]=>
  array(2) {
    ["room"]=>
    string(5) "room7"
    ["door"]=>
    string(5) "close"
  }
}
```
で、めでたく取得できました。おーいえ。
AWS S3 Glacierからリストアしてファイルをダウンロードする

# まとめ

Glacier状態のS3オブジェクトを取り出す際には、リストア期間を指定した上でrestore-objectを実行する必要があります。

# 手順

## リストア
recursiveオプションが無いため、list-objectsしてオブジェクトパスを取得してからrestore-objectを実行します。

```bash

for key in `aws s3api list-objects --bucket (バケット名) --prefix (ディレクトリ名) --output json | jq -r '.Contents[].Key'`; do echo $key; aws s3api restore-object --bucket (バケット名) --key $key --restore-request '{"Days": 3}';done
```

## ダウンロード

リストア済みのオブジェクトをダウンロードするときもresursiveが使えないため、list-objectsしてオブジェクトパスを取得してからダウンロードします。

```bash

for key in `aws s3api list-objects --bucket (バケット名) --prefix (ディレクトリ名) --output json | jq -r '.Contents[].Key'`; do echo $key; aws s3 cp s3://(バケット名)/$key .;done
```
初等深層学習・CNNで精度を上げる手法

#精度を向上させる
精度を向上するためには、様々な方法があります

①学習するデータ量を増やす
②正則化する
③アンサンブル学習を取り入れる。

主に私が使うのはこの3つの手法です。

今回はそれぞれ精度が向上する理由と、Kerasでの実装例を紹介していきます。

#①学習するデータ量を増やす
当たり前のことですが、多くのデータに目を通せば、もちろん精度は向上します。しかし、インターネットが発達したとはいえ、数万枚の画像データを持ってくるのは厳しいのが現状です。
そこで、データの水増しというのを行います。

MNIST画像を例にとります。
MNIST画像は28×28の画像であることはご存知の通りです。
これに、乱数を用いてのノイズを加算します。

具体的にはこうです。

```python:
#xTrainに(60000,28,28,1)のMNIST画像が格納されているとします。

xTrain2 = xTrain + np.random.rand(60000,28,28,1)
xTrain = np.concatenate([xTrain,xTrain2])
```

軽度のノイズを乗せたところで、人間が数字を見誤ることはほとんどありません。これは、人間の脳を模していると言われる人工知能でも同様です。

しかし、計算する値は若干違ってきます。例えば今まで0.123だったものが、0.126になっているかもしれません。

これは視覚的には大した差ではありませんが、人工知能はこれでも違うデータと認識します。つまり、データが増えたということです！

しかし、この方法では似たような画像が増えるということでもあり、汎化性を失う過学習に陥りかねません。あまり褒められた方法ではないのです。

#②正則化する
これは、AI研究者の中でも意見が分かれる手法ですが、ことCNNにおいては基本的に優秀なので、ここで紹介します。

```python:
from keras.layers import BatchNormalization
model.add(BatchNormalization())
```

これを各層の活性化層の前、もしくは後に挿入するだけです。どちらに挿入するかはあなた次第です。(どっちがいいか、という問題は宗教戦争を招きますので触れません。)

バッチサイズを指定して学習する際に特に効果を発揮します。
あるバッチの中で、平均0、標準偏差1になるように全体の値を調節します。
これは、偏りのないデータを提供することになるので、精度が向上します(たぶん)

出力値があまりに大きくなりすぎるのを防止し、勾配消失・爆発問題をある程度解消します。

データの質を上げる手法とも言えます。

#③擬似アンサンブル学習を取り入れる
アンサンブル学習とは、一つのモデルで答えを導くのではなく、複数のモデルで一度解答を出し、それを統合して全体の解答として出力する方針です。

古来から「三人寄れば文殊の知恵」と言われてきたことを、最先端技術に活かすのです。

ただ、複数のモデルを動かすというのは、モデルの構築、運用の面からしてコスパがいいとは言えません。

そこで、これを擬似的に実装します。

```python:
from keras.layers import Dropout
model.add(Dropout(0.25))
```

このDropout()は、入力された情報の一部を0に置き換えます。ここでは0.25を引数に取ったので、25%が無かったことにされます。

せっかく計算した結果を不意にするような人に見えますが、これはランダムに消去されます。つまり、epochが変わるごとに、消去する情報も変わるということです。ということは、1つのモデルが、epochの数だけ微妙に違うモデルとなることを意味します。

出力された値には、0.25が乗算されます。
これは、強制的に0にするノードを増やしたことで、1つ1つのノードが強力になっているだろう、という概念に基づきます

このようにして、効果的、かつ効率的にモデルの能力を上げることができます。

#最後に
ここまで紹介してきた3つの手法は、基本的な部分です。他にも、モデルに応じて様々な手法が存在します。
回転処理、マスキング、反転処理、ZCA白色化など、枚挙にいとまがありません。

自作したモデルの特性に合わせて、色々な方法を試してみてください！
もしかしたら、思いもよらない方法が、精度向上につながることもあります。
何故そうなるのかを考えてみても面白いでしょう！
CSSアニメーションをとりあえず動かすことだけを考えた記述方法

#CSSアニメーションをぱっと記述できない。
何言ってんの？と言われそうですが、できないもんはできない。
原因はわかってる。何がどうなってんのかよくわかってない。
というわけでめんどくさがりの自分用にCSSアニメーションを動かすために最低限必要な記述をメモ。
そして理解を深める作戦・・・。

【続きの記事】[CSSアニメーションをとにかくそれっぽく使えるようになる記述方法](https://qiita.com/kape/items/0c13d823ecd20badfb9d)

##1. とりあえずやってみよう（transition編）
結論から。

```CSS:CSS
transition:all 1s;
```
これを、**変化させたい要素(変化前)**に追加すれば動く。
<font color="Red">※ちゃんと変化後の状態をトリガーの要素に記述してないとだめだよ！</font>

つまり、トリガー＝ホバーだったとする。

<p data-height="265" data-theme-id="0" data-slug-hash="bjadWV" data-default-tab="css,result" data-user="kapeking" data-pen-title="CSS3 アニメーション（基本のホバー）" class="codepen">See the Pen <a href="https://codepen.io/kapeking/pen/bjadWV/">CSS3 アニメーション（基本のホバー）</a> by かぺ (<a href="https://codepen.io/kapeking">@kapeking</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

このボタンの変化させたい要素は **a** だから

<p data-height="265" data-theme-id="0" data-slug-hash="rrpRqR" data-default-tab="css,result" data-user="kapeking" data-pen-title="transitionの最低限必要な記述" class="codepen">See the Pen <a href="https://codepen.io/kapeking/pen/rrpRqR/">transitionの最低限必要な記述</a> by かぺ (<a href="https://codepen.io/kapeking">@kapeking</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

こうね。動いた！transitionパネェ。
ちなみに、変化後の要素（:hover）に transition を追加しても動きました。
基本的な記述は**変化させたい要素（変化前）**でよさそうだけど、どっちに記述するのが正しいとかあるのかしら。

そして詳しい解説は後回しで。いいの、それで。

##2. とりあえずやってみよう（animation編）
結論から（2回目）。

```CSS:CSS
@keyframes anime{
  to{
       変化させたい内容
  }
}
```
まず、こんなふうにアニメーションさせたい内容をCSSに記述。そして

```CSS:CSS
animation:anime 1s;
```
これを、**変化させたい要素(トリガーがある場合はトリガーの要素)**に追加すれば動く。

では基本のホバーで実際に動かした場合。

<p data-height="265" data-theme-id="0" data-slug-hash="XBVQwj" data-default-tab="css,result" data-user="kapeking" data-pen-title="animationの最低限必要な記述 " class="codepen">See the Pen <a href="https://codepen.io/kapeking/pen/XBVQwj/">animationの最低限必要な記述 </a> by かぺ (<a href="https://codepen.io/kapeking">@kapeking</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

なんかtransitionの時と動きが若干違うけど動いたよ！
ちなみにtransitionの時みたいに**変化させたい要素（変化前）**にanimationプロパティを追加したら、一瞬だけ勝手に動いたよ（笑）

<p data-height="265" data-theme-id="0" data-slug-hash="qypGLJ" data-default-tab="css,result" data-user="kapeking" data-pen-title="animationの最低限必要な記述 （番外編）" class="codepen">See the Pen <a href="https://codepen.io/kapeking/pen/qypGLJ/">animationの最低限必要な記述 （番外編）</a> by かぺ (<a href="https://codepen.io/kapeking">@kapeking</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

マジで一瞬だから見逃したらリロードしてね！

##3. やってみてわかったこと
とりあえずこれを覚えとけば最低限動く。

+ **transition** は<font color="red">トリガーが必須</font>。
+ **animation** は<font color="red">トリガーがなくても動く</font>。
+ **transition** は、アニメーションが終わったら<font color="red">変化後の状態で止まる</font>。
+ **animation** は、アニメーションが終わったら<font color="red">変化前の状態で止まる</font>。



詳しい記述については次回調べます！
【続きの記事】[CSSアニメーションをとにかくそれっぽく使えるようになる記述方法](https://qiita.com/kape/items/0c13d823ecd20badfb9d)
ARKitの可能性を知るためにオススメの教材3選

「**ARKitでどんなアプリを作ったらいいのか？**」という話になると、そもそもどこまでできるのか？という話になってアイデアが出にくいものです。

そのイメージを掴むために私がオススメするのは、

- 堤さんの[ARKit-Sampler](https://github.com/shu223/ARKit-Sampler)
- Udemyの[ARKit 2.0 Build Augmented Reality apps on iOS with Scenekit](https://www.udemy.com/learnarkit/?couponCode=GRAFFITY)
- 僕のUdemy講座 [【ARKit2.0対応】6つのチャレンジでARKitを徹底攻略](https://www.udemy.com/kboy-arkit/?couponCode=QIITA_KBOY)

の3つです。

それぞれからピックアップして、ARアプリを作りたいあなたにインスピレーションを与えたいと思います。

[GRAFFITYブログ](http://graffity.hatenablog.com/entry/arkit_possibility)にもより詳細を書いたので興味のある方はご参照下さい。

## 物理的インタラクション
![physics.gif](https://qiita-image-store.s3.amazonaws.com/0/111366/550720f4-df65-e084-9da6-d71952dfa67d.gif)
[ARKit 2.0 Build Augmented Reality apps on iOS with Scenekit](https://www.udemy.com/learnarkit/?couponCode=GRAFFITY)

そもそもSceneKitでこのような物理的インタラクションができます。これを実際の空間で行うとこのように、公園でファイヤボールを投げてブロックを倒したりするゲームが作れます。

## 空間に線を書く

![image](https://github.com/shu223/ARKit-Sampler/raw/master/README_resources/ardrawing.png)
https://github.com/shu223/ARKit-Sampler

弊社[GRAFFITY](https://www.graffity.jp/)でも実装されている線を書く機能。毎フレームごとに線のnodeのgeometryを更新ことで、長い線を空間に引くことができます。

## オクリュージョン(3D物体が平面に隠れる)
![oclusion.gif](https://qiita-image-store.s3.amazonaws.com/0/111366/82c3d11a-b3a3-e5f6-8269-b2432c593a7a.gif)
[ARKit 2.0 Build Augmented Reality apps on iOS with Scenekit](https://www.udemy.com/learnarkit/?couponCode=GRAFFITY)

ARは実際に空間に物を置いているわけではなく、3Dに見えるように描画しているだけなので、そのままだと図にあるような机も通り抜けて見えてしまいます。しかし、平面認識と組み合わせることでARKitでも**オクリュージョン**と呼ばれる現実の物の後ろに3D物体が隠れるという表現が可能です。

## ドローンが近づいたら音声が聞こえる
![sound.gif](https://qiita-image-store.s3.amazonaws.com/0/111366/99aebf31-7e53-5dfc-debc-5413a7432b59.gif)
[ARKit 2.0 Build Augmented Reality apps on iOS with Scenekit](https://www.udemy.com/learnarkit/?couponCode=GRAFFITY)

このdroneはxcode上でSceneKitのGUIで作ることができます。このデモではそれで作ったdroneをある点を中心に回るようにアニメーションさせてさらに、音声ファイルを使ってdroneから音が鳴っているように表現しています。

## 画像の認識
![image.gif](https://qiita-image-store.s3.amazonaws.com/0/111366/3a7cb8cb-4ab2-e8de-eef8-52854aa6cd8c.gif)
[ARKit 2.0 Build Augmented Reality apps on iOS with Scenekit](https://www.udemy.com/learnarkit/?couponCode=GRAFFITY)

ARKit1.5からできますが、2.0でかなり精度が上がっています。図のように動かしても画像に地球がくっついてきます。

## 平面認識
![image](https://github.com/shu223/ARKit-Sampler/raw/master/README_resources/irregular.gif)
https://github.com/shu223/ARKit-Sampler]

ARKit1.0平面認識ができますが、ARKit1.5では壁も認識できるし、gifのように短形だけでなくて円のような形も判別することができます。テーブルの上に水を張り巡らせるといったような演出ができるのです。

## カスタム3D物体
![custom.gif](https://qiita-image-store.s3.amazonaws.com/0/111366/7dd19754-d7c9-2951-c327-f8fb0c33040c.gif)
[ARKit 2.0 Build Augmented Reality apps on iOS with Scenekit](https://www.udemy.com/learnarkit/?couponCode=GRAFFITY)

このような物体を、線と線を繋いだpathで二次元で作った後に三次元の物体にすることができます。これもswiftのコードだけで作れます。

##まとめ

堤さんの[ARKit-Sampler](https://github.com/shu223/ARKit-Sampler)は自由に参照できますし、[ARKit 2.0 Build Augmented Reality apps on iOS with Scenekit](https://www.udemy.com/learnarkit/?couponCode=GRAFFITY)は有料ですが動画をみながらわかりやすくARKitを習得できるのでオススメです。

そして最後に、僕の[【ARKit2.0対応】6つのチャレンジでARKitを徹底攻略](https://www.udemy.com/kboy-arkit/?couponCode=QIITA_KBOY)では、ARKitに入門できるように短く動画講座を作っているのでご確認ください！

(Udemyの動画は作者から掲載の許可をもらっています)
【Railsチュートリアル】 いいねが二回リクエスト送信される(rails-ujs)

# はじめに
いいねボタンを押したら本来一回しかリクエストが飛ばないはずなのに、2回リクエストしてしまう現象が発生しました。その時の原因対応メモです。

## 現象
いいねボタンを押した時の様子。Googleクロームのデベロッパーツールで見るとこんな感じ。生成も削除も二回。

![ajax-duble.PNG](https://qiita-image-store.s3.amazonaws.com/0/273424/8156c9ce-625f-d5ca-9648-2ad67e3d249d.png)

通信のコード元は`jquery`と`rails-uis`、この箇所で通信されている様子。はて？

## 原因
色々調べると今までRailsからクライアントサイドを操作するためにjquery-ujsが使用されていたみたいですが、Rails5.1からはJquery依存がなくなった`rails-ujs`使うようになった様子。`jquery_ujs`から`rails-ujs`に変更されたにもかかわらず、`jquery_ujs`と`rails-ujs`を混在させていたのが原因みたいでした。どうやら自分がいつの間にかに混在させてしてしまっていたみたいです。。
jquery-ujsとはRuby on RailsについてくるJavaScriptのライブラリのようです。

* jquery → jquery-ujs
* rails-ujs

この２つの流れが存在し、2回リクエストを送っていたんだと思います。

```app/javascript/application.js
//= require jquery
//= require jquery_ujs
//= require rails-ujs
//= require turbolinks
//= require_tree .
```

Rails5.1で`rails new` された時は恐らく下。`# rails -v
Rails 5.1.6`

```
//= require rails-ujs
//= require jquery
//= require bootstrap
//= require turbolinks
//= require_tree .
```

## 対応
Rails5.1からは`jquery_ujs`と`rails-ujs`に移行するということなので`jquery_ujs`を削除しました。結果、問題なく動作するようになりました。めでたしめでたし。


```diff
・
//= require jquery
- //= require jquery_ujs
//= require rails-ujs
//= require turbolinks
//= require_tree .
```
vue-routerで遷移した後、ブラウザの戻るボタンで、前のページのスクロールした位置に戻るようにする

## 前のページのスクロールした位置に戻れない時の条件
* 前のページに戻った際にheightに変動のあるDOM構築を行っている場合
* 現在のページのスクロール可能領域が前のページのスクロール可能領域よりも少なく、前のページのスクロール位置が現在のページのスクロール可能領域の最大よりも大きかった場合
※本当にコレが原因かは不明。

## 対処法
DOM構築が終わった後に`scrollTo()`で前のページのスクロール位置まで移動させる。

## 実装方法
### 前のスクロール位置の情報をsessionStorageに持たせる
Routerに以下を追加

```js
    scrollBehavior(to, from, savedPosition) {
        if (savedPosition) {
            sessionStorage.setItem('positionY', savedPosition.y);
            return savedPosition
        } else {
            sessionStorage.setItem('positionY', 0);
            return { x: 0, y: 0 }
        }
    }
```
scrollBehaviorを使うとページを戻ったタイミングで、前のスクロール位置の情報取れるので前のスクロール位置の情報をsessionStorageに持たせる。
今回は横スクロールはなかったので縦軸の値だけ。
[scrollBehaviorについて](#scrollbehaviorについて)

### 前のページに戻って、そのページのDOM構築が終わったタイミングで、sessionStorageに保存した、スクロール位置の情報をscrollTo()の引数に渡して、スクロールする処理を入れる。
前のページのコンポーネントに以下を追加

```js

        watch: {
            hogeList: function() {
                this.$nextTick(() => {
                    var positionY = sessionStorage.getItem('positionY')
                    scrollTo(0, positionY);
                    setTimeout(function(){
                        scrollTo(0, positionY);
                    }, 500);
                })
            }
        },
```
今回はbeforeCreateでdispatchしていて、computedでstateの値をreturnしています。(詳しくは[vuexのドキュメント](https://vuex.vuejs.org/ja/)を読んで)
なので、上の例ではhogeListの値が変わったタイミングで実行されるwatch内で処理しています。DOMが更新されたタイミングで発火するようにnextTickを使っています。
[nextTickについて](#nexttickについて)
ただDOM構築が終わっていても画像のロードが終わっていない場合があり、その場合、nextTickの後にもheightが変わる可能性があり、nextTickを使ってscrollTo()をしてもスクロール位置がずれてしまう場合があります。
そこで画像のwidthを100%などにしなければならなくheightを固定出来ない場合などは、setTimeoutを使いscrollTo()の実行タイミングを画像のロードが終るタイミングで実行するようにします。

## nextTickについて
> nextTickは実行時点から次のキューイングが実行されDOMが更新されたタイミングでコールバック関数が呼び出されます。

([Vue.jsでビューの変更がされないときに疑うこと+主な解決策方法](https://qiita.com/bobu_web/items/ec5a98d03758d12ad721) より引用)

## scrollBehaviorについて
* ページ遷移時に発火します。
* 前のページに戻った時にsavedPositionに前のページのスクロールした位置がオブジェクトで返ってくる。例 { x: 1234, y: 5678 }
* returnしたら、その箇所までスクロールするのかと思ったのですが、そうではないようです。
returnした値をどこで取得できるかは分かりませんでした。

https://router.vuejs.org/ja/guide/advanced/scroll-behavior.html




## その他vue-routerを使う上での注意点
> 注意: ルートの行き先が現在のルートと同じで、かつパラメータのみが変更されている場合(例: /users/1 -> /users/2 のようにあるプロファイルから他へ)、変更(例: ユーザー情報の取得など)に反応するためにbeforeRouteUpdate を使用しなければなりません。

（https://router.vuejs.org/ja/guide/essentials/navigation.html より引用）


## まとめ
sessionStorageで値を持ってscrollTo()を使って無理やりスクロールの位置を合わせているので、あまり良い実装とは言えないです。
scrollBehaviorを使ったりしてもっといい感じに実装できるよって方いれば教えてください。
[質問]SSL VPN環境でのLinuxサーバー構築に関するご質問

始めまして。
早速ですが、今回海外の会社と提携してWEBサーバーの構築とWEBサイトを開設することになりまして、下記の情報を頂きました。

・FortiGate SSL-VPN PortalのURL（IPアドレス）とログイン情報
・Server lan IPアドレス
・Server pub IPアドレス
・サーバーのrootユーザーアカウント情報
サーバーのOSは、CentOS Linux release 7.2.1511 (Core)です。


諸事情により相手方へ質問が出来ない状況で当方へ振られまして、この情報が何なのかもわからない状態でした。
現状ではブラウザでServer lan IPにも直接アクセスできません。
そこでVPNについて自分なりに調べた所、インターネットを介して遠方と社内LANのような環境を構築することが出来るシステムだと解釈しました。
色々と試しているうちに、SSL-VPN PortalよりFortiClientをダウンロードしてVPN接続をし、Tera Termを使ってServer lan IPよりサーバー機にSSH接続することが出来ました。この際はポート22で接続して特にTera Termの設定は変更していません。

その後、初心者用のサーバー設定方法の書いてあるサイトを確認して、RPMパッケージのアップデートを行い、SELinuxを無効化し、サーバー起動時にSELinuxが起動しなくなる設定に変更してサーバーの再起動を行いました。
すると再起動前まで出来ていたTera TermでのSSH接続が出来なくなりました。他にサーバーへ接続して設定を確認する方法がわからず困っております。
コミュニケーションとリサーチ不足で素人がいじくってしまった事はとても反省しています。


そこでご質問ありましてご教授を頂きたいのです。
・VPNに対する当方の認識は正しいのかいう点。
・FortiClientの使い方は正しいのかという点。
・SSL-VPN Portalにログインするとブラウザ内でVAN環境にアクセスしているような状態になるという認識で正しいのかという点。
・SSH接続が出来なくなった考えられる原因
・再度SSH接続が出来るようにするための設定方法や解決策。


ちなみにWEBサーバーと、後々はこちらのサーバーにSSLと独自ドメインとメールサーバーとMySQLの設定も行う必要があるそうです。
非常に心配なのですが、こちらに関してもアドバイスをいただけないでしょうか。
Linuxに関しては数年前にサーバー環境構築済みのRed Hat Linuxを触ったことがありますが、基本操作がわかる程度で素人のレベルと言って差し支えなく、とても危険な行為だと認識はしています…。
ですので代行のほうが良いという意見がありましたらそのようなアドバイスでも構いません。

抽象的な物言いもあり申し訳ありません。
Qiitaも登録したばかりでご無礼な点もあるかと思いますが、よろしくお願いいたします。
Androidの自動UIテストでPermissionダイアログをスキップする（自動許可）

# 概要
Androidの自動UIテストで[Espresso](https://developer.android.com/training/testing/espresso/)を導入するケースが増えてきていますが、Espressoは基本的に自アプリのUIしか動かせないので、端末の設定画面が出ると固まってしまいます。
今回はAndroid Marshmallow以上で出る[実行時のパーミッションリクエスト](https://developer.android.com/training/permissions/requesting)ダイアログをスキップする方法をご紹介します。

# 解決方法（例）
## build.gradle
```
dependencies {
    ・・・
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test:rules:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
　　　　　　　　・・・
}
```
## テストコード
```
@Rule
public GrantPermissionRule mGrantPermissionRule =
        GrantPermissionRule.grant(
                "android.permission.RECEIVE_SMS",
                "android.permission.READ_CONTACTS",
                "android.permission.RECEIVE_MMS",
                "android.permission.READ_PHONE_STATE");
```

# 説明
Googleが導入した[Android Testing Support Library 1.0](https://android-developers.googleblog.com/2017/07/android-testing-support-library-10-is.html)の **Grant Permission Rule** の項によると、[GrantPermissionRule](https://developer.android.com/reference/android/support/test/rule/GrantPermissionRule)をメンバに定義しておけば、ダイアログポップアップを完全にスキップして自動的にパーミッション許可を与えられるようです。

# 補足
[UI Automator](https://developer.android.com/training/testing/ui-automator)の[UiDevice](https://developer.android.com/reference/android/support/test/uiautomator/UiDevice)を使い、「許可」ボタンをテキスト検索して押すという手もあります。
他の設定画面も含めて大体それで解決します。が、以下の制限がつきまといます。

* 複数の言語への対応が面倒（英語だと「ALLOW」だったり…）
* コードが冗長・複雑化する

Android Studioの操作録画機能（[Record Espresso Test](https://developer.android.com/studio/test/espresso-test-recorder)）では、Android Studio3.1.3では上記のルールは自動記録されませんが、3.2？3.3？以降でポップアップ許可操作を録画するとGrantPermissionRuleの自動挿入されるようです（正確な対応バージョンは調べきれてません）。
なので、GoogleはTesting Support Libraryの使用を推奨しているようです。
document.getElementsByClassNameでうまく取得できない…

**初投稿！！**

document.getElementsByClassNameで特定のclassを取得して、forEachでループさせる際に、2つあるはずの要素が1つしかカウントされない…

```Javascript:script.js
MODAL.methods = {
    show: function(elm){
        var $self = elm;
        var $next = $self.nextElementSibling;
        if($next.classList.contains(MODAL.tar) && !$self.classList.contains(MODAL.active)) {
            $self.classList.add(MODAL.active);
            $next.classList.add(MODAL.active);

            $next.style.display = 'block';

            console.log(document.getElementsByClassName(MODAL.active));

            MODAL.methods.overlay();
        }
    },
    close: function(){
        var $close = document.getElementById(MODAL.close);
        console.log(document.getElementsByClassName(MODAL.active));
        Array.prototype.forEach.call(document.getElementsByClassName(MODAL.active), function(elm){
            elm.classList.remove(MODAL.active);
            if(elm.classList.contains(MODAL.tar)){
                elm.style.display = 'none';
            }
        });
        $close.remove();
    },
    overlay: function(){
        console.log(document.getElementsByClassName(MODAL.active));
        document.body.insertAdjacentHTML('beforeend', '<div id="' + MODAL.close + '" class="modal-overlay" onClick="MODAL.methods.close();"><span class="modal-overlay_child">close</span></div>');
    }
};
```

MODAL.methods.show()だとlength: 2
MODAL.methods.overlay()だとlength: 2
なのに…
MODAL.methods.close()だとlength: 1

querySelectorAllで対応すると解決するのだが、getElementsByClassNameだとうまくいかない理由がわからないので気持ち悪い（　＾ω＾）・・・

理由がわかる方いらっしゃいましたらご教授ください<(_ _)>
Zabbix3.4 PostgreSQL版をCentOS7にインストールする

ZabbixをCentOS7環境にインストールする手順を纏めます。実行環境は次の通りです。
続いてElasticsearch

・Zabbix 3.4
・CentOS 7.5 
・PHP 5.4.16 
・PostgreSQL 9.2.23 

CentOS7で、yum -y updateを実行

```
# yum -y update
# reboot
```

Firewallの設定　（10051：Zabbixエージェントからサーバ
10050：サーバからエージェント）

```
# firewall-cmd --add-port=10051/tcp --zone=public --permanent
# firewall-cmd --add-service=http --zone=public --permanent
# firewall-cmd --add-port=10050/tcp --zone=public --permanent
# systemctl restart firewalld
```

SELinuxの設定

```
# vi /etc/selinux/config
SELINUX=permissive
```

#<b>Zabbixのインストール</b>
Zabbix3.4 の yum リポジトリの登録

```
# rpm -ivh http://repo.zabbix.com/zabbix/3.4/rhel/7/x86_64/zabbix-release-3.4-1.el7.centos.noarch.rpm
```

Zabbixのインストール（Zabbixサーバ、Webインターフェース、Zabbixエージェント：ローカル監視用、PostgreSQL利用）

```
# yum -y install zabbix-agent zabbix-server-pgsql zabbix-web-pgsql zabbix-web-japanese
```

PostgreSQLのインストール

```
# yum -y install postgresql-server
```

DBの初期化とサービス起動

```
# postgresql-setup initdb
# systemctl start postgresql
# systemctl enable postgresql
```
OS上のpostgresユーザからPostgreSQL上のpostgresユーザーのパスワードを変更する

```
# su - postgres
$ psql -c "alter user postgres with password 'password'"
```

postgresユーザーのまま、Zabbix用データベース接続用アカウントzabbixを作成し、パスワードを設定する

```
$ createuser zabbix -P -S -R -D
新しいロールのためのパスワード:
もう一度入力してください：
$
```

zabbixユーザにて、zabbix DBを作成

```
$ createdb -O zabbix -E UTF8 zabbix

```

rootユーザーに戻り、/var/lib/pgsql/data/pg_hba.conf内の認証設定（local/IPv4/IPv6）を、trustに変更

![キャプチ1.JPG](https://qiita-image-store.s3.amazonaws.com/0/251519/86bc2e0d-87e0-944e-302d-0109370c37be.jpeg)

PostgreSQLを再起動

```
# systemctl restart postgresql
```

#<b>初期データベースの作成</b>
初期データベース作成用のスクリプトを解凍して利用する

```
# zcat /usr/share/doc/zabbix-server-pgsql-3.4.12/create.sql.gz | psql -U zabbix zabbix -W
ユーザ zabbix のパスワード:
NOTICE:  CREATE TABLE / PRIMARY KEYはテーブル"maintenances"に暗黙的なインデック ス"maintenances_pkey"を作成します
CREATE TABLE
.....
INSERT 0 1
INSERT 0 1
COMMIT
#
```

#<b>Zabbix設定ファイルの編集</b>
Zabbix DB用アカウントzabbixのパスワードをDBPasswordに設定し、
DBPortにPostgreSQLサーバーのデフォルトのポート番号5432を設定する

```
# vi /etc/zabbix/zabbix_server.conf
DBPassword=password
DBPort=5432
```

#<b>Zabbix Webインターフェース用の設定</b>

TimezoneをAsia/Tokyoに設定

```
# vi /etc/httpd/conf.d/zabbix.conf
php_value date.timezone Asia/Tokyo

```

Zabbixサービスの起動

```
# systemctl start zabbix-server
# systemctl start zabbix-agent
# systemctl start httpd
# systemctl enable zabbix-server
# systemctl enable zabbix-agent
# systemctl enable httpd
```

#<b>Webインターフェースへのアクセス</b>

http://ZabbixサーバーのIPアドレス/zabbix/

初期設定(DB接続時のパスワード等)が終わるとログイン画面になり、
アカウント「Admin」、パスワード「zabbix」でログインする

Web UI を日本語化する
Administration > Users > Admin > LanguageでJapanese(ja_JP)を選択
![Zabbix.JPG](https://qiita-image-store.s3.amazonaws.com/0/251519/2c9528c0-a20f-b7be-5850-2e6b363e7106.jpeg)


![zabbix2.JPG](https://qiita-image-store.s3.amazonaws.com/0/251519/00d8e804-316d-e7af-20c4-7c52038256f7.jpeg)
Python + Flask + Blueprint で複数のアプリケーションを登録する際に気をつけること

# 概要
* PythonのFlaskを使ってアプリケーションを公開したい
* FlaskのBlueprintを使うとアプリケーションのURLを分けて管理できる
* URLに分けて管理する際には（Flaskの仕様に則った）ディレクトリ構成に気をつける

# Flaskを使う場合の自分のディレクトリ構成
```text:ディレクトリ構成
run.py
app1/
    __init__.py
    views.py
    static/
        stylesheet.css
    templates/
        app1/
            index.html
app2/
    __init__.py
    views.py
    static/
        stylesheet.css
    templates/
        app2/
            index.html
```
* staticフォルダ，templatesフォルダはappごとにディレクトリに格納できる
* templatesをapp以下に置く場合は，そのディレクトリ以下にapp名のディレクトリを挟む
* 今回の例では`app1/templates/app1/index.html`のように配置

### メインファイル
```python:run.py
from flask import Flask
app = Flask(__name__)

from app1.views import app1
app.register_blueprint(app1, url_prefix='/app1')

from app2.views import app2
app.register_blueprint(app2, url_prefix='/app2')

if __name__ == "__main__":
    app.run(host='0.0.0.0')
```
* 各ディレクトリからappを取ってきて登録する
* url_prefixを指定することでアドレス指定

### viewファイル
```python:app1/views.py
from flask import Blueprint, render_template
app1 = Blueprint('app1', __name__, template_folder='templates', static_folder='./static')

@app1.route('/')
def index():
    return render_template('app1/index.html')
```
```python:app2/views.py
from flask import Blueprint, render_template
app2 = Blueprint('app2', __name__, template_folder='templates', static_folder='./static')

@app2.route('/')
def index():
    return render_template('app2/index.html')
```
* Blueprintで構成する
* templates_folderはスラッシュなしで記述
* 例`template_folder='templates'`
* static_folderは相対パスで記述した（良い方法がわかってないです）
* 例`template_folder='./static'`
* テンプレートからレンダーする場合はapp名を挟む
* 例`return render_template('app1/index.html')`

# 感想
ややこしい．
このへんの話はstack overflowとかでもかなり議論されている．が実装上の都合でこういったことになっているようだ．
FlaskとBlueprintを使えば1つのサーバで複数のアプリケーションを登録できるので便利．Blueprintでこのようなファイル構成にすれば各アプリケーションごとを分離して管理できるところがうれしい．


# 参考文献
[いまさらながら Flask についてまとめる 〜Blueprint〜](http://www.subarunari.com/entry/2017/10/11/003225)
[Flask Blueprint における template_folderパス解決の罠](http://ymizushi.hateblo.jp/entry/2016/05/20/040827)
node.jsでwebサーバーを立ち上げるメモ

node.jsでwebサーバーを立ち上げるメモ。

```
npm install -g http-server
```

```
http-server
```

これだけ！

gulpfile.jsも作らないから、
gulp-webserverより、どちゃくそ楽チンだった。
[gulp-webserverでローカルにサーバーを立ち上げる手順まとめ](https://qiita.com/kfunnytokyo/items/d1de44674c97c92832bf) 

おわり
備忘録 CentOS7  crontabでRedmineとGitLabを毎日バックアップ

centOS上で動いている RedmineとGitLabを自動でバックアップしたくて色々調べた結果

crontabとやらでゴニョゴニョするとできる

現状確認

```
crontab -l
```
何も設定してないと

```
no crontab for root
```

登録を行う

```
crontab -e
```

vimが開くので

例えば

```
0 0 * * * /opt/gitlab/bin/gitlab-rake gitlab:backup:create
```

分 時 日 月 曜日 コマンド

で毎日　0時0分にGitLabのバックアップができます。

テキストファイルで

```
cp -r /var/opt/gitlab/backups /backups(バックアップ先フォルダ)
```

xxx.sh保存

できとうな場所に置いて

```
crontab -e
0 0 * * * xxx.sh
```

で登録すれば毎日バックアップできる！

失敗してたら権限を

```
chmod u+x　xxx.sh 
```
AmazonLinux以外のAMIをAWS Batchで使う

#　背景

[OpenShot Cloud API](https://www.openshot.org/ja/cloud-api/)を使いたかったのですが、C++の組み込みライブラリを商用ライセンスで購入するか、MarketPlaceのEC2インスタンスで稼働させるかの２択でした。

しかしサーバレスに慣れてEC2の運用がだるかったことと、スパイクするタイプのサービスで利用するという背景から、AWS Batchでオンデマンドで動かせれば最高じゃ？という発想でトライしました。

#　手順

## OpenShot設定

MarketPlaceで購入したAMIを立ち上げ、まずは迷うことなく、[チュートリアル](http://cloud.openshot.org/doc/getting_started.html)に従って設定します。
S3設定を有効にし、Server&Workerの構成で進みます。

## ecs-agent導入

ここで利用しているAMIはUbuntuのため、[Amazon Linux ではない EC2 インスタンスに Amazon ECS コンテナエージェントをインストールする](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-agent-install.html)に従ってecs-agentを頑張ってインストールする必要があります。

ステップ7までは何も迷わず言われた通りに作業します。
ただ、このマニュアルはECSのマニュアルであってAWS Batchのマニュアルでは無いため、ステップ8以降にそのまま進んでも正常に動作しません。
残るステップ10-aでecs-agentの取得までを行なった後は、以下の作業を行う必要があります。

ポイントは`/etc/ecs/ecs.config`のECS_CLUSTERです。

### ECS_CLUSTERの罠
このオプションは何も指定しないとdefaultというECSのクラスターが指定され、ECS側にそのクラスターが作成されてしまいます。
そのためAWS Batchで利用するECSクラスター名を設定する必要があります。

しかしAWS Batchでマネージドのコンピューティング環境を利用した場合、AMIを指定した後にコンピューティング環境に対応したクラスターが作成されるため、AMIの中にクラスター名を指定することができません。

### 解決策

[起動時に ecs.config ファイルを Amazon S3 からロードするには](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-agent-config.html#ecs-config-s3)

上記に従い、ecs.configをS3上に置いておき、コンピューティング環境作成後にS3後のecs.config#ECS_CLUSTERを設定することで正常に動作させることができます。

[こちら](https://qiita.com/msrks/items/5201ae15d0e1f8de5946#ubuntu-1604)を参考にして、起動スクリプトにconfigのダウンロードとecs-agentの`docker run`を記載します。

```sample
sudo aws s3 cp s3://your-bucket/ecs.config /etc/ecs/ecs.config

sudo docker run --name ecs-agent \
--detach=true \
--restart=always \
--volume=/var/run:/var/run \
--volume=/var/log/ecs/:/log \
--volume=/var/lib/ecs/data:/data \
--volume=/etc/ecs:/etc/ecs \
--net=host \
--env-file=/etc/ecs/ecs.config \
amazon/amazon-ecs-agent:latest
```

ecs.configにパブリックアクセス権を渡すのも忘れずに！

# 終わりに
おっ、意外と簡単じゃん、と思ってからが長く、なんだかんだ丸1日費やしました。
AWS BatchとECSの両方の知識が要るのでハードル高かったです。
Batchのアンマネージド環境まで手を出す気にはなれませんでした、、、

他にお困りの方の役に立てば！
Gitで特定のコミットを含むマージコミットを検索する

備忘録です、先人達の知恵に感謝!!
[git - Find merge commit which include a specific commit - Stack Overflow](https://stackoverflow.com/questions/8475448/find-merge-commit-which-include-a-specific-commit)

### gitconfigにaliasを登録
gitconfigは```C:/Users/{username}/.gitconfig```に。

```ini
[alias]
    find-merge = "!sh -c 'commit=$0 && branch=${1:-HEAD} && (git rev-list $commit..$branch --ancestry-path | cat -n; git rev-list $commit..$branch --first-parent | cat -n) | sort -k2 -s | uniq -f1 -d | sort -n | tail -1 | cut -f2'"
    show-merge = "!sh -c 'merge=$(git find-merge $0 $1) && [ -n \"$merge\" ] && git show $merge'"
```

### 使い方
```sh
# current branch
git find-merge <SHA-1>
# specify master
git find-merge <SHA-1> master
```

### 表示が文字化けする場合
環境変数に言語設定を追加する。  

```
変数名:LANG
変数値:en_US.UTF-8
```
GooglePlayConsoleのリリース前テストでNoSuchMethodErrorの対処

#概要
GooglePlayConsoleのリリース前テストで大半の端末でNoSuchMethodErrorが発生するが、実機では一切確認ができないため相当困った。
GsonBuilder.createとか　Retrofit2のGsonConverterFactory.createで発生しているようだったのでgsonのバージョン依存かなと思って色々調べたりしたけど結局解決できなかったところ、問い合わせをしたLogBaseの方に原因を教えて頂きました。他にもつまづく人がいるかもしれないので記事に残しておきます。

```
FATAL EXCEPTION: Thread-9
java.lang.NoSuchMethodError: No direct method <init>(Lcom/google/gson/Gson;)V in class Lcom/google/gson/Gson$1; or its super classes (declaration of 'com.google.gson.Gson$1' appears in /data/app/com.google.android.apps.mtaas.crawler-1T77G3Bwbj_NvCEDDbl0Vg==/base.apk)
	at com.google.gson.Gson.doubleAdapter(Unknown Source:7)
	at com.google.gson.Gson.<init>(Unknown Source:103)
	at com.google.gson.GsonBuilder.create(Unknown Source:75)
	at net.p_lucky.logpop.MessageRuleDiskDataStore.<init>(Unknown Source:25)
	at net.p_lucky.logpop.Injection.b(Unknown Source:2)
	at net.p_lucky.logpop.MessageRuleUpdateService.handleResult(Unknown Source:4)
	at net.p_lucky.logpop.MessageRuleUpdateService.a(Unknown Source:0)
	at net.p_lucky.logpop.MessageRuleUpdateService$1.run(Unknown Source:23)
	at java.lang.Thread.run(Thread.java:764)
```


#原因
GooglePlayConsoleの最新版のリリース前テストの不具合


#対処法
過去のリリース前テストを実行する
[リリース前レポート]　→　[設定]　→ [リリース前レポートのバージョン]

（バンドル名）の再署名が行われるリリース前レポートの生成を無効にするの右にあるスイッチをON


参照
[NoSuchMethodError Lcom/google/gson/Gson; upon retrofit response](https://stackoverflow.com/questions/51557749/nosuchmethoderror-lcom-google-gson-gson-upon-retrofit-response/51566968)