OmniAICreator/Qiita-1.07M huggingface dataset:
KerasでRNN Attentionを試す

# はじめに
　Attentionを試して見たくて、調べて見たところ、下記の記事がサンプルプログラムもあってわかりやすく解説されていたので、試して見ました。

https://medium.com/datalogue/attention-in-keras-1892773a4f22
https://github.com/datalogue/keras-attention

# チュートリアル
　様々な日付表記文字列をエンコードし、bidirectional LSTMモデルで YYYY-MM-DD フォーマットの文字列をデコードするというものです。データセットは、Fakerいうツールで日付文字列を生成したあとbabelでフォーマット、多言語に変換することで多様な日付表記のデータセットを作り出しています。

# トレーニング結果
　手元のPCだと、2時間ほどかかりました。最終的にはAccuracyは99%以上になりました。

```
Epoch 50/50

  1/100 [..............................] - ETA: 1:54 - loss: 0.0119 - acc: 0.9962 - all_acc: 0.0000e+00
  2/100 [..............................] - ETA: 1:57 - loss: 0.0073 - acc: 0.9975 - all_acc: 0.0000e+00

...

 98/100 [============================>.] - ETA: 2s - loss: 0.0092 - acc: 0.9970 - all_acc: 0.0000e+00
 99/100 [============================>.] - ETA: 1s - loss: 0.0092 - acc: 0.9970 - all_acc: 0.0000e+00
100/100 [==============================] - 161s 2s/step - loss: 0.0092 - acc: 0.9970 - all_acc: 0.0000e+00 - val_loss: 0.0086 - val_acc: 0.9972 - val_all_acc: 0.0000e+00
```

