OmniAICreator/Qiita-1.07M huggingface dataset:
DBeaver をインストールしたので記録しておく

SQL クライアントソフトの DBeaver をインストールしたので記録しておきます。


## 環境
OS：Windows 11 Home 64 ビット オペレーティング システム
CPU：Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz   1.80 GHz
RAM：16.0 GB

## ダウンロードとインストール
[https://dbeaver.io/download/](https://dbeaver.io/download/)
から Windows 64 bit (installer) を選択してダウンロードする。
インストール作業で特に難しいところは無いので、そこは省略します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/1314b087-9146-de2c-81ed-adf6882d90d6.png)

Sample DB も一緒にインストールすると初期画面はこのようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/d17cadad-405f-7d8f-32e7-9ec0cf5dbfcc.png)

## トピック
[データベース] - [新しい接続] を選択すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/5664eb5e-ddbf-e7e2-f971-e88251d0dc23.png)

接続できるデータベースが表示されます。
SAP HANA や Elasticsearch、Neo4j などが接続できるのが嬉しい。
今回はこの記録を投稿します。

### Popular
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/b73b09d6-c20a-2519-6d2e-3910b13f5358.png)

### SQL
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/4eba6a19-4468-3ed0-dd92-596f736bfee1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/c94f5154-241b-9772-e875-d0160e7082da.png)


### NoSQL
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/c4a8a3c3-c3be-d033-b88c-746fc164ca4b.png)

### Analytical
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/b9b33d5a-43c0-7091-7805-50d27131fa16.png)

### Timeseries
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/04afafab-c697-26db-3e59-4c6b3c9df4a0.png)

### Embedded
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/27832558-a99d-d33b-8d2c-29d4758cb8ef.png)


### Hadoop / BigData
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/212764f8-1975-00a7-2e7e-3187dc7955b9.png)

### Full-text search
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/dcfbfa26-86cd-b3b5-231c-36e5e1719709.png)

### Graph databases
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/ca9c8c96-66d7-b691-c671-7450cd9bd879.png)
cos類似度計算を高速に行う

## cos類似度計算の高速化
sickit-learnのcosine_similarity関数を使うと、cos類似度を一度に計算できる
    
- https://stackoverflow.com/questions/17627219/whats-the-fastest-way-in-python-to-calculate-cosine-similarity-given-sparse-mat

#### 悪い例
- 2重ループを回して類似度計算を1つ1つやっていた
  
```py
vector_list1 = [[0.3423, 0.5123, 0.4232], [0.1412, 0.9634, 0.7292]]
vector_list2 = [[0.6461, 0.8734, 0.9854], [0.1412, 0.9425, 0.8392]]
for vector1 in vector_list1:
    for vector2 in vector_list2:
        # 類似度計算
        similarity = calc_cos_sim(vector1, vector2)
```

#### 改修後
- 関数一発で実行。結果は2次元配列。

```py
from sklearn.metrics.pairwise import cosine_similarity

vector_list1 = [[0.3423, 0.5123, 0.4232], [0.1412, 0.9634, 0.7292]]
vector_list2 = [[0.6461, 0.8734, 0.9854], [0.1412, 0.9425, 0.8392]]
        
similarities = cosine_similarity(vector_list1, vector_list2)
[[0.2, 0.5], [0.1, 0.8]]
```

- また、ベクトルに0が多い場合は疎行列にしてあげるとさらに速くなるみたい
    - word2vecとかは0はないが、BagOfWordsだと使えるかも？
【C#】すべてのソースファイル(.csファイル)でUsingディレクティブを参照する方法

# 結論
`global using`を使います。

```C#
global using System.Diagnostics;
```

# 解説
`using`の前に`global`をつけることでそのプロジェクトのすべてのソースファイル(.csファイル)に`using`ディレクティブが適応されます。例えば、下記のソースコードをソースファイルに実装すると`エラー	CS0246	型または名前空間の名前 'Stopwatch' が見つかりませんでした (using ディレクティブまたはアセンブリ参照が指定されていることを確認してください)`というエラーが発生します。

```C#:エラーが発生するソース
var sw = new Stopwatch();

sw.Start();

Thread.Sleep(1000);

sw.Stop();

Console.WriteLine($"{sw.ElapsedMilliseconds}[ms]経ったぞ！");
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/8b8478eb-f343-495f-defe-ad016645fc23.png)
通常であれば`using`ディレクティブをソースファイルの上部に記載すればエラーは発生しなくなります。

```C#:エラーが発生しないソース
using System.Diagnostics;

var sw = new Stopwatch();

sw.Start();

Thread.Sleep(1000);

sw.Stop();

Console.WriteLine($"{sw.ElapsedMilliseconds}[ms]経ったぞ！");
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/e625da7b-d65d-a540-c7d0-9e0132e74793.png)

しかし、上記の実装だと`StopWatch`クラスを使用したいソースファイルの上部に毎回`using System.Diagnostics;`と記載する必要があり面倒です。そこで`global using`を使用します。今回は`_Imports.cs`というソースファイルを作成してその中に記載することにします。
まず、`_Imports.cs`ファイルを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/ef64fa57-42b4-bd66-ad36-c2011aca4604.png)
作成した`_Imports.cs`ファイルに`global using System.Diagnostics;`ディレクティブを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/1df8a15e-88c6-78d4-4edd-231194c2ded2.png)
こうすることで、`StopWatch`クラスを使用したいソースファイルの上部で`using`ディレクティブを記載しなくても良くなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/fc425e05-ed5c-cafc-b74b-e2b3e8914679.png)
また、`global`とかほざいてますがスコープは`プロジェクト`です。
なので、下記のように別プロジェクトでは参照されずにエラーが発生します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519245/cfd48231-e47d-1fdd-bf0f-1e9c6113d85e.png)

以上です。

# 追記(2022/02/10)
Using`ステートメント`と記載しておりましたが正しくはUsing`ディレクティブ`です。

Using`ステートメント`とusing`ディレクティブ`に違いは下記をご参照下さい。
>[usingステートメントとは](https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/using-statement)
>[usingディレクティブとは](https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/using-directive)
MongoDB を docker-compose で volume 使ったら mongo-express が動かなくなった

## 現象

久しぶりに MongoDB 使おうとしたら以前使っていた docker-compose（mongo-express の方）が動かなくなっていた。

```docker-compose.yml
version: "3.1"

services:
  mongo:
    image: mongo
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: user
      MONGO_INITDB_ROOT_PASSWORD: secret
      MONGO_INITDB_DATABASE: app_marketing
    ports:
      - 27017:27017
    volumes:
      - ./configdb:/data/configdb
      - mongoDataStore:/data/db

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: user
      ME_CONFIG_MONGODB_ADMINPASSWORD: secret

volumes:
  mongoDataStore:
    driver: local
```

こんなの。2020年9月にはこれで動いていた模様。mongodb は動くけど、mongo-express は動かない。

## 環境

docker: 20.10.11
docker-compose: 1.29.2

## docker hub の公式のものから作り直す

https://hub.docker.com/_/mongo

```docker-compose.yml
# Use root/example as user/password credentials
version: '3.1'

services:

  mongo:
    image: mongo
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: root
      ME_CONFIG_MONGODB_ADMINPASSWORD: example
      ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/
```

動く。
volume を追加


```docker-compose.yml
# Use root/example as user/password credentials
version: '3.1'

services:

  mongo:
    image: mongo
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example
    volumes:
      - ./configdb:/data/configdb
      - mongoDataStore:/data/db

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: root
      ME_CONFIG_MONGODB_ADMINPASSWORD: example
      ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/

volumes:
  mongoDataStore:
    driver: local
```

動かない。

## 原因と解決策

volume を使う場合は、mongo と mongo-express でネットワーク構成を共有しないと、この問題が起こる。

```docker-compose.yml
# Use root/example as user/password credentials
version: '3.1'

services:

  mongo:
    container_name: mongo-dev
    image: mongo
    restart: always
    networks:
      - mongo-compose-network
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example
    volumes:
      - ./configdb:/data/configdb
      - mongoDataStore:/data/db

  mongo-express:
    container_name: mongo-express
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    networks:
      - mongo-compose-network
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: root
      ME_CONFIG_MONGODB_ADMINPASSWORD: example
      ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/

networks:
  mongo-compose-network:
    driver: bridge
volumes:
  mongoDataStore:
    driver: local
```

これで動きました。
M1 Macでjuman++をインストールする(2022)

M1 Mac環境でjuman++をインストールしたらめっちゃ詰まったのでログを残します。

# 基本手順

