OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerの動作が怪しいときにすること

# 経緯
dockerさん起動し続けていると挙動がおかしくなることがあったので、正気に戻してあげる方法のメモです。

# 環境
Windows10

# 状況1
タスクマネージャ見ると、Vmmemのメモリ使用量がとても多くなっていました。
コマンドプロンプトから以下コマンドを叩くと、
プロセス再起動してメモリ使用量が初期状態に戻ります。
```
wsl --shutdown
```

https://devlights.hatenablog.com/entry/2021/10/27/135350

# 状況2
1の方法を実施してもなんかおかしかったので、
docker自体も再起動しておくとよいです。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20061/79a51779-e92d-7d0c-76bf-43d90ee72c40.png)

# その他
dockerのディスク容量が気になる場合は以下コマンドで未使用なボリューム、イメージなどを削除しましょう。
```
docker system prune
```


https://docs.docker.jp/config/pruning.html#id5


すっきり！
[JMeter]API実行結果を変数に保存する方法 メモ

* JMeterを用いてAPI実行結果から特定要素のみを抽出し、結果出力する方法をメモする。

## テスト用API及びJMeter設定

* [こちら](https://qiita.com/KWS_0901/items/3e9fd1e32a1b1e247e05)で試した環境をそのまま流用し、変更点のみを記載する。

## 設定手順

1. HTTP RequestにRegular Expression Extractorを追加する(Add -> Post Processors ->Regular Expression Extractor)

2. 下記のように設定する。

   ![jm_ree.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/573174b3-4279-530e-f9a4-6bd04b69fb27.png)
  ![jm_ree2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/102224c1-4b59-d838-baa8-6cb58644524c.png)


   

3. 実行結果出力用のBeanShell Samplerを追加する。(Add -> Listener -> BeanShell Sampler)

4. 次のように記述する※API実行結果

   ```java
   String allAPIResult = vars.get("allAPIResult");
   if(allAPIResult == null){
   	allAPIResult = "${result_user_id}"+","+"${result_time}" + "\n";
   }
   else{
   	allAPIResult += "${result_user_id}"+","+"${result_time}" + "\n";
   }
   vars.put("allAPIResult",allAPIResult);
   return vars.get("allAPIResult");
   ```

   

## 動作確認

* Jmeter実行

  ※以下のようにAPI実行結果がCSV形式で出力される。

  ![jm_result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/f9db5a66-9fd6-a292-62bf-10baeb940c64.png)
[JMeter]CSVファイル読み込みに応じたAPI繰り返し実行方法 メモ


* JMeterでCSVファイルで一覧化しているIDリストを読み込み、APIリクエストを繰り返し実行したかったので、その方法を個人用にメモしておく。



## テスト用API

* パスパラメータに指定したユーザーIDをそのまま取得結果として返却するAPI

* コード※Python/FastAPI製

  ```python
  import uvicorn
  from fastapi import FastAPI
  import uuid
  import datetime
  app = FastAPI()
  
  @app.get("/v1/users/{user_id}")
  def users(user_id):
      user = {
          "user_id":user_id,
          "time":str(datetime.datetime.now())
      }
      return user
  
  
  if __name__ == "__main__":
      uvicorn.run(app, port=8000, loop="asyncio")
  ```

  

## テストデータ

* user_list.csv

  ```csv
  user_id
  ABCDE12345
  FGHIJ67890
  XXXXX98765
  ```

  

## 設定手順

1. Thread Group に While Controllerを追加(Add -> Logic Controller -> While Controller)

   ![jm_while.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/07808b9a-c5ca-6fd3-f634-91205aed0e6a.png)


2. Wihle controller の Conditionに以下を設定

   ```
   ${__javascript("${user_id}" != "",)}
   ```

   ※変数user_idが空でない間繰り返す

3. Wihle controller 配下にCSV Data Set Configを追加(Add -> Config Element -> CSV Data Set Config)

4. CSV Data Set Configを下記のように設定

   ![jm_csv.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/52388ee1-4b2e-94bd-e5f8-bde3849d19d0.png)


   

5. Wihle controller 配下にHTTP Requestを追加(Add -> Sampler -> HTTP Request)

6. HTTP Requestを下記のように設定

   ![jm_http.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/7fb39c33-74d0-097b-4f18-1564d67a5d46.png)




## 動作確認

* テスト用API起動

  ```
  uvicorn main:app --reload --host 0.0.0.0 --port 8000
  ```

  

* Jmeter実行

  ※以下のようにuser_list.csvにあるユーザーID分APIが実行される。

  ![jm_result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/1aa3d524-0b4a-a0ab-7de3-563909080dbb.png)


  

## 参考情報

* [JMeter での While コントローラの使用](https://www.blazemeter.com/ja/blog/using-while-controller-jmeter)
ActiveAdminで検索条件で生SQLを使用する方法

# 概要
ActiveAdminの検索条件を追加するにあたり、ちょっと複雑な条件で検索をかけたかったです。いろいろ検討した結果、生のSQLを組む実装となったので、その方法を残しておきます。

## activeadminの実装
```app/admin/users.rb
ActiveAdmin.register Article do
  filter :search_name, as: :string
end
```

## Modelの実装
```app/models/User.rb

SQLはもっと複雑な感じで同じテーブルの外部キーがあったり、joinした先のさらに先のテーブルの項目見たり…

# 検索条件：キーワード
scope :search_keyword, lambda { |keyword|
  sql = "SELECT * FROM users LEFT JOIN users u1 ON users.partner1_id = u1.id LEFT JOIN users u2 ON users.partner2_id = u2.id"
  User.find_by_sql(sql)
end

def self.ransackable_scopes(_auth_object = nil)
  %i(search_keyword)
end
```

このまま実行するとエラーがおきます。
`undefined method where' for #<Array:0x0000ffff79a1ee50> Did you mean? when`

find_by_sqlの戻り値がArrayなので、ActiveRecord_Relation型に変換する必要があったようです。
```
User.search_keyword("abc").class
=>Array

# 期待するのはこっち
=> User::ActiveRecord_Relation
```

コードを以下のように書き換えると…できた！！
```
    as_array = User.find_by_sql(sql)
    as_relation = where(id: as_array.map(&:id))
```

# 参考
https://stackoverflow.com/questions/43326662/find-by-sql-to-something-that-returns-an-activerecords-relation
Pythonでブロックチェーンの理解に重要なハッシュ値を出してみる。

## ブロックチェーンの理解のために
ブロックチェーンを勉強している際にアドレスという各自が暗号通貨を管理するための口座番号が出てきました。
アドレスの作成のためにハッシュ関数とハッシュ値を使っていることを知りました。

ハッシュ値の主な特徴として3つ挙げられます。
1. 関数を通したあとのデータからは、もとのデータが何か分からない。
2. どんなデータをハッシュ化しても、同じ長さのハッシュ値になる。
3. 同じデータを何度ハッシュ化しても、常に同じハッシュ値になる。

ハッシュ値の上記の3つの特徴がブロックチェーンの改ざんが大変になる要因となっているようです。
詳しくはまた記事で紹介できたらと思います。
まずはPythonでハッシュ値の特徴が正しいのか確かめてみましょう。

## 実行環境
Google Colaboratoryを使用しました。

## ライブラリ
hashlibというPythonのライブラリを使います。

## コード
```python hash1.py
# -*- coding: utf-8 -*-
import hashlib 

message = "りんご"

#ハッシュ値を求めた結果
a = hashlib.sha256(message.encode("utf-8")).hexdigest()
print(a)
len(a)

#出力結果
4261abfc91324dc5319312592125610a16b0b0a996fcdfae1d24766b918afae9
64
```
りんごが4261abfc91324dc5319312592125610a16b0b0a996fcdfae1d24766b918afae9というハッシュ値に変わりました。
関数を通したあとのデータからは、もとのデータが何か分からない。
という特徴があることが分かります。

```python hash2.py
message2 ="りんごごりら"

#ハッシュ値を求めた結果
b = hashlib.sha256(message2.encode("utf-8")).hexdigest()
print(b)
len(b)
#出力結果
1cfe0892e70062529d32f8ee430871684235bcc0d29f0a0329ebc3d1e02d8aa5
64
```
ハッシュ値の長さは64文字です。
どんなデータをハッシュ化しても、同じ長さのハッシュ値になる。
という性質があることが分かりました。

```python hash3.py
message3 ="りんご"

#ハッシュ値を求めた結果
c = hashlib.sha256(message3.encode("utf-8")).hexdigest()
print(c)
len(c)
a == c 

#出力結果
4261abfc91324dc5319312592125610a16b0b0a996fcdfae1d24766b918afae9
64
True
```

りんごをハッシュ化した場合同じハッシュ値になりました。
同じデータを何度ハッシュ化しても、常に同じハッシュ値になる。
という性質を満たすことが分かりました。
Ruby オブジェクト指向

Ruby Ruby on Rails の世界ではオブジェクトで溢れています。
では、オブジェクトとは一体なんなのでしょうか？
辞書で調べるといろいろな意味が出てきますが、
簡単にいうと「もの」のことです。
私たちの身の回りにもいろいろなものが溢れています。
例えば、椅子　水筒　ベッドなどなど、
それぞれの「もの」が仕事をしてくれて私たちの生活を豊かにしてくれています。

Rubyの世界も同じで、たくさんの「オブジェクト」で溢れています。
「オブジェクトを自ら作り、使うことで、コンピューターにしてもらいたい仕事をしてもらう」これがRubyです。

それぞれのオブジェクトは自分のクラスを持っています。
例えば

昨日の記事の例で言うのならば
「佐藤先生　・・・　先生クラスに属している」
このようなイメージです。

では実際にコードを書いてクラスを調べていきましょう。
```
"あああ".class
=> String  /文字列
2.class
=> Integer　/整数
```

"あああ"はString(文字列)クラスに属しています。
２はInteger(整数)クラスに属しています。

ここで大切なのは、オブジェクトの仕事はそのオブジェクトがどんなクラスに属しているかで変わってきます。
length・・・文字列の文字数を尋ねることができる
```
"あああ".length
=> 3
1.length
=> エラー発生
```
1は整数オブジェクトのため、文字列オブジェクトに有効である,lengthは使えないのです。このようにオブジェクトはどのクラスに属するかでできる仕事が変わってきます。
しっかりと押さえていきましょう。
EclipseにSonarLintプラグインを追加する

EclipseにSonarLintプラグインを追加する手順です。


https://www.sonarlint.org/


## 通常

`https://eclipse-uc.sonarlint.org`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/d01579ba-a0bc-8923-f765-d1a5275c8b4a.png)

参考: [Eclipseにプラグインを追加してみよう (1/3)：CodeZine（コードジン）](https://codezine.jp/article/detail/13932)

## zipから静的追加

バイナリ配布: https://binaries.sonarsource.com/?prefix=SonarLint-for-Eclipse/releases/
URLからお好みのVersionのzipを取得する。

https://github.com/SonarSource/sonarlint-eclipse/wiki/Installation

ダウンロードしたフォルダから zip を指定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/d9c1546d-343f-fa3a-212e-137b56142d00.png)

チェックを入れる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/40a3bb4c-dd3d-4058-90ab-15eeffe59393.png)

