OmniAICreator/Qiita-1.07M huggingface dataset:
[BigQuery]再びアクティブになったユーザ行動変化分析のための下準備クエリ

同じような車輪の再発明を自分の中で３回はやった気がするので、Qiitaにやり方をのこす
想定読者：未来の自分

# やりたいこと

しばらく利用がなかったが、再び使い始めたユーザの行動が以前と変化があるか？の統計的な情報を知りたい

どんな変化を知りたいかor調べられるかは、仮説やらサービス特性やらログ設計やら利用規約やらに大きく依存するため、ここではBigQueryのSQLで「同じユーザ内で以前と以後の期間を区別する」ためだけのSQLをのこす

# ここでの用語

一般的な用語を知らないので自分流の定義をここで整理する

Phase (N): そのサービスを熱心に使っている期間。いわゆるアクティブな期間だが、一定期間空いた後に何度もアクティブになることを想定しているため、N番目のアクティブ期間を PhaseN と書く。
span: PhaseとPhaseの間。いわゆる休眠期間だが、通常の意味と違って未来から見たときに再アクティブになるのがわかっている期間だけを指す

図にするとこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108572/4369743a-b738-b473-bb35-ba994ea09217.png)

行動ログ: time (Date型、分割テーブルのパーティションに使われがち), id (個人を識別するための情報、デバイスのIDとかcookieの値とか、を仮名化したもの), action (興味ある行動全般。実際は複数あるはず)の形で、何らかのactionごとに保存されるログで、BigQueryに保存されている (eventテーブル) 

やりたいことを言い換えると、「span が一定間隔以上 (約１ヶ月とか)で行動ログをidとPhaseで分けてactionを分析したい」になる

# SQLサンプル

```

WITH
  ordered_action AS (
    SELECT
      *,
      ROW_NUMBER() OVER (PARTITION BY id ORDER BY time DESC) as ordered #idごとにaction=hogeが発生した順番を付与
    FROM
      dataset.event
    WHERE
      action='hoge'
  ),

  span_action AS (
    SELECT
      a.*,
      CASE WHEN DATE_DIFF(time, time, DAY) > 28 THEN 1 ELSE 0 END as span # Phaseの最初はspan=1になる。ちなみにMONTH>=1にすると 1/31~2/1でもtrueになるので注意
    FROM
      ordered_action a
    LEFT OUTER JOIN #外部結合にしないと最初のログが消える
      ordered_action b
    ON
      a.id=b.id
      AND
      a.ordered+1=b.ordered #ここの同一テーブルでJOINの処理のサンプルがなかなか見つけられずに車輪の再発明を繰り返している
  ),

  phase_action AS (
    SELECT
      *,
      SUM(span) OVER (PARTITION BY VISID ORDER BY DATE_TIME ROWS UNBOUNDED PRECEDING) as phase #cumsumすることでpahseがインクリメンタルされる
    FROM
      span_action
)

SELECT
  id,
  pahse,
  count(*) #action hogeの数を数えてるだけ。ここまでくれば真にやりたいことに合わせて煮るなり焼くなりできるはず
FROM
  phase_action
GROUP BY
  id, phase

```
Centos8 に日本語入力をできるようにする方法

#背景

Centos8にて日本語入力ができませんでした。入力しても文字が反映されません。

```
# echo $LANG

en_US.UTF-8
```

デフォルトでは英語設定となっています。


#解決方法

日本語のパッケージをインストールした後、日本語入力をできるようにします。

```
# dnf -y install langpacks-ja

# localectl set-locale LANG=ja_JP.UTF-8

# source /etc/locale.conf

# echo $LANG

ja_JP.UTF-8
```

これで日本語に設定ができ、入力ができるようになりました。



#参考

参考にさせていただきました。ありがとうございます。

https://www.server-world.info/query?os=CentOS_8&p=japanese
論理演算子について



|演算子|記述例|意味|別の演算子|
|--|--|--|--|
|&&|a && b|aとbが共に真の場合に真|and|
|II|a II b|aかbの少なくとも1つが真の場合に真|or|
|!|!a|aが真の時に偽、偽の時に真|not|

※ちなみにマークダウン法では　｜｜は表をかく記号と同じだから
＊railsとは無関係ですが、マークダウン法でアルファベットアイ「i」の大文字を使うとダミーの演算記号ができ上がります。
正規表現と仲良くなって使いたい技。文字列変換からフォーマット変更、パスワードチェック、住所分割まで

freecodecamp のJavaScript講座

[JavaScript Algorithms and Data Structures Certification | freeCodeCamp.org](https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/)

を続ける中JavaScriptのアルゴリズムだ正規表現だで時々これ良いねというものに出会うので書き溜めていました。こういうことをしたいときにこれが使えそうというものが出てくるのです。


## 便利な正規表現

### 文字列を `-` でつなぐ 等

記事のタイトル文字列などをうまく `-` で接続してファイル名にする等。

```js
"Hello World".toLowerCase().trim().split(/\s+/).join("-");
"HELLO WORLD".toLowerCase().trim().split(/\s+/).join("-");
" hello world  ".toLowerCase().trim().split(/\s+/).join("-");
```
→ いずれも `hello-world`

```js
" Hello World 2021.04.30 ".toLowerCase().trim().split(/\s+/).join("-");
```
→ いずれも `hello-world-2021.04.30`


```js
"HelloWorld".replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().trim().split(/\s+|_+/).join("-");
```
→ ケバブケースも `hello-world`
他、ついでに見つけたので以下も参照。

- 全角文字検索
- キャメルケースからスネークケース
- スネークケースからキャメルケース
- フルパスからファイル名を取り出す

https://qiita.com/takoyan/items/449dd72a20f04a3c31f0

他バリデーション。

https://qiita.com/nasuB7373/items/17adc4b808a8bd39624d


### 日付や通貨等のフォーマットを変更する

`$1 $2` という分け方を覚えたところで以下。

```js
"今日は2021年4月30日、明日は2021年5月1日です。".replace( /(\d+)年(\d+)月(\d+)日/g , "$1/$2/$3" );
```
→ `今日は2021/4/30、明日は2021/5/1です。` 

```js
"今日は2021年4月30日、明日は2021年5月1日です。".replace( /(\d+)年(\d+)月(\d+)日/g , "$2/$3（$1年）" );
```
→ `今日は4/30（2021年）、明日は5/1（2021年）です。`


### パスワード要件をチェックする

以上のところくらいまで分かると、業務アプリでも使いそうな以下など。

https://qiita.com/mpyw/items/886218e7b418dfed254b

例) 半角英数字8文字以上100文字以下

```
/^[a-z\d]{8,100}$/i
```

```
let password = "abc123";
let checkPass = /(?=\w{3,6})(?=\D*\d)/;
checkPass.test(password);
```

で「3文字から6文字で少なくとも数字を含む」。

以下もメモ。

https://qiita.com/mpyw/items/886218e7b418dfed254b#%E5%8D%8A%E8%A7%92%E8%8B%B1%E6%95%B0%E5%AD%97%E3%82%92%E3%81%9D%E3%82%8C%E3%81%9E%E3%82%8C1%E7%A8%AE%E9%A1%9E%E4%BB%A5%E4%B8%8A%E5%90%AB%E3%82%808%E6%96%87%E5%AD%97%E4%BB%A5%E4%B8%8A100%E6%96%87%E5%AD%97%E4%BB%A5%E4%B8%8B%E3%81%AE%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE


https://qiita.com/momotaro98/items/460c6cac14473765ec14

https://qiita.com/e99h2121/items/f9f468b84f01258382f6




### 住所を「都道府県/市区町村/それ以降」に分ける

...で更にのめり込むとこんな大作が作れる。スゴイ。

https://qiita.com/zakuroishikuro/items/066421bce820e3c73ce9

https://qiita.com/jkr_2255/items/c7958b1e62696a1fe183

以下引用。

```引用
(...??[都道府県])((?:旭川|伊達|石狩|盛岡|奥州|田村|南相馬|那須塩原|東村山|武蔵村山|羽村|十日町|上越|富山|野々市|大町|蒲郡|四日市|姫路|大和郡山|廿日市|下松|岩国|田川|大村)市|.+?郡(?:玉村|大町|.+?)[町村]|.+?市.+?区|.+?[市区町村])(.+)
```




## 正規表現チートシート

ここまで書いておいて何だが、実際のところ実用時は忘れている気しかしない...。
結局チートシートを頼りにしています。この正規表現どういう意味なんだっけ、というチェックツールも必須。

https://qiita.com/tossh/items/635aea9a529b9deb3038

https://qiita.com/aqril_1132/items/c185c7ad84c129e5a2df

