OmniAICreator/Qiita-1.07M huggingface dataset:
CentOS7+pxe+dhcp（ネットワークブートinstall）-2  postscript sample

    %post
    ## set sudo ##
    cp /etc/sudoers /etc/sudoers.org
    echo 'hoge        ALL=(ALL)       ALL' >> /etc/sudoers

    ### set sshd #####
    cp /etc/ssh/sshd_config /etc/ssh/sshd_config.org
    cat << EOF >> /etc/ssh/sshd_config
    ### change sshd settings #####
    AddressFamily inet
    UseDNS no
    PermitRootLogin no
    PubkeyAuthentication yes
    EOF

    ### set ntp #####
    cp /etc/chrony.conf /etc/chrony.conf.org
    cat /dev/null > /etc/chrony.conf
    cat << EOF >> /etc/chrony.conf
    ### change ntp settings #####
    server 192.168.1.10 iburst
    stratumweight 0
    driftfile /var/lib/chrony/drift
    rtcsync
    makestep 10 3
    bindcmdaddress 127.0.0.1
    bindcmdaddress ::1
    keyfile /etc/chrony.keys
    commandkey 1
    generatecommandkey
    noclientlog
    logchange 0.5
    logdir /var/log/chrony
    EOF

    #snmp setting
    cp /etc/snmp/snmpd.conf /etc/snmp/snmpd.conf.org
    cat /dev/null > /etc/snmp/snmpd.conf
    cat << EOF >> /etc/snmp/snmpd.conf
    ### change snmp settings #####
    rocommunity    hogehoge
    trapCommunity  hogehoge
    trap2sink      192.168.1.11
    com2sec devnet     192.168.1.11  hogehoge
    group   devGroup   v2c           devnet
    view    all        included      .1
    access  devGroup   "" any noauth exact all none none
    EOF

    # mail setting
    cat << EOF >> /root/.mailrc
    set smtp=smtp://192.168.1.11:25
    set from=tst11@hoge.test
    EOF

    # mail alias
    cat << EOF >> /etc/aliases
    root: admin@hoge.test
    EOF
    newaliases
    %end
sedでcsvの先頭行にカラム名を追加する（Mac編）


MacではSedの挙動がLinuxとかとは違ったのでメモ。

## やりたいこと

下記のようなCSVがあったとき、

```csv:test.csv
01,aaa
02,bbb
03,ccc
```

下記のように、1行目にカラム行を追加したい。

```csv:test.csv
no,name
01,aaa
02,bbb
03,ccc
```

通常、エディタで開いて追加すればいいだけの話ですが、ファイルが1億行とかの場合、開くのだけでも大変なので、sedで追加したい。

## やりかた

### 本当は・・・

```bash
sed -i '' '1s/^/no,name\n/' test.csv
```

のようにしたい（linuxではできる）。がMacだと期待通り動かない。どうやらBSD系, Linux系の差らしい。

### Macでは

```bash
sed -i '' '1s/^/no,name\
/' test.csv
```

のように、実際に改行したコマンドを実行する（nは消す）。

なんかダサイけどとりあえず。

### 確認

先頭行を見たい場合、lessコマンドを使うのが結局一番よいらしい。
openpyxl と xlwings の名前付き範囲

# よく使う API の比較

