OmniAICreator/Qiita-1.07M huggingface dataset:
Text Analytics APIのセンチメント分析で映画のセリフを分析してみた

AzureのText Analytics APIでセンチメント分析（感情的なネガポジ）を行えることは [Azure Text AnalyticsをPythonから使ってみた - Qiita](https://qiita.com/oyngtmhr/items/8b305986e7aab823fb62) の記事で説明しました。
今回は実際に映画のセリフを使ってセンチメント値がどのように推移するかを検証してみました。

# 元データ

今回は「風に谷のナウシカ」の全セリフを分析してみます（集め方は自分で考えましょう）

# 前処理

集めてきたセリフをまずGoogle翻訳で日本語から英語に翻訳します。
（日本語でやってみたけどText Analyticsの判定結果が大半が0.5で中立だったため）
翻訳したセリフをText Analytics APIで読める形に整形します。
各セリフは短かったので適当にシーンごとにまとめた上で、以下のような形に整形します。今回はPythonで作った簡単なスクリプトと手作業の半々で処理しました。

```
{'id': '1', 'language': 'en', 'text': '\n Another village died.\n \n '}
```

# 分析

Text Analytics APIを呼び出します。Pythonを使う場合のスクリプトは [Azure Text AnalyticsをPythonから使ってみた - Qiita](https://qiita.com/oyngtmhr/items/8b305986e7aab823fb62) の記事を参照ください。
今回は映画の全セリフ、140件のテキストを一度に渡しましたが約4秒で結果が返ってきました。速い。

# 結果

センチメント値の高いトップ３（肯定的）です。

```
0.993096828
英語：'Whatever\n \n Please become a godparent of this child\n \n Always make a good breeze blow her\n \n Let\'s undertake\n \n I will give you a good name\n \n Thank you\n \n May you grow strong like a princess\n \n '
元の日本語：'どうかこの子の名付け親になって下さい\n いつもいい風がその子に吹きますように\n 引き受けよう\n よい名を贈らせてもらうよ\n ありがとう\n どうか姫様のように丈夫に育ちますように\n'

0.99137938
英語：'Mysterious place\n \n Hi\n \n Finally I came.\n \n How are you?\n \n '
元の日本語：'不思議な所\n やあ\n やっと見つけて来たよ\n 気分はどう？\n '},

0.990973055
英語：'What do you think?\n \n Yupa! It is a ship.\n \n boat?\n \n I will come.\n \n large!\n \n Wow\n \n '
日本語:'何ごとかね\n ユパ様！船です\n 船？\n 来るわ\n 大きい！\n ワ～\n '},
```

次にセンチメント値の低いトップ３（否定的）です。

```
0.003649145
英語：'There is no choice but to burn it\n \n This forest is already useless\n \n When it\'s too late\n \n The valley is only got into the rotting sea\n \n What\'s wrong?\n \n Forest who protected the reservoir for 300 years\n \n If you do not come shit down with me\n \n Well then, why not just hold on\n \n Let\'s also go\n \n '
元の日本語：'燃やすしかないよ\n この森はもうだめじゃ\n 手遅れになると谷は腐海にのみ込まれてしまう\n どうにかならんのかのう？\n 貯水池を３００年も守ってくれた森じゃ\n くそ　あいつらさえ来なければ\n こりゃ　このままじゃおさまらんぞ\n わしらも行こう\n '},

0.006181002
英語：'Nausicaa\n \n I am scared of myself\n \n I do not know what to do with hatred.\n \n I do not want anyone to kill any more\n \n '
元の日本語：'ナウシカ\n 私自分が怖い\n 憎しみにかられて何をするかわからない\n もうだれも殺したくないのに\n'

0.006376058
英語：'I do not feel like being fucked like Baba\n \n It is the same thing\n \n I just wish for the mystery of the corrupt sea\n \n I just wish to solve it\n \n We humans are like this\n \n It seems to be ruined by rotting seas\n \n Is it a defined tribe?\n \n I want to find out\n \n to me\n \n I wish I could help Mr. Yupa\n \n '
元の日本語： 'ババ様からかわれては困る\n 同じことじゃろうが\n 私はただ腐海のなぞを解きたいと願っているだけだよ\n 我々人間はこのまま腐海にのまれて滅びるよう定められた種族なのか それを見きわめたいのだ\n 私にユパ様のお手伝いができればいいのに\n '
```

結構妥当な結果が出ています。

次にセンチメント値の推移をグラフにしてみました。映画中の盛り上がる部分、シリアスな部分の波のようなものが見えそうです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/69163/f5636812-79d1-bf1e-1d49-8db6a360ddfa.png)

# まとめ

今回は検証なのでデータの前処理は手作業の部分が多いですが、ちょっと工夫すれば自動化して、セリフさえあればすぐに何でも分析できそうです。
アイデアとAzureと少しのテクニックがあれば、映画のセリフとその評価の定量分析がすぐに簡単にできてびっくりするくらいでした。また、なにかアイデアを思い付いたら試してみたいです。
配列内のソートと値のハードコピー

### 配列のハードコピー
```js
//items=[....]
var newitems= items.slice();
```
### 配列内の特定オブジェクトのソート
```js
//target is .value
items.sort(function (a, b){return a.value - b.value;});//smaller
items.sort(function (a, b){return b.value - a.value;});//bigger
```
### 全部
```js
var items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: -12 },
  { name: 'Magnetic', value: 13 },
  { name: 'Zeros', value: 37 }
];
console.log(items.slice()) ; //nil slice be the hard copy

items.sort(function (a, b){return a.value - b.value;});//smaller
console.log(items.slice())

items.sort(function (a, b){return b.value - a.value;});//bigger
console.log(items)
```
### 追記 ラムダの方が短い
```js
items.sort((a,b)=>a.value - b.value);//a.small
items.sort((a,b)=>b.value - a.value);//b.igger
```
Flutter で使えるマテリアルアイコンを探す方法

Flutter でアイコンを使いたい場合は以下のように書きます。

```dart
new Icon(Icons.settings)
```

このアイコンはたくさんの種類が用意されています。これらの一覧を確認したい場合は、Icons の API ドキュメントを見ます。

- https://docs.flutter.io/flutter/material/Icons-class.html

以下のような感じで、定数ごとのアイコン画像が分かるので、ここから探しましょう。

<img width="359" alt="スクリーンショット 2018-02-22 16.24.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/21341/0fdf4f05-582f-c238-8948-242215e6f79a.png">
CentOS7 の ip_forward 有効化で rp_filter が邪魔してる話

## やりたいこと
- CentOS7 で eth0 に届くパケットを全て eth1 に転送し出力する

これだけ！！！

## 問題
- カーネルパラメータ ip_forward を有効化 (ip_forward=1) 、iptables で FORWARD チェーンにルールを追加しても転送が行われない
- 詳しくしらべると、iptables の PREROUTING チェーンにはパケットが届いているが、その先の FORWARD チェーンに到達していない
    - iptables の仕組みついてはこちらを参照 (http://oxynotes.com/?p=6361)

## 解決策
- rp_filter を無効化する

これだけ！！！

CentOS7 では、スプーフィング対策で rp_filter というフィルターが稼働しており、これが自身宛以外のパケットを drop させている模様。

## まとめ
やるべきことは以下の通り
- ip_forward を有効化
- eth0 の rp_filter を無効化　(タイポ修正しました)
- eth1 の rp_filter を無効化　(タイポ修正しました)
- iptablesのFORWARDチェーンにルールを追加

```
# echo 1 > /proc/sys/net/ipv4/ip_forward
# echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter
# echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter
# iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT
```
create-react-app で CSS Modules を使う

create-react-app v1.1.1 では現在、標準では CSS Modules を利用することができません。
検索したところ、[ejectしろ（要約）](https://medium.com/nulogy/how-to-use-css-modules-with-create-react-app-9e44bec2b5c2)という記事が出てきましたが、react-scripts の新しいバージョンでは導入が進められていて、テスト中ながらその機能を利用することができます。
reac-scripts を v2.0.0 アルファ版にアップデートしましょう。

**新しいアプリケーションを作る場合**

```
$ npx create-react-app@next --scripts-version=2.0.0-next.b2fd8db8
```

**既存のアプリケーションに適用する場合**

```
$ yarn upgrade react-scripts@2.0.0-next.b2fd8db8
```

アップデートを行うことで、`[name].module.css` という命名規則に則ったファイルのみ、CSS Modules として認識されるようになります。

react-scripts v2.0.0 はまだアルファ版のため、当然ですが以下のような注意書きがあります

- 機能が壊れているか、期待どおりに機能しない可能性があります
- react-scripts v1 系からの破壊的変更があるようです

---

参考:
- [Roadmap for react-scripts@2.0](https://github.com/facebook/create-react-app/issues/3815)
- [Add support for CSS Modules with explicit filename - [name].module.css](https://github.com/facebook/create-react-app/pull/2285)
EndNote 「範囲を編集することができません。」

# Endnoteのエラー

調べてもわからなかったので問い合わせた。解決策を載せておく。

## エラーの内容

> （1）EndNote のバージョン
> EndNote X7.7.1
> （3）PC の OS のバージョン
> Windows 7 Professional
> （4）Word のバージョン
> Microsoft Word 2010

> ワードのEndnoteアドインを使用しております。
> リファレンスをインサートしようとすると，別ウィンドウが開かれ，「範囲を編集することができません。」と表示され，リファレンスを追加することができなくなってしまいました。
> Insertの方法は，Edit&Manage Citationのボタンやドラッグ＆ドロップなどいくつかの方法で試してみましたが，いずれもダメです。
> EndNoteを再インストールしてみてもダメでした。
> この症状は，今週の始めごろからです。それ以前は普通に使えていました。
> 別のPC（Win7）に入っているEndnote X5で試してみても，同じ症状が出ました。

以下のエラーが現れる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/99215/9b3adbd7-820a-f281-2424-018916df22c1.png)

## 回答

> Wordの校閲機能（編集履歴とコメント
機能）は使用していますか。もし使用している場合、それを
オフにしてからもう一度お試していただけますでしょうか。
また、ほかのプログラムのアドイン/プラグインはインストール
されていますでしょうか。例えばMendeleyなどのもの。
ほかのアドインはEndNote のアドインと競合になるため、
それらをアンインストールしていただけると幸いです。

## というわけで、以下を確認しました。

- 校閲機能
　　　オフになっていました。
- ほかのアドインとの競合
　　　これが原因でした。

ファイル→オプション→アドイン→（テンプレート）設定→Mendeleyのチェックを外す

![image.png](https://qiita-image-store.s3.amazonaws.com/0/99215/1a3428f0-7d24-e4ee-e1a7-dbef8762d167.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/99215/cd6e250e-a990-0938-8589-a91ccf20e990.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/99215/5b609f02-2269-2dbf-0b26-80b276b0f9cf.png)

Mendeley-1.17.12.dotm
ここのチェックをはずした。
OKしたら、エラーは出なくなった。

でも、最近Mendeleyをインストールしたわけでもないのに、なぜ急に使えなくなったのだろう。

ユサコの方、ありがとうございます。
Parcel + Riot 高速で環境構築

parcelは設定ファイル不要の高速バンドラ。

今回は公式のものではありませんがparcel用のriotプラグイン`parcel-plugin-riotjs`を使います。

##インストール
`npm init -y`
`npm install --save riot parcel-bundler parcel-plugin-riotjs`

##ディレクトリ構成
--index.html
--main.js
--app.tag
--package.json
## コード
まずはindex.html。

```index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Parcel-Riot</title>
</head>
<body>
  <app></app>
  <script src="main.js"></script>
</body>
</html>

```
次にエントリーファイルを作ります。

```main.js
import riot from 'riot'
import './app.tag' //ここでタグファイルを読み込む
riot.mount('app')
```
そしてタグファイル

```app.tag
<app>
  <h1>{ title }</h1>
  this.title = 'Hello'
</app>
```

## 実行
package.jsonにこれを追加する

```json
  "scripts": {
    "start": "parcel index.html"
  },
```
`npm start`で実行。
そしてここにアクセスhttp://localhost:1234/

本当に設定ファイルとか書かずにできましたね。:+1:

##発展
たとえばriotで、pugで書きたいときとか、buble・babelの細かい設定をしたいときは`.riotrc.js`というファイルを作成します。
まぁ　中身は公式のriot.config.jsと同じなので書き方は公式に任せます ->>> http://riotjs.com/ja/guide/compiler/

例としてpugを設定してみます。
まずはインストール `npm i -S pug`

```　.riotrc.js
const pug = require('pug')

module.exports = {
  template: 'pug',
  parsers: {
    html: {
      pug: html => pug.compile(html)
    }
  }
}

```

作成したら設定完了です！これでタグファイル内をpugでかけるようになります。
実行はいつも通りに`npm start`

## 最後に
設定ファイル書かなくてもいいのはとても楽ですね。
brewインストールパッケージメモ

Macを新規でセットアップしたのでメモ。Homebrew自体は https://brew.sh/index_ja.html の手順でインストール。

```sh
brew tap railwaycat/emacsmacport ; brew install emacs-mac ; brew untap railwaycat/emacsmacport
brew linkapps

brew install fish
brew install fzf
brew install wireshark --with-qt

brew cask install qlstephen qlcolorcode qlmarkdown

brew cask install docker
brew cask install sourcetree
brew cask install java
brew tap caskroom/versions
brew cask install java8
brew cask install intellij-idea-ce
brew install graphviz

brew install protobuf
brew install sbt

brew install pyenv
brew install pyenv-virtualenv
```
influx retention policy not found: default

普通に保存しようとしたら下記エラーが

```
{"error":"retention policy not found: default"}
```

```bash
> settings
Setting           Value
--------          --------
Host              localhost:8086
Username          xxxxx
Database          myDatabase
RetentionPolicy   # 確かにない ...
Pretty            false
Format            column
Write Consistency all
Chunked           true
Chunk Size        0
```

```bash
$ influx -username root -password root
Connected to http://localhost:8086 version 1.3.9
InfluxDB shell version: 1.3.9
> use myDatabase
> CREATE RETENTION POLICY "default" ON "myDatabase" DURATION 7d REPLICATION 1
> show retention policies on myDatabase
name    duration shardGroupDuration replicaN default
----    -------- ------------------ -------- -------
autogen 0s       168h0m0s           1        true
default 168h0m0s 24h0m0s            1        false
```

__そもそも変な時間で送ってたのが問題だったのかも__
ダミーだからといって一年前とかを指定してたし。

default 作ってから1年前データ送ると下記のように怒られたため

```
{"error":"partial write: points beyond retention policy dropped=1"}
```

policyの範囲外にあたるデータは送れないとのこと
とりあえずの決めで7dを保存期間としたので、一昨日の日付でインサートするようにしたら通った。

時系列DBなのでダミーデータといえど特に必要ない限りは直近の時刻で入れた方がよいのかも
ATOM1.24で最新のPythonシンタックスハイライトを使用する



# 概要
2018年02月安定版のATOM(1.24)上でPython3のType hints機能を使用するとハイライトが上手く機能しなくなります。
![スクリーンショット 2018-02-22 12.36.49.png](https://qiita-image-store.s3.amazonaws.com/0/189239/2103b372-539e-ecf4-7d4d-6f157e52de93.png)
理由としてはATOM(1.24)に同梱されているlanguage-python(0.45.6)がType hintsを考慮していないからです。

# サポート状況
最新の*language-python(0.49.2)*はType hintsをサポートしています.（PR:[#234](https://github.com/atom/language-python/issues/234
)）

そのため以下の方法で解決することができます
* ATOM1.25のベータ版を使用する(追記: 2018年05月現在安定版が存在します)
* ATOM1.24に最新のlanguage-pythonを入れる

今回は後者の方法で対応することにしました。

# buildin-packageアップデート出来ない問題
language-pythonはATOMに最初から同梱されているパッケージなのですが、
apmでアップデートしようとすると警告がでてきます。

```bash
% apm install language-python
The language-python package is bundled with Atom and should not be explicitly installed.
You can run `apm uninstall language-python` to uninstall it and then the version bundled
with Atom will be used.
Installing language-python to /Users/user/.atom/packages ✓
```
ただ、アップデートが出来ないだけで、apmの管理ディレクトリにインストールされます。
※ buildinと最新の二つがATOMにインストールされた状態になる。

# パッケージ名被る問題
このまま利用開始しようとすると0.45.6と0.49.2が競合して動かないので古い方を無効化したいのですが
バージョン単位で無効化する機能がATOMにないので上手く行きませんでした.
buildinのパッケージを削除してやろうと思ったのですがどこにあるかわかりませんでした。

そこでパッケージ名を変更することにしました。以下の方法で変更できます。

```
% cd ~/.atom/packages
% mv language-python language-python-latest
```
その後language-pythonを無効化、language-python-latestを有効化します。

# 1.25向けのパッケージを1.24向けにする対応
1.25では言語名の管理方法が変更されているようなので以下のファイルを修正します
`language-python-latest/grammars/tree-sitter-python.cson`

```cson
id: 'python'
name: 'Python'
type: 'tree-sitter'
parser: 'tree-sitter-python'
legacyScopeName: 'source.python'
```
↓

```
id: 'python'
# name: 'Python'
type: 'tree-sitter'
parser: 'tree-sitter-python'
legacyScopeName: 'source.python'
scopeName: 'source.python'
```

うまくいきました
![スクリーンショット 2018-02-22 12.53.06.png](https://qiita-image-store.s3.amazonaws.com/0/189239/16ec5f3b-1a49-8647-bf56-2d75ee51e2c6.png)

上手く表示されない場合はファイルを閉じて再度開くとうまくいきます(古いlanguage-pythonが選択されている状態になっている)。
python3 pyserial メモ

# ubuntu: permission denied
/dev/ttyのアクセスでpermission denied食らって，
ユーザーがttyのグループに入ってなかったら
```
$gpasswd -a USERNAME dialout
```
でユーザー追加する．(/dev/ttyのグループ: dialout)
一旦ログアウトして，ログインし直したらできるようになってるはず．

# 読み書き
## write
byteで書き込む

```python:serial.py
import serial

with open("/dev/tty~~", 38400) as ser:
   ser.write(b"hoge")
   ser.write("hoge".encode('utf-8'))
```

## read
```
ser.read(n)
ser.readline()
```
read(n)でn文字読み込む
readlineで"\n"まで読み込む
"\n"が来るかわからないときはread()で読み込む．
全部byteで返ってくるくるからdecode('utf-8')とかする．
python　メモ：タイプヒントについて

def ma(text:str,symbol:str):
こんな感じで関数を作ったときに:strの意味がずっとわからず。。

###結果、タイプヒントというもので下記に情報記載###

```python
def greeting(name: str) -> str:
    return 'Hello ' + name
```
関数 greeting で、実引数 name の型は str であり、返り値の型は str であることが期待されます。サブタイプも実引数として許容されます。
https://docs.python.jp/3/library/typing.html
※上はpython公式から引用、

・strとして値をいれて返す時もstrとして出してくださいという意味と捉えました。
強制ではない？？
CentOS 6.6にcrowi-plusをインストールする

# インストール
```
# yum install git
# git clone https://github.com/creationix/nvm.git ~/.nvm
# source ~/.nvm/nvm.sh
# vi ~/.bash_profile

if [[ -s ~/.nvm/nvm.sh ]];
 then source ~/.nvm/nvm.sh
fi

# nvm install 6.11.4
# nvm alias default 6.11.4
# npm install -g npm
# npm install -g yarn@1.1.0

# vi /etc/yum.repos.d/mongodb.repo

[mongodb]
name=MongoDB Repository
baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/
gpgcheck=0
enabled=1

# yum install mongodb-org
# service mongod start
# chkconfig --add mongod 

# git clone https://github.com/weseek/crowi-plus.git
# cd crowi-plus
# yarn

# npm start
```
アクセス先はhttp://x.x.x.x:3000/

# プラグイン
```
# yarn install crowi-plugin-lsx
# yarn install crowi-plugin-pukiwiki-like-linker

# npm start
```
## lsxへの要望
ユーザーのメモをlsxで一覧表示できないかな？
Aさん
2017/10/11
2017/10/10
Bさん
2017/10/05
2017/10/01
とかしたい。

# ファイルアップロードを許可
```
# vi .bash_profile
export FILE_UPLOAD=local

# npm start
```
オレオレマイクロフレームワーク

# 世界最小（自称）のフレームワーク
Webをウロウロしていたりして、「お？このライブラリちょっと使ってみたいな」という時に、HTMLを用意して、jQueryならjQueryを、目的のライブラリはCDNのアドレスとかをindex.xxxxみたいなファイルに書いて、DOMが生成されたら実行されるJavaScriptを書いて、それを指定したりして、とかとか…雛形をコピーしてきてちょこちょこいじるのがめんどくさかったので、バックエンドをnode.jsで書いてAPIとかもサクっと実装出来るように作った、私だけが幸せになれるフレームワークです。
ちなみに、全部**CoffeeScript2**です。
あと、**jQuery3.0**と、**jQueryUI**がデフォルトで読み込まれます←ここポイント

# 使い方
完全に自分用の備忘録なのですが、使うにはまずgithubからクローンしてきます。

```bash
$ git clone https://github.com/digitarhythm/jsframe.git jstest
```
こんな感じで叩くとカレントディレクトリに「**jstest**」というディレクトリが出来ます。ディレクトリが無事に出来ていたら中に入ります。

```bash
├── apps
│   ├── js
│   │   ├── control
│   │   └── view
│   └── src
│       ├── control
│       └── view
├── config
├── libs
│   ├── control
│   ├── template
│   └── view
├── plugins
└── public
```
中はこんな感じになっています。中に入って最初に、

```bash
$ npm i
```
と実行し、必要なnodeモジュールをインストールします。
次に、

```bash
$ ./build
```
と実行します。すると、**apps/src/view**と、**apps/src/control**と、**config**にファイルが生成され、**config**以外はコンパイルされます（CoffeeScriptなので）。生成されるファイルは、

```bash
apps/src/view/main.coffee
apps/src/control/api.coffee
```
です。コンパイルされたJavaScriptファイルは、

```bash
apps/js/view/main.min.js
apps/js/control/api.min.js
```
になります。拡張子が「.min.js」になっているのは、npmモジュール「terffee」でコンパイルするため、自動的にminify化されます。そして察しの良い方はディレクトリで分かると思いますが、**view**のほうに入っているのがクライアントサイドで実行されるJavaScriptにコンパイルされるソースです。
**control**のほうに入っているのが、node.js+expressで実装するAPIにコンパイルされるソースになります（デフォルトでアプリケーションバージョンを返すAPIが定義してあります）。
基本的にはこのファイルを修正して必要な機能を実装していくことになります。

```bash
$ ./build -w
```
を実行すると、

```bash
$ build -w
watching directory [プロジェクトのディレクトリ/apps/src/view]
watching directory [プロジェクトのディレクトリ/libs/view]
watching directory [プロジェクトのディレクトリ/apps/src/control]
watching directory [プロジェクトのディレクトリ/libs/control]
```
と表示され、ソースのタイムスタンプを監視し、変更があった場合に自動的にコンパイルされます。
使いたいプラグインファイルなどは、**plugins**ディレクトリに入れておくと、自動的に読み込まれます。
CDNなどを指定して読み込ませたい場合は、**libs/template/main.ect**ファイルに記述してください。
CSSなどを使いたい場合もこのテンプレートファイルで指定してください。

# Webアプリケーション実行
作っているWebアプリケーションは、node.jsのアプリケーションサーバーでアクセスします。
**config**に生成された、**develop.json**と、**default.json**で使用するポート番号を指定します。**develop.json**がデバッグモード用で、**default.json**がプロダクト用です。

```bash
$ npm run debug
```
と実行するとデバッグモードでアプリケーションが起動します。**node-dev**を使用して起動するので、ソースの修正をすると自動的にアプリケーションサーバーが再起動して変更が反映されます。停止するにはCTRL+Cを押してください。

```bash
$ npm start
```
と実行すると**forever**を使いバックグラウンドで起動します。こちらではソースの修正は自動で反映されませんが、バックグラウンドで動いているプロセスが落ちても自動的に再起動します。

```bash
$ npm stop
```
を実行すると停止します。
デフォルトでは、デバッグモードのアプリケーションに

```bash
http://(アドレス):3001/
```
でアクセスするとブラウザの画面サイズをブラウザに表示します。

```bash
http://(アドレス):3001/api/version
```
でAPIにアクセスすると、package.jsonのバージョン番号を返します。
Cloud TPUの使いどころガイドライン

TPUもリリースされ、CPU, GPU, TPUをどういった時に、何を基準に使い分ければよいのかと思っていたら、以下に記載されていることだったのでメモ。
https://cloud.google.com/tpu/docs/tpus

Cloud TPUは特定のワークロードに最適化されているので、機械学習のワークロードによってはCompute EngineのインスタンスでCPUやGPUを使用した方がよいケースがある。一般的には、どの環境を選択すべきかは以下のガイドラインに従えばよい。

### CPU
- 柔軟性があるプロトタイプを素早く作る必要がある場合
- モデルのトレーニングに時間がかからないような単純なモデル
- 小さなモデル
- C++で記述されたカスタムTensorFlow operationが大部分を占めるモデル
- 利用可能なI/Oやホストのネットワークバンド幅が制限されているモデル

### GPU
- TensorFlowで記述されてないモデルやTensorFlowで記述できないモデル
- ソースが存在していなかったり、変更するのがあまりにも煩わしいモデル
- CPUで一部実行しないといけないようなカスタムTensorFlow　operationがある膨大にあるモデル
- Cloud TPUで利用できないTensorFlowオペレーションがあるモデル
- 大きなバッチサイズを用いる中規模から大規模なモデル

### TPU
- 行列計算が大きく占めているモデル
- 主要なトレーニングループの中にカスタムTensorFlow operationがないモデル
- トレーニングに数週間や数ヶ月かかるモデル
- 大きなバッチサイズを用いる大規模なモデル

### Cloud TPUに向いてないワークロード
- 頻繁にブランチングしてたり要素ごとの積が多くを占めるような線形代数のプログラム。TPUは大量の行列積演算が速くなるように最適化されている。そのため行列積が多くを占めてないワークロードはTPU上では十分なパフォーマンスがでない。
- TPU上で利用できないようなスパースにメモリアクセスするワークロード
- 高精度演算を要求するワークロード。例えば倍精度はTPUに向いてない
- CD++で記述されたカスタムTensorFlow operationを含むニューラルネットワークのワークロード。特にメインのトレーニングループの中にカスタムオペレーションが含まれているケースはTPUに向いてない

参考） TPUで利用可能なTensorFlow ops
https://cloud.google.com/tpu/docs/tensorflow-ops
IdeaVimのCtrl+A(inclement number)が、007を8進数と認識してしまう。[追記あり]

特に技術的tipsでもなんでもないのですが、面白かった＆謎＆不便なので。

[追記]
後ろの方に追記しました。
おんなじ問題を抱えてこの記事にたどり着いたひとのお役に立てればと思います・・・

# tl;dr;
以下のファイルにて、各行でCtrl+A(increment number)を使用する。

```
  Foo007,
  Foo017,
  Foo077,
```

### 普通のVim

```
  Foo008,
  Foo018,
  Foo078,
```

### IdeaVim

```
  Foo010,
  Foo020,
  Foo0100,
```


# くわしく

[IdeaVim](https://github.com/JetBrains/ideavim) において、数値は2進数、8進数、16進数かどうかを判定してincrementしているようです。

- 実装 -> https://github.com/JetBrains/ideavim/blob/0015a4357eb5502faaed20e8238d83a91537b5af/src/com/maddyhome/idea/vim/group/ChangeGroup.java#L1691
- テストケース -> https://github.com/JetBrains/ideavim/blob/b595dfd44320a119d52bda1a8216450e2985b3c0/test/org/jetbrains/plugins/ideavim/action/ChangeNumberActionTest.java#L32

普通のVim（少なくとも私の手元にあるVim 8.0.1420 + MacVim）は、全ての数値を10進数として扱うので、007の次は008になります。


普通の開発では007の次は008であってほしいことのほうが多いような気がします。
バグ報告投げてみたんですが、果たして反応は返ってくるのでしょうか…？

https://youtrack.jetbrains.com/issue/VIM-1418

# 追記
`nrformats` という設定で、8進数認識するか設定可能でした。

デフォルトでは、

```
:set nrformats=octal,hex
```

になっているので、

```
:set nrformats=hex
```

としておけば良いです。
デフォルトでoctalいれてほしくないですが……

https://github.com/JetBrains/ideavim/blob/0dda443cc8febc17d7a0d7f45288981da3df69be/doc/set-commands.md
VSCodeで自動整形ツールのprettierで自動フォーマットされるようにする

去年ぐらいからJavaScriptは[prettier](https://prettier.io/)を使って自動フォーマットされるようにしましょうというのが当たり前になってきたので、その設定の仕方。

というか[Prettier - Code formater](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)という拡張をインストールして完了。

Command(Winはctrl) + p で

```
ext install prettier-vscode
```

でインストール。これでVSCodeのフォーマットが自動的にprettierのものになる。便利。完了。

なお、保存時に自動的にフォーマットがかかるようにするには、基本設定 > 設定で、

```js
  // JavaScriptでのみ保存時フォーマットを有効化
  "[javascript]": {
    "editor.formatOnSave": true
  },
  // prettierのシングルクオーテーションオプションをon
  "prettier.singleQuote" : true
```

を末尾に追加しておけばOK。ここではシングルクオーテーションオプションもオンにしてあるけども、他にも設定で色々変えられるけども、デフォルトが無難。

なお、過去のjsファイル全部フォーマットし直したいときなどは、

```sh
npm install prettier --save-dev
find . -name \*.js | grep -v node_modules/ | grep -v public/ | xargs node_modules/.bin/prettier --write --single-quote=true
```

こんな感じのコマンドを実行しておけばOKだと思われる。除外するのは `node_modules` と `public` フォルダを除外したけどもご随意に。
create-react-app の npm start のポート番号を変える

## まとめ

どちらかでできる。

1. 環境変数 `PORT` を設定する。
1. プロジェクトルートに `.env` ファイルを作って `PORT` を設定する。

```:.env
PORT=4000
```

## 説明

`create-react-app` コマンドで作られたアプリケーションは、`npm start` コマンドで Web ブラウザでアプリケーションを開くよう設定されます。
この `npm start` コマンドは、内部では [react-scripts](https://github.com/facebook/create-react-app/tree/master/packages/react-scripts) というスクリプトを介して実行されています。

```package.json
{
  ...

  "scripts": {
    "start": "react-scripts start",

  ...
```

デフォルトでは `http://localhost:3000` と 3000 番ポートで実行するのですが、設定を書くことでポート番号を変えることができます。

- https://github.com/facebook/create-react-app/tree/master/packages/react-scripts/template#advanced-configuration

環境変数を設定するか、`.env` ファイルを置くことで反映させられます。

#### 環境変数でやる

たとえば `$ PORT=4000 npm start` とすることで、http://localhost:4000 でアプリケーションを開くことができます。
他のプロジェクトに影響がなければ `export PORT=4000` でもいいと思います。

#### `.env` ファイルでやる

プロジェクトルートに `.env` ファイルを作り、以下のように書いて `npm start` すれば OK です。

```:.env
PORT=4000
```

ちなみに `.env` ファイルの仕様はこちら。

- https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-development-environment-variables-in-env
QIIME2 のデータをLEfSe 用に変更する

# QIIME2 の出力結果をLefSe で解析したい．
HuttLab の[LEfSe](https://bitbucket.org/biobakery/biobakery/wiki/lefse) は各サンプル間の統計的有意性があるか解析し各群に特徴的な微生物コミュニティを絞り出してくれるツール．
これまで，QIIME1 ではTaxonomic Analysis で出力されたファイルをLEfSe に与えることで迅速に解析をすることができた．
QIIME2 では，QIIME1 と異なりTaxonomic Analysis で各細菌の割合が相対値ではなく，絶対値で出力されている．そのため，LEfSe に出力結果をそのまま投げることができない．
以下の手順を踏むことにより，相対値のテキストファイルを出力する．

---

## やること
**1. 解析したいLevel をテーブルから抽出する．**
**2. 抽出したテーブルの値を絶対値から相対値に変換する.**
**3. BIOMファイルに出力する.**
**4. BIOMからテキストファイルに出力する.**

---

### 1. 解析したいLevel をテーブルから抽出する．
[collapse: Collapse features by their taxonomy at the specified level](https://docs.qiime2.org/2017.12/plugins/available/taxa/collapse/)
`--p-level 6` はLevel 6(Genus)を指定している．

Level 1 = Kingdom (e.g Bacteria)
Level 2 = Phylum (e.g Actinobacteria)
Level 3 = Class (e.g Actinobacteria)
Level 4 = Order (e.g Actinomycetales)
Level 5 = Family (e.g Streptomycetaceae)
Level 6 = Genus (e.g Streptomyces)
Level 7 = Species (e.g mirabilis)

```bash
qiime taxa collapse --i-table table.qza --i-taxonomy taxonomy.qza --p-level 6 --o-collapsed-table collapsed_table.qza
```

### 2. 抽出したテーブルの値を絶対値から相対値に変換する．
[relative-frequency: Convert to relative frequencies](https://docs.qiime2.org/2017.10/plugins/available/feature-table/relative-frequency/)

```bash
qiime feature-table relative-frequency --i-table collapsed_table.qza --o-relative-frequency-table relative-collapsed_table.qza
```
### 3. BIOMファイルとして出力する.

```bash
qiime tools export --input-path relative-collapsed_table.qza --output-path exported-feature-table

cd exported-feature-table/
```

### 4. BIOMからテキストファイルに変換する.

```bash
biom convert -i feature-table.biom -o table.from_biom_w_taxonomy.txt --to-tsv --header-key taxonomy
```

### `table.from_biom_w_taxonomy.txt` をLEfSeに投げよう！

チュートリアルはこちら
[LEfSe Tutorial](https://bitbucket.org/biobakery/biobakery/wiki/lefse#rst-header-lefse-galaxy)

解析はこちら
[Hutlab Galaxy](http://huttenhower.sph.harvard.edu/galaxy/)
textareaが異常に重い時はspellcheck="false"

# 経緯
現在英作文を書くwebサービスを趣味で作っているが、50words程度の文章であってもtextareaに書き込むとページが非常に重くなり、一文字打つのにすら大幅な遅延が発生してしまう。
<img width="863" alt="スクリーンショット 2018-02-22 14.16.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/171028/18e9548b-cf3d-379c-006d-51629f8b0639.png">

（※写真の文章はアメリカ・トランプ大統領の一般教書演説の一部です）
これは困った、と思い色々調べた。
# 結果
この赤線が原因だった。
<img width="197" alt="スクリーンショット 2018-02-22 14.16.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/171028/7f1ccf26-333a-408d-6961-18429f0425f8.png">
この赤線はHTMLの`spellcheck`属性によるもの。テキストを編集可能な要素について、スペルミスがあったら教えてくれるらしい。現在は日本語には未対応らしいが、英文はちゃんとチェックしてくれる。(の割に、"than"とか"year"とか絶対スペルミスなさそうな単語にもついてるのはなぜだろう・・・)
文章を入力するたびにいちいちスペルチェックをするので、こんなに重くなっていたようだ。
ちなみに、下のリンクにあるように、現在ほとんどのブラウザがtextareaについてはデフォルトで`spellcheck="true"`を適用している。なので、なんとなく作ったtextareaに英文を打つと自動的にスペルチェックがなされる。なんてお節介な・・・
<img width="886" alt="スクリーンショット 2018-02-22 14.36.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/171028/a7ef3637-26c8-2e1e-f813-f376a97f42b4.png">



[spellcheck](https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/spellcheck)

と、いうわけで、こうだったHTMLタグを

```html
<textarea></textarea>
```
こう直すと

```html
<textarea spellcheck="false"></textarea>
```
<img width="869" alt="スクリーンショット 2018-02-22 14.36.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/171028/8f8b8c13-bb4b-5e8d-8a88-3a2548f20b56.png">
見た目もスッキリしたし、めちゃくちゃ軽くなった。皆さんもお気をつけください。

# 参考
https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/spellcheck
https://stackoverflow.com/questions/16736198/typing-in-textarea-super-slow-when-lots-of-text-inside
同じ四半期に属する月を求めるSQL(Oracleのみ)

四半期の開始日は

```
TRUNC(日付, 'Q')
```
で求められる。

使用例.

```
SELECT
    TO_CHAR(TRUNC(TO_DATE(20180228/*対象日*/,'YYYYMMDD'),'Q'), 'MM') || '月' AS M1,
TO_CHAR(ADD_MONTHS(TRUNC(TO_DATE(20180228/*対象日*/,'YYYYMMDD'),'Q'), 1), 'MM') || '月' AS M2,
TO_CHAR(ADD_MONTHS(TRUNC(TO_DATE(20180228/*対象日*/,'YYYYMMDD'),'Q'), 2), 'MM') || '月' AS M3
FROM
  DUAL
```
Kinesis Firehose、S3、Glue、Athenaでビッグデータ分析基盤は作れるか

#AWSのサービスを活用したビッグデータ分析基盤

今日、様々なサービスで大量のデータが発生し、それを分析するニーズが出てきています。
その中で、ビッグデータ分析基盤としてAWSの各サービスを組み合わせる例が増えてきています。
ここでは下記の流れでどうやって分析基盤を構成するかを考えてみます。

IoTのデータや、サービスのログなどをKinesis FirehoseでS3に保存（前段としてAWS IoTがあったり、サービス自体が出しているログがあったり、など）
↓
AWS Glueでカタログ（Athenaで分析するためのテーブルのようなもの）作成
↓
Athenaでクエリを投入、分析
（さらに、QuickSightで可視化など）
![ビッグデータ分析構成.png](https://qiita-image-store.s3.amazonaws.com/0/53386/ba2ceecf-ddd5-4ed2-a059-2fa67e2c899b.png)


サービスの追加やアップデートなどで今後もっと組み合わせやすくなる可能性はあります。

#それぞれの設定の仕方

Kinesis Firehoseの設定
クラスメソッドのブログに詳細な設定方法を記載していただいています。
https://dev.classmethod.jp/cloud/kinesis-firehose-tokyo/
[こちらのスライド](https://www.slideshare.net/dcubeio/kinesis-firehose-80037243)も非常に詳しいです。
また、[サンプルデータ](https://dev.classmethod.jp/cloud/test-drive-amazon-kinesis-firehose-using-built-in-sample-data/)の投入にも対応しているため、
とりあえずFirehoseの設定を行えば、以後のテストも行えます。
実際には動かしているサービスだったり、AWS IoTだったり、様々なソースを選択することになります。
今回はS3に保存するケースで考えます。

S3に保存したデータに対して、AWS Glueでカタログ作成をします。
（※現状ここで少々問題があるのですが、ここではあえて無視して後述します。）
コンソールでAWS Glueを選択
↓
Crawlers→Add Crawlerを選択してクローラーを作成
↓
画面に従ってクローラーを設定。データベースは任意で作成。S3バケットはKinesis Firehoseで作られたバケットを指定。
<img width="869" alt="スクリーンショット 2018-02-22 14.27.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/53386/2aa8c386-01d3-1584-0c8d-3055156639ac.png">
※細かな設定は色々ありますが、とりあえず動かして、あとで調整する、でよいかと。
クローラーの定義の仕方はクラスメソッドさんのブログにスクリーンショット入りで細かく書いてくれています。
https://dev.classmethod.jp/cloud/aws/aws-glue-tutorial/
↓
クローラーを実行

ここまでの流れでAthenaのクエリを投げるためのテーブルができる…と言いたいところなのですが、現状では下記の問題があり、上手く実現できません。

FirehoseではS3に/YYYY/MM/DD/hh/〜のようなフォルダ構成でファイル保存するのですが、GlueではAthenaの自動パーティション認識が可能な「/year=YYYY/month=MM/day=DD/〜」のようにkey=value形式でないと、うまくパーティションを作ってくれません。

の、はずなのですが、自分が実際にやってみると、同じようにデータを入れているのに正しくパーティションを切ってくれるケースと、全くうまくいかないケースが分かれてしまい、ここはもう少し検証が必要なポイントです。
年、月、日という典型的なパーティションの切り方についてはGlue、Athenaのほうで対応してくれると非常に助かるポイントですね…。

パーティションが設定されたら、最後にAthenaで任意のクエリを投入します。
AthenaではパーティションをWhere句に指定せずにクエリを実行したりすると、大量のデータを参照してしまいものすごいデータ量になったりするので、パーティションの設定は忘れないようにしましょう。
ちなみに、パーティションが自動で設定されない場合は手動でクエリを投げて、一つ一つ設定する必要があります…。
参考
https://dev.classmethod.jp/cloud/aws/athena-partition-reinvent/

AthenaであればS3のデータに対してクエリ（参照系のみ）を直接投げられるので、S3に適切にデータが入っていれば特別なことをせずそれだけで分析が行なえます。
素晴らしいですね。

#課題や今後の希望など

途中で書いたとおり、Firehoseで年月日のフォルダ構成で保存されるものに対して、Glueのクローラーを実行した時に年月日でパーティションを設定する（もしくは、Athenaが自動でパーティション認識する）、というのが正常に行えるようになると、上記の構成が楽に行えるようになります。
現状だと手作業でパーティションを設定しなければならず、非常に煩雑です。
Lambdaを使ってフォルダ配置をいじって認識してくれる形式に直すというのもアリかもしれませんが…。

#まとめ
まだ課題は残っているものの、AWSのサービスを利用すれば大規模分析基盤がかなり楽に作れそう、という状態です。
通常であればこれだけの基盤を作るのは消して簡単ではないのですが、クラウドサービスとしてAWSのリソースを使うことによって、個人レベルでも簡単にそれだけの基盤を利用することが出来るようになります。
さらに使いやすくなるように今後のアップデートにも是非期待したいですね。
Java -> Kotlin 変換して NullPointerException が起きがちなメソッド

Android Studio で Java を Kotlin に自動変換したら引数に null が渡されて NPE がよく起こるので適宜検索できるようにメモしておく。


- ```fun onPostExecute```

```kotlin
    override fun onPostExecute(result: String) {
    // doInBackground で null を返したら result が null で落ちるので下記のように変更する
    override fun onPostExecute(result: String?) {
```

- ```fun onActivityResult```

```kotlin
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
```

- ```fun onQueryInventoryFinished```

```kotlin
    // IabHelper.QueryInventoryFinishedListener interface の実装クラス
    override fun onQueryInventoryFinished(result: IabResult, inventory: Inventory?) {
```

以下、適宜追記する予定。
[memo] MySQL5.7 install on EC2

## **MySQL install**
### **yumリポジトリ設定**
```
$ sudo yum install http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm
$ sudo yum-config-manager --disable mysql56-community
$ sudo yum-config-manager --enable mysql57-community-dmr
```

yum-config-managerコマンドが入っていない場合は下記でインストール。

```
$ sudo yum install yum-utils
```

### **MySQL install**
```
$ sudo yum install mysql mysql-devel mysql-server mysql-utilities
```
```
$ mysql --version
mysql  Ver 14.14 Distrib 5.7.21, for Linux (x86_64) using  EditLine wrapper
```

### **MySQL起動**
```
$ sudo service mysqld start
```

## **初期設定**
### **パスワード設定**

ログに出力されている初期パスワードを用いる。

```
$ cat /var/log/mysqld.log | grep 'password is generated'
2018-02-22T03:46:29.817769Z 1 [Note] A temporary password is generated for root@localhost: hogehoge
```
※ hogehoge 部分が初期パスワード

初期パスワードでログインする。

```
$ mysql -u root -phogehoge
```

新たなパスワードを設定。
※MySQL5.7から「**大小英文字＋数字＋記号の4種を含んだ8文字以上**」がパスワードの条件になった。

```
> SET PASSWORD = 'Password-0123' ;
```

一度ログアウトし、新たなパスワードでログイン確認。

```
> exit
$ mysql -u root -pPassword-0123
```

### **tmpディレクトリ作成**
```
$ sudo mkdir -p /var/lib/mysqltmp
$ sudo chown mysql:mysql /var/lib/mysqltmp
$ sudo chmod 755 /var/lib/mysqltmp
```

MySQL 再起動

```
$ sudo service mysqld restart
```

### **補足**

下記のようなエラーを出力して起動に失敗する事がある。

```bash:/var/log/mysqld.log
[ERROR] InnoDB: The Auto-extending innodb_system data file './ibdata1' is of a different size 768 pages (rounded down to MB) than specified in the .cnf file: initial 65536 pages, max 0 (relevant if non-zero) pages!
```

「DBファイルが不適切」との事なので、初回起動時に作られたファイルを削除してから再起動させる。

```
$ sudo rm -f /var/lib/mysql/ibdata1
$ sudo rm -f /var/lib/mysql/ib_logfile0
$ sudo rm -f /var/lib/mysql/ib_logfile1
$ sudo service mysqld restart
```

以上
プロファイラーツールの使い方 

.htaccessに以下を追記

```
#xDebug profiler
php_flag xdebug.profiler_append Off
php_flag xdebug.profiler_enable On
php_flag xdebug.profiler_enable_trigger On
php_value xdebug.profiler_output_dir /home/sv01/www/html/logs
php_value xdebug.profiler_output_name xdebug%Rlog 
```

XDEBUG_PROFILEをGETパラメーターにしてサイトにアクセスします。
※mod_rewriteでリライトされると取れない場合があると思うので気をつけて下さい

例）
http://example.com/?XDEBUG_PROFILE

この設定を行うと、リクエストごとのプロファイルファイルが、xdebug_profiler_output_dirに出力されます。
例）xdebug_products_detail25795_htmllog

このログを見てもいいですがみにくいのでGUIを利用します。
https://github.com/ceefour/wincachegrind/releases/tag/1.1
手が止まったらオートセーブする。

### lodashの_.throttleを使えば簡単に実装できる。
```js
save=_.throttle(_save,10*1000)
```
### サーバーの通信制限をフロント側で回避できる。
例えば、gistへの認証付きcorsなら10秒に１回程度のリクエストは規制にかからない。

```js
_save=(str)=>{
  //to gist, with api
}
```

### oninput系の間引きにも使える。
```js
t.oninput =_.debounce(on,50); //fps20 =1000/20
```

### 全部
```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
```
```js
let fn={}
fn.ce=(d=>document.createElement(d))
fn.now =function(time){
 /*add local time jp*/	 
 if(time=='jp'||time=='jpn') return new Date( Date.now()+ 1000*60*60*9  ).toISOString().split('.')[0] +'Z'
 if(time) return new Date(time).toISOString().split('.')[0] +'Z';
 else return new Date( Date.now() ).toISOString().split('.')[0] +'Z';
}
;
let t=fn.ce('textarea')
,o=fn.ce('pre')
,l=fn.ce('label')
,_save=(str)=>{
  let n=fn.now('jp');
  console.log(n,str)
  l.textContent =n;
}
,save=_.throttle(_save,10*1000)
,on=function(ev){
  o.innerHTML = t.value;
  save(t.value);
}
;[t,l,o].forEach(d=>document.body.appendChild(d))
;
t.oninput =_.debounce(on,70);
```
Pythonでslack apiを使ってみた

メモ程度にまとめます.
以下python3を用いた.


#目次
1. <a href="#参考にしたサイト">参考にしたサイト</a>
1. <a href="#環境">環境</a>
1. <a href="#初期設定">初期設定</a>
2. <a href="#チャンネルリスト取得">チャンネルリスト取得</a>
3. <a href="#メッセージを送る">メッセージを送る</a>
4. <a href="#最後に">最後に</a>

#参考にしたサイト

- https://github.com/slackapi/python-slackclient
- https://api.slack.com/
- https://realpython.com/blog/python/getting-started-with-the-slack-api-using-python-and-flask/

#環境
- pyenv 3.6.3

#初期設定

**python-slackclient**
https://github.com/slackapi/python-slackclient

```terminal
$ pip install slackclient
```

slack APIを使用するにはslackの**トーケン**が必要になってくる.

```terminal
$ export SLACK_TOKEN='your token'
```

# チャンネルリスト取得

slack APIを使ってメッセージやファイルを送るのにはIDが必要になってくるのでとりあえず初めにチャンネルIDを取得するためにチャンネルリストを返すプログラムを作った.

```python
import os

from slackclient import SlackClient

slack_token = os.getenv("SLACK_TOKEN")
client = SlackClient(slack_token)
```
これでslack APIが使用できる環境ができた.
そこでチャンネルリストを返す関数を作って見た.

```python
def channel_list(client):
    channels = client.api_call("channels.list")
    if channels['ok']:
        return channels['channels']
    else:
        return None
```
これでうまくいけばJSON形式で以下のようになる

```terminal
[{'id':'channel id', 'name':'channel name', 'is_group':True, ...,}]
```

ただし上記はpublicチャンネルだけであるので、privateチャンネルのidを得るためには`channels.list`ではなく`groups.list`を使用するべき.

# メッセージを送る

idを取得できたので早速メッセージを送る関数を作ってみた

```python

def send_message(client, channel_id, message):
    client.api_call(
        "chat.postMessage",
        channel=channel_id,
        text=message
```
他にも色々条件をつけることができるらしいが、とりあえず一番簡単な形式がこれだと思う.
でも文章長すぎたりするとあれかなって思ったのでsnippetも試してみた.

```python

def send_file(client, channel_id, content, title):
    client.api_call(
        "files.upload",
        channels=channel_id,
        content=content,
        title=title
```
デフォルトだとtextファイルになるらしいけど、`filetype`でいじれるらしい.
あと、`content`の代わりに`file`を設定すればファイルをアップロードできるらしい.


# 最後に
一通りやってみたところ結構簡単で色々できるんだなって感じです.
dnsの`TXT`レコードを見る


GCP/GAEのcustom domainのverificationで利用

## nslookup
```sh
$ nslookup -q=TXT example.com 01.dnsv.jp
example.com text = "google-site-verification=AaH99r_AlJAng42S2d5CkINRWTp0ABfx9cPIJ0f6JIA"
```
## dig
```sh
$ dig TXT example.com | grep TXT
example.com.                3198    IN      TXT     "google-site-verification=AaH99r_AlJAng42S2d5CkINRWTp0ABfx9cPIJ0f6JIA"
```
WindowsForm/WPFでBlinkレンダリングエンジンを使用する

# はじめに

ここ最近いろいろQiitaのとレンジ記事を読んでいると，ReactやNode.jsといったサーバーサイドと，Vue.js等フロントエンド設計もJavascriptを使う機会が増えてきているように感じますね．

ソフトウェア設計でも，UI/UXの設計でWeb系，Python＋Django，Bottle，FlaskやRuby on Rails等の技術者が多くなり，また案件もそのようなものが増えているように思います．一方，生粋なVisual StudioでC# Applicationを使用する機会は減少しているようにも感じるコトがあります．．

しかし，B to Bの現場においてこういうことはないでしょうか．

**業務系アプリなのでブラウザはちょっと・・・**

運営事業者が提供するサービスは，コンシューマーが使用するのが前提．囲い込むためには専用アプリを必要とせずにブラウザでいいのかもしれないですね．しかし，客先に収めるシステムの場合はURLが入力できてもダメ．進む，戻る，ブックマークがUIに表示されるのもダメ．これはよくあることです．

つまり・・・ネイティブアプリでなければならない．

## Windows Form/ WPFにブラウザコントロール

感のいい人はとっくに気づいているし使っていると思います．C#にはデフォルトでブラウザコントロールが搭載されている．では，コレを使用してWEBアプリケーションを組んでしまえばいいのである．単純な答えですね．

しかしこのコントロール，じつは問題がありまして，実行エンジンはIE11です．Windows標準搭載のコンポーネントを使用します．このコンポーネントにはいくつかの問題が．

#### Chrome

![chrome](https://user-images.githubusercontent.com/23314412/36520350-e6ff78da-17d3-11e8-8477-8d6c9e2d7412.png)

#### IE11

![ie11](https://user-images.githubusercontent.com/23314412/36520337-d1601034-17d3-11e8-8d22-ed4b55ae95e2.png)

見比べてもらえればわかると思いますが，一部のChromeのコンポーネントはIE11上では動作しません．（当然）  
GoogleのChromeレンダリングエンジンはBlinkを使っており，これはOpera, Vivaldi, Sleipnirでも採用されているため最近では”実績有り”といったところでしょうか．

オマケ

#### IE11 （互換モード)

![ie11to6](https://user-images.githubusercontent.com/23314412/36520395-1736a384-17d4-11e8-8f98-e51fd63456cd.png)


こっちは右上のボタンとかも使えない．これがIE5準拠時代のものですね．で，話を戻しますと，IE11をなぜ使わなければならないというところ．

## 俺達はChromeを使いたいんだ！！！

そう，俺達はChromeで開発をしたいんです．社内でデバッグ時も当然Chrome．F12を叩きデバッグコンソールは出しっぱなしでコーディングを進めたいと思わないですか？

開発をChromeで行うと同時に客先納品もChromeであれば最高．しかしやっぱり，それは叶わぬ夢ですね・・・

OSはわりとWindowsの場合が多いですね．というか，システム納品先の9割はWindowsです．
仮にブラウザが使用できたとしても，VPNを経由するのでChromeのインストールも難しい．しかしIE11であれば，問題はないのですよ．（標準搭載）

**しかし，IE11の寿命は・・・？**

このように，ブラウザによって大きく使えるものと使えないものが別れてしまっている．納品先によってはこれがネックとなる場合もある上に，ブラウザは**自分たちで設定を変えるなど”余計な操作”ができてしまう．**

だいたいこの余計な操作が**”何もしてないのに動かない”**と言われる要因である．

# 対策

正直，WebでUI/UXを設計するコストなどを考えるとWindowsのネイティブなアプリを作るのは非常に無駄が多いと思うことがあります．ビルドエラーやコンポーネントの使用の制約，DOM操作みたいなのも作り込みは結構たいへん・・・

ブラウザコントロールを搭載すればいいのですが，これにも問題が．以下の画像見てもらえるとわかりますが，デザインが何処かでみたのと同じですね・・・

![orig2](https://user-images.githubusercontent.com/23314412/36520834-d2c599a0-17d6-11e8-8f47-59ecf36b2c75.png)

## 俺達はChromeを使いたいんだ！！！（再）

というわけで，Chromeで使えるコンポーネントはないかと探してみたところ・・・

**やっぱり有りました．**

[CEFSharp](http://cefsharp.github.io/)

実装すると，こんな感じ．

![orig](https://user-images.githubusercontent.com/23314412/36521142-87e751ec-17d8-11e8-8afe-076dbaf91afd.png)

導入は，また別記事にて．
electron-vueを導入する

# この記事について
electronでアプリ開発をしようとした際にフレームワークとして`vue`を選択しました。
導入からテンプレートの起動までの手順書となります。
手順を覚えるために記載しました。

# 実行環境
windows 10

# 初期設定
[electron-vue導入](https://simulatedgreg.gitbooks.io/electron-vue/content/ja/)
公式ページを参照に進めていきます。

事前にnode.jsとyarnのインストールが必要です。

```
# vue-cliをインストール
npm install -g vue-cli
```

```
# テンプレートを生成
vue init simulatedgreg/electron-vue プロジェクト名
```

全部Enterで問題なし。

```
? Application Name temp-project
? Project description An electron-vue project
? Select which Vue plugins to install axios, vue-electron, vue-router, vuex
? Use linting with ESLint? Yes
? Which eslint config would you like to use? Standard
? Setup unit testing with Karma + Mocha? Yes
? Setup end-to-end testing with Spectron + Mocha? Yes
? What build tool would you like to use? builder
? author ysks-y <ysks-y@example.Welcome>

  vue-cli · Generated "temp-project".
---

All set. Welcome to your new electron-vue project!

Make sure to check out the documentation for this boilerplate at
https://simulatedgreg.gitbooks.io/electron-vue/content/.

Next Steps:

 $ cd temp-project
 $ yarn (or `npm install`)
 $ yarn run dev (or `npm run dev`)
 ```

 プロジェクトのテンプレートを作成後に依存関係のライブラリを入れます。
 `yarn` または `npm` を使って導入できます。
 ※windows環境で`npm install`をした際に適切なビルドツールが入っていなかったり古いバージョンである可能性があり、`npm-windows-upgrade`を使用したりと面倒なので`yarn`を使用した方が良いです。

 ```
 cd プロジェクト名
 yarn # or npm install
 ```
 nodejsのバージョンで怒られた場合は`nodist`等でバージョン管理すると良いと思います。

# 実行
正常に終了したら以下のコマンドで実行です。

```
yarn run dev
# (or `npm run dev`)
```

![yarn-run-dev.png](https://qiita-image-store.s3.amazonaws.com/0/198773/dfc71e76-64a6-8df5-8dab-918b06a1cd67.png)
google chromeと同様のchromium driverを使用しているので、developer toolsが使用できます。

これでelectron-vueの導入は完了です。
elasticsearch-modelを使ってelasticsearchからデータ取得するときの注意

# 概要
elasticsearchの_idカラムは指定しないと適当に一意のidが振られるが、それだと更新、削除の時に不便なので、なるべく自分で指定したい。で、今回テーブルのidの値でない値を_idにしたのだが、elasticsearch-modelでうまく動かなかったので、どうやったのかをメモとして残す

# やった事
複数のDBに同じ名前のテーブルがあって、それらを一つのElasticsearchに突っ込む時に「_id」に何をセットするか注意が必要。、対象のテーブルのidカラムの値を入れようと思っても、値が重複してしまうのでidカラムの値ではなく違う値をセットする。

で、例えば以下のようにする


```
   result = es.client.bulk(
           index: 'hogehoge_index',
           type: es.document_type,
           body: entries.map { |entry| { index: { _id: "dbNum#{どのdbのデータかわかるようにするid}id#{entry.id}", data: entry.as_indexed_json } } },
          refresh: true,
           )
```

こうやって_idの値を違うテーブルのidと違うようにしたが、今度は検索がうまく動かない。どうしてかなと思ってデバッグする。

```
$ bundle open elasticsearch-model
 ```

で[こちら](https://github.com/elastic/elasticsearch-rails/blob/master/elasticsearch-model/lib/elasticsearch/model/adapters/active_record.rb#L22)のコード見て「あ！！そうか！」という発見。

```
  def records
    sql_records = klass.where(klass.primary_key => ids)
    # 以下省略
  end
```

もしかしてここのidsは・・・と思って<code>ids</code>を見に行ったら、[こちら](https://github.com/elastic/elasticsearch-rails/blob/15761247f3e99654bda946a178e50b5365414b59/elasticsearch-model/lib/elasticsearch/model/response/records.rb)に書いてあるように

```
module Elasticsearch 
  module Model
    module Response
      class Records
        def ids
          response.response['hits']['hits'].map { |hit| hit['_id'] }
        end
      end
    end
  end
end
```

やっぱり_idの値を見ている。という事でこちらの処理を上書きしました。


```
module Elasticsearch
  module Model
    module Response
      class Records
        def ids
          response.response['hits']['hits'].
            map { |hit| hit['_source'] }.
            map { |source| source['id'] }
        end
      end
    end
  end
end
```

これで「やったー」と思ったら、今度はsortがおかしい。あれと思い、さっき見てたrecordsメソッドをもう一度見ると、[ここ](https://github.com/elastic/elasticsearch-rails/blob/master/elasticsearch-model/lib/elasticsearch/model/adapters/active_record.rb#L38)に書いてあるように、ここでも_idを見ている

```
@records.sort_by { |record| hits.index { |hit| hit['_id'].to_s == record.id.to_s } }
```

なので、こっちも

```
@records.sort_by { |record| hits.index { |hit| hit['_source']['id'].to_s == record.id.to_s } }

```

となるようにして、改善した方を使うように変更。
これで無事検索できて、ソートも問題なくできるようになった。
めでたし、めでたし。
AWSを活用した機械学習とIoT

#AWSで実現できる機械学習

AWSは単なるクラウドサーバーという域を超えて、様々な活用が可能です。特に今後注力されていく分野が、人工知能の一分野である機械学習および、Iotの領域です。
Amazon社は創業当初から20年以上機械学習を活用しており、この分野でのパイオニア企業の一つです。例えば「この商品を買った人はこんな商品も買っています」という推薦が出るアイテムベースの協調フィルタリングアルゴリズムなどが有名です。（下図参照）

![スクリーンショット 2018-02-22 13.44.16.png](https://qiita-image-store.s3.amazonaws.com/0/198259/ae3dac9d-e25c-1393-277e-1b68a33500d9.png)

今話題のAmazonのスマートスピーカーechoも、機械学習技術を活用したものです。
さらに、AWSの年次イベント「re:Invent」では、 2017年に、音声アシスタント「Alexa」オフィスで利用するためのサービス「Alexa for Business」、機械学習のモデル構築などを容易にする
「Amazon SageMaker」などが発表され、機械学習を利用する環境がますます向上しています。
これによりコールセンターの自動化など、今後ますますAWSを利用した様々な業務の効率化が進むことが予想されます。


#モノのインターネットとAmazon IoT Core
そしてもう一つのIotですが、これはInternet of Things（モノのインターネット）と言う言葉の略で、従来のパソコンやスマートフォンだけではなく、家電製品や自動車、産業用ロボットなどありとあらゆるものがインターネットに接続されるという状況を意味します。
これに対し、Amazonは、AWS IoT Core という、インターネットに接続されたデバイスから、クラウドアプリケーションやその他のデバイスに簡単かつ安全に通信するためのマネージドクラウドプラットフォームを用意しています。
Iot時代には、コンピュータばかりではなく、GPSやカメラ、温度センサーなど数多くのセンサーやデバイスがインターネットに接続され、それらの情報を処理・解析する必要が出てきます。その数は膨大であり、しかも頻繁に大量の情報が行き来します。
そのため、AWS IoT Coreは、数十億個のデバイスと数兆件のメッセージをサポートしており、デバイスに確実かつ安全に処理してルーティングできる仕組みが用意されています。

#Iot とAIの融合

このIotと機械学習が融合することによって、世の中は劇的に変化するといわれています。これが、第4次産業革命やインダストリー4.0と呼ばれるものです。

第1次産業革命は19世紀のイギリスで起こった機械化であり、機械による製造が可能になりました。
第2次産業革命は20世紀のアメリカで起こり、電力の活用により大量の機械で大量の製品が可能になりました。
第3次産業革命は20世紀半ばから後半に起こり、コンピュータの導入によって、指示を与えれば機械が自動的に生産が出来るようになりました。

それに対し第4次産業革命の主役はIotおよび機械学習であり、これにより機械が自ら考えて動くようになっていく自律化が起こっていき、現在はその過渡期にあると言われています。つまり、コンピュータが「自分で考えて行動する」時代になるわけです。

AWSは第4時産業革命を牽引するための様々なインフラを提供していると言う事が出来ます。

#　まとめ

このようにAWSは時代の変化に応じ単なるサーバーではなく様々なサービスをユーザーに提供しています。今後の課題は、仮想通貨などで用いられているブロックチェーン技術であり、この分野はマイクロソフトのAzureやGoogleなどがAWSよりも一歩進んでいるのが現状です。

しかし、そう遠くない将来、Amazonはこの分野でもあっと驚くようなサービスを提供してくる可能性があり、今後も目が離せません。
NATインスタンスとNATゲートウェイの違い

NATインスタンスとNATゲートウェイの違いで混乱したのでまとめます。

まずそれぞれについてとても軽く説明

#NATインスタンス

[NATインスタンス](https://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/VPC_NAT_Instance.html)

プライベートサブネットはインターネットからのアクセスを受け付けないため
パッチのダウンロードやS3やDynamoDBのようなリージョンサービスへのアクセスができません。
それを可能にするのがNATインスタンスで、実体はそのEC2インスタンス。
AWSからNATインスタンス用のAMIも提供されています。
プライベートサブネット内からのトラフィックを受け付け、
プライベートIPをNATインスタンスのグローバルIPに変換して外との通信を可能にします。

ポイントとして、
・NATインスタンスの送信元/送信先チェック(Change Source/Dest.Check)を無効化する必要がある
・NATインスタンスにグローバルIPの割り当てが必要(EIPでもPublic IPでもOK)

グローバルIPは構成とか運用とか用途とか考えると別にEIPを割り振らなくていいパターンもあるのでしょうか。
AWSを実業務で使ったことないので想像の域を出ないです。誰かこのド素人に教えてください。

#NATゲートウェイ

[NATゲートウェイ](https://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/vpc-nat-gateway.html)

2015年12月より登場したサービス。
目的はNATインスタンスと同じですが、AWSのマネージドサービスなので運用管理が必要ありません。
その点NATインスタンスはEC2インスタンスなので冗長性を持たせないと単一障害点になってしまうんだそう。
作成もNATインスタンスを作るよりも簡単です。

ポイントとして、
・EIPの割り当てが必須(割り当てできるEIPがなく、EIPの数が上限に達していると作れません)
・一般的には費用がNATインスタンスより高い(使用状況にもよる？)

#NATインスタンスとNATゲートウェイの違い

以下を参考にさせて頂きました。
[・NAT インスタンスと NAT ゲートウェイの比較](https://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/vpc-nat-comparison.html)
[・AWS NAT構成の作り方(NATインスタンス編)](https://qiita.com/TK1989/items/ece84500ee87d2d96c4b)
[・AWS NAT構成の作り方(NATゲートウェイ編)](https://qiita.com/TK1989/items/5d9bd5d49708c02dff3f)
[・AWS NATゲートウェイのメリット・デメリットをまとめてみる](https://blog.situs.co.jp/tech/%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89/aws-nat%E3%82%B2%E3%83%BC%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A4%E3%81%AE%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88%E3%83%BB%E3%83%87%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88%E3%82%92%E3%81%BE%E3%81%A8%E3%82%81/)
[・NATインスタンスとNAT ゲートウェイの料金比較](http://blog.serverworks.co.jp/tech/2016/03/08/nat-service-price-compare/)

一部上でも書きましたが、個人的に大事かなと思う異なるポイントは
【グローバルIP】
　NATインスタンス：パブリックIPまたはEIP
　NATゲートウェイ：EIPのみ
【冗長化や障害対策などの運用管理】
　NATインスタンス：必要
　NATゲートウェイ：マネージドサービスなので不要
【帯域幅】
　NATインスタンス：選択したインスタンスタイプに依存
　NATゲートウェイ：10Gbps
【セキュリティグループ】
　NATインスタンス：使える(実体がEC2なので)
　NATゲートウェイ：使えない(ネットワークACLで制御する)
【料金】
　NATインスタンス：EC2の料金体系に従う
　NATゲートウェイ：NATゲートウェイの料金体系に従う
　
NATゲートウェイのほうが作るのが簡単そうだなという印象なんですが
制約事項もあるしどっちがいいというのはなさそうですね。
メリット・デメリットを踏まえた上で正しく選択する必要がありそうです。
あと、NATゲートウェイはインスタンスではないので停止できません。
ある限り料金が発生するのでいらなくなったら削除しないといけないですね。
Oracle スキーマ及びロールに付与されたシステム権限取得

```SQL:
-- #!/bin/sh
-- #@(#) \$Id get_ddl_grant_system_privs.sh, v1.0
-- #
-- # su - oracle
-- # export ORACLE_SID=xxxx
-- # export ORACLE_HOME=/opt/app/oracle/product/12.2.0
-- #
-- # ../sql/get_ddl_grant_system_privs.sh
-- #
-- #export NLS_LANG=JAPANESE_JAPAN.AL32UTF8
-- ${ORACLE_HOME}/bin/sqlplus / as sysdba << EOF
--
-- スキーマ及びロールに付与されたシステム権限
--
SET ECHO OFF
SET FEEDBACK OFF
SET LINESIZE 100
SET PAGESIZE 50000
SET TAB OFF
SET TRIMOUT OFF
SET TRIMSPOOL ON
-- SPOOL pass includes CONNECT_IDENTIFIER, USER_NAME and SYSDATE
COLUMN USER_NAME    NEW_VALUE USER_NAME
COLUMN SYSTEM_DATE  NEW_VALUE SYSTEM_DATE
SELECT USER || '_' AS USER_NAME
     , TO_CHAR(SYSDATE, 'YYYYMMDD_HH24MISS') AS SYSTEM_DATE
FROM DUAL ;
SPOOL get_ddl_grant_system_privs_&&_CONNECT_IDENTIFIER._&&USER_NAME&&SYSTEM_DATE..log
-- Windows ↑,  UNIX/Linux では ↓ を有効に
-- SPOOL get_ddl_grant_system_privs_\&&_CONNECT_IDENTIFIER._\&&USER_NAME\&&SYSTEM_DATE..log
COLUMN GRANTS  FORMAT A1000
SELECT 'GRANT ' || RPAD(SP.PRIVILEGE, 40) || ' TO ' || SP.GRANTEE
    || CASE
           WHEN SP.ADMIN_OPTION = 'YES' THEN  -- ADMIN OPTION の有無
               ' WITH ADMIN OPTION'
       END || ' ;' AS GRANTS
FROM(
    SELECT COLUMN_VALUE AS GRANTEE FROM TABLE(PKG_USERS_SCHEMA.GET_USERS_SCHEMA) -- ユーザーが作成したスキーマのみ
    ) A
INNER JOIN DBA_SYS_PRIVS SP
ON    SP.GRANTEE = A.GRANTEE
ORDER BY SP.GRANTEE
       , SP.PRIVILEGE ;
--
-- ROLE_SYS_PRIVS
-- PL/SQLではロール経由の権限は無視されるので注意のこと。
--
SELECT 'GRANT ' || RPAD(SP.PRIVILEGE, 40) || ' TO ' || SP.ROLE
    || CASE
           WHEN SP.ADMIN_OPTION = 'YES' THEN  -- ADMIN OPTION の有無
               ' WITH ADMIN OPTION'
       END || ' ;' AS GRANTS
FROM ROLE_SYS_PRIVS SP
ORDER BY SP.ROLE
       , SP.PRIVILEGE ;
SPOOL OFF
COLUMN GRANTS  CLEAR
SET ECHO ON
SET FEEDBACK ON
SET LINESIZE 80
SET TRIMOUT ON
-- exit
-- EOF
-- #export NLS_LANG=en_US
-- # ---------------------- End of get_ddl_grant_system_privs.sh ------------------------------
```
参照
[Oracle 純粋にユーザー側のスキーマのみを取得](https://qiita.com/Papageno/items/2d4ccae4b99d79d0b48b)
FreeMarkerの?sortビルドインがList<String>で使えないのはどうなの

## なんでこういう状況に遭遇したか
JBake のテンプレートをFTLで書いていたのです。JBake なんて使っている人いないですよね、そうですよね。
まあそれは良いとして、その中でサイト内の記事で使われている全てのタグ一覧なんていう情報がありまして、これがどうやらJBakeが処理対象となる記事データをクロールして見つけた順に並んでいるらしいのです。並び順がばらばらです。

このまま出したら見た目悪いなあ。どんな順番でもいいから規則性のある並べ方にしとくか。
とか思って、FTLのビルドインを調べたのがことのはじまり。 

## え、なんでこれエラーなのさ？

というわけで、FreeMarkerのサイトを見るわけです。そうするとあるじゃないですか[お目当てのビルドイン](https://freemarker.apache.org/docs/ref_builtins_sequence.html#ref_builtin_sort)が。

```text:TEMPLATE
<#assign ls = ["whale", "Barbara", "zeppelin", "aardvark", "beetroot"]?sort>
<#list ls as i>${i} </#list>
```
```text:OUTPUT
aardvark Barbara beetroot whale zeppelin
```
数値、文字列、日付、ブール値ならソートしてやるぜ、?reverseもあるぜよ（意訳）。

そうそう、こういうのでいいんです。FTLは知らないナニカがたくさん隠れているので油断なりません。誰かドキュメント翻訳してくれませんかね。英語だと読めなくはないけれど目が滑るので。

というわけでスピード解決だぜと思って、以下のような記述をしてBakeするわけです（JBakeではサイトコンテンツの変換・生成処理のことをBakeすると呼称します）。

```text:TEMPLATE
<#-- ソートして出力(?sort足しただけ) -->
<#list alltags?sort as tag>
  <span>${tag}</tag>
</#list>
```
そしたら思わぬ例外メッセージですよ奥さん。

```
Failed to render file. Cause:
freemarker.core.NonSequenceException:
For "?sort" left-hand operand:
Expected a sequence, but this has evaluated to a collection
(適当に略)
```

要するに「それSequenceじゃないから?sortとか使えないし？（意訳）」って言いやがるわけですね。なんだよそれ、ソートが実装されてるのにCollectionで使えないとか意味わからないよ！？

## まあこうすれば動きますが

```text
<#-- Sequencesに入れ直し -->
<#assign seq=[]/>
<#list alltags as tag>
  <#assign seq=seq+[tag]/>
</#list>
<#-- ソートして出力 -->
<#list seq?sort as tag>
  <span>${tag}</tag>
</#list>
```

リスト、配列要素なんて<#list>で回すくらいしかしていなかったので、まさかSequenceとCollectionにこんな差異があるなんて思ってませんでした。
っていうか?sort、実装おざなりだと思うの。