https://murashun.jp/article/programming/regular-expression.html

https://ihateregex.io/

https://github.com/geongeorge/i-hate-regex

https://dev.to/mathlete/cheatsheet-for-the-regular-expressions-cheatsheet-part-1-247f

[サルにもわかる正規表現入門](https://userweb.mnet.ne.jp/nakama/regexp2.html)

## おまけ

https://qiita.com/paddy-oti/items/399a0bbd16f3f062c666

[君たちは正規表現におけるインド数字の罠にハマったことはあるかい？(١٢٣٤٥٦٧٨٩) - Qiita](https://qiita.com/papi_tokei/items/0e0e9b46708e007bb72e)

追記しておく。
以上、参考になればさいわいです。
fanotifyによる削除検出について調べてみた


## 概要

- 元々fanotify（ファイルシステムイベントの監視）で削除ができなかった。
- Linux 5.1より削除が検出できるようになった。
- 具体的な実装方法を探してみた。

## 結果

- [dmacvicar/fanotify\_example: Example of fanotify API including the new FAN\_DELETE in kernel 5\.1](https://github.com/dmacvicar/fanotify_example)を参考に削除を検出できる
- そのままだと再帰的な検出ができないのでファイルシステム単位での監視に変更するには`fanotify_mark`の引数に`FAN_MARK_FILESYSTEM`を加えてマウントポイント`/`等を指定する。

```diff
--- fanotify_example.c.org      2021-05-01 20:55:37.356846871 +0000
+++ fanotify_example.c  2021-05-01 20:57:37.118257631 +0000
@@ -40,7 +40,7 @@
     }

     int ret = fanotify_mark(fan,
-                            FAN_MARK_ADD,
+                            FAN_MARK_ADD | FAN_MARK_FILESYSTEM,
                             FAN_CREATE | FAN_DELETE | FAN_MODIFY | FAN_EVENT_ON_CHILD,
                             AT_FDCWD,
                             argv[1]
```
- `rm /tmp/a/a.txt`を実行したときの出力は以下となる。

```
$ gcc -Wall fanotify_example.c
$ sudo ./a.out /
FAN_DELETE/tmp/a
```

- [fanotify\(7\) \- Linux manual page](https://man7.org/linux/man-pages/man7/fanotify.7.html)下部に`fanotify_fid.c`があるが、`FAN_REPORT_DFID_NAME`がLinux 5.9 以降でないと動かない。（現在最新ubuntu 21.04はLinux 5.8.0だったのでここまで）


[fanotify\(7\)めも \- φ\(・・\*\)ゞ ｳｰﾝ　カーネルとか弄ったりのメモ](https://kernhack.hatenablog.com/entry/2021/03/13/153129)
[ファイルを監視して、将来どのプロセスがファイルを書き込みまたは削除するかを確認する方法 \- Javaer101](https://www.javaer101.com/ja/article/46100514.html)
[fanotify\(7\) \- Linux manual page](https://man7.org/linux/man-pages/man7/fanotify.7.html)

[Man page of FANOTIFY\_INIT](https://linuxjm.osdn.jp/html/LDP_man-pages/man2/open.2.html)

[dmacvicar/fanotify\_example: Example of fanotify API including the new FAN\_DELETE in kernel 5\.1](https://github.com/dmacvicar/fanotify_example)

[c \+\+\-fanotify\-カーネル5\.1で導入された新しいフラグの問題\-スタックオーバーフロー](https://stackoverflow.com/questions/59015209/fanotify-problem-with-new-flags-introduced-in-kernel-5-1)
【Neos VR】VIVE Pro Eyeを使ったAdvancedまばたき設定

# 概要
VIVE Pro Eyeを使うと目蓋の動きをトラッキングして，アバターにまばたきさせることが出来ます．
しかしNeos VRの自動セットアップでは目閉じの設定が行われるだけで，SRanipalの機能を活かしきれていません．
そこで本記事ではEyeWiden，EyeSqueezeも利用したAdvancedまばたき設定の方法を紹介します．

# 設定方法

### 薄目の改善
EyeCloseの値をそのままBlendShapeに繋げると
目を閉じているつもりでも薄目になってしまったり
薄目を開けているときに目蓋がひくついてしまったりします．

そこでEyeCloseから出力される値を0.8~0.9で割ってあげることで，完全に目を閉じなくてもアバターは目を瞑るようにできます．
そのままだと数値が1を超えて破綻してしまうため，Clamp01を間に挟みます．
![Photo1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426108/a9d961f2-4e81-d3fc-53d6-6337a999fe3e.png)
![Step1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426108/3d2e699c-7712-a548-9381-5217c1b37982.gif)

### 目を見開けるようにする
VIVE Pro Eyeでは目蓋を閉じるだけではなく，見開くことも出来ます．
しかし多くのアバターには目を見開くBlendShapeが用意されていません．
そこで目閉じのBlendShapeを使って目を見開く設定を行います．

EyeWidenから出力された値に0.2~0.4程度の値をかけます．
この値を引いてあげることで目閉じのBlendShapeの値がマイナスになり，逆方向に動かすことが出来ます．
目閉じと合わせて使うためにEyeCloseから出力された値から引いてBlendShapeに繋ぎます．
![Photo3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426108/d531af64-0f73-0d22-4916-0acbd69bae7f.png)
![Step2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426108/e84147ba-dd37-85ae-9779-a212b75d8d89.gif)

### にっこり目に切り替える
VIVE Pro EyeにはEyeSqueezeの値があります．
これは目閉じの状態からさらにギュッと閉じた目にする為の値ですが
にっこり目に切り替えるために使ってみます．

EyeSqueezeの値をにっこり目のBlendShapeに繋ぎます．
このままだと目閉じのBlendShapeと干渉して目を閉じすぎてしまうため，
EyeCloseからEyeSqueezeを引いて目閉じのBlendShapeに繋ぎます．
こうすることで目を閉じた状態からにっこり目へと滑らかに切り替えることが出来ます．
![Photo4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426108/1f59e6d7-55c7-aede-0772-3f188cff71a7.png)
![Step3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426108/9b238522-8a30-3e47-a614-8500fce117c6.gif)

# 終わりに
BlendShapeを自分で作れる方であれば，EyeWidenとEyeSqueezeを作成することでComponentを利用し設定することが出来ます．
しかし，モデリングソフトの使い方がわからない初心者であってもVR内だけでVIVE Pro Eyeを使いこなした設定が出来ることを目的に本記事を作成しました．

今回作成したLogiXは下記パブリックフォルダーに入れておきます．
neosrec:///U-1ab6590e-9cac-43c3-a23f-147579e0f277/R-e4afd443-eb3d-4d3c-aab4-8d58ca61386b
シンプルに Docker を試してみる〜 Ubuntu を起動してみる〜

# シンプルに Docker を試してみる〜 Ubuntu を起動してみる〜

Dockerと聞くと、**なんだか難しそうなイメージ**を持たれがちだと思います。以前の私もそうで、手を出しづらいイメージを持っていました。

**初めてDockerを試す**ときに、こんな感じでとにかくシンプルにまとめてあるドキュメントがあったらよかったのにと思ったのでそのメモ。

# Dockerとは
Dockerは、インフラ関係やDevOps界隈で注目されている技術の一つで、Docker社が開発している、コンテナ型の仮想環境を作成、配布、実行するためのプラットフォームです[^1]。

### Dockerを用いることによって何が嬉しいのか
コード化された設定ファイル`Dockerfile`を共有することで、どこでも誰でも同じ環境が作れることや、**スクラップ&ビルドが容易にできる**ことから開発に関して理想的な環境を手に入れることができる。

# 環境

+ macOS BigSur 11.2.3（20D91）
+ Docker Desktop for Mac 20.10.5, build 55c4c88

### Dockerのインストール

![](https://storage.googleapis.com/zenn-user-upload/nmifmqq7v5vkubr3imytadieiq08)

### Docker for Macをインストール

- 公式サイトからDockerのアカウントを作ってログイン
- DockerHubからダウンロードしてインストール

https://hub.docker.com/editions/community/docker-ce-desktop-mac


インストール後CLIで確認してみる。

```bash
$ docker -v
Docker version 20.10.5, build 55c4c88
```

このようにバージョンが表示されたら完了。

# 試しにubuntuを使ってみる
まず、`test`フォルダーを作って`Dockerfile`を作成する。

```bash
$ mkdir test
$ cd test
$ echo "From ubuntu" > Dockerfile
```

次にビルドして、shellに入ってみます。

```bash
$ docker build -t test .
$ docker run -it test bash
$ cat /etc/os-release
```

### オプションの意味

+ -t タグ
+ -i インタラクティブ(アタッチしていなくても STDIN を開き続ける)

無事にUbuntuが起動できればこのようなメッセージが表示されると思います。

```bash
NAME="Ubuntu"
VERSION="20.04.2 LTS (Focal Fossa)"
```

そうなんです、これだけでUbuntuが使えてしまうのは感動しませんか。

***

これでDockerの動作を確認できました。
このコンテナは不要になると思うので一旦キャッシュを含めて削除しましょう。

```bash
$ docker system prune -a
```

以上で完了です。

[^1]: 「Docker入門（第一回）～Dockerとは何か、何が良いのか～」 https://knowledge.sakura.ad.jp/13265/
バインド変数に値を入れてSQL実行(SQL*PlusとOSqlEdit)

主に管理用途で、バインド変数へ値を入れてSQL実行する方法として、OSqlEditとSQL*Plusでの2パターン記します。

# [OSqlEdit]バインド変数へ値を入れてSQL実行

```
!bind set a = 'abc'
select :a from dual;
```

実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85051/ec740d12-f720-10cc-d67f-b2bf4dc248af.png)

他にも下記があります（command.txtを転記）
!bind set a = 'abc'    -- バインド変数aに，abcを設定
!bind unset a          -- バインド変数aを削除
!bind print a          -- バインド変数aの内容を表示
!bind print            -- 全てのバインド変数をリスト表示
!bind clear all        -- 全てのバインド変数を削除


### 参考
インストールしたフォルダのdoc/command.txt

# [SQL*Plus]バインド変数へ値を入れてSQL実行

```
--12cR2以降、定義と代入が1行で可能
SQL> variable a varchar2(10) = 'abc'
SQL> select :a from dual;

:A
----------------------------------------
abc

--12cR1より前、定義と代入は別々
SQL> variable a varchar2(10)
SQL>  exec :a := 'abc';

PL/SQLプロシージャが正常に完了しました。

SQL>  select :a from dual;

:A
-----------------------------------------
abc

--変数の中身の確認
SQL> print :a

A
----------------------------------------------------------------
abc

```
### 参考
[SQL*Plusユーザーズ・ガイドおよびリファレンス(19c)
12.51 VARIABLE]
(https://docs.oracle.com/cd/F19136_01/sqpug/VARIABLE.html#GUID-B4A0DAA3-B6E0-42F7-89B0-EF9C41F02FA3)
[12.32 PRINT](https://docs.oracle.com/cd/F19136_01/sqpug/PRINT.html#GUID-3C8951DC-7895-46DE-8FBB-7508B4D16499)
[Rails] Deviseのユーザー登録後失敗後のルーティングが/usersになる件の対処

# 概要
現在運営しているカフェサークルのサイトをrailsで作成しているのですがdeviseの新規登録が失敗したときのルーティングが`users/sign_in` > `/users` になってしまい、リロードした際にページが見つからないエラーが出ている状態でした。

# 解決策
deviseのscopeで`/users`を新規登録のルーティングに設定してあげればよい。
具体的には以下のようにroutes.rbに設定を追加する。

```ruby:routes.rb
  devise_scope :user do
    # TIPS: ユーザー登録しっぱいのリダイレクトのエラーを防ぐ https://github.com/heartcombo/devise/blob/master/app/controllers/devise/registrations_controller.rb
    get '/users', to: 'devise/registrations#new'
  end
```

これで、deviseが`/users`を新規登録のルーティングと認識してエラーが起こらなくなる。

# 参考

https://github.com/kazuki-kitaguchi/hmw_exhibit/issues/9
Google Data Analytics Professional Certificateを二週間で取得してみた

#何それ？
オンライン学習サイト[Coursera](https://www.coursera.org/)(コーセラ)でGoogleが提供している講座です。
**データ分析の工程を分析技術だけでなく、問題提起からデータの収集、
ステークホルダーへのプレゼンなどデータアナリストとしての動きを包括的に学べる内容になっていました。**

#受講のキッカケ
もともと私自身はデータ分析とはかけ離れた職種でしたが、去年の初めより機械学習を学び始めて、Kaggleに恋した人でした。ただ、**Kaggleではデータセットも親切に用意され、評価指標もこれだよって教えてくれて、分析する対象まで指定されている中で、実務ではこうはいかないよな〜**なんて考えていると、今回取得したGoogle Data Analytics Professional Certificateに出会ったというわけです。

#料金
講座は**サブスク制で月$38.88(約4300円)**でした。最初の一週間は無料で受講でき、この期間内であれば無料で退会できます。早く終われば安く済み、長ければよりお金がかかります。
**標準180時間の内容なので、週10時間くらい勉強できれば5ヶ月かからず取得できる計算になります。**

#内容はざっくりこんな感じ
あまり詳しく書くと怒られるかもなのでざっくりと。
実務でデータアナリストが問題発生の一報を受け取った際に、問題の本質を探るためのどのように思考、質問すべきなのか、他部署や上司と実際にどのように会話をして仕事を進めていくのか、そして手に入れたデータをどのように扱って、データ分析し、ステークホルダーに対して次の改善行動につながるプレゼンを行うのかについて学ぶことが出来ました。

**技術のところは、Google Spreadsheets(またはMS Excel)、SQL(Bigquery)、Tableau、Rのエントリーレベルを学べます。**ここら辺の知識がほぼない私みたいな人でも実際に渡されるサンプルで作業しながら進めることができ、ただ動画を見ているだけより定着出来たと思います。

感覚的には
**データアナリストとしての仕事の進め方(考え方) : 分析技術 = 50 : 50**
みないな比重だと思います。

前述しましたが、この講座は実際に自分の手を動かしてタスクを行う必要があるので、事前知識がない方には少しヘビーというか時間がかかります。ですが、とても丁寧に教えてくれるので一言一句取りこぼさないように聞けば、基本的にはスムーズに講座を進めることが可能です。

忘れてはいけないことがひとつ。
**講座は全て英語です。**
TOEIC700くらいあればついていけるのかなと思います。
動画には英語字幕がつけられるので私は活用しました。
自分の考えを文章で提出する形式のテストが多くあるので、文章力も必要かもしれません。ただそれの目的はすごい考えを持っているかのテストではなくて、**自分の中で実務を想像できているかを自ら問うことが目的**と思われるのでそれを念頭にしておけば大丈夫かと思います。

**とは言ってもオンラインなので、理解なしで進めていくこともある程度可能かもしれませんが、折角の機会なのでより現実的な状況を想定しながら学習を進めることが重要かと思いました。**

#最後に
学生時代に受けたかった。

#最後の最後に
データ分析の面白さを一層感じ、次のステップへのモチベーションになりました。皆さんも良ければどうぞ。

#最後の最後の最後に
Tableauすげぇ。
railsでYou must have ImageMagick or GraphicsMagick installedを解決する

railsで`ruby:X.X.X-alpine`ってdocker image使ってて`You must have ImageMagick or GraphicsMagick installed`ってエラーに遭遇した時は、次のコマンドで解決

```
$ docker exec {container name} apk add imagemagick
```

apkってのがalpine linuxのpackage managerなんだけど知らなくて時間食った。yumが使えなくてずっと泣いてた
(エラー)PluginlibFactory: The plugin for class 'jsk_rviz_plugin/NormalDisplay' failed to load

<発生した問題>
jsk_pcl_rosの法線推定を動作させたところ次のエラーが発生

```
PluginlibFactory: The plugin for class 'jsk_rviz_plugin/NormalDisplay' failed to load
```

<原因>

jsk_rviz_pluginが入っていない

<解決方法>

```
sudo apt-get install -y ros-melodic-jsk-visualization
```
[O(N×5!)] C - MAD / TEAM ZONeエナジー プログラミングコンテスト “HELLO SPACE”

# 問題
https://atcoder.jp/contests/zone2021/tasks/zone2021_c

##要旨

$i, j, k ∈ { 1, 2, ..., N }$
$min(max(A_i, A_j, A_k), max(B_i, B_j, B_k), ..., max(E_i, E_j, E_k))$ を最大化

## 考え

$N$が最大で3,000なので、全探索だと $_{3000}P_3$ = 4,495,501,000 でTLE。
中央値を探すときのように二分探索法がよさそう。
小問題は総合力を $k$ 以上にすることが可能かどうか。

仮に５人選んでよいのであれば、AからEそれぞれについての最強メンバーを集めればよいのであるが、実際には３人であるので兼任が必要となる。５種類の能力を３人（以下）で担当する必要がある。

ここで能力担当の分け方を軸に考え直す。
例えば分け方を AB | CD | E に固定した場合、N人の内の誰かがABを、誰かがCDを、誰かがEを満たせば条件を満たす。この「誰か」は重複が可能であり、例えばABCDEの能力全てを１人が担当するケースもカバーしている。
$\\{0 (=A), 1 (=B), 2 (=C), 3 (=D), 4 (=E)\\}$ から作られる順列を全列挙して、例えば {2, 0, 4, 3, 1} なら 能力の分担を CA | ED | B に対応させて判定し、分け方のうち一つでも要件を満たせばOKだ。できた!!!!サンプルも通った。GO!!!!! → WA

```rust:c.rs&#x20[WA!!!]
use itertools::Itertools;

fn main() {
    proconio::input! { n: usize, abcde: [[i64; 5]; n], };

    let mut left = 1;
    let mut right = 1_000_000_001;
    while right - left > 1 {
        let mid = (left + right) / 2;
        let mut res = false;
        for i in (0usize..=4).permutations(5) {
            let mut flag = [false; 3];
            for v in &abcde {
                flag[0] |= v[i[0]] >= mid && v[i[1]] >= mid;
                flag[1] |= v[i[2]] >= mid && v[i[3]] >= mid;
                flag[2] |= v[i[4]] >= mid;
            }
            res |= flag[0] && flag[1] && flag[2]; 
        }
        if res {
            left = mid;
        } else {
            right = mid;
        }
    }
    println!("{}", left);
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428825/74346e6f-60cc-b8bb-1193-0510b0ca5289.png)


……なんかコーナーケースで蹴られたっぽい。本番中はこれ以上の進展がなく、Dも解けず茶パフォ止まりとなった。

## 敗因

風呂に入りながら考えた。能力の分担方法を全列挙する。

- １人５役
- １人４役、１人１役
- １人３役、１人２役
- １人３役、１人１役、１人１役
- １人２役、１人２役、１人１役

2-2-1フォーメーションでは3-1-1への対策が出来ていなかった（他は全てカバーしている）。

## 発展
更には、能力の分担方法を固定した状態では総合力の最善値を直接求めることが可能（二分探索法が不要）なことに気がついた。例えばABC | D | Eの分け方であれば、ABCの最低値が一番大きい人、Dが一番大きい人、Eが一番大きい人を重複を許して連れてきて最低値を取ると、それがその分け方での最善のスコアとなる。
全ての分け方を走査して最大値をとれば、それがそのまま回答となる。
$O(N×5!)$であり、いらんくらい高速である。


```rust:c.rs&#x20[AC!!!]
use itertools::Itertools;
fn main() {
    proconio::input! { abcde: [[i64; 5]], };
    let mut ans = 0;
    for i in (0usize..=4).permutations(5) {
        let (mut s01, mut s23, mut s4) = (0, 0, 0);
        let (mut s012, mut s3) = (0, 0);
        for v in &abcde {
            let f = |x| v[i[x]];
            s01 = s01.max( f(0).min(f(1)) );
            s23 = s23.max( f(2).min(f(3)) );
            s4 = s4.max( f(4) );
            s012 = s012.max( f(0).min(f(1)).min(f(2)) );
            s3 = s3.max( f(3) );
        }
        ans = ans.max( s01.min(s23).min(s4) ).max( s012.min(s3).min(s4));
    }
    println!("{}", ans);
}
```

## 抱負

結果にめげず、マイペースで最良のアルゴリズムを追求し続ける。
（だから点が取れないというのに）
これが記事の初公開です。今後ともよろしくお願いします。
Raspberry Pi Picoでモータを動かす①（ユニポーラ１相励磁）

しばらく手に入らなかったRaspberry Pi PicoがGW前に手に入ったため、ステイホーム的に遊んでみる。
C/C++とMicroPythonのライブラリがあるが、基本MicroPythonで行くことにする。
何故？C/C++は飽きた…。

## 環境構築
まずはステッピングモータを回すということでモータを入手。
Ren He 5V ステッピングモータ+ 28BYJ-48 ULN2003ドライバーボード セット Arduino用 3個セット
という激安のステッピングモータ（3個セットで￥689）をAmazonで購入した。
こいつの良いところは安いところと5Vで動き、抵抗が200Ωであること。
つまり、USB電源で動く。

配線は下記とした
![ULN2003接続.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1391167/6fa56e2b-c44b-1b0e-d3ea-047b5b855c38.png)

このステッピングモータはユニポーラなのでとりあえず1相励磁で動かす
1相励磁はその名のごとく1相づつ動かす
そのためとても制御が簡単
コードは以下

```
from machine import Pin
import utime
IN1 = Pin(2, Pin.OUT)
IN2 = Pin(3, Pin.OUT)
IN3 = Pin(4, Pin.OUT)
IN4 = Pin(5, Pin.OUT)
wait_ms = 2
while True:
    # CW
    IN1.value(1)
    IN2.value(0)
    IN3.value(0)
    IN4.value(0)
    utime.sleep_ms(wait_ms)
    IN1.value(0)
    IN2.value(1)
    IN3.value(0)
    IN4.value(0)
    utime.sleep_ms(wait_ms)
    IN1.value(0)
    IN2.value(0)
    IN3.value(1)
    IN4.value(0)
    utime.sleep_ms(wait_ms)
    IN1.value(0)
    IN2.value(0)
    IN3.value(0)
    IN4.value(1)
    utime.sleep_ms(wait_ms)
```

CCWにしたい場合はINx.valueの回転方向を逆にすると良い
なお、wait_ms=1にすると脱調して動かなくなる。
カタログスペックでは
**無負荷周波数引き：>600Hz、無負荷周波数抜く：>1000Hz**
とまぁ分かりそうで分からないことが書いてあるが、1ms=1kHzが限界に近いのは事実のようだ。
Pandas で SQLite の Upsert(車輪の再開発)

# PandasでUpsertが待ちきれず、自作してみた

[PandasのSql Upsertを試してみた](https://qiita.com/mynkit/items/b329ce4f9d6c229382ff) を見て、Upsert なる言い方を知った（SQLiteの"INSERT OR REPLACE"は大昔使っていたけど）

これこれ、と思ったけど、まだリリースされていないいし(21年4月現在)、なんとPandas の `to_sql`だと、primary keyやunique keyが作れない。
（`SQLTable`/`SQLiteTable`には`keys`で指定できるけど、`to_sql`にない。Why?）

とりあえず、下記を参考にして、SQLite専用だけどUpsertを作ってみた。
[Python Pandas to_sql, how to create a table with a primary key?](https://stackoverflow.com/questions/30867390/python-pandas-to-sql-how-to-create-a-table-with-a-primary-key)

```python
def upsert(frame, name: str, unique_index_label, con):
    pandas_sql = pd.io.sql.pandasSQL_builder(con)
    
    if isinstance(frame, pd.Series):
        frame = frame.to_frame()
    elif not isinstance(frame, pd.DataFrame):
        raise NotImplementedError(
            "'frame' argument should be either a Series or a DataFrame"
        )
    
    # table = pd.io.sql.SQLiteTable(name, pandas_sql, frame=frame, index=False, if_exists='append')
    table = pd.io.sql.SQLiteTable(name, pandas_sql, frame=frame, index=False, if_exists='append', keys=unique_index_label)
    table.create()
    # pandas_sql.execute('CREATE UNIQUE INDEX IF NOT EXISTS "{0}_{1}" ON "{0}" ("{1}");'.format(table.name, unique_index_label))
    
    def _execute_insert(self, conn, keys, data_iter):
        wld = "?"  # wildcard char
        escape = pd.io.sql._get_valid_sqlite_name

        bracketed_names = [escape(str(column)) for column in keys]
        col_names = ",".join(bracketed_names)
        wildcards = ",".join([wld] * len(bracketed_names))
        insert_statement = (
            f"INSERT OR REPLACE INTO {escape(self.name)} ({col_names}) VALUES ({wildcards})"
        )
        data_list = list(data_iter)
        conn.executemany(insert_statement, data_list)
    
    table.insert(method=_execute_insert)
```

こんな感じで使用

```python
import pandas as pd
import sqlite3
from contextlib import closing

large_category_list = []
middle_category_list = []
for large_category in large_categories:
    large_category_list.append(dict(id=large_category['id'], name=large_category['name']))
    for middle_category in large_category['middle_categories']:
        middle_category_list.append(dict(large_category_id=large_category['id'], id=middle_category['id'], name=middle_category['name']))

large_category_df = pd.DataFrame(large_category_list)
middle_category_df = pd.DataFrame(middle_category_list)

with closing(sqlite3.connect(args.sqlite)) as con:
    upsert(large_category_df, 'large_categories', 'id', con)
    upsert(middle_category_df, 'middle_categories', 'id', con)

```


ちなみに、sqlite3には、下記を使ってExcelからもアクセス可能。
ExcelのTableの機能と合わせると結構便利かも(試行錯誤中)。
Webから取得したデータはSQLiteで管理(更新されたらupsertで対応)。
分析やデータの加工はExcelのテーブルとかで対応。

[SQLite ODBC Driver](http://www.ch-werner.de/sqliteodbc/)
32/64bitに注意。Excelは32bitだと思い込んでいてえらい時間くった。
インストールしたけど使えないのが、(ODBC初めてで)使い方ミスったと思って、インストールミスにすぐ気が付かなかった。。。
kswapが頻発してシステムが重い

AWSを触っているとシステムが重くなってきて、topを見たらkswapdの負荷がとても高かった

```
$ top
  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                                                                                       
   80 root      20   0       0      0      0 R 36.1  0.0  11:16.34 kswapd0
```

kswapの頻発を避けるために、とりあえずswap領域を32GB確保して収まった。

# 参考
[TOPコマンドでkswapd0 が出現したので再起動で対処した](https://blog.ybbo.net/2015/10/06/what-is-kswapd0/)
[UbuntuでkswapdがCPU使用率100％になる](UbuntuでkswapdがCPU使用率100％になる)
[Ubuntu/CentOSサーバのスワップ領域の割り当て](https://morizyun.github.io/blog/linux-swap-memory-space/index.html)
Ubuntu Server 20.04.2 LTS に SQL Server をインストールしてみた

# いまさら Ubuntu 触りだしてます
CentOS8のサポート期限問題で最近は、Ubuntu触ったりしてます。ちょうどPi4を触っているので丁度よかったのと、Debian系は割と食わず嫌いだったのでいいかな。と。

・[Ubuntuを入手する](https://jp.ubuntu.com/download)

# ライセンス形態
Microsoft SQL Serverは、利用形態によりライセンスが異なります。Free版でも商用利用できるのでちょっとしたサービスを作るにはいいかもしれない。

・[How to license SQL Server](https://www.microsoft.com/en-us/sql-server/sql-server-2019-pricing)
・[SQL Serverは無料で使える？価格プランごとの特徴とは](https://www.fenet.jp/dotnet/column/%E7%94%9F%E6%B4%BB%E3%83%BB%E4%BE%BF%E5%88%A9/245/#SQL_Server-2)

# Microsoft SQL Serverクイック スタート
Microsofのページがわかりやすい。これみればいいかもしれない。手順もシンプルで簡単にインストールできる。SAのパスワードを設定すればよい。

・[クイック スタート:Ubuntu に SQL Server をインストールし、データベースを作成する](https://docs.microsoft.com/ja-jp/sql/linux/quickstart-install-connect-ubuntu?view=sql-server-ver15)
・[SQL Server on Linux のインストール ガイド](https://docs.microsoft.com/ja-jp/sql/linux/sql-server-linux-setup?view=sql-server-ver15#system)

あとここらへんも

・[UbuntuServer20.04LTSにSQLServer2019をインストールする](https://xn--v6q832hwdkvom.com/post/ubuntuserver20.04lts%E3%81%ABsqlserver2019%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B/)
・[Ubuntu 18.04 LXC に SQL Server をインストールする方法](https://knkomko.hatenablog.com/entry/2020/07/05/025514)

# SSMSでアクセスする
SQL Server Management Studio (SSMS) は、SQL Server のすべてのコンポーネントを構成、管理、開発し、それらのコンポーネントへアクセスするための統合環境で基本的にSQL Serverの設定を行うことができるツール。立ち上げるのにちょっともっさりするけどなれると使いやすい。ただインストール時に毎回やってしまうのが、SSMSダウンロードデフォルトが英語版なんですよね。。。

・[Windows で SQL Server Management Studio を使用して SQL Server on Linux を管理する](https://docs.microsoft.com/ja-jp/sql/linux/sql-server-linux-manage-ssms?view=sql-server-ver15)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/d079322a-a9e0-7838-5178-0195bf3fbc4a.png)

# Azure Data Studio
最近は、SSMSでなく Azure Data Studio を使うのがいいらしい。軽くていいかもしれない。VSCodeと同じで日本語化するといいね。

・[Azure Data Studio とは](https://docs.microsoft.com/ja-jp/sql/azure-data-studio/what-is-azure-data-studio?view=sql-server-ver15)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/ff9c141e-7c5b-e7b7-f9e1-6025043d2b6f.png)


# Ubuntuの日本語化
日本語関連のパッケージをインストールしてシステムの文字セットを日本語に変更する。

```text
$ sudo apt -y install language-pack-ja-base language-pack-ja ibus-kkc
$ sudo localectl set-locale LANG=ja_JP.UTF-8 LANGUAGE="ja_JP:ja"
$ sudo source /etc/default/locale
```
TWELITEでEEPROM

# はじめに

　TWELiteは電力消費が少なく無線通信もできるスグレモノのマイコンだが、何しろ情報が少ない。MONO Wireless社のページにある解説はなかなかとっつきにくい。が、どうしても使いたいので、少しずつ勉強している。
　今回は、無線通信せず長時間データをロギングする方法について検討した。とはいえまだ机上の検討だが...。

# 保存先は？

　Arduinoを使っていた時の経験から、通常最初に思いつくのはSDカード。ただ、TWELiteからSDカードに読み書きする方法が見つからない。また、SDカードは電力消費が多いという話もあり、出来れば避けたい。
　EEPROMはマイコン本体に装着されているメモリの一種であり、容量が限られているものの、これを使うことも可能とのこと。確かに書き込む内容を厳選すれば、これでも良さそうだ。TWELiteは4kbyte弱くらいの容量を持つらしい。
　Mono Wiress社のホームページで調べると、以下のページにぶつかる。

[sdkのページ](https://sdk.twelite.info/hw-api-rifurensu/flash-eeprom/eeprom)
[mwxのページ](https://mwx.twelite.info/api-reference/predefined_objs/eeprom)

　また、mwxのページには[Unit_???](https://mwx.twelite.info/act_samples/unit_acts)もあり、どうやらAct_samplesの中にUnit_EEPROMというものがあるらしい。sdkのページに紹介されている内容はどうもピンとこないし、また、Act_samplesから始めるのはとっつきやすそうなので、ということで、Unit_EEPROMで試してみようか、と、思った。

　ここから、はまる。私の持っているMWSDKのAct_samplesの中にはUnit_EEPROMというファイルはない...。
　GoogleでUnit_EEPROMを検索し、Githubに見つけてそれをダウンロードして入手できた。
　さらにもう一つ難関があった。Unit_EEPROMをコンパイルしてTWELite Dipにアップしようとしても、エラーが出てコンパイルできない。「EEPROMなんてしらないよ」というようなエラーメッセージだ。[mwxのページ](https://mwx.twelite.info/api-reference/predefined_objs/eeprom)
の説明に#includeするべきファイルが抜けているのか...。
　
　解決策は、Unit_EEPROMの置かれていたGitHubページのMonoWirelessの[メインのページ](https://github.com/monowireless)から見出すことができた。[mwxへのリンク](https://github.com/monowireless/mwx)をクリックすると、EEPROM関連と思われるmwx_periph_eeprom.cppが存在する。また、このフォルダのファイルは/Applications/MWSTAGE/MWSDK/TWENET/current/src/mwx内のファイルとかなり一致している。/Applications/MWSTAGE/MWSDK/TWENET/current/src/mwxに[mwxへのリンク](https://github.com/monowireless/mwx)のファイルを上書きしたところ、ようやく「EEPROMなんてしらないよ」エラーが出なくなった。
LeetCode日本語修行18日目- [690-社員の重要性]

###Employee Importance
参考：https://leetcode.com/problems/employee-importance/
###問題の内容:
従業員情報のDBの中に、従業員の固有ID、重要度の値、直属の部下のIDが含まれています。
例えば、従業員1は従業員2のリーダーであり、従業員2は従業員3のリーダーであり、それぞれ重要度の値が15、10、5であるとします。すると、社員1は[1, 15, [2]]、社員2は[2, 10, [3]]、社員3は[3, 5, []]のようなデータ構造になります。なお、従業員3は従業員1の部下でもありますが、関係は直接的ではありません。
さて、会社の従業員情報と従業員IDがあれば、この従業員とその部下全員の重要度の合計値を返す必要があります。
###例:
例1:
Input: [[1, 5, [2, 3]], [2, 3, []], [3, 3, []]], 1
Output: 11
Explanation:
従業員1の重要度は5で、彼には2人の直属の部下、従業員2と従業員3がいます。つまり、社員1の重要度の合計は、5＋3＋3＝11となります。

###ヒント:
1.One employee has at most one direct leader and may have several subordinates.
2.The maximum number of employees won't exceed 2000.

---
普通の深さ優先探索を使って解決できます。

```Kotlin
/*
 *	// Definition for Employee.
 *	class Employee {
 *		var id:Int = 0
 *		var importance:Int = 0
 *		var subordinates:List<Int> = listOf()
 *	}
 */

class Solution {
    var map = HashMap<Int, Employee>()
    fun getImportance(employees: List<Employee?>, id: Int): Int {
        for ( employee in employees) {
            map[employee!!.id] = employee
        }
        return dfs(id);
    }
    private fun  dfs(id : Int) : Int {
        var employee = map[id];
        var total = employee!!.importance;
        var subordinates = employee.subordinates;
        for (subId in subordinates) {
            total += dfs(subId);
        }
        return total;
    }
}
```
golangのdeferでのエラー処理方法

# はじめに
`golangci-lint`で、こんなエラーでた。`defer`でエラーを返す関数をよんで、エラーを無視してたからみたい。

```Error return value of `t.Disconnect` is not checked (errcheck)```

# 修正前
こんな感じでやってた。 ローカルではtest通ってたけど、githubのCIでこけた。
もう、エラー無視してくれたらいいからって気分ではある。

```go
func (t *hoge) hogeFunc(arg []byte) (hogeError error) {
	ごにょごにょ
	if err := t.Connect(); err != nil {
		return err
	}
	defer t.Disconnect()
	ごにょごにょ
}

func (t *hoge) Disconnect() error{
	ごにょごにょ

}
```

## 修正後
調べると、無名関数にして、名前付き戻り値にしたエラーに代入したらよいみたい。`main()`内なら、`log.Fatal()`とかよんだらいいのかも。

deferのあとで、`return err`してるところもあったので、そのまま代入しちゃうとdeferのあとでエラーがでても握りつぶしちゃうから、`t.Disconnect()`がエラーのときだけ、代入した。deferのあとでエラーがあると、上書きしちゃうから、ほんとはappend的なことをしたほうがいいんやろうけど、サボった。

```go
func (t *hoge) hogeFunc(arg []byte) (hogeError error) {
	ごにょごにょ
	if err := t.Connect(); err != nil {
		return err
	}
	defer func() {
		err := t.Disconnect()
		if err != nil {
			hogeError = err
		}
	}()
	ごにょごにょ
}
```

# おわりに
deferで、エラーあったときどうなるんやろうと思ってたけど、CI通らなかったので真面目に調べて、多少すっきりした。
ただ、自信はないので、変なところあったら、指摘お願いしたいです。

# 参考
[【Go】 deferに渡した関数内のエラーを呼び出し元に返す - Qiita](https://qiita.com/vengavengavnega/items/fd0782c30574a983b8a5)
[Deferred Cleanup, Checking Errors, and Potential Problems -- Bleve](https://blevesearch.com/news/Deferred-Cleanup,-Checking-Errors,-and-Potential-Problems/)
JS~オブジェクト~

#概要
JavaScriptでは、配列とはオブジェクトから派生したデータ構造です。
プログラミングでは、配列の操作だけでなくオブジェクトの操作もあります。
オブジェクトの作成の仕方とアクセス方法、分割代入についての記事です。

今回使用するオブジェクトリテラルはこちらです。

```index.js
 menu = {
   name :'パンケーキ',
   price : '580円',
   set : '1000円' 
 };
```


#オブジェクトリテラル
```
{key名(プロパティ名):'データ'(プロパティ値)} ▶プロパティ
```
オブジェクトリテラルとはオブジェクトをプログラムに書く方法です。
オブジェクトリテラルは、{ }で囲い、各プロパティはカンマで区切ります。

#書き方
オブジェクトは、文字列に指定はありません。また文字列のように「''」「" "」で囲う必要はありません。
ハイフンなどの記号を使うとerrorになるのでその場合は囲う必要があります。

1.複数行

```index.js
menu = {
 name :'パンケーキ',
 price : '580円',
 set : '1000円' 
};
//{name: "パンケーキ", price: "580円", set: "1000円"}
```
このように入れ子にすることができます。

```index.js
const menu = {
  cake: {name:'ショートケーキ', price:'500円'},
  coffee: {name:'コーヒー', price:'400円'}
};
```

２．短く書く

```index.js
const name = 'パンケーキ';
const price = '580円';
const set = '1000円';

const menu ={name,price,set};

console.log(menu);
```

変数名だけをかき、変数名をプロパティ名、変数の値をプロパティ値にすることができます。


#オブジェクトへのアクセス

1.オブジェクト.プロパティ名

```index.js
 const name = 'パンケーキ';
 const price = '580円';
 const set = '1000円';

 const menu ={name,price,set};


 menu.name = 'ハンバーガー';//書き換え
 menu.price = '900円'; //書き換え

 console.log(menu);

 //{name: "ハンバーガー", price: "900円", set: "1000円"}

```

```index.js
const menu = {
  cake: {name:'ショートケーキ', price:'500円'},
  coffee: {name:'コーヒー', price:'400円'}
};

 console.log(menu.cake.name);
 console.log(menu.coffee.price);

```

2.オブジェクト['プロパティ名']

```index.js
menu['name'] = 'ハンバーガー';
menu['price'] = '900円';

```
どちらでもアクセスすることができます。

#プロパティの追加

```index.js
const name = 'パンケーキ';
const price = '580円';
const set = '1000円';
const menu ={name,price,set};

menu.name = 'ハンバーガー';
menu.price = '900円';

menu.drink = 'りんごジュース';
delete menu.set;

console.log(menu);

//{name: "ハンバーガー", price: "900円", drink: "りんごジュース"}

```

#分割代入

1.オブジェクトの分割代入

左辺に{}と変数名を書くことで、右辺のオブジェクトから変数名と同じ名前のプロパティを取り出すことができます。

```index.js
const menu = {
  name :'パンケーキ',
  price : '580円',
  set : '1000円' 
};

console.log(menu);
//{name: "パンケーキ", price: "580円", set: "1000円"}

const {name,price,set} = menu;

console.log(name,price,set);

//パンケーキ 580円 1000円
```

2.変数名を変える分割代入

```index.js
const{name:food,price:prices,set: setMenu} = menu;

console.log(food,prices,setMenu);
```

#残りのプロパティを取得

```index.js
const menu = {
 name :'パンケーキ',
 price : '580円',
 set : '1000円' 
};

console.log(menu);

const{name,...food} = menu;

//パンケーキ {price: "580円", set: "1000円"}
```
【VSCode】MacOS BigSurでpythonを実行するとWARNINGが出る時の解消法

## はじめに
MacOSをBigSurにアップデートしてから遭遇したエラーを解消したので、自分用のメモを。

##「問題が起きたためpythonを開けませんでした」
MacOSをBigSurにアップデートしてから出現した始めたこのポップアップ。なんやねん。
python2.xで実行していると出現するらしい。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527664/b92226ed-3f42-1f15-17d7-cba3d57bb055.png" width=30%>

## まずはMacOS側の設定
```q:TERMINAL.app
//あらかじめbrewをインストール済みであること！（👉http://brew.sh/index_ja.html）
$ xcode-select --install // xcodeのCommand Line Tool(CLT)を使えるようにする
$ brew update // Already up-to-date.が返ってこればOK
$ brew install pyenv //言わずと知れたpyenv様をインストールする
$ vim ~/.bash_profile // pyenvが提供してくれている自動補完機能を使えるようにする。zshの方は~/.zshrcに読み替えてください。
```

```bash:/.bash_profile
if [ `uname` = "Darwin" ]; then
  if [ -e /opt/homebrew ]; then
    HOMEBREW_ROOT=/opt/homebrew
  else
    HOMEBREW_ROOT=/usr/local
  fi
  export HOMEBREW_ROOT

  eval $(${HOMEBREW_ROOT}/bin/brew shellenv)

  export PIPENV_VENV_IN_PROJECT=true
  export PYENV_ROOT=${HOMEBREW_ROOT}/var/pyenv

  if command -v pyenv 1>/dev/null 2>&1; then
    eval "$(pyenv init -)"
  fi
fi
```

```q:TERMINAL.app
$ source ~/.bash_profile // bash_profileに書いた変更を反映する
$ pyenv --version //pyenvがインストールできたか確認する
$ pyenv install --list // インストールできるバージョンリストを確認する
$ pyenv install 3.8.5 // お待ちかねpythonをインストールする。お好きなバージョンを。
$ pyenv global 3.8.5 // インストールしたpython 3.8.5を使えるようにする
$ pyenv versions // 使えるようになったか確認する
$ python -m pip list // pipevを使う準備のために古いバージョンがすでにあるかを確認する
$ python -m pip install pip --upgrade // 古いバージョンがあるよ〜と怒られたらupgradeを実行する
$ python -m pip install pipenv // pipenvをインストールする
$ brew install pyenv-virtualenv // pyenvについてるpyenv-virtualenvも一緒にインストールする
```
```d:TEMINAL.app
// 💡pyenv-virtualenvのインストールで躓いたら下の2コマンド実行すると解消される

$ sudo rm -rf /Library/Developer/CommandLineTools
Password:
$ sudo xcode-select --install
xcode-select: note: install requested for command line developer tools
```

## vscode側の設定
1. vscodeを開いて、`Command⌘`＋`Shift`＋`P`を押してコマンドパレットを表示する。
1. `>Python:Interpreter`と入力して、「Python:インタープリターを選択」を選択する。
![interpreter01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527664/b8f247b8-ca47-a9cf-3bc8-adf21232d342.png)
1. 続いて、自分がインストールしたPythonバージョンを選ぶ。
![interpreter02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527664/e48ebfc4-04ac-bb0d-1991-e0145b913910.png)
1. vscodeのターミナルに表示されるpathが指定したpython3.x系の環境pathになる。

## おわりに
こちらの@crankcube様の記事を参考にしました🙏
https://qiita.com/crankcube/items/15f06b32ec56736fc43a

ありがとうございました〜〜
設定されている初期化パラメータがデフォルト値か判断する

- V$PARAMETER の ISDEFAULT 列から判断可能。


https://docs.oracle.com/cd/E82638_01/refrn/V-PARAMETER.html#GUID-C86F3AB0-1191-447F-8EDF-4727D8693754




- ISDEFAULT 列の値が TRUE なら **デフォルト値(または init.ora , spfile に指定されていない)**
- FALSE なら **任意に指定した値**

## 試しに db_writer_processes を変更してみる。

```sql

SQL> -- 変更前のパラメータ値確認
show parameter db_writer_processes;SQL> 

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_writer_processes                  integer     1

SQL> -- 変更前、デフォルト値か否かを確認
set lines 120 pages 1000
col name           format a35
col value          format a25
col isdefault      format a9
col default_value  format a25 

select 
  name,
  value,
  isdefault,
  default_value
from v$parameter
where name = 'db_writer_processes';SQL> SQL> SQL> SQL> SQL> SQL> SQL>   2    3    4    5    6    7  

NAME                                VALUE                     ISDEFAULT DEFAULT_VALUE
----------------------------------- ------------------------- --------- -------------------------
db_writer_processes                 1                       ★TRUE★    0

# ISDEFAULT 列が TRUE なので現在デフォルト値、またはspfileに指定されていない値となっている。

SQL> -- パラメータ値変更
alter system set db_writer_processes = 3 scope = spfile;SQL> 

システムが変更されました。

SQL> -- DB 再起動
shutdown immediateSQL> 
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。

SQL> startup
ORACLEインスタンスが起動しました。

Total System Global Area 1392508928 bytes
Fixed Size                  8620608 bytes
Variable Size             469763520 bytes
Database Buffers          905969664 bytes
Redo Buffers                8155136 bytes
データベースがマウントされました。
データベースがオープンされました。

SQL> -- 変更後のパラメータ値確認
show parameter db_writer_processes;SQL> 

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_writer_processes                  integer     3

SQL> -- 変更後、デフォルト値か否かを確認
set lines 120 pages 1000
col name           format a35
col value          format a25
col isdefault      format a9
col default_value  format a25 

select 
  name,
  value,
  isdefault,
  default_value
from v$parameter
where name = 'db_writer_processes';SQL> SQL> SQL> SQL> SQL> SQL> SQL>   2    3    4    5    6    7  

NAME                                VALUE                     ISDEFAULT DEFAULT_VALUE
----------------------------------- ------------------------- --------- -------------------------
db_writer_processes                 3                       ★FALSE★   0

# ISDEFAULT 列が FALSE なので指定した値がセットされている。
```
boto3 で EC2 のインスタンスのタグをつけたり消したりしたい

# 目的
EC2 のタグを操作したいpython を使いたいので前回使った AWS cli ではなくて boto3 を使う。

# やってみた

コマンドライン引数でインスタンスのIDや設定・削除するタグのKey、Valueを設定したい！

tag.py

```
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import boto3
import sys
from boto3.session import Session

def ec2_client():
    session = Session(profile_name='default')
    client = session.client('ec2')
    # profileの指定が必要ない場合
    # client = boto3.client('ec2')
    return client


def show_tag(instances=[]):
    response = ec2_client().describe_tags(Filters=[{'Name': 'resource-id','Values': instances}])
    print(response)

def create_tag(instances,key,value):
    response = ec2_client().create_tags(Resources=instances,Tags=[{'Key': key,'Value': value}])
    print(response)

def delete_tag(instances,key,value):
    response = ec2_client().delete_tags(Resources=instances,Tags=[{'Key': key,'Value': value}])
    print(response)

if __name__ == '__main__':

    args = sys.argv
    app_name  = args.pop(0)
    if len(args) != 4 :
        print('ex)' + app_name + ' show|create|delete instance_id key value')
        exit()

    command = args.pop(0)
    instances = args.pop(0).split(',')
    key = args.pop(0)
    value = args.pop(0)

    print('command:' + command )
    print('instances:' + str(instances))
    print('key:' + key)
    print('value:' + value)

    if command == 'show':
        show_tag(instances)
    elif command == 'create':
        create_tag(instances,key,value)
    elif command == 'delete':
        delete_tag(instances,key,value)
    else:
        print('first argument must be "show" , "create" or "delete"')

```

# 使い方

```
# 指定した id のインスタンスに設定されているタグを表示する key と val は使用されないが設定が必要（手抜き）
python tag.py show i-xxxxxxxx,i-yyyyyyyyy key val

# 指定した id のインスタンスに key , valu を設定する。既に key が存在する場合は上書きされる。
python tag.py create i-xxxxxxxx,i-yyyyyyyyy key val

# 指定した id のインスタンスに設定されている key , val を削除する。
python tag.py delete i-xxxxxxxx,i-yyyyyyyyy key val
```

# 調べて参考にしたサイト（感謝）

boto3 を使ったいい感じのサンプル

http://grmn.hatenablog.com/entry/2018/09/12/113250

python コマンドライン引数

https://qiita.com/taashi/items/07bf75201a074e208ae5

boto3 ドキュメント

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2.html#EC2.Client.create_tags

describe_tags は ページングとかいろいろできるっぽい
【Rails】DBにデータを取りに行ったときに、ActiveRecord::RecordNotFound と怒られた時の対処法

<h2>症状</h2>
Rails6.0.3でcontrollerからDBに対して、findでデータを取りに行ったとき、下記エラーメッセージが出てしまいました。

```ruby:humans_controller#show
def show 
    classroom_id = Classroom.find_by(id: params[:classroomId])
    human = Human.find_by(id: params[:id],classroom_id: classroom_id)

    render json: {
           human: human
　         }, status: :ok
    end
```

```ruby:findでエラー
app/controllers/api/v1/foods_controller.rb:26:in `show'
Started GET "/api/v1/classroom/1/human/2" for ::1 at 2021-05-02 00:16:30 +0900
   (0.1ms)  SELECT sqlite_version(*)
Processing by Api::V1::HumansController#show as HTML
  Parameters: {"classroom_id"=>"1", "id"=>"2"}
  Restaurant Load (0.3ms)  SELECT "classrooms".* FROM "classrooms" WHERE "classroom"."id" = ? LIMIT ? 
 [["id", nil], ["LIMIT", 1]]
  ↳ app/controllers/api/v1/humans_controller.rb:26:in `show'
Completed 404 Not Found in 174ms (ActiveRecord: 1.9ms | Allocations: 2232)

ActiveRecord::RecordNotFound (Couldn't find Classroom with 'id'={:id=>nil}):
```

下記記事で同様のエラーメッセージを発見。
<a src="https://qiita.com/nakayuu07/items/3d5e2f8784b6f18186f2#%E4%B8%BB%E3%82%AD%E3%83%BC%E3%81%8C%E8%A6%8B%E3%81%A4%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88">【Rails】find・find_by・whereについてまとめてみた</a>

そこには主キーが見つからない場合、上記のActiveRecord::RecordNotFoundと怒られる模様。

<h2>解決策</h2>
findをfind_byに変更したら、解決しました。

findだと、主キーに対してのみ条件づけするので、find(id)と書けます。
が、find(id: id)とは書けないため、idにnilが入ってしまい、結果として、主キーに該当するデータがないと怒られていたようです。

```ruby:find
#できる
id = 1
human = human.find(id)

#できない
human = human.find(id: 1)
```

find_byだと、主キー以外にも条件づけできるので、カラム名を指定する必要があります。
なので、下記のように条件づけるカラム名も一緒にしてできます。

```ruby:find_by
#できる
human = human.find(id: 1)

#できる
human = human.find_by(name: "太郎")
```

<h2>参考</h2>
【Rails】find・find_by・whereについてまとめてみた
https://qiita.com/nakayuu07/items/3d5e2f8784b6f18186f2
MacOS Big SurでFTDI系の周辺機器に接続

# はじめに

Big Surにしてから、IoT関連USB機器への接続について何かと不安を感じる。

-Arduno Unoは大丈夫だけど、シリアルアダプターを介してArduino Pro Miniと接続することができない。
-アダプターを介してXBeeに接続することもできない。
-TWELITEとは、TWELite Stageを介して接続することは可能だが、シリアルの信号を普通のシリアル通信ソフトで取り込むことができない。

これらを解決すべく、Big Surに以前のMacOSで動くバーチャルマシンを入れてみようと思いたった。

# 結果
## 
[@minnsou氏](https://qiita.com/minnsou/items/54491c01ac95a245b010)の記述をもとに、Virtual Box上にCatalinaをインストールした仮想マシンを構築した。いくつかハマった点を記録しておく。

- El Capitanのインストール用のファイル（El Capitan Install.app）を持っていたので、それをisoに変換してみた。isoファイルはうまくできたのだが、仮想マシンへのインストール時に、「書き込み可能なディスクをつかってインストールしてください」というような趣旨のエラーが出て、止まってしまう。Virtual Boxにiso以外の外部ディスク（特にUSBメモリ）を検出させるすべがよくわからない。困った...。
- 他のバージョンのインストールディスクを入手しようとしたが、私のBig SurだとダウンロードできたのはCatalinaだけ。そして、[@minnsou氏](https://qiita.com/minnsou/items/54491c01ac95a245b010)にはBig Sur上ではCatalinaは同ページの方法だとisoにできないと書いてある。が、やってみたら、変換できた！
- 無事に仮想マシンにCatalinaをインストールした。少なくとも、TweLiteはシリアル通信ソフトから検出できることが確認できた。

　なお、作業の途中でParallelsも試してみた。インストールや設定はParallelsが圧倒的に簡単だが、El Capianはisoファイルからはやはりインストールできなかった。App Storeからシステムファイルをダウンロードしようとするためのよう。
　動作もParallelsの方が快適。Virtual Boxだと時々マウス（トラックパッド）の動きが悪くなる。とはいえ、Virtual Boxでも再起動するとマウスの動きが良好になるようであり、私の要求する水準には達している。

　ホストのMacとフィイルをやり取りするために、Virtual Box上のCatalinaにはさらに、Google Driveを導入した。これで、ファイル交換にもあまり不便はない。

# その後（20210807追記）
[Longan nano氏のページ](http://blueeyes.sakura.ne.jp/2021/06/17/4045/)にFTDIのBig Sur対応ドライバーが公開されたとの記事。これでvirtual Machineは使わなくても解決。
ネットワーク機器諸元情報（Cisco、Juniper、PaloAlto、YAMAHA等...）まとめ

ネットワークエンジニアをしていると「あれ、この機器の大きさってどのくらいだっけ」「電圧いくらだっけ」などたまに調べたりする時がある。
「○○　機器諸元」や「○○　データシート」とかで調べてもいいけどいろんな機器をいつでも見つけやすくするために備忘として特に利用するサイトリンクを残しておくことにした。
もちろん日本語サイトで順不同。

更新履歴
■2021/06/05(土)　パナソニックLSネットワークスを追加
■2021/06/11(金)　富士通を追加
■2021/07/11(日)　NECを追加

#Cisco
[Cisco ルータ製品](https://www.cisco.com/c/ja_jp/products/routers/product-listing.html)
[Cisco スイッチ製品](https://www.cisco.com/c/ja_jp/products/switches/product-listing.html)
[Cisco ワイヤレス製品](https://www.cisco.com/c/ja_jp/products/wireless/product-listing.html)

自分の調べたい機器シリーズをクリック→【データシートを見る】をクリック

#Juniper
[Juniper ルータ製品](https://www.juniper.net/jp/jp/products-services/routing/)
[Juniper スイッチ製品](https://www.juniper.net/jp/jp/products-services/switching/)
[Juniper セキュリティ製品](https://www.juniper.net/jp/jp/products-services/security/)

自分の調べたい機器シリーズをクリック→【データシート】をクリック

#Paloalto
[Paloalto 次世代ファイアウォール製品](https://www.paloaltonetworks.jp/network-security/pa-series)

自分の調べたい機器シリーズの詳細クリック→【ダウンロード】をクリック
#YAMAHA
[YAMAHA 製品](https://network.yamaha.com/products)

製品一覧を見るをクリック→機器をクリック→【仕様】をクリック

#Fortinet
[Fortinet 次世代ファイアウォール製品](https://www.fortinet.com/jp/products/next-generation-firewall#models-specs)
[Fortinet セキュアSD-WAN製品](https://www.fortinet.com/jp/products/sd-wan#models-specs)

【製品】をクリック

#Allied Telesis
[Allied Telesis 製品](https://www.allied-telesis.co.jp/products/index.html)

調べたい区分をクリック→【製品】をクリック

#パナソニックLSネットワークス
[パナソニックLSネットワークス製品](https://panasonic.co.jp/ls/plsnw/product/index.html)

調べたい区分をクリック→調べたいシリーズをクリック→調べたい製品をクリック→PDFファイルの製品仕様書を選択

#富士通
[富士通製品](https://www.fujitsu.com/jp/products/network/)
調べたいプロダクトをクリック→調べたいシリーズをクリック→調べたい製品をクリック→「製品仕様」に諸元情報が載っている。マニュアルから仕様一覧を選択しても確認できる。
※Cisco社などの他社製品も載っている。

#NEC
[NEC製品](https://jpn.nec.com/products/net/index.html)
調べたいプロダクト（例えばスイッチ・ルータなど）をクリック→調べたいシリーズ（例えば【マルチレイヤスイッチ・ルータ】UNIVERGE IP8800シリーズなど）をクリック→調べたい製品をクリック→「仕様」や「諸元」に諸元情報が載っている。
※Juniper社などの他社製品も載っている。

#Radware
[Alteon](https://jp.radware.com/products/alteon/)→こちらのメーカーサイトだと、メールアドレス等記載しないと諸元情報が見れない模様（間違っていたらコメントください。

[他社(株式会社テリロジー)](https://www.terilogy.com/radware/alteon.html#01)
全てでは無いが、こちらから機器諸元情報を見ることも可能


#まとめ
物理周りのトラブルが多いので大きさや電力電圧は要チェック
買ったのは良いものの実は2U分の大きさでしたとか、200Vしか対応してないよとか怖すぎますからね。
セッションベースの権限セットとセキュリティ ⇒ 有効化フローへの容易なアクセスの作成

１．マークアップを使用せずに、エンドユーザが簡単に権限セットを有効化できるようにするにはどうすればよいですか?
２．フローを参照する Lightning アプリケーションページを作成するにはどうすればよいですか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/1f28f43b-6220-7082-14af-9c329a746c15.png)
Reactとの連携（１）

今回は「index.html.erb」表示まで

react用アプリケーション作成
-

```react:rails
rails new RailsReactApp --webpack=react
```

indexページ作る
-
```react:rails
rails g controller hello index
```
```rails:app/controllers/hello_controller.rb
class HelloController < ApplicationController
  def index
  end
end
```



indexファイルコーディング
-
```react:rails
<%= javascript_pack_tag 'hello_react' %>

<h1 class="display-4 text-primary">
Hello#index</h1>
<div id="hello"></div>
```

Viewファイル修正
-
```rb:app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>RailsReactApp</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <link rel="stylesheet"
    href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css
    bootstrap.css>
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>
```
Reactで表示完了
-

![20210502-001817.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/5bc63994-91a3-d351-1dd6-546cff39e421.png)

Reactを利用した処理が実行されています。
appフォルダ内の　JavaScriptフォルダ内にはpacksというフォルダがあり、この中にhello_react.jsxというファイルが用意されています。このスクリプトが読み込まれています。
*標準でReactコンポーネントのJavaScriptファイルについて、拡張子を「.js」ではなく「.jsx」にすることが推奨されている。
今日はここまで