Next。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/6653bf0d-1f45-f9fb-e834-6aa7e8499fcb.png)

インストール後、ダイアログに従いEclipseを再起動する。
Preference > SonarLint > Rules Configuration から設定が行えるようになります。
右クリック `SonarLint` からAnalyze。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/1b26caab-b765-38d7-74b7-261f7fdb6b90.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/6770b081-f4be-6141-c835-2c85bc8b5ac6.png)



## ほか参考記事
[java - Do not use System.out.println in server side code - Stack Overflow](https://stackoverflow.com/questions/8601831/do-not-use-system-out-println-in-server-side-code)
[java - Why is using System.out.println() so bad? - Software Engineering Stack Exchange](https://softwareengineering.stackexchange.com/questions/161194/why-is-using-system-out-println-so-bad)
[SonarQubeでソースコードの品質チェック - Qiita](https://qiita.com/teradonburi/items/776e4735395af872320a)
[sonarlintのEclipse設定 - Qiita](https://qiita.com/cheng_rancher/items/57335b59345e2cba8f33)

以上 Happy Analyzing！
Jetson Xavier NX上でOpenGLを呼び出せるROS環境をDockerで構築する



## はじめに
Jetson Xavier NXでROSを使うのに，dockerコンテナを立てて中で一般ユーザを設定し，virtualenv的な使い方をしたかったのですが良い設定が見つからなかったので作りました．
cudaにアクセスできてrvizをjetson単体で実行でき，簡単に起動できて，ROSをネイティブインストールしたのと同じような感覚で使えることを目指しました．

以前に[OpenGLを呼べるDocker環境までは作っていた](https://qiita.com/B-SKY-Lab/items/46b1e7d457d9684c60e0)のですが，肝心のROS部分を用意していなかったのでその続きです．


## 想定環境
- ハードウェア : Jetson Xavier NX
- ホスト側OS : Jetpack 4.5.0 --- Jetpack 4.6以降だとnvidia-runtimeを使ってコンテナを立てる際にPermmission Deniedが出る[[1]](https://forums.developer.nvidia.com/t/docker-error-response-from-daemon-failed-to-create-shim-oci-runtime-create-failed-container-linux-go-starting-container-process-caused-error/197663/3)そうなので，4.5系を使っています．
（後で確認したらSDに焼いたイメージは4.5.0でしたが勝手に4.5.2まで上がっていました，ぱっと見は動作に問題なさそうです．）
- コンテナ側OS : Jetpack 4.5.0
- ROS Distribution : Melodic
- CUDA使用 : あり
- GUI使用 : あり
- コンテナ内ユーザ種別 : 一般ユーザ
- コンテナ内ユーザ名 : docker
- コンテナ内ユーザPW : docker （ユーザ名/PWはDockerfileを編集して適宜変更してください）
- Dockerバージョン : 20.10.13 build 1224086
- docker-composeバージョン : 1.29.2 build unknown（aptで入れると1.19が入りますが，1.21以降でないとruntimeのタグが使えないためエラーで落ちるので注意．僕はpip3でインストールしました）


## 注意
- コンテナ内ユーザのID/PWをDockerfileに平文でベタ書きしているので，セキュリティには気をつけてください．
- コンテナ内にattachしている間は分かりやすいようにbashのユーザ名表示をデフォルトの緑から水色に変えていますが，かなり無理矢理に設定を変えています．気になる方はDockerfile末尾3行をコメントアウトしてからお使いください．


## 使い方
1. リポジトリをcloneする．
   
   ```
   git clone https://github.com/kim-xps12/jetson_docker_ros.git
   ```

2. 公式の手順でDockerをインストール[[2]](https://docs.docker.com/engine/install/ubuntu/) する．
3. pip3でdocker-composeをインストール[[3]](https://matsuand.github.io/docs.docker.jp.onthefly/compose/install/)する．
   ```
   sudo apt install python3-pip
   pip3 install --upgrade pip
   pip3 install docker-compose
   sudo reboot
   docker-compose --version
   ```


5. お使いのユーザをdockerグループに追加し，sudo無しでdockerコマンドが実行できるように[[4]](https://qiita.com/ITF_katoyu/items/1bdaaad9f64af86bbfb7)する．
6. launch_compose.shに実行権限を付与する．

   ```
   cd jetson_docker_ros
   chmod +x
   ```
   
7. launch_compose.shを実行する．エラーが起きなければattachまで自動で行われる．
   ```
   ./launch_compose.sh
   ```

9. コンテナ内で`glmark2`や`rviz`正常に動作すればOK！

   glmark2の場合
   ```
   glmark2
   ```
   
   rvizの場合
   
   tmuxでペインを2個以上作り，片方で`roscore`，もう片方で`rviz`

1. お好みでパッケージ名のtab補完[[5]](https://penguin-coffeebreak.com/archives/242)も使えるようにしておくと便利かもしれません．


## 参考
[1] [https://forums.developer.nvidia.com/t/docker-error-response-from-daemon-failed-to-create-shim-oci-runtime-create-failed-container-linux-go-starting-container-process-caused-error/197663/3](https://forums.developer.nvidia.com/t/docker-error-response-from-daemon-failed-to-create-shim-oci-runtime-create-failed-container-linux-go-starting-container-process-caused-error/197663/3)

[2] [https://docs.docker.com/engine/install/ubuntu/](https://docs.docker.com/engine/install/ubuntu/)

[3] [https://matsuand.github.io/docs.docker.jp.onthefly/compose/install/](https://matsuand.github.io/docs.docker.jp.onthefly/compose/install/)

[4] [https://qiita.com/ITF_katoyu/items/1bdaaad9f64af86bbfb7](https://qiita.com/ITF_katoyu/items/1bdaaad9f64af86bbfb7)

[5] [https://penguin-coffeebreak.com/archives/242](https://penguin-coffeebreak.com/archives/242)
vscodeでwsl2のubuntuにつなげてdockerとか使うための設定

# やりたいこと
1. windowsマシンにubuntu仮想環境を立てて、そこでプログラムを作成・実行などしたい
1. windows上のvscodeからubuntu上のプログラムなどを触れるようにしたい
1. ubuntu上でdockerを使いたい

# ubuntu仮想環境の構築
"wsl2"を入れればよい。
次のぺージを参考にした。
https://www.teamxeppet.com/wsl2_win10_install/

# windows上のvscodeからubuntuへの接続
"Remote WSL"というvscodeのパッケージを利用すればよい。
次のページを参考にした。
https://enia.hatenablog.com/entry/2021/09/13/090000

:::note warn
自分用覚書：基本的にはURLの通りだが、ubuntu上で```code .```を実行してもうまく進まない場合、windows上のvscodeのリモートエクスプローラーからUbuntuが既に選択できるようになっている可能性がある。その場合はそちらから接続するとうまくいった。
:::


# ubuntu上でのdocker環境構築
2つのインストールを進めることになる。
 - genieのインストール（```systemctl```コマンドがwslでうまく使えないための解決法）
 - dockerのインストール

:::note warn
自分用覚書：この章で```sudo apt-get update```などがうまくいかない場合、ファイヤーウォールが邪魔していることがある。Symantec Endpoint Protectionとかだとここで詰まる。ファイヤーウォールを一旦止めよう。
https://qiita.com/riraosan/items/3b036367d6d9f4e6b52a などを参考。
:::

## genieのインストール
wsl上で```systemctl```コマンドを使えるように"genie"をインストールする。
インストールは次のページの通り進めればOK。
https://snowsystem.net/other/windows/wsl2-ubuntu-systemctl/

途中のgenie起動時のエラー解消のための設定については次のURLも参考。
https://hiro20180901.hatenablog.com/entry/2022/03/10/070000

:::note warn
自分用覚書：途中のgenie起動時のエラー解消のための設定を終えた後はubuntuを```reboot```しよう（上で挙げたページなどに明記されてない気がする）。
:::


## dockerのインストール
基本的には次のページの通り進めればOK（step2まで）。
https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-20-04-ja


# おわりに
いつものことだが、環境構築のための作業が一番大変。。。
今回の作業も途中のエラーなどで止まって結局3時間ほど作業していた。。
2022/5/8主にITとかセキュリティの記事

フィッシング対策協議会をかたるフィッシング詐欺に注意──フィッシング対策協議会(5/6)
https://www.itmedia.co.jp/news/spv/2205/06/news118.html

巧妙化するランサムウエア攻撃　ＮＴＴサイバー専門家・松原実穂子(5/6)
https://www.sankei.com/article/20220506-3WOGIKV7YFLBDNPRJEU4B6OC6E/

2022年5月5日は世界パスワードの日、Bitwarden が日本人のパスワード管理の実態や意識を調査(5/6)
https://ascii.jp/elem/000/004/090/4090834/?rss

Heroku、全ユーザーのパスワードをリセット - OAuthトークンの漏洩受け(5/6)
https://news.mynavi.jp/techplus/article/20220506-2338798/

GitHub、ユーザーの2要素認証を義務化すると発表(5/6)
https://news.mynavi.jp/techplus/article/20220506-2338244/

ICANNが悪質なオンライン活動の監視・対抗ツールを開発(5/6)
https://kyodonewsprwire.jp/release/202205060842

米「ハイブリッド戦」対応を視察　岸防衛相、サイバー司令部訪問(5/6)
https://news.goo.ne.jp/topstories/politics/999/8985136e59076bfc97ac0f8159792d42.html?fr=RSS

アップル・Google・MSがFIDOの新パスワードレス認証導入。スマホでPCサインイン(5/6)
https://gunosy.com/articles/avVxJ

Apple・Google・Microsoftがパスワードなしの認証システム「パスキー」の利用拡大に合意(5/6)
https://news.livedoor.com/lite/article_detail/22117371/

ソラナペイがNFT特典の配布やトークン報酬に対応　店舗側のユースケース増やす(5/6)
https://coinpost.jp/?p=347490

5月Webサイト向けLinuxシェア、Debianが増加(5/6)
https://news.mynavi.jp/techplus/article/20220506-2338756/

IT3社、パスワードなし認証へ
指紋や顔、システム開発で連携(5/6)
https://nordot.app/895128865119404032?c=39546741839462401

NFT、投機から実用へ　メタバース視野にサービス多様化(5/6)
https://www.nikkei.com/article/DGXZQOUB030JF0T00C22A5000000/

韓国のアルトコイン増加に備えよ、次期大統領がＩＣＯ禁止撤回へ(5/6)
https://vc.morningstar.co.jp/010684.html

アサヒグループ、情報資産の「ハブ」基盤としてBoxを導入(5/6)
https://www.itmedia.co.jp/enterprise/spv/2204/28/news200.html#utm_campaign=itm_sidelink_dx

「電話番号100以上あります」と豪語するSMS認証代行業者も...盗品販売などに利用されるケースもある『犯罪インフラ？』の実態(5/6)
https://www.mbs.jp/news/feature/scoop/article/2022/05/088824.shtml

ICチップ奪い合いで納品遅れ…クレカに半導体不足の影(5/6)
https://news.yahoo.co.jp/articles/baf9687b21bce4480ca3d91b19ffdd125f26c9d3

イーサリアム財団が法定通貨を保有する理由【コラム】(5/6)
https://finance.yahoo.co.jp/news/detail/20220506-00167966-coindesk-bus_all

Apple、Google、MicrosoftがFIDO標準のサポート拡大にコミット、パスワードレス認証の普及を促進　（国際版の日本語訳）(5/6)
https://www.jiji.com/sp/article?k=000000021.000037279&g=prt

米、ロシア旗艦沈没に関与か＝ウクライナに位置情報提供(5/6)
https://news.nifty.com/article/world/worldall/12145-1616850/

5月Webサーバシェア、NginxとApacheが増加(5/6)
https://news.mynavi.jp/techplus/article/20220506-2338760/

Steamのキー詐欺業者にうんざりしたゲーム開発者、自ら詐欺師に聞き込み対策を編み出す。その手口とは(5/6)
https://automaton-media.com/articles/newsjp/20220506-201522/

KDDI、5G安定配信で先陣「ネットワークスライシング」(5/6)
https://www.nikkei.com/article/DGXZQOUC202HG0Q2A420C2000000/

イーロン・マスクがツイッタープロフィールをBAYCに：APEは1時間で20%急上昇(5/6)
https://nextmoney.jp/?p=50136

子どものスマホ、通信事業者はどこを選ぶべき？　キャリアかMVNOか、それとも？(5/6)
https://www.itmedia.co.jp/mobile/spv/2205/06/news045.html

米ＩＴ大手３社がパスワードなし認証で連携(5/6)
https://kumanichi.com/articles/647374

「Thunderbird 91.9.0」が公開 ～互換性維持のためにOpenPGP署名でSHA-1を一部許可(5/6)
https://forest.watch.impress.co.jp/docs/news/1407209.html

パスワードなし認証で連携　アップルなど米ＩＴ大手３社(5/6)
https://www.sankeibiz.jp/article/20220506-SRFCV5Z2GZMSTG457NFEUBL7KY/

シスコの複数製品に緊急の脆弱性、ただちにアップデートを(5/6)
https://news.mynavi.jp/techplus/article/20220506-2338810/

F5 BIG-IPに緊急の脆弱性、ただちにアップデートを(5/6)
https://news.mynavi.jp/techplus/article/20220506-2338265/
Diskisym - 逆Fanfansym

# はじめに
KiCad用のSymbol Generator - [Fanfansym.py](https://qiita.com/maclineto/items/31ceef855b72159dc098)の逆変換プログラムです。
KiCadからSymbolをExport。これはLISPで読めるS式になってます。
これをDiskisymに通すとFanfansymで読み取り可能なtextを出力します。
似たようなLSIがすでにある時、いったんDisfisymしてテキストエディタで修正して、Fanfansymで変換すれば楽にSymbolを作れます。
例えばファミリーの64QFNがあるのに48QFPは未登録だった場合が該当します。

# 環境
KiCad 6
Python 3

# 使い方
- diskisym.pyをDownLoadしてinput, outputを書き換えます。
- KiCadでSymbolをExportします。
- 出力されたファイルをdiskisym.pyで変換します。
- 適当なText Editorで編集します。
- fanfansym.pyで変換します。
- KiCadでimportします。

# プログラム
```python: diskisym.py
# diskisym.py: Inverse Fanfansym.py for KiCad6
# Written in Python 3
# Copyright (c) 2022 Fanfan
# Lisence: MIT
input = "fanfan.kicad_sym"
output = "fanfan.pintext"
import sexpdata
LL = []

def parse(s):
    if type(s) == list and len(s) > 0:
        a = sexpdata.car(s)
        d = sexpdata.cdr(s)
        if type(a) == list:
            parse(a)
        else:
            LL.append(a)
        if type(d) == list: 
            parse(d)
        else:
            LL.append(d)
        return

dictword = {
    'pin': 'p',
    'number': 'n',
    'name': 'm',
}

n = ''
m = ''
p = ''

f = open(input,"r")
fo = open(output,"w")
lines = f.read()
s = sexpdata.loads(lines)
parse(s)
fo.write ('#%s' % (LL[6]))
for i in range(2,len(LL)-1):
    if type(LL[i]) == sexpdata.Symbol:
        v = LL[i].value()
        if v in dictword:
            dic = dictword[v]
            if dic == 'n':
                n = LL[i+1]
                fo.write('\n%s\n@%s %s' % (m,n,k))
            elif dic == 'p':
                k = (LL[i+1]).value()
            elif dic == 'm':
                m = LL[i+1]     
```
監視カメラ作ってみた

我が家のちびっ子怪獣を見守るべく監視カメラを作ってみた。
# 使用するアイテム
- ESP32-cam

# 開発環境
- win10
- ArduinoIDE
    - vscodeでも可
# 調達
　ESP32-camはAmazonで購入。
# ArduinoIDEで実装
### 実装準備
　Arduinoの設定を以下に変更する。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172184/deb10e24-af4c-d3fc-16a2-a1fa55d6a6e8.png)
#### Upload Speedについて
他の記事では921600とあったが、上手く行かなかったため115200に変更。
（wifiが安定していないって事なのかな。。。）
スケッチのサンプルCameraWebServerを開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172184/32814507-21a2-901f-3323-fbd742f202c9.png)
### CameraWevServerを編集
- 10行目をコメントアウト 
```Arduino:CameraWevServer.ino(10行目)
//#define CAMERA_MODEL_WROVER_KIT
```
- 14行目のコメントアウトを外す
```Arduino:CameraWevServer.ino(14行目)
#define CAMERA_MODEL_AI_THINKER
```
- 18,19行目でネットワークの設定。
```Arduino:CameraWevServer.ino(18行目)
const char* ssid = "wifinoSSID";
const char* password = "password";
```
編集はこれだけ。
# 書き込んでシリアルモニタを確認
- 書き込みが終了したら一度、ESP-camのRSTを押す。（押しにくいのでしっかりと押す。）
- シリアルモニタを確認するとipアドレスが表示される(192.168.XX.XXみたいな数字。)
# カメラの接続を確認
- chromeなどのブラウザにipアドレスを打ち込み接続を確認。

# 参考情報
- https://qiita.com/Nabeshin/items/b195cad1afe99ce29f1e
- https://exp-sp.denpa.soumu.go.jp/public/help/startNotice_detail.html
Rust の serde で複数形式の Serialize/Deserialize を実装するときのコピペ用実装例 + map/map_or の参考おまけ付き

```rust
// note: derive(Serialize, Deserialize) とかするための `use` は T (Rustで扱う型) にだけ付ければよいです。
// これを使いたい場合は `cargo add serde -F derive` (`cargo install cargo-edit`してある環境)
// Cargo.toml の `[dependencies]` に `serde = { version = "*", features = [ "derive" ] }` しておきます。
#[derive(Serialize, Deserialize)]
struct Neko(String); // またはお好みで複雑にして読み替えて下さい。

/// (A): file や http など 👉  MyInterimStorage  👉 T (Rustで扱う型)
/// (B): file や http など 👈 (MyInterimStorage) 👈 T (Rustで扱う型)
/// のように変換前の中間貯蔵庫を使いたい場合の実装です。このまま使わない場合も、
/// 必要に応じてシリアライズ部分だけ、デシリアライズ部分だけを fn として使うなど
/// お好みでどうぞ。※この実装例の(B)ルートでは content_type の参照をしているだけです。
#[derive(Debug, Clone)] // ← お好みで
pub struct MyInterimStorage
{
 pub content_type: String, // ← Content-Type とか mime や mime-guess で形式判定する用
 pub serialized_data: Vec<u8> // ← file や http などで受け取ったバイナリーを入れる
}

impl<'de> MyInterimStorage // ← こういう中間データ貯蔵庫を使う場合はここで <'de> ライフタイムを入れておく
{
 /// 形式に基づいてデシリアライズします。こっちに <'de> が必要
 pub fn deserialize<T>(&'de self) -> Option<T>
 where
  T: Deserialize<'de> + std::fmt::Debug
 {
  // content_type::APPLICATION_MSGPACK などは const な &str を定義しているだけです。
  // mod content_type { const APPLICATION_MSGPACK: &str = "application/msgpack" }
  // のように。必要に応じて定義するといいです。
  // (mime crateは非constなので必要な分だけさっと定義書けばいいと思います。)
  match self.content_type.as_str()
  {
   // たいていの serde 対応実装はこのパターンで binary を読めます。
   content_type::APPLICATION_MSGPACK => rmp_serde ::from_slice(self.serialized_data.as_slice()).ok(),
   content_type::APPLICATION_TOML    => toml      ::from_slice(self.serialized_data.as_slice()).ok(),
   content_type::APPLICATION_JSON    => serde_json::from_slice(self.serialized_data.as_slice()).ok(),
   // その他、YAMLとかRONとか必要に応じてどうぞ: https://serde.rs/
   _ => None
  }
 }

 /// 形式に基づいてシリアライズします。こちらはライフタイム管理不要です。
 pub fn serialize<T>(&self, from: T) -> Option<Vec<u8>>
 where
  T: Serialize + std::fmt::Debug
 {
  match self.content_type.as_str()
  {
   content_type::APPLICATION_MSGPACK => rmp_serde ::to_vec(&from).ok(),
   content_type::APPLICATION_TOML    => toml      ::to_vec(&from).ok(),
   content_type::APPLICATION_JSON    => serde_json::to_vec(&from).ok(),
   _ => None
  }
 }

 // おまけ実装例 (1): 中身を形式に基づいてデシリアライズ👉Fで変換👉元と同じ形式でシリアライズの組み合わせの実装例 
 pub fn map<T, F>(&'de self, fun: F) -> Option<Vec<u8>>
 where
  T: Deserialize<'de> + Serialize + std::fmt::Debug,
  F: Fn(T) -> Option<T>
 {
  let src = self.deserialize::<T>()?;
  let dst = fun(src);
  let r = self.serialize(dst);
  r
 }

 // おまけ実装例 (2): (1) の途中でデシリアライズに失敗したときにデフォルト値に挿げ替えてシリアライズする版
 pub fn map_or<T, F>(&'de self, fun: F, default: T) -> Option<Vec<u8>>
 where
  T: Deserialize<'de> + Serialize + std::fmt::Debug,
  F: Fn(T) -> Option<T>
 {
  let r = self.deserialize::<T>().and_then(fun).unwrap_or(default);
  self.serialize(r)
 }
}
```

> 久しぶりにQiitaへ。フォロー頂いている方への生存 ping を兼ねて🤣
【SwiftUI】リワード広告の表示

第0部: [スタートガイド](https://qiita.com/SNQ-2001/items/44f3446ce0966c78641b)

第1部: [リワード広告](https://qiita.com/SNQ-2001/items/253173abefc6f90f86ea) ← イマココ
第2部: [インタースティシャル広告](https://qiita.com/SNQ-2001/items/5590a55324c39582a9ef)
第3部: [ネイティブ広告](https://qiita.com/SNQ-2001/items/7151fdcb8e9f8c2c42c2)
第4部: [バナー広告](https://qiita.com/SNQ-2001/items/9bf389475cb5995469a0)
第5部: [アプリ起動広告](https://qiita.com/SNQ-2001/items/75ce24982bf418c52349)

# はじめに
多くのドキュメントはUIKitで書かれていてSwiftUIで書かれていることはほとんどありません。
ドキュメントを見て毎回書き直すのは苦痛です。楽しくありません。
今回のお題である[AdMobのリワード広告ドキュメント](https://developers.google.com/admob/ios/rewarded?hl=ja)もUIKitで書かれています。
今後、同じ事をするであろう方のために書き直したものを公開しておきます。

# 実装準備
実装の前に[スタートガイド](https://developers.google.com/admob/ios/quick-start?hl=ja)に記載してある事を行います

①: Mobile Ads SDK のインポート
②: Info.plist の更新
③: Mobile Ads SDK の初期化

[こちら](https://qiita.com/SNQ-2001/items/44f3446ce0966c78641b)で詳しく解説してあります。
これが終われば準備は完了です。

# 実装
```Reward.swift
import GoogleMobileAds

class Reward: NSObject, GADFullScreenContentDelegate, ObservableObject {
    @Published var rewardLoaded: Bool = false
    var rewardedAd: GADRewardedAd?

    override init() {
        super.init()
    }

    // リワード広告の読み込み
    func LoadReward() {
        GADRewardedAd.load(withAdUnitID: "ca-app-pub-3940256099942544/1712485313", request: GADRequest()) { (ad, error) in
            if let _ = error {
                print("😭: 読み込みに失敗しました")
                self.rewardLoaded = false
                return
            }
            print("😍: 読み込みに成功しました")
            self.rewardLoaded = true
            self.rewardedAd = ad
            self.rewardedAd?.fullScreenContentDelegate = self
        }
    }

    // リワード広告の表示
    func ShowReward() {
        let root = UIApplication.shared.windows.first?.rootViewController
        if let ad = rewardedAd {
            ad.present(fromRootViewController: root!, userDidEarnRewardHandler: {
                print("😍: 報酬を獲得しました")
                self.rewardLoaded = false
            })
        } else {
            print("😭: 広告の準備ができていませんでした")
            self.rewardLoaded = false
            self.LoadReward()
        }
    }
}
```

```ContentView.swift
import SwiftUI

struct ContentView: View {
    @ObservedObject var reward = Reward()
    var body: some View {
        Button(action: {
            reward.ShowReward()
        }) {
            Text(reward.rewardLoaded ? "リワード広告表示" : "読み込み中...")
        }
        .onAppear() {
            reward.LoadReward()
        }
        .disabled(!reward.rewardLoaded)
    }
}
```
![Videotogif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/58263995-950e-c4f3-f2d0-60d8716d2d99.gif)

# おわり
今回作成したプロジェクトを置いとくので参考にしてください。

https://github.com/SNQ-2001/AdMob-Reward-Demo
【Docker】Djangoの環境構築

## Djangoの環境構築


### Dockerfile
```Dockerfile
FROM python:3
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /myapp
COPY requirements.txt /myapp/
RUN pip install -r requirements.txt
COPY . /myapp/
```

### docker-compose.yml
```docker-compose.yml
version: "3.9"
   
services:
  db:
    image: postgres
    volumes:
      - db:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/myapp
    ports:
      - "8000:8000"
    environment:
      - POSTGRES_NAME=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    depends_on:
      - db
volumes:
  db:
```
ABC081B - Shift onlyをビット演算で解いてみた

【趣旨】
プログラミング（競技プログラミング）を初めて2日目。掲題の問題を解くにあたり、ビット演算による解法に挑戦しました。問題名がShift Onlyであることから、Remainder（剰余）やDivision（割算）は出題者の狙いなのか？という疑問が湧いたことが理由です。AtCorderのC++初心者ガイドを眺めながら解いたので時間がかかりました。

【コード（開発環境：VS2022）】
```cpp
#include <iostream>
#include <vector>
#include <bitset>

using namespace std;

int main()
{
	//回数を入力
	int N = 0;
	cin >> N;

	//配列にN個の変数を格納したのちビット演算（OR）
	vector<int> vec(N);
	bitset<32> bitnum;
	for (int i = 0; i < N; i++) {
		cin >> vec.at(i);
		bitnum |= vec.at(i);
	}

	//一番右のビットが1になるまでループ
	int ans = 0;
	while(true) {
		if (bitnum[0] == 0) {
			bitnum = bitnum >> 1;
			ans++;
		}else if (bitnum[0] == 1) {
			break;
		}
	}
	cout << ans << endl;

	return 0;
}
```
Symbolの新SDKからSSS(Safely Sign Symbol) Extensionを利用してみる


SSSは現在old-sdk対応ですが、新sdkでも使用することができます。
今回は新sdkからSSSを利用する方法について説明します。

######  symbol-sdk(v3)の埋め込み 

ブラウザコンソールを使用して表示中ページにsymbol-sdk-v3を埋め込みます。
```js
(script = document.createElement('script')).src = 'https://xembook.github.io/symbol-browserify/symbol-sdk-3.0.0.js';
document.getElementsByTagName('head')[0].appendChild(script);
```

###### 環境定義
トランザクション送信に必要な環境の定義、情報を取得します。

```js
node = window.origin;

sdk = require("/node_modules/symbol-sdk");
Buffer = require("/node_modules/buffer").Buffer;

res = await fetch(node + "/network/properties");
json = await res.json();
generationHash = json.network.generationHashSeed;
networkId = json.network.identifier;
currencyMosaicId =  json.chain.currencyMosaicId.split("'").join('').slice(2);
epochAdjustment = Number(json.network.epochAdjustment.replace("s",""));

function createDeadline(secs = 7200) {
	const value = ((Math.trunc(Date.now() / 1000) + secs) - epochAdjustment) * 1000
	return BigInt(value);
}

function setMaxFee(tx,multiplier){
    return new sdk.symbol.Amount(BigInt(tx.size * multiplier))
}

facade = new sdk.facade.SymbolFacade(networkId);
privateKey = new sdk.CryptoTypes.PrivateKey("896E43895B908AF5847ECCB2645543751D94BD87E71058B003417FED5123****")
keypair = new sdk.facade.SymbolFacade.KeyPair(privateKey);

```
###### トランザクション作成

トランザクションを作成してペイロードを出力します。

```js
tx = facade.transactionFactory.create({
	type: 'transfer_transaction',
	signerPublicKey: keypair.publicKey.toString(),
	deadline:createDeadline(),
	recipientAddress: 'TD4WXUXYAPPB5Y42VT6FHISG6T32I2IBUXIKKPQ',
	message:[0,...(new TextEncoder('utf-8')).encode('GoodLuck!')],
	mosaics: [
		{ mosaicId: 0x3A8416DB2D53B6C8n, amount: 1000000n }
	]
})
tx.fee = setMaxFee(tx,100);
payload = Buffer.from(tx.serialize()).toString("hex");
```
###### SSSへのトランザクションセットと署名要求
ペイロードを利用してトランザクションをセットします。
```js
window.SSS.setTransactionByPayload(payload);
signedTx = await window.SSS.requestSign();
```

###### ネットワークへの配置(PUT)

SSSから受け取ったオブジェクトからpayloadを取り出し、
fetchを利用して、ブロックチェーンへトランザクションを配置します。

```js
signedPayload = signedTx.payload;
jsonPayload = `{"payload": "${signedPayload}"}`
response = await fetch(`${node}/transactions`, {
	method: 'put',
	body: jsonPayload  ,
	headers: {'Content-Type': 'application/json'}
});
await response.text();
```

###### 確認

ネットワークに配置したトランザクションを確認してみましょう。

```js
//承認状態の確認
res = await fetch(`${node}/transactionStatus/${signedTx.hash}`);
console.log(await res.json());

//承認済みトランザクションの確認
res = await fetch(`${node}/transactions/confirmed/${signedTx.hash}`);
console.log(await res.json());

//エクスプローラーで確認
console.log("https://testnet.symbol.fyi/transactions/" + signedTx.hash);
```
【Laravel入門】Validator::Extend

<h2> 導入 </h2>
1周目のLaravel入門を実践中、引っかかった点があったので共有がてらあげます。

<h2> 経緯 </h2>
p157の「Validate::extendを利用する」を実践中、以下コードの「extend」の部分にエラーが出ていたため、「use」に問題があるのではないかとは思っていた。

```php
    public function boot()
    {

        Validator::extend('hello', function($attribute, $value, $parameters, $validator){
            return $value % 2 == 0;
        });
    }
```


しかしまだ始めてから少ししか経っていないのにValidatorのuseに種類があるとは思わなかった。

なので別サイト（結構前にやったのでどのサイトか忘れました）から持ってきた、こちらのuseを使っていた。
```php
use Illuminate\Validation\Validator;
```


しかし<a href = "https://readouble.com/laravel/5.5/ja/validation.html">このサイト</a>を見て、

```php
use Illuminate\Support\Facades\Validator;
```
が正しいということがわかった。


<h2> 最後に </h2>
この2つの違いがわかっていないのでちゃんと調べます。<br>
そして引き続き勉強頑張ります。
AWS SAPに合格したので効率的な勉強方法（だと思う）を纏めてみました

# はじめに
先日、AWS認定資格の最難関と言われるAWS SAP（AWS Certified Solutions Architect - Professional）に一発合格したので、個人的に効率的だと思う勉強方法を纏めてみます。
これからSAPの勉強をしようと思っている方に向けて、この記事が少しでも参考になれば幸いです。

# 勉強方法
本記事は前提として、SAAを取得している方向けとなります。取得していない方は、まずは必ずSAAから取得するようにしましょう。

### ①AWS SAPの模擬試験を受験する
最初にAWS SAPの模擬試験問題を受験しましょう。
資格試験の鉄則は、初めに模擬試験や過去問を解いて**試験のレベル感を知ること**です。問題をいきなり解くことは中々ハードルが高いですが、こちらの模擬試験は問題数が20問程度と少なめなので、そこまで負担なく取り組めるかと思います。
以下の記事を参考にして、登録・受験を行いましょう。

https://dev.classmethod.jp/articles/new-aws-official-practice-questions/


### ②参考書の巻末問題集を解く
現在出版されているSAPの日本語参考書は以下の2つです。これのどちらか（出来れば両方）を購入しましょう。

https://www.amazon.co.jp/dp/B08F9CQ6LT/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%EF%BC%86%E5%95%8F%E9%A1%8C%E9%9B%86-AWS%E8%AA%8D%E5%AE%9A%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%88-%E3%83%97%E3%83%AD%E3%83%95%E3%82%A7%E3%83%83%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%AB-%E5%B1%B1%E4%B8%8B-%E5%85%89%E6%B4%8B-ebook/dp/B09DKZWX7N/ref=bmx_dp_64qfuyyo_sccl_1_5/356-0564800-5008510?pd_rd_w=A6zrw&pf_rd_p=8a57ca45-fb21-4c3a-8a8a-1f3041206442&pf_rd_r=13VZD0RFY5P15P7VWPJA&pd_rd_r=a54bfd50-96cd-4fbb-8803-8cd4a90a6536&pd_rd_wg=3Ksgm&pd_rd_i=B09DKZWX7N&psc=1

参考書なので各AWSサービスを詳細に説明したテキストが載っているのですが、だいぶ分厚いテキストとなっていますので、**最初から全部読み進めるのはお勧めしません。**（とても時間がかかり、途中で挫折する可能性大だからです）
なので**巻末の問題集から解き進めましょう**。どちらの参考書の問題集も、かなり実戦に近い形式となっています。解き終わった後はじっくりと時間をかけて解説を読みながら解き直しを行いましょう。（最初は解答を読みながら解くでも問題ないです）
その上で解説を読んでも理解が不十分な箇所が出てきたら、**そのサービスについて書かれている章に絞ってテキストを読めば**と良いと思います。

こちらの問題集を3周ほど解くことで、試験に必要な知識の殆どが身につくかと思います。

### ③コンソールを動かして設定方法を確認する
問題集のみだと、解答を読んで無理やり納得してしまいがちなので、学んだサービスの設定方法について実際にコンソールを動かして操作してみましょう。
とはいえ、一つ一つ構築しようとすると時間がかかったり、変なところで料金が発生したりする可能性があるので、**実際に構築はせずともコンソールを操作してみて**、「ここを操作すれば解答に書いてある設定が出来るんだな～」と確認することが大事かと思います。

（例）「S3のオブジェクトロックってどうやって設定するんだろう？」→ S3のコンソールにアクセスしてみる → バケットを作成ボタン押す → 詳細設定の項目にオブジェクトロックの有効化/無効化のラジオボタンがある → 「なるほど、ここを有効化にすればオブジェクトロックが有効になるんだな～」

☝みたいな感じです。
設定の途中でキャンセルボタンを押せば、料金は発生しません。私はこれで**実際に構築するときのイメージを掴むこと**が出来るようになりました。

### ④ハンズオンやチュートリアルを活用する
こちらは必須ではないのですが、問題集ばかり解いていると途中で飽きる時期が来ます。（私自身そうでした 笑）
やはりAWSは実際に動かしてみてナンボなので、息抜きの意味合いも兼ねて公式のハンズオンやチュートリアルを活用してサービスを動かしてみましょう。（問題集を解いたときに、自分の理解が甘いサービスのハンズオンをやってみると良いと思います）

https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-hands-on/

https://aws.amazon.com/jp/getting-started/hands-on/?awsf.getting-started-category=*all&awsf.getting-started-level=*all&awsf.getting-started-content-type=*all&awsm.page-getting-started-all=1

# さいごに
今回はAWS SAPの勉強方法について纏めてみました。
AWSの問題集では他に[koiwa club](https://aws.koiwaclub.com/)があるのですが、模擬試験や参考書の巻末問題集をじっくり時間をかけて深く理解できるレベルまで引き上げることが出来れば、十分に合格できるように思います。
とはいえやはり試験範囲が広く内容も難しいので、短期集中ではなく**毎日コツコツと勉強して頭に馴染ませることが何よりも大事**かと思います。
SAPに合格することでSAAよりも遥かに高度な知識が身に付きますので、興味がある方は是非ともチャレンジしてみてはいかがでしょうか！
Tailwind/typographyを導入したらエラーで詰まった

# はじめに
現在、Next.jsとmicro CMSでブログを作成しています。
その中でリッチテキストエディタの文字部分をいい感じにスタイリングしてくれるTailwind/typographyを導入したらエラーで詰まり、エラー分をググって解決できたのですがgithuｂなどの英語情報しかなかったので今回記事に書き留めようと思った次第です。

## Tailwind/typographyを導入する
1. Tailwind CSS を導入する（割愛）
2. Tailwind/typographyを導入する

```
npm install -D @tailwindcss/typography
               or
yarn add -D @tailwindcss/typography
```
これだけで良いと公式ドキュメントにも書いてますが表題のとおりエラーが発生。。。
【Tailwind CSS公式ドキュメント】

https://tailwindcss.com/docs/typography-plugin

## エラー文
```
TypeError: Cannot read properties of undefined (reading '700')
```

上記のようなエラー文が発生。

## 解決方法
以下githubのリンクにて解決。

https://github.com/tailwindlabs/tailwindcss/issues/6398


自分で作成したNext.jsのテンプレートリポジトリの中のTailwind　CSSのバージョンが古く、typographyと互換性がなかった為に発生したようです。(旧バージョンは^2.2.4)
Tailwind　CSSを最新版にすれば解決しました。

## 最後に
今回はパッケージのバージョン管理はしっかり行うことの大切さを学び、日本語での記事などが見つからなかったことから解決に少し時間がかかってしまったので記事を書くことにしました。
同じエラーで詰まった方の助けになればと思います。
create-react-appで作成したReactのバージョンを18から17に変更する

## 内容

create-react-appで作成されたReactアプリケーションのバージョンが18となるので、17.0.2に変更する方法。

```bash
# create-react-appを使用してアプリケーションを作成
npx create-react-app my-app
```

## 目次
- [手順](#手順)

## 手順
### package.json の下記を18から17に修正

```json
"react": "^17.0.2",
"react-dom": "^17.0.2",
```

### npm installを実行

```bash
npm install
```

### index.js を下記ファイルに修正

```js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

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

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
```

以上
【jq コマンド】JSON 要素を「キー名の長さ」でソートする

> `jq` コマンド[^jq]でソートをする際に、要素の**キー名の「長さ」でソートしたい**。

[^jq]: [jq](https://stedolan.github.io/jq/) は JSON データ（要素やオブジェクト）を操作するためのコマンド・ツールです。[Stephen Dolan](https://github.com/stedolan) 氏によって C 言語で書かれた軽量プログラムです。

```json:ソート前
{
  "": "0x0",
  "2DEkCJF8vWIheS0f": "0x5b7b3440",
  "A3rjGqZK": "0x2cc8df37",
  "CRSQQITHOHfhCFwRXEit9M8j7UhKobqq": "0x81250d75",
  "GNRay1oRg4waBzYiLLrYKkZ6CU6flZwinxiSdBtx7a38g2AET2VnktciCcmlcsDG": "0x856f5418",
  "Hello world!": "0x7b98e751",
  "This is a string": "0x3a779320",
  "hush now don't you cry": "0x4021e5a5"
}
```

上記 ↑ を以下 ↓ のようにソートしたい。

```json:ソート後
{
  "GNRay1oRg4waBzYiLLrYKkZ6CU6flZwinxiSdBtx7a38g2AET2VnktciCcmlcsDG": "0x856f5418",
  "CRSQQITHOHfhCFwRXEit9M8j7UhKobqq": "0x81250d75",
  "hush now don't you cry": "0x4021e5a5",
  "This is a string": "0x3a779320",
  "2DEkCJF8vWIheS0f": "0x5b7b3440",
  "Hello world!": "0x7b98e751",
  "A3rjGqZK": "0x2cc8df37",
  "": "0x0"
}
```

「[jq sort by key "length"](https://www.google.com/search?q=jq+sort+by+key+%22length%22)」や「[jq キーの長さ ソート](https://www.google.com/search?q=jq+%E3%82%AD%E3%83%BC%E3%81%AE%E9%95%B7%E3%81%95+%E3%82%BD%E3%83%BC%E3%83%88)」でググっても、ドンピシャの記事がなかったので自分のググラビリティとして。

- 関連記事: [JSON 要素を「キー名」でソートする](https://qiita.com/KEINOS/items/58025b7816aa5456481e) @ Qiita

## TL; DR <sub><sup><sub><sup>（今北産業）</sup></sub></sup></sub>

1. `to_entries` で、各要素のキーと値を `{"key": <キー名>, "value": <値>}` に変換する。
1. `sort_by(.key|length)` で、キー名の長さにソートする。
1. `from_entries` で、`{"key": <キー名>, "value": <値>}` を元の型（`<キー名>:<値>`）に戻す。

## TS; DR <sub><sup><sub><sup>（マスター動くものをくれ）</sup></sub></sup></sub>

```bash:昇順
cat mydata.json | jq 'to_entries|sort_by(.key|length)|from_entries'
```

```bash:降順
cat mydata.json | jq 'to_entries|sort_by(.key|length)|reverse|from_entries'
```

- [オンラインで動作をみる](https://paiza.io/projects/qQs3JDQGapLFIUbarAP6SQ) @ paiza.IO

## 参考文献

- [to_entries,from_entries](https://stedolan.github.io/jq/manual/#to_entries,from_entries,with_entries) @ `jq` 公式マニュアル
- [length](https://stedolan.github.io/jq/manual/#length) @ `jq` 公式マニュアル
- [コメント](https://stackoverflow.com/a/51914402/18152508) | Use jq in Bash to sort object properties by descending length of their value @ StackOverflow
rails ネスト機能について

今回はrailsのルーテイングの時に役に立つnestについてまとめて見ました。
ネストを使うとルーテイングの見やすさが一気に上がるので、ぜひこの記事を参考にして見てください。

早速ですが、ネストを理解する前に、掲示板とコメントの関係を思い出してください。

...

掲示板とコメントの関係ですが、これは、必ずと言っていいほど、掲示板の中にコメントが書かれていますよね。
このQiitaも全く同じ機能で、掲示板を僕が一つ記事を書き、そこに読者様からのコメントがありますよね。
こういう風に一対多（掲示板が１、コメントが多）の関係になっているものはネストでルーテイングを表現してあげましょう。
そちらの方が視覚的にも見やすいです。

具体的には以下をご覧ください。
Boardモデル
```
class Board < ApplicationRecord
  has_many :comments
end
```

Commentモデル
```
 class Comment < ApplicationRecord
  belongs_to :board
end
```

ネストの表現方法は下のようになります。
親がboards 子がcommentsのように書きましょう。
親boardsの中に子供commentsがいる、そんなイメージです。
```
resources :boards do
  resources :comments
end
```

rails routesでルーテイングを確認すると
```
board_comments POST   /boards/:board_id/comments(.:format)                                                     
comments#create
```
このような形でboardの中にcommentが存在していますね。
だいぶコードが見やすくなりました。
rustfmtの設定ファイルってどう書くの？？？

## 主題
rustfmtの設定ファイルの記述方法がパッとみてよくわからなかったので備忘録
基本はrustfmtのREADMEに書いてある。

## 設定ファイルの形式
rustfmt.tomlまたは.rustfmt.tomlを作ればOK。
あとはtomlの形式に沿って書く。

<details>
<summary>tomlって？</summary>
ざっくり言うと、設定を簡単に書く用の形式。

下記みたいな感じで単純に左辺と右辺をイコールで結ぶだけ
```toml
max_width = 100
```

参考: https://toml.io/ja/v0.4.0
</details>


## 簡単に設定を記載する方法
[README](https://github.com/rust-lang/rustfmt#tips)に書いてあるが、下記コマンドを叩くとデフォルト設定を勝手に吐き出してくれるので、それを書き換えるだけで良い

```zsh
rustfmt --print-config default rustfmt.toml 
```
### 各設定項目の詳細
下記を参照
https://rust-lang.github.io/rustfmt/

### no stableな設定
`stable: No`である設定項目に関してはrustupをstableからnightlyへ変更する必要がある。
※rustupというかtoolchain?のversionを切り替えるイメージだろうか。
正直ここはちょっとよくわかってないので教えて欲しいです。

```zsh
rustup toolchain install nightly
```
その上で、+nightlyをつけてフォーマットをかけると下記の様になる。

```zsh
cargo +nightly fmt

# report_todo = "Always"に変更した場合のメッセージ
# 余談だけど、この機能結構便利

warning: found TODO
  --> /Users/ryoga/dev/git/rust_traning/src/main.rs:17
   |
17 | // TODO
   |

warning: rustfmt has failed to format. See previous 1 errors.
```
## 参考
https://github.com/rust-lang/rustfmt
Lambda 関数 URL

# 概要

従来は、HTTP(s)経由で、API Gateway --→ Lambda とアクセスしていたが、関数 URL がサポートされた事で、API Gateway なしででアクセスできるようになった。

パブリックに公開するAPIや、簡易な認証実装でも差し支えの無いAPIの場合は、AWSLambdaで実装する場合には、関数 URL の利用を検討するとよい。

# 認証タイプ

「認証タイプ」には**AWS_IAM**と**NONE**があります。

- **AWS_IAM** : 認証された IAM ユーザーとロールのみがアクセス可能。
- **NONE** : パブリックにアクセス可能。

# CORS

CORS を使用して、任意のドメインから関数 URL へのアクセスを許可することも可能。

# 参考URL

https://aws.amazon.com/jp/blogs/aws/announcing-aws-lambda-function-urls-built-in-https-endpoints-for-single-function-microservices/

# やってみた

## 認証タイプ:NONE

![url001.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/b817f3ae-ebc3-8d36-4036-6df62e9d2a06.png)

認証タイプ **NONE** を選択すると、Lambda によって以下のリソースベースのポリシーが自動的に作成され、関数にアタッチされます。

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "StatementId": "FunctionURLAllowPublicAccess",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "lambda:InvokeFunctionUrl",
      "Resource": "arn:aws:lambda:ap-northeast-1:123456789012:function:my-webhook-handler",
      "Condition": {
        "StringEquals": {
          "lambda:FunctionUrlAuthType": "NONE"
        }
      }
    }
  ]
}
```

Hello, World! の適当な Lambda 関数。

```js:
exports.handler = async (event) => {
    return 'Hello, World!!';
};
```

関数 URL にアクセスしてみると、パブリックにアクセスされます。

```
$ curl 関数URL
Hello, World!!
```

## 認証タイプ:AWS_IAM

![url002.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/8613490c-3e39-c3ab-a3ed-b78eaa626037.png)

AWS_IAM でアクセスする場合は、AWS Signature Version 4 (SigV4) を使用して、HTTPリクエストに対して署名する必要があります。
下記のドキュメントに従って、**awscurl**, **Postman**, **AWS SigV4 Proxy** などを利用後、アクセスを試みてみます。

https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html#urls-invocation-basics

```
$ pip install awscurl

$ awscurl --service lambda --region ap-northeast-1 関数URL
Hello, World!!
```
deno.landにモジュール公開

n番煎じかもしれませんが https://deno.land/x/ にモジュールを公開する方法について。

## deno.landにモジュールを公開する方法

### 1. https://deno.land/add_module にアクセスして必要事項を埋める

Select a module name に、公開したいモジュール名を入力します。
他の設定は基本的に不要でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678625/d4f78396-e78f-d297-11fa-6a0cf9abe986.png)

### 2. GitHubリポジトリにwebhookを追加する

Add the webhook に従って、GitHubリポジトリにwebhookを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678625/20e69175-eff7-1eb0-499f-9ed02f0ec34f.png)

これも書いてある通りにGitHub上で設定します。

1. 追加するリポジトリに移動する
1. `Settings`タブに移動する
1. `webhooks`タブに移動する
1. `Add webhook`ボタンをクリックする
1. `Payload URL`に`https://api.deno.land/webhook/gh/{<モジュール名>}`を入力する
1. `Content Type`は`application/json`を選択する
1. `Let me select individual events.`を選択する
1. `Branch or tag creation`のみを選択する（ほかのチェックは外す）
1. `Add webhook`をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678625/d89d0c6f-deda-0f44-bc55-eef8310e82ac.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678625/6c5bdb8b-bff1-9059-62d1-25140916023c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678625/b9389d14-4d06-26e8-3731-549963f112ff.png)

### 3. https://deno.land/add_module に戻ってsubmitを押す

submitを押すと登録完了するので、これで設定は完了です。

### 4. GitHubにタグをpushする

タグを作成してpushするか、GitHub上でリリースを作成すると、モジュールの新しいバージョンが公開されます。
案件管理やタスクをダッシュボードを使って見やすく管理する Dynamics 365

## はじめに
Power BI のBIツールをつかってダッシュボードを作成し、Dynamics 365で公開する
Dynamics 365 の設定内容やできることを標準ベースで記録しています。

## Dynamics 365 完成イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/5c47feac-b34a-d03f-af60-dcc3c80c697b.png)

Dynamics 365 にダッシュボード公開
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/9d797711-2ef6-5de8-7b76-e31da253e0ad.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/9383fb28-17a8-5e68-5291-8959b21bfe9b.png)


工事案件管理として営業案件で管理するイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/e80daa98-ba82-0912-f8df-8cf3d9b6e5e8.png)


## Power BI で作成する
↓の動画をみて作成する

https://youtu.be/Yv4sMztEoU4

### つまったところ
カレンダーマスタの作り方で関数入れてもエラーとなった。

### 解決策
テーブル作成し、CALENDARAUTO()　作成することで解決
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/43331088-eaf3-2b2b-6116-f7eaf3980034.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/e85d11c1-acbe-0c84-303b-f0a8cab0b0b6.png)

今回はExcelデータをダッシュボードとして見える化
これをテーブル管理することでリアルタイムで見える化可能。

Teamsにも埋め込みすることでDynamics 365 アクセス権限ない人も、ログインせずにいつでも見える。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/7bbe9e27-de77-8d8f-0cc7-3d2b98edff94.png)

## 参考にしたURL
* [Power BIでタスク管理をする方法【ハンズオン解説】](https://youtu.be/Yv4sMztEoU4)

https://youtu.be/Yv4sMztEoU4

* [Power BIのダッシュボード作成とDynamics側での表示](https://esp-labo.com/powerbi_dashboard/#:~:text=Dynamics%E5%86%85%E3%81%A7Power%20BI%E3%81%AE%E8%A1%A8%E7%A4%BA%E3%82%92%E6%9C%89%E5%8A%B9%E5%8C%96%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AB%E3%81%AF%E3%80%81%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%81%8B%E3%82%89,%5B%E3%83%AC%E3%83%9D%E3%83%BC%E3%83%88%5D%E3%82%BF%E3%83%96%E3%81%AE%20%5BPower%20BI%E3%81%AE%E3%83%93%E3%82%B8%E3%83%A5%E3%82%A2%E3%83%AB%E5%8C%96%E3%81%AE%E5%9F%8B%E3%82%81%E8%BE%BC%E3%81%BF%E3%82%92%E8%A8%B1%E5%8F%AF%E3%81%99%E3%82%8B%5D%E3%82%92%E3%80%8C%E3%81%AF%E3%81%84%E3%80%8D%E3%81%AB%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%BE%E3%81%97%E3%82%87%E3%81%86%E3%80%82)

https://esp-labo.com/powerbi_dashboard/#:~:text=Dynamics%E5%86%85%E3%81%A7Power%20BI%E3%81%AE%E8%A1%A8%E7%A4%BA%E3%82%92%E6%9C%89%E5%8A%B9%E5%8C%96%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AB%E3%81%AF%E3%80%81%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%81%8B%E3%82%89,%5B%E3%83%AC%E3%83%9D%E3%83%BC%E3%83%88%5D%E3%82%BF%E3%83%96%E3%81%AE%20%5BPower%20BI%E3%81%AE%E3%83%93%E3%82%B8%E3%83%A5%E3%82%A2%E3%83%AB%E5%8C%96%E3%81%AE%E5%9F%8B%E3%82%81%E8%BE%BC%E3%81%BF%E3%82%92%E8%A8%B1%E5%8F%AF%E3%81%99%E3%82%8B%5D%E3%82%92%E3%80%8C%E3%81%AF%E3%81%84%E3%80%8D%E3%81%AB%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%BE%E3%81%97%E3%82%87%E3%81%86%E3%80%82


以上
【C++】型Tが暗黙に構築可能かどうか判定する、is_implicitly_constructibleクラスを作りました

# はじめに
型Tが引数Args...から暗黙に(implicitに)構築可能かどうか判定する、is_implicitly_constructibleクラスを作りました。

# 動機
自作のクラスのコンストラクタが、想定通りexplicitになっている（またはなっていない)のを確認したいことがあったので作りました。

# 実装
クラス宣言は以下のようになります。
```cpp
// 型Tが引数Args...から暗黙に構築可能かどうか調べる
template <typename T, typename... Args>
struct is_implicitly_constructible;
```
これを実装するには、
```cpp
template <typename T>
void func(T);
```
があったとき、`func<T>({Args...});`の形で呼び出し可能であれば、
型TはArgs...から暗黙に構築可能と言えますので、それを利用します。
```cpp
// 実装のためのヘルパークラス
template <typename T, typename... Args>
struct is_implicitly_constructible_impl
{
private:
	template <typename T1>
	static void test_helper(T1);

	template <typename T1, typename... Args1>
	static auto test(int)
		-> decltype(test_helper<T1>({std::declval<Args1>()...}), std::true_type());

	template <typename T1, typename... Args1>
	static auto test(...) -> std::false_type;

public:
	using type = decltype(test<T, Args...>(0));
};

// is_implicitly_constructible定義
template <typename T, typename... Args>
struct is_implicitly_constructible
	: public is_implicitly_constructible_impl<T, Args...>::type
{};
```

:::note
実際にはもう少し考慮しなければいけないことがあるのですが、ここではわかりやすくするため簡略化しています。
完全なソースコードはGitHubに上げてあります。
https://github.com/shibainuudon/HamonEngine/blob/develop/libs/type_traits/include/hamon/type_traits/is_implicitly_constructible.hpp
:::

# 使い方
```cpp
struct S1
{
	S1(int);
};

struct S2
{
	explicit S2(int);
};

static_assert(is_implicitly_constructible<S1, int>::value == true);
static_assert(is_implicitly_constructible<S2, int>::value == false);
```
# 用途
型Sをラッピングするような型Tを作るときに、引数からSが暗黙に構築可能であるかどうかによって、Tのコンストラクタにexplicitをつけるかどうか切り替えるときなどに使えるのではないでしょうか。
関連：https://cpprefjp.github.io/lang/cpp20/explicit_bool.html

# 他の選択肢
Stack Overflowの方法で暗黙に構築可能か判定することもできると思います。
https://stackoverflow.com/questions/42786565/how-to-check-if-type-is-explicitly-implicitly-constructible
しかし、この方法は任意の引数に対応していません。

## is_explicitly_constructibleを定義するかどうか
`is_constructible && !is_implicitly_constructible`を`is_explicitly_constructible`と定義すると便利かもしれません。
しかし、implicitに構築可能である場合はexplicitにも構築可能なはずなので、名前とあっていないような気がします。[^1]
explicitに**のみ**構築可能ということを表現する短い名前があるといいのですが・・・。

[^1]: 正しくするにはis_not_implicitly_constructible_but_explicitly_constructibleとか？？？

# まとめ
is_implicitly_constructible、標準ライブラリにほしくないですか？