OmniAICreator/Qiita-1.07M huggingface dataset:
KMMを触ってみて思ったこと

##はじめに
KMM(Kotlin Multiplatform Mobile)とは、Kotlin/NativeというKotlinのコードをさまざまなOSのネイティブコード(マシン語)に変換する技術を使って、モバイル(iOSとAndroid)に特化したクロスプラットフォーム開発をできるようにするSDKです。

僕は~~KMMってなんか響きがかっこ良いんで~~KotlinでiOSアプリが作れるっていうところが凄いなと思って勉強を始めてみました。勉強を始めて一番最初に浮かんだ疑問として、Kotlinで開発するのであればただのAndroid開発と何が違うのかというのがありました。その疑問について色々調べてみました。

##仕組みの違い
そもそもAndroidのネイティブ開発ではKotlinやJavaを使うことができます。それぞれのコードがART(Android RunTime)という実行環境でAndroidOS上で動くようなネイティブコードにコンパイルされることで動いています。

対してKMMはKotlin/NativeがKotlinを各OSのネイティブコードに変換するための諸々をやってくれているので動くそうです。Kotlin/Nativeの公式ドキュメントの文章を見てみると、
>Kotlin/Native is a technology for compiling Kotlin code to native binaries, which can run without a virtual machine. It is an LLVM based backend for the Kotlin compiler and native implementation of the Kotlin standard library.

ということらしいです。全然わけがわからないです。色々調べてみたところ、この部分の詳しい説明として↓の記事がありました。
https://developers.cyberagent.co.jp/blog/archives/23149/
要約すると、Kotlin/Nativeは
・  標準ライブラリ
・  メモリ管理
・ プログラムランチャー
の3つの機能を提供してくれていることで動くそうです。

なので普通のAndroid開発とKMMでは、最終的にAndroidOS上で動くネイティブコードに変換している点は共通していてそのプロセスが違うということらしいです。
##開発する上での具体的な違い
まずKMMはマルチモジュール構成となっていて、共有モジュールと各OSのモジュールの三つの構成になっています。各OSのモジュールではそれぞれのOSでしか使えないライブラリ等が使えます。僕はとりあえずサンプルアプリはMVVMで、ViewModelとViewをそれぞれのOS毎に分岐して書くというやり方で作りました。普通のAndroid開発とKMMで開発するときの具体的な実装時の違いとして使えるライブラリの違いがありました。ここがかなり重要な違いかなと思いました。例えば、
####HTTPクライアント
・Android -> Retrofit(+ OkHttp)
・KMM -> Ktor client
####Coroutines
・Android -> coroutines-android
・KMM -> native-mt
####AAC(Android Architecture Components)
・Android -> 使える
・KMM -> 共有部分のコードでは使えない

他にもあると思いますがこの辺りが違いを実感しました。特にiOSにも対応しないといけないので当たり前ではあるんですが、共有部分のコードでAACが使えないのが辛かったです。ViewModelScope等のAndroidのライフサイクル対応のCoroutineが使えなかったので結局ViewModelを分ける以外にやり方がわかりませんでした。それに関係する話ですが、アーキテクチャに関しても、
・Android -> MVVMが推奨
・KMM -> 何が正解か全くわからない
といった感じでKMMは何が正解なのかよくわかりませんでした。KMMはそれぞれのOSの違いに対応する時に、どうしてもコードを共通化できない部分が出てきてしまってそれぞれ分岐させなければいけないところがあると思うんですが、その分け方のベストプラクティスみたいなものがわからないです。

##感想
とりあえずKotlinでiOSのアプリが作れたのはめちゃくちゃ感動しました。ただ結局ViewModel以降はそれぞれのOS毎に書いているのであんまりクロスプラットフォームで開発している！みたいな実感は湧きませんでした。アーキテクチャ等のベストプラクティスみたいなものがわかればもう少し共通化できる部分が増やせるのかなと思いました。またKMMでの開発を通してAndroid自体の開発に関して少し理解が深まる部分があったのでそれもよかったなと思います。KMM開発においてiOS側からKotlinのflowをobserveする時などもっと具体的な壁もあったのでその辺りもいつか記事に書きたいです。

拙い理解と変な文章の記事をここまで読んでくださってありがとうございました。

###参考記事
https://developers.cyberagent.co.jp/blog/archives/23149/

https://developer.android.com/guide/components/fundamentals?hl=ja

https://www.codetd.com/ja/article/11817820
自作レーザーポインター　Ⅱ



#はじめに
・絶対に人体に向けて照射しないこと。 プレゼンテーションでの画面への指示や手で触れない物の指摘等の本来の目的外の用途では使用しないこと。 鏡やガラス等の正反射するものに向けて照射しないこと。 レーザー光線は直接目に入ると網膜に障害を起こす危険性があるので、レーザー光線を絶対に直視しない、のぞかないこと。

・電池に直接はんだ付けをしますので、自己責任でお願いいたします。

__絶対に守って下さい。__

#目的
プロジェクタやポスターを使ったプレゼンテーションでの使用。
FRISKケースを__スライド__する事で、電源がONになります。

※注意※
電源を逆に接続しますと、レーザー発光モジュールの素子が破損する恐れがありますので十分に注意してください。

#目次
1. 電子部品リスト
2. 配線図
3. ケース加工
4. 動作確認



#１.電子部品リスト
|名称|型番|備考|
|:----:|:----:|:---:|
|赤色ドットレーザーモジュール 4mm×13.5mm　1mW　超小型　スポット調整可|RP650AD5-4C|https://akizukidenshi.com/catalog/g/gM-12279/|
|マイクロスイッチ||https://www.marutsu.co.jp/pc/i/54435/|
|単6乾電池||[LR61電池分解]|
|FRISKケース|||
※レーザーモジュールやリミットスイッチを固定するために、接着剤を使用しました。
TAMIYA EPOXY PUTTY（タミヤ・エポキシ造形パテ）

[LR61電池分解]:https://qiita.com/m2y2/items/12082f7c5124388a095a
[LR61電池分解]はここから

![IMG.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675881/e854f7ac-6510-9bdf-ea57-3103bd42ab7a.jpeg)


#２.配線図
配線図は以下の通りになっています。
マイクロスイッチとは、「マイクロスイッチの接点が感知している時は機械がON、感知していない時は機械がOFFになります。」が<font color="red">この回路のマイクロスイッチでは、機能を逆に使用しています。</font>
__「マイクロスイッチの接点が感知している時は<font color="red">電源がOFF</font>、感知していない時は<font color="red">電源がON</font>になります。」__

単6乾電池を取り出すとプラスとマイナスが__逆形状__だったするのでしっかりと確認して下さい。
__<font color="red">電池に長時間・高温に気を付けて下さい。</font>__
![テーション1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675881/f9e76916-54c7-c2f2-ba64-1beaf7c7cebc.jpeg)

完成した回路
![IMG_2524.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675881/ec0bbe87-e5e1-fe2f-b645-2cb09bd45e9f.jpeg)






#３.ケース加工
FRISKケースに赤色が付いてる所に穴を開けます。
レーザー発光が出る穴とスイッチの部分になります。
![IMG_2528.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675881/05861bf6-7faa-8a7e-df3c-92e610fe6621.jpeg)









#４.動作確認
内部の様子になります。
ケースと平行にすると開閉じに、スイッチが動作しない。常時、OFFの状態になり続ける。
マイクロスイッチの設置を__斜めに配置__することがポイントになります。
![スライド1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675881/c379f294-86cc-56b3-ad61-c5ded99539fe.jpeg)
![IMG_2525.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675881/3e15adc7-5475-dbbd-fc64-2c0d492a958b.jpeg)
![IMG_2526.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675881/3f338c4d-863b-107e-bce9-8cc3cfa7aa89.jpeg)
開閉の様子になります。
![プレゼンテーション2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675881/b62b12f3-c0dd-ebf5-097b-da810275a17a.jpeg)