基本的には[こちらの記事](https://dev.classmethod.jp/articles/pyknpjumann-tutorial/)にあるように、以下でインストールできます。

```
wget http://lotus.kuee.kyoto-u.ac.jp/nl-resource/jumanpp/jumanpp-1.02.tar.xz
tar xJvf jumanpp-1.02.tar.xz
cd jumanpp-1.02
./configure
make
sudo make install
```

# 詰まったところ
## "Error: cannot find available Boost library."
Boostが無いと怒られます。

```
checking for boostlib >= 1.57... configure: We could not detect the boost libraries (version 1.57 or higher). If you have a staged boost library (still not installed) please specify $BOOST_ROOT in your environment and do not give a PATH to --with-boost option.  If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.
configure: error: "Error: cannot find available Boost library."
```

[こちらの記事](https://qiita.com/Mohrey/items/fe5774a44e6ebb894f35)にあるように、Boostをインストールします。

Boostをダウンロードしたら展開して以下を実行します。

```
~/Downloads/boost_1_72_0
./bootstrap.sh
```

コア数を確認します。

```
system_profiler SPHardwareDataType
```

```
Hardware:

    Hardware Overview:

      Model Name: MacBook Air
      Model Identifier: MacBookAir10,1
      Chip: Apple M1
      Total Number of Cores: 8 (4 performance and 4 efficiency)
```

以下を実行します。

```
sudo ./b2 install -j9 --prefix=/opt/local
```

## Boost/unordered_map.hpp' file not found

juman++のインストールに戻り、makeを実行すると `fatal error: 'boost/program_options.hpp' file not found` が出ます。

[この記事](https://qiita.com/U-chom/items/87fab9d4a89b8ff53319)のとおり、HomebrewでBoostを入れ直します。

```
brew install boost
```

PATHも通しておきます。

```
echo 'export PATH="/usr/local/opt/icu4c/bin:$PATH"' >> ~/.zshrc
echo 'export PATH="/usr/local/opt/icu4c/sbin:$PATH"' >> ~/.zshrc
echo 'export LDFLAGS="-L/usr/local/opt/icu4c/lib"' >> ~/.zshrc
echo 'export CPPFLAGS="-I/usr/local/opt/icu4c/include"' >> ~/.zshrc
```

再度makeするのですが解消しないので、何故かと思ったら、どうやらM1版のBoostではだめなようです。
なので、Intel版のHomebrewをインストールしてそれを使います。

# Homebrew Apple M1 / Intel の共存環境を作る
[こちらの記事](https://www.nire.com/2021/02/homebrew-coexist-m1-intel/)を参照して、Homebrewの共存環境を作ります。
※M1版Homebrewのインストール手順は省略します。

Rosettaがない場合は先に入れておきます。

```
softwareupdate --install-rosetta --agree-to-license
```

Intel版Homebrewをインストールします。

```
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 
```

PATHを通すために `.zshrc` に以下を書きます。

```
eval $(/usr/local/bin/brew shellenv)
eval $(/opt/homebrew/bin/brew shellenv)
```

# juman++をインストールする
改めてjuman++をインストールします。

```
cd jumanpp-1.02
make
sudo make install
```

今回は成功しました。

```
~ jumanpp -v
JUMAN++ 1.02 
```
S3 クロスリージョンレプリケーションについて

## はじめに
AWS SAAの対策を必死にしている。
問題でつまづいた点などをこのQiitaにまとめておく。

## レプリケーションとは
レプリケーションとは、「複製」ということらしい。
レプリカという言葉なら馴染みがあるかもしれない。
この言葉から、レプリケーションは来ている。

## クロスリージョンレプリケーションとは
S3ではクロスリージョンレプリケーションという仕組みが備わってる。
これは、異なる2つのリージョン間にあるS3バケットを、自動的に非同期でコピーしてくれる仕組みらしい。
AI初学者が『ゼロから作るDeepLearning』のもやもやした点をまとめてみた

この度DeepLearningの勉強を始めました。
記念すべき１冊目は『ゼロから作るDeepLearning』という名著中の名著を選んだのですが、それでも初学者の私にはすぐに理解できない点が多くあったのでメモとして残しておこうと思います。

## 筆者のプロフィール
社会的属性：文系大学生４年
プログラミング経験：Java(Spring boot)2年, Flutter(1年)
　WebアプリとNativeアプリ双方の制作経験あり
　機械学習経験は初めて

## 4.2.4　【バッチ対応版】交差エントロピー誤差の実装
### 疑問点：教師データがラベルとして与えられた時の交差エントロピー誤差の中身なんかおかしくない？
#### one-hotの場合
```
def cross_entropy_error(y, t):
    if y.dim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)
   
    batch_size = y.shape[0]
    return -np.sum(t * np.log(y + 1e-7)) / batch_size
```
#### not one-hotの場合（問題の関数）
```
def cross_entropy_error(y, t):
    if y.dim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)
   
    batch_size = y.shape[0]
    return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7) / batch_size
```

これを見た時、「？？？？？」となりました。
one-hot形式の関数(以下「oh関数」)とnot one-hot形式の関数（以下「noh関数」）は出力が違うと思ったのです。

というのも、oh関数の場合はsoftmax関数の出力であるyのlogにtをかけています。
一方でnoh関数の場合は、単にlogyを足しているに過ぎないため、「t倍されてないじゃん！！！」と思ったからです。

結論から言うと、tは0または1のみなので、t倍した結果は0かyの値そのままなんですね。
t倍する意味は正解を選ぶ確率y\[i](iは正解のインデックス)を抽出するためなので、noh関数の場合はt倍する必要がなかったんですね。

その代わりnoh関数では、正解を選ぶ確率を抽出するために[(), t]としているんですね。

全部本に書かれているのですが、理解力のない私は理解するのに時間がかかりました。

## 4.2.5　なぜ損失関数を設定するのか？
### 疑問点：できるだけ小さな損失関数の場所を探すなら最小値を計算して求めれば良くない？
この疑問はナンセンスすぎますね。
DeepLearning以前の問題で、高校数学で高次元関数の最小値問題をきちんと解いておけばこんなこと思わないわけです。
でも筆者は疑問に感じてしまいました。

なぜ最小値を計算して出さないのか、それは出せない（出すのが難しい）からですね。
そこで、できるだけ最小の値を探す手がかりとして登場するのが勾配なわけです。

大変恥ずかしいことではありますが、これを理解するのに時間がかかりました。

##さいごに
ここまで読んでいただきありがとうございました。
今では筆者が完全に理解しているような書きぶりですが、いまだに1割も理解できていないと思います。
誤っている点等あれば是非教えていただければと思います。

また、理解が難しい点が見つかり次第追記していきたいと思います。

それでは、Good DeepLearning!
【Node.js】過去のバージョンへダウングレードする方法

# はじめに
新規のPJでNode.jsのv16をダウンロードしたら、別PJで使用していたv12が使えなくなったということがありました。その際にv12に戻すのに苦労したため、解決策を紹介していきます:point_up_tone1:

# 前提
- 公式サイトからNode.jsのインストールを2回行い、2回目のバージョンでローカルのNode.jsのバージョンが上書きされた
 - 1回目がv12で、2回目がv16です。
- nvm useコマンドによる切り替えができない
 - 通常はこのコマンドを使用した場合にはバージョンの切り替えが可能ですが、切り替えができませんでした。nvm availableコマンドを実行した際に変更したいバージョン(v12)が表示されないことが原因かなと考えています。

# 解決策（Windows）
1．PCの設定画面のアプリを開き、Node.jsをアンインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700107/d2b307b2-4429-35d4-d442-ae03f8e55d1b.png)
2.公式よりインストールし直します。
https://nodejs.org/download/release/v12.22.5/
※私は12.22．5をインストールしました
3.インストール後はセットアップします。

これで、過去のバージョンへダウングレード完了しました！

## さいごに
その後、nvm useコマンドでv12 →　v16 →　v12への変更はまだ怖くて試していません。
何かご存知の方いましたら、情報共有をお願いします:pray_tone1:
UiPath「アクティビティパックのバージョンアップ」するかしないか...

## 皆もすなるQiitaといふものを、儂もしてみむとてするなり。

と言う訳で、こん＊＊は！はなっち！です。

ロボットを作成して、安定稼働していますが、時折異常終了する事があり。。。
実に困った事に、そのロボが我がチームのメンバーが作成し、更にそのメンバーが退職してしまったりしていて。。。

無論、引継ぎは受けている訳なのですが、それでも数か月も経つと、すっかり忘れてしまうわけで。。。

解決の糸口は、ログファイル上の内容になる訳であります。

今回発生したのは、2018.4.4で作成したロボで、アクティビティの「表示名」から「セルに書き込み」で異常終了した事が判明しています。
この「表示名」がユニークになっていたので、対象箇所が特定できたのですが、従来より動いているので、何がおかしいのかが皆目面等が付かない。

ま、兎に角、「セルに書き込み」でどんなケースで異常終了するかを検証してみようと思ったのです（至極当然の行動）。

現在のUiPath Studioの版数は、2020.10.7です。

単純にダミーEXCELファイルを読み、適当な文字を、適当なセルに対して、「セルに書き込み」させる。ただこれだけのもの。

「セルに書き込み」のセル指定で、ありえないアドレスを指定して、同様のエラーメッセージが出ると思っていたら…

結果はそうではありませんでした。

【セルアドレスに変な情報"3"を指定】

|  バージョン  |メッセージ|
| ---- | ---- |
|2018.4.4|セルに書き込み: 範囲が存在しません。|
|2020.10.7|セルに書き込み: 範囲 3 は存在しません。|

【保護掛かってるセルアドレスを指定】


|  バージョン  |メッセージ|
| ---- | ---- |
|2018.4.4|セルに書き込み: 範囲が存在しません。|
|2020.10.7|"セルに書き込み: "Protect" を書き込もうとしているデータの形式が間違っているか、Excel がビジー状態です。<br>データが式である場合は、パラメーターの区切り記号としてコンマを使用していることをご確認ください。<br>また、値の編集中ではなく、ダイアログ ウィンドウがすべて閉じていることをご確認ください。|


おぉ！EXCELのアクティビティパックのバージョンが上がると、エラー時のメッセージが違っている！より分かりやすい内容になっている！


と、まぁ、再現試験にはならなかったのですが、アクティビティパックのバージョンによって、吐き出すエラーメッセージが進化している事がわかりました！

でしたら、今動いているロボが使っているアクティビティパックのバージョンを上位に上げてしまえばいいか！とも思うのですが、
流石にバージョンアップしただけではリリースできませんね。

というわけで、異常終了の対策を施し、現在の業務が遂行できるまでにして、動作検証用に共有いただいたファイルを使って、アクティビティパックのバージョンアップを考える事にしました。

##おわりに
いかがでした？

▼アクティビティも所詮人が作ったもの。利用者からの反響で、良いものになっていくんですね。
▼古いバージョンのロボは、新しい環境で動くことは保証されていますが、何時までも古いバージョンのままでは、有事の調査が難しくなる場合がありますね。
▼かといって、どんどん新しいバージョンに上げていくのは、やれまたロボットのインストールしなければならないとか、CONFIGファイルを見直ししなきゃならないなど、却って迷惑になってしまう事もありそうですね。
▼というわけで、安定稼動しているロボットはそのままに、異常終了したタイミングが、バージョンアップを検討するタイミングかもしれませんね。

今回も読んでいただきありがとうございました！
是非UiPathでのロボ開発の一助になればと思っています。

ありがとうございました！
【メモ】Node.jsでAPI通信するサンプル実装

下記の動画のメモです。

ゼロから半年でWeb系エンジニアになろう【完全まとめ版】
https://www.youtube.com/watch?v=O9D18lhLa2Y

```sh
# expressをインストール
npm i express
```

```js:app.js
const express = require('express')
const app = express()
const port = 3000 //通信の宛先を区別する　どのアプリケーションと通信したいのか識別するもの
let booklog = {} //初期化する

app.use(express.json())

// 投稿POSTする
app.post('/booklog', (req, res) => {
  booklog = req.body

  if (!(booklog.name && booklog.text)) {
    res.json({
      "ok": false,
      "error": "invalid parameter"
    })
  }

  res.json({
    "ok": true,
    "booklog": booklog
  })
})

// 取得する
app.get("/booklog", (req, res) => {
  res.json({
    "ok": true,
    "booklog": [
      booklog
    ]
  })
})

// ポート3000番でサーバーを立ち上げる
app.listen(port, () => {
  console.log(`App listening at http://localhosst:${port}`)
})

```

```sh
# サーバーを起動する
node app.js
```

## API通信するための叩くコマンド
```sh
# POST
curl -X POST -H "Content-Type: application/json" -d '{"name":"キングダム", "text":"熱い"}' localhost:3000/booklog

# GET
curl -X GET -H "Content-Type: application/json" localhost:3000/booklog
```
Golangの環境設定(Mac編)

#記事作成にあたって
Goの環境設定は様々な経緯があり、資料によってPath設定が様々。せっかくやる気出して始めたのに、環境設定で息詰まるのはよくある話。Goは特にPath設定が面倒なので、本記事を参考に設定してもらえると楽です。

#環境設定情報
PC：Mac(CPUはintel製)
Go：1.17.6 ←Goのver大事。versionは1.16以降をインストールしてください。
開発エディタ：Visual Studio Code

#Golangのインストール
　https://go.dev/　 からインストール。
　versionは1.16以降をダウンロードください。

#Pathの設定
①ターミナルを開き、zshrcに2行追加。

```shell:zshrcの設定
vi ~/.zshrc ← zshrcを開く
#go言語
export GOPATH=$HOME/go 
export PATH=$GOPATH/bin:$PATH
```

②環境変数に反映。(ターミナルの再起動でもOKです)　

```shell:環境変数の反映
source ~/.zshrc
```

#VSCodeの設定
①拡張機能のインストール
![スクリーンショット 2022-02-09 19.40.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/b7249e42-a760-4754-c2fa-f3c35688c710.png)

②コマンドパレットで、install/update Toolsで検索
![スクリーンショット 2022-02-09 19.41.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/883c61ec-cf55-8078-ec78-317bb5607a88.png)

③全てのツールにチェックを追加。
![スクリーンショット 2022-02-09 19.42.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/a85aa2f0-0823-3f9b-004a-04570371c77d.png)

④setting.jsonを開き、go.gopathを設定。
![スクリーンショット 2022-02-09 19.43.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/ad689324-0acc-4d2c-0f54-f8507577734f.png)

#プログラム作成
　では実際にプログラムを作成してみましょう。
①GOPATHディレクトリにsrcディレクトリを作成。

```shell:srcディレクトリを作成
　cd $GOPATH
　mkdir src
```
②srcディレクトリ配下にhello.goを作成

```go:hello.go
package main

import "fmt"

func main(){
	fmt.Println("HelloWorld!! Golang!!!")
}
```

③go modを追加

```go:gomodを追加
go mod init hello
```

④hello.goの実行

```go:hello.goの実行
~/go/src $ go run hello.go 
HelloWorld!! Golang!!!
```
KMK を ItsyBitsy M4 Expressへ導入する

# KMK を ItsyBitsy M4 Expressへ導入する

今回は持て余しているItsyBitsy M4へ導入するものの、Raspberry Pi picoなどでも同じ手順で可能なはず。

とりあえず動くところまでを試す。

## CircuitPythonのインストール

[CircuitPython.org](https://circuitpython.org/) からダウンロード。

インストール方法についてはダウンロードページの各マイコン向けページの下の方からTutorialを辿って見られるAdafruitのドキュメントを参照。

[ItsyBitsy M4 Expressのダウンロードページ](https://circuitpython.org/board/itsybitsy_m4_express/) > [ItsyBitsy M4 ExpressのTutorialページ](https://learn.adafruit.com/introducing-adafruit-itsybitsy-m4) > [CircuitPythonのインストール方法についてのページ](https://learn.adafruit.com/introducing-adafruit-itsybitsy-m4/circuitpython)

## KMKの入手

- [download kmk_firmware](https://github.com/KMKfw/kmk_firmware/archive/refs/heads/master.zip)

Zipファイルを解凍して中にある**KMK**フォルダと**boot.py**をItsyBitsy M4 Expressへコピー。

- KMKをLibへ
- boot.pyをルートディレクトリへ

## code.pyの作成

[Getting started](https://github.com/KMKfw/kmk_firmware/blob/master/docs/Getting_Started.md#tldr-quick-start-guide) を参考に**code.py**を書いてボードに保存。

ItsyBitsyで動作させるためにピンの設定は変更。

### 変更前

```python
keyboard.col_pins = (board.GP0,)
keyboard.row_pins = (board.GP1,)
```

### 変更後

```python
keyboard.col_pins = (board.A0,)
keyboard.row_pins = (board.A1,)
```

## 配線

A0 → SW → A1

ここまでの作業でボタンを押すと「a」が入力できる1キーキーボードが出来る。

## 今後

ここまでの手順で1つボタンのキーボードは出来て、普通のPCでならこのまま使うことが可能と思うし、マトリックス配線で複数のキーを扱うのもそんなに難しくはないはず。

利用していると気になるのはドライブやCDC（シリアル）が有効になっているあたり。

CircuitPythonではそのあたりを無効にすることは可能ではあるものの、KMKを利用せずにキーボードエミュレーションをした場合、ドライブやCDCを無効にしてもNintendo Switchなどの特定ハードウェア上ではキーボードとして動作できない。これが困る。

QMKでは動作するのを確認しているのでKMKで同じように動作が可能なのかを探るのが今後の目標

-----

## 追記

ドライブとCDCを無効にするためのコードをboot.pyに入れる。
GNDとD11が接続されている場合はドライブとCDCが無効になる。

```python
import supervisor
import board
from digitalio import DigitalInOut, Pull
import storage
import usb_cdc

supervisor.set_next_stack_limit(4096 + 4096)

p11 = DigitalInOut(board.D11)
p11.pull = Pull.UP

if p11.value == False:
    storage.disable_usb_drive()
    usb_cdc.disable()
```

しかし、やはりNintendo Switchではキーボードとして動作しなかった。
Safe Software FMEを使ってMicrosoft SharePoint上のデータにアクセスする

# 前提
FMEからSharePoint上のデータへアクセスするために、パッケージを利用する方法を用います。


# SharePoint Online パッケージのインストール

とりあえずこちらをインストール。
FMEの開発元であるSafe Software自らが作ってくれています。（最初から入れといてもいいのに）

https://hub.safe.com/publishers/safe/packages/microsoft-sharepoint

> The connection to SharePoint is established with a web connection using the Microsoft SharePoint Online (safe.microsoft-sharepoint) service. Published workspaces for FME Server 2019 will require a user provided client id and secret.

説明にあるように、SharePointに接続するためのClient IDとClient Secretを取得する必要があります。

# Client IDとClient Secretの取得
Azureにてアプリケーションを作成し、接続に必要な2つを取得します。
Client IDはアプリケーションを作成すれば自動的に付与されます。
![スクリーンショット 2022-02-09 18.39.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647095/0df2e51d-7034-e067-5379-d51cdbf7d55f.png)

Client Secretは、[証明書とシークレット]から生成できます。
![スクリーンショット 2022-02-09 18.37.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647095/2d839383-e22e-217b-f38d-709815a2649d.png)

# リダイレクトURI、パーミッションの設定
認証応答を返す場所を`https://localhost/`に設定します。
もしかしたらデフォルトでなっているかもしれません。
![スクリーンショット 2022-02-09 19.00.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647095/f11483c4-bc27-e99c-80ac-8afcf77d0499.png)

パーミッションの設定も必要です。
[Microsoft Graph] -> [委任されたアクセス許可] を選択後、[Sites.ReadWrite.All]にチェックを入れればOKです。
許可項目は検索ができるので、`site`とかで検索すると早いです。![スクリーンショット 2022-02-09 19.11.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647095/b99f86ea-a0fb-1f5c-5cca-ae1ab6cf8025.png)

# ウェブ接続の設定
FMEに戻ります。
[ツール] -> [FME オプション]を開き、ウェブ接続の「サービスの管理」ボタンを押します。
![スクリーンショット 2022-02-09 19.17.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647095/e24a6a65-6e0e-1c05-d0e4-de8dbc3cf4b2.png)

`safe.microsoft-sharepoint.Microsoft SharePoint Online` を選択し、Client Infomationに先ほど取得した情報を入力します。
![スクリーンショット 2022-02-09 19.22.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647095/d86a031a-be1b-e5a8-e60b-85ba98acda1c.png)

入力を終えたら適用し、ひとつ前の画面で接続を追加します。
先ほどの`safe.microsoft-sharepoint.Microsoft SharePoint Online`を選択し、Authenicate...を押します。
アカウントを選択し、サインインができれば準備は完了です。
![スクリーンショット 2022-02-09 19.30.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647095/10842d3b-d3ab-f552-a023-4d0e9bd062f3.png)

# SharePointのデータにアクセスする
今回は例としてSharePoint上のExcelを読み込みます。
リーダーの追加で`Microsoft Excel`をフォーマットに指定し、データセットから先ほど追加したSharePointを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647095/727de48c-5a96-5f3f-ebe9-3a089e341a5e.png)

