OmniAICreator/Qiita-1.07M huggingface dataset:
JSでスイカゲームみたいなの part2

# 前回の記事

https://qiita.com/babu-ch/items/6c0d3d5d1be61fe761a3

# パワーアップさせたい

具体的にはボールに画像を使いたかった

# 完成形

![CPT2311041650-802x602 (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329559/616108dd-241c-448b-628c-bb86e75c986f.gif)

画像は著作権とかめんどかったので適当に書きましたが、ちゃんとしたデータを使うといい感じだと思います

## URL

https://babu-ch.github.io/ballgame2/

# やったこと

・physicsをarcadeからmatterに

arcadeだとボールに設定した画像を回転させることができなかったのでmatterに変更した
それによってかなり書き換えとかはあったけど（衝突判定やオブジェクトの設定等）挙動がいい感じになった

matterになってから以下のようにボールを押し込んだりできるようになったので面白くなった

![CPT2311041648-320x658.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329559/9ee06de9-6f2f-8f63-30b5-7850f665dab5.gif)



・合体したときにピョンってなるようにした

くっついたときに動きがあることでちょっと楽しい

・matterになって、空中にボールが浮いたままになってしまうことがあった

何故かはわからない
ボールが消えたときに生きているボールは下方向に力を加えることで解決した
```js
                // ボールが消えたときに空中に残ることがあるので、生きているボールに下方向の力を加える
                setTimeout(() => {
                    this.balls.filter(b => b.active).forEach(b => {
                        if (b === this.lastBall) {
                            return
                        }
                        b.applyForce(new Vector2(0, 0.01))
                    })
                }, 20)
```

# ソース

https://github.com/babu-ch/ballgame2

メインのソースは相変わらず↓
https://github.com/babu-ch/ballgame2/blob/main/src/scenes/MyScene.ts
AWSのスイッチロール/MFA設定されているアカウントでTerraformCLIを使う

# はじめに
TerraformCLIを利用する際に、スイッチロールやMFAを設定しているアカウントの設定方法について調べたので、その際の設定方法についての備忘。
（TerraformCLIというよりかは、AWSの設定方法）

## 環境
- MacOS12(Monterey)
- CLI
    - Terraform: v1.5.7
    - aws-vault: 7.2.0
    - aws-cli: 2.13.21

# 設定
いきなりですが、最終的な`.aws/config`の設定は以下の通り

```config.
[profile hoge-origin]
region = ap-northeast-1
output = json

[profile hoge-vault]
region = ap-northeast-1
output = json
role_arn = arn:aws:iam::{スイッチ先アカウントID}:role/{ロール名}
source_profile = hoge-origin
mfa_serial = arn:aws:iam::{スイッチ元アカウントID}:mfa/{ユーザーアカウント}

[profile hoge]
region = ap-northeast-1
output = json
credential_process = aws-vault exec hoge-vault --json --prompt=osascript
```

ここでは`hoge-origin`をスイッチ元のアカウント(`credentials`が設定されているアカウント)
`hoge-vault`はスイッチ先アカウントとして、`hoge`を最終的に*AWS_PROFILE*として設定するアカウントとします。(`default`で運用されている場合は適宜読み替えてください)

AWSCLIの利用だけであれば、上記で言うところの`hoge-vault`を*AWS_PROFILE*に設定すれば、問題なく利用できると思いますが、terraformを実行すると

> Error: error configuring S3 Backend: Error creating AWS session: AssumeRoleTokenProviderNotSetError: assume role with MFA enabled, but AssumeRoleTokenProvider session option not set.

というエラーが発生するため、後述するaws-vaultというツールを利用して、これを回避しました。

## aws-vault

[aws-vault](https://github.com/99designs/aws-vault)はAWSアクセスキーをキーチェーン等で暗号化して安全に扱うことができるツールです。
Macであればhomebrewでインストールします。

```sh
$ brew install aws-vault
$ aws-vault --version
7.2.0-Homebrew
```
### 設定
aws-vaultに認証情報を設定します。
credentialsが設定されているのは`hoge-origin`のため、以下のように設定します。

```sh
$ aws-vault add hoge-origin
Enter Access Key ID: {aws_access_key_id}
Enter Secret Access Key: {aws_secret_access_key}
Added credentials to profile "hoge-origin" in vault
```
登録ができているか確認
```sh
$ aws-vault list
Profile                  Credentials              Sessions                 
=======                  ===========              ========                 
default                   -                        -                        
hoge-origin               hoge-origin              -                        
hoge-vault                -                        -   
hoge                      -                        -   
```

設定は以上です。
あとは、実際に`hoge`プロファイルに切り替えて、いつも通りにawsコマンド及びterraformコマンドが実行できます。
※MFAを設定しているため、コードの入力は必要です

```sh
$ export AWS_PROFILE=hoge
$ aws s3 ls
2023-02-08 12:06:02 xxx
2022-05-18 19:21:10 yyy
```



### その他
実行に関して、都度キーチェーンのパスワードの入力を求められる場合があります。
その場合は、以下のように設定変更することで、無効化 or 時間を変更することができます。

```sh
$ open ~/Library/Keychains/aws-vault.keychain-db
```

キーチェーンの設定を変更する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457889/128b4daa-ec42-77ad-2dc8-cd970f554a58.png)

実行時間の変更かロック事態を無効化する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457889/cae512d7-71d9-17a5-59a9-746f8fa854ae.png)





# 参考
https://dev.classmethod.jp/articles/iam-switchrole-for-beginner/

https://dev.classmethod.jp/articles/terraform-assumerole/
【UiPath】プロキシ設定が誤りでも自動実行はできるが遅くなる（uipath.config 設定）

# はじめに
先日、以下の問題点を抱えたまま運用を続けていた自動実行事例に遭遇しました。
①自動実行の初回プロセスの実行が遅い（同シナリオの手動実行に比べる+5分程度かかる）
②自動実行では新規パッケージDLができない。ただし、同端末のStudioは正常にパッケージDL可能

結論としては「プロキシ設定が誤っている」ため発生する事象で、uipath.configファイルを正しく編集することで解決可能でした。

このケースの問題点は **「自動実行ができない」わけではないので、そのまま運用がされてしまう**ことです。①・②が発生した現場でも、以下の理由で発覚が遅れていました。
①　プロセス自体は正常実行される
　「ロボット接続サービスURL参照try→失敗→タイムアウトまで待機→プロセス実行」
 　という挙動のため。
 　※プロセスに使用されるかどうかに関係なく、ロボット接続サービスは参照されます
②自動実行端末＝開発機/検証機であり、運用的に回避されていた（これは偶然）
　「本番運用前、自動実行端末のStudioで動作検証を実施する」運用ルールがあり、
　　正常にプロキシ設定されたStudio（ユーザーモード）でパッケージDLがされ、
　　自動実行運用前には端末に必要パッケージが必ずDLされている状態だった。
　　　※プロキシ設定はユーザーモードとサービスモードで参照先が異なる。
　　　　自動実行はサービスモードで実行される。
　
ということで、**プロキシ利用環境の自動実行において、uipath.configファイルを未編集の方**、設定を見直してみませんか？

# 本記事の対象者
* プロキシ利用環境で自動実行を実施しているが、uipath.configファイルを未編集
* 初回自動実行プロセスだけ遅い（2回目以降の実行、及び手動実行に比べて）
* 自動実行端末でパッケージDLに失敗する
* ログファイルに以下のエラーメッセージが表示される
    Unable to load the service for source https://・・・

>  全般的なプロキシ設定について
> [UiPathナレッジベースの記事](https://www.uipath.com/ja/community-blog/knowledge-base/robot-orchestrator-proxy-configuration-v202210 "Robot→Orchestrator 接続時のプロキシ設定 [v2022.10 版]")をご参照ください。

# 【uipath.configファイルの場所】
UiPath Studioのインストールディレクトリと同じ場所にあります。

「ファイルの場所を開く」機能で探すと早いです。
スタートメニューから使うと、１回目はショートカット格納場所へ行くので、そこで再度「ファイルの場所を開く」を実行してください
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1776370/e72d86f1-51b9-1894-81b0-d70d195c564e.png" width="50%">

# 【編集する値】
以下の赤字部分をを編集しましょう
　add key="ProxyAddress" value="<font color="Red">ここです！</font>" 

 ここに編集すべきプロキシのアドレスですが、レジストリエディタのProxyServerの値を記入します。
`HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyServer `
 
 ＊同じ値がWindowsの設定メニューにもありますが、こちらは勝手に「http:// 」が自動追加され、実際と異なる値が表示されるケースがあるようなので、参照先はレジストリエディタにしましょう

（補足）
オンプレOCの場合、"defaultServiceUrl"も編集する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1776370/74cc5453-c1d0-d8bd-cdfc-b7e56c05864e.png)

オンプレOCのURLに修正しておきましょう。
Vagrant+VirtualBoxでvagrant sshでsshに入れなくなった時の対処

VirtualBox+Vagrantで開発環境を作成してシステム開発をしています。
VagrantとVirtualBoxをタイトルのバージョンに上げたら```vagrant ssh```で仮想マシンにsshで入ることができなくなってしまいました。