　トレーニング後、例として"2001年01月01日"という文字列をinputした時のAttentionの様子です。
![2001年1月1日.png](https://qiita-image-store.s3.amazonaws.com/0/128327/1485df31-0a72-fbb7-ff95-ad442c79e045.png)
　"01"という文字列が複数含まれていても、ちゃんと正しいところをAttentionしてOutputしていることがわかります。

# 最後に
　deep learningはブラックボックスとよく言われますが、Attentionによって着目しているところが明確になることで、ブラックからグレーぐらいにはなるように思います。
download-db-log-file-portion でログファイルを一括ダウンロード


download-db-log-file-portion の説明にこのように書いてあった

>Downloads all or a portion of the specified log file, up to 1 MB in size.

1 MB 超えたらどうなるんだろう。
ということで越してた時のワーニングもつけよう。

# 参考
[download-db-log-file-portion — AWS CLI 1.14.46 Command Reference](https://docs.aws.amazon.com/cli/latest/reference/rds/download-db-log-file-portion.html)

# 前提
- Amazon Linux 2

# 説明にはこう書かれてた
>In order to download the entire file, you need --starting-token 0 parameter:

>aws rds download-db-log-file-portion --db-instance-identifier myinstance \
>--log-file-name log.txt --starting-token 0 --output text > full.txt

# スクリプト
```download_rds_logs.sh
#!/bin/bash

set -u
: $1

DB_INSTANCE_IDENTIFIER=$1
OUTPUT="."

logs_json=`aws rds describe-db-log-files --db-instance-identifier ${DB_INSTANCE_IDENTIFIER} | jq ".DescribeDBLogFiles"`

len=$(echo $logs_json | jq length)
for i in $( seq 0 $(($len - 1)) )
do
        row=$(echo $logs_json | jq .[$i])
        logfilename=`echo $row | jq -r ".LogFileName"`
        size=`echo $row | jq -r ".Size"`
        if [ ${size} -gt 1000000 ]; then
                echo ""
                echo "WARN: ${logfilename} is over 1M ${size}. Please check this logfile is copmletion."
                echo ""
        else
                echo ${logfilename}
        fi
        
        # 保存用のファイル名用意
        savefile=`echo ${logfilename}| sed -e "s/\//-/g"`

        aws rds download-db-log-file-portion --db-instance-identifier ${DB_INSTANCE_IDENTIFIER} \
        --log-file-name ${logfilename} --starting-token 0 --output text \
        > ${OUTPUT}/${savefile}
done
```
centOS7 パーティション切り直し

仮想環境に入れたcentOS7のルートディレクトリの容量が100%となりDockerが動かなくなったのでパーティションを切り直した。
今回良くわかったのは、仮想環境を作る段階で十分な容量を取っておくとあとあと苦労しないということ。

以下、基本的な流れ。

```
fdisk -l /dev/sda

GPartedでパーティション切り直し

lvextend -A n -l 100%VG /dev/mapper/hoge

df -h

pvresize /dev/sda2
lvresize /dev/sda2

centOS6 
  resize2fs  /dev/mapper/hoge

centOS7 
  xfs_growfs /dev/mapper/hoge
```


参考サイト

CentOS7で仮想Disk拡張後のLVM論理ボリューム拡張設定
http://yomon.hatenablog.com/entry/2016/04/22/233825

「GParted」の使い方
https://pctrouble.net/software/gparted.html
TortoiseGitがgithubとうまく連携しない

いろいろやってうまくいった方法を残す。

環境
win10 home

# gitをインストール
gitbashで`ssh-keygen`で公開鍵を作る
作った公開鍵をgithubのセッティングから設定しておく


# Tortoisegitをインストール

Tortoiseの設定画面で名前とメールアドレス入力

githubのリポジトリのclone or DownloadのOpen in DesktopでTortoisegiを開く。
連携するらしい。

いろいろいじって、うまくいかず、インストール、アンインストールを繰り返し、余計な設定ファイルがどこかに残っていて次やったらこの方法ではうまくいかないかもしれませんが、その都度ぐぐるしかないと感じました。



サルでもわかるGit入門
https://backlog.com/ja/git-tutorial/intro/intro2_1.html
差分追加更新のためのSQL



- MERGE ステートメント
- delete insert
    - http://docs.aws.amazon.com/ja_jp/redshift/latest/dg/t_updating-inserting-using-staging-tables-.html
    - https://www.postgresql.jp/document/9.1/html/sql-delete.html
- FULL OUTER JOIN

## delete insert
- redshiftの例引っ張ってきた
- join version(昔ハマった)
- ハマったときに諦めてやったin

```sql:delete_using.sql
delete from target 
using stage 
where target.primarykey = stage.primarykey;
```

```sql:delete_table_as.sql
delete a
from target as a
inner join stage
on target.primarykey = stage.primarykey;
```

```sql:delete_in.sql
delete
from target
where primarykey in (
  select primarykey from stage
)
```

```sql:delete_after.sql
insert into target 
select * from stage;
```

## MERGE
```
merge into target
using stage
on target.primarykey = t2.primarykey
when matched then
  update set target.column_1 = stage.column_1
when not matched then
  insert values (stage.primarykey, stage.column_1)
;
```

```
INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
  ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
```

```
update target a 
set column_1 = column_1
from stage
where a.id = stage.id;
```

## FULL OUTER JOIN
旧verも更新されつつ新verも更新されるパターンで使った

- めんどう
- 自由度が高い

```sql:full_outer.sql
select
  case
    when stage.primarykey is not null then stage.primarykey 
    else target.primarykey
  end as primarykey
  , case
    when stage.primarykey is not null then stage.column_1 
    else target.column_1
  end as column_1
  -- etc.
from target
full outer join stage
on target.primarykey = stage.primarykey
```
BigQueryよく使うもの

## query template
```
#standardSQL
-- outline
select
```

## meta
## table wild card
viewが含まれるとエラーになる

```sql
select
  _table_suffix as table_suffix_ymd
  , count(1) as record_count
from dataset.table_*
group by 1
```

```sql
#standardSQL
-- table record counts (日付テーブル用、じゃなくても集計対象にはなる)
select
  _table_suffix as table_suffix
  , regexp_extract(_table_suffix, '(.*)_\\d{8}') as table_name
  , regexp_extract(_table_suffix, '.*_(\\d{8})') as ymd
  , count(1) as record_count
from
  `for_wild_card.*`
group by 1,2,3
```

## timestamp
```sql
#standardSQL
select
  -- not date_add
  timestamp_add(timestamp('yyyy-mm-dd'), interval n part)
  , format_timestamp("%F %X", timestamp('yyyy-mm-dd hh:mm:ss'))
```

## array
### unnest
```sql
#standardSQL
-- five record
with t as (
  -- [1,3,5]
  select 1 as id, generate_array(1, 5, 2) as ary union all
  select 2 as id, [6,7] as ary
)
select
  t.id
  , ary2
from t
cross join unnest(t.ary) as ary2
```

### aggregation
```sql
#standardSQL
-- length, records value to array, concat arrays
with t as (
  select 1 as id, 1 as v, [1, 2, 3] as ary union all
  select 2 as id, 2 as v, [1, 2, 3]    as ary union all
  select 2 as id, 2 as v, [1, 2]    as ary union all
  select 2 as id, 3 as v, [4]        as ary
)
select
  id
  , sum(array_length(ary)) as total_length
  , array_agg(v order by v desc) as v_ary
  , array_agg(distinct v order by v) as v_uniq_ary
  , array_concat_agg(ary) as concat_ary
from t
group by id
```

## json(struct, int64, array)
```sql
#standardSQL
-- nested struct, int64
create temporary function to_struct(json_str string)
returns struct<
  key int64
  , nested struct<key2 string>
>
language js as """
  return JSON.parse(json_str)
"""
;
with t as (
  -- 2^63 -1
  -- 9223372036854775807
  -- 9223372036854776000 <- JSON.parsed (over 64bit)
  
  -- 2^62-1, js number is double
  -- 4611686018427387903
  -- 4611686018427387904 <- JSON.parsed (not equal)
  select '{"key": 4611686018427387903, "nested": {"key2": "string_value"}}' as json_str
)
select
  json_str
  , cast(json_extract(json_str, '$.key') as int64) as json_value
  , json_extract(json_str, '$.nested.key2') as json_quoted_value
  , json_extract_scalar(json_str, '$.nested.key2') as json_scalar_value
  , to_struct(json_str) as bq_struct
from t
```

```sql
#standardSQL
-- array of struct
create temporary function to_ary(json_str string)
returns array<struct<
  key int64
>>
language js as """
  return JSON.parse(json_str)
"""
;
with t as (
  select '[{"key": 1}, {"key": 2}]' as json_str
)
select
  json_str
  , to_ary(json_str) as bq_ary
from t
```


## create table using bq query
```shell
cat .sql | bq -q --apilog=apilog.log query \
  --destination_table=dataset.table \
  --allow_large_results \
  --use_legacy_sql=false \
  --replace=true
```
IN句生成君

Vue.jsで作ってみました。
テキストボックスに改行区切りのデータを貼ると、
IN ('00001', '00002') みたいな形式になおしてくれます。

<p data-height="626" data-theme-id="0" data-slug-hash="EQgqeO" data-default-tab="result" data-user="watabean" data-embed-version="2" data-pen-title="create IN (sql)" class="codepen">See the Pen <a href="https://codepen.io/watabean/pen/EQgqeO/">create IN (sql)</a> by watabean (<a href="https://codepen.io/watabean">@watabean</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>



このままだと使いづらすぎるのであとでGitHub Pagesに上げると思います！


2/24追記
でかく表示できると知ったのでこのままにしておきます。
ちょっとだけコードを修正しました。
【SSIS】ForEach ループコンテナーで取込ファイル内容をループさせる

# はじめに
SSISの日本語ドキュメントが少ないので、、、

がんばってしらべました。

#サンプルパッケージ
早速、以下のようなForEach ループコンテナーが動作するパッケージを作成します！
実行すると、取込ファイルの内容がメッセージボックスに出力される処理をします。
###取込ファイル
![テストデータ.png](https://qiita-image-store.s3.amazonaws.com/0/115879/6164cd3a-db99-9511-9c21-44fe87d02d77.png)
###実行動作
####1件目
![実行動作.png](https://qiita-image-store.s3.amazonaws.com/0/115879/db51e429-dc2c-2f04-9378-bff9ecf6bedd.png)
####2件目
![実行動作2.png](https://qiita-image-store.s3.amazonaws.com/0/115879/ba234783-016b-9c2c-f539-e50b04e00b16.png)
###制御フロー
![ForEachコンテナー設定(制御フロー).png](https://qiita-image-store.s3.amazonaws.com/0/115879/235bfb0c-6583-a8cf-c73e-1a6cb8e4ea0d.png)
###データフロー
![ForEachコンテナー設定(データフロー).png](https://qiita-image-store.s3.amazonaws.com/0/115879/6c16b1de-5020-9d60-ef55-f432b17d5419.png)
###変数
![ForEachコンテナー設定(変数の定義).png](https://qiita-image-store.s3.amazonaws.com/0/115879/ead45328-dadc-7322-520d-5f0c7948ec1d.png)
#ForEachループコンテナ設定
データフロータスクで取得したファイル内容(変数:ListOfFileData)をForEachに設定します。
![ForEachコンテナー設定(コレクション).png](https://qiita-image-store.s3.amazonaws.com/0/115879/8ecd77e5-4ef7-dddc-8ef9-536049d91166.png)
メッセージボックスに表示させたい変数をマッピングしてください。
![ForEachコンテナー設定(変数のマッピング).png](https://qiita-image-store.s3.amazonaws.com/0/115879/2891b877-4d77-806d-11f2-4e3b381409ea.png)
# ちなみに、
Enumeratorの設定を__Foreach Item列挙子__でなく**Foreach ADO列挙子**をお使い下さい。
Foreach Item列挙子は1~12月とか、月~日といった固定値でループさせたい場合に使用するらしいです。
Twilio Functionsを使ってRestAPI経由で電話をかける

:::note alert
2023年5月1日を持ちまして、株式会社KDDIウェブコミュニケーションズのTwilioリセール事業が終了したため、本記事に記載されている内容は正確ではないことを予めご了承ください。
:::

# はじめに

この記事は、中京テレビハッカソン（Hack-Chu）2018で要望があったため作成したサンプルです。
実行するためには、Twilioのアカウントが必要です。

## Twilio Functionsとは

Twilio Functionsは、Node.jsで書かれたコードを、Twilioのサーバー上で実行するためサーバーレスアーキテクチャです。
Twilioの管理コンソールのRuntimeメニューの中に、Functionsというメニューがあるので、その中から作成します。
また、この記事のコードを実行するためには、FunctionsのConfigureの設定で、「Enable ACCOUNT_SID and AUTH_TOKEN」にチェックを入れてください。

## サンプルコード

```lang:Functions
exports.handler = function(context, event, callback) {
	const twilioClient = context.getTwilioClient();
	twilioClient.calls.create({
		from: '+8150XXXXXXXX',  // Twilioで購入した番号
		to: '+81X0XXXXXXXX',    // 発信先電話番号（E.164形式）
      url: 'https://example.com/twiml.xml'  // 相手が応答した時に実行したいTwiML
	}, function(err, result) {
      if (err) {
        callback(err);
      } else {
          console.log(result.sid);
          callback(null, result.sid);
      }
	});
}
```
修正する箇所は以下の３ヶ所です。

from: 発信者番号です。ここはTwilioで購入した番号だけが指定できます。
to: 発信先の番号です。E.164形式で指定してください。
url: 相手が応答した時に実行したいTwiMLを返すためのURLを指定します。
urlの指定部分は以下の記事も参考にしてください。
https://qiita.com/mobilebiz/items/dc2d3cad76760d39c967
Amazon Linux2にnginxをinstallするメモ

Extrasというレポジトリにあるらしい

```$ amazon-linux-extras | grep nginx```
3  nginx1.12=latest  enabled  [ =1.12.2 ]

インストール
```sudo amazon-linux-extras install nginx1.12```

起動
```sudo systemctl start nginx.service```

自動起動
```$sudo systemctl enable nginx.service```

自動起動の確認
```[ec2-user@ip-10-40-0-142 ~]$ systemctl is-enabled nginx.service```
enabled
Domo の アクセストークンを取得する (Node.js)

こちらのプログラムを Node.js で書きました。
[Python で Domo の アクセストークンを取得する](https://qiita.com/ekzemplaro/items/91ddb8a19f3ec861666f)

```js:get_token.js
#! /usr/bin/node
/*
	get_token.js

					Feb/24/2018
*/
// ----------------------------------------------------------------
var config_domo=require("./config_domo")
// ----------------------------------------------------------------
console.error ("*** 開始 ***")

const config = config_domo.config_domo_proc ()

var Client = require('node-rest-client').Client
var client = new Client(config)

const url="https://api.domo.com/oauth/token?grant_type=client_credentials&scope=data"

client.get(url,function (data, response) {
	console.log(data)
	console.error ("*** 終了 ***")
})

// ----------------------------------------------------------------
```

次の user と password は書き換えて下さい。

```js:config_domo.js
/*
	config_domo.js

					Feb/24/2018
*/
// ----------------------------------------------------------------
exports.config_domo_proc = function ()
{
	var config = {}
	config['user'] = "0ab7adx2-1ep8-11bb-a622-67g91f578e56"
	config['password'] = "cd295ed5dd11eb70914f8fx61523e8370b9e72d23c084a1209154ad6d203b3ba"

	return config
}

// ----------------------------------------------------------------
```
Python matplotlib 図と凡例のタイトルのフォントサイズを変える

# はじめに
ここでは，図と凡例のタイトルのフォントサイズを変更する方法を紹介します．
私の場合，正式な図のタイトルは，報告書に図番号をつけて図の下側に配置するのですが，同じような図のケースの判別ため，図のタイトルを挿入しています．この目的のため，matplotlibによる図タイトルのフォントは小さめにしたい．
また，凡例にタイトルをつけることもあるのですが，そのフォントサイズの制御方法がわからなくて，調べました．世の中には，同じようなことをやりたい人がいるものですね．

[ここ：https://github.com/matplotlib/matplotlib/issues/8699](https://github.com/matplotlib/matplotlib/issues/8699)

# やっていること
それでは，図を見てみましょう．

![fig_title1.png](https://qiita-image-store.s3.amazonaws.com/0/129300/ddc8d1c6-c94f-fc26-eb81-65cd052a2ac2.png)

## Case-1: subplot(131)
以下の部分で，図全体のフォントサイズを 20 に，フォントファミリーを sans-serif に指定します．

```
fsz=20
plt.rcParams["font.size"] = fsz
plt.rcParams['font.family'] ='sans-serif'
```

これにより，軸の数字および凡例内のフォントサイズは 20 になり，図タイトルのフォントサイズはデフォルトで指定値 20 の 1.2 倍になっています．図タイトルの位置はデフォルトでは図の中央です．凡例の位置は，matplotlib は中央右を選びました．

## Case-2: subplot(132)
以下を実行しました．

+ 凡例位置を上左に設定
+ 凡例内のフォントサイズを 10 に指定（flg=10）
+ 図タイトルのフォントサイズを 20 に指定（fti=fsz）
+ 図タイトルの位置を左寄せに指定

凡例と図タイトルに関する指定は以下の通り．

```
flg=10  # 凡例のフォントサイズ
fti=fsz # タイトルのフォントサイズ
......
......
plt.legend(loc='upper left',fontsize=flg,title='Function')
plt.title('Case-2',loc='left',fontsize=fti)
```

ここで違和感があるのが，凡例のタイトルのフォントが大きすぎる！
これをなんとか制御したい．

## Case-3: subplot(133)
凡例のタイトルのフォントサイズを指定する方法が以下の部分．変数 ```lg``` に凡例を描く部分を取得し，タイトル部分のフォントサイズを再指定するという処理のようです．

```
lg=plt.legend(loc='upper left',fontsize=flg,title='Function')
lg.get_title().set_fontsize(flg)
```
これでやりたいことができました．
一行でもいけるようです．

```
plt.legend(loc='upper left',fontsize=flg,title='Function').get_title().set_fontsize(flg)
```

# プログラム全文
プログラムを以下に示します．

```python:
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-np.pi, np.pi, 100, endpoint=True)
c, s, t = np.cos(x), np.sin(x), -np.tanh(x)

fig=plt.figure(figsize=(14,4),facecolor='w')
fsz=20
plt.rcParams["font.size"] = fsz
plt.rcParams['font.family'] ='sans-serif'

plt.subplot(131)
plt.plot(x, c, label='cos')
plt.plot(x, s, label='sin')
plt.plot(x, t, label='-tanh')
plt.legend(title='Function')
plt.title('Case-1 (default)') # デフォルトではフォントサイズは1.2倍？

flg=10  # 凡例のフォントサイズ
fti=fsz # タイトルのフォントサイズ

plt.subplot(132)
plt.plot(x, c, label='cos')
plt.plot(x, s, label='sin')
plt.plot(x, t, label='-tanh')
plt.legend(loc='upper left',fontsize=flg,title='Function')
plt.title('Case-2',loc='left',fontsize=fti)

plt.subplot(133)
plt.plot(x, c, label='cos')
plt.plot(x, s, label='sin')
plt.plot(x, t, label='-tanh')
lg=plt.legend(loc='upper left',fontsize=flg,title='Function')
lg.get_title().set_fontsize(flg)
plt.title('Case-3',loc='left',fontsize=fti)

fnameF='fig_title2.png'
#plt.tight_layout()
plt.savefig(fnameF, dpi=200, bbox_inches="tight", pad_inches=0.1)
plt.show()
```

# 参考：tight_layoutの効果
コードではコメントにしてある ```plt.tight_layout()``` のコメントを外すと以下のような図になります．図と図の間を少し開けてくれます．その分，軸数値の小数点がなくなりました．これについては欲しい数値をコード内で指定すれば良い．

![fig_title2.png](https://qiita-image-store.s3.amazonaws.com/0/129300/8c036630-f36c-f5ec-31d5-0da82cfb877f.png)

以　上
Twilio Functionsで、AITalkを組み合わせたTwiMLを生成する

:::note alert
2023年5月1日を持ちまして、株式会社KDDIウェブコミュニケーションズのTwilioリセール事業が終了したため、本記事に記載されている内容は正確ではないことを予めご了承ください。
:::

# はじめに

この記事は、中京テレビハッカソン（Hack-Chu）2018で要望があったため作成したサンプルです。
実行するためには、Twilioのアカウントと、AITalkのアカウントが必要です。

## Twilio Functionsとは

[Twilio Functions](https://jp.twilio.com/functions)は、Node.jsで書かれたコードを、Twilioのサーバー上で実行するためサーバーレスアーキテクチャです。
Twilioの管理コンソールのRuntimeメニューの中に、Functionsというメニューがあるので、その中から作成します。

## AITalkとは

WEBサービスなどから、高品質音声合成エンジンAITalk®をSaaS型で利用できるサービスです。感情も表現することができるため、単調な音声合成のイメージを覆す表情豊かな音声読み上げが実現できます。
TwilioのTTS（Text to Speech）は日本語がイケてないので、AITalkさんのサービスを使うケースは有効です。

今回ご紹介するのは、話したいメッセージをAITalkを通じて流暢な音声にしてTwiMLを生成するものになります。
生成したFunctionsのPATHを呼び出すことで、TwiMLを返すことができます。

## サンプルコード

```lang:Functions
exports.handler = function(context, event, callback) {
    const text = event.text || "とても残念なお知らせです。"; // 話させたいメッセージ
    const emotion_j = event.j || "0.0"; 	// 喜び（0.0〜1.0）
    const emotion_s = event.s || "1.0"; 	// 悲しみ（0.0〜1.0）
    const emotion_a = event.a || "0.0"; 	// 怒り（0.0〜1.0）
    const username = "XXXXXXXX";  // AITalkのユーザID
    const password = "XXXXXXXX";  // AITalkのパスワード

    let mp3Url = "http://webapi.aitalk.jp/webapi/v2/ttsget.php?username="+username+"&password="+password
    mp3Url += "&speaker_name=maki_emo&ext=mp3&text=" +encodeURIComponent(text)
    mp3Url += "&style="+encodeURIComponent('{"j":'+emotion_j+', "s":'+emotion_s+', "a":'+emotion_a+'}');
  
    const twiml = new Twilio.twiml.VoiceResponse();
    let playParams = {};
    playParams.loop = 1;    // 再生回数（デフォルトは1、0なら無限ループ）
    twiml.play(playParams, mp3Url);
  
    callback(null, twiml);
};
```
Functionsの実行は、Functionsを生成したときのPATH欄で指定したURLを実行します。
今回のサンプルでは、以下のパラメータを指定することも可能になっています。

|パラメータ|内容|
|:--|:--|
|text|再生させたいメッセージ|
|j|感情（喜び） 0.0〜1.0の範囲で指定|
|s|感情（悲しみ） 0.0〜1.0の範囲で指定|
|a|感情（怒り） 0.0〜1.0の範囲で指定|


生成されるTwiMLはこんな感じになります。

```lang:TwiML
<Response>
<Play loop="1">
http://webapi.aitalk.jp/webapi/v2/ttsget.php?username=XXXXXXXX&password=XXXXXXXX&speaker_name=maki_emo&ext=mp3&text=%E3%81%A8%E3%81%A6%E3%82%82%E6%AE%8B%E5%BF%B5%E3%81%AA%E3%81%8A%E7%9F%A5%E3%82%89%E3%81%9B%E3%81%A7%E3%81%99%E3%80%82&style=%7B%22j%22%3A0.0%2C%20%22s%22%3A1.0%2C%20%22a%22%3A0.0%7D
</Play>
</Response>
```

こんな感じです。
Happy Hacking!
Android 8.1 OreoのBluetooth関連の注意点




## まえがき
AOSP(Android Open Source Project)へのBluetooth関連のコミットを見ていたら
Androidの公式ドキュメントには記載されていないAndroid 8.1のBluetoothの動作を見つけたので紹介します。

## スクリーンオフ中はフィルタ無しのBLEスキャンが停止する

### AOSPへのコミット
https://android-review.googlesource.com/c/platform/packages/apps/Bluetooth/+/449136/

### コミットの内容
スクリーンがオフになった時にフィルタ無しのBLEスキャンが停止します。
スクリーンオンになるとBLEスキャンが再開しアプリケーションにスキャン結果が通知されます。

スクリーンオフ中もフィルタ無しBLEスキャンを開始することは出来ますが、スキャン結果が
アプリケーションに通知されるのは次回スクリーンオン時以降になります。

### 回避方法
BLEスキャンをかける時は、適切なフィルタを設定しましょう。
一部の古いAndroid端末では不具合によりBLEスキャンフィルタが機能しない機種があったため
スキャンフィルタを使わない実装をしている方は注意してください。
スキャンフィルタはBluetoothのチップで処理しているため、Bluetoothスタック等の相性により
以前はうまく動かないケースが過去にありました。
8.1以降に対応するAndroid端末ではさすがに解消されている可能性が高いので
スキャンフィルタを使う実装を行っても問題ないかと思います。


## アプリがバックグラウンドになるとBLEスキャンモードが省電力モードになる

### AOSPへのコミット
https://android-review.googlesource.com/c/platform/packages/apps/Bluetooth/+/454618/

### コミットの内容
アプリがバックグラウンド(non-foreground state)になるとBLEスキャンモードが
SCAN_MODE_LOW_POWERになります。SCAN_MODE_BALANCED、SCAN_MODE_LOW_LATENCYを想定した実装をしている方は注意してください。バックグラウンドになると勝手にBLEスキャン結果の通知が遅くなります。

### 回避方法
調査中です。フォアグラウンドサービスでスキャンしておくと良さそう？？


## おわりに
Android Marshmallowで入ったDoze機能、さらにNougatで入ったDeep-Doze、
Oreoではバックグラウンドの実行制限、位置情報の制限など、省電力に関する機能が色々とはいっています。
上記のコミットもその省電力対応の一貫と思われますが、開発者としては公式ドキュメントに注意点として
記載しておいて頂けると大変助かるなー、と思いました。
M5Stackで日本語表示させてみる

M5StackのTFTディスプレィAPIは日本語表示に対応していないのですが、Arduino IDEが使えるので、過去のArduino関係での表示例を探したところ、手頃なものがありました。

探した元ネタはこちらです: [NefryBTで日本語表示させてみる](https://qiita.com/m2wasabi/items/8e882715bace48cfea9f)

元ネタと同様に [misakiUTF16_1.04.zip](https://github.com/m2wasabi/Arduino-misakiUTF16/releases/download/1.04-b/misakiUTF16_1.04.zip)をダウンロードして、
Arduino IDEの「スケッチ」→「ライブラリをインクルード」→「.ZIP形式のライブラリのインクルード」でインストールします。

表示サンプルコードの移植は、ほとんどフォントのドットデータの描画をM5StackのAPIで置き換えるだけでした。

以下、結果です。

```C++
#include <M5Stack.h>
#include <misakiUTF16.h>

void misakiPrint(int x, int y, char * pUTF8) {
  int n=0;
  byte buf[40][8];  //320x8ドットのバナー表示パターン
  while(*pUTF8)
    pUTF8 = getFontData(&buf[n++][0], pUTF8);  // フォントデータの取得

  // 文字の描画
  for (byte i=0; i < 8; i++) {
    for (byte j=0; j < n; j++) {
      for (byte k=0; k<8;k++) {
        if(bitRead(buf[j][i],7-k)) {
          M5.Lcd.drawPixel(x + 8*j + k , y + i, TFT_WHITE);
        }
      }
    }
  }
}

void setup() {
    M5.begin();
    M5.startupLogo();

    M5.Lcd.setBrightness(100);
    M5.Lcd.fillScreen(TFT_BLACK);
    misakiPrint(0,0, "みさきフォントで書き出してみる☆");
    misakiPrint(0,16, "ごめん、ヘルシェイク矢野のことを考えてた…");
    misakiPrint(0,24, "ごめん、ヘルシェイク矢野のことを考えてた…");
    misakiPrint(0,32, "ごめん、ヘルシェイク矢野のことを考えてた…");
    misakiPrint(0,40, "ごめん、ヘルシェイク矢野のことを考えてた…");

    delay(5000);

    M5.Lcd.fillScreen(TFT_BLACK);
    misakiPrint(60,28, "ヘールシェイク！！");
    delay(1500);
    misakiPrint(15,50, "ヘールシェイク！！");
    delay(1500);
    misakiPrint(80,36, "ヘールシェイク！！");
    delay(1500);
    misakiPrint(20,3, "ヘールシェイク！！");
}

void loop() {
}
```

動かすと...

![IMG_4355.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/106817/212fd546-f137-76ab-b71b-e36f92ee85a7.gif)


M5StackのTFTディスプレイに表示するにはちょっと小さいので、そのうち別のフォントでも試してみようと思います。
JavascriptでStyle Transfer

## ml5js
deeplearnjsをラッピングしたml5を使うと簡単にmachine learningで遊べます。
https://github.com/ITPNYU/ml5
https://itpnyu.github.io/ml5/


## code
Style-Transferのwebアプリもわずか50行くらいでできます。
https://github.com/sleepy-maker/fast_style_transfer_in_p5ML


### image uploader version
https://sleepy-maker.github.io/fast_style_transfer_in_p5ML/imguploader/

### Webcam version
https://sleepy-maker.github.io/fast_style_transfer_in_p5ML/webcam/

### Mirror version
https://sleepy-maker.github.io/fast_style_transfer_in_p5ML/live/
aws wait で RDS のリストアを自動化

Aurora のリストア後にパラメータとかも付け替えないといけないので、できる限り自動化したい。

# 参考
- [AWS CLIのWaitersによる待ち受け処理を実装する ｜ Developers.IO](https://dev.classmethod.jp/cloud/aws/aws-cli-waiters/)
- [db-instance-available — AWS CLI 1.14.45 Command Reference](https://docs.aws.amazon.com/cli/latest/reference/rds/wait/db-instance-available.html)
- [Aurora を AWS CLI でスナップショットから復元する - Qiita](https://qiita.com/paper2/items/48aeb92cea56428d524f)

# aws wait help
```
$ aws rds wait help

NAME
       wait -

DESCRIPTION
       Wait until a particular condition is satisfied.

AVAILABLE COMMANDS
       o db-instance-available

       o db-instance-deleted

       o db-snapshot-completed
```

# スクリプト

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

set -u
: $1 $2

COLOR=$1
INSTANCE_CLASS=$2

DB_CLUSTER_IDENTIFIER="test-aurora-cluster-${COLOR}"
DB_INSTANCE_IDENTIFIER="test-aurora-${COLOR}"

DB_CLUSTER_PARAMETER_GROUP_NAME="test-cluster-parameter"
DB_PARAMETER_GROUP_NAME="test-parameter"

# alias 有効にする
shopt -s expand_aliases
alias wait_available="aws rds wait db-instance-available --db-instance-identifier ${DB_INSTANCE_IDENTIFIER}"

aws rds restore-db-cluster-from-snapshot \
--cli-input-json file://restore-db-cluster-from-snapshot.json \
--db-cluster-identifier ${DB_CLUSTER_IDENTIFIER}

aws rds create-db-instance \
--cli-input-json file://create-db-instance.json \
--db-instance-identifier ${DB_INSTANCE_IDENTIFIER} \
--db-cluster-identifier ${DB_CLUSTER_IDENTIFIER} \
--db-instance-class ${INSTANCE_CLASS}
wait_available

aws rds modify-db-cluster \
--db-cluster-identifier ${DB_CLUSTER_IDENTIFIER} \
--db-cluster-parameter-group-name ${DB_CLUSTER_PARAMETER_GROUP_NAME} \
--apply-immediately
# wait_available

aws rds modify-db-instance \
--db-instance-identifie ${DB_INSTANCE_IDENTIFIER} \
--db-parameter-group-name ${DB_PARAMETER_GROUP_NAME} \
--apply-immediately
# wait_available

# Reboot は手動でやる
# aws rds reboot-db-instance \
# --db-instance-identifier ${DB_INSTANCE_IDENTIFIER}
# wait_available
```

# Reboot は自動化できなかった
パラメーター変えたので再起動をする必要がある。
`modify-db-cluster`, `modifi-db-instance` で `--apply-immediately` オプションをつけてパラメータグループを変えても DB instance はしばらく avalibale な状態になるため wait を使ってもまたずに進んでしまった。独自に wait を作ってもよいけどそれならこのままでいいか。

# 追記
aws wait はタイムアウトがあるようです。大きなデータを持った RDS の復元ではエラーになって先に進んでしまう。結局ステータスチェックするスクリプト作らないといけないのか。。。
Android端末が使っているBluetoothモジュールを調べる方法


# はじめに

Bluetoothの仕事をしているとちょくちょくBluetooth SIGの認証情報を調べることがあります。
認証情報を見るとスマホ等のガジェットに載っかっているBluetoothチップ・モジュールやスタックのことが分かるので、暇を見つけては眺めて一人でにやにやしています。

調べる目的は２つあります。

1. 発売前のBluetoothを搭載したスマホやガジェットの情報を知りたいとき
2. スマホやガジェットが搭載しているBluetoothモジュールのことを知りたいとき

私の場合はこんな感じです。

特にAndroid端末では搭載しているBluetoothモジュールやスタックが機種によってバラバラですが、認証情報を見ることでどんなBluetoothモジュール、スタックを使っているかわかります。

Bluetooth SIG特有の略語や専門用語が多くちょっとわかりづらいですが、いつもやっている調べ方を紹介します。

# Bluetooth SIG認証とは

Bluetoothを使った機器を販売したり、Bluetoothロゴを製品に使用するためにはロゴ認証を取得する必要があります。ロゴ認証を取得するためには認証試験にパスする必要があります。

※既に認証取得済みのBluetoothモジュールを利用する場合はSIGへの登録のみ必要(有料)

詳しい認証の情報のについてはBluetooth SIGの公式サイトをご覧ください。


# Bluetooth 認証取得済み機器
Bluetooth SIGが公開している認証情報のサイトはこちらです。
Search欄に適当な会社名やデバイス名で検索すると認証情報を確認できます。

https://launchstudio.bluetooth.com/Listings/search
![スクリーンショット 2018-01-14 21.41.25.png](https://qiita-image-store.s3.amazonaws.com/0/102273/462714d1-ff03-e633-5537-44c8cbad8eff.png)



# Bluetooth SIGの認証情報から分かること
主に以下のような情報が分かります。

- DID(Declaration ID)
- QDID(Qualified Design ID)
- Listing Date(認証済み機器としてBluetooth SIGにリスティングされた日)
- 会社名
- 製品名
- 製品タイプ
- 認証済みBluetooth機器を使用している場合はその製品のQDID
- 認証取得日(Listingされた日)

# さっそく調べてみる

試しにNokiaのAndroid端末について調べてみましょう。
NokiaはHMD Globalという会社が販売しているのでその会社名で検索してみます。
![スクリーンショット 2018-01-14 21.52.35.png](https://qiita-image-store.s3.amazonaws.com/0/102273/696f953b-dee9-660f-e4a8-ec8fb134a380.png)

Nokia 2というAndroid端末らしき情報が見つかりました！
Listing Dateを見ると **2017-10-26**になっています。Nokia 2が発表されたのが10/31なので
発表のちょっと前にBluetooth　SIG認証を取得したようです。



Declaration IDをクリックして詳細ページに飛ぶとこのような画面になります。

Nokia 2の公式サイトではBluetooth 4.1対応となっていますが、SIG認証は4.2となっています。
![スクリーンショット 2018-01-14 22.58.39.png](https://qiita-image-store.s3.amazonaws.com/0/102273/0c696cf2-3980-604e-bff3-34c2513ebf86.png)

おや、Qualcommという名前が出てきました。Qualcommが申請したSIG認証情報を参照しているようです。
![スクリーンショット 2018-01-14 23.01.35.png](https://qiita-image-store.s3.amazonaws.com/0/102273/17bbd21c-29b9-10ca-5edd-4d56eb08e042.png)

さらに他のSIG認証情報も参照しているようです。
![スクリーンショット 2018-01-14 23.01.26.png](https://qiita-image-store.s3.amazonaws.com/0/102273/8d7c5aa9-18a8-18b5-e74b-3e6c93db5260.png)

QDID 86918という参照情報をたどってみます。
![スクリーンショット 2018-01-14 23.08.54.png](https://qiita-image-store.s3.amazonaws.com/0/102273/f397eff9-e41b-a87f-99f5-9ee1cbac9797.png)
Nokia 2はFluorideというBluetoothスタックを使っていることが分かりました！
FluorideはAndroid 6以降で使われているAndroid標準のBluetoothプロトコル・スタックです。
Nokia 2はPure Androidなので、やはり標準のスタックを使っているようです(カスタマイズしているかどうかまでは分かりません。。。)

と、こんな感じで参照しているQDIDを調べていきます。。

### わかったこと
Nokia 2のBluetooth周りはこんな感じなっているのではないかと推測できそうです。

- 認証取得日：2017-10-26
- Bluetoothスタック：Fluoride(Android標準のBluetoothプロトコル・スタック)
- Bluetoothモジュール：Qualcomm社製(Bluetoothモジュール名は複数出てきたため特定できず)


# 参考リンク
- [Bluetooth SIG](https://launchstudio.bluetooth.com/Listings/search)
- [Nokia 2](ç†√)
FessのデータストアクロールでRedmineのチケットを検索する

[Fess](https://github.com/codelibs/fess)でRedmineをクロールする場合の設定が[公式ドキュメント](https://fess.codelibs.org/ja/12.0/admin/webconfig-guide.html?highlight=redmine#redmine)に載っている。

公式ドキュメントでは、ウェブクロールでクロールする手順になっている。

では、[データストアクロール](https://fess.codelibs.org/ja/12.0/admin/dataconfig-guide.html)でのクロールはどのような手順になるのかと思い、試してみた。

## 環境など
* Redmine
    * バージョン 3.3.4
    * DBはPostgreSQL
* Fess
    * バージョン 12.0.1
    * CentOSにrpmでインストール

クロール対象はRedmineのチケットのみとする。


## 設定1. JDBCドライバの配置

[こちら](https://jdbc.postgresql.org/download.html)からPostgreSQLのJDBCドライバをダウンロードする。

ダウンロードしたJDBCドライバを`<Fessのインストールディレクトリ>/app/WEB-INF/lib/`（RPMでインストールした場合は`/usr/share/fess/app/WEB-INF/lib/`）に配置する。

## 設定2. データストアクロールの設定

![2018-02-18_21h15_25.png](https://qiita-image-store.s3.amazonaws.com/0/177284/6d97caa6-50ee-e5ee-ac09-b68c74354345.png)


「パラメータ」欄
```
driver=org.postgresql.Driver
url=jdbc:postgresql://<Redmineのホスト名>:5432/redmine?&    ssl=false?charSet=UTF-8
username=<RedmineのDBにアクセスするためのユーザ名>
password=<RedmineのDBにアクセスするためのパスワード>
sql=select id, subject, description, updated_on from issues
```

ポイント

* 「sql」にRedmineのDBのissuesテーブルからチケットのID、題名、説明、更新日時を取得するSQLを指定する

「スクリプト」欄
```
url="http://<Redmineのホスト名とパス>/issues/" + id
host="<Redmineのホスト名>"
site="<Redmineのホスト名>"
title="【Redmine - チケット】" + subject
content=description
cache=description
digest=description
anchor=
content_length=description.length()
last_modified=updated_on.substring(0,10) + "T" + updated_on.substring(11,23) + "Z"
location=
latitude=
longitude=
```

ポイント

* SQLで取得するチケットのID、題名、説明、更新日時を各パラメータに当て込む

## 動作確認
以下のようなチケットを用意した状態でFessのクローラを実行する。

![2018-02-21_08h04_44.png](https://qiita-image-store.s3.amazonaws.com/0/177284/55236df8-e9bf-ec33-0210-0932def5e3da.png)

クロール完了後、チケットの説明欄にある文言をFessで検索すると、Redmineのチケットがヒットする。

![2018-02-21_08h05_42.png](https://qiita-image-store.s3.amazonaws.com/0/177284/da561321-1530-d70e-1fc0-468c6f41ea27.png)

## 課題
上記の設定では、チケットの題名と説明等のみしかFessに登録していない。
その他の項目（カスタムフィールドや注釈など）でも検索をしたい場合は、それらをクロールするよう、データストアクロールの設定を工夫する必要がある。

## Tips
### クローラのデバッグログを出力する

意図した通りにクロールがされていない場合は、クローラのデバッグログを出力すると、原因がわかる場合がある。

デバッグログを出力するには、ジョブの設定を編集し、logLevelに"debug"を指定する。

![2018-02-24_12h12_21.png](https://qiita-image-store.s3.amazonaws.com/0/177284/9e0d3176-6862-7fc8-5074-5ee268c506ff.png)

この設定により、「システム情報 ＞ ログファイル」から参照できる「fess-crawler.log」にデバッグログが出力されるようになる。
GoのSliceをSortする(sort.Sliceとsort.SliceStable)


# GoのSliceをSortする(sort.Sliceとsort.SliceStable)
sort.Sliceとsort.SliceStableを使用してGoのSliceをSortしてみる。

本記事のコード全体は以下。
https://play.golang.org/p/Lnj8kAwWxyy

## 安定ソート(stable sort)とは
まずsortは[安定ソート](https://ja.wikipedia.org/wiki/%E5%AE%89%E5%AE%9A%E3%82%BD%E3%83%BC%E3%83%88)かどうかで挙動が異なる

安定ソート(stable sort)については以下がわかりやすいので引用させていただいた。
> 安定ソート（あんていソート、stable sort）とは、ソート（並び替え）のアルゴリズムのうち、同等なデータのソート前の順序が、ソート後も保存されるものをいう。つまり、ソート途中の各状態において、常に順位の位置関係を保っていることをいう。
> たとえば、学生番号順に整列済みの学生データを、テストの点数順で安定ソートを用いて並べ替えたとき、ソート後のデータにおいて、同じ点数の学生は学生番号順で並ぶようになっている。

引用元 : [安定ソート - Wikipedia](https://ja.wikipedia.org/wiki/%E5%AE%89%E5%AE%9A%E3%82%BD%E3%83%BC%E3%83%88)

## Goのsort packageのSliceとSliceStable
Goのsort packageには、安定ソートを保証しないSlice関数と安定ソートを保証するSliceStableが存在する。

それぞれ以下で実装とその結果を記す
### sort.Slice

```go
func Slice(slice interface{}, less func(i, j int) bool)
```
安定ソートを保証しない。
第二引数で与えたless関数を使用して、第一引数で与えたSliceをソートする。
安定ソートを行うには、SliceStableを使用する。


#### 実装
```go
		people := []Person{
    		{Name: "V", Age: 3},
    		{Name: "K", Age: 3},
    		{Name: "Y", Age: 3},
    		{Name: "A", Age: 4},
    		{Name: "E", Age: 3},
    		{Name: "D", Age: 1},
    		{Name: "C", Age: 3},
    		{Name: "X", Age: 2},
    		{Name: "B", Age: 3},
    	}
    
    	sort.Slice(people, func(i, j int) bool { return people[i].Name < people[j].Name })
    	fmt.Printf("NameでSort(Not-Stable):%+v\n", people)
    
    	sort.Slice(people, func(i, j int) bool { return people[i].Age < people[j].Age })
    	fmt.Printf("AgeでSort(Not-Stable):%+v\n", people)
```

#### 実行結果

```

NameでSort(Not-Stable):[{Name:A Age:4} {Name:B Age:3} {Name:C Age:3} {Name:D Age:1} {Name:E Age:3} {Name:K Age:3} {Name:V Age:3} {Name:X Age:2} {Name:Y Age:3}]
AgeでSort(Not-Stable):[{Name:D Age:1} {Name:X Age:2} {Name:V Age:3} {Name:C Age:3} {Name:E Age:3} {Name:K Age:3} {Name:B Age:3} {Name:Y Age:3} {Name:A Age:4}]
```

### sort.SliceStable

```go
func SliceStable(slice interface{}, less func(i, j int) bool)
```

安定ソートを行う

```go
people2 := []Person{
		{Name: "V", Age: 3},
		{Name: "K", Age: 3},
		{Name: "Y", Age: 3},
		{Name: "A", Age: 4},
		{Name: "E", Age: 3},
		{Name: "D", Age: 1},
		{Name: "C", Age: 3},
		{Name: "X", Age: 2},
		{Name: "B", Age: 3},
	}

	sort.SliceStable(people2, func(i, j int) bool { return people2[i].Name < people2[j].Name })
	fmt.Printf("NameでSort(Stable):%+v\n", people2)

	sort.SliceStable(people2, func(i, j int) bool { return people2[i].Age < people2[j].Age })
	fmt.Printf("AgeでSort:%+v\n", people2)
}
```

#### 実行結果

```
NameでSort(Stable):[{Name:A Age:4} {Name:B Age:3} {Name:C Age:3} {Name:D Age:1} {Name:E Age:3} {Name:K Age:3} {Name:V Age:3} {Name:X Age:2} {Name:Y Age:3}]
AgeでSort:[{Name:D Age:1} {Name:X Age:2} {Name:B Age:3} {Name:C Age:3} {Name:E Age:3} {Name:K Age:3} {Name:V Age:3} {Name:Y Age:3} {Name:A Age:4}]
```

ソート前の順序が、ソート後も保存されている。
Nameで、整列済みのPersonデータを、AGEの順で安定ソートを用いて並べ替えると、ソート後のデータは、同じAGEのPersonはName順で並んでいる。

## 参考にさせていただいた記事
[sort - The Go Programming Language](https://golang.org/pkg/sort/#SliceStable)
[安定ソート - Wikipedia](https://ja.wikipedia.org/wiki/%E5%AE%89%E5%AE%9A%E3%82%BD%E3%83%BC%E3%83%88)
Chrome で自動入力設定の情報を削除

https://support.google.com/chrome/answer/142893?co=GENIE.Platform%3DDesktop&hl=ja

フォーム入力時に表示される自動入力候補は、Windowsの場合、Shift + Delete で削除できる。

忘れそうなので自分用の備忘録。
VBAの正規表現の参照設定の5.5 と 1.0の違い

#ヒントは1999年の文章


>https://msdn.microsoft.com/ja-jp/library/ms974619.aspx
December 13, 1999
日本語版最終更新日 2000 年 11 月 21 日
Microsoft Windows Script 5.5 の最終リリースにより、Microsoft は先進的な ECMA-262 (ECMAScript) の実装を提供するという約束を果たしました。バージョン 5.5 の Windows Script は、既存のスクリプト コードとの互換性を保つために必要ないくつかの違いを除いて、バージョン 3 の ECMAScript に準拠しています。ECMAScript バージョン 3 の変更点は、言語そのものの根本的な改善ではなく、もっぱら組み込みオブジェクトの拡張に関するものです。この記事では、JScriptR と Visual BasicR Scripting Edition (VBScript) 5.5 のいくつかの新機能を簡単に紹介します。

>##VBScript について
これまで、VBScript の正規表現のサポートは JScript のサポートほど完全なものではありませんでしたが、VBScript 5.5 ではようやくそのギャップが埋まりました。VBScript (および VBScript.RegExp COM コンポーネント) には、***サブマッチと置換関数を含む***、JScript の正規表現のすべての機能が含まれています。

>##VBScript におけるサブマッチ
VBScript 5.5 は、JScript と同じように格納を行うための括弧 (サブマッチ) をサポートするようになりました。この新しい機能は、Execute メソッドが返す個々の Match オブジェクトごとに SubMatches コレクションを用意することによって実装されています。次に、電子メール アドレスのコンポーネントを取得するための単純な例を示します (ただし、これは電子メール アドレスをマッチングするための完全な正規表現ではありません)。

##Microsoft VBScript Regular Expressions 5.5 とMicrosoft VBScript Regular Expressions　1.0の違いはSubMatchオブジェクト
正規表現を参照設定するには5.5が1.0のいずれかを選択しなければならない。同時に指定した場合は5.5を優先順位の上にしなければならない。では何が違うか。1.0（5.0まで）SubMatchがないのである。

```vb.net
Dim SMs As SubMatches
```
これは1.0を参照設定するか5.5より1.0を優先するとエラーになる。

##正規表現はIeのエンジンだった
[正規表現によるマッチング - officetanaka](http://officetanaka.net/excel/vba/tips/tips38.htm)[魚拓](http://megalodon.jp/2017-1017-0537-20/officetanaka.net/excel/vba/tips/tips38.htm)

>VBAから正規表現を使うには、VBScriptが便利です。ただし、正規表現をサポートしているVBScriptはVer5.0からですから、IE5.0がインストールされているパソコンでないと使えません。
VBScriptの中で正規表現エンジンを提供しているのはRegExpオブジェクトです。参照設定によるEarly Bindingか、CreateObject関数を使ったLate Bindingで参照します。ここではLate Bindingによるサンプルを紹介します。

>まずは、正規表現で使用するオブジェクトとプロパティやメソッドを整理しましょう

この中にSubmatchコレクションが存在しない。Version5.0までSubMatchは存在しないのである。


[バージョン情報次の表は、ホスト アプリケーションによって実行される Microsoft Visual Basic Scripting Edition のバージョンの一覧です。](https://msdn.microsoft.com/ja-jp/library/cc392490.aspx)

SubMatchは5.5からだが、この表から、これはIE5.5を入れていないと動かないことがわかる。
　Jscriptの方がネットと親和性が高いが、正規表現がJscriptが先行したのもIEのエンジンに近かったからだと理解できる。つまり正規表現はIEのエンジンであり、いまだにIEのエンジンを使っているのである。

https://qiita.com/daik/items/15f9a95d14498f5476aa
>しかし、VBAでの正規表現はPerlやRuby,Javaといったメジャーなプログラミング言語と異なる点が多く、そういった言語でのプログラミングに習熟している方が戸惑うことも多いと思われます。

これもMSの正規表現の成り立ちを見るとよくわかる。テキスト検索のためではなく、あくまでもIE+JAVAからきているからだ。JscriptはJavaにとって代わろうとして作られた言語である。もちろん現在は完全に敗北し、ほとんど知られていない。IEでもIE11では標準では動かない。
BOMに関わるトラブル（個人メモ）

コードの品質チェックでBOMーUTF8が発見されたので
Webページをあたっていくつかピックアップ。

なるほど、即刻直すべき、、、と。

http://yanok.net/2013/03/bom-utf-8.html


>Javaで書かれた処理プログラムがUTF-8のテキストを読み込む際に、BOMを消費せずに単なるUnicode文字のように扱うため、1行目のデータの先頭にゴミが付いた状態になっていたのです。それで、見えないゴミ付きのデータになってしまい、意図どおりに動作しないし、テキストエディタで開いてみても異常に気付かなかったわけです。

>JavaのライブラリでUTF-8のテキストを読み込むとき、先頭にBOMがあると、それを単なるU+FEFFという符号位置の文字データとして読み込んでしまいます。本来のBOMは、Byte Order Markという名前のとおり、バイト順を示す役割のものであって、文字を符号化したデータの一部ではありません。UTF-16/32と違ってバイト順の問題のないUTF-8にBOMを付けるべきかという問題は議論が分かれるところかもしれません。しかし現実にはBOM付きUTF-8は生成されることがあります。

>ウェブ検索で「java utf-8 bom」などとしてみると、BOM付きUTF-8をJavaで読み込んでトラブルになった話が複数出てきたり、また互換性のためにJavaではUTF-8読み込み時の挙動を変える予定はなさそうだという話が出てきたりします。

https://hondou.homedns.org/pukiwiki/pukiwiki.php?JavaSE%20BOM%C9%D5%A4%ADUTF8%A5%D5%A5%A1%A5%A4%A5%EB%A4%F2%C6%C9%A4%DF%B9%FE%A4%E0%A4%C8%A4%C9%A4%A6%A4%CA%A4%EB%A4%AB%A1%A9

>Javaで、UTF-8文書を扱う時に具体的に注意するシーン †
Javaプログラムで独自形式の設定ファイルの読み込むとき
JavaプログラムでXML文書を読み込む時
Windows の notepad(メモ帳) は、BOM付きのUTF-8 形式でファイルを記録するので、notepad(メモ帳)では、これらの文書を編集してはいけない

http://www.rgagnon.com/javadetails/java-handle-utf8-file-with-bom.html

うん、なるほど！
set -e を利用する時は関数の返り値に気をつける

shell で set -e を利用するとエラー時にそこでスクリプトを止めてくれる。
関数の return が 0 以外でも、エラーとしてそこでシェルスクリプトが止まるから注意する。

# 例
```test.sh
set -e

function truehoge() {
    return 0
}

function falsehoge() {
    return 1
}

truehoge
echo "test1"
falsehoge
echo "test2"
```

```
$ ./test.sh
test1
```
[VS Code]Haskell(Stack)用tasks.json


```tasks.json
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "type": "shell",
            "command": "stack",
            "args": [
                "build"
            ],        
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "presentation": {
                "panel": "new"
            },
            "problemMatcher": []
        },
        {
            "label": "run",
            "type": "shell",
            "command": "stack",
            "args": [
                "build; if [ $? = 0 ]; then stack exec ${workspaceRootFolderName}-exe; fi"
            ],
            "presentation": {
                "panel": "new"
            },
            "problemMatcher": []
        },
        {
            "label": "test",
            "type": "shell",
            "command": "stack",
            "args": [
                "test",
                "--fast"
            ],
            "group": {
                "kind": "test",
                "isDefault": true
            },
            "presentation": {
                "panel": "new"
            }
        },
        {
            "label": "clean",
            "type": "shell",
            "command": "stack",
            "args": [
                "clean"
            ],
            "problemMatcher": []
        },
        {
            "label": "haddock",
            "type": "shell",
            "command": "stack",
            "args": [
                "haddock"
            ],
            "problemMatcher": []
        }
    ]
}
```
Raspbianでpiユーザ名とパスワードをうまいこと変更する

Raspbianのセットアップでユーザ名とパスワードを変更するための手順をまとめました。

いつもはpiユーザを削除したり新しいユーザを作成してましたが、
piユーザを変更する方法が良いという[記事](https://jyn.jp/raspberrypi-username-change/)を見かけましたので、
そちらの方式をやってみたいと思います。

#実行環境

```
$ lsb_release -a
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 9.3 (stretch)
Release:        9.3
Codename:       stretch
```

**ここからはすべてSSH接続で作業します。**

#piユーザ情報
初期設定時のユーザIDとパスワード
>User: pi
Pass: raspberry

#tmpユーザを作成
```
$ sudo useradd -M tmp
$ sudo gpasswd -a tmp sudo
Adding user tmp to group sudo
$ sudo passwd tmp
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
```

#自動ログインユーザの変更
2ファイル変更します。

```
$ sudo vim /etc/lightdm/lightdm.conf
```

```:/etc/lightdm/lightdm.conf
autologin-user=pi
↓　
# autologin-user=pi
```

```
$ sudo vim /etc/systemd/system/autologin@.service 
```

```:/etc/systemd/system/autologin@.service
ExecStart=-/sbin/agetty --autologin pi --noclear %I $TERM
↓　piをtmpに変更
ExecStart=-/sbin/agetty --autologin tmp --noclear %I $TERM
```
変更したら再起動します。

```
$ sudo reboot
```

#tmpユーザでログインしてpiユーザ名変更
tmpユーザしかいないことを確認

```
$ who
tmp      tty1         2018-02-24 01:07
tmp      pts/0        2018-02-24 01:08 (192.168.1.4)
```

piユーザ名を変更する

```
piユーザ名を変更する(例：newpi）
$ sudo usermod -l newpi pi

$ sudo usermod -l newpi pi

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for tmp:
$
```

usermod と groupmod を変更する

```
$ sudo usermod -d /home/newpi -m newpi
$ sudo groupmod -n newpi pi
```
変更したら再起動します。

```
$ sudo reboot
```

#newpiでログインしてnewpiのパスワードを変更
```
$ sudo passwd newpi
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for newpi:
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
```

#自動ログインユーザの変更
tmpをnewpiに変更します。

```
$ sudo vim /etc/systemd/system/autologin@.service 
```

```:/etc/systemd/system/autologin@.service
ExecStart=-/sbin/agetty --autologin tmp --noclear %I $TERM
↓
ExecStart=-/sbin/agetty --autologin newpi --noclear %I $TERM
```
変更したら再起動します。

```
$ sudo reboot
```


#tmpユーザを削除
```
$ sudo userdel tmp
[sudo] password for newpi:
$
```

#参考資料
[[Raspbian]ユーザ名変更の個人的に「正しい」と思うやり方]
(https://jyn.jp/raspberrypi-username-change/)
[Raspberry Pi3(ラズパイ)でpiユーザーの自動ログインを外す方法](https://qiita.com/t0yohei/items/f5355f8c456d9cf64679)
<br>
5分で解決・Google AIY Voice Kit　ssh接続でプログラム実行エラーが発生したら

#はじめに
sshを使用して、Google AIY Voice Kitの[assistant_library_demo.py]実行時に下記エラーが出た時の解決方法を説明します。

エラー内容
>Traceback (most recent call last):
  File "./assistant_library_demo.py", line 30, in <module>
    import aiy.assistant.auth_helpers
ImportError: No module named 'aiy'

#解決方法
sshから実行するには、どうやらvenv環境に入る必要がある様です。


###下記の通りコマンドを実行すると

```
cd AIY-voice-kit-python
source env/bin/activate
```

###(env)と表示されvenv環境に切り替わります。
![スクリーンショット 2018-02-24 10.33.11.png](https://qiita-image-store.s3.amazonaws.com/0/240244/cd2037e9-040e-58dc-43fb-5921bb9d8e5a.png)



###デモプログラム実行すると

```
./assistant_library_demo.py 
```

###無事実行され、「オッケーグーグル」機能で遊ぶことができます。
![スクリーンショット 2018-02-24 10.30.34.png](https://qiita-image-store.s3.amazonaws.com/0/240244/7b3b5507-735a-912b-a298-b7c7851758ad.png)

#まとめ
Google AIY Voice Kitのサンプルプログラムをsshで実行する場合は、venv環境への切り替えが必要。
"source env/bin/activate"
[Vue.js]bodyに直接appendする

#概要

モーダルを使うときなど、しばしばrootのappの外側にコンポーネントを挿入したくなることがあります。
vueのツリー構造から外れるので、無理っぽいように一見思えるのですが、render関数と$forceUpdate関数を使うことで実現できます。

#デモ
https://jsfiddle.net/huigo/gdnwqzzu/


#コード

```html
<div id="app">
  <h1>App</h1>
  <input type="text" v-model="message">
  <ul>
    <li v-for="item in list">{{item}}</li>
  </ul>
  <to-body>
    <div>
      <h1>to body</h1>
      <p>{{ message }}</p>
      <button @click="list.push('hello!')">
       Hello!
      </button>
    </div>
  </to-body>
</div>
```

```js
Vue.component('to-body',{
  beforeCreate(){
    this._el = document.body.appendChild(document.createElement("div"));

    //bodyに挿入されるvmです。
    this._vm = new Vue({
      methods:{
        //<to-body>コンポーネントのslotを受け取って、再描画します。
        forseRender(slots){
          this._slots = slots;
          //もらってきたslotはこのvmが監視しているわけではないので、強制的に更新させます。
          this.$forceUpdate();
        }
      },
      render(createElement){
        if (this._slots){
          return createElement('div',this._slots);
        }
      }
    }).$mount(this._el);
  },
  render(createElement){
    //render関数が呼ばれたタイミングでbodyに挿入したvmを再描画させます。
    this._vm.forseRender(this.$slots.default);
  }
});
```
pythonでループさせながら何件かごとにログを出したい

たまに使いたくなるのだが、毎回考えているのがめんどくさくなったので
ここに記載しておく。

## enumerateを使う。

    loopCount = len(xxxList)
    logger.info("Data Count {}".format(str(loopCount)))
    # [Loop]リストに対してループ
    for count,keyCode in enumerate(xxxList):
        try:
            LoopMethod(keyCode)
            if((count+1) % 500 == 0):
                logger.info("{} / {}".format(str(count),str(loopCount)))
        except:
            logger.error(traceback.format_exc(sys.exc_info()[2]))
            logger.error("Error keyCode : {}".format(str(keyCode)))

- ログ出力用にloggerを使っています。
- countで現在のループ回数が取れるけど、毎回出力すると多いので500件に一回だけ出力。
- 総件数をループの前に出力しているので、ループ内では初回は出さないようにする。(countは0始まり)
- 2系。このまま3系でもいけそうな気がするけど試してない。


なんかもう少しかっこいい書き方があったら教えてください。
CentOS7で、ダブルクリックでスクリプトファイルを実行する方法。

デスクトップで、スクリプトファイル vvv を作成します。
そして実行属性をつけます。
（ここでは、chrome を root から起動する例です。）

```
% cd Desktop
% vi vvv
% chmod 0755 vvv
```

中身はこんな感じです。

```
% cat vvv
#!/bin/bash
google-chrome-stable --no-sandbox
```

このままでは、このファイルのアイコンをダブルクリックしても中身を表示するだけですので、gnome の設定を変えます。
まずは、dconf-editor をインストールします。

```
% yum install dconf-editor
```

次に、dconf-editor を起動して、
/org/gnome/nautilus/preferences/executable-text-activation を選択して、値を display -> launch に変更すれば完了です。

![Screenshot.png](https://qiita-image-store.s3.amazonaws.com/0/240366/6a31bb44-a67d-8780-adab-02163321f8a2.png)
JitPackでmulti moduleなAndroid Libraryを配信する

以下のようなmulti module project構成のAndroid LibraryをJitPackで配信できるようにします

```
root
├── core // 主となる機能を格納したmodule
└── plugin  // coreに対して機能を追加するmodule
```

# `core`のみ配信

まずは`core`のみ配信してみます

## Library側
root直下の`build.gradle`に以下を追加します

```build.gradle
buildscript {
  ...

  dependencies {
    // gradle version毎にversionを変更する必要あり
    // https://github.com/dcendents/android-maven-gradle-plugin#note-on-releases
    classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' 
    ...
  }
}
```
次に、`core/build.gradle`に以下の記述を追加します

```core/build.gradle
apply plugin: 'com.github.dcendents.android-maven'

group="com.github.$USERNAME.$REPO"
```

これをGithubにpushするとJitPackでlibraryを配信可能になります

versionはbranch名やtag, commitなど指定可能ですが、今回はbranch名を`example`でpushした体で進めようと思います
この場合、以下のようなversionで配信されます

```
example-SNAPSHOT
```

## Library利用側

配信したLibraryを利用する場合は以下のように記述します

```app/build.gradle
repositories {
  ...
  maven { url 'https://jitpack.io' } // ※ Private repositoryで配信されている場合はauthTokenの設定も必要
}


dependencies {
   ...
   implementation 'com.github.$USERNAME:$REPO:example-SNAPSHOT@aar'
}
```

### 余談

JitPack配信のsetupをしていてこの辺でハマってしまったのですが、
前知識として"multi moduleなlibraryを `com.github.$USERNAME.$REPO:$MODULE:$VERSION`のように読み込むことができる"という情報を仕入れていたため`core`のみ配信可能な状態で以下のような設定をしてしまいました

```app/build.gradle
dependencies {
   ...
   implementation 'com.github.$USERNAME.$REPO:core:example-SNAPSHOT@aar'
}
```

しかし配信されるmoduleが１つだけの場合JitPackが気を利かせて（?）module名を使わないpathに変更してくれるため、このpathでは読み込むことができませんでした :innocent: :innocent: :innocent: 

multi moduleなlibraryを一つ一つsetupする際にはご注意ください :cry: 

# `core`と`plugin` を配信

次に`plugin`を配信します

## Library側

rootの`build.gradle`は既に設定済みなので、`plugin/build.gradle`のみ変更します
変更内容は`core/build.gradle`と同じです

```plugin/build.gradle
apply plugin: 'com.github.dcendents.android-maven'

group="com.github.$USERNAME.$REPO"
```

これをGithubにpushします

## Library利用側

`core`と`plugin`が利用可能になりましたので読み込んでみます

### `core`のみ利用する

`plugin`はいらないよという場合は以下のようにして`core`だけ利用することができます

```app/build.gradle

dependencies {
   ...
   implementation 'com.github.$USERNAME.$REPO:core:example-SNAPSHOT@aar'
}
```

### `core`と`plugin`を利用する

`core`と`plugin`を利用する場合は2通りの設定方法があります

```app/build.gradle

dependencies {
   ...
   implementation 'com.github.$USERNAME.$REPO:core:example-SNAPSHOT@aar'
   implementation 'com.github.$USERNAME.$REPO:plugin:example-SNAPSHOT@aar'
}
```

もしくは


```app/build.gradle

dependencies {
   ...
   implementation 'com.github.$USERNAME:$REPO:example-SNAPSHOT@aar'
}
```
module名を指定しない場合、repository内の全てのmoduleを落としてくるので新しくmoduleが追加されたりした場合、それも配信されます

どちらの方法で読み込むかはユースケースごとに選択すると良いかと思います

# 参考

https://jitpack.io/docs/ANDROID/
https://android.jlelse.eu/publish-multi-module-android-libraries-on-jitpack-339213f6224c
１０分で解決（ちょいハマり）・Google AIY Voice Kit　音声認識失敗 「オッケーグーグル」「アクチュアリ (Actually, there are some basic settings that need your permission first...」しか答えてくれない時の回避策

#この記事について

Google AIY Voice Kit　「assistant_library_demo.py」実行時に、

- 私　「オッケーグーグル　"what's on my calendar?"」

- AIY 「Actually, there are some basic settings that need your permission first...」

- 私　（泣）

と、全然認識してくれない場合の回避策です。


#前提条件
- Google AIY Voice Kit組み立て済み
- [Check Audio] [Check WiFi] テスト完了済み
- GCP (Google Cloud Platform)アカウント作成済み


#解決方法
GCP (Google Cloud Platform)のアクティビティー設定を行うことで解決しました。

Voice Kitのマニュアルに記載がありましたが、読み飛ばしていました。。。

> If the response is Actually, there are some basic settings that need your permission first..., perform step 7 again, being sure to use the same account that you used for the authorization step.


>Go to the Activity Controls panel. Make sure to log in with the same Google account as before.

>Turn on the following:
Web and app activity
Device information
Voice and audio activity


下記３つの設定をONにしないと、「オッケーグーグル」と話しかけても
無視されちゃうみたいですね。

- ウェブとアプリのアクティビティー
- 端末情報
- 音声アクティビティー

![スクリーンショット 2018-02-24 9.23.11.png](https://qiita-image-store.s3.amazonaws.com/0/240244/1007112c-92ee-8e04-a92e-26a7bd3859b4.png)


![スクリーンショット 2018-02-24 9.23.19.png](https://qiita-image-store.s3.amazonaws.com/0/240244/1f355e83-c7eb-e05b-a3b3-24fba64b8286.png)

![スクリーンショット 2018-02-24 9.23.24.png](https://qiita-image-store.s3.amazonaws.com/0/240244/955315c2-b06f-6d20-73ef-4dd3845733f2.png)


#まとめ

Google AIY Voice Kit　「assistant_library_demo.py」実行時に、
認識してくれない場合はGCP (Google Cloud Platform)のアクティビティー設定が必要

- ウェブとアプリのアクティビティー
- 端末情報
- 音声アクティビティー

早く作りたかったせいか、マニュアルをざっと斜め読みして作業を進めましたが、
それが仇になった様です。
急がば回れでしょうか。。。