アカウント、サイトやライブラリ、パスを選択してお目当てのファイルを選択すればOKです。


![スクリーンショット 2022-02-09 19.37.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647095/63ab3727-1ae6-5782-48c3-953ebdb9a31c.png)
favicon 設定しようよ


# ① 素材をダウンロード
https://www.flaticon.com/

# ② faviconを自動作成
https://favicon.io/favicon-converter/


# ③ ダウンロードしたファイルの変更

site.webmanifest を manifest.json に変更

```manifest.json

"name":"ころちゃんクラブ",
"short_name":"ころちゃん"

```




# ④ head に追記

```vue.blade.php

<link rel="shortcut icon" href="/favicon.ico">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/manifest.json">

```

`OK`
本物のプログラマはタイムリープを恐れず使う

普通にプログラマが生活する上で時間を戻すということはあまりない。
しかし場合によってはプログラマは時間を戻すという行為に手を出すことがある。
そのような話をここでは書いていこうと思う。

1. バックアップからデータ復旧するときにプログラマはタイムリープを使う

HDDが吹っ飛んだ。大変だ。こんなこともあろうかとバックアップしておいたデータがある。
バックアップからデータを復旧しよう。

2. githubからプログラムを巻き戻す。

プログラムを色々修正したが大きな間違いをしてバグを組み込んでしまった。
こんなこともあろうかと github にバックアップがあるので３つ前のバージョンに戻そう。