|ソフトウェア|バージョン|
|:--|:--|
|Vagrant|2.2.19|
|VirtualBox|6.1.48|

### 現象
```
>vagrant ssh
Bad owner or permissions on C:\\Users\\myuser/.ssh/config
```
エラーメッセージに書いてある通り、configファイルへのアクセス権限が厳密でない為、エラーになっているようです。

### 対応
コマンドプロンプトを管理者で起動し、```icacls```コマンドで内容を確認すると、複数のユーザにアクセス権があります。
```batch
cd C:\Users\myuser\.ssh
icacls config

実行結果
config NT AUTHORITY\SYSTEM:(I)(F)
       BUILTIN\Administrators:(I)(F)
       PC-NAME001\myuser:(I)(F)
       S-1-5-21-7777777777-8888888888-9999999999-1001:(I)(F)
```

自分のアカウントのみ読み書きができるように権限を再設定します。
configファイルのプロパティのセキュリティを見ても、自分だけになります。
```batch
cd C:\Users\myuser\.ssh
icacls cofig /reset
icacls config /grant: r myuser:(R,W)
icacls config /inheritance: r
```
### 対応結果
これで、今まで通りに```vagrant ssh```で入れそうですが、パスワードを入力待ちになってしまします。
パスワードは、```vagrant```で良いようです。
```batch
vagrant ssh
vagrant@127.0.0.1'a password:
```

### 終わりに

以前は、```vagrant ssh```では、パスワードを入力しなくてもsshに入れたと思うんですが、そこ辺りは、今後の課題にしておこうと思います。
IntelliJ: OkHttp の使い方

こちらと同じことを行いました。
[Recipes](https://square.github.io/okhttp/recipes/)
Synchronous Get です。

サーバーは、こちらと同じ設定とします。
[IntelliJ: Java 標準ライブラリーで HTTP リクエスト](https://qiita.com/ekzemplaro/items/aba4ba29fbe869d09d76)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/9b3d54ff-50bf-9879-42c4-ae08ecabb77d.png)

## 環境

```build.gradele.kts
（省略）
dependencies {
    implementation ("com.squareup.okhttp3:okhttp:4.11.0")

    testImplementation(kotlin("test"))
（省略）
}
```

## プログラム

```Main.kt
import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.IOException

private val client = OkHttpClient()

  fun run() {
    val request = Request.Builder()
        .url("https://ekzemplaro.org/tmp/country_all.json")
        .build()

    client.newCall(request).execute().use { response ->
      if (!response.isSuccessful) throw IOException("Unexpected code $response")

      for ((name, value) in response.headers) {
        println("$name: $value")
      }

      println(response.body!!.string())
    }
  }

fun main(){
    run()
}
```

## 実行結果

```text
/usr/lib/jvm/java-1.21.0-openjdk-amd64/bin/java -javaagent:/snap/intellij-idea-community/464/lib/idea_rt.jar=38511:/snap/intellij-idea-community/464/bin -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath /home/uchida/IdeaProjects/get05/build/classes/kotlin/main:/home/uchida/.gradle/caches/modules-2/files-2.1/com.squareup.okhttp3/okhttp/4.10.0/cd63657ac15770ed1420647154c9f44645533bef/okhttp-4.10.0.jar:/home/uchida/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.9.0/e000bd084353d84c9e888f6fb341dc1f5b79d948/kotlin-stdlib-jdk8-1.9.0.jar:/home/uchida/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.9.0/8ee15ef0c67dc83d874f412d84378d7f0eb50b63/kotlin-stdlib-1.9.0.jar:/home/uchida/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.9.0/f320478990d05e0cfaadd74f9619fd6027adbf37/kotlin-stdlib-jdk7-1.9.0.jar:/home/uchida/.gradle/caches/modules-2/files-2.1/com.squareup.okio/okio-jvm/3.0.0/ab5a73fa2ccb4a36b0b5c69fe10b16d0255bcf8/okio-jvm-3.0.0.jar:/home/uchida/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.9.0/cd65c21cfd1eec4d44ef09f9f52b6d9f8a720636/kotlin-stdlib-common-1.9.0.jar:/home/uchida/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar MainKt
Server: nginx/1.24.0
Date: Sat, 04 Nov 2023 08:12:47 GMT
Content-Type: application/json
Content-Length: 407
Last-Modified: Sat, 04 Nov 2023 02:02:15 GMT
Connection: keep-alive
ETag: "6545a627-197"
Access-Control-Allow-Origin: *
Accept-Ranges: bytes
[{"id":18,"countryName":"Kenya"},
{"id":20,"countryName":"Tanzania"},
{"id":21,"countryName":"Ethiopia"},
{"id":22,"countryName":"Malawi"},
{"id":23,"countryName":"Country"},
{"id":24,"countryName":"Country"},
{"id":25,"countryName":"Kenya"},
{"id":26,"countryName":"Country"},
{"id":27,"countryName":"USA"},
{"id":28,"countryName":"USA"},
{"id":29,"countryName":"Kenya"},
{"id":30,"countryName":"Kenya"}]



Process finished with exit code 0
```
【Ruby on rails】どちらか一方必須のバリデーション

# はじめに
プログラミングを勉強して2か月半ほどです。
プログラミングスクールを卒業し、現在就職活動をしています。

今回はオリジナルアプリでどちらか一方必須のバリデーションを設定したので、その方法について共有したいと思います。

# Let's start!!!
今回、私のオリジナルアプリでは、ユーザーがアイテムを投稿する際に、PDFまたは画像のどちらか一方が必須であるバリデーションを設定しました。さらに、両方が入力されている場合も、一方も入力されていない場合も保存を許可しないように設定しました。

それでは、実装していきましょう！

## モデルへの記述

```item.rb
class Item < ApplicationRecord
  
  validate :image_or_pdf

  def image_or_pdf
    return if item_image.present? ^ pdf.present?

    errors.add(:base, '画像またはPDFのどちらか一方を入力してください')
  end

end
```

この例では、カスタムバリデーションを作成しています。
`return if item_image.present? ^ pdf.present?`この記述でどちらか一方を設定しています。
この記述の中でのポイントは`^`です。
`^`は排他的論理はというものです。
`※排他的論理和とは、ブール論理や古典論理、ビット演算などにおいて、2つの入力のどちらか片方が真でもう片方が偽の時には結果が真となり、両方とも真あるいは両方とも偽の時は偽となる演算（論理演算）である。XOR、EOR、EX-OR（エクスオア、エックスオア、エクソア）などと略称される。
wikipediaより引用`

つまり、PDFか画像のどちらかの値があればtrue、PDFと画像のどちらも入力されている場合や入力されていない場合はfalseを返します。


もう一つのポイントは、`validate :image_or_pdf`です。
みなさん気づいていると思いますが、普段のバリデーションの設定時と少し違うところがあります。
`validates`ではなく`validate`になっています。
今回のようにバリデーションをカスタムした場合は`validate`と記述する必要があります。

# 終わりに
今回はどちらか一方必須のバリデーションの設定方法を共有させて頂きました。
このようにバリデーションをカスタムすることができれば、オリジナルアプリの作成にも幅が広がりそうです。
みなさんのお役に立てていれば幸いです！

今回も最後まで読んでいただきありがとうございました！
JupyterNotebookに画像を埋め込むのに便利なの作った

## 使い方

1. 画像をクリップボードにコピー。`Windows + Shift + S` でスクショ等
2. 下記関数を読んでpic2html()を実行。クリップボードの画像がhtmlに変換されクリップボードに戻される
3. Markdown形式のセルに貼り付けてEnter

## 必要ライブラリ

``` python
pip install pillow
pip install pyperclip
```

## 注意点

クリップボードを読み込む都合上ローカルのJupyterでしか動かないです。リモートのJupyterやColab等では使えません。
macOSとWindowsでは動作確認済みです

## コード
``` python
import base64
import io
from PIL import ImageGrab
import pyperclip

def pic2html():

    im = ImageGrab.grabclipboard()
    if not im:
        print("画像をコピーしてから実行してください")
        return

    w, h = im.size
    max_width = 970
    max_height = 500
    nw = min(w, max_width)    
    nh = int(h * (nw / w))
    if nh > max_height:
        nh = min(h, max_height)
        nw = int(w * (nh / h))

    im = im.resize((nw,nh))
    buf = io.BytesIO()
    im.save(buf, "webp")
    data = base64.b64encode(buf.getvalue()).decode('utf-8')
    html = '<img src="data:image/png;base64,{}" style="border:solid 1px #000000" width="{}" height="{}">'.format(
        data, im.width - 2, im.height - 2
    )
    try:
        pyperclip.copy(html)
        print("クリップボードにコピーされました")
    except Exception as e:
        print("クリップボードへのコピーに失敗しました:", str(e))
```

## いきさつ
JupyterNotebookで集計を詳しく説明する際にExcelの資料をコピペで貼り付けたかった。
1. 画像を外部ファイルとして参照するようにするのが普通だが、ノートをどこに持って行っても表示できるようにしておきたかった。ファイルをどこかにアップしてURLを参照するやり方は面倒でやりたくなかった。
2. Base64で埋め込む方法が良いのだが、画像サイズを小さくしないと文字数が増えすぎるので変換ツールを作ることにした。高圧縮のwebp形式で解像度をノートブックで表示するのにちょうどいい感じにする
3. 画像の読み込みのために、ファイルのパスを指定するのは面倒なのでクリップボードを使うことにした
intellijで変更があったファイルを開くコマンド

## 背景
Intellijで色々作業していると、いざgit add,commitする前にそれぞれ確認したいと思うのですが、開いているファイルが多すぎて見えづらかったり対象ファイルを開いていなかったりします。
そこで、確認するファイル（＝git add, commitしていない前提のファイル）を一気に開くことができるコマンドを作りました。
※intellijをideaコマンドで開ける設定にしてある前提があります。


## コマンド
```bash
git status -s | rev | cut -d " " -f1 | rev | grep -v "/$" | xargs idea
```
Jetson Nano超入門を始めてみる

AIエンジニアにあこがれて、NVIDIAさんのJetson Nanoに入門してみます。

参考文献
- Jetson Nano超入門
https://www.switch-science.com/products/7398
- Get Started With Jetson Nano Developer Kit
https://developer.nvidia.com/embedded/learn/get-started-jetson-nano-devkit

# サマリ
- 秋葉原　千石電商にてJetson nano B1を入手
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/cf2a99e7-ef72-7876-ed56-7e0ba48ab047.png)
- 構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/0dc928af-36db-f8d0-30e8-7f82481881ed.png)
- TerminalでslLコマンドの実行までできた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/2a933afd-2dd6-64c3-a47f-2aa63919e0a6.png)


