OmniAICreator/Qiita-1.07M huggingface dataset:
【Node-RED操作歴5日間】今にでも行きたい海外旅行に向けて「世界の今を覗けるLINE Bot」を作ってみた

<h1>海外旅行に行きたい！ </h1>
私は現在入社2年目で、旅行会社に勤務しています。
多くの他業界と同様に、観光業界も新型コロナウイルスによる影響を大きく受けており、私自身入社時から既にコロナ禍であったため、自由に旅ができる状態の業界の様子などをまだ実感していません。
<h1>業務上感じる課題</h1>＜BtoC向けの旅行商品を扱う部署にてWEB販促などを担当しています。＞
①「旅行を勧めていい状態か?」によってプランの販促文言なども配慮が必要で、前向きな告知が難しいことが多い。
例）「今、沖縄に行こう！とは謳えないなぁ」「緊急事態宣言が再発令しそうだ」「海外はそもそも商品がない（渡航できない）」など<br>
②メールマガジンなどでも「おトクなプランの紹介」や「キャンペーン紹介」ばかりになってしまい、旅行に行きたくなるような【面白さ】を出すのが難しい。直接的なプランの告知広告ではない販促はできないか？<h1>以上の課題を踏まえ</h1>「自分が旅行に行きたくなるのは？」を改めて考えてみた結果、私の場合は、何気なく雑誌やYouTubeなどで見た景色やグルメを自分の目で見て感じたい！食べたい！と衝動的に旅行を計画することが多いなと感じました。<h1>そんな時、世界中のリアルタイム定点カメラが観察できる面白サイトのAPIを発見！</h1>https://api.windy.com/
このサービスでは特別な場所でもない、観光地でもない、ごく普通の場所に設置されているWEBカメラをリアルタイムに覗くことができます！
昔旅行した国やまだまだ知らない国のなんでもない場所を見るのが楽しい。。<br>
:point_down:WEBサイト版はこちら

https://www.windy.com/

海外旅行は、もはや夢のような話となってしまいましたが、海外への興味や旅行意欲は変わらずにあります。そこで、私と同じように今にでも海外旅行に行きたい方に少しでも楽しんでもらいたいという思いで「世界の今を覗けるLINE Bot」の作成に挑戦しました。
直接的な旅行プランの販促にはなりませんが、いつかの旅行の小さなきっかけになればいいなと思います。
<h1>使用ツール</h1>下記のサービスはそれぞれインストールやアカウント登録などの事前準備が必要になります。LINEBotを作るためには「LINE Developers」の登録準備もしておきましょう。
*<a href="https://jp.heroku.com/home/">Heroku</a>
*<a href="https://nodered.jp/">NodeRED</a>
*<a href="https://developers.line.biz/ja/">LINE Developers</a>
*<a href="https://api.windy.com/">Windy API（WEBカメラAPI）</a>
※アカウント登録後APIキーの取得が必要です。<h1>最終完成イメージ</h1><b>①2桁の国コードを送信する
②その国のリアルタイム定点カメラを見れるURLが送られてくる</b>
※都市や地域まで詳細設定できるようにしたかったのですが、パラメーターの設定などに苦戦し、APIで取得しているリストの中の一番上にある地域のみが固定で表示されるようになっています。
![image0.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496382/ce762fcf-918d-fed9-9b48-be54d86b812c.jpeg)
<h1>最初に感覚で並べてみたフローがこちら</h1>タイトルにも書いたように、Node-REDを今回初めて知ってから【約5日間】で実装に取り組んでいたため、初めはノードの役割もよくわからないまま感覚で並べてみるレベルからスタートしました。特に私が選んだAPIは基本的な使い方として理解していたものと異なる使い方をする特殊なもので、サポートを頂くまで全く理解ができませんでした。（特にchangeノードの使い方など…）もちろん以下のフローでは、エラーとなってしまいます。![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f323439363338322f33326363343962632d666532662d653532642d663537652d6536656233626263623432352e706e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496382/0421874d-448e-a0cd-00ce-6632450bdf71.png)
ここからNode-REDの基礎や、過去に作成されたNode-RED×LINEbotの活用例などを調べては行き詰まり、アドバイスも段階ごとに沢山いただきながら進めていきました。
<h1>その結果、最終的に動くようになったフローがこちら</h1><b>①Webhook</b>
LINEで任意の国コードを送信します。
<b>②template</b>
windy.comから情報を取得するURLを作成。payload箇所にLINEで送信する任意の国コードが入ります。

```
https://api.windy.com/api/webcams/v2/list/country={{payload}}?show=webcams:url&key=取得したAPIキー
```

