OmniAICreator/Qiita-1.07M huggingface dataset:
デイリースクラムで進捗の順調度を宣言すると危機察知しやすい

この記事は以下のイベントに参加して書いてます。
https://qiita.com/official-events/c826cda7a9514df143cb

# デイリースクラムでの困りごと

デイリースクラムでは昨日やったこと、今日やること、困っていることを聞いているけれども、実際そのメンバーが余裕を持ってタスクを進めているのか、それとももうすでにリリースに支障が出るレベルで問題が発生しているのかがわかりづらく、困っていることを一緒に解決しようという気持ちがチーム全体的に芽生えづらかった。デイリースクラムではプロジェクトの進行に関わる問題を明確にしたい。

# 順調度を宣言してみた

私のチームでは順調度という指標を取り入れ、昨日やったこと、今日やること、困っていることに加えてこれを各自宣言するようにしてみた。順調度は１〜５の数字で表現し、それぞれ次のような意味を持たせている。

５：計画以上の進捗
４：計画に変更はないが余裕もない
３：少し遅れていて挽回できるか五分五分
２：手詰まり感あり、計画通りとはいかない
１：確実に遅れてる

順調度の宣言時には理由も添えるようにする。例えば「○○のタスクでxxの問題に当たって、原因の調査に想定以上に時間がかかっているため、計画より少し遅れています。順調度は3です。」のように宣言する。

# 成果

プロジェクトスケジュールに対しての危機察知と課題解決が行いやすくなった。順調度は概ね３以下になり始めたら警戒しなければと意識している。３以下になったときには「困っていること」をどのようにしてチームで解決するかを議論開始するためのトリガーになってくれている。

# まとめ

デイリースクラムにて進捗の順調度を各自宣言すると、素早く危機察知と課題解決のアクションを起こせるようになるので良い。
Debian のセットアップ手順(インストールから簡単な設定まで)

# 概要
Debian 10(10.10)をインストールした際の手順です｡
ここに記載されている手順をなぞれば余計なものがほとんど入っていない Debian が利用可能になります｡
一時的な検証用途での利用を想定し､セキュリティについてはあまり考慮していない内容です
非エンジニアでも分かりやすいように記載したつもりです｡
ほぼ備忘録です

# 構築環境
* MacOS Big Sur(11.4)
* VMware Fusion Player 12
    * 非商用目的なら無料で利用可能です

# セットアップ手順

### インストーラーのダウンロード
1. 公式サイトにアクセスする
    * https://www.debian.org

2. トップページの Download ボタンをクリックする
    * debian-10.10.0-amd64-netinst.iso がダウンロードされます


### 仮想マシン作成(VMware Fusion Player 12 の場合の手順)

1. VMware Fusion Player 12 を起動する
2. ファイル → 新規 をクリックしてウィンドウを開く
3. ダウンロードした ISO ファイルをウィンドウにドラッグアンドドロップする
3. インストールウィザードの指示に従って設定を続けていく
    * ブートファームウェアの指定: UEFI
    * CPU コア数､メモリ量､ネットワーク設定はお好みで
4. 設定が完了すると仮想マシンのウィンドウが表示される

### Debian インストール作業
* インストール中はインターネットに接続できる環境である必要があります

1. 作成した仮想マシンを起動する
1. Graphical install を選択してエンター
1. 各種設定したい内容を選択していく
    * 言語 → 日本語(CUI 環境としてセットアップする場合は英語のほうが文字化けしない)
    * 場所 → 日本
    * キーボード → 日本語(英語キーボード利用なら米国)
    * ホスト名 → デフォルトの debian で問題ない
    * ドメイン名 → 空欄でOK
    * root パスワード → お好きなもの(今後必要になるので忘れない)
    * 新しいユーザの本名 → お好きなもの
    * あなたのアカウントのユーザ名 → お好きなもの(ログインする際に必要になるので忘れない)
    * 新しいユーザーのパスワード → お好きなもの(今後必要になるので忘れない)
    * パーティショニングの方法 → ガイド - ディスク全体を使う
    * パーティショニング機構 → すべてのファイルを1つのパーティションに
    * ディスクに変更を書き込みますか? → はい
    * 他の CD や DVD を検査しますか? → いいえ
    * Debian アーカイブミラーの国 → 日本
    * Debian アーカイブミラー → deb.debian.org(どれでもいいと思う)
    * HTTP プロキシの情報 → 空欄(プロキシ環境下ではその情報)
    * Debian パッケージ両調査に参加しますか → いいえ(どっちでも良い)
    * ソフトウェアの選択
        * 下記の項目にチェックを付ける
            * Debian デスクトップ環境(CUI 環境が希望の場合はチェックしない)
            * GNOME(CUI 環境が希望の場合はチェックしない)
            * SSHサーバー(SSH や SFTP を利用しない場合はチェックしない)
            * 標準システムユーティリティ
1. インストールが完了するまで待機
1. これでセットアップが完了する

### Debian 起動後にやること
* 操作はすべて端末(Mac で言うところのターミナル Windows だとコマンドプロンプト)で行う
    * 開き方は 画面左上のアクティビティ → 検索バーに terminal と入力すると 端末 が表示されるのでそれ開く
        * よく使うのでアイコンを右クリック → お気に入りに追加 すると良いかも
* 説明では一般ユーザーの名前は user として説明しています

#### sudo の設定
1. 端末に su - と入力してエンター
1. root パスワードを求められるのでインストール時に設定したものを入力してユーザーを(root)管理者に切り替える
1. visudo と入力してエンター
1. 下記の内容を root ALL=... と書かれている下に追記する
    * user ALL=(ALL:ALL) ALL
1. Ctrl + o を入力してエンターでファイルを保存
1. Ctrl + x でエディタを閉じる

#### apt の設定
1. sudo apt-get update
1. sudo apt-get upgrade

#### open-vm-tools のインストール
* sudo apt-get install open-vm-tools

とりあえずここまで行えば簡易的な Debian 環境が用意できます｡
サーバーとして外部に公開する場合は SSH のポート番号の変更やファイアーウォールの設定など行ってください｡
DjangoのMultiple Databasesのときのselect_for_updateでエラーが出た

DjangoでSQLのSLECT FOR UPDATEをするときはQuerySetの`select_for_update()`を利用しますが、これを利用してもエラーが出たので少々調べました。
# 経緯
`select_for_update()`はトランザクション内、Djangoの`transaction.atomic()`内でしか使えません。
もしトランザクション外で`select_for_update()`を使うと

```python
django.db.transaction.TransactionManagementError: select_for_update cannot be used outside of a transaction.
```
とエラーが起きます。

今回、レプリカDBがあるためMultiple Databasesの環境でDjangoを使用していましたが、このMultiple Databasesの環境のトランザクション内で`select_for_update()`を使用したら上記のエラーが起きました。
`transaction.atomic()`のコンテキスト内なのになぜ？となり、少々このあたりのコードを読みました。

# 結論
Multiple Databasesの環境かつトランザクションを開始するDBが`default`ではないときは`transaction.atomic`の引数`using`を指定しましょう。例えば`hoge`DBに保存されたモデル`Hige`を更新するなら、

```python
with transaction.atomic(using="hoge"):
    hoge = Hige.objects.select_for_update().get(pk=1)
```
のような感じです。

# なぜエラーが起きたのか
Djangoではsettings.pyの`DATABASES`に追加することでDBを複数利用できますが、色々なところで`default`のDBが選択されます。今回もそのケースです。
`transaction.atomic()`はusingでDBを指定しない場合、`default`DBに対してトランザクションを開始します。そして、`default`ではない他のDBに保存されているモデルに対して`select_for_update()`を使用したため、トランザクション外での`select_for_update()`となりエラーが起きてしまいました。

考えてみると当然で、何も指定せず`transaction.atomic()`を使ってもどのDBでトランザクションを開始すればいいかDjango側では判断ができないですよね。
docker+nginx+railsでアプリケーション側でクライアントのIPアドレスが取得できずに困った話

dockerで起動しているrailsアプリケーションで、クライアントのIPアドレスを取得しようとしたら
docker内のIPアドレスしか取得できずに困った。

```ruby
p request.remote_ip  //これがクライアントのIPではない
```

ただ、nginxのaccess_logには、末尾にクライアントのIPアドレスが出力されていた。

```access_log
xxx.xxx.xxx.xxx - - [30/Jun/2021:13:19:53 +0000] "HEAD /robots.txt HTTP/1.1" 301 0 "-" "-" "クライアントのIPアドレス, xxx.xxx.xxx.xxx"
```

そこでnginxの設定ファイルに以下を追記

```default.conf
+    proxy_set_header X-Forwarded-For $http_x_forwarded_for;
```

以下でクライアントのIPをrailsアプリケーション内で取得できた。

```ruby
p request.env['HTTP_X_FORWARDED_FOR']
```
Docker初心者が陥ったエラー集