# 詳細手順
## OSのダウンロード＆セットアップ
https://developer.nvidia.com/embedded/learn/get-started-jetson-nano-devkit#write
- SD Card Image (OS的なもの)をダウンロード
 Jetson Nano Developer Kit SD Card Image : sd-blob-b01.img 6Gバイト　
- SDカードのフォーマットでSDカードをきれいにする
https://www.sdcard.org/downloads/formatter/sd-memory-card-formatter-for-windows-download/
- SDカードへライターで.img焼く
https://etcher.balena.io/#download-etcher

## ハードのセットアップ
https://developer.nvidia.com/embedded/learn/get-started-jetson-nano-devkit#setup
* microUSBカードを刺す
* HDMIを刺す
* micro USB(電源)を刺す
* intitial set upが走り出す

## Next step
### JETSON AI COURSES AND CERTIFICATIONS
https://developer.nvidia.com/embedded/learn/jetson-ai-certification-programs#course_outline
Jetsonを使ったAIの資格があるらしい。ゲットしたい。

### GUI
ソリティアが動きました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/aba711ae-0ec3-3993-f584-250078ec20d4.png)

### CLI
slコマンドが動きました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/f0e31c2e-c1b1-e24a-b61e-4a3d34296ba1.png)

カメラモジュールも買ったので、物体検知とかしたい。
IntelliJ: Java 標準ライブラリーで HTTP リクエスト

次のサンプルの
Java 標準ライブラリの API を使用して Kotlin で HTTP リクエストを作成する
と同じことを行いました。
[Kotlin で HTTP リクエストを作成する](https://www.delftstack.com/ja/howto/kotlin/kotlin-http-request/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/c748a48b-5391-8637-f1bd-da090cf35e45.png)

## サーバー仕様
次のようにして、JSON が GET で取得できるとします。

```bash
http https://ekzemplaro.org/tmp/country_all.json
```

取得できる JSON

```json:country_all.json
[{"id":18,"countryName":"Kenya"},
{"id":20,"countryName":"Tanzania"},
{"id":21,"countryName":"Ethiopia"},
{"id":22,"countryName":"Malawi"},
{"id":23,"countryName":"Country"},
{"id":24,"countryName":"Country"},
{"id":25,"countryName":"Kenya"},
{"id":26,"countryName":"Country"},
{"id":27,"countryName":"USA"},
{"id":28,"countryName":"USA"},
{"id":29,"countryName":"Kenya"},
{"id":30,"countryName":"Kenya"}]
```

## プログラム

```Main.kt
import java.net.HttpURLConnection
import java.net.URI

fun main(){

    val url_string = "https://ekzemplaro.org/tmp/country_all.json"
    val uri =  URI(url_string)
    val url = uri.toURL()
    val con = url.openConnection() as HttpURLConnection

    // 接続設定(ミリ秒で指定)
    con.connectTimeout = 20_000 // 20 秒
    con.readTimeout = 20_000    // 20 秒
    con.requestMethod = "GET"   // GETの場合は省略可能

    // 接続を確立
    con.connect()

    // レスポンスを取得
    val str = con.inputStream.bufferedReader(Charsets.UTF_8).use { br ->
        br.readLines().joinToString("")
    }

    // 表示
    println(str)
}
```

## 実行結果

```text
/usr/lib/jvm/java-1.21.0-openjdk-amd64/bin/java -javaagent:/snap/intellij-idea-community/464/lib/idea_rt.jar=36781:/snap/intellij-idea-community/464/bin -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath /home/uchida/IdeaProjects/get01/build/classes/kotlin/main:/home/uchida/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.9.0/e000bd084353d84c9e888f6fb341dc1f5b79d948/kotlin-stdlib-jdk8-1.9.0.jar:/home/uchida/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.9.0/f320478990d05e0cfaadd74f9619fd6027adbf37/kotlin-stdlib-jdk7-1.9.0.jar:/home/uchida/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.9.0/8ee15ef0c67dc83d874f412d84378d7f0eb50b63/kotlin-stdlib-1.9.0.jar:/home/uchida/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.9.0/cd65c21cfd1eec4d44ef09f9f52b6d9f8a720636/kotlin-stdlib-common-1.9.0.jar:/home/uchida/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar MainKt
[{"id":18,"countryName":"Kenya"},{"id":20,"countryName":"Tanzania"},{"id":21,"countryName":"Ethiopia"},{"id":22,"countryName":"Malawi"},{"id":23,"countryName":"Country"},{"id":24,"countryName":"Country"},{"id":25,"countryName":"Kenya"},{"id":26,"countryName":"Country"},{"id":27,"countryName":"USA"},{"id":28,"countryName":"USA"},{"id":29,"countryName":"Kenya"},{"id":30,"countryName":"Kenya"}]

Process finished with exit code 0
```
Rails ToDoアプリにて　完了機能追加した

<h1>この記事を書くことにした理由</h1>
<p>これから何度もポートフォリオ制作にて使う気がしたので、今後のために書き残そうとした。</p>
<h2>やり方</h2>
<h3>最初はmigrateの作成or追加から</h3>

```console
$rails g migration テーブル名（例　CreateToDos)
```
テーブルも新しく作る場合
```ruby:テーブル名(例 日時_create_to_dos.rb）
class テーブル名(例 日時_create_to_dos.rb） < ActiveRecord::Migration[7.0]
    def change
    create_table :テーブル名(例 to_dos) do |t|
        t.追加したい型（例　string） :カラム名(例 text)
        t.boolomen :done(一例）
        
        t.timestamps
    end
  end
end
```
既存のテーブルに追加する場合
```ruby:テーブル名(例 日時_create_to_dos.rb）
class テーブル名(例 日時_create_to_dos.rb） < ActiveRecord::Migration[7.0]
    def change
        add_column :既存のテーブル名(例 to_dos), :done, :boolean
    end
  end
end
```
どっちか入力したら、rails db:migrateを忘れずに

<h3>次にrootとcontroller</h3>
rootから

```ruby:routes.rb
 post '/tasks/:id/done' => 'tasks#done', as: 'done'
```

controller
```ruby:tasks_controller.rb
def index
    @todo = ToDo.where(user_id: session[:user_id])
end

def done
    @todo = ToDo.find(params[:id])
    if @todo.done
      @todo.update(done: false)
      redirect_to tasks_path
    else
      @todo.update(done: true)
      redirect_to tasks_path
    end
end
```

<h3>最後にボタンを追加する</h3>

```erb:index.html.erb
<% @todo.each do |todo| %>
<%= button_to '完了', done_path(todo.id),  date:{"turbo-method": :post} %>
<% end %>
```

cssとかは好きなようにレイアウトすれば完成
CCNA（200-301）合格 未経験35歳の奮闘

はじめに
将来エンジニアとして業務に就きたいと考え、最初に学習したのがCCNAであり、これに合格することで、ネットワークの基礎が身に付くとのアドバイスを受けて学習を開始した。合格までの学習期間は約２か月で合格することができた。
同じような境遇の方に向けて少しでもお役に立てればと思い記事にしてみました。

１　合格のためにしたこと及び使用教材
使用教材は「黒本のみ」です。独学です。
ひたすら理解と暗記です。５回以上復習で読み返し、理解を深めるために動画を見たこともありました（動画の解説は動画によって異なるため、あくまで参考に少しだけ見る。）。１日当たりの学習時間は恥ずかしくて言えないくらいに勉強しました。。２か月で合格できたものの、合格点ギリギリでした。はっきり言って難しいです。勉強しているうちに、２巡目あたりから変な自信がついてきますが、それは改めた方が良いです。

２　感じた難易度
先程も記載しましたが、「難しい」です。情報収集を行ううちに、必殺技を使う方法について目にすると思いますが、自らしっかり学習することを強くおすすめします。問題もコロコロ変わるらしいですし、理解しないと後々記憶と実際に業務等に触れたときに記憶と繋がりません。

３　受験してびっくりしたことｗ
出ない出ないとネットに記載のあったシミュレーション問題・・・出ます。やはりCCNAは実務で経験されている現役の方向けの内容となっています(´;ω;｀)

さいごに
不合格となってしまった方や、最初の方で挫折してしまった方、挫折しそうな方、これから学習する方に激励するとすれば、「とにかくCCNAの教材はネットワークの基礎です。教材を完璧にしてやっと土台に乗り、そこからネットワークに関する学習が進むと思って、黒本を頭に叩き込んでください。」
私はAWS SAAを１年以内に取得したいなーと漠然と考えています(笑)では
Windows11でOracle VM VirtualBox 7.0.8をSetupしようとするとエラーになる

# Windows11のノートPCを新調しました
　以前使っていたパソコンがかなり古いものを使っていたので新調しました。本当はデスクトップを買いたい気持ちももちろんあるのですが、お財布とかその他事情もろもろ加味して素人判断で一番コスパのよさそうなノートを購入しました(この前置きいる？)。

　早速勉強のためにVirtuarl Boxをダウンロード…と思っていたところ、エラーが出たので備忘録として残しておきます。
https://www.oracle.com/jp/virtualization/technologies/vm/downloads/virtualbox-downloads.html

# 出てきたエラー

　 どうやら最新バージョンではC++2019が足りないとのこと。 VirtuarlBoxを利用して勉強するためには、まずその環境を準備する必要がありそう。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3604849/20114671-678f-d640-e139-92fdb066752f.png)

