OmniAICreator/Qiita-1.07M huggingface dataset:
サザン vs TUBE 真の夏うた王はどっちだ!?　MeCabで歌詞分析をしてみた

#はじめに
さて、気づけば今年も8月20日。
夏が始まったばかりだと思っていたら、もう終わりを告げようとしています…
まぁサラリーマンなんで、夏休みとか関係ないんですけどね:sweat_smile:

夏といえば、やはり夏うた。夏うたを聞いて、せめて気持ちだけでも夏休み気分を味わいたくなりますよね…。
ドワンゴさんの[こちらの記事](https://news.dwango.jp/j-pop/17019-1607)によると、海の似合うアーティストの投票で、1位サザンオールスターズ2位TUBEと、3位を大きく引き離してバチバチのデッドヒートを繰り広げている模様です。
サザンは「TSUNAMI」「真夏の果実」、TUBEは「シーズン・イン・ザ・サン」「あー夏休み」と両者ともに名曲揃いで、これはどちらも優劣をつけがたい感じです。

ということで今回はPython+Mecabで歌詞の形態素解析を実施し、夏ワード:sunny:の出現回数を比較することで、真の夏うた王を決定したいと思います。

#ルール
- 全曲の夏ワード（「海」「ビーチ」など）の出現回数の合計を曲数で割り、1曲あたりの夏ワード出現回数で勝敗を決定する。
 
(TUBEが約450曲、サザンが約270曲と開きがあるため、1曲あたりの比較としています。）

#手法
（何らかの手法を使って）歌詞のテキストファイルを集める
↓
すべての歌詞ファイルを結合し、文字列とする
↓
Mecabで形態素解析
↓
単語の出現回数を集計
↓
出現回数を比較

歌詞ファイルの取得については、センシティブな部分かと思いますので、今回は詳細は省きます。
MeCabで形態素解析をすると、単語の分かち書きおよびに単語の品詞を取得できますので、今回は品詞が名詞のものに絞って集計しています。
なお夏ワードについては、完全に私の主観に基づき決定しています。

#結果
| 単語/歌手 | TUBE | サザン |
|-----------|------|--------|
| 夏        | 462  | 118    |
| 海        | 187  | 57     |
| 波        | 124  | 66     |
| summer    | 114  | 7      |
| 太陽      | 110  | 38     |
| beach     | 80   | 5      |
| 渚        | 43   | 20     |
| 真夏      | 42   | 17     |
| 砂        | 35   | 30     |
| 湘南      | 32   | 8      |
| wave      | 23   | 11     |
| 花火      | 22   | 6      |
| surfin    | 21   | 0      |
| sunshine  | 18   | 15     |
| 浜辺      | 14   | 11     |

| 結果/歌手 | TUBE | サザン |
|-----------|------|--------|
| 合計      | 1327 | 409    |
| 曲数      | 454  | 271    |
| 1曲あたり | **2.92** | **1.51**   |

どう見ても**TUBEがダブルスコアで圧勝**です。本当にありがとうございました。
サザンは「ピースとハイライト」のように、社会問題など比較的いろいろなテーマを取り上げてる印象ですが、TUBEは**夏にステータス全振り**してるので、そのあたりが影響してこれだけの差がついたのだと思います。

特徴的な部分として、**TUBEは「summer」「beach」というワードをそれぞれ100回近く使用しているのに対し、サザンは10回も使っていません。**サザンは直接的な夏のワードを使わずに、夏の情景が浮かんでくるような歌詞を書くのが得意なのかもしれませんね。

:bikini::bikini::bikini:
**Congratulations!**
**TUBE is king of summer.**
:beach::beach::beach:


#コード
最後に集計用のコードを記載しておきます。

```python:
import csv
import MeCab
import glob
from collections import Counter

def make_word_list(all_lyric):
  tagger = MeCab.Tagger('-Ochasen')
  node = tagger.parseToNode(all_lyric)
  word_list = []
  while node:
      if node.feature.split(",")[0] == "名詞":
              word_list.append(node.surface.lower())
      node = node.next
  return word_list

def dict_to_csv(artist,histogram):
    with open(artist + ".csv", "w") as csv_file:
        writer = csv.writer(csv_file, lineterminator='\n')
        header = ["単語", "回数"]
        writer.writerow(header)
        for key in histogram:
            row = [key,histogram[key]]
            writer.writerow(row)
        csv_file.close()

if __name__ == "__main__":
    # download_lyrics()
    artists = ["サザン","TUBE"]
    for artist in artists:
      if artist == "サザン":
        artist_folder_name = "southern_lyrics"
      elif artist == "TUBE":
        artist_folder_name = "tube_lyrics"

      all_lyric = ""
      for lyric_path in glob.glob(artist_folder_name + "/*"):
          with open(lyric_path, "r",encoding="shift_jis") as f:
              all_lyric += f.read()

      word_list = make_word_list(all_lyric)
      histogram = Counter(word_list)
      dict_to_csv(artist,histogram)
```
Arch Linuxで非rootユーザーを作成する

# 1.ユーザー作成
ルート権限で
`useradd -m -g wheel -s [ログインシェル] [ユーザー名]`　でユーザ作成

# 2.ユーザのパスワードを設定
`passwd [ユーザー名]`

# 3.sudo をインストール
`pacman -S sudo `
visudoで`# Defaults env_keep += "HOME"`　と　`# %wheel ALL=(ALL) ALL` をコメントアウトして保存。 
> Defaults` 行は、 `sudo` したときユーザの `$HOME` を参照する設定。
　%wheel` は `wheel` グループのユーザに `sudo` する権限を付与。


これらを終えたら`exit`して上記で作ったユーザーでログインができるか確認。


ちなみに

#グループ作成
`groupadd [グループ名]`

#ユーザー削除
`userdel -r [ユーザー名]`
ディスク容量が余裕でも"No space left on device"と怒られる怪現象


mongodbが落ちていたのでログを確認すると`No space left on device`と出力されていた。

```
$ # /var/log/mongodb/mongod.log の内容
( 略 : )
2018-08-18T21:44:32.320+0900 E STORAGE  [thread1] WiredTiger (28) [1534596272:318424][943:0x7ff7d77b2700], file:WiredTiger.wt, WT_SESSION.checkpoint: /var/lib/mongodb/WiredTiger.turtle.set: handle-open: open: No space left on device
2018-08-18T21:44:32.321+0900 E STORAGE  [thread1] WiredTiger (28) [1534596272:321564][943:0x7ff7d77b2700], checkpoint-server: checkpoint server error: No space left on device
( 略 : )
```


ディスクフルだろうとディスク容量を確認する、、、空き容量はある。怪現象だ。

```
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            990M  4.0K  990M   1% /dev
tmpfs           201M  412K  200M   1% /run
/dev/vda1        48G   29G   17G  63% /
none            4.0K     0  4.0K   0% /sys/fs/cgroup
none            5.0M     0  5.0M   0% /run/lock
none           1001M     0 1001M   0% /run/shm
none            100M     0  100M   0% /run/user
$
```

サイズではなくファイル数がフルなのであった。

```
$ df -i
Filesystem      Inodes   IUsed  IFree IUse% Mounted on
udev            253417     419 252998    1% /dev
tmpfs           256223     354 255869    1% /run
/dev/vda1      3145728 3145728      0  100% /
none            256223      11 256212    1% /sys/fs/cgroup
none            256223       1 256222    1% /run/lock
none            256223       1 256222    1% /run/shm
none            256223       3 256220    1% /run/user
$
```

このマシンではサイズの小さなファイル(1KB程度)を200万ファイル/年のペースで生成するようなシステム(※1)が動いているため、ファイル数(inode数)の上限に達してしまっていたのであった。

対処法としては以下が挙げられる。

- 不要or古いファイルをアーカイブor退避or削除する
- ファイル数を監視し一定に保つ仕組みを設ける
- ストレージorディスク容量を増やす

(※1) 
将棋の棋譜ファイルをスクレイピングで収集するサービス( [将棋クエスト履歴検索β]( http://c-loft.com/shogi/quest?u=loftkun&g=shogi10) )を稼働させている。
Raspberry Piで使っているSDカードの容量を増やす方法

Raspberry Piを使っていると、容量がいっぱいになってしまい、大きい容量のSDカードに移し替えたいと思い、容量の大きいSDカードに移す方法を色々調べて試していましたが、どれもうまくいかず、唯一うまくいった方法を備忘録として残します。なお、raspbianのカーネルバージョンは４．１４．５２で確認しています。

# SD Card Copier
Raspbianに標準で入っている「SD Card Copier」というSDカードにOSをバックアップをするためのソフトを使うだけです。
「メニューアイコン」→「アクセサリ」→「SD Card Copier」から開けます。

![スクリーンショット 2018-08-20 19.21.35.png](https://qiita-image-store.s3.amazonaws.com/0/170520/2a88ac66-276e-8111-0ec9-d7fe02873c9b.png)

# 使い方
「Copy From Device」には今OSを動かしているSDカードを選びます。コピーしたいSDカードを接続して、「Copy To Device」にはコピー先のSDカードを選択します。「Start」ボタンを押すとコピーが始まります。

![スクリーンショット 2018-08-20 19.24.51.png](https://qiita-image-store.s3.amazonaws.com/0/170520/279df283-3dac-93ec-b92c-034391f1e2a9.png)

コピーしたSDカードがコピー元のSDカードよりも大きい容量だった場合はその容量に合わせて調整してくれるようです。

# 結果
１６GB→３２GBに移した結果、次のようになりました。「/dev/root」が5.5GB→２８GBとして認識されました。

１６GB
![スクリーンショット 2018-08-20 19.41.29.png](https://qiita-image-store.s3.amazonaws.com/0/170520/123e29d6-112b-25c5-b279-81c10fc31395.png)

３２GB
![スクリーンショット 2018-08-20 19.38.38.png](https://qiita-image-store.s3.amazonaws.com/0/170520/bf0688c1-231c-3c38-60e2-f64462fb3ae6.png)
Mac で Julia #2 Variables


前回に引き続きJuliaについてです。

[ドキュメント](https://docs.julialang.org/en/stable/)に沿って試していきます。

## Variables

```julia
julia> x=10
10

julia> x+1
11

julia> x=1+1
2

julia> x="Hello"
"Hello"

julia> x=10
10

julia> 2x
20

julia> x="こんにちは"
"こんにちは"
```

- 普通ですね。日本語も問題無いようです。

### Allowed Variable Names

- 予約語はふつーにだめです。

```julia
julia> if = "もし"
ERROR: syntax: unexpected "="

julia> else = false
ERROR: syntax: unexpected "else"

julia> try = "No"
ERROR: syntax: unexpected "="

julia> 日本語の変数名 = "でもOKです"
"でもOKです"

julia> 日本語の変数名
"でもOKです"
```

- 日本語の変数名でもOKですけど、まぁ使いませんよね。

### Stylistic Conventions

juliaでの変数のお約束です。ええと...


- Names of variables are in lower case.（変数は小文字で）
- Word separation can be indicated by underscores ('_'), but use of underscores is discouraged unless the name would be hard to read otherwise.（アンダースコアは使ってもいいけど読みにくい場合のみ）
- Names of ```Types``` and ```Modules``` begin with a capital letter and word separation is shown with upper camel case instead of underscores.（TypeとModulesは大文字開始のキャメルケースで）
- Names of ```functions``` and ```macros``` are in lower case, without underscores.（関数とマクロは小文字でアンダースコアなし）
- Functions that write to their arguments have names that end in !. These are sometimes called "mutating" or "in-place" functions because they are intended to produce changes in their arguments after the function is called, not just return a value.（引数を変更して値も返すような関数には！マークをつける。インプレイス関数と呼ばれる。）

大体普通ですねJavaに近いかな？、あと最後のは引数が破壊的な場合には関数名に！をつけろということなんでしょうか？？

こういうことですね、[説明](https://docs.julialang.org/en/stable/manual/style-guide/#Append-!-to-names-of-functions-that-modify-their-arguments-1)がありました。

#### Append ```!``` to names of functions that modify their arguments

Instead of:

```julia
function double(a::AbstractArray{<:Number})
    for i = firstindex(a):lastindex(a)
        a[i] *= 2
    end
    return a
end
```

use:

```julia
function double!(a::AbstractArray{<:Number})
    for i = firstindex(a):lastindex(a)
        a[i] *= 2
    end
    return a
end
```

実行してみます。

```julia
julia> a=[1,2,3]
3-element Array{Int64,1}:
 1
 2
 3

julia> double!(a)
3-element Array{Int64,1}:
 2
 4
 6

julia> a
3-element Array{Int64,1}:
 2
 4
 6
```

aの値が破壊されていることがわかります。

[詳細なStyle Guideはこちら](https://docs.julialang.org/en/v1/manual/style-guide/#Style-Guide-1)

今日はこの辺で。
RaspberryPiにNode-REDを立ち上げるまで


## やること

[Node-REDをVagrant上で立ち上げて、ブラウザで確認する](https://qiita.com/iganari/items/761b2d2d6403570b7a27) をRaspberryPi上に行います

## 筐体

Raspberry Pi 2 Model B

https://www.amazon.co.jp/dp/B00T356SFO


##  RaspberryPiにrasbianを焼く

### Raspbianをダウンロード

[公式サイト](https://www.raspberrypi.org/downloads/raspbian/)からダウンロード

デスクトップはいらないので、RASPBIAN STRETCH LITE(2018-06-27-raspbian-stretch-lite.zip)の方を使用しました。

## MicroSDにRasbianを焼く

[DD for Windows](http://www.si-linux.co.jp/techinfo/index.php?DD%20for%20Windows) を使用して、データをMicroSDに書き込み。

![dd_for_windows.png](https://qiita-image-store.s3.amazonaws.com/0/25582/621f41e3-4705-b329-e338-fcb4eb7cfad2.png)


### Rasbianの初期設定

+ 上記のMicsoSDをRaspberryPiにセットし、有線LANとUSBキーボードをセットして、起動します。
+ 最初のログイン設定は、以下のよう。(パスワードは適宜変更して下さい)
    + User
        + pi
    + Password
        + raspberry

+ ROOT化

```
sudo su -
```

+ aptの更新と必要なパッケージのインストール
    + 後でSSH接続したいので `openssh-server` もいれる

```
apt-get update
apt-get upgrade
apt-get install -y vim openssh-server
```

+ openssh-serverの起動・自動起動設定

```
systemctl start ssh
systemctl enable ssh
```
```
systemctl status ssh
```

+ IPを確認する

```
ip a
```

---> 以後は、他のクライアントPCからSSHログインして操作する `ssh pi@{RaspberryPiのIP}`

## Raspbianの基本手設定

Debianの基本設定を行う

https://qiita.com/iganari/items/761b2d2d6403570b7a27#debianの基本設定

上記を参考にNode-REDを起動して実行するとこまで行う


##  ブラウザから確認

http://{RaspberryPiのIP}:1880

---> 上記が確認出来ればOK

![nodered-top.png](https://qiita-image-store.s3.amazonaws.com/0/25582/319e0d93-990f-65a3-3d5f-6e380000a84d.png)
PHPは使えるけどWebDAVが使えないレンタルサーバをgitのリポジトリにする

# 概要

ウェブサイト用に使っているエックスサーバーの余った領域をGitのリポジトリにすることを思いついたが、
残念ながらエックスサーバーではWebDAVは標準では使えなかったので、
PHP製のWebDAVサーバの[SabreDAV](http://sabre.io/dav/)を使って構築してみた。

# 環境

* エックスサーバーのX10プラン
* SSHでログインできるように設定済み
* 標準のSSL機能でHTTPSでアクセスするように設定
* GitとPHP7は標準でインストール済み

## SabreDAVの導入

サーバにSSHでログインし、最新の安定版(3.2.2)をダウンロードして展開。

~~~bash
$ wget https://github.com/sabre-io/dav/releases/download/3.2.2/sabredav-3.2.2.zip

$ unzip sabredav-3.2.2.zip

$ mv -r SabreDAV/* ./
~~~

必要なディレクトリを作成してパーミッションを設定。

~~~bash
$ mkdir data public
$ chmod a+rxw data public
~~~

次にBASIC認証用のファイルを作成。
エックスサーバーの場合、`public_html`と同じ階層に`htpasswd`ディレクトリがあるので、そこに置く。
なお、Digest認証だと、ユーザ名とパスワードの自動入力ができなかった。

~~~bash
$ htpasswd -c -b -m .htpasswd username password
~~~

~~~:.htaccess
AuthUserFile ".htpasswd"
AuthName "input your id and passwd"
AuthType Basic
require valid-user
~~~

以下の内容の`server.php`を作成する。

~~~PHP:server.php
<?php

use
    Sabre\DAV;

// The autoloader
require 'vendor/autoload.php';

// Now we're creating a whole bunch of objects
$rootDirectory = new DAV\FS\Directory('public');

// The server object is responsible for making sense out of the WebDAV protocol
$server = new DAV\Server($rootDirectory);

// If your server is not on your webroot, make sure the following line has the
// correct information
$server->setBaseUri('/server.php');

// The lock manager is reponsible for making sure users don't overwrite
// each others changes.
$lockBackend = new DAV\Locks\Backend\File('data/locks');
$lockPlugin = new DAV\Locks\Plugin($lockBackend);
$server->addPlugin($lockPlugin);

// This ensures that we get a pretty index in the browser, but it is
// optional.
$server->addPlugin(new DAV\Browser\Plugin());

// All we need to do now, is to fire up the server
$server->exec();
~~~

`setBaseUri('/server.php');`の部分は、ウェブサーバにアクセスしたときのパス部分(`https://git.example.com/server.php`なら`/server.php`)を指定。

以上ができたら、ブラウザから`server.php`にアクセスして確認。
下のような画面が出ればOK。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/197772/b27f4672-8713-72db-2b1d-cebaf3b41dc1.png)

一応、ブラウザからフォルダの作成とファイルのアップロードは可能。削除はできない。

# リポジトリの作成
## `public`ディレクトリ以下にリポジトリを作成

サーバ側で下記を実行。

~~~bash
$ cd public/
$ mkdir test.git
$ cd test.git/
$ git init --bare
~~~

`git update-server-info`を実行。

~~~bash
$ git update-server-info  
~~~

## ローカルのリポジトリからpushできるようにする

以下はローカルで実行。
ユーザ名とパスワードが平文で書かれてしまうので、毎回入力しても構わない場合は`username:password@`の部分を抜く。
(セキュリティをしっかりやりたい場合はWebDAVではなく、SSHでGitサーバを構築しよう)

~~~bash
# remote追加
$ git remote add origin https://username:password@git.example.com/server.php/test.git
~~~

`push`してみる。

~~~bash
$ git push origin master
Fetching remote heads...
  refs/
  refs/heads/
  refs/tags/
updating 'refs/heads/master'
  from 0000000000000000000000000000000000000000
  to   e516d655aa07fd1ec0cd90b2457af5e054089c5d
    sending 3 objects
    done
Updating remote server info
To https://git.example.com/server.php/test.git
 * [new branch]      master -> master
~~~

できた。

必要であれば、サーバ側で`git update-server-info`を実行するように設定する。

~~~bash
$ mv hoge/hooks/post-update.sample hoge/hooks/post-update
~~~

ただ、私がテストした限りでは、このフックは設定しなくても問題なく`push`や`pull`ができたので、不要かも。
SpyderでgetpassのWarningが表示されるときの応急処置

## 環境
```shell-session
$ cat /etc/issue
Ubuntu 18.04.1 LTS \n \l
$ python3 --version
Python 3.6.5
```

## 症状
[getpass](https://docs.python.jp/3/library/getpass.html) を使用したプログラムを [Spyder](https://www.spyder-ide.org/) を用いてデバックする際， `Warning` が表示され，入力したパスワードが表示されてしまう．

### 例
```python:no_distinguish_getpass.py
import getpass
p = getpass.getpass('Using getpass: ')
print('Read:', p)
```
#### Terminalで実行したとき
```shell-session:Terminalで実行したとき
$ python3 no_distinguish_getpass.py 
Using getpass:  # 入力したパスワードが表示されない（正常）
Read: password
```
#### Spyderで実行したとき

```shell-session:Spyderで実行したとき
Warning: QtConsole does not support password mode, the text you type will be visible.  #  Warningが表示される
Using getpass: password  # 入力したパスワードが表示されてしまう
Read: password
```

## やりたいこと
とりあえず，Spyderではdebugのためだけに使用するため，Spyderで実行してしまった際に，getpassの部分をexceptできるようにする．


## 結論
`if sys.stdin.isatty():` を使用する．

### 理由
[PyMOTW](http://ja.pymotw.com/2/getpass/)によると
> Unix 環境では、 getpass() はターミナル経由で制御できる tty を常に必要とするので表示を無効にできます。これは非ターミナルストリームから標準入力へリダイレクトしてもその入力文字が読み込まれないことになります。
入力ストリームが tty ではないときは呼び出し側で検出して、そのときは代替方法で読み込みます。

という．~~が，いまいち意味が分からん~~

### 例
```python:distinguish_getpass.py
import getpass
import sys

if sys.stdin.isatty():
    p = getpass.getpass('Using getpass: ')
    print('Read:', p)
else:
    print("Could not use getpass")  # ここで，Spyder使用時の動作を決めれば良い
```
#### Terminalで実行したとき
```shell-session:Terminalで実行したとき
$ python3 distinguish_getpass.py 
Using getpass: 
Read: password
```

#### Spyderで実行したとき
```shell-session:Spyderで実行したとき
Could not use getpass
```
一応，Spyderを用いたdebug時の不具合は回避可能となる．

## 参考文献
[getpass – パスワードのために入力文字を表示しないプロンプト](http://ja.pymotw.com/2/getpass/)
Vim —  カット&ペーストではなく単に削除する ( "_d   ) ( クリップボードにコピーしない削除 ) 

`"_d` で可能。

何にこれ？ と思うが、そのとおりにキーを入力すれば良い。

**ダブルクォート・アンダースコア・ディー。**
(「詠唱」、「祈り」、「念じろ」)

削除したテキストは `p` でもペーストされないのが分かる。

## 組み合わせ

- `"_3dd` - 3行をコピーせずに削除

など。


## 呼び方

 `"_` は **ぶらっくほーるれじすたー** というらしい。吸い込まれそうだ。

## 押しにくい

そのままでは押しにくいので、キーマップを登録すると良いっぽい。

>You can setup your own mappings to save typing, of course. I have these:
>
>nnoremap <leader>d "_d
>xnoremap <leader>d "_d
>xnoremap <leader>p "_dP

[copy paste - How to delete (not cut) in Vim? - Stack Overflow](https://stackoverflow.com/questions/11993851/how-to-delete-not-cut-in-vim)



## Version

- Vim version 8.1.250

## あわせてよみたい？

- [Qiitaに記事を書く動機は「ググりにくい記事を、ググりやすく」するためでOK - Qiita](https://qiita.com/YumaInaura/items/e83df9a45836f7b2929b)








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
JuliaをUbuntu16.04にインストールしてみた～Jupyter notebook

# はじめに
Juliaが流行り始めた気がするのでとりあえずいれてみたメモ

# 環境

- Ubuntu 16.04
- Julia 1.0.0

# 参考

- https://www.youtube.com/watch?v=wjfrvLo8QJ4
- https://www.math.uci.edu/~lzepeda/documents/ijulia_installation.pdf
- https://qiita.com/miiton@github/items/33c2b62c4911216d5fdb

# STEP1:公式HPへいってダウンロード

https://julialang.org/downloads/

Ubuntuの場合はこれ
64bitじゃない人もいるので各自確認お願いします

![image.png](https://qiita-image-store.s3.amazonaws.com/0/261584/281e5cef-611d-ce67-8df9-07650b0282b0.png)

# STEP2:コピーしてペースト
ダウンロードしたファイルを解凍

自分がjuliaを置きたいところにフォルダをまとめて移動させる
今回はHOMEにしてます

![Screenshot from 2018-08-20 17-47-21.png](https://qiita-image-store.s3.amazonaws.com/0/261584/4245c950-9d89-cbee-6137-cfeafdace4f0.png)

# STEP3:PATH設定

次にPATHを通します

PATHを通すために自分が移動させたjulia1.0.0のフォルダの中のbinまでいってください

今回だと
home/julia-1.0.0/bin
ですね

![Screenshot from 2018-08-20 17-47-47.png](https://qiita-image-store.s3.amazonaws.com/0/261584/ce65243f-b3d2-fd77-0c05-64a2175f91e0.png)


でそのPATHをコピー

そこでTerminalで

```
sudo gedit etc/environment
```

を実行

なにやらこんな画面が出てくるので

そこに
コロン:を忘れずにいれてから，さっきコピーしたPATHを入れる

こんな感じになります

![Screenshot from 2018-08-20 18-01-58.png](https://qiita-image-store.s3.amazonaws.com/0/261584/bab1c544-bd59-958d-f38d-85a3fef98706.png)


```
PATH="何ならたくさんかいてある...games:/home/"username"/julia-1.0.0/bin"
```

ここでいう

```
:/home/"username"/julia-1.0.0/bin"
```

が追加すべきものです

saveして

ここで必ず
**再起動**
をしてください

# STEP4:Pkg.add('IJulia')する
さてここで，Pkg.addするわけですがまず
さきほどのPATH設定によって，Juliaをインストールできたか確認してください

Terminalで

```
julia
```

と打つとこんな画面！
おしゃれですね

![image.png](https://qiita-image-store.s3.amazonaws.com/0/261584/aa089d7d-dfaa-a357-b4fe-f2e8696edec5.png)

では，Juliaを起動させた状態で（上の画面で）

まず

```
import Pkg
```

と打ちます
これがないといくらaddしてもエラーがでます
**ちなみにWindowsもそうなので気を付けてください**

```
Pkg.update()
```

で終わったら
juliaを起動した状態（上記の画面で）

```
Pkg.add(“IJulia”)
```

で終わると

```
using IJulia
```

```
notebook()
```

の2つのコマンドで，Jupyternotebookが起きます
ので

![image.png](https://qiita-image-store.s3.amazonaws.com/0/261584/7496667e-5aa1-2b72-c902-015953040dd2.png)

これで完了ってわけです

Juliaで実行できてますね！！

![Screenshot from 2018-08-20 18-12-00.png](https://qiita-image-store.s3.amazonaws.com/0/261584/6a4857e0-0eb8-884a-eed0-631544628bfd.png)

# 注意点
たぶん．．．これはpipがインストールされてないといけないかも？

間違っていたら，コメントお願いします
다국어 사이트 이동 조금 꼼수를 부려서 해결함

## 현재 url 을 알아내서 문자열 대체후 원하는 url로 이동하기
요즘 일이 너무 없어서 검도 관련 자료를 알아보고 있었는데
거의 3달만에 일 시킴
다국어 사이트가 있는데 그건도 드림위버로 만들었는지 템플릿에서 수정한면 파일들이 수정됨
이제껏 프로젝트 하면서 이런 종류의 작업은 거의 하지 않았지만

2시간정도 고민함
현재 url 을 알아내서 현재 url 의 문자열을 대체한뒤 url 이동이 중요포인트

```html:qiita.rb
<ul>
   <li class="current guide"><a href="javascript:void(0)" class="btn-lang">日本語-</a></li>
   <li class="eng guide_eng"><a href="javascript:void(0)" class="btn-lang">English</a></li>
   <li class="chi guide_chi"><a href="javascript:void(0)" class="btn-lang">中文</a></li>
   <li class="kor guide_kor"><a href="javascript:void(0)" class="btn-lang">한국</a></li>
   <li class="easy"><a href="../guide_easy/index.html">やさしい日本語</a></li>
</ul>
```

```javascript:qiita.rb

$(function(){

  function langChg() {
  
    var langBtn = $('.btn-lang'); // 버튼에 적용할 class
    var currentUrl = window.location.href; // 현재 url 을 알아낸다
    var currentPath = window.location.pathname.split("/")[1]; // 첫벗째 슬러값뒤의 문자열을 알아낸다
    
    langBtn.on('click', function(){
      
      //japanese 현재 클릭된 부모의 guide 클래스를 가지고 있는경우
      if ($(this).parent('li').hasClass('guide')) {
        //현재 url을 알아내서 currentPath로 알아낸 값을 대체한다
        var newPath = currentUrl.replace(currentPath,"guide");
        //url 이동
        location.href = newPath;

        console.log(newPath);
      }
      //english
      if ($(this).parent('li').hasClass('guide_eng')) {
        var newPath = currentUrl.replace(currentPath,"guide_eng");
        location.href = newPath;
      }
      //chiinese
      if ($(this).parent('li').hasClass('guide_chi')) {
        var newPath = currentUrl.replace(currentPath,"guide_chi");
        location.href = newPath;        
      }
      //korean
      if ($(this).parent('li').hasClass('guide_kor')) {
        var newPath = currentUrl.replace(currentPath,"guide_kor");
        location.href = newPath;        
      }                  
    })
  }  
  langChg() //함수실행
})
```
Python3: PDF の表を csv に変換する

次のページを参考にしました。
[PDFの表を表のまま読み取るには tabula](https://qiita.com/HeRo/items/29596ef2a95f3cb583eb)
[chezou/tabula-py
](https://github.com/chezou/tabula-py)

バッチで変換ができるようにしました。
Arch Linux で確認しました。
>前提ソフトのインストール
Java が必要です。

```bash
sudo pacman -S jdk10-openjdk
sudo pip install tabula-py
```

変換プログラム

```py:pdf_to_csv.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
#	pdf_to_csv.py
#
#					Aug/22/2018
#
# ------------------------------------------------------------------
import	sys
import tabula
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
file_pdf = sys.argv[1]
file_csv = sys.argv[2]

tabula.convert_into(file_pdf, file_csv, pages="all", output_format="csv")
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

サンプルの PDF のダウンロード

```bash
wget http://www.fdma.go.jp/html/life/saigai_densyo/02.pdf
```

実行方法

```bash
./pdf_to_csv.py 02.pdf output.csv
```

変換結果

```text:output.csv
"",都道府,,,
"事例No",市町村名,,言い伝えの内容 趣旨・ポイント,出典(添付資料)
"",県名,,,
012122- 北海道 留萌市,,,堤防へヤナギを植える。 ヤナギの根を張らす事によ,「留萌川の変遷」
1,,,り、堤防に強度を与え、河,(平成5年) 添付
"",,,川を保護する。,資料2-1・P-210
"",,,,「水害を考える」よ
"",,,,り
013676- 北海道 奥尻町,,,地震がきた、高台へ逃げろ。 津波による被害から逃げる,「言い伝え」として
1,,,ための教訓。,の口伝情報のみ
013676- 北海道 奥尻町,,,避難路の確認を日常の合言葉に。 家族で災害時の避難路の確,添付資料2-1を参
2,,,認、待ち合わせ場所の確認,照。
"",,,を常にしていくための教,
"",,,訓。,
013676- 北海道 奥尻町,,,地震が発生したらすぐにドアを開こ 玄関が唯一の逃げ道になり,添付資料2-1を参
3,,,う。 がちなので、逃げ道の確保,照。
"",,,をしておくという教訓。,
013676- 北海道 奥尻町,,,避難は徒歩がいちばん。 車が立ち往生すると避難活,添付資料2-1を参
4,,,動の妨げとなるという教,照。
"",,,訓。,
013676- 北海道 奥尻町,,,火の始末はそれぞれの義務。 地震後の火災はみんなが火,添付資料2-1を参
5,,,の始末を心がけることとし,照。
"",,,た教訓。,
015580- 北海道 上湧別町,,,アイヌ同士の大きな争いが起き、湧別 湧別川は雨が降ればたちま,アイヌ人の言い伝え
1,,,アイヌは遠軽町瞰望岩の砦まで追い詰 ち氾濫する。屯田入植後も,遠軽町史(昭和32年7
"",,,められていたが、夜半の暴風雨で湧別 例年のように悩まされた,月)p35~37(添付資
"",,,川が大洪水を起こし、勝利寸前だった が、その後の徹底した治水,料2-1)
"",,,十勝アイヌを全滅させた。 対策に活かされた。,
"",,,,写真(添付資料2-
"",,,,2)
016918- 北海道 別海町,,,地震雲(飛行機が通過した後のような 地震発生への警戒を促す前,情報のみ
1,,,直線上の雲など)が空に出たらその何 兆現象を示すもの,
"",,,日後かに地震がくる。,
016918- 北海道 別海町,,,ネズミが家屋から逃げるとその家屋は 火災への警戒を促す前兆現,情報のみ
2,,,火災に遭う。 象を示すもの,
024031- 青森県 百石町,,,地震直後、海鳴りがしたら避難する 津波による被害から逃れる,百石町誌(上巻1233
1,,,ための教訓。昭和8年三陸大 頁),
"",,,津波時に古老が触れ回って,
"",,,いた。,
024066- 青森県 横浜町,,,地震がきたら山に避難しろ。 津波からの被害を防ぐ。,「言い伝え」として
1,,,,の口伝情報のみ
024465- 青森県 階上町,,,海の災害としての伝説がある。「鶏に これは防災に係る言い伝え,舘花久二男:「階上
1,,,ほろぼされた村」 とはいえないかもしれない,の昔話」
"",,,が、津波等の海災害にかか,正部家種康:「歴史
"",,,る伝説と考えられる。,と伝説 はちのへ物
"",,,,語」
030007- 岩手県,,,津波てんでんこ 津波による共倒れという悲,山下文男「津波
1,,,劇を防ぎ、生存率を高める,TSUNAMI」1997年、
"",,,ための哀しい知恵,P169-182
030007- 岩手県,,,地震があったら高台に逃げろ。 津波による被害から逃れる,「言い伝え」として
2,,,ための教訓。,の口伝情報及び津波
"",,,,記念碑に残された警
"",,,,句。
030007- 岩手県,,,低いところに住家を建てるな。 津波による被害を防ぐため,「言い伝え」として
3,,,の教訓。,の口伝情報及び津波
"",,,,記念碑に残された警
"",,,,句。
```

次の環境で動作を確認しました。

```text
$ python --version
Python 3.8.2
```
Jenkinsで日付フォーマットを行った所、予期せぬエラーが発生

#予期せぬエラーの状況


- Jenkinsで日付フォーマットを行ったのだが、以下のエラーが発生した。

```
BUILD_TIMESTAMP = new Date().format("yyyy-MM-dd_HH-mm-ss")
```

```
Started by user anonymous
[Pipeline] End of Pipeline
org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use method java.util.Date getDay
	at org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.StaticWhitelist.rejectMethod(StaticWhitelist.java:175)
	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor$6.reject(SandboxInterceptor.java:261)
	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:381)
	at org.kohsuke.groovy.sandbox.impl.Checker$6.call(Checker.java:284)
	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:288)
	at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:29)
	at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
	at WorkflowScript.run(WorkflowScript:7)
```

#調べた結果

- 調べた所、日付を使用する場合は、Script Approval（）を使用して承認する必要があるようです。
https://support.cloudbees.com/hc/en-us/articles/226504048-How-to-use-Date-with-Pipeline-

#対応内容
- 上記、サイトに記載の通り、Approveする事で対応しました。
http://（Jenkinsホスト）/scriptApproval/
にて

signature : method java.util.Date getDayをApproveしました。

![Jenkins-Approve.PNG](https://qiita-image-store.s3.amazonaws.com/0/235774/d9c8a997-7c0e-e97f-f560-2aa61fb15e00.png)
lodash で id 毎に最大値と合計値を一緒の配列で出したい


## やりたいこと

以下のデータを id,name 毎に最大値と合計値を出した配列にしたい。

```javascript
const data = [
  { id: '111', name: 'A', score: 100 },
  { id: '111', name: 'A', score: 50 },
  { id: '222', name: 'B', score: 100 },
  { id: '222', name: 'B', score: 50 },
  { id: '222', name: 'B', score: 70 }
];
```

こんな形にしたい

```javascript
[
  { id: '111', name: 'A', sum: 150, max: 100 },
  { id: '222', name: 'B', sum: 220, max: 100 }
];
```

## コード

実際できたコードはこちら
`name` をもう少し綺麗な形で書きたかったけれどやりたいことはできました。

```javascript
const _ = require('lodash');

const data = [
  { id: '111', name: 'A', score: 100 },
  { id: '111', name: 'A', score: 50 },
  { id: '222', name: 'B', score: 100 },
  { id: '222', name: 'B', score: 50 },
  { id: '222', name: 'B', score: 70 }
];

const result = _(data)
  .groupBy('id')
  .map((obj, key) => ({
    id: key,
    name: _(obj).maxBy('name').name,
    sum: _.sumBy(obj, 'score'),
    max: _(obj).maxBy('score').score
  }))
  .value();

console.log(result);
```
[iOS][Swift] XIBのカスタムビューを生成するときのextention

XIBファイルでカスタムビューを作りコードから呼び出すときに、型を解決した状態でextensionのコードとして一つ用意するいい方法ないかと思って試したら、以下のようなヘ関数が楽でした。

> 注意
> .xibファイルと.swiftファイル名が一致している前提


```swift
import UIKit

/// xibで作成するViewに準拠させる
protocol NibView {
    
    /// Viewのクラス
    associatedtype NibClass
}

extension NibView where NibClass: UIView {
    
    /// NibからViewを生成する
    /// xibファイルのCustom Classに同名のUIViewのクラスが指定されている前提
    ///
    /// - Returns: Viewのインスタンス
    static func generateViewFromNib() -> NibClass? {
        let nib = UINib(nibName: String(describing: self), bundle: nil)
        return nib.instantiate(withOwner: self, options: nil).first as? Self.NibClass
    }

}
```

UIViewのクラス側でプロトコルに準拠

```swift
class FooView: UIView {
  ...
}

// MARK: - NibView

extension FooView: NibView {
  typealias NibClass = FooView
}
```

使い方

```swift
if let fooView = FooView.generateViewFromNib() {
  ...
}
```

## 良くなかった例1

BundleのloadNibNamedはキャッシュされないためパフォーマンスが悪いので、UINibから生成すべきでした。

```swift:UIView+NibExtension.swift
import UIKit

protocol UIViewNibHelper {
}

extension UIViewNibHelper {

    /// NibからViewを生成する
    ///
    /// - Returns: 自身のView
    static func generateViewFromNib() -> Self? {
        let className = String(describing: self)
        return Bundle.main.loadNibNamed(className, owner: nil, options: nil)?.first as? Self
    }
}

extension UIView: UIViewNibHelper {}
```

```swift
// 戻り値はFooView?になる
if let fooView = FooView.generateViewFromNib() {
}
```


## 良くなかった例2

以下の方法ではxibのCusstom Classに設定するのではなく、File's OwnerのClassに同名のClassを指定した場合を前提とします。

```swift
extension UIView {
    
    /// Nibから生成したViewを追加する
    func addContentViewFromNib() {
        let nib = UINib(nibName: String(describing: type(of: self)), bundle: nil)
        let view = nib.instantiate(withOwner: self, options: nil).first as? UIView
        guard let contentView = view else {
            return
        }
        self.addSubview(contentView)
        contentView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            topAnchor.constraint(equalTo: contentView.topAnchor),
            leftAnchor.constraint(equalTo: contentView.leftAnchor),
            rightAnchor.constraint(equalTo: contentView.rightAnchor),
            bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
        ])
    }
    
}
```

一度initするしかなく冗長でした。

```swift
let fooView = FooView(frame: ...)
fooView.addContentViewFromNib()
```
EC-CUBE4の最新ブランチに追従しながら開発していく手順 - GitHub/Git使い方 -

Githubで活発に開発されているプロダクトの最新ブランチに追従しながら開発を進めていくための方法をEC-CUBE4を例に紹介します。

---

# とりあえずFork
とりあえず本家のレポジトリをフォークする

[EC-CUBEのリポジトリ](https://github.com/EC-CUBE/ec-cube)で、右上のForkボタン押す。

---

# 次にclone
自分のレポジトリからcloneする

```shell
$ git clone https://github.com/ユーザ名/ec-cube.git
```

ブランチの状態を確認してみる

```shell
$ git branch -a
* master
  remotes/origin/4.0
  remotes/origin/HEAD -> origin/master
```

これでまずはソースコードをローカルに持ってきました

---

# 本家レポジトリの追従

本家が更新されても追従できるように、本家レポジトリをupstreamとして登録

```shell
$ git remote add upstream https://github.com/EC-CUBE/ec-cube.git
$ git remote -v
origin  https://github.com/ユーザ名/ec-cube.git (fetch)
origin  https://github.com/ユーザ名/ec-cube.git (push)
upstream        https://github.com/EC-CUBE/ec-cube.git (fetch)
upstream        https://github.com/EC-CUBE/ec-cube.git (push)
```

originには自分のが、upstreamには本家が登録されてるのがわかります。
この状態ではまだupstreamの情報を取得していないので一度fetchしておきます。

```shell
$ git fetch upstream
```

---

# 開発する時の流れ

## ローカルに開発用ブランチを作成

```shell
$ git checkout -b ブランチ名 upstream/4.0
```

## GitHubの自分のレポジトリに反映

```shell
$ git push origin ブランチ名
```

---

## 開発する

.
.
.

---

## 完了したらコミット

```shell
$ git add /path/to/file
$ git add /path/to/file
$ git commit -m "コメント"
```

---

## 本家の変更を確認

```shell
$ git fetch upstream
```

何か変更があればとってくる

---

## 本家の変更をマージ

```shell
$ git merge upstream/4.0
```

何か変更があれば、マージする

---

## 自分のレポジトリにpush

```shell
$ git push origin ブランチ名 -f
```

---

# プルリクを送る
GitHubの自分のレポジトリから、PullRequestする

---

# 参考
* https://qiita.com/chihiro-adachi/items/f31c9d90b1bcc3553c20
Soundをループ再生させる

[Audio [sequence] | HTML5](http://labo.project-nya.jp/createjs/sound_sequence/ver0/)
[Sound [sequence] | CreateJS](http://labo.project-nya.jp/createjs/sound_sequence/ver1/)

iOSで見ると、Audioの方は拍手の後、音が鳴らないが、Sound(CreateJS)の方は拍手の後、BGMがループして鳴り続ける。
react-native-qrcode-scannerのAndroidで詰まった話

# はじめに
検証時のデバイスは「Android 7.0」です。

## 詰まった箇所
iOSでは動くが、Androidで動作しない。

「<a href="https://github.com/moaazsidat/react-native-qrcode-scanner" target="_blank">react-native-qrcode-scanner</a>」を使うとこんなエラーがでる

```
FAILURE: Build failed with an exception.

* Where:
Build file '/YOUR_WORKING_FOLDER/react-native-apps/react-native-qrcode-scanner-test/node_modules/react-native-camera/android/build.gradle' line: 8

* What went wrong:
A problem occurred evaluating project ':react-native-camera'.
> Could not find method google() for arguments [] on repository container of type org.gradle.api.internal.artifacts.dsl.DefaultRepositoryHandler.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 1.305 secs
Could not install the app on the device, read the error above for details.
Make sure you have an Android emulator running or a device connected and have
set up your Android development environment:
https://facebook.github.io/react-native/docs/getting-started.html
```

## 解決策
### gradleの更新

gradle-3.5.1-all.zipのままだと、google()がないとかでエラーがでますが
gradle-4.1-all.zipにしたら出なくなりました。

```パス
/YOUR_WORKING_FOLDER/react-native-apps/react-native-qrcode-scanner-test/android/gradle/wrapper/gradle-wrapper.properties
```


```変更内容
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5.1-all.zip
↓
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip

```

### gradleを更新した際は「classpath」もアップデートしないとビルドで失敗します。

```パス
/YOUR_WORKING_FOLDER/react-native-apps/react-native-qrcode-scanner-test/android/build.gradle
```


```変更内容
dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
↓
dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'
```

## 注意
gradleの変更でライブラリーによってはエラーがでるかもなので、導入する際は要注意です。（今の所はエラーにぶつかってないですが。。）


## 参考サイト
- https://stackoverflow.com/questions/50151803/react-native-camera-gradle-sync-failed-could-not-find-method-google-for-argum
- https://github.com/react-native-community/react-native-svg/issues/584
- https://github.com/react-native-community/react-native-camera/issues/1530
リフト曲線を描いてモデルの精度を確かめる 

##リフト曲線の定義
リフト曲線は、機械学習の領域において、モデルの精度を確認する上で役立ちます。
「リフト曲線」の定義は様々ありますが、
私はいつも、書籍『戦略的データサイエンス入門 ビジネスに活かすコンセプトとテクニック』の定義に従って、
リフト値をプロットしたもの、としています。

モデルの何かしらのロジックでインスタンスにスコアが付与され、その降順で並べ替えてスコア上位でフィルタしたときに、
どの程度正しく分類されたインスタンスがあるか、
その割合がランダムな分類器と比べてどの程度高いかを示したのが、リフト値です。

##リフト値の簡単な例
分類問題において、正例と負例が1:1の割合で含まれるデータセットに対してモデルを作成し、
スコア上位25%のところまでのデータを見たとします。
ランダムな分類器だとしたら、その中に正例は半分見つかるはずなので、リフト値は0.5/0.5 = 1です。
ここで別の分類器があり、スコア上位25%の中で正例の割合が95%を占めたとすると、リフト値は0.95/0.5 = 1.9です。
このリフト値を、スコア上位から見ていった時のインスタンス割合を横軸にとってプロットしたものがリフト曲線です。

見ていることは累積反応曲線と同じなのですが、
「ランダムなものより"約2倍の精度"がある」という直観的な言及がしやすいため、
リフト曲線を用いることが個人的には多いです。

##リフト曲線を描くには
リフト曲線を描くためには、
各インスタンスに付与されたスコアと、正例／負例のラベルが必要です。

|スコア|ラベル|
|:-----------------|:------------------|
|0.1248|no|
|0.3422|no|
|0.9123|yes|
|0.7239|yes|
|0.7423|no|
|0.5214|yes|
|・・・|・・・|

##Rで実際に描いてみる

まずは、上記のデータを得るために、
RのC50パッケージに用意されているchurnデータセットを例にモデルを作成します。
（ここでは何も考えずに、caretパッケージを使ってtrain→predictをやってしまいます）

```r
library(dplyr)
library(C50)
library(ggplot2)
library(caret)

data(churn)

# データ確認
str(churnTrain)
str(churnTest)

# モデル作成。スコアを付けたいため、trainControlでclassProbsを適用
fit.glmnnet <- train(churn ~ ., data = churnTrain, method = "glmnet", 
                     trControl = trainControl(classProbs = T))

# 予測の実行
pred <- predict(fit.glmnnet, churnTrain, type = "prob") %>% 
  cbind(select(churnTrain,churn))

str(pred)
# 'data.frame':	3333 obs. of  3 variables:
#  $ yes  : num  0.1372 0.0537 0.1227 0.4423 0.4498 ...
#  $ no   : num  0.863 0.946 0.877 0.558 0.55 ...
#  $ churn: Factor w/ 2 levels "yes","no": 2 2 2 2 2 2 2 2 2 2 ...
```

yesが対象となるスコア、churnが正例／負例のラベルです。
ここからリフト値を計算します。

```r
pred.rownum <- nrow(pred)
instance.ratio <- (1:pred.rownum)/pred.rownum

# スコア降順に並べ替え
pred.arranged <- pred %>% 
  arrange(desc(yes)) %>% 
  mutate(res = (churn=="yes"))

# 該当インスタンスより上位にある正例をカウント
pred.arranged$res.cum <- cumsum(pred.arranged$res)

# リフト値を計算
lift <- 
  (pred.arranged$res.cum/(1:pred.rownum)) / 
  (pred.arranged$res.cum[pred.rownum]/pred.rownum)

# プロット。ついでに lift=1 の線も。
graph.lift <- ggplot() +
  geom_line(aes(x = instance.ratio,
                y = lift)) +
  geom_line(aes(x=c(0,1), y=c(1,1)), color = "red")
print(graph.lift)
```
![Rplot.png](https://qiita-image-store.s3.amazonaws.com/0/169364/f4aee034-4140-d96c-b332-afc17775a8c2.png)

リフト曲線が描けました。
これを見れば、「"3倍の精度"が担保されるのは、インスタンス割合が約2割の地点である」ことがすぐわかり、そのときのスコアも下記のように求めることができます。

```r
# リフト値3のインスタンス割合の算出
sum(lift>=3)/length(lift)
# 0.2118212

# 閾値となるスコアの算出
pred.arranged$yes[sum(lift>=3)]
# 0.2126706
```

##応用、他
複数モデルについて、モデルごとに同じ要領で計算し、色分けして描画すれば、
インスタンス割合とリフト値の関係が一目瞭然になります。

- インスタンスを1割に絞り込むときの最良のモデルは何か
- "5倍の精度"を担保するとき、インスタンス数を最も確保できるモデルは何か

等、複数の軸でモデルの比較検討することができます。

ただ、リフト値は、モデルの精度を示す一つの指標にすぎませんので、
他の指標についても確認する等、多角的に検討すべきであることを最後に付け加えておきます。
MFA設定済みの状態でAWS-CLIを利用する手順メモ

## 前提
* awsに関する知識がそこそこある前提で書きます
* CLIのセットアップが完了していること
* CLIの利用に際して、profileでの切り替えに理解があること
* MFAを設定したIAMアカウントの認証情報が.aws/credentialや.aws/configに記載されていること（profile名をtargetとします）

## いつ実施しますか
MFAが設定されたIAMアカウントからAWSのCLIで操作を行う必要がある際に利用します。

今回の場合、RDSのイベントログがwebコンソール上だと1日分しか表示されないため、
過去分を確認したく、今回に至ります。

cf. [【小ネタ】RDSイベントは直近1日分しか表示されないのでAWS CLIで確認しよう](https://dev.classmethod.jp/cloud/aws/getting-rds-events-by-aws-cli/)

※頻度が高いなら、別の手段の検討がオススメ

## 手順
webでログインするときと同様に、MFAのトークンを準備してください。

以下のコマンドのtoken-codeに、表示されている値を設定してください。

```
$ aws --profile target sts get-session-token --serial-number arn:aws:iam::012345678900:mfa/mesh1nek0x0  --token-code 00000
```

実行すると

```
{
"Credentials": {
    "SecretAccessKey": "secret-access-key",
    "SessionToken": "temporary-session-token",
    "Expiration": "expiration-date-time",
    "AccessKeyId": "access-key-id"
    }
}
```
こういう結果が得られるので、上記の結果を元に.aws/credentialに以下のように追記します

```
[target-mfa]
output = json
region = ap-northeast-1
aws_access_key_id = <Access-key-as-in-returned-output>
aws_secret_access_key = <Secret-access-key-as-in-returned-output>
aws_session_token = <Session-Token-as-in-returned-output>
```

あとは実行したいコマンドでprofileに 今ほど追加した`target-mfa`を指定すればいけます。

```
$ aws rds describe-events --profile target-mfa --duration $(bc <<< "60 * 24 * 7")
```


## 参考
[AWS CLI 経由で AWS リソースへのアクセスを認証するには、どのように MFA トークンを使用したらよいですか?](
https://aws.amazon.com/jp/premiumsupport/knowledge-center/authenticate-mfa-cli/)
Pycharmでターミナル変更


Shell pathに以下を設定する。

```
"C:\Program Files\Git\bin\bash.exe" -login -i
```

![2018-09-06 15_12_40-test [C__Users_masaaki_PycharmProjects_test] - ..._test.py [test] - PyCharm.png](https://qiita-image-store.s3.amazonaws.com/0/64552/934047ff-e674-b809-17be-31df787359ed.png)

#### 参考
<https://www.jetbrains.com/help/pycharm/working-with-system-console.html>
<http://www.tcom242242.site/entry/2018/06/30/175610>
F#で唐揚げ

#趣旨
F#と関数プログラミングの勉強がてら、[唐揚げの問題](
https://qiita.com/stkdev/items/5c021d4e5d54d56b927c)をやってみた。

```
課題：
唐揚げ弁当がいくつかあるとします。それぞれ唐揚げが複数入っています。
この中からｘ個の唐揚げをつまみ食いするプログラムを作りましょう。
つまみ食いはバレないようにするために、
その時点で最も唐揚げ数が多いお弁当から取るという仕様にします。
```

##コード
```fsharp

open System

let stealOne(list:List<int>) = 
    let stole = list.Head - 1
    List.append [stole] list.Tail 

let rec stealing(list:List<int>, times:int) = 
    let stoleList =
        list |> List.sortDescending |> stealOne

    printfn "%A" stoleList

    if List.max stoleList = 0 || times = 1 then
        ()
    else
        stealing(stoleList, (times-1))

[<EntryPoint>]
let main argv = 
    // 何個奪うか(コマンドライン引数から取得)
    let times = int argv.[0]

    printfn "唐揚げを%d回奪い取る" times
    stealing([8;6;10], times)

    Console.ReadLine() |> ignore
    0
```

##実行結果

```
唐揚げを5回奪い取る
[9; 8; 6]
[8; 8; 6]
[7; 8; 6]
[7; 7; 6]
[6; 7; 6]
```

##やってみて
mapとかreduce使わなくても、必要な要素を整理したらシンプルに書けた:grinning:
シンプルに実装しすぎて、結局勉強になってない気がするけども。

- 唐揚げは個数だけ保持したリストで管理
- 最大数は降順ソートさせる
- 先頭の要素を一個減らしたリストを再組立て

ソートさせるのが副作用に含まれるかがよくわからない部分。
元々のものに破壊的変更を加えてないから、副作用は発生していないって考えですが...

もっと綺麗に書けないか悩み中。

##ご意見など
もっと綺麗に書けるよとか考え方おかしいよとか
ご意見ありましたらぜひ教えてください！！:blush:
プログラミングパラダイム/アルゴリズムの講義

#プログラミングパラダイムとアルゴリズム
過去投稿のプログラミングパラダイムの記事と少し重複するところがありますが、
今回講義という形で復習したものからの学びとなります。


##プログラミングパラダイム
プログラミングパラダイムはスタイルや方法である

リソース＝＝＝作りたいもの
この仲介を担うものがプログラミングパラダイムです。

---

###関数型プログラミング
例えば、X=3　Y=３なら常に答えは５という表示がされる。

**メリット**
・副作用が少ない
・テストがしやすい
・プログラムがわかりやすい

---

###オブジェクト指向
部品を作って、部品を組み立てて車を作るイメージ
・クラス（オブジェクトを実装する型）
・インスタンス（クラスから生まれた実体）
・オブジェクト（状態を表すデータと振る舞いを表すメソッドで構成）
・メソッド（関数）
・プロパティ（変数）

**メリット**
・大規模なプログラムを書きやすい
・綺麗に書けば理解しやすいプログラムを書ける
・プログラムの設計に時間がかかる
・きれいに書かないと理解しにくいプログラムになる

---

##アルゴリズム
アルゴリズムは課題を解決する際の思考法のことをいいます。
課題を解決する際の思考のパターンであったり、定石ともいえます。
また計算や作業を遂行するための手順のことです。

###二大検索アルゴリズム
---
**線形検索**
リストや配列に入ったデータの検索を行う。
先頭から順番に検索を行って見つかったら終了する。

**二分探索**
ソート済みのリストや配列に入ったデータにおいて、
検索する間隔を半分に分割しながらデータを検索するアルゴリズム。


###例（Python）
number=[1,10,5,4,2,7,3,9]
というものが与えられた際に、初めから数値を探索するという線形探索をする場合のコードになります。


````Python
for i in range(len(list));
 if(list[i]==3):
  print(i)
  break
```



##オーダー記法
アルゴリズムの性能を評価するための指標になります。
何秒処理にかかったのか。というのではなく、何ステップで処理できたのかを考察する過程になります。

以下幾つかの例になります。

####O(1)
命令数がデータ数に比例する場合。


####O(n)
命令数がデータ数に比例する場合。また、ｎに比例する回数以内のループ処理で終わる場合を指す。
例として、線形探索が挙げられます。

####O(n^2),O(n^3)
2*n^2+4*n+5といった計算量があった場合は、ｎの最大時数を取る。この場合は2*n^2に注目する。
O(n^2)に関して、バブルソートなどが例になります。


####O(logn)
データ数をｎとします。この際に2をステップ数乗した値の定倍値が計算量になります。
また、対数を意味し、二分探索が主な例になります。

##最後に
講師の方曰く、実際に自分でアルゴリズムを作ってみて評価されるのがいいとのこと。
[HackerRank](https://www.hackerrank.com/)といったサイトで学習するといいとのことです。
シェルスクリプトでウェブサイトのダウンタイムを検出する

ウェブサイトにアクセス出来ない時間（ダウンタイム）が発生しないかチェックしたい時にブラウザリロード連打でチェックするのが面倒くさい人向けです。

例えばデプロイ中にダウンタイムが発生しないかチェックしたい場合などに便利かもしれません。

```bash:check.sh
#!/usr/bin/env bash
readonly CHECK_URL="https://example.com/"
while true; do
  status=$(curl -sL --head -m 3 -w "%{http_code}" "$CHECK_URL" -o /dev/null)
  if [ $status = 200 ]; then
    printf '.'
  else
    printf 'F'
  fi
  sleep 0.5
done
```

`CHECK_URL` で設定した URL へ 0.5 秒おきにアクセスして、
レスポンスのステータスコードが 200 だった場合は標準出力に「.」を、
200 以外だった場合は「F」を出力します。

「F」が出てきたらダウンタイムが発生しているなー、「.」に戻ったら復活したなーという感じで可視化できます。終了は CTRL + C キーなどで。
VirtualBoxでどうしてもエラーが解決できない場合にやること

権限回りの問題でVirtualboxの利用で大変苦労している方が結構いらっしゃると思う。
バージョン 4.3.12　が安定性が良いといわれています。

実際に試してみると、確かに安定性が良い感じ！
たまに初回起動でエラーになる場合はあるけど、２回目は成功するので
これぐらいなら使える。
CDS for Apps を試しに使うには

#はじめに
先日日本マイクロソフトの [吉田さん](https://twitter.com/TaikiYoshidaJP) がブログで書いてくださった Common Data Service for Apps を PowerApps で使おうという内容の以下の記事。

**ETLツールとはおさらば！PowerAppsのデータ統合機能とは？**
https://memo.tyoshida.me/powerapps/powerapps-data-integration-feature/

試したい方は上記の吉田さんのブログの手順通りやっていただければよいのですが、おそらく初めて使う方は、「メニューがない！」って言って、いきなり詰まっちゃうと思います。かく言う私も詰まりました。

なので、上記の吉田さんのブログの手順を実施する前に以下を実行していただければーと思い、本記事を書いておきます。
私の備忘録も兼ねてます。

#最初につまるところ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/152946/9314923e-5ca8-9717-8f48-81e2693a4830.png)
おそらく最初に詰まるのは画面の [データ] 以下に「[エンティティ]、[データ統合] がない！」というところだと思います。

これはお使いの PowerApps のアカウントが CDS for Apps を使えないアカウントだからです。
CDS for Apps は Commmon Data Service for Apps の略で PowerApps で Common Data Service を使用する際のデータの入れ物（データベース）のことです。

以下にどのプランなら CDS for Apps が使用できるかの一覧を載せておきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/152946/4fc812c7-5001-0519-6043-cd6d07b464e7.png)
（https://powerapps.microsoft.com/ja-jp/pricing/ から引用）

画像の [Common Data Service for Apps の使用] に〇が付いているプランなら使用可能です。つまり上記の [エンティティ], [データ統合] のメニューが出てくるはずです。これが表示されない人は Office 365 に付帯している PowerApps for Office 365 のプランの可能性が高いです。

**「え、有料のプランじゃないと CDS for Apps は使えないの？」**と思われた方、**正解**です。
自組織内において実運用で使用する場合は、有料のプランを検討してください。
ただし、Office 365 に付帯しているプランのアカウントだったとしても **試す** ことは可能です。

**試す** には **PowerApps Community Plan** という個人向けの使用環境が必要です。Community Plan は実運用はできませんが、PowerApps のすべての機能を試すことが可能です。開発環境や PoC 環境と位置付けるとわかりやすいと思います。また、Community Plan で作成したアプリをエクスポートすることは可能ですので、Community Plan で作成したアプリを十分に試した後に、実運用環境にインポートして使用するというシナリオが可能です。

PowerApps コミュニティ プラン: 個人用の無料開発環境
https://docs.microsoft.com/ja-jp/powerapps/maker/dev-community-plan

PowerApps コミュニティプランのサインアップは以下から可能です。
https://powerapps.microsoft.com/communityplan

#次の手順
さて、上記で Community Plan の準備ができたら、以下の手順で使えるようになります。

1. https://web.powerapps.com/ にサインイン
2. 画面右上で Community Plan の環境に切り替える
![image.png](https://qiita-image-store.s3.amazonaws.com/0/152946/4264124b-b5a1-4f6a-ca6f-488bba438cff.png)
サインインするとアカウントによっては Office 365 for PowerApps プランの環境が最初に開いてしまうことがあります。上記の画像は私の場合ですが、上の2つは Office 365 for PowerApps プランの環境です。Community Plan の環境は一番下のやつです。残念ながら、この名称では区別ができないのですが、おそらく下に表示される方が新しいようなので、今作成した方は一番下を試しにクリックしてください。

3. 左側の [データ] を開いてみて、[エンティティ]と[データ統合]が表示されれば、Community Plan の環境です
4. [エンティティ] をクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/152946/77989bc5-c38b-2706-523c-b74704ecd734.png)

5. [データベースの作成] をクリックしてプロビジョニングが終わるのを待つ（数分～数十分）
6. プロビジョニングが終わったら [データ統合] を開く
![image.png](https://qiita-image-store.s3.amazonaws.com/0/152946/30c92560-c941-d5f4-cac2-bceb53c34e33.png)

7. 画面右上に [新しいデータ統合プロジェクト] が表示されていたら完了です！

ここまで行けば、あとは吉田さんのブログ記事を参考に進められます！
もう一度リンクを載せておきます。

**ETLツールとはおさらば！PowerAppsのデータ統合機能とは？**
https://memo.tyoshida.me/powerapps/powerapps-data-integration-feature/

#おわりに
以上です。今後手順が変わるかもしれませんが、2018 年 8 月 20 日現在ではこの手順で CDS for Apps を試すことができます。
ちなみに私もまだここまでの準備しかやってません。あしからず。

少しでも参考になれば幸いです！
Androidアプリ依存ライブラリの最新バージョン確認方法

# はじめに

Androidアプリ開発していると依存しているライブラリが更新されることがある。
後述のやり方で確認しているけれど、皆どうやってるのか気になったので投稿してみた。

※ バージョンを明示せずに+で最新版を使うdynamic versionsは推奨されてないし面倒なことがあったので使わない。
※ ライブラリアップデートによる影響の有無確認は別の話なので置いとく。

# 環境
- macOS 10.13.6
- Android Studio 3.3

# 確認方法

## 1. build.gradleで指摘されたら更新

`build.gradle` を開くと新しいバージョンが存在することを指摘してくれる。
![スクリーンショット 2018-08-20 15.43.14.png](https://qiita-image-store.s3.amazonaws.com/0/6290/c3c7c273-e2e2-cb3e-82cf-61541478e653.png)

ただ、ここで指摘くれないけれど、新しいバージョンが存在するケースがたまにある。
以下の `com.squareup.okhttp3:okhttp` は現時点だと `3.11.0` が最新バージョンなのに上記ktxのように指摘されない。
![スクリーンショット 2018-08-20 15.18.26.png](https://qiita-image-store.s3.amazonaws.com/0/6290/3ec3369f-1a4f-1a2d-7d44-ec26ac7cf6e8.png)

## 2. Project Structureで確認して更新

「Flie - Project Structure...」(`command`+`;`)で表示できるProject StructureのDependenciesで依存関係を確認できる。
`build.gradle`上では指摘されなかった`com.squareup.okhttp3:okhttp`もここでは新しいバージョンである`3.11.0`が存在することが表示されている。
![スクリーンショット 2018-08-20 15.19.19.png](https://qiita-image-store.s3.amazonaws.com/0/6290/b382aaa8-3f0b-adaf-7c61-fbfc6da23c97.png)
conference-app-2018をビルドしたらエラーになるとき

DroidKaigi2018のアプリを読んでみようと思って手元に持ってきたらビルドでエラーになった。
build.gradleはスクリプトで生成するようになっているので、名前を指定する。

```settings.gradle
rootProject.buildFileName = 'build.gradle.kts'
```
ionic3ビルド時に`FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory`エラーが発生する場合の対処方法

OS: Win 10 64bit v1803
node: v8.9.3
npm: v5.6.0
cordova: v7.1.0
ionic: v3.20.0
Firebase: v5.3.1

# 1. 概要

ionic3プロジェクト内でFirebaseを`v4.12.1`から`v5.3.1`にバージョンアップしてビルドしたら`FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory`エラーが発生した。

```
PS D:\src\002-memo\prod> node --max-old-space-size=6144 ./node_modules/@ionic/app-scripts/bin/ionic-app-scripts.js build
 --prod --aot
[13:32:57]  ionic-app-scripts 3.1.11
[13:32:57]  build prod started ...
[13:32:57]  clean started ...
[13:32:57]  clean finished in 3 ms
[13:32:57]  copy started ...
[13:32:57]  deeplinks started ...
[13:32:57]  deeplinks finished in 99 ms
[13:32:57]  ngc started ...
[13:33:06]  ngc finished in 9.04 s
[13:33:06]  preprocess started ...
[13:33:06]  preprocess finished in 1 ms
[13:33:06]  webpack started ...
[13:33:07]  copy finished in 9.74 s

<--- Last few GCs --->

[12516:0000028A1E113C10]   759259 ms: Mark-sweep 6147.3 (6299.4) -> 6147.3 (6299.4) MB, 5559.8 / 0.0 ms  allocation failure GC in old space requested
[12516:0000028A1E113C10]   765408 ms: Mark-sweep 6147.3 (6299.4) -> 6147.2 (6274.4) MB, 6145.5 / 0.0 ms  last resort GC in old space requested
[12516:0000028A1E113C10]   770207 ms: Mark-sweep 6147.2 (6274.4) -> 6147.2 (6274.4) MB, 4796.8 / 0.0 ms  last resort GC in old space requested


<--- JS stacktrace --->

==== JS stack trace =========================================

Security context: 0000019BC05A5EE1 <JSObject>
    1: setEmitFlags [D:\src\002-memo\prod\node_modules\typescript\lib\typescript.js:~49349] [pc=0000014EA238DB6B](this=000002E5D8228039 <Object map = 000003D4CD9834E9>,node=000000C7E6E703A9 <IdentifierObject map = 000000B3198FE1C9>,emitFlags=16777216)
    3: createEntityNameFromSymbolChain(aka createEntityNameFromSymbolChain) [D:\src\002-memo\prod\node_modules\typescript\lib\typescript.js:2635...

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
```

# 2. 原因

一見Firebaseのバージョンアップで発生したためFirebaseに問題ありそうだが、[Firebaseの中の人の話](https://github.com/firebase/firebase-js-sdk/issues/714)を見るに他に原因がありそう。

詳細な原因は不明だが暫定的な対処方法は見つかった。

# 3. 暫定対処方法

以下のパッケージを追加することで、エラーは発生せずに正常に動作した。

```bash:対処方法
npm install --save @angular-devkit/build-optimizer@0.6.8
```
rubygemがssl接続問題でインストールできなかったときの対処法

nokogiriをインストールしようとした。

```
ERROR:  Could not find a valid gem 'nokogiri' (>= 0), here is why:
          Unable to download data from https://rubygems.org/ - SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A: tlsv1 alert protocol version (https://rubygems.org/latest_specs.4.8.gz)
```

エラーが出てしまった。


```
$ gem source -a http://rubygems.org/
https://rubygems.org is recommended for security over http://rubygems.org/

Do you want to add this insecure source? [yn]  y 　　//yを入力
http://rubygems.org/ added to sources
```

これで解決できました。

###上記方法はセキュアではないみたいなのでコメントにあるやり方のほうがいいようです
プログラミングパラダイム（Programming Paradigms）とは

#プログラミングパラダイム（Programming Paradigms）
プログラミングを学習し始めて、1か月ほど経ちました。
主に、実際に手を動かしたり、言語の勉強をしていました。
このプログラミングパラダイムは概念の部分になります。
そのため取っつきにくかったですが、今まで学習してきたこととつながる部分で理解しておくべき内容でした。
パラダイムとは、ある分野や時代において支配的となる物の考え方や認識のことを指します。

##概要
プログラミングパラダイムは一種のプログラミング様式だと言えます。
例えば、オブジェクト指向型のプログラミングではその考え方に乗っ取ってコーディングしていきます。
命令型のプログラミングであれば、その考え方によって進めていきます。
他にも、宣言型、手続き型と様々なプログラミングパラダイムがあります。
PHPやJAVAなどの言語は、複数のプログラミングパラダイムを持っており、
状況に応じて、単体または複数のパラダイムを用いてコーディングをしていきます。（マルチパラダイムプログラミング言語）

---
###関数型プログラミング
メリットとしては、副作用が少なく、関数相互が影響しあわないことです。
A=5,B=3,の場合は必ずA+B=8となるというのが関数型プログラミングのメリットです。

---
###オブジェクト指向
メリットとしては、部品を作ってそれを組み合わせていくという考え方なので、大規模なシステムを作りやすいというところです。
また、継承の機能があるので簡潔に記述することができるということです。

---

##気付き
学んだ概念を頭に入れながら実際に手を動かすことが必要だなと思いました。
この部分はこのパラダイムがある。というように認識できれば、より綺麗にコーディングが進められるのではと思った次第です。
学習を進めていく過程で、メリットの発見や他のプログラミングパラダイムについて理解を深めた際にはまた更新します。