3. トランザクションでロールバックを使う。

DBを操作中にエラーが発生してしまいデータの不整合が起きそうなとき、プログラマはトランザクションを開始し成功したらコミット、失敗したらロールバックをしてなかったことにします。
どうも普通のプログラマにとって時間を戻すのは不吉なことが多いです。

4. パーサコンビネータでバックトラックをする。

本物のプログラマは時間を戻すことを前向きに行います。
パーサを作る際にパーサを組み合わせて大きなパーサを作るパーサコンビネータという手法があります。
パーサコンビネータは予想された文法に従った文字列が入力されれば成功し結果を返しますが、失敗した場合は分岐点までバックトラックして次の選択をするような処理を行います。

5. Prologでバックトラックをする。

Prologのバックトラックは強力です。汎用的にバックトラックを用いてパーサを普通のプログラムとして書いて失敗したらやり直す機構が言語自体が持っています。
通常のプログラムでは分岐のチェックをすることで論理的な不整合があった場合に巻き戻すというような処理は行話なかったり、パーサコンビネータのように必要な時だけバックトラックの仕組みを作って巻き戻すことをしますが、Prologは常にバックトラックを使います。パターンマッチガードの一線を超えてプログラムを進め破壊的と思えるような変数の変更を行いますが、途中で問題が起きれば何もなかったかのように分岐点に戻って次の分岐の処理を行います。

Prologのプログラムはタイムリープを使いこなすような普通の感覚ではあり得ないことをします。なので使い方が分かっても気持ち悪いふわふわした気持ちになります。しかし使い慣れることで当たり前になるのでその感覚に慣れてネイティブ感が出るまで使ってみると４次元空間を操作する魔術師のような感覚が得られて使いこなすことができるようになると思います。

例えばFizzBuzzのプログラムをPrologで書いてみましょう。

```prolog
fizzbuzz(I,fissbuzz):- 0 is I mod 3, 0 is I mod 5,!. %世界線1
fizzbuzz(I,fizz):- 0 is I mod 3,!.%世界線2
fizzbuzz(I,buzz):- 0 is I mod 5,!.%世界線3
fizzbuzz(I,I).%世界線4

:- forall(begin(I,1,20),(fizzbuzz(I,R),writeln(R))).
:- halt.
```

このプログラムは4つの世界線がありすばる君はレベル1から20までで生まれてfizzbuzzの世界に送り込まれます。
レベル１のすばる君は世界線1で3でお主は割り切れるか。割り切れないな。死ね。ということで殺されてしまいます。しかしすばる君は次の世界線２で生き戻ります。3で割り切れないので死ね。世界線3で生き戻りします。5で割り切れるか。割り切れないなら死ね。世界線4で生き返ります。そのまま数値を返せ。レベル１すばる君は１を持ち帰ります。
レベル３のすばる君はfizzを持ち帰ることができるでしょうし、レベル５のすばる君はbuzzを持ち帰る。
レベル15のすばる君は最初の世界線である `fizzbuzz(I,fissbuzz):- 0 is I % 3, 0 is I % 5,!` を旅します。Iは3でも割り切れるし5でも割り切れるのでfizzbuzzを持ってすばる君は帰ります。

というようにタイムリープをしまくるイメージでプログラムするのです。
sftpの設定ではまったこと

## はじめに

sftpの設定をしようとして、全然接続出来なくてはまったので、残しておきます。

## 前提

以下の設定でパスワード認証で接続できるようにします。

|項目|設定値|
|-|-|
|ユーザ名|sftpuser|
|パスワード|sftp1234|
|ホーム|/var/share/sftpuser|

## グループの追加