# 必要バージョンのC++をインストールしてから再度実施
https://learn.microsoft.com/ja-jp/cpp/windows/latest-supported-vc-redist?view=msvc-170#visual-studio-2015-2017-2019-and-2022

上記のページから、環境に合わせたC++をダウンロード、インストールする。
※ご自身のパソコンのCPUの調べ方は下記補足欄ご参照。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3604849/543c1889-02d0-dceb-8d48-bd4ba62b0061.png)

上記完了後、もう一度VirtualBoxのインストーラーを起動すると、
エラーは解除されて無事にインストールされる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3604849/7d09ed84-ecfd-fd8c-b8dd-4fcab68847d5.png)

↓Nextで進めていってFinishで完了。
本当にしたいのはこの先なんですけど、疲れたので一休みします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3604849/551fe5b1-f047-5853-f954-a235c7deeb1d.png)


# 補足：CPUアーキテクチャ種別の調べ方
コマンドプロンプトで下記を打つと出てきました。
```
>echo %PROCESSOR_ARCHITECTURE%
AMD64
```

私の環境の場合x64でした。

# 参考記事
■Virtualbox7インストール時のVisual C++2019エラーの対処方法を解説
https://1nux.com/archives/318

■CPUアーキテクチャの種類(x86, x64, arm)
https://www.wakuwakubank.com/posts/809-it-cpu-x86-x64-arm/
オブジェクト指向　なぜ型を指定するのか

### プログラムにおいて型を指定する理由
##### コンパイラにメモリ領域の大きさを教えるため
変数に必要なメモリ領域は、整数型なら32ビット、浮動小数点なら64ビットといったように、型によって自動的に決まる。このため変数の型を宣言することで、コンパイラはその変数をメモリ上に確保するために必要なメモリ容量の計算が可能になる。

##### プログラムのエラーの防止をするため
整数と文字列の掛け算、配列からの浮動小数点の引き算など、意味的におかしなロジックが書かれた場合に、プログラムのコンパイル時や実行にエラーを明示することができる。

### オブジェクト指向プログラミングでは、クラスも型として定義できるようになった
##### クラスを使った型宣言
```java
// 変数の型にクラスを指定する
TextFileReader reader;

// メソッドの引数の型にクラスを指定する
int getCount(TextReader reader) { /* ロジックは省略 */ }

// メソッドの戻り値の値にクラスを指定する
TextReader getDefaultReader() { /* ロジックは省略 */ }
```

##### 静的な型付け
プログラムのコンパイル時点でエラーを検出する方式。JavaやC#などが採用されている。

##### 動的な型付け
プログラムの実行時点でエラーを検出する方式。PythonやRuby,PHP,Smalltalkなどが採用されている。
「本を一度読んで終わり」からは卒業したい

## 背景

![activity.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551316/949c2079-8476-bb14-19e8-ac49b5dc9243.jpeg)


「本を一度読んだら終わり」

こんな状況に出くわしたことはありませんか？

私は沢山あります。
2回以上読んだ本は無いですし、アウトプットを実践したこともほとんどない気がします。

――これではまずい。

そう思い、私は現在作成しているアプリ（Yommy）にて「アウトプット機能」というものを作りました。

これ自体は大した機能ではないのですが、どういった考えのもと、作成したのかと、今後どうやってアウトプットのしやすさを向上させていくかを、簡単に説明させてください。

## アウトプット機能

そもそもアウトプット機能とは何なのか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551316/5666e48e-cb9a-9a85-6272-a3bc521bed30.png)

https://yommy-books.com/detail/83/

アウトプット機能とは、「書籍に対してアウトプット吐き出せる」機能のことです。
元々は書籍にメモをつける程度の機能だったのですが、メモだと曖昧過ぎるため、「アウトプット」という意味合いをつけることにしました。

また、レビューは「1回のみ」に対して、アウトプットは何回でも作成できるようにしています。

この機能の使い方はとても簡単で、検索バーから書籍を検索し、「アウトプット」タブにて自分なりの考えや学んだことをアウトプットするだけです。

## 書籍アウトプットの問題点

次に、現状の書籍のアウトプットに関する問題点について触れたいと思います。

まず、アウトプットの問題点は何なのでしょうか？

私が思うに、冒頭にもあげた「一度読んだら終わり」という現象が一番の問題だと思います。

いわゆる「インプットはしたがアウトプットはしない」というパターンで、これは身に付きにくい読書方法かと思います。

では、何故これが起きてしまうのか。
私は主に３つの原因があると思っています。

1. 発信する場所がない
2. アウトプットの管理が面倒くさい
3. モチベーションが続かない

それぞれ詳しく見ます。

### 1. 発信する場所がない

本来、本を読んだらアウトプットしなければいけませんが、アウトプットする機会って、普通に暮らしていたら中々巡り合うものではないと思っています。

そのため、アウトプットするには自らが発信して、「私はこう思っている」というのを声に出して言わなければならないのですが、そういった発信をする場所って、中々ないです。

たまにSNSを使って発信している人もいますが、趣味アカの場合、投稿一覧を汚すわけにもいかず、躊躇する人も多いでしょう。

つまり、一般的には「気軽にアウトプットできる」環境が無い、というのが一つの原因かと思っています。

### 2. アウトプットの管理が面倒くさい

昔、書籍に対してアウトプットを管理するというのを、Notionで行ったことがあります。
NotionのDBを使って、記事を書いていく感じで整理していました。

しかし、これがとても面倒くさかったです。
いちいち書籍情報をNotionに入力して、そこからがスタート。
これを毎回やっていると、次第に管理がおろそかになり、10冊目ぐらいからやめてしまいます。

結局のところ、書籍管理とアウトプットの管理を同時進行で進めなければいけないのが、面倒くさいポイントだと思っています。

つまり、書籍管理しているプラットフォームにアウトプットできれば、それらの問題は解決すると考えています。

### 3. モチベーションが続かない

結局はここにいきつくのですが。何をやるにもモチベーション維持が大事だとは思っています。

Yommyでは、日々のアウトプットを「活動履歴」で残すようにしています。

![activity.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551316/b11bc926-d307-1098-804c-edd858e41cfb.jpeg)

エンジニアにとって見慣れた風景ですね。

マイページにアクセスすると上記のような状態が見れます。

これは、アウトプットをコミットとして扱い、アウトプットを増やせば増やすほど草が生えるようにしています。

この草の生える感覚を、一般の方にも提供するためにこの機能を作りました。

これで少しでもモチベーション維持できるようになればいいかなー、って思っています。

## 「本を一度読んで終わり」から卒業するために

ここまで、「一度読んだら終わり」になる、３つの原因を見てきました。

――では結局のところ「本を一度読んだら終わり」から卒業するためにはどうしたらいいのでしょうか？

アプリを使わない場合で考えると、「書籍に対して直接メモをぺたぺた張り付ける」のが、結局のところ一番良いアウトプットだと思っています。

本に直接残せるのなら、メモの管理をしなくてもいいですし、愚直にアウトプットだけを考えられるようになります。

