OmniAICreator/Qiita-1.07M huggingface dataset:
Webフォントが反映されないあるある

※ 2018/08/03 追記： TypeSquareのAPIのバージョンがv3になりましたので一部加筆しました。

TypeSquareなどのCloudサービスのWebフォントを使用している案件で、開発中にしばしば「Webフォントが当たらない」などと言われることがあります。

結構あとで言われて開発をとめて検証しないといけなくなるので、
どういうときにそうなるのか、よくあるハマりパターンをまとめてみます。
※実体験のみなので、網羅しているわけではありません。適宜あれば追記します。

個人的にこういうのはエンジニアだけではなく、できればデザイナーやディレクターにも事前に理解しておいてほしい内容ですのでなるべく平たく書くようにします。
分かりづらいところがあったらコメントください。

### Webフォントサービスに開発用のドメインが設定されていない

モリサワのTypeSquareなどはWebフォントを利用できるドメインをホワイトリストで指定する必要があります。
本番環境のドメインだけしか登録されていないと、開発環境など他のドメインでは表示することができません。
また本番でもサブドメインや `localhost:3000` のようなローカルでのURLも同様です。
ドメイン数で費用が変わったりするので、クライアントに了承の上で上記を追加する必要があります。

またモリサワに関しては、モリサワ製品（Morisawa Passport）を利用していればTypeSquareも利用できるので、開発用にタグを切り替える必要はありますが、そちらを設定しておくのもよいと思います。
（本番でタグを切り替えるのを忘れずに…）

### Webフォントサービスのアクセス制限の上限に達している

モリサワのTypeSquareなどは呼び出し回数に上限があります。（プランによります）
管理画面を確認しましょう。

### 要素を動的に追加したときにフォントが更新されていない

クラウドサービスのWebフォントのいくつかは、表示時にWebフォントを読み込む際、表示されている文字だけ動的に読み込むことで読み込みサイズを最適化しています。

そのため、あとからユーザーの操作等で要素が動的に追加されると、そこに含まれている文字にはWebフォントが反映されません。（厳密には読み込み済みの文字のみ反映される）

だいたいJavaScriptのAPIが用意されているので、要素を生成したあとでWebフォントをリロードしましょう。

#### TypeSquareの場合

参考: https://typesquare.com/ja/service/api_reference

URLを `/accessor/script` から `/accessor/apiscript/` にするとJSのAPIが利用できる。
※ 2018/08/03 追記 : v3からURIについての記載がなくなりました。

```html
<script type="text/javascript" src="//typesquare.com/accessor/apiscript/typesquare.js?0Jyi6TwLGMA%3D" charset="utf-8"></script>
```

要素を生成したらリロード処理を呼ぶ。

```js

function render() {
  // render的処理
  // Ts.reload(); // v2
  Ts.loadFont() // v3
}
```

### placeholder属性やCSSで生成した文字には当たらない

Webフォントの内部で対象になるのはHTMLのテキストノードのみのようです。
フォームコントロールの `placeholder` の文字列や、 CSSの `content: "hoge"` などで生成した文字列は対象になりません。

```html
<label>あなたのコメントをお願いします！</label><!-- ここはWebフォントになる -->
<textarea placeholder="ここにコメントを記入して下さい"><!-- この文字列はWebフォントにならない -->
</textarea>
```

```css
.require-form:before {
  content: "※必須"; /* この文字列はWebフォントにならない */
}
```

別途HTMLに記述しておくか、あらかじめそういうので記号以外の文字列をつかわないようにしたほうが良いでしょう。
`placeholder`は仕方ないので、ローカルにありそうな汎用的なフォント指定をしておくのがいいと思います。

### `text-transform` で整形した大文字小文字は対象にならない

```css
text-tramsfrom: uppercase; /* 全部大文字に変換する */
```


これもCSSで大文字小文字等を整形するとその内容はリロードの対象になりません。
CMS等で入力内容と表記を別々にコントロールしないといけない場合は、CSSではなくPHPなどHTML出力時に変換するようにしましょう。
英語サイトなどアルファベットが全部読み込まれている保障があればその限りではありませんが。


現場からは以上です。
Azure Web Apps のステージングスロットで IP アドレス制限

