OmniAICreator/Qiita-1.07M huggingface dataset:
Spring BOOT

OS: Windows7/10(64bit)
開発言語: Java 8
フレームワーク： Spring Boot 1.1.8/2.0.5
開発環境(IDE)： STS(Spring Tool Suite) 4.8

#Spring Tool Suiteのダウンロード
以下のサイトからダウンロードしてください。
https://spring.io/tools
![4.png](https://qiita-image-store.s3.amazonaws.com/0/353060/6b310eb9-02d1-2dd2-8d48-f4448b3c8eea.png)
解凍したフォルダの中にあるsts-4.1.1.RELEASEフォルダを開き、
SpringToolSuite4.exeを実行して起動します。

#新規プロジェクトの作成
[File] > [New] > [Spring Starter Project]で新規プロジェクトを作成します。
![03.png](https://qiita-image-store.s3.amazonaws.com/0/353060/5dd6f09a-76bc-bfdd-a9c5-21e52f86654b.png)
Nameに「SpringDemo」と入力し、[Next]をクリックします。
![04.png](https://qiita-image-store.s3.amazonaws.com/0/353060/93cb4cff-eceb-ed6a-08bc-bb6f3889a06f.png)
Availableの入力欄に文字を入力してCoreを検索します。
以下の3つのCoreを検索してチェックを入れてください。
- Web
- Thymeleaf
- DevTools
Selectedに追加されているのを確認したら、[Finish]をクリックします。
![05.png](https://qiita-image-store.s3.amazonaws.com/0/353060/5ca826e1-8fe4-acb3-dada-d256a62569ca.png)
#新規Javaクラスの作成
Package Explorerから、
SpringDemo [boot][devtools] > src/main/java > com.example.demoを右クリックします。
[New] > [Class]で新規Javaクラスを作成します。
![06.png](https://qiita-image-store.s3.amazonaws.com/0/353060/1c434d2c-ea6b-91d1-5d60-920cc847759b.png)
Nameに「HelloController」と入力して、[Finish]をクリックします。
![08.png](https://qiita-image-store.s3.amazonaws.com/0/353060/50e26e8b-b62b-5577-d6fa-efea12d71b91.png)
![12.png](https://qiita-image-store.s3.amazonaws.com/0/353060/3b749f45-30bf-bb32-fced-3cb6e2b2cdc1.png)

HelloController.javaを以下のように編集してください。

```Java:HelloController.java
package com.example.demo;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
	@RequestMapping("/hello")
	public String hello() {
		return "Hello World !!";
	}
}
```
###実行する
Package Explorerから、
SpringDemo [boot][devtools]を右クリックして、
[Run As] > [Spring Boot App]をクリックします。
Console画面に「Started SpringDemoApplication」と表示されれば成功です。
![13.png](https://qiita-image-store.s3.amazonaws.com/0/353060/67d38297-066b-6157-0d20-eb9f182f5cbd.png)
![14.png](https://qiita-image-store.s3.amazonaws.com/0/353060/e981f5c4-b7e0-54a2-cec9-a47b1d29bae6.png)
ウェブブラウザから以下のURLにアクセスします。
http://localhost:8080/hello
![15.png](https://qiita-image-store.s3.amazonaws.com/0/353060/3761a048-6b19-c817-b5ae-c40f5409a50e.png)
#JetBrains アカウントはIDE毎に設定できる

スプラッシュ画面の"Manage License..."を開き、
<img width="718" alt="Screen Shot 2019-02-18 at 16.36.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/9676/547625cf-090b-4a10-7a6c-baae80a743a6.png">
異なるアカウントとパスワードを入れて"Activate"ボタンを押す。
(スクショは押した後)
<img width="583" alt="Screen Shot 2019-02-18 at 16.23.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/9676/a8cb8509-453f-90c2-3bc4-4e510df553fa.png">
この状態で別のIDEを起動しても[以前設定した](https://qiita.com/mazgi/items/508423929807f736eea7)アカウントとライセンスが適用されたまま。
<img width="583" alt="Screen Shot 2019-02-18 at 16.24.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/9676/f6c45183-0584-0dd2-c6d4-a89e00006d52.png">
ちょっと不安だったけど併用問題なしで安心。
Rails vs PostgreSQL カラムをstringからintegerに変更できない

#バージョン情報
- Ruby: 2.5.0
- Rails: 5.1.6
- Postgres: 11.1
- macOS: 10.14.1

#事象
usersテーブルのgenderカラムをstringからintegerに変えるため、以下のコマンドでマイグレーションファイルを作成し、

```
bin/rails g migration change_gender_datatype_to_integer_in_users
```

作成されたマイグレーションファイルに以下のように記載した後、

```2019mmddhhmmss_change_gender_datatype_to_integer_in_users.rb
class ChangeGendersDatatypeInUsers < ActiveRecord::Migration[5.1]
  def change
    change_column :users, :gender, :integer
  end
end
```

マイグレーションを実行すると、

```
bin/rails db:migrate
```

以下のエラーが表示されました。

```
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

PG::DatatypeMismatch: ERROR:  default for column "gender" cannot be cast automatically to type integer
```

ググってみると、同様のエラーに遭遇している先人たちがおりましたので参考にしましたが、いずれの方法でも回避することはできず。。。

<https://qiita.com/gam0022/items/a73910de5b8eb44e5b13>
<https://stackoverflow.com/questions/12603498/rails-migration-error-w-postgres-when-pushing-to-heroku>
<https://dzone.com/articles/rails-5-change-database-column>

#解決方法
一度該当カラムをremoveして、再度追加することで対応しました。

一度ドロップして、

```
remove_column :users, :gender
```

ドロップできたら新しいマイグレーションファイルを作成して、add_columnしてあげます。

```
add_column :users, :gender, :integer, after: :phone, default: 0
```

すると追加できました！が、なぜかafterが機能しておらず、末尾に追加されてしまいました。

```schema.rb

    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer "gender", default: 0
```

解決したら更新します。
ConoHa VPS で Debian 9 をセットアップした　～その3～

[ConoHa VPS で Debian 9 をセットアップした　～その2～](https://qiita.com/ludwigem/items/2011407c86f1be4f6879)からの続きです。
ここでは下記のようなセキュリティの設定を行います。

- ファイアーウォール（ufw）のインストールと設定
- SSHポートの変更

# ファイアーウォール（ufw）のインストールと設定

### その前に(1)
ConoHaのダッシュボードから「接続許可ポート」を

- [x] 全て許可

に変更します。
設定する場所は、[サーバー]→[ネームタグ]→[ネットワーク情報]→[接続許可ポート]です。

## ufwのインストール
`iptables`の設定を~~楽するた~~便利にするためのツール `ufw` を使います。

```
$ sudo aptitude install ufw
```

初期状態を確認します。

```
$ sudo systemctl status ufw
● ufw.service - Uncomplicated firewall
   Loaded: loaded (/lib/systemd/system/ufw.service; enabled; vendor preset: enabled
   Active: inactive (dead)
     Docs: man:ufw(8)
```

`ufw`のデフォルトのルールーはすべて遮断(deny)です。

```
$ sudo ufw status
Status: inactive
```

**現在のssh接続は切らないでください。**
ufwを有効にします。

```
$ sudo uwf enable
```

## ufwの設定

**このままでは以後ssh接続できなくなる**のでsshのポートを許可します。


```
$ sudo ufw allow 22/tcp
$ sudo ufw reload
```

`ufw`について下記の記事を参考にしました。

1. [ufwコマンドの使い方](https://qiita.com/hana_shin/items/a630871dce209cff04f3)
1. [ufwの基本操作](https://qiita.com/RyoMa_0923/items/681f86196997bea236f0)

# SSHポートの変更
sshのポートが22番のままでは、そこに集中攻撃を食らうリスクがあります。ポートを変更することで多少なりでもリスクをヘッジします。
例として新しいsshのポート番号を `54321` に変更します。実際に設定するポート番号は50000番台の適当な数値が無難でしょう。

### その前に(2)
お使いのターミナルソフトに新しいポート番号の設定を追加しておきましょう。
[`RLogin`](http://nanno.dip.jp/softlib/man/rlogin/)なら「接続先を複写する」を行ってポート番号を変更するのが簡単だと思います。

## 再びファイヤーウォール設定
ファイヤーウォール設定で `54321/tcp` のポートを許可します。

```
$ sudo ufw allow 54321/tcp
$ sudo ufw reload
```

## sshポート番号を変更する
新しいsshのポート番号を `54321` に変更します。
`/etc/ssh/sshd_config`を設定します。

```
$ sudo nano /etc/ssh/sshd_config
```

キーワードPortを設定します。

```:/etc/ssh/sshd_config
Port 54321
```

編集が終わったら、sshdを再起動します。

```
$ sudo /etc/init.d/ssh restart
```

**現在の22番ポートでの接続はまだ切らないでください。**

ターミナルソフトの新しいポート設定で接続を試みます。
うまく接続できましたか？
接続できなたら、以後の作業はそれで行います。

## みたびファイヤーウォール設定
22番ポートを閉じます（`arrow 22/tcp` 設定を削除します）。
例えば、

```
$ sudo ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    Anywhere
[ 2] 54321/tcp                  ALLOW IN    Anywhere

```
```
$ sudo ufw delete 1
```
```
$ sudo ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 54321/tcp                  ALLOW IN    Anywhere

```


`ufw`の設定方法の説明は前述の参考記事（[1.](https://qiita.com/hana_shin/items/a630871dce209cff04f3) [2.](https://qiita.com/RyoMa_0923/items/681f86196997bea236f0)）に譲ります。

# もし途中で切断してしまい、接続できなくなったら？

- ConoHaダッシュボードの[ネットワーク設定](https://qiita.com/ludwigem/items/52caf0f9569ba6e2c40a#%E3%81%9D%E3%81%AE%E5%89%8D%E3%81%AB1)を忘れていませんか。
- [ターミナル](https://qiita.com/ludwigem/items/f6626603c4fce1bd78ec#%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%81%AB%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%8A%E3%83%AB)の出番です。rootでログインして修正作業しましょう。


# 次記事
独自ドメインを取ったり、SSL接続の仕込みなどを行いましょうか。
WordPress で is_rest()

WordPress には `is_home()` とか `is_singular()` とかリクエストされたページがなにかを判別する関数がいろいろありますが、それが REST API であるかどうかを判別するための関数がないので書いた。

```
/**
 * Returns the true if the requested URL is REST API.
 *
 * @return bool
 */
function is_rest() {
	return ( defined( 'REST_REQUEST' ) && REST_REQUEST );
}
```

ただし、これは `parse_request` というアクションフックが発火したあとじゃないと常に `false` を返すので以下のように使ってください。

```
add_action( 'parse_request', function() {
	if ( ! is_rest() ) {
		// do something.
	}
}, 11 );
```
Sidekiqのデフォルト再試行スケジュール表（目安）

> It will perform 25 retries over approximately 21 days. 

Sidekiqの再試行が **デフォルト設定の場合にどのくらいの間隔で行われるか** が知りたかったのだけれども、[公式](https://github.com/mperham/sidekiq/wiki/Error-Handling#automatic-job-retry) を読んでも `約21日で25回行う` くらいしか書かれていなかったので表にしてみた。

## 追記（2019-02-19）

と思ったら、[公式](https://github.com/mperham/sidekiq/wiki/Error-Handling#automatic-job-retry) に書いてあった。プルダウン見てなかった。。。

## リトライの計算式

[公式](https://github.com/mperham/sidekiq/wiki/Error-Handling#automatic-job-retry)を参照。

```ruby
(retry_count ** 4) + 15 + (rand(30) * (retry_count + 1))
``` 

## 結果

### 前提

1. **あくまで目安**
1. 最短、平均、最長の各値は、最初のジョブが失敗してから実行されるまでの期間を表す
1. ジョブ自体の処理時間等は加味していない（仮に処理が10秒かかるものだとすれば、2回目が実行されるタイミングは最短でも41秒後）
1. `再試行回数`は、何回目の再試行かを表す
1. `最短`は、上記計算式の`rand(30)` が毎回`0`を返した場合としている
1. `平均`は、上記計算式の`rand(30)` が毎回`15`を返した場合としている
1. `最長`は、上記計算式の`rand(30)` が毎回`30`を返した場合としている

### 表

| 再試行回数 | 最短 | 平均 | 最長 |
| :-- | :-- | :-- | :-- |
| 1回目 | 0日00時間00分15秒後 | 0日00時間00分30秒後 | 0日00時間00分45秒後 |
| 2回目 | 0日00時間00分31秒後 | 0日00時間01分16秒後 | 0日00時間02分01秒後 |
| 3回目 | 0日00時間01分02秒後 | 0日00時間02分32秒後 | 0日00時間04分02秒後 |
| 4回目 | 0日00時間02分38秒後 | 0日00時間05分08秒後 | 0日00時間07分38秒後 |
| 5回目 | 0日00時間07分09秒後 | 0日00時間10分54秒後 | 0日00時間14分39秒後 |
| 6回目 | 0日00時間17分49秒後 | 0日00時間23分04秒後 | 0日00時間28分19秒後 |
| 7回目 | 0日00時間39分40秒後 | 0日00時間46分40秒後 | 0日00時間53分40秒後 |
| 8回目 | 0日01時間19分56秒後 | 0日01時間28分56秒後 | 0日01時間37分56秒後 |
| 9回目 | 0日02時間28分27秒後 | 0日02時間39分42秒後 | 0日02時間50分57秒後 |
| 10回目 | 0日04時間18分03秒後 | 0日04時間31分48秒後 | 0日04時間45分33秒後 |
| 11回目 | 0日07時間04分58秒後 | 0日07時間21分28秒後 | 0日07時間37分58秒後 |
| 12回目 | 0日11時間09分14秒後 | 0日11時間28分44秒後 | 0日11時間48分14秒後 |
| 13回目 | 0日16時間55分05秒後 | 0日17時間17分50秒後 | 0日17時間40分35秒後 |
| 14回目 | 1日00時間51分21秒後 | 1日01時間17分36秒後 | 1日01時間43分51秒後 |
| 15回目 | 1日11時間31分52秒後 | 1日12時間01分52秒後 | 1日12時間31分52秒後 |
| 16回目 | 2日01時間35分52秒後 | 2日02時間09分52秒後 | 2日02時間43分52秒後 |
| 17回目 | 2日19時間48分23秒後 | 2日20時間26分38秒後 | 2日21時間04分53秒後 |
| 18回目 | 3日19時間00分39秒後 | 3日19時間43分24秒後 | 3日20時間26分09秒後 |
| 19回目 | 5日00時間10分30秒後 | 5日00時間58分00秒後 | 5日01時間45分30秒後 |
| 20回目 | 6日12時間22分46秒後 | 6日13時間15分16秒後 | 6日14時間07分46秒後 |
| 21回目 | 8日08時間49分41秒後 | 8日09時間47分26秒後 | 8日10時間45分11秒後 |
| 22回目 | 10日14時間51分17秒後 | 10日15時間54分32秒後 | 10日16時間57分47秒後 |
| 23回目 | 13日07時間55分48秒後 | 13日09時間04分48秒後 | 13日10時間13分48秒後 |
| 24回目 | 16日13時間40分04秒後 | 16日14時間55分04秒後 | 16日16時間10分04秒後 |
| 25回目 | 20日09時間49分55秒後 | 20日11時間11分10秒後 | 20日12時間32分25秒後 |

### 表を作った時に書いたプログラム

秒から日に変換する処理は、[秒を時間表示へ変換する](https://qiita.com/riocampos/items/2c4e4a9b45ad83a0bdc7)を使用させていただいた。

```ruby
require "time"

def retry_seconds(retry_count, additional_value)
  (retry_count ** 4) + 15 + (additional_value * (retry_count + 1))
end

def print_retry_schedule(retries, execution_time)
  sec_list = (0..retries).reduce([0, 0, 0]) do |sum, retry_count|
    sum[0] += (retry_seconds(retry_count, 0) + execution_time)
    sum[1] += (retry_seconds(retry_count, 15) + execution_time)
    sum[2] += (retry_seconds(retry_count, 30) + execution_time)
    sum
  end

  str = "| #{retries + 1}回目 |"
  sec_list.each do |sec|
    day, sec_r = sec.divmod(86400)
    str += (Time.parse("1/1") + sec_r).strftime(" #{day}日%H時間%M分%S秒後 |")
  end

  p str
end

(0...25).each { |n| print_retry_schedule(n, 0) }
```
AtomのHydrogenでMatplotlib, Bokeh, HoloViewsおよび他ライブラリのプロットを表示する

# はじめに

[Atom](https://atom.io/)の[Hydrogen](https://atom.io/packages/hydrogen)で[Matplotlib](https://matplotlib.org/), [Bokeh](https://bokeh.pydata.org/en/latest/), [HoloViews](http://holoviews.org/)のプロットを表示する方法です。


# Matplotlib

```python
import matplotlib.pyplot as plt
plt.scatter([1, 2, 3], [1, 2, 3])
```

Jupyter Notebookで必要な

```python
%matplotlib inline
```

は要りません。

# Bokeh

```python
from bokeh.plotting import figure, output_notebook, show
from bokeh.resources import INLINE
output_notebook(INLINE)

plot = figure()
plot.circle([1, 2, 3], [1, 2, 3])
show(plot)
```

`output_notebook`がないと外部ブラウザにプロットが表示されてしまいます。`INLINE`は必ずしも必要ないですが、こうすると、BokehJS x.x.x successfully loaded.のメッセージが確認できます。

# HoloViews

プロットの準備

```python
import numpy as np
import pandas as pd
import holoviews as hv

xs = np.arange(-10, 10.5, 0.5)
ys = 100 - xs**2
df = pd.DataFrame(dict(x=xs, y=ys))
curve = hv.Curve(df,'x','y')
```

ここまでは特定の可視化ライブラリに依存していません。

### バックエンドがMatplotlibの場合

```python
hv.extension('matplotlib')
hv.render(curve)
```

### バックエンドがBokehの場合

```python
from bokeh.io import show
hv.extension('bokeh')
show(hv.render(curve))
```

HoloViewsを通してBokehのプロット表示する際には、`output_notebook`は不要です。また、Jupyter Notebookの場合は、`curve`をセルの最後に入力するだけでプロットが表示されますが、Hydrogenの場合は、`hv.render`や（Bokehの場合には）`show`が必要となるようです。

## hvPlot

```python
import pandas as pd
import numpy as np
import holoviews as hv
import hvplot.pandas
from bokeh.plotting import show

idx = pd.date_range('1/1/2000', periods=1000)
df = pd.DataFrame(np.random.randn(1000, 4), index=idx,
                  columns=list('ABCD')).cumsum()
show(hv.render(df.hvplot()))
```

## Altair

```python
import altair as alt
import pandas as pd

source = pd.DataFrame({
    'a': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'],
    'b': [28, 55, 43, 91, 81, 53, 19, 87, 52]
})

alt.Chart(source).mark_bar().encode(x='a', y='b')
```
DonkeyCar 教師データから不要な部分を除いて訓練する（旧バージョン2.5.8）

#目的
良くない教師データを含んで訓練すると推論に悪影響を及ぼすので除去する．

#不要データの除去

スロットルとステアリングを可視化した動画を見て良くないデータの画面に表示されている番号をチェック．
ファインダーのtubフォルダで該当する番号のjpegファイルをゴミ箱に移動（jsonファイルはそのままでよい）．

#訓練

trainのコマンドで訓練を行うが，番号が連続していないとエラーになるので，
~/donkeycar/donkeycar/parts/datastore.pyの218行目(def ～)と219行目(path ～)の間に以下の行を追加する．

```python:datastore.py

        while True:
            path = os.path.join(self.path, str(ix) + '_cam-image_array_.jpg')
            if(os.path.exists(path)):
                break
            ix += 1
            if(ix > 100000):
                break
        self.ix = ix
```

これで訓練する．
スキルマップを作って活用しよう

# はじめに
この記事は現場でスキルマップを作ったことによって得られたことがいくつかあったので、スキルマップ作成における狙いと効果を書いていこう思います。

# 記事を読んでほしい人
- チームリーダーをやっている人
- モチベーションマネジメントに悩んでいる人
- メンバーのことをよく知らない人
- 作業割り振りに悩んでいる人

など

# スキルマップとは
スキルマップとは各能力毎に項目を作り、その習熟度を一覧化した表です。
詳しくは https://www.skillnote.jp/knowledge/skillmap1/ を参照すると分かりやすいと思います。

# なぜスキルマップを作ろうと思ったのか
当初私が案件のリーダーとしてメンバーを7〜8名ほど抱えることになったのですが、そのメンバーとは一緒に仕事をしたことがなく、どんなスキルを持っているかわからないという状態でした。
そこで、ミスマッチアサインを減らすことを目的としてスキルマップ作成を試みたというのが作成に至った経緯です。

# どんなスキルマップを作ったか
### 習熟度
5：かなり詳しい
4：概ね理解している
3：部分的に理解している
2：触ったことある
1：ﾅﾆｿﾚｵｲｼｲﾉ

### 技術スキルマップ
| 名前 |Java|SQL|JavaScript|Spring|HTML/JSP|SQLチューニング|
|------|------|------|------|------|------|------|
|〇〇太郎|3|2|1|3|1|2|
|〇〇次郎|2|4|2|2|2|4|
|〇〇三郎|1|1|4|1|4|1|

### 業務仕様スキルマップ
| 名前 |A機能|B機能|C機能|D機能|E機能|F機能|
|------|------|------|------|------|------|------|
|〇〇太郎|5|2|1|3|1|4|
|〇〇次郎|2|3|2|2|2|3|
|〇〇三郎|1|4|1|1|2|3|

こんな感じに技術面と仕様面に分けてスキルマップを作り、メンバー本人に自己評価で記入してもらいました。
記入項目については、案件で必要なスキルや知識に限定しました。

# どんな使い方をして、どんな結果が得られたか
### アサインの適正化
前述の通りミスマッチアサインを減らすためにこの表をベースに担当割り振りを考えました。
できる人を得意なところにアサインするだけでなく、できない人をアサインした場合にフォローにつける人などを決めたりするのに使用しました。

### 有識者の見える化
誰が何が得意かがスキルマップによって見える化するので、A機能であれば○○太郎さんに、SQLであれば○○次郎さんに。という風に誰に聞けば分かるか判断に迷わなくなりました。

### 成長の見える化
スキルマップを案件開始時と案件終了時の2回のタイミングで記入してもらいました。その結果、開始前より開始後の方が数字が大きくなっている項目が増えます。メンバーにとっては成長が見える化するのでモチベーションアップに繋がりました（おそらく）

# 最後に
スキルマップはマネジメント側の理解のためだけでなく、全体最適化や有識者の見える化、成長の見える化などチーム全体にプラスをもたらせてくれる良いものです。
まだまだ改善点はあると思いますが、スキルマップありなしで比べたらありの方が断然よい結果を得られました。
ただし、スキルマップを作成する前には必ずメンバー全員に同意を得る必要があります。
メンバーによっては周りと比べられているようで嫌だという人もいます。
なので、メンバーの同意を得た上で評価には使用しない旨をしっかり共有して理解をしてもらった上で使用するとよいでしょう。
Firebase Meetup #11 Meetup内容まとめ

# はじめに
Firebaseコミュニティ Firebase Japan User Group（FJUG）の2019/2/18に開催されたMeetup内容のまとめです。

# LT

## Firestore rulesの運用とLocal Emulatorを使ったテスト
#### スピーカー
- Ginco

#### 内容

- FirebaseDatabaseの62%が漏洩
- そこで、Firestoreのセキュリティ基礎
    - クライアントから直接アクセスできる
    - アクセスはAPIキーが必要
    - だれでもアクセスできるからrulesを整理
    - rules
        - read/ write権限
        - データのバリデーション
        - 漏洩しないためのrules設定
                - 機密データは別階層にしてrules設定を厳しく
        - ワイルドカードでのrules設定できるが多用しないほうが良い
- Ginco
    - リリース中期でrulesが300件こえて管理困難に
- rulesのテスト方法
    - ClientSDKだけrulesが適用される
    - テストProjectを使った方法
        - あまり良くなかったそう
- 現在はFirestore Local Emulator でテストしてる
    - 認証、未認証アカウント、Adminアカウントを簡単に利用可能
    - テストデータの競合しない、truncateしなくていい
        - プロジェクトIDかえればまっさらな状態にできる
    - テスト実行時間が1/8に削減できた

     
#### 資料
- https://speakerdeck.com/tomokazukozuma/firebase-meetup-number-11-2019-02-18

## Firestore東京リージョン利用に伴う Firebaseプロジェクト移行手順
#### スピーカー
- @vexus2

#### 内容
- アルで現在移行作業中
- 100回程度のgetベンチマーク
    - us-centralは平均200ms
    - 東京リージョンだと平均100ms
- firestoreのデフォルトリージョンはus-central(β以前のプロジェクトは全部この状態)
    - firebaseは１プロジェクト１firestoreなのでリージョン変更は作り直さないといけない
- Firebase AuthenticationはInport/Exportできるので新プロジェクトでも同じユーザにできる
    - 匿名ユーザはログイン状態が引き継がれないためデータが消えてしまう
    - 旧Firestore　-> GCSにデータをExport　ー＞GCS　ー＞新Firestoreに
- ロンチ後だとデータ整合性担保するためにメンテナンス入れて移行が現実的
#### 資料
- https://speakerdeck.com/vexus2/alu-firestore-number-aru

## Firestore x React Hooks
#### スピーカー
- Mamoru Amano

#### 内容
- ReactHooks
    - React16.8から導入されたFunctionComponentの新しいAPI
    - componentのstateをfunctionで管理
      
#### 資料
- 未公開

## firebase × Vueと開発速度
#### スピーカー
- k-okina

#### 内容
- firebaseつかってインフラ、バックエンドのリソース余裕できた分、フロントに力入れよう
- Firebase が時間を生んでくれたおかげで堅牢な設計や凝った UI ができた
- pring.ts + vue.jsで開発すると開発速度上がりそう
- firebaseはいい感じにcacheしてくれて状態管理で困らない
- 次はElm　＋　Firebase構成を使いたい。
    - ElmはReduxやVuexなどに影響を与えた言語なので最高なのでは？
- firestoreのちょいテク
    - 分散カウンタ
        - 同一ドキュメントの更新は１秒に１回の制限がある
        - 多重いいねやCloudfunctionの多重実行対策にサブコレクションで保持する
#### 資料
- https://slides.com/kahirokunn/deck-11#/

## FirestoreのセキュリティルールをCircleCIでCIする
#### スピーカー
- ninjinkun

#### 内容
- 個人開発したBlogFeedbackアプリ
    - PWAで開発してる
    - Firestoreはセキュリティルールが命
    - セキュリティルールをCIしたい
        - データ構造修正のたびにセキュリティルール更新が発生する
        - 更新のたびにルールが正しいか保証したい
        - そこでLocal Emulator
        - circleciでやってる
            - cloud fanctionをcircleciでデプロイする場合、nodeのバージョンがちがうと動作しないので注意
        - firebase-tools > 6.1.1問題
            - circleciでのエミュレーター起動で落ちる
            - 原因；エミュレーターがIPv6アドレスにバインドするように変更されてた
                - cicleciではIPv6がサポートされてない
                    - Jarを直接起動することで解決
                        - Jar直接起動だとHostが上書きできるのでIPv4に書き換えれる
#### 資料
- https://ninjinkun.hatenablog.com/entry/cloud-firestore-circleci

## FirebaseとJIRAで進めるクラッシュ管理
#### スピーカー
- 株式会社ナビタイムジャパン　向井さん

#### 内容
- firebaseのCrashlytics
    - JIRAとの連携
        - CrashlyticsのissueからJIRAチケットを作ることができる
        - Firebaseとの統合からJIRAを選択する必要あり
- ナビタイムさんでの運用
    - Crash対応に集中する時間を設けている
    - スプリントとチケットにより運用に乗せている
#### 資料
- 未公開
Raspberry PiとHomebridgeでLEDを操作する方法

Raspberry PiにHomebridgeを入れることでRaspberry PiにつなげたものをiPadやiPhoneの「ホーム」アプリから操作することができるようになります。
Raspberry PiにHomebridgeを入れる際に何度か失敗したので自分がうまくいった方法を書きます。
## Homebridgeとは
Homebridgeをいれることでwifiを経由してRaspberry Piにスマートホームを操作する信号を送ることができます。今回はRaspberry PiにHomebridgeを入れてLチカをする方法を説明します。
## homebridgeのインストール
Raspberry PiのLXTerminal（ターミナル）に以下のコマンドを打ち込んでHomebridgeを入れます。

```
sudo apt-get update
sudo apt-get upgrade
sudo apt install nodejs npm
sudo apt-get install libavahi-compat-libnssd-dev
sudo npm install -g -unsafe-perm homebridge
```

これでHomebridgeのインストールは完了です。次に、操作する対象用のパッケージをインストールします。
## homebridge-cmdのインストールと設定
今回はhomebridge-cmdというパッケージを使います。
このhomebridge-cmdというのは、iPhoneやiPadから信号を送ったときに、事前に指定したコマンドやスクリプトを実行することができるパッケージです。  
iPhoneやiPadから操作した時にLEDをオン・オフするコマンドをRaspberry Piに実行させるようにします。

```
sudo npm install -g homebridge-cmd
```

と入力し、homebridge-cmdをインストールします。
次に、Raspberry Piの中の「/home/pi/.homebridge」にconfig.jsonを作ります。
ターミナルで`cd /home/pi/.homebridge」`を入力したあと、`nano config.json`と入力し、下記のファイルを書きます。


```config.json
{
    "bridge": {
        "name": "Homebridge",
        "username": "CC:22:3D:E3:CE:30",
        "port": 51826,
        "pin": "031-45-154"
    },

    "description": "This is an example configuration file with one fake accessory and one fake platform. You can use this as a template for creating your own configuration file containing devices you actually own.",

    "accessories": [
        {
            "accessory": "CMD",
            "name": "LED",
            "on_cmd": "echo 1 > /sys/class/gpio/gpio14/value",
            "off_cmd": "echo 0 > /sys/class/gpio/gpio14/value"
        }
    ]
}
```  
引用:https://qiita.com/nyata/items/e8304f4d3643d4cee377  
今回はRaspberry PiのGPIOにつなげたLEDの操作をiPhoneやiPadから遠隔でできるようにします。
GPIO14にLEDのプラス極、GNDにマイナス極をつなげます。
## 使い方
事前にターミナルで`echo 14 > /sys/class/gpio/export`と`echo out > /sys/class/gpio/gpio14/direction`を実行して、GPIOを有効化しておきます。  
そして、`homebridge`とターミナルに入力してHomebridgeを起動します。
すると、QRコードが出てくると思うので、それをiPadやiPhoneの「ホーム」アプリからプラスボタンを押して、「アクセサリを追加」を選択してそのQRコードを読み込むと、Homebridgeと「ホーム」アプリが接続されます。ただし、iPadやiPhoneとRaspberry Piが同じWi-Fiに接続している必要があります。  
最後に、接続することで「ホーム」アプリのなかにでてくるボタンを押すと、LEDのオン・オフができます。
EntityFrameWorkでSQLのログを出力する方法

## 環境
Entity Framework Version 6

## ログの出力指定
DbContextクラスを継承したクラスのコンストラクタにてログ出力の設定を行う。具体的はDbContextクラスのDatabaseプロパティのLogプロパティにログの出力方法を指定すればよい。
    
```C#
public partial class SampleModel : DbContext
    {
        public SampleModel(string connectionString)
            : base(connectionString)
        {
            this.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
        }

        public virtual DbSet<Sample> Samples { get; set; }
    }
```

上記のような設定を行うことでコマンドライン上にEntityFrameworkが実行したSQLのログを確認することができる。
Vim の "make test" を読み解く 第 1 回 (make test 概要)

[Meguro.vim #14](https://megurovim.connpass.com/event/115767/) に参加したとき、Vim 本体の主にテスト関連のコードを読んでもくもくしたので記事にすることにしました。Vim 自身のテストに関する記事ってあんまりないような気がしたので。理解できた部分を少しずつ追記していきます。大変に地味な記事になる予感。けど Vim script を使い倒しているはずなので、自分の勉強にもなるかも。面白そうなトピックがあれば教えてください。
OS は Linux で、以下の設定で実行した場合を想定しています。

```bash
$ ./configure --with-features=huge --enable-fail-if-missing --prefix=$HOME
```

# 目次
まだ未完成で雑多だけどとりあえず目次。
(本記事) Vim の "make test" を読み解く 第 1 回 (make test 概要)
[Vim の "make test" を読み解く 第 2 回 (scripttests 概要)](https://qiita.com/m_nish/items/f0c389d2fa1e0e4b67bb)
[Vim の "make test" を読み解く 第 3 回 (src/testdir/README.txt)](https://qiita.com/m_nish/items/957f52c71884fa055dd9)
[Vim の "make test" を読み解く 第 4 回 (単体 new-style-testing の実行)](https://qiita.com/m_nish/items/97f79bacfc920fbd7317)
[Vim の "make test" を読み解く 第 5 回 (runtest.vim)](https://qiita.com/m_nish/items/9f9ab25974e617400e3d)

# make test
[`:help testing`](https://vim-jp.org/vimdoc-ja/eval.html#testing) を見てみると分かるように、一般的なアプリケーションと同様に Vim にもテストが存在していて、`make test` で実行することができます。また、[src/Makefile](https://github.com/vim/vim/blob/b0e2da2b23e7497d0a145ecce9c1e08b6fab6dbf/src/Makefile#L108-L112) には以下のような記述があります。

```Makefile
# 4. "make test"  {{{1
#	This is optional.  This will run Vim scripts on a number of test
#	files, and compare the produced output with the expected output.
#	If all is well, you will get the "ALL DONE" message in the end.  If a
#	test fails you get "TEST FAILURE".  See below (search for "/^test").
```
日本語訳
> このステップは任意です。これはたくさんのテストファイル上で Vim script を実行し、生成された出力と期待される出力を比較します。すべてが正常だった場合、"ALL DONE" というメッセージが最後に表示されます。もしテストが失敗した場合は "TEST FAILURE" が表示されます。("/^test" で検索して) 下のほうを参照してください。

2018/02/18 現在 (tag: v8.1.0946) では、"ALL DONE" は実際には最後ではなく途中に表示されます。これは次の章で説明しますが、もともとあった Vim 本体のテストに対して unit test と libvterm のテストが後から追加されたためではないかと推測します。libvterm に関しては以下のサイトが参考になります。
https://qiita.com/mattn/items/5aed718a65d21ca7855c
libvterm のテストを実行するためには、`sudo apt install libtool-bin` を実行しておく必要があるようです。

# Makefile
`make test` (もしくは `make check`) でテストを実行すると、

1. scripttests
1. unittests
1. test_libvterm

の 3 つが実行されることが分かります。

```Makefile
# TESTING
#
# Execute the test scripts and the unittests.
test check: scripttests unittests test_libvterm
```
先に種明かしをしてしまうと、scripttests は Vim 本体の機能のテスト、unittests は Vim の内部に存在する関数のユニットテスト、test_libvterm は上述の libvterm に関するテストです。

とりあえず、第 1 回はここまで。

# 読み解きネタ
- terminal-dumptest
- test_largefile -> `make test` には含まれていないことを、[第 2 回](https://qiita.com/mnishz/items/f0c389d2fa1e0e4b67bb) で言及
- new-style-test の単体実行 -> src/testdir/README.txt の内容として [第 3 回](https://qiita.com/mnishz/items/957f52c71884fa055dd9) で紹介
- flaky_tests
Windowsのtreeをpathに変換するコードを書いてみた。

PCを初期化したとき、初期の構造を記憶するためにディレクトリ構造を取得したくて取得したのだが、
`dir C:\\* /s /b /ad`で取得すればいいものを
`tree`で取得してしまった。

でも今更もっかい初期化とかできないし。どうしよう。
そうだ、唯一使えるPythonを使ってPath化しよう！

ということで書いた。

#コード

ちなみに私はインデントにタブを使っている。タブが好きだからだ。クソコードごめんね

```Python
import os


class DirectoryTreeChangeToPath:

	def __init__(self, path):
		paths = self.shaping(self.get_file_content(path))
		with open(".\\changed_directory_tree_to_path.txt","x") as f:
			for i in paths:
				f.write(i + "\n")

	@staticmethod
	def get_file_content(path, mode="r", encoding='utf-8'):
		if os.path.exists(path):
			with open(path, mode=mode, encoding=encoding) as f:
				for i in f:
					yield i
		else:
			raise FileNotFoundError

	@staticmethod
	def shaping(default_dir_tree_data):
		directory = [next(default_dir_tree_data)[:-2]]
		for i in default_dir_tree_data:
			i = i.replace("\n", "", -1)
			i = DirectoryTreeChangeToPath.pipe_count(i)
			DirectoryTreeChangeToPath.merge(directory,i)
			yield "\\".join(directory)

	@staticmethod
	def merge(subject_,object_):
		if len(subject_) > object_[0]:
			del subject_[object_[0]:]
		return subject_.append(object_[1])

	@staticmethod		
	def pipe_count(string):
		indent = 0
		while True:
			if string[:2] in ("└─","├─"):
				string = string[2:]
				indent += 1
				break
			elif string[:3] == "│  ":
				string = string[3:]
				indent += 1
			elif string[:4] == "    ":
				string = string[4:]
				indent += 1
		return indent,string


def main():
	os.chdir(os.path.dirname(__file__))
	DirectoryTreeChangeToPath(".\\infomation\\default_dir_tree_data")


main()
```

#書いてる間の思考

パイプをただのインデントとしてみたら簡単に数値に置換できた。
PHPで土日祝日の一覧を出力する

土日と祝日だけを取得したくて、書いてみました。
祝日は[Yasumi](https://github.com/azuyalabs/yasumi)で確認します。
土日はCarbon使うことも出来ますが、曜日を見て判断しています。

## 準備
```sh:console
% composer require azuyalabs/yasumi
```

## コード
```php:holiday.php
<?php
declare(strict_types=1);
require_once 'vendor/autoload.php';

/**
 * 土日祝日ジェネレータ
 *
 * @param int $year 範囲の年
 * @param string $start 開始年月日(Y-m-d)
 * @param string $end 終了年月日(Y-m-d)
 * @param string $format 出力フォーマット
 * @return Generator
 * @throws ReflectionException
 */
function getStaticHoliday(int $year, string $start, string $end, string $format = 'Y-m-d'): Generator
{
    try {
        $startObj = new \DateTimeImmutable($start . 'T00:00');
        $endObj = new \DateTimeImmutable($end . 'T24:00');
        $interval = new \DateInterval('P1D');
        $period = new \DatePeriod($startObj, $interval, $endObj);
    }catch (Exception $e) {
        echo $e->getMessage(), PHP_EOL;
        return;
    }

    $holidays = \Yasumi\Yasumi::create('Japan', $year, 'ja_JP');

    foreach ($period as $day) {
        // 休日または土日である場合
        if ($holidays->isHoliday($day) || false !== array_search($day->format('w'), [0, 6])) {
            yield $day->format($format);
        }
    }
}

try {
    foreach (getStaticHoliday(2019, '2019-02-18', '2019-08-01', 'Y/m/d') as $holiday) {
        echo $holiday, PHP_EOL;
    }
} catch (ReflectionException $e) {
    echo $e->getMessage(), PHP_EOL;
}
```

## 出力結果
```sh:coneole
% php holiday.php
2019/02/23
2019/02/24
2019/03/02
2019/03/03
2019/03/09
2019/03/10
2019/03/16
2019/03/17
2019/03/21
...
```

## 参考
[【PHP】日本の祝日を扱うときは「Yasumi」を使ってみてはどうですか](https://qiita.com/sola-msr/items/7901835b3bfe145de033)
[【PHP】日付を一日ずつ進めて表示させてゆく](https://qiita.com/sugar020855/items/bbfe3f8275cb65500d69#comment-794385f031d907e7cacd)(コメントより)
DockerでWebpack+Babel開発環境作ってみた

# はじめに
ES6以上のJSをES5にトランスパイルするのに便利なBabelの環境を作ってみたいと思います。
vue.jsやReact.jsと組み合わせたwebpackやbabel環境構築の記事はよく見かけますが、今回はdockerでwebpack+babelのみの開発環境構築をご紹介します。

# 環境
以下の環境で動作確認はしております。

MacOS Mojave 10.14.3
Docker version 18.09.2
docker-compose version 1.23.2, build 1110ad01

# 構成
dist/にbundle.jsを作成することをゴールとします。

```
├── dist
│   └── bundle.js
├── docker
│   └── webpack
│       ├── Dockerfile
│       ├── package.json
│       └── webpack.config.js
├── docker-compose.yml
└── src
    ├── app.js
    └── test.js

```

# 構築

## 1. docker-compose.yml作成
今回は、bundle.jsを作成するためだけのコンテナを作成します。

```docker-compose.yml
version: '3'

services:
  webpack:
    build: ./docker/webpack
    volumes:
      - ./src:/my_webpack/src
      - ./dist:/my_webpack/dist
      - ./docker/webpack/package.json:/my_webpack/package.json
      - ./docker/webpack/webpack.config.js:/my_webpack/webpack.config.js
    ports:
      - 2000:2000
```

## 2. Dockerfile作成

```Dockerfile:Dockerfile
FROM node:8.15.0
WORKDIR /my_webpack
RUN npm init -y
RUN npm install -D webpack webpack-cli babel-loader @babel/core @babel/preset-env
RUN npm install jquery

CMD ["npm", "run", "build"]
```

## 3. package.json作成
ファイルの変更を検知して、再ビルドしてもらうために --watch オプションをつけてます。
あと、今回はjQueryもちゃっかり入れてます。不要な人は、削除しても構いません。

```json:package.json
{
  "scripts": {
    "build": "webpack --watch"
  },
  "dependencies": {
    "jquery": "^3.3.1"
  },
  "devDependencies": {
    "@babel/core": "7.0.0",
    "@babel/preset-env": "7.0.0",
    "babel-loader": "^8.0.0",
    "webpack": "^4.17.1",
    "webpack-cli": "^3.1.0"
  },
  "private": true
}
```

## 4. webpack.config.js
[ターゲットのブラウザ](https://browserl.ist/?q=%3E0.25%25+in+JP%2C+not+ie+%3C%3D+10%2C+not+op_mini+all)も指定できるので、ここで指定しちゃいます。
エントリポイントはsrc/直下に配置するapp.js、dist/以下にbundle.jsとして出力するように設定しています。

```javascript:webpack.config.js

const presets  = [
  [
    '@babel/preset-env',
    {
      "targets": [">0.25% in JP", "not ie <= 10", "not op_mini all"]
    }
  ]
];
module.exports = {
  mode   : 'development',
  devtool: 'inline-source-map',
  entry  : './src/app.js',
  output : {
    path    : `${__dirname}/dist`,
    filename: 'bundle.js'
  },
  module : {
    rules: [
      {
        test: /\.js$/,
        use : [
          {
            loader : 'babel-loader',
            options: {
              presets: presets
            }
          }
        ]
      }
    ]
  }
};

```

## 5. ES6のサンプル用意
トランスパイル用のES6で書かれたサンプルを用意します。

```javascript:app.js
import Test from './test';

Test.viewConsole();
```

```javascript:test.js
export default class Test {
  static viewConsole () {
    ['cat', 'dog', 'bear'].forEach(item => {
      console.log(item);
    });
  }
}
```

# 結果

## docker-composeで起動

```bash
$ docker-compose up -d
```

dist直下にbundle.jsが作成されて入れば成功です。
また、app.jsやtest.jsを編集してみて下さい。
それに応じて、bundle.jsも再ビルドされていることでしょう。
EntityFrameworkでデータ挿入時、Identity指定列をInsert文から除外する

## 環境
Entity Framework Version 6

## DatabaseGenerated属性
DatabaseGenerate属性にDatabaseGeneratedOption.Noneを指定することでupdateやinsertの更新対象から除外することができる。以下の例であればId列を更新および新規作成の対象列から除外することができる。

```C#:Account.php
    public partial class Account
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int Id { get; set; }

        public string Name { get; set; }
}
 ```
gasでスプレッドシートに営業日を挿入したシートを作成

#やりたかったこと
下の画像（月次の営進捗管理的なやつ）の黄色い箇所に平日のみ日付をいれたシートを毎月作成したい。

![スクリーンショット 2019-02-11 14.57.21.png](https://qiita-image-store.s3.amazonaws.com/0/205237/acc6a629-914e-7513-7521-1b34466db28f.png)

##コード
```javascript:qiita.gs
function createSheet() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet(); 
  var sheetName = sheet.getSheetName();
  var reg = /\(.+?\)/;
  var name = sheetName.match(reg);
  var index = sheet.getIndex();
  var templateSheet = ss.getSheetByName('テンプレート');
  var m = Moment.moment();
  var year = m.format("YYYY");
  var month = m.format("MM");
  var newSheet = ss.insertSheet(month + "月" + name, index + 2,{template: templateSheet});
 
  var endDay = Moment.moment(year+"-"+month, "YYYY-MM").daysInMonth();
  var calendarId = "ja.japanese#holiday@group.v.calendar.google.com";
  var calendar = CalendarApp.getCalendarById(calendarId);

  var counter = 2;
  for (var i = 1; i <= endDay; i++) {
    var day = new Date(year,month - 1,i);
    var dayOfWeek = day.getDay();
    var todayEvents = calendar.getEventsForDay(day);
    if (dayOfWeek == 0 || dayOfWeek == 6 || todayEvents.length == 1){
      continue;
    } else {
      if (dayOfWeek % 5 == 0) {
        newSheet.getRange(counter, dayOfWeek += 1).setValue(month + "/" + i);
        counter += 6;
      }  else {
        newSheet.getRange(counter, dayOfWeek += 1).setValue(month + "/" + i);
      }
    }
  }
}
```

テンプレートは非表示にして、「図形描画」でシートを作成ボタンを挿入。
ボタンにスクリプトを割り当てる。

##できた..けど...

![スクリーンショット 2019-02-18 18.53.29.png](https://qiita-image-store.s3.amazonaws.com/0/205237/c1c2e4c3-0752-bd1b-1af7-81edfb669319.png)

##欲を言えば
・自分が管理しているのでシート作成ボタンを他の人が押すことは無いが、誰が押しても順番が変わらないようにしたい
・↑ほんとはトリガーで自動作成したい（どうやって３人分ののシートを取得するかが分からなかった）
・最初の1月も自動で作成したい
・繰り返し処理がもっとスマートに書けんもんかね、、、

アドバイスいただけたら助かります！
Missing :controller key on routes definition, please check your routes. (ArgumentError)

#1.↑って何？
Missing :controller key on routes definition, 
「**routes**のコントローラーのキーが”欠けています。”」

please check your routes. (ArgumentError)
「**routes**見てね。」


#２.解決策

```ruby:routes.rb
get "blogs/new" => "blogs#new"
```
一度上記ように書き直す。
chrome起動時に発生したエラー「このアプリケーションのサイド バイ サイド構成が正しくないため、アプリケーションを開始できませんでした」の対処法


##表示されたエラーメッセージ
「このアプリケーションのサイド バイ サイド構成が正しくないため、アプリケーションを開始できませんでした。詳細については、アプリケーションのイベント ログを参照するか、コマンド ライン ツール sxstrace.exe を使用してください。」

##発生したタイミング
chromeを起動しようとしてchromeのアイコンをダブルクリックしたとき
どういうタイミングで発生するようになったのかは不明


##エラーが発生して開けなくなった時の暫定対処法
chromeをダウンロードし、再インストールしたら起動できるようになった。
参考にしたサイトではchromeのアンインストールも書いてあったが、再インストールだけで起動するようになった。

ブックマークも開いていたブラウザのタブもそのまま残っていたのでよかったよかった。

###参考にしたサイト
-[Chrome「サイドバイサイド構成が正しくないため」エラーの解決方法](http://pasokatu.com/10791)
-[Google Chrome が 「サイド　バイ　サイド構成が正しくない」 エラーで使えない](https://answers.microsoft.com/ja-jp/windows/forum/windows_vista-windows_programs/google-chrome-が/5a188abe-93f3-44ed-afc1-f73e3c384685)
プログラミング学習記録2〜railsチュートリアルにかかる時間〜

##今日やったこと
- railsチュートリアルはどれくらいの時間をかけるとクリアできるのか？を調べた
- ProgateのRuby1 リセット復習
- ProgateのRuby2 リセット復習
- ProgateのRuby3 リセット復習&そのまま復習

###railsチュートリアルにかかる時間【40〜130時間】
Progateのrailsが終わったらrailsのチュートリアルをやろうと思っています。

そこで「他の人は大体どれくらいの時間をかけてやっているのだろう？」と思い、気になったので調べてみました。

結論から言うと当たり前ですが「人による」みたいですね。

早い人だと40時間で終わってたりもしますが、130時間くらいはかかるといった意見もありました。

私はそんなに飲み込みが早い方でもないですし、復習に時間をかけがちなタイプなので最低でも130時間以上はかかると思って、railsチュートリアルに臨みたいと思います。

###Progate Ruby1,2,3
今日Progate Rubyの復習をしてみた結果、Rubyの1,2,3はもうリセット復習はしなくていいなと思いました。

復習するにしても、そのまま復習（コードを打たず、見るだけの復習）しかしないことにします。

私は9割理解してても、残りの1割ちょっとでも理解できないところがあるとできるまで復習してしまうタイプです。

ただ、プログラミングは基礎学習に完璧を求めてもスキルは向上しないみたいなので、名残惜しいですが割り切って前に進みます。


##100DaysOfCode Day2感想
100DaysOfCodeが１日坊主にならずに済んでよかったです。

Qiitaに投稿することを考えると、ちょっとカッコつけたくなるというか、ちゃんとした記録を載せなきゃダメだなと思えるので、学習過程を記録していくことは今のところ自分にとってプラスだと思いました。

このまま100Days完走できるように頑張ります。

おわり
Googleスプレッドシートのリンクのいろいろ

# 構文
```
=HYPERLINK(URL, [リンクラベル])
```
- HYPERLINK - ドキュメント エディタ ヘルプ(Google 公式)  
https://support.google.com/docs/answer/3093313?hl=ja

# 外部URLに飛ばす
```
=HYPERLINK("https://www.google.com","Link")
```
新しいウィンドウで「https://google.com 」が開かれます。

# シートに飛ばす
```
=HYPERLINK("#gid=1234567890","Link")
```
gidに指定したシートに移動します。
gidに関しては対象シートを開いたときのURLのところに記載されています。

# シートのセルに飛ばす
```
=HYPERLINK("#gid=1234567890&range=C8","Link")
```
gidで指定したシート内のrangeで指定したセルに移動します。

# シートのセルに飛ばし、範囲選択されている状態にする
```
=HYPERLINK("#gid=1234567890&range=C8:E10","Link")
```
gidで指定したシート内のrangeで指定した範囲の左上の位置に移動し、指定した範囲を選択状態にします。
上記の場合C8のところに飛び、C8:E10が選択されている状態になります。


# シートの値が記載されているところに飛ばす

```
=HYPERLINK("#gid=1234567890&range=B"&match("検索値",'シート名'!B:B,0),"Link")
```
少し応用、gidで指定したシートの特定列から、"検索値"を探し出し、その記述が書かれているところに飛ばす。 
上記の場合、対象シートのB列から検索値を探し出しそこに飛ぶ。

なお、「'シート名'」のシートはgidで指定しているシートのシート名を入れてやる必要がある。 
gidとシート名が混在するためちょっと面倒。
※次項に記載している方法を使えば多少スマートになる。

# gidではなくシート名でリンクを作りたい場合
「メニュー＞ツール＞スクリプトエディタ」でスクリプトエディタを開きに以下の記述を追加したうえで

```js:
function getSheetId(sheet_name) {
    var sheet_id = SpreadsheetApp.getActive().getSheetByName(sheet_name).getSheetId();
    return sheet_id;
}
```

以下のようにスプレッドシートに関数を記述すれば可能になります。

```:
=HYPERLINK("#gid="&getSheetId("シート名"),"Link")
```

# 補足
他、良さそうなものがあれば追記していきます。
フィボナッチが30倍早くなった話

KS8695という古いARM SOCのBare Metalにmrubyをのせてfib(32)を計算させたところ、1155秒もかかりました。いくら古いといえ同時期のMIPS SOCのADM5120が114秒なので遅すぎです。

ARMはMMUを有効にしないとパフォーマンスが出ないという話を思い出しいろいろ調べてみました。

以下のコードが大変参考になりました。

https://github.com/dwelch67/raspberrypi/tree/master/mmu

上記のディレクトリにも長いREADMEが入っていますが、このコードを解説した人も見つけました。

https://www.snaums.de/informatik/mmu-on-raspberry-pi.html

KS8695はARMv4ですが、ARMv6まではそれほど違いがないようなので、そのままコードが利用できました。ARMv7以降はこれより複雑になっているようです。

Bare MetalでMMUを有効にするには物理アドレス=仮想アドレスにして固定のテーブルを作ります。

![MMU.png](https://qiita-image-store.s3.amazonaws.com/0/104066/124d51d6-bef3-4a42-9673-28482849f4ea.png)

dwelch67さんのmmuのディレクトリのコードはmmuを有効にしているだけでキャッシュを有効にしてないので、extestディレクトリのコードや解説の方を参考にしてコードを取り込んでみました。

セクションと呼ばれる1Mバイト単位の処理で先頭の8つ(8M)のSDRAMをキャッシュ可能に設定してL1をスタートしました。他はFlashやIOになるので、キャッシュ無しの設定です。

このケースはmmuをスタートの前と後でアドレスが同じでなので、処理に影響はありません。FreeBSDのarmやmipsではkernelの物理アドレスと仮想アドレスが違いますが、絶対アドレスでのジャンプはないので、ちょっとしたテクニックで、仮想アドレスに移行できます。

```c
        for(ra=0;;ra+=0x00100000)
        {
                if (ra < 0x800000)   /* SDRAM */
                        mmu_section(ra,ra,0x0000 | BUFFERABLE | CACHEABLE);
                else
                        mmu_section(ra,ra,0x0000);
                if(ra==0xFFF00000) break;
        }

        start_mmu(MMUTABLEBASE,0x00000001|0x1000|0x0004);

        start_l1cache();
```

これでfib(32)を計ったところ37秒まで短縮されました。

通常の処理はこれで良いのですが、Network機能などでDMAをおこなう場合は、キャッシュされると困ります。FreeBSDのドライバではキャッシュを物理メモリに強制的にはく処理と、キャッシュを捨てる（メモリから読み直し）の処理を入れています。Bare Meralの場合DMAするバッファのメモリだけはキャッシュ無しにしておいてそこを使うのが良いと思います。

私のコードはここに置いてあります。

https://github.com/yamori813/ksbm-mruby
CloudFrontでハマった

# 概要
CloudFrontのdeployが完了するまで暇なので、
CloudFrontでハマったあれやこれやについて、恥を忍んで書き連ねました。
皆様におかれましては、「いやそれはねーわ」と呟きつつ、何かの参考にしていただければ幸いです。

# Path Patternでハマった
公開画面と管理画面があり管理画面はキャッシュしないという要件のシステム。
管理画面は「/manage/hogehoge」となる設計であるため、
CloudFrontのPath Patternを利用し、以下の通りとした。

|Precedence|Path Pattern  |Origin or Origin Group|
|:----------------|:------------------|:------------------:|
|0                   |manage/      |ELB-hogehoge-web     |
|1                   |Default (*)      |ELB-hogehoge-web     |

[Default (*)]では、キャッシュする設定を行い、
[manage/]では、キャッシュしない設定とした（[参考](https://dev.classmethod.jp/cloud/aws/create-no-cached-cloudfront-distribution/))

## ハマった！
数日後…。
管理画面のログイン部分が完成。

完成…したはずだが、なんか動作が怪しい。
というか、そもそもログインができない時がある。
セッション周りか？バグか？と思うが、怪しい点は見つからない…
（こういうときに限って本題とは関係ないバグや設定ミスを見つけたりするのはなんでだ）

## 原因
 **Path Pattern**は末尾に **\***をつける！
つまり

|Precedence|Path Pattern  |Origin or Origin Group|
|:----------------|:------------------|:------------------:|
|0                   |manage/**\***      |ELB-hogehoge-web     |
|1                   |Default (*)      |ELB-hogehoge-web     |
 
 いや、うん、常識だよね…わかるよ…
 最初に設定した時に、なんの気無しに設定しちゃったから…
 
# CloudFront経由で繋がらずハマった
初構築でいきなりハマった。
## ハマった！
CloudFront初導入！意気揚々と接続すると504エラー
![error.png](https://qiita-image-store.s3.amazonaws.com/0/358513/ac891078-0ee8-6b96-112c-86d8166fdd2f.png)

## 原因
構築中だったため、セキュリティグループのインバウンドを自社のIPアドレスだけに絞っていた。
CloudFrontは世界中のエッジから接続されるため、HTTPS(or HTTP)のインバウンドをAny(0.0.0.0/0)で開放する必要がある。
外部公開したくない場合は、WAFによって制御する。[[参考]](https://qiita.com/Yuki_BB3/items/3bca17836a43ea678450)
（または、CloudFrontのエッジサーバのIPアドレスを自動登録する仕組みを作成する [[参考]](https://docs.aws.amazon.com/general/latest/gr/aws-ip-ranges.html)）

# 次
To be continued.
(他にもいっぱいあった気がしますが、CloudFrontのdeployが完了しました)
:nth-childにおけるeven, oddの挙動の整理

#はじめに
HTMLを書く場合に偶数番目、奇数番目の要素に独自の装飾をするのに便利な:nth-child(even)や:nth-child（odd）の動作を整理した。

#本題
## 表示に使うCSS
文字色が青で、偶数の場合は赤になる

```css
.list {
  color: blue;
}

.list:nth-child(even) {
 color: red;
}

.list2 {
  color: aqua;
}
```

## まずは基本の書き方
偶数要素の文字色を赤にする0からカウントされる

```html
<ul>
  <li class='list'>0</li>
  <li class='list'>1</li>
  <li class='list'>2</li>
  <li class='list'>3</li>
</ul>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/5390/d3874b96-6513-93a6-0c8f-a05030223407.png)

## タグは同じだけどクラスが違う場合
1番目の要素のクラスを別のものにしても、兄弟要素の数は変わらないので２番目の要素に.list:nth-child(even)が適用される

```html
<ul>
  <li class='list2'>0</li>
  <li class='list'>1</li>
  <li class='list'>2</li>
  <li class='list'>3</li>
</ul>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/5390/1e1649b7-90b8-2bd8-45a6-d998ae081b0b.png)

## 間に別のタグを挟んだ場合
兄弟要素は同じタグのものだけ見る。間に別のタグを挟んでしまうと偶数奇数のカウントはリセットされる

```html
<ul>
  <li class='list'>0</li>
  <p>間の要素</p>
  <li class='list'>1</li>
  <li class='list'>2</li>
  <li class='list'>3</li>
</ul>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/5390/e8702dc1-10b8-f9f5-ac8f-faaa354c1351.png)


今回のサンプルコードはこちら
https://jsfiddle.net/kon_yu/9p8qzbjc/13/
OpenCV+ AI Yoloで飲食店でのクーポンアプリ


ONETECH クーポンアプリ（OpenCV+ AI Yolo)

バインミーバーバーの看板を読み取り、クーポン券やWEBサイトを表示！


いままでのクーポンアプリとの違いは、ビーコンやマーカーの読み取りではなくAI Yolo + OpenCV で実行しています。バインミーバーバー の画像データを５０枚ほど教師データとしてAI Yoloでディープラーニング。

  ![AI_Yolo_OpenCV_onetech_demo.jpg](https://qiita-image-store.s3.amazonaws.com/0/332191/056bcfe7-e196-c469-e21c-f7ce07f937f6.jpeg)
OpenCV+ AI Yoloで飲食店でのクーポンアプリAI Yolo + OpenCV

周囲が薄暗くなっても読み取れました。

Video: https://www.youtube.com/watch?v=qedx6o4gvfA

今後の進化としては、アプリから複数の写真を教師データとしてサーバへ送り[AI Yolo](https://onetech.jp/news-detail/OpenCV-AIYoloで飲食店でのクーポンアプリ/175)でディープラーニングで処理し、AIロジックだけアプリ側に格納してクーポンアプリを実行する。

 

CMSで画像データ（教師データ）、店舗、GPS、URL、クーポンなどのメタ情報を登録し、アプリ完結でクーポンアプリが作れます。
ONETECH ASIA ベトナムオフショア開発で作成しました。
[Read more](https://onetech.jp/news-detail/OpenCV-AIYoloで飲食店でのクーポンアプリ/175)

ちなみにバインミーバーバーは、弊社のグループ会社です。

 

応用に関して気軽に問い合わせください。
MeCab Jupyterで形態素解析をして名詞のみをリストアップした

# まずは試しに解析してみる

```python
import MeCab as mc
tagger = mc.Tagger('')
results = tagger.parse('列島縦断 鉄道乗りつくしの旅～JR20000km全線走破～ダイジェスト')
print(results)

# 列島	名詞,一般,*,*,*,*,列島,レットウ,レットー
# 縦断	名詞,サ変接続,*,*,*,*,縦断,ジュウダン,ジューダン
# 鉄道	名詞,一般,*,*,*,*,鉄道,テツドウ,テツドー
# 乗り	名詞,接尾,一般,*,*,*,乗り,ノリ,ノリ
# つくし	名詞,一般,*,*,*,*,つくし,ツクシ,ツクシ
# の	助詞,連体化,*,*,*,*,の,ノ,ノ
# 旅	名詞,サ変接続,*,*,*,*,旅,タビ,タビ
# ～	名詞,サ変接続,*,*,*,*,*
# JR	名詞,一般,*,*,*,*,*
# 20000	名詞,数,*,*,*,*,*
# km	名詞,一般,*,*,*,*,*
# 全線	名詞,一般,*,*,*,*,全線,ゼンセン,ゼンセン
# 走破	名詞,サ変接続,*,*,*,*,走破,ソウハ,ソーハ
# ～	名詞,サ変接続,*,*,*,*,*
# ダイジェスト	名詞,サ変接続,*,*,*,*,ダイジェスト,ダイジェスト,ダイジェスト
# EOS
```

文字列形式でアウトプットされ、tabやら改行やら、カンマなどいろいろ区切り文字があるのでめんどくさそう。

ちなみに名詞は名詞でも英語(ローマ字)は以下のように、カンマの区切りの数も変わるよう

```python
tagger = mc.Tagger('')
results = tagger.parse('NHK紅白歌合戦')
print(results)

# NHK	名詞,固有名詞,組織,*,*,*,*   　　　　　　　　　 <= カンマ6個
# 紅白	名詞,一般,*,*,*,*,紅白,コウハク,コーハク　　　　 <= カンマ8個
# 歌合戦	名詞,一般,*,*,*,*,歌合戦,ウタガッセン,ウタガッセン　<= カンマ8個
# EOS
```

# 名詞だけ抽出してみる
## 簡単な処理の順番
処理の順番的には、
### ①形態素解析
### ②改行で分割
### ③tabで分割

```
2つに別れる
["紅白","名詞,一般,*,*,*,*,紅白,コウハク,コーハク"]
```

### ④後半をさらにカンマで分割

```
['名詞','一般','*','*','*','*','紅白','コウハク','コーハク']
```

### ⑤上記リストの始まりが名詞であれば、名詞リストに追加

## ソースコード

```python
# 名詞を抽出
def extractNoun(text):
    tagger = mc.Tagger('')
    results = tagger.parse(text)
    keywords = []
    keywords_kana = []
    for r in results.split('\n'):
        cols = r.split("\t")
        if len(cols) >= 2:
            parts = cols[1].split(",")
            if parts[0].startswith("名詞"):
                keywords.append(cols[0])
                if len(parts) > 7
                    keywords_kana.append(parts[7])
    return keywords, keywords_kana
```

# 色々試してみた

```python
list = [
    'NHKニュース',
    '生活の知恵',
    'ピーマン袋',
    '生活ほっとモーニング',
    '土曜元気市',
    'お元気ですか日本列島',
    '経済羅針盤'
]

for name in list:
    keyword, kana = extractNoun(name)
    print('○' + name)
    print('名詞  : ' + ','.join(keyword))
    print('カナ   : ' + ','.join(kana))


# ○NHKニュース
# 名詞  : NHK,ニュース
# カナ   : ニュース
# ○生活の知恵
# 名詞  : 生活,知恵
# カナ   : セイカツ,チエ
# ○ピーマン袋
# 名詞  : ピーマン,袋
# カナ   : ピーマン,ブクロ
# ○生活ほっとモーニング
# 名詞  : 生活,モーニング
# カナ   : セイカツ,モーニング
# ○土曜元気市
# 名詞  : 土曜,元気,市
# カナ   : ドヨウ,ゲンキ,シ
# ○お元気ですか日本列島
# 名詞  : 元気,日本,列島
# カナ   : ゲンキ,ニッポン,レットウ
# ○経済羅針盤
# 名詞  : 経済,羅針盤
# カナ   : ケイザイ,ラシンバン
```

# 最後に
次回は実際に名詞が羅列されたcsvやエクセルを読み込んで
いい感じにDataFrameにするところまでやりたい
【rspec】APIモードで404 Not Foundをjsonで返す時のテストについて

#APIモードで404 Not Foundをjsonで返す時のテストについて

存在しないプロジェクトのページにアクセスしたら、404 not foundのページを返すテストを書いていた。

しかし、今回はAPI仕様なのでhtmlで404を返してはいけない。

そのため、「APIモードでは、存在しないprojectにアクセスしてきたら、status404を返すだけで良い」という結論。

そもそも論だった。

```
expect(response).to have_http_status :not_found
```

もしくは、

```
expect(response.status).to be 404
```

というテストを書くだけで良い！（この２つは同義）

**have_http_statusは、rspecのマッチャー。（eq等と同じ）**
https://www.masalog.site/entry/2018/07/26/214211

このhave_http_statusにHTTPステータスを引数（シンボル）で渡せば、引数のステータスが返せる。

HTTPステータスコード一覧
https://blog.toshimaru.net/rails-http-status-symbols/

###success
:okは２００番

###client error
:not_foundは４０4番

###server error
:internal_server_errorは５００番

そしてこの２つは同義。

```
expect(response).to have_http_status :ok
```

```
expect(response.status).to be 200
```
URLのクエリパラメタを取得する（IE11対応）

# やりたいこと

現在の表示しているwebページのURLからクエリパラメタを取得したいとします。

コード例は ↓にアクセスしたときの結果です。
https://example.com?hello=こんにちは&bye=さようなら
CodePen置いておきます。https://codepen.io/anon/pen/YBdvye

# 方法1: モダンブラウザの場合

[URL#searchParams](https://developer.mozilla.org/ja/docs/Web/API/URL/searchParams) を使います。

```js
const params = (new URL(window.location)).searchParams;
console.log(params.get('hello')); // "こんにちは"
console.log(params.get('bye'));   // "さようなら"
console.log(params.get('hoge'));  // null
```
返却されるのは plaing Object ではなく `URLSearchParams` なので、`get`メソッドを通してパラメタ値を取得します。

↓ここにあるように、IE11では利用できません。
https://developer.mozilla.org/en-US/docs/Web/API/URL#Browser_compatibility

# 方法2: Internet Explorer 11 (IE11) の場合

[URI.js](https://github.com/medialize/URI.js) を使います。

**ライブラリの取得**

* Bowerやnpmといったツールを使う → [GitHub の README](https://github.com/medialize/URI.js)
* 必要なコンポーネントのみダウンロード → [build tool](http://medialize.github.io/URI.js/build.html) 
* CDN → https://cdnjs.com/libraries/URI.js/

**使い方**

```js
var uri = new URI(window.location);
var params = uri.query(true);
console.log(params['hello']); // "こんにちは"
console.log(params['bye']);   // "さようなら"
console.log(params['hoge']);  // undefined
```

`URI#query` の引数を `true` にすると Object 型で返ってきます。それ以外はクエリパラメタの文字列そのもの（`hello=こんにちは&bye=さようなら`）が返ってきます。
http://medialize.github.io/URI.js/docs.html#accessors-search

# 不採用

* `split('&')` とか使う・正規表現を使う
    * イレギュラーなケースを考えたくないので不採用
* [purl.js](https://github.com/allmarkedup/purl)
    * README.md にあるように、メンテナンスされていません
プロジェクトの振り返りで見えた反省点

新規のプロジェクトを進めたときの反省メモがありましたので、まとめてみました。

# 既存踏襲という言葉に注意 
仕様決めのときに既存のサイトの流用や踏襲という言葉が出るが、何を指しているのかわからない。 
あるあるですね。 なにをもって要件を満たしているか判断ができないので、ちゃんと要件をつめましょう。 

# 学習、習熟コストの考慮 
既存の利用している技術から新規技術を採用して場合、パフォーマンスを発揮できるまでに期間がかかるので、可能な限り習熟期間を設けて見ましょう。 
いきなりハイパフォーマンスが出る人は別として、一般論としては最初はパフォーマンスが発揮できず、後半にパフォーマンスが上がる曲線になるはずです。 
習熟度を度外視して、タスクを機械的に算出、割り当てすると、初期のWBS上進捗がわるく見えるため進捗報告時に苦労します。自分は苦労しました。 

# 単体テストを作る 
ソース修正によりのデグレが発生しないことがある程度担保できるようになります。 
副次的な利点として、テストを意識したコードになり、シンプルになります。 
テストかけない、書きにくいとなったら要注意。 
複雑である、前提条件があるなどの要因が考えられます。 
シンプルにできないかを再検討しましょう。
509. Fibonacci Number

**Easy,
Array.**


The Fibonacci numbers, commonly denoted F(n) form a sequence, called the Fibonacci sequence, such that each number is the sum of the two preceding ones, starting from 0 and 1. That is,

F(0) = 0,   F(1) = 1
F(N) = F(N - 1) + F(N - 2), for N > 1.
Given N, calculate F(N).

 

Example 1:

```
Input: 2
Output: 1
Explanation: F(2) = F(1) + F(0) = 1 + 0 = 1.
```

Example 2:

```
Input: 3
Output: 2
Explanation: F(3) = F(2) + F(1) = 1 + 1 = 2.
```

Example 3:

```
Input: 4
Output: 3
Explanation: F(4) = F(3) + F(2) = 2 + 1 = 3.
```

#### Answer

java

```
class Solution {
    public int fib(int N) {
        if(N==0) return 0;
        if(N<=2)  return 1;
        return fib(N-1)+fib(N-2);
    }
}
```
ブレークポイントを貼らずにアニメーション処理などの途中で画面を一時停止させる方法

## 概要
ビルドされたファイルが難読化されてたりすると該当部分がよくわからないことがあり、ブレークポイントを貼るのに時間がかかったりする。

そんなときはアニメーション処理のコードの途中に

```javascript
debugger;
```

を書けばGoogle Chromeのデベロッパーツールが画面を停止させてくれる。アニメーション中の細かい位置などを確認したいときにおすすめ。

## 出典
[コードをステップ実行する方法  |  Tools for Web Developers  |  Google Developers](https://developers.google.com/web/tools/chrome-devtools/javascript/step-code?hl=ja)

```
onClick が呼び出されるたびに、f という関数が呼び出され、スクリプトは強制的に debugger キーワードで一時停止されます。
```
git clone から rails s までの5ステップ

（ほぼ自分用メモです）

新規ではなく、動くものがすでGitHubにあがっているRailsプロジェクトをcloneしてローカルで動かすための5ステップ。
ローカルにRails自体が動く環境ができている＝Yay! You're on Rails!が表示できる状態であることが前提。
gitコマンドが使える状態なのも前提。

```
$ git clone https://github.com/<user_name>/<project_name>.git
$ cd <project_dir>
$ bundle install
$ bin/rails db:migrate
$ bin/rails s
```