##はじめに
Dockerを初めて使っている初心者エンジニアです。
コンテナを起動したり、イメージを作っていく中で、同じエラーによくつかまるので備忘録としてまとめます。

### Dockerの基本コマンドの確認
(1) イメージをDockerリポジトリから取得 or Docker fileからビルド
↓ `$ docker image pull` or `$ docker image build`
(2) コンテナの生成
↓ `$ docker container create`
(3) コンテナの起動
↓ `$ docker container start`
(4) コンテナの停止
↓ `$ docker container stop`
(5) コンテナの削除
  `$ docker container rm`

※(2)と(3)を同時に行う
  `$ docker container run`

### 複数のコンテナをまとめて操作するコマンドも確認
(1) docker-compose.ymlを用意
↓
(2) イメージを複数のコンテナをビルド
↓ `$ docker-compose build`
(3) 複数のコンテナを生成・起動
↓ `$ docker-compose up`
(4) 複数のコンテナを停止
↓ `$ docker-compose stop`
(5) 複数のコンテナを削除
  `$ docker-compose rm`

※(4)と(5)を同時に行う
  `$ docker-compose down`

###それでは本題のつまづいたエラーたち

####エラー①

```
Cannot connect to the Docker daemon. Is the docker daemon running?
```

原因：Dockerが起動していない。
対策:`docker run`で起動させる。


◆ コンテナをバックグラウンドで起動させたい場合は`-d`(--detach)をオプションでつける。

```
docker run -d 
```

ホストのシェルからコンテナプロセスをデタッチして、バックグラウンドでコンテナを起動する。これによりシェルで入力操作が可能になる。


####エラー②

```
"docker run" requires at least 1 argument.
```

原因：実行するイメージが指定されていない
対策: `docker run [オプション] イメージ名`で実行する
https://stackoverflow.com/questions/56308424/docker-container-run-requires-at-least-1-argument
https://docs.docker.com/engine/reference/run/


####エラー③

```
docker: Error response from daemon: driver failed programming external connectivity on endpoint 
```

原因:他のコンテナとポートが被っている
対策：ホスト側のポート番号を変更する。

https://qiita.com/ponsuke0531/items/f3490f571b5eee16ea87


####エラー④

```
Error response from daemon: You cannot remove a running container . Stop the container before attempting removal or force remove
```

原因：起動中はコンテナを削除できない。
対策：`docker stop <CONTAINER IDまたはNAME>`でコンテナを停止させ、`docker rm <CONTAINER IDまたはNAME>`で削除する。

https://access.redhat.com/documentation/ja-jp/red_hat_3scale_api_management/2.7/html/administering_the_api_gateway/apicast-docker-advanced

####エラー⑤

```
Error response from daemon: conflict: unable to remove repository reference "nginx" (must force) - container 1ea55b6d3589 is using its referenced image 4f380adfc10f
```
原因:ドッカーイメージを削除する際(`docker rmi nginx`)にコンテナ(1ea55b6d3589)が参照しているため、消すことができない。
対策:`docker rm 1ea55b6d3589`の後に`docker rmi nginx`を実行する。

##おわりに
まだまだ基礎部分を学習中で、これからまだまだエラーを頻発させると思うので
備忘録の厚みも増やしていきます。
【Swift】Extensionを使って便利にカスタムセルを登録、生成する

#はじめに
今回はExtensionを使ってカスタムセルを登録、生成するする方法を紹介します。

#Extension

```swift
extension NSObjectProtocol {
    
    static var className: String {
        return String(describing: self)
    }
    
}

extension UITableViewCell {
    
    static var identifier: String {
        return className
    }
    
}

extension UITableView {
    
    func registerCustomCell<T: UITableViewCell>(_ cellType: T.Type) {
        register(
            UINib(nibName: T.identifier, bundle: nil),
            forCellReuseIdentifier: T.identifier
        )
    }
    
    func dequeueReusableCustomCell<T: UITableViewCell>(with cellType: T.Type) -> T {
        return dequeueReusableCell(withIdentifier: T.identifier) as! T
    }
    
}

extension UICollectionViewCell {
    
    static var identifier: String {
        return className
    }
    
}

extension UICollectionView {
    
    func registerCustomCell<T: UICollectionViewCell>(_ cellType: T.Type) {
        register(
            UINib(nibName: T.identifier, bundle: nil),
            forCellWithReuseIdentifier: T.identifier
        )
    }
    
    func dequeueReusableCustomCell<T: UICollectionViewCell>(with cellType: T.Type,
                                                            indexPath: IndexPath) -> T {
        return dequeueReusableCell(withReuseIdentifier: T.identifier,
                                   for: indexPath) as! T
    }
    
}
```

#実装例

```swift
class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.delegate = self
        tableView.dataSource = self
        
        // before
        tableView.register(
            UINib(nibName: "CustomTableViewCell", bundle: nil),
            forCellReuseIdentifier: "CustomTableViewCell"
        )
        // after
        tableView.registerCustomCell(CustomTableViewCell.self)
        
    }

}

extension ViewController: UITableViewDelegate {
    
}

extension ViewController: UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 100
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // before
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell") as! CustomTableViewCell
        // after
        let cell = tableView.dequeueReusableCustomCell(with: CustomTableViewCell.self)
        return cell
    }
    
    
}
```

#おわりに
おわりです。
残プロ　第-29回　~今月のまとめ~

# 余命を計算する

81歳(平均寿命)で大往生する予定なので，その場合の余命を計算します．


~~~lastday.py
import datetime

today = datetime.date.today()
rip = datetime.date(year=2081, month=6, day=1)
print(abs(rip - today).days)
~~~


~~~
-21886
~~~


残り21886日でした．まだまだ余裕ありますね．


# 今月の各週のまとめ

