OmniAICreator/Qiita-1.07M huggingface dataset:
Railsのparamsはキーの型に関係なく値を取り出すことができる


###この記事で紹介すること

`params`は`Hash`ではなく`ActionController::Parameters`のインスタンスのため、キーの型が`String`か`Symbol`かを区別することなく値を取ってくることができます。

###開発環境
ruby2.5.1
rails5.2.1

###paramsはキーがStringかSymbolかを区別しない

rubyでは、`Hash`はキーの型を区別するため、以下のように動作します。

```ruby
#rubyでは...

h = { :last_name => "佐藤", "first_name" => "太郎" }

#キーに指定した要素の型で値を取ってくることができる
h[:last_name]   #=> "佐藤"
h["first_name"] #=> "太郎"

#指定した要素とは違う型で値を取ってくることはできない
h["last_name"] #=> nil
h[:first_name] #=> nil

```

ところが、railsの`params`は`ActionController::Parameters`のインスタンスであり、`Hash`の機能が拡張されているためキーの型に関係なく値を取ってくることができます。

```ruby
#railsで受け取ったparams
params
　　=> <ActionController::Parameters {"last_name"=>"佐藤", "first_name"=>"太郎"}>

#paramsの見た目はHashだが、ActionController::Parametersのインスタンス
params.class
　　=> ActionController::Parameters

#キーの型に関係なく値を取ってくることができる！
params["last_name"]  #=> "佐藤"
params["first_name"] #=> "太郎"
params[:last_name] #=> "佐藤"
params[:first_name] #=> "太郎"

```

###追記　paramsの型をHashに変換するには？
以下、この記事を読んでいただいた経験豊富なエンジニアの方から教わった知見です。
マスアサインメントによる事故を防ぐためにRails4以降ではparamsを直接`Hash`に変換することは出来なくなっています。

```ruby
#適当にparamsのようなインスタンスをつくる
pry(main)> params = ActionController::Parameters.new(:hoge => :huga, 'foo' => 'bar')
 => <ActionController::Parameters {"hoge"=>:huga, "foo"=>"bar"} permitted: false>

#外部から入力できるparamsのマスアサインメントによる事故を防ぐために
#そのままではハッシュにならない（Rails4よりも前のバージョンではこれでも変換できた）
pry(main)> params.to_h
 => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash

#明示的に許可したものだけハッシュになる
pry(main)> params.permit(:hoge).to_h
 => Unpermitted parameter: :foo  　　# :foo は許可されないため捨てられる
 => {"hoge"=>:huga}              　　# :hogeは許可されるためハッシュ化する

pry(main)> params.permit(:hoge, :foo).to_h
　　=> {"hoge"=>:huga, "foo"=>"bar"} # 全てハッシュになる

#危険なのを分かっていて、無理やりハッシュにしたい時
# やりかた１
pry(main)> params.to_unsafe_h
　　=> {"hoge"=>:huga, "foo"=>"bar"}

# やりかた２
pry(main)> params.permit!
　　=> <ActionController::Parameters {"hoge"=>:huga, "foo"=>"bar"} permitted: true>
pry(main)> params.to_h
　　=> {"hoge"=>:huga, "foo"=>"bar"}

```


参考サイト
・ActionController::Parametersの内部実装など
https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/strong_parameters.rb
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/hash_with_indifferent_access.rb

・マスアサインメントについて
https://railstutorial.jp/chapters/sign_up?version=4.2#sec-strong_parameters
https://railsguides.jp/action_controller_overview.html#strong-parameters
sublime text 3 のtable editor で日本語を使った時のインデントをそろえる設定

