OmniAICreator/Qiita-1.07M huggingface dataset:
elasticsearchのindexを整理するcuratorのactionファイルを整理した話

### これは何
elasticsearchのindexを削除するときにはcuratorを使うと思うが、そのactionファイルがわかりにくく、大きくなりがちだったのでメモ。
curator はver 4での記法（ver3だとちょっと違うみたいなので注意）

### curator action fileの基本の書き方
1から順番に実行される。

```
actions:
  1:
    action: delete_indices
    description: "delete application log indices"
    options:
      disable_action: False
      ignore_empty_list: True
    filters:
    - filtertype: pattern
      kind: prefix
      value: "application."  # elasticsearchのindex名と"kind","value"設定が対応するようにする
      exclude: False
    - filtertype: age
      source: creation_date
      direction: older
      timestring: '%Y.%m.%d'
      unit: days
      unit_count: "30"   # 30日残す設定
  2:
    action: delete_indices
    description: "delete indices"
    options:
      disable_action: False
      ignore_empty_list: True
    filters:
    - filtertype: pattern
      kind: prefix
      value: "application."
      exclude: True   # ここでexcludeしておかないと30日保存したいのに10日までになってしまう
    - filtertype: kibana
      exclude: True  # kibanaを使っている場合には入れたほうがよい。.kibanaファイルが消えて、kibana indexを毎回登録しないといけなくなる。
    - filtertype: age
      source: creation_date
      direction: older
      timestring: '%Y.%m.%d'
      unit: days
      unit_count: 10

```

### 削除日数を細かく制御したい場合(ansible templateで解決)
上の例の1の記述のところみたいなのを並べて、さらに2のexcludeにも突っ込んでいかないといけない。コード量が増えて管理しづらい。
ansibleで配置するなら以下のようにすればvarsのリストに追加するだけで簡単。

* varsで以下のように設定する
* 
```
CURATOR_DELETE_LIST:
 - { TARGET: "application."          , DAYS: "30" }
 - { TARGET: "httpd.error."          , DAYS: "30" }
 - { TARGET: "httpd.access.hoge." , DAYS: "7" }
 - { TARGET: "httpd.access.hoge."     , DAYS: "7" }
```

* loopでまわす

```
actions:
{# 明示的な削除対象のためのブロック-#}
{% for t in CURATOR_DELETE_LIST %}
  {{ loop.index }}: 
    action: delete_indices
    description: "delete {{ t.TARGET }} indices"
    options:
      disable_action: False
      ignore_empty_list: True
    filters:
    - filtertype: pattern
      kind: prefix
      value: "{{ t.TARGET }}"
      exclude: False
    - filtertype: age
      source: creation_date
      direction: older
      timestring: '%Y.%m.%d'
      unit: days
      unit_count: "{{ t.DAYS }}"
{% endfor %}

{# .kibana を除くその他の index は 10 日間保持。最後のactionになるように99としておく。 #}
  99: 
    action: delete_indices
    description: "delete indices"
    options:
      disable_action: False
      ignore_empty_list: True
    filters:
{% for t in CURATOR_DELETE_LIST %}
    - filtertype: pattern
      kind: prefix
      value: "{{ t.TARGET }}"
      exclude: True 
{% endfor %}
    - filtertype: kibana
      exclude: True
    - filtertype: age
      source: creation_date
      direction: older
      timestring: '%Y.%m.%d'
      unit: days
      unit_count: 10
```
もっとまとめて綺麗にできるかも。でもまあ役割ごとにブロックで分けれたからよし。
D言語で半角・全角含めた文字幅を取得するeast_asian_width

# はじめに