第1週 [LineNotifyで通知](https://qiita.com/R1nY1x1/items/ef444ea809a8061e8adc)
第2週 [RaspberryPiとcronでpythonの定期実行](https://qiita.com/R1nY1x1/items/3a3def1a3fc9cd34b3eb)
第3週 [tkinterでcsv編集](https://qiita.com/R1nY1x1/items/c95ae1baa157cc659d12)
第4週 [FlaskとBootStrapでcsv編集](https://qiita.com/R1nY1x1/items/02b85f92d90c654c4df4)
error: the following files have local modifications:


# 事象 : とあるディレクトリ配下をGit管理対象外にしようとしたら怒られた

```zsh
# .gitignoreを書いて
$ cat ../.gitignore
mkdocs/site/

# さぁ、削除しよ・・・としたら怒られた
$ git rm -r site/
error: the following files have local modifications:
    mkdocs/site/404.html
(use --cached to keep the file, or -f to force removal)
```

## 原因 : ローカルに変更があるから
メッセージを和訳すると「エラー:次のファイルにローカル変更があります。」でした。

```zsh
$ git status
On branch feature/mkdocs
Your branch is up to date with 'origin/feature/mkdocs'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   site/404.html
no changes added to commit (use "git add" and/or "git commit -a")
```

### 対応1 : `-f`オプションをつけて`git rm`する
ローカルの変更なんていらない！Git管理対象外にするファイルも削除しちゃってOK!な時の対応。

> git rm will not remove a file from just your working directory.
> (和訳)git rmは、作業ディレクトリからファイルを削除しません。
> [Git - git-rm Documentation](https://git-scm.com/docs/git-rm)

基本は「作業ディレクトリからファイルを削除しません。」がこのやり方ではファイルが作業ディレクトリから削除されちゃうので注意して、自己責任で実行してください。

> The files being removed have to be identical to the tip of the branch, and no updates to their contents can be staged in the index, though that default behavior can be overridden with the -f option.
> (頑張った和訳)削除されるファイルは、ブランチの先端と同じである必要があり、その内容の更新をインデックスにステージングすることはできません。ただし、デフォルトの動作は`-f`オプションで上書きできます。
> [Git - git-rm Documentation](https://git-scm.com/docs/git-rm)

```zsh
# -fオプションでローカルの変更チェックを無視！
$ git rm -fr site/
rm 'mkdocs/site/404.html'

# めでたく削除されたので後はコミット&プッシュする
$ git status
On branch feature/mkdocs
Your branch is up to date with 'origin/feature/mkdocs'.
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        deleted:    site/404.html
```

### 他の対応方法
今回はやってないけど将来のためにメモ

- 作業ディレクトリにファイルは残おかない場合 : ローカルの変更を消すなりコミットするなりする
- 作業ディレクトリにファイルは残しておきたい場合 : `git rm --cached {ファイル}`する

|`git rm`のオプション|意味|参考サイト|
|:--|:--|:--|
|`-r`|ディレクトリが指定された場合、再帰的に削除する|[Git - git-rm Documentation](https://git-scm.com/docs/git-rm)|
|`-f`<br/>`--force`|最新のチェックを上書きする|[【Git】特定の名前のフォルダ配下のファイルを管理対象外にする｜coglay Blog](https://coglayblog.com/2018/02/03/%E3%80%90git%E3%80%91%E7%89%B9%E5%AE%9A%E3%81%AE%E5%90%8D%E5%89%8D%E3%81%AE%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80%E9%85%8D%E4%B8%8B%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E7%AE%A1/)|
|`--cached`|インデックスからだけ削除して、作業ディレクトリにファイルは残す|[[git]commitした後に.gitignoreに追加したい時 &#124; あくあ&#124;development_blog](https://aqua-engineer.com/post-753/)|
AWS CodeGuru リポジトリ分析で推奨事項・プルリクエストの指摘をしてもらう

# 手順

## 1. リポジトリを関連付ける

以下のように「リポジトリの関連付け」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/6a78b787-02b5-7342-3f4d-c92c8e114ead.png)

GitHub を選択し、「GitHub アカウントに接続」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/a72893b8-d5e5-2e14-be2e-49272a3bfa04.png)

関連付けで認証が終了した後、「リポジトリの場所」でリポジトリを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/5e6ad8eb-557f-97fd-e14e-9e130ebb552c.png)

## 2. フルリポジトリ分析を作成する

以下のように「フルリポジトリ分析を作成」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/343353bb-b973-e4a1-a32e-1ade491c1631.png)

関連付けたリポジトリを選択し、ブランチを選択します。その後「フルリポジトリ分析を作成」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/1bedbf6b-0ca2-ede3-a915-817d694bd962.png)

## 3. 分析結果を確認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/332f3396-d0c8-675e-0352-efc943b8de2e.png)

> API メソッド list_tables は、すべての結果ではなく、ページ分割された結果を返します。ページネーション API を使用するか、レスポンスの以下のキーのいずれかをチェックして、すべての結果が返されたことを確認することを検討してください。ExclusiveStartTableName, IsTruncated, LastEvaluatedTableName, NextToken.

## 4. プルリクエストを提出する

プルリクエストを提出すると、自動で増分コードレビューが開始されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/83c4b7c6-3097-7aa9-66e4-7da2fe610f69.png)

以下のように GitHub から CodeGuru のコメントを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/b82d509a-e834-4032-0f91-bbbb5900d416.png)

## サンプルコード

```codeguru_test.py
import json
import boto3


def lambda_handler(event, context):
    dynamodb = boto3.resource('dynamodb')
    # table = dynamodb.Table(event['user'])
    response = dynamodb.tables.all()
    print(type(response))
    print(response)
    print()
    for x in response:
        print(x, type(x), x._name)

    dynamodb = boto3.client('dynamodb')
    response = dynamodb.list_tables()
    print(type(response))
    print(response)
    print(response['TableNames'])
    print()
    response = dynamodb.describe_table(
        TableName='appDatabase'
    )
    print(type(response))
    print(response)

    
def lambda_handler(event, context):
    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table('myTable')
    response = table.scan()
    print(response['Items'])

    search = event['search']
    for dic in response['Items']:
        print(dic['word'], search)
        if search == dic['word']:
            return {
                'statusCode': 200,
                'body': dic
            }
    return {
        'statusCode': 200,
        'body': {"explain": "Not Found", "word": "Not Found"}
    }
```

# 参考記事

https://docs.aws.amazon.com/codeguru/latest/reviewer-ug/code-reviews.html
2021年のITトレンドざっくりまとめ

#■はじめに
2021年のIT業界の動向から、関心の高まっている
概念や技術について初心者向けにまとめていく。
当記事ではその導入として、直近の概況とキーワードを列挙する。

※キーワードに無い技術に関しても追々記載予定。

##`３行まとめ`
・テレワーク需要により「場所に縛られない働き方」の実現が進む
・IoT→IoBへの移行によってモノからヒト中心のインターネットへ
・ソフトウェア開発そのものの簡略化で業務効率UP

#■「場所に縛られない働き方」の実現
##`テレワーク需要によるIT化の促進`
近年の情勢に伴い、IT業界外においてもテレワークが普及しつつある。
これを実現するため、通信やインフラ分野の技術が注目されている。

###クラウドサービスの限界と変化
クラウド化が困難だったりコスト維持が厳しい業界において、
エッジコンピューティングが台頭。
上記の利点を活かして、クラウド自体も従来の「集中型」から「分散型」へ

###デジタルファーストのサービスの台頭
場所を選ばずにどこからでも利用できるビジネスの仕組みが求められ、
インターネットを介して必要な機能をサービスとして提供する
ソフトフェアの需要が高まっている。
専門的には、これをSaaS型のサービスと呼ぶ。

例えば、Slackはチャット機能、ZoomはWeb会議機能を
インターネットを通じて提供するSaaSと言える。

###非接触型／非密集型のソリューション需要
ソーシャルディスタンスの確保や人との物理的な接触の削減のため、
様々なサービスの自動化や無人化が促進されている。

その実現のため、いわゆる「AIを搭載した機器」の普及が進んでいる。
専門的には、機器のことをエッジデバイスと呼び、
エッジデバイスに搭載されるAIをエッジAIと呼ぶ。

##`関連ワード`
・エッジコンピューティング
・集中型／分散型クラウド
・SaaS（Software as a Service）
・エッジデバイス／エッジAI

#■「IoT」から「IoB」へ
##`IoTとIoB`
>IoT（Internet of Thing）

様々な物がインターネットに接続され、
情報交換することにより相互に制御する技術。

>IoB（Internet of Behavior／Bodies）

（-Behavior）
顔認識、位置情報の追跡など、人の行動に関する技術を組み合わせ、
収集したデータを個人に提供する技術。

（-Bodies）
体にインターネットを繋げた状態で人の動作を追跡し、
収集したデータを個人に提供する技術。

##`IoTからの発展`
IoTの普及により様々なデバイスにデータが蓄積されるようになった。
IoBは、これらのIoTから収集されたビッグデータを活用して
個人の行動に影響を与えることが出来るようになる。

例えば、
スマートフォンの位置情報から
ウイルスの感染経路を特定するアプリなども、IoBの賜物である。

#■ソフトウェア開発の低敷居化
##`開発者なのにソースを書かなくてよい？`
先端技術の普及が進められる一方で、
ローコード／ノーコード開発を始めとした
ソフトウェア開発を誰でも行えるようにする環境作りが活発化している。

##`ローコード開発／ノーコード開発`
必要最低限のソースコードを用いる、もしくは
ソースコードを書かずにWebサービスやアプリを開発する手法のこと。
現在、様々な企業から開発支援ツールが提供されている。

#■参考文献
【2021年版】ITトレンドを紐解く16のキーワード IoB・継続的DX・エッジAIなどわかりやすく解説
https://tech-camp.in/note/technology/97662/

IoTの次は“IoB”？インターネットと身体が繋がる未来とは
https://www.capa.co.jp/archives/21438

今注目のローコード開発とは？従来開発との違いとメリット・デメリット
https://www.tdi.co.jp/miso/low-code-merit-demerit

ノーコード（NoCode）開発とは？特徴とおすすめの開発ツール
https://persol-tech-s.co.jp/hatalabo/it_engineer/524.html
Asciinema による再生時の文字を色付けする方法.



2021/06/30 時点での Asciinema には、再生時の文字色を変更する機能は無い.

そこで独自に色付けするための方法を検討したので、書き残しておく.

## 概要

ここでは次のように「cd /tmp」を一文字ずつ色を変えて、「pwd」は反転表示させて再生させる

**Before**　　　　　　　　　　　**After**
![Screenshot from 2021-06-30 22-29-25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/2603e69e-db0f-396a-d29a-d8e5ace9d909.png)　　![Screenshot from 2021-06-30 22-31-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/27c8a549-8a58-faa8-c0f6-da3e474c1b8c.png)



## 手順

### 1. 録画をする

単に `cd /tmp` と `pwd` を実行するだけの処理を記録する

```
$ asciinema rec ./demo.cast  # 録画開始
$ cd /tmp
$ pwd
/tmp
$ exit  # 録画終了
```


### 2. 録画ファイルを編集して色付けする

次のように、録画ファイル `./demo.cast` に対して次のように [ANSIカラーコード](https://melborne.github.io/2010/11/07/Ruby-ANSI/)を付与してやる.

```diff
$ diff -u demo.cast.ORIG demo.cast
--- demo.cast.ORIG	2021-06-30 22:15:28.526810575 +0900
+++ demo.cast	2021-06-30 22:21:06.726480164 +0900
@@ -1,17 +1,17 @@
 {"version": 2, "width": 143, "height": 48, "timestamp": 1625058784, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}}
 [0.09784, "o", "\u001b]0;foo@mypc: /tmp\u0007$ "]
-[3.171138, "o", "c"]
-[3.339062, "o", "d"]
+[3.171138, "o", "\u001b[31mc\u001b[0m"]
+[3.339062, "o", "\u001b[32md\u001b[0m"]
 [3.451687, "o", " "]
-[3.580648, "o", "/"]
-[3.721906, "o", "t"]
-[3.818249, "o", "m"]
-[4.018552, "o", "p"]
+[3.580648, "o", "\u001b[33m/\u001b[0m"]
+[3.721906, "o", "\u001b[34mt\u001b[0m"]
+[3.818249, "o", "\u001b[35mm\u001b[0m"]
+[4.018552, "o", "\u001b[36mp\u001b[0m"]
 [4.291077, "o", "\r\n"]
 [4.291348, "o", "\u001b]0;foo@mypc: /tmp\u0007$ "]
-[4.882962, "o", "p"]
-[4.931557, "o", "w"]
-[5.02746, "o", "d"]
+[4.882962, "o", "\u001b[07mp\u001b[0m"]
+[4.931557, "o", "\u001b[07mw\u001b[0m"]
+[5.02746, "o", "\u001b[07md\u001b[0m"]
 [5.260433, "o", "\r\n"]
 [5.26078, "o", "/tmp\r\n\u001b]0;foo@mypc: /tmp\u0007$ "]
 [6.491377, "o", "e"]

```

### 3. 再生する

```
$ asciinema play ./demo.cast
```

　
以上
【備忘録】LinuxとMacでのdateコマンドの差異について

Linux上にて、特定の日付での挙動を調べるために

```
date -s "12/31 12:00 2021"
```

というコマンドを実行して調査指定していました。  
これをMacのローカル環境でも調べようと思って同じコマンドを叩くと

```
date -s "12/31 12:00 2021"

date: illegal option -- s
usage: date [-jnRu] [-d dst] [-r seconds] [-t west] [-v[+|-]val[ymwdHMS]] ...
            [-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format]
```

と怒られました。　　
「"s"なんてオプションは無え！」ということらしいです。
  

## 何でこんなことになるのか

  
普段からはそこまで差を感じないので「なんとなく同じなんじゃないの」と思い込んでしまっていましたが、MacOSとLinuxはそもそも違います。  
まあ当然と言えば当然ですね。  
MacはBSDというUnixをベースに作られているらしいです。  


## 対処法

GNU Linuxにおけるdateコマンドと同様のものをbrewでインストールできます。

```
brew install coreutils
```



こうすることで、GNU Linuxにおけるdateコマンドと同じ働きをするgdateコマンドが使えます。
これをこのまま使ってもいいのですが、あくまでdateコマンドとして使いたい時は、.zshrcに

```
alias date=’/usr/local/bin/gdate’
```

を追記するなどして、エイリアスを定義しましょう。
一応、whichでgdateの保存先などを確認しておくとより確実ですね。
  
…

とまあ、ここまで説明しておいてアレですが、

```
sudo date 123112002021
```
でも変更できるみたいですね。


## +α

  
今回はdateコマンドでしたが、
- xargs
- sed
- grep
- base64
もBSD UnixとGNU Linuxで挙動が違うコマンドの代表例らしいです。  
ここら辺のある程度の知見を持っておきたい…。
Vue.js / FlaskアプリにSlack for boltを組み込むには

フロントエンドをVue.js
バックエンドをFlask(python)
で作っているWebアプリを書いているのですが、そこにSlack botを組み込む必要がありました。
せっかくpythonで書いているので、slack bolt for pythonを使えば簡単にかけるはずです。
https://github.com/SlackAPI/bolt-python

このboltなのですが、 @seratch さんの尽力もあって、Flask用のexampleも書いてあるのです。ありがたや。
https://github.com/slackapi/bolt-python/tree/main/examples/flask

コード自体はそこに書いてあるとおりに書けば良いのですが、今回はもともと作っていたアプリに組み込みたい。そうなると、このままでは書けません。

イメージとしてはここにあるようなものです。
https://qiita.com/y-tsutsu/items/67f71fc8430a199a3efd

```backend/main.py
from flask import Flask, render_template

app = Flask(__name__, static_folder='../frontend/dist/static', template_folder='../frontend/dist')

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def index(path):
    return render_template('index.html')

if __name__ == '__main__':
    app.run()
```

こんな風になっているので、そこに組み込みましょう。

```backend/main.py
from flask import Flask, render_template

app = Flask(__name__, static_folder='../frontend/dist/static', template_folder='../frontend/dist')

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def index(path):
    return render_template('index.html')

from .bolt import bolt as bolt_blueprint
app.register_blueprint(bolt_blueprint)

if __name__ == '__main__':
    app.run()
```

bolt用のファイルは、別に分けたいのでblueprintで分割します。
新規に作るファイルはbackend/bolt.pyにします。

```backend/bolt.py
import logging
logging.basicConfig(level=logging.DEBUG)

from slack_bolt import App
from slack_bolt.adapter.flask import SlackRequestHandler

import os

bolt_app = App(
    token=os.environ.get("SLACK_BOT_TOKEN"),
    signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
)

@bolt_app.event("app_mention")
def event_test(body, say, logger):
    logger.info(body)
    say("What's up?")


@bolt_app.event("message")
def handle_message():
    pass

handler = SlackRequestHandler(bolt_app)

bolt =  Blueprint('bolt', __name__)

@bolt.route("/slack/events", methods=["POST"])
def slack_events():
    return handler.handle(request)
```

こんな形になります。
blueprintで切り出してbolt.py側に持っていきます。
実はここでめちゃくちゃハマったのですが、ハマりどころがどこだったかというと
flask_app = Flask(\_\_name\_\_)
handler = SlackRequestHandler(app)

この二行ですね。
SlackRequestHandlerに入れるのはflask_appじゃないのです。
slack_boltで生成したappインスタンスなので注意してください。

handler = SlackRequestHandler(app)
flask_app = Flask(\_\_name\_\_)

こんな風に逆に書いてあったほうが勘違いしないかもしれない。

@bolt としたものは、main.pyから呼んだflaskのインスタンスです。
こいつを使ってrouteに設定した/slack/eventsに通ってきたリクエストをhandlerを通じてbolt側に渡して処理する形になっています。

処理の流れが分かってしまえば、理解しやすいのですが、初学者だとtypoに気付くのが辛いかもしれません。
どなたかの理解につながれば幸いです。
AWS小ネタ5選

AWS関係の小ネタを集めました。

# Fireshipが「AWSの50のサービス」という動画を出した
「100秒で説明してみた」シリーズで有名なYoutuber Fireshipが「AWSサービス50個を10分で説明してみた」を投稿しました。AWS初期の歴史的な流れがとても勉強になります。EC2が登場したのが2006年。そこからロードバランサーELBが出るまで3年以上かかっている。Elastic beanstalkやLightSailが出てきた理由。Lambdaが出てきたのが2014年（また7年しかたっていない）。初期のデータベースサービスにSimpleDBというものがあった、などなど。明らかにデータベース系のサービスが特に詳しく説明されていて、AI系のサービスなどはかなりざっくりしているところはご愛敬ですが。またFireship特有のシニカルなjokeはこの動画でも光っています。日本語対応なしですが、英語字幕つけて止めながらでも観る価値あり。

https://www.youtube.com/watch?v=JIbIYCM48to&ab_channel=Fireship

# SageMakerとS3の連携の楽さ
```python
from sagemaker.session import TrainingInput

train_input = TrainingInput(
    "s3://{}/{}/{}".format(bucket, prefix, "data/train.csv"), content_type="csv"
)
validation_input = TrainingInput(
    "s3://{}/{}/{}".format(bucket, prefix, "data/validation.csv"), content_type="csv"
)
```

学習用のデータをS3から持ってくる際にSageMaker SDKを使うとこうなります。簡単ですね。



# AWS Forumは神
S3やSageMakerよりAWS Forumは素晴らしいサービスです。

https://forums.aws.amazon.com

日本語版は過疎っているので英語で質問する必要がありますが、英語が苦手な人は質問をできるだけ短い文章をつなげて書くようにしてDeepLに投げればほとんどのケースで意味の通る英語になると思います。筆者もGreengrassやエッジ推論、コンテナ周りで何度もAWS Forum（みんなAWSのスタッフが答えてくれます）に助けてもらいました。

※2021/8/16追記　GreenGrass以外のサービス（例えばSageMakerなど）ではあまりAWSからの返答は無いようです。もともとみんなで教え合うというのがフォーラムのコンセプトなので現状のようにAWSの人だけがアンサーしてるのはAWSが意図していたものじゃ無いことは確かでしょう。今頃どこかでAWSの偉い人が「こんなはずでは・・・」と頭を悩ませていることは確実です。

# 意外と知られていない良学習リソース
AWSのDeveloperDocumentも良いですが

・リファレンスアーキテクチャ
いろいろなユースケースでのAWSサービスの設計図が150以上あります（英語版の方が多い）。

https://aws.amazon.com/jp/solutions/reference-architectures/?whitepapers-main.sort-by=item.additionalFields.sortDate&whitepapers-main.sort-order=desc&awsf.Diagrams-Tech-Category=*all&awsf.Diagrams-Industry=*all&awsm.page-whitepapers-main=1

・AWS クイックスタート
よくあるユースケースと、そのCloudformationテンプレートを集めてあります。

https://aws.amazon.com/jp/quickstart/?solutions-all.sort-by=item.additionalFields.sortDate&solutions-all.sort-order=desc&awsf.filter-tech-category=*all&awsf.filter-industry=*all&awsf.filter-content-type=*all&awsm.page-solutions-all=25

・AWS Blog
ニュース代わりに時々見て気になったものを読むのはあり。英語版はさらに充実しています。

https://aws.amazon.com/jp/blogs/news/

インフラとオートメーション（英語）

https://aws.amazon.com/jp/blogs/infrastructure-and-automation/

機械学習（英語）

https://aws.amazon.com/jp/blogs/machine-learning/

IoT（英語）

https://aws.amazon.com/jp/blogs/iot/


最近気になったのは、

「ヒュンダイが、SageMakerの並列処理ライブラリーとSageMakerDebuggerによる学習プロセスのデバッグ高速化で、再学習の時間を短縮」や、

https://aws.amazon.com/jp/blogs/machine-learning/hyundai-reduces-training-time-for-autonomous-driving-models-using-amazon-sagemaker/

「AWS Video Streaming Serviceの使い分け」など。

https://aws.amazon.com/jp/blogs/iot/choose-the-right-aws-video-service-for-your-use-case/

# AWS関係で名前の由来3つ
・MySQLのMyはMySQLの創業者の一人Michaelさんの娘の名前(https://en.wikipedia.org/wiki/MySQL)

・boto3のbotoはアマゾン川に生息するイルカの現地名（ポルトガル語？）

・RedShiftは「Oracle（しばしばBig Redと呼ばれる）からの脱却(Shift away)」という意味が込められている(https://en.wikipedia.org/wiki/Amazon_Redshift)

以上です。
Filterクラスの作成

## Filterクラスとは
* フィルタを設定するとサーブレットのdoPost(),doGet()の前後でFilterクラスに設定した処理を実行することができる
* 複数のサーブレットで同じ処理をする場合など、共通の処理をまとめることができる
* １つのサーブレットに複数のフィルタをかけることも可能
    * ログインフィルタ
    * 権限フィルタ 等

## Filterの実装
 @WebFilterアノテーションを付与する

```java:WebFilter
@WebFilter("/*") //　フィルタを設定するサーブレットのURLパターンを指定
```

java.servlet.Filter インターフェースを実装する

```java:Filter
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

// すべてのサーブレットクラスに設定する場合は("/*")
@WebFilter("/*")
public class Filter implements javax.servlet.Filter {
    // デフォルトコンストラクタ
    public Filter() {}

    // インスタンス化された直後に実行される処理
    public void init(FilterConfig fConfig) throws ServletException {}

    // インスタンスが破棄される直前に実行される処理
    public void destroy() {}

    // 設定したサーブレットクラスをリクエストした時に実行される処理
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // doFilter()の前に書くとサーブレット実行の前処理となる
	    request.setCharacterEncoding("UTF-8");
	    chain.doFilter(request, response);
        // doFilter()の後に書くとサーブレット実行の後処理となる
        // ~~~~
	}
}
```

## EclipseからFilterクラスを作成する場合
新規→フィルタを選択すると簡単に実装できる
【Python】 binary data を読み書き

# はじめに

少し前に、python でバイナリデータを読んでpacket をparse したり（PREAMBLEから読み始めてチェックサムで確認するとか）、データを読んだり(2byte を整数値にするとか）したりしました。そのとき、改めてバイナリデータの扱いを調べたので、メモ。何度も調べて、良く分かんらないまま使っていましたが、今は少しわかった気でいます。??

実際に仕事ではセンサーにコマンドを送ったり受け取ったメッセージを出コードするところを行うための実装でした。皆さんＯＳＳを使うところを、おじさんはポチポチとコードを書いて読み解いています。

# bytes型 (自分の理解)

pythonで定義されている bytes 型のデータを正しく使えば、何事もなく実装ができるはず、、です。

## bytes型はどこからくるか

プログラム上で変数を作ることもできますが、自分の場合、ずばり、
- binary type でfileを読んでいるとき
- socket 通信しているとき
- serial ポートからデータを読んでいるとき

です。そのとき、read/write しているのはこのbytes 型です。

```Python
In [  ]: with open("hoge.bin","rb") as f:
    ...:     buf = f.read(4)
    ...:     print(type(buf))
    ...:
<class 'bytes'>
```

## 整数値のリスト <--> bytes型

bytes 型と「整数値のリスト」は異なるものです。相互には変換可能です。（もちろん整数値は0から255に限られますが）

### 整数値

0から255までの整数値が1 byte を表すのはご存じのとおりです。なので、0から255までの整数値の系列（list 型)をbytes型に相互に変換できるのは分かり易いです。```int()```  や ```bytes()``` で cast するだけです。

```console
In [15]: aaa = [1,2,3,4,5,255]
In [16]: bytes(aaa)
Out[16]: b'\x01\x02\x03\x04\x05\xff'
In [25]: list(bytes(aaa))
Out[25]: [1, 2, 3, 4, 5, 255]
```

ただし、整数値は0から255の間の整数値に限られます。

```Python
In []: aaa = [1,2,3,4,5,256]
In []: bytes(aaa)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-18-3b250851e608> in <module>
----> 1 bytes(aaa)

ValueError: bytes must be in range(0, 256)
```

### １６進数で表記

0xff と書くとint 型になります。bytes 型にするには ```b'\xff```と書きます。

bytes型の変数は、リストで参照するように [ ] でインデックスを指定して参照することができます。

```Python
In []: b1 = b'\xaabbcc'
In []: type(b1)
Out[]: bytes
In []: b1[0]
Out[]: 170
In []: hex(b1[0])
Out[]: '0xaa'
```

以下のように書いたら、変数で整数値になります。

```
In [15]: i1 = 0xaabbcc
In [16]: type(i1)
Out[16]: int
In [17]: i1
Out[17]: 11189196
```

当然、これを [ ]　で参照することはできません。

```Python
In [18]: i1[0]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-18-9726669fc462> in <module>
----> 1 i1[0]

TypeError: 'int' object is not subscriptable
```

これをbytes 型にするには、to_bytes で変換する必要があります。endian を指定します。

```Python
In [21]: i1.to_bytes(3, 'little')
Out[21]: b'\xcc\xbb\xaa'
In [22]: i1.to_bytes(3, 'big')
Out[22]: b'\xaa\xbb\xcc'
In [27]: i1.to_bytes(3,'big')[0]
Out[27]: 170
```

### bytes 型とstr型

これはdecode/encode するだけです。文字コードは必要な時に指定します。

```
In [31]: "こんにちは".encode()
Out[31]: b'\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf'
In [32]: b2 = "こんにちは".encode()
In [33]: b2.decode()
Out[33]: 'こんにちは'
```

## int型とstr型(２進数、１６進数表記)

話は前後しますが、整数値は２進数や１６進数表記の文字列に変換できます。

```
In [37]: hex(100)
Out[37]: '0x64'
In [38]: bin(100)
Out[38]: '0b1100100'
```

一方で、コードに直接書けばint 型になります。

```
In [39]: i3 = 0x64
In [40]: i3
Out[40]: 100
In [41]: i4 = 0b1100100
In [42]: i4
Out[42]: 100
```

### import struct

そして、最後に、float を含めて連続していろいろつまっているbytes には unpack で全てdecode させてしまう、という、とても便利な関数unpack が用意されています。素直に、docs のexample を読むのが分かり易いです。

https://docs.python.org/ja/3.9/library/struct.html#examples

このunpack のおかげで、かなりコードの長さが短くなった気がします。


# まとめ

bytes型で入ってくるデータは、適切な処理をすることで所望の読み方をすることができた。
あと少ししたら、どうせすぐ忘れてしまうので、メモしました。TODOは今のところ無しかな。
(2021/06/30)
GOKI2バージョンアップしました。

表題の通りです。

GOKI2.0.0.9
https://github.com/Halo1234/Avalanches/blob/master/release/2.0.0.9/Avalanches.zip?raw=true

今回から吉里吉里２と吉里吉里Zでソースを統合しました。

そしてさらにSLGを作成できるように環境整備することとしました。
まだ構想もなにもありませんが気長に作っていきたいと思います。
CKEditor エラー「Uncaught TypeError: Cannot read property 'unselectable' of null」の解消

Every Qiita #1
のんびり独学初学者の毎日投稿チャレンジ 1日目
今回は・・・
自作コミュニティアプリ開発でリッチテキストエディタを実装した時の備忘録です。

##Uncaught TypeError: Cannot read property 'unselectable' of null
```php5
 <form action="{{ route('question.store') }}" method="post" accept-charset="utf-8">
   @csrf
   <textarea id="editor" name="ckeditor"></textarea>
   <input class="btn btn-primary" type="submit" name="question_submit" value="質問確認画面へ">
 </form>
 <script>
   CKEDITOR.replace("editor", {
     uiColor: "#EEEEEE",
     width:700,
     height:600,
   });
 </script>
```
上記コードだとscriptタグないが先に読み込まれプロパティがないと言われている？
##[解消方法]scriptタグの読み込みを遅らせてみる
```php5
      <form action="{{ route('question.store') }}" method="post" accept-charset="utf-8">
        @csrf
       <textarea id="editor" name="ckeditor"></textarea>
       <input class="btn btn-primary" type="submit" name="question_submit" value="質問確認画面へ">
      </form>
      <!-- scriptがページを読み込む前に発動するため、一定時間を置いて起動させる -->
      <script>
        setTimeout(function(){
            CKEDITOR.replace("editor", {
            uiColor: "#EEEEEE",
            width:700,
            height:600,
           });
         },100);
      </script>

```
とりあえずエラーは解消できたとさ〜

##追記2021/7/3
scriptタグにtype="module"を指定すると最後に読み込まれるそうです！上記のやり方よりも簡単ですね・・・
Matrice300RTKとManifold2のUSB接続時の内部デバイス名の固定化

##目的
Matrice300RTK(M300)とManifold2をUSBケーブルで接続する際に順番やタイミングよってManifold2(ubuntu16.04)内でのUSBデバイス名が想定したものにならないことがあり、DJI Onboard SDK(OSDK)やOSDKを使用したプログラムがエラーになることがあるため、USBデバイス名を固定する。


##使用機器
* DJI Matrice 300 RTK
* Manifold2シリーズ(初期インストール時のubunu16.04を想定。もしくは他Ubuntu16.04を搭載したPC)
* USBシリアル変換ケーブル(UARTをUSBに変換するケーブル。Amazon等で購入)
* デュアルUSBケーブル(A-AタイプUSBケーブル。M300に同梱)

##前準備
OSDKを使用するためにDJIが用意したドキュメントを元に機器同士を接続する

M300とManifold2の接続についての説明(DJIのドキュメントへリンク)
https://developer.dji.com/document/1bb1b2dc-9694-4d6b-ad43-fa69c5a10400


##USBデバイス情報確認
USBシリアル変換ケーブル、デュアルUSBケーブルだけをManifold2を接続した場合下記のように認識される。
* シリアル変換ケーブルデバイス名： /dev/ttyUSB0
* デュアルUSBケーブルデバイス名： /dev/ttyACM0
※順番やタイミング、その他のUSB機器を繋いだ場合、/dev/ttyUSB1や/dev/ttyACM1と認識される

上記のデバイス名で認識している状態で、それぞれのidVendorとidProductを調べる
調べるコマンド


* シリアル変換ケーブル(/dev/ttyUSB0と認識している場合)

```bash
udevadm info -a -p $(udevadm info -q path -n /dev/ttyUSB0)
```
実行時の一部キャプチャ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164731/d10c70c4-528d-1016-f7f1-65364f04b667.png)


* デュアルUSBケーブル(/dev/ttyACM0と認識している場合)

```bash
udevadm info -a -p $(udevadm info -q path -n /dev/ttyACM0)
```
実行時の一部キャプチャ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164731/1d528a7e-e827-90c9-1613-fe6b8eeeb2d6.png)


上記コマンドを実行しlessやgrepで確認


##デバイス名固定用設定ファイル作成
前述したコマンドで確認したidVendorとidProductを元に設定ファイルを作成する

* シリアル変換ケーブル用

```/etc/udev/rules.d/98-USBSerial.rules
KERNEL=="ttyUSB*", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="ttyUSBSerial"
```

* デュアルUSBケーブル用

```/etc/udev/rules.d/99-ACMDJI.rules
KERNEL=="ttyACM*", ATTRS{idVendor}=="2ca3", ATTRS{idProduct}=="001f", SYMLINK+="ttyACMDJI"
```

上記のファイルを作成したあとに該当するUSBを刺すとSYMLINKで指定した名前でシンボリックリンクが張られその名前でUSBデバイス名で使用できるようになる。

* 別パターン(上記の2つのファイルを1つにまとめることも可能)

```/etc/udev/rules.d/99-USBDJI.rules
KERNEL=="ttyUSB*", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="ttyUSBSerial"
KERNEL=="ttyACM*", ATTRS{idVendor}=="2ca3", ATTRS{idProduct}=="001f", SYMLINK+="ttyACMDJI"
```

##(おまけ)OSDKサンプルプログラム用設定およびファイル
####OSDKサンプルプログラム設定ファイル
```Onboard-SDK/build/bin/UserConfig.txt
app_id : abcdefg(DJIから取得したもの)
app_key : abcdefghijkemlasdfoajsdofijsadpofiajsdpfijasdfpiajspofdij(DJIから取得したもの)
device : /dev/ttyUSBSerial
baudrate : 921600 (DJI Assitant2で設定したものと合わせる)
acm_port : /dev/ttyACMDJI
```

####DJI Assitant2 for Matriceの設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164731/fa44cad1-117f-6673-2223-9efad83717a4.png)



----
https://qiita.com/official-events/d523df99d6479293ffa7
Windowsでポート8080を調べてプロセス終了する

###環境
Windows10
SpringBoot 2.5.2

###エラーログ

```
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-06-30 22:16:21.436 ERROR 8536 --- [  restartedMain] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Web server failed to start. Port 8080 was already in use.

Action:

Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.

```


###8080を使用しているプロセスを終了する

ちょっとしらべたらLinuxコマンドは出てくるけど、Windowsはあまり出てこなかったのでメモしときます。



コマンドプロンプトで以下のコマンドを実行

```:調べるとき
$ netstat -nao | findstr 8080
  TCP         0.0.0.0:8080           0.0.0.0:0              LISTENING       25952
  TCP         [::]:8080              [::]:0                 LISTENING       25952
```

最後の25952がPIDなので、終了させる

```:終了するとき
$ taskkill /f /pid 25952
成功: PID 25952 のプロセスは強制終了されました。
```
ダイジェスト認証　 #2 response="XXX"の導出

[ダイジェスト認証　 #1 Apache設定～動作確認](https://qiita.com/sgtrducky/items/8ab6d737d4af50c82042)に続きまして。
HA1（「ユーザ名:レルム：パスワード」のハッシュ値）が何らかの形で漏洩しているという前提で、ブラウザにユーザ・パスワードを入力することなく、response="XXX" の部分を算出、Webプロキシでリクエストを編集して認証を突破しよう、という「CTFの練習問題」的な文脈から本件検証・確認を行っております。

# 実機での確認動作
前回記載の通り、要「ダイジェスト認証」パスへの初回リクエストに対して、サーバから以下のレスポンス（改行を入れています）。

```
WWW-Authenticate:
Digest realm="digest",
nonce="jeqPGvfFBQA=9e2e2d4c04ea2ad4758a1129484608c9e8abea85",
algorithm=MD5,
stale=true,
qop="auth"
```
こちらに対してブラウザで正しいユーザ・パスを入れることで生成されたリクエスト（同上）。

```
Authorization:
Digest username="digest_user",
realm="digest",
nonce="jeqPGvfFBQA=9e2e2d4c04ea2ad4758a1129484608c9e8abea85",
uri="/digest/",
algorithm=MD5,
response="e6af4f81fa87ccde2bc4769ee237eea2",
qop=auth,
nc=00000001,
cnonce="10057899296509bc"
```

# response="XXX" 導出仕様
[Digest access authentication](https://en.wikipedia.org/wiki/Digest_access_authentication)から読み取るに（algorithm=MD5,qps=authの場合）


> HA1 = MD5(username:realm:password)

> HA2 = MD5(method:digestURI)

> response = MD5(HA1:nonce:nonceCount:cnonce:qop:HA2)


前回の記載の通り、
ユーザ：レルム：パスワード＝digest_user:digest:password
ですので、HA1は

```
# echo -n "digest_user:digest:password" | md5sum
46328f2142603a1d167a1a19de5210bf
```
HA2は

```
# echo -n "GET:/digest/" | md5sum
9942091bc79111e32fecde3962416017
```

そうすると上掲のnonce,cnonce,qop,ncと合わせて

```
# HA1=46328f2142603a1d167a1a19de5210bf
# HA2=9942091bc79111e32fecde3962416017
# nonce=jeqPGvfFBQA=9e2e2d4c04ea2ad4758a1129484608c9e8abea85
# cnonce=10057899296509bc
# qop=auth   
# nc=00000001
```

response="XXX"は

```
# echo -n "${HA1}:${nonce}:${nc}:${cnonce}:${qop}:${HA2}" | md5sum
e6af4f81fa87ccde2bc4769ee237eea2  -
```

ブラウザが導出した（＝認証OKとなった）response="XXX"と同値を導出することができました。
HA1がわかる（何らかの形で漏洩した）という前提では、サーバから返されたnonce等の値により認証をパスできるresponse="XXX"を導出できることを改めて確認しました。

いったん完了とはしますが、

- 認証パス後のリクエスト、レスポンスヘッダ
- サーバがレスポンスしたnonceの扱い
- nonceCount? qop?
- httpサーバ実装による差異

等、可能であれば追記をしたいと考えております。

2021年06月30日　初版
SpringBoot2.5.2でGoogleAPIのOAuth2のブラウザリダイレクトを自動的にしたい

###自動的に認証ページが開かない

SpringBootでGoogleAPIを使用しているページにアクセスするときに、コンソールに下記のようなメッセージが現れる。

```
Please open the following address in your browser:
https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=....
```

わざわざコンソールを確認して、URLをコピってブラウザに貼って・・・

いや、自動的に開いてよ！ってなったときに調べました。


###mainメソッドを変更しないといけない！！

初めてこんなところいじりましたけど。

参考にしたサイトはこちら。
https://github.com/googleapis/google-api-java-client/issues/1119

>
problem occurred because of headless system of spring boot,
headless system's can't open browser
so use this below code to set headless false in spring boot
>
public static void main(String[] args) {
SpringApplicationBuilder builder = new SpringApplicationBuilder(App.class);
builder.headless(false).run(args);
}

とありました。

headlessについてはまだ調査してませんが、とりあえずheadlessをfalseにせなあかんらしい。

ちなみに、Appの部分はmainメソッドがあるクラス名を入れなあかんです。

「〇〇Application」とかだと思われる。

とりあえずこれで自動的にブラウザがリダイレクトページを開いてくれるようになりました！！

すでに認証は手動でやっていたので、

```
Received verification code. You may now close this window.
```

このページが勝手に開くようになりました！！！やったーワン！！

（これだけでめっちゃ調べるのに時間がかかった。。。）
CSSだけで作るモーフィング

## これは何

- タイトル通りですが、あくまで「なんちゃってモーフィング」です
    - こんなものが作れます

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/48d57075-70ab-b23a-67fa-7b8efa3659a0.gif)

## そもそもモーフィングとは？

[Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%BC%E3%83%95%E3%82%A3%E3%83%B3%E3%82%B0)より引用。

> モーフィング（morphing）とは、映画やアニメーションの中で使用されるSFXの1つで、コンピュータグラフィックスの手法の1つでもある。

> ある物体から別の物体へと自然に変形する映像をみせる。これはオーバーラップを使った映像のすり替えとは異なり、変形していく間の映像をコンピュータによって補完して作成する。変身・変化を意味する単語「メタモルフォルシス(metamorphosis)」の中間部分から命名されたという説と、move(移動)+morphology(形態) の合成語であるとする説がある。

要は、ある形状からある形状へ、なめらかに変化していくイメージです。

## 実際のコード

今回の例に必要なコードはこれだけです。

```html:index.html
<div class="wrapper">
  <div class="mark"></div>
</div>
```

`css:style.css
.wrapper {
  background-color: #eee;
  display: grid;
  place-items: center;
  height: 400px;
  width: 400px;
}

.mark {
  background-color: #55c500;
  clip-path: polygon(0 100%, 50% 0, 50% 0, 50% 0, 50% 0, 100% 100%, 100% 100%, 100% 100%, 85% 100%, 15% 100%, 0 100%, 0 100%);
  display: inline-block;
  height: 300px;
  transition: all 0.2s ease-in-out;
  width: 300px;
}

.wrapper:hover > .mark {
  clip-path: polygon(33% 0, 33% 41%, 60% 0, 100% 0, 59% 51%, 100% 100%, 60% 100%, 41% 67%, 33% 67%, 33% 100%, 0 100%, 0 0);
}
`

### clip-pathを使う

CSSの`clip-path`を使うのがポイントです。

あまり馴染みがないかもしれないので[MDN](https://developer.mozilla.org/ja/docs/Web/CSS/clip-path)より引用。

> clip-path は CSS のプロパティで、要素のどの部分を表示するかを設定するクリッピング領域を作ります。具体的には、領域の内部の部分は表示され、外側の部分は非表示になります。

デザイナー相手なら「クリッピングマスクと同じです」といえばだいたい想像つくと思います。

これと`:hover`と`transition`を組み合わせると、マウスカーソルを乗せた瞬間にパスの形が変わるのでモーフィングっぽく見えます。

ポイントは、カーソルを乗せる前後でパスの頂点の数を変えないことです。
そのため三角形を作るパスでも頂点を12個用意しています。

最後にもう一度

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/48d57075-70ab-b23a-67fa-7b8efa3659a0.gif)
SSHで接続先のサーバでコマンドを実行、SCPで接続先のファイルをダウンロード、SCPで接続先にファイルをアップロード

実行前に接続先のサーバで「鍵認証のユーザ」を作成しておく必要があります。

## ■設定

```bash
### 踏み台サーバの設定
HOST1=192.168.1.100
PORT1=22
USERID1=user1
# shellの実行サーバのパス
FILE1=/tmp/server_rsa

### コマンド実行/ファイルのダウンロードおよびアップロードをするサーバの設定
HOST2=192.168.1.101
PORT2=22
# 踏み台と同じ鍵ユーザを作成している前提で同じIDを使用
USERID2=user1
# shellの実行サーバのパス
FILE2=/tmp/server_rsa

```

## ■接続先のサーバでコマンドを実行

```bash
CMD="echo 123"

ssh -o "StrictHostKeyChecking=no" -p ${PORT2} -i ${FILE2} ${USERID2}@${HOST2} "${CMD}"
```

## ■踏み台サーバを経由して接続先のサーバでコマンドを実行

```bash
CMD="echo 123"

# 踏み台サーバ
PROXY_CMD="ssh -W %h:%p -o \"StrictHostKeyChecking=no\" -i ${FILE1} ${USERID1}@${HOST1} -p ${PORT1}"

# ※「-oProxyCommand='${PROXY_CMD}'」以外に違いはありません
ssh -o "StrictHostKeyChecking=no" -oProxyCommand='${PROXY_CMD}' -p ${PORT2} -i ${FILE2} ${USERID2}@${HOST2} "${CMD}"
```

## ■接続先のサーバからファイルをダウンロード

```bash
PATH_LOCAL="."
PATH_SERVER="/tmp/test.log"

# 接続先のサーバの「/tmp/test.log」を現在のディレクトリに保存
scp -p -C -P ${PORT2} -o "StrictHostKeyChecking=no" -i ${FILE2} ${USERID2}@${HOST2}:${PATH_SERVER} ${PATH_LOCAL}
```

## ■踏み台サーバを経由して接続先のサーバからファイルをダウンロード

```bash
PATH_LOCAL="."
PATH_SERVER="/tmp/test.log"

# 踏み台サーバ
PROXY_CMD="ssh -W %h:%p -o \"StrictHostKeyChecking=no\" -i ${FILE1} ${USERID1}@${HOST1} -p ${PORT1}"

# ※「-oProxyCommand='${PROXY_CMD}'」以外に違いはありません
scp -p -C -P ${PORT2} -oProxyCommand='${PROXY_CMD}' -o "StrictHostKeyChecking=no" -i ${FILE2} ${USERID2}@${HOST2}:${PATH_SERVER} ${PATH_LOCAL}
```

## ■接続先のサーバにファイルをアップロード

```bash
PATH_LOCAL="/tmp/test.conf"
PATH_SERVER="/tmp/test/aaa.conf"

# 「/tmp/test.conf」を接続先のサーバの「/tmp/test/aaa.conf」に保存
scp -p -C -P ${PORT2} -o "StrictHostKeyChecking=no" -i ${FILE2} ${PATH_LOCAL} ${USERID2}@${HOST2}:${PATH_SERVER}"
```

## ■踏み台サーバを経由して接続先のサーバにファイルをアップロード

```bash
PATH_LOCAL="/tmp/test.conf"
PATH_SERVER="/tmp/test/aaa.conf"

# 踏み台サーバ
PROXY_CMD="ssh -W %h:%p -o \"StrictHostKeyChecking=no\" -i ${FILE1} ${USERID1}@${HOST1} -p ${PORT1}"

# ※「-oProxyCommand='${PROXY_CMD}'」以外に違いはありません
scp -p -C -P ${PORT2} -oProxyCommand='${PROXY_CMD}' -o "StrictHostKeyChecking=no" -i ${FILE2} ${PATH_LOCAL} ${USERID2}@${HOST2}:${PATH_SERVER}"
```

## 参考
https://qiita.com/error484/items/05fc4113c1aa11db14cc
PHPのコールバック色々

### 無名関数

オブジェクトのメソッドをコールバックとして使いたい時、無名関数を使って次のように書くことが多いです。

```php
$service = new Service();

array_map(function($item) use ($service) {
    return $service->func($item);
}, $array);
```

### アロー関数

php7.4からはアロー関数という構文が追加され、もう少し楽に書くことができます。
アロー関数は親スコープの変数を自動でバインドするので、無名関数と違って`use`を使う必要がありません。

```php
$service = new Service();

array_map(fn ($item) => $service->func($item), $array);
```

### 配列

さらに、PHPのならではの書き方としてこのような書き方もできます。0番目の要素にオブジェクト、1番目の要素に関数名を入れた配列は、PHPでは`callable`として扱われ、関数として呼び出すことができるのです。

```php
$service = new Service();

array_map([$service, 'func'], $array);
```

```php
is_callable([$service, 'func']); // true
[$service, 'func']($param); // 呼び出せる
```

クラスの静的関数を呼び出すだけなら、インスタンス化すら必要ありません。

```php
array_map([Service::class, 'func'], $array);
array_map('NAME\SPACE\Service::func', $array);
```

配列を使う方法は他の言語ではあまり見ないため、~~これだからPHPはクソと言われかねません~~使用する際はチームメンバーに確認を取るなど、用法容量を守って使いましょう。
Node.jsのテストフレームワーク比較 2021

# はじめに
Node.jsでアプリ開発をするにあたり、2021年現在で使用するのが良さそうなテストフレームワークについて調査しました。
2021/5/29時点での情報です。

# テストフレームワーク比較表
調査したテストフレームワークは以下の３つです。
概要については、[こちらの記事](https://postd.cc/a-complete-guide-to-testing-javascript-in-2017/)を参考にさせていただきました。
推奨は、調査結果から使うのが良さそうかどうか私が判断した項目です。

|項目名              |概要|npmダウンロード数|推奨|URL|
|:------------------|:------------------|:------------------|:------------------|:------------------|
|Jest|・テストに必要な機能をほぼ全て網羅している<br>・テスト速度が速く、大規模プロジェクトのテストにおいても有効|9,847,324|◎|https://jestjs.io/ja/|
|Mocha|・アサーション機能がないため、chaiなどのアサーションツールと併用する必要がある<br>・別のライブラリも使用するのでセットアップが少し難しい<br>・他のライブラリを選択できるという意味で柔軟性がある|4,237,700|△|https://mochajs.org/|
|Jasmine|・テストに必要な機能をほぼ全て網羅している|1,632,876|△|https://jasmine.github.io/|


# ダウンロード数比較グラフ
参考サイト
https://www.npmtrends.com/jest-vs-mocha-vs-jasmine
![node_test_npmtrends.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539406/4dc6122f-b66d-9a44-fe03-3eb15c3acd57.png)


# 結論
最も使用されているJestを使うのが良さそうです。
複数行のリテラル ― J 言語入門

文字列リテラル `'...'` は改行を含むことができません。`,` と `LF` を使って繋げる方法はありますが、何行にもわたる文字列を書くには不便です。

explicit definition の一種を使うことで、複数行の文字列リテラルを書くことができます。

# noun define

`noun define` は、終端の `)` の手前までを文字列として返します。ヒアドキュメントやヒア文字列のような機能です。

`noun define` の直後の改行は文字列に**含まれません**が、`)` の前の改行は文字列に**含まれます**。改行は全て LF です。

```j
   text=: noun define
abcde
あいうえお 漢字 😀
) ...
)
   text
abcde
あいうえお 漢字 😀
) ...

   text -: 'abcde' , LF , 'あいうえお 漢字 😀' , LF , ') ...' , LF
1
```

他の explicit definition とは異なり、どんな文字を含んでいても構いません。ただし、終端の `)` の行は explicit definition の構文通り他の文字を含んではいけません。逆に、`)` と空白のみからなる行は**必ず終端と見なされる**ので、注意しましょう。

# 複数行コメント

`noun define` は `)` までの文字列を返しますが、その値を単に無視すれば**複数行コメント**として使うことができます。それをするための verb が標準ライブラリに定義されています [^1]。

`Note` (monad) は複数行コメントとして機能します。引数には何を渡しても構いません。

```j
Note''
ここがコメント。

改行も含んでよい。
)
```

explicit definition を丸ごとコメントアウトするのにも使えます。

```j
Note''
box=: monad define
   <y
)
```

`Note` (dyad) は単一行バージョンですが、実体は `[` と同じです。

```j
   1 % 0 Note 'エラーは発生しない'
_
```

---

\[ 前 : [explicit definition](https://qiita.com/unsigned-wrong-wrong-int/items/0bc6385d4e640b097651) \] \[ [目次](https://qiita.com/unsigned-wrong-wrong-int/items/e15a87999cedfc6b9ced) \] \[ 次 : [define の実体](https://qiita.com/unsigned-wrong-wrong-int/items/968640fb004867c9dcce) \]

[^1]: 標準ライブラリはデフォルトで使えるので、インポートなどは必要ありません。
explicit definition ― J 言語入門

# tacit definition

フックやフォークなどの、noun 以外の値を作る字句の並びを **train** と呼び、train を使った定義を **tacit definition** (暗黙の定義) と言います。

```j
average=: +/ % #
```

tacit definition は、シンプルな計算を定義するのに向いていますが、複雑なアルゴリズムなどを記述するのは困難です。

# explicit definition

**explicit definition** (明示的な定義) は、具体的な処理を記述して verb などを定義する機能です。

上の `average` の例を explicit definition で表現すると、以下のようになります [^1]。

```j
average=: monad define
   sum=. +/y
   count=. #y
   sum % count
)
```

まず 1 行目を見てみましょう。`monad define` とありますが、これが explicit definition を開始します。文字通り monad を定義しています。

5 行目の **`)` まで**が、explicit definition の本体になります (*この `)` に対応する `(` はありません*)。

explicit definition の内部では、**ローカル変数**を使うことができます。引数 `y` もローカル変数です。ローカル変数へ代入するときは、`=.` を使います。

複数の文 (sentence) を続けて実行するには、改行で区切って並べます。*1 行に複数の文を書いたり、1 つの文を複数行にわたって書くことはできません。***最後に実行した文の結果**が、verb の返す値になります。

# 種類

verb に加えて modifier の定義もできます。

|定義方法|内容|
|---|---|
|`monad define`|monad|
|`dyad define`|dyad|
|`verb define`|monad と dyad 両方の使い方ができる (*dual-valence*) verb|
|`adverb define`|adverb|
|`conjunction define`|conjunction|

# verb

`monad define` の場合は引数 `y`、`dyad define` の場合は引数 `x` と `y` が定義されています。

```j
   negate=: monad define
      -y
   )
   negate 1
_1
   subtract=: dyad define
      x - y
   )
   3 subtract 1
2
```

`verb define` の定義部分は、monad バージョンと dyad バージョンを **`:` で区切って**書きます。順番は `monad`・`dyad` の順です。

```j
   minus=: verb define
      NB. monad
      -y
   :
      NB. dyad
      x - y
   )
   minus 1
_1
   3 minus 1
2
```

# modifier

`adverb define` では、`u` か `m` が被演算子を表します。verb の被演算子を受け付ける場合は `u` を、noun の被演算子を受け付ける場合は `m` を使います。

modifier は、noun, verb, adverb, conjunction のいずれの値も返すことができます。

```j
   NB. u を 2 回適用する verb を返す
   twice=: adverb define
      u@u
   )
   0&,twice 1
0 0 1
```

```j
   NB. 文字列 m のバイト値 (noun) を返す
   bytes=: adverb define
      a. i. m
   )
   'Text'bytes
84 101 120 116
```

被演算子の種類が一致しない場合 (間違った使い方をした場合) はエラーになります。

```j
   3 twice
|domain error
|   u    @u
   +bytes
|value error
|   a.i.    m
```

verb を返す modifier の場合、`x`・`y` を使って verb の定義をそのまま書くこともできます。`verb define` と同様に `:` が monad・dyad を区切る役割をします。この方法で定義するときは、noun を返す必要があります。

```j
   NB. 引数と u の結果を返す
   show=: adverb define
      y ; u y
   :
      x ; y ; x u y
   )
   -show 1
┌─┬──┐
│1│_1│
└─┴──┘
   3 -show 1
┌─┬─┬─┐
│3│1│2│
└─┴─┴─┘
```

`conjunction define` も adverb と同じように定義できます。右の被演算子は `v` (verb の場合) または `n` (noun の場合) です。

# 注意点

explicit definition には、いくつか注意するべき点があります。

まず、explicit definition を**入れ子にすることはできません**。これには多分歴史的な事情もあると思うのですが、代替の構文 [^2] があるので困ることはありません。

もう一点、区切りや終端を表す `:` と `)` の行にはスペース (インデント) は入れてもいいですが、他の文字を含んではいけません。コメントもダメです [^3]。

---

\[ 前 : [フックとフォーク](https://qiita.com/unsigned-wrong-wrong-int/items/03f1b408fd89bdbc18ff) \] \[ [目次](https://qiita.com/unsigned-wrong-wrong-int/items/e15a87999cedfc6b9ced) \] \[ 次 : [複数行のリテラル](https://qiita.com/unsigned-wrong-wrong-int/items/4f63903f7ae00b145ee6) \]

[^1]: 説明のため あえて冗長な書き方をしています。
[^2]: この記事には書ききれないので、改めて紹介しようと思います。
[^3]: その位置にコメントを書くことはないと思いますが、念のため。