# 設定方法
というか[公式のGitHubページ](https://github.com/vkocubinsky/SublimeTableEditor#cjk-support)に載ってました。

1. Preferences → Settings を押下
2. 別ウィンドウで設定画面が開くので、以下のように'font_face'を設定
![table editor font_face.PNG](https://qiita-image-store.s3.amazonaws.com/0/145181/9f68dd0b-f291-c39f-d2cc-5531f769db69.png)
3. ctrl+s で保存

すると、以下のように日本語でもキレイに整形してくれます
![after save font_face.PNG](https://qiita-image-store.s3.amazonaws.com/0/145181/c94abc6b-66c5-9a5a-43b6-6e73d313fb37.png)

選べるフォントの例として以下が上がっていました。
- NSimSum
- FangSong
- SimHei

NSimSunは画像内でも使用している通り、ちょっと特徴的な見た目です。
FangSong, SimHeiは普通の見た目でした。
そのほかのCJK言語のフォントは試していませんが、こだわる人は探してみてはいかがでしょうか。
Spacemacsに乗り換えてみた（４）ウェブ制作編

# はじめに

- ウェブ制作に欠かせない``web-mode``周りについて設定した
- ``emmet-mode``についても調べてみた


# ``html``レイヤーを追加した

[htmlレイヤーのドキュメント](http://spacemacs.org/layers/+lang/html/README.html)を読むと以下のパッケージが追加される

1. [web-mode](http://web-mode.org/)
2. [emmet-mode](https://github.com/smihica/emmet-mode)
3. [evil-matchit](https://github.com/redguardtoo/evil-matchit)
4. [slim-mode](https://github.com/slim-template/emacs-slim)
5. [jade-mode](https://github.com/brianc/jade-mode)

この中の``web-mode``を使えるようにした


# ``web-mode``の設定

- [web-modeのウェブサイト](http://web-mode.org/)を読みながら、必要だと思った設定を``dotspacemacs/user-config()``に追記した

```emacs-lisp:dotspacemacs/user-configにweb-modeの設定を追記
(defun dotspacemacs/user-config ()
  ...
  ;; web-mode
  (setq web-mode-enable-comment-interpolation t)
  (setq web-mode-enable-current-element-highlight t)
  (setq web-mode-enable-current-column-highlight t)
  ...
  )
```

## ``web-mode-enable-comment-interpolation``

- ソースのコメント内で``TODO``や``FIXME``などのキーワードを使ったときに強調表示される
- あんまり使わないかもしれないが、たぶんあると便利だと思ってONにした

## ``web-mode-enable-current-element-highlight``

- カーソルのあるHTMLタグ名をハイライトする

## ``web-mode-enable-current-column-highlight``

- カーソルのあるHTMLのタグのブロックの列をハイライトする
- 上の説明だとよくわからないけれど、とても便利なので設定すべき

# ``web-mode-whitespace-show``

- [web-modeのウェブサイト](http://web-mode.org/)によると``C-c C-w``で空白文字の表示／非表示（``web-mode-whitespace-show``）をトグルできると書いてあるが、``Spacemacs``では``eyebrowse``に割り当てられている
- [るびきちさんのeyebrowse.el紹介の記事](http://emacs.rubikitch.com/eyebrowse/)を読むと、``eyebrowse``のキー割り当てのお行儀が悪いためらしい。記事を参考に、``eyebrowse-keymap-prefix``を``C-c w``に変更した
- この設定は``dotspacemacs/user-init()``に書く必要がある（最初に``user-config``に書いてみたが、設定が反映されなかったので、``user-init``に書いたらOKだった）

```emacs-lisp:user-initでプリフィックスを変更
(defun dotspacemacs/user-init ()
  ...
  ;; avoid key-bind conflicts with web-mode
  (setq eyebrowse-keymap-prefix (kbd "C-c w"))
  ...
  )
```

# ``emmet-mode``の設定

-  特に追加で設定することはない
-  入力するときの省略ルールを覚える必要がある
-  詳しくは[emmet-mode](https://github.com/smihica/emmet-mode)の``Usage``を読む
- ``web-mode``で``(setq web-mode-enable-auto-expanding t)``にした場合の上位互換な動作をするようなマイナーモード（``web-mode-enable-auto-expanding``はデフォルトでは``nil``になっている）


# ``evil-matchit``の設定

- 特に追加で設定することはない
- ``%``でタグ移動ができる（``web-mode``の``C-c C-n``と同じカーソル動作）

# 目次

1. [Spacemacsに乗り換えてみた（１）導入編](https://qiita.com/shotakaha/items/da1282327f0dbc1b6289)
2. [Spacemacsに乗り換えてみた（２）キーバインド編](https://qiita.com/shotakaha/items/bba69546c6cd43ed4927)
3. [Spacemacsに乗り換えてみた（３）レイヤー編](https://qiita.com/shotakaha/items/364fca7d09596d636a8b)
4. [Spacemacsに乗り換えてみた（４）ウェブ制作編](https://qiita.com/shotakaha/items/dcd11c3afade2f0efb49)
5. [Spacemacsに乗り換えてみた（５）メーラ編](https://qiita.com/shotakaha/items/e2ba10457fa9b8d6e895)
6. Spacemacsに乗り換えてみた（６）LaTeX編（予定）
docker環境でvue.jsとfirebaseを構築してみた

#概要
docker環境でのfirebaseの構築、ローカルでのvue + firebaseの構築方法などはあるがdocker環境でのvue + firebase構築は見当たらなかったので備忘録も兼ねて。
まあ対してvueは関係なかったりする。

#環境
mac OS v10.13.6
docker for mac v16.06.1

#Dockerfile
```
FROM node:8.11.3-alpine

WORKDIR /app

RUN apk update && \
    apk add git && \
    npm install -g npm && \
    npm install -g vue-cli && \
    npm install -g firebase-tools

CMD ["/bin/sh"]
```

#つまづいた点
##localhost:9005に入れない
コンテナ内でfirebase login叩いた後に出るURLに飛んでgoogleアカウントの認証をするが、その後飛ばされるlocalhost:9005はdockerに9005ポートが設定されてなければ失敗する。
なので以下を叩くようにすればポートの設定は不要になる。

```
firebase login --no-localhost
```

これを叩くとアカウントの確認を行った後にコードが貰えるので、それを入れて認証完了。

```
/app # firebase login --no-localhost
? Allow Firebase to collect anonymous CLI usage and error reporting information? Yes

Visit this URL on any device to log in:
https://accounts.google.com/o/oauth2/xxxxxxxx

? Paste authorization code here: code
✔  Success! Logged in as xxxxxx@gmail.com
```

##認証完了してるのにpermission deniedが出る
firebaseのコンソールからデータベース→ルール
以下に変更する。

```
{
  "rules": {
    ".read": true,
    ".write": true
  }
}
```
python3でDBにデータを保存する（with PostgreSQL and psycopg2）

# この記事について
　[前回の記事](https://qiita.com/yokotate/items/e91aadbdf9e18b40b832)にてpsycopg2をインストールしました。
　なので今回はそれを利用してDBにデータを保存してみようと思います。
　圧倒的初心者記事ですがご容赦ください。

# 関連記事
 [ANACONDA NAVIGATORを使って仮想環境を作ってpsycopg2を入れる](https://qiita.com/yokotate/items/e91aadbdf9e18b40b832)

# 環境
　Python3
　Anaconda

# ソースコード
### 使用準備

```python:postgres.py
import psycopg2
```
まずはインストールしたpsycopg2をインポートします。
これで使用準備はOK。

### 接続用ステータス設定
```python:postgres.py
path = "localhost"
port = "5432"
dbname = "test"
user = "postgres"
password = "password"
```
次に接続用のステータスを設定していきます。
今回はローカル（自分のPC）上に環境を用意していますのでPATHはlocalhost。
もしネットワーク上の別PCだったりクラウド上に存在するDBの場合にはそのpathに書き換えます。
portはpostgreSQLだと5432がデフォルトです。

dbnameで迷ってしまうかもしれませんが下の画像の赤枠で囲まれた箇所の名前です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296240/eab179c8-13dd-c064-1b5f-116d2bafeaef.png)
userとpasswordについてはPostgreSQLをインストールした際に自身で設定したものを入力してください。
これで接続先の設定は終了です。

### 接続部分

```python:postgres.py
conText = "host={} port={} dbname={} user={} password={}"
conText = conText.format(path,port,dbname,user,password)
```
次に先ほど設定した値を使用して実際に接続を行います。
conText.format(path,port,dbname,user,password)の部分はその上の"host={} port={} dbname={} user={} password={}"
の{}の置き換えを前から順番に行っています。
文字列の途中に変数を入れる際の方法の一つです。

```python:postgres.py
connection = psycopg2.connect(conText)
cur = connection.cursor()
```
実際に繋いでみます。
psycopg2.connect(conText)の部分で実際に繋いでみるのですが、もし入力が間違っていた場合以下のエラー文が出力されます。

```txt:exception.txt
Traceback (most recent call last):
  File ".\test.py", line 12, in <module>
    connection = psycopg2.connect(conText)
  File "E:\anaconda\lib\site-packages\psycopg2\__init__.py", line 130, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
psycopg2.OperationalError
```
curは実行するためのエリアです。
例えばSLECT文などでデータを取得してきた場合にはここにデータが収録されます。

### テスト用のテーブル準備
次にSQLを実際に実行してみましょう。
まずテストのためにテーブルを用意します。

```sql:Test.sql
CREATE TABLE TEST(
    id SERIAL,
    name text,
    nedan numeric(15,4)
);
```
SERIALは自動付番です。

### DBにデータを保存
それでは今回の本題。
DBにデータを保存してみようと思います。

```python:postgres.py
sql = "insert into test(name,nedan) values('リンゴ',100);"
cur.execute(sql)
connection.commit()
```
今回はsql変数を用意していますが、cur.execute(sql)の部分に直接入力しても大丈夫です。
cur.execute(sql)で実行しているのですが、これでは保存されておらず、その次の文章のconnection.commit()でDBにコミットされます。
これはPostgreSQLの設定でAuto CommitがデフォルトでOFFになっているためです。autocommitをTrueにすればこの文章は不要になります。


### DBに保存されたデータを確認
SQLを実行したことで下の図のようにデータが保存できているはずです。
ですのでここではちゃんと保存できていることを確認してみましょう。

|id |name|nedan|
|---|---|---|
|1  |リンゴ  |100  |

次にこのテーブルを取得してくるSQLをPythonのコード内に組み込んで実行してみます。

```python:postgres.py
sql = "SELECT * FROM TEST"
cur.execute(sql)
```
以上によりSELECT文が実行され、その結果がcurの中に保存されました。
試しに取り出してそれを出力してみます。

```python:postgres.py
print(cur)
```

```text:test_sql.txt
<cursor object at 0x0000016267A4E208; closed: 0>
```
実はこれを実行してもだめなんです。
よくわからない文字列が出力されるだけです。
for文を使用して１行ずつ取り出して表示していきます。

```python:postgres.py
for row in cur:
    print(row)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296240/5f30f350-4ecc-52b4-7400-54425829c8b4.png)
はい、今度はちゃんとデータが保存できていることを確認できましたね！
これにて今回の記事を終了とさせていただきます。
ありがとうございました。
固定IP設定

テキストファイルから対象のPCを検索して
対応するIPアドレスを設定する

<ip.txt>の内容
pcname   ip
------   --
test1,10.189.192.3
test2,1.1.1.1
DESKTOP-JL63VBE,192.168.0.200


<設定するパソコンのホスト名をテキストファイルから検索してIPを表示>
$array1=Get-Content .\ip.txt | Select-String $hname
$s=$array1 -split(",")
$n=@($s)
$n[1]
192.168.0.200

静的ip削除
Remove-NetIPAddress -InterfaceIndex 11 -IPAddress "192.168.0.100" -DefaultGateway "192.168.0.1"
※Get-NetAdapterで表示されたifIndex Statusの値

静的DNS削除
Set-DnsClientServerAddress -InterfaceIndex 11 -ResetServerAddresses

静的IP設定
New-NetIPAddress -InterfaceIndex 11 -IPAddress "192.168.0.200" -AddressFamily IPv4 -PrefixLength 24 -DefaultGateway "192.168.88.1"
静的DNS設定
Set-DnsClientServerAddress -InterfaceIndex 11 -ServerAddresses "192.168.88.1"

<ip設定>
New-NetIPAddress -InterfaceIndex 11 -IPAddress $n[1] -AddressFamily IPv4 -PrefixLength 24 -DefaultGateway "192.168.0.1"


IPAddress         : 192.168.0.200
InterfaceIndex    : 11
InterfaceAlias    : Wi-Fi
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 24
PrefixOrigin      : Manual
SuffixOrigin      : Manual
AddressState      : Tentative
ValidLifetime     : Infinite ([TimeSpan]::MaxValue)
PreferredLifetime : Infinite ([TimeSpan]::MaxValue)
SkipAsSource      : False
PolicyStore       : ActiveStore

IPAddress         : 192.168.0.200
InterfaceIndex    : 11
InterfaceAlias    : Wi-Fi
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 24
PrefixOrigin      : Manual
SuffixOrigin      : Manual
AddressState      : Invalid
ValidLifetime     : Infinite ([TimeSpan]::MaxValue)
PreferredLifetime : Infinite ([TimeSpan]::MaxValue)
SkipAsSource      : False
PolicyStore       : PersistentStore



Set-DnsClientServerAddress -InterfaceIndex 11 -ServerAddresses "192.168.0.1"
Pythonでパーセンタイル値を計算をする


# 概要
Pythonでパーセンタイル値の計算をします。

パーセンタイルの明確な定義無いため実装方法も複数あるようですが、計算方法が違っていても、大量のデータで計算した場合有意な差にはならないとのこと。

今回は下記のサイトを参考に実装しました。また、numpyを用いた方法も紹介します。
http://marketer-thinking.com/statistics/data2.html

# 実装

```python

def calc_pt(values, pt):
    """
    パーセンタイル値を計算する
    """
    import math
    # 求めるパーセンタイル値がリストの何番目の要素か
    order = (len(values) + 1) * (pt / 100)
    # 小数部と整数部に分ける
    f, i = math.modf(order)
    sorted_vals = sorted(values)
    # math.modf()はfloatで結果が返るのでキャスト
    i = int(i)
    return sorted_vals[i-1] + f * (sorted_vals[i-1] - sorted_vals[i])


def calc_pt_numpy(values, pt):
    """
    numpyでパーセンタイル値を計算する
    """
    import numpy
    return numpy.percentile(numpy.array(values), pt)


def main():
    """
    メイン処理の実行
    """
    import random
    for n in [100, 10000, 1000000]:
        values = []
        for _ in range(n):
            values.append(random.uniform(0.0, 100.0))

        # パーセンタイル値を計算
        for pt in [50, 80, 90, 99]:
            my_pt = calc_pt(values, pt)
            numpy_pt = calc_pt_numpy(values, pt)
            print("n={}, my_pt={}, numpy_pt={}, ratio={}".format(
                n, my_pt, numpy_pt, my_pt/numpy_pt
            ))
        print()


if __name__ == '__main__':
    main()

```

## 実行結果

```
n=100, my_pt=59.334260375137355, numpy_pt=59.41420584791042, ratio=0.9986544384186888
n=100, my_pt=83.55682075034058, numpy_pt=83.73113216533889, ratio=0.9979182006681324
n=100, my_pt=86.45906782186731, numpy_pt=89.49530919428327, ratio=0.9660737372746022
n=100, my_pt=97.24633378796958, numpy_pt=98.2281366779185, ratio=0.9900048710771318

n=10000, my_pt=49.94757837390801, numpy_pt=49.95727347919067, ratio=0.999805932057387
n=10000, my_pt=80.35364111790138, numpy_pt=80.35485783190325, ratio=0.9999848582396298
n=10000, my_pt=90.1259765722587, numpy_pt=90.15243353511485, ratio=0.9997065307965775
n=10000, my_pt=98.96393575713691, numpy_pt=98.9824941131185, ratio=0.9998125087052223

n=1000000, my_pt=49.985451493835484, numpy_pt=49.98563688434545, ratio=0.9999962911243804
n=1000000, my_pt=80.01341181661982, numpy_pt=80.01344482978872, ratio=0.9999995874047296
n=1000000, my_pt=90.00047774373063, numpy_pt=90.00065066573823, ratio=0.9999980786582505
n=1000000, my_pt=98.99860932658436, numpy_pt=98.99886918947561, ratio=0.999997375092328

```


numpyで計算したパーセンタイルと一致しませんが、nが大きくなるほど、差異が小さくなっていることがわかります。


# 疑問

データ数とパーセンタイルによっては、リストのインデックスを超えることになるが、どうすれば良いのか。

例えば、今回の実装ではデータ数が10でパーセンタイルが99を求めることができない。
Linux コマンド２ (cat,grep)

#cat -concatenate-
~~~
$ cat [オプション] ファイルパス
~~~
ファイルの内容を出力し、確認することができます。
しかしGUIが入った環境でなかったりすると長文のテキストが書かれたものが見にくいので、表示だけに関しては他コマンドの`more`や`less`を使って表示することが多いかもしれません。
 
 - オプション
   + `-n`  
次のように左に行数が出力されます。

~~~
1 aaa
2 bbb
3 ccc
...
~~~
ただ出力して使うことより、cat-concatenate-(連結)とあるようにXとYのファイルを連結して新しいファイルを作成する`>`「リダイレクト」や、XにYの内容を追記する`>>`「アペンド」を使うことが多いみたいです。
**リダイレクション**や**パイプ**の説明は別途記事にしようと思います。

~~~
$ cat X.txt Y.txt > Z.txt
$ cat Y.txt >> X.txt
~~~

リダイレクト結果 : `X.txt`,`Y.txt`がそのまま残って、XにYを追記した`Z.txt`作成。
アペンド結果 : XにYの内容を追記したものを`X.txt`に上書き,`Y.txt`はそのまま。
リダイレクトの`Z.txt`とアペンドの`X.txt`の中身は同じです。
###more、less
~~~
more ファイル名
less ファイル名
~~~
前述で話した通り、ファイルを表示するコマンドで`cat`と違ってページング機能があります。

 - `more`  
一定の量をページとして分けて表示し、次ページに飛ぶには「スペース」キー、ページ戻りは「b」キーで操作します。
最後のページで「スペース」キーを押すと終了となります。
 - `less`  
`more`との違いは上下にスクロールできるページング機能なことです。
「q」キーを押すと終了になります。

#grep
~~~
$ grep [オプション] 検索条件 ファイルパス
~~~

`cat`は指定したファイルの内容を出力でしたが、こちらはその中の文字列を探し出しそこだけを出力します。
検索条件には**正規表現**を用いることができます。
これも検索内容をリダイレクションやパイプを用いて運用することが多いので簡潔なものだけを紹介します。

~~~
$ grep test sample.txt
~~~

sample.txt内のtestという文字列が入った行が出力されます。
もしtestという文字列がなかった場合エラーがでます。
この「標準出力」ではない「標準エラー出力」はリダイレクトの時に注意が必要となります。

 - オプション
   + `-i`  
検索条件とファイル双方で、英大文字の区別を行わない。（A=a）  
   + `-v`  
検索条件とマッチしなかった行を選択する。

###正規表現

文字列のパターンを表現する表記法。
よく使いそうなものをいくつか。

   + `^`  
 行の先頭。
   + `.`  
 任意の一文字。  
 `ca.`で検索をするとcat、car、capなどが対象となる。
   + `*`  
 直前の文字の0回以上繰り返し。  
 `ca*t`で検索するとct、cat、caaaatなどが対象となる。
   + `+`  
 直前の文字の1回以上の繰り返し。  
 `ca+t`で検索するとcat、caaaatなどが対象となる。
   + `?`  
 直前の文字は省略可能。  
 `bes?t`で検索するとbetまたはbestが対象となる。
   + `[A-Z]`  
 AからZまでの1文字。  
   + `[^A-C]`  
 AからC以外の1文字。
   + `(A|B)`  
 AかBどちらか。 

###エスケープシーケンス  
 文字列の中に制御コードなどを混在させるときに使う特殊記法。
[ ] ( ) < > { } ; & | ^ ? * $ \` ' " \ ! 、改行、タブ、スペースなどが対象。
これらの前に`¥`をつける。
または`""`で囲むと文字列として扱われる。
例外として`""`の中でも$ ' ¥は更に`¥`をつける必要がある。

---
####参考・引用
WEB
[IT用語辞典 e-Words](http://e-words.jp/)
[正規表現とは](http://gimite.net/help/devas-ja/100regex.html)
[Linux die net](https://linux.die.net/man/1/)
Rubyで始めるLIFF API

# はじめにLIFFとは
LIFFとはLINEがリリースしているフロントエンドのフレームワークです。
基本的にはFront周りのAPIなのですが、pathの設定などのめんどくさい部分があります。簡単に登録できるliff_selectorについて説明します。

※今回の記事では[ローカルで始めるLINE bot @Ruby](https://qiita.com/4geru/items/aa076fa57d1913312307)を基にして作成しています。

# liff_selectorの機能
helpで見るとliffは次のような機能を提供しています。
今回は、LIFFアプリのテンプレートを作成する部分までを説明します。

```
 → bundle exec liff_select help
liff_select show                  : display all apps
liff_select same                  : display same url and type apps
liff_select clean                 : delete same url and type apps
liff_select upload _TYPE_ _URL_   : upload new apps with type and url.
                                  : type is <type:compact|tall:|full>
liff_select delete _LIFF_ID_      : delete app _LIFF_ID_ is referenced show number.
liff_select help                  : commands helps
liff_select new _html_name_       : make liff sample html
```

### テンプレートの作成
liff_selectorを使うことにより、シンプルなテンプレートを作成することができます。

```shell
 → bundle exec liff_select create index
> [SUCESS] make ./views/index.erb
```

### liffの登録
LIFFアプリのテンプレートを作成したので、rubyからliffアプリ呼び出す受け口を作成します。

```ruby:app.rb
get '/' do
  erb :index
end
```

LIFFアプリとして、lineで起動させるためには、LINE側へliffアプリのURLを登録する必要があります。

```shell
 → bundle exec liff_select upload tall https://6fd2cf79.ngrok.io
> make liff app
> [SUCCESS] make app
> app uri : line://app/1598664616-30ozn5rM
```

### 登録したLIFFアプリ一覧
登録したアプリは　`show` コマンドを使うことにより簡単に閲覧することができます。

```shell
 → bundle exec liff_select show
id liffId               type    url
1. 1598664616-30ozn5rM  tall    https://6fd2cf79.ngrok.io
```

### 最後に

liff_selectorなら簡単にliffアプリを管理することができます。
Happy LINE LIFE :)

<img src=https://qiita-image-store.s3.amazonaws.com/0/64677/f6fac6f0-bfe3-9f01-66cd-bac54872cd27.png width=200px>
【Rails】 3日後は、3.days.since(time)とtime.since(3.days)、どちらで書くべきか？

### 結論
少なくとも**全体で統一した方が良い**。 こんな感じの使い分けかと考えています。

| `3.days.since(time) `       |   `time.since(3.days)` | 
|:-----------------|:------------------:|
|• 「3daysという**期間**」の意味合いを主張したい。<br>•　英語の「3 days ago」と同じ語順にしたい。| **Timeを主語に**書きたい |

[備考]
[Rails4.2のコード](https://github.com/rails/rails/tree/4-2-stable/activesupport)を参照しましたが、確認した限りRails5でも仕様には変更ないようです。
(コードの変更自体はあります →[参考になる記事](https://techracho.bpsinc.jp/hachi8833/2017_02_14/35055))

### コードレベルで2つを比較する
[paiza.io](https://paiza.io/projects/fGy6GiDa2gOVaBVa-bgWLQ?locale=ja-jp)にコードを置いてあります。

#### はじめに
`since`は[rails/active-support](https://github.com/rails/rails/tree/4-2-stable/activesupport)により提供されている機能です。
まず、そもそも両者は異なるclassというのが大事です。

```ruby
puts 3.days.class # => ActiveSupport::Duration
puts current_time.class # => Time
```

それぞれの`since`の挙動を確認しましょう

#### [Durationの`since`](https://github.com/rails/rails/blob/3804d017333da16d76d9fc6633faf5635c7b03d7/activesupport/lib/active_support/duration.rb#L99)

```rails/activesupport/lib/active_support/duration.rb
# Calculates a new Time or Date that is as far in the future
# as this Duration represents.
def since(time = ::Time.current)
  sum(1, time)
end
alias :from_now :since
```

`since`は、↓の`sum`メソッドを呼んでいるのがわかる。

```rails/activesupport/lib/active_support/duration.rb
def sum(sign, time = ::Time.current) #:nodoc:
  parts.inject(time) do |t,(type,number)|
    if t.acts_like?(:time) || t.acts_like?(:date)
      if type == :seconds
        t.since(sign * number)
      else
        t.advance(type => sign * number)
      end
    else
       raise ::ArgumentError, "expected a time or date, got #{time.inspect}"
    end
  end
end
```

引数のtimeに対して、 値を加算しているのがわかる
`parts`はDurationインスタンス生成時に生成される期間パラメータの格納先であり、例えば`puts 3.days.parts # => {:days=>3}`である。
各期間(dayやmonth,year)をtimeに対して順に加算していく、という挙動をする。

#### [Timeの`since`](https://github.com/rails/rails/blob/3804d017333da16d76d9fc6633faf5635c7b03d7/activesupport/lib/active_support/core_ext/time/calculations.rb#L152)

```rails/activesupport/lib/active_support/core_ext/time/calculations.rb
# Returns a new Time representing the time a number of seconds since the instance time
def since(seconds)
  self + seconds
  rescue
    to_datetime.since(seconds)
  end
alias :in :since
```

コードそのままであり、`time.since()`は引数の秒数を現在時刻に足すことを意味する。
例えば`puts 3.days # => 259200秒`なので、`time.since()`はtime自身に259200秒を足すという挙動をする。
LaravelプロジェクトをCircleCI2.0でUIテストまで行う


# バージョン等

検証したアプリケーションのバージョンを記載しています。


|名称|バージョン|
|:-----|:-------|
|Laravel|5.6.35|
|PHP|7.2.0|

# 概要

- Seleniumのように、自動でUIテストを行いたい
- CI等でもUIテストを行いたい

# 手順

## Github連携


1. https://circleci.com/ でGithubアカウントでログイン後、 `ADD_PROJECT` でリポジトリを追加してください

2. PullRequest等行うと自動でCIが実行されます。 (設定ファイルがなければ実行しません)

## Project設定

1. `dusk` をインストール
	
	```bash
	$ composer install laravel/dusk
	```

2. `/tests/Browser/` にテストケースを追加

3. テストを実行
	
	```bash
	$ php artisan dusk
	```

## CI設定

```yml:[LravelProject]/.circleci/config.yml

# PHP CircleCI 2.0 configuration file

version: 2
jobs:
  build:
    docker:
      - image: circleci/php:7.1-jessie-node-browsers
        environment:
          APP_ENV: circleci
          APP_DEBUG: true
          DB_CONNECTION: sqlite

    working_directory: ~/repo

    steps:
      - checkout

      - run: sudo apt install -y libsqlite3-dev zlib1g-dev
      - run: sudo composer self-update

      - restore_cache:
          keys:
          - v1-dependencies-{{ checksum "composer.json" }}
          - v1-dependencies-

      - run: composer install -n --prefer-dist

      - save_cache:
          paths:
            - ./vendor
          key: v1-dependencies-{{ checksum "composer.json" }}

      - run: touch database/database.sqlite

      - run: php artisan migrate

      - run:
         name: Start Chrome Driver
         command: ./vendor/laravel/dusk/bin/chromedriver-linux
         background: true

      - run:
         name: Run Laravel Server
         command: php artisan serve
         background: true

      - run: php artisan dusk
```

### 解説（一部だけ）

> Chrome Driver の開始

```config.yml
- run:
     name: Start Chrome Driver
     command: ./vendor/laravel/dusk/bin/chromedriver-linux
     background: true
```

> WebServerの開始

```config.yml
- run:
     name: Run Laravel Server
     command: php artisan serve
     background: true
```

> テストの実行

```config.yml
- run: php artisan dusk
```

# 最後に

あとはPushするだけ。

以上
jupyter nbextensionsタブが出ない！ jupyter-notebook5.7.0


jupyter-notebookのnbextensionsの設定タブが出てこないということでissueに上がっていたので日本語用としてメモしておきます。
2018/09/29現在はjupyter-notebookのバージョン5.7.0ではnbextensionsの設定タブが消えている現象が起きています。

[cannot see jupyter nbextension configurator tab #72](https://github.com/Jupyter-contrib/jupyter_nbextensions_configurator/issues/72)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/195174/1f2f035b-b5d8-f373-b0bd-993632e868ef.png)

---

※2019/01/16現在は5.7.4で修正されていることが確認されました。

```
$ pip3 freeze | grep notebook
notebook==5.7.4
$ jupyter-notebook --version
5.7.4
```

---

基本的にjupyterは

```
$ pip3 install --user jupyter
```

などのコマンドでインストールするのですが、jupyter-notebookも最新バージョンの5.7.0がインストールされてしまいます。

```
$ pip3 freeze | grep notebook
notebook==5.7.0
$ jupyter-notebook --version
5.7.0
```

https://github.com/jupyter/notebook

## バージョンを下げる解決法

そこで以下のコマンドでnotebookのバージョンだけ5.6.0にしてやることで解消されます。

```
$ pip3 uninstall notebook                 # 現在のバージョンを削除
($ sudo chown -R $USER:$USER ~/.local    # もしPermissionエラーが出る場合はこのコマンドを実行)
$ pip3 install notebook==5.6.0     # バージョン5.6.0をインストール
```

もし、他のパッケージをpip installでインストールした場合、それによってjupyter-notebookのバージョンがアップグレードされる可能性があります。その際は最後に上のコマンドをもう一度実行してバージョンを5.6.0を戻せば治ります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/195174/4809aab5-deb7-d3ea-c724-44dafab01886.png)


## 直接URLにアクセスする解決法

![image.png](https://user-images.githubusercontent.com/33354327/46385590-ce96a100-c6f7-11e8-88e1-c4313078b996.png)
【.NET】IPv6を直接ファイル名には使えない

# はじめに
アプリケーションの改修作業をしていて、自PCでは動作していたが同僚のPCでは例外エラーが出て動作しなかった。
エラー名は憶えてないが、「cache\comm\fe80::6c2c:7539:7e8a:c350%11.xml」にはアクセスできない旨のエラーであった。

# 原因
キャッシュ用ファイルとしてIPv4のアドレスを想定してファイルを作成しようとしたところ、IPv6のアドレスとなり、ファイル名に使えない文字のコロン(:)が含まれているためエラーとなった。

[ファイル名に使わない方が良い文字](http://www.all.undo.jp/asr/1st/document/01_03.html)

プログラム上ではIPアドレスを取得する際に先頭アドレスを返すようになっていた、自PCではIPv4を優先にするようにしていたため、問題が発生しなかったが、同僚PCはIPv6が返された。

[「IPv6無効設定」はもう古い？IPv6を有効にしたままIPv4の優先順位を上げる設定](https://freesoft.tvbok.com/tips/web/ipv6_ipv4.html)

# 対応
単純に先頭アドレスの取得ではなく、AddressFamily.InterNetworkの条件を入れてIPv4アドレスを返すように修正した。LINQを使ってシンプルに。
[Get IPv4 addresses from Dns.GetHostEntry()](https://stackoverflow.com/questions/1059526/get-ipv4-addresses-from-dns-gethostentry])

```csharp
public static string GetIpAddress() {
    IPAddress ipAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList
                         .FirstOrDefault(a => a.AddressFamily == AddressFamily.InterNetwork);

    return Convert.ToString(ipAddress);
}
```

別の対応としては、IPアドレスにIPv6を返ることも考慮して、ファイル名にする際にコロン(:)を除外してしまう。
cache\comm\fe806c2c75397e8ac350%11.xml

```csharp
return GetIpAddress().Replace(":","") + ".xml";
```

パーセント(%)はファイル名としては使用できます。
ちなみに、IPv6の「%」の後の文字はインターフェイス識別子です。

[いまさら聞けない、IPv6アドレス体系の基礎 (1/2)](http://www.atmarkit.co.jp/ait/articles/1107/19/news122.html)

# 最後に
IPv4アドレスを取得する方法は何番煎じのネタなので別に書かなくてもよかったのですが、別の切り口で書いてみれば、何か発見があるかなと思いました。
プログラミング関連備忘録 書きつくすに新しい動画を入れてデプロイする方法

今回アプリをあげたのはこのURLでした。
https://fathomless-oasis-23087.herokuapp.com/birmingham

新しくYOUTUBEのプレイリストをもらったので、それをアップするって感じで。
typescriptの中のURLいじるのね。これはわかるでしょう。

この3つめのやつね。
![スクリーンショット 2018-09-29 17.48.34.png](https://qiita-image-store.s3.amazonaws.com/0/296267/f360f644-a31a-cbf2-9268-1541e1a98f4b.png)

>やり方としては
1.GitHubにあるリポジトリをローカル上(PC)にクローンする。
2.そこにもともとあったExhaustingADaijiro(typescript変えた奴)ぶっこむ
3.新しくHeroku(リモートリポジトリ)のはこをつくる
4.そこにpushする


以下手続き。
1.と2.はもう終わってて、PC上にGitに紐づいたローカルリポジトリがある状態からはなしはじめる。
書類に格納されているからDocumantからGitにいく

![スクリーンショット 2018-09-29 18.10.13.png](https://qiita-image-store.s3.amazonaws.com/0/296267/567e0024-45da-d8a9-54f2-d4ef57076586.png)

これからはここのGitの中のファイルを変更するようにすれば大丈夫そう。

で、みてわかる通り
originしかないから、リモートでリポジトリをつくる必要があってだな。

![スクリーンショット 2018-09-29 18.17.10.png](https://qiita-image-store.s3.amazonaws.com/0/296267/bf324495-2f2f-9c3b-a001-1dde1d58766b.png)

>heroku create

をするわけです。そうしたらorigin以外にherokuってのができる。
そしたら
>git push heroku master

ですね。
そしたらへろくに反映されるので
>heroku open

でアプリをあげるとな。

かいかいが言ってた、紐づいてるとか順番をしっかり守らないとだめだぞ〜〜っていうのがいまさらわかりましたとさ。

いや〜もっとがんばろ〜てかんじ。🔰
設計書はExcel以外認めないって風潮を変えていきたい

Excel方眼紙で設計書を書いているエンジニアです。MarkDownやPlantUMLに憧れて勉強中で、色々メモを書き溜めています。
いやしかし、何でもかんでも設計はExcel方眼紙って文化を少しずつでもいいから無くしていきたい。
ただ、MarkDownはViewerによって文法の解釈や見栄えが異なるみたいで、そこはちょっと問題かなぁ…
今回はMarkDownの文法メモをVSCで下書きしてから投稿。


参考
- [Daring Fireball](https://daringfireball.net/projects/markdown/syntax)

ヘッダー
--

# This is an H1
## This is an H2
### This is an H3
#### This is an H4
##### This is an H5
###### This is an H6

    # This is an H1
    ## This is an H2
    ### This is an H3
    #### This is an H4
    ##### This is an H5
    ###### This is an H6

テーブル
--

|ヘッダー１|ヘッダー２|
|---|---|
|項目１|項目２|
|結合項目|
何故か結合されない…

    |ヘッダー１|ヘッダー２|
    |---|---|
    |項目１|項目２|
    |結合項目|

リスト
--

* リストAの階層1
  * 階層2
      * 階層3
          * 階層N
* リストBの階層1
  - 階層2
      + 階層3
    * 階層2
      + 階層3
          - 階層N

階層にならねぇ…
と思いきや、やはり方言があるようですね。Qiitaだと空白4つ必要で、VSCだと２つでOKでした。

<pre>
* リストAの階層1
  * 階層2
    * 階層3
      * 階層N
* リストBの階層1
  - 階層2
    + 階層3
  * 階層2
    + 階層3
      - 階層N
</pre>
1. 番号リスト1
2. 番号リスト2

3\. ドットをエスケープすればリスト化されない

<pre>
1. 番号リスト1
2. 番号リスト2
3\. ドットをエスケープすればリスト化されない
</pre>

バッククォート
--

>バッククォート
>>ネスト バッククォート
>>>ネスト2 バッククォート
>>>>ネストN バッククォート
>改行されない
><br>&lt;br&gt;で改行<br>
&gt;が先頭に無くともバッククォート内に記述される

改行されない箇所がされとる…　やはりViewerによって差分が出るのはよろしくないよなぁ…

    >バッククォート
    >>ネスト バッククォート
    >>>ネスト2 バッククォート
    >>>>ネストN バッククォート
    >改行されない
    ><br>&lt;br&gt;で改行<br>
    &gt;が先頭に無くともバッククォート内に記述される

空行を挟むとバッククォートから外れるみたいね

プレーンテキスト
--

空行の後に先頭スペース4桁でプレーンテキスト化

    <script type="text/JavaScript">
        alert("test");
    </script>

hrタグ
--

* * *
***
****
- - -
---
    * * *
    ***
    ****
    - - -
    ---

リンク
--

Googleへのリンク [link](https://www.google.co.jp/)

Yahooへのリンク [link](https://www.yahoo.co.jp/ "Yahooへのリンクです")

    Googleへのリンク [link](https://www.google.co.jp/)

    Yahooへのリンク [link](https://www.yahoo.co.jp/ "Yahooへのリンクです")

文字強調
--

**Markdown**を普及させて*Excel方眼紙*の依存から脱却しよう！

<pre>
**Markdown**を普及させて*Excel方眼紙*の依存から脱却しよう！
</pre>

改行
--
ここで
改行します

↓任意の行で行末尾に空白４つを記述

    ここで   
    改行します


インラインリンク
--

[Qiitaトップページ]: https://qiita.com/ "Qiitaを開きます"
[Bingホームページ]: <https://www.bing.com/> "Bingを開きます"

* ここに[Qiitaトップページ]を載せておきます。
* ここに[Bingホームページ]を載せておきます。

<pre>
&nbsp;[Qiitaトップページ]: https://qiita.com/ "Qiitaを開きます"
&nbsp;[Bingホームページ]: &lt;https://www.bing.com/&gt; "Bingを開きます"

* ここに[Qiitaトップページ]を載せておきます。
* ここに[Bingホームページ]を載せておきます。
</pre>

コードタグ
--

バッククォートで括ると&lt;code&gt;扱いになる

`System.out.println("Hello World!");`

``echo "Hello"``


    バッククォートで括ると&lt;code&gt;になる

    `System.out.println("Hello World!");`

    ``echo "Hello"``

画像
--
![sample.png](https://qiita-image-store.s3.amazonaws.com/0/295858/a8231af4-32a9-cda3-6b4f-512f3f851ba5.png)


    ![代替テキスト](https://AAA/BBB/CCC/sample.png "サンプル用の画像です")

自動リンク
--

<https://twitter.com/>

<localhost@example.com>

    <https://twitter.com/>

    <localhost@example.com>
AutoMLの画像判別を使用して、ディープラーニングでアルトリア顔を区別する

世間ではFGOというソーシャルゲームが人気のようです。
自分もPCゲームとして発売していたぐらいの頃ではFateは好きだったんですが……気がついたらなんとも派生が増えていました。

# アルトリア顔って？
[これ](https://dic.pixiv.net/a/%E3%82%A2%E3%83%AB%E3%83%88%E3%83%AA%E3%82%A2%E9%A1%94)

時代にはついていけず、もう区別がつかないので機械に判断してもらおうと思います。

# AutoMLの登録
GoogleCloudPlatformは有効になっているという前提で( ˘ω˘)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/d617bbf6-d9d7-e85e-dbda-f8731ec2969b.png)

Visionを選択します。
初回の場合は有効にしますか？ 等々、色々と聞かれると思うので流れに沿って答えて下さい。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/cd06c9ac-3561-0150-32b5-7769d96a36f5.png)

AutoMLを開始します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/b5b623b2-0db5-6424-9a7c-50c39fc728df.png)

こーんな感じで設定してあげます。
画像ファイルの一覧は後から登録してあげるので今は設定しない感じで。
最後のチェックボックスは……1枚の画像に複数のラベルの結果が入るか？ということなので、お好きな方で！
必要なパラメータを入れるだけ入れたら後は作成するだけです。

# テスト用画像の配置と読み込み

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/1754e2a7-0fb0-3675-f275-fe27e7e378ab.png)

こんな感じでファイルを配置してみました。
csvの中にはgcs上でのパスとラベルの設定が書かれています。

```csv
gs://neko-tech-test-vcm/altria_face/altria/001.jpeg,altria
gs://neko-tech-test-vcm/altria_face/altria/002.jpeg,altria
```

今回は教師データとして、google画像検索で取得したアルトリア顔のキャラの画像をそれぞれ100枚ぐらい入れています。
本当は1000枚ぐらいあれば良いんですが、画像集めに疲れてしまいました……
もっとアルトリア顔のキャラが存在するだろうとも言われそうなんですが、ディープラーニングより前に人間の方が覚えきれない＋区別できなくって……:older_man_tone1:

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/011cd5c6-93b6-d20e-8c0c-c9d3e1f73d38.png)

読み込ませてみます……！
終わるまで時間がかかるので、気長に待ちます。
終了するとメールでも通知してくれるので、それまで他のことでも。

# 学習完了したので判定してみる

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/0bf15609-a88a-cbf3-bb2a-15e557671115.png)

こんな感じで登録されたので、PREDICTから画像をアップロードして楽しんでみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/83a5b9fb-9fa9-bc5c-b5ea-d13ecbe5abc2.png)

AIからしたら顔の構成なんて些細なことのかもしれない:skull:

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/9a853353-d594-8311-f400-f2b8af737e3e.png)

~~アグリアスはセイバーのパクリじゃないよ！~~

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/c9da2a40-b3f9-6a24-4505-34c35190b8a1.png)

実在のネロの彫像はさすがに無理があった。
どのあたりを持って元祖セイバーと判断したのだろうか。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/010b06d1-01fd-ffb0-dea9-a24afaaa9fb3.png)

わかりやすい画像だと精度も高い！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/79a6adee-6c75-9978-705d-d2f9e540910d.png)

新選組っぽい画像だと沖田総司と判定されるのか……

# 感想

とにかく簡単です！ ディープラーニング？　何それ？　という方でも簡単に実現できてしまいます。
今回は教師データとなる画像も少なく、あまり精度のいい画像とも言えなかったので……
ちょっと意地悪な画像にしてみると、少し残念な結果になることもあったのですが。
商品のカテゴリ分けなど、真面目な用途？で使えば間違いなく期待する通りの結果が帰ってくるかと！

本当に手軽に使えるので色々な用途で使ってみたいところ:heart_eyes:

# マシュってアルトリア顔じゃなくね？
終わった後に気づいたよ……:frowning2:
母親がゲーム機のことを全てファミコンと言うようなものなので、寛大な心で許してください:dizzy_face:
Developers Summit 2018 KANSAI登壇資料まとめ

* 2018/09/28に神戸で開催されたDevelopers Summit 2018 KANSAI登壇資料まとめです
* 追加があれば随時編集します。
* ここに含まれていないものがあれば教えていただけると嬉しいです。

## 公開されている資料まとめ
* [Developers Summit Kobe 2018 0928 - Speaker Deck](https://speakerdeck.com/pnsk/developers-summit-kobe-2018-0928)
* [ユーザー体験にフォーカスした管理画面の実装 - Developers Summit 2018 KANSAI - Speaker Deck](https://speakerdeck.com/leonardo_mbc/yuzati-yan-nihuokasusitaguan-li-hua-mian-falseshi-zhuang-developers-summit-2018-kansai)
* [改善を重ねるリモートスクラム開発 〜kintone開発の現場から〜 - Speaker Deck](https://speakerdeck.com/kaiichiro/gai-shan-wozhong-nerurimotosukuramukai-fa-kintonekai-fa-falsexian-chang-kara)
* [等身大の主人公。だから未来で待ってる - Speaker Deck](https://speakerdeck.com/araitakeshi/deng-shen-da-falsezhu-ren-gong-dakarawei-lai-dedai-tuteru)
* [Mackerelの200週連続リリースの舞台裏とこれから / DevsumiKansai2018 - Speaker Deck](https://speakerdeck.com/daiksy/devsumikansai2018)
* [クラウドネイティブなアーキテクチャを設計する次世代の現場力 - Speaker Deck](https://speakerdeck.com/shkitayama/kuraudoneiteibunaakitekutiyawoshe-ji-suruci-shi-dai-falsexian-chang-li)
* [なぜYahoo!カレンダーはPHPからKotlinへ技術移行を進めるのか - Speaker Deck](https://speakerdeck.com/bulbulpaul/nazeyahoo-karendahaphpkarakotlinheji-shu-yi-xing-wojin-merufalseka)
* [勝てる「開発プロセス」のつくり方](https://www.slideshare.net/hiromasaoka/ss-117079546)
* [東京本社よりも地方開発拠点を活性化させるコツ！！！！](https://www.slideshare.net/maoohnishi3/ss-117061163)
* [B2Bクラウドサービスをゼロから立ち上げて、利用社数が1000社を超えるまでの道のり](https://speakerdeck.com/kizashi1122/a-startup-started-b2b-saas-business-from-ground-zero)
* [VUIで未来をはじめる](https://speakerdeck.com/torisankanasan/vuidewei-lai-wohazimeru)
* [農家と流通業者のタッチポイントにLINE Botを導入した話](https://speakerdeck.com/n11sh1/line-bot-case-studies-touch-points-of-farmers-and-distributors)
* [改善を重ねるリモートスクラム開発 〜kintone開発の現場から〜](https://speakerdeck.com/kaiichiro/gai-shan-wozhong-nerurimotosukuramukai-fa-kintonekai-fa-falsexian-chang-kara)
* [意外と知らない？！GitHubの新機能を紹介します](https://speakerdeck.com/pnsk/developers-summit-kobe-2018-0928)

## 参加者のブログや関連記事など
* [20180928 Developers Summit 2018 KANSAI に参加して - TsuyoshiKusakaの日々思うこと　その2](http://tsuyoshikusaka.hatenablog.com/entry/2018/09/28/235525?_ga=2.136522992.1547414146.1538144431-870849105.1515288606)
* [Developers Summit 2018 KANSAI に参加してきました。人間です。](https://irony9901.hatenablog.com/entry/2018/09/30/152022)
* [「今日から始める機械学習〜はてなの事例〜」というタイトルでデブサミ2018関西で登壇しました](https://www.yasuhisay.info/entry/2018/10/01/090000)
* [デブサミ関西2018は刺激がたくさん、学びがたくさん。](https://iucstscui.hatenablog.com/entry/2018/09/30/211612)
【Swift】ナビゲーションバーをステータスバーまで広げる

# １．はじめに

`UINavigationController` 配下ではない`ViewController` に自分で`UINavigationBar` を設置する場合、ナビゲーションバーがステータスバーの領域までは伸びず、大変かっこ悪い。

このような感じ。

<img width="476" alt="スクリーンショット 2018-09-29 17.17.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/124577/8cdcb36d-1af6-ad1a-eba3-dce88088effc.png">


このナビゲーションバーをステータスバーの領域まで伸ばします。

# ２．Storyboard

Storyboardで`UINavigationBar` を設置します。
ステータスバーにはかぶせないようにします。

今回は見やすいようにStyleをBlackにしています。

<img width="429" alt="スクリーンショット 2018-09-29 17.17.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/124577/f6260cef-e419-e08b-8f97-acd146dd2d5d.png">

# ３．コード

```swift
class ViewController: UIViewController, UINavigationBarDelegate {

    @IBOutlet weak var navigationBar: UINavigationBar!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        navigationBar.delegate = self
    }
    
    func position(for bar: UIBarPositioning) -> UIBarPosition {
        return .topAttached
    }
}
```

`UINavigationBarDelegate` に準拠します。
`position(for:)` で`.topAttached` を返します。

# ４．完成

こうなります。

<img width="480" alt="スクリーンショット 2018-09-29 17.17.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/124577/2bb49193-5db4-272f-fbc6-376c03f71474.png">
Dockerを使ってnginxのWebサーバを構築する



## Dockerを利用してnginxのWebサーバを構築してみる

さて、今回はDockerを利用してnginxをためしてみます。
はじめてのDockerはこちらをご参照ください。

[Dockerをはじめからていねいに](https://qiita.com/umeee/items/cdf30e037a0ee66e8d10)

## pullする
まずはDockerイメージをおとしてきます。
今回はubuntuを使います。

```
$ docker pull docker.io/ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
124c757242f8: Pull complete
9d866f8bde2a: Pull complete
fa3f2f277e67: Pull complete
398d32b153e8: Pull complete
afde35469481: Pull complete
Digest: sha256:de774a3145f7ca4f0bd144c7d4ffb2931e06634f11529653b23eba85aef8e378
Status: Downloaded newer image for ubuntu:latest
```

## dockerを起動する
次に、docker起動です。

```
$ docker run -td --name ubuntu-latest docker.io/ubuntu:latest
ea7e5b555f66cde78126d227f6fe62db8dfd19aef827d112370549a14e44bc3b
```

## nginxコンテナを起動する
nginxコンテナを起動してみます。

```
$ docker pull docker.io/nginx
Using default tag: latest
latest: Pulling from library/nginx
802b00ed6f79: Pull complete
c16436dbc224: Pull complete
683eac851b28: Pull complete
Digest: sha256:e8ab8d42e0c34c104ac60b43ba60b19af08e19a0e6d50396bdfd4cef0347ba83
Status: Downloaded newer image for nginx:latest

$ docker run -d -p 8000:80 --name nginx-latest docker.io/nginx:latest
e3a624000ac66f2172d0ac936aa396906ca276a5a0ee9dbf57dc7836ac33fe67
```
今回は-pオプションを使っています。

>
p-：ポートフォワードを行う

Dockerホストマシンの8000番ポートが、nginx-latestコンテナの80番ポートにつながっていることになります。

psでみるとこんな感じ。

```
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                  NAMES
e3a624000ac6        nginx:latest        "nginx -g 'daemon of…"   About a minute ago   Up About a minute   0.0.0.0:8000->80/tcp   nginx-latest
ea7e5b555f66        ubuntu:latest       "/bin/bash"              5 minutes ago        Up 5 minutes                               ubuntu-latest
```

PORTSのカラムでポートフォワードの設定が確認できますね。

## 実際にnginxコンテナにアクセス確認してみる
実際にアクセスして確認してみましょう。

```
$ curl http://localhost:8000/index.html
<!DOCTYPE html>
<html>
...
...
```
index.htmlの結果がかえってくればOKです！

## nginxログの確認
nginxのログも確認することができます。

```
$ docker logs -f nginx-latest
172.17.0.1 - - [29/Sep/2018:07:24:52 +0000] "GET /index.html HTTP/1.1" 200 612 "-" "curl/7.53.1" "-"
```

-fをつけることでtail- fのような見方ができます。

以上でnginxのWebサーバが構築できました。

OSインスタンスから構築した場合、OSをインストールして、nginxをインストールして、起動してと多くのステップ・時間がかかりますが、Dockerイメージを利用することでクイックに構築できますね。
ANACONDA NAVIGATORを使って仮想環境を作ってpsycopg2を入れる

# この記事について
　Anacondaの仮想環境を使用してpyscopg2をインストールしてみました。

# 環境
　Python3
　Anaconda

# 使ってる仮想環境
　個人的にAnacondaの仮想環境が簡単に使えてインストールするライブラリも簡単に操作出来て好きです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296240/4d4230b4-c18e-f900-4bb8-17719e9f20c8.png)
　今回はここに環境を作っていきましょう。
　まずは下に表示されているCreateボタンをクリックします
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296240/36224ea1-f391-8140-3509-db630bbb9b8b.png)
　するとこんなウィンドウが開きますので名前を入力してCreateボタンを押すだけです。
　Pythonのバージョンを変更したい場合やRを使用したい場合にはここで設定しましょう。今回はスルーします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296240/8ee41b46-43eb-384c-55f7-4b90695e2122.png)
　Createボタンを押すとPGTEST（任意の名前）が追加されました！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296240/59de7cfc-caa1-069a-d450-796c92061573.png)

# psycopg2のインストール
　次に今回PostgreSQLに繋ぐためのライブラリとしてpsycopg2を使用します。
　インストールするにはまず先ほど作成した環境をクリックして下の画像の②の欄をNot installedに変更します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296240/8ef67a70-86f9-beb1-9517-a628bfc9ae78.png)
　こうすることで下に表示されるライブラリがインストールされていないものに変更されます。
　そこで下の画像の右上①にpsycopg2と入力をします。
　そして中央付近の②のチェック欄にチェックを入れて、最後の右下のApplyをクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296240/b72c7d5c-b129-ae97-6130-42da62bab6c9.png)
　すると少しロードが入った後に一緒にインストールするべきライブラリも表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/296240/303d2393-dec7-2fc4-3112-e1954aadc14d.png)
　あとはapplyを押せばインストールが開始されます。

# 次回
　次回はインストールしたpsycopg2を使ってPostgreSQLに繋いでDBにデータを保存するまでを書きます。
processing(android mode)におけるtouchesのバグとその対処法

#はじめに
processingのtouchesとはPointer型の配列として現在タッチされている点の座標等を保存しています
Pointerクラスは

```

public class Pointer {
  public int id;
  public float x, y;
  public float area;
  public float pressure;
}

```

となっています

#BUGの内容
一つ目の指を一切動かさずタップし続け、二つ目の指を押して離したとき二つ目の指が離れたことを認識しません

#BUGの解決法
touchesを自分で作成してしまいます
具体的には

```

import android.view.*;
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List;
Pointer[] touches;
List<Pointer> touchesList=Collections.synchronizedList(new ArrayList<Pointer>());
@Override
public boolean surfaceTouchEvent(MotionEvent event) {
  int count=event.getPointerCount();
  int action=event.getAction();
  int actionMasked = action & MotionEvent.ACTION_MASK;
  int idx = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
  boolean flag = actionMasked==MotionEvent.ACTION_UP||actionMasked==MotionEvent.ACTION_POINTER_UP;
  touchesList.clear();
  for(int i=0;i<count;i++){
    if(flag&&idx==i)continue;
    Pointer t=new Pointer();
    t.id=event.getPointerId(i);
    t.x=event.getX(i);
    t.y=event.getY(i);
    t.area=event.getSize(i);
    t.pressure=event.getPressure(i);
    touchesList.add(t);
  }
  return super.surfaceTouchEvent(event);
}
class Pointer {
  public int id;
  public float x, y;
  public float area;
  public float pressure;
}

```
というコードを書いたあとvoid draw{…}にて

```

touches = touchesList.toArray(new Pointer[touchesList.size()]);

```
と書いてListを配列に変換します

#あとがき
やはりprocessingは複雑な処理には向かないというのが正直な感想です
ただ、processingでは実現が大変なことに対してprocessingのコードを読み込んで解決法を見出すことは勉強になるし、何より楽しいです
ClamAVについてまとめてみた


セキュリティ系のOSSの理解を深めるためのメモ書き


## ClamAVとは？

正式名称は**Clam AntiVirus** （クラム・アンチウイルス。略称Clam AV）

CentOSやUbuntuなどのサーバでウイルス対策したいなーというときに使えるソフト
もともとはメールから入ってくるウイルスを対策する目的で開発されていたらしい。
クロスプラットフォームで動くのでMacOSやWindowsでも使用可能

最近０．９９からアップデートして０．１００になった、一体いつになったらメジャーリリースするのだろうか。。。

## どんなことができるの？

デーモン実行によるリアルタイムスキャンや局所的なディレクトリ、ファイルに対してのスキャンが可能。あとはsendmailのメールフィルタリング拡張コンポーネント機能を持っているので、オンデマンドのスキャンもできる。

また、ZIPやtar、gzipといった圧縮ファイルや、Microsoft Officeで作成されたファイルやPDFファイルもスキャンすることが出来る。

シグネチャ型（特定の文字情報のパターン）をベースにウイルスを発見できる。

各OSでのインストール方法

Redhat系ではCentOS７からパッケージの名称やコマンドが若干変ったので注意

CentOSの場合

```
yum -y install epel-release ※ epelリポジトリがない場合
yum install --enablerepo=epel clamav-server \
clamav-data clamav-update clamav-filesystem \
clamav clamav-scanner clamav-scanner-systemd clamav-devel \
clamav-lib clamav-server-systemd
```

Ubuntuの場合

```
$sudo apt-get install clamav-base clamav-daemon clamav-freshclam
```

まずはこれでインストール完了です。

つかぱい’ｓ　TODO
使用方法や、設定などは今度書きます。
2クラスロジスティック回帰でスケーリングの影響を見る

#概要
Kerasで2クラスロジスティック回帰をするときにデータのスケーリングを変えて見て、結果がどう変わるか見てみる記事。


#スケーリング
スケーリングについては以下の記事に詳細がわかりやすく書かれています。
[Feature Scalingはなぜ必要？](https://qiita.com/ttskng/items/2a33c1ca925e4501e609)

各フィーチャーの値の幅がバラついていると、勾配降下法で重みを更新するときの更新幅(偏微分の値)がフィーチャーごとに大きく異なってってしまうので学習が遅くなるよう。



#2クラスロジスティック回帰
今回は以下の記事のコードとデータを参考にして実験しました。
[Kerasによる2クラスロジスティック回帰](http://aidiary.hatenablog.com/entry/20161030/1477830597)

上記サイトでデータのスケーリングをしている箇所がある。

```python
X = preprocessing.scale(X)
```

ここを変えてみて結果がどう変わるか見てみる。

ちなみにこれは

```python
X = X - x.mean()) / x.std()
```

と同じ。

# 試してみるスケーリングパターン
1. スケーリングなし
2. 標準偏差除算
3. 平均値減算
4. 平均値減算+標準偏差除算  

batch=10
Epoch=600
で結果を可視化してみる。

# データ分布

1.スケーリングなし
![data_normal.png](https://qiita-image-store.s3.amazonaws.com/0/250063/e3dfd165-7f68-df7a-bbce-e7f4ed155a4a.png)

2.標準偏差除算
![data_std.png](https://qiita-image-store.s3.amazonaws.com/0/250063/da7a7b13-7e90-6bf3-1039-c362a65d20e6.png)


3.平均値減算
![data_mean.png](https://qiita-image-store.s3.amazonaws.com/0/250063/76ee9a73-ac72-d6f6-2e7f-c4a880915b6f.png)


4.平均値減算+標準偏差除算
![data_scale.png](https://qiita-image-store.s3.amazonaws.com/0/250063/30077fe7-c2d5-44e1-19f9-b1cdd2eaccc8.png)


# accuracy
1.スケーリングなし
![acc_normal.png](https://qiita-image-store.s3.amazonaws.com/0/250063/efaaaa33-be90-1da7-58d0-eb48881be177.png)
全くだめ。

2.標準偏差除算
![acc_std.png](https://qiita-image-store.s3.amazonaws.com/0/250063/a6f56b36-3c27-865f-f545-eff0ede677bd.png)
もっとEpoch増やせば上がりそう。

3.平均値減算
![acc_mean.png](https://qiita-image-store.s3.amazonaws.com/0/250063/45ff558a-3009-d335-7ff6-430b9cdbe3c5.png)
この中では一番精度がいい。

4.平均値減算+標準偏差除算
![acc_scale.png](https://qiita-image-store.s3.amazonaws.com/0/250063/d2b8c51d-7f26-6caa-e114-5aa60e7b2692.png)
平均値減算より90%付近に到達するのに時間がかかっている。


# loss
1.スケーリングなし
![loss_normal.png](https://qiita-image-store.s3.amazonaws.com/0/250063/8a00188b-7983-19ad-d685-42c55fa6e540.png)

2.標準偏差除算
![loss_std.png](https://qiita-image-store.s3.amazonaws.com/0/250063/8e469243-8c6b-571b-4c67-f13c6a0e5f85.png)

3.平均値減算
![loss_mean.png](https://qiita-image-store.s3.amazonaws.com/0/250063/2168a3fc-9233-7329-89a7-8dc3fec3473b.png)

4.平均値減算+標準偏差除算
![loss_scale.png](https://qiita-image-store.s3.amazonaws.com/0/250063/e572c88f-8591-c825-688a-ce4bb2cec499.png)



# decision boundary
1.スケーリングなし
スケーリングなしは全く収束していないので割愛

2.標準偏差除算
![graph_std.png](https://qiita-image-store.s3.amazonaws.com/0/250063/1fa6a828-d3f3-ea1e-3399-ec780f43aa38.png)
まだロスが下がりきっていないので線がうまく引けていない。

3.平均値減算
![graph_mean.png](https://qiita-image-store.s3.amazonaws.com/0/250063/aefcd5a3-2537-48e4-c3c9-7d32990ba2a1.png)

4.平均値減算+標準偏差除算
![graph_scale.png](https://qiita-image-store.s3.amazonaws.com/0/250063/8dd4bcdb-a7f6-76b7-911e-ab29c6b05f2c.png)


# まとめ
スケーリングありのときの収束過程
![test.gif](https://qiita-image-store.s3.amazonaws.com/0/250063/4a1e15aa-8b2a-a624-fa2a-676b44448bc1.gif)

今回のデータの例に限っては、平均減算が一番速く学習が収束した。スケーリングは今までお決まりの処理として書いていたけど、こうやって実際に違いを見ることでスケーリングの大切さを再認識できた。
【Game a Week】８週間目

# Game A Week
1. 一週間（月曜日から日曜日）に一本ゲームをリリースする。
2. 日曜日（まで）に制作したゲームを何らかの手段で公開する。
3. 制作したゲームはGame A Weekが終わるまで改変しては行けない。

# 前置き
先週の作品：[【Game a Week】7週間目](https://qiita.com/hota1024/items/88cdc7f56911f095b3af)

# 今回作ったゲーム
今回は[Scratch2.0](https://scratch.mit.edu/)を使って*格闘ゲーム*を作ってみました。

# 使った技術
| 名前 | 説明 |
|:-:|:-:|
| [Scratch2.0](https://scratch.mit.edu/)  |  子供向けのプログラミング環境。  |

# ゲームの詳細
名前は「SmashCats」。
[こちら](https://scratch.mit.edu/projects/248532980/#player)から遊べるので是非遊んでみてください。

格闘ゲームです。
二人でプレイできます。

<img width="481" alt="スクリーンショット 2018-09-29 16.43.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/154299/52a24e62-f9fb-a461-63ab-204c3ec5719d.png">

青い猫の操作方法：
Aキーで左移動
Dキーで右移動
Wキーでジャンプ
Sキーで攻撃

黄色い猫の操作方法：
左矢印キーで左移動
右矢印キーで右移動
上矢印キーでジャンプ
下矢印キーで攻撃

相手に攻撃を当ててHPを0にすると勝ちです。
<img width="479" alt="スクリーンショット 2018-09-29 16.44.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/154299/e2ea4edb-5615-d528-7fda-d7d0b89c043f.png">

また攻撃を当てると攻撃を相手が**ふっ飛び**びます。

相手をふっ飛ばし縁の赤い部分に当てれば勝ちです。

# 8週間目の感想
今回は前回と同様Scratch2.0で開発をしました。

猫のプログラムの全体はこんなかんじです。
<img width="722" alt="スクリーンショット 2018-09-29 16.47.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/154299/4c730071-6542-629f-d6f7-8701a54dba94.png">

ちなみに「メッセージ」スプライトのプログラムの「重力を1にする」というプログラムの1という値を増やすと重力が強くなり、減らすと重力が軽くなります。

<img width="219" alt="スクリーンショット 2018-09-29 16.49.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/154299/100337f1-0971-3a9a-ddf7-9f17ac9def1e.png">

# 最後に
ここまで読んでいただきありがとうございます。
良ければアドバイスや質問よろしくおねがいします。
HTML5プロフェッショナル認定資格Level1 合格記

2018年9月初旬に、HTML5プロフェッショナル認定資格Level1を受験し合格しました！
本記事では、試験の概要と合格までの受験勉強法を記しました。

# 動機
普段業務でWebアプリケーション開発をしています。その中でフロントサイドの開発、UIの構築を少しずつ担当することになり、毎度調べながらなんとか実施してきました。そこで改めて正しい知識を身に付けるのと、今まで実施してきた知識、経験がどれだけ定着しているか確かめる目的で受験したいと思いました。

# 試験の概要
公式：[HTML5 Professional Certification Level.1について（Ver2.0）](https://html5exam.jp/outline/lv1_v2.html)

認定者は、下記のスキルと知識を持つ Webプロフェッショナルであることを証明できます。

* HTML5を使ってWebコンテンツを制作することができる。
* ユーザー体験を考慮したWebコンテンツを設計・制作することができる。
* スマートフォンや組み込み機器など、様々なデバイスに対応したコンテンツ制作ができる。
* HTML5で何ができるのか、どういった技術を使うべきかの広範囲の基礎知識を有する。


所要時間：90分
試験問題数：約60問
受験料：￥15,000 （税別）
試験実施方式：コンピュータベーストテスト（CBT）
認定の有意性の期限：5年間

# Ver2.0
2017年3月1日に、新出題範囲「Ver2.0」がリリースされました。下記内容が「Ver1.0」との変更点になります。

* サーバ関連技術に関する出題が減少。クライアント系のみの仕事をしている方に配慮した内容に変更。
* HTML5で何ができるのか？ Web アプリの知識を問う問題が増加。認定対象者として、Web ディレクターをより意識した内容に変更。

個人的にはスマートフォンなどのマルチメディアへ対応した問題が、大きな違いとして感じられました。

# 私の勉強法
ここからは私が実践した勉強法を共有します。だいたい受験の1ヶ月前から勉強をはじめました。

### 公式サンプル問題
https://html5exam.jp/measures/sample.html#lv1
まず公式が発表するサンプル問題を解きました。解いた感想として「結構細かくて知らないことが多い！」と感じました。この時点でこれは知識を頭に叩き込まないとダメだと思い、体系的に学べる学習本をベースに学習を進めていきます。

### HTML5プロフェッショナル認定試験 レベル1 対策テキスト＆問題集　Ver2.0対応版
https://www.amazon.co.jp/exec/obidos/ASIN/B07485SSV3/neos21-22/
こちらの本を購入して、HTML,CSSの書式について勉強してきました。ただ、読むだけではなかなか知識が定着しないなと感じ...

### HTML教科書 HTML5プロフェッショナル認定試験 レベル1 スピードマスター問題集 Ver2.0対応
https://www.amazon.co.jp/HTML教科書-HTML5プロフェッショナル認定試験-レベル1-スピードマスター問題集-Ver2-0対応-ebook/dp/B079PMR94Q/
先ほどの紹介した本をある程度読み進めて、問題集となっているこちらの本を読んで問題を解き進めていきました。わからないことや知らないことがあれば、先ほど紹介した本で調べたり、ググったりして問題を解きながら覚えていく、というペースで勉強を進めました。
2周くらいして、あとはミスした問題に印をつけておいてあとで見返すことを最後にしました。

# 本番
試験時間が90分ですが丸々時間を使うことなく、かなり余裕を持って問題を解くことができました。全然わからない、知らない単語がある、といったような問題も特にはありませんでしたが、やはり「3つ選べ」「複数選べ」といったように正確に覚えていないと悩んでしまうことが多々ありました。問題を解き終えるとすぐに合否がわかります。無事合格！

# 感想とこれから
レベル1を受験してみて、自分が知らないことが結構あるんだなと感じました。特に普段使わないようなHTML,CSSの書式がたくさんありました。
今回はレベル1を受験しましたが、すぐにレベル2を受験しようと考えてます。レベル2はレベル1よりも高いレベルのマークアップとJavaScriptが出題範囲となってます。JavaScriptも普段扱っているので、復習のつもりでまた勉強を始めたいと思っています。