これをアプリで考えた場合、「書籍詳細から直接アウトプットを書く」、これが一番楽な方法だと思っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551316/d3b4b553-e8f6-c882-74b3-7191f5d3b877.png)

ということで、Yommyでは書籍詳細からアウトプットを書く方法を採用しています。

https://yommy-books.com/detail/83/

個人的にはこれが一番アウトプットしやすいかなー、って思っています。

## 最後に

ここまで読んでいただきありがとうございます。
最後になりますが、宣伝になります。

現在Yommyという書籍管理アプリケーションを作成しています。

もしよろしければ、利用して頂けると物凄く喜びます。

https://yommy-books.com/detail/83/

リーダブルコードへのリンクを貼りましたので、自分の考えをアウトプットに出力して頂けると幸いです。

よろしくお願い致します。
【UE,C++メモ -1- 】 Live Codingについて

## あくまで仮実装という認識
C++コードを記述しファイルを保存。
UEエディタ上に記述内容を反映するためにLiveCodingを実行。
しっかりと記述内容が反映されている。
**しかし、このままエディタを閉じてしまうと次回起動時は記述内容が反映されていない状態で起動してしまう。**
起動した際いちいちLiveCodingを実行すれば記述内容が反映されるが、、、
レベル内に配置したC++データは、記述内容が反映されていない状態に引き戻るのでなくなってしまう。
## IDE上でビルドすることで記述内容が保存される。
#### VisualStudioの一例を挙げる。
デバッグ無しで開始［ctlr + F5］。ウィンドウ中央上部の色が塗りつぶされていない再生マークを押しても実行できる。
実行するとビルドが開始される。**UEエディタを起動しているとビルドに失敗するので、実行する際はエディタを一度閉じる必要がある**(案外面倒である。他にいい方法があるかもしれない。)
### 追記
Live Codingは[ctlr + alt * F11]でも実行できる。
AWS EC2でのbundle install中にプロセスが停止する問題の解決方法


# はじめに

AWSを利用してアプリケーションを公開しています。RailsアプリケーションをEC2にデプロイしている際に、Gemをインストールするためにbundle installを実行したところ、以下のような表示から先に進まなくなってしまいました。

```terminal:EC2
Installing gem名 gemのバージョン with native extensions
Building native extensions. This could take a while…
```


# 原因

しばらく待っても上記の状態から進まなかったため、プロセスを中断し、何が問題かを探るべくログを確認しました。その結果、**bundle installが4つのプロセスで並行して実行されている**ことがわかりました

```terminal:EC2
 DEBUG [b81b3574] Command: ( export RBENV_ROOT="$HOME/.rbenv" RBENV_VERSION="3.0.3" ; $HOME/.rbenv/bin/rbenv exec bundle install --jobs 4 --quiet )
```

この情報を基にいろいろと調べたところ、**複数のプロセスでbundle installを実行した際に、そのうちのどれか１つでも問題が発生すると、複数のプロセスのすべてが止まってしまう**ということがわかりました。

そこで、**１つのプロセスでbundle installを実行することで、どのGemに問題があるのかを特定できるのではないか**と考えました。


# 実施した対応
複数のプロセスでの実行ではなく、**1つずつbundle installを実行する**ように変更しました。
```terminal:EC2
bundle install --jobs=1
```



# 結果
エラーの原因となっているGemを特定するために上記の対応を行いましたが、結果的にこれで**bundle installが成功しました**。


# 原因を調査

一つずつbundle installを実行したことで問題が解消されたという結果から、**個々のGemに不具合は存在しなかった**のではないかと考えました。

そこで、bundle installがうまくいかなかった原因を調べたところ、以下のような可能性があることがわかりました。

+ EC2インスタンスのリソース不足
+ 並列でインストールを行った場合、Gemの依存関係が適切に処理されないことがある
+ 並列処理が原因でプログラムが予期せぬ挙動を示し、エラーやバグが発生する可能性がある

# おわりに

今回は、AWSのEC2インスタンスでbundle installを実行した際に直面したトラブルと、それに対する解決方法について共有させていただきました。同じ問題でお困りの方がいらっしゃれば、この記事が一助となれば幸いです。


### 最後までお読みいただきまして、ありがとうございました！
mpv とループの設定

日本語の記事がなかったので念のため

動画プレイヤーと言えば [mpv](https://mpv.io/)
軽いしキーボード操作がしやすい

初期設定だと動画の最後まで来たときにウィンドウが閉じる
デフォルトでループするように設定するには、
- mpv のフォルダに移動
    - Windows であれば `C:\users\USERNAME\AppData\Roaming\mpv\mpv.conf`
- mpv.conf を作成し、`loop-file=inf` と書く

参考：https://superuser.com/questions/1581867/how-to-infinite-loop-every-video-i-play-as-defaut-on-mpv-player-without-having-t
「Teams の複数テナント切り替えがメンドクサイ」への対応

こんにちは。
蒙古タンメン中本に心を奪われた男です。
久々の Qiitaです。あれ？すっごく編集画面が使いやすくなってない？
## はじめに
Teams は複数テナントを同時に表示できません。
他社 Teams を参照するにはテナント切り替えが必要です。
これ、意外とメンドクサイので、改善する方法を説明して行きます。

11/4 追記）
直近のアップデートでテナント間の切り替えがすごくラクになった噂を聞きました。
ひょっとしたら、こんな事をしなくてよくなるかも。

## ブラウザ版Teamsを使う
単純な話なんですが、「アプリ版 Teams」 と「ブラウザ版 Teams」両方使えば、複数のテナントを同時に開くことができます。
以下、ブラウザで Teams を開く方法です。

0. Teams で対象Team の「...」→「チームのリンクを取得」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/46da95c5-12cb-b8ff-731d-948512dc8f05.png)

0. URL を「コピー」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/7ccf3b22-0532-958c-d43a-d69d2ec9ea92.png)

0. Webブラウザ（Edge や Chrome）を起動し URL を Ctrl+V で貼り付け、「代わりに Web アプリを使用」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/a23a8a5f-b418-19ed-24b4-09d3eee015f7.png)

以上で Teams をブラウザで 開くことができます。

Edge と Chrome と アプリ版を使えば、３テナントに同時アクセス可能。
これによって、同時に複数のテナントの Teams にアクセスすることができます。
あとは、ブックマークを設定するなどで完了です。

（アクセスできるのは１ブラウザで１テナントまでのようです。同じブラウザで同時に複数のテナントにアクセスすると、先に開いた方にアクセスできなくなります）



## アプリとして登録する
Edge で開いた Teams を「アプリ」として登録しておくと、起動が楽になります。

0. Edge で Teams を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/1ce64674-b5df-0dda-a2f0-05b76ca3d00a.png)

0. Edge の右上「...」→「アプリ」→「このサイトをアプリとしてインストール」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/22e734c7-9846-9627-1672-771097bf4835.png)

0. ショートカット名を設定して、「インストール」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/d0c84e35-320a-03d7-2d33-b0dc8203098e.png)

0. ショートカットを設定する場所を設定して「許可」
（タスクバーとデスクトップがオススメ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/625fcaba-5130-2c25-556e-3e97a531ab5a.png)

0. デスクトップ、タスクバーにアイコンが追加されたことを確認
デスクトップ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/28defd03-0bfd-e480-e3e3-ad0ea052e00a.png)
タスクバー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/14d05a72-8e23-6d06-94f9-7512a9b5f16e.png)

以上です。


## 補足
* チャットでのコミュニケーションって思いついた時にちゃちゃっとやりたいんですよね。
「一手間掛かる」というハードルは意外と大きいので、できるだけ排除したく。
ボクは 会社スマホ と 個人スマホ でテナントを分けて使っていたりします。

* この記事を書いている途中で以下のようなメッセージが表示されました。
一旦 サインアウト して サインインしなおしたら解決。
大した問題ではないと思われます（深追いしない）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955093/9aeb31ff-1de5-5e5d-49c9-527b18b0f1c0.png)

* 複数アカウントを切り替え、１ブラウザで複数テナントにアクセスすることもできるようです。
でも、自社ではできないよな・・・と。
https://qiita.com/KCbogard/items/f70358c4de0fb2b95c12 

以上です。
【APIの仕組み】同一オリジンポリシーとCORS

# 【APIの仕組み】同一オリジンポリシーとCORS

この記事では、ウェブのキーワードである「オリジン」の構成要素について説明し、さらに「同一オリジンポリシー」と「CORS」の重要性についても議論します。

## ウェブの主要な用語

1. **スキーム（プロトコル）**：ウェブアクセスのための通信プロトコルを示します。一般的なものには、`http://`や`https://`などがあります。`http://`は通信が暗号化されていない一般的なプロトコルであり、`https://`はセキュアな通信を提供します。

2. **ホスト**：ウェブサーバーのアドレスを指します。一般的なものには、`www`や`localhost`があります。これはウェブサイトがホストされている場所を示します。

3. **ドメイン**：ウェブサイトの識別名です。例えば、`twitter.com`や`youtube.com`などがドメインです。これにより、ウェブサイトを一意に識別できます。