sftp用のユーザを設定します。

```
sudo groupadd sftp
```

## openssh-serverの設定

デフォルトでsftpの設定は有効になっているはずです。

sftp用の設定を追記します。

```
Match group sftp
    ChrootDirectory ~
    ForceCommand internal-sftp
    PasswordAuthentication yes
    AllowTCPForwarding no
    X11Forwarding no
```

その後sshdを再起動します。

```
sudo systemctl restart sshd
```

## ユーザ設定

前提の設定でユーザを作成します。

```
sudo useradd -b /var/share -m --password $(perl -e 'print crypt("sftp1234", "\$6\$salt")') -g sftp -N sftpuser
```

ChrootDirectoryに指定したフォルダは、rootのみに書き込み権がある状態にしないとエラーになるため、変更します。

```
sudo chown root /var/share/sftpuser
sudo chmod 755 /var/share/sftpuser
```

データ格納用フォルダを作成します。

```
sudo mkdir /var/share/sftpuser/data
sudo chown sftpuser:sftp /var/share/sftpuser/data
```

確認します。

```
ls -la /var/share/sftpuser
total 12
drwxr-xr-x  3 root     sftp  74 Feb  9 18:08 .
drwxr-xr-x 12 root     root 174 Feb  9 18:02 ..
-rw-r--r--  1 sftpuser sftp  18 Jul 28  2018 .bash_logout
-rw-r--r--  1 sftpuser sftp 193 Jul 28  2018 .bash_profile
-rw-r--r--  1 sftpuser sftp 231 Jul 28  2018 .bashrc
drwxr-xr-x  2 sftpuser sftp   6 Feb  9 18:08 data
```

## まとめ

- ChrootDirectoryで指定するフォルダに気を付けましょう。（エラーがわかりにくい）
- 自動的にまとめて設定できるようにシェルスクリプトを作成しておくとよいでしょう
Prologはなぜ気持ち悪いのか

Prologが嫌いというプログラマは多いと思います。
色々理由は言われていますが、新たな説を思いついたので書いてみようと思います。

Prolog が気持ち悪い本当の理由とはタイムリープを使いこなす貪欲の魔女のようなことを何度もしなくてはならないからではないかと思います。普通の人は当たり前ですがタイムマシンに乗って時間を行ったり来たりしませんし、すばる君が失敗したら生き戻りさせてやり直させるということもしません。

しかしながら、Prologのプログラムでは失敗したらなかったことにして別な世界線が始まり別の選択を実行し始めます。そして失敗したらまた突然時間が巻き戻って別な世界線の別な選択が始まります。

我々は経験的に、普通の生活をしていてさまざまな計画を立てます。その計画では雨天の時は中止であるとか決行であるとか決めたりはします。事故が起きれば中止とかになります。

ですから普通のプログラムでも同様に計画を立てて、事故が起きたら中止するようなプログラムを書きます。

しかし、Prologのプログラムは違います。事故が起こったらなかったことにして時間を巻き戻して何事もなかったかのように別の世界線が始まります。これは気持ち悪いです。あり得ない感覚があります。

この時間を操作する感覚に慣れるには時間がかかります。４次元空間に慣れろと言われているようなものなので簡単に慣れられるものではありません。

だから普通のプログラマはPrologが嫌いなのではないかと思います。
ブログでrel属性を埋め込むときのタグと埋め込み位置についてメモしておく

特に、Googleの検索エンジン向けなのですが、rel属性の理解やアップデートは結構重要な部分でもあるのでメモしておきます。

ベタ打ちというか、コピペでrel属性を埋め込んでいきたいときに利用する用のメモ記事です。

内容的には外部リンクを埋め込む時のrel属性についてです。

rel属性のタグは正確に記述するように努力しますが、その効果についての見解は公式を参照していただき、それ以外の個別に書いてあることは<b>筆者の見解であって100%正解ではない</b>ことをご理解ください。

文献、参照については本文の最後に外部リンクをdofollowのまんま載せておきます。

<h2>前提条件</h2>

<ol>
<li>CMSはWordPress
<li>埋め込むときは「カスタムHTML」を使用
<li>WordPressテーマやSEOプラグインによってはリンクのrel属性をプルダウンで設定出来たりするので意味ない場合もあり
</ol>

<h2>dofollow属性について</h2>

dofollowは、特にrel属性を指定しなければdofollow扱いとなりますので、打ち込む必要はないかと思います。

<h2>nofollow属性について</h2>
nofollow属性については、あまり関係のないページにリンクを貼るときとか、被リンクする必要性がない場合に利用する促成なのですが、特別、アフィリエイト広告などで"nofollow"が指定されていない時は、最近の筆者の場合では使用していない属性です。

リンク先がSSL(https)を適用していないとか、リンクが切れるかも...っていうときには埋め込むかもです。

nofollow属性の埋め込みは
```
<a rel="nofollow" href="リンク先のページURL">テキスト</a>
```
になります。

ただ、特にブログ記事の場合、参考になるモノをリンクすると思うので、広告関連は別として、それ以外ではnofollow属性を使う状況ってあまり出てこない気がする...。けど書いておきます。

「<a」から半角空けて埋め込んで、また半角空けて、というイメージで大丈夫です。

<h2>sponsored属性について</h2>
広告として商品サービスを紹介して外部リンクを埋め込むときに使用するrel属性になります。

が、アフィリエイトで各ASPの注意事項に「コードをいじると〜」と書いてある以上いじりにくいところではあるかなと思います。

直広告でやりとりしている場合などは、もうrel="sponsored"にした方が良いかもです。

sponsored属性の埋め込みは
```
<a rel="sponsored" href="リンク先のページURL">テキスト</a>
```
になります。

こちらも「<a」から半角空けて埋め込んで、また半角空けて、というイメージで大丈夫です。

<h2>ugc属性について</h2>
ブログ運営などの場合は、あまり意識する必要のない属性かもですね。

最近は、パブリックにコメントで議論をするブログサイトも少なくなったと思うのであまり利用しないし、自分で埋め込むこともないかもです。

ugc属性の埋め込みは
```
<a rel="ugc" href="リンク先のページURL">テキスト</a>
```
またたこちらも、「<a」から半角空けて埋め込んで、また半角空けて、というイメージで大丈夫です。


以上になります。

ブログ記事を書くときにrel属性を付ける用でブックマークします。

<h2>参考文献</h2>
<a href="https://developers.google.com/search/docs/advanced/guidelines/qualify-outbound-links?hl=ja"_blank" rel="noopener noreferrer">
  ● Google検索セントラル｜Google に外部リンクの関係性を伝える
</a>

<a href="https://unicorn-blog.jp/archives/20599"_blank" rel="noopener noreferrer">
  ● アンカーリンクでSEO内部対策を行う方法を初心者向けに分かりやすく解説
</a>
VSCode でよく利用するエディター・サイドバー・パネルを操作するショートカット

ショートカットが覚えられない族のため、3日で忘れてしまう。
タイトルの用途で本当によく使っているものだけまとめます。

便宜的に書き3つに分けて memo.

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19223/4c729975-6de5-3bd8-3c9f-88beb042b0a7.png)


## Editor

表示しているエディター間を移動する。

- macOS: `ctrl + tab`, `ctrl + shift + tab`
- Windows: `ctrl + tab`, `ctrl + shift + tab`

https://qiita.com/DriftwoodJP/items/cdb7e01a1d15ac0aae5d

指定した行にジャンプする。

- macOS: `ctrl + g`
- Windows: `ctrl + g`

## Sidebar

サイドバーを表示する。

- macOS: `cmd + b`
- Windows: `ctrl + b`

### サイドバーを開いた後

割り当てが直感的なものを利用。

エクスプローラー（ファイルリスト）

- macOS: `cmd + shift + e`
- Windows: `ctrl + shift + e`

検索

- macOS: `cmd + shift + f`
- Windows: `ctrl + shift + f`

デバッグ

- macOS: `cmd + shift + d`
- Windows: `ctrl + shift + d`


## Panel

パネルを表示する。

- macOS: `cmd + j`
- Windows: `ctrl + j`

https://qiita.com/DriftwoodJP/items/7b0db35d99cd03350b83

### パネルを開いた後

割り当てが直感的でない。覚えられそうなものだけ。
手元の Windows 環境だと、ターミナルがうまく開かないので諦める。

ターミナル
`shift` を加えると新しいウィンドウが開く。

- macOS: ``ctrl + ` ``
- Windows: ``ctrl + ` ``

デバッグコンソール

- macOS: `cmd + shift + y`
- Windows: `ctrl + shift + y`
Qiita事始め


１．EXCELグラフをQiitaに張り付ける（カット＆ペースト）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524780/8406fbd0-cfac-e5a3-4b6b-f2b4acc34f6b.png)