昨年のアドベントカレンダーで、[d-man{say,think}](https://qiita.com/simd_nyan/items/778fb22135b68e873781#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB)を開発しました。
ところが全角文字に対応していませんでした。

```shell-session
$ d-mansay D言語くんだよ
 _____________________
< D言語くんだよ             >
 ---------------------
    \    _   _
     \  (_) (_)
       /______ \
       \ (O(O \/
        | | | |
        | |_| |
       /______/
         <   >
        (_) (_)
```

そこで今回は全角文字に対応させます。

# east_asian_width

文字通りのdubパッケージがあります。
https://code.dlang.org/packages/east_asian_width
READMEから使い方を抜粋します。

```d
import eastasianwidth;

assert(displayWidth("あいうえお") == 10);

// '☆' is Ambiguous character
assert(displayWidth('☆') == 1);
assert(displayWidth('☆', AmbiguousCharWidth.wide) == 2);
assert(displayWidth("☆D言語くん☆") == 11);
assert(displayWidth("☆D言語くん☆", AmbiguousCharWidth.wide) == 13);

assert(eastAsianWidth('Ａ') == EastAsianWidthProperty.F); // Fullwidth
assert(eastAsianWidth('ｱ') == EastAsianWidthProperty.H);  // Halfwidth
assert(eastAsianWidth('ア') == EastAsianWidthProperty.W); // Wide
assert(eastAsianWidth('A') == EastAsianWidthProperty.Na); // Narrow
assert(eastAsianWidth('☆') == EastAsianWidthProperty.A); // Ambiguous
assert(eastAsianWidth('À') == EastAsianWidthProperty.N);  // Neutral
```
`displayWidth('☆', AmbiguousCharWidth.wide)` を使ってあげれば良さそうです。

# Improve d-man{say,think}

というわけで[実装](https://github.com/simdnyan/d-mansay/commit/d26aa9e5d1075f42447c18722625c5dff7f09e73)しました。

```shell-session
$ d-mansay 新しいD言語くんは日本語が流暢だよ -W 17
 ___________________
/ 新しいD言語くんは \
\ 日本語が流暢だよ  /
 -------------------
    \    _   _
     \  (_) (_)
       /______ \
       \\(O(O \/
        | | | |
        | |_| |
       /______/
         <   >
        (_) (_)
```

# 参考

* [文字列の長さを取得するときはlengthを使ってはいけない](https://kotet.github.io/2016/12/23/b6f1630928af176147e4.html)
memcachedのサイズ別データ数のカウント

### これは何
memcachedからredisへ移行したいので、redisのベンチマークを取っていたが、その時にmemcachedに保存されているデータがどれくらいのサイズがどれくらいの量で出現するのか確認した。その話を適当にまとめておく。

### chunkサイズとslabについて
参考： http://gihyo.jp/dev/feature/01/memcached/0002


memachedはメモリのフラグメンテーションを防ぐために slab allocator というのを使っているっぽい。単にmalloc と freeを使ってメモリを扱うとばらばらになってしまう。確保したメモリをいろいろなサイズの塊(chunk)にわけて同じサイズの塊をクラスとしてひとまとまりにする。stats itemの出力はどうもこのchunk別に別れている模様。

#### class別個数カウント

```
$ echo "stats items" | nc localhost 11211    | grep number
STAT items:1:number 6
STAT items:2:number 4990
STAT items:3:number 1
STAT items:4:number 39
STAT items:5:number 160
STAT items:6:number 3
STAT items:7:number 17
STAT items:8:number 19
STAT items:9:number 46
STAT items:10:number 1
STAT items:11:number 5326
STAT items:12:number 1397
STAT items:13:number 60
以下略
```
このコマンドは↓でもよい

```
$ echo "stats slabs" | nc localhost 11211  | grep used_chunk
```

#### classのサイズを確認する

上からサイズ順になっている。

```
$ echo "stats slabs" | nc localhost 11211  | grep chunk_size
STAT 1:chunk_size 96
STAT 2:chunk_size 120
STAT 3:chunk_size 152
STAT 4:chunk_size 192
STAT 5:chunk_size 240
STAT 6:chunk_size 304
STAT 7:chunk_size 384
STAT 8:chunk_size 480
STAT 9:chunk_size 600
STAT 10:chunk_size 752
STAT 11:chunk_size 944
STAT 12:chunk_size 1184
STAT 13:chunk_size 1480
以下略
```


#### トータル個数とか一定サイズ以上のものとか
```
$ echo "stats slabs" | nc localhost 11211  | grep used_chunk | awk 'BEGIN {num = 0};{ sum =+ sum + $3} END {print sum }'

```

大きいサイズの個数が知りたいななど。例えばclass 19以上のもの（size 5kでの区切りで見たやつ）

```
$  echo "stats slabs" | nc localhost 11211  | grep used_chunk | egrep "(STAT 19|STAT [2-4][0-9])" |  awk 'BEGIN {num = 0};{ sum =+ sum + $3} END {print sum }'
```
redisとmemcachedのベンチマークをmemtier-benchmarkで取る

### これは何
redisとmemcachedのベンチマークを memtier-benchmark というツールで取った。
ざっくりまとめておく。

https://github.com/RedisLabs/memtier_benchmark


### memtier-benchmark と redis-benchmark の比較
主にmemtier-benchmarkのメリット。redis-benchmarkにできないこと。

* redis, memcache の両方のプロトコルを喋れる（redis-benchはredisのみ）
* SET/GETの重み付けができる（redis-benchはそれぞれ別に全力で投げる）
* keyとvalueサイズを変えられて（redis-benchはkeyサイズを変えるのが大変。valueサイズはどちらもオプションで変えられる。）

### memtier-benchmark のインストール
概ねREADMEどおりにできた。
インストールしたlibevent-2.0がmemtier-benchmark実行時に見つからなかったので雑にlinkして見えるようにした（多分良い解決策ではないが、使い捨て負荷試験環境なので良し）。

```
sudo ln -s /usr/local/lib/libevent-2.0.so.5 /usr/lib64/libevent-2.0.so.5
```

### コマンド

```
memtier_benchmark -p 6379 -P redis --threads 4 -c 250  --test-time=10 --ratio=1:10 --data-size-list=1000:60,5000:30,100000:10  --key-prefix=memtier-memtier-memtier- --key-maximum=100000
```
実際にやったコマンドとは異なるが、サンプルとして書いておく。以下雑な説明

* -p port
* -P protocol
* --threads クライアントのスレッド数
* -c スレッド数あたりのコネクション数。トータル4*250=1000となる
* --test-time テスト時間
* --data-size-list.  今回はmemcachedからredisへの移行が目的。現行のmemcachedのデータに合うようにweightを決めた（別記事として書くかもしれない）
* --key-prefix  key長を適当に調整するために使える
* --key-maximum  キーのバリエーションになると思う
micro:bitの電源供給について

こんにちは。
NaKaTaFuです。
microbit Advent Calendar 2017 の６日目です。


今日は、micro:bitの電源について確認して行きたいと思います。
所謂 NeoPixel LED、WS2812Bは最大輝度で50mAの電流を消費します。
デバイスの供給電流に制限がある場合は、多数のWS2812Bを使う場合はプログラムで同時点灯数や輝度を調整する必要があります。

micro:bit本体経由でエッジコネクタに電源を供給する場合は、取り出せる電流を良く確認の上、プログラムを工夫(brightnessの調整など)する必要があります。

micro:bitの電源供給についての仕様は、
http://tech.microbit.org/hardware/powersupply/
に記されていますので、これをじっくり読んで、どうすればどれくらいの電流が取り出せるのか、確認してみました。

#電源概要
電源供給方法は大きく３つに大別されます。
1. USBポートから供給
2. 電源コネクタ(PHコネクタ)から供給
3. エッジコネクタから供給

それぞれについて、自分なりにまとめたものを以下に示します。

| 供給方法         | 供給電圧範囲(V) | 供給電圧(V)|エッジコネクタ供給可能最大電流(mA) |
|:----------------|----------------:|:----------------:|:-------------------------:|
| USBポート(>3.6V) | 5 (3.6～5.5)   |3.3                | 90mA                      |
| USBポート(<3.6V) | (2.7～3.6)     | 入力電圧-(0.1～0.2)| 90mA                      |
| PHコネクタ       | 3 (1.9～3.6)   | 入力電圧-(0.1～0.2)| 供給側制限と3Aの小さいほう  |
| エッジコネクタ    | 3 (1.7～3.6)   |入力電圧            |供給側制限                 |

#USBから供給する場合
USB I/FのKL26が内蔵しているレギュレータを使ってmicro:bit用の3.3Vが生成されます。
逆流防止用のダイオードBAT60を経由して他のデバイスに供給されます。
KL26のレギューレータにかけられる電圧は2.7～5.5Vとなります。供給電圧が3.6V以上の時に供給される電圧は3.3V, それ以下の場合はパススルーモード(ほぼ入力電圧を供給)として動作します。この値からBAT60の電圧降下(0.1～0.2V)を引いた電圧が回路に供給されます。

KL26のレギュレータが供給可能電流の最大値は120mAとなっています。ただし、micro:bitボード上のデバイスで30mAを最大使用するので、エッジコネクタ等から取り出して使用出来るのは最大90mAとなります。

#電源コネクタ(PHコネクタ)から供給
逆流防止用のダイオードBAT60を経由して他のデバイスに供給されますので、供給される電圧は0.1～0.2V電圧降下します。
ボード上のデバイスの動作下限とBAT60の電圧降下を考慮すると、最低電圧は1.9Vとなります。
センサー類の最大電圧が3.6Vですので、3.7V以上を供給するとmicro:bit上のデバイスを壊す可能性があります。

オフィシャルサイトには、Li-Poバッテリはフル充電時に4.2Vを超えるので直結するとメインデバイスのnRF51822を壊す可能性があると記載されています。PHコネクタからの供給は電池での供給に留めるのが良いでしょう。
BAT60の順方向最大電流は3Aですので、この場合でもエッジコネクタにそれを超えるようなデバイスを接続することはできません。

参考：
乾電池電流目安 ： http://ecwkit.nomaki.jp/shiryou/batt.htm
コイン電池電流目安 ： https://ja.wikipedia.org/wiki/%E3%82%B3%E3%82%A4%E3%83%B3%E5%BD%A2%E3%83%AA%E3%83%81%E3%82%A6%E3%83%A0%E9%9B%BB%E6%B1%A0

#エッジコネクタから供給
エッジコネクタから供給する場合、回路の直接電圧がかかります。電圧はボード上の電圧制限値に収める必要があります。電流は、特に制限はありません。

#参考資料
- USB I/Fに使われているKL26のデータシート : https://www.nxp.com/docs/en/data-sheet/KL26P64M48SF5.pdf
- BAT60ダイオードのデータシート : https://www.infineon.com/dgdl/Infineon-BAT60ASERIES-DS-v01_01-en.pdf?fileId=db3a304313d846880113def70c9304a9
redisのリバプロとしてhaproxy設定

### これは何
redis+sentinelの前段にhaproxyを置いてクライアントがあんまりnode poolを意識しなくてもよさそうな感じにしたい。

### 方針
redis slaveにgetを負荷分散したりするほど負荷は高くない系に使えるかも。
常にmasterに接続しに行き、slaveは待機系。

### 設定ファイル
ansible templateの形。

```
global
  {# chroot内で動いているため/dev/logへアクセスできない。そのためUDP経由でrsyslogにログを渡す。-#}
  log         127.0.0.1 local2
  chroot      {{ HAPROXY_JAIL_DIR }}
  user        {{ HAPROXY_USER }}
  group       {{ HAPROXY_GROUP }}
  daemon
  {# maxconn: redisで設定しているものより大きければよい。このレイヤでは特に制限はかけない。 -#}
  maxconn     10000

{# stats: haproxyのステータスを取れるようにするための設定 -#}
listen stats 
  {# bind: ポート9000への外部からの経路はないが念のためback側からのみ疎通可能としておく。-#}
  bind :9000 interface eth0
  mode http
  stats enable
  stats uri /haproxy_stats 
  {# refresh: stats画面の自動リフレッシュを有効にする -#}
  stats refresh 10    

defaults
  mode                    tcp
  log                     global
  option                  dontlognull
  {# retries: バックエンドサーバへ接続失敗した時の再試行回数-#}
  retries                 3
  {# timeout queue: maxconnを超えたリクエストはキューに入る。そのキューに入った接続を開放するまでの時間。そんなに待たせても意味が無いのであまり大きな値じゃなくてよい。 -#}
  timeout queue           10s
  {# timeout connect: haproxyのbackendへの接続のタイムアウト。近いネットワークにいれば基本的に短い時間で接続できるはず。 -#}
  timeout connect         5s 
  {# timeout check: コネクションが確立したあとの追加のヘルスチェックのタイムアウト。これに時間がかかるということはラグの大きなサーバなので、長い時間待つ必要はない。-#}
  timeout check           5s
  {# timeout client-fin/server-fin: 正しく接続断しなかった場合に切る（こちらからFIN送信したがクライアントがFINを送ってこなかった場合）。FIN_WAIT状態が続くのを防ぐ。 -#}
  timeout client-fin      10s
  timeout server-fin      10s

{# その他入れない設定について。いれるのが推奨のようなので要検討。
* timeout client: 非活性なクライアントからの接続を切る設定。redis設定に合わせて設定しない。 
* timeout server: haproxyから非活性backendへの接続を切る時間。redis設定に合わせて設定しない。 
-#}


frontend  main
  bind *:5000
  default_backend             myredis

backend myredis
  {# balance: どれか１台だけがコネクションを受け付ける設定(first)。id設定があれば一番値が小さいもの。なければリストの１番上から優先される。負荷分散よりも１台のmasterにキャッシュがのることを優先する。 -#} 
  balance    first
  {# 通常時のヘルスチェック間隔はredisのマスター昇格のタイムスケールにあわせて秒単位でよい。haproxyのreload直後などでヘルスチェックをしていない場合には即座に行う(fastinter)。-#}
  {% for srv in HAPROXY_BACKEND_LIST -%}
  server  redis{{ loop.index }} {{ srv }} check inter 1s fall 2 rise 1 fastinter 10ms
  {% endfor %}

  option tcp-check
  tcp-check connect
  tcp-check send info\ replication\r\n
  tcp-check expect string role:master
  tcp-check send QUIT\r\n
  tcp-check expect string +OK
```

ちなみに rsyslog設定のansible taskはこんな感じ

```
# haproxyのログ出力のためのrsyslog設定
- name: enable UDP log acceptance for rsyslog for haproxy 
  lineinfile:
    dest: "/etc/rsyslog.conf"
    line: "{{ item }}"
  with_items:
    - "$ModLoad imudp"
    - "$UDPServerRun 514" 
    - "local2.* {{ HAPROXY_LOG_DIR }}/haproxy.log"
```
JAVAでEXCELファイル更新サンプル

//下記のURLでPOIのJARファイルをダウンロードする。
https://www.apache.org/dyn/closer.lua/poi/release/bin/poi-bin-3.17-20170915.tar.gz

import java.io.*;
import org.apache.poi.ss.usermodel.*;

public class UpdateExcel {
	public static void main(String[] args) throws Exception {
		// Excelファイル
		File f = new File("C:\\Book1.xlsx");
		InputStream is = new FileInputStream(f);
		Workbook wb = WorkbookFactory.create(is); 
		is.close(); 

		// シート１
		Sheet s = wb.getSheetAt(0);

		//第一行目
		Row r0 = s.getRow(0);
		// A1
		Cell A1 = r0.getCell(0);
		A1.setCellValue("W");
		// A2
		Cell A2 = r0.getCell(1);
		A2.setCellValue("K");
		// A3
		Cell A3 = r0.getCell(2);
		A3.setCellValue("O");

		OutputStream os = new FileOutputStream(f);
		wb.write(os);
	}
}
kibanaで認証かけたいんだけど（nginxによるbasic認証）

### 背景
kibanaは認証もなくがら空きである。fluentで本番サーバのログをelasticsearchへ流してそれをkibanaでみる。本番のデータでいろいろ表に出ちゃいけない情報もあるので、社内であってもカジュアルすぎる感じで見られると嫌。
そういう訳でkibanaにnginx経由でアクセスを強制することでbasic認証を挟む。

### やったこと
* nginxインストール
* nginx設定
* パスワードファイルの配置
* kibana設定

### nginxインストール
詳しく書きません。tar ballからver 1.9のものをインストール。

### nginx config 
メインの設定は他のサーバと共通。なんでもいい。vhostに以下のような設定。ansibleで書いたやつ。

```
# basic authentification for kibana
upstream kibana {
    server localhost:5601;
}

server {
    listen       80;
{% if ENVIRONMENT == "production" %}
    server_name  kibana.o-in.hoge.jp
{% else %}
    server_name  kibana.dev.o-in.hoge.jp
{% endif %}
    charset utf-8;

    # allow ip
    include /usr/local/nginx/conf/common-ip.conf;
    deny all;

    error_log /var/log/nginx/nginx_kibana.error.log warn;
    access_log  /var/log/nginx/nginx_kibana.access.log  mylog;

    proxy_buffering off;
    
    # basic auth 
    auth_basic "Enter your ID and password." ;
    auth_basic_user_file "/usr/local/nginx/.htpasswd" ; 

    location / {
        proxy_pass http://kibana;
    }
}
```
### パスワードファイルの配置
nginx 設定ファイルで .htpasswdを読み込んでいる。
apache付属のhtpasswd コマンドを用いる。今構築中のサーバにapache居なくてもOK。他のサーバで作ってコピペしてくればいい。

```
$ /usr/local/apache2/bin/htpasswd -c ./kibana_pass myloginid
New password:
Re-type new password:
```
作成したファイルは nginxユーザの持ち物で0600にでもしておく。他のユーザによって書き換えられても嫌だし、ハッシュ化されているとはいえ見られても嫌。

### kibana設定
localhostのnginxからのみアクセスできるようにする。
kibanaのhomeディレクトリの下にconfig/kibana.ymlとかがあるので、

```
server.host: localhost
```
みたいな記述を入れる。そうするとlocalhostからのみのアクセスを受け付ける。

### 忘れずに
nginx. kibanaのrestartをして設定を反映する。

### コメント
basic認証を初めて使ったけどそんなに難しくない。認証の経路を作って、直接のアクセス経路を断つのを忘れないようにするのが重要だと思った。
SourceTreeでgit-svnしたリポジトリを扱う

参考
- [git-svnでSourceTreeを使う！](https://qiita.com/mapyo/items/d81d6577c91dc5ac4b62) 
- [すぐ忘れる！SourceTreeを使ったリベースとスカッシュの手順](https://qiita.com/ryounagaoka/items/7c129e98a7f81c507a61)
自分はこうやっていますというメモ

#  ローカルのbranchのコミットをまとめてリモートにpushする 
1. svnのtrunkの最新の内容を取得する
    - 「プル」をクリック
1. ローカルブランチを切る
    - 「ブランチ」をクリックして新規ブランチを作成する
    - Gitローカルブランチとして作成する
1. 作業する
1. 作業内容をローカルブランチにコミットする
    -  変更分を「Indexにステ―ジしたファイル」にしてコミットする
    - 「変更をすぐに Subversion にプッシュする」のチェックは外しておく
1. 3~4 を繰り返す
    - キリのいいとろころでmasterに変更を加える用意をする 
1. ローカルブランチのコミット内容を整理する
    - ローカルブランチをチェックアウトした状態でmaster のHeadリビジョンを選択し、「～の子とインタラクティブなリベースを行う」を選択する
    - [ここの手順](http://qiita.com/ryounagaoka/items/7c129e98a7f81c507a61) でコミットを纏める。
    - Windows版では以下の問題を確認済み(v1.9.11.3, OS:Win10 2017/09/14)
       - コミットメッセージに日本語があると文字化けする 
       - 直前のコミットとしかsquashできない(２つしかまとめられないので何回かくりかえした)
1. masterをローカルブランチにリベース(ローカルブランチの状態で付け替え)する
    - masterをチェックアウトした状態でローカルブランチのHEADリビジョンを選択し、「リベース」を選択する
1. リモートにコミット(push)する
    - 「最後のコミットを上書き（Amend）」をつかう
    - 「変更をすぐに Subversion にプッシュする」にチェックを入れる
docker-syncが効かないのはOverrideが原因かも

docker-syncがどうも効いていないと思ったら。

docker-syncについて説明している多くのウェブサイトでは、以下のようにdocker-composeを呼び出すことを推奨している。というか、公式でこう言っている。

```bash
docker-compose -f docker-compose.yml -f docker-compose-dev.yml up
```

```yaml:docker-compose.yml
version: "2"
services:
  someapp:
    image: alpine
    container_name: 'fullexample_app'
    command: ['watch', '-n1', 'cat /var/www/somefile.txt']
  otherapp:
    image: alpine
    container_name: 'simpleexample_app'
    command: ['watch', '-n1', 'cat /app/code/somefile.txt']
```

```yaml:docker-compose-dev.yml
version: "2"
services:
  someapp:
    volumes:
      - fullexample-sync:/var/www:nocopy # nocopy is important
  otherapp:    
    # thats the important thing
    volumes:
      - simpleexample-sync:/app/code:nocopy #  nocopy is important

volumes:
  fullexample-sync:
    external: true
  simpleexample-sync:
    external: true
```

マウントする大元のディレクトリは、docker-sync.ymlのsyncsに指定する。

```yaml:docker-sync.yml
syncs:
  fullexample-sync:
    src: '/var/www'
  simpleexample-sync:
    src: './app/code'
```

この例は確かに動く。しかしこれには穴があり、書き方次第ではちゃんと動かない場合がある。
**`docker-compose.yml`に同じvolumesを定義していた場合である。**

複数のymlを指定した場合、volumesのオプションはオーバーライドされない。
https://github.com/EugenMayer/docker-sync/issues/479
> Your issue is, that you think you can override volume defintions, but you cannot.
>
> So ${SYMFONY_APP_PATH}:/var/www/symfony stays in charge and supersync-sync:/var/www/symfony:nocopy never gets used.

確かに上の例ではdocker-compose.ymlにはvolumesを定義していない。だが例えばdocker-compose.ymlを以下のように書いた場合、結局nativeのコピーと変わらないどころか、コンフリクトしてしまうことになる。

```yaml:docker-compose.yml
version: "2"
services:
  someapp:
    image: alpine
    container_name: 'fullexample_app'
    command: ['watch', '-n1', 'cat /var/www/somefile.txt']
    volumes:
      - /var/www:/var/www # この部分はoverrideされない
  otherapp:
    image: alpine
    container_name: 'simpleexample_app'
    command: ['watch', '-n1', 'cat /app/code/somefile.txt']
    volumes:
      - ./app/code:/app/code # この部分はoverrideされない
```

docker-compose.ymlのみの場合はdocker-syncを使わず、docker-syncを使う場合のみdocker-compose-dev.ymlを一緒に読み込むという使い方をしている人も少なくないだろう。
しかし、docker-compose.ymlにはvolumesの設定を書くべきではない。

docker-syncの使用/不使用を使い分けたい場合はvolumeのみを記述した別設定を用意し、docker-compose.ymlと一緒に呼び出してあげる必要がある。

コンテナ側マウントポイントのディレクトリが重複した場合は、ちゃんとoverrideしてくれるという報告もある。
https://github.com/docker/compose/issues/2633
しかし今回の場合はこれは適用されないのだろうか…？

nocopyを付けた場合はちゃんと動作しないのかもしれないが、よく分からない。
少なくともドキュメントに書いていないのは、ちょっと不親切と言えるかもしれない。
Python実行時のコマンドライン引数を取得する

実行環境

sys.argvのリストとして取得できる。
最初の要素は実行ファイル名。
要素は全て文字列になるので、数値にしたいときは変換必要。

```py3
# coding = utf-8
import sys

if __name__ == "__main__":
    for arg in sys.argv:
        print(arg)
```

```bash
$ python arg_test.py arg1 arg2
arg_test.py
arg1
arg2
```
Tkinterインポートエラーの対処法

Pythonの標準ライブラリであるTkinterがインポートできずに困ったので、備忘録として残しておきます。

#状態
実行すると下記のエラーがでました。
>\>python ./gui1.py
 Traceback (most recent call last):
   File "./gui1.py", line 1, in <module>
     from Tkinter import *
 ImportError: No module named 'Tkinter'

Tkinterがインポートされてないよとでます。
#直し方
大文字と小文字を区別するらしく、下記で修正できました。
×：from Tkinter import *
〇：from tkinter import *

大文字と小文字を区別するのはpython3かららしく、
python2のサイトを参考にしてると引っかかります。

参考：
[答えを知りたい](http://programming.ironsand.net/2011/tkinter-importerror/)

#その他
初めはどっかからインストールしなければいけないのかと思って探してしまいました。
また、標準のpythonではなく、ダウンロードしたpythonで実行するとだめな場合があるようです。
自分は初めに下記を試してみましたが、事象が異なり、上記の方法で修正できました。
参考：
[stack overflow](https://ja.stackoverflow.com/questions/29781/python3-%E3%81%A7-tkinter-%E3%82%92-import-%E3%81%97%E3%81%9F%E3%81%84)
ヘッドレスChromeが動かない？SSL証明書のせいならこれで！

[ラクス Advent Calendar 2017](https://qiita.com/advent-calendar/2017/rakus)の4日目です。
昨日は @MasaKu さんの「[Laravelで作るRESTなWebアプリ](https://qiita.com/MasaKu/items/82b9743383e73cb62c3e)」でした。

今回は私がヘッドレスChromeを使ってみた際につまづいたポイントについて、書いてみたいと思います。

# はじめに

Windows版のChromeでもヘッドレスモードが使えるようになりましたね :clap:

私の担当するプロジェクトはレガシーなもので、あまりコードの変更が発生しません。そのため、自動UIテストはWindowsのローカル開発環境で実施する程度です。
これまでWebDriverでGUIのChromeを立ち上がる形でテストしていたのですが、テスト中にうっかりChromeに触ってしまって、テスト失敗になってしまう事が何度かありました :cry:

そこでヘッドレスモードなら、この事故をなくせるのではないかと考えました。

# 環境

* Windows10
* Chrome 62.0.3202.94
* ChromeDriver 2.33.506120


# ヘッドレスChromeについて

Chromeのヘッドレスモードについては、詳しい記事が世にございますので、省かせていただきます。
ざっくり言えば、「GUIのないモード」です。
GUIがないので、私が遭遇している問題のように、うっかりテスト中に触ってしまうこともありません。

ヘッドレスモードでの起動方法は、Chromeの起動引数に下記をつけるだけで動作します。

```
--headless --disable-gpu
```

※`--disable-gpu`はいずれ不要になるとか（[ヘッドレス Chrome ことはじめ](https://developers.google.com/web/updates/2017/04/headless-chrome?hl=ja)）

# 自動UIテストをヘッドレスにしてみたけど・・・動いてない？

自動UIテストを、上記引数を渡すよう変更して実行してみました。
・・・が、動いていない・・・？
次々とテスト失敗が告げられます :persevere:

テスト対象のアプリケーションサーバーには、リクエスト時のログさえ出ていない。
テスト失敗時に撮っているスナップショットを見ると、真っ白な画面。。
（ヘッドレスでもスナップショットは撮れます）


# 動作しなかった原因

どうやらSSL証明書に問題があると動かないようです。アドレスバーに注意が出るようなやつですね。

「ヘッドレスでなければ動くのに！ :angry:」とも思ってしまいますが、SSL証明書自体をテスト対象として見た場合はこれが正しい気もします。GUIがないので「注意を引くには止まるしか・・・」という事なのかな？

私の開発環境ですと、SSL証明書は雑に作ったいわゆるオレオレ証明書です。
オレオレ証明書でも、ちゃんと作れば大丈夫なのかも知れませんが、それを用意する時間も手間も惜しいので、SSL証明書の問題を無視してくれる設定がないか探してみました。


# 回避方法

起動引数に下記をつけると、SSL証明書に問題があっても動作します。
（どんなSSL証明書でも大丈夫かは不明です）

```
--allow-insecure-localhost
```

ただし、制約があります。
引数を見た感じでも分かりますが、ドメインが `localhost` でないとダメです。

その制約が問題なければ、下記のような状態のSSL証明書でもヘッドレスChromeが動作しました。

![shoumeisho.png](https://qiita-image-store.s3.amazonaws.com/0/151018/46af1bb0-27c9-a545-bbe5-88b7e57a72f4.png)

# 回避方法＋α

上記の回避方法だけでは問題があるケースもあるかと思います。
`localhost`だけだと、テスト対象のドメインが複数ある場合に対応できません。

私の担当プロジェクトが正にそうで、ドメインをまたいだ画面移動があります。
その場合、ドメインを `localhost` に統一してしまうと、ドメインまたぎの遷移テストが不十分になってしまいます。

すがる思いでChromiumの[ソースコード](https://cs.chromium.org/chromium/src/headless/lib/browser/headless_content_browser_client.cc?type=cs&q=allow-insecure-localhost)を確認したところ・・・
`--allow-insecure-localhost` が効くドメイン名は「.localhost」で終わっていればなんでも良いみたいです。（ロジックが変わってしまったらスミマセン）

これならテスト対象のドメインを `hoge.localhost` や `fuge.localhost` にすればOKですね。


# 自動UIテストのヘッドレス化に再挑戦

ここまでの回避方法を適用すると、無事にヘッドレスモードで動作させることができました :relaxed:
ドメインを変えなければいけないのが、結局手間ではありましたが :pensive:

実現してみての感想ですが、想定通り、テスト中にブラウザに触ってしまう事故はゼロになりました :sunny:

速度については少し速くなったものの、思ったほどではありませんでした。気持ち程度ですかね :partly_sunny:
GUIとして出てないだけで、レンダリングはしっかりしてると思うので、こんなものかも知れません。

# まとめ

* ヘッドレスChromeが動作しない場合はSSL証明書が原因なこともある
* SSL証明書が原因なら、ドメインを `localhost` か `hoge.localhost` にして、Chromeの起動引数に `--allow-insecure-localhost` を追加する

・・・ただ、ドメインを変えること自体が結構な手間なので、ちゃんとしたSSL証明書を作ってしまった方が良いのかも :sweat_smile:
回避策の１つとしてどなたかの助けになれば幸いです。

最後までお読みいただき、ありがとうございました。


# 参考サイト
* [ヘッドレス Chrome ことはじめ](https://developers.google.com/web/updates/2017/04/headless-chrome?hl=ja)
* [chromium ソースコード](https://cs.chromium.org/chromium/src/headless/lib/browser/headless_content_browser_client.cc?type=cs&q=allow-insecure-localhost)
bashで連番リネーム時の依存関係解決(Python3もある)

# 連番リネームの問題点

```
$ ls
0  1  2
```

な時に

```
0 -> 2
1 -> 3
2 -> 4
```

とリネームしたい時

```
$ mv 0 2
$ mv 1 3
$ mv 2 4
```

とすると
`$ mv 0 2` で`2`が`0`で上書きされて結果

```
$ ls
3　4
```

となってしまう.

# bashの連想配列を使って依存関係を解決
※bashの連想配列はbash 4.x以降でしか使えません.
リネーム元とリネーム先の組み合わせは連想配列arrayに格納されているものとする.

``` rename.sh
#!/bin/bash

function output(){
    if ! [[ -z "${array[${array[$1]}]}" ]]; then
        output "${array[$1]}"
    fi
    echo mv "$1" "${array[$1]}"
    unset -v array[$1]
}

declare -A array

array=(
    [0]=2
    [1]=3
    [2]=4
)

for i in "${!array[@]}";do
    if ! [[ -z "${array[$i]}" ]]; then
        output "$i"
    fi
done
```

出力

``` 
mv 2 4
mv 0 2
mv 1 3
```

# bashの連想配列の解法の問題点
```
"${array[${array[$1]}]}"
```

などがある為ファイルネームにスペースが含まれていると動かない.
頑張ってevalを使いまくればいけるかもしれない.

# Python3で書くと

``` rename.py
#!/bin/python3

def output(item):
    if item[1] in array:
        output((item[1], array.pop(item[1])))
    print('mv "' + item[0] + '" "' + item[1] + '"')

array = {
    '0': '2',
    '1': '3',
    '2': '4',
}

while array:
    output(array.popitem())

# ファイル名に"が含まれている場合は以下
# print('mv "' + item[0].replace('"', '\\"') + '" "' +
#       item[1].replace('"', '\\"') + '"')

# 追記: $もエスケープしないといけなかった
# print('mv "' + item[0].replace('"', '\\"').replace('$', '\\$') + '" "' +
#       item[1].replace('"', '\\"') + '"').replace('$', '\\$')
```
出力

``` 
mv "2" "4"
mv "0" "2"
mv "1" "3"
```

出力は毎回異なるが`mv "0" "2"`は必ず最初でない.
これならスペースが含まれていても大丈夫.
SubversionリポジトリをGitで扱うためにしたこと

ググった記事を色々参考にしたがうまくいかなかったので、成功した手順を書いておく。
まだ良くわかっていない部分もある。

## 前提
- そこそこでかいリポジトリである
- branchやtagもある
- OSはWindows

## 手順
### ディレクトリの作成

```
$ mkdir C:¥workspace¥hoge
$ cd C:¥workspace¥hoge
```

### git svn init

```dos:
$ git svn init  http://subversion.example.com/svn/myrepo -T trunk/hoge --prefix svn/
```

### .git/configを編集する。
 - `[core]`は元ファイルを優先すること
 - `[gc]`部分の記述が重要だった

```
[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true

# ここから下について変更する。
[svn-remote "svn"]
    noMetadata = 1
    url = http://subversion.example.com/svn/myrepo
    fetch = trunk/hoge:refs/heads/master
    # branchの自動更新が不要なら以下2行は省略可
    branches = branches/*:refs/heads/*
    tags = tags/*:refs/tags/*

# ここの変更が重要だった
[gc]
    auto = 0
```

### git svn fetchをする
-  結構時間がかかるが途中で失敗することは無かった
- 完了後に`git gc`する
- 最後に`.git/config`から[gc]の設定を取り除く

```
$ git svn fetch --fetch-all
$ git gc
```
LumberyardのShaderを覗いてみた

# LumberyardのShaderシステムを調べてみようと、ざっくりとShaderコードを読んでみました。

## 前置き
　**Lumberyard**に関してはほとんどまだ何も作業した事が無く、知識も皆無に等しいのですが、素人が参加できるチャンスは今しかないかと思ったので、アドカレに参加してみました。
　初心者丸出しですが、少しでも賑やかしになれば幸いです。色々間違った事を書いているかもしれませんが、その辺はご容赦ください。

## LumberyardのShaderシステム
　マニュアルをざっと斜め読みしたところ、**Lumberyard**ではUE4の様なノード形式のマテリアルエディタは存在しないみたいで、ユーザーが手軽に独自のマテリアルを組めるわけではなさそうです。
　とは言え、かなりの種類のShader Typeが用意されているので一般的なPBRな画作りをするには十分すぎる機能が揃っているようです。

## Shaderコードを覗く
　**Lumberyard**で使用されるShaderコードは以下のフォルダに配置されているようです。
**C:/Amazon/Lumberyard/(Version)/dev/Engine/Shaders/**

　このフォルダに**Shaders.sln**というVisualStudioのソリューションファイルがあるので、これをVisual Studioで読み込むことで、IDEでファイルを扱うこともできます。

　拡張子.extのファイルはマテリアルエディタで選択するShaderのプロパティを定義したファイルで、**HWScripts/CryFX**にShaderのソースコードが格納されています。**Lumberyard**のベースになった**CryEngine**の名前が残ってるんですね。

　ファイルの中身を見ていくと**Common.cfi**に共通の処理が詰め込まれています。これを一通り見るとどんなレンダリングをしてるかがざっと把握できそうです。
　AAA級のゲームエンジンのShaderのキモを誰でも見られる時代になったのは凄いことだと思います。けっこう秘伝のタレ的なものもあるものなので、勉強になります。

**\#define PI 3.1415**
割りと大雑把なPI定義。3.1416の方が良くね？とかどうでも良いツッコミ

DecodeGBuffer/EncodeGBuffer関数を見ると、GBufferはABCの３枚を使用している。
ライティングモデルによって若干の違いはあるみたいですが、
A.xyzにNormal、A.wにlighting modelのフラグなど
B.xyzにalbedo、B.wにocclusion
C.xにSmoothness,C.yzwにReflectance、UE4で言うRoughnessとSpecular/Metallicに相当します。
ざっくり言うとAは法線、Bはカラー、Cは質感情報が格納されるといった感じです。
まだ詳しくは見られていませんが、PBRライティングは、Shader内ではSmoothness＝表面の滑らかさ、Reflectance＝表面の反射率で計算されているようです。

ライティングモデルはGBufferAのwを2bit使用していて、
\#define LIGHTINGMODEL_STANDARD       0
\#define LIGHTINGMODEL_TRANSMITTANCE  1
\#define LIGHTINGMODEL_POM_SS         2
標準、透過、表面化散乱の３種類のモデルが使用できるみたいです。

Lumberyardではカラーを格納する際にはカラー値の平方根を格納して、取り出すときに２乗して戻しています。暗い部分の精度を高くする工夫でしょう。

GBufferに情報を詰め込むときには色々工夫をするのですが、よくやるのは8bitのチャンネルにbit単位で情報を詰め込むやり方です。とはいえ、Shaderで読み書きするときには浮動小数点で0～1の値です。これを0～255の整数値にしてbit演算して戻すといった面倒くさくてわかりにくい処理を実装する必要があるのですが、この辺のコードなんかもとても勉強になります。

GetLuminanceでRGBの要素に掛ける係数が、0.2126, 0.7152, 0.0722。よく0.299, 0.587, 0.114を使ってるのを見かけますがNTSCの輝度計算値なので、sRGBモニターの場合は前者を使うのが良いみたいです。僕も最近まで後者を使ってました。

RGBMのEncode/Decodeなんかもありますが、HDR警察怖いので特に言及しませんｗ

Deferred Lightingなので、ベースパスでまずGBufferに法線、カラー、質感の情報を書き込み、その後のライティングパスでGBuffer情報を使ってライティングをするわけです。

Reflectanceの求め方や、Specular Colorをどう処理してるかなど、まだまだわからない部分が多いですが、おいおい調べて行きたいと思います。CryEngineのドキュメントとか見ると書いて有りそうな気はしますが。

## まとめ
　LumberyardのShaderコードのごく一部から上っ面だけ撫でてみましたがいかがでしょうか。画像もない記事で興味のない人には全くおもしろくない内容だったかもしれません。
　できればカスタムのShaderを組み込むやり方を調べたり、ポストプロセスについても調べて行きたいと思っています。
CodeIgniter 3.xのForm validationで知っておいたほうがいいかも知れないこと

# 1. CallbackはControllerでしか定義できない

検証ルールをメソッドに定義するCallbackと呼ばれる方法は、Controllerでしか使えません。つまり、Modelに検証メソッドを定義する場合には使えません。

# 2. Callableにパラメータを渡す方法は用意されていない

Callbackではパラメータを`callback_foo[bar]`のように渡すことができます。

> If you need to receive an extra parameter in your callback method, just add it normally after the method name between square brackets, as in: callback_foo[bar], then it will be passed as the second argument of your callback method.
https://www.codeigniter.com/userguide3/libraries/form_validation.html#callbacks-your-own-validation-methods

しかし、Callableではパラメータを渡す方法は用意されていません。

パラメータを渡したい場合は、クロージャを使うことを検討してください。

# 3. Callback/Callableは最優先で検証される

検証ルールは定義した順番で実行されると思うかも知れませんが、実は違います。Callback/Callableが最優先で実行され、その後、`required`が検証されます。

> "Callbacks" are given the highest priority (always called),
> followed by 'required' (called if callbacks didn't fail),
> and then every next rule depends on the previous one passing.
https://github.com/bcit-ci/CodeIgniter/blob/develop/system/libraries/Form_validation.php#L505

# 4. set_data()は検証ルールを定義する前に実行する必要がある

`$_POST`以外のデータを検証する際に使う`set_data()`は、`set_rules()`を呼び出す前に実行しなければなりません。

> You have to call the set_data() method before defining any validation rules.
https://www.codeigniter.com/userguide3/libraries/form_validation.html#validating-an-array-other-than-post

# まとめ

1. CallbackはControllerでしか定義できない
2. Callableにパラメータを渡す方法は用意されていない
3. Callback/Callableは最優先で検証される
4. set_data()は検証ルールを定義する前に実行する必要がある

# 参考

* https://www.codeigniter.com/userguide3/libraries/form_validation.html

---

[![クリエイティブ・コモンズ・ライセンス](https://i.creativecommons.org/l/by-sa/4.0/88x31.png)](http://creativecommons.org/licenses/by-sa/4.0/deed.ja)
この記事は[CC BY-SA 4.0（クリエイティブ・コモンズ 表示 4.0 継承 国際 ライセンス）](http://creativecommons.org/licenses/by-sa/4.0/deed.ja)の元で公開します。
【Splunk】特定の条件下のデータが全体のどれくらいの割合なのかを表示する方法

Splunkで、とある条件下のデータが全体のどれくらいの割合なのかを表示するやり方。

例えば、あるマラソン大会の選手とスコアのデータが下記のようにあったとする。
※ 名前、性別、記録(分単位)のデータがあり、Splunkには"runner"というインデックスで登録したとする

```
name,gender,finish_time
Bob,male,198
Mike,male,235
Kate,male,317
Jack,male,257
David,male,299
Noah,male,181
James,male,233
Alex,male,271
Alice,female,281
Emma,female,325
Amelia,female,245
Chloe,female,309
Lily,female,356
Amy,female,239
```
上記データからサブ４(4時間内で完走)した選手の割合を出すときのサーチ文は

```
index="runner" 
| eval class=if(finish_time<240, "sub_4", "other")
| stats count by class
```
となって、視覚エフェクトで円グラフを表示すると、こんな感じになります。

<img src="https://qiita-image-store.s3.amazonaws.com/0/172282/14fc4317-7f4f-b817-c766-a34ff78350e7.png" width=50%>


さらに、サブ4からサブ3.5(3.5時間で完走)した選手の割合も一緒に出したいときは

```
index="runner" 
| eval class=if(finish_time<210, "sub_3.5", if(finish_time>=210 AND finish_time<240, "sub_4", "other"))
| stats count by class
```
こんなサーチ文を実行すると、下みたいな円グラフを出せます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/172282/a39bb4ad-02ba-3cca-768a-2bdfcb82b0c7.png" width=50%>

Splunkはif文にelseがない(?)のか、
複数条件分岐をするときはマトリョーシカ的にやらないといけないのかもしれないです。

備忘までに。
AWS S3上にあるファイルのダウンロード

```groovy
// Groovy Version: 2.4.11 JVM: 1.8.0_144 Vendor: Oracle Corporation OS: Mac OS X
@Grab('com.amazonaws:aws-java-sdk-s3:1.11.184')
import com.amazonaws.regions.Regions
import com.amazonaws.services.s3.AmazonS3
import com.amazonaws.services.s3.AmazonS3ClientBuilder

import java.nio.file.Files
import java.nio.file.StandardCopyOption



AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
        .withRegion(Regions.AP_NORTHEAST_1)
        .build()

def bucketName = 'your-bucket-name'
def key = 'some/s3/object/key'

def content = s3Client.getObject(bucketName, key).getObjectContent()
def file = new File('/path/to/download/dir/filename')
Files.copy(content, file.toPath(), StandardCopyOption.REPLACE_EXISTING)
```
Golang 環境の設定 macOS + IntelliJ 


## 環境
- IntelliJ IDEA 2022.2.3 (Ultimate Edition) + Go plugin
- macOS Monterey 12.6.1
- Go 1.19.2

## Golang のインストール

まずは Go 自体をマシンにインストールする。
`brew install go` でサクッとインストールできる。
Go は後方互換性が保たれているので、あんまり古いバージョンを使い続けないことがおおい（と思う）。
が、念の為、複数バージョンを使い分けられるようにしておく。

*goenv* でもいいのだけど、おすすめは [*asdf*](https://asdf-vm.com/)。
*asdf* は様々なCLIツールに対応したバージョンマネージャでプラグインで拡張できる。
CLIツールには各種言語の実行環境も含まれている。
Go のプラグインも複数あるが、 [go-sdk](https://github.com/yacchi/asdf-go-sdk)[^go-sdk]がおすすめ

[^go-sdk]: https://zenn.dev/yacchi21/articles/dd6d41b50fa1be

```bash
brew install asdf          # asdf 本体のインストール
asdf plugin add go-sdk     # go-sdk プラグインのインストール
asdf install go-sdk 1.19.2 # go v1.19.2 のインストール
```

## IntelliJ IDEA と Go プラグインをインストール

IntelliJ のインストールも Homebrew で可能。

```shell
brew intall --cask intellij-idea
```

### Go プラグインのインストール

Go プラグインは JetBrains 純正のものがある。[GoLand](https://www.jetbrains.com/ja-jp/go/)相当の機能を追加するもの。

- [Go - IntelliJ IDEA Plugin | Marketplace](https://plugins.jetbrains.com/plugin/9568-go)

*Preferences* > *Plugins* を開いて *Marcketplace* で 「go」 で検索すると見つかる。
選択してインストールする。

### GOROOT の設定

*Preferences* > *Language & Frameworks* > *Go* > *GOROOT* で GOROOT を指定する。

Homebrew で Go をインストールした場合だと `/opt/homebrew/Caller/go/<version>/libexec` にあるので指定する。
asdf の go-sdk でインストールした場合だと `~/.asdf/installs/go-sdk/<version>` にある。

### フォーマッターの設定

*Preferences* > *Editor* > *Code Style* > *Go* の *Import* を開いて、 *Sorting type* を選択する。
*gofmt* がデフォルトで、 *goimport* も選択できる。 より良い感じに調整してくれる *goimport* を選ぶ。
まあ、 *gofmt* が好みならそのままでも良い。

次に *Preferences* > *Tools* > *Action on Save* を開いて *Reformat code* にチェックを入れて *File* で *Go* を選択する。
フォーマットの範囲は *Whole file* を選ぶほうがいいだろう。 
既存コードがあって、そのフォーマットがイケてない場合は *Changing line* にしないと Diff がむやみに増えるのだけど、 Golang は `gofmt` で整える習慣があるので大丈夫だろう。

そして *Optimize imports* にもチェックを入れて、 *Files* で *Go* を設定しておく。

これでファイル保存時に自動的にコードをフォーマットしてくれる。
 
## Hello Worldしてみる

新規プロジェクトのダイアログを開き、 *Language* で *Go* を選択する。その時、 `GORROT` を指定する必要がある。
予め *Preferences* で設定しているので何らかの選択肢はあるはずなので選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32533/d66edb84-21d7-ccfe-582a-e26c7c045e1c.png)

プロジェクトができたら、Goのファイルを追加する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32533/0d45bd6a-c2e0-8131-3bce-54fc2506f326.png)

次の内容で`main.go`という名前でファイルを作る。

```golang
package main

import "fmt"

func main() {
    fmt.Println("Hello World !!")
}
```

コードの左に表示される緑の三角矢印をクリックして *Run 'go build main.go'* を選択すると実行できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32533/8fec7d7e-9683-2bc6-0811-5a6c3d6cbc17.png)

次のように表示されればOK

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32533/2ca532df-1a50-df7c-7cbc-684e0fac1cbf.png)


## デバッガ

コードの左に表示される緑の三角矢印をクリックして*Debug 'go build main.go'* を選択するとデバッガも使える。便利。
【初心者向け】量子ゲート方式と量子イジングモデル方式の違い

アドベントカレンダー参加者のみなさまがガチで書きすぎて、量子コンピュータに興味はあったけど、まだ詳しく知らない方々は、ちょっとどうしようって思ってるんじゃないでしょうか。
案外誰も書かないので、ここでは、量子コンピュータの話題についていくために本当に最低限必要なこと、つまり、量子コンピュータには2種類ある、という話を書こうと思います。

これ知ってるだけで、量子コンピュータ関係のニュースの見方が変わってきますよ。

#量子コンピュータは大きく分けて2種類
量子コンピュータは大きく分けて、量子ゲート方式と量子イジングモデル方式の2種類があります。
どちらも、量子力学の原理を応用して計算に活かしていることには変わりはないのですが、単なるデバイスや処理系の違いというにはあまりにも大きすぎる違いがあるので、必ず区別する必要があります。
雑な例え話をすると、電気ポットも電気掃除機もどっちも電気を使った製品だけど、全然同じではないですね。

#量子ゲート方式
2007年以前は、量子コンピュータといえば、量子ゲート方式を指していました。
それ以後は量子イジングモデル方式も盛り上がってきたので、あえて「量子ゲート方式」のように呼ばれることが増えてきました。
今まで「電話」と呼ばれていたものが携帯電話の普及と共に「固定電話」と呼ばれるようになったのと似ています。

古典コンピュータ(通常のコンピュータのこと)が、AND, OR, NOTなどのゲートの組み合わせによっていかなる計算も実現できるように、アダマールゲート(H)、回転ゲート(π/8)、制御NOTゲート(CNOT)という3種類のゲートがあれば、いかなる量子計算も行えます。
これらのゲートの組み合わせによって、汎用的な量子計算を行おう、というのが量子ゲート方式です。
ここでは、量子計算とは何かについては述べませんが、古典コンピュータでできる計算はもちろん、量子計算に含まれています。

素因数分解が早くできる、ソートされていない配列から O(√N) でデータを探し出せる、などの話は、量子ゲート方式の話です。
(なお、素因数分解に関しては、量子ゲート方式でのショアのアルゴリズムとは別物ですが、量子イジングマシン方式でも、実現しているようです。
https://qiita.com/mdrft/items/ed8f5e52fd364c605468 が詳しいです。)

なのですが、現時点では、動いている実機は少なく、また、実用的な性能を持った実機はありません。
IBMのQという量子ゲート方式のマシンがクラウドで使えて、量子ビットの数が5のものと16のものが動いています。けれど、5量子ビットは暗算でも素因数分解できる数しか表現できません。16量子ビットだって、しょぼいコンピュータでも一瞬で解けるような大きさです。

けれど、希望がないわけでもなく、問題の種類によっては、量子ビットの数に対して指数関数的、あるいは準指数関数的に性能が上がっています。そして56量子ビットを超えると今のスパコンではシミュレーションできなくなる、とも言われています。(ただし、この数値はスパコンの性能向上とともに上がっていきます。最近までは49量子ビットでした。)
一方、Googleは49量子ビットの実機を作ろうとしています。
もしかしたら、ある日突然、量子ゲート方式のマシンがスパコンを追い抜く日が来るかもしれません。

#量子イジングモデル方式 (量子アニーリング方式と量子ニューラルネットワーク)
2007年にD-Waveというカナダの会社が、全く新しい形式の計算機を発表しました。
これは、量子アニーリングと呼ばれる処理を実機で行うことで、最適化問題を解く計算機です。

数値計算や最適化法に詳しい方なら、焼きなまし法という手法を聞いたことがあるでしょう。量子アニーリングは焼きなまし法と似た手法で、イジングモデルという磁性体のモデルを使って最適化を行う手法です。
D-Waveのマシンは、イジングモデルに従う系を作って実際に実験し観測することで、量子アニーリングの「計算」を高速で行います。

なんだか、粘菌を使って迷路の最短経路を求めるとか、そういった類の話みたいですね。

量子イジングモデル方式は、量子ゲート方式のような汎用性はないのですが、上述のD-Wave社の計算機のように、既に商用化されている実機があります。

最近、NTTから量子ニューラルネットワークという新しい計算機が発表されました。
D-Waveの計算機は超電導を使っているのに対し、NTTは光を使っていて、全く別物に見えます。けれど実は、これも実機でイジングモデルと同等のモデルを作って実験するタイプの計算機です。なので、量子ニューラルネットワークは量子イジングマシン方式に含まれます。

量子イジングモデル方式は、いずれも、イジングモデルを実機で再現して実験を行うことで最適化問題を解く、それに特化した方式です。

#量子ゲート方式と量子イジングモデル方式の利点、欠点
それぞれの違いが分かったところで、利点、欠点をまとめます。

##量子ゲート方式
- 利点
    - 汎用的で、いかなる量子計算も実現できる
    - 量子イジングモデル方式でできる計算は、量子ゲート方式でもできる
- 欠点
    - 現時点では、実用的な性能の実機がない
    
##量子アニーリング方式
- 利点
    - 既に、商用レベルの実機が存在している
    - 最適化問題は現在のコンピュータでは解きにくい問題も多く、それに特化していたとしても、十分にうれしい
- 欠点
    - 最適化問題以外は解けない

#量子ゲート方式と量子イジングモデル方式 まとめ
量子コンピュータには大きく分けて2種類。

- 量子ゲート方式
- 量子イジングモデル方式
  - 量子アニーリング方式 (D-Wave社)
  - 量子ニューラルネットワーク (NTT)

量子ゲート方式⇒汎用的な量子計算を行うことを目指した計算機。2017年12月現在、まだ実用的な実機がない。
量子イジングモデル方式⇒最適化問題を解くことに特化した計算機。既に商用レベルの実機がある。
いくつかの文字領域の呼び方について

特定の領域の文字を呼ぶ場面がありますが、正式に名称がないこともあります。

# いわゆる「半角カナ」

Unicodeにも正式に入ってしまったこともあって、互換性の低い文字としての問題はほぼ収束した感のある「半角カナ」ですが、本来「半角」という文字のサイズと文字コードは結びつくものではありませんし、「1バイトカナ」と言っても1バイトになるのはJIS X 0201とシフトJISだけで、EUCでは2バイト、UTF-8では3バイトを消費するので、これまた適切な表現ではありません。

厳密に言うなら、

* JIS X 0201の仮名文字
* シフトJISの1バイトカナ

なのですが、Unicodeに採録された名称が「Halfwidth Katakana」なので、「半角カナ」という名前もほぼ公式のものになった…というところです。

# BMP外の文字

Unicodeの規格上は、17の「面」（16ビットの文字空間）がありますが、現状ではそのうち7つしか定義されていません。

* 第0面…基本多言語面（BMP）、元はここだけで済ませようと計画していた（のが破綻した）面。
* 第1面…追加多言語面（SMP）、絵文字や古代文字など、BMPに入らなかった用字系を入れる面。
* 第2面…追加漢字面（SIP）、漢字専用の面。
* 第3面…第三漢字面（TIP）、もとは甲骨文字や古代漢字を入れる計画だったけど、追加漢字面が一杯になってきたので現代漢字が先に入る予定。
* （第4面～第13面は未定義）
* 第14面…追加特殊用途面（SSP）、異体字セレクタなどの制御コード専用の面
* 第15面・第16面…私用面、Unicode規格では何も定義しない、いわゆる「外字」専用の領域

このうち、「BMP」と「それ以外」には大きな格差があります。

* UTF-16の場合、BMPはコードポイント1つで済むのに対して、それ以外は「サロゲートペア」としてコードポイント2つを使います。
 * 仕様上UTF-16をつかうことになっているJavaScriptの場合、ハンドリングを間違えればサロゲートペアの途中で文字をぶった切ってしまうことが起きます。
* UTF-8では、BMP内の文字は3バイト以内で表現されるのに対し、それ以外の文字は4バイトとなる。
 * MySQLの`utf8`は3バイト以内の文字しか格納できず、全部入れようとすれば`utf8mb4`という別の設定に切り替えが必要

いちおう、「BMP外」の文字を入れる面には「追加面」という総称がついているのですが、あまり使われているのを見なくて、「BMP外の文字」とか（UTF-8/UTF-16を前提に）「4バイト文字」と呼ばれることが多い気もします。
【Splunk】自動起動設定を入れてみる

Splunkをインストールしたあと、やっておくべきこととして自動起動設定があります。

RedHat系だったらchkconfigをいじるなどOSごとに色々とやり方はありますが、
Splunkは下記コマンドを実行しておけばOSごとにやるべき設定が勝手にされます
※ Splunkは「/opt」にインストールされた想定です

```
 # /opt/splunk/bin/splunk enable boot-start
```

上記コマンドが実行されると、下記メッセージが出てきます。(おそらく環境ごとにそんな違いないはず)

```
Init script installed at (自動起動スクリプトのインストール先、OSごとに違う)
Init script is configured to run at boot.
```

これをやっておけば、PCなりサーバなりが再起動されても勝手にSplunk起動します。
node-red、msg.payloadの値を後で使いたい場合のやり方

#背景
node-redで、フローの最初の方で取得したmsg.payloadを後で使いたいケースがよくある。
msg.payloadとかmsg.payload.xxxとかmsgの下に格納するとフローの途中で消えるので困った。

#対応
global.xxxとかflow.xxxを使う。

```js:node-red_sample

//flowへ格納
flow.set("user_name",msg.payload.user_name);

//flowから取り出す。同じフロー内だったら、どこからでも呼べる
var user_name = flow.get("user_name");

//flow.user_nameって使い方はできないらしい

```

######参考
---
[Node-RED日本ユーザ会 : Functionノードの書き方](https://nodered.jp/docs/writing-functions
)
ionic3でハイブリッドアプリを作ってみよう。 - ページ遷移編

[前回](https://qiita.com/ryosomiya/items/277826a7418aeef06976)の続きです。
## ボタンを設置する
まずは画面遷移のトリガーとなるボタンを設置します。

```html:src/page/home/home.html
<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Blank
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  The world is your oyster.
  <p>
    If you get lost, the <a href="http://ionicframework.com/docs/v2">docs</a> will be your guide.
  </p>

  // ボタンを追加
  <button  ion-button>next</button>

</ion-content>
```
これで一度実行してみましょう。

```
$ ionic cordova run ios
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/53709/3f8d5884-b210-381f-d5b7-80cc0129295f.png)
`next`と表示されたボタンが表示されました。
今は表示されただけなので、反応はしますが遷移はしません。

## ページを生成する
次は遷移先のページを作っていきます。
ionicには`generate`という便利なコマンドが用意されていて、ページの追加も簡単にできます。
[コチラ](https://ionicframework.com/docs/cli/generate/)に一覧があります。

```
$ ionic generate page nextPage
[OK] Generated a page named nextPage!
```
`src/pages/`配下に`next`というディレクトリと、その中に以下のようなファイルが生成されました。

```
src/pages/next/next.html
src/pages/next/next.module.ts
src/pages/next/next.scss
src/pages/next/next.ts
```

## ページを読み込む
ページが生成されたらルートモジュールでこの新しく生成されたモジュールを読み込んでおく必要があります。

```ts:src/app/app.module.ts
.
.
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { NextPageModule } from '../pages/next/next.module'; // ←追加

@NgModule({
  .
  .
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp),
    NextPageModule  // ←追加
  ],
  .
  .
})
export class AppModule {}
```
上記の二行を加えます。
仕様するモジュールが増える度にこのファイルに追加設定をしていきます。
これでページを使う準備ができました。

## 遷移処理を追加
ページ自体とページを使う準備ができたので、今度はボタンを押してページ遷移をする処理を追加していきます。

先程追加したボタンにクリックイベントを付けます。

```html:src/pages/home/home.html
<button ion-button (click)="toNextPage()">next</button>
```

これでボタンがクリックされたら`toNextPage()`という処理してくれます。
次はこの`toNextPage()`の中身を書きます。

```ts:src/pages/home/home.ts
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { NextPage } from '../next/next';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  constructor(public navCtrl: NavController) {

  }

  // ボタンが押されたときのページ遷移処理
  toNextPage(){
    this.navCtrl.push(NextPage);
  }
}

```
追加しているのは3行目の`import`と、`toNextPage()`という処理です。

## 実行
動かしてみましょう

```
$ ionic cordova run ios
```
![nextPageLoop.gif](https://qiita-image-store.s3.amazonaws.com/0/53709/e3c90c4c-32b0-51d7-2a03-156e715072f5.gif)



次はデータの永続化とか書きます。
Raspberry Pi にNode-RED をインストールする


## 環境
次のモデルで確認済

- Raspberry Pi 1 MODEL B+
- Raspberry Pi 3
- Raspberry Pi Zero W

- インストールイメージ：2017-11-29-raspbian-stretch-lite.img

初期設定は [Raspberry Pi 初期設定 \- Qiita](https://qiita.com/HeRo/items/c1c30d7267faeb304538) を参照

## Node-REDのインストール

```bash
$ sudo apt-get install nodered
$ update-nodejs-and-nodered 

 
This script will remove versions of Node.js prior to version 6.x of Node.js and Node-RED
and if necessary replace them with Node.js 8.x LTS (carbon) and the latest Node-RED from Npm.
 
It also moves any Node-RED nodes that are globally installed into your user
~/.node-red/node_modules directory, and adds them to your package.json, so that
you can manage them with the palette manager.
 
It also tries to run 'npm rebuild' to refresh any extra nodes you have installed
that may have a native binary component. While this normally works ok, you need
to check that it succeeds for your combination of installed nodes.
 
To do all this it runs commands as root - please satisfy yourself that this will
not damage your Pi, or otherwise compromise your configuration.
If in doubt please backup your SD card first.
 
Are you really sure you want to do this ? [y/N] ? y


Running Node-RED update for user pi at /home/pi

This can take 20-30 minutes on the slower Pi versions - please wait.

  Stop Node-RED                       ✔
  Remove old version of Node-RED      ✔
  Remove old version of Node.js       ✔
  Install Node.js for Armv6           ✔   Node v8.9.4   Npm 5.6.0
  Clean npm cache                     ✔
  Install Node-RED core               ✔   0.18.2 
  Move global nodes to local          ✔
  Install extra Pi nodes              -
  Npm rebuild existing nodes          ✔
  Add menu shortcut                   ✔
  Update systemd script               ✔
  Update update script                ✔

Any errors will be logged to   /var/log/nodered-install.log

All done.
  You can now start Node-RED with the command  node-red-start
  or using the icon under   Menu / Programming / Node-RED
  Then point your browser to localhost:1880 or http://{your_pi_ip-address}:1880

Started  2018年  2月 11日 日曜日 16:12:44 JST  -  Finished  2018年  2月 11日 日曜日 16:29:33 JST
```

2018/02/11 時点では NodeのバージョンはLTSである *v8.9.4* になっている。

ちなみに`update-nodejs-and-nodered`コマンドは Node-REDのアップグレードに利用できる。
既存の Node.js と Node-REDをアンインストールしてから最新をインストールするが、
Node-REDの設定（追加インストールしたノード、登録したフロー）が消えることはない。

## 起動確認
`node-red-start`コマンドで起動する。

```bash
$ node-red-start
```
実行後、http://raspberrypi.local:1880/ にアクセス。
ホスト名を変更していたら、 [http://<変更後のホスト名>.local:1880/](http://<変更後のホスト名>.local:1880/) にアクセスする。

Node-REDのエディタが開けば起動成功

## 自動起動設定
次のコマンドを実行する。

```bash
$ sudo systemctl enable nodered.service
```

再起動して、起動しているのを確認する。

## 参考
[Node\-RED : Running on Raspberry Pi](https://nodered.org/docs/hardware/raspberrypi)
PowerShellで期間指定してファイルを削除

```
$path = “path\to\logs”
ls $path | ? {$_.LastWriteTime -lt <日時>} | rm
```

* `ls $path` ... Get-ChildItem
* `? {$_.LastWriteTime -lt <日時>} ` ... 更新日時が~より前
* `rm` ... Remove-Item パイプで渡されたファイルを削除する

## 日時の指定方法
|指定方法 | 内容 |
|----|----|
|(Get-Date).AddHours(-n) | n時間前 |
|(Get-Date).AddDays(-n)  | n日前 |
|(Get-Date).AddMonths(-n)| nヶ月前 |
|(Get-Date).AddYears(-n) | n年前 |

### 更新日時が一ヶ月以前のファイルを削除する例
```
$path = “D:\logs”
ls $path | ? {$_.LastWriteTime -lt (Get-Date).AddMonths(-1)} | rm
```
プロ野球をPythonで分析するためにデータ集めでしたこと

　プロ野球のデータ分析をしようと思いましたが、想定したデータ形式にするまでに手間取ったので、その備忘録として記録しています。今回の目的は、数年分のプロ野球データを[プロ野球データFreak](http://baseball-data.com/)から取得し、取得した各年の選手成績を統合するまでです。

##選手成績の取得
　スクレイピングという言葉も知らないまま、pandasでページに記載されている表をpandas形式に読み込めないかと探したら、丁度よいリンク[HTML の表（＜table＞タグ） をスクレイピングする時も pandas が超便利](https://qiita.com/kitsuyui/items/4906bb457af4d0e2d0a5)がありました。
　表も各ページに１つしかなく、また、各年の情報が記載されているURLのルールもシンプルだったため情報を取得するのに、工夫はありませんでした。今回は、投手データを規定回数に関係なく取得しています。条件によってURLが少し変わるので注意してください。

```py3:投手データの取得
import numpy
import pandas as pd
#import matplotlib.pylab as plt

#urlをリスト形式で取得
df_all = []//各要素に各年のデータが入る
years = range(17,8,-1)
urls = []

#URLを入力：2017年だけ命名規則が違う
for year in years:
    if(year==17):
        urls.append('http://baseball-data.com/stats/pitcher-all/era-1.html')
    else:
        urls.append('http://baseball-data.com/'+ "{0:02d}".format(year)+'/stats/pitcher-all/era-1.html')

#データをURLから取得
for url in urls:
    print('取得URL：'+url)
    df = pd.io.html.read_html(url)
    df = df[0]
    df_all.append(df)
```

##各年のデータ統合
　各年のデータを紐づけるのに、選手名をindexにしようと思いましたが、pd.concatでさくっとできませんでした。問題は２つあって、１つはpd.concatが日本語に対応していないこと、２つ目はindexの重複に対応していないことです。重複の発生原因は、シーズン中の移籍による複数チームへの所属でした。
　まず、9年間の選手名から重複を除去して、各選手名にIDを与えています。

```py3:選手IDの作成
#選手IDの作成
name_list = []
dic = {}
for i in range(len(df_all)):
    name_list.extend(df_all[i]['選手名'])
name_list = list(set(name_list))
for i,name in enumerate(name_list):
    dic[name] = i
    
#選手IDの付与
for i in range(len(df_all)):
    df_all[i]['ID'] = -1
    for j in range(len(df_all[i])):
        df_all[i].loc[j,'ID'] = dic[df_all[i].loc[j,'選手名']]
    df_all[i].index = df_all[i]['ID']
    df_all[i] = df_all[i].drop('ID',axis=1)
```
次に各年に複数球団に所属した選手を除去しています。

```py3:index被りを除去
#index被りを除去
for i in range(len(df_all)):
    doubled_index = []
    count = df_all[i].index.value_counts()
    for j in count.index:
        if(count.loc[j]>1):
            doubled_index.append(j)
    df_all[i] = df_all[i].drop(doubled_index)
```
最後に選手IDで紐づけることにより、選手の９年間のデータをまとめることができました。

```py3:データ統合
#カラム名に年を付ける
for i in range(len(df_all)):
    for col_name in df_all[i].columns:
        df_all[i] = df_all[i].rename(columns = {col_name:col_name+"20"+"{0:02d}".format(years[i])})

df_m = pd.concat(df_all,axis=1)
```
##データの確認
　最後にデータの確認をします。今回は2017年の勝利数上位２０人の最近９年間の勝利数を見たいと思います。

```py3:データ確認
data = '勝利'
data_col = ['選手名2017']
for col in df_m.columns:
    if '勝利' in col:
        data_col.append(col)
df_m = pd.concat(df_all,axis=1)
df_m = df_m.sort_values('勝利2017',ascending=False)
df_m = df_m[data_col]
df_m.head(20)
```
#####結果
<img width="481" alt="成績.png" src="https://qiita-image-store.s3.amazonaws.com/0/196468/e58500d6-3899-962c-e01a-0f8bb3082861.png">

##終わりに
　TOP10にここ９年間毎年勝利している人っていないんですね。なかなか厳しい世界だなと改めて感じました。今回は、分析せずに終わったので、面白い分析ができたらまた上げたいと思います。分析した方は、コメントなりここのリンクを張るなりしていただけると幸いです。