4. **ポート**：ウェブサーバーにアクセスするための通信ポートを示します。通常、`localhost:3000`のようにポート番号が指定されます。これにより、複数のアプリケーションが同じホスト上で異なるポートで実行できます。

5. **オリジン**：ウェブアプリケーションの安全性とセキュリティを考える上で非常に重要な概念で、スキーム、ホスト、ドメイン、およびポートからなる識別子です。パスはオリジンに含まれません。例えば、`https://twitter.com`は一つのオリジンを表します。

## 同一オリジンポリシー（SOP）

**同一オリジンポリシー（SOP）**は、セキュリティの観点から非常に重要な原則です。これは、ウェブブラウザが異なるオリジン間でデータやコードのアクセスを制限する仕組みです。同一オリジン内のウェブページは、互いに自由にデータを共有できますが、異なるオリジンのウェブページからのアクセスは制限されます。

同一オリジンポリシーの目的は、セキュリティを向上させ、クロスサイトリクエストフォージェリ（CSRF）やクロスサイトスクリプティング（XSS）などの攻撃を防ぐことです。これにより、悪意のあるウェブサイトからのデータの不正利用が制限されます。

## CORS（Cross-Origin Resource Sharing）

一方、**CORS（Cross-Origin Resource Sharing）**は、同一オリジンポリシーに対抗する仕組みです。CORSは、異なるオリジンからのリクエストを許可するために使用されます。これは、異なるオリジンのウェブアプリケーション間でデータを共有したり、APIにアクセスしたりする際に非常に役立ちます。

CORSの設定は、ウェブサーバー側で行われ、許可されたオリジンからのリクエストを受け入れるように構成されます。一般的に、CORSヘッダーを使用して、許可されたオリジンを指定します。

## CORSとRailsのrack.cors

CORSを実装するために、Railsでは一般的に**rack.cors**というGemを使用します。これにより、異なるオリジンからのアクセスを許可したり制限したりする設定が可能になります。これにより、ウェブアプリケーションがセキュリティを維持しながら、必要なデータの共有ができるようになります。

まとめると、ウェブのセキュリティとデータ共有にはオリジン、同一オリジンポリシー、CORSなどの概念が関与しており、これらを理解することはウェブアプリケーションのセキュリティ強化に役立ちます。同時に、適切に設定されたCORSは、異なるオリジン間でのデータ共有を実現し、ウェブアプリケーションの機能向上に寄与します。
MyBatisでコレクションを返す

MyBatisでは親子関係のテーブルのレコードをマッピングによって取得することができます。

## POJO

Javaでは以下のように子テーブルをネストしたPOJOを用意しておきます。

```java
public class MainJoho implements Serializable {

	private String mainId;

	private String mainName;

	private List<SubJoho> subJohoList;
}
```
```java
public class SubJoho {

	private String subId;

	private String subName;

 	private String subType;
}
```
## Mapper

Mapperではcollectionを使ってネストした子テーブルをマッピングできるようにします。

```xml
  <resultMap id="MainJohoResultMap" type="jp.co.hoge.pojo.MainJoho">
    <result column="MAIN_ID" jdbcType="VARCHAR" property="mainId" />
    <result column="MAIN_NAME" jdbcType="VARCHAR" property="mainName" />
    <collection ofType="jp.co.hoge.pojo.SubJoho" property="subJohoList">
       <result column="SUB_ID" property="subId" />
       <result column="SUB_NAME" property="subName" />
       <result column="SUB_TYPE" property="subType" />
     </collection>
  </resultMap>
  <select id="selectList" resultMap="MainJohoResultMap">
    SELECT
    M_MAIN.MAIN_ID
    , MAIN_NAME
    , SUB_ID
    , SUB_NAME
    , SUB_TYPE
    FROM M_MAIN
    LEFT JOIN M_SUB
    ON M_MAIN.MAIN_ID = M_SUB.MAIN_ID
  </select>
```
[SAA-C03] AWS Cost and Usage Report

# 更新日
- 2023/11/04 初回

# [AWS Cost and Usage Report](https://aws.amazon.com/jp/aws-cost-management/aws-cost-and-usage-reporting/)

## これ何？[^1]
AWSのコストと使用状況データをより詳しく見る仕組み。CURと略されるらしい。[^3]

## 何が便利？
- Budgetsと違い、使用状況も同時に見ることができるため原因分析もしやすいので、最適化が可能。[^1]
- AthenaやRedshift,S3と連携が可能。[^3]
- Budgets同様、月次、週次、日次で集計可能。[^3]

## 利用例
- そのまま

# 実装[^3]
のちほど追記します

