OmniAICreator/Qiita-1.07M huggingface dataset:
terminalから英単語を検索する

# はじめに
terminalから全ての動作を完結させたいというのは，どんなプログラマーでも思っていることと信じたい．
(emacsは使えないのでvscode派なのは内緒)

ということで，rubyでterminalから英単語の意味を調べる.

# プログラム本体

## 旧バージョン

```ruby:dic.rb
system "curl -s https://ejje.weblio.jp/content/#{ARGV[0]} | grep 主な > ~/dic/tmp.txt"

File.open("#{Dir.home}/dic/tmp.txt", "r") do |f|
  f.readlines[0].match(/.*<td class="content-explanation .*\">(.*)<\/td>.*/)
  puts $1
end

system "rm ~/dic/tmp.txt"

```

1行目:システムコールでcurlを使用．[Weblio英和辞典](https://ejje.weblio.jp/)を使用させていただいている．引数をurl内で展開して，grepで絞り込んでいる．それを，~/dic/tmp.txtに書き込む．

2行目:先ほどのファイルを読み込みモードで開く.Fileメソッドでは"~"が使えなかったので，Dir.homeとしている．



3行目:ファイルを読み込み，正規表現を用いて和訳部分を抽出．それを出力する．

最後に，ファイルを消去．

## 新バージョン 
@scivola さんよりコメントで指摘いただきました．ありがとうございます．

```ruby:dic.rb
result = `curl -s https://ejje.weblio.jp/content/#{ARGV[0]}`
puts result.match(%r{主な.*<td class="content-explanation .*">(.*)</td>}).to_a[1]

```

こんなにも簡潔に記述できるなんて!
まだまだ，学ぶことがたくさんあると痛感しました．


# aliasを追加

```bash:config.fish
alias dic='ruby ~/dic/dic.rb'
```

# 使用例
```bash
~ 
❯❯❯ dic dog
犬、(イヌ科の動物の)雄、雄犬、くだらない人間、魅力のない男、醜い女、「ぶす」、やつ、くだらないもの、失敗作
```

単語はもちろん

``` 
~ 
❯❯❯ dic takecareof
…を世話する、大事にする、…に気をつける、…を引き受ける、を処理する、切り抜ける、自分のことは自分で始末する、をやっつける、殺す
```

連語もok

```
~ 
❯❯❯ dic 物理
natural philosophy、physics
```

逆に英訳もok
DynamoDB + AppSync設計パターン(備忘録)

# はじめに
プロジェクトでDynamoDB + AppSyncを利用したサービスの設計をしたので、その時のハマりポイント等を備忘録として残します。

## DynamoDB設計の備忘録
DynamoDBに対してScanすることは避ける。
なぜ？？？ → テーブルを総ナメにする為。
### 設計ポイント
**1. 関連するデータをまとめる**
DynamoDBはできるだけ、少ないテーブルを維持する必要がある。

**2. GSI(グローバル・セカンダリ・インデックス)を利用する**
GSIを利用すると、同一テーブルでPKを切り替えることができます。つまり、特定のGSIを作成することで、メインのテーブルでサポートできるクエリとは異なるクエリを有効にできるのです。**これがすごく使えます。**

**ユースケース** : 例えばoperation[query]を使用している前提で、SKを範囲指定し検索した結果をfeachしたい場合、メインのテーブルのPKに対し一意になるような値[例えばuuid等]を設定していると、通常の[query]で範囲検索をしfeachすることができません。その場合、テーブルにある他のカラムをPKとしたい時にGSIが利用できます。

### RDBMSとDynamoDBの違い
**RDBMS**
クエリの最適化は、スキーマ設計に依存しないので、正規化が重要です。

**DynamoDB**
よく使われるクエリを早く問い合わせできるようにスキーマを設計します。


## AppSyncにおけるスキーマ/リゾルバ設計の備忘録

### DynamoDBに対する操作ができるOperationの一覧
**GetItem**
Partation keyを条件として指定し、一件のアイテム取得

**PutItem**
１件のアイテムを書き込む

**Update**
1件のアイテムを更新

**Delete**
1件のアイテム削除

**Query**
Partation KeyとSort Keyの複合条件にマッチするアイテム群を取得

**BatchGet**
複数のプライマリキーを指定して、マッチするアイテム群を取得

**Scan**
テーブルを総ナメにする

**重要 : DynamoDBに対するQuery or Scanのオペレーションでは最大で1MBのデータしか取得できない。**
その為、Scanを利用してしまうと、項目内のデータサイズによっては全て取得しきれない可能性がある(テーブル内データを総ナメにする為)。

* **では、どうするのか**
答えは、**Projectionの利用**です。  
DynamoDB は、デフォルトですべての項目属性を返します。すべての属性ではなく、一部の属性のみを取得するには、Projectionを使用します。

* **projectionは分かったけど、どう設定するのか**
まず、DynamoDB側でインデックスの設定を行います。
その際に[属性]という項目があるので、必要な項目のみ記載します。記載されない項目は、削ぎ落ちます。つまり、ここがインターフェースになるということです。

次にAppSync側の設定です。
Operationに[Query]を利用している場合、リゾルバ内のオプション項目[select]を使用し、
ALL_PROJECTED_ATTRIBUTES]を設定します。
ALL_PROJECTED_ATTRIBUTESとは、インデックスにクエリを実行する場合のみ使用できます。インデックスに投射されたすべての属性を取得します。つまり、これで、見たい項目のみに絞り込みができます。

[設定例]

```
"select" : "ALL_PROJECTED_ATTRIBUTES"
```


## おまけ (AppSyncに対する認証はどうするべき・・)
いくつかある認証方式の中で、よく使われるものを抜粋

**[API_KEY認証]**
 
* **利用方法**
クライアント側に認証用のAPI_KEYを埋め込みApp Syncを利用します。

* **問題点**
API_KEYが発行されるとdefaultで7日後に有効期限が切れます。
API_KEYは、最大 365 日間有効に設定可能で、該当日からさらに最大 365 日、既存の有効期限を延長できます。
API_KEYは、パブリック API の公開が安全であるユースケース、または開発目的での使用が推奨されます。


**[AMAZON_COGNITO_USER_POOLS認証]**

* **利用方法**  
GraphQL オペレーションを送信するときに authorizaton ヘッダーで AWS AppSyncに送信します。

# 引用
[DynamoDB Projection](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html)  
[AppSync Projectionの利用](https://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/resolver-mapping-template-reference-dynamodb.html#aws-appsync-resolver-mapping-template-reference-dynamodb-query)
[Laravel 8] JetStreamは「laravel new」コマンドで楽々インストール

Laravel 8 が公開されました！（2020年9月上旬のことです）Laravel 8 では、認証機能パッケージに「Jetstream」が追加されました！

ちなみに、Laravel 8 系でも、今までのように認証機能作成の際に使用していた「Laravel/ui」パッケージを使用できます！選択する幅が増えたということで、自分にあった認証パッケージを選らんでくださいませ。

今回は、新しい認証パッケージである「Jetstream」をインストールするための紹介をしています。

## Laravelインストーラーで楽々インストール

本家の公式 [Jetstream](https://jetstream.laravel.com/) ドキュメントによると、インストール方法は2種類あり、`Laravel Installer を使用する`ケースと、`composerコマンドを打ち込んでLaravelプロジェクトを作成する`ケースがあります。今回はLaravel Installerを使用していきます。

## Laravel Installer でのインストール方法

まずは、composer を使ってLaravel Installerをインストールします。ちなみに、この「Laravel Installer」はLaravelのプロジェクト本体ではありません。インストーラですのでLaravelをインストールするためのプログラムです。

```
$ composer global require laravel/installer
```
Laravel Installerがインストールできました。この後、Laravelコマンドを使用できるように環境変数のPATHにLaravel Installerの場所を入力します。Windowsの場合は「システム環境変数」から自分のユーザー環境変数の「編集」をクリックして「新規」ボタンを押して、以下のようにLaravel Installerの場所を入力。

```
C:\Users\ユーザ名\AppData\Roaming\Composer\vendor\bin
```
実際に、Laravelコマンドが使用できるようになっているか、以下のコマンドでLaravel Installerのバージョンを確認してみてください。

```
$ laravel -v
```
バージョン情報が確認できたら、インストーラの設定は完了です。では、早速Laravel本体と一緒に認証パッケージのJetstreamをインストールしてみましょう。Jetstreamのインストールはプロジェクト名の後に `--jet` を付けてあげるだけです。

```
$ laravel new project-name --jet
```

インストール完了後、コマンド待ち状態になったら

```
$ php artisan migrate
```

をして準備完了！ようこそ、Jetstreamへ！(=ﾟωﾟ)ﾉ
Cypress: PCとSPで異なるテストを実行する

# Cypressの仕様

Cypressでは、UserAgentや環境変数などの設定を、テストの実行中に変更することはできません。(https://docs.cypress.io/api/cypress-api/config.html#Not-all-config-values-can-be-changed-at-all-times)

そのため、PCとSPなどUserAgentに応じて異なるテストを実行したい場合、UserAgentごとにテストファイルを分けてテストを実行するなどの工夫を行う必要があります。

そのような時、環境変数でUserAgentや実行するテストファイルの設定を上書きして切り替えられるような仕組みを用意すると便利です。

## cypress/plugins/index.js

設定の上書き処理は、`cypress/plugins/index.js`に記述します。


```js:PCとSPでテストを分ける例
module.exports = (on, config) => {
  const configOverride = {};

  if (config.env.device === 'sp') { // sp用の設定
    configOverride.userAgent = '< SPテスト用のUserAgent >';
    configOverride.testFiles = 'sp/**/*.*';
  } else { // pc用の設定
    configOverride.userAgent = '< PCテスト用のUserAgent >';
    configOverride.testFiles = 'pc/**/*.*';
  }

  return { ...config, ...configOverride };
};
```

上記のように設定の上書き処理を追加してあげることで、
PC用のテストファイルを`integration/pc`配下に、
SP用のテストファイルを`integration/sp`配下にまとめておくだけ、
`cypress run --env device=pc`でPCのテスト、
`cypress run --env device=sp`でSPのテストを実行できるようになります。

---

また、同じようにして、環境変数でテストを実行するURLを変更することもできます。

```js:テストを実行するURLを切り替える例
module.exports = (on, config) => {
  const configOverride = {};

  if (config.env.env === 'dev') {
    configOverride.baseUrl = '< 開発環境のURL >';
  } else if (config.env.env === 'prod') {
    configOverride.baseUrl = '< 本番環境のURL >';
  } 

  return { ...config, ...configOverride };
};
```

`cypress run --env env=dev`で開発環境でのテスト、
`cypress run --env env=prod`で本番環境のテストを実行できるようになりました。

このような感じで、`cypress/plugins/index.js`に、環境変数による設定の上書きをすることで、Cypressはとても便利になります。

皆さんもぜひ、`cypress/plugins/index.js`を上手に活用して、Cypressをより便利にしていきましょう！！

## 参考
https://docs.cypress.io/api/cypress-api/config.html#Not-all-config-values-can-be-changed-at-all-times
https://github.com/cypress-io/cypress/issues/2100
exif_imagetype()だけで画像かどうかを判別してはいけない

# はじまり
マイナーなWordPressプラグイン[Simple:Pressに脆弱性が見つかりました](https://blog.nintechnet.com/wordpress-simplepress-plugin-fixed-critical-vulnerabilities/)。認証無しでPHPスクリプトをアップロードして任意コード実行できる脆弱性なので致命的なものと言えます。

この記事の数日後、Qiitaで@satorunooshieさんの[PHPによる(複数)画像アップロード処理](https://qiita.com/satorunooshie/items/f9ff5a9c3ece45b5a6ce)という記事を目にすることになります。ここで2つの記事に関連性が見られたので、本稿を書こうと思います。

# 意外な落とし穴
問題となったSimple:Pressには、ファイルアップロード時に認証を回避できる脆弱性があったわけですが、それでもまだアップロードされたファイルが画像かどうかチェックする機構があれば、任意コード実行のような大きな問題にはならなかったはずです。
ただし、実際にはそのような機構が存在していたにもかかわらず、落とし穴があったため期待通りに機能していませんでした。

## exif_imagetype()の問題
Simple:Pressは画像であるかどうかを``exif_imagetype()``を使って判別しています。

```php
# check image file mimetype
$mimetype = 0;
$mimetype = exif_imagetype($_FILES['uploadfile']['tmp_name']);
if (empty($mimetype) || $mimetype == 0 || $mimetype > 3) {
	echo 'invalid';
	die();
}
```

@satorunooshieさんの記事においてもほぼ同様の処理を行っている部分があります。


```php
        $tempfile = $_FILES['photo']['tmp_name'];
        switch (@exif_imagetype($tempfile)) {
            case 1:
                $photo .= '.gif';
                break;
            case 2:
                $photo .= '.jpg';
                break;
            case 3:
                $photo .= '.png';
                break;
            default:
                header('Location: upload.php');
                exit();
        }
```

実はここに問題があり、``exif_imagetype()``は画像かどうかの判別が**「[画像の先頭バイトを読み そのサインを調べます](https://www.php.net/manual/ja/function.exif-imagetype.php)」**となっているため、画像に偽装した有害なファイルをアップロードすることが可能です。
（ただし、@satorunooshieさんのケースでは、拡張子を明示的に付与していることで、PHPスクリプトとしては実行できなくなっています。）

## 問題の検証
偽装したgif画像として、以下のようなテキストファイルをdummy.gifとしてuser_edit.phpにアップロードします。アップロードされた画像のURLにアクセスしても、画像としては無効なので表示できません。

```dummy.gif
GIF89a
<?php echo time();
```

ここで、アップロードされたファイルの拡張子を.phpに変更して、ウェブブラウザでアクセスすると、以下のように表示されます。この結果から、``exif_imagetype()``をすり抜けてPHPスクリプトをアップロードできることがわかります。
もしSimple:Pressのようにアップロード時のファイル名を利用するような場合は大変危険な状態となります。

```
GIF89a 1601392715
```
10秒でwordpress環境を作れる!Amazon Lightsailを使ってみた

## Amazon Lightsailとは
AWSが提供するVPSです。
タイトルでも触れているWordPress以外にもLAMP,Node.js,GitLab,Redmine等
事前に設定されたアプリケーションまたは開発スタックをクリックして起動できます。

### メリット
- 早く簡単にできる 
LightsailはおそらくAWSでwordpress環境を立ち上げるのに一番簡単なサービスです。

- 料金の見通しが立てやすい
[料金体系](https://aws.amazon.com/jp/lightsail/pricing/)は月額固定で非常にシンプルです。
データ転送枠を超えた場合はさらに課金されますが、超過分に関してもEC2等とほぼ同等の料金となっています。

- ドキュメントが易しい
Lightsailのドキュメントは[こちら](https://lightsail.aws.amazon.com/ls/docs/ja_jp/all)に
ありますが、他のAWSのサービスよりも初心者向けでわかりやすい印象を受けます。

### デメリット
- スケールしづらい
例えば、EC2のように$3.5のインスタンスで始めて、
後で$5のインスタンスに変更するということができません。
ただし、サーバのスペックを変更したいときはEC2に移行することで可能になります。

- 自由度が低い
他のAWSのサービスのように、柔軟に組み合わせて使うことはしづらいです。
カスタマイズ性を重視するなら従来のサービスを使うほうがいいと思います。

## 作ってみる
超簡単3ステップです。
### 1. インスタンスイメージを選択
![スクリーンショット 2020-09-28 20.14.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93882/4dbce298-9fb3-5110-ca5d-35c1eccfef0e.png)

SSHのキーペアをデフォルトのもの以外にするときはここで設定できます。

### 2. インスタンスプランを選択
![スクリーンショット 2020-09-28 20.15.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93882/36773424-ba95-0ae7-1773-b66e7e05a40d.png)

条件に合ったスペックを選択。

### 3. リソース名の設定
![スクリーンショット 2020-09-28 20.15.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93882/7edd122a-d96c-f783-5b6e-bef368ecb87b.png)

最後に名前を設定します。必要であればタグもここで設定します。
必要な設定後、「インタスンスの作成」ボタンを押すと、ホームに戻り作成中のインスタンスが表示されます。

10秒は正直盛りすぎかもしれませんが、名前さえ気にしなければ本当に最小1クリックでwordpress環境が完成します。

## 環境作成後
![スクリーンショット 2020-09-30 0.18.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93882/7a41c8c3-f260-7d4f-2c55-eaff95a0cfae.png)

インスタンスの詳細画面はこのようになっています。
この[Wordpress入門ガイド](https://lightsail.aws.amazon.com/ls/docs/ja_jp/articles/amazon-lightsail-quick-start-guide-wordpress)を見れば簡単にwordpressの設定を完了することができます。

## 本番に公開するサイトとして必要な設定
上記のステップでworpress自体は使えるようになりますが、本番運用するサイトとしては下記の設定が必要になるかと思います。

- 静的IPアドレス設定
- 独自ドメイン設定
- SSL対応

こちらはすべてLightsailのサービスでまかなうことができ、ハウツーも載っています。
(ドメインの取得はできないのでRoute53等で取得する必要があります。)

## まとめ
Lightsailはwordpressだけでなく、人気のアプリケーション環境が簡単に構築できます。
よろしければ参考にしてみてください。
VSCodeのターミナルをUbuntuにする設定方法

WindowsでVSCodeを触るにあたり、UbuntuをVSCodeに設定したのでその方法をまとめます。

#環境

* Windows10
* Ubuntu
* VSCode

#参考にさせていただいたもの

* [【Windows】VS Codeのターミナルをubuntuにする方法【WSL】](https://from-age35.com/799.html)

画像付きでとてもわかりやすいです。自分の環境だと少し方法が違ったので記事にしました。

* [Visual Studio Codeで日本語化する方法[Windows]](https://qiita.com/nanamesincos/items/5c48ff88a4eeef0a8631)

VSCodeの日本語化の設定をまとめてくださっています。

#Ubuntu設定
1. VSCodeの拡張機能で`WSL`と検索して`Remote - WSL`をインストール
2. VSCode左下画面にある歯車マークをクリックして`設定`を選択
3. `ターミナル`と検索
4. タブを`ユーザー`から`ワークスペース`に切り替える（ない場合はユーザー設定内にあるのでスキップ）
5. 下にスクロールして`Terminal > Integrated > Shell:Windows`を探す
6. `settings.jsonで編集`をクリックする
7. 以下のように編集する（パスの`user`の部分は各自のユーザー名に変更）

```
{
    "terminal.integrated.shell.windows": "C:\\Users\\user\\AppData\\Local\\Microsoft\\WindowsApps\\ubuntu.exe"
}
```
8.VSCodeを再起動してターミナルがWSLになっていることを確認

#終わりに
何か間違っている等のご指摘があればよろしくお願いします。
robot.txtってなに？

## 勉強前のイメージ

robot.txtってLBに入れたときの死活監視先のファイル的な存在のイメージ

## robot.txt について調べてみた

### robot.txtの概要

- `収集されたくないコンテンツをクロールされないように制御するファイル`
	- 検索エンジンのクローラーに自分のwebページにとって重要なコンテンツを中心にクロールさせることが出来る

### そもそもクローラーとは

- 検索エンジンの仕組みの中の一部
- 現在の検索エンジンは、ロボット型検索エンジンで、仕組みには以下がある。
	1. `クローラー` : インターネット上でWebサイトのページ情報を収集する
	2. `インデクサ` : 取得したコンテンツを解析しデータベースへ保存
	3. `クエリサーバ` : ユーザからの検索キーワードの結果ページを返す

### robot.txtの役割

- 検索エンジンが勝手にwebページの中身を収集する際、収集されるファイルを制御すること

### なぜファイルを制御する必要があるのか

クローリングする際(上記の仕組みでいうと`インデクサ`の部分で)、
webサイトの全体を取得した時、テスト運用中のページやまだ内容がないコンテンツがあると検索結果に表示させる価値が低いwebサイトと認識され、検索エンジンで検索した際上位に表示されにくくなる
なので、上位に表示されるようにするため(SEOという)にファイルの制御を行う

### robot.txtの書き方

#### クローラーの指定を行う

クローラには、Googlebot や Googlebot-Image など種類がある。
クローラーの指定を行う際の記述方法

- すべてのクローラーを指定

```
User-Agent:*
```

- Googleのクローラーを指定

```
User-agent:  Googlebot
```

### クロールの拒否を行う

クロールされるファイルの拒否を行う
拒否したいページや、ディレクトリのパスの記述方法

- ディレクトリの拒否

```
Disallow:  /test/
```

- ページの拒否

```
Disallow:  /test/test.html
```

- 全体の拒否

```
Disallow:  /
```

### クロールの許可を行う

クロールされるファイルの許可を行う
許可したいページや、ディレクトリのパスの記述方法
デフォルトで許可されているので、使う場面は少ないが
用途としては、ディレクトリの拒否を行った後、特定のファイルのみ許可を行いたい場合に記述する

- ページの許可

```
Disallow:  /test/
Allow:  /test/test.html
```

### サイトマップを知らせる

サイトマップとは検索エンジンにwebページの認識を促すことができるファイル
重要なファイルをクロールさせるために使用

```
Sitemap:http://test.com/sitemap.xml
```

## 勉強後のイメージ

最初の LBに入れたときの死活監視先のファイル的な存在のイメージ とは違い、
.htaccessのAllow,Deny見たいなイメージ。
webページの構成なども検索の順位に関わると知った。

## 参考

- [robots.txtとは？意味から設定方法まで詳しく解説](https://wacul-ai.com/blog/seo/internal-seo/seo-robots-txt/)
- [クローラーとは？SEOに必要な基礎知識とクローリングを最適化する方法](https://innova-jp.com/3711/)
- [クローラーとは／検索エンジンの仕組みをおさらい。クローラー対策とステータスコード](https://webtan.impress.co.jp/e/2009/03/27/4952)
- [robots.txtとは？書き方などわかりやすく解説](https://seolaboratory.jp/41315/)
Ubuntu 20.04.1 LTS で HDMI 音声出力ができなくなったときの解決策

## 症状
普段は自作パソコンを外部モニタにつないでUbuntuで運用。音声はHDMI経由でモニタから出力している。が、2~3日前から音声が出なくなった。SettingでSoundを確認したら、Output Device でHDMIが選択できない、というか出てこない。選択できるのはDigital Outputs(S/PDIF)のみ。ググると昔からよくあるトラブルみたい。情報が古かったり上手くいかなかった方法もあったりしたので、自分が解決できた方法を記録しておく。
![Screenshot from 2020-09-29 23-17-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321085/e90c1580-b895-9323-fdaf-cd64d5f24a37.png)

## 環境
パソコン: 自作パソコン
CPU: Ryzen5 3600
グラフィックボード: NVIDIA GeForce GTX 1660
OS: Ubuntu 20.04.1 LTS

## 参考サイト
[Ubuntu18.04にNVIDIAドライバーをインストール](https://qiita.com/kannkyo/items/c506437704cd62b31077)

## 解決策
というより参考サイトそのまんま。@kannkyo様ありがとうございます:bow_tone1:

### 1. `sudo ubuntu-drivers devices` でドライバーを確認

```bash

$ sudo ubuntu-drivers devices
== /sys/devices/pci0000:00/0000:00:03.1/0000:09:00.0 ==
modalias : pci:v000010DEd00002184sv000010DEsd00001324bc03sc00i00
vendor   : NVIDIA Corporation
model    : TU116 [GeForce GTX 1660]
driver   : nvidia-driver-435 - distro non-free
driver   : nvidia-driver-450 - distro non-free recommended
driver   : nvidia-driver-418-server - distro non-free
driver   : nvidia-driver-450-server - distro non-free
driver   : nvidia-driver-440-server - distro non-free
driver   : xserver-xorg-video-nouveau - distro free builtin
```
### 2. `sudo ubuntu-drivers autoinstall` でドライバーをインストール

```bash
$ sudo ubuntu-drivers autoinstall
```
そうすると自動でNVIDIAのドライバーがインストールされる

### 3. Settings の Sound で Output Device からHDMIを選択
これで無事HDMI経由での音声出力が可能になった。
![Screenshot from 2020-09-29 23-39-18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321085/38693974-d21f-5771-ed9e-e532fce8a58c.png)

いきなり音が出なくなったのは焦ったが理由がわからない。`sudo apt update` を頻繁にしてるからドライバーがアップデートされて不具合が生じたのか？何にせよNVIDIA のドライバーをインストールすれば解決したということで、良かった良かった。
UICollectionView must be initialized with a non-nil layout parameter

## なんか落ちる

`UICollectionView`をコードで追加したところ、`UICollectionView must be initialized with a non-nil layout parameter`エラーが。。。


```Swift
let collectionView = UICollectionView(frame: view.frame)
collectionView.delegate = self
collectionView.dataSource = self
view.addSubview(collectionView)
```


## 解決方法

コードで`UICollectionView`を追加するときは、`FlowLayout`をinit時に追加しなければならないらしい。

```Swift
let flowLayout = UICollectionViewFlowLayout()
flowLayout.itemSize = CGSize(width: 100, height: 100)
let collectionView = UICollectionView(frame: view.frame, collectionViewLayout: flowLayout)
collectionView.delegate = self
collectionView.dataSource = self
view.addSubview(collectionView)
```

圧倒的油断。
【phpMyAdmin】 「構造」で「主キー」を表示させたい

#### プルダウンに格納されていた「主キー」を表示させたかった ####

※「プルダウン、ドロップダウン、リスト、セレクト」など呼び名はさまざまですが、この場では「▼その他」の中から選択する一手間を省きたかった。
##### 初めてって大変 #####
分からないことだらけ。未知の世界。
だから参考にしている教材と同じ表示にしたいではないですか。
だって右も左も分からない全くの未経験ですもの。そこで、タイトル通り「主キー」を表示したかったのです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691238/b0ad18aa-5ca2-38d7-b664-3a7f74d1929c.png)
初心者な私はググり倒した。それでも出てこない。
ちなみに表示したいのはココ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691238/dd09eeeb-6912-3e90-0a4e-7595957b2a26.png)
そう、求めていた「主キー」です。これを表示させたかった。万が一の場合でも手数は少ない方が絶対いい（楽したいだけとも言う←
さてさて、もう前置きは十分だ。
はい！結論です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691238/46635d7c-fa5f-59c2-62fe-f1141791e272.png)
はい、どーん！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691238/e6ab4b7e-2c4e-5c26-4753-944161680da3.png)
表示されました！

--備忘録として
※MAMP使用者です
カスタムViewControllerのクラスを定義せずにxibだけでViewControllerを用意する

`xib`を使うとカスタムViewなどをGUIで指定しておいてコードで読み込むことで使うことができる。今回は、ViewControllerが必要だがロジックは必要がないときに、カスタムViewControllerのクラスを定義せずにxibだけでViewControllerを用意したいというケースにあたり方法を調査した。

## 具体的なケース

`NSPopover`を用いると下の画像のようなポップを簡単に作ることができる。
![スクリーンショット 2020-09-29 23.58.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67153/9f0744fb-6879-9885-633a-e524bd355156.png)
ポップの中身の指定にはViewControllerを指定すれば良い。

```swift
let popover = NSPopover()
popover.contentViewController = NSViewControllerを継承したクラス
// 表示する
popover.show(relativeTo:of:preferredEdge:)
// 閉じる
popover.performClose(nil)
```

ただし、ラベルや画像を表示するだけでロジックが必要ないなら、カスタムViewControllerを定義したくはない。というようなケースがある。

## 方法

- `xib`ファイルを追加して`File's Owner`に`NSViewController`を指定する
- ラベルや画像などを配置してAuto Layoutを指定する
- `File's Owner`のOutletsのviewとCustom Viewを関連づける
- NSViewControllerの`init(nibName:bundle:)`を用いてインスタンスを取得する

これだけで、カスタムViewControllerのクラスを定義せずに、ViewControllerを用意できる。
![fo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67153/ae52ce34-845a-bd35-1473-36d18ed4ffe9.png)
![view.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67153/451d8710-6e29-02ef-2dd1-61893f50daaa.png)
AI自動運転ラジコンカープロト 目次

# はじめに
自動運転ラジコンカーを開発しています。ラジコンの自動運転化の試みは多数ありますが、ハイエンドのデバイスを採用した実装は多くないようなので苦労した点などシェアしていきたいと思います(記事の公開は順不同で、内容も適宜更新予定)。

## 0. 方針
- 現在の技術水準を見極めるため性能の制約は少なくする。
- クイックにアルゴリズムを試せる構成とする。
- 美しく走る(零号機なので実験機っぽさが無い程度)。
 
## 1. デザイン
1-1 [アーキテクチャ](https://qiita.com/tutu/items/75dbf4109854bd3d4de4)
1-2 組み立て

## 2. ハードウェア
2-1 PWMによる車両制御
2-2 [Dimming Turn Signal (ティータイム1)](https://qiita.com/tutu/items/9d0ea067c15581f08b8f)
2-3 タミヤCC-01のクローラー化 (ティータイム2)


## 3. ソフトウェア
3-1 [JetPackのインストール](https://qiita.com/tutu/items/c6b6a80773347716f837)
3-2 Autowareのインストール
3-3 ROSのインストール
3-4 RealSense SDKのインストール

## 4. 自己位置推定アルゴリズム
4-1 RTK
4-2 2D LiDAR SLAM
4-3 [Visual SLAM (RTAB-Map)#1](https://qiita.com/tutu/items/94cec6e25b94e8120140)
4-4 2D LiDAR SLAM
4-5 3D LiDAR SLAM

## 5. TBD

## 改訂履歴
2020.09.28 ドラフト
2020.09.30 4-3 追加
2021.01.23 3-1 追加
AI自動運転ラジコンカープロト (1-1 アーキテクチャ)

# はじめに
ハードウェアとソフトウェアのアーキテクチャについてまとめます。

# ハードウェアアーキテクチャ
性能制約を少なくするためラジコンカー向けとしてはハイエンドなデバイスを使用します。制御用コンピュータにはJetson AGX Xavier、センサーデバイスとしてRGB-Dカメラ D455、2D LiDAR RPLIDAR-A3、3D LiDAR L515、RTKモジュール ZED-F9Pなどを搭載します。ノートPCを搭載するという力業もありますが、外見も大事なので見送ります。

![Unimog_hardware_arch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109483/1900e78d-7a05-a752-5207-471668256533.png)

# ソフトウェアアーキテクチャ
ROSプラットフォーム上に構築します。一部は自動運転ソフトウェアはAutowareの力を借りることとしましたが、現時点ではオーバスペックなため、自己位置推定機能の一部を使用しているのみです。このプラットフォーム上で高度な自律走行を実現する自己位置推定アルゴリズムや車両制御アルゴリズムを検討する予定です。

![Unimog_software_arch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109483/dbc0faa8-4d7e-5423-5696-6b83ac9b2bc6.png)

# BOM
参考までに使用している主なハードウェア部品は以下になります。

| # | 部品 | 個数 |
|:-:|:--|:-:|
| 1 |タミヤ 1/10 XB No.196 メルセデス・ベンツ・ウニモグ425 |1  |
| 2 |NVIDIA Jetson AGX Xavier | 1 |
| 3 |WD Blue SN550 NVMe WDS500G2B0C| 1 |
| 4 |Intel Dual Band Wireless AC8265| 1  |
| 5 |HiLetgo PCA9685   | 1  |
| 6 |Pololu 4-Channel RC Servo Multiplexer| 1 |
| 7 |RAVPower RP-PB201JP| 1 |
| 8 |Intel RealSense L515| 2 |
| 9 |Intel RealSense D455| 1 |
|10 |Slamtec RPLIDAR A3| 1 |
|11 |RTK Module ZED-F9P| 1 |
|12 |RTK Antenna Tallysman 7872 | 1 |
|13 |LENTION 4ポートUSB Type-Cハブ| 1 |

# 目次ページへのリンク
[目次](https://qiita.com/tutu/items/604b123fd1153b99f6a5)
LINEBOTからTrelloに新規カードを追加する

Integromatを使いLINEとTrelloをつなげていきます！
###Integromatとは
[公式サイト](https://www.integromat.com/)のキャッチコピーです。
***「Integromat is the glue of the internet」***
（Integromatはインターネットの接着剤です）
そうなんです！IntegromatはWEBサービス同士をつなぐ接着剤であり。IFTTTやZapierと同じサービスです。無料で使用できますがタスクは1000回までなどの制限があります。

>参考:   [最強連携サービス「Integromat」がZapier/IFTTTをあっさり超えるラスボス感](https://awe-some.net/2016/10/integromat) 

#[Trello](https://trello.com)のカード追加とLINEをつなぐ

前からタスクを管理したいと思っていたので[Trello](https://trello.com)にアカウント登録してみました、Trelloでは新規にカードを追加する際にTrelloを開いて`カード追加`をするみたいなのでめんどくさい・・・(他に方法はあるかも)

以下は通常の登録手順
1.スマホロック解除
2.Trelloアプリをタップ
3.プロジェクトを選択
4.カード追加を押す
5.入力→ **追加される**

#３タップで登録する
そこで今回はスマホを持っていればTrelloに新規カードをわずか**３タップ**で登録できるようにしました。

1.スマホロック解除
2.LINE開く
3.BOT開く
4.やるべきことを入力→ **追加される**

LINEBOTに入力するだけで新しいカードが追加されていくので楽ちん！Integromat最高！

#できたもの
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Trelloの新規カード追加をLINEからできるものを作成しました。<a href="https://twitter.com/hashtag/Protoout?src=hash&amp;ref_src=twsrc%5Etfw">#Protoout</a>　<a href="https://twitter.com/hashtag/LINE?src=hash&amp;ref_src=twsrc%5Etfw">#LINE</a>　<a href="https://twitter.com/hashtag/%E6%A5%AD%E5%8B%99%E6%94%B9%E5%96%84?src=hash&amp;ref_src=twsrc%5Etfw">#業務改善</a><a href="https://t.co/TdF07qSFfD">https://t.co/TdF07qSFfD</a> <a href="https://t.co/mVHc77KzVw">pic.twitter.com/mVHc77KzVw</a></p>&mdash; Toshiki (@Hirasawa1987) <a href="https://twitter.com/Hirasawa1987/status/1311073436454715392?ref_src=twsrc%5Etfw">September 29, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#ラスボス感

機能が多岐にわたり、設定項目が多く複雑になっている気がします、そして英語に慣れていないので、、ラスボス感

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

LINEBOTの作り方は以下の記事を参考にしています。
[1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017 #nodefest](https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d)

作成したLINEBOTのアクセストークンとユーザーIDを登録することでLINEBOTに連携することができます。
[![Image from Gyazo](https://i.gyazo.com/b047a6fe1a2133351d778dc8afda75d9.png)](https://gyazo.com/b047a6fe1a2133351d778dc8afda75d9)

Webhookが発行されます。

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


コピーしてLINEDevelopersのMessaging API設定の下のほうにあるWebhookに登録します。

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

そしてTrelloの設定を行い。

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

scenariosを選択して、以下の画像のようにの赤枠ボタンをオンにすることで動いてくれています。


![4a667a0ba7900c0c95b1a3f67e1b7078.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206019/71367f00-9ce9-475b-4b49-5e47ff5e4163.png)



#終わりに
Integromatを見ていると、たくさんのサービスが出てきて**アイデア次第で自動化**がどんどんできそう、メールをつなぎたかったけど、Gmail・Office 365
ともにつなげることができなかったのでまた挑戦する。
CSSでプロフィール画像設定のような円系に切り取るUIを作る

よくある画像をアイコンのように丸くトリミングするUIを作る際、画像のトリミング自体はその辺のJSライブラリを利用して容易に実現できます。
しかし、その多くが四角くトリミングするもののため、実際に丸く表示されている範囲はわかりません。
それを解決するためにCSSで丸く表示される範囲を明るく表示してそれ以外をグレーアウトさせるコードを以下にメモします。
↓こんな感じのやつ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253700/622a48a3-6528-133c-48a8-f811fb73202f.png)

```triming.scss
.triming:after {
    position: absolute;
    top: 4px;
    bottom: 0;
    left: calc((100% - 280px)/2 + 4px);
    width: 272px;
    height: 272px;
    pointer-events: none;
    content: "";
    // 背景を透明にする（円形で画像が見える部分）
    background: transparent;
    border: 2px solid #fff;
    border-radius: 140px;
    // 円以外の部分を影で埋める
    box-shadow: 0 0 1000px 1000px rgba(0,0,0,.5);
}
```

## 解説
軽く解説をすると、切り取るライブラリ（大体Canvas)の要素にafter要素を与え、そこで円を描画しています。
CSSにおける`box-shadow`は要素が透明の場合要素にかぶっているところは描画されないことから、影でグレーの部分を表現します。(上位でoverflow: hidden;していればいい感じに収まります)
kubernetesのクラスターにknativeを入れてゼロスケールするPodを作る

先日knativeを使って、ゼロスケールするAPIを作ったので備忘録です。

# 前提条件
- kubernetesのクラスターは構築済み
- istioはインストール済
- knativeのversionはv0.17を使用しています

手順
1. knativeのインストール
2. アプリケーションコードの実装
3. Dockerfileの実装
4. manifestの実装
5. 動作確認

# knativeのインストール
以下のURLの参照をお願いします(ここはそれぞれの環境による部分もあると思うので省略します)
https://knative.dev/v0.16-docs/install/any-kubernetes-cluster/


# アプリケーションコードの実装
```
# main.goとしてディレクトリ内に保存する
package main

import (
	"net/http"
	"github.com/gin-gonic/gin"
)


func main() {
	r := gin.Default()
	r.POST("/", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"code": http.StatusOK,
			"body": "OK",
		})
	})
	r.Run()
}
```

# Dockerfileの実装
```
FROM golang:1.13-alpine as builder

WORKDIR /opt/application

COPY  go.mod .
COPY  go.sum .
RUN  go mod download

COPY  . .

RUN go build -o app ./main.go

FROM alpine

COPY --from=builder /opt/application/app /usr/local/bin/app

EXPOSE 8080

```
Dockerfileをbuildして、repositoryにpushをする

# manifestの実装
```
# knativeのservice
# service.yamlとして保存
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: application
   namespace: anynamespace
spec:
  template:
    metadata:
      annotations:
        # see https://knative.dev/v0.15-docs/serving/configuring-autoscaling/
        autoscaling.knative.dev/class: kpa.autoscaling.knative.dev
        autoscaling.knative.dev/metric: concurrency
        autoscaling.knative.dev/target: "1"
        autoscaling.knative.dev/minScale: "0" # レプリカの最小値
        autoscaling.knative.dev/maxScale: "1" # レプリカの最大値
        autoscaling.knative.dev/window: "60s" # この期間にトラフィックがない場合スケールアウトする
    spec:
      containers:
        - name: application
          image: app # docker imageを保存したrepositoryのパスに変更
          imagePullPolicy: Always
          command:
          - "/usr/local/bin/app"
```

```
# 作ったmanifestのapply
$ kubectl apply -f service.yaml
```

# 動作確認

```
# serviceがあることを確認
$ kubectl get ksvc
NAME          URL                         LATESTCREATED       LATESTREADY          READY   REASON
application   http://application.xxxxxx   application-pzxhm   application-pzxhm   True

$ CLUSTER_HOST=<CLUSTER_HOST>
curl  $CLUSTER_HOST -H "Host: http://application.xxxxxx"
OK
```
このように表示されたら成功です
Datadogでログの長期可視化

# 背景
Datadog を使い始めてまだ間もないですが、ログを転送しておけばささっと可視化できてとても便利です。
ただ、Datadog 上では最長でもログ保持期間が 60日ということで、
ログ解析する対象期間が長くなるとアーカイブしてリハイドレイトするなどの運用が必要となってきます。
可視化する場合はというと、Log Events によるグラフ化もやはりログ保持期間に依存するため、最長 60日のグラフとなってしまいます。

そこで、
去年の同時期と比較したいなど、長期で可視化したい場合はログベースのメトリック (15ヶ月間保持) にしておくことをおすすめします。

# ログベースのメトリック作成

### 前提
- ログ保持期間は 7日間で契約中
- 例として、Datadog へ転送された JVM GC ログのメトリックを作成
- 当 GC ログは Datadog Agent 側で FullGC 行のみをフィルタし、**service_name** タグにサービス名をマッピングして転送

### メトリック作成
- Logs > Generate Metrics > New Metric (or [Add a new metric])
![qiita_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30470/1c66c7a3-9d69-7d9b-3dd5-7c10917b86cd.jpeg)
  - クエリは、Log Explorer で検索するクエリと同等
  - group by (DIMENSIONS) にはグラフ化する際に付加するタグを記述<br>
    クエリでガサっと取得したログをホスト単位やサービス単位で分割する際のキー設定のようなイメージ<br>
    ※クエリ作成後の変更は可能だが、過去に取得した値には適用できないので注意

### 作成したメトリックの確認
- Generate Metrics 画面で、作成したメトリックをフォーカスし、Metric Explorer (下記赤丸) で開く
![qiita_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30470/fbdde669-52c8-65a9-ef80-6ec37cb155ab.jpeg)

- メトリックの内容を確認
![qiita_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30470/0ed47e49-6d00-6daa-9212-095eba601ace.jpeg)
  - ログ保持期間に依存していない (上記例のメトリックは 3週間前に作成)
  - メトリック作成時に DIMENSIONS 設定しておいた **service_name** をスコープとし<br>
    さらに DIMENSIONS 設定しておいた **host** ごとに値が入ったメトリックが作成された

### グラフ化
あとは作成されたログベースのメトリックをダッシュボード上で通常通りグラフ化して完了

---
### 参考
- https://docs.datadoghq.com/ja/logs/logs_to_metrics/
もう迷わない！RSpec導入の流れ

#RSpecとは
　Railsにおいて、単体テストコードを記述するときに用いるGemのこと。
##テストコードを記述する直前までの大まかな流れ
1. Gemfileに追記
2. Gemをインストール
3. rspecをインストール
4. テストコードをターミナル上で可視化できるようにする
5. FactoryBotとFakerのGemをGemfileに追記
6. Gemのインストール
7. （テスト用の画像を用意）

###1. Gemfileに追記

gem 'rspec-rails'と記述する。
<font color="Red">必ず、group :development, :test do ~ endのグループ内に</font>

```Ruby:Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails'
end
```
###2. Gemをインストール
ターミナルでカレントディレクトリがテストコードを使用するアプリケーションのディレクトリであることを確認の上

```
bundle install
```
###3. rspecをインストール
```
rails g rspec:install
```
これによって、「specディレクトリ」や「.rspecファイル」が生成される
###4. テストコードをターミナル上で可視化できるようにする
```ruby:.rspec
--format documentation
```
を追記する。
###5. FactoryBotとFakerのGemをGemfileに追記
必要に応じてGemを導入。今回はチャットアプリを想定しているため、導入。

```ruby:Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails'
  gem 'factory_bot_rails'
  gem 'faker'
end
```
<font color="Red">先ほどと同じgroupの中に記述。</font>
###6. Gemのインストール
```
bundle install
```
###7. （テスト用の画像を用意）
public/imagesにファイル名「test_image.png」で配置。

##ポイント

- [x] rspecは「bundle install」だけでなく、「rails g rspec:install」をして初めて使える。
- [x] 記述するのは、group :development, :test do ~ endのグループ内。

##最後に
bundle installはRailsに取り込んだだけ！
rails g rspec:installで解凍するイメージ！

細かいテストコードはまた別の機会に。
Ruby で解く AtCoder ACL Beginner Contest C UnionFind(DSU)

# はじめに
*[AtCoder Problems](https://kenkoooo.com/atcoder/#/)* の Recommendation を利用して、過去の問題を解いています。
AtCoder さん、AtCoder Problems さん、ありがとうございます。

# 今回のお題
*[AtCoder Beginner Contest C - Connect Cities](https://atcoder.jp/contests/abl/tasks/abl_c)*
<font color="gray">Difficulty: 363</font>

今回のテーマ、UnionFind

つい最近、[同様の問題](https://atcoder.jp/contests/abc177/tasks/abc177_d) があったり、[AtCoder Library Practice Contest](https://atcoder.jp/contests/practice2) があったりとは言え、灰レートは凄いです。
ちなみに、前回は<font color="brown">Difficulty: 676</font>でした。
# Ruby
```ruby.rb
class UnionFind
  def initialize(n)
    @parents = Array.new(n, -1)
  end
  def find(x)
    @parents[x] < 0 ? x : @parents[x] = find(@parents[x])
  end
  def parents
    @parents
  end
  def union(x, y)
    x = find(x)
    y = find(y)
    return if x == y
    if @parents[x] > @parents[y]
      x, y = y, x
    end
    @parents[x] += @parents[y]
    @parents[y] = x
  end
end

n, m = gets.split.map(&:to_i)
u = UnionFind.new(n)
m.times do
  a, b = gets.split.map(&:to_i)
  u.union(a - 1, b - 1)
end
puts u.parents.select{ _1 < 0 }.size - 1
```
```sub.rb
puts u.parents.select{ _1 < 0 }.size - 1 # 今回

puts -u.parents.min # 前回
```
[前回 --Qiita](https://qiita.com/superrino130/items/086c2f192cc741196680)の最終行を変更するだけで`AC`します。

```sub.rb
@parents = [-3, 0, -2, 2, 0]
```
前回の`入力例 1`で説明しますと、`u.parents`の中は、`u.parents[0]`と`u.parents[2]`が代表の2グループに分けれらますので、それを1つの道路で結べばOK。
# AtCoder Library (ACL)のRuby版
[ここ --github](https://github.com/universato/ac-library-rb)で、ACLのRuby版を作成されている動きもあります。
`要注目`ですね。

||Ruby|
|:--:|:--:|
|コード長 (Byte)|567|
|実行時間 (ms)|170 |
|メモリ (KB)|15612|
# まとめ
+ ACLBC C を解いた
+ Ruby に詳しくなった

参照したサイト
*[Ruby で解く AtCoder ABC177 D UnionFind --Qiita](https://qiita.com/superrino130/items/086c2f192cc741196680)*
Thymeleafを使用した、MVCモデル(モデル⇒コントローラ)(コントローラ⇒モデル)

#必要なクラス
・Controller
・html
・bean

◆モデル⇒コントローラ

●Controllerクラス

ResultModel ⇒モデルクラス
@ModelAttribute⇒入力フォームで取り扱うオブジェクトを設定

    // register.htmlで使用するモデル「fmodel」を用意する必要がある
    	// 登録ページ
    	@RequestMapping(value = "/customerRegister", method = GET)
    	public String customerRegister(@ModelAttribute("fmodel") ResultModel fmodel) {
                        
               //表示するhtmlをリターンする
        		return "/register.html";
    	}
    
    // customerRegisterConfirm.htmlでから取得した値が設定されるモデル
      「fmodel」を用意する必要がある
    	// 登録内容確認ページ
    	@RequestMapping(value = "/customerRegisterConfirm", method = POST)
    	public String customerRegisterResult(@ModelAttribute("fmodel") ResultModel fmodel) {
    
    		return "/customerRegisterConfirm.html";
    	}



●html
th:object="${XXX}⇒マッピングするvalue値を設定 
th:action="@{/YYY}⇒データを取得するモデル名を設定


    	<form th:action="@{/customerRegisterConfirm}" method="post"
    		th:object="${fmodel}">



●データ取得
th:field="*{AAA}"⇒モデルのフィールドを設定

		<input type="text" th:field="*{userName}"
						style="width: 400px; height: 30px;">




---

◆コントローラ⇒モデル

●表示用html
コントローラから渡される値をモデルを通じて取得するため、
コントローラで設定したモデルの変数名を設定

th:object="${YYY}"⇒データを取得するモデル名を設定


    <div th:object="${fmodel}">

th:text="*{AAA}"⇒データを取得するモデル名を設定

    <div class="confirm" th:text="*{useID}"></div>
2回目でなんとか受かったAWS SAA-C02の思い出

## SAA-C02とは 
[AWS 認定 ソリューションアーキテクト – アソシエイト](https://aws.amazon.com/jp/certification/certified-solutions-architect-associate/)のことであります。
15,000 円（税別）というなかなかお値段する試験を2回目でなんとか合格できたので、まとめておこうと思います。

## 元々のAWS力と学習期間
* もともと触ったことあったサービス
    * IAM : ロールとかポリシーとかどんなもんか知ってたぐらい
    * EC2 : インスタンス立てて, sshぐらい
    * RDS : Lambdaとつないで、RDSプロキシとか触ってた
    * Lambda : [音声ファイル文字起こし](https://qiita.com/haruhiko28/items/99d3469515f567e7ef19)とかしてた
    * S3 : 普通にデータ保存しとく用で使ってた
    * SNS : なんかSMS飛ばして遊んだりしてた
    * VPC : インターネットゲートウェイとかNATゲートウェイとか設定したりしたことあった
    * それ以外は多分触ったことなかった...
    
* 1回目の学習期間 : 3週間(最初2週間は1日2,3h。最後の1週間はガッツリ1日10hぐらい)
* 2回目の学習期間 : 1回目落ちてから4週間(1日2,3h)

## スコア
* 1回目:680点
* 2回目:779点<br>
720点で合格です。1回目落ちた時に次回絶対オーバーキルしようと思って挑んだにも関わらず、大したスコアでもなかったので、上記のようなタイトルになってます。

## やったこと
### 1回目受験までにやったこと
#### 本
* [徹底攻略 AWS認定 ソリューションアーキテクト – アソシエイト教科書](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5-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-%E2%80%93-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88%E6%95%99%E7%A7%91%E6%9B%B8/dp/4295005495)
    * 基本を抑えるにはいいと思います。これだけで受かるのはなかなか難しいかと。

#### Udemy
他の記事でも紹介されてますが、私も以下の2つをやりました。

* **[これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座（SAA-C02試験対応版）](https://www.udemy.com/course/aws-associate/)**
  * 長かったので、ハンズオンは気になる&お金が掛からないものだけやりました。あとは知ってる内容は飛ばすなどしてやりました。正直、試験に特化した対策をするならそんないらなかったかなという気もしてます。
* **[【SAA-C02版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）](https://www.udemy.com/course/aws-knan/)**
  * こちらは何回もやりました。これは本番より難易度高いという意見もありますが、私は本番同等かそれ以下に感じています。本番は日本語が変っていうのもあって難しく感じました。

1回目はこの2つ、主に2番目の方ばっかりやって受験しました。

### 2回目受験までにやったこと
#### Udemy
* **[【SAA-C02版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）](https://www.udemy.com/course/aws-knan/)**
  * 1回目同様こちらは使用しました。ただ1回目の受験までに何回もやって覚えてるような状態だったので、忘れた頃に見返す程度でした。
* **[これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座（SAA-C02試験対応版）](https://www.udemy.com/course/aws-associate/)**
  * レクチャーは全く見ず、模擬試験だけ使いました。こちらも忘れた頃に見返す程度。

#### [AWS WEB問題集で学習しよう](https://aws.koiwaclub.com/)
* ２回目はこちらをメインで学習して、用意されている136回分(1回分あたり7問)のうち、80~136回までを3周解きました。(ゴールドプラン以上に登録する必要あり)
* 私はこの問題集のおかげで受かったという感じでした。1回目の受験時からやっておけば受かったんじゃないかなと後悔してます。
* こちらの問題集は本番に酷似した問題を提供してくれているので、Udemyよりおすすめですし、解説もすぐに出てきて、参考リンクがついてるので復習しやすいです。

## 後悔してること・気をつけた方がいいこと
### 1回目受験の後悔
* 見直しをしなかったことです。どうせ受かんないなぁという感覚だったので、1周解いて終わってしまいましたが、意外と680とちょっと惜しかったので、見直ししとけばワンチャンあったかもと思ってます。
* それでも不合格は不合格で、悪かったこととしては**Udemyの問題丸暗記状態**になってしまっていたことです。「なんでこの回答になるのか、他の選択肢がなぜ違うのか」ちゃんと理解しきれていなかったと思います。

### 2回目受験の後悔
* [AWS WEB問題集で学習しよう](https://aws.koiwaclub.com/)での学習においても、「なんでこの回答になるのか、他の選択肢がなぜ違うのか」をより意識すべきだったと思ってます。試験本番でも2択に絞れるけどどっちかわからないみたいなことが何問もありました。

## 終わりに
上に書きましたが、ただ問題を解くだけでなく、回答になる理由ならない理由をしっかり理解しながら学習を進めることが非常にこの試験では重要だと思います。例えば私の試験には出ませんでしたが、SNSとSQSどっち使うかとかAmazon ElastiCacheのMemcachedとRedisのどちら使うかなど割と深いところまで知っといた方が良いと思います。
今後は一回AWS周りの勉強はおやすみして、直近のセキスペに向けて勉強します。GCPもなんか取りたいなぁ。
MQTT

#【MQTT】

業務内でのコーディング担当箇所にて、MQTTが出てきました。
MQTTってなに。ってなったので簡単に自分用メモとして残します。

##MQTT （Message Queue Telemetry Transport）

IoT時代の通信プロトコルとして注目されている。
TCP/IPネットワークで利用できる通信プロトコルである。

Publish/Subscribeモデルという仕組みである。

データの送受信をPublisher（送信者）, Subscriber（受信者）の役割にわけて行う。
MQTTブローカーというものに送受信され利用される。

##MQTTブローカー

MQTTブローカーとは、Publisher,Subscriberでメッセージを配信するサーバ

・PublisherはMQTTブローカーにデータを送信する。
・SubscriberはMQTTブローカーにデータを受信しにいく。

また、遺言（Will）という仕組みは、万が一接続が意図せず途切れてもPublisher,Subscriberのメッセージは機能させる。

##MQTTの特徴

・仕組みがとてもシンプル
・軽量メッセージ通信
・省電力で機能する

→ひとつひとつが小さい大量のデータを低遅延で通信することが可能。

##MQTTの使用例

・機械のパイプライン
・自動運転（IoT）
・医療現場の機器
・アプリケーションのメッセージ送受信　など。

→MtoM（MACHINE to MACHINE）

##余談　【今年、残り３ヶ月の目標】

<strong>AWS認定クラウドプラクティショナー、LPIC１の資格を取得する！！</strong>

Javaを開発言語にしたサーバサイドの開発をしています。
AWS,Linuxを使う場面が多々あるので、今後のためにもっと深く学んでいきます。
そのための基礎として、入門資格をまず取得します。

AWS,Linuxは、今回のMQTTともかなり関わりがあるとわかりました。
rpi-imager を Raspberry Pi で試してみる

RaspberryPi OS は、 rpi-imager を使うとダウンロードしながら書き込みができる。
Windows/Mac/Linux などの母艦から書き込みができるが、Raspberry Pi 自身を使っての書き込みもできるらしい。


「Installing operating system images - Raspberry Pi Documentation」
https://www.raspberrypi.org/documentation/installation/installing-images/

には、

> If you want to use Raspberry Pi Imager on the Raspberry Pi itself, you can install it from a terminal using

とあります。

どうやら書き込みするターゲットの microSD カードと、踏み台になる micro SD カードを2つ用意し、踏み台の microSD カードで起動して rpi-imager をインストール、ターゲットは USB カードリーダライタで接続して書き込むらしい。

![IMG_20200929_231521321.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/19b6e84d-50aa-8440-6cb1-4537ffaefd78.jpeg)

しかしながら詳細は不明だったので試してみました。


# 用意するもの

- Raspberry Pi 本体
- 起動のために必要な microSD カード
- 書き込み先の microSD カード
- USB microSD リーダー

2つの microSD カードは両方共 A1規格の SanDisk Ultra 98MB/sのものを使用しました。

# 環境

- 踏み台の microSD カードには、2020-05-27-raspios-buster-lite-armhf.zip をインストール
- RaspberryPi Model B+
- 有線LAN(100Mbps)


# CUI で試す・・・失敗

書き込みをヘッドレスで行いたかったので、踏み台の microSDカードには  RaspiOS の Lite を使いました。 なので Xorg は使わずに、ssh でログイン。以下を作業してみた。

```

$ sudo apt update
```
とした後、

```

$ sudo apt install rpi-imager
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  adwaita-icon-theme at-spi2-core dbus-user-session dconf-gsettings-backend
.
.
.
  qml-module-qtquick-window2 qml-module-qtquick2 qt5-gtk-platformtheme
  qttranslations5-l10n rpi-imager udisks2 x11-common
0 upgraded, 161 newly installed, 0 to remove and 0 not upgraded.
Need to get 64.8 MB of archives.
After this operation, 711 MB of additional disk space will be used.
Do you want to continue? [Y/n] 
```

結構増えますね。X 関係も入ってきているようですが・・・
Yを押して進めます。

インストールした後に実行。

```

$ rpi-imager --help
qt.qpa.screen: QXcbConnection: Could not connect to display 
Could not connect to any X display.
```

なあんだ。X必須かあ。

```

$ rpi-imager --help
```

としましたがオプション表示などはありませんでした。

# GUIで操作

Xorgをインストールして、キーボード、マウス、ディスプレイを繋いで起動しました。

![IMG_20200929_173855226.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/e3984267-db7b-507c-2b8d-fac1989c389c.jpeg)

画面操作がどえらく遅いです。
システム負荷がかかっているのかなと思って Top を見てみましたが、ロードアベレージがどんどん増えたりはしていないので、GUI 処理の問題ぽいです。


![IMG_20200929_174414123.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/0a596faf-4f2c-2976-1dbc-0937512b66c9.jpeg)


Raspberry Pi OS Lite(32-bit)を選択してみます。


![IMG_20200929_174530545.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/a7d21634-04e5-a577-d492-a2dec4ade34d.jpeg)


10分強で書き込みができた後、5分程度の Verify が行われ、操作完了しました。
AWS ECRでAWS CLIの認証で弾かれた問題

# なにこれ
AWSのECRへ認証するコマンドを叩いた時に、下記のエラーが発生したのでその対策

## エラー文
`auth error An error occurred (UnrecognizedClientException) when calling the GetAuthorizationToken operation: The security token included in the request is invalid. Error: Cannot perform an interactive login from a non TTY device`

訳）auth error GetAuthorizationToken操作の呼び出し中にエラーが発生しました（UnrecognizedClientException）：要求に含まれているセキュリティトークンが無効です。エラー：TTY以外のデバイスからインタラクティブログインを実行できません

はい、訳を読んでも意味が分からないです。
セキュリティートークンが無効だから、認証系の問題かな？と予想。
とりあえず、エラー文をはっつけて検索する初歩的な方法をしました。

# 原因
AWSのACCESS_KEYとSECRET_KEYの情報が一致しないため（？）

# 原因を調べる
`aws configure list`コマンドを叩いて、アクセスキーとシークレットキーが何と設定されてるか確認します。
#
```
~ $ aws configure list
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                <not set>             None    None
access_key     ****************1234             env    
secret_key     ****************1234             env    
    region           ap-northeast-1      config-file    ~/.aws/config
```

ここで本来あって欲しいアクセスキーとシークレットキーになっていないことに気づく。

なので、下記のコマンドで変更する
#
```
export AWS_ACCESS_KEY_ID=****5678
export AWS_SECRET_ACCESS_KEY=****5678
```
このコマンドで、`~/.zshrc`

再度`aws configure list`を叩いてキー2つを確認する。
#
```
~ $ aws configure list
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                <not set>             None    None
access_key     ****************5678             env    
secret_key     ****************5678             env    
    region           ap-northeast-1      config-file    ~/.aws/config
```

ターミナルを再起動後、もう1回ECRへ認証するコマンドを叩いたら、成功しました！
【Windows10】VSCodeでunresolved import 'django.xxx' python(unresolved-import)が発生時の解消方法

##発生事象
vscodeでdjango関連のunresolved importが発生。
たとえば、unresolved import 'django.urls' python(unresolved-import)といった具合です。

気持ち悪かったので、解消した対応方法を。

##ローカル環境
- Windows版dockerで開発環境を構築。Pythonの仮想環境はpipenvを利用しています。

| 項目 | バージョン |
|:-----------|:------------|
| OS | Window10 2004 |
| Python | 3.8.2 |
| docker | 2.3.0.5 |
| Editor | VSCode:1.49.2 |

- 仮想環境の各種ソフトウェアバージョンは下記の通りです。

| 項目 | バージョン |
|:-----------|:------------|
| OS | ubunts:20.04
| python | 3.8.2 |
| Django |3.0.6 |
| gunicorn | 20.0.4 |
| psycopg2 | 2.8.5 |
| PostgeSQL | 2.3 |
| nginx | 1.17.10 |

##仮想環境の構築は
* Workplaces配下にappフォルダを作成しています。
* appフォルダ直下で **pipenv install** を実行しています。
* djangoプロジェクトは **pipenv shell** からappフォルダ直下で **startproject** で作成ています。

##対応
####1.ワークスペース直下に.envファイルを作成

####2..envファイルに下記を記載

``` python:.\.env
PYTHONPATH = app\.venv\Lib\site-packages
```
####3.VSCodeのenvFileの設定を確認します。
#####3-1.VSCodeのメニューから _File->Preferences->Settings_ で設定を開きます。

![Settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679829/0c9927ac-7a58-efe1-59ca-2fc796a03d14.png)

#####3-3.検索窓に「python.envFile」を入力します。
#####3-4.python.envFileの値が「${workspaceFolder}/.env」であるならそのままで問題なし。おそらくデフォルトでワークスペース直下がパスとなっていると思います。

![envfile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679829/910bf736-65ba-54d2-ad3e-bc3b90535078.png)

#####3-5.VSCodeを立ち上げなおす。

**おそらく、django関連のunresolved importが解消されているかと**

##あとがき
VSCodeからは見えていないので当たり前といば当たり前なのですが、、、

##参考にさせていただいたサイト
https://blog.mrym.tv/2019/08/vscode-python-unresolved-import/
【PowerShell】 ターミナル画面を最小化する

別ソフトを開くようなコマンドを実行したあと、（特に最大化せずに複数ウィンドウを並べながら作業しているようなとき）開いていたターミナル画面が邪魔になることがないでしょうか？

そんなときは下記の内容を `$PROFILE` から読み込んでおくと、処理の最後に `Hide-ConsoleWindow` と呼び出すことでターミナル画面を最小化することができます。

```powershell
function Get-ConsoleWindowHandle {
    $p = Get-Process -Id $PID
    $i = 0
    while ($p.MainWindowHandle -eq 0) {
        if ($i++ -gt 10) {
            return $null
        }
        $p = $p.Parent
    }
    return $p.MainWindowHandle
}
$Global:CONSOLE_HWND = Get-ConsoleWindowHandle

if(-not ('Console.Window' -as [type])) {
    Add-Type -Name Window -Namespace Console -MemberDefinition `
@'
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

public static void Minimize(IntPtr hwnd) {
    SendMessage(hwnd, 0x0112, 0xF020, 0);
}
'@
}
function Hide-ConsoleWindow {
    if ($Global:CONSOLE_HWND -and ($env:TERM_PROGRAM -ne "vscode")) {
        [Console.Window]::Minimize($Global:CONSOLE_HWND)
    }
}

```



仕組みとしては C# のコードを Add-Type してウィンドウを操作しています。

（[ドキュメント](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/add-type?view=powershell-7) を見たところ、 Add-Type はデフォルトで名前空間 `System` を参照し、さらに `-MemberDefinition` を指定すると自動的に `System.Runtime.InteropServices` も参照するようです。ヒアドキュメント内のインデントが浅くなりコード内への埋め込みやすさが上がりますね）

ウインドウハンドル取得のためにわざわざ `Get-ConsoleWindowHandle` を作っているのは Cmder や ConEmu などのコンソールエミュレータを想定しています。1回ではウィンドウハンドルを取得できないことがあるため、最大10回のリミットを設けてループさせています。

何もしないと VSCode の統合ターミナル上で実行したときに VSCode 自体が最小化されてしまうので、[前回の記事](https://qiita.com/AWtnb/items/799884db3f5cffbc834e) でも紹介した `$env:TERM_PROGRAM` で判定しています。
【Golang】Go言語　channel（チャネル）について

##channelとは？

Goroutineは並行実行されているので、通常だとデータのやりとりができません。
しかし、channelというのををつかうとデータのやりとりができます。

トンネルをつなぐようなイメージです！

```golang

package main

import (
	"fmt"
)

func goroutine1(s []int, c chan int) {
	sum := 0
	for _, v := range s {
		sum += v
	}
　　　　//チャネルにデータを送信
	c <- sum
}

func main() {
	s := []int{1, 2, 3, 4}
	c := make(chan int)
	go goroutine1(s, c)
      //送られてきたデータを受信
	p := <-c
	fmt.Println(p) // => 10
}
```

c <- sum でcに値を送信し、p := <-c　で受信しています。ここでは受信するまでブロッキングされていて、pはsumを受信するまで待っている状態です。sync.Waitと同じような状態ですね！

##Buffered channels
バッファとはプログラムで処理を行なうときに、データを一時的に格納するためのメモリー領域のことをいいます。
チャネルに一時データを保存するイメージです。

```golang

package main

import "fmt"

func main() {
	//2つまでバッファを保存できる
	ch := make(chan int, 2)
	ch <- 100
	//len()でチャネルの長さを調べられる
	fmt.Println(len(ch))
	ch <- 200
	fmt.Println(len(ch))
	//3つめのデータを送信しようとするとエラーになる
	ch <- 300
	fmt.Println(len(ch)) // => fatal error: all goroutines are asleep - deadlock!
}
```

```
実行結果
1
2
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
	/tmp/sandbox795806942/prog.go:11 +0x16f
```

2つまでしか保存できないので、3つめを送信しようとすると当然ですがエラーになります。（デッドロック）

↓にように手前で一個チャネルを取りだしてから300を送信すれば、エラーにならなくなります。

```golang

func main() {
	ch := make(chan int, 2)
	ch <- 100
	fmt.Println(len(ch))
	ch <- 200
	fmt.Println(len(ch))

	x := <-ch
	fmt.Println(x)
	ch <- 300
	fmt.Println(len(ch))
}
```

```
実行結果
1
2
100
2
```

次に以下のコードをご覧ください↓

```go

package main

import "fmt"

func main() {
	ch := make(chan int, 2)
	ch <- 100
	fmt.Println(len(ch))
	ch <- 200
	fmt.Println(len(ch))

	for c := range ch {
		fmt.Println(c)
	}
}
```

これはチャネルをrangeでループさせようとしているのですが、これはエラーになります。

```
実行結果
1
2
100
200
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
	/tmp/sandbox892357489/prog.go:12 +0x1f3
```

これは存在しない3つ目のチャネルまでループしようとしてしまうからです。
2つ目のチャネルでループ処理を止めるにはチャネルを一旦クローズする必要があります。
そのためにはclose(ch)を記述する必要があります。

```go

package main

import "fmt"

func main() {
	ch := make(chan int, 2)
	ch <- 100
	fmt.Println(len(ch))
	ch <- 200
	fmt.Println(len(ch))
	close(ch)
	for c := range ch {
		fmt.Println(c)
	}
}
```

```
実行結果
1
2
100
200
```

##最後まで読んでいただきありがとうございます！
ご指摘などございましたら、コメントいただけると幸いです！！
文字列をひらがなで分割したい

# 文章をひらがなで分割
漢字の文章のルビを振ることになった。その過程で作った。
以下コード

```python
def hiragana_split(s):
    # 元の文章をひらがなで分割
    # 50音のリスト
    fifty_text = [chr(i) for i in range(12353, 12436)] + ['。', '、']
    split_list = []
    # ひらがなかどうか
    start_point = 0
    section = ''
    for i in range(len(s) - 1):
        if not (s[i] in fifty_text) == (s[i + 1] in fifty_text):
            split_list += [s[start_point:i + 1]]
            start_point = i + 1
    return split_list


if __name__ == '__main__':
    s = 'どこで生れたかとんと見当けんとうがつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。'
    print(hiragana_split(s))
# ['どこで', '生', 'れたかとんと', '見当', 'けんとうがつかぬ。', '何', 'でも', '薄暗', 'いじめじめした', '所', 'で', 'ニャーニャー泣', 'いていた', '事', 'だけは', '記憶']
```
AI自動運転ラジコンカープロト (2-2 Dimming Turn Signal)


# はじめに
サーボ制御に使用されるPWMコントローラですが、LEDの輝度の制御にも使用できます。これを使って、Mazda 3のターンシグナルを模擬してみました(Mazdaファン以外には分かりにくいですが...)。

# 前提
- デバイス：HiLetgo PCA9685
- ライブラリ： [Adafruit Python PCA9685](https://github.com/adafruit/Adafruit_Python_PCA9685)

# LEDのPWM制御について

PWMコントローラは、周波数とHighからLowにタイミングを設定することができます。例えば、下記の図(a)は(b)と比較してHighの期間が長いため相対的に明るく見えます。常にHighであれば最大輝度、常にLowであれば消灯になります。

![pwm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109483/4a47ed9f-9947-3d98-05ee-5c68c86cbe06.png)

# インストール
```
sudo apt-get install git build-essential python3-dev
cd ~
git clone https://github.com/adafruit/Adafruit_Python_PCA9685.git
cd Adafruit_Python_PCA9685
sudo python3 setup.py install
```

# 実装
PWM周波数はサーボ制御の関係で57.8Hz、点滅の周波数は1.5Hz、4096階調で30ステップごとに輝度を変化させるとそれっぽく見えます。


# 結果
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Dimming Turn Signal <a href="https://t.co/33uruU7WKn">pic.twitter.com/33uruU7WKn</a></p>&mdash; tutu (@tutu68018594) <a href="https://twitter.com/tutu68018594/status/1310586938177384449?ref_src=twsrc%5Etfw">September 28, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 目次ページへのリンク
[目次](https://qiita.com/tutu/items/604b123fd1153b99f6a5)