２．Qiita上でwxMaximaを利用する

```
brew install maxima;
solve( 0.4373*x^2 - 13.2363*x + 208.4 == 100 , x );
```
MapLibreとは

## MapLibreとは？
[MapLibre](https://maplibre.org/)とは[Mapbox GL JS](https://docs.mapbox.com/mapbox-gl-js/guides/)のv1.13.0がフォークして生まれたオープンソースプロジェクトです。![スクリーンショット 2022-02-09 17.23.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467847/340b21cd-320b-8665-fa94-84cb2f8a0609.png)

2020年12月にMapbox GL JSがver2.0をリリースする際、オープンソースを辞めMapbox独自で開発を進める方針に切り替え、API利用による重課金制を導入しました。これに伴い、Mapbox GL JSとは別のオープンソースプロジェクトとしてMapLibreが生まれました。

[このリポジトリ](https://github.com/maplibre/maplibre-gl-js)から現在の開発状況を確認することができます。

## 開発を始めるために
初めてMapLibreに触れる人は、まず[Quickstart](https://maplibre.org/maplibre-gl-js-docs/api/)を参考にしてみましょう。

CDNもしくはModule bundlerを使って簡単にMapLibreでの開発をスタートすることができます。![スクリーンショット 2022-02-09 18.21.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467847/a7a5b2ce-de7f-b7e7-8f8d-8caa2ef17ef9.png)




## MapLibreでどんなものが作れるの？
MapLibreで制作できる様々なマップを[Examples](https://maplibre.org/maplibre-gl-js-docs/example/)として提供しています。
![スクリーンショット 2022-02-09 18.16.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467847/bc61d94a-b6e8-6176-8d1e-45759dc50178.png)

## 細かい設定を行うために

Examplesを参考にしつつも、より細かくマップを開発していきたいと思う方は[Style Specification](https://maplibre.org/maplibre-gl-js-docs/style-spec/)を参考にしてみましょう。

Style Specificationのルールに従いコードを書いていくことで、自分好みのマップを自由に作ることができます。

![スクリーンショット 2022-02-09 18.26.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467847/396fa753-0458-0252-5a09-dc5326a835ee.png)

## Mapbox GL からMapLibre GL への変更

Mapbox GLからMapLibre GLへ移行するは JavaScript,HTML,CSSを以下の通りに変更します。

```
-    <script src="https://api.mapbox.com/mapbox-gl-js/v1.13.0/mapbox-gl.js"></script>
-    <link
-      href="https://api.mapbox.com/mapbox-gl-js/v1.13.0/mapbox-gl.css"
-      rel="stylesheet"
-    />

     <!--  Use maplibre-gl version 1.15.2 for backwards compatibility with mapbox-gl version 1.x. -->
+    <script src="https://unpkg.com/maplibre-gl@1.15.2/dist/maplibre-gl.js"></script>
+    <link
+      href="https://unpkg.com/maplibre-gl@1.15.2/dist/maplibre-gl.css"
+      rel="stylesheet"
+    />

-    var map = new mapboxgl.Map({
+    var map = new maplibregl.Map({

-    <button class="mapboxgl-ctrl">
+    <button class="maplibregl-ctrl">
```


## MapLibreコミュニティーに興味がある方へ
MapLibreはSlackを用いて、コミュニティ開発を行っています。
興味のある人は、SlackチャンネルにJoinしてみましょう（[Slackチャンネル](https://osmus-slack.herokuapp.com/)）
DOBOT×AI 判別対象をグリッパーで掴む

以下のテキストのソースコードは、判別対象を吸引カップで移動させるようになっています。
[DOBOT Magician AIｘ画像認識ｘロボットアーム制御](https://afrel.co.jp/dobot/education-product/)

対象物が小さい、あるいは細長く、吸引カップでは保持できないことがあります。
そのような場合、DOBOT magicianに付属する空気式グリッパーで掴む必要があります。

# 変更前
グリッパーで対象物を掴んで動かすプログラムに修正します。
dobot_aiフォルダ内にある「dobotClassifier.py」の以下の部分で対象物を移動させています。

```python:dobotClassifier.py
# Z座標
# オブジェクトの大きさ、環境に合わせて変更する
z = -58
```

```python:dobotClassifier.py
def dobot_classifier(label, pos_x, pos_y):
    '''
    指定された座標のオブジェクトを取り、ラベルごとに仕分ける
    '''
    # オブジェクトの真上に移動
    dobot.move(pos_x, pos_y, 0, 0)
    dobot.wait(1)
    # オブジェクトを取れる位置まで移動し、オブジェクトを取る
    dobot.move(pos_x, pos_y, z, 0)
    dobot.suctioncup(True, True)
    dobot.wait(1)
    # オブジェクトの真上に移動
    dobot.move(pos_x, pos_y, 0, 0)
    dobot.wait(1)

    # ラベルに合わせた座標を指定
    if label <= 3:
        x = 150 + 50 * label
        y = 100
    elif label <= 6:
        x = 150 + 50 * (label - 4)
        y = 150
    elif label <= 8:
        x = 150 + 50 * (label - 7)
        y = 200
    else:
        x = 300
        y = 0

    # ラベルごとに仕分ける位置の真上に移動
    dobot.move(x, y, 0, 0)
    dobot.wait(2)

    # オブジェクトを置く
    dobot.move(x, y, -30, 0)
    dobot.suctioncup(False, False)
    dobot.wait(2)

    print("move -> (%d, %d)" % (x, y))

    # カメラに映らない場所に移動
    dobot.move(150, 100, 0, 0)

    return True
```

# 変更後
以下の様に修正します。

```python:dobotClassifier.py
# Z座標
# オブジェクトの大きさ、環境に合わせて変更する
z = -40
```
※ 上記の数値は、オブジェクトの大きさや動かす環境に合わせて変更してください。

```python:dobotClassifier.py
def dobot_classifier(label, pos_x, pos_y):
    '''
    指定された座標のオブジェクトを取り、ラベルごとに仕分ける
    '''
    # オブジェクトの真上に移動
    dobot.move(pos_x, pos_y, 0, 0)
    dobot.wait(1)
    # オブジェクトを取れる位置まで移動し、オブジェクトを取る
    dobot.gripper(True, False)
    dobot.move(pos_x, pos_y, z, 0)
    dobot.gripper(True, True)
    dobot.wait(1)
    # オブジェクトの真上に移動
    dobot.move(pos_x, pos_y, 0, 0)
    dobot.wait(1)

    # ラベルに合わせた座標を指定
    if label <= 3:
        x = 150 + 50 * label
        y = 100
    elif label <= 6:
        x = 150 + 50 * (label - 4)
        y = 150
    elif label <= 8:
        x = 150 + 50 * (label - 7)
        y = 200
    else:
        x = 300
        y = 0

    # ラベルごとに仕分ける位置の真上に移動
    dobot.move(x, y, 0, 0)
    dobot.wait(2)

    # オブジェクトを置く
    dobot.move(x, y, -30, 0)
    dobot.gripper(True, False)
    dobot.wait(2)
    dobot.move(x, y, 0, 0)
    dobot.gripper(False, False)

    print("move -> (%d, %d)" % (x, y))

    # カメラに映らない場所に移動
    dobot.move(150, 100, 0, 0)

    return True
```

修正したプログラムは、グリッパーの角度（R座標）は0度のままなので、対象物や置き方によって変更する必要があります。
[Android]GroovyからKTSに移行によるメリデメを調査

##はじめに
Gradle Plugin4.0からKTSのサポートがあります。
KTSに移行してみて、個人的に調べたり感じたりしたメリデメのお話です。

##メリット
###1. コンパイルエラーを吐いてくれる
これが、一番のメリットな気はします。
書いていて感動しました。
Groovyは動的型付けであるのに対して、みんな大好きKotlinは静的型付けなので実現できます。
今までは、Syncして初めて文法ミスなどに気づけていましたが、これで書きながらミスに気づくことが出来るように。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599059/5d2d3f39-8b91-073a-9572-aadbed9411d3.png)

###2. メソッド引数の補完が効く。
途中まで気づかなかったが、地味にありがたい。

↓Groovyの時はなかった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599059/585c09bd-f5b8-4c7e-964d-407539b1b23e.png)

###3. 良く分からんGroovyの文法を調べなくても良い
正直、Groovyは適当に貼り付けたら動く感じだと思ってます。
なので、そこまで文法で困ることはないもののKotlinの方がなじみがあってよいことはあるかなと。

実際、Groovyは `()`（＝メソッド呼び出し）や `=` (代入)の省略が多いですし、対してKotlinはメソッド呼び出しなので可読性は移行したほうが高くなりますね。

```groovy:groovy
task clean(type: Delete) {
    delete rootProject.buildDir
}
```

```kotlin:kts
tasks.create("clean", type = Delete::class) {
     delete(rootProject.buildDir)
}
```

###4. Groovyのファイルとの共存が可能なので、移行が段階的に出来る
これは、KTS自体のメリットではないのですが、もし移行する決定をした時、全ファイルを一気にビルド通すみたいな面倒なことをしなくて済みます。

###5. IDEとの相性が良い
Ctr + speceでブロック内で書けるプロパティのサジェスチョンを出すことが出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599059/9067b100-ee84-4684-3dbb-2d23e2ed2851.png)

###6. コードジャンプできる
Groovyでは、extで定義したプロパティにコードジャンプできませんでしたよね。

方法としては、ルート直下に`buildSrc`ディレクトリを作成します。
この中に書かれたスクリプトは、projectスコープで参照可能になります。

空の`settings.gradle.kts` と KotlinDSLを使えるようにした `build.gradle.kts`をその中に定義します。

```kotlin:build.gradle.kts
plugins {
   "kotlin-dsl"
}

repositories {
   jcenter()
}
```

`buildSrc/src/main/kotlin/Dep.kt` となるようにディレクトリとファイルを作成します。

```kotlin:Deps.kt
object Deps {
    object AndroidX {
        val core = "AndroidX.core:core-ktx:1.7.0"
        val compat = "AndroidX.appcompat:appcompat:1.4.1"
        val junit = "AndroidX.test.ext:junit:junit:junit:1.1.3"
        val constraintLayout = "AndroidX.constraintlayout:2.1.3"
    }

    object Test {
        val espresso = "AndroidX.test.espresso:espresso-core:3.4.0"
    }

    object Google {
        val material = "com.google.android.material:material:1.5.0"
    }

    object Junit {
        val junit = "junit:junit:4.13.2"
    }
}
```

```kotlin:build.gradle.kts
dependencies {
    implementation(Deps.AndroidX.core)
    implementation(Deps.AndroidX.compat)
    implementation(Deps.Google.material)
    implementation(Deps.AndroidX.constraintLayout)
    testImplementation(Deps.Junit.junit)
    androidTestImplementation(Deps.AndroidX.junit)
    androidTestImplementation(Deps.Test.espresso)
}
```



###7. 型がある
エラーが少なくなる！

###8. 色鮮やかに！
全体的に見やすくなってますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599059/354af853-b413-83dc-0dc5-2cd078df4a58.png)



##デメリット
特にないかなと思っていますが、挙げるとすれば・・・

###1. コード補完とコンパイルチェックが遅いかも
（手元の環境限定かもしれないが）
###2. ビルドが遅くなる場合がある
（らしい）
###3. Kotlinでどうかけばいいのか結局調べる・・
少しの手間ですが、プロパティ名が変わってなどGroovyで書いてたものをKotlinで書く場合どうするんだろう・・となります。

まぁ、ドキュメントを見れば済む話ですが。
最初はやや大変かなと思います。


##おわりに
おまけとして今回使うであろうショートカットを添えておきます。

ファイル名の変更は、shift + F6
置換は、Ctr + R

##参考
https://www.youtube.com/watch?v=_s-0MbA5Gvw&t=1543s

https://qiita.com/b4tchkn/items/7b66abba44589a282a2e
DOBOT×AI カメラのセッティング方法

以下のテキストを使用する際、カメラのセッティング等で上手くいかない場合があるので、解決方法を記載します。
[DOBOT Magician AIｘ画像認識ｘロボットアーム制御](https://afrel.co.jp/dobot/education-product/)

# 測定マット上の色を読み取れない
カメラの座標からロボットアームの座標へ変換するために測定マット上の4色の座標を読み取り、変換マトリックスを生成するステップがあります。その際、4色の座標だけを上手く読み取れないことがあります。

例えば、以下の画像の場合、黄色の座標は読み取れていますが、それ以外の色は読み取れていません。
また、灰色の部分を誤認識しています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145092/ca5bdf49-9d28-4423-535c-c7b6b29b758e.jpeg" width=70%>

## 対策：余計な部分を隠す
余計な部分を認識する場合は、誤認識する部分を隠すのが簡単な解決方法だと思います。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145092/e9583106-f5f9-878c-fddd-5af5802f931d.jpeg" width=70%>

## 対策：認識するサイズを調整する
認識してほしいところを認識しない場合は、領域抽出用のサイズを調整すると正しく認識するようになることがあります。ソースコード上の以下の箇所の最小サイズ、最大サイズの値を調整します。

```python:opencv_setting.py
# 領域抽出用の最小／最大サイズ
MIN_AREA_SIZE = 80
MAX_AREA_SIZE = 200
```

↓　変更後

```python:opencv_setting.py
# 領域抽出用の最小／最大サイズ
MIN_AREA_SIZE = 150
MAX_AREA_SIZE = 400
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145092/00380f48-9ef6-9cfc-9309-3ca1224a5fac.jpeg" width=70%>

# 判別対象が認識しない
AIによる対象物の判別をするために学習データを集めます。その際、判別対象を認識しないことがあります。

## 対策：認識するサイズを調整する
以下の画像のようにバイナリー化（2値化）した画像で物体がくっきり見えている場合は、前述した領域抽出用のサイズを変更することで認識するようになります。

![dobotxai_camera_04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145092/26687487-0ee6-ee57-f74c-5da260af4827.jpeg)

```python:opencv_setting.py
# 領域抽出用の最小／最大サイズ
MIN_AREA_SIZE = 1.5e3  #  1500
MAX_AREA_SIZE = 1e4    # 10000
```

↓　変更後

```python:opencv_setting.py
# 領域抽出用の最小／最大サイズ
MIN_AREA_SIZE = 250
MAX_AREA_SIZE = 3000
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145092/f9b6bed8-1d8a-844d-4e55-cc12a8d7c84e.jpeg" width=70%>
【Dynamics 365】サポート情報記事の検索性能

Customer Serviceのサポート案件フォームにあるサポート情報記事の検索性能が気になったので検証してみました～

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524942/b719f07b-d63c-7dcc-9aa9-a63725f48ae0.png)



◇検証対象
　・タイトル
　・説明
　・キーワード
　・コンテンツ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524942/deade34a-38ee-82ac-f078-8ee8c28af011.png)


◇検証性能
　①完全一致
　②前方一致
　③後方一致
　④漢字、ひらがな、カタカナ、ローマ字


◇検証結果

①前方一致
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524942/e8c084e1-c7d7-2679-b8ac-5a0f51f9786b.png)

　②前方一致
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524942/e9136e4a-bacb-9b5d-2e0b-a0ea6d9f5981.png)

