OmniAICreator/Qiita-1.07M huggingface dataset:
Flutter2.0のデスクトップを試してみた

この記事は Goodpatch Advent Calendar 2021 の11日目です。

こんにちは、Goodpatchの [ReDesigner](https://redesigner.jp/)サービスでバックエンドを担当している荒木です。

## はじめに

Flutterは以前AndroidでWebRTCアプリのプロトタイプ開発に使っていましたが、今年の3月に2.0がリリースされて気になっていたので今回軽く試してみました。

検証バージョン
Flutter 2.5.3
Dart 2.14.4

## Flutter 2.0について

2021年3月3日にリリース。

気になる変更ポイント

- Web対応のベータが外れた！
- デスクトップアプリがベータに追加された！！
- Null Safetyのサポート
- 新しいウィジェットの追加
- 複数インスタンスのサポート強化
- 非推奨APIの削除
- GooglePayが使えるようになった

## デスクトップアプリの所感

新しくサポートされたデスクトップアプリで、実際にmac用のアプリを作ってみます。

```言語:プロジェクト作成
flutter config --enable-macos-desktop

flutter create desktop_app

```

```言語:アプリ実行
cd desktop_app

flutter run
```
実行だとmacosとchromeの選択肢が出てくるので、オプションで「-d macos」を付けましょう。

![スクリーンショット 2021-12-10 15.00.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908790/76aec033-2886-1e3e-3df0-48facf49a9c4.png)

お馴染みの画面が表示されました。サンプルとはいえ、これだけで簡単にデスクトップアプリが起動するのは良いですね。
ビルドしても問題なく起動してました。

Electronの比較して考えてみると、現実的な仕事で使うならまだElectronを選択します。
まあベータなんで仕方ないんですけど、社内利用アプリくらいなら有りだと感じる安定感なので正式版になるのが楽しみです。

## オートコンプリート

以前はオートコンプリートの実装にライブラリを入れたりして手間がかかっていたのですが、ずいぶん楽になっていたのでそちらも試しておきます。

```言語:サンプルにWidgetを追加
            Autocomplete<String>(
              optionsBuilder: (TextEditingValue textEditingValue) {
                if (textEditingValue.text == '') {
                  return const Iterable<String>.empty();
                }
                return _kOptions.where((String option) {
                  return option.contains(textEditingValue.text.toLowerCase());
                });
              },
              onSelected: (String selection) {
                debugPrint('You just selected $selection');
              },
            ),
```

![スクリーンショット 2021-12-11 22.16.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908790/95cf9804-879b-d7c6-7ec3-aba8cbc9c91a.png)

固定で入れるだけならリストの準備とWidgetの追加だけで動作します。

一応、日本語でもチェック

- ひらがな
![スクリーンショット 2021-12-10 17.05.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908790/dd7d4495-0d24-9e32-c663-2fadf570dd65.png)

- カタカナ
![スクリーンショット 2021-12-10 17.05.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908790/3537aa49-ba57-9958-2035-5a9d9c35cbf8.png)


## まとめ

ひさしぶりにFlutterでコードを書きましたが環境を含めてスタートが楽だとあらためて感じました。
実際に運用で使うデスクトップアプリでも作ってみようと思うので、その投稿はまた別の機会に。

## 参考サイト

https://medium.com/flutter/whats-new-in-flutter-2-0-fe8e95ecc65


https://api.flutter.dev/flutter/material/Autocomplete-class.html
Azure FunctionsでLINE Bot作成 -アレンジ編vol.1-

# はじめに
[Azure FunctionsでLINE Bot作成](https://qiita.com/RyogaTakao/items/a86522d560178f83652c)の記事にてAzure Functionsを用いたLINEのオウム返しLINEBotの作成方法を説明している。
今回はただのオウム返しではなく、語尾に絵文字を付けて返すLINEBotの作成方法を記載する。

# 前提

- LINEアカウントを持っていること
    - 通常のLINEを利用できるもの
    - もしLINEを使っていない場合は、アカウントの作成が必要
- Azureアカウントを持っていること
    - もしアカウントを持っていない場合は、[こちら](https://azure.microsoft.com/ja-jp/free/search/?&ef_id=EAIaIQobChMIkviS3O3m8gIVUltgCh2S0QKUEAAYASAAEgIIgPD_BwE:G:s&OCID=AID2200208_SEM_EAIaIQobChMIkviS3O3m8gIVUltgCh2S0QKUEAAYASAAEgIIgPD_BwE:G:s&gclid=EAIaIQobChMIkviS3O3m8gIVUltgCh2S0QKUEAAYASAAEgIIgPD_BwE)からアカウント登録
- [Azure FunctionsでLINE Bot作成](https://qiita.com/RyogaTakao/items/a86522d560178f83652c)の記事にてオウム返しLINEBotを作成していること

# 手順

Azure Functionsのコードを下記のものに書き換え、LINE Messaging API channelの作成で発行した「チャンネルシークレット」と「チャンネルアクセストークン」を<YOUR_TOKEN>と<YOUR_SECRET>に入力します。

```index.js
const line = require('@line/bot-sdk');

const config = {
    channelAccessToken: '<YOUR_TOKEN>',
    channelSecret:  '<YOUR_SECRET>',
};

const client = new line.Client(config);

module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');

    if (req.query.message || (req.body && req.body.events)) {
        if (req.body && req.body.events[0]) {
            message = {
                type: "text",
                text: req.body.events[0].message.text + "(๑>◡<๑)"
            }
            console.log(message);
            if (req.body.events[0].replyToken) {
                client.replyMessage(req.body.events[0].replyToken, message);
            }
        }
        else {
            context.res = {
                status: 200,
                body: req.query.message
            };
        }
    }
    else {
        context.res = {
            status: 200,
            body: "Please check the query string in the request body"
        };
    };
};
```

置き換えたら、「保存」ボタンをクリックする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/1034a01e-409c-6562-18b5-d09fa717a45e.png)

# 動作確認

作成したLINEアカウントにメッセージを送信してみる。
すると「<送信したメッセージ>+(๑>◡<๑)」が返ってくることが確認できる。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/a37c4ed5-0b91-b365-f10c-130ef10091d7.jpeg)

# さいごに

今回同様、返すmessageの中を編集することで返信メッセージを変えることができる。
そのため、今回のような簡単な修正ではなく、自然言語処理を導入すれば、オウム返しではないチャットボットができる。
Twitter Webで新規ツイートを表示したときに特定ユーザーのツイートがあればそれをいいねする

## きっかけ
https://twitter.com/canary_kurifuzi/status/1469622795051368450

## コード
2021/12/11時点[^1]では、下のコードを`devtools`で入れて [@sytkm](https://twitter.com/sytkm)をフォローすれば、タイムラインに [@sytkm](https://twitter.com/sytkm)のツイートが出てきたときに自動でいいねされます。

[^1]: TwitterはよくUIが変わっているイメージがあるので。

5行目の`"sytkm"`ってところを任意の`screen_name`に変えればその人になるのでお試しあれ。

```javascript
const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
        if(mutation.addedNodes.length>0){
            const target = mutation.addedNodes[0];
             if(target.querySelector('[tabindex="-1"]').href.replace(/^.*\//g, "")=="sytkm"){
                target.querySelector('[data-testid="like"]').click();
                console.log("like!");
             };
        }
    });
});

const element = document.querySelector('[aria-label="タイムライン: ホームタイムライン"]').firstElementChild;

const config = {
    childList:true
};

observer.observe(element, config);
```

## 解説
DOMの変更を監視できる`MutationOvserver`を使いました。
`config`で`childList:true`とすることで新しく追加されるDOMを確認し、`mutation.addedNodes[0]`でその新規追加DOMを指定。
`sytkm`のツイートならいいねボタンのDOMを`click()`しいいねするように。

## 思ったこと
Twitter WebはReactを使っているので該当のDOMを選択するのが大変でした。
ユーザーの判定は`tabindex="-1"`となっているDOMの`href`が運良くツイートユーザーのURLだったのでそこで判定しました。
ちょっと構成変わったら使えなくなるのと現時点でも読み込みが遅いとエラーが出るのが微妙かも。
とりあえず使えるので投稿。
サブドメインをvpsサーバーで使う

①さくらサーバーのサブドメイン作って、
②さくらのVPSでそのサブドメイン使って、
③ssl付けたかった。

ーーーーーーーーーーーーーーーーーーーーーーーー


①まずさくらのドメインコントロールパネルに入って、
ゾーンのところで編集ボタンを押し、
レコードを追加する。

```:知ってる限りの説明
・エントリ名
ここにサブドメインの付けたい名前を書く。
example.hoge.comを作りたかったら、exampleと入れる。

・種別
IPアドレス(A)・・・
つなぎたいサーバのIPアドレスを入れる。

別名(CNAME)・・・
IPアドレス以外も入れられる。

メール交換ホスト(MX)・・・
メールサーバを入れる。

ネームサーバ(NS)・・・
使ったことないからわからない。
他社のネームサーバーを使うとか。

IPv6アドレス(AAAA)・・・
使ったことないからわからない。
IPv6アドレスが使えるのでしょう

テキスト(TXT)・・・
ここはメールのSPFレコードの設定に使ったことあったなあ。
```

今回の場合は
エントリ名にexampleと入れて、
種別はCNAMEにして値にvpsサーバーのipアドレス入れる。

これでexample.hoge.comはvpsサーバーに飛ぶ、はず。


 


②次にvpsサーバーの方で、サブドメイン用のページを作る。
あとapacheの設定ファイルもちょっと追加して、（/etc/httpd/のあたり）

```:適切なところのconfファイル
<VirtualHost *:80>
  ServerName example.hoge.com
  DocumentRoot /var/www/[サブドメイン用のページ]
</VirtualHost>
```
そんでサーバーを再起動して（systemctl restart httpd）、
とりあえずhttp://example.hoge.comを表示させる。



③無料のSSL、Let's Encryptを入れる。

```:vpsサーバーにsshで入って、
#mod_ssl インストール
$ yum install mod_ssl
#httpsをファイアウォールで許可
firewall-cmd --add-service=https --zone=public --permanent
#ここで一回サーバー再起動して
#SSLを入れる
yum install certbot python2-certbot-apache
#証明書を入れる
certbot --apache -d example.hoge.com
```

ここから色々質問に答えていくはずが、これで終わってしまった。
あれーと思ってapache見に行ったら勝手にSSLのconfファイルが作られてた。
びっくり。
サーバーを再起動したらsslができてた！

あとは最初に書いた、適切なとことのconfファイルにsslのリダイレクト書いたらOK。


ただ、Let's Encryptは３ヶ月ごとに更新しないといけないみたいなので、それをcronに書いておく。
場所は/var/spool/cron/

```
0 3 *  *  * root /usr/bin/certbot renew
```


ーーーーーーーーーーーーーーーーーーーーーー
参考

https://knowledge.sakura.ad.jp/10534/
【React】デバッグするためのTips

デバッグをうまくできるかどうかで開発速度が大きく変わります。
ReactでデバッグするためのTipsをまとめました。

## console出力


#### jsx内にconsoleを仕込む
`console.log()`はvoidを返します。
OR演算子でつないであげればJSX内にconsoleを仕込むことができます。

``` tsx
const Component = (
  <>
    {console.log("hoge") || (<Hoge />)}
  </>
);
```

#### いろんなconsoleを使う
`console.log`以外にも便利なコンソール出力があります。

例えば、`console.table`は配列をオブジェクトをテーブル形式で見やすくしてくれます。

``` js
console.table({ a: ["A1", "A2"], b: ["B1", "B2"] });
```
![スクリーンショット 2021-12-11 132749.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1063605/b504d0ad-4e28-34ef-50a4-fbcffa0ffcc2.png)

他にも色々あるので使ってみてください。
参考↓
https://developer.mozilla.org/ja/docs/Web/API/console
https://qiita.com/kashira2339/items/874f95aaaa59f4a17d3d

#### Errorを使って出力する
`Error`を使ってconsole出力すると、どの関数から呼ばれたログなのかが分かります。

``` js
function hoge() {
  console.log(
    new Error("test")
  )
}

function main(){
  hoge()
}

main()
```

```console
Error: test
    at hoge (https://nc8tc.csb.app/src/index.js:4:15)

    at main (https://nc8tc.csb.app/src/index.js:8:3)

    at $csb$eval (https://nc8tc.csb.app/src/index.js:11:1)

    at H (https://codesandbox.io/static/js/sandbox.8f9f4000c.js:1:99995)

    ...
```
エラーコードの上部を確認するとhogeとmainが呼ばれたことが分かります。

#### 

## react-dev-tools
react-dev-toolsはreactのためのデバックツールです。
Reactのコンポーネントのためのインスペクタが使えたり、レンダリングをプロファイルしてコンポーネント毎のレンダリング時間を表示できたりします。

インスペクタ機能↓
![スクリーンショット 2021-12-08 165249.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1063605/540996c8-34aa-72fa-e8f3-265b9e8abb7f.png)

プロファイル機能↓
![スクリーンショット 2021-12-08 165511.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1063605/14f05ec4-c3ea-e6af-5b4f-7a1e45cacf1c.png)


chromeの拡張機能が用意されています。
リンクからダウンロードするだけで使えるようになります。
https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=ja

## redux-dev-tools
redux-dev-toolsはredux内にどのような値が入っているのかを簡単に確認できるツールです。

使用するにはcreateStoreの第二引数を設定する必要があります。

```jsx
  const store = createStore(
     reducer,
     window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
  );
```

![スクリーンショット 2021-12-11 134856.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1063605/2347d9aa-5484-013a-d028-f72ff8d874cc.png)

react-dev-toolsと同様、chromeの拡張機能が用意されています。
https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=ja

## why-did-you-render
https://github.com/welldone-software/why-did-you-render

`why-did-you-render`は無駄なレンダリングがあれば、console出力で教えてくれるライブラリです。

こちらのsandboxが分かりやすかったので触ってみてください。
https://codesandbox.io/s/pyi14
SORACOMの製品とサービスを使って、IoTシステムを構築してみた。

## はじめに
この記事は[TechCommit アドベントカレンダー2021](https://qiita.com/advent-calendar/2021/tech-commit)の投稿です。 

当時ネットワークやDBの知識を全くない、自分でも(専門は電気回路とC/C++などの組み込みエンジニア)
SORACOM製品・サービスを使い、簡単にIoTモニタリングシステムを作成しました。

## 目次
* 作品の概要
* SORACOMとは
* 準備するもの
* 実際の作品
* 参考資料
* 今後の課題
* あとがき

## 作品の概要
リモートワーカーのための室内環境⁺姿勢モニタリングシステムです。
ラズパイと3G回線ドングルを中心とした構成で、
温湿度・大気圧センサで室内環境の状況をセンシングし、
デスクに置かれた超音波距離センサを使いリモートワーカーの姿勢をモニタリングします。

### 主な機能
* ラズパイと3G/LTE回線のUSBモデム
* 温度・湿度・気圧センサで環境を見れる
* 超音波センサで人の位置を測定し長時間同じ姿勢を検知する
* SORACOM Harvest/SORACOM Lagoonにより、Webブラウザ上で簡単に確認できる

### システム構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432868/fa00d13f-5076-4d48-11ed-7ea992a44858.png)
温湿度・距離センサからの取得値をRaspberryPiで加工し、セルラー通信を使いデータをクラウドへ送信します。([SORACOM Air](https://soracom.jp/services/air/))
次に、[SORACOM Harvest](https://soracom.jp/services/harvest/)が受信データを収集・蓄積します。
SORACOM Harvest自身でデータを見ることは可能ですが、[SORACOM Lagoon](https://soracom.jp/services/lagoon/)でデータを見やすくするためにダッシュボードの作成します。
SORACOM Lagoonにより、Webブラウザ上でURLを公開すれば開発者以外の方にも閲覧が簡単になります。



## [SORACOM](https://soracom.jp/)とは?
「IoTテクノロジーの民主化」をモットーに掲げ、IoTプラットフォーム(デバイス・サービス・インフラ・etc)を提供する会社です。

自分の推し企業でもありますw(企業に対して「推し」という言葉を使っていいのかわかりませんが･･･)
モットーにもあるように、IoT技術の浸透のためにサポートも大変豊富です！エンジニアとしての自分も大変助かっております！！
例えば･･･
* [IoTレシピ(記事・動画)](https://soracom.jp/iot-recipes/)
* SORACOM製品のユーザーグループ主催の勉強会・イベント(SORACOM社員も参加されてたりします！)
* テックカンファレンス
* イベント(夏休みの自由研究:製品貸し出し、コンテストの主催や協賛)

## 準備するもの
* RaspberryPi4 Model B
    * RaspberryPiOS
* [3G USBドングル AK-020 (SORACOM スターターキット)](https://soracom.jp/store/5228/)
* センサ
    *  温湿度・大気圧センサ(BME280)
    *  超音波センサ （HC-SR04)

## ソースコード
ソースコードは全てPythonで書いています。
全てフルスクラッチで書いているわけではなく、SORACOM IoTレシピ等を参考にして手を加えております。

https://github.com/Yuki2Kisaragi/RoomMonitor

## 実際の作品

### 作品物の写真
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432868/959e1e9c-a811-2d51-5f66-f8679cd52f7e.png)

### Webブラウザ上のグラフ(SORACOM Harvest)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432868/b7e9f6d9-6571-1691-87b0-bf40c9711710.png)

### ダッシュボード(SORACOM Lagoon)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432868/e22a0f7d-4011-d899-85bc-8fcb46bd651f.png)

### 実際に動かしてみた動画
リアルタイムでダッシュボード内の値が変化することが分かるかと思います。
(初の撮影＆YouTube投稿なので、かなり見にくいのはご容赦を…)

https://www.youtube.com/watch?v=gfu7rI1_teY

## 今後の課題
* ダッシュボードはまだまだ改良できる点が多く、SORACOM Lagoon自体も奥が深いのでもっと弄って遊んでみたい
* SORACOM Lagoon機能である、データの異常値通知機能を導入していきたい

## 参考資料
* [公式ガイドブック SORACOM プラットフォーム](https://soracom.jp/store/5177/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432868/60ef0ba4-cc20-e889-4707-55b7f69b1084.png)

* [公式ワークブック SORACOM 実装ガイド](https://soracom.jp/store/5176/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432868/04a70ac3-4603-d03e-9da5-019c7d7a13e4.png)


## あとがき
実際にSORACOMサービスを使い開発することで、IoT製品開発の障壁の低さに驚きました。(それだけSORACOMさんが使いやすくなるために頑張っていることが伺えます。)
ネットワーク・データ収集/蓄積を知らなかった、組み込みエンジニア初心者でも1週間で作れることができました。
ぜひ、他の方も試して頂きたいです。
PowerBI: 日付への変換

# 背景

https://qiita.com/shumaishuhei/questions/781b4c6a5b92fba2f428

質問があったので、分かりやすいようにしてみた。

# Power Query
元データ<br>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/651a44bd-b26a-c2de-a87f-2fb8f0571dba.png)

|対象|型|例|[TransformColumnTypesで変換](https://docs.microsoft.com/ja-jp/powerquery-m/table-transformcolumntypes)|補足|
|-|-|-|-|-|
|"yyyy/MM/dd"|Text|2019/01/01|〇|
|"yyyy-MM-dd"|Text|2019-01-01|〇|
|"yyyyMMdd"|Text|20190101|〇|
|yyyyMMdd|nubmer|20190101|×|↑ Textで変換出来るので、先に型変換すれば OK|
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/a3264db1-f808-7916-be8b-427723d0fabc.png)

# DAX
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/bd32f42e-fe10-f7c3-40c4-bdf0f2dc53bd.png)

|対象|型|例|[datevalueで変換](https://docs.microsoft.com/ja-jp/dax/datevalue-function-dax)|[Date で変換](https://docs.microsoft.com/ja-jp/dax/date-function-dax)|
|-|-|-|-|-|
|"yyyy/MM/dd"|Text|2019/01/01|〇|-|
|"yyyy-MM-dd"|Text|2019-01-01|〇|-|
|"yyyyMMdd"|Text|20190101|×|Year/Month/Day に分割して Date() で変換|
|yyyyMMdd|nubmer|20190101|×|Year/Month/Day に分割して Date() で変換|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/77f6aeaf-03ea-5cdd-9cb4-a607e6f7f54f.png)
分割が Text なら [Left](https://docs.microsoft.com/ja-jp/dax/left-function-dax)/[Mid](https://docs.microsoft.com/ja-jp/dax/mid-function-dax)/[Right](https://docs.microsoft.com/ja-jp/dax/right-function-dax) で、数字は計算で。
ラビットチャレンジレポート＿応用数学

**第１章：線形代数**

スカラーとベクトル
スカラー：普通の数
ベクトル：大きさに加え向きを持つ


固有値と固有ベクトル：
ある行列Aに対して，以下のような式が成り立つような，特殊なベクトル$\vec{x}$と，右辺の係数λがある。
この特殊なベクトル$\vec{x}$とその係数λを，行列Aに対する固有ベクトル，固有値という。
$$A\vec{x} = λ\vec{x}$$

行列を、固有値と固有ベクトルを使って分解することを固有値分解という。
分解することで行列の累乗計算が容易になる等の利点がある。



**第２章：確率・統計**

頻度関数とベイズ関数
確率は大きく分けて頻度確率（客観確率）とベイズ確率（主観確率）に分けられる。

条件付確率
ある事象Aがすでに起こっているとしたときに、事象Bが発生する確率
$$P(B|A)=P(B∩A)P(A)$$

AとBが独立事象であるならば
$$P(B∩A)=P(A)P(B)$$

確率変数Xの確率分布
変数Xの取りうる値x1,x2,...,xnに対して、それぞれ確率p1,p2,...,pnのとき、変数Xを確率変数という。また、XからPへの対応関係を、確率変数Xの確率分布という。
$$\sum_{n=1}^k x_ip_i$ $

確率変数が連続値をとる場合
$$∫X(x)p(x)dx$$

分散：データの散らばり具合
$$V(X)=E(X^2)−(E(X))^2$$

共分散：２つのデータ系列の傾向の違い　
$$Cov(f,g)=E(fg)−E(f)E(g)$$

標準偏差：
$$σ=\sqrt{V(X)}$$


ベイズの定理：
条件付き確率。ある事象X=Aが与えられたもとでY=Bとなる確率について、以下の定理が成り立つ。
$$P(B | A)=\dfrac{P(A | B)P(B)}{P(A)}$$

ベルヌーイ分布：
確率関数  $P(X=x）=P^x(1-p)^{1-x}$ 
で与えられ、その期待値は $P$、分散は $p(1-P)$  である

二項分布：
ベルヌーイ分布の多試行版






**第３章：情報理論**

自己情報量：
ある事象xの発生確率がP(x)であるときの情報量のこと。
事象xが起ることの情報量は次のように定義される。
$$-log_2P(x)$$

エントロピー（平均情報量）：
自己情報量の期待値。
離散確率変数Xにおいて、X＝xとなる確率がP(x)nのとき、確率変数Xのエントロピー は次のように定義される。
$$H(X)=-\sum_{x}  p(X）log_2P(x)$$

交差エントロピー：
２つの確率分布p(x),q(x)の交差エントロピーは次のように定義される。
$$H(p,q)=-\sum_{x}  p(X）log_2q(x)$$

KLダイバージェンス：
２つの確率分布p(x),q(x)に対して、次のように定義される量のこと。
$$D(p||q)=\sum_{x}  p(X）log_2(p(x)/q(x))$$
２つの確率分布p(x),q(x)が全く同じ分布のとき、最小値０をとる。



**この記事の参考図書**
「機械学習のエッセンス」 加藤公一
「入門線形代数」 三宅敏恒


~Fin~
Vue.jstとVuexに入門してまだ3日だけどコンポーネントの扱い方についてメモしておく

これは「[「はじめに」の Advent Calendar 2021](https://adventar.org/calendars/7037)」11日目の記事です。

※駄文ですが、自分の考えをまとめるためのメモです。

## Vue.jsとは
ユーザーインターフェイスを構築するためのプログレッシブフレームワーク(公式より抜粋)

https://jp.vuejs.org/

## Vuexとは
Vue.jsアプリケーションのための利用できる、状態管理パターン＋ライブラリ(公式より抜粋)

https://vuex.vuejs.org/ja/

## 状態管理
実はVue.jsだけでも状態管理はできます。

https://jp.vuejs.org/v2/guide/state-management.html#%E3%82%B7%E3%83%B3%E3%83%97%E3%83%AB%E3%81%AA%E7%8A%B6%E6%85%8B%E7%AE%A1%E7%90%86%E3%82%92%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E4%BD%9C%E3%82%8B

![state.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1546/9ea67a80-7f8f-9c84-bfcd-c11d49f7f6c3.png)

ただ、コンポーネントとの依存が強く、アプリケーションの規模が大きくなり、コンポーネントが増えてくると、このままでは難しくなります。

そこで、アプリケーション全体の状態とVueコンポーネント個別の状態を同期しつつしつつ、うまく分離する方法が必要になってきます。

![vuex.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1546/53307af8-ed05-ca5c-8936-907db41a2fe0.png)

VuexはVueコンポーネントから状態管理という責務を抽出し担っています。

## Vueコンポーネント

一言に状態と言っても、大きく分けて2種類ありそうです。

1. アプリケーションデータ
2. 画面の表示制御に使うデータ

また、Vueコンポーネントもいくつか種類がありそうです。

1. パーツとして再利用できるコンポーネント
    - リッチなセレクトボックスとか、カレンダー選択できるInputとか。
2. パーツが組み合わさリ、データに依存しない機能を提供するコンポーネント
    - フィルター機能やソート機能がある一覧表示とか
3. データに依存して、価値を提供することができる単位のコンポーネント
    - Vueだと `views` に配置するようなもの

コンポーネントの大きさとしては下に行くほど大きくなり、 3 → 2 → 1という依存関係になります。

[Atomic design](https://qiita.com/kahirokunn/items/f188b2362a4d3cdf0204)と照らし合わせると

1. Atoms
2. Molecules、Organisms
3. (Templates)、Pages

になりそうです。
(※Templatesは迷いがあります)

現時点(2021/12/11)の自分の判断だと、
- **Vuexは `アプリケーションデータ` だけを保持する***
- **Vuexを利用するのは、`Templates, Pages`に**
- **`Atoms、Molecules、Organisms` はpropsを利用し `画面の表示制御に使うデータ`として扱う**

とすると、アプリケーションデータと画面の表示制御に使うデータはどう区別するのか、ですが
- **`Vue.js` アプリケーションの外部から取得しVue.js外で保存する必要があるデータを`アプリケーションデータ`とする**

で良い気がしています。それ以外のデータはすべて表示制御用データとして扱うのが良さそうです。
単語帳アプリ（Oboeru）

# 使用技術
フロントエンド ： HTML, CSS, JavaScript
バックエンド : Node.js 
データベース : MySQL


# アプリ概要
単語帳アプリ。
単語帳を複数作成可能。
テスト機能付き。

# 開発期間
約1ヶ月

# デモ動画
<iframe width="560" height="315" src="https://www.youtube.com/embed/3ngoa1olYcU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# 今後
ログイン機能を実装し各人が使えるようにする
直感的に使えるようにUIを改善
モバイル対応
デプロイ

# GitHubリンク
https://github.com/issei0420/Oboeru
ros c++ python ファイルの読み込み

ros c++のプログラム内でファイルを読み込む方法を調べました.
以下サイトのプログラムでできました.

# c++

https://bi.biopapyrus.jp/cpp/syntax/file.html

```file_read.cpp
#include <fstream>
#include <iostream>
#include <string>

int main()
{
    std::ifstream ifs("./test.txt");

    int buf_size = 81;

    char str[buf_size];
    if (ifs.fail()) {
        std::cerr << "Failed to open file." << std::endl;
        return -1;
    }
    while (ifs.getline(str, buf_size)) {
        std::cout << str << std::endl;
    }
    return 0;
}
```

```CMakeLists.txt
cmake_minimum_required(VERSION 3.0.2)
project(linux_mac)

find_package(catkin REQUIRED)

catkin_package(
)

include_directories(
)

add_executable(file_read src/file_read.cpp)
target_link_libraries(
  file_read
)
```

# python2/3

```fread.py

import sys

f = open('test.txt', 'r')

data = f.read()

if sys.version_info.major != 2:
  data = data.decode('utf-8')

print(data)

f.close()
```


実行ディレクトリ内に```test.txt```を作成し実行するとファイル内の文字が出力されます.
フロントエンドでDIするときのインスタンス管理方法について調べてみた

この記事は[ラクスAdvent Calendar 2021](https://qiita.com/advent-calendar/2021/rakus) 12日目の記事です。

### はじめに

Vue.js のプロジェクトをリファクタリングする際、DIする機会がありました。
バックエンドだと SpringBoot でのDIは経験がありますが、フロントエンドでは初めてで、インスタンスのライフタイム、特にシングルトンのインスタンスはいつリセットされるのか（ページをリロードするまで？ブラウザキャッシュを捨てるまで？）、気になったので検証してみました。

正直やる前からなんとなく思っていたとおりの結果だったので溜め込んでいたのですが、アドベントカレンダーはいい機会なので供養します。

### 環境

DIコンテナライブラリには [TSyringe](https://github.com/microsoft/tsyringe) を利用しました。
主要なライブラリは以下のバージョンで検証しています。

* TSyringe: 4.6.0
* Vue.js: 2.6.14
* TypeScript: 4.1.5

### 検証

他のDIコンテナライブラリ、例えば SpringBoot では`singleton`・`prototype`・`request`・`session`のスコープを指定できますが、ここではもともとの興味の対象であるシングルトンに絞って検証します。
シングルトンでカウンタを生成し、カウントが引き継がれるかどうかで確認します。

#### 検証コード

検証に利用したコードを記載します。
詳しい説明は省略しますが、TSyringe では以下のようにシングルトンなインスタンスを取得します。

* クラスに`@singleton()`アノテーションをつける
* `container.resolve()`でDIコンテナよりインスタンスを取得

```typescript
import { singleton } from "tsyringe";

@singleton()
export class Counter {
  count: number;
  constructor() {
    this.count = 0;
  }

  countUp(): void {
    this.count++;
  }
}
```

```vuejs
<template>
  <div>
    <div>
      <div>count1: {{ instance1.count }}</div>
      <div>&nbsp;</div>
      <button @click="countUp1">countUp</button>
    </div>
    <div>
      <div>count2: {{ instance2.count }}</div>
      <div>&nbsp;</div>
      <button @click="countUp2">countUp</button>
    </div>
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import { container } from "tsyringe";
import { Counter } from "@/di/tsyringe";

export default Vue.extend({
  data() {
    return {
      instance1: container.resolve(Counter),
      instance2: container.resolve(Counter),
    };
  },
  methods: {
    countUp1() {
      this.instance1.countUp();
    },
    countUp2() {
      this.instance2.countUp();
    },
  },
});
</script>
```

#### 結果

検証コードによる動作で以下の内容が確認できました。

* instance1, instance2 のカウントが同じ（＝シングルトンになっている）
* instance1, instance2 ともに、ページリロードするとカウントがリセットされる

リロードでリセットされることから、おそらくオンメモリでインスタンスを管理しているのだろうと思って TSyringe のソースを読むと シンプルに Map で実装されていました。
https://github.com/microsoft/tsyringe/blob/master/src/registry-base.ts

#### 補足：バックエンドで検証

ちなみにバックエンドではどうなるのか、オンメモリでインスタンスを管理していることから結果は見えていますが、 Express でサーバーを立てて検証してみました。検証には以下のコードを使いました。

```typescript
import { container } from "tsyringe";
import { Counter } from "@/di/tsyringe";

router.get('/counts/tsyringe', (req: express.Request, res: express.Response, next: express.NextFunction) => {
    const counter = container.resolve(Counter);
    counter.countUp();
    res.json({"count": counter.count});
});
```

検証コードによる動作確認では、やはり想定通りの挙動になっていました。

* サーバ起動中はアクセスするたびにカウントが増える（＝シングルトンになっている）
* サーバ再起動するとカウントがリセットされる

### まとめ

TSyringe のDIコンテナはオンメモリなので、シングルトンのインスタンスは「フロントエンドだとページリロード」、「バックエンドだとサーバ再起動」でリセットされる。
また他のDIコンテナライブラリ（[injection-js](https://github.com/mgechev/injection-js)、[InversifyJS](https://github.com/inversify/InversifyJS)）もざっとソースを読んだ限りでは、TSyringe 同様オンメモリで管理しているようでした。
データサイエンティスト検定™ リテラシーレベルの合格体験記

## 概要

先日、「データサイエンティスト検定™ リテラシーレベル」に合格しました。

https://www.datascientist.or.jp/dskentei/

後の受験者の役に立てたらと思い、本記事では対策内容や助言を記載します。

## 筆者の前提

- これまでは雰囲気でやりくりしてきた
- 必要になったら勉強していたため体系的なリテラシーは怪しい

## 受験の動機

- リテラシーの底上げを望んだ
- 自分の発言に説得力を持たせたかった

## 対策内容

主な対策は以下4つです。

- 書籍を読み込む（問題は解く）

https://gihyo.jp/book/2021/978-4-297-12261-4

- 対策アプリをやりこむ

https://www.skillupai.com/ds-app/

- 出題範囲の確認

https://www.datascientist.or.jp/common/docs/PR_skillcheck_ver3.00.pdf

http://www.mi.u-tokyo.ac.jp/consortium/model_literacy.html

- テーマを絞って応用情報技術者試験の過去問も解く

「書籍を読み込む（問題は解く）」では少なくとも出てくる単語で知らないものはない状態にしました。「対策アプリをやりこむ」では、反射で解きまくって毎回満点になる状態にしました。「出題範囲の確認」は受験前日に見てみたのですが、上記の方法では網羅できてないポイントがあることに気がつきました。セルフチェックをして、わからないものは都度調べました。

実はそのころ応用情報技術者試験の勉強もしていました。かぶるテーマもあることと、過去問がなかったためどんな問題が出るかわからず、不安だったこともあり、このタイミングでやり込んでおきました。

## 感想と助言

結果は合格でした💯

受験当日はひととおりを見直せるくらいの時間を残してひととおりを解き、その後見直していくつか修正をしました。

CBT形式ということでその場で正答率が出ます（※合否は後日）。勝利を確信して、受験直後にちょっといいスーパーでちょっといい寿司を買いました🍣

対策について振り返りつつ助言を記載します。

書籍と対策アプリに関しては出題範囲のよく考えられた要約だったり、具体的に落とし込まれた問題だったりするので抑えておくべきです。わからない単語がないレベルにはしておくといいと思います。まずはこれらにより検定に対する土台が固まったと思います。

ただし、これだけ解けたらOKだと過信はしないほうがいいと思います（過学習🙅‍♂️）。を読んでいるとわかるのですが、書籍と対策アプリには書いてないことがあります。網羅しているわけではありません。どこまでやればいいのか、難しいところだと思いますが一読をおすすめします。

応用情報技術者試験に関しては検定に直接意味があったのかはわかりませんが、自身にはつながりました。

## おわりに

合格し目的も達成しました。これより高いレベルの試験のリリースも楽しみにしています。
ros 内でコマンド実行 + etherのmacアドレス取得 (C++ Python)

ros c++内でetherのmac addressを取得したいと思い方法を調べました.
結論としてはプログラム内でそれを取得できるbashを実行して結果を取得するとうまくできました.

# 環境

ros noetic
ubuntu 20.04

# 内容

## C++

1.以下を参考にbashコマンドの値を取得するプログラムを作成しました

https://www.jeremymorgan.com/tutorials/c-programming/how-to-capture-the-output-of-a-linux-command-in-c/

```ls.cpp
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

string GetStdoutFromCommand(string cmd) {

  string data;
  FILE * stream;
  const int max_buffer = 256;
  char buffer[max_buffer];
  cmd.append(" 2>&1");

  stream = popen(cmd.c_str(), "r");
  if (stream) {
    while (!feof(stream))
      if (fgets(buffer, max_buffer, stream) != NULL) data.append(buffer);
    pclose(stream);
  }
  return data;
}

int main() {

  string ls = GetStdoutFromCommand("ls -la");
  cout << "LS: " << ls << endl;
  return 0;
}
```

2.上記のbashコマンドをmacアドレスを取得するもの(`cat /sys/class/net/enp0s31f6/address`)に変更
※デバイス名は適宜変更

```mac.cpp
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

string GetStdoutFromCommand(string cmd) {

  string data;
  FILE * stream;
  const int max_buffer = 256;
  char buffer[max_buffer];
  cmd.append(" 2>&1");

  stream = popen(cmd.c_str(), "r");
  if (stream) {
    while (!feof(stream))
      if (fgets(buffer, max_buffer, stream) != NULL) data.append(buffer);
    pclose(stream);
  }
  return data;
}

int main() {

  string mac = GetStdoutFromCommand("cat /sys/class/net/enp0s31f6/address");
  cout << "MAC: " << mac << endl;
  return 0;
}
```

ちなみにCMakeLists.txtは以下のようになります

```CMakeLists.txt
cmake_minimum_required(VERSION 3.0.2)
project(linux_mac)

find_package(catkin REQUIRED)

catkin_package(
)

include_directories(
)

add_executable(ls src/ls.cpp)
target_link_libraries(
  ls
)

add_executable(mac src/mac.cpp)
target_link_libraries(
  mac
)
```

## Python2/3

コマンドの値を取得するプログラム

```getcmd.py
import subprocess

cal_output =  subprocess.check_output("ls", shell=True)
print(cal_output)
```

イーサーのmacを取得するプログラム

```getmac.py
import subprocess

cal_output =  subprocess.check_output("cat /sys/class/net/enp0s31f6/address", shell=True)
print(cal_output)
```

以上
CSSの読み込みに失敗する（HTTP 401：認証エラーが返る）

# はじめに
IIS + WSGI + Django環境の構築でstaticファイルを読み出せずに丸１日悩んだので，IIS初心者向けの方のために記載しておきます。

# 環境
* WindowsServer 2012 R2
* IIS 8.0
* Django 3.2.3
* WSGI 3.0.0

# CSSが読めない
Djangoアプリを作成し，staicファイル用のstaticフォルダを作成する。
参考：[Django staticファイル まとめ](https://qiita.com/okoppe8/items/38688fa9259f261c9440)
その結果，，，，何故か401エラーが返る

# IISマネージャから設定変更する
特定のユーザからアプリケーションプールIDに変更する
![スクリーンショット 2021-12-11 084535.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423321/e88fbbcb-c35f-4ba7-6c14-b120c8be2835.png)
（参考：特定のユーザをIUSRに変更するでもよい。）
Fargateでdockerにnginxを入れて動かすとessential container in task exited

Fargateで以下のようなDockerfileからビルドしたイメージで起動すると、タスクのステータスが```essential container in task exited```で終了してしまう。
Fargate自体は開発環境で利用していて、アーキテクチャとか設定の仕方は分かってる。今回理由があって、別のAWSアカウントに一からFargateを立てて、適当なDockerイメージで検証することにした。
で、Fargateの環境を立てたのはもうだいぶ前なので、最初からの立て方は色々忘れてて、復習を兼ねて良い機会だと思い出しながら進めてく。先にリポジトリ立ててタスク定義作って、ALBも先に作っておいた方が良くて、そのターゲットグループはIPで作るんだったよな..と思い出しながら進めてく。で、そんなに時間かからずに環境できたので、Dockerイメージは適当にnginxを利用することにして、ubuntuのイメージにインストールするのがいいかなあ、nginxの公式(OSはdebian)がいいかなあなんて進めてく。で、とりあえずこんなもんかなとサービス作成してタスクが起動されると、上記のエラーでタスクは終了する。そのときターゲットグループのターゲットのステータスはヘルスチェック失敗でdraining(破棄)になってく。CloudWatch見ると、普通に起動処理が終わったあとの20秒後くらいに、sigexitを食らって終了するような出力がでてる。sigexitということは外部(AWS?)から終了が実行されてる?? タスクが終了するとまたタスクが起動するが、それも同じエラーで終了する、のループが続く。ここから、普段どおり以下のような切り分け(設定確認)をしてく。

- ポート番号の整合性取れてるか
    - タスク定義、ターゲットグループ(ヘルスチェック)、ALBのリスナー、nginxのポート番号
- セキュリティグループちゃんと空いてるか
    - サービス/タスク用、ALB用

で、見直しても問題ない。ここから深みにはまっていく..

- タスクの配置サブネットはパブリックとプライベートで制約はあったか
- プライベートサブネットからNAT経由でインターネット接続可能になってるか
- VPCエンドポイントのセキュリティグループは正しいか。エンドポイントの配置サブネットやプライベートDNS設定は正しいか
- etc

で、その辺で何が問題か分からないので、Dockerfileの中身を変えてみると、以下が分かった

- nginxの公式イメージはOK
- ubuntuの公式イメージはNG
 
nginxの公式イメージ利用時は```FROM nginx```の1行なんだけど、ubuntuの公式イメージ利用時は、apt-getでnginxを入れている。nginxのインストールがうまくできていないのか?? 起動できていないのか?? など手元でdocker runしても特に問題なくて、なんでFargateで動かせないのか意味が分からない。

ただ、ubuntuで手でnginxを入れたときがだめ、という切り分けがついたので、インターネット上で同じ使い方している人の、実績があるであろうコードをコピペで入れて動かしてみようと調べたら、あるサイトに理由が書いてあった

https://chusotsu-program.com/dockerfile-generate-nginx-image/

> 6行目のENTRYPOINTコマンドは、コンテナを起動した際に実行するコマンドの指定だ。
Dockerでnginxを扱う場合、daemon off;の指定がないとコンテナが終了してしまうので、起動時に必ず必要なコマンドだ。

なるほどと、```ENTRYPOINT ["nginx", "-g", "daemon off;"]```をDockerfileに追加したらタスク正常起動。
単にDockerの知識不足。。
(でも手元では普通に動いてた?)

以下のような状況だと、環境周りの設定が悪いのかなと疑ってしまうけど、こういうケースもある、と勉強になったのでした

- 被疑箇所を絞りづらいログ出力、ヘルスチェック失敗から環境設定周りを疑う
- 構成要素が多いサービス(サブネット/NAT/ルートテーブル/VPCエンドポイントなどNW周り, ALB/ターゲットグループ, タスク定義, etc..)で、久々にさわるのもあり、基本的な部分で見落としや、仕様に沿った設定の確認不足があるのではないか
VS Code 1.63 の新機能 - スクリーンキャストモードでコマンド名の表示

https://code.visualstudio.com/updates/v1_63#_screencast-mode-shows-command-names

キーの入力内容を画面に表示する[スクリーンキャストモード機能](https://qiita.com/12345/items/4ba59be50c6ee9407131#%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%AD%E3%83%A3%E3%82%B9%E3%83%88%E3%83%A2%E3%83%BC%E3%83%89%E3%81%AE%E8%BF%BD%E5%8A%A0)で、ショートカットキーを入力した場合にそのコマンド名が表示されるようになった。

![scmode.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181011/8fa4376d-5fe0-0b69-083b-cd87106e6daa.gif)

ただしすべてのショートカットキーでコマンド名が表示されるわけではなく、単純な編集ショートカットキーなどはコマンド名は表示されない(コマンドではない？)。

なお、これに関する設定`Keyboard Shortcuts Format`が新たに追加された。選択肢は以下のとおり。

- keys：ショートカットキーのみ表示
- command：コマンド名のみ表示？
    - (だが実際はショートカットキーも表示される)
- commandWithGroup：グループ名付きでコマンド名のみを表示？
    - (だが実際はショートカットキーも表示される)
- commandAndKeys：コマンド名とショートカットキーを表示(デフォルト)
- commandWithGroupAndKeys：コマンド名とグループ名付きでコマンド名を表示
職業訓練校での面接

<h1>はじめに</h1>
こんにちは。本記事は、職業訓練校のwebプログラマーコースでの面接の流れを実体験を踏まえてシェアしたいと思います。
<hr>

<h1>面接までの準備</h1>
<b>必要なもの</b>
・受験票
・履歴書
・ジョブカード
<hr>
※ジョブカード
これまでの職歴、学歴や価値観を記入していくようなもの　

<h1>面接当日</h1>
まず服装なのですが、スーツが大多数でした。私服の方はおられましたが、私の所では、浮いてました。😂
おそらく、面接の順番は申し込みを行なった順番で、私は早かったので、朝一番の面接でした。時間は20分〜30分でした。

<h1>実際に聞かれた事</h1>
・前歴
・自己PR
・授業カリキュラムを知っているか
・なぜプログラミングを勉強したいのか
・パソコンはよく使っているか
・画像編集ソフトや動画編集ソフトは使えるか
・半年間休まず通学できるか
・クラスメートと仲良くできるか

面接内容はこんな感じでした。ハローワークの方から応募が多いとは聞いていたのである程度面接の準備はしていきました。合格後に実際聞いた事ですが、倍率は二倍以上あったらしいので準備はしていった方が無難です。職業訓練校が恐れていることは途中で辞められることや協調性が無く授業の妨げになることなのでやる気と協調性がある事をアピールすれば大丈夫だと思います。
面接後は、中学レベルの国語と数学のテストが合わせて20問ほど出題されました。こちらは対策なしでほとんどの方が問題ないと思います。

<h1>まとめ</h1>
多少、年齢や経歴などを見て判断されますが、私のクラスメートは私のような未経験や40代の方もおられたので、やる気と協調性があれば大丈夫です。また軽く授業のカリキュラムを見て、興味がある分野を面接で言えれば評価されると思います。
Goでmapをキー順にソートする

## mapは順序を持たない
Goでmapの値は順序を持ちません。
実際下記のようなプログラムを実行してみると、実行するたびに出力順序が変わることがわかります。

```go
package main

func main() {
	m := map[int]string{3: "c", 5: "e", 2: "b", 1: "a", 4: "d"}
	for _, e := range m {
		println(e) // この順番は実行するたびに変わる
	}
}

```
Go Playgroundでコードの実行ができます。
https://go.dev/play/p/jqXOpZiGafd

## 順序を保証するには
mapが保持しているデータの順序を保証するには、配列かスライスに入れ直してソートするしかありません。
ただ、何も考えずにループで回しながら入れ直してソートすると効率が悪くなるので、そこはシンプルに行きたいところですね。
所要時間計測のために、1000万個のデータを格納しているmapを用意し、その値をソートしてみました。
そして、所要時間比較のためにイマイチの実装とよりスマートな実行の両方を試してみました。

## イマイチな実装
脳死状態で、mapの中身をsliceに入れ直してソートする方法です。
実行時間を計測してみると、あくまで一例ですが「**8525** milli seconds」かかりました。
何回か実行してみても、だいたい8000ミリ秒以上かかってしまいます。
https://go.dev/play/p/ZhFI_l7Kw4t

```go
package main

import (
	"fmt"
	"sort"
	"strconv"
	"strings"
	"time"
)

func main() {
	m := getMap()

	now := time.Now()

	// 一旦sliceに入れ直す
	s := []string{}
	for _, e := range m {
		s = append(s, e)
	}

	// sliceソート
	sort.Slice(s, func(i, j int) bool {
		return strings.Compare(s[i], s[j]) > 0
	})

	fmt.Println(time.Since(now).Milliseconds(), "milli seconds")
}

func getMap() map[int]string {
	m := map[int]string{}
	for i := 0; i < 10000000; i++ {
		m[i] = strconv.Itoa(i)
	}
	return m
}
```

## スマートな方法
上の方法に対して、mapのキーだけを格納したsliceをソートする方法です。
この方法では「**4380** milli seconds」かかりました。
上の方法に比べて所要時間が半分くらいに減りましたね。
https://go.dev/play/p/PTiOsdG7bv6

```go
package main

import (
	"fmt"
	"sort"
	"strconv"
	"time"
)

func main() {
	m := getMap()

	now := time.Now()

	// mapのキーだけを取り出てソートする
	keys := getKeys(m)
	sort.Ints(keys)

	// 後はキーの順番で入れ直す
	s := []string{}
	for key := range keys {
		s = append(s, m[key])
	}

	fmt.Println(time.Since(now).Milliseconds(), "milli seconds")
}

func getMap() map[int]string {
	m := map[int]string{}
	for i := 0; i < 10000000; i++ {
		m[i] = strconv.Itoa(i)
	}
	return m
}

func getKeys(m map[int]string) []int {
	keys := []int{}
	for k := range m {
		keys = append(keys, k)
	}
	return keys
}
```
seabornでヒートマップを作ってみる

# はじめに
データ分析の際に思いつく仮設やアイデアが枯れてしまい、何かないかと調べた際にヒートマップの存在を知りました。備忘録として書き残します。

# 使いどころ
とりあえず、何かしらの相関や傾向がないか探るのに使えます。
数値ではなく、色の強弱で表現されるため、直感的に傾向をつかみやすいです。

# 書き方
Pythonのビジュアライゼーションライブラリ`seaborn`を使うと、二次元データを可視化するヒートマップが簡単に作成できます。

ヒートマップを作るには`seaborn`を`import`して、`seaborn.heatmap()`関数を使います。

```Python
import seaborn as sns

# ヒートマップ作成
plt.figure()
sns.heatmap(ヒートマップにしたい変数)

plt.savefig('seaborn_heatmap_df_example.png')
```
# 使用例
データ分析コンペでおなじみのkaggleにある、Forest Cover Type Predictionのデータを例にヒートマップを作成してみます。まずは下準備。
### 参考
[Forest Cover Type Prediction](https://www.kaggle.com/c/forest-cover-type-prediction)

```python
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

# 最大表示列数の指定
pd.set_option('display.max_columns', 100)

df_test = pd.read_csv("./test.csv", encoding="utf8")
df_test3 = pd.read_csv("./test3.csv", encoding="utf8")
df_train = pd.read_csv("./train.csv", encoding="utf8")
df_sample = pd.read_csv("./sampleSubmission.csv", encoding="utf8")

# どんなデータか確認
print("df_sample")
display(df_sample.head(10))
display(df_sample.info())
print(df_sample["Cover_Type"].unique())
print("df_test")
display(df_test.head(3))
display(df_test.info())
print("df_test3")
display(df_test3.head(3))
display(df_test3.info())
print("df_train")
display(df_train.head(3))
display(df_train.info())
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571046/a493bf35-7087-bc41-71f9-ae4e549d0bb8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571046/8c3060a5-44b6-5809-67c8-c20fad4d254c.png)

ここからヒートマップの作成です。
とりあえずカラムは指定せずに、すべて表示させます。

```python
df_test = pd.merge(df_test, df_sample, on="Id")
show_covertype = df_test.set_index("Id")
display(show_covertype)

# ヒートマップ表示
plt.figure(figsize=(50,50))
sns.heatmap(show_covertype, vmin=0 ,cmap="Reds")
plt.savefig("./show_data_heatmap.png")

```
するとこんな感じにヒートマップを表示させることができました。

![show_data_heatmap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571046/ffb2c787-a02e-c1eb-4e06-fde71b1657e2.png)

11列目以降のWilderness_Area1からは、0/1の表現になっているため、ヒートマップ上ではあまり目立っていません。


ちなみにcsvを取り込むとインデックスがないため、`set_index`する必要がありますが、
上記を忘れるとこんなエラーが出ます。

`TypeError: Image data of dtype object cannot be converted to float!`



# よく使うと思われる引数
## annot
ヒートマップのマス上に値を表示させる。
大量にあるデータでヒートマップを作製すると、黒塗り状態となって見づらくなるので、使い分けは必要です。
## square
ヒートマップのマスを正方形で表現してくれる。
デフォルトは`False`です。

## vmin, vmax, center 
最小値、最大値、中央値を設定できます。
設定せずとも、自動でいい感じにカラーバーの値を設定してくれますが、より明示的に指定したい場合に使います。

## cmap
ヒートマップに表示される色を変えられる。
多分、凝り性ははまると思う。
私は'Reds'で表示させています。

# 感想
matplotのように、細かいオプションをリストで用意する必要があるかと身構えていましたが、思ったよりも簡単でした。ヒートマップを表示させる機会はあまり多くないかもしれませんが、データを俯瞰してみたい時には悪くないと思いました。Forest Cover Typeの場合はそれぞれのカラムで出てくる値の範囲がバラバラなため、もう少し工夫が必要だと感じました。
React フックについて勉強してみた

# 初めに
React のフックについて以下のドキュメントを参考に勉強してみました。

https://ja.reactjs.org/docs/hooks-intro.html

# フックとは

クラスコンポーネントの state や setState を関数コンポーネントでも扱えるようにしたのがフックです。

例えば、以下のような `date` という state と、それを更新する setState は、`const [date, setTimer] = useState(new Date());` と定義されます。

```react
class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }
```

↓ フックを使う場合

```react
const Clock = () => {
  const [date, setTimer] = useState(new Date());

  const tick = () => {
    setTimer(new Date());
  }
```

このように、`setTimer` は `date` 更新用の setState です。また、`useState(new Date())` の `new Date()` は、`date` の初期値です。これは、クラスコンポーネントで以下のように初期値を設定することと同等です。

```react
this.state = {date: new Date()};
```

# 副作用フックとは

クラスコンポーネントの `componentDidMount` と `componentDidUpdate `と `componentWillUnmount` をまとめて `useEffect` で記述したものが副作用フックです。

例えば、以下の 1 秒おきに時間を更新するマウントとアンマウントは、`useEffect` で書くことができます。

```react
  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }
```

↓ 副作用フックを使う場合

```react
  useEffect(() => {
    setInterval(
      () => tick(),
      1000
    );
  })
```

# サンプルコード

こちらにある時計のサンプルをフックを使って書き換えてみました。

https://ja.reactjs.org/docs/state-and-lifecycle.html

```react
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';

const Clock = () => {
  const [date, setTimer] = useState(new Date());

  useEffect(() => {
    setInterval(
      () => tick(),
      1000
    );
  })

  const tick = () => {
    setTimer(new Date());
  }

  return (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {date.toLocaleTimeString()}.</h2>
    </div>
  );
}

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);
```

# まとめ

以下の 2 点について勉強しました。

- フックとは何か
- 副作用フックとは何か

# 参考記事

https://ja.reactjs.org/docs/hooks-intro.html

https://ja.reactjs.org/docs/hooks-effect.html

https://ja.reactjs.org/docs/state-and-lifecycle.html
google-home-notifierの代替となりそうなgoogle-home-playerを試してみる

# はじめに

Google Home発売当初、Google HomeハックのHello Worldとも言える「Google Homeを喋らせてみた」ハックで誰もが使用したであろう「google-home-notifier」ですが、動かなくなったりメンテされなくなったりで、もはや多くの方がGoogle Homeを喋らせることをやめてしまったのではないでしょうか。

https://github.com/noelportugal/google-home-notifier

そんな折ふとnpmを眺めていたら「google-home-player」というパッケージがあり、READMEでもgoogle-home-notifierの代替とあったので試してみました。



# google-home-player

https://github.com/mihyaeru21/google-home-player

google-home-notifierはcallback形式の書き方でしたが、google-home-playerはPromiseで書けます。もちろんasync/awaitでも。
そのおかげもあってかgoogle-home-notifierに比べ大分すっきり書ける気がします。

内部の実装は基本的にはgoogle-home-notifierと同様「castv2-client」でGoogle Home / Google Nestへキャストして「google-tts-api」で生成した発話mp3 URLを再生しているようです。

https://github.com/thibauts/node-castv2-client

https://github.com/zlargon/google-tts#readme

また更新はパッケージのアップデート等軽微なものですが、最終更新がひと月前とちょこちょこメンテナンスされていそうです。

https://github.com/mihyaeru21/google-home-player/commits/master



# サンプルコード

機能をコメントを交えたコードで紹介します。

```js:Google&nbsp;Home&nbsp;/&nbsp;Google&nbsp;Nestを喋らせる
const GoogleHomePlayer = require("google-home-player")

const ip = "x.x.x.x" // Google Home / Google NestのIPアドレスを入力
const lang = "ja"

const googleHome = new GoogleHomePlayer(ip, lang)

; (async () => {
	await googleHome.say("first text")
	await googleHome.say("second text", "en") // 第二引数で言語を指定
	await googleHome.say("final text", "en", true) // 第三引数でslowの有効/無効を指定
})()
```

ちなみに`lang`、`slow`はインスタンス作成時にもデフォルトを指定できます。

```js:インスタンス作成時にデフォルト指定
const GoogleHomePlayer = require("google-home-player")

const ip = "x.x.x.x" // Google Home / Google NestのIPアドレスを入力
const lang = "ja"
const slow = true

let googleHome
googleHome = new GoogleHomePlayer(ip)             // lang: "en", slow: false
googleHome = new GoogleHomePlayer(ip, lang)       // lang: "ja", slow: false
googleHome = new GoogleHomePlayer(ip, lang, slow) // lang: "ja", slow: true
```

google-home-notifier同様、音楽再生もいけます。

```js:音楽再生
const GoogleHomePlayer = require("google-home-player")

const ip = "x.x.x.x" // Google Home / Google NestのIPアドレスを入力
const lang = "ja"

const googleHome = new GoogleHomePlayer(ip, lang)

; (async () => {
	await googleHome.play("https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3")
})()
```



# おわりに

google-home-playerのおかげで再びGoogle Home / Google Nestを喋らせることができました。
ただgoogle-home-notifierもそうでしたがキャストの仕組みを使っている以上、音楽再生中などに喋らせると音楽が中断されたまま再開しないという動きとなるため、やっぱ使わなそうです…😢
Google Maps API：Places APIを使ってみる　その①

# 今日の目標
* Qiita初投稿
* Google Maps API：Places APIをとにかく使ってみる

## Google Maps API：Places APIをとにかく使ってみる
まずは[公式](https://developers.google.com/maps/documentation/places/web-service/details)掲載のサンプルコードをもとに動かしてみる。
正常レスポンスが返ってくることをゴールとする。

#### Request

```{}
>curl -L -X GET "https://maps.googleapis.com/maps/api/place/details/json?place_id=ChIJN1t_tDeuEmsRUsoyG83frY4&fields=name%2Crating%2Cformatted_phone_number&key=API_KEY"
```

place_idなるものを送り、name、rating、formatted_phone_numberを取得するもの。
place_idは[ここ](https://developers.google.com/maps/documentation/places/web-service/place-id)から検索できる。

#### 1st Response

```
{
   "error_message" : "You must enable Billing on the Google Cloud Project at https://console.cloud.google.com/project/_/billing/enable Learn more at https://developers.google.com/maps/gmp-get-started",
   "html_attributions" : [],
   "status" : "REQUEST_DENIED"
}
```
エラーメッセージより課金設定周りでこけている様子。
[リンク先](https://www.nowte.net/article/1740/)を参考にするとやはりそうで、Google Cloud Platformにて課金設定実施。

* 請求先アカウント作成
* プロジェクトへ作成した請求先アカウントを割り当て

#### 2nd Responce
結果、Responceが以下に変化。

```
{
   "html_attributions" : [],
   "result" : {
      "formatted_phone_number" : "(02) 9374 4000",
      "name" : "Google Workplace 6",
      "rating" : 4.1
   },
   "status" : "OK"
}
```
正常レスポンスが返ってきた！

### お試し
place_idを変えてみてどんなレスポンスが返ってくるか試してみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262169/0ff85e98-0a8b-5bab-9652-daff6f8a28dc.png)
#### Request
```
>curl -L -X GET "https://maps.googleapis.com/maps/api/place/details/json?place_id=ChIJlVE-9wblBGARqr9M8wheltU&fields=name%2Crating%2Cformatted_phone_number&key=API_KEY"
```
#### Responce
```
{
   "html_attributions" : [],
   "result" : {
      "formatted_phone_number" : "0531-23-3516",
      "name" : "Cape Irago Lighthouse",
      "rating" : 4.2
   },
   "status" : "OK"
}
```
当然ではあるがこれまた正常レスポンス。
ちなみにレスポンス掲載の電話番号は[渥美半島観光ビューロー](https://www.taharakankou.gr.jp/)というところ。

ということで今回の目的は達成。

## 余談
### curlコマンドオプション
| オプション | 意味 |
| ---- | ---- | 
| -L | リダイレクトさせる |
| -X | HTTPメソッドの指定 | 

* [よく使うcurlコマンドのオプション](https://qiita.com/ryuichi1208/items/e4e1b27ff7d54a66dcd9)
* [よく使うcurlコマンドのオプションまとめ（14個）](https://qiita.com/shtnkgm/items/45b4cd274fa813d29539)
* [逆引きcurlコマンドのオプション一覧](https://www.setouchino.cloud/blogs/99#l)

## 参考URL
* [Google mapのPlaces APIで指定したエリア内にある特定の場所を調べてみよう！](https://qiita.com/yoshii0110/items/7938085151f569427af6)
* [Windows 10の curlコマンドで Protocol "'https" not supported or disabled in libcurlの解決方法](http://www.neko.ne.jp/~freewing/software/windows_10_curl_protocol_https_not_supported/)
paraviewでのレイトレーシング（OSPRay）

#paraviewのバージョン
paraviewの最新バージョンは、2021年12月現在で5.9.1です。
#レイトレーシング機能
paraviewにはレイトレーシング機能であるintel社のOSPRayが内蔵されています。
paraviewの最新版のレイトレーシング機能で、マテリアルを選択できることを確認しました。
逆に、5.6.xのような古いバージョンでは、レイトレーシング機能でマテリアルを選択することはできませんでした。
#適用例
ダムブレイクのチュートリアルケースの計算結果の後処理で、paraviewのレイトレーシング機能を適用したスナップショットを作成しました。スナップショットより作成したアニメーションを以下に示します。
ダムブレイクは次のケースを使用しました。
$FOAM_TUTORIALS/multiphase/interFoam/laminar/damBreakWithObstacle
なお、AMRは使用しないように変更してあります。
![sample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/d235fd76-2bc8-7057-7604-8ea563207965.gif)
#paraviewの設定例
以下はcaseディレクトリで
$ touch case.foam
として空のcase.foamファイルを作成した後、paraviewでcase.foamを選択する例です。
##case.foam
![case.foam.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/729f52df-60ab-ef39-cff9-c628c84ce626.png)
##Contour
![contour1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/861353d5-1afa-031b-4653-f14fa2a47a4c.png)
![contour2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/2a797364-20f2-cb38-22f6-354301cc4e78.png)
![contour3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/3190ae61-ef8f-3c6c-8cae-f9b48d4398fb.png)
##ExtractBlock
![extractblock.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1784513/832ce675-03e3-9555-c0b9-2efc274cc48c.png)
OutSystemsなら10分でアプリが作れる！

# はじめに
本記事では、簡単に[日記帳アプリ](https://protopedia.net/prototype/2688)を作成する。

# 前提
- ServiceStudioがインストール済みであること
- ServiceStudioにログインしていること

# 手順

## 1. Entityの作成

ServiceStudioを開き、「New Application」ボタンをクリックする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/9f14078c-85d8-991b-96f8-676f3d3baa79.png)

「From scratch」を選択し、右下の「Next」ボタンをクリックする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/6ee450e5-788f-db3e-e83e-975cfae7a204.png)

「Reactive Web App」を選択し、右下の「Next」ボタンをクリックする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/a2850dab-b1af-430a-3744-7b9d63542552.png)

アプリ名（例では「Diary」）を入力し、右下の「Create App」ボタンをクリックする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/233ac315-2cd2-80cd-b335-12411245763b.png)

真ん中の「Create Module」ボタンをクリックする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/3bdf4e27-ff01-d862-44a3-2d583c921a9e.png)

「Data」タブを開き、「Entities」配下の「Database」で右クリックをし、「Add Entity」をクリックする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/52e523cc-a6e4-4759-87d1-4d275f52df0c.png)

「Entity1」という名前のEntityが作成されるため、名前を「Diary」に変更する。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/0a951192-1157-dfd8-0fc0-b95ef0919b5f.png)

作成したEntity「Diary」を右クリックし、「Add Entity Attribute」をクリックする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/968a5157-3a41-cd48-0413-691ce75a0347.png)

「Attribute1」という名前のEntity Attributeが作成されるため、名前を「Title」に変更し、Data Typeを「Title」に変更する。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/b5603caf-4a8f-cfac-d024-5c22ae723e89.png)

同様の手順で下記に記すEntity Attributeを全て作成する。

|Name  |Data Type  |
|---|---|
|Title  |Text  |
|Content  |Text  |
|User Id |User Identifier  |
|TargetDate |Date  |

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/eebe4624-f5d1-f4c4-2d7a-a6a4654dfe92.png)

## 2. 一覧画面と詳細画面の作成

「Interface」タブの「MainFlow」をダブルクリックする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/920c096b-29e7-a294-66f2-1f4d7ace9121.png)

「Data」タブの先ほど作成した「Diary」Entityを「MainFlow」にドラッグ&ドロップする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/4fa77ef0-3030-f0e5-a7ca-5b22a024e6da.png)

## 3. アプリ公開

真ん中上部の「Publish」ボタンをクリックする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/7b30b717-735c-c421-68f5-212da33f652e.png)

## 4. 起動確認

「Open in browser」をクリックする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/dd1592eb-4ea4-600b-af25-c3b6c1edd105.png)

OutSystemsのアカウントの「Username」と「Password」でログインする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/080e2f36-fc8e-1947-9d53-ae5f573242d7.png)

右上の「Add Diary」をクリックする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/fe9ca668-29a6-34a6-f2ae-0f2a955984d3.png)

日記に記載する事項を入力し、「Save」ボタンをクリックする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/778f12d9-32c2-60e4-fb57-c6508e8b91a3.png)

下図のように表示されれば完成！
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505689/8c1a9736-b311-8dad-3e54-6e8474c4f260.png)
PowerShell 配列の空白要素を削除する

PowerShellで配列の空白 `""` を削除して切り詰める方法です。

## コマンド

```powershell
$array = $array -ne ""
```

## 実行結果

```
PS > $array = "a","b","","c",""
PS > echo $array
a
b

c

PS > $array = $array -ne ""
PS > echo $array
a
b
c
PS C:\Users\Owner>
```

## 参考： `-ne` には2種類ある

`-ne` には2種類の役割があります：

- **フィルターとしての `-ne` ：** 左側の配列から、右側に一致しない要素だけを返す。
- **比較演算子としての `-ne` ：** 左側と右側が一致しないとき偽を返す。

左側が配列のときはフィルターとして動作します。上のコマンドで使用した `-ne` はフィルターです。

注意する必要があるのは `if ($a -ne $b)` のような文です。この文を書くときは比較を期待しているはずですが、 `$a` が配列のときはフィルターとして動作します。

`-eq` についても同じことが言えます。

## 参考リンク

- [Array要素の削除に$null代入するとビックリすることがある - Qiita](https://qiita.com/ppyv/items/c1c27b6dc68c730e06b5)
- [なぜVisual Studio CodeはPowerShellで右辺に$nullを置くと怒り出すのか - Qiita](https://qiita.com/bigfirtreeman/items/d95a6c7b09b8edf5dc9b)
- [if($array -eq $null) には要注意！ - PowerShell Scripting Weblog](https://winscript.jp/powershell/222)