#はじめに
　本記事の内容は「[Azure App Service の静的なアクセス制限](https://docs.microsoft.com/ja-jp/azure/app-service/app-service-ip-restrictions)」機能が提供されたことで不要となりましたが、過去の記録のために残してあります。

　Azure App Service の静的なアクセス制限は、スロット単位で指定でき、スワップ後もスロットに固定で機能するため、本記事の IP アドレス制限が標準機能で提供された事を意味します。

#概要
　Azure App Service (WebApps) は、[ステージングパブリッシング機能](https://docs.microsoft.com/ja-jp/azure/app-service/web-sites-staged-publishing)を提供しています。これにより、WEB サイトの運用者は新しいバージョンの Web サイトを公開する前にステージングスロットでテストを実施し、検証完了後に本番スロットとステージングスロットをスワップする事が可能です。

#ステージング環境の IP アドレス制限
　多くの WEB サイトの運用者は検証用のステージングサイトの一般公開を制限したいという要望があります。このため Azure App Service においてもステージングスロットにのみ IP アドレス制限を実施し、本番スロットのみを公開したいという要望があります。またスワップ後もその状態（新しいステージングスロット = 以前の本番スロットの IP アドレス制限の実施）を維持出来なければなりません。

　これを実現するには web.config のルールでホストの環境を識別し、ステージング環境に配置されている場合のみ IP 制限を設定するルールを組み込む方法があります。

#サンプル例
[正規表現](https://qiita.com/whisky-shunsuke/items/d719c92c566c133f51b1)のルールを環境に合わせて修正します。作成した web.config は、本番スロット、ステージングスロットの両方の Azure App Service の site/wwwroot に配置する必要があります。

```config:web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Block unauthorized traffic to staging sites" stopProcessing="true">  
          <match url=".*" />  
            <conditions>  
              <!-- 正規表現でステージグスロットの名前と一致するパターンを指定 -->  
              <add input="{HTTP_HOST}" pattern="^hogeogewebsite\-staging\." />  
              <!-- 正規表現で許可する IP アドレスパターンをホワイトリストで記述 -->  
              <add input="{REMOTE_ADDR}" pattern="167\.220\.232\.156" negate="true" />  
            </conditions>  
          <action type="CustomResponse" statusCode="403" statusReason="Forbidden" statusDescription="Site is not accessible" />  
        </rule> 
      </rules>
    </rewrite>
  </system.webServer>
</configuration>
【Rails】Rakeタスクを追加する小さなメモ

- `[RAILS_ROOT]/lib/tasks` に `xxx.rake` ファイルを追加
- 名前空間kure
- desc [説明文] 
- task [タスク名] => [他タスク名] do [処理] end
    - [他タスク]実行後に[処理]が進むみたい

```ruby:[RAILS_ROOT]/lib/tasks/test.rake
namespace :kure do
  desc "kure1"        # description.
  task :kure1 do            # rake task name.
    p "kure1"                 # print "hello world!"
  end

  desc "kure2"
  task :kure2 do
    p "kure2"
  end

  desc "kure1 and kure2"
  task :kure1kure2 => ["kure:kure1", "kure:kure2"] do
    p "kure1andkure2"
  end
end

```

```sh:実行サンプル
 % rails kure:kure1kure2
"kure1"
"kure2"
"kure1andkure2"
```

## 参考
Rakeタスクを追加する | Railsの小技 | DoRuby https://doruby.jp/users/t_article/entries/Rake_

railsのrakeタスクについて - Qiita https://qiita.com/you88/items/ce893fa27b19fd6da031
NLTK環境を構築する


NLTK は Python の自然言語処理用ライブラリです。

```環境
macOS High Sierra 10.13
Python 3.6.5
```


NLTKとNUMPYをインストール
NUMPYとは、pythonでベクトルや行列計算を高速に行うのに特化したライブラリらしいです。オプションと記載がありますが推奨らしいですのでインストールしてます。

```
pip install -U nltk
pip install -U numpy
```

早速実行するとエラー。。

```
Resource punkt not found.
  Please use the NLTK Downloader to obtain the resource:
  
  >>> import nltk
  >>> nltk.download('punkt')
```
調べてみるとNLTKを使う前には機能をダウンロードする必要があるらしいです。と言うわけで早速ダウンロード。

```
python -c "import nltk; nltk.download()"
```

無事分かち書きができました。

```
>>> import nltk
>>> sentence = "You have eaten lunch, haven't you?"
>>> nltk.word_tokenize(sentence)
['You', 'have', 'eaten', 'lunch', ',', 'have', "n't", 'you', '?']
```


<b>参考サイト</b>
以下のサイトを参考にさせて頂きました。
http://www.nltk.org/install.html
http://www.nltk.org/book/ch01.html
https://qiita.com/okayu9/items/a123d1a2ef3a9a90fd66
https://code.i-harness.com/ja/q/4a447d
Jestを導入したのでメモ

気付いたらかいしゃが Qiita Organizations に入っていて、記事書いてねって言われたので Jest を導入した際のメモを上げてみます。

新しいものの導入ってまあ楽しいけど、でも手間だよね。たまにドキュメント読んでも躓く箇所があったりするし。(見落としの場合もあるけど)
今回は Webpack の alias を解決する所で一瞬躓いたので、その情報共有も兼ねたいと思います。

## Jest とは

[Jest · 🃏快適なJavaScriptのテスト https://facebook.github.io/jest/ja/](https://facebook.github.io/jest/ja/)

ざっくり: Facebook製JSテストツール。 Node.js 上で実行される。

## 動機

- JavaScript のテスト環境とかテスト方法がよく分かってなかったので。
- 小さく疎結合にIFをシンプルにデバッグしやすく作っても、どうしてもバグは混入すると思うので、もうちょっと何かをどうにかしたい気持ちがあった。 (ふわっとしてる)
- 予想しない挙動 (=バグのことだけど...) を早めに拾えるようにしたかった。
- Mocha, Chai, Karma, ... と色々あって、何がどれでどんな役割か調べるのがめんどうくさかった。
- とりあえず触ってみようと思い、Facebookさまの Jest を選択した。

## 導入方法

### 基本作業

```sh
npm i -D jest
```

```json:package.json
{
  "scripts": {
    "test": "jest"
  }
}
```

`--no-cache` と付けるとBabel?のキャッシュが参照されなくなる。
テストコードのコンパイル時間はかかるけど、意図しないテスト結果を避けられる？

### 追加作業

#### ESLint によるテストコードのエラーの表示をなんとかしたい場合

```sh
npm i -D eslint-plugin-jest
```

```json:.eslintrc
{
  "extends": ["plugin:jest/recommended"]
}
```

とか。

#### Babel, AsyncFunction を使う場合

```sh
npm i -D babel-jest regenerator-runtime
```

.babelrc は自動で参照してくれるらしい。
ただし、ENVには自動で `test` が適用されるそう。

#### `import` 構文を使う場合

Node.js は ES Modules (ESM) がまだちゃんと使えないと思うので、CommonJS形式に変換する方向で作業させると無難。もしくはそうしないと動いてくれない。

```sh
npm i -D babel-plugin-transform-es2015-modules-commonjs
```

```json:.babelrc
{
  "env": {
    "test": {
      "plugins": ["transform-es2015-modules-commonjs"]
    }
  }
}
```

## テストとして実行されるファイル

デフォルトでは、 Jestの [rootDir](https://facebook.github.io/jest/docs/en/configuration.html#rootdir-string) 配下にある
次のパターンのファイルをテストコードと見做して実行しようとしてくれる。 (オプションの [testMatch](https://facebook.github.io/jest/docs/en/configuration.html#testmatch-array-string) という設定で変えられる.)

```
[
  '**/__tests__/**/*.js?(x)',
  '**/?(*.)(spec|test).js?(x)'
]
```

正規表現を簡単に説明すると

- `__tests__` ディレクトリ配下の、全ての `*.js` ファイル
- 全ての `*.spec.js` または `*.test.js`

となる。

## Webpack の alias の解決

[公式ドキュメント](https://facebook.github.io/jest/docs/en/webpack.html) をチラ見しただけだと上手く動かせなくて一瞬困った。
`String.replace()` みたいに、 key の `()` でパターンマッチした値を value に `$1` とか書いて置いてあげる必要があるみたい。

```json
{
  "moduleNameMapper": {
    "^@utils/(.+)$": "<rootDir>/resources/assets/js/utils/$1",
    "^@js/(.+)$": "<rootDir>/resources/assets/js/$1"
  }
}
```

---

テストコードはドキュメント読めばなんとかなりそうだったのでかつあい。

![done](https://media.giphy.com/media/QhmboW0R7eUbm/giphy.gif)
ラズベリーパイを縦置きのタッチスクリーンで使用する設定

# この文章について

ラズベリーパイを縦置きタッチスクリーンで使用できるようにしたときのちょっとしたOS設定変更についてのメモです。

# 環境

- [raspberrypi 3b](https://www.raspberrypi.org/products/raspberry-pi-3-model-b/)
- RASPBIAN STRETCH WITH DESKTOP
- [PN-L401C](http://www.sharp.co.jp/business/bigpad/lineup/pnl401c/)
- OS起動時にpiユーザで自動的にDesktopログインするようになっています。

# ディスプレイ表示の回転

設定ファイル「/boot/config.txt」に起動時のパラメータをセットすることでディスプレイ表示を回転させることができます。

設定できる値は下記です。

|設定値|回転|
|---|---|
|0|回転なし|
|1|時計回りに90°|
|2|時計回りに180°|
|3|時計回りに270°|

※「/boot/config.txt」の末尾に回転させたい向きを設定して再起動します。

## ディスプレイ表示を時計回りに90°回転する場合

```:/boot/config.txt
display_hdmi_rotate=1
```

## ディスプレイ表示を時計回りに270°回転する場合

```:/boot/config.txt
display_hdmi_rotate=3
```

再起動したら画面表示が回転した状態になっているかと思います。

# タッチデバイスの回転

ここまでの手順のままだとタッチデバイスの上下左右がディスプレイの回転に追従できていません。
xinputコマンドにてタッチデバイスの回転を制御することが可能です。

まずは、タッチデバイスのデバイス名を知る必要があるので次のコマンドで確認します。

```:bash
pi@raspberrypi:~ $ xinput --list
⎡ Virtual core pointer                          id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ Sharp Corp.   Sharp LT40 TouchPanel       id=7    [slave  pointer  (2)]
⎣ Virtual core keyboard                         id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ UVC Camera (046d:0825)                    id=6    [slave  keyboard (3)]
```

「Virtual core pointer」のツリーにぶらさがっている「Sharp Corp.   Sharp LT40 TouchPanel」が「PN-L401C」なのでこのデバイスに対してxinputの設定をします。
コマンドは次の通り

## タッチデバイスを時計回りに90°回転する場合

```bash
pi@raspberrypi:~ $ xinput --set-prop 'Sharp Corp.   Sharp LT40 TouchPanel' 'Coordinate Transformation Matrix' 0 1 0 -1 0 1 0 0 1
```

## タッチデバイスを時計回りに270°回転する場合

```bash
pi@raspberrypi:~ $ xinput --set-prop 'Sharp Corp.   Sharp LT40 TouchPanel' 'Coordinate Transformation Matrix' 0 -1 1 1 0 0 0 0 1
```

ここまでの手順でディスプレイ表示とタッチデバイス入力の回転ができるようになりました。


# デスクトップ開始時にタッチデバイスを設定

最後にデスクトップ環境起動時のxinputでのタッチデバイスを設定をします。

前準備としてさきほどのxinputコマンドを実行するシェルスクリプトを作成しておきます。保存先は「~/rotate_touch_screen.sh」とします。

```:~/rotate_touch_screen.sh
!/bin/bash
xinput --set-prop 'Sharp Corp.   Sharp LT40 TouchPanel' 'Coordinate Transformation Matrix' 0 1 0 -1 0 1 0 0 1
```
※上記は「タッチデバイスを時計回りに90°回転する場合」です。

スクリプト実行できるようにフラグをつけておきます。

```:bash
pi@raspberrypi:~ $ chmod +x ~/rotate_touch_screen.sh
```

次に起動時設定にスクリプト実行設定を追加します。設定するファイルは「~/.config/lxsession/LXDE-pi/autostart」で末尾に追加します。

```:~/.config/lxsession/LXDE-pi/autostart 
@/home/pi/rotate_touch_screen.sh
```

再起動してみて、画面の回転、タッチデバイスの回転が問題なければ設定完了です。
【メモ】Watson Studioで強化学習サンプルを動かすNotebook

[Pythonではじめる強化学習](https://qiita.com/Hironsan/items/56f6c0b2f4cfd28dd906)の記事を参考に、
[aima-python](https://github.com/aimacode/aima-python/blob/master/README.md)のNotebookをWatson Studio上で動くように加工してみました。

作ったNotebookファイルは [Git リポジトリ](https://github.com/makaishi2/watson-studio-sample-notebooks/blob/master/mdp.ipynb)にアップしてあります。

中身はなかなか難解でこれから要勉強という感じです。

![mdp-a.png](https://qiita-image-store.s3.amazonaws.com/0/206130/562777fa-044d-f02a-83cc-fde98bde70e8.png)

![-0.04.jpg](https://qiita-image-store.s3.amazonaws.com/0/206130/658ba31a-7d19-8258-0ecb-a5996b2d37c9.jpeg)
中華ワンチャンネルリレーモジュールの調理法

#はじめに
amazon.co.jpで販売されているSODIAL [ワンチャンネルリレーモジュール](https://www.amazon.co.jp/gp/product/B01GNKV6OO/ref=oh_aui_detailpage_o03_s00?ie=UTF8&psc=1)を購入し使ってみました。リレーモジュールなど3本線を繋げば動くに決まっていると高を括っていたら、そうでもなかったのでまとめておきます。
#仕様がない
出力の仕様は書いてある通りですが、入力は不完全で間違っています。「ハイレベル」でなくローレベルでONであり、Vth=4V以上です。つまり、3.3VのRPi, NanoPIにそのまま接続すると常時ONになり制御不能です。
#どうすれば使えるか？
要するに使えないのですが、135円という悲しいほどの安さにつられて買ってしまったもののそのまま捨てるのでは部品に申し訳なく、使ってみることにしました。![rom024.jpg](https://qiita-image-store.s3.amazonaws.com/0/245853/8c5fe80e-0aec-cb38-c0ab-d4e1c340921f.jpeg)
タダのリレーにLED,逆起電力阻止ダイオード、出力端子台が載った基板で入力はそのまま、と思えばよいのです。INをGNDに繋ぎVcc5Vとして、パワーMOSでドライブすればインチキなし、仕様満足でドライブすることができます。
#注意
仕様満足って[2SK2796](http://akizukidenshi.com/catalog/g/gI-07145/)はVgs=4Vって書いてあるぞ！3.3VのRPi, NanoPIじゃあドライブできないじゃん！とおっしゃる貴兄に、仕様書は最後まで読みましょう。このディバイスはTypical Output Characteristics
のグラフに示されている通りVgs=2Vでonになり3.3Vではすでに飽和します。Id>5Aにするならともかく0.1Aも流れないこの用途では、十分なドライブなのです。
#結論
安かろう悪かろうではなく、仕様違いですね。基板の裏には Low level Triggerと明記されてます。
良い子の皆さんは、避けたほうが良いかもしれません。
冒険好きなおじさんには格好の餌なのですが…
Ionic3のiOSアプリでステータスバーのオーバーレイ表示をしない方法

* OS: macOS High Sierra 10.13.4
* Xcode: 9.3 Build version 9E145
* Node.js: v8.9.3
* npm: v5.6.0
* cordova: v7.1.0
* Ionic: 3.20.0
* cordova-ios: 4.5.4

### 1. ステータスバー制御プラグインを追加

```bash
$ ionic cordova plugin add cordova-plugin-statusbar
$ npm install --save @ionic-native/status-bar
```

### 2. app.module.ts の providers に StatusBar を追加

```src/app/app.module.ts
import { StatusBar } from '@ionic-native/status-bar';
...
    providers: [
        StatusBar,
    }
...
```

### 3. ステータスバーのオーバーレイ表示設定

```src/app/app.component.ts
import { StatusBar } from '@ionic-native/status-bar';

public constructor(private platform: Platform, private statusBar: StatusBar) {
    this.initializeApp();
}

private initializeApp() {
    this.platform.ready().then(() => {
        // Okay, so the platform is ready and our plugins are available.
        // Here you can do any higher level native things you might need.
        this.statusBar.styleDefault();
    
        // ステータスバーのオーバーレイ表示設定
        this.statusBar.overlaysWebView(false);
    });
}

```
PrestoとHiveのクエリだけでリストを作ってみる

## 概要
クエリを書いている際、実際のテーブルは存在しないが、仮のてリストを作ってJOINしたい場合などあったので、調べた内容をメモしておく。
※TreasureDataで実行している話なので、HIVEのバージョンがもっと上なら・・・などについては触れないことにする

## Prestoで作ってみる
```sql
WITH rates AS (
  SELECT * FROM (
    VALUES
      ('2018-01', 0.92, 0.195),
      ('2018-02', 0.92, 0.195),
      ('2018-03', 0.92, 0.195),
      ('2018-04', 0.92, 0.195),
      ('2018-05', 0.92, 0.195),
      ('2018-06', 0.92, 0.195),
      ('2018-07', 0.92, 0.195),
      ('2018-08', 0.92, 0.195),
      ('2018-09', 0.92, 0.195),
      ('2018-10', 0.92, 0.195),
      ('2018-11', 0.92, 0.195),
      ('2018-12', 0.92, 0.195),
      ('2019-01', 0.92, 0.195),
      ('2019-02', 0.92, 0.195),
      ('2019-03', 0.92, 0.195)
  ) AS t (month, tweek, rate)
)
SELECT * FROM rates;
```

## Hiveで作ってみる
HIVEで、「VALUES」が使えなかったので、どうにもならず普通にSELECTで書いてみる・・・
とりあえず、実行はできたが非常に微妙・・・何かいいやり方他にないのかな・・・

```sql
WITH rates AS (
  SELECT * FROM (
    SELECT '2018-01' as month, '0.92' as tweak, '0.195' as rate
    UNION ALL
    SELECT '2018-02' as month, '0.92' as tweak, '0.195' as rate
  ) AS t1
)
SELECT * FROM rates;
```
ベクトル解析-ベクトルの掛算

# ベクトルの掛算

[戻る](https://qiita.com/bobchin/items/aafe7e0e25ff4e8689bc#ベクトルの掛算)

```math
\begin{array}{lccl}
　&\boldsymbol{A} &=& A_x e_x + A_y e_y + A_z e_z \\
　&\boldsymbol{B} &=& B_x e_x + B_y e_y + B_z e_z \\
　&|\boldsymbol{A}| &=& \sqrt{{A_x}^2 + {A_y}^2 + {A_z}^2} \\
\\
　1. 整数倍:& k \boldsymbol{A} &=& k A_x e_x + k A_y e_y + k A_z e_z \\
\\

　2. 内積:& \boldsymbol{A} \cdot \boldsymbol{B} &=& |\boldsymbol{A}||\boldsymbol{B}| cos \theta = A_xB_x + A_yB_y + A_zB_z \\
\\
　3. 外積:& \boldsymbol{A} \times \boldsymbol{B} &=& |\boldsymbol{A}||\boldsymbol{B}| sin \theta = e_x(A_yB_z - A_zB_y) + e_y(A_zB_x - A_xB_z) + e_z(A_xB_y - A_yB_x) \\
\\
　4. ﾃﾝｿﾙ積:& \boldsymbol{A} \otimes \boldsymbol{B} &=& (A_x e_x + A_y e_y + A_z e_z) \otimes (B_x e_x + B_y e_y + B_z e_z) \\
　&  &=&e_x \otimes e_xA_xB_x + e_x \otimes e_y A_xB_y + e_x \otimes e_zA_xB_z\\
　& &  &e_y \otimes e_xA_yB_x + e_y \otimes e_y A_yB_y + e_y \otimes e_zA_yB_z\\
　& &  &e_z \otimes e_xA_zB_x + e_z \otimes e_y A_zB_y + e_z \otimes e_zA_zB_z\\
\end{array}
```
ベクトル解析-ベクトル関係の記述

# ベクトル関係の記述

[戻る](aafe7e0e25ff4e8689bc#ベクトル関係の記述)

```math
\vec{A}\\
f'(x)\\
f''(x)\\
f^{(3)}(x)\\
f_{x}\\
f_{xy}\\
\frac{\partial f}{\partial y}\\
\frac{\partial^2 f}{\partial^2 y}\\
\frac{\partial}{\partial x} \left(\frac{\partial z}{\partial y}\right)\\
\frac{\partial}{\partial x} (\frac{\partial z}{\partial y})\\
\Delta = \nabla^2 = \frac{\partial^2 f}{\partial x^2} + \frac{\partial^2 f}{\partial y^2}\\
\vec{a} = (a_1, a_2, \cdots, a_n)\\
\boldsymbol{A}\\
\vec{a} \perp \vec{a}\\
\vec{a} \parallel \vec{a}\\
{}^t\boldsymbol{A}\\
\boldsymbol{a} \cdot \boldsymbol{b}\\
\boldsymbol{a} \times \boldsymbol{b}\\
\boldsymbol{a} \otimes \boldsymbol{b}\\
```
ubuntu 16.04 有線接続で外部へpingは通るのにブラウザからは外が見えないときの解決法メモ

きっと数百番煎じ

# 前提
Ethernetドライバはインストール済とする

# ネームサーバーが解決されていない
そりゃそうですよね。
IP直打ちで要求が通ってもドメイン名で通るかどうかはわからない。

```
$ nano /etc/resolve.conf
```

nameserver 127.0.0.1

そりゃ通らへんわ。

nameserver 1.1.1.1　に変更して終了。


## 課題
/etc/resolve.conf　を直接に編集するのではなく、 /etc/network/interfaces で

```
$nano /etc/network/interfaces
>auto eth0
>    iface eth0 static
>    address 192....../24
>    gateway 192......
>    dns-nameservers 1.1.1.1 (8.8.8.8でもお好きなものを)

$ service networking restart
```

する方が安全らしい。
私の場合は再起動しないと受け付けてくれなかったけども。

なぜ resolve.conf ではなくinterfaces をいじる方が安全なんだろう。
redis clusterを自力で構築する

# はじめに
redis-serverとredis-cliだけが使える状況で3台でのクラスターを構築します。
ほとんど [redis clusterを自力で構築してみた](https://qiita.com/sawada_masahiko/items/c58ff2953e04c2956c6f) と同じ内容です。

# 前提条件
3台のredisが起動できる状態とします。
標準設定のポートだとバッティングしますので、2台め／3台めをそれぞれ別ポート（ノード）で起動できるようにして下さい。

経験則として、ポート番号は100／1000単位で設定すると、後からのトラブルシューティングやlog確認時にredisであることが伝わりやすいのでおすすめです。

# slot設定

## ポートごとの割当
単純に3分割した数を設定します。
16383 / 3 = 5461となるので、表にまとめると以下のようになります。

| ポート | slot範囲 |
| :----:| :-----: |
| 6379  |    0 - 5461|
| 6479  | 5462 - 10922|
| 6579  | 10933 - 16383|

## slotの割当
for文で上記slot数分を1つ1つ割当します。
redis-cliに範囲指定の方法は無いのでしょうか、あってもいいような気もします。

```bash
# パスワードを設定している場合
password="password"

# 0-5461
for slot in `seq 0 5461`; do
  if [ $(($slot % 1000)) == 0 ]; then
    echo '$slot: '$slot
  fi
  redis-cli -p 6379 -a ${password} CLUSTER ADDSLOTS $slot > /dev/null
done

# 5462-10923
for slot in `seq 5462 10923`; do
  if [ $(($slot % 1000)) == 0 ]; then
    echo '$slot: '$slot
  fi
  redis-cli -p 6479 -a ${password} CLUSTER ADDSLOTS $slot > /dev/null
done

# 10924-16383
for slot in `seq 10924 16383`; do
  if [ $(($slot % 1000)) == 0 ]; then
    echo '$slot: '$slot
  fi
  redis-cli -p 6579 -a ${password} CLUSTER ADDSLOTS $slot > /dev/null
done
```
じゃっかん処理に時間が掛かるので、進行状況を確認するために1000単位の時にechoするようにしています。

今回は設定しませんでしたが、各ポートでの初めと終わりにも表示した方が親切です。
その場合、ポートごとの範囲の初めと終わりは環境変数に持つと良いと思います。

## slot割当後のnode.conf
```conf:6379port/nodes.conf
2e6a31d530b15d79cf2bf58550899a7073ca5704 :6379 myself,master - 0 0 0 connected 0-5461
vars currentEpoch 0 lastVoteEpoch 0
```
1行目の一番の項目が0-5461となっているのが6379 portのノードが割当てられているslotです。
同じように6479 port、6579 portの設定ファイルも確認出来ます。

# クラスタリング
## 作業概要

| ポート | slot範囲 |
| :----:| :-----: |
| 6379  | 起点ノード（親）|
| 6479  | 接続要求を6379に出す（子）|
| 6579  | 接続要求を6379に出す（子）|

slotの割当てが完了しました。
次は3台をつなげるクラスタリングを行います。

クラスタリングでは
「ある基点となるノード一台(基点ノード)を決めて、そのノード以外から基点ノードへ接続要求を出す」という感じでつなぎます。

子から親へ許可を求めるイメージでしょうか。

## CLUSTER MEET

クラスタリングの接続要求はCLUSTER MEETを実行します。

ノードのIPがlocalhostなどの場合、
環境によってはクラスター動作後のリダイレクトでうまくスイッチされないことがあるので内部IPアドレスを使用することをおすすめします。

```bash
# パスワードを設定している場合
password="password"

# cluser meet: 6479->6379
redis-cli -p 6479 -a ${password} CLUSTER MEET 10.1.1.10 6379
#実行後に正常終了であればOK

# cluser meet: 6579->6379
redis-cli -p 6579 -a ${password} CLUSTER MEET 10.1.1.10 6379
#実行後に正常終了であればOK
```
## 動作確認
設定ファイルを確認後、動作確認として単純なget/setを行います。
**クラスタに対してredis-cliをするときは-cオプションを忘れずに**

```bash:動作確認
$ redis-cli -c -p 6379
10.1.1.10:6379> set num:1 1
-> Redirected to slot [15698] located at 10.1.1.10:6479
OK
10.1.1.10:6479> set num:2 2
-> Redirected to slot [3377] located at 10.1.1.10:6379
OK
10.1.1.10:6379> get num:1
-> Redirected to slot [15698] located at 10.1.1.10:6579
"1"
```

setの度に異なるノードにリダイレクトされ、正しく動作していることが確認出来ました。
層圏トポス: 前層の2つの定義の同値性その1

前層の第一の定義から第二の定義が導けることについて、本では詳細が割愛されていたのでそれを証明します。 (p.14)

第一の定義によって前層が定義されていると仮定して、第二の定義による前層を導きます。

## 第一の定義による前層の仮定

p.13~ の定義より次が仮定できます。

```math
A : Set\\
E : A \to \mathfrak{O}(U)\\
\neg : A \times \mathfrak{O}(U) \to A\\
```

そして、第一の定義の４つの性質が成り立つものと仮定できます。

## Fとrを具体的に構成する

ここで、 $F$ と $r_{UV}$ を次で与えます。

```math
F: A \to A\\
F(U) := \left\{f \in A \mid Ef=U \right\} ~~ (つまりEの逆像)\\
U\subset V のとき、
r_{UV} : F(V) \to F(U) を次で与える\\
f\in F(V)について、 r_{UV}(f) := f\neg U ~~(\in F(U))
```

この作り方で関数 $r_{UV}$ が $F(V) \to F(U)$ に本当になっているかですが、今 $U\subset V$ であって、$Ef = V$ なので、 $E(f\neg U) = V \cap U = U$ となって大丈夫です。

## 第二の定義の性質を満たすことを示す

これから $F, r_{UV}$ が前層の第二の定義に従うことを示します。それは次の３つの項目でした。

1. $F(\emptyset)$ が単一集合
1. $r_{UU}$ が恒等写像
1. $U\subset V \subset W$ ならば $r_{UW} = r_{UV} \circ r_{VW}$

順番に示します。

### 1. について

$\forall f, g\in F(\emptyset)$ について $f = g$ を示すという方針で示します。

今、 $F$の与え方から次が成り立ちます。

```math
F(\emptyset) = \left\{ f \mid Ef = \emptyset \right\}
```

なので $Ef = Eg = \emptyset$ が成り立ちます、ここで前層の第一の定義より $f\neg Ef = f$ も成り立つので、 $f\neg \emptyset = f$ となります。
同様に $g\neg \emptyset = g$ ともなります。
前層の第一の定義より $f\neg \emptyset = g\neg \emptyset$ となるため、 $f=g$ となるわけです。

($F(\emptyset)$ が空になることはありえない...?)

### 2. について

任意の $f \in F(U)$ について

```math
\begin{eqnarray}
r_{UU}(f) &=& f\neg U\\
          &=& (f\neg Ef)\neg U\\
          &=& f \neg (U \cap U)\\
          &=& f \neg U\\
          &=& f
\end{eqnarray}
```

よって恒等写像になります。

### 3. について

$U \subset V \subset W$のとき、任意の $f \in F(W)$ について、 $r_{UW}(f) = r_{UV}(r_{VW}(f))$ を示します。

```math
\begin{eqnarray}
(右辺) &=& r_{UV}(r_{VW}(f))\\
       &=& r_{UV}(f \neg V)\\
       &=& (f\neg V) \neg U\\
       &=& f \neg (V\cap U)\\
       &=& f \neg U\\
       &=& (左辺)
\end{eqnarray}
```

以上です。
バブルソート


```c
#include <stdio.h>

void SortBubble(int array[], int n, int asc);

int main(void){
    int array[] = {7,1,6,9,3};
    int arraySize = (int)(sizeof(array)/sizeof(array[0]));
    SortBubble(array, arraySize, 1);
    SortBubble(array, arraySize, 0);

    return 0;
}

void SortBubble(int array[], int n, int asc){
    int tmp;

    for(int i = 0; i < n - 1; i++){
        for(int j = 0; j < n - 1; j++){
            if(asc) {
                // 昇順
                if(array[j+1] < array[j]){
                    // jとj+1番目の値を入れ替える
                    tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                }
            } else {
                // 降順
                if(array[j+1] > array[j]){
                    tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                }
            }
        }
    }

    asc 
        ? printf("昇順：")
        : printf("降順：");
    for(int i = 0; i < n; i++){
        printf("%d,", array[i]);
    } 
    printf("\n");
}
```

数値の流れ

i=0のとき,jのループを回すと...
1,7,6,9,3
1,6,7,9,3
1,6,7,9,3
1,6,7,3,9

i=1のとき,jのループを回すと...
1,6,7,3,9
1,6,7,3,9
1,6,3,7,9
1,6,3,7,9

.
.
.


```bash:出力
昇順：1,3,6,7,9,
降順：9,7,6,3,1,
```


> 参考
[苦しんで覚えるＣ言語 バブルソート](https://9cguide.appspot.com/a_sort-bubble.html)
macOS から WindowsOS へリモートデスクトップ接続ツール - 日本語入力まわりに困っていたら Parallels Client が無難?

macOS (OS X) から、WindowsOS へリモートデスクトップ(RDP)接続するためのツールがいくつか存在します。
過去 Microsoft 謹製のリモートデスクトップ接続ツールでは、日本語入力でとても苦しみました（ネット検索すると先達方の苦労の跡がみられます。私も参考にさせていただいて、キー入力を独自に割り当てたり、レジストリをいじったりしてみたものの、どうも解消できず）
結論からしますと、Parallels Client によって解消され、現在は快適にMacOSとWinOSの両刀使いをしております。
また今回検証してみたところ、数か月前まで Microsoft Remote Desktop の8系でも10系でも日本語入力まわりが（私の環境では）うまくいかなかったのですが、現在問題は解消されていました。
とりあえず、こちらにまとめさせていただきます（随時補完）

※この記事は2018年4月に作成しました。

#比較

| 製品名 | Microsoft<br>Remote Desktop Connection<br>2.1.1 | Microsoft<br>Remote Desktop<br>8.0.43 | Microsoft<br>Remote Desktop<br>10.1.7  | Parallels<br>Client<br>16.2 |
|:------|:-------|:-------|:-------|:-------|
|入手元|現在非公開|App Store|App Store|App Store|App Store|
|費用|無償|無償|無償|無償|
|ツール言語|日本語|英語|英語|日本語|
|日本語入力|良好|難|良好|良好|
|複数ディスプレイ|NG|OK|OK|OK|
|Win10へ接続|難※1|可能|可能|可能|

※1 - 接続元（Mac側）で「証明書または関連するチェーンが無効です」や「接続先のコンピューターの ID を確認できません」と表示されて失敗したりします。接続できる場合もあるのですが、原因を切り分けできていません。
![2.png](https://qiita-image-store.s3.amazonaws.com/0/100206/272581b0-ff89-e5d2-1e9a-63b892e2c552.png)
git-completion がきえた

hello.

mac に　commandlinetools いれるとはいってた 

```
/Library/Developer/CommandLineTools/usr/share/git-core/git-completion.bash
```

がいつのまにかなくなってた I don't know why.

ので、

https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash

を DL してきて .bashrc 書き換えた。

over.
ATOM　for Windows　設定　備忘録


参考(https://qiita.com/nekotank/items/6106dfcad7c7ed828979)

# Download

http://atom.io/

Download をクリックする。

# Install先
実行ファイルを実行して、インストールをすると以下に保存される。

C:\Users\(ユーザ名)\AppData\Local\atom\

# Proxy環境設定

C:\Users\(ユーザ名)\\.atom\\.apmrc　に以下を記述
.atom\\.apm\\.apmrc　に記述しても変更内容が反映されない
.atom\\.apmrcがなければ新規作成

```
http-proxy = http://(ユーザ名):(Password)@(Proxyサーバアドレス):(Port番号)
https-proxy = http://(ユーザ名):(Password)@(Proxyサーバアドレス):(Port番号)
strict-ssl = false

```

参考URLでは、設定しては行けない項目として
strict-ssl = false
となっていますが、trueだと会社の環境ではうまくいきませんでした。
素直にfalseを設定しました。


# インストールしたパッケージ

japanese-menu
メニューの日本語化
Oracle メモ　DUAL


```sql

SELECT TO_CHAR(SYSDATE,'HH24MI'),
　　　　TO_CHAR(SYSDATE,'D') INTO　
　　　　　　CHK_TIME,CHK_YOBI FROM DUAL;

```

[https://www.shift-the-oracle.com/table/dual.html](https://www.shift-the-oracle.com/table/dual.html "DUAL 表")

>注意
>PL/SQLで DUAL 表を関数呼び出しだけを目的とした使用方法は避ける(SQL 文>の解析で実行速度が低下する)。 高速化のつもりで DECODE 関数を使用するた>めに DUAL 表にアクセスしているのは、現在では古いコーディングスタイルと
>いえるだろう。 現在(Oracle 9i 以降)では CASE 文(および CASE 式) がサポー>トされている。そちらを使用するほうが見た目も効率も良い。
[調査中]AIエンジニアに、俺はなりたい

スキル習得の為、学習パスを学んでいる。
# ０．手っ取り早く
- [ ] [Windowsで簡単にAI開発の環境構築＜人工知能を体験したい人向け＞](https://qiita.com/AfricaUmare/items/f15ef281d7d0f3aa4d44)

# １．機械学習の知識

・教師あり学習と教師無し学習
・回帰と分類
・決定木、重回帰分析
・ディープラーニング


# ２．プログラミングの知識

## Anaconda（pythonの実行環境とライブラリ一式）
　anacondaは、Pythonの主要なライブラリをパッケージした
　オープンデータサイエンスのプラットフォーム.
　だいたいこれをインストールしておけば、環境が整う

- [ ] [Anaconda で Python 環境をインストールする](https://qiita.com/t2y/items/2a3eb58103e85d8064b6)

## Jupyter（ＩＤＥ）
　Jupyter Notebook(旧ipython notebook)は、Pythonをはじめとした
　プログラムのインタラクティブな実行環境を実現するウェブアプリ.

## scikit-learn（ＭＬライブラリ）
　scikit-learnは、Google製の機械学習用のライブラリ集.

## tensorflow（ＣＮＮ／ＲＮＮ）
　データフローグラフを使って数値演算を行う
　オープンソースソフトウェア.Google製.

## NumPy（数値計算）
　「Python」のベクトルや行列計算を高速に行うためのライブラリ
　「NumPy（ナンパイ）」の基礎を学びます。
　「NumPy」を用いることで、効率的な科学技術計算が可能になり、
　機械学習分野に必須のライブラリです。

## Pandas（データ処理）
　「Python」のデータ分析用ライブラリ
　「Pandas（パンダス）」の基礎を学びます。
　「Pandas」を用いることで数表や時系列データの計算が楽になり、
　定量データ解析には必須のライブラリです。

## Matplotlib（データの可視化）
　matplotlibを用いてデータを可視化する方法を学びます。
　折れ線グラフ、円グラフ、ヒストグラム等の作成から、
　3Dグラフを作成する方法まで学びます。

## gensim 
## MeCab 
## Keras
## BeautifulSoup
## Flask
## CapsNet
## Adversarial Examples

# BIG4のAI関連プロダクト(Amazon/Google/IBM/Microsoft)

## Amazon/API

Amazon Rekognition
Amazon Polly
Amazon Lex
Alexa Skills Kit（ASK）
Alexa Voice Services（AVS）

## Google/API

Google Cloud Vision API
Google Cloud Speech API
Google Natural Language API
Google Cloud Translate API

## IBM/API

AlchemyLanguage
Conversation（日本語）
Document Conversion（日本語）
Language Translator
Natural Language Classifier（日本語）
Natural Language Understanding
Personality Insights（日本語）
Retrieve and Rank（日本語）
Tone Analyzer
Speech to Text（日本語） 
Text to Speech（日本語）
Visual Recognition（日本語）
AlchemyData News
Discovery
Tradeoff Analytics

## Microsoft/API

Computer Vision API
Content Moderator
Emotion API
Face API
Video API
Bing Speech API
Custom Speech Service
Speaker Recognition API
Bing Spell Check API
Language Understanding Intelligent Service
Linguistic Analysis API
Text Analytics API
Translator API
Web Language Model API
Academic Knowledge API
Entity Linking Intelligence Service
Knowledge Exploration Service
QnA Maker
Recommendations API
Bing Autosuggest API
Bing Image Search API
Bing News Search API
Bing Video Search API
Bing Web Search API
We're sorry, but something went wrong.If you are the application owner check the logs for more information.でハマる。

ブログの会員登録を機能を作成中に起こったエラー、
submitボタンを押すと、下記が表示される。

![railssomethingwrong.png](https://qiita-image-store.s3.amazonaws.com/0/223487/b8fbe3e4-4489-8322-b26f-1b13e396206d.png)

### 参考スペック
```
cloud 9
Rails 5.1.4
ruby 2.4.0p0
psql (PostgreSQL) 9.3.18
Ubuntsu 14.04.5
```


Railsのエラー表記ではないので、DBかhtmlの問題か。

### 疑い① DB系の原因

いろいろ調べてみると、どうやらpostgreの認証、もしくはデプロイの過程で弾かれている例が多いみたい。

[peer認証の関係でpsqlログインできない時の対処法/qiita](https://qiita.com/tomlla/items/9fa2feab1b9bd8749584)
[PostgreSQLでパスワード認証を行う方法/qiita](https://qiita.com/Mitsunori_Tsukada/items/383a7b7124e3c4d9c82f)
こちらを参考にさせて頂き、レッツトライ。


どうやらpg_hba.confの中で、認証方法を変える必要があるらしい。。
ログインは出来たのに別の認証が必要なの？
奥が深い。


```pg_hba.confを探す
$ sudo find / -name pg_hba.conf
```

```pg_hba.confを開く

$ sudo vi /etc/postgresql/9.3/main/pg_hba.conf

# Database administrative login by Unix domain socket
local   all             postgres                                peer

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
host    all             all             ::1/128                 md5
# Allow replication connections from localhost, by a user with the
# replication privilege.
#local   replication     postgres                                peer
```                                                                     
ここのpeerの部分を「trust」もしくはコメントアウトすると良いらしい。


変更する、、が、上書き出来ない？
そもそも、sudoの終了の仕方も理解してないし、DBは別で勉強の時間が必要だなこりゃ><
とりあえず保留。

### 疑い② viewの原因
submit後は、user詳細画面に飛ぶ設計にしてあるので、users配下のビューファイルをチェック。

```user.html.erb
<h1><%= @user.company, @user.name %>さん、ようこそ。</h1>

```

ずっと分からなかったのですが、指摘してもらいようやく分かりました。

```user.html.erb
<h1><%= @user.company %>,<%= @user.name %>さん、ようこそ。</h1>

```
切り分けなきゃなんですね。
新たな課題にも気づけたし、日々精進。
TFS 2013 > 手順 > 過去の履歴のファイルを取得する

```txt:動作環境
Windows 7 Pro (32bit)
Microsoft Visual Studio 2013 Shell (Integrated)
Team Explorer for Visual Studio 2013
```

TFS (Team Foundation Server)を使って9年前のソースコードを取得している。

30個ほどのファイルに対して、以下の手順で取得するのが簡単だった。

1. 履歴の表示
2. 取得したい「変更セット」をダブルクリック
    - >> チームエクスプローラ - 変更セット が表示される
3. 取得したいソースをダブルクリック
4. ファイル > 名前を付けて***を保存(A)
5. デスクトップなどに保存する
6. 右側のチームエクスプローラを選択
    - >> 先ほど選択したファイルにフォーカスがある
7. 次のファイルをダブルクリック
8. 手順4から全ファイルに対して繰返す
AWS超初心者が無料利用枠制限でやってしまった失敗

オンプレインフラエンジニアがAWSを勉強ようとして、失敗したことがこちら。

**EC2インスタンスを起動しっぱなし**で、請求するよ〜！ってメールが来た。

勉強するぞ！コリコリ触ろ！
１年間無料だし。

って思ってたら、このままいくと１ヶ月の利用が無料枠を超えそうだよ！ってメールが来たので、
慌てて全てのインスタンスを止めました。

という超初歩的なお話でした。

2018/04/26追記
無料利用枠でどれくらいのリソースが使えるかがAWS見積りツールにありました。
ここで利用枠のあたりをつけるのがいいのかも。

[AWS見積りツール](http://calculator.s3.amazonaws.com/index.html?lng=ja_JP)
TreasureDataで今月の1日を取得する

## 概要
データ抽出で１年間とかをする場合、今月の１日を取得してそこからマイナス３６５日の期間を取得するようにしたかったので調べた内容を記載しておきます。

## 今月の１日の取得方法
下記のようにしたら取得できました。

```sql
SELECT
  TD_TIME_FORMAT(
    TD_DATE_TRUNC('month', TD_SCHEDULED_TIME()),
    'yyyy-MM-dd',
    'JST'
  )
;
```
結果

```
2018-04-01
```


## 今月1日から365日マイナスした期間を取得する

```sql
SELECT
  -- 開始日(今月1日からマイナス365日した日付)
  TD_TIME_FORMAT(
    TD_TIME_ADD(TD_DATE_TRUNC('month', TD_SCHEDULED_TIME()), '-365d'),
    'yyyy-MM-dd',
    'JST'
  ) AS s,
  -- 終了日（今月1日)
  TD_TIME_FORMAT(
    TD_DATE_TRUNC('month', TD_SCHEDULED_TIME()),
    'yyyy-MM-dd',
    'JST'
  ) AS e
;
```

結果

```
| s          | e          |
| 2017-04-01 | 2018-04-01 |
```

## 先月の末日から365日マイナスした期間をWHERE条件に指定する
「2018/０４/24 PM12:00」で実行すると 「2017-04-01 <= time < 2018-04-01」の期間が取得できます。
※　TD_TIME_RANGEは、開始日は含むが終了日は含まないため、今月1日を指定すると先月末日までとなる。

```sql
SELECT
  MIN(time) AS min,
  MAX(time) AS max
FROM
  hoge
WHERE
  TD_TIME_RANGE(
    -- 判定対象カラム
    time, 
    -- 開始日(今月1日からマイナス365日した日付)
    TD_TIME_ADD(TD_DATE_TRUNC('month', TD_SCHEDULED_TIME()), '-365d'),
    -- 終了日（今月1日） ※期間には含まれない
    TD_DATE_TRUNC('month', TD_SCHEDULED_TIME())
  )
;
```



以上です。

## 参考サイト
* https://y-mattu.hatenablog.com/entry/2016/01/30/000452
ベクトル解析-２階テンソルとベクトルの積

# ２階テンソルとベクトルの積

[戻る](https://qiita.com/bobchin/items/aafe7e0e25ff4e8689bc#２階テンソルとベクトルの積)

- ２階テンソルの前からベクトルを掛けると、２階テンソルの前とベクトルが同じ場合のみ２階テンソルの後のモノが出てくる。  
  ２階テンソルの後ろのもの取り出したいなら、２階テンソルの前と同じベクトルを前から掛ける。

```math
\begin{array}{lll}
\hline
　e_x \cdot (e_x \otimes e_x) = e_x, & e_x \cdot (e_x \otimes e_y) = e_y, & e_x \cdot (e_x \otimes e_z) = e_z　\\
　e_x \cdot (e_y \otimes e_x) = 0,   & e_x \cdot (e_y \otimes e_y) = 0,   & e_x \cdot (e_y \otimes e_z) = 0　\\
　e_x \cdot (e_z \otimes e_x) = 0,   & e_x \cdot (e_z \otimes e_y) = 0,   & e_x \cdot (e_z \otimes e_z) = 0　\\
\hline
　e_y \cdot (e_x \otimes e_x) = 0,   & e_y \cdot (e_x \otimes e_y) = 0,   & e_y \cdot (e_x \otimes e_z) = 0\\
　e_y \cdot (e_y \otimes e_x) = e_x, & e_y \cdot (e_y \otimes e_y) = e_y, & e_y \cdot (e_y \otimes e_z) = e_z\\
　e_y \cdot (e_z \otimes e_x) = 0,   & e_y \cdot (e_z \otimes e_y) = 0,   & e_y \cdot (e_z \otimes e_z) = 0\\
\hline
　e_z \cdot (e_x \otimes e_x) = 0,   & e_z \cdot (e_x \otimes e_y) = 0,   & e_z \cdot (e_x \otimes e_z) = 0\\
　e_z \cdot (e_y \otimes e_x) = 0,   & e_z \cdot (e_y \otimes e_y) = 0,   & e_z \cdot (e_y \otimes e_z) = 0\\
　e_z \cdot (e_z \otimes e_x) = e_x, & e_z \cdot (e_z \otimes e_y) = e_y, & e_z \cdot (e_z \otimes e_z) = e_z\\
\hline\\
\end{array}
```

- ２階テンソルの後からベクトルを掛けると、２階テンソルの後とベクトルが同じ場合のみ２階テンソルの前のモノが出てくる。  
  ２階テンソルの前のもの取り出したいなら、２階テンソルの後ろと同じベクトルを後ろから掛ける。

```math
\begin{array}{lll}
\hline
　(e_x \otimes e_x) \cdot e_x = e_x, & (e_x \otimes e_y) \cdot e_x = 0,   & (e_x \otimes e_z) \cdot e_x = 0　\\
　(e_y \otimes e_x) \cdot e_x = e_y, & (e_y \otimes e_y) \cdot e_x = 0,   & (e_y \otimes e_z) \cdot e_x = 0　\\
　(e_z \otimes e_x) \cdot e_x = e_z, & (e_z \otimes e_y) \cdot e_x = 0,   & (e_z \otimes e_z) \cdot e_x = 0　\\
\hline
　(e_x \otimes e_x) \cdot e_y = 0,   & (e_x \otimes e_y) \cdot e_y = e_x, & (e_x \otimes e_z) \cdot e_y = 0　\\
　(e_y \otimes e_x) \cdot e_y = 0,   & (e_y \otimes e_y) \cdot e_y = e_y, & (e_y \otimes e_z) \cdot e_y = 0　\\
　(e_z \otimes e_x) \cdot e_y = 0,   & (e_z \otimes e_y) \cdot e_y = e_z, & (e_z \otimes e_z) \cdot e_y = 0　\\
\hline
　(e_x \otimes e_x) \cdot e_z = 0,   & (e_x \otimes e_y) \cdot e_z = 0,   & (e_x \otimes e_z) \cdot e_z = e_x　\\
　(e_y \otimes e_x) \cdot e_z = 0,   & (e_y \otimes e_y) \cdot e_z = 0,   & (e_y \otimes e_z) \cdot e_z = e_y　\\
　(e_z \otimes e_x) \cdot e_z = 0,   & (e_z \otimes e_y) \cdot e_z = 0,   & (e_z \otimes e_z) \cdot e_z = e_z　\\
\hline
\end{array}
```
AppStoreの予約注文に対応してみた

ひさびさに（といっても2017/11ぶり）アプリリリースのためitunes connectを覗いたところ、予約注文ができてた。普段は [予約トップ10](https://yoyaku-top10.jp/u/a/MjYxOTQ)をつかっていたけれど、こういう手段も増えたんですね。気になったので試してみた記事を書きます。

# 選択するとリリース日を求められる
リリース日は審査次第だしなー、ということで最初は手動リリースを選択。審査に提出。

# 審査通った後
デベロッパーによるリリース待ちになってから予約注文開始を選択することができた。選択するとやはりリリース日を求められる。4/24朝に審査通過で、リリース日は4/27以降を選択可能だった。4/27を選択したが、きっと日本時間だと4/28にリリースなんだろうな。本当は4/27にリリースしたかったところ。（追記：2018/04/27 思い込みで、しっかり日本時間の4/27の朝にリリースされました！）

``The status for your app, 勝ち馬アナリスト (1357056787), is now Pre-order Ready for Sale.``
というメールがきてitunes connectでも黄色から緑に変化。数時間待てばストアに現れるかな。

# 2時間後
予約注文として公開されました。
[勝ち馬アナリスト](https://apple.co/2HpmtoQ)

# リリースまでの間にバグ修正版を審査に出せるか？
テストフライトでは公開できた。審査に提出すると予約注文がどうなるのか躊躇。

# むむむ
で、少しコストをかけて予約注文に対応したら「予約注文カテゴリに置かれて目立つんだろう！」と期待してましたが、そんなものは現時点では存在しない様子。プロモーション力のある企業だけが美味しい機能なのかもしれない。

[予約注文できるアプリを探す方法](https://apptopi.jp/2018/02/18/appstore-app-preregist/#i-5)

# というわけで、予約注文無効になってもまあよしとしてバグ修正版を審査に出した
手動リリースを選択し、審査提出。審査通過後「このバージョンを予約注文としてリリースする」というボタンが現れ、予約注文受付中もバグ修正等ができました。
現場の朝会にパワプロアイコンを導入してみた話

現場のチームに急遽メンバーが増加して全員の状況を把握することが難しくなったために工夫してみたことです。

## やったこと
現場の朝会で使用しているConfulenceのページの各個人の欄にパワプロで使われている調子を表すアイコンを導入してメンバーに日々の状態をアイコンで表してみてくださいとお願いしてみました。
↓こんな感じのやつ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/207298/465b49b2-4d5d-2ad2-c21b-cccd9e55b8e2.png)

↓こんな感じで各メンバーの欄に記載してもらいました
![image.png](https://qiita-image-store.s3.amazonaws.com/0/207298/55f28393-75c8-389f-c858-dc9909d2b25e.png)



## 得られたこと
- 現状割り振っているタスク状況（やばいのかやばくないのか）が見えるようになった
- メンバーの日々の体調が分かるようになった
- メンバーの精神状態が分かるようになった
- 報告がいつもより楽しくなった（←意外と大事）

## 具体的にどんな効果があったのか
### タスクの見える化、報告粒度の平準化
メンバーのタスク状況が見える化しただけでなく、報告が不得手なメンバーも同じ粒度で状況を把握できるようになりました。
やはり、口頭での報告だけであると人によって報告粒度に差が出てきてしまいます。
とはいえ、細かく毎日報告内容を記載してもらうのも本人に負担になってしまうので、パッと見てわかるこの方法は最小の労力で大きな効果を得ることができました。

### 体調の見える化、遅延リスクの察知
体調はプロジェクトでマネジメントする上であまり管理されていないところですが、実は結構進捗に影響の出る要素（リスク）だと考えてます。
体調が悪いと生産性は当然落ちるので、期限ぎりぎりのタスクを割り当てている場合など、遅延のリスクが出てきます。
ですが、なかなか「体調が悪いです」とは報告しにくい部分もあるので、アイコンを利用して表現することでそこの敷居を低くすることができました。
（もともとパワプロアイコンは調子を表すものですしね）

### 精神状態の見える化、離脱リスクの察知
精神状態も生産性に大きく影響を与える要因となります。なので、こちらを見える化したことでメンバーの精神状態を把握することができるようになりました。
精神状態がいまいちなメンバーはメンタル的なフォローが必要になります。
もしかしたら今のタスクが嫌でモチベーションが上がらないのかもとか、メンバー離脱のリスクを事前に察知できる可能性もあります。

### 報告が楽しくなった
パワプロアイコンという一見仕事と関係なさそうな遊び感覚のものを採用したことでアイスブレイクのような効果を得られました。

## なんでパワプロなの？
分かりやすかったので(笑)
正直表現できればなんでもよいと思います！！

## 参考
カイゼンジャーニー（ https://www.shoeisha.co.jp/book/detail/9784798153346 ） に出てくるファイブフィンガーにヒントを得ました！（ググってもファイブフィンガーについて出てこなかったですが）
ファイブフィンガーとはカイゼンジャーニーの中で朝会で五本指で今の状態を表現するというマネジメント手法のことです。
今回のパワプロアイコンはそれを自分なりにアレンジして導入してみたものとなります。
CentOSにPostgreSQL コード2

```sql
postgres=# create view clubgroup(name,age,address,flag,id,clubname)
as
select * from grouplist as g left outer join clublist as c on g.flag=c.id ;
```

```sql
postgres=# select
postgres-# sum(case when(age between 20 and 29) and (clubname='tennis') then 1 else 0 end)as hoge1,
postgres-# sum(case when(age between 30 and 39) and (clubname='music') then 1 else 0 end)as hoge2,
postgres-# sum(case when(age between 40 and 49) and (clubname='baseball') then 1 else 0 end)as hoge3
postgres-# from clubgroup ;


 hoge1 | hoge2 | hoge3
-------+-------+-------
     8 |     7 |     1
```

```sql
select * from flaglist1 as f
left outer join clublist as c
on f.flag = c.id ;


```
mysql-connector-java-8.0.11 の XADataSourceクラスの所在

【MySQL8.0リリース記念】

MySQL server 8.0.11のリリースと同時に、Connector/J のバージョンもアップ。
新しいバージョンのConnector/J を使ってWildflyからアクセスしようと試みたらxa-datasourceクラスの名前が変更されていたのでメモ。

######xa-datasourceクラスパスの確認
```
# jar tf mysql-connector-java-8.0.11.jar |grep XA
com/mysql/cj/jdbc/MysqlXAConnection.class
com/mysql/cj/jdbc/MysqlXADataSource.class
com/mysql/cj/jdbc/MysqlXAException.class
com/mysql/cj/jdbc/SuspendableXAConnection.class
com/mysql/cj/protocol/x/XAsyncSocketConnection.class
com/mysql/cj/protocol/x/XAuthenticationProvider$1.class
com/mysql/cj/protocol/x/XAuthenticationProvider.class
```

**"com/mysql/cj/jdbc/MysqlXADataSource.class"が該当**

######ドライバファイルをコピー
1. *Wildfly_home*/modules/system/layers/base/com/mysql/main/ ディレクトリを作成
2. 配下に mysql-connector-java-8.0.11.jar をコピー
3. 配下に module.xmlを作成

``` module.xml
 <?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.5" name="com.mysql">
    <resources>
        <resource-root path="mysql-connector-java-8.0.11.jar"/>
    </resources>
    <dependencies>
        <module name="javax.api"/>
        <module name="javax.transaction.api"/>
        <module name="javax.servlet.api" optional="true"/>
    </dependencies>
</module>
```

######ドライバを登録
standalone.xmlのdatasourcesセクション内の*drivers*セクションにドライバを追加
**上記で調べたクラスパスをxa-datasoure-classとして記載する**

```standalone.xml
  <drivers>
    <driver name="mysql" module="com.mysql">
      <xa-datasource-class>com.mysql.cj.jdbc.MysqlXADataSource</xa-datasource-class>
    </driver>
  </drivers>
```

うまく登録されていれば、Wildflyの起動時のログに下記のように表示される。

```server.log
... INFO  [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-1) WFLYJCA0018: Started Driver service with driver-name = mysql
```
PowerShellでNTFSアクセス許可を設定する

## Script

ローカルユーザーlocalUserにE:/ShareフォルダのNTFSアクセス許可(編集)を与える.

``` powershell
$folder = “E:¥Share”
$hostname = [System.Environment]::MachineName
$user= "user"
$aclParams = @("$hostname\$user",
    [System.Security.AccessControl.FileSystemRights]::Modify,
    [System.Security.AccessControl.InheritanceFlags]::None,
    [System.Security.AccessControl.PropagationFlags]::None,
    [System.Security.AccessControl.AccessControlType]::Allow)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule  $aclParams
$acl = Get-Acl $folder
$acl.AddAccessRule($rule)
Set-Acl $folder -AclObject $acl
```


## 補足

### NTFSって？

Windows NT系のファイルシステムらしい.


## 参考

http://yomon.hatenablog.com/entry/2015/04/10/170518
https://www.blackcat.xyz/article.php/ProgFAQ-PS_Set-Acl
http://tech.lecume.net/power-shell/configure-filesystem-acl
Node.jsでGmailからメールをOAuth認証で送信する方法

LINE BOT(Node.jsで実装)で手軽に会社に勤怠連絡メールを送りたくて、OAuth認証でGmailからメールを送ろうと思いました。パスワード認証だと2段階認証にしてるとダメらしくて、これのために2段階認証を解除するのもナンセンスだと思ったので、nodemailer(Node.jsのメール送信のためのモジュール)を使ってOAuth認証でメールを送ろうと思ったのですが、ハマった点があったので共有です。

# Node.jsでGmailからメールをOAuth認証で送信する流れ
1. Google Developers ConsoleでOAuth認証のための情報(トークン等)を取得
2. nodemailerで、1で取得した情報を使ってメールを送信

基本的には[node.js 上の nodemailer で OAuth 2.0 を使って gmail からメールを送る](https://gist.github.com/neguse11/bc09d86e7acbd6442cd4)がとてもわかりやすくて、書かれていることを順番にやっていけば大丈夫です。しかし、リンク先ではxoauth2というモジュールを使っているのですが、メール送信を試みても認証エラーが怒られてしまいます。トークン等が間違ってるんじゃないかと思って何回も確認しましたがそんなことはなかったので、しばらくハマりました。

# 解決策
xoauth2を使うのをやめて、authに直接指定する。
具体的には以下のようにコードを修正する。

```javascript
  var nodemailer = require('nodemailer')

  // メッセージ
  var message = {
  	from    : '送信元',   
    to      : '送信先',
    subject : 'タイトル',
    text    : '本文'
  };
  
  // 認証情報
  var auth = {
  	type         : 'OAuth2',
    user         : 'ユーザ名@gmail.com',
    clientId     : 'クライアントID',
    clientSecret : 'クライアントシークレット',
    refreshToken : 'リフレッシュトークン'
  };
  
  // トランスポート
  var transport = {
    service : 'gmail',
    auth    : auth
  };
  
  var transporter = nodemailer.createTransport(transport);

  transporter.sendMail(message, function(err, response) {
    console.log(err || response);
  });
```

# 原因
わからん＼(^o^)／
nodemailerの仕様変わった？
Dialogflow v2のuserStorageの使い方

Dialogflowがv2になってuserStorageの保存方法も変わりました。
userStorageはアクションを終了しても永続的にデータが残るものです。
別途データベースを用意しなくても簡易的なデータの保存にはうってつけです。

※100日間何も更新無ければ消えるらしいです。後、ユーザーがアプリをリセットすると消えます。

Inline Editorにあるindex.jsを編集します。

# 保存方法
まずは、保存の仕方です。`conv.user`の中にある`storage`を使います。
convはDialogflowConversationのことです。storageの後の`memo`とかは自由に決めることができます。


```javascript:保存方法
function save(agent) {
  // Dialogflowから来るパラメータを取得
  const memo = agent.parameters.memo;

  // DialogflowConversationを取得
  const conv = agent.conv();

  // userのstorageに保存する
  conv.user.storage.memo = memo;

  conv.ask('メモを保存しました');
  
  agent.add(conv);
}

// ここはIntent名
let intentMap = new Map();
intentMap.set('SaveIntent', save);

agent.handleRequest(intentMap);
```

# 読み込み方法
次は、保存した値を取得する方法です。`conv.user.storage`にある値を単純に取得すればOKです。

```javascript:読み込み方法

function load(agent) {
  // DialogflowConversationを取得 
  const conv = agent.conv();

  // storageにあるmemoを取得
  const memo = conv.user.storage.memo;
        
  if (memo === undefined) {
    conv.ask('メモがありません');

  } else {
    conv.ask('メモが見つかりました。「'+ memo + '」です');    

  }
  agent.add(conv);

}

// ここはIntent名
let intentMap = new Map();
intentMap.set('LoadIntent', load);

agent.handleRequest(intentMap);

```

# 動作例
WelcomeIntentでメモをセーブするかロードするかを案内して、
StartIntentでメモを`セーブ` or `ロード`の設定を切り替えています。

![スクリーンショット 2018-04-24 9.25.34.png](https://qiita-image-store.s3.amazonaws.com/0/154355/324c6885-fa26-c822-0b59-4ef95125bedf.png)

# まとめ
手軽にデータを永続的に保存することができました。
占いアプリでユーザーの星座情報を保存したり、天気アプリで住んでいる地域を保存する等
様々な用途で使えます。是非！お試しあれ！
別ウィンドウで開く設定のリンクテキストの後ろに「矢印」アイコンを表示させて、WordPress内の記事をリッチにする時のお作法

その「矢印」アイコンはこちら。

* [external-link-alt - Font Awesome](https://fontawesome.com/icons/external-link-alt?style=solid)

# スタイルシート

```css:style.css
// 「矢印」アイコン
.content a[target="_blank"]:after {
    margin: 0 3px;
    font-family: FontAwesome;
    vertical-align: middle;
    content: '\f08e';
    display: inline-block;
    text-decoration: none;
}

// 記事内の画像リンク
.content a[href$=".png"]:after, .content a[href$=".jpg"]:after, .content a[href$=".jpeg"]:after {
  margin: auto;
  content: '';
}

// カエレバの商品リンク
.content .kaerebalink-box a[target="_blank"]:after {
  margin: auto;
  content: '';
}
```

記事内の画像リンクと、WordPressにはお馴染みの「カエレバ」の商品リンクへのスタイルの適用を無効にしています。記事内の画像リンクは画像の種類（拡張子）に応じて増やしてください。

# 参考
* https://developer.mozilla.org/ja/docs/Web/CSS/Attribute_selectors
cordova-plugin-file サンプルコード

# cordova-plugin-file
https://github.com/apache/cordova-plugin-file/blob/master/doc/ja/index.md

cordova-plugin-fileプラグインのサンプルコードを記載します。

## カウント
Documents配下のファイル数をログ出しします。

```
window.requestFileSystem(
  LocalFileSystem.PERSISTENT,
  0,
  (fileSystem) => {
      let directoryEntry = fileSystem.root;
      var directoryReader = directoryEntry.createReader();
      directoryReader.readEntries((fileEntries) => {
      console.log('fileEntries.length', fileEntries,  fileEntries.length);
      });
  }
);
```

## コピー
Documents配下のcopyIndex番目にあるファイルを、1000個複製します。

```
window.requestFileSystem(
  LocalFileSystem.PERSISTENT,
  0,
  (fileSystem) => {
    let directoryEntry = fileSystem.root;
    var directoryReader = directoryEntry.createReader();
    directoryReader.readEntries((fileEntries) => {
      const copyIndex = 1;
      const copyLength = 1000;
      for (var index = 0; index < copyLength; index++) {
        console.log('index', index);

        // ファイルを新しいディレクトリにコピーし、名前付け替えます
        fileEntries[copyIndex].copyTo(fileSystem.root, `${fileEntries[copyIndex].name}_${index}.png`, (sucsses) => {
      // console.log('sucsses', sucsses);
    }, (error) => {
      // console.log('error', error);
    } );
      }
    });
  }
);
```

## 削除
Documents配下のファイルを全て削除します。
ディレクトリは削除しません。

```
window.requestFileSystem(
  LocalFileSystem.PERSISTENT,
  0,
  (fileSystem) => {
      const directoryEntry = fileSystem.root;
      const directoryReader = directoryEntry.createReader();
      directoryReader.readEntries((fileEntries) => {
          for (let index = 0; index < fileEntries.length; index++) {
              const fileEntry = fileEntries[index];
              if (fileEntry.name.match(/IMG_/)) {
                  fileEntry.remove(
                    (aaa) => {
                        console.log('成功', aaa);
                    },
                    (bbb) => {
                        console.log('失敗', bbb);
                    }
                  );
              }
              console.log(fileEntries[index].name)
          }
      });
      console.log('directoryEntry', directoryEntry); },
  (onFileSystemFail) => {
      console.log('onFileSystemFail', onFileSystemFail)
  }
);
```

## 削除(ログなし)
Documents配下のファイルを全て削除します。
ディレクトリは削除しません。
ログを出さず、削除にかかった時間を計測するのに使いました。

```
console.time('timer1');
window.requestFileSystem(
  LocalFileSystem.PERSISTENT,
  0,
  (fileSystem) => {
      const directoryEntry = fileSystem.root;
      const directoryReader = directoryEntry.createReader();
      directoryReader.readEntries((fileEntries) => {
          for (let index = 0; index < fileEntries.length; index++) {
              const fileEntry = fileEntries[index];
              if (fileEntry.name.match(/IMG_/)) {
                  fileEntry.remove();
              }
          }
          console.timeEnd('timer1');
      });
    }
);
```
LinqのあれをRustのイテレータでやってみた

#参考
[C#のLinqでGroupByを使っているのならPythonの方が2倍速くなる - Qiita](https://qiita.com/yniji/items/6585011633289a257888)
[C# の Linq が python の２倍遅い、は嘘 - Qiita](https://qiita.com/Akira_Kido_N/items/d9519b05ccee6a67158f)

#コード

```rust
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;

extern crate csv;
extern crate itertools;
extern crate serde;

use std::fs::File;
//use std::io::prelude::*;
use itertools::Itertools;
use serde::Serializer;

fn main() {
    #[derive(Debug, Deserialize)]
    struct Record(String, String, f64, f64);

    let mut rdr = csv::Reader::from_reader(File::open("test.csv").expect("File open err."));
    let multiply_to_int = |x: f64, y: f64| if x > 0.0 {
        (x * y + 0.0000001) as i32
    } else {
        (x * y - 0.0000001) as i32
    };
    let mut ser = serde_json::Serializer::new(File::create("result.json").expect("File open err."));
    ser.collect_seq(rdr.deserialize()
            .map(|result| result.expect("Bad CSV"))
            .map(|record: Record| (record.0.to_owned(), multiply_to_int(record.2, record.3)))
            .into_group_map()
            .into_iter()
            .map(|(k, v)| json!({"a": k, "z": v.iter().sum::<i32>()})))
        .expect("Serialize err.");
}
```

#実行時間
##Python ([元記事](https://qiita.com/yniji/items/6585011633289a257888)のを使用)
$ python app.py 
所要時間:0.4632906913757324[sec]
$ python app.py 
所要時間:0.44978904724121094[sec]
$ python app.py 
所要時間:0.4565582275390625[sec]

##Rust
$ time ./target/release/foo

real    0m0.339s
user    0m0.331s
sys     0m0.007s
$ time ./target/release/foo

real    0m0.340s
user    0m0.330s
sys     0m0.010s
$ time ./target/release/foo

real    0m0.338s
user    0m0.328s
sys     0m0.010s

#感想
- 速くなるのは分かっててやったので、速度については、こんなもんか程度の感想。
- イテレータ使い倒したらLinqとそんなに遜色ないコーディング量で書けて、別にそれで遅くなるわけでもないのはRust尊いなーって印象。
- コンパイル時のライフタイム地獄にはあんまり陥らなかった。型が主に`i32`と`f64`だったのと`String`は`to_owned()`で逃げたためと思われる。
- それでもやっぱり、型を合わせるのがしんどかった。
- serde_json、地味に便利。
- `Record`型の`String`を`&str`にしてコピーを避ける方法、探せばある気がするんだけど、分からなかった。
- itertoolsに`group_by`というそれっぽい関数があるけど、[ドキュメント](https://docs.rs/itertools/*/itertools/trait.Itertools.html#method.group_by)読んだ感じ、SQLの`GROUP BY`やlinqの`GroupBy`とは挙動違いそう。これ、罠だろ。

```rust:ドキュメント中のサンプルコード
// group data into runs of larger than zero or not.
let data = vec![1, 3, -2, -2, 1, 0, 1, 2];
// groups:     |---->|------>|--------->|

// Note: The `&` is significant here, `GroupBy` is iterable
// only by reference. You can also call `.into_iter()` explicitly.
for (key, group) in &data.into_iter().group_by(|elt| *elt >= 0) {
    // Check that the sum of each group is +/- 4.
    assert_eq!(4, group.sum::<i32>().abs());
}
```