　③後方一致
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524942/72835ccf-e448-defd-a587-48951affc39d.png)

　④漢字、ひらがな、カタカナ、ローマ字
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524942/b68d8c44-b1eb-bd34-9ba4-0d2832f2497e.png)


◇結論
・基本的に気にすることなく使える
・「漢字」と「ひらがな」が区別できないのはユーザーへの注意が必要
【XAMPP】MySQLの全てのクエリログを保存する方法

#経緯
初投稿です。
XAMPPでPHPを動かしていたところ、エラーは出ないけど操作が思っていたのと違う...なんてことがよく起こるので、データベースと接続して使うなら必ず設定しておきたいところ。
この設定を行っておくと、XAMPPのMySQLにクエリを飛ばすたびにログが残るので、bindParam等でうまくいっていない時などに、最終的にどんなクエリが飛んだのかなどを確認でき、根本原因の究明につながるかと思います。

#設定方法
では早速設定方法です。
###my.iniを編集する
XAMPPを起動して「Explorer」をクリックすると、xamppのフォルダに飛べます。
![スクリーンショット (42)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524944/04a006c3-964d-973c-ba8c-847d7746d978.jpeg)

xamppフォルダの中の「mysql」の中に「bin」というフォルダがあり、そこに「my.ini」というMySQLの設定ファイルが入っています。こちらをメモ帳などのテキストエディタで開いてください。
するとずらーっと設定が書き連ねてあるかと思いますが、割と上の方に[mysqld]と書いてある場所があるかと思います。そのすぐ下で一般ログをオンにして保存場所を記述します。

```[mysqld]
general_log=1
general_log_file="C:/xampp/mysql/general-query.log"
```
xamppフォルダがCドライブ直下にない人は適宜書き換えてください。
これでMySQLを再起動してください。
試しに何かしらのSQLを飛ばしてみて、mysqlフォルダの中にあるgeneral-query.logを開いてみてください。飛ばしたSQLが書いてあれば成功です。

さほど難しくない内容ですが、案外ネットに情報が落ちていない、、、
あと書き方も初心者に優しくない感じ。もちろん難しく書いてあっても理解できるようにいろいろ調べるのは大切ですが、私の投稿ではなるべく初心者の方でもわかるように書いていきたいと思います。
SignTool Error: Multiple certificates were foundと出た場合の解決