<b>③http request</b>
APIへアクセスします。
<b>④change</b>
APIから得られたJSONそのままではなく、JSONの中に含まれているいずれかの要素を msg.payload として出力するようにします。
<b>⑤ReplyMessage</b>
LINEメッセージとしてURLを送信します。
![スクリーンショット (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496382/a705adcd-efdd-3cd9-6512-18526e5f9c7f.png)<h1>最後に</h1>初めてのNode-RED操作では、ノード一つ一つが何の役割をするのか、どこが引っかかってエラーとなっているのか、など分からないことが山積みながらもプロセスを教えていただきながら実装までたどり着くことができました。気軽なLINE Botで<b>「気になる場所」が沢山できればいつかの旅行のきっかけにもなるのではないでしょうか。</b>

今後は、アイデアとしてやりたいことと実装イメージを多様に結び付けられるように、使える技術の種類を増やしていきたいと思います。

最後までご覧いただき、ありがとうございました:airplane::sparkles:
UnityでDOTweenしようの際に、DOFadeがエラーとなる

#はじめに
嵌ったので備忘として記録

#エラー内容
【ソース】

```
public void FadeOut()
{
   canvasGroup.DOFade(1, fadeTime)
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846650/7f064841-5e9b-5d8e-a27b-138ff13dc9f7.png)

【エラー】
CS1929	'CanvasGroup' に 'DOFade' の定義が含まれておらず、最も適している拡張メソッド オーバーロード 'ShortcutExtensions.DOFade(Material, float, float)' には 'Material' 型のレシーバーが必要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846650/7c6aa7f7-739f-6855-99d8-6155b4d20f81.png)


候補にも表示されない状況でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846650/863eb420-0f86-e9ab-7f98-96d21f2787fa.png)

#解消方法】
パッケージマネージャーから再度インポートを行って、再セッティングしたらエラーが消えました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846650/975fb7c0-2d52-c98f-5454-f4cdffac13cc.png)


#さいごに
原因は不明でしたが依存関係か何かがおかしくなってしまったと思われます。
e-Taxのログインがあまりに面倒なので自動化いたしました件

## はじめに

[e-Taxソフト（WEB版）のログイン](https://clientweb.e-tax.nta.go.jp/UF_WEB/WP000/FCSE00001/SE00S010SCR.do)が面倒くさくてかなわないのです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/04ca0fe0-50a4-e86d-ab2e-43bbe8c24f70.png" width=80%>

マイナンバーカードでログインできればいいんですが、法人だと使えません（電子署名には使えますが、ログインはダメです。このあたりの仕様もあまり納得がいかない）。

ですので利用者識別番号を入力しなければならないわけですが、フィールドが4つにわかれているのです。ですので、コピーペーストができない（きわめて面倒くさい）のですね。

かしこいパスワードマネジャーならフィールドが分かれていても入力してくれそうですが、macOSのキーチェーンはそこまでかしこくないのです。

NCSCもNISTも、**パスワードはペーストできるようにせよ、パスワードマネジャーを使え**と言っているのに、e-Taxでキーチェーンを使えなくしている正当な理由をいまのところ考えつきません。（パスワードじゃなくて、IDだからペーストしにくくていいということなのでしょうか？）

わたしの不勉強で、正当な理由があるのかもしれません。だいいち、文句を言っていてもすぐには変わらなさそうなので、ツールをつくりました。

### 環境

- Alfred 4.6.1
- macOS Monterey 12.1
- MacBook Pro (13-inch, 2020, Four Thunderbolt 3 Ports)

## 概要

### 操作の概要

- 入力フィールドの1つめにカーソルを入れます
- Alfredを起動し、`etaxlogin`と入力します（実際には`et`ぐらいで）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/abb7b71d-6818-a976-ac3d-6030b8b7b303.png" width=80%>
↓
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/5b6c0fe7-6aa3-e91b-c7a1-db9505796a44.png" width=80%>
やったね！

### ツール構成の概要

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/e8590b8e-64b8-0d4b-e617-bd1015a2e66c.png" width=80%>

- `Keyword`モジュールと、`Run Script`モジュールでできています
- Keywordを入力すると、スクリプト（AppleScript）が動きます

## 詳細

### Keywordモジュール

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/8631161c-1506-5942-b975-3ef9e5b306f8.png" width=80%>

起動するためのキーワードを設定します。

### Run Scriptモジュール

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/afeecc92-c927-2606-989b-ffc8851b7cac.png" width=80%>

あまりスマートなスクリプトではないのですが😆、AppleScriptをつかってキーを押します。

```applescript
tell application "Safari" to activate
tell application "System Events"
	key code 55 -- 英数
	key code xx
	key code xx
	key code xx
	key code xx
	key code 48 -- tab
	key code xx
	key code xx
	key code xx
	key code xx
	key code 48 -- tab
	key code xx
	key code xx
	key code xx
	key code xx
	key code 48 -- tab
end tell
```

はじめの3フィールドをAppleScriptに入力させ、4フィールドめに入ると、キーチェーンが反応するので、そこからはキーチェーンをつかいます。

キーコードは、ググればでてきますが、たとえばこの記事に詳しく書かれています。
[AppleScript 七つ道具 〜 Mac 上の反復入力は簡単に自動化できる。 - Qiita](https://qiita.com/MMRN/items/5e622eee5c736a42ee38)

## おわりに

あまりスマートではない解決策ですが、とてもストレスフリーになれます。

パスワードのペーストについては、下記のように多くのところで推奨されています🧐
本質的には**パスワードマネジャーを使おう**ということで、パスワードだけじゃなくてIDもパスワードマネジャーで扱うべきものだと理解しています。

- [セキュリティ | UK政府機関推奨 パスワードのペーストを許可しよう - Qiita](https://qiita.com/YumaInaura/items/a7b8d9f1f998cb311350)
- [Let them paste passwords - NCSC](https://www.ncsc.gov.uk/blog-post/let-them-paste-passwords)
- [NIST Password Guidelines and Best Practices in 2021](https://www.loginradius.com/blog/start-with-identity/nist-password-guidelines-2021/)

※NCSCはアメリカのNPO：[National Cybersecurity Center - Wikipedia](https://en.wikipedia.org/wiki/National_Cybersecurity_Center)
※NISTはアメリカの商務省配下の技術部門：[アメリカ国立標準技術研究所 - Wikipedia](https://ja.wikipedia.org/wiki/アメリカ国立標準技術研究所)


### 参考リンク

[Alfred - Productivity App for macOS](https://www.alfredapp.com)
→macOSのパワーユーザは買って損はないとおもいます
poetry installが動いているか確認したい

# この記事について
Poetryで、python仮想環境を作ろうとしたときに、下記の表示で止まっていてインストールが動いているか分からない。
もうチョット詳細なログを出して、インストールが動いていることを確認したい。

```bash
$ poetry install 
Using virtualenv: /hoge/foo/bar/.venv
Updating dependencies
Resolving dependencies...
```

# 確認方法
### verboseすればよい
https://python-poetry.org/docs/cli/#:~:text=verbose

#### ざっくりverbose（for normal output）
```bash
$ poetry install -v
```

#### 細かくverbose（for more verbose output）
```bash
$ poetry install -vv
```

#### もっと細かくverbose（for debug）
```bash
$ poetry install -vvv
```

# まとめ
* 細かく見たい時は、***-vvv***する。（vvvは少し笑ったｗｗ）
* 小文字（v）で、大文字（V）はバージョン確認なので注意

以上
備忘録 React Reduxエラー "export 'Switch' was not found in 'react-router-dom'で


少し古いガイドラインに沿ってアプリ制作をしていたら、いきなりSwitchがないというエラー。

`react-router-dom`のバージョンが原因。v6以降は`Switch`が`Routes`になり書き方に変更点が数カ所。

①v5に戻す、②v6の書き方へ変更するの２種類の対処法をまとめました。

## 対処法① 
### バージョンをv5に戻す
以下のコマンドで、現行バージョンをアンインストールして、v5をインストールし直す。

`npm uninstall react-router-dom`

`npm install react-router-dom@5.2.0`



## 対処法②

### Switch → Routesに変更

```javascript:index.jsx＜変更前＞
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { BrowserRouter, Route, Switch } from 'react-router-dom';

import App from './components/app';

const store = createStore()

ReactDOM.render(
  <Provider store={store}>
    <BrowserRouter>
      <Switch>
        <Route path="/channels/:channel" component={App} />
      </Switch>
    </BrowserRouter>
  </Provider>,
  document.getElementById("root");
);
```

```javascript:index.jsx＜変更後＞
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { BrowserRouter, Route, Routes } from 'react-router-dom';

import App from './components/app';

const store = createStore()

ReactDOM.render(
  <Provider store={store}>
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<App />} />
      </Routes>
    </BrowserRouter>
  </Provider>,
  document.getElementById("root");
);
```

* importの変更
* Switch→Routesに変更
* component→element
* {App}→{<App />}
【Chrome】ServiceWorkerを今度こそ決定的かつ完全に消去する

前、[Chromeを使うなら、必ずServiceWorkersを無効化しよう](https://qiita.com/rana_kualu/items/52d8cb7b200d6fefddc8)という記事を書いたのですが、あの方法はてんで全然ダメダメでした。
[chrome://serviceworker-internals](chrome://serviceworker-internals)には無用なServiceWorkerが増え続け、[chrome://flags/](chrome://flags/)からはServiceWorkerの削除設定が削除されました。

そんなわけで、今度こそServiceWorkerを決定的かつ完全に消し去りたいと思います。

といっても自力でどうこうしたわけではなく、全面的に他人の力を借りただけですが。


# Reject Service Worker

[Reject Service Worker](https://chrome.google.com/webstore/detail/reject-service-worker/falajmifjcihbmlokgomiklbfmgmnopd)をインストールする。
おわり。

かんたん！

作者は[toshiさん](https://www.bugbugnow.net/)です。
ありがとうございます。

アドオンの技術的内容は[ServiceWorkerを無効化する](https://www.bugbugnow.net/2020/03/Reject-to-register-a-ServiceWorker.html)という記事に書かれているのですが、ServiceWorkerを登録する関数を書き替えて登録できないようにしているみたいです。
なかなかのハック感。


# 既存のServiceWorkerを削除

`Reject Service Worker`は、今後のServiceWorkerの新規登録こそ止めてくれますが、それまでに登録されてしまったServiceWorkerはそのままであり消去されません。

削除する方法はふたつ。

まずは、`Reject Service Worker`が有効な状態で、ServiceWorkerが登録されたサイトを再度訪問すれば、そのタイミングで消えます。

もうひとつは、URLに[chrome://serviceworker-internals](chrome://serviceworker-internals)と入力し、ひたすら`Unregister`を連打することです。

もしくは[コメント](https://qiita.com/rana_kualu/items/52d8cb7b200d6fefddc8#comment-20197965b101b9bf14ed)で、一括削除する方法を @negabaro さんが紹介してくれていました。

```js
$$('.unregister').forEach(b => b.click())
```


# ホワイトリスト

ホワイトリストが用意されています。

このサイトだけはServiceWorkerを許可したい、といった場合は以下の手順で登録できます。

・許可したいサイト上で拡張機能から`Reject Service Worker`を選択する。
・すると`Add to Whitelist`というボタンが出るので選択する。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/31fd2fc9-236e-cbed-d51b-7c40a33714e1.png)

とても簡単ですね。

まあ、そもそもデフォルトがホワイトリストであるべきで、勝手にインストールしてくる現状が異常なわけですが。


# ソースコードを確認

せっかくServiceWorkerを消し去ることに成功したとはいえ、[実はアドオンそものがマルウェアでした](https://pc.watch.impress.co.jp/docs/news/1295872.html)みたいなことになったら台無しですね。
そんなわけで`Reject Service Worker`が安全かを、実際にソースコードを見て確認してみましょう。

アドオンの位置は`%LOCALAPPDATA%\Google\Chrome\User Data\Default\Extensions\falajmifjcihbmlokgomiklbfmgmnopd`です。
`Default`はプロファイル名なので、環境によって異なる可能性があります。

幾つかファイルがありますが、中身はただのJavaScriptなので普通に読めます。
ソースコードはコメントを用意してくれているのでとても読みやすいです。

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/560c839d-fc36-d432-b1c5-add4c19d0870.png)

ソースコードを見るかぎりでは、何か怪しいことをやっていたり、外部と通信しているような素振りは全くありませんでした。
そもそも作者自身が[アドオンのソースコードを確認する方法](https://www.bugbugnow.net/2021/06/sourcecode-for-extension.html)を提供していますからね。
これで変なことをやっていたら自爆でしかない。

ということで、このアドオンは[所有者が変わらないかぎり](https://gigazine.net/news/20210218-open-source-extensions-malware/)きっと安全であり続けるでしょう。


# まとめ

`Reject Service Worker`導入前後で、インターネット体験には何一つ変化がありません。
振り返り⑧(AWSセキュリティグループの設定をしよう！)

Elastic IPとEC2インスタンスの紐付けができたので、
セキュリティグループの設定をしてみます！！

#AWSのセキュリティグループとは？
VPC（AWSネットワーク）上で通信制御をするファイアウォール機能だそうです。

Amazon VPC(Amazon Virtual Private Cloud)とは、
AWS上に作成できるプライベート仮想ネットワーク空間です。
AWSアカウント内に専用のネットワークを作成でき、
このネットワーク内に「EC2」などのAWSリソースを配置できます。

Amazon VPCの代表的なコンポーネントは、以下になります。
※コンポーネントとは、機器やソフトウェア、システムの構成する部品や要素などのことを意味する

・サブネット｜大きなネットワーク内の小さなネットワーク
・インターネットゲートウェイ｜Amazon VPCとインターネットを接続するための出入り口
・ルートテーブル｜パブリックサブネット内のリソースがどこにアクセスするか？のルールを定めた表

#Let's try !

まずAWSコンソールのEC２ インスタンス > 作業環境の「 Furikaeri-Dev 」 のセキュリティをクリック！
![スクリーンショット 2022-01-17 18.38.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2224485/f822c289-51a7-1960-0d43-1fe7abf9a154.png)
あれ？なんかある、先約？


![スクリーンショット 2022-01-17 19.22.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2224485/bee3e5a5-c590-876a-0b88-6026fb8d131b.png)
もうセキュリティグループが設定してあるぞ？？
おかしいな？

みんなで相談した結果、VPCを作ってみよう！ということに。

#VPCを作ろう!
VPCの作成ボタンを押下して適宜設定を入力して…作成ボタンを押下したが！

![スクリーンショット 2022-01-13 16.36.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2224485/98093851-1abf-0839-74ab-1e1b21205233.png)

エラーが！！
調べると、VPCの作成に上限値があり、既に上限値に達していたのでした。。。
OMG…

なので、他のインスタンスと紐付いているので、削除していいか
K池さんに確認が必要になり、今日の作業はここまでとなりました。

ちなみにK池さんから既にある研修用のVPC消していいと許可が出ているので、
次回は消してしまおうと思います。
(これに紐付いているインスタンス等も削除してしまってOKとのこと)


今回はここまで〜
written by ジョジョ６部のアニメが始まって嬉しい大森
OpenCVでRGB画像と2値化画像を連結させて表示したい

<h2>OpenCVでの画像連結方法</h2>

OpenCVでは複数の画像を連結させたい時は、cv2.hconcat/vconcat関数を用います。例として、以下のコードのように記述します。

```main.py
import cv2