下の画像を選択すると動画が再生されます。
__YouTube__に飛びます。
[![ビデオが開けなかった場合に表示されるテキスト](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675881/fd4d38c4-cf9a-51c9-69b7-559010c6d907.jpeg)](https://youtu.be/fW0_99XTTN4)
しっかりと動作している事を確認出来ました。
更新するべきパッケージ一覧をCSVで出力(ruby, js)

メモ

## Ruby

```bash=
$ bundle outdated --strict | sed -n "/^Gem /,\$p" | sed -e "s/  \+/,/g"
```

出力例

```
i18n-js,3.8.0,3.8.4,~> 3.8.0,default
js-routes,1.4.9,2.0.8,>= 0,default
json,2.3.1,2.5.1
jwt,2.2.2,2.2.3
```

## JavaScript

jqを利用する

### package-lock.json

```bash=
$ npm outdated --json | jq -r "to_entries | .[] | [.key, .value.current, .value.wanted, .value.latest] | @csv"
```

出力例

```
"i18next","19.8.7","19.9.2","20.4.0"
"jest","26.6.3","26.6.3","27.0.6"
...
```

### yarn.lock

```bash=
$ npx yarn outdated --json | tail -n 1 | jq -r ".data.body[] | [.[0], .[1], .[2], .[3]] | @csv"
```

出力例

```
"@babel/plugin-transform-runtime","7.13.10","7.15.0","7.15.0"
"@babel/preset-typescript","7.13.0","7.15.0","7.15.0"
...
```

### 1つのプロジェクト以下に複数のpackage-lock.jsonやyarn.lockがある時

```
$ find . -type d -name node_modules -prune -o -type f -name 'package-lock.json' -print -o -type f -name 'yarn.lock' -print | xargs -I{} dirname {} | uniq | xargs -I{} bash -c 'echo {} && cd {} && (if [ -e ./package-lock.json ]; then (npm outdated --json | jq -r "to_entries | .[] | [.key, .value.current, .value.wanted, .value.latest] | @csv"); else (npx yarn outdated --json 2>/dev/null | tail -n 1 | jq -r ".data.body[] | [.[0], .[1], .[2], .[3]] | @csv"); fi)', .value.wanted, .value.latest] | @csv"); else (npx yarn outdated --json 2>/dev/null | tail -n 1 | jq -r ".data.body[] | [.[0], .[1], .[2], .[3]] | @csv"); fi)'
```

出力例

```
./hoge #<= ディレクトリパス
"@babel/plugin-transform-runtime","7.13.10","7.15.0","7.15.0"
"@babel/preset-typescript","7.13.0","7.15.0","7.15.0"
...
./hoge/foo
"i18next","19.8.7","19.9.2","20.4.0"
"jest","26.6.3","26.6.3","27.0.6"
...
./fuga
"jest","26.6.3","26.6.3","27.0.6"
...
```

## 参考

- https://bundler.io/man/bundle-outdated.1.html
- https://docs.npmjs.com/cli/v7/commands/npm-outdated
- https://classic.yarnpkg.com/en/docs/cli/outdated/
AWS Cognito Reactでサインアップ・サインイン機能を実装してみた

# 初めに

入門中の React を使って Cognito のサインアップ・サインインのサンプルを作ってみました。

リポジトリは以下になります。

https://github.com/quryu-1/cognito-authentication

# パッケージ

Cognito で認証機能を実装するには以下のパッケージが必要です。

```
npm install --save amazon-cognito-identity-js
npm install --save cross-fetch
```

```react
import 'cross-fetch/polyfill';
import * as AmazonCognitoIdentity from 'amazon-cognito-identity-js';
```

# 使い方

必要なことは、以下のコードにユーザープール ID とクライアント ID を設定することです。

```react:App.js
const poolData = {
  // setting ids
  UserPoolId: '',
  ClientId: ''
};
```

# 参考記事

https://www.npmjs.com/package/amazon-cognito-identity-js

https://www.npmjs.com/package/cross-fetch
デザインパターン目次

#デザインパターン（GoF）

1. Iterator
1. Adapter
1. Template Method
1. Factory Method
1. Singleton
1. Prototype
1. Builder
1. Abstract Factory
1. Bridge
1. Strategy
1. Composite
1. Decorator
1. Visitor
1. Chain of Responsibility
1. Facade
1. Mediator
1. Observer
1. Memento
1. State
1. Flyweight
1. Proxy
1. Command
1. Interpreter


#デザインパターン（マルチスレッド編）
1. Single Threaded Execution
2. Immutable
3. Guarded Suspension
3. Balking
3. Producer-Consumer
3. Read-Write Lock
3. Thread-Per-Message
3. Worker Thread
3. Future
3. Two-Phase Termination
3. Thread-Specific Storage
3. Active Object

#参考本
Java言語で学ぶデザインパターン入門
Java言語で学ぶデザインパターン入門 マルチスレッド編

#マンガでわかる
https://qiita.com/advent-calendar/2019/memory-chan
MS-Accessで、ボタン操作でVBAマクロを実行できない？

Accessのフォームで単語帳を作っていて、
答えが見えないようにしたいときってありますよね。

そして、自分が回答したら、すぐに答えを見たい。

そういうときにどうするか？
二つの解決法を思いつきました。

1. 問題フォームと答えフォームを別々に作る。使うときには、交互に見て、レコードを一つずつ送っていく。

2．フォームの答えを非表示にしておいて、コマンドボタンなどを押すと、表示されるようにしておく。

今回、2.の方法をとろうとしてハマったポイントをシェアしたいと思います。

まず、Accessの世界では、マクロとVBAマクロは違うもののようです……。
これが元でさまざまな勘違い、躓きが起きていました。

下記サイトで、やっとそれに気がつきました。

https://jsdg.org/blog/view007/

次に、いくらやっても、ボタンからVBAが実行できなかった理由がわかりました。

それは、

「デザインビューで」「フォームのプロパティーの」「コード保持」を「はい」にする。

これをやっていなかったので、エラーが出ていました。まず、デザインビューレイアウトビューが自分の頭のなかでごっちゃになっていて、フォームプロパティーは、レイアウトビューから見つかりそうで見つからず、イライラしていました。また、コード保持などという、プロパティーがあること、しかも微妙に違う名前でエラーメッセージに出ていたりして、かなり混乱しました。

さらに、
レイアウトビューで、ボタンの「イベント」「クリック時」を「イベントプロ－ジャ」にする。
（最初にここにVBAの関数名とか書くのかなと、思ったら全然違ってました。一律、イベントプロシージャ」にするみたいです）

それでやっと、できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139486/fc33b2b1-94cc-13ca-f496-b5e634dd45c2.png)

上のtoggleEnglish()は、私が勘違いして書いた関数。
下のように、Form用のモジュール（？）を作って、その中に、イベント・ハンドラの形式で書くということなのですね。

単語帳が完成したら、またこちらでご報告したいと思います。

久しぶりの投稿でした。

実は、1の方法が簡単かつエレガントな方法です。Accessを使い慣れている方ならすぐに思いついたかもしれません。実は私はこれ(Qiita）を書いているときに思いつきました。
Spring boot H2 の基礎のアレコレ。

## H2 Database

**必要な Spring Dependencies**

- H2 Database
- JDBC API
- Spring Web
- Spring Boot Devtools(you shoud install if you need.)

application.properties で以下のように書くより、yml で書く方が好きなので、ここでは yml ファイルで設定を書いていきます。

```properties
// application.properties(個人的に嫌い。。。)
spring.datasource.url=~
spring.datasource.username=~
```

```yml
// mem(メモリ)=Springを起動するたびに初期化される。
spring:
  datasource:
    url: jdbc:h2:mem:test
    driverClassName: org.h2.Driver
    // 管理者権限
    username: sa
    password:
// Webブラウザから確認できるようにする。
  h2.console.enabled: true
```

この状態で、`localhost:8080/h2-console`にアクセス出来ると思います。

開発では、事前に仮想 DB としてテーブルを作成して、データを突っ込んだ上で使用するだろうから、その部分をやっていきます。

`src/resouce/~`
ここに SQL を作って配置するだけ〜。
今回は、2 ファイル用意。

- scheme.sql
- data.sql

```sql
// scheme.sql
create table music(
   id int not null auto_increment,
   bandName varchar(100) not null,
   bestSong varchar(100) not null,
   created datetime not null,
   primary key(id)
);

// data.sql
insert into music (bandName,bestSong,created) values('Queen', 'We Will Rock You', '2019-11-12 08:34:19');
```

![snap1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1383112/8a708ab1-a1f7-3d77-7ffa-69415d4f95fa.jpeg)
![snap2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1383112/adac57c0-6568-1ab2-612e-4826d0a95626.jpeg)
VSCode に WakaTime を導入してコード編集時間を可視化する

## WakaTimeとは？

[WakaTime](https://wakatime.com/)は、エディタと連動してコード編集の作業時間を可視化できるサービスです。
編集したコードのプロジェクト（リポジトリ）、言語、ブランチを自動的に検出してダッシュボード化してくれます。
エディタ操作が一定時間止まると自動的に計測停止してくれます。自分でタイマー開始・停止する必要はありません。

たいていのエディタは対応しています。
https://wakatime.com/plugins
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290998/a373e853-4e48-dc31-c47e-bc32bfe09f02.png)

この記事では、VSCode に WakaTime を導入してダッシュボード確認するまでの手順を説明します。

## WakaTimeアカウント登録

https://wakatime.com/signup からサインアップしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290998/38d07e32-85e2-a123-788e-79ed7b5d03b6.png)

## APIキー発行

https://wakatime.com/settings/account からAPIキーを発行できます。
VSCode と WakaTime を連携させるのに使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290998/471e8c12-2597-d8f4-f15e-0db903fc829b.png)