アプリ更新の機会があったので久しぶりにビルドしなおしたところ

```
SignTool Error: Multiple certificates were found that meet all the given
        criteria. Use the /a option to allow SignTool to choose the best
        certificate automatically or use the /sha1 option with the hash of the
        desired certificate.
The following certificates meet all given criteria:
    Issued to: xxxxx.co.jp
    Issued by: COMODO RSA Extended Validation Code Signing CA
    Expires:   Sun Jan 29 08:59:59 2023
    SHA1 hash: D8AB4636FBD474256D928B90B421107E3EDCE1DC

    Issued to: WDKTestCert xxxxx,132823738331490962
    Issued by: WDKTestCert xxxxx,132823738331490962
    Expires:   Wed Nov 26 09:00:00 2031
    SHA1 hash: CBE1951F71011058E84725B9809205FA22817D77
```

証明書はCOMODOから取得したもの。
デバイスドライバに署名したときの証明書と判別できないらしい。
アナウンスに従って/a付きで試すも

```
Signtool Error: The provided cross certificate would not be present in the certificate chain.
```
んー
数分悩んだあと、直接SHA1ハッシュを指定すればいけるかもという事に気づく。

```
signtool sign .... /sha1 D8AB4636FBD474256D928B90B421107E3EDCE1DC 
Done Adding Additional Store
Successfully signed: xxxxx.exe
```

ちょっと泥臭いけど解決！
Salesforceのフローを作成しよう～参照関係のオブジェクトで必ず最新の１レコードしか紐づかないフロー～

　なにかとSalesforceで話題になっているフローですが、おもしろいフローを作成したので共有します


「やりたいこと」
オブジェクトＡ,オブジェクトＢがあり、参照関係で結ばれています（オブジェクトＡが親)
オブジェクトAのレコードにはオブジェクトＢのレコードは必ず１レコードしか紐づけたくない
（常にオブジェクトＢの最新に紐づけたレコードしか紐づけたくない。過去のオブジェクトＢレコードは自動的に参照関係が空欄になる）


例として下記のような動きです
・オブジェクトA＝取引先オブジェクト
・オブジェクトＢ＝商談オブジェクト
・取引先オブジェクトで「株式会社Ｘ」というレコードがあり、「株式会社Ｘ」に「商談Ａ」を紐づけ、その後「商談Ｂ」を紐づけた場合、自動的に「商談Ａ」レコードは「株式会社Ｘ」から参照関係が外れる（商談Ｂはもちろん株式会社Ｘに紐づいている）


考えとしては
起動条件：商談レコード作成または更新の場合でなおかつ取引先ＩＤが空欄ではないときにフロー起動
ステップ１：作成または更新された商談の取引先ＩＤに紐づくすべての商談の取引先項目を空欄にする
ステップ２：作成または更新された商談の取引先ＩＤを更新する

です。

フローの全体像です
![フロー１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/cf0ce453-b27e-f0f3-a658-a5cbe92a4b26.png)

ステップ１です
![フローステップ１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/6a3e87b3-f6bb-ca72-037e-2671377d1e3f.png)

ステップ２です
![フローセカンドステップ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/45937032-e2a7-0cd8-3c35-e5269e9a44a5.png)
ラズパイ４環境設定、RealSense

#環境　
HW: Raspberry Pi 2 Model B Rev 1.1
OS:Raspbian(Linux raspberrypi 5.10.63-v7+ #1496 SMP Wed Dec 1 15:58:11 GMT 2021 armv7l GNU/Linux)

#ビルドツール
sudo apt-get install build-essential

# make -j1
-j1 はコア数の指定。ラズパイ２で-j4とするとメモリを使い果たすのか、途中で全く進まなくなり効果。PC-Ubuntsuだと-j8として、ビルド成功する事を確認してから、-j1で再ビルドするとよさそう。


# メモ

１．
RealSense L515をラズパイ4 Raspberry Pi OSのPythonから起動する最速手順＆サンプルコード

https://ichiken-usa.blogspot.com/2021/04/install-realsense.html#toc_13

Raspberry Pi 4 Model B 8GB
Raspberry Pi OS 32bit (Linux arm 5.10.17-v7l+, Raspbian 8.3.0-6+rpi1)
Visual Studio Code ver 1.55.2
Python 3.7.3
OpenCV 4.5.1
Cmake 3.16.3
protobuf 3.5.1
RealSense L515
RealSense SDK 2.44.0

２　Intel® RealSense™ Depth Camera D435i を使ってみる（2）

環境
Raspberry Pi 4 Model B 4GB
Intel® RealSense™ Depth Camera D435i

https://openvino.jp/intel-realsense-camera-d435i-2/

３．　公式
https://github.com/IntelRealSense/librealsense/blob/master/doc/installation_raspbian.md

４．Jetson NanoでRealsenseのPythonラッパーPyRealsenseを使用する方法
からあげ。

#５．ラズパイ4(Raspberry pi OS 32bit)にpyrealsenseを入れる
https://qiita.com/masa_masa_ra/items/a4406e3c10b72c3f0fda
「これでやるのがベスト!!!」ってあるけど、ほんまか？

conda かpipでprotobufインストールできるんじゃね？
↓
conda install -c conda-forge protobuf などもラズパイCPU用モジュールは見つからない。
↓
やっぱりビルド
↓
make check でエラーでるけど、無視して進める。

OpenCVでエラーでる。
↓
sudo apt-get install libopencv-dev python3-opencv
OpenCVはココ参照。https://raku-tech.com/rasberrypi/opencv-install/



９． 
https://ytyaru.hatenablog.com/entry/2019/01/04/000000
【Vue】コンポーネントのcomputedをテストする

## きっかけ
コンポーネントのcomputedをテストする機会がありました。
しかしコンポーネント内の他の要素（ライフサイクルやストアなど）に依存してしまい、純粋にロジックのみをテストできないのだろうか...となっていました。
その際のメモです。
## 使用しているバージョン
- nuxt@2.15.8
- vue@2.6.14
- @vue/test-utils@1.3.0


## 方法
computedのテストには大きく分けて2つあります。
- mountやshallowMountを使う方法
- callを使う方法　**<-** **今回はこちら**

## テストしてみる
今回テストするコンポーネントはこちらです。
```vue:UserList.vue
<template>
  <div>
    <!-- テンプレートの内容 -->
  </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  data() {
    return {
      searchKeyword: '佐藤太郎',
    }
  },
  computed: {
    ...mapGetters({
      users: 'users/users',
    }),
    filteredUsers() {
      return this.users.filter((u) => u.name === this.searchKeyword)
    },
  },
}
</script>
```

それではcallを使ったテストを書いてみましょう。
```javascript:UserList.spec.js
import VCard from '@/components/VCard.vue'

const dummyUsers = [
  { id: '1', name: 'hoge太郎' },
  { id: '2', name: 'fuga二郎' },
  { id: '3', name: 'piyo三郎' },
]

describe('VCard test', () => {
  test('filteredUser computed', () => {
    const localThis = {
      users: dummyUsers,
      searchKeyword: 'fuga二郎',
    }

    const expected = [dummyUsers[1]]
    const received = VCard.computed.filteredUser.call(localThis)
    expect(received).toEqual(expected)
  })
})

```
VCard内で`this.users`や`this.searchKeyword`がlocalThisの内容に置き換えられます。
つまり`mapGetters`や`data()`の中身を気にすることなく、ロジックがテストできます。

[Vueテストハンドブック](https://lmiller1990.github.io/vue-testing-handbook/ja/computed-properties.html)によると、以下の理由で`this`を置き換えることができるそうです。
> shallowMountなどでレンダーしないので、thisに何もバインドしません。

便利！
これでライフサイクルを無視した純粋なcomputedのテストができました。
## callかshallowMountどちらを使うか?　（おまけ）
[Vueテストハンドブック](https://lmiller1990.github.io/vue-testing-handbook/ja/computed-properties.html)より引用です。

>算出プロパティのテストを書くにはcallとshallowMountが両方とも便利なテクニックです。callが特に便利な場合は：
>- `mounted` などの [インスタンスライフサイクルフック](https://jp.vuejs.org/v2/guide/instance.html#%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB%E3%83%95%E3%83%83%E3%82%AF) の実行に時間がかかる場合、またライフサイクルフックを呼び出したくない場合です。コンポーネントをレンダーしないので、ライフサイクルフックも実行しません。
>- `this`を細かく設定したい場合
もちろんコンポーネントが正しくレンダーするテストも必要です。テストしたいことに合わせてもっとも適切なテクニックを選んで、エッジケースをちゃんとテストします。

うまく使い分けることが重要ですね。