img1 = cv2.imread("img1.jpg")
img2 = cv2.imread("img2.jpg")

# サイズをそろえる
window_size = (400,400)
img1 = cv2.resize(img1, window_size)
img2 = cv2.resize(img2, window_size)

# 画像を横に連結
img = cv2.hconcat([img1,img2])
# img = cv2.vconcat([img1,img2]) # 画像を縦に連結する場合

# 画像を表示
while True:
    cv2.imshow("img",img)
    if cv2.waitKey(1) == ord('q'):
        break
cv2.destroyAllWindows()

```

ここで、ある画像のRGB画像と2値化画像を連結させようとします。
コードは以下のようになると思います。

```main.py
# 注：これは間違ったコードです。
import cv2

# 2値化閾値
th = 100

img1 = cv2.imread("img1.jpg")
img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
img1_binary = cv2.threshold(img_gray, th, 255, cv2.THRESH_BINARY)

# サイズをそろえる
window_size = (400,400)
img1 = cv2.resize(img1, window_size)
img1_binary = cv2.resize(img2, window_size)

# 画像を横に連結
img = cv2.hconcat([img1,img1_binary])

# 画像を表示
while True:
    cv2.imshow("img",img)
    if cv2.waitKey(1) == ord('q'):
        break
cv2.destroyAllWindows()

```

上のコードを実行すると次のようなエラーが出ます

```

cv2.error: OpenCV(4.5.3) C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-1i5nllza\opencv\modules\core\src\matrix_operations.cpp:67: error: (-215:Assertion failed) src[i].dims <= 2 && src[i].rows == src[0].rows && src[i].type() == src[0].type() in function 'cv::hconcat'

```

このエラーは、異なるタイプの画像を連結させようとしたために生じたものです。よって画像のタイプを合わせます。例えば連結させる直前に次のコードを記述することで2値化画像をRGB画像として変換させます。

```

img1_binary = cv2.cvtColor(img1_binary, cv2.COLOR_GRAY2BGR)

```

すなわち、先ほどの「間違ったコード」を正しく修正したものは以下のようになります。

```main.py

import cv2

# 2値化閾値
th = 100

img1 = cv2.imread("img1.jpg")
img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
img1_binary = cv2.threshold(img_gray, th, 255, cv2.THRESH_BINARY)

# 画像のタイプを揃える
img1_binary = cv2.cvtColor(img1_binary, cv2.COLOR_GRAY2BGR) # ←追加

# サイズをそろえる
window_size = (400,400)
img1 = cv2.resize(img1, window_size)
img1_binary = cv2.resize(img2, window_size)

# 画像を横に連結
img = cv2.hconcat([img1,img1_binary])

# 画像を表示
while True:
    cv2.imshow("img",img)
    if cv2.waitKey(1) == ord('q'):
        break
cv2.destroyAllWindows()

```
NestJS + GraphQLでページネーションを実装してみた[要改良]

# 概要
いちいちnodes, totalCount, hasNextPageとか書くのめんどくさいから
ジェネリクス使って汎用的に使えるようにしてみた
**ベストプラクティスじゃないと思うので参考までに見てください！**

# こんな風にかける
```typescript
    const query = {};
    query['id'] = productsInput.id;
    query['name'] = Like(`%${name}%`);

    const paginationQuery = new PaginationQuery<User>(
      query,
      this.userRepository, // Repository<User>
      limit,
      offset,
      ['posts', 'posts.comments'], // entityのリレーションも取得したいならここも書く
    );

    paginationQuery.setOrderCond({ updatedAt: 'DESC' }); // 任意

    const result = await paginationQuery.run();
```

# コード
```typescript
import {
  FindConditions,
  JoinOptions,
  ObjectLiteral,
  Repository,
} from 'typeorm';
import { EntityFieldsNames } from 'typeorm/common/EntityFieldsNames';

export class PaginationQuery<T> {
  private query:
    | string
    | ObjectLiteral
    | FindConditions<T>
    | FindConditions<T>[];
  private limit: number;
  private offset: number;
  private relations: string[];
  private repository: Repository<T>;
  private order: { [P in EntityFieldsNames<T>]?: 'DESC' | 'ASC' | 1 | -1 };
  private join: JoinOptions;

  constructor(
    query: string | ObjectLiteral | FindConditions<T> | FindConditions<T>[],
    repository: Repository<T>,
    limit?: number,
    offset?: number,
    relations?: string[],
  ) {
    this.query = query;
    this.limit = limit || 10;
    this.offset = offset || 0;
    this.relations = relations || [];
    this.repository = repository;
  }

  async setOrderCond(
    order: { [P in EntityFieldsNames<T>]?: 'DESC' | 'ASC' | 1 | -1 },
  ) {
    this.order = order;
  }

  async setJoinCond(join: JoinOptions) {
    this.join = join;
  }

  async run() {
    const [data, total] = await this.repository.findAndCount({
      where: this.query,
      take: this.limit,
      skip: this.offset,
      relations: this.relations,
      order: this.order,
      join: this.join,
    });

    let hasNextPage = true;
    if (data.length !== this.limit || total - (this.offset + this.limit) <= 0)
      hasNextPage = false;

    return {
      nodes: data,
      totalCount: total,
      hasNextPage: hasNextPage,
    };
  }
}
```

# 捕捉
Q. なんでorderとjoinはセッター使ってるの？

A.
`[P in EntityFieldsNames<T>]` こいつが問題児
例えば、createAt: "DESC"って書きたいんだけど上記の型エラーが出ちゃう
Tの中にcreateAtなんてないやんけ！的なやつ
なので、インスタンス生成してからセッタ経由でやったらうまくいったって話

# まとめ
この辺りはtypeorm側で用意してくれたら嬉しいな〜っていうのと
joinしてからのリレーション先のカラムをwhereで使いたい時が上手くいかない
この辺りはうまい方法あったら教えて欲しいです
営業即時行動の為の営業数値配信 (未完)

営業行動速度向上の為、営業数値のLine Bot配信

【作成理由】
①営業に必要な数値を収集する為に、4つのシステム＋エクセルを行き来する必要がある。
②営業共有項目が設定されていない為、個人判断での項目設定となっている。
③数値を収集する事が目的化しており、収集後の実施事項が定まっていない。

【使用したツール】
□Google スプレッドシート
□Node-RED

【作成過程】
□Google スプレッドシートの作成
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2492115/9cfbf9ee-cdf5-4b56-6ba7-3dd75a989de6.png)
□Node-REDの各設定 (未完)
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2492115/beb4f7fb-d9f5-c11c-39a3-1068191b74ac.png)
・Google Developers Consoleより鍵作成
・Edit G Sheetのノードを編集もデバッグが出来ず。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2492115/7dc63454-5081-42dc-91d6-b0ca52c963ac.png)

【課題】
□最終まで完成させる事。
□スプレッドシートの中身をより具体的実行レベルに詳細化させる事。
 (Botでの応答完成後に編集予定、)
golangのinterface

# interface がよくわからん

interface を[英和辞典][1]で調べると**境界面、接点、共通の問題**と出てくる。
[コンピューター用語辞典][1]によると

> インタフェースは,実装についての情報をもたないメソッドの集合の宣言とする.
> インタフェース及び継承をサポートするオブジェクトシステムでは,
> インタフェースは,一般に他のインタフェースから継承できる

ここからはコードを用いて go のコードを使いながら interface の理解を進める。

## interface のメソッドを満たしていれば異なる構造体でも interface に代入できる。
### 1

```go:main.go
type Hoge interface {
	FuncA()
	FuncB()
}