## VSCodeにWakaTimeエクステンションインストール

`WakaTime` で検索すればすぐ出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290998/6f4569fd-e038-4cf3-5f05-ecbedf8a4d98.png)

インストールするとAPIキー入力を求められます。
先ほど発行したAPIキーを入力してください。

## WakaTime導入完了！

APIキー設定完了すると、 https://wakatime.com/dashboard でダッシュボード確認できるようになります。
わりとリアルタイムに反映されます。

以下、導入して3分間だけいじった時点のキャプチャです。
「`nextjs-tutorial` リポジトリの `main` ブランチで、 `pages/index.js` を 3mins だけいじったんだな〜」ということが分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290998/58c8a43c-437f-6ba9-0a4b-12ec9bb37c40.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290998/827400e6-4781-7fdc-d2c0-b0e130ed84d6.png)

このように、

- どのリポジトリの、
- どのブランチで、
- どのファイルを、
- どれくらい編集したか？

みたいな情報を確認することができます。
他にもいろいろな機能がありそうです。

## まとめ

実際のプログラミング作業は「調査が9割、実装は1割」みたいなケースも多いです。
そのため、 WakaTime で厳密にエディタ上のコード編集時間だけを計測してもそれをそのまま実装時間としては使えません。

それでも、ペアプロ・モブプロで誰が一番多くコード書いたか、みたいな可視化には使えそうですね。

## 参考

https://wakatime.com
CML2を使いこなす。（その９：ストレージの増設）

# はじめに
`CML2`を使用している際、後述の理由でディスク拡張を行ったため、その際に実施した手順を記します。