| openpyxl   | xlwings   | 内容    |
|------------|-----------|---------|
|            |           |         |
| [px.workbook.defined_name.DefinedNameList](http://openpyxl.readthedocs.io/en/latest/api/openpyxl.workbook.defined_name.html) | [xw.main.Names](http://docs.xlwings.org/en/stable/api.html#names) | [Names](https://msdn.microsoft.com/ja-jp/vba/excel-vba/articles/names-object-excel) 型相当 |
| [px.workbook.defined_name.DefinedName](http://openpyxl.readthedocs.io/en/latest/api/openpyxl.workbook.defined_name.html)    | [xw.main.Name](http://docs.xlwings.org/en/stable/api.html#name) | [Name](https://msdn.microsoft.com/ja-jp/vba/excel-vba/articles/name-object-excel) 型相当 |
|            |           |         |
| names = wb.defined_names                 | names = wb.names                            | [Workbook.Names](https://msdn.microsoft.com/ja-jp/vba/excel-vba/articles/workbook-names-property-excel) 相当 |
|            |           |         |
| name = names['ブック単位範囲名']            | name = names['ブックorシート単位範囲名']     | ネーム情報 |
| name = names.get('ブック単位範囲名')        |                                            |  |
| name = names.get('シート単位範囲名', False) |                                            |  |
| name.attr_text                             | name.refers_to[1:]   | アドレスを得る   |
| [wb[s][r] for s, r in name.destinations]   | name.refers_to_range | セルor範囲を得る |

# サンプル

## openpyxlサンプル

[本家説明](http://openpyxl.readthedocs.io/en/latest/defined_names.html) がざっくり過げててアレ。

```python
names = wb.defined_names
name = names['ブック単位範囲名']
name = names.get('ブック単位範囲名')
name = names.get('シート単位範囲名', False)
cells = [wb[s][r] for s, r in name.destinations]

# シートインスタンスからも手繰れるが deprecated 扱いになっている
cells = wb['シート名'].get_named_range('ブック単位範囲名')
```

## xlwingsサンプル

```python
rng = wb.sheets['シート名']['範囲名']
```
CentOS7+pxe+dhcp（ネットワークブートinstall）-1

#PXEブートマシンに必要なPackage
	syslinux
	dhcp
	tftp-server
	httpd
	xinetd

#起動プロセス
	httpd
	xinetd	・・tftpはxinetdにて起動
	dhcp

#DHCP.conf
    allow booting;
    allow bootp;

    ignore client-updates;
    set vendorclass = option vendor-class-identifier;

    option pxe-system-type code 93 = unsigned integer 16;

    subnet 192.168.1.0 netmask 255.255.255.0 {
       option subnet-mask         255.255.255.0;
       option dhcp-server-identifier 192.168.1.254;
       option broadcast-address 192.168.1.255;
       range dynamic-bootp        192.168.1.150 192.168.1.159;		　　　←IPレンジの指定
       default-lease-time         21600;
       max-lease-time             43200;
       next-server                192.168.1.11;				　　　　　　　←DHCPサーバ自身のIP
       filename                   "/linux_install/pxelinux.0";　　　　　　    　←PXEメニューのパス
    }

#tftp起動ファイル
     service tftp
     {
         socket_type             = dgram
        protocol                = udp
        wait                    = yes
        user                    = root
        server                  = /usr/sbin/in.tftpd
        server_args             = -c -u root -s /var/lib/tftpboot	　　　←tftpルートディレクトリ
        disable                 = no				　　　　　　　　　　　　←デフォルトはdisableなので、enableに変更
        per_source              = 11
        cps                     = 100 2
        flags                   = IPv4
     }


#PXEブート準備
    /var/lib/tftpboot/linux_install配下に、pxelinux.0や、menu.c32、mboot.c32などのPXEブート用ファイルの配置
    ※syslinuxパッケージからコピーでOK
    下記のような感じ

    # mkdir /var/lib/tftpboot/linux_install
    # cp -rp /usr/share/syslinux/* /var/lib/tftpboot/linux_install/.

    続いて、/var/lib/tftpboot/esx_install配下に、導入したいOSメディアの内容を丸っとコピーする

    # mkdir /mnt/cent7
    # mount -t iso9660 /dev/cdrom /mnt/cent7
    # cp -rp /mnt/cent7/* /var/lib/tftpboot/linux_install/images/cent7/.

    ★上述のbootmenuやlabelを指定した際の実施内容ファイルの修正
    pxelinux.cfgディレクトリを作成する

    # mkdir /var/lib/tftpboot/linux_install/pxelinux.cfg
    # vi default

    default menu.c32
    PROMPT 0
    TIMEOUT 300
    ONTIMEOUT local

    menu title ######## PXE Boot Menu ##########

    label 1
    menu label ^1) Minimal Install CentOS Linux OS 7.3 x64 with local Repository
    kernel images/cent7/vmlinuz
    append initrd=images/cent7/initrd.img inst.repo=http://192.168.1.11/cent7

    label 2
    menu label ^2) Kickstart Install CentOS Linux OS 7.3 x64 with local Repository
    kernel images/cent7/vmlinuz
    append initrd=images/cent7/initrd.img inst.repo=http://192.168.1.11/cent7 ks=http://192.168.1.11/kickstart/cent7_ks.cfg

    :wq!
djangoのインストール（Mac）

##前提条件
MacまたはLinux
pythonインストール済み
##バージョンを決める
https://www.djangoproject.com/download/
ここからインストールするバージョンを決めましょう。

今回はLTS（長期サポート）の最新（2018/2現在）である1.11をインストールします。


##pipのインストール
pipとはpythonのパッケージ管理ツールです。

```
$ pip --version
pip 9.0.1 from /Users/user/.pyenv/versions/3.6.0/lib/python3.6/site-packages (python 3.6)
```

※python3.4以降はpipが付いています


なければcurlで入れましょう。

```
curl -kL https://bootstrap.pypa.io/get-pip.py | python
```


##djangoのインストール

```
$ pip install django==1.11
```

###バージョン確認

```
$ python
Python 3.6.0 (default, Jan  9 2018, 17:49:17)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> django.get_version()
'1.11'
```
UnityのプロジェクトをiOS用にビルドする方法

**実機テストをしたい場合**
[Build Settings] 
iosをクリック　
[Player Settings]で変更したい点を編集
　　　[Resolution and Presentation] / Default Orientation → 画面向き
　　　[Other Settings] →　Bundle Identifiler　を編集しておく　デフォルトだとエラー（？）
Company Nameも変更しておく

Build 
save as ...
Xcodeプロジェクトが作成される。

Xcodeから実機テストする。
右下のopen another projectをクリック
Xcode用のプロジェクトファイル　.xcodeprojeファイルを選択
上のをクリックして実機テストを行うデバイスを選択
この状態でプレイを押す

Xcodeでエラー発生
developmentTeamに登録しろとのこと。（前は入ったよちくしょうめ！！！！）

今のところの解決方法
Unityプロジェクトファイルを一番左のダイアログから開いて、[General]タブでSigningよりTeamを選ぶ。（これ記録しといてくれないの？automaticcallyにはチェック入れてんだけど）
Homebrewのformulaをアップデートする方法



[Homebrew公式](https://github.com/Homebrew/homebrew-core/tree/master/Formula)から，アップデートしたいformulaの.rbファイルを探します．
（`cd $(brew --repository homebrew/core)`でローカル内のFormula保管場所へ移動できるので，そちらを参考にしても問題ありません)

今回は[blast.rb](https://github.com/Homebrew/homebrew-core/blob/master/Formula/blast.rb)を更新したいと思います．

`brew bump-formula-pr`コマンドを使用することで簡単に既存formulaの更新 (forking, committing, pushing等)を行うことができるようです．

既存のblast.rbの中を参考に，アップデートする項目を引数に与えてコマンドを実行します．

```sh
$ brew install hub && brew bump-formula-pr --audit --version=2.7.1 --url=ftp://ftp.ncbi.nlm.nih.gov/blast/executables/blast+/LATEST/ncbi-blast-2.7.1+-src.tar.gz --mirror=ftp://ftp.hgc.jp/pub/mirror/ncbi/blast/executables/blast+/2.7.1/ncbi-blast-2.7.1+-src.tar.gz blast
```

これまでhubコマンドがインストールされていなかった場合，途中でhubのエラーが出る可能性があります．
その場合は`hub -C "$(brew --repo homebrew/core)" fork`を実行してgithubのユーザー名，パスワードを入力してセッティングした後に再度上記コマンドを実行してみてください．
もちろん，既にhubがインストールされている場合は`brew install hub &&`の部分は不要です．

途中でエラーが出てしまい，最初からやり直したい場合は以下のようにしてブランチを削除してみてください．

```sh
$ cd $(brew --repository homebrew/core)
$ git checkout master
$ git branch -D blast-2.7.1
```

### 手動で修正したいとき
```sh
$ git add blast.rb
$ git commit -m "hoge"
$ git push --set-upstream <YOUR_USERNAME> blast-2.7.1
```

### ローカル上での確認
```sh
$ brew install --build-from-source <formula>
$ brew audit --strict <formula>
```


## 参考
https://github.com/Homebrew/brew/blob/master/docs/How-To-Open-a-Homebrew-Pull-Request.md
ESXi+pxe+dhcp（ネットワークブート）

#PXEブートマシンに必要なPackage
	syslinux
	dhcp
	tftp-server
	httpd
	xinetd

#起動プロセス
	httpd
	xinetd	・・tftpはxinetdにて起動
	dhcp

#DHCP.conf
    allow booting;
    allow bootp;

    ignore client-updates;
    set vendorclass = option vendor-class-identifier;

    option pxe-system-type code 93 = unsigned integer 16;

    subnet 192.168.1.0 netmask 255.255.255.0 {
       option subnet-mask         255.255.255.0;
       option dhcp-server-identifier 192.168.1.254;
       option broadcast-address 192.168.1.255;
       range dynamic-bootp        192.168.1.150 192.168.1.159;		　　　←IPレンジの指定
       default-lease-time         21600;
       max-lease-time             43200;
       next-server                192.168.1.11;				　　　　　　　←DHCPサーバ自身のIP
       filename                   "/esx_install/pxelinux.0";　　　　　　　←PXEメニューのパス
    }

#tftp起動ファイル
     service tftp
     {
         socket_type             = dgram
        protocol                = udp
        wait                    = yes
        user                    = root
        server                  = /usr/sbin/in.tftpd
        server_args             = -c -u root -s /var/lib/tftpboot	　　　　　←tftpルートディレクトリ
        disable                 = no				　　　　　　　　　　　　　　←デフォルトはdisableなので、enableに変更
        per_source              = 11
        cps                     = 100 2
        flags                   = IPv4
     }


#PXEブート準備
	/var/lib/tftpboot/esx_install配下に、pxelinux.0や、menu.c32、mboot.c32などのPXEブート用ファイルの配置
	※rhelやcentと同様のsyslinuxパッケージからコピーでOK

	# mkdir /var/lib/tftpboot/esx_install/
	# cp -rp /usr/share/syslinux/* /var/lib/tftpboot/esx_install/.

	続いて、/var/lib/tftpboot/esx_install配下に、導入したいESXiメディアの内容を丸っとコピーする

	# mkdir /mnt/esxi6
	# mount -t iso9660 /dev/cdrom /mnt/esxi6
	# cp -rp /mnt/esxi6/* /var/lib/tftpboot/esxi_install/esxi6/


#esxi6配下のboot.cfgの編集

	まず、booot.cfgの全ての"/"を削除しておく（相対パスのため）
	# sed -i 's/\///g' /var/lib/tftpboot/esx_install/esxi6/boot.cfg

★configファイルの準備
　PXE Bootサーバにて下記ファイルをMAC分（ESXホスト分）準備する

	■bootmenuファイルの準備
	pxelinux.cfgディレクトリを作成する

	例：
	# cd /var/lib/tftpboot/esx_install/pxelinux.cfg/
	# vi 01-xx-xx-xx-xx-xx-xx 　　　　　　　　　　　　　 ←MAC別にconfigファイル準備しておく

		中身：
		DEFAULT menu.c32
		MENU TITLE ESXi-6.0.0-full Boot Menu
		NOHALT 1
		PROMPT 0
		TIMEOUT 80
		LABEL install
		KERNEL esxi6/mboot.c32
		APPEND -c esxi6/boot.cfg ks=http://192.168.1.11/esxi6/01-xx-xx-xx-xx-xx-xx.cfg
		MENU LABEL ESXi-6.0.0-full ^Installer

	■MACアドレスのconfigも準備する
	※MACアドレスの前に01-を付与する

	例：
	# cd /var/www/html/esxi6
	# vi 01-xx-xx-xx-xx-xx-xx.cfg

		中身：
		vmaccepteula
		install --firstdisk --overwritevmfs
		rootpw password
		keyboard Japanese

		network --bootproto=static --ip=192.168.1.73 --gateway=192.168.1.5 --nameserver=192.168.1.47,192.168.1.48 --netmask=255.255.255.0 --hostname=<hostname> --addvmportgroup=1 --vlanid=1001

		reboot

		%firstboot --interpreter=busybox

		vim-cmd hostsvc/enable_ssh
		vim-cmd hostsvc/start_ssh
		vim-cmd hostsvc/enable_esx_shell
		vim-cmd hostsvc/start_esx_shell
		esxcli system module parameters set -m tcpip4 -p ipv6=0
		
		reboot
pythonのインストール（Mac）

Macにはデフォルトでpython2.7が入っています。

```
$ python --version
python 2.7.10

$ which python
/usr/bin/python
```

##Command Line Toolsのインストール
Command Line Toolsをインストールしておきます。
＊バージョンが6.1以降のXcodeをインストールすれば自動でCommand Line Toolsもインストールされます。

```
$ xcode-select --install
```

##Homebrewでpyenvのインストール
pythonのバージョン管理を行うpyenvをインストールします。

```
$ brew install pyenv
```


##インストールするバージョンを確認

```
$ pyenv install --list
```

##インストール

好きなバージョンを指定します。
ここでは3.6.0とします。

```
$ pyenv install 3.6.0
```

##バージョンの切り替え
使うバージョンを切り替えます。

```
$ pyenv global 3.6.0
```

##環境変数（パス）の設定

.bash_profileを編集

```
$ vi ~/.bash_profile
```

以下を追記します。

```
export PATH="$HOME/.pyenv/shims:$PATH"
```

ファイル再読み込み

```
$ source ~/.bash_profile
```
###確認

```
$ python --version
Python 3.6.0

$ which python
/Users/oka.haruna/.pyenv/shims/python


☝︎パスとバージョンが変わっていることを確認
```
angular-cliでCannot find module '@angular-devkit/core'エラーが出た件



# angular-cliでCannot find module '@angular-devkit/core'エラーが出た件

環境：windows

[angular/angular-cli: CLI tool for Angular](https://github.com/angular/angular-cli)

```
ng new PROJECT-NAME
cd PROJECT-NAME
ng serve
```

エラーが出ました

```
C:\Temp\PROJECT-NAME>ng serve
module.js:472
    throw err;
    ^

Error: Cannot find module '@angular-devkit/core'
    at Function.Module._resolveFilename (module.js:470:15)
    at Function.Module._load (module.js:418:25)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (C:\Temp\PROJECT-NAME\node_modules\@angular-devkit\schematics\src\tree\virtual.js:10:16)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)

C:\Temp\PROJECT-NAME>ng --version
module.js:472
    throw err;
    ^
```


以下ページに同様のIssuが立っていました。
[npm update -g @angular/cli](https://github.com/angular/angular-cli/issues/9307)


その中で解決策が以下のように提言されていました。

1. npm update -g @angular/cli
2. editing my package.json changing the line
"@angular/cli": "1.6.0",
to
"@angular/cli": "^1.6.0",
3. npm update
did the trick.


という事で、"^1.6.0"に変更したら動きました。
提言者が「did the trick.」と言ってたようにトリックですね。

```
C:\Temp\PROJECT-NAME>ng --version

    _                      _                 ____ _     ___
   / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
  / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
 / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
/_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
               |___/

Angular CLI: 1.6.8
Node: 7.2.1
OS: win32 x64
Angular: 5.2.4
... animations, common, compiler, compiler-cli, core, forms

以下略
```
NanoPi NEOのCPUの温度を得る　/sys/class/thermal


NanoPi NEOもラズパイなどと同様に/sys/class/thermal/ にある温度センサーでCPUの温度を得られる

```
# cat /sys/class/thermal/thermal_zone0/temp 
39974
```

単位は1/1000℃
1000で割った値が欲しいならば

```
# cat /sys/class/thermal/thermal_zone0/temp |awk '{print $1/1000}'
39.551
```

# カーネルのドキュメント

https://www.kernel.org/doc/Documentation/thermal/sysfs-api.txt

# /sys/class/thermal　を散策してみる

```
# cd /sys/class/thermal/
# ls
cooling_device0  thermal_zone0
# cd thermal_zone0/
# ls
available_policies  integral_cutoff     subsystem           trip_point_2_temp
cdev0               k_d                 sustainable_power   trip_point_2_type
cdev0_trip_point    k_i                 temp                trip_point_3_hyst
cdev0_weight        k_po                trip_point_0_hyst   trip_point_3_temp
cdev1               k_pu                trip_point_0_temp   trip_point_3_type
cdev1_trip_point    mode                trip_point_0_type   type
cdev1_weight        offset              trip_point_1_hyst   uevent
cdev2               policy              trip_point_1_temp
cdev2_trip_point    power               trip_point_1_type
cdev2_weight        slope               trip_point_2_hyst
# cat type
cpu_thermal
# cat mode
enabled
# cat trip_point_3_type 
critical
# cat trip_point_3_temp 
105000
# 
```

105℃が限界の温度のようだ。
仮想通貨の総採掘量を簡単に計算してみよう

# はじめに (注意点)
仮想通貨の総採掘量を**簡単に**計算します。
実際のネットワークやブロックチェーンとは無関係に計算するので、実際の総採掘量とは異なることがあります。

# 計算方法
## 前提
Insightを開いて目に止まった[この](https://insight.bitpay.com/block/0000000000000000005d7c5db804b5c63aff09c3399b178915e4217f3b95249a)ブロックを例に解説します。

Bitcoinフォークの仮想通貨には、*半減期*というものが存在します。
*半減期*とは一定のブロックごとに報酬を半減させるというものです。
例えば、Bitcoinでは、最初は50BTCであった報酬が、210000ブロックごとに半減していき、2018/02/11時点では12.5BTCとなっています。
半減期とは、この210000ブロックを指します。

## 半減期
この半減期ごとに一々計算してはラチがあかないので、0ブロック目から最後の半減期まで一括で計算してしまいます。
最初のブロック報酬を1とすると、そこから半減期ごとに0.5、0.25、0.125...と減っていくことになります。

ですから、    
![image](https://latex.codecogs.com/gif.latex?Reward*%5Csum_%7Bn%3D0%7D%5E%7BN-1%7D%202%5En)    
を計算すれば最後に到達した半減期まで一括で求められます。
(`Reward` = 最初のブロック報酬、`N` = 到達した半減期の回数)
小数点以下切り捨てしてNを求めると、`N = 508677 / 210000 = 2`となりました。
この場合、`50 * 210000 * 1.5 = 15750000`が出てきます。

## 半減期から先
次に、最後に到達した半減期から今までのブロックまでの報酬ですが、これはそこまで難しくないです     
先に、最後に到達した半減期から今までのブロックまでのブロック数を求めてしまいましょう。
割り算の余り使えば簡単ですね。
`508677 mod 210000 = 88677`が出てきました     
これに今のブロック報酬を掛けます。
`88677 * 12.5 = 1108462.5`になりました。

## 最後    
これらの値を合計すれば答えが出てきます。
`15750000 + 1108462.5 = 16858462.5`となります。
これより、これまでに約8割が採掘された事が分かりました。

# 計算機
使用は自己責任でお願いします。
[こちら](https://nao20010128nao.github.io/cc-total-mined/)からどうぞ。
ソースコードは[こちら](https://github.com/nao20010128nao/cc-total-mined/tree/gh-pages)から。
rsyslog設定-メッセージを2重出力させない

#filter掛けた場合、ログが2重出力されないよう編集

---抜粋---
"#### RULES ####
RULE1
$template ClientMessage,"/var/log/systemlog/%fromhost%/%fromhost%.log"
*.*     -?ClientMessage
& ~

"# Log all kernel messages to the console.
"# Logging much else clutters up the screen.
"#kern.*                                                 /dev/console

"# Log anything (except mail) of level info or higher.
"# Don't log private authentication messages!
*.info;mail.none;authpriv.none;cron.none                /var/log/messages
---抜粋---
Oracle COMMENT ON COLUMN 文取得

[Oracle12.2 SQL言語リファレンス COMMENT](https://docs.oracle.com/cd/E82638_01/SQLRF/COMMENT.htm#GUID-65F447C4-6914-4823-9691-F15D52DB74D7) 使用されるOracleのバージョンのマニュアルを確認してからお使いください。

```SQL:comment_on_column.sql
--
--  COMMENT ON COLUMN 文取得
--
-- history
--    2018/03/08 PKG_USERS_SCHEMA 対応  かなり遅くなったような？
--
SET ECHO OFF
SET FEEDBACK OFF
SET HEADING OFF
SET LINESIZE 500
SET PAGESIZE 50000
SET TERMOUT OFF
SET TRIMSPOOL ON
-- SPOOL pass includes CONNECT_IDENTIFIER, USER_NAME and SYSDATE
COLUMN USER_NAME    NEW_VALUE USER_NAME
COLUMN SYSTEM_DATE  NEW_VALUE SYSTEM_DATE
SELECT USER || '_' AS USER_NAME
     , TO_CHAR(SYSDATE, 'YYYYMMDD_HH24MISS') AS SYSTEM_DATE
FROM DUAL ;
SPOOL comment_on_column_&&_CONNECT_IDENTIFIER._&&USER_NAME&&SYSTEM_DATE..sql
-- Windows ↑,  UNIX/Linux では ↓ を有効に
-- SPOOL comment_on_column_\&&_CONNECT_IDENTIFIER._\&&USER_NAME\&&SYSTEM_DATE..sql
COLUMN COMMNET_ON_COLUMN  FORMAT A500
SELECT                                                                               -- ↓ 桁数は現場対応
    'COMMENT ON COLUMN ' || RPAD(TC.OWNER || '.' || TC.TABLE_NAME || '.' || TC.COLUMN_NAME, 81)
 || ' IS ''' || TO_SINGLE_BYTE(TRIM(CM.COMMENTS)) || ''' ; ' AS COMMNET_ON_COLUMN
    FROM(
        SELECT
            TA.OWNER
          , TA.TABLE_NAME
        FROM(
            SELECT COLUMN_VALUE AS OWNER FROM TABLE(PKG_USERS_SCHEMA.GET_USERS_SCHEMA)  -- ユーザーが作成したスキーマのみ
            ) MS
        INNER JOIN DBA_TABLES
        ON  TA.OWNER = MS.OWNER
        WHERE
            TA.DROPPED = 'NO'  -- except trash box, since Oracle10.1.0
        AND TA.TABLE_NAME NOT IN
            (
            'CHAINED_ROWS'  -- except Oracle side table
          , 'EXCEPTIONS'
          , 'PLAN_TABLE'
          , 'PLAN_TABLE$'
            )
        ) A
    INNER JOIN DBA_TAB_COLUMNS
    ON  TC.OWNER      = A.OWNER
    AND TC.TABLE_NAME = A.TABLE_NAME
    LEFT OUTER JOIN DBA_COL_COMMENTS CM
    ON  CM.OWNER       = A.OWNER
    AND CM.TABLE_NAME  = A.TABLE_NAME
    and CM.OWNER       = TC.OWNER
    AND CM.TABLE_NAME  = TC.TABLE_NAME
    AND CM.COLUMN_NAME = TC.COLUMN_NAME
--  WHERE
    --  TRIM(CM.COMMENTS) IS NOT NULL  -- とりあえず、すでにCOMMENTがある列は除く
    ORDER BY
        TC.COLUMN_NAME
      , TC.OWNER
      , TC.TABLE_NAME
    --  TC.OWNER       -- 表示順を変更したい時
    --, TC.TABLE_NAME
    --, TC.COLUMN_ID
;
SPOOL OFF
COLUMN COMMNET_ON_COLUMN  CLEAR
SET ECHO ON
SET FEEDBACK ON
SET HEADING ON
SET LINESIZE 80
SET TERMOUT ON
```
参考
[Oracle 純粋にユーザー側のスキーマのみを取得](https://qiita.com/Papageno/items/2d4ccae4b99d79d0b48b)
Jinja2のwhitespace controlについて

Python(Jinja2)で出力したhtmlについて、[インライン要素で謎の隙間が出てくる問題](https://qiita.com/nabettu/items/f34624d9094276d05e70)  が発生したので、Jinja2側で解決できないか調査。

## アプリケーション側でできる設定
`trim_blocks` `lstrip_blocks` という設定を有効にすることで、ブロックのみの行（ifやfor文）は、スペースや改行を含めて何も出力しないようにできる。

ただし、これらは出力がないブロックのみの行にのみ適用されるもので、その行にhtml要素（タグor文字列）が埋め込まれていたり、ブロックから要素を出力した行には効かない。

```python:foo.py
from jinja2 import Environment
jinja_env = Environment()
jinja_env.trim_blocks = True
jinja_env.lstrip_blocks = True
```

### `trim_blocks`
ブロック（{}）の直後の改行を詰めて出力する

### `lstrip_blocks`
ブロックの手前のスペースを詰めて出力する


## html要素同士の改行スペースを詰める方法
### htmlでコメントアウトする

```html
   <span><!--
-->{{ hoge }}<!--
--></span>
```

### cssで `font-size:0;` にする

```html
<span style='font-size:0;'>
  {{ hoge }}
</span>
```

### Jinja2のテンプレートで強制スペース詰めを行う

```html
<span>
  {{- hoge -}}
</span>
```
enchant.jsで作ったゲームをアプリ化しよう(monaca)

enchant.jsで作ったゲームは、ブラウザ上でそのまま動きますが、せっかくならアプリにしたい。
そこで、先日monacaを使ったアプリ化のテストを行ったので備忘録として書いておきます。

#主な手順
1.作ったゲームをダウンロード
2.monacaにアップロード
3.monacaデバッガでテスト
4.ビルドしてアプリ化

今回はjsdo.itで作ったブロジェクトをアプリ化する手順を説明します。

##1.作ったゲームをダウンロード
Downloadボタンをクリックすると、zipファイルでプロジェクト内のファイルがダウンロードされます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/234600/8074ae28-ef4d-734d-2c77-d5ead75e2d35.png)
jsdo.itの場合、ダウンロードされるのは、html、js、cssのファイルのみなので、必要な画像ファイルやライブラリファイルは別途準備しておく。
##2.monacaにアップロード
###1)インポート
インポートボタンをクリックし、zipファイルをそのまま指定して新規プロジェクトとして読み込みます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/234600/9ef780d1-0c65-5ed4-d1a4-e2dc4df89f09.png)
（GitHubの連携もサポートされています）
###2)ファイル追加
画像ファイルやライブラリを、ドラッグアンドドロップでwwwフォルダに追加します。
追加前
![image.png](https://qiita-image-store.s3.amazonaws.com/0/234600/50b4baac-5ad8-6124-d5bf-cdc8bfe8bd66.png)
追加後
![image.png](https://qiita-image-store.s3.amazonaws.com/0/234600/d6baa526-d0f7-08af-49e0-65f7c145f48e.png)
###3)「保存」ボタンをクリックし更新します。
###4)index.htmlの修正
修正前
```html:index.html
<script type="text/javascript" src="http://jsdo.it/lib/enchant.js-0.8.0/js"></script>
```

修正後：追加したenchant.jsファイルを参照するように変更しました。
```html:index.html
<script type="text/javascript" src="enchant.js"></script>
```

###4)index.jsの修正

```js
// 修正前
var IMAGE_BG = 'http://jsrun.it/assets/K/j/g/A/KjgAq.png';
var IMAGE_BEAR = 'http://jsrun.it/assets/i/b/H/X/ibHXq.png';
var IMAGE_ICON = 'http://jsrun.it/assets/q/P/4/w/qP4wF.png';

// 修正後：追加した画像ファイルを参照するように変更しました。

var IMAGE_BG = 'bg1.png';
var IMAGE_BEAR = 'chara1.png';
var IMAGE_ICON = 'icon1.png';
```

#3.ｍｏｎａｃａデバッガでテスト
スマホやタブレットにmonacaデバッガアプリをインストールしておくと、「実機デバッグ」ボタンでスマホやタブレットでの動作確認が簡単にできます。
#4.ビルドしてアプリ化
##Androidアプリのデバッグ向けビルド
###1)ビルド方法の選択
今回はデバッグビルドを行いました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/234600/cf205f9d-d9f3-a2f4-7642-a20bd47a773d.png)
###2)ビルド完了後apkファイルをダウンロード
![image.png](https://qiita-image-store.s3.amazonaws.com/0/234600/4f8a9b15-9a75-b658-4b5f-279b12c4d294.png)
###3)動作テスト
今回はNoxPlayerを使いました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/234600/c2901b84-e113-fec8-c134-28e58838d86a.png)

#monacaのプラン比較
無料プランの場合、いくつか制限事項がありますので、利用の場合は事前の確認をお勧めします。
https://ja.monaca.io/pricing-detail.html
Oracle JDBC で DB ダウン時の接続タイムアウトを設定する

# 概要

DBCP を使って Oracle に接続しているアプリで、DB ダウン時のテストを行ったところ・・・ OS の TCP 接続タイムアウト時間まで待ってタイムアウトしてしまいました。DBCP の各種タイムアウトをちゃんと設定しているのに・・・

Oracle JDBC でタイムアウト設定が必要だった、という話です。

# ハマってしまった事象

DBCP で以下のタイムアウト設定をしていました。

* maxWaitMillis
* validationQueryTimeout
* defaultQueryTimeout

それぞれ 5-10s に設定し、DB を落としてテストしました。せいぜい 10s でタイムアウトエラーが発生することを期待していたのですが・・・ OS の TCP 接続タイムアウト時間でタイムアウトしました。

# 原因

上記の設定は、コネクションが張られている状態で有効になるようです。
コネクションが張られる前は、socket で connection timeout となるまで待ってしまいます。

# 対応

connection timeout を設定する必要があります。
これは DB により設定方法が異なるようです。

Oracle の場合は DBCP の connectionProperties に以下のように設定します。

```
<property name="connectionProperties" value="oracle.net.CONNECT_TIMEOUT=5000;oracle.jdbc.ReadTimeout=10000"/>
```
※接続タイムアウトを 5s に、読み取りタイムアウトを 10s に設定しています。
AWS DynamoDBのメモ

#前提  
Dynamo初めて触る人向けのDynamoのまとめ  
多分これだけ知ってればDynamoチョトデキル  

#About
DynamoはNoSQLにジャンルされる　KVSである。当然RDBより速い  
機能的には、Redisより少し出来る事が多く、MongoDBより少ない  
速度的には Redisに劣るので、必要に応じてAPI CacheでRedisを建てる  
従量課金なので常時起動するコストがない  

##メリット
フルマネージドなので、設定もデプロイも不要でオートスケーリングする  
死活監視も不要なので、夜もゆっくり寝ることができる  
  
##テーブル仕様
Indexが2個しか指定できない（後述GlobalSecondaryIndexで追加は可能だが制限がある）  
Indexは PartitionKey(PK)のみか、PartititionKey＋SortKey(SK)　のどちらかを設定する必要がある  
Index以外のフィールドは自由（レコード毎にフィールドが違っても問題ない）  
PK（PK+SK）で一意性が保たれる必要がある（Indexが同じレコードはエラー）  

##フィールド（アトリビュート）
基本的には数字か文字列  
日付は文字列なりUNIX Timeにして・・  
バイナリも入る（未使用）  
それらの配列も入れることができる
Booleanもある  
Mal、List、Nullもあるが未使用  


##クエリー
PKは =判定しか出来ない（完全一致オンリー）
Indexはテーブル作成時に設定し、以降変更することが出来ない  
IndexにSKを含めて作成した場合でも PKのみのクエリが可能  
SKでクエリーする場合はかならず PKと併用する必要がある（SK単体のクエリは不可能）  
SKは =、<、<=、>、>=、Betweer、BeginWith（前方一致）　が出来る
SK指定時はソートすることが可能  

##スキャン
全件取ってくるので遅いのでなるべく使わない  
Indexでクエリかけられない場合は後述のGSIも検討すべき

##フィルタ
クエリやスキャンの後、条件でレコードを除外することが出来る  
Indexに指定していないフィールドでも条件一致させられる  
でもクエリ後なので、ヒット件数が多い場合は遅い  

##Update、Insert
Dynamoではアップサートである（同じIndexの項目があればUpdate、なければインサート） 
Update時はフィールドの即値指定以外に計算式が入るため  f = f+5 のようなアトミック計算も可能  
またUpdate時に update if f == 5　のような条件指定も可能  
アトミックカウンタも存在するので、トランザクションが無くてもそれなりの事ができる  

##GlobalSecondaryIndex（GSI）
Indexとは別に 検索用のIndexを作成することが出来る  
Indexと同じく PKあるいはPK+SK で作成することが出来る  
クエリもIndexと同じ  
内部実装は同じテーブルをレプリケーションしているため、GSIを増やすとデータ容量増えるので注意  
投影フィールド（レプリケーションするフィールド）を指定できるので必要なものだけにすること  
Indexと違い キーの一意性は必要ない（PK+SKが同じレコードも作成可能）  

##バッチオペレーション
ReadやInsert、Delete等をまとめることができる  
Dynamoの料金体系は基本的に Read/Write単位で課金されるため（もちろんデータ量もあるが）バッチ処理出来る時はしたほうがお得  
ただし Updateはバッチ処理できません！

##トリガー
Dynamoでレコードの変更があったさい Lambda関数を呼ぶことが可能  
ただし、1秒間に4回ポーリングして変更があったさい起動するようなので、重いかもしれない  

##トランザクション
ない。楽観的なトランザクション  
が、Updateの条件式などを使えば ロックフリー的なことは可能
dynamodb-transactions というのが簡易トランザクション機能を提供する  

##バックアップ
通常S3等に退避させることが多いと思う  
特定リージョンでは オンデマンドバックアップが可能  
テーブルやレコードを削除しても、バックアップから復元することが可能（未使用のため詳細不明）

##グローバルテーブル
他のリージョンとも自動的にレプリケーションされるテーブルを作成することが可能


##DocumentClient（ライブラリ）
AWS.DynamoDB.DocumentClient を使うとほんの少し楽になる  
具体的には、素でDynamoDBライブラリを使うと　すべてのフィールドにたいして "N"　や "S" といった型情報が必要だが、それを省略可能  

```json
"Key": {
  "PK": {"S":"pk"},
  "SK": {"N":1} 
},
```

が

```json
"Key": {
  "PK":"pk",
  "SK": 1 
},
```

と出来る。地味にありがたい
[備忘録]Unity で始める C# セーブについての調べたことまとめ

#「ステージセレクト画面を作って、前のステージをクリアしたら次のステージに進めるようにしたい！」 

**ならどうするか？**
PlayerPrefsを利用する。　--データを保存してくれる機能
→【使い方】
PlayerPrefsとそのメソッドを使って書き込みと読み出しを行う。読み書きの際には**キー**（値を識別するための名前）と**値となる数値や文字列**が必要となる。

```
PlayerPrefs.SetInt ("Test", 100); //Testというキーで書き込み
int v = PlayerPrefs.GetInt("Test"); //testというキーで読み出し
```
メソッドには値を設定する**Set@@@と、値を取得するGet@@@**があり、それぞれにfloat, int, string型の３種類用意されている。
上の例では"Test"というキーを入力することで、100というint型の整数を入手している。

```
void Start () {
		PlayerPrefs.SetInt ("test", 100);
		int i = PlayerPrefs.GetInt ("test");
		Debug.Log (i);
}
```
これで返される値は100。　簡単だね。

---

##では応用編
**ゲームクリア時にクリアしたステージの番号を書き込む処理**をしよう。
すでにステージ４をクリアしているのにステージ１をクリアしたら、クリアしたステージの情報が１に書き換わるのは嫌なので、書き込み済みの値と比較して、それより大きいときだけ書き込むようにする。　

```
//セーブデータ更新
		if(PlayerPrefs.GetInt("CLEAR", 0)<StageNo){
			//セーブされているすてーじNoより今のステージNoが大きければ
			PlayerPrefs.SetInt("CLEAR", StageNo); //ステージナンバーを記録
```
最初はGetIntメソッドは０を返すので問題なし。
いま記録されているステージナンバーより今クリアしたステージのほうがナンバーが上のときだけ、SetIntでそのステージのナンバーが値に更新される。次のステージに行ったとき、最初の行の0は、先程クリアしたステージナンバー＃になっている。

##ちょっと粋な計らい
**ステージクリア後に自動的に画面を移す。**
Invokeメソッドを使って、

```
Invoke("GobackStageSelect",3.0f);
```
第一引数に指定するのはメソッドで、第２引数はその時間後に第一引数を呼び出す。この場合は、事前に

```
void GoBackStageSelect(){
}
```
を作成しているという前提。

---

##どこまでクリアしたかの情報をセレクト画面に反映させる

```
public GameObject[] stageButtons; //ステージ選択ボタン配列

void Start () {
		//どのステージまでクリアしているのかをロード(セーブ前なら０）
		int clearStageNo = PlayerPrefs.GetInt("CLEAR", 0);

		//ステージボタンを有効化
		for (int i = 0; i <= stageButtons.GetUpperBound (0); i++) {
			bool b;

			if (clearStageNo < i) {
				b = false; //前ステージをクリアしていなければ無効
			} else {
				b = true; //前ステージをクリアしていれば有効
			}

			//ボタンの有効・無効を設定
			stageButtons [i].GetComponent<Button> ().interactable = b;
		}
		
	}
```

順に解説していくと、
パブリック変数stageButtonsを追加。
Startメソッド内で、変数clearStageNoを定義、これにはセーブデータが入る。
for文でstageButtonsの配列の要素数になるまでiに１ずつ足していき、iが要素数を超えるまで繰り返し以下の処理を行う。
ちなみに**GetUpperBoundメソッドは、配列変数の要素数を数えるArrayクラスのメソッドで、引数には次元数をセットし、一次元変数の場合は０をいれる。**
bをbool型変数(true or false)として定義し、clearStageNoがiより小さいならbにfalseを代入。
clearStageNoがi以上ならばbにtrueを代入。ここで**for文のカウンターが0から始まっていることに注意。**つまり、ステージ１を表すカウンター変数iは0となるので、clearStageNoが0のときはclearStageNo以下となってクリック可能となる。
つまり可視化するとこういうこと

変数i  | 0 | 1 | 2 |
stage   |未プレイ | 1 | 2 | 3 |
clearstageNo     | 0 | 1 | 2 | 3 |
 

clearstage < i 無効
clearstage >= i 有効

iとclearの値を比較している。なにもクリアしていない状態のときは、０が入っている状態なのでelseの方の処理に入る。ステージ１のカウンター変数は０なので、クリック可能。

trueのときの処理を見てみよう。
bにtrueが代入される。
その後は　true , false でも下の処理に進む。
```
interactable = b;
```
となっている。
これは、**Buttonコンポーネントで、値がfalseのときは、そのボタンはクリックできないようになる。**


###おまけ
動作テストのためにPlayerPrefsに記録したデータを消して初期状態に戻したいときがある。
そのときはプログラムのどこかのStartメソッドに「PlyerPrefs.DeleteAll();」と書いて、一度プレイモードにし、その後に書いたやつを削除する。特定のデータだけ消したい場合はDeleteKeyメソッドを利用する。
npm dedupeでモジュールの重複を解消する

フロントの開発をしている際に独自のライブラリを集めたローカルのモジュールを作成することがあります。
そんなときにローカルモジュールで依存しているモジュールと、使う側でのモジュールが重複してしまうことがあります。

たとえば以下のような構成

```
parent (depends on hoge@1.0.X)
 ├ node_modules
 |  └ hoge@1.0.7
 └ local_modules
    └ child (depends on hoge@~1.0.9)
       └ node_modules
          └ hoge@1.0.10
```

モジュールによっては重複してバンドルしてしまうと思わぬ動作をしてしまいます。
(自分の環境では`Vue.js`が重複してバンドルされてしまいエラーとなった :sweat:)

そんな重複を解決してくれる便利コマンドが**`npm dedupe`**です。
https://docs.npmjs.com/cli/dedupe

上記の構成で`npm dedupe`を実行すると以下のように解消してくれます。

```
parent (depends on hoge@1.0.X)
 ├ node_modules
 |  └ hoge@1.0.10
 └ local_modules
    └ child (depends on hoge@~1.0.9)
```

注意点としてはローカルモジュールをwebpack等を使ってビルドする際に依存モジュールを外から読み込むように設定してください。
ビルドされたjsファイルにモジュールが含まれてたら意味ないですからね :sunglasses:

webpackでモジュールを外部参照する方法は[externals](https://webpack.js.org/configuration/externals/)を参照

# おまけ

[`npm`じゃなくて`yarn`使えば重複はない](https://yarnpkg.com/lang/en/docs/cli/dedupe/)

# 参考サイト

http://yosuke-furukawa.hatenablog.com/entry/2014/06/10/100410
https://docs.npmjs.com/cli/dedupe
https://qiita.com/youkaiantena/items/be4fb46ac7f5af2de2fb
https://yarnpkg.com/lang/en/docs/cli/dedupe/
create-react-app で SourceMap を無効にする

React の開発環境を用意するにあたって [create-react-app](https://github.com/facebook/create-react-app) という便利なツールがありますが，普通に使っていると SourceMap も生成されてしまいます。最近，某サービスで SourceMap が置かれたままになっていて，イケてるUIのソースコードが丸見えという事案もありました。

create-react-app で SourceMap の生成を無効にするには `GENERATE_SOURCEMAP` という環境変数に `false` を設定して build すればよいです。create-react-app では `.env` ファイルが利用できるので，これを使うと便利です。

```bash:.env.production
GENERATE_SOURCEMAP=false
```

https://github.com/facebook/create-react-app/tree/e9abde739240b3124ab7237cbf32a370c209511e/packages/react-scripts/template#advanced-configuration
Amazon Transcribe使ってみた

# 概要
2017/11/30 AWSで文字起こしのPaaSが発表された。
https://aws.amazon.com/jp/blogs/news/amazon-transcribe-scalable-and-accurate-automatic-speech-recognition/

招待制ということでさっそく申し込んだが、いつになってもAWSから承認が降りず、すっかり忘れ去った2018/2/13にAWSからPreview使っていいよ。というメールをもらった。
![スクリーンショット 2018-02-13 13.30.46.png](https://qiita-image-store.s3.amazonaws.com/0/75761/8f1fdc87-8399-c48b-2bb6-10dde83bbe57.png)


ちなみにGCPでは似たようなサービスが既にあり、この点においてはGCPがAWSをリードしている。

# 使い方
S3に音声ファイルを置く。
Amazon Transcribeがそれを読む。
自動で文字起こしされる。これだけ。

# Amazon Transcribeの入力項目
![スクリーンショット 2018-02-13 13.34.17.png](https://qiita-image-store.s3.amazonaws.com/0/75761/7828d9af-0c3e-55bf-8407-f4107ed109b7.png)

1) ジョブ名を決める。
2)  S3のパスを入れる
3) 変換元の言語を選択
4) 音声フォーマットを選択
5) レートを入力(必須ではない)

# Amazon Transcribeの注意するところ
S3にバケットを掘る際、東京リージョンは対象外である。とりあえず米国東部（バージニア）にした。
変換元の音声は現時点で英語,スペイン語の文字起こししか対応していない。日本語は対象外。
音声ファイルはmp3,mp4,wav,flacファイルでなければならない。m4aは対象外。無理やりやってもエラーになるw
Amazon Transcribeから読めるようパーミッションを適宜設定する。

# 変換時間
約25分のmp3データを文字起こしするのに約25分かかった。

# Output
Json形式で出力される。
Laravelでファイルアップロードが失敗する場合の対処法


Laravelで作成したアプリケーションでファイルアップロードしようとしたら失敗しました。
ログを見るとこんなWarningが出力されています。

```
PHP Warning:  POST Content-Length of 20663856 bytes 
exceeds the limit of 8388608 bytes in Unknown on line 0
```
POSTリクエストの中身が8MBを超えてますよっていう内容ですね。
PHPではセキュリティなどの都合でリクエストの上限サイズが設定されています。
上限サイズを変更したい場合はphp.iniの設定を変更する必要があります。

## post_max_sizeを確認する
php.iniファイルを開いて```post_max_size```を探します。

```
post_max_size = 8M
```

これを超えるサイズのリクエストは空になってしまいますので、指定サイズに変更します。

```
post_max_size = 20M
```
大きなファイルをアップロードすると403になってしまったりする場合はこれが原因である場合が多いです。
ログインユーザー情報もリクエストから消えてしまうんですね。


## upload_max_filesizeを確認する
同様にしてphp.iniファイルから```upload_max_filesize```を探します。

```
upload_max_filesize = 2M
```

これを超えるサイズのファイルアップロードは、リクエストの中から<b>ファイルのみ空</b>となってしまいます。
こちらはリクエスト自体は空にならないので注意が必要です。

```
upload_max_filesize = 30M
```

2つの値を設定したら<b>サーバーを再起動する</b>のを忘れないようにしてください。

## それでも改善しない場合
プロジェクトが参照しているphp.iniと異なるファイルを変更しているかもしれません。
```phpinfo()メソッド```を使用して、指定のphp.iniと変更したphp.iniが同じパスのものか確認してください。
会社で少し盛り上がった Project Euler をやってみる 016

# Problem 016

> 215 = 32768 であり, 各位の数字の和は 3 + 2 + 7 + 6 + 8 = 26 となる.
> 同様にして, 21000 の各位の数字の和を求めよ.

https://projecteuler.net/problem=16

---

# Answer 016 (Python)

急にこんな簡単な問題が出てくる。
面白さも一切ない。

```python3
import sys


class Problem16:

    def main(self, n):
        return sum(int(i) for i in str(2 ** n))


if __name__ == '__main__':
    num = 1000
    if len(sys.argv) == 2:
        num = sys.argv[1]
    p = Problem16()
    print(p.main(int(num)))
```
---

# (参考) Project Euler とは

[Project Euler](https://projecteuler.net/) はプログラミングで数学の問題を解くサイトです。問題は600問以上あるので、勉強に使うのも良し、楽しむのも良しです。

サイトに登録すれば、解答を submit することができ、その場であっているか判定してくれます。

また、問題だけであれば、日本語に翻訳された Wiki もあるのでそちらを見ながらやると捗ると思います。

[Project Euler(日本語訳)](http://odz.sakura.ne.jp/projecteuler/)
Oracle COMMENT ON TABLE 文, COMMENT ON MATERIALIZED VIEW 文取得

[Oracle12.2 SQL言語リファレンス COMMENT](https://docs.oracle.com/cd/E82638_01/SQLRF/COMMENT.htm#GUID-65F447C4-6914-4823-9691-F15D52DB74D7) 使用されるOracleのバージョンのマニュアルを確認してからお使いください。

```SQL:comment_on_table.sql
--
--  COMMENT ON TABLE 文, COMMENT ON MATERIALIZED VIEW 文取得
--
-- history
--    2018/04/20 PKG_USERS_SCHEMA 対応  かなり遅くなったような？
--
SET ECHO OFF
SET FEEDBACK OFF
SET HEADING OFF
SET LINESIZE 500
SET PAGESIZE 10000
SET TERMOUT OFF
SET TRIMSPOOL ON
-- SPOOL pass includes CONNECT_IDENTIFIER, USER_NAME and SYSDATE
COLUMN USER_NAME    NEW_VALUE USER_NAME
COLUMN SYSTEM_DATE  NEW_VALUE SYSTEM_DATE
SELECT USER || '_' AS USER_NAME
     , TO_CHAR(SYSDATE, 'YYYYMMDD_HH24MISS') AS SYSTEM_DATE
FROM DUAL ;
SPOOL comment_on_table_&&_CONNECT_IDENTIFIER._&&USER_NAME&&SYSTEM_DATE..sql
-- Windows ↑,  UNIX/Linux では ↓ を有効に
-- SPOOL comment_on_table_\&&_CONNECT_IDENTIFIER._\&&USER_NAME\&&SYSTEM_DATE..sql
COLUMN COMMENT_ON_TABLE FORMAT A1000
--
-- COMMENT ON MATERIALIZED VIEW, TABLE
--
SELECT
    CASE
        WHEN A.COMMENTS IS NULL                -- まだコメントがない
        OR   A.TABLE_NAME LIKE 'MLOG\$_%'      -- MATERIALIZED VIEW LOG
        OR   A.TABLE_NAME LIKE 'RUPD\$_%' THEN -- temporary updatable snapshot log
            '-- '  -- コメント行に
    END
 || 'COMMENT ON '
 || RPAD(A.TABLE_TYPE, 18)            -- ↓桁数は現場対応
 || RPAD(A.OWNER || '.' || A.TABLE_NAME, 45) || ' IS '''
 || A.COMMENTS || ''' ;' AS COMMENT_ON_TABLE
FROM(
    SELECT
        NVL(OB.OBJECT_TYPE, TM.TABLE_TYPE) AS TABLE_TYPE
      , TA.OWNER
      , TA.TABLE_NAME
      , TA.TEMPORARY
      , TO_SINGLE_BYTE(TRIM(NVL(TM.COMMENTS, MM.COMMENTS))) AS COMMENTS
    FROM(
        SELECT COLUMN_VALUE AS OWNER FROM  TABLE(PKG_USERS_SCHEMA.GET_USERS_SCHEMA)  -- ユーザーが作成したスキーマのみ
         ) MS
    INNER JOIN DBA_TABLES TA
    ON  TA.OWNER = MS.OWNER
    LEFT OUTER JOIN DBA_OBJECTS OB
    ON  OB.OWNER       = MS.OWNER
    AND OB.OWNER       = TA.OWNER
    AND OB.OBJECT_NAME = TA.TABLE_NAME
    LEFT OUTER JOIN DBA_TAB_COMMENTS TM
    ON  TM.OWNER      = MS.OWNER
    AND TM.OWNER      = TA.OWNER
    AND TM.TABLE_NAME = TA.TABLE_NAME
    LEFT OUTER JOIN DBA_MVIEW_COMMENTS MM
    ON  MM.OWNER      = MS.OWNER
    AND MM.OWNER      = TA.OWNER
    AND MM.MVIEW_NAME = TA.TABLE_NAME
    WHERE
        TA.DROPPED = 'NO'  -- except trash box, since Oracle10.1.0
    AND TA.TABLE_NAME NOT IN
        (
        'CHAINED_ROWS'  -- except Oracle side table
      , 'EXCEPTIONS'
      , 'PLAN_TABLE'
      , 'PLAN_TABLE$'
        )
    AND OB.OBJECT_TYPE IN('MATERIALIZED VIEW', 'TABLE')
    -- AND TM.COMMENTS IS NOT NULL  -- コメントが設定されていないテーブルのみ
    ) A
ORDER BY 
    A.OWNER
  , A.TABLE_NAME
  , A.TABLE_TYPE ;
SPOOL OFF
COLUMN COMMENT_ON_TABLE CLEAR
SET ECHO ON
SET FEEDBACK ON
SET HEADING ON
SET LINESIZE 80
SET TERMOUT ON
```
参考
[Oracle 純粋にユーザー側のスキーマのみを取得](https://qiita.com/Papageno/items/2d4ccae4b99d79d0b48b)
phpstan を使ったコードの静的解析を CI に取り入れる


## Getting Started 

インストールして、

````
$ composer require --dev phpstan/phpstan
````

対象パスを指定して実行。

````
$ vendor/bin/phpstan analyse src tests
````

あら簡単。

## 設定ファイルの利用

`phpstan.neon` 設定ファイルを作成して、以下のように参照することが出来る。 `-l` はレベルのオプションで　デフォルトは0。　最大で 7まで指定でき数字が大きいとより厳しい検査が実施される。

````
$ vendor/bin/phpstan analyse -c phpstan.neon app -l 0 
```` 

### 過剰なエラーの抑制

設定ファイル内にエラー文言を正規表現で記述してエラーの抑制を設定することが出来る。

````
parameters:
    ignoreErrors:
        - '#Call to an undefined static method App\\Model\\File(set)?::withTrashed\(\)#'
        - '#Call to an undefined static method Illuminate\\Support\\Facades\\DB::[\w]*\(\)#'
````

DBクエリの結果とかを入れる動的なオブジェクトは明示的な宣言をしてやると楽。

````
parameters:
    universalObjectCratesClasses:
        - Illuminate\Database\Eloquent\Model
````

フレームワーク固有の拡張などを入れるのも良い。 

Laravel の場合は以下など。

https://github.com/Weebly/phpstan-laravel

````
$ composer require --dev weebly/phpstan-laravel
````

````
includes:
    - vendor/weebly/phpstan-laravel/extension.neon
````
Amazon Rekognitionで画像ファイルのラベル検出(Python boto3で)

# 概要
Amazon Rekognitionでは様々な画像認識機能が提供されます。
今回はLabel Detect、画像からのラベル検出をPythonから実行するスクリプトを紹介します。
ラベル検出では、例えば例えば海辺の写真なら海、岩、灯台、砂浜などのラベルが検出されます。
[DetectLabels - Amazon Rekognition](https://docs.aws.amazon.com/ja_jp/rekognition/latest/dg/API_DetectLabels.html)

# 前提条件
Rekognitionを実行できる権限としてAmazonRekognitionFullAccessなどを付けたIAMアカウント、もしくはロールを事前に設定しておきましょう。

# スクリプト
Pythonとboto3を使った場合のスクリプト例です。
S3のURLパスを渡す方法と画像ファイルのバイト列を渡す方法があります。今回はバイト列を渡す方法でやってみました。

```python3
# -*- coding: utf-8 -*-
import boto3

#boto3のclient作成、rekognitionとリージョンを指定
client = boto3.client('rekognition','us-east-1')

# 画像ファイルを読み込んでバイト列を取得
with open('sample.png', 'rb') as source_image:
    source_bytes = source_image.read()

# rekognitionのdetect_labelsにバイト列を渡してラベル検出実行
response = client.detect_labels(
               Image={
                   'Bytes': source_bytes
               }
)

# 返ってきたresponseからラベル名(Name)と確度(Confidence)を整形して出力
for label in response['Labels']:
    print("{Name:30},{Confidence:.2f}%".format(**label))
```

# 処理結果
今回はレスポンスのJSONを整形したので以下のような結果が返ります。ラベルとその確度になります

```
Beacon                        ,96.46%
Coast                         ,76.84%
Nature                        ,76.84%
Ocean                         ,76.84%
Outdoors                      ,76.84%
Sea                           ,76.84%
Water                         ,76.84%
Architecture                  ,51.37%
Building                      ,51.37%
Lighthouse                    ,51.37%
Tower                         ,51.37%
Flora                         ,50.57%
Grass                         ,50.57%
Plant                         ,50.57%
```
Ansible 色々

# 日付付きディレクトリ
元ネタ: https://teratail.com/questions/25330

```
vars:
  dir: "/tmp/base_{{ lookup('pipe','date +%Y%m%d%H%M') }}"
```

# ディレクトリ作成
元ネタ: https://qiita.com/hnakamur/items/b5a17d8cb289432014d5

```
file: path="{{ base_dir }}" state=directory

state=directory がキモ
```

# ディレクトリ削除

```
file: path="{{ base_dir }}" state=absent

state=absent がキモ
```

# 一時ディレクトリ作成
元ネタ: https://awsbloglink.wordpress.com/2017/01/24/ansible-2-3-%E6%96%B0%E6%A9%9F%E8%83%BD-tempfile-%E6%A4%9C%E8%A8%BC/

```
- hosts: all
  tasks:
    - name: create tmpdir
      tempfile:
        prefix: ppp
        state: directory
      register: tmpdir
```
VS Codeでファイル末尾に自動的に改行を挿入する設定

```settings.json
"files.insertFinalNewline": true
```

または、設定から `insertFinalNewline` で検索してチェックを付けて有効に
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25818/3a7dbfe2-04a1-e681-1f33-2b53c1051d92.png)
Pageantに秘密鍵をセットして自動起動する(Windows)

## 概要
Windowsを使っているスタッフ向けに、Pageantの設定をメモしておく。
※ この記事は、下記記事で秘密鍵を作成した後の続きとして作成しています。

- [SourceTreeでGithubの認証に秘密鍵を使う (Windows)](https://qiita.com/reflet/items/4f7b5c4a312bc27df10e)

## Pageantの常時起動
Windowsを再起動するとPageantが自動で起動していないので、自動起動するように設定する。

### スタートアップにPageantを登録する
スタートアップのフォルダは以下のところにあります。

```shell
# Windows 7/8/10
C:\Users\ユーザー名\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
```

下記の検索で下記コマンドを実行しても、スタートアップのフォルダが開けるようです。

```shell
shell:startup
```

![01.png](https://qiita-image-store.s3.amazonaws.com/0/142279/5d306ef1-3204-7543-a9eb-dac940bfc7ca.png)
「右クリック」 → 「検索」 をクリックする。

![02.png](https://qiita-image-store.s3.amazonaws.com/0/142279/9af0d5b6-a1b4-6283-5b68-0a5bfd7eebf0.png)
「shell:startup」と入力して、表示される候補をクリックする。

![03.png](https://qiita-image-store.s3.amazonaws.com/0/142279/de9e121a-8d93-62a4-6f33-ef08913c1373.png)
フォルダが開きます。

Pageantのショートカットをコピーします。

![05.png](https://qiita-image-store.s3.amazonaws.com/0/142279/087186f8-fd29-9cab-2095-f4db4875fb49.png)
Pageantを検索し、ファイルの場所を開く

![06.png](https://qiita-image-store.s3.amazonaws.com/0/142279/1211004c-4a90-10ce-60d3-686499247669.png)
Pageantを右クリックしてコピーする

![07.png](https://qiita-image-store.s3.amazonaws.com/0/142279/1a93766d-0a3e-b4b5-8a9e-cfa283c1b1f3.png)
スタートアップのフォルダ内に張り付ける。

張り付けたショートカットを右クリックして、プロパティを確認すると
実際のプログラムは、下記のようなところにあるようです。

```shell
C:\Program Files\PuTTY\pageant.exe
```

### 自動で秘密鍵を読み込ませる
普通にPageantを起動しただけでは、秘密鍵が読み込まれていないので、都度追加が必要となる。
面倒なので、自動で読み込むように設定する。

![10.png](https://qiita-image-store.s3.amazonaws.com/0/142279/30e67d4e-f440-7ce0-98bd-d48a143e86cc.png)
スタートアップに登録したPageantのショートカットを右クリックしてプロパティを選択する。

![11.png](https://qiita-image-store.s3.amazonaws.com/0/142279/c7264b79-23c1-77b4-b2f1-ed09977fac05.png)
「リンク先」の項目にあるパスの最後に、秘密鍵のパスを指定する。

**修正前）**

```
"C:\Program Files\PuTTY\pageant.exe"
```

**修正後）**

```
"C:\Program Files\PuTTY\pageant.exe" "C:\Users\ユーザー名\.ssh\id_rsa.ppk"
```

※ 秘密鍵のパスやファイル名は、各自の作成したパスに変更してください。

以上です。


## 参考サイト
- [スタートアップに登録(Windows10)](https://pc-karuma.net/windows-10-app-startup/)
- [スタートアップに登録(Windows8)](https://pc-karuma.net/windows8-startup-application/)
- [スタートアップに登録(Windows7)](https://pc-karuma.net/windows7-startup-app-add/)
- [pageantを自動起動しつつ秘密鍵も自動的読み込ませる方法](http://fakeyakuza.hatenablog.com/entry/20110726/1311686076)
- [PuTTYのたちあげがめんどくさくなったからPageantとか使ってみたAdd](http://d.hatena.ne.jp/nattou_curry_2/20090110/1231598308)
ディレクトリに対してos.path.getsize()をすると間違った値が返される

ディレクトリ内のファイルの合計サイズ（Windowsで言うところのフォルダを右クリック→プロパティで表示されるサイズ）を取得したいとします。素直にディレクトリに対してos.path.getsize()とすると明らかに異なる値が返されました。

```
＋dir # このディレクトリ以下の合計サイズがほしい
　－file1
　－file2
　－：：
```

環境：Windows7、Python3.6

##例
dirフォルダをエクスプローラーで見たときこうだったとします
![python_dir.png](https://qiita-image-store.s3.amazonaws.com/0/232088/1283947c-e15c-b1df-10de-155e98b96907.png)

###ダメな例

```py3:Python
import os.path

size = os.path.getsize("dir")
print(size) #12288←異なる値
```

os.path.getsize()はバイト数で返されるので、明らかに小さい値です。これはディレクトリのinodeが参照されているためです（後述）。

###良い例
glob.glob()等でファイルリストを取得して、ファイルサイズを合計しましょう。

```py3:Python
import os.path
import glob

files = glob.glob(os.path.join("dir", "**"), recursive = True)
size = sum((os.path.getsize(f) for f in files if not os.path.isdir(f)))
print(size) #13869976←正しい値
```

正しい値が取得できました。Python3.5以降ではglob.glob()の引数に**を指定、recursive=Trueとすることで、サブディレクトリを再帰的に取得することができます（[詳細](https://docs.python.jp/3/library/glob.html)）。
対象のディレクトリ以下にディレクトリが含まれる場合は、if not os.path.isdir(f)のフィルターを入れても入れなくても、若干誤差が出る（エクスプローラーの値とは数KB異なる）ことがありますので、これは好みで入れてください。

##簡単な解説
StackOverFlowにありました。

> This value (4624B) represents the size of the file that describes that directory. Directories are described as inodes (http://en.wikipedia.org/wiki/Inode) that hold information about the files and directories it contains.

ディレクトリは、それ以下に含まれるファイルやディレクトリの情報を持っているinodeとして記されており、os.path.getsize("dir")としたときの値はその[inode](https://ja.wikipedia.org/wiki/Inode)のサイズを参照しているとのこと。

Windowsにはinodeはありませんが、NTFSに似たようなシステムはあるそうです。

関連：os.path.getsize Returns Incorrect Value?
https://stackoverflow.com/questions/10404534/os-path-getsize-returns-incorrect-value
windowsのファイルシステムにiノードという概念はないですよね??
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1334197648
NanoPi NEO用にfluent-bitをクロスビルドする

#fluent-bitとは
http://fluentbit.io/

[Fluentd](https://www.fluentd.org/)のクライアントの軽量版。Fluentdはrubyで書かれていますが、fluent-bitは小さなシステム用にCで書かれています。
これを使うと、いろいろなログデータを簡単にサーバー側にアップロードすることができます。
センサーの計測データはもちろんですが、kernel log, syslog, cpu負荷、memory使用状況なども全部送信しておくと障害解析に役立ちます。

#クロスビルド
今回はNanoPi NEOを題材にしますが、クロスコンパイラさえあれば他のボード向けにも同様にできます。

## クロスコンパイラの準備
クロスコンパイラにはbuildrootで作成した`arm-buildroot-linux-uclibcgnueabihf-gcc` を使用します。buildrootのソースディレクトリの下の`output/host/usr/bin` にPATHを通しておきます。

## fluent-bitのソースの入手

fluent-bitのgitリポジトリからとってきます。
今回は最新版でなくて、他のプロジェクトで使用経験のあるv0.11.x を使用します。

```
git clone https://github.com/fluent/fluent-bit.git
cd fluent-bit
git checkout -b v0.11 v0.11.17
```

## クロスビルド
CMakeはあまり使ったことがなくて作法がよくわかりませんでしたが、試行錯誤した後、次のようにすればソースファイルを一切変更しなくてもクロスビルドできることがわかりました。

```
cd build
GNU_HOST=arm-buildroot-linux-uclibcgnueabihf
CC=${GNU_HOST}-gcc CXX=${GNU_HOST}-g++ cmake -D GNU_HOST=$GNU_HOST ..
make
```

## インストール

デバッガをあてる時のことを想定して、シンボル情報付きの実行ファイルを `_g`のsuffixをつけてコピーし、stripしたものを実機に持っていくことにします。

```
$ cd bin
$ file fluent-bit 
fluent-bit: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, not stripped
$ cp fluent-bit fluent-bit_g
$ arm-buildroot-linux-uclibcgnueabihf-strip fluent-bit
$ ls -l fluent-bit*
-rwxrwxr-x 1 koba koba 2420796 Feb 13 02:41 fluent-bit
-rwxrwxr-x 1 koba koba 3613964 Feb 13 02:41 fluent-bit_g
$ ls -lh fluent-bit*
-rwxrwxr-x 1 koba koba 2.4M Feb 13 02:41 fluent-bit
-rwxrwxr-x 1 koba koba 3.5M Feb 13 02:41 fluent-bit_g
$ 
```

このfluent-bit を実機の`/usr/local/bin`にコピーすればインストール完了。

## 軽く動作確認

NanoPi NEOで

```
# /usr/local/bin/fluent-bit -i mem -o stdout
Fluent-Bit v0.11.17
Copyright (C) Treasure Data

[1970/01/01 00:56:57] [ info] [engine] started
[0] mem.0: [3418, {"Mem.total"=>510556, "Mem.used"=>23276, "Mem.free"=>487280, "Swap.total"=>0, "Swap.used"=>0, "Swap.free"=>0}]
[1] mem.0: [3419, {"Mem.total"=>510556, "Mem.used"=>23276, "Mem.free"=>487280, "Swap.total"=>0, "Swap.used"=>0, "Swap.free"=>0}]
[2] mem.0: [3420, {"Mem.total"=>510556, "Mem.used"=>23276, "Mem.free"=>487280, "Swap.total"=>0, "Swap.used"=>0, "Swap.free"=>0}]
[3] mem.0: [3421, {"Mem.total"=>510556, "Mem.used"=>23276, "Mem.free"=>487280, "Swap.total"=>0, "Swap.used"=>0, "Swap.free"=>0}]
^C[engine] caught signal
# 
```

fluentd に送信できることも確認しました。