type Foo struct {
    x string
    y int
    z bool
}
```

上記のコードの Hoge インターフェイスは FuncA、FuncB という関数を持った集合体 = メソッドの集合体
実装部分は Foo が担っている。
実装：Foo
インターフェイス：Hoge
まず初めに実装部分の Foo にメソッドを定義する

```go:main.go
func (f *Foo) FuncA() {}
func (f *Foo) FuncB() {}
```

Hoge インターフェイスが持っているメソッドと同じ名前のメソッドを構造体 Foo に実装する。
ここで Hoge と Foo の関係が生まれる。
ここからインターフェイスがどういう役割を果たすかを考えていく。

```go:main.go
package main

type Hoge interface {
	FuncA()
	FuncB()
}

type Foo struct {
	x string
	y int
	z bool
}

func (f *Foo) FuncA() {}
func (f *Foo) FuncB() {}

func hogehoge(d Hoge) {
	d.FuncA()
	d.FuncB()
}

func main() {
	var hoge Hoge
	hoge = &Foo{} // 型はHoge
	hogehoge(hoge)

	foo := &Foo{} // 型はFoo
	hogehoge(foo)
}
```

hogehoge という新しい関数を追加した。hogehoge は引数に型 Hoge を受け取る。
main 関数に hoge と foo 二つの変数を用意し関数 hogehoge の引数に入れる。
ここで注目してほしいのが、変数 hoge と変数 foo はそれぞれ異なる型を持った変数であるが、
どちらもエラーは起きない。ここでもうひとつ新しい構造体を追加する。

```go:main.go
package main

type Hoge interface {
	FuncA()
	FuncB()
}

// foo struct
// foo method

type HogeFoo struct {
	a string
	b string
	c string
}

func (h *HogeFoo) FuncA() {}
func (h *HogeFoo) FuncB() {}

func hogehoge(d Hoge) {
	d.FuncA()
	d.FuncB()
}

func main() {
	var hoge Hoge
	hoge = &Foo{}
	hogehoge(hoge)

	foo := &Foo{}
	hogehoge(foo)

	hogefoo := &HogeFoo{}
	hogehoge(hogefoo)
}
```

新しく追加した構造体 HogeFoo を持った変数 hogefoo も関数 hogehoge の引数に正しく入っている。
エラーは起きない。つまり、異なる構造体を持っている変数でもひとつの interface を満たしていれば、どちらも同じ interface に代入できる。

## 構造体の実装と構造体の使用を切り離して考えられる。

最初に新しい interface を追加する。

```go:main.go
package main

// Hoge interface

type Half interface {
	FuncA()
}

// foo struct
// foo method

// HogeFoo struct
// HogeFoo method

func hogehoge(d Hoge) {
	d.FuncA()
	d.FuncB()
}

func half(ho Half) {
	ho.FuncA()
}