- 【前】[CML2を使いこなす。（その８：WAN Emulator）](https://qiita.com/sakai00kou/items/04c043b3e9a1189efd90)
- 【次】[CML2を使いこなす。（その10：ホストマシンへのSSH接続）](https://qiita.com/sakai00kou/items/47d49b525b1014052aef)

# なぜディスク拡張が必要になったか
`CML2`では仮想マシンを起動する際、**CPU**、**メモリ**などの仮想マシンの起動・動作に直結するリソースだけではなく、`CML2`を動作させているホスト側の**ディスク容量**も一定の割合以上になると仮想マシンが起動できなくなる仕様になっているようです。

`OVA`形式で公開されている`CML2`はデフォルトで16GBのディスク容量しかないため、独自のカスタムイメージを使おうとしたところ、容量オーバーとなったためディスク拡張が必要となりました。

ちなみに、ディスク使用率が80%以上となると、`Dashboard`上の下部に表示されているディスク使用率のステータスが赤になるようなので、80%以上になると、ラボ上のノードが起動できなくなるようです。

# ディスク拡張方法
以下作業を行うことで`CML2`ホストのディスク容量を拡張することができます。

特に`CML2`に限った方法ではなく、やっていることは`Linux`の`LVM`ボリューム拡張になるので、`LVM`の操作に慣れている方はコマンドで実施してもOKです。

1. CML2ホストへのディスク追加
2. Cockpitから物理ボリューム追加
3. Cockpitから論理ボリューム拡張

## CML2ホストへのディスク追加
私の環境では`Ubuntu`上の`VMware Workstation Player`で`CML2`を動作させているため、`VMware Workstation Player`での操作を示します。

一度`CML2`を停止させ、「**Edit virtual machine settings**」の「**Add**」ボタンから好きな容量のディスクを適当な場所に追加して、「**Save**」で設定を保存します。

![capture_15082021_123350.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/f13ede13-c217-20d0-6e3c-acf0dcdc1383.jpeg)

画面が戻ったら再度`CML2`のホストを起動しておきます。

## Cockpitから物理ボリューム追加
`CML2`起動後、`Cockpit`画面にログインしたら「**ストレージ**」より容量を追加したいファイルシステム名を選択します。（今回の場合`/dev/cl_cml2-controller/root`）

![capture_15082021_123557.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/7022d7e7-5e8b-8162-ff92-274463388a27.jpeg)

`Cockpit`画面へのログインは以下等を参照。

- [CML2を使いこなす。（その５：外部との接続）](https://qiita.com/sakai00kou/items/3ed6d644935b8cb7fcb9)

選択したファイルシステムの情報が表示されるため、「**物理ボリューム**」の「**＋**」を選択。

![capture_15082021_123703.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/62bb5b45-eef7-5c3c-7f72-cc64d8b61d71.jpeg)

追加するディスクを選んだ後、「**追加する**」で物理ボリュームを追加します。

![capture_15082021_123723.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/71fe1b43-40fa-80d2-beda-5a71e17d07e2.jpeg)

## Cockpitから論理ボリューム拡張
前手順を実行することで、物理ボリュームへの追加とボリュームグループの容量が変わりましたが、論理ボリュームはそのままなので、論理ボリュームを拡張していきます。

![capture_15082021_123756.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/d56a3a4e-94c0-3a39-9de9-b1b86dbd5ff9.jpeg)

上図より拡張したい論理ボリューム（今回の場合`/dev/cl_cml2-controller/root`）を選択することで論理ボリュームの拡張を行う画面が表示されるため、「**増加**」を選択します。

![capture_15082021_123830.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/494ecb3b-f5a1-292b-d5f4-af3798005d2e.jpeg)

「**論理ボリュームの増加**」画面が表示されるため、好きな容量分、バーをスライドさせ、「**増加**」を選択します。

![capture_15082021_123903.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/406e8303-b864-38dc-e8c5-a8920e6e59ae.jpeg)

論理ボリュームのサイズ表示が拡張後のサイズに変わっていれば終了です。

![capture_15082021_123931.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/399275bb-555c-8751-6446-55346287ef84.jpeg)

# おわりに
ディスク使用率の閾値超過で既存ノードも起動できなくなるとは思っておらず、少しハマったため、次に同じことが起こってもすぐに対処できるように記事にしてみました。

`CML2`を使いこなしてくるとすぐに容量が足りなくなると思うので、ディスク容量が少なくなってきたら早めに拡張するようにしましょう。
ExcelのOpenとプロセス

# はじめに
別の記事（ https://qiita.com/etoootak/items/9b37ef362d4aaf358d1a ）
を書いていたときに、気づいた小ネタです。

Automaton Anywhere V11ではBotのExcelコマンドで開いた複数のExcelは別プロセスになっていました。しかしAutomation360では１つのプロセスになります。

# V11の場合
「Excel : Open Spreadsheet」コマンドで２つのExcelを開きます。
プロセスは以下のように別になります。
（タスクマネージャの表示です）
![V11_excel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/f05f8284-4957-8702-3c25-c7956921ef87.png)

# Automation 360の場合
「Excel の高度な操作: 開く」アクションで２つのExcelを開きます。
プロセスは以下のように１つになります。
![A360_excel2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/83ab7b5b-a926-c810-f8bf-8790c8e3e4e5.png)


# これによって何が変わるか
V11のときにExcelを２つ（Open Spreadsheetで）開いて、Excel間で「行／列の入れ替え」を指定したコピーができませんでした。
プロセスが別なので「形式を選択して貼り付け」が使えなかったのです。
（File/FoldersのOpen Fileで開くなどで回避していました）

別プロセスのために、手でExcelを操作するとうまくいくのに、AutomationAywhereで操作するとうまくいかない、という場面が稀にあって、最初悩まされました。

Automation360でプロセスが１つになるなら、手でExcelを操作していたときと同じ感覚で扱えるので、これは嬉しい変更だと思います。
protocolの基本と種類(swift)

#protocolとは
直訳すると議定書・手順。

swiftでは、クラス・構造体などに対してプロパティとメソッドを定義する機能。
プロトコルを適用したクラス・構造体は、プロトコルに定義されているプロパティ・メソッドを必ず定義しなければならない。

つまり、「クラス作成のルールを定めて、それを守らせる」という認識であっているでしょうか🤔


#protocolを定義する


```swift:sample
protocol プロトコル名 {
    var プロパティ名 : 型 {set get}
    func メソッド名(引数名 : 型) -> 戻り値の型
}
```

プロパティ名の横には{set get}もしくは{get}
を記入する。
`{set get}`　読み書き可能
`{get}`　読み込み専用

#代表的なプロトコルの種類

###CustomStringConvertible
インスタンスの文字表現を自由にカスタマイズできるプロトコル。


```swift:CustomStringConvertible
class Shoe: CustomStringConvertible {
    let color: String
    let size: Int
    let hasLaces: Bool
 
    init(color: String, size: Int, hasLaces: Bool) {
        self.color = color
        self.size = size
        self.hasLaces = hasLaces
    }

 　 //ここでインスタンスの文字表現をカスタマイズする　　
    var description: String {
        return "Shoe(color: \(color), size: \(size), hasLaces: \
        (hasLaces))"
    }
}

let myShoe = Shoe(color: "Black", size: 12, hasLaces: true)
let yourShoe = Shoe(color: "Red", size: 8, hasLaces: false)
print(myShoe)
print(yourShoe)
```

```swift:出力結果
Shoe(color: Black, size: 12, hasLaces: true)
Shoe(color: Red, size: 8, hasLaces: false)
```

もしCustomStringConvertibleを使わずに、descriptionも定義しないで出力すると

```swift:出力結果（プロトコルなし）
Shoe
Shoe
```

###Equatable
対象が一致するかどうか（イコール）の確認を可能にするプロトコル。


```swift:Equable
struct Person: Equatable{
    var name: String
    var age: Int

    //年齢が同じかどうかをBoolで返すメソッド
    static func == (lhs: Person, rhs: Person) -> Bool{
        return (lhs.age == rhs.age)
    }
}

//インスタンス化
let yamada = Person(name: "YAMADA", age: 20)
let Takahashi = Person(name: "TAKAHASHI", age: 30)

//年齢が同じかどうかの確認が可能になる!
 yamada == takahashi //false

```


###Comparable
対象の大小を確認するためのプロトコル。


```swift:Equable
struct Person: Equatable: Comparable{
    var name: String
    var age: Int

    //年齢が同じかどうかをBoolで返すメソッド
    static func == (lhs: Person, rhs: Person) -> Bool{
        return (lhs.age == rhs.age)
    }

    //年齢が小さいかどうかをBoolで返すメソッド
    static func < (lhs: Person, rhs: Person) -> Bool{
        return (lhs.age < rhs.age)
    }
}

//インスタンス化
let yamada = Person(name: "YAMADA", age: 20)
let Takahashi = Person(name: "TAKAHASHI", age: 30)

//年齢の比較が可能になる!
 yamada < takahashi //true

```


###Codable
jsonなどのデータをデコード、エンコードするプロトコル。



```swift:Codable
struct Person: Codable{
    let name = String
    let height = Int
    let weight = Int
}
```

これだけで、エンコード、デコードともに可能な状態になります。
インスタンス化後に、JsonDecoder/Encoder()などで変換します。

###Error
throw文のエラーを処理する型で必要なプロトコル。
Errorプロトコルは列挙型で定義するのが一般的である。
また、プログラム全体で起こりうるエラーを１つの列挙型で表すのではなく、エラーの種類ごとに別の型に定義する。


```swift:Codable
enum DatabaseError: Error{
    case entryNotFound
    case duplicatedEntry
    case invalidEntry(reason: String)
}

enum NetworkError: Error{
    case timeout
    case cancelled
}
```




#参考文献
・swift実践入門
・App Development With Swift - Unit4 Lesson4.1
>![F560A0CB-D19D-44CC-A61A-0B5397C6FA58_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261100/a7728b86-805a-36af-7959-ecce2e8b5654.jpeg)


#_
*本記事は初心者による作成です。細心の注意は払っていますが内容に誤りが含まれる場合がございます。
ご指摘いただけると幸いです。
健康管理チェックをExcelからGoogleフォームとGmailで毎日チェック通知できる機能


1回目の記事でも投稿した、社内での健康管理チェック表のアンケート改善で
再チャレンジしたいと思います。
良かったら1回目の記事も確認してみてください。

https://qiita.com/yudiramaruyama/items/9b791476027b6f74781f

#毎朝Excel入力改善したい
なぜ：
イメージとしては下の表が健康管理チェックの表になります。
この表を各部署のメンバーが毎日（〇）か（✖）を入力。
![（開発＆戦略室）体調管理チェックシート_page-0001 (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1806084/5bfd934e-ee0d-71a1-9097-742f1cd705d7.jpeg)

①1つのエクセルで複数の方が同時に入力出来ず時間のロスが発生。
②毎日の入力をし忘れる方もいるので、改善出来ればと思いました。

改善方法：
①毎朝指定時間にメールでフォームを通知。
⇒メール通知で少しでも入力もれを避けれると思いました。
②アンケートはGoogle formを使用する事で複数入力が可になり自動管理も出来る。
⇒Google FormのURLで複数の方が使用できることで、時間のロスを改善。

ルーティーン作業を少しでも改善しようと思い考えてみました。

#届く通知メール
![Inked１_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1806084/953d6b50-a612-b060-a448-a0ab2a740cd5.jpeg)


#使用
- [Google Cloud Platform](https://console.cloud.google.com/)<br>
- [Integromat](https://www.integromat.com/)<br>
- [Google form](https://www.google.com/intl/ja_jp/forms/about/)<br>
- [Gmail](https://www.google.com/intl/ja/gmail/about/)<br>

#流れ
##①Google Cloud Platform
アカウントを作成し、次のステップで使用する [Integromat](https://www.integromat.com/)と
Gmail APIの有効化の連携は[こちら](https://www.integromat.com/en/help/connecting-integromat-to-google-services-using-a-custom-oauth-client)からご確認ください。

##②Integromat
モジュールを画像のように組み合わせていきます。
![２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1806084/6f0ac721-8818-24a5-f9c8-2d5c43be35f2.png)

###<b>Tools</b>
あらかじめアンケートをGoogle formで作成しここではGoogle formのURLを主に追加します。
name:自由です。
lifetime:一度のメールに1回の設定がしたいのでOne executionを選択。
![Inked３_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1806084/108dd233-3c95-4020-05a8-62f9b9408ea4.jpeg)

Toolsの横にある時計マークをクリックして設定。
今回は毎日朝9時にメールが来るように設定しました。
![４.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1806084/3b9d54e4-b88f-d51e-6024-69eec330232a.png)

###Gmail
Google Cloud Platformと連携したClient IDとClient Secretをconnectionで入力します。
[My google restricted connected(登録したGmail）」になっていれば連携完了。

To：宛先のメールアドレスを入力（登録したGmail以外）
subject:件名を入力
content:メール内容入力

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1806084/9e63bf73-4fb1-de99-8448-4ced9128e919.png)

#完成
これでRun Onceボタン押すと通知メール画像のように届きます。
最初はIntegromat連携やGmailAPI有効化の部分が少し戸惑いましたが、
個人的には最初の記事で使用したNode-Redよりも比較的に分かりやすいです。

これで、入力もれと自動管理と時間のロスを少しでも改善が出来ると思いました。
PG::ConnectionBad (could not translate host name "db" to address: Name or service not knownが出た際の対処

# 事象

```
PG::ConnectionBad (could not translate host name "db" to address: Name or service not known
```

`docker-compose build`時に上記エラー

# 対処

dockerのimageがたくさん立ち上がったままでデバイスの容量を圧迫していたのが原因っぽい。

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

上記の

```
$ docker image prune
```

でbuildし直したら治った
Visual Studio Code で LaTeX に SVG を貼り込んだ原稿のコンパイル設定

#はじめに
LaTeX の原稿を Visual Studio Code の拡張 LaTeX Workshop を使って書いていたときに
SVG を埋め込みたくなる状況になりました。
VSCodeでSVGを埋め込んだ原稿をコンパイルするには少し設定の修正が必要だったので、メモを残します。

使用した環境は以下です。

* macOS Big Sur 11.5.2
* TeXLive2021
* VSCode バージョン: 1.59.0
* LaTeX Workshop v8.20.2

#事前準備
LaTeX にSVGファイルを埋め込むには SVGパッケージと Inkscape が必要になります。

SVGパッケージについては以下を参考にしました。
https://konoyonohana.blog.fc2.com/blog-entry-432.html
https://pyopyopyo.hatenablog.com/entry/2019/11/17/180855

TeXLive だとデフォルトでインストールされてるはずで、`texdoc svg` としてドキュメントが参照できるなら、特にインストール作業は不要です。

SVGファイルを LaTeX に埋め込める形式に変換するために SVGパッケージではInkscape を使います。
これは mac であれば `brew` を使って以下のコマンドでインストールできます。

```
brew install --cask inkscape
```

# Visual Studio Code 拡張の設定
SVGパッケージを使うときには内部で Inkscape を呼び出すので LaTeX のコンパイルコマンド
(`pdflatex`, `lualatex` 等)に `-shell-escape` オプションが必要になります。

VSCode の LaTeX Workshop 拡張のデフォルト設定では `-shell-escape` は実行時に指定されませんので、
追加する必要があります。
とはいえ、これは任意の外部コマンドを実行できるようにするオプションなのでユーザのデフォルト設定とすることは
セキュリティ上の懸念があると考え、ワークスペース固有の設定とすることにしました。

`⌘,` で設定画面を開いたら、`latex.tools` で検索すると変更したいオプション `latex-workshop.latex.tools` が見つかります。
![設定画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1200958/5e4ceb2f-335c-3c88-ecce-27132eddd90b.png)

`settings.json で編集` を選んで、例えば `latexmk` に対しては以下のように `"args"`オプションの中の `"%DOC%"` の直前に *`-shell-escape`* を追加します。
必要に応じて `lualatexmk`, `pdflatex` など、他のコマンドの設定にも`-shell-escape` を追加します。

```json:settings.json
        {
            "name": "latexmk",
            "command": "latexmk",
            "args": [
                "-synctex=1",
                "-interaction=nonstopmode",
                "-file-line-error",
                "-pdf",
                "-outdir=%OUTDIR%",
                "-shell-escape",
                "%DOC%"
            ],
            "env": {}
        },
```

これでコンパイル時に自動的に inkscape が呼び出されてSVGを埋め込んだPDFが出力されるはずです。
QiitaのMarkdown記法備忘

QiitaのMarkdown記法がはじめ戸惑ったので備忘で残しておきます。
随時更新していきます。

#タイトルの書き方
\#タイトルの書き方
と入力

#コードの挿入

```python:test
if __name__ == '__main__':
    main()
```

\`\`\`python:test
if __name__ == '__main__':
&nbsp;&nbsp;&nbsp;&nbsp;main()
\```
と入力

※バッククォート（Shift+@）なので注意。

#エスケープ方法
バックスラッシュ+markdownでエスケープ可能。
\\#のような具合。

#スペースの入力
&nbsp;あいうえお&nbsp;と入力。
\&nbsp;あいうえお\&nbsp;と入力。

また他に以下の種類があるようです。
\&thinsp;\&nbsp;より狭い空白
\&nbsp;半角スペースと同じ
\&ensp;半角スペースより少し広め
\&emsp;半角スペースよりさらに広め、全角スペースとほぼ同じ幅

#リンクの挿入
ベタ書きすると↓になる。
https://www.google.co.jp/

htmlのaタグ的に書くには、
\[Googleです。](https://www.google.co.jp/)
と書くと、
[Googleです。](https://www.google.co.jp/)
となる。
apt-get updateで`N: This must be accepted explicitly before updates for this repository can be applied`

「何もしてないのに壊れた！」じゃないけど一度通ったはずのテストがmasterにマージしてpushしたらCricleCIでこけました。テストは関係なくて`sudo apt-get update`がこけてるようです。エラーは下記。


```
Get:3 http://deb.debian.org/debian buster-updates InRelease [51.9 kB]
Reading package lists... Done      
E: Repository 'http://security.debian.org/debian-security buster/updates InRelease' changed its 'Suite' value from 'stable' to 'oldstable'
N: This must be accepted explicitly before updates for this repository can be applied. See apt-secure(8) manpage for details.
N: Repository 'http://deb.debian.org/debian buster InRelease' changed its 'Version' value from '10.0' to '10.10'
E: Repository 'http://deb.debian.org/debian buster InRelease' changed its 'Suite' value from 'stable' to 'oldstable'
N: This must be accepted explicitly before updates for this repository can be applied. See apt-secure(8) manpage for details.
E: Repository 'http://deb.debian.org/debian buster-updates InRelease' changed its 'Suite' value from 'stable-updates' to 'oldstable-updates'
N: This must be accepted explicitly before updates for this repository can be applied. See apt-secure(8) manpage for details.

Exited with code exit status 100
```


いまいち内容理解してないけど`apt-get update`に`--allow-releaseinfo-change`オプションを追加したらパスしました。

```
sudo apt-get update --allow-releaseinfo-change
```

`buster`のバージョンが変わったので`releaseinfo`を更新してやらないとupdateできないとかって感じですかね。だとするとこのオプションは必ず付けておいた方が間違いないということでしょうか。

下記を参考にさせていただきました。
https://www.reddit.com/r/debian/comments/ca3se6/for_people_who_gets_this_error_inrelease_changed/

同じエラーでハマる人がいそうなので記事にしました。
AWS 認定 データベース – 専門知識に合格したので勉強方法を書いておく

#はじめに
AWS 認定 データベース – 専門知識に合格したので、勉強方法を備忘として書いておきます。参考になれば幸いです。これで８冠、残り３冠・・・・がんばります・・・

職業：現在インフラエンジニア6年目でAWSをメインに設計構築をするようになって、2年くらい。
最近はもっぱらオンプレミスからAWSへの移行などのコンサルをやることが多いです。
AWSをやる前は、VMwareやWindows、Linuxなどいろいろやってましたが、
今では、AWSが得意！と言えるくらいになってます。

他のAWS関連の資格：
　ソリューションアーキテクトアソシエイト(SAA)(2018年取得)
　SysOpsアドミニストレータアソシエイト(SOA)(2019年取得)
　ソリューションアーキテクトプロフェッショナル(SAP)(2020年取得)
　セキュリティ – 専門知識（SCS）(2021年取得)
　デベロッパーアソシエイト（DVA）(2021年取得)
　クラウドプラクティショナー（CLF）(2021年取得)
　DevOpsエンジニアプロフェッショナル（DOP）(2021年取得)

https://qiita.com/Regryp/items/0645fb976655262e9229

https://qiita.com/Regryp/items/2066ffca878e1726aa3c

https://qiita.com/Regryp/items/19f85ca4aec1940ca106

https://qiita.com/Regryp/items/228936a4c991ad925254

#試験について
SAP、DOPを取得しており、データベース関連の基礎知識はあったので、それほど難しくないかなと行く所感でした。
あまり触れたことのないサービス（Neptune、DocumentDB、QLDBなど）を中心に勉強したのと、Auroraの復習も実施しました。全体的に見て、対象サービスも限定されるので、取得はしやすいと感じました。


#試験までに何をやるか
###1.「AWS 認定試験に備える」を参照する
これは基本です。どの試験にも共通しますが、出題範囲、見るべきドキュメント、トレーニングが列挙されています。
基本的に私の勉強方法は以下URLのリンク先を潰していくことがメインとなります。
学習のヒントとして、出題範囲や、参考とするドキュメントなど事細かにリンクが載っていますので、
最初に見ることをおすすめします。

https://aws.amazon.com/jp/certification/certification-prep/

###2.試験ガイド、サンプル問題を読む
出題される分野、配分、問題の形式をしっかり読みましょう。
配分は以下のとおりです。

分野 1: ワークロード固有のデータベース設計 26%
分野 2: 展開および移行 20%
分野 3: 管理および運用 18%
分野 4: 監視およびトラブルシューティング 18%
分野 5: データベースセキュリティ 18%

[試験ガイド](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-database-specialty/AWS-Certified-Database-Specialty_Exam-Guide.pdf)
[サンプル問題](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-database-specialty/AWS-Certified-Database-Specialty_Sample-Questions.pdf)

###3.公式トレーニングを受ける
無料でデジタルトレーニングが受けられます。
分野ごとの基本的な解説、練習問題、模擬試験を受けることができますので、イントロとしてはちょうど良いレベル感です。ただし、このトレーニングを受けたからといって試験に受かるというわけではなく、更に深堀りして勉強することが必要です。残念ながら日本語ではないのですが、Chromeの翻訳機能を使って一通り学習しました。
[Exam Readiness: AWS Certified Database - Specialty](https://www.aws.training/Details/eLearning?id=47245)

###4.参考書を読む
以下の本を購入しました。
この本はかなりよかったです。
試験に出題されるサービスを網羅的に抑えていて、試験のポイントとなりそうな機能や仕様を解説してくれています。
この本だけでも十分合格できるレベルかと思います。

https://www.amazon.co.jp/%E8%A6%81%E7%82%B9%E6%95%B4%E7%90%86%E3%81%8B%E3%82%89%E6%94%BB%E7%95%A5%E3%81%99%E3%82%8B%E3%80%8EAWS%E8%AA%8D%E5%AE%9A-%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9-%E5%B0%82%E9%96%80%E7%9F%A5%E8%AD%98%E3%80%8F-Compass-Books%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-NRI%E3%83%8D%E3%83%83%E3%83%88%E3%82%B3%E3%83%A0%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE-ebook/dp/B0936PSMXT

###5.問題集を解く
先程の本の問題集を２周しました。かなりよくできた問題集なので、本は是非オススメです。
やはり、問題集を解くことが一番ためになります。試験で求められる知識をチェックできる、間違えた問題から苦手な分野、深堀りすべきドキュメントが参照できるというところがあるので、一番おすすめです。

Udemyも購入してみました。
本だけでもよかったかもですが、念の為・・・
案の定英語なので、Chromeの翻訳機能を利用しました。

https://www.udemy.com/course/aws-certified-database-specialty-practice-exams-dbs-c01/

###6.ホワイトペーパー、よくある質問、BlackBeltを見る
全体的に苦手な分野を軽く目を通すレベルでよいかなと思います。
私の場合、BlackBeltで、DMS、Neptune、ElasticCacheなど、苦手なサービスをメインに
見ました。

https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/#compute-services

#最後に
専門知識系の制覇に向けたスタートでしたが、順調な滑り出しだったかと思います。
対策本にだいぶ助けてもらいましたね。

結果、847点
もうちょい取りたかった！
これで、CLF、SAA、SOA、DVA、SAP、SCS、DOP、DBSの8冠を取得しました。
次回ANSの取得を目指します！
Git BashのSSHからWindows 10本家のOpenSSHへ移行する

Windowsでsshを使うときは、Git for Windowsに附属するsshを使うのが慣例だったが、Windows 10のBuild 1809 (2019年)からOpenSSHがOSの本体にも含まれるようになった。

参考：　[OpenSSH in Windows](https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_overview)

本家のOpenSSHを使えば起動時にssh-agentが自動でstartするため使い勝手がよくなる。また、Git for Windowsへの依存も減るので移行した。

# OpenSSHの有効化

設定のManage Optional Features画面で、OpenSSH clientがインストールされていることを確認する。インストール済みでない場合、追加する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334026/178cb00a-58ad-190f-a98b-96ebae8ce79f.png" height=200 />

## 確認手順

利用するコマンドラインから

```
where ssh
```

をたたき、

```
C:\Windows\System32\OpenSSH\ssh.exe
```

が含まれていることを確認する。

# ssh-agent の自動スタート

次に、services.mscの管理画面からOpenSSH Authentication Agentを選択し、右クリックでプロパティを選択する。

1. Startup typeをAutomaticかAutomatic (Delayed Start)（自動）に変更する
2. サービスを起動する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334026/48f1937e-2329-4dfc-a940-54ab2fb140f3.png" height=200 />

# Git Bashで使うsshを変える

もともとGit Bashを使っていた場合、

```
$ where ssh
C:\Program Files\Git\usr\bin\ssh.exe
C:\Windows\System32\OpenSSH\ssh.exe
$ which ssh
C:\Program Files\Git\usr\bin\ssh.exe
```

となり、古いsshがデフォルトになっている。Pathの一番前にC:\Windows\System32\OpenSSHをつけることで直せた。

```bash:.bashrc
PATH="/c/Windows/System32/OpenSSH:${PATH}"
```

また、GitでSSHを使っている場合、GIT_SSHの環境変数にパスを書くと良さそう。(未検証)

```bash:.bashrc
GIT_SSH=/c/Windows/System32/OpenSSH/ssh.exe
```

編集した.bashrcを読み込めば完成。

```
$ source ~/.bashrc
```
PHP-JWTライブラリを用いてAuth0のWEBアプリケーションを作成する

#まず、Auth0無料登録を行い、Applicationを作成する(この記事ではhasami.jp.auth0.com)  
![FireShot Capture 001 - Application Details - manage.auth0.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1224758/e66eb05c-c41e-f782-f436-4691635cbcf6.png)
![FireShot Capture 002 - Application Details - manage.auth0.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1224758/dab25430-21ad-d24b-6cbd-2ad1dad5d692.png)


#ログイン(authorization-code-flow)  
http://openid-foundation-japan.github.io/openid-connect-core-1_0.ja.html#AuthRequest  

##AUTHORIZEエンドポイントへGETリクエストすることでログイン画面へ遷移  
https://auth0.com/docs/api/authentication#authorization-code-flow  
  
##GET "https://hasami.jp.auth0.com/authorize?client_id=DJjstTQAtZsX2mF1WucvC0925YTrNDol&response_type=code&scope=openid+email+profile&redirect_uri=https%3A%2F%2Fmail.hasami.uk%2Fcallback%2F"  
（これがログインボタンのリンクになる）    

- response_type = code  
- client_id = DJjstTQAtZsX2mF1WucvC0925YTrNDol(Auth0のApplicationsの設定で取得できます)  
- scope = openid profile email  
- redirect_uri = https://mail.hasami.uk/callback/
  
https://github.com/fujio-ux/login-auth0-php/blob/master/document-root/index.html  


##ログイン画面でログイン成功ときに得られるコールバック画面に付与されるGETパラメータ（code）をトークンに変換する  
https://auth0.com/docs/api/authentication#authorization-code-flow45  
http://openid-foundation-japan.github.io/openid-connect-core-1_0.ja.html#TokenRequest  
##POST "https://hasami.jp.auth0.com/oauth/token"  
- client_id  
- client_secret  
- grant_type = authorization_code  
- code = コールバックページ（/callback/）のGETパラメータ  
- redirect_uri = authorizeで投げたものと同じものを指定するhttps://mail.hasami.uk/callback/  


https://github.com/fujio-ux/login-auth0-php/blob/master/php-include_path/functions.php  

##PHP-JWTライブラリでAuth0のユニバーサルログイン画面からの戻りで得られるIDトークンを検証（デコード）する  

Auth0 が公開しているPHP-SDKはPHP７でないといけない。(https://auth0.com/docs/libraries/auth0-php)  
PHP-JWT(firebase)であればPHP５から８まで対応している！  
インストールは

```
composer require firebase/php-jwt
```


デコードに必要なPEMキー($publicKey)は　テナントのURL/pem で手に入れられる（https://hasami.jp.auth0.com/pem）  

```php
use Firebase\JWT\JWT;
require_once("vendor/autoload.php");
try{
    $publicKey = file_get_contents("/usr/share/php/rs256.pem");
    #$decoded_ac = JWT::decode($token["access_token"], $publicKey, array('RS256'));
    //Auth0では、AUTHORIZEエンドポイントにaudienceを指定しなかったら（初期状態）JWT形式ではない(opaque)アクセストークンが返ってくるのでデコードしないこと
    //https://auth0.com/docs/tokens/access-tokens#opaque-access-tokens
    //https://auth0.com/docs/tokens/access-tokens#jwt-access-tokens
    $decoded_id = JWT::decode($token["id_token"], $publicKey, array('RS256'));
}catch(Exception $e){
    //検証できなければログイン失敗
}
```

https://github.com/fujio-ux/login-auth0-php/blob/master/document-root/callback/index.html
【Flutter】グラデーションをつける

#サンプルコード
beginとendでグラデーションの開始位置と終了位置を設定します。

```dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      home: GradationScreen(),
    );
  }
}

class GradationScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: <Widget>[
          Container(
            decoration: BoxDecoration(
              gradient: LinearGradient(
                begin: Alignment.topRight,
                end: Alignment.bottomLeft,
                colors: [
                  Color(0xFF21D4FD),
                  Color(0xFFB721FF),
                  Color(0xFF8EC5FC),
                  Color(0xFFE0C3FC),
                ],
              ),
            ),
          )
        ],
      ),
    );
  }
}
```

# イメージ
![スクリーンショット 2020-07-25 11.01.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663839/b7f5a0f3-0277-200e-5746-1ac7622684d3.png)
integromatでGmailとLINEを連携　週間業務リマインド＆効率化

## 忘れてた・・・から始まるイレギュラー
　「沖中さん　週間業務報告書と交通費申請まだですか？」集計担当者からの催促メールで
　慌ててバタバタ作業開始。メールに気づいてないときは、催促電話をもらう始末。
　ファイルを探し、週間を振り返りつつ急いで記入、ん？さっきまで何してたっけ・・・
　<font color="Red">**うっかりから発生するムダを　自動化で少しでも減らしたい**</font>

## 何をどうやって自動化するか決める

　まず関連するすべての業務の洗い出し。自動化できそうな業務をピックアップ。![自動化.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/f6ed0daf-3efc-2067-20a4-c907683f4478.png)
　次にどのように自動化するのかを決める。

###　**<u>①リマインドメール送信**
　　integromatでGmailとLINEを連携。報告〆曜日(月)に毎週購読しているメルマガがあり、
　　<font color="Red">**毎週メルマガを受信したら、GmailからリマインドメールをOutlookとLINEに自動配信。**</font>

###　**②Excelファイルを探す・送信**</u>
　　Excelの報告書はGoogleDrive保管。Outlookリマインドメール内にファイルURLを記載し、
　　<font color="Red">**メール上からクリック1つでジャンプ。集計担当者とURLを共有し、メール送信業務廃止。**</font>

###　**③交通費申請ページへ移動**</u>
　　同様にOutlookメール内に交通費申請ページURLを記載し、即申請ページに移行可。

## integromatでGmailとLINEを連携
　「メルマガと連携せず、毎週月曜9時にリマインド自動配信」も検討したが、
　<u>決まった時間に通知が来ると効果が薄れると考え、毎週月曜日午前中のランダムな時間に
　配信されるメルマガとの連携をあえて継続した。</u>
![integro.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/97359a45-7088-bc52-d268-65bef823e4d5.png)

###　①GmailからOutlookへリマインドメール
　　<font color="Red">**リマインドメール本文から　①報告Excelシート②申請画面　に1クリック即ジャンプ!
　　思い起こさせてくれるだけでなく、すぐに作業に取り掛かれるよう工夫してみました！**</font>

　　＜Gmail受信画面＞
![gmai.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/658166f3-37be-f81d-2635-b33a9cf2a156.png)
　　＜Outlookでのリマインドメール受信画面＞
![gmail.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/80f3f294-8435-6bff-cb2e-992e0f12d5b7.png)

###　②GmailからLINEへのリマインド通知
　　<font color="Red">**Outlook＆LINEのダブルリマインド!**</font>
![line.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/bfc03df1-db97-30f2-73ca-24264fcebdc0.png)

##　さらに発展 PowerAutomateDesktopで自動化範囲拡大
　交通費申請も『途中まで自動化できるのでは？』と思い、PADで自動化してみました!
![交通費.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793443/e18a5a21-d648-3ffc-d9a3-9927b086056a.png)
　<font color="Red">**手作業箇所直前のルーティンワーク4ステップを　1クリックで自動化</font>**

<iframe width="560" height="315" src="https://www.youtube.com/embed/5A4-js21cbw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

##　さいごに　身近な業務効率化の威力
　同じ部内のメンバーに本技術を紹介。<font color="Red">**「すごい！今すぐ俺のPCにも入れてくれ！」**</font>と
　太鼓判。今回の数倍時間をかけた「品切AI」を見せた際の「ふーんすごいねー(遠い目)」
　という反応とは雲泥の差で驚愕。技術のすごさより、便利かどうかが重要だと身に染みた。
　今後も自分の技術は磨きつつ<font color="Red">**「大勢が共感・利用できる身近で小さな業務改善」と
　「将来的な大きな業務改善」の両方にトライ**</font>できるようにしていきたい！
Python で文字列の末尾の改行を削除する

#急ぐ人向け

`str_line.rstrip('\r\n')` を使いましょう。

```ptyhon
line_content = string_line.rstrip('\r\n')
```
(注: Perl の `chomp` と異なり、元の文字列を保持する非破壊操作です。)

#以下、この記事を書いた理由(愚痴)

誰もが通ると思われる道だが、きっかけは「文字列を splitlines してから iterate するの、効率悪いんじゃね？」って思ったこと。

```python
for line in string_content.splitlines():
    print(line)
```

google って調べて、
[stack overflow] (https://stackoverflow.com/questions/3054604/iterate-over-the-lines-of-a-string) の質問と回答にたどり着いた。

そこの回答を見て、「改行が `\r\n` の場合に対応するにはどうしたらいいか」

で Bing で「python chomp」で検索し、「`rstrip()` 使うといい」という Blog記事を見つけ、そのまま実装してしまった。

```python
    # 注:問題ありコード
    def bad_line_iter(string_content):
        stri = io.StringIO(string_content)
        while True:
            nl = stri.readline()
            if nl != '':
                yield nl.rstrip()
            else:
                return
```

プログラム組み込み終わってテストする。
いくつか試していて想定外の動きをするものがあった。
デバッグ出力入れて調べたらiterator が空白のみの行を空文字列にしていた。

コードを見返す。・・・ `rstrip` って、名前からして右空白削除の関数やん。
調べたら実際にそうだった。で、末尾の連続する特定の文字群を削除する場合には `rstip` に引数に与えればよい。

そういうわけで修正。

```python
    def line_iter(string_content):
        stri = io.StringIO(string_content)
        while True:
            nl = stri.readline()
            if nl != '':
                yield nl.rstrip(’\r\n’)
            else:
                return
```

で、改めて「python chomp」や「python 改行削除」で検索したのだが、
`rstrip(’\r\n’)` を挙げているものを(少なくとも上位では)見つけられなかった。(2021年8月15日現在)


そういうわけで、記事にしました。

なお、途中にでてきた Perl の `chomp` は破壊的関数(元も文字列を書きかえる)だが、Python の `rstip` は非破壊関数(元の文字列が保持される)点には注意。

```python
>>> l = 'aaa \r\n'
>>> l
'aaa \r\n'
>>> print(l)
aaa 

>>> l.rstrip()
'aaa'
>>> l
'aaa \r\n'
>>> l.rstrip('\r\n')
'aaa '
>>> l.rstrip('\n')
'aaa \r'
>>> print(l.rstrip('\n'))
aaa 

>>> print(l.rstrip('\r\n'))
aaa 
```
NLBとAuto Scallingを連携させる

NLBのターゲットにAuto Scallingグループを指定できます。

AWS公式のドキュメントとしては[Auto Scaling グループにロードバランサーのアタッチ](https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/attach-load-balancer-asg.html)にやり方が書いてあります。

今回はこれをTerraformでやる方法を残しておきます。

ざっくりとは普通にNLB、リスナー、ターゲットグループを作成し、Auto Scallingグループをターゲットグループにアタッチしています。

## nlb.tf

```nlb.tf
resource "aws_lb" "nlb" {
  name               = "${var.base_name}-nlb"
  internal           = false
  load_balancer_type = "network"
  subnets            = var.public_subnet_ids

  tags = {
    "Name" = "${var.base_name}-nlb",
  }
}
```

## nlb-listener.tf

```nlb-listener.tf
resource "aws_lb_listener" "listener" {
  load_balancer_arn = aws_lb.nlb.arn
  port              = var.listener_port
  protocol          = "TCP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.target-group.arn
  }

  tags = {
    "Name" = "${var.base_name}-listener"
  }
}
```

## nlb-target-group.tf

```nlb-target-group.tf
resource "aws_lb_target_group" "target-group" {
  name     = "${var.base_name}-target-group"
  port     = var.target_port
  protocol = "TCP"
  vpc_id   = var.vpc_id

  tags = {
    "Name" = "${var.base_name}-target-group"
  }
}
```

## nlb-autoscaling-attachment.tf

今回のキモです。パラメータ名は`alb_target_group_arn`ですがNLBTのターゲットグループでもちゃんと紐付けてくれます。また、今回はEKSのマネージドノードグループをターゲットとしたかったため、マネージドノードグループからAuto Scallingグループ名を引っ張ってくる書き方をしています。

```nlb-autoscaling-attachment.tf
resource "aws_autoscaling_attachment" "attachment" {
  autoscaling_group_name = aws_eks_node_group.worker.resources.0.autoscaling_groups.0.name
  alb_target_group_arn   = aws_lb_target_group.target-group.arn
}
```

## variables.tf

```variables.tf
variable "base_name" {
  description = "作成するリソースに付与する接頭語"
  type        = string
}

variable "vpc_id" {
  description = "リソース群をデプロイするVPCのID"
  type        = string
}

variable "public_subnet_ids" {
  description = "パブリックサブネットのID"
  type        = list(string)
}

variable "listener_port" {
  type = number
}

variable "target_port" {
  type = number
}
```
Linuxのtarコマンド(備忘録)

複数ファイルを送信したりするとき、予めtarコマンドで一つのファイルとしてまとめておくと
一度の送信で済むので便利である。
#共通オプション
###-f
アーカイブファイル名を指定する
###-v
アーカイブ結果を表示する
###-w
コマンドを実行する直前に確認メッセージを表示する

###--show-defaults
tarコマンドの規定値を表示する

#アーカイブ
####アーカイブを新規作成する。
```
$tar -cvf [アーカイブファイル名] [アーカイブに内包するファイル]
``` 
[アーカイブに内包するファイル]では、
・複数ファイルの指定が可能（ワイルドカードでの指定可能）
・ディレクトリでの指定が可能
・ファイルを指定せず、空のアーカイブを作成することは不可能

####既存のアーカイブに新たなファイルを追加する

```
$tar -rvf [アーカイブファイル名] [アーカイブに内包するファイル]
```
[アーカイブに内包するファイル]で指定したファイルのディレクトリ・ファイル名と
既にアーカイブされているファイルと被った場合、
両ファイルともアーカイブされるが、展開・解凍時は最後にアーカイブされたファイルで上書きされる。

####更新されたファイルのみアーカイブする

```
$ tar -uvf [アーカイブファイル名] [アーカイブに内包するファイル]
```

####アーカイブファイルを統合する
```
$ tar -Avf [アーカイブファイル名] [統合されるアーカイブファイル]
```
[統合されるアーカイブファイル]にアーカイブされているファイルが[アーカイブファイル名]に取り込まれる。

####アーカイブファイル内から指定したファイルを削除する
```
$ tar --delete -f [アーカイブファイル名] [削除ファイル名]
```


#圧縮
####アーカイブしつつgzip形式で容量を圧縮する
```
$ tar -z -cvf [アーカイブファイル名] [アーカイブ元ファイル]
```
[アーカイブファイル名]は、例えば「test.tar.gz」というように圧縮ファイルと判断できるようにする

#展開
####アーカイブされたファイルを展開する
```
$ tar -xvf [アーカイブファイル名]
```

#解凍
####圧縮したファイルを解凍する
```
$ tar --gunzip -xvf [アーカイブファイル名]
```


#アーカイブされたファイルの確認
```
$tar -tf [アーカイブファイル名]
```

#圧縮・解凍のデメリット
・圧縮すると、元のデータとは全く異なる形のファイルになるということなので、正常に解凍できないことがある
・サイズの大きいファイルを圧縮・解凍しようとすると時間がかかる

#関連リンク
https://eng-entrance.com/linux-command-tar
満経過月数を計算するロジック(Ruby)

経過月数(満月)を計算するロジックについて解説します。(あまり記事がなかった)
具体的に言うと以下のようなロジック。

start：2021年01月15日
end：2021年02月14日
→経過月数0を返す

start：2021年01月15日
end：2021年02月15日
→経過月数1を返す

start：2021年01月15日
end：2022年03月15日
→経過月数14を返す

## コード

IN：開始日(start),終了日(end) ：Date型
OUT：満経過月数

```ruby
def calculate_diff_months(start, end)
  (end.year - start.year) * 12 + end.month - start.month - (end.day >= start.day ? 0 : 1)
end
```

## コードの解説
■年の計算
`(end.year - start.year) * 12`
→　年の差分を求めて月変換

■月の計算
`end.month - start.month`
→　そのまま月の差分を求める
ここまではシンプル。

■日付の計算
`(end.day >= start.day ? 0 : 1)`
終了の日付>=開始の日付の場合はそのまま月数を出したいので0で計算
終了の日付<開始の日付の場合は月数をマイナス-1にしたいので1で計算

閏年のこととか考えて最初、戸惑いましたが以外とシンプルに実装できました。
[Android] HiltでApplicationComponentが見つからない

`Hilt`のcodelab [Android アプリでの Hilt の使用](https://developer.android.com/codelabs/android-hilt?authuser=1&hl=ja#0) で、以下のエラーが発生しました。

```
エラー: シンボルを見つけられません
@dagger.hilt.InstallIn(value = {ApplicationComponent.class})
                                ^
シンボル: クラス ApplicationComponent
```

# 原因
`Hilt`のバージョンを最新の`2.38.1`にしていたことが原因で、エラーが発生していました。

# 修正
`Hilt`のバージョンをcodelabで指定されている`2.28-alpha`、または`2.28.3-alpha`にすることで解決しました。

```build.gradle
buildscript {
    ext.kotlin_version = '1.5.21'
    ext.hilt_version = '2.28-alpha'
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.0.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
    }
}
```
JavaScriptを基本からまとめてみた【11】【onchangeイベント】

##はじめに

####学習するに至った経緯

2020年より、未経験からエンジニアへの転職を目指し、某プログラミングスクールへ通う。
入学後、『Ruby』を未経験から学ぶ人が多いのと『Ruby』の求人が思っていた以上に少ないので、
卒業後、フロントエンドのエンジニアを目指す事に。
Javascriptの学習した事を言語化し、認識の深化による備忘録として記載。

##JavaScriptのonchangeイベントとは
『onchangeイベント』とは、入力欄の内容を変更した時のイベント。JavaScriptでプログラミングを行っていると、ユーザーの入力に合わせて動的に表示内容を変えたい場合に便利なのがonchangeイベントで、HTML要素の値の変更が完了した時に発生するイベント。

対象のHTML要素は <input> と <select>、及び <textarea> で、値の変更が完了したタイミングは、 <input> と <textarea> は入力が完了して他の要素にフォーカスが移動した時、<select> は選択値が変わった時になる。

##onchangeイベントの書き方
onchangeイベントの書き方は2つある。
####① HTMLで指定する方法

```html
<input onchange="関数名()">
```

####② JavaScriptで指定する方法
document.getElementById(“要素名”)で対象の要素を指定する。関数名を指定せず、以下のように直接function()を記述できる。※ onchangeのようなイベントが発生した時に動作する関数をイベントハンドラーと呼びます。

```js
document.getElementById("要素名").onchange = function() {
  // onchangeイベントが発生した時の処理を記述する
};
```


##参考サイト
[アルファシス]
(http://alphasis.info/2013/09/javascript-dom-event-onchange/)
[JavaScriptのonchangeイベントの使い方を現役エンジニアが解説【初心者向け】]
(https://techacademy.jp/magazine/20723)
PandasのDataFrameやSeriesで重複要素を取り除く方法

初投稿かつ備忘録として残しておく。
といっても、参考になったサイトのURLを残すだけ。

〇参考URL
 ・https://qiita.com/kira4845/items/6798e54eb76b15329e3c
〇やりたいこと
　・データフレームdfの特定の列col_aの重複要素を削除したい。
  ・重複のないデータフレームをdf2とする。
  ・df=(col_a , col_b , col_c,
          0   ,  0    ,  0   ,
          1   ,   2   ,  0   ,
          0   ,   5   ,  3   )
  ・df2=(col_a , col_b , col_c,
           0   ,  0    ,  0   ,
           1   ,   2   ,  0   )
  
〇解決方法
  ・drop_duplicatesというメソッドを使用する。
　　df2 = df.drop_duplicates(subset="col_a")
WindowsでSourcetreeを使ったGitHubの認証方法でパスワード認証からトークンベース認証への移行方法

# はじめに

2021年8月13日から、GitHub.comでのGit操作の認証時にアカウントのパスワードを受け付けなくなるような仕様に変更されました。
> https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/

これにより、今後はパスワード認証ではなく、トークンベース認証を使用しなければ、GitHubを操作することができなくなります。私はWindowsマシンでSourcetreeを使って、パスワード認証でGitHubを操作していたので、この仕様変更で使えなくなりました。今回は、この状態からGitHubを操作できる状態までの手順を記事にしようと思います。

この記事では、**WindowsでSourcetreeを使ったGitHubの認証方法でパスワード認証からトークンベース認証への移行方法**を記載します。トークンベース認証に関しては、個人用アクセストークン、OAuthトークン、GitHub Appインストールトークンなどありますが、ここでは**個人用アクセストークン**を用いた認証方法を使います。
よろしくお願いします。

# 手順

## 手順１：個人用アクセストークンの発行

まずは、個人用アクセストークンの発行をします。（以下、公式の手順）
> https://docs.github.com/ja/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token

これは、GitHub上で作業します。手順は以下の通りです。
1. 自分のアカウントでログイン。
2. Settingsページへ移動。
3. Developer settings > Personal access tokens > Generate new tokenの順番で移動し、発行準備。
4. Note、Expiration、Select scopesを設定して、トークンを発行する。
5. 発行されたトークンは一度しか表示されないので、必ずローカルなどへ保存し、控えておいてください。

以上で、個人用アクセストークンの発行は終了です。


### [追記 2024/09/14] Personal access tokens（Fine-grained tokens）

1. すべてのリポジトリにアクセスするなら All repositories を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309633/39afff56-0da4-d71e-ba07-5939832af841.png)
2. Permissions は基本的な操作のみなら Contents を Read and write に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309633/83e9e028-fc17-baf3-6459-0bd1efbea8e8.png)
3. Genarate し、個人用アクセストークンを控えておく。


## 手順２：Sourcetreeのpasswdファイルの削除
次に、ローカルにある、Sourcetreeのpasswordファイルを削除します。
これをすることで、今まで適用されていたパスワードを削除することができます。
以下の場所に置いてあるので、このpasswdファイルを削除します。

```
C:\Users\{USERNAME}\AppData\Local\Atlassian\SourceTree\passwd
```

削除したら、Sourcetreeを再起動します。
以上で、Sourcetreeのpasswdファイルの削除の終了です。

## 手順３：Sourcetreeで個人用アクセストークンを使って、再認証する
最後に、Sourcetreeで個人用アクセストークンを使って、再認証します。
これは、Sourcetree上で作業します。手順は以下の通りです。

1. Sourcetreeを起動したら、ツール > オプション > 認証 > アカウント > 編集 を選択します。
2. 認証がBasicに選択されている状態で、パスワードを再読み込みします。
3. パスワードに、先ほど発行した個人用アクセストークンを入力します。

※ Sourcetree操作時に、再度パスワードを求められたら、個人用アクセストークンを入力してください。

以上で、Sourcetreeで個人用アクセストークンを使って、再認証は終了です。

### [追記 2024/09/14] Personal access tokens（Fine-grained tokens）
1. Sourcetreeを起動したら、ツール > オプション > 認証 > アカウント > 編集 を選択します。
2. 認証が Personal Access Token に選択されている状態で、Personal Access Token を再読み込みします。
3. パスワードに、先ほど発行した個人用アクセストークンを入力します。

# おわりに
これで無事に、WindowsでSourcetreeからGitHubを操作することができるようになったと思います。
ここまで読んでいただき、ありがとうございました。