# Ref
[^1]: [Amazon EventBridgeとは何か](https://qiita.com/ishibashi-futoshi/items/586ebe17b174a478eb6a)
[^2]: [AWS::CUR::ReportDefinition](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cur-reportdefinition.html)
[SAA-C03] Amazon Budgets

# 更新日
- 2023/11/03 初回

# [Amazon Budgets](https://aws.amazon.com/jp/aws-cost-management/aws-budgets/)

## これ何？[^1]
その名の通り、AWSのコストを算出する仕組み。月・週・日毎のコストを予測値とともにBudgetReportを算出することもできる。

## 何が便利？
- 条件に応じたコストを算出ができる。[^2]
- CloudFormationでも算出できそう。属人性を排除できるのはコスト管理工数削減にも寄与しそう。[^3]

## 利用例
- CloudWatchなどと組み合わせて毎月定期的なレポートを算出することもできそう。
- 予算目標値に達した際に承認プロセスを要求することも可能。[^4]

# 実装[^3]
のちほど追記します

# Ref
[^1]: [AWS BudgetsでAWSの想定外コストを監視する](https://www.stylez.co.jp/columns/monitor_aws_unexpected_costs_with_aws_budget/)
[^2]: [AWS Budgetsとは？コスト予算の設定](https://www.skyarch.net/column/aws-budgets/)
[^3]: [AWS::Budgets::Budget](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-budgets-budget.html)
[^4]: [AWS Budgets](https://aws.amazon.com/jp/aws-cost-management/aws-budgets/)
ESP32マルチスレッドとSPI

# ESP32等のマルチスレッディングでSPI使用する際にはHSPI選択が必要な場合がある。

* 標準ライブラリの　SPI　をはじめとする大抵のライブラリでは VSPI が暗黙で選択されている。
* マルチスレッドで複数のSPI処理（例えばTFT描画とセンサ入力とかね）を並行処理する場合、VSPIとHSPIを使い分けることで同時処理できる。
:::note warn
* ただし、pin配置で「HSPI」とされているpinに繋ぐだけではHSPI処理にならない。
    * →　ESP32内部の“__GPIOマトリクス__”によってVSPIのピンに繋がっているから。
* コード上で __明示的にHSPIを選択する必要がある。__
:::
↓　本件に関しては次のページがとても参考になりました（感謝）
https://trac.switch-science.com/wiki/esp32_tips

---
サンプルとしてMCP3008というADコンバータをHSPIで使う時のコードを置いときます。
```cpp:selecting_HSPI_for_MCP3008
//  #define ALTERNATE_PINS  //  Uncomment this line for irregular pin-setting
#ifdef ALTERNATE_PINS
  #define VSPI_MISO   **
  #define VSPI_MOSI   **
  #define VSPI_SCLK   **
  #define VSPI_SS     **

  #define HSPI_MISO   **
  #define HSPI_MOSI   **
  #define HSPI_SCLK   **
  #define HSPI_SS     **
#else
  #define VSPI_MISO   MISO  //19
  #define VSPI_MOSI   MOSI  //23
  #define VSPI_SCLK   SCK  //18
  #define VSPI_SS     SS  //5

  #define HSPI_MISO   12
  #define HSPI_MOSI   13
  #define HSPI_SCLK   14
  #define HSPI_SS     15
#endif

SPIClass * hspi = NULL;  
hspi = new SPIClass(HSPI);    //  <--HSPIを選択
// ↓　デフォルトのVSPIをあえて明示的に選択したい場合にはこちらを使う。
//SPIClass * vspi = NULL;  
//vspi = new SPIClass(VSPI);　　//  <--VSPIを選択

#include <Adafruit_MCP3008.h>
Adafruit_MCP3008 adc;
adc.begin(15, hspi);  // (cs, *spi);

// adc.begin(14, 13, 12, 15);  // (sck, mosi, miso, cs);
// ↑ このようにSPIの指定無しでbegin()した際は、デフォルトのVSPIとなる。
```
Wordpress + Dockerの最適な運用を考えてみた。

# こんな人向けの記事です。
- 本番環境と同じ環境を検証環境に再現したい、最小の工数で。
    - 本番環境以外でテーマを改修してみたい。
    - プラグインのアップデートとかを開発環境でテストしたい。
    - WordpressをDockerで開発しようとしても設定ファイルとか面倒すぎる。
    - 本番と同じ内容のDBを再現したいけど上手くいかない。
    - できればコンテナ起動時に本番と同じ内容にしたい。


# 何ができるようになるの？
- 本番環境と全く同じものをDocker環境に再現します。
    - チーム開発を爆速にするよ。
- 疎結合でね。
    - 普通にやろうとすると本番環境のリソースを見に行ってたりしてちょっと残念。


# 注意点
- 完全に自分用のメモです。
- 多分、もっと良い方法があると思います。
- このやり方は、なるべく本番環境に影響を与えないことを考慮しています。
- そのために、wp-contentをgitリポジトリとして管理しています。（これ以上の階層はできれば触りたくない・・・・）


# Get Started!!
## テーマを安全に開発しよう！
- 基本的に`wp-content`をgitリポジトリとして管理します。
- なぜなら、これ以上のディレクトリは設定ファイルとかがあって管理が大変だから。
- 環境変数とか使えば良いけど、面倒臭いので今回はそういうのなしで行きます。

ディレクトリ構造
```
.git
docker
  db
    initdb.d
      localhost.sql
  wordpress
    Dockerfile
languages
plugins
themes
uploads
.gitignore
docker-compose.yml
index.php
```

```yml
version: '3'

services:
   db:
     image: mariadb:10.5-focal
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: {{お好きなものを}}
       MYSQL_DATABASE: {{お好きなものを}}
       MYSQL_USER: {{お好きなものを}}
       MYSQL_PASSWORD: {{お好きなものを}}
     volumes:
       - ./docker/db/initdb.d:/docker-entrypoint-initdb.d

   wordpress:
     depends_on:
       - db
     build: ./docker/wordpress/
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: {{お好きなものを}}
       WORDPRESS_DB_USER: {{お好きなものを}}
       WORDPRESS_DB_PASSWORD: {{お好きなものを}}
     volumes:
       - .:/var/www/html/wp-content

   phpmyadmin:
     image: phpmyadmin/phpmyadmin:latest
     restart: always
     depends_on:
       - db
     ports:
       - 8888:80
```

```Dockerfile
FROM wordpress:latest

# 必要なツール郡をインストール
RUN apt-get update
RUN apt-get -y install wget unzip

# WP プラグイン (zip) ダウンロード
WORKDIR /tmp/wp-plugins
RUN wget https://downloads.wordpress.org/plugin/contact-form-7.4.6.zip
RUN wget https://downloads.wordpress.org/plugin/syntaxhighlighter.zip
RUN wget https://downloads.wordpress.org/plugin/wp-emmet.zip

# Zip ファイルを解凍してインストール
RUN unzip './*.zip' -d /usr/src/wordpress/wp-content/plugins

# 不要になった一時ファイルを削除
RUN apt-get clean
RUN rm -rf /tmp/*
# デフォルトテーマなんていらないよね！
RUN rm -rf /usr/src/wordpress/wp-content/themes/twenty**

# サーバが読めるように以下の所有者を変更
RUN chmod -R 777 /usr/src/wordpress
RUN chmod -R 777 /var/www/html

WORKDIR /var/www/html

```

- ディレクトリ構造のポイントは、Dockerに必要なものは`docker-compose.yml`を除いてすべて`/docker`リポジトリの中に格納していることです。
- これでわかりやすくなりましたね。


## 本番環境->Docker環境へのDB反映
1. 本番環境からsqlをエクスポートしてくる。
1. Docker環境の`initdb.d`の中にエクスポートしてきたsqlを入れる
1. (2)をテキストエディタで開いてURLをDockerのものに置換する
    - ex
        - `xxx.com` -> `http://000.00.0.000:8000`みたいな感じ。
        - 特にoptionにある以下の２箇所は必須で変更が必要
        - 他の場所は変えなくても動きはする、、、本番のパスを読んでいくだけなので。
            - でもどうせ２箇所買えるなら全部置換しちゃおう！
1. 最後はやっぱり`docker-compose up -d`

```diff
INSERT INTO `wp_options` (`option_id`, `option_name`, `option_value`, `autoload`) VALUES
- (1, 'siteurl', 'xxx.com', 'yes'),
+ (1, 'siteurl', 'http://000.00.0.000:8000', 'yes'),
- (2, 'home', 'xxx.com', 'yes'),
+ (2, 'home', 'http://000.00.0.000:8000', 'yes'),
```
webjarsでプラグインを組み込む

gradleでプラグインを組み込む方法を記載します。
以下では、Bootstrap、Bootstrap-multiselectを組み込みます。
同時にHTML上でのバージョンの指定をwebjarsに依存させるため、webjars-locatorを利用します。
プラグイン情報は以下から検索することができます。

https://mvnrepository.com/


```gradle
    implementation 'org.webjars:webjars-locator:0.42'

    implementation 'org.webjars.bower:bootstrap:4.5.3'

    implementation 'org.webjars.bower:bootstrap-multiselect:1.1.1'
```

---

Thymeleafでは、以下のようにth:srcに指定します。
ソースの場所は、Eclipseのプロジェクトの「パッケージ・エクスプローラー」上でも確認することができます。

![bootstrap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198138/920d00cc-febe-f2b6-d800-ec54f558d5bd.png)

```html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" lang="ja">
<body>
<th:block th:fragment="comscripts">

  <!-- Bootstrap -->
  <script th:src="@{/webjars/bootstrap/dist/js/bootstrap.bundle.min.js}"></script>
  <script th:src="@{/webjars/bootstrap-multiselect/dist/js/bootstrap-multiselect.min.js}"></script>
```
良いテストとは

# 背景
テストに関して以下疑問があった。
- テストを書く・書かないの判断基準はなにか。
  - 課金系など、壊れると明らかに影響が大きいものは書くべきとわかるが、それ以外の場合の明確な基準が自分になかった。
- 適切なテストの書き方とは。
  - 変更を加えた時に、変更と関係ないところでテストが落ちて、テストとして適切に機能していない時があった。

上記疑問は、良いテストの定義が自分になかったことが要因であり、そのことが[こちらの本](https://qiita.com/ken1min86/items/d5f0aa14659b23ab35c3#%E5%8F%82%E8%80%83)で解消されたので、それについて記載します。

# 定義
- 単体テスト
  - 1単位の振る舞い検証するテスト。
  - railsでいうmodelに対するテスト。
- 統合テスト
  - 個々のソフトウェアモジュールを組み合わせて集合体として検証するテスト。
  - railsでいうcontrollerに対するテスト。
  - E2Eテストも統合テストに含まれる

# 良い単体テストの構成要素
- 退行(regression)に対する保護が備わっている
- リファクタリングへの耐性が高い
- 迅速なフィードバックが行われる
- 保守がしやすい

上2つについて自分が特に参考になったことを記載します。
下2つはそのままの意味なので説明は省略します。

## 退行(regression)に対する保護が備わっている
- 退行に対する保護がどれだけ備わっているかの評価軸
  - テスト時に実行されるプロダクションコードの量(多いほど保護性能が高い)
    - 量が多いほど、退行する可能性が高いため
  - そのコードの複雑性(高いほど保護性能が高い)
    - 複雑性が高いほど、退行する可能性が高いため
  - そのコードが扱っている重要性(高いほど保護性能が高い)
    - ビジネス的に重要な機能になるほど、持ち込まれたバグによって生じる被害が大きくなるため
- テストを書くかどうかの基準
  - 上記評価軸において、評価が高い場合に関しては、テストによるメリットとテストにより発生するコスト(書くための労力, 保守etc…)とを比較して、メリットが大きい場合にテストを書く(ここは主観で判断するしかないっぽい)
  - 一方、上記評価が低い、取るに足らないコードに対してはテストをする価値はほとんどの場合ない。このようなコードは間違いが起こる可能性が低いため、退行を見つけ出すことがほとんどないため。価値が低いテストコードは負債なので、書かない方がいい(あるいは、手元でテストを書いて正常に動作することを確認したらテストを削除する。)。

## リファクタリングへの耐性が高い
- リファクタリングをした時に壊れない = 偽陽性を引き起こさない ということ。
  - 偽陽性に対して注意を払う必要がある理由は、偽陽性によってテストを実施すること自体の意味が損なわれてしまうため。
- 偽陽性を引き起こす多くの原因は、テストコードがプロダクションコードと密接に結びついていること。
- 対処法は、テストコードが検証する対象を、実行されたコードがもたらす最終的な結果にすること。その結果を得るための細かい手順である実装の詳細に目を向けないようにすること。

 # 統合テスト
## 特徴
- 保守コストは単体テストよりも高くなる
  - 協力者オブジェクト(処理上必要な他のクラスとのやり取り)の数が増えるにつれ、テストケースのコード量が増えるため
- 単体テストに比べて優れた退行に対する保護が備わる
  - 単体テストよりも多くのコードを実行させることになるため
- リファクタリングへの耐性も単体テストよりも備わる
  - プロダクションコードとの結びつきが、単体テストよりも直接的でなくなるため

## テスト方針
- 1件のハッピーパスと、単体テストでは検証できないすべての異常ケースを行うべき。
  - 検証する内容のほとんどを単体テストに持たせることで、テスト全体の保守コストを少なくし、それと同時にビジネスシナリオごとに1, 2件の包括的な結合テストを行うことで、システム全体が正しく機能することに自信を持てるようになる。

# 参考
[単体テストの考え方/使い方](https://www.amazon.co.jp/%E5%8D%98%E4%BD%93%E3%83%86%E3%82%B9%E3%83%88%E3%81%AE%E8%80%83%E3%81%88%E6%96%B9-%E4%BD%BF%E3%81%84%E6%96%B9-Vladimir-Khorikov-ebook/dp/B0BLTG8Z9K/ref=sr_1_1?adgrpid=146552030392&hvadid=665685951506&hvdev=c&hvlocphy=1009308&hvnetw=g&hvqmt=e&hvrand=7075532377688307378&hvtargid=kwd-1959808738956&hydadcr=27487_14701027&jp-ad-ap=0&keywords=%E5%8D%98%E4%BD%93%E3%83%86%E3%82%B9%E3%83%88%E3%81%AE%E8%80%83%E3%81%88%E6%96%B9%E4%BD%BF%E3%81%84%E6%96%B9&qid=1699074186&sr=8-1)
【JS必須知識】プリコンパイル&モジュールバンドラ

# 【JS必須知識】プリコンパイル&モジュールバンドラ

ウェブ開発において、高級言語から低級言語に変換するプロセスを「コンパイル」と呼びます。通常、コンパイラが高級言語から低級言語に翻訳する作業を行います。この記事では、事前翻訳となるプリコンパイルの方法に焦点を当て、アセットパイプライン（sprockets）とモジュールバンドラ（webpacker）について詳しく説明します。

## プリコンパイルとは？

プリコンパイルは、コンパイラが処理できないファイルや言語を事前に翻訳するプロセスを指します。これにより、ウェブ開発において非常に重要なファイルの最適化や結合が可能になり、ウェブアプリケーションのパフォーマンス向上に貢献します。

### **1. アセットパイプライン (sprockets)**

アセットパイプラインは、ウェブアプリケーションのリソース（CSS、JavaScript、画像など）を効率的に管理するためのツールです。以下はアセットパイプラインの主要なステップです。

- **プリコンパイル**: アプリケーション内の各リソース（例: SassファイルやCoffeeScriptファイル）をコンパイルし、通常のCSSやJavaScriptファイルに変換します。
- **連結**: 複数のリソースを1つのファイルに結合します。これにより、ブラウザが必要とするリソースの数を削減し、ページの読み込み速度を向上させます。
- **圧縮**: ファイルサイズを最小化し、ダウンロード時間を短縮するためにファイルを圧縮します。
- **配置**: リソースファイルを適切な場所に配置し、ウェブアプリケーションがそれらを利用できるようにします。

アセットパイプラインは、ウェブ開発におけるリソース管理を効率化し、ユーザーエクスペリエンスを向上させる重要なツールです。

### **2. モジュールバンドラ (webpacker)**

モジュールバンドラは、JavaScriptのモジュールを効率的に管理し、複数のJSファイル（モジュール）の依存関係を整理しながら1つのモジュールにまとめる役割を果たします。以下はモジュールバンドラの主要な特徴です。

- **プリコンパイル**: JavaScriptファイル内のモジュールを事前にコンパイルし、ブラウザで実行可能な形式に変換します。
- **モジュール整理**: 複数のJavaScriptファイルに分かれたコードを、依存関係に応じて適切に整理し、1つのファイルにまとめます。
- **依存関係の解決**: JavaScriptモジュール間の依存関係を適切に解決し、読み込み順序を最適化します。これにより、通信の高速化とパフォーマンス向上が実珸できます。

モジュールバンドラは、現代のウェブ開発において複雑なJavaScriptコードを整理し、効率的に提供するための不可欠なツールです。例えば、ReactやVue.jsなどのフレームワークと組み合わせて使用することで、モダンなウェブアプリケーションの開発を簡素化できます。

## まとめ

プリコンパイルとモジュールバンドラは、ウェブ開発において効率向上とパフォーマンス最適化を実現する重要なツールです。アセットパイプラインとモジュールバンドラは、リソースの管理とJavaScriptのモジュール管理において大きな役割を果たします。これらのツールを適切に活用することで、ウェブアプリケーションの品質を向上させ、ユーザーエクスペリエンスを向上させることができます。
パッケージ管理ツールとバージョン管理ツール

# パッケージ管理ツールとバージョン管理ツール

## パッケージ管理ツール

パッケージ管理ツールは、様々なファイルやライブラリ（プログラム部品の集まり）やパッケージ（ライブラリの集まり）の依存関係を適切なバージョンで管理するツールです。以下に示すのは、一般的なパッケージ管理ツールとその主な特徴です。

### Homebrew (macOS向け)

HomebrewはmacOS向けのパッケージ管理ツールで、以下の特徴があります：

- **パッケージの管理**: macOSに必要なソフトウェアやライブラリを簡単にインストール、アップデート、および削除できます。
- **依存関係の解決**: パッケージ間の依存関係を自動的に管理し、適切なバージョンを選択してインストールします。
- **アップデートの簡素化**: Homebrew自体とインストール済みパッケージを最新のバージョンにアップデートできます。

### Gemfile (Ruby用)

GemfileはRubyプロジェクト内でGem（Rubyライブラリ）の依存関係を管理するためのファイルで、以下の特徴があります：

- **依存関係の宣言**: Gemfileに必要なGemとそのバージョンを宣言します。これにより、プロジェクトに必要なGemを明示的に指定できます。
- **バージョンのピン留め**: 特定のGemバージョンを指定することで、プロジェクトの一貫性を維持し、予期せぬ変更を避けることができます。
- **`bundle`コマンド**: Gemfile内の依存関係をインストールするには、`bundle install`コマンドを使用します。これにより、Gemの一貫性を確保できます。

## バージョン管理ツール

バージョン管理ツールは、プログラムのバージョンを管理し、必要に応じて異なるバージョンを切り替えるツールです。以下に示すのは、Ruby向けのバージョン管理ツールとその主な特徴です。

### rbenv (Ruby用)

rbenvはRubyのバージョン管理ツールで、以下の特徴があります：

- **複数バージョンのサポート**: rbenvは異なるRubyバージョンをサポートし、プロジェクトごとに異なるバージョンを選択できます。
- **バージョン切り替え**: プロジェクトごとに異なるRubyバージョンを使用でき、グローバルにも切り替えられます。
- **Gemとの統合**: Gem（Rubyライブラリ）と組み合わせて使用することで、プロジェクトごとに異なるRubyバージョンと依存関係を管理できます。

## まとめ

パッケージ管理ツール（Homebrew、Gemfile）はソフトウェアやライブラリの依存関係を管理し、バージョンを適切にコントロールします。一方、バージョン管理ツール（rbenv）はRubyのバージョンを管理し、異なるバージョンの切り替えと依存関係の管理をサポートします。これらのツールは、プログラミングプロジェクトを効率的に管理し、問題なく実行するために不可欠なツールです。
Reactのmaterial-uiでDatePickerを実装する。

## はじめに
表題通り、Reactのmaterial-uiでDatePickerを実装します。

## 成果物
![スクリーンショット 2023-11-04 12.56.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/43823fc8-d78b-272e-590a-31ee38215a58.png)

```shell:ディレクトリ構成
~/develop/HITOTSU/react_date_picker$ tree -I node_modules 
.
├── README.md
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
├── src
│   ├── App.tsx
│   ├── MyDatePicker.tsx
│   ├── index.css
│   ├── index.tsx
│   └── logo.svg
├── tsconfig.json
└── yarn.lock

3 directories, 15 files
```

https://github.com/kouji0705/react_date_picker

### ソースコード
```tsx:src/MyDatePicker.tsx
import 'date-fns';
import React, { useState } from 'react';
import Grid from '@material-ui/core/Grid';
import DateFnsUtils from '@date-io/date-fns';
import {
  MuiPickersUtilsProvider,
  KeyboardTimePicker,
  KeyboardDatePicker,
} from '@material-ui/pickers';

export default function MaterialUIPickers() {
  const [selectedDate, setSelectedDate] = useState<Date | null>(new Date());

  const handleDateChange = (date: Date | null) => {
    setSelectedDate(date);
  };
  console.log('selectedDate', selectedDate);

  return (
    <MuiPickersUtilsProvider utils={DateFnsUtils}>
      <Grid container justifyContent="space-around">
        <KeyboardDatePicker
          disableToolbar
          variant="inline"
          format="yyyy/dd/MM HH:mm"
          margin="normal"
          id="date-picker-inline"
          label="Date picker inline"
          value={selectedDate}
          onChange={handleDateChange}
          KeyboardButtonProps={{
            'aria-label': 'change date',
          }}
        />
        <KeyboardDatePicker
          margin="normal"
          id="date-picker-dialog"
          label="Date picker dialog"
          format="MM/dd/yyyy"
          value={selectedDate}
          onChange={handleDateChange}
          KeyboardButtonProps={{
            'aria-label': 'change date',
          }}
        />
        <KeyboardTimePicker
          margin="normal"
          id="time-picker"
          label="Time picker"
          value={selectedDate}
          onChange={handleDateChange}
          KeyboardButtonProps={{
            'aria-label': 'change time',
          }}
        />
      </Grid>
    </MuiPickersUtilsProvider>
  );
}

```