func main() {
	var hoge Hoge
	hoge = &Foo{}
	hogehoge(hoge)

	foo := &Foo{}
	half(foo)

	hogefoo := &HogeFoo{}
	half(hogefoo)
}
```

新しく追加した interface、Half は FuncA だけ持っていて FuncB は持っていない。
構造体 Foo と構造体 HogeFoo は Hoge インターフェイスと Half インターフェイス、どちらも満たしている。
関数 half は Half の型を持った引数を受け取るがこの時引数に変数 foo、変数 hogefoo をそれぞれ入れると FuncA しか使用できなくなっている。
Half インターフェイスは FuncA しか持っていないので当然なのだが、これが interface を使用する有用性なのではないかと推測する。
つまり構造体の使用方法を interface によって明確にでき、構造体にさまざまなメソッドが実装されていたとしても、使用するときには必要なメソッドのみを指定し、使用できるので、不要なメソッドに依存せずに済む。

## 終わりに

まだ実際に開発などで使用していないので確実に掴めた感覚にはなりませんでしたが、
何となくでも使い方のイメージが掴めました。
この記事が誰かの参考になると嬉しいです。
最後まで読んでいただきありがとうございました。

## 参考サイト

[Golang インターフェース][3]

[[Golang]interface は何者だ-Gopher への道 ②][2]

[1]: https://ejje.weblio.jp/content/interface
[2]: https://cloudsmith.co.jp/blog/backend/go/2021/08/1847845.html
[3]: https://zenn.dev/rstliz/articles/1e45e7330f9b77
scssのmixinであらかじめ定義されている変数リストを使用できるようにする



## 宴もたけなわでございますが、こう書けば良い。

意外に参考書とかネット記事を探しても見当たらなかったから苦戦しました。
カラーマネジメントとかでも頻繁に使えそうなので重宝しそうです。


```scss
@import url(http://fonts.googleapis.com/earlyaccess/notosansjp.css);

$weights: (
    'regular': 400,
    'medium': 700
) !default;

@mixin notoFont ($weight: medium) {
    font-family: 'Noto sans jp';
    font-weight: #{map-get($weights, $weight)};
}

$colors: (
    'black': '#000',
    'white': '#fff',
    'error': '#f00'
) !default;

@mixin color ($color: black) {
    color: #{map-get($colors, $color)};
}

p {
    @include notoFont();
    @include color();
}
```
[備忘録]GithubのClone時にユーザ名と個人アクセストークンを指定

いつも忘れてしまうので、備忘録として投稿。
複数のユーザを使い分けている場合などで結構使ってます。

# Clone
```shell
git clone https://{GIT_USER}:{GIT_PERSONAL_TOKEN}@github.com/xxx/xxx.git
```
# Config
```shell
git config --local user.name "USERNAME"
git config --local user.email "USERMAIL"
```

以上です！
Visualforce脆弱性について

##本文にてApexサーバ側のデータをVisualforce画面に表示する時の脆弱性を整理する。

##Apexサーバ側のデータをVisualforce画面に表示する方法
#### ◆従来のJSを利用すること
つまり、VisualforceのHiddenタグを定義して、JSやjQueryを利用して値を取得する

```testVFPage1.html
<apex:inputHidden id="testId" value="{!testApexValue}" />
<script>
function getValue() {
    console.log($('id$=testId').val());
}
</script>
```
#### ◆Visualforce独自な値取得方法を利用すること
つまり、VisualforceのHiddenタグを定義しなくても、{!$component.XXXX}を利用してサーバ側のデータが参照できること。

```testVFPage2.html
<script>
function getValue() {
   // Hidden項目を定義しない
    console.log('{!$component.testApexValue}');
}
</script>
```
##脆弱性になるパターン
◆上記の２つの方法は特に脆弱性にならないです。
◆上記の２つコードを混ぜて実装する場合、脆弱性になる!!!

```testVFPage3.html
<!-- Hidden項目を定義する -->
<apex:inputHidden id="testId" value="{!testApexValue}" />
<script>
function getValue() {
    console.log('{!$component.testApexValue}');
}
</script>
```
##解決案
一つの項目について、Hiddenタグと{!\$component.XXXX}を同時に利用しないように注意しましょう。
・Hiddenを定義する場合、JSの中に{!\$component.XXXX}を利用しないこと。従来のJSを利用して値を取得すること。
・JSの中に{!$component.XXXX}を利用する場合、Hiddenを定義しないこと。
MacのPythonで音声データを扱う：PyAudio環境構築メモ

PythonでAudioデータを扱いたくなったのでプログラミングを始めようと思いました。
環境構築に思ったより時間がかかったので、メモとして残します。

##開発環境
・Mac(Mac Book Air ２０１３）
・MacOS Big Sur(11.5)
・Python 3.9.1
・pip 21.3.1

##目的
Audioファイル入力、外部入力音声を利用して、加工後の音声データを音声出力、ファイル出力したいと考えています。

##わかったこと
・Audioデータの録音と再生にはPyAudioモジュールが使える
・PyAudioモジュールは、PortAudioというソフトのPython用インターフェース
・要するに、PortAudioを入れて、その後PyAudioを入れると良さそう

##参考にしたページ
https://qiita.com/mayfair/items/abb59ebf503cc294a581

```%brew install portaudio
```
実行するとエラーでした。ログを残せていないのですが、HomeBrewの更新が必要と判断。
```%brew upgrade
```
またまたエラー。以下のページと同様の状態だったはずです。
とても参考になりました。ありがとうございます。
https://techracho.bpsinc.jp/wingdoor/2021_04_09/104821

OS更新は流石に時間がかかりすぎるので、コマンドラインツールだけ更新します。
```%sudo rm -rf /Library/Developer/CommandLineTools
%sudo xcode-select --install
```
ようやくPortAudioを導入できそうです。

```% brew install portaudio
```
取得に失敗したのか、ソースからビルドしたようでした。なんとか入りました。

いよいよPyAudioです。

```
% pip install pyaudio   
Collecting pyaudio
  Using cached PyAudio-0.2.11.tar.gz (37 kB)
  Preparing metadata (setup.py) ... done
Building wheels for collected packages: pyaudio
  Building wheel for pyaudio (setup.py) ... done
  Created wheel for pyaudio: filename=PyAudio-0.2.11-cp39-cp39-macosx_10_15_x86_64.whl size=23691 sha256=141ea65aa52f3d6f8e74d9f9c7b0ddb2dee65dad1d0ba83a75111a6a642da89d
  Stored in directory: /Users/hogehoge/Library/Caches/pip/wheels/76/e7/d6/193c174cc4cba9409e8eecea8f9e986fc9c88e08160759dfe8
Successfully built pyaudio
Installing collected packages: pyaudio
Successfully installed pyaudio-0.2.11
```

ようやく入りました。
なかなか時間がかかりました。
開発ツールはこまめに更新を確認して適時反映しておかないと
このように苦労することになりますね。
Dockerなどの意義も身に染みて理解できました。

今回はここまで。ようやく音声をつかったプログラミングができそうです。
以下は本家のリンク

---
http://www.portaudio.com/

---
https://pypi.org/project/PyAudio/

---
超音波センサーで距離を測ってみた

秋月から超音波センサーが届いたので、下記の記事を参考に作成してみた。

https://zenn.dev/kotaproj/books/raspberrypi-tips/viewer/200_kiso_hcsr04

ブレッドボードより基板使った方がかっこいいかなと思い、久ぶりに電子工作工作してみた。
完成したのがこちら。半田に手こずったし、機材そろえるのに少しお金かかったけど、手を動かすと楽しい。。
![IMG_3974.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176158/15f3f2c1-9b13-0b24-e693-1f5827099464.jpeg)

#回路図
HC-SR04のECHOから出力は、5Vが出てくる。ラズパイのGPIOは、3.3Vまでしか許容しないため、抵抗を使って3.3Vにしている。

![HC-SR04_回路図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176158/b5d8c49b-c1cd-5e1a-2053-55168cc0e919.png)

#code 
TRIG,ECHOの指定ができれば、DistanceSensorを使えばm単位で結果を出力される。

##1.1 pigpio
Raspberry PiのGPIOを制御するため、再起動して有効になるようにsystemctlのenableをonにした。

```
$ sudo service pigpiod start
$ sudo systemctl enable pigpiod.service
```
##1.2 python 
測定誤差が生じるため、10回測定しそのmedian値を結果に出力するようにした。
単位は、cmにしている。

```python:hc_cr04.py
from gpiozero import DistanceSensor
from gpiozero.pins.pigpio import PiGPIOFactory
import statistics
import math 

import time

PIN_TRIG = 22
PIN_ECHO = 27
point    = 10
tmp      = [num for num in range(point)]

factory = PiGPIOFactory()
sensor = DistanceSensor(PIN_ECHO, PIN_TRIG, pin_factory=factory)

for i in range(point):
    print('Distance to nearest object is', sensor.distance, 'm')
    tmp[i] = sensor.distance * 100
    time.sleep(0.5)

median = statistics.median(tmp)
print('Distance to nearest object is', '{:.2f}'.format(median), 'cm(median', point ,'point)')

```

#感想
ひとまず超音波センサーを使って距離を測定することができるようになった。電子工作をしてみて手を動かすのは、難しいけど、信号が出なかったときにどこが原因か考えて答えを見つける楽しさがある。テスターとオシロスコープ使うような複雑なことやれると、もう少し面白くなりそう。
M1 Macでiterm2をかっこ使いやすくカスタマイズ

本職の方のように頻繁にterminalを使用するわけではありませんが、環境構築の際にhomebrewやpoetry等をたまに使用します。そのときに、webサイトを参照しながらコマンドをコピペして実行するには、guake風+カスタマイズで、terminalをキーボードショートカットキーで呼び出せる用にして、ブラウザを見ながら操作できるのが個人的ベストです。iTerm2を個人的に使いやすい形にする設定方法を紹介します。
さらにiTerm2にcpuやメモリ使用状況の表示させる設定、テーマカラーの変更や、preztoの導入についても紹介します。

## 完成形
![Screen Shot 2022-01-17 at 17.24.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64403/c0323c02-b135-b08e-7122-288e377e09b4.png)

上の画像の形を構築していきます。
主な設定内容
1. キーボードショートカットキー（F12）を押すと下からterminal画面が迫り上がってくる
2. 下部にcpuやメモリ使用状況を表示
3. Color Presetにicebergを設定し、zshにpreztoを導入し、テーマをpureにする

## iterm2の設定

- icebergのリポジトリをclone (https://github.com/Arc0re/Iceberg-iTerm2)

```
$ git clone https://github.com/Arc0re/Iceberg-iTerm2.git
```

- Color Presetに先ほどダウンロードしたicebergをimportして設定します。設定ファイルはディレクトリを移動していなければ、/Users/(ユーザー名)にあるはず。
 
![Screen Shot 2022-01-17 at 17.40.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64403/c2efc413-33a3-45c7-c4a6-7f73c383fd86.png)

- windowの見た目や下から迫り上がってくるように設定

![Screen Shot 2022-01-17 at 17.52.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64403/19407b9d-e2ba-38ed-8a1f-95c3da06f0dd.png)

- キーボードショートカットキー（F12）でiterm2が表示されるようにする

![Screen Shot 2022-01-17 at 17.54.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64403/3f11fe61-a013-2077-32a6-acc50949faf0.png)

![Screen Shot 2022-01-17 at 17.54.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64403/fc89c7c2-be7b-0192-aaf1-c7633ee743fb.png)

- 他の見た目の調整

![Screen Shot 2022-01-17 at 18.00.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64403/a4cb8b9f-f8e4-5c10-2e87-ef571f998960.png)


## cpuやメモリ使用状況を表示

- Status bar enbaledにチェックを入れ、Configure Status Barで設定に移動します。

![Screen Shot 2022-01-17 at 18.02.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64403/820176fe-1219-6f5b-f7b4-e77d49728960.png)

- お好みで表示したいものを次のように配置します。フォントや背景色も設定したい場合はAdvancedをクリックして、フォント等の設定画面に移動します。

![Screen Shot 2022-01-17 at 18.04.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64403/589c338f-15ff-a128-54b1-355b9b6f2ecc.png)

- お好みで背景色、フォントの種類やサイズを設定します。

![Screen Shot 2022-01-17 at 18.04.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64403/f1bf1390-d23f-94c3-5059-df4231bea70c.png)


## zshにpreztoを導入

preztoを導入します。
Catalinaからデフォルトのシェルがzshになっているそうなので、zshへの切り替えの設定は省略します。


```
// リポジトリをclone
$ git clone --recursive https://github.com/sorin-ionescu/prezto.git "${ZDOTDIR:-$HOME}/.zprezto"
```

```
// 既存の設定ファイルを退避(必要な場合)
$ mkdir zsh_orig && mv zshmv .zlogin .zlogout .zprofile .zshenv .zshrc zsh_orig
```

```
// 設定ファイルを作成
$ setopt EXTENDED_GLOB
for rcfile in "${ZDOTDIR:-$HOME}"/.zprezto/runcoms/^README.md(.N); do
  ln -s "$rcfile" "${ZDOTDIR:-$HOME}/.${rcfile:t}"
done
```

- テーマはpureを設定することにしました。.zpreztorcファイルを編集します。テーマの編集箇所は私の場合は123行目にありました。

```
$ vim .zpreztorc
```

```
zstyle ':prezto:module:prompt' theme 'pure'↲
```

## 参考文献

https://shinshin86.hateblo.jp/entry/2018/02/10/233159

https://dev.classmethod.jp/articles/zsh-prezto/
Twitterのシェアボタンを実装

# 目的
今回、以下の画像の下の方にあるTwitterシェアボタンの実装をどうやったかご紹介します。
同じように実装したいと思っている人のお役に立てれば嬉しいです。

[![Image from Gyazo](https://i.gyazo.com/a98adf439feb3f86c27b89fd23d546a6.jpg)](https://gyazo.com/a98adf439feb3f86c27b89fd23d546a6)

Twitterのボタンをクリックすると別タブでTwitterのページが表示され以下の画像のように
文字やシェアしたいURLが表示されツイートできる状態になります。

[![Image from Gyazo](https://i.gyazo.com/7bf50f1b79b39f19044029ba061c257e.png)](https://gyazo.com/7bf50f1b79b39f19044029ba061c257e)

このようにシェアしたいページをボタンを押せばシェアできるようになっています。

# 実装
結論から言うと以下のように実装しています
実装したいviewの中に

例>show.html.erb

```html
<%= link_to image_tag('twitterアイコン', class: :twitter_icon), 
"https://twitter.com/share?url=#{request.url} & text=#{@artist.name} のDIG ARTISTページ", 
data: { show_count: false }, title: 'Twitter', target: '_blank', rel: "noopener noreferrer" %>
```

簡単に言うと
画像にTwitterシェアのリンクを埋め込んでいます。

### 画像
まずボタンにしたい画像(ファイル名はなんでも大丈夫です)を
app/assets/imagesに入れ

```html
<%= link_to image_tag('画像のファイル名') %>
```
で画像を呼び出してます。

### URL
```html
<%= "https://twitter.com/share?url=#{request.url}" %>
```
でシェアしたいページを指定しています。
 #{requests.url}で現在表示しているURLを入れていますが。
シェアしたいページが決まっているのであればそのページのURLを入れれば
そのシェアしたいページのURLがシェア出来るようになります。

### text
textは入れても入れなくてもどちらでも大丈夫です。
URLの後に

```html
<%=  "https://twitter.com/share?url=#{request.url}　& text=入れたい文章” %>
```
で好きな文章を入れる事ができます。

### ハッシュタグ
今回の実装には入れていませんがハッシュタグも追加する事ができます。
URLの後に

```html
<%= "https://twitter.com/share?url=#{request.url} & hashtags=好きなハッシュタグ" %>
```
今回の実装に追加するとこんな感じです。

```html
<%= link_to image_tag('twitterアイコン', class: :twitter_icon), 
"https://twitter.com/share?url=#{request.url} & text=#{@artist.name}のDIG ARTISTページ & hashtags=バンド",
 data: { show_count: false }, title: 'Twitter', target: '_blank', rel: "noopener noreferrer" %>
```
[![Image from Gyazo](https://i.gyazo.com/84222255492dd5bd2672537538db497a.png)](https://gyazo.com/84222255492dd5bd2672537538db497a)
上の画像のようにハッシュタグが追加されました。

### その他
```ruby
target: '_blank'
```
これを記述することで別タブで表示しています。
これを外すと同じタブで表示されます。

```ruby
rel: "noopener noreferrer"
```
こちらは外部サイトへのリンクのためセキュリティの観点から記述してます。

以下の記事参照

https://www.marorika.com/entry/rel-noopener-noreferrer

# まとめ
Twitterシェアボタンを実装したいviewに

〇〇.html.erb
（テキストあり、ハッシュタグあり)

```html
<%= link_to image_tag('画像のファイル名', class: :クラス名), 
"https://twitter.com/share?url=#{request.url} 
& text=シェア時に入れたい文章 & hashtags=シェア時に入れたいハッシュタグ", 
data: { show_count: false }, title: 'Twitter', target: '_blank', rel: "noopener noreferrer" %>
```
（テキストあり、ハッシュタグなし)

```html
<%= link_to image_tag('画像のファイル名', class: :クラス名), 
"https://twitter.com/share?url=#{request.url} 
& text=シェア時に入れたい文章", 
data: { show_count: false }, title: 'Twitter', target: '_blank', rel: "noopener noreferrer" %>
```
（テキストなし、ハッシュタグなし)

```html
<%= link_to image_tag('画像のファイル名', class: :クラス名), 
"https://twitter.com/share?url=#{request.url} ",
data: { show_count: false }, title: 'Twitter', target: '_blank', rel: "noopener noreferrer" %>
```

以上のようになります。
ぜひ試してみてください！
単体テストと結合テストの違い

# テストとは
Webアプリケーションを開発するときに、
こちらが```動いて欲しいような動作をしてくれるかを検証する```ためにテストをします。

Railsで開発する場合はRSpecと言うテスト用のフレームワークです。
テストはコードを書いて、想定通りの動作をするのかを検証していきます。
テストをしないとサービスをリリースするときに、
ちゃんと動作せずにリリースすることになり、
クライアントなどに迷惑がかかってしまうことがあります。

# 単体テスト
***一つ一つのプログラムが正常に動くのかを確認していくテストです。***
飛行機で例えると部品を一つ一つ異常がないかをチェックしていくイメージです。
部品に異常があれば空を飛んでる途中に事故が起きてしまいますよね。

アプリケーションなども同じでシステムに異常があれば、
思ったように動作しなくなってしまいます。


# 結合テスト
インターフェースが正常に動いているかをテストです。
つまり***複数の機能を合わせて想定通りに動作するのかをテストするのが結合テストです。***

飛行機で例えるとこのボタンを押せば車輪が出るのか、このレバーを引けば上昇するのかなど
部品と部品で連動して動作するかをテストします。

railsなどは
controllerなどのAPI関連のテストでRequest specと言います。

# どんなテストツールがあるか
例えばこんなのがあります。

- Rails
RSpec

- React、Vue.jsなどのフロントエンド
Jest Cypress Autify

- Laravel
phpunit


# 最後に
総合テストとシステムテストというものがあります。

総合テストは大きな単位でのテストです。
システムテストは実践的なテストです。
新幹線のテスト走行みたいなイメージです。

よければ色々調べてみてください。


# 参考資料
https://www.geekly.co.jp/column/cat-technology/1903_058/
ros c++ boost::threadを使う

# はじめに

rosをインストールするときインストールされるboostを使用してthreadを行う方法

# 環境

ros-noetic

# 内容

1.パッケージを作成
2.プログラム作成

```src/thread_sample.cpp
#include <iostream>
#include <boost/thread.hpp>

#define LOOP_NUM 5

// hogehogeと標準出力する関数
void Hoge() {
  for(int i = 0; i != LOOP_NUM; i++) {
    // hogehogeと標準出力(標準出力はスレッドセーフじゃないから本当は排他制御が必要だけど今回は省略)
    std::cout << "hogehoge" << std::endl;

    // 100ミリ秒スリープ
    boost::this_thread::sleep(boost::posix_time::milliseconds(100));
  }
}

// piyopiyoと標準出力する関数
void Piyo() {
  for(int i = 0; i != LOOP_NUM; i++) {
    // piyopiyoと標準出力(標準出力はスレッドセーフじゃないから本当は排他制御が必要だけど今回は省略)
    std::cout << "piyopiyo" << std::endl;

    // 100ミリ秒スリープ
    boost::this_thread::sleep(boost::posix_time::milliseconds(100));
  }
}

// main
int main() {
  // Hogeスレッドの生成と実行(&は無くてもよい)
  boost::thread th_hoge(&Hoge);

  // Piyoスレッドの生成と実行(&は無くてもよい)
  boost::thread th_piyo(&Piyo);

  // スレッドの終了を待つ(逆順でも問題ない)
  th_hoge.join();
  th_piyo.join();

  return 0;
}
```

引用: https://www.mathkuro.com/c-cpp/boost/how-to-use-boost-thread/

3.CMakeLists.txtを以下のように変更

```cmake:CMakeLists.txt
cmake_minimum_required(VERSION 3.0.2)
project(boost_sample)

find_package(catkin REQUIRED)

## (ref) https://stackoverflow.com/questions/56575376/cmake-with-boost-thread-library
find_package(Boost REQUIRED COMPONENTS thread) ## add

catkin_package(
)

include_directories(
# include
# ${catkin_INCLUDE_DIRS}
  ${Boost_INCLUDE_DIRS} ## add 
)

message(${Boost_VERSION_STRING}) ## add

add_executable(thread_sample src/thread_sample.cpp)
target_link_libraries(thread_sample
  Boost::thread ## add 
)
```

以上
初めてのLINEbot制作でECサイト運営の業務効率化！ ～注文番号入力で納期予定日がわかるbot作りに挑戦～

初めてのLINEbot制作でECサイト運営の業務効率化！
～注文番号入力で納期予定日がわかるbot作りに挑戦～



前職では必要なものは全てシステム化されている職場で勤務しておりましたが、転職を行い、ECサイトを扱う会社で今は業務しています。ベンチャー企業ということもあり、できる限りお金をかけずに課題を解決し、業務効率化を目指して日々業務に取り組んでいます。


お客様より注文があると普通のECサイト同様、おおよその予定配送日は自動メール送付されます。ただ普通のECサイトと異なり、商品を加工しお客様にお届けするため、加工状況によってはお届けが前後することがあります。


そのため、加工状況に応じて納期予定が分かり次第、1件ごとに手動でメールを送信しています。（某大手ECサイトではステータスごとに自分で確認することができるかと思います。）


この業務を効率化することは出来ないかと思い、IT初心者、知識ゼロに等しい私が、今回LINEbotを使って自分自身で注文番号を入力すると配送予定納期が分かるというbotを作成したいと考えました。


【プログラミング初心者がやってみた】

使用ツール
・Googleスプレッドシート
・Node-red
・LINE Developers

まず、Node-redを使い、Googleスプレッドシートと連携するNodeを入手、使用できるように準備を行いました。
こちらのサイトでとでとても詳しく、紹介されており、初心者の私でも簡単にできそう！と思い作業してみました。（参照https://blog.enebular.com/nodes/letsuse-google-spreadsheet-node/）

すると、最後まで順調に進んだと思いきや、エラーが発生し、進まず、、。

システム詳しい方に相談したところ、秘密のキーの貼り付けに問題があり教えて頂いたのですが、何度やってもうまくいかず、、、。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2494868/ea961aaf-1f15-4d82-188b-649b0defa9d2.png)



今回は時間を確保できないということもあり、一時断念することにしました、、。


ただ、LINEbotは優秀な誰かが作成したIPAアドレスや、Googleスプレッドシートを組み合わせることにより
とても便利なものにすることができるということを実感したので、時間をみて引き続きチャレンジしていきたいと感じました。

【もっと学びたい！】
今後はECサイト運営するにあたり、お客様への適切な表現方法などを瞬時に回答してくれるLINEbotなどもあったらいいなと思うので、今回試作品が完成次第チャレンジしたいと思います！！


できるできないにかかわらず、アイデアをもって業務にあたりたいと思います！！

最後まで読んでいただいた方、ありがとうございます。
Dataverseテーブルのキーについて

Dataverseのテーブルのキーについて以前調べたので備忘録を残します。

#Dataverseのテーブルのキーについて
Dataverseはテーブルごとに自動的にGUIDという一意識別子を生成されますが…

#外部システムに接続させるために、代替キーを設定することができる。
- レコードを作成後でなければ以下の手順でキーは動作します。

https://www.d3654.be/cds-entity-key-setting/


#テーブルでキーを設定してもキーが動作しない場合について
この現象が発生するのは、キーを定義する前に同一のキーを持つレコードを複数作成してしまっていた場合です。
 この場合は以下の作業2点を行えば改善できます。（①だけだとキーが重複する現象は改善されませんでした。）

1.  作成してしまった重複レコードを1つにする
1.  列の情報を編集するなどでテーブルを保存しなおす
【Project Euler】Problem 34: 各桁の階乗の和

* 本記事は[ProjectEuler](https://projecteuler.net/about)の「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。

### 問題 34：各桁の階乗の和

原文 [Problem 34: Digit factorials](https://projecteuler.net/problem=34)

**問題の要約：各桁の階乗の和が元の数と同じになる数の合計を求めよ**

これも上限が問題になりますが、7桁を超えると全桁が9でも階乗の和は7桁にならないので$9! \times 7$まで調べればOKです。

```python
import math
fct = [math.factorial(d) for d in range(10)]
def digFactSum(n):
  return sum(fct[int(d)] for d in str(n))

print(f"Answer = {sum([n for n in range(11,fct[9]*7) if n == digFactSum(n)])}")
```

（開発環境：Google Colab）
【Project Euler】Problem 33: 桁を消して約分

* 本記事は[ProjectEuler](https://projecteuler.net/about)の「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。

### 問題 33：桁を消して約分

原文 [Problem 33: Digit cancelling fractions](https://projecteuler.net/problem=33)

**問題の要約：以下の例のように1より小さい分子・分母ともに2桁の分数の共通の1つの数字を消したときに約分になっているような分数（4つある）の積を約分したときの分母を求めよ**

```math 
\frac{4 \underline{9}}{\underline{9}8}=\frac{4}{8}
```

条件を満たす分数は以下のような形をしているので、$n,d,i$を$n<d$の条件で全探索します。答えは4つの分数の積を約分した分母なので、pythonのFractionモジュールを使って自動的に約分しました。

```math 
\frac{10n+i}{10i+d} = \frac{n}{d} \ \ \ \   (n<d)
```

```python
import itertools
from fractions import Fraction

prd = Fraction(1)
for n, d in itertools.combinations(range(1,10),2):
  for i in range(1,10):
    if (10*n+i)*d == (10*i+d)*n:
      print((10*n+i),(10*i+d), n, d )
      prd *= Fraction(n,d)

print(f"Answer is {prd.denominator}, (prodct={prd})")
#16 64 1 4
#19 95 1 5
#26 65 2 5
#49 98 4 8
#Answer is 100, (prodct=1/100)
```

（開発環境：Google Colab）
基本設計と詳細設計の違いについて

# 設計とは
これから開発するアプリケーションのレシピを考えることです。
よく映画とかで基地の設計図とかありますがあのアプリケーションバージョンみたいな
イメージです。
設計の前後に```要件定義```と```プログラミングでの開発```があります。

要件定義がわからない初学者の方は下記の資料で確認してください。

https://qiita.com/Hashimoto-Noriaki/items/46be6a1202503dc4f99e

# 基本設計とは
Webアプリケーションの***全体像を設計したもので何の機能があるのか***を
わかりやすくまとめたものです。
```クライアントに見せること前提で書くことが多い```みたいです。

ex)具体的には以下のものを洗い出すみたいです。

|業務フロー |業務の流れを理解し機能を洗い出す|
|:-----------|------------:|
|機能一覧表|	開発範囲となる機能の一覧|
|ネットワーク構成図|ネットワークの構成
|テーブル定義|データベースのテーブルの定義|
|ER図|	データベースのER図の作成|
|画面レイアウト|画面イメージ|
|帳票レイアウト	|帳票イメージ|

⚫︎引用資料
https://products.sint.co.jp/obdz/blog/basic-design-detailed-design


# 詳細設計
基本設計で***設計したものをどのように開発していくのか***をわかりやすくまとめたものです。
```開発者向けに作ることが多いみたいです。```
ここで細かい機能などを決めたらコードを書いてプログラミング(開発)していきます。

⚫︎具体的にはどんな内容か？
処理内容などを言語化し、手順書１から実装するとこまでコメントを入れて
何をやりたいかをそれぞれ手順ごとに説明しながら書いていきます。

ざっくりですが

ex)
① 〜を設定
②〜の内容を取得
③〜を削除
④〜をした場合は取得だけど〜しなければ削除

みたいな感じです。

# 最後に
未経験や経験が浅いエンジニアは特に０から設計して開発することはあまりないみたいです。
既存のアプリのコードを修正したり機能を追加したりすることが多いみたいです。
未経験からエンジニアを目指す人は
０からアプリを開発してポートフォリオのクオリティをあげるだけでなく
設計書をもとに調べながら実装していく、共同開発などで既存のアプリを修正、
他の人のコードを読む、コードレビューなどを学習段階でやるといいなと思いました。


# 参考資料

https://wa3.i-3-i.info/diff236design.html

https://products.sint.co.jp/obdz/blog/basic-design-detailed-design
KotlinでviewBindingを使う

## ブロジェクト作成
赤のMainActivityを開きSplitで開くと、コードとデザインを同時に確認できます。
水色が`texttView`のコードとエディタです。
![スクリーンショット 2022-01-17 16.48.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/9abe33b5-9bb7-281c-fd0d-fa209cba6ad8.png)

## ボタン追加
ボタンを追加すると、コードとデザイン両方追加されます。
![スクリーンショット 2022-01-17 17.05.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/c56b9b9c-4324-34bb-abad-889b3d0051b3.png)

## 背景色も変更してみる
赤枠のbackgroundをいじれば変更できました。
![スクリーンショット 2022-01-17 17.08.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/d5598323-d5b8-1c3c-0790-727b60ad5791.png)

## バインディングの設定
build.gradleを開いて、赤で囲ったコードを追加し、右上のSync Nowを押します。
この辺りのやり方は[公式ドキュメント](https://developer.android.com/topic/libraries/view-binding?hl=ja)を見てください。
![スクリーンショット 2022-01-17 17.13.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/1e8a45b0-9b09-1d6d-f35c-a97cca61c1f1.png)

## バインディングを使う
### バインディングクラス
上で設定したので、バインディングクラスがファイルごとに生成されるそうです。
今回、初期ではactivity_main.xmlがあるので、ActivityMainBindingが生成されています。
例えば、activity_result.xmlを作成すると、ActivityResultBindingが生成されるはずです。

### 定義に飛んでみる
ActivityMainBindingにカーソルを合わせて`command + クリック`するとxmlファイルに飛べるので関連性が分かると思います。

### 使い方
このbindingを使って、レイアウトの変数とビューにアクセスできます。
設定方法はバインディングクラスの`inflate()`メソッドを使用して、オブジェクトをバインドできるそう。
`layoutInflater`をいうのは、`レイアウトXMLファイルを対応するViewオブジェクトにインスタンス化するもの`だそうです。([公式ドキュメント](https://developer.android.com/reference/kotlin/android/view/LayoutInflater))
詳しいことは[公式ドキュメント](https://developer.android.com/topic/libraries/data-binding/generated-binding?hl=ja#kotlin)参照。
![スクリーンショット 2022-01-17 17.24.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/44a55516-48b0-e0a8-9ede-a99f705a061f.png)


## カウントアップ処理を追加してみた
`tapCount`を作成してこれを`textView`に反映します。
`binding`を通して`textView`や`button`にアクセスしてやりたい処理を書くことができるそうです。
![スクリーンショット 2022-01-17 17.45.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/a9a4e4ab-a681-c896-889f-2c242ac8fa0a.png)

## 最後に
今回はバインディングの方法について書いてみました。
まだAndroid・Kotlin始めて３日目くらいなので他の方法などあれば教えてくださーい
"rvictl"が"FAILED"になったときの解決策

# はじめに

「rvictl」はiPhone(実機)の通信ログ(パケットのキャプチャ)を取得する際に使用されるコマンドです。
iPhoneをMacにライトニングケーブルに繋いだ後、Macから以下のコマンドを実行することで仮想的なネットワークカードが作成され、WiresharkなどからiPhoneの通信を参照することが可能となります。

```text:
$ rvictl -s "iPhoneのUDID"
```

iPhone(実機)から通信ログ(パケットのキャプチャ)を参照する方法については、他の記事を参照すると良いでしょう。

参考記事
- [iPhone(実機)の通信ログ(パケットのキャプチャ)を簡単に取得する方法](https://qiita.com/shirochan/items/cdb244b12cf5d08d4766)
- [MAC OS CatalinaでiPhoneの通信をキャプチャする方法](https://qiita.com/U_Sukeee/items/82348c82af0242c37d3d)

# "rvictl"が"FAILED"になった
```text:
# rvictl -s "iPhoneのUDID"
```

あるとき、上記のコマンドを実行した場合、以下のように"FAILED"になってしまいました。

```text:
Starting device "iPhoneのUDID" [FAILED]
```

こちらの解決策について書きたいと思います。
ちなみに、私の環境は以下の通りです。

|  項目  |  詳細  |
| ---- | ---- |
|  Mac  |  Apple Silicon Macではない  |
|  OS  |  macOS Monterey バージョン 12.1  |
|  Xcode  |  Version 13.2.1(13c100)  |
|  iPhone  |  iPhone11(iOS 15.2)  |

# 一応の確認

今回紹介するのは、あくまで以下のような"FAILED"になったときの解決策となります。

```text:
Starting device "iPhoneのUDID" [FAILED]
```

もし、コマンドを実行しても何も起こらずにプロンプトが返ってくるのであれば、「UDIDが誤っている」可能性が高いかと思います。
その場合は、UDIDが大文字英数であれば小文字英数に変換したり、その逆を行なっていただければうまく行くかもしれません。

# 解決策

"rvictl"が"FAILED"になるのは、MacのOSがアップデートにより、Appleシステムのセキュリティパフォーマンスが改善されたためとのことです。（詳細は私も良くわかっていません。。）
以下を行うことで解決することができました。

1. Macをシャットダウンし、macOS 復旧システムで再起動させる。（macOS 復旧システムは、Mac起動時に「command(⌘) + R」を押下することでなることができます）
1. macOS 復旧システムで起動したら、画面右上のメニューバーから「ターミナル」を起動
1. ターミナルから、コマンド「csrutil disable」を実行
1. Macをシャットダウンし、通常モードで再起動
1. 通常モードで起動したら、「システム環境設定」 > 「セキュリティとプライバシー」へと遷移すると、「一般」タブの下部に「Apple.Incからの設定変更があります」（うろ覚え）のような文言が表示されますので、それを許可します。
1. これでOKです。再度「rvictl -s "iPhoneのUDID"」を実行しましょう。

# おわりに

macOS 復旧システムで実行したコマンド「csrutil disable」は、System Integrity Protection (SIP) を無効にするコマンドのようです。
iPhoneの通信ログを参照し終わったら、再度有効にした方が良いと思います。その場合は、上記の「3.」のコマンドを以下に置き換えれば、SIPを再び有効にすることができます。

```text:
# csrutil enable
```

以上、お役に立てたら幸いです。

# 参考
- [【上級者向け】System Integrity Protection (SIP) を無効にする方法](https://www.too.com/support/faq/mac/maintenance/23554.html)
- [rvictl not working on big sur and ios 14 beta 3](https://developer.apple.com/forums/thread/655329)
GitHub Import a repositoryでパスワードを何度も聞かれて進まない

## Import a repositoryでログインを何度も迫られる

Githubでrepositoryを別のアカウントへコピーしたいとき、
『Import a repository』が便利に思えるが、

なぜか

```
Your old project requires credentials for read-only access. 
We will only temporarily store them for importing.
```

というメッセージとともに
何度もログインを迫られてしまう。

「read権限のあるアカウントでログインしているのにな…」と不思議に思い
普段行っている`メールアドレス + パスワード` だけでなく
`ユーザー名 + パスワード` でもログインを試したが、変わらずログインを再度迫られてしまう。

## 解決方法は個人アクセストークンでのログイン

`ユーザー名 + 個人アクセストークン` を入力したところ
無事にインポートが開始された。


![スクリーンショット 2022-01-17 17.44.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25725/d1c43de5-c127-2711-1dbe-d4f78118cf08.png)


個人アクセストークン作成は、
[こちらの記事](https://qiita.com/shiro01/items/e886aa1e4beb404f9038)を参考にした
【RxSwift】テストを書こうとしたら「No such module 'RxSwift'」

# はじめに
RxSwiftで実装した個人アプリにテストを書き始めましたが

普段テストを書かないので、こんな初歩的なところで詰まりました。

![スクリーンショット 2022-01-17 16.31.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631585/57ce36a5-5dcf-46f3-c9e3-957f1f759327.png)


# やったこと

`Editor` -> `Add Target` -> `Unit Testing Bundle` を追加

![スクリーンショット 2022-01-14 12.49.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631585/5eb0c6fd-82eb-3c1f-9d92-c786542954fc.png)

![スクリーンショット 2022-01-14 12.52.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631585/2fe2ffef-f3e9-154d-a57a-293e6f7e72e7.png)

テストファイルも追加

![スクリーンショット 2022-01-16 16.24.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631585/c4d2016d-e7e9-b612-f68c-c23343ae9f42.png)

![スクリーンショット 2022-01-16 16.27.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631585/e5e3accd-c9bc-9fd2-6e05-9eef5aef5d4e.png)

さてテスト書くか、ってところで `No such module'RxSwift'` と怒られる

![スクリーンショット 2022-01-17 16.31.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631585/57ce36a5-5dcf-46f3-c9e3-957f1f759327.png)


# 解決方法

![スクリーンショット 2022-01-17 16.32.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631585/ccc40687-f49e-9cc2-8f39-6c3d968d7a5b.png)

```swift
target '{$AppName}Tests' do
    inherit! :search_paths
end
```

が必要だったんですね。


# おまけ
**inherit!**
現在のターゲットに対する継承モードを設定する

**Parameters**
*inheritanceSymbol*
設定する継承モード

*Available Modes*
`:complete` ターゲットは親からすべての動作を引き継ぎます。
`:none` 対象は親からどの動作も引き継ぎません。
`:search_paths` 対象は親の検索パスのみを継承します。

https://stackoverflow.com/questions/37060065/what-does-inherit-search-paths-do




# 参考記事
https://dev.classmethod.jp/articles/how-to-start-ios-unit-test/

https://guides.cocoapods.org/syntax/podfile.html#inherit_bang
[Mac]Flutterで保存したドキュメントのpath

# iPhone
```dart:sample.dart
  void _saveFile() async {
    final documents = await getApplicationDocumentsDirectory();
    new Directory('${documents.path}/log').create().then((Directory directory) {
      print(directory.path);//ここでpath取得
      final file = File('${directory.path}/test.log');
      file.writeAsString('test');
    });
  }
```
普通に保存したパスをコンソール出力して
FInde上でcmd + shft + Gにて貼り付ければ飛べます

# Android
Androidの場合、上述のIPhoneの方法では出来ません

[View] > [Tool Windows] > [Device File Explorer] 

data/data/アプリ名/app_flutter/以下にありました。
Finderのパスですと
/Users/ユーザー名/Documents/AndroidStudio/DeviceExplorer/エミュレーター名/data/data/アプリ名/app_flutter/以下でした

人によって違うかもしれないので参考程度に

[公式ドキュメント](https://developer.android.com/studio/debug/device-file-explorer?hl=ja)
JIMDO+Cloudflare DNSでハマった件

JIMDO+Cloudflare DNSでハマった件。

・独自ドメインをJIMDOに移管せずにCNAMEで利用
・Cloudflare側でプロキシを有効化
していたら、ある日突然独自ドメインからJIMDOサイトに接続できなくなった。

エラーの内容はSSL証明書の期限切れ。
証明書をみるとJIMDOはLet's Encryptを利用していた。
なので期限は3ヶ月。それが切れていた。

なぜ期限が切れた？
→更新できなかったから。

なぜ更新できなかった？
→Cloudflare側でプロキシを有効化していたから。

証明書更新の際にLet's Encryptが件のドメインでJIMDOサーバー（AWS）にアクセスしようとすると、Cloudflareのプロキシサーバーにつながるから更新できなかったと推察。

以下で解決。
一旦JIMDO側で接続を削除。
Cloudflare側でプロキシを無効化。
再度JIMDO側で接続を登録。

しばらくするとCloudflareから「証明書の発行を監視しました」とメール。（要：証明書の透明性の監視）
その後もまたしばらくしてJIMDOから「接続しました」とメール。
独自ドメインでアクセス可能になった。

JIMDO+Cloudflare DNSではプロキシを無効化は必須みたい。
「常にHTTPSを使用」も切らないとダメかも。
Let's Encryptの証明書更新の際にhttp接続が必要なはずだから。