OmniAICreator/Qiita-1.07M huggingface dataset:
2023/5/6主にITとかセキュリティの記事

Appleが「緊急セキュリティ対応」アップデートを配信。機能実装後初(5/2)
https://pc.watch.impress.co.jp/docs/news/1498041.html

Google Chrome、南京錠アイコンを2023年9月に廃止(5/4)
https://news.mynavi.jp/techplus/article/20230504-2671546/

米、生成AIのリスク協議　マイクロソフトなどと対応策を検討へ(5/4)
https://mainichi.jp/articles/20230504/k00/00m/030/067000c

米、ＡＩ利用指針案策定へ　国際規格整備に着手　開発企業に情報公開要求/(5/4)
https://www.sankei.com/article/20230504-GRPBRRAIWVIDXKJ53Z6QPHFLQI/?ownedutm_source=owned%20site&ownedutm_medium=referral&ownedutm_campaign=ranking&ownedutm_content=%E7%B1%B3%E3%80%81%EF%BC%A1%EF%BC%A9%E5%88%A9%E7%94%A8%E6%8C%87%E9%87%9D%E6%A1%88%E7%AD%96%E5%AE%9A%E3%81%B8%E3%80%80%E5%9B%BD%E9%9A%9B%E8%A6%8F%E6%A0%BC%E6%95%B4%E5%82%99%E3%81%AB%E7%9D%80%E6%89%8B%E3%80%80%E9%96%8B%E7%99%BA%E4%BC%81%E6%A5%AD%E3%81%AB%E6%83%85%E5%A0%B1%E5%85%AC%E9%96%8B%E8%A6%81%E6%B1%82

元SEC高官がバイナンス（Binance）の顧客に向けて警告(5/3)
https://nextmoney.jp/?p=58254

【注意！】Appleを装うフィッシングメールが出回る(5/2)
https://iphone-mania.jp/news-535074/

「世界のGoogle」が成し遂げてきた“常識を覆すDX事例”3選(5/4)
https://news.nicovideo.jp/watch/nw12523167

アングル：比のＮＦＴゲームブーム、暗号資産急落で残った巨額損失(5/4)
https://jp.reuters.com/article/phillipines-nft-idJPKBN2WO066

海外旅行では4人に1人が被害。GW旅行先の無料Wi-Fi、USB充電スポットでのハッキングに注意！(5/4)
https://news.yahoo.co.jp/byline/shinoharashuji/20230504-00348244

【TV朝鮮ニュース動画】韓国選管、北に7回ハッキングされてもセキュリティー点検勧告を拒否(5/4)
https://www.chosunonline.com/site/data/html_dir/2023/05/04/2023050480016.html

内閣サイバーセキュリティセンター名乗る男　ニセ電話詐欺事件(5/4)
https://news.yahoo.co.jp/articles/fa7d7715e77c7440ec09b64fe4826e34bfa4c51e

ニセ電話で高齢男性が約１３００万円だまし取られる(5/3)
https://news.yahoo.co.jp/articles/7b974648f32b4a6d4f96df150d7b2be9ce5ba9a1

「内閣サイバーセキュリティセンター」名乗る男らから電話、８５歳男性が１３２１万円だまし取られる(5/4)
https://news.yahoo.co.jp/articles/36ef28d215a46407f48d87950ef090ea3cb5efec
入力したメールアドレスをリンクに変える方法

Rubyを勉強する一環で、入力したメールアドレスをリンクに変えるコードを書いてみました。

## 目次
0. [サンプルコード](#サンプルコード)
1. [正規表現で入力されたメールアドレスを抜き出す](#正規表現で入力されたメールアドレスを抜き出す)
2. [email_regexで抜き出したメールアドレスをリンクに変換する](#email_regexで抜き出したメールアドレスをリンクに変換する)
3. [（確認）irbでRubyファイルを実行する](#irbでRubyファイルを実行する)
4. [最後に](#最後に)

## <span id="サンプルコード">サンプルコード</span>

```Ruby:Ruby
def replace_email_with_links(input_string)
  # メールアドレスの正規表現
  email_regex = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z]{2,}\b/i
  # 入力文字列内のメールアドレスをリンクに変換
  result = input_string.gsub(email_regex) do |email|
    "<a href='mailto:#{email}'>#{email}</a>"
  end
  result
end
# テスト
input_string = "Hello, my email address is example@example.com. Please feel free to contact me."
puts replace_email_with_links(input_string)
```
## <span id="正規表現で入力されたメールアドレスを抜き出す">正規表現で入力されたメールアドレスを抜き出す</span>
以下のコードによって正規表現で入力をふるいにかけられます。

```Ruby:Ruby
  # メールアドレスの正規表現
  email_regex = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/i
```

- 補足

  - \b：単語の境界を表す
  - [A-Za-z0-9._%+-]+：英数字、ドット、アンダースコア、パーセント、プラス、ハイフンの1文字以上の繰り返しを意味する
  - \\.：メールアドレスのドメイン名とトップレベルドメインを区切るドットを意味する。なお、\は.をエスケープさせる文字として使用されている。.は、正規表現では任意の1文字にマッチする特殊なメタ文字であるが、\.としてエスケープすることで、.をリテラル文字として扱うことができる。
  - /i：正規表現のフラグで、大文字小文字を無視することを示す。



## <span id="email_regexで抜き出したメールアドレスをリンクに変換する">email_regexで抜き出したメールアドレスをリンクに変換する</span>
以下のコードでは、input_stringから、email_regexの条件に合う部分を抜き出し、その変数名をemailと置いている。その後、emailをリンク化している
```Ruby:Ruby
  # 入力文字列内のメールアドレスをリンクに変換
  result = input_string.gsub(email_regex) do |email|
    "<a href='mailto:#{email}'>#{email}</a>"
  end
```

## <span id="最後に">最後に</span>
今回は自らの勉強用に記述したコードを解説しました。Railsでなんとなく記載していることでしたが、細かく分解して読解しようとすると慣れるまでは少し厄介だと思うので、備忘録として記事にしました。
Gitチートシート

# はじめに
作業しているとああしたいこうしたいとなるので、忘れずに...

# 削除したファイルのログを確認したい(git log)
```powershell:gitLog.ps1
> git log -- [ファイルパス]
```


# 特定のコミットIDまで戻したい(git reset)
```powershell:gitReset.ps1
# 特定バージョンに戻す
> git reset hard [コミットID(6 or 40 chars)]

# 手順
#  １．特定のコミットIDに戻す
#  ２．リモートブランチ削除
#  ３．リモートブランチにプッシュ
```

# 特定コミットを取り込みたい(git cherry-pick)
```powershell:gitCherrypick.ps1
> git cherry-pick [コミットID(6 or 40 chars)]

# コミットID側を優先してマージ
> git cherry-pick -Xtheirs [コミットID(6 or 40 chars)]

# Mergeコミットを適用
> git cherry-pick -m [コミットID(6 or 40 chars)]
```
【参考サイト】
　◆git cherry-pick の基本仕様と、主要なオプション
　　https://www-creators.com/archives/2578

# 特定バージョンに戻したい(git checkout)
```powershell:gitCheckout.ps1
# 特定バージョンに戻す
> git checktout [コミットid]

# 最新バージョンに戻す
> git checkout master
```
【参考サイト】
　◆知らずに使ってた【git checkout HEAD -- . 】の「--」ハイフンハイフンと「.」ドットの意味
　　https://qiita.com/wagase/items/5b65d0efaf3d4985256b
　◆[git] 戻したい時よく使っているコマンドまとめ
　　https://qiita.com/rch1223/items/9377446c3d010d91399b
Javaで球体を描画してみた（レイトレーシング）

# 概要
Javaで球体を描画してみました（レイトレーシング）。今回は簡単のため球体上に赤色点光源があるものを想定しました。
視点とスクリーンと物体の関係は以下の通りです。
![図面2023.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/882e9d5d-c7fc-0129-c6eb-55e3b8807bb8.png)

# ソースコードは以下の通りです。
マウスをクリックすると、球体を巨大化し再描画するようにしました。
```Sphere.java
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Sphere extends JPanel implements MouseListener {
    static int iWidth = 600;
    static int iHeight = 600;
    static double iShiten = -10.0;
    static double dSphereSize = 0.10;
    public Sphere(){
	addMouseListener(this);
    }
    public void paint(Graphics g){
	super.paint(g);
	for(int i=-iWidth; i<iWidth; i++){
	    for(int j=-iHeight; j<iHeight; j++){
		for(double d=iShiten; d<+1.0; d+=0.1){
		    double x=(double)i/(double)iWidth;
		    double y=(double)j/(double)iHeight;
		    if(Math.sqrt(x*x+y*y+d*d)<dSphereSize){
			g.setColor(Color.red);
			g.drawLine(iWidth+i,iHeight+j,iWidth+i,iHeight+j);
		    }
		}
	    }
	}
	System.out.println("paint()");
    }
    public void mouseClicked(MouseEvent e){
        System.out.println("mouseClicked");
	dSphereSize += 0.1;
	repaint();
    }
    public void mouseEntered(MouseEvent e){
        System.out.println("mouseEntered");
	dSphereSize = 0.10;
    }
    public void mouseExited(MouseEvent e){
        System.out.println("mouseExited");
    }
    public void mousePressed(MouseEvent e){
        System.out.println("mousePressed");
    }
    public void mouseReleased(MouseEvent e){
	System.out.println("mouseReleased"); 
    }	 
    public static void main(String[] args) {
	JFrame jf = new JFrame();
	jf.getContentPane().add(new Sphere());
	jf.setTitle("Sphere");	
	jf.setSize(iWidth*2, iHeight*2);
	jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	jf.setVisible(true);
    }
}
```

# 実行結果
はじめは小さいですが、
![Screenshot from 2023-05-06 02-52-41-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/e8476095-7c5a-74db-67e5-53b702bc98c1.png)
クリックすると大きくなります。
![Screenshot from 2023-05-06 02-53-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/9fb0ae54-cc18-979c-eac5-0f7fa22fc060.png)

何かの役に立てばと。
使われているはずのポート番号を「lsof」コマンドでgrepして叩いても何も返って来ずヒヤヒヤした件

## 状況
jarファイルを実行しようとしたところ、「8080」が使用中だと怒られる。
![20230506-022636.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659821/8ceabeb7-6076-d5cb-1d4c-d49b016d07ed.png)
・「lsof」コマンドで確認
```
lsof -i -P | grep 8080
```
、、、何も表示されない？？

## 解決方法
管理者権限を使用して起動したアプリやミドルウェアについては、以下の例のように「sudo」をつけて「lsof」コマンドを実行しないと、利用しているプロセスが確認ができないようです。

### ✖️ 失敗例
```
lsof -i -P | grep 8080
```

### ◯ 成功例
```
sudo lsof -i -P | grep 8080
```

## まとめ
最初は使われているはずのプロセスが表示されず、目の前で何が起きているのかわかりませんでした。後から考えたら至極当然のように思えますが、管理者権限を使用した起動なのか曖昧な場合も、「sudo」を付けることで確認できるので頭の片隅に入れておくと安心ですね！
【WSL2】ubuntu20.04にdockerとdocker-composeを導入する

## 概要
`Windows11` 上の `WSL2` に `docker` と `docker-compose` をインストールする手順です。
（[公式ページ](https://matsuand.github.io/docs.docker.jp.onthefly/engine/install/ubuntu/) にもしっかり載っています）

## 作業手順
1. `docker` インストール
1. `docker-compose` インストール

## 1. `docker` インストール

### 1-1. パッケージ更新
```bash
sudo apt update
```

### 1-2. 必要なパッケージインストール
```bash
sudo apt install apt-transport-https ca-certificates curl software-properties-common
```

### 1-3. dockerの公式 `GPG` 鍵を追加
```bash
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
```

### 1-4. dockerリポジトリを追加
```bash
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
```

### 1-5. dockerインストール
```bash
sudo apt install docker-ce
```

### 1-6. バージョン確認
```bash
docker version
```

### 1-7. docker起動
```bash
sudo service docker start
```

以下のような結果になれば正常に起動できています。
```bash
$ sudo service docker start
 * Starting Docker: docker                                     [ OK ]
```

## 2. docker-compose インストール

### 2-1. `github` の `docker-compose` のリリースノートからバージョンを確認
[リリースノート](https://github.com/docker/compose/releases)

今回は `v2.16.0` をインストールしようと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3340968/eb36172b-a57d-870b-214f-882ec76e322c.png)

タグページの下のほうにダウンロードリンクがありますので、 `docker-compose-linux-x86_64` があるか確認しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3340968/ca07afd3-f90d-d68f-62ec-694a4a2b0b44.png)

`curl` コマンドでダウンロードします。
```
curl -L https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-linux-x86_64 > ./docker-compose
```

`/usr/local/bin` 移動させます
```
sudo mv docker-compose /usr/local/bin/docker-compose
```


### 2-2. docker-composeに権限付与
```
sudo chmod +x /usr/local/bin/docker-compose
```

### 2-3. バージョン確認
```
docker-compose -v
```

### 2-4. （任意） `docker-compose` は長いので `dc` で呼び出せるようにする
※ 既に `dc` コマンドが存在することもあるので注意（macなど）

`.bash_aliases` に `alias dc='docker-compose'` を追加します

```
vi ~/.bash_aliases
```

以下の文言を追加
```
alias dc='docker-compose'
```

以上で `WLS2` 環境に `docker-compose` のインストールは完了です！
Djangoをpythonanywhereでdeployしたときの注意事項や備忘録

基本はこちらを参照しましたが、追加で色々やる必要があったので、その備忘録

https://tutorial.djangogirls.org/ja/deploy/

## pythonanywhere
pythonanywhereは無料で利用できるが、使用期間をクリックし更新しなければ
3ヶ月ほどで、期限が切れるため注意
api tokenの作成もここで行なっておく

https://www.pythonanywhere.com/

# Djnagoをdeploy
consoleにアクセスし、黒いCLI画面から諸々の操作を行う。

## git pullする
githubのkeyを作成し、pull可能にする。
githubのkey取得に手間取り、pullの許可も行う。

以下を参考にpull
```
git pull https://ghp_hogehoge@github.com/username/repositoyname.git
```

https://denblog.info/archives/2217

## mysqlのconsoleから、databaseを作成する。

consoleに入って、databaseを作成する

settings.pyを本番用にカスタマイズする必要があるため
mysqlのhostnameを調べる
→databaseタブからhostnameが見れる

`pip install mysqlclient`も実行しておきましょう

以下のようになります
`
hostname: <username>.mysql.pythonanywhere-services.com
`
`
name: <username>$test_db
`

https://help.pythonanywhere.com/pages/UsingMySQL/

# wsgiの記述を変更
書き方がダメだったのか、setdefaultの書き方だとエラーが出たので、変更しました

```
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'test.settings')
↓
os.environ['DJANGO_SETTINGS_MODULE'] = 'test.settings'
```

また、本番のpathも追加で記述が必要になります。
このpathの追加がかなり調べるのがしんどかった

完成コード
```python wsgi.py
import os

import sys
#追加
path = '/home/username/test/test1'
if path not in sys.path:
    sys.path.append(path)


from django.core.wsgi import get_wsgi_application
#変更
os.environ['DJANGO_SETTINGS_MODULE'] = 'test.settings'

application = get_wsgi_application()
```
https://blog.mtb-production.info/entry/2018/06/01/070000

https://www.pythonanywhere.com/forums/topic/14421/

# static file

djangoではstatic fileにcssや画像データを格納するみたいです
このあたりのpath周りをセッティング

```settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    BASE_DIR / 'static',
    
]
STATIC_ROOT = '/home/username/test/static'

```

` python manage.py collectstatic`
を実行するとstaticフォルダに移動される
この時、staticフォルダを手動で作る必要あり


https://7me.nobiki.com/2017/django-collectstatic.html

https://docs.djangoproject.com/en/4.2/howto/static-files/

https://www.tohoho-web.com/django/settings.html

# form.is_valid()
formを使い登録するところでエラーが発生
debug=Trueには本番ではあまりやらない方がいいので、localで対応

messageをtemplate上に出して、確認を行う
```
form = UserCreationForm(request.POST)
for e in form:
        messages.error(request,e.errors)
```

https://torajirousan.hatenadiary.jp/entry/2019/10/09/173502

https://yu-nix.com/archives/django-form-get-val/

また、databaseのエラーも出たが、migrateがうまくいっていなかったみたい。
きちんとやり直すといいかも

https://tech.kurojica.com/archives/11243/

#その他
localでdotenvを使用していたが、本番ではうまく機能しなかった
また後ほど調査してみる

https://stackoverflow.com/questions/59572174/no-module-named-dotenv-python-3-8
MockInterceptorを使ったモックレスポンスの返し方

:::note warn
以下の文言は、AI (ChatGPT4) による出力結果です。そのため内容が一部不正確である可能性があります。
:::

開発中にサーバーサイドの実装がまだ完了していない場合、フロントエンドの開発をスムーズに進めるためには、モックレスポンスを返す方法が役立ちます。今回は、サンプルアプリ [zero-2023-android](https://github.com/dignicate/zero-2023-android) を元に、Retrofit2 を使って MockInterceptor を利用し、モックレスポンスを返す方法を解説します。

### 1. MockInterceptorの実装

まずはじめに、MockInterceptor クラスを実装します。これにより、アプリがサーバーにリクエストを送る代わりに、内部で定義したモックレスポンスを返すことができます。リポジトリ内の MockInterceptor.kt に実装があります。

### 2. RetrofitにMockInterceptorを追加

次に、Retrofit のインスタンスを作成する際に、MockInterceptor を追加します。リポジトリ内の ApiModule.kt に実装があります。

```kotlin
@Module
@InstallIn(SingletonComponent::class)
object ApiModule {
    @Provides
    @Singleton
    fun provideMockInterceptor(@ApplicationContext context: Context): MockInterceptor {
        return MockInterceptor(context)
    }

    @Provides
    @Singleton
    fun provideOkHttpClient(mockInterceptor: MockInterceptor): OkHttpClient {
        return OkHttpClient.Builder()
            .addInterceptor(mockInterceptor)
            .build()
    }

    @Provides
    @Singleton
    fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .baseUrl("https://api.example.com")
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }
}
```
このコードでは、provideMockInterceptor で MockInterceptor を生成し、provideOkHttpClient で生成された OkHttpClient に追加しています。最後に、provideRetrofit で、設定した OkHttpClient を使用して Retrofit のインスタンスを作成しています。

### 3. JSONリソースの準備

モックレスポンスとして返す JSON をアプリのリソースに配置します。リポジトリ内にある mock ディレクトリに、モック用の JSON ファイルが格納されています。例として、以下のような JSON ファイルが用意されています。

mock/api1.json

```json
{
  "key1": "value1",
  "key2": "value2"
}
```
mock/api2.json

```json
{
  "key1": "value3",
  "key2": "value4"
}
```
MockInterceptor では、
```kotlin
context.assets.open(mockResponseFile).bufferedReader().use { it.readText() } 
```
により、リソースに格納された JSON ファイルを読み込み、モックレスポンスとして返しています。

これにより、サーバーサイドの実装が未完成であっても、アプリの開発をスムーズに進めることができます。サーバーとの接続が不要な状況でも、モックレスポンスを利用して UI やロジックの開発を行うことが可能です。
【AWS】SpringBootアプリのサービス化で作成する「〇〇.service」ファイルの[service：ExecStart = ]の内容について解説

# はじめに
SpringBootアプリをAWSのec2からデプロイしサービス化を試みたところ、思った以上に躓いたため同じような状況で悩んでいる方の助けになれば幸いです。

### 開発環境
・ java 11
・ SpringBoot 2.5.6
・ MySQL 8.0
・Apache Tomcat 9.0.73

## 結論
以下の内容で、無事にサービス化できアプリが正常に起動しました。
実際に、SSH接続が切れてもアプリが起動した状態を保ち、該当のURLでブラウザから動かせる事も確認済みです。

＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

[Unit]
Description = 任意の文言
After=syslog.target

[Service]
ExecStart = <font color="Tomato">__/bin/java -jar__</font> /jarファイルのパス
Restart = always
Type = simple
User = ユーザ名
group = グループ名
SuccessExitStatus = 143
KillMode = process

[Install]
WantedBy = multi-user.target

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

・ユーザ名とグループ名の確認方法
```
ls -l jarファイルのパス
```
※pwdコマンドで

## 解説

[Service]
ExecStart = <font color="Tomato">__/bin/java -jar__</font> /jarファイルのパス

__※今回の記事で一番お伝えしたいのは①の部分です。__
①<font color="Tomato"> __/bin/java -jar__</font>
② /jarファイルのパス

【イメージ】
ExecStart = ① ②
※①と②の設定の間に半角スペースがあります。

jarファイルのパスの指定②だけでなく、jarファイルを実行する時と同じように(上記の赤文字でハイライトした)「__java -jar__ 」のコマンドの設定①が、「ExecStart = 」以降に必須のようです。「/binディレクトリの配下にjavaコマンドの実行用ファイルがあり、それを「ExecStart = 」以降に設定することでサービスファイルを実行できる」くらいのイメージで大丈夫だと思います。②のjarファイルのパスについては、jarファイルが置いてある階層で「__pwd__」コマンドを叩けば確認できます。

・サービスファイルの実行用コマンド
```
sudo systemctl start 〇〇.service
```
・ステータス確認用コマンド
```
sudo systemctl status 〇〇.service -l
```
起動に成功している場合、以下のように緑色の「active (running)」が確認できます。
この状態になれば、アプリが裏側で動き続けてくれるようなので、SSH接続が切れても問題なくアプリが使用できます。
![20230506-002256.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2659821/d119231c-5b15-77be-37a4-fc0cae413c10.png)
・ログ確認用コマンド
```
sudo cat /var/log/messages
```
もし、①のjavaコマンドの指定ができていない場合は、サービスファイルの実行後に起動に失敗し以下のようなエラーがログに出力されます。
```
Failed at step EXEC spawning ... Exec format error
...main process exited, code=exited,status=203/EXEC
```

## 最後に
今回、サービス化用のファイルを作成したのが初めてであったため、解決するのに時間がかかってしまいました。。間違った内容がございましたら、恐れ入りますがご指摘いただければ幸いです。
最後までお読みいただきありがとうございました。

## 参考にしたサイト
・[EC2+RDS+SpringBootアプリケーションでwebページを公開する。](https://qiita.com/kachikata96/items/cdc961a860c63108ae76)
・[SpringBootをサービス化（デーモン化）して常駐させる](https://springhack.com/springboot%E3%82%92%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E5%8C%96%EF%BC%88%E3%83%87%E3%83%BC%E3%83%A2%E3%83%B3%E5%8C%96%EF%BC%89%E3%81%97%E3%81%A6%E5%B8%B8%E9%A7%90%E3%81%95%E3%81%9B%E3%82%8B/)
【Git & GitHub 初心者が躓いたポイントまとめ】


GitとGitHubを使い始めると、初心者が躓くポイントや疑問に思ったポイントがいくつかあります。
ここでは、それらのポイントを整理し、解決策を提案します。
なお、解決策は基本的にチャットGPT先生に教えてもらいました。


1. コミットの単位

問題: どの単位でコミットするべきか分からない（1行、1ファイル、1クラスなど）。

解決策: コミットは関連性のある変更に対して行うことが望ましい。機能追加やバグ修正など、ひとつの目的に対してまとめてコミットしましょう。


２. 環境の使い分け

問題: git bash、cloud9、VSCodeなど、複数の環境を使い分けることに頭が混乱する。

解決策: 最初は一つの環境に絞って使うことをおすすめします。慣れてきたら、他の環境も使い分けられるようになるでしょう。


３. ステージングエリアへのファイル追加

問題: git add . を入力すると、そのディレクトリ内のファイルが全てステージエリアにアップされるのか？

解決策: git add . は現在のディレクトリとそのサブディレクトリ内の全ての変更をステージングエリアに追加します。特定のファイルだけステージングしたい場合は、git add <ファイル名> を使いましょう。


４. ファイル削除と変更のバージョン管理

問題: gitのバージョン管理はファイルの削除とファイル内容の変更を別にaddしないといけないのか？まとめてやれないのか？

解決策: git add . を使えば、ファイルの削除と変更を同時にステージングエリアに追加できます。また、git commit -a を使うと、変更されたファイルを自動的にステージングエリアに追加してコミットできます。


５. ローカルリポジトリの内容の閲覧

問題: ローカルリポジトリにアップしたものはGitのサイトの自分のページで見られるのか？

解決策: ローカルリポジトリの内容は、リモートリポジトリにpushされるまで、Gitのサイトで見ることはできません。ローカルリポジトリの変更履歴は、git logコマンドを使って閲覧できます。


６. ユーザー名とパスワードの確認

問題: pushした時にユーザー名とパスワードを聞かれなかったけど大丈夫なのだろうか？

解決策: Gitの設定で、認証情報を保存している場合、ユーザー名とパスワードを聞かれなくても問題ありません。git configコマンドを使って設定を確認できます。


７. コミット履歴の確認

問題: GitHubの画面上にコミットの履歴を確認するボタンがない。

解決策: GitHubのリポジトリページで、「Commits」タブをクリックすると、コミット履歴を確認できます。また、ブランチごとに履歴を表示することも可能です。


８. 変更の取り消し

問題: Gitの変更を取り消すコマンドだけど、どの範囲で取り消すのか？

解決策: git revertやgit resetを使って、特定のコミットまで変更を取り消すことができます。これらのコマンドは、コミットの範囲を指定して実行します。


９. ブランチの利用

問題: ブランチを使った開発は個人開発でも有益なのか？

解決策: ブランチを使うことで、新機能の開発やバグ修正を安全に行えます。個人開発でも、ブランチを使って作業を分けることが有益です。



１０. ブランチとローカルファイルの関係

問題: ブランチを使って分けた時に、ローカルのファイルとの関係性はどうなるのか？

解決策: ブランチを切り替えると、ローカルファイルもそのブランチの状態に合わせて変更されます。複数のブランチで同じファイルを編集する場合、マージ時にコンフリクトが発生することがありますが、適切な手順で解決できます。


１１. ブランチの枝分かれ

問題: ブランチを3つ以上に枝分かれさせることができるのか？

解決策: ブランチは3つ以上に枝分かれさせることができます。複数の機能開発やバグ修正を同時に行いたい場合、それぞれのタスクごとにブランチを作成することで、作業を効率的に進められます。


１２. プルリクエストとマージ

問題: プルリクエストを送ってマージされたら、ローカルのファイルも自動で更新されるのか？

解決策: プルリクエストがマージされても、ローカルのファイルは自動で更新されません。マージされた内容をローカルに反映させるためには、git pullコマンドを使ってリモートリポジトリの最新の変更を取得する必要があります。


１３. ローカルでのブランチ削除

問題: リモートリポジトリでブランチが削除されたら、ローカルのブランチも自動で削除されるのか？

解決策: リモートリポジトリでブランチが削除されても、ローカルのブランチは自動で削除されません。ローカルのブランチを削除するには、git branch -d <ブランチ名> コマンドを使って手動で削除する必要があります。


１４. コンフリクトの解決

問題: コンフリクトが発生した場合、どのように解決すればいいのか？

解決策: コンフリクトが発生したファイルを開き、コンフリクトが発生している箇所を特定します。その箇所には、<<<<<<<, =======, >>>>>>> のマークが付いています。適切な状態に修正した後、再度コミットとプッシュを行います。




１５. マージ先の選択

問題: マージはどっちがどっちを取り込むかをどうやって決めるのか？

解決策: マージ先のブランチを選択する際、通常は master や main ブランチに他のブランチの変更を取り込む形が一般的です。リモートリポジトリでプルリクエストを作成するときに、ベースブランチ（変更を取り込むブランチ）と比較ブランチ（取り込む変更があるブランチ）を選択します。ローカルでマージを行う場合には、git checkoutでベースブランチに移動し、git merge <比較ブランチ>でマージを行います。


１６. プライベートリポジトリとパブリックリポジトリ

問題: リポジトリを作る時はパブリックがいいのかプライベートがいいのか？

解決策: どちらを選ぶかは、プロジェクトの目的や内容によります。パブリックリポジトリは誰でもアクセスでき、コードを閲覧・フォーク・プルリクエストを送ることができます。オープンソースプロジェクトやポートフォリオとして公開したい場合に適しています。プライベートリポジトリは指定したメンバーのみがアクセスでき、プロジェクトの機密性が高い場合や企業の内部プロジェクトで利用されることが多いです。



１７. 個人開発とブランチ

問題: ブランチを使った開発って個人開発でも有益なのか？

解決策: 個人開発でもブランチを使った開発は有益です。ブランチを使うことで、新しい機能の開発やバグ修正を安全に行うことができます。また、コードの履歴が分かりやすくなり、機能や修正毎に分けられたコミットが追跡しやすくなります。個人開発でも、masterやmainブランチは安定した状態を保ち、新しい機能や修正は別ブランチで行い、完成したらマージするという流れが推奨されます。
1次元波動方程式を解く

# プログラム
解法には差分法を用います。差分法とは、微分方程式を漸化式に近似し、離散的に解く解法です。
精度は多少落ちますが、比較的計算しやすく、直感的にもわかりやすい方法で、偏微分方程式は、だいたい差分法で解けます。

解くべき式は、
```math
\frac{\partial^2 u}{\partial t^2} = c^2 \frac{\partial^2 u}{\partial x^2}
```
です。普通の波動方程式ですが、初期条件によっては紐を両端で持って中央を上下させるような運動です。

ここでu(x,t)は波の変位を表す関数であり、cは波速度です。この方程式を差分法によって解くために、空間方向と時間方向にグリッドを作り、各点の変位を数値で求めます。具体的には、以下のように差分をとります。

```
u(i,j+1) = u(i,j) + c^2dt/dx^2(u(i+1,j) - 2u(i,j) + u(i-1,j))
```

ここでu(i,j)はグリッド上の(i,j)の位置の変位を表しています。この式は、(i,j)周りの3点の変位を使って(i,j+1)の変位を求めるものであり、波動方程式を離散化したものです。この差分方程式は、時間ステップごとに解くことで波動方程式を数値的に解くことができます。

このコードでは、初期条件として与えられた関数f(x)をsin(2πx)としています。空間方向のグリッド数nx、空間方向の刻み幅dx、時間方向の刻み幅dt、波速度c、計算の終了時刻tmaxなどのパラメータも定義されています。初期条件の設定後、時間ステップのループに入り、先ほどの差分方程式を用いて、時間ステップごとに変位u(x,t)を計算しています。最後に計算結果を出力しています。

```
 u[i] = func(x, 0.0);
```
の部分は、初期条件を表しています。t=０における、各点の初期位置をsin2πxで表現しています。
（ちなみにxは離散の実数なので、sin2πxは常に0ではないことに注意。）


```C
#include <stdio.h>
#include <math.h>

#define PI 3.14159265358979323846

double func(double x, double t) {
    // 初期条件として与えられた関数 f(x)
    return sin(2*PI*x);
}

int main() {
    int nx = 100;          // 空間方向のグリッド数
    double dx = 0.1;       // 空間方向の刻み幅
    double dt = 0.001;     // 時間方向の刻み幅
    double c = 1.0;        // 波速度
    double tmax = 1.0;     // 計算の終了時刻
    double t = 0.0;        // 現在の時間
    double u[nx];          // u(x, t)の配列
    double u_new[nx];      // 時間ステップt+dtでのu(x)の配列

    // 初期条件の設定
    for (int i = 0; i < nx; i++) {
        double x = i*dx;
        u[i] = func(x, 0.0);
    }


    // タイムステップのループ
    while (t < tmax) {
        // 端点以外の空間方向の差分を計算
        for (int i = 1; i < nx-1; i++) {
            u_new[i] = u[i] + c*c*dt/dx/dx*(u[i+1] - 2*u[i] + u[i-1]);
        }
        // 端点の差分を計算
        u_new[0] = u[0] + c*c*dt/dx/dx*(u[1] - 2*u[0] + u[nx-1]);
        u_new[nx-1] = u[nx-1] + c*c*dt/dx/dx*(u[0] - 2*u[nx-1] + u[nx-2]);
        // u(x, t+dt)を更新
        for (int i = 0; i < nx; i++) {
            u[i] = u_new[i];
        }
        // 時間を更新
        t += dt;
    }

    // 結果の出力
    for (int i = 0; i < nx; i++) {
        double x = i*dx;
        printf("%f %f\n", x, u[i]);
    }

    return 0;
}
```
HTML/CSSでロゴを作ってみた

## 1. 初めに

HTML/CSSでロゴの作成に挑戦してみました。
cssは完全に慣れていませんが、本物のロゴに近づけるようネットなどを駆使して作成しました。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="poxWJpp" data-user="tsubasamaru" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/tsubasamaru/pen/poxWJpp">
  National Geographic Logo</a> by tsubasa (<a href="https://codepen.io/tsubasamaru">@tsubasamaru</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


## 2. 気をつけたこと 

### ⑴ ロゴに使用されている字体について　

ロゴの字体を英語で検索したところ、「geometric sans serif」というフォントが使用されていましたが、CSSのfont-familyでは、sans-serifとか色々ありましたが,今回は「"geometric sans serif" sans-serif」を使用しました。

### ⑵ 金色の四角形に四角い穴を開けるには

まず、２つの四角形を用意します。金色の四角形と黒色の四角形です。それから、黒色の四角形を金色の四角形に埋め込みます。
このとき、黒色の四角形を金色の四角形に埋め込むため、中まで移動する必要があるので、cssの「tansform」というプロパティを使用しました。

## 例:　transform:translate(-50px, 120px) scale(0.8, 1);

### 3. 最後に

今回作成した四角形が上に位置するナショジオのロゴですが、今度は左側に位置するロゴを作りたいのでですがフォントもまた違ってくるため、苦戦しています。
geometric sans serifと英語で表記していましたが、中々ロゴのような感じが出てきませんでした。まだ模索しています。
メインフローからサブフローへ、サブフローからメインフローへ値の引き渡し

画面フローを使って値の受け渡しについて紹介します。個人的に面白い作りでした。
しかし、受け渡し値が余りにも多くなると、メインフローがすごく重たくなりますので、ご注意ください。
（経験談から話すと300くらいの変数を作ると、もう動きが遅くなります、その際、ブラウザの更新をお勧めします）

やりたいこと：
サブフロー１で入力した値をメインフロー経由で確認画面のサブフローaで出力する
※サブフロー１の後ろにサブフロー２，サブフロー３....など追加することができます。
用途は、フローを実行するユーザから情報を収集したり、そのユーザに情報を表示したりします。
最もイメージしやすいのは、どこかの会社のアカウントの新規作成時
入力画面１→入力画面2→入力画面3→入力した情報の確認画面

1.サブフロー1:　
⓵テキストコンポーネント配置
表示ラベル：お名前；Api名：fullName
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/8b6df0e6-919c-367b-7920-31612cf24bda.png)
⓶出力可能なテキスト型変数を作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/2a268bf7-cbf0-154a-69cf-329cdd033c60.png)
⓷入力する値のApi名を出力変数に割り当て
※ここは右から左へ代入するという意味です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/0c650ed7-d2cb-1a3c-060d-fa090a8527a8.png)
⓸保存して、有効化する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/cab53b26-f65b-a30a-a619-f9b56ec7c8d2.png)

2.サブフローa： 
⓵入力可能なテキスト型変数を作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/6266963e-3eb9-b5d3-d0d0-ae77d6520210.png)
⓶表示テキストコンポーネント配置
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/ac850d38-54a1-712a-ff4c-b74192880f6d.png)
表示テキスト１：表示ラベル：お名前；Api名：QuestionLabel(適切）
表示テキスト２：表示ラベル：2.⓵で設定した変数値；Api名：fullName(適切）
⓸保存して、有効化する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/95753439-222a-fad7-1cfe-bda978ae8e31.png)

3.メインフロー
値の受け渡し
⓵1と2で作ったサブフローを追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/98c01401-2192-2c3c-1f1c-b6616efbdd78.png)
⓶入力と出力可能なテキスト型変数を作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/dd61233e-60dd-aeac-fc38-20747f48c051.png)
⓷サブフローaの前で割り当て要素を配置し、サブフロー1の出力値を3.⓶で作った変数に割り当てします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/84715e96-5304-8f20-c9fe-bd8f2d27c0d8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/e40aaccc-65ef-fb9c-2acf-33f93597fa19.png)
⓸サブフローaをダブルクリックし、
入力値を設定→含める　メインフローの変数3.⓶を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/272b6687-0891-73a2-898e-f42d1685f9aa.png)
⑤保存して、有効にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/682637ec-78e9-0203-b235-7a9df61789be.png)

上記のメインフローを実行してみます。
⓵任意の名前を入力し、「次へ」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/23cfeccd-b243-114a-9bdb-c12cd9928623.png)
⓶二つ目の画面に⓵で入力した値が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/0e2aff3c-2eaa-353f-49e4-da63b10470db.png)

以上は画面フローの一例になります。
【JavaScript】appendChildの記述方法

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/a784b92d-ae17-7817-a999-0882271e6888.png)

# JavaScriptのappendChildの記述方法
**InsertAdjacentHTML**を使う方法も、追加で記述しています。

>左のボタン：appendChild
右のボタン：insertAdjacentHTML


https://codesandbox.io/embed/zealous-rui-23dnjm?autoresize=1&fontsize=14&hidenavigation=1&theme=dark

Create AppendChild ボタンを押すと、下記のタグが生成されます。

>クリックする前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/f82c7c17-0af0-4a38-6e05-5321e90ff10e.png)

<hr>

>クリックした後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/871f5209-4567-6d32-e1f8-c6e8fbb42913.png)


# 参考動画
https://youtu.be/Ttf3CEsEwMQ

# 実際に作ってみました
GitHub Ations にdeployしました。

https://iwasaki-hub.github.io/website/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/f68221a9-b582-cb1a-c0ae-d2911c07f477.png)
Go言語でzipファイルを解凍したい

Go言語は標準ライブラリだけでzipファイルの解凍ができます。以下は`./example.zip`をカレントディレクトリに解凍するサンプルコードです。


```go
zipFilePath := "./example.zip"

// zipファイルをOpenする。
zr, err := zip.OpenReader(zipFilePath)
if err != nil {
	log.Fatal(err)
}
defer zr.Close()

for _, zf := range zr.File {
	// 解凍先のディレクトリを作成する。
	// 圧縮されているエントリがディレクトリの場合はそのディレクトリを
	// ファイルの場合はそのファイルを格納しているディレクトリをそれぞれ作成する。
	var dirPath string
	if zf.FileInfo().IsDir() {
		dirPath = zf.Name
	} else {
		dirPath = path.Dir(zf.Name)
	}
	if err := os.MkdirAll(dirPath, 750); err != nil {
		log.Fatal(err)
	}

	if !zf.FileInfo().IsDir() {
		// 圧縮されているエントリがファイルの場合、そのファイルをオープンする
		src, err := zf.Open()
		if err != nil {
			log.Fatal(err)
		}
		defer src.Close()

		// 解凍先のファイルを作成する。
		dst, err := os.Create(zf.Name)
		if err != nil {
			log.Fatal(err)
		}
		defer dst.Close()

		// 圧縮されているファイルの内容を解凍先のファイルに書き込む
		if _, err := io.Copy(dst, src); err != nil {
			log.Fatal(err)
		}
	}
}
```

__環境情報:__

```
~$ go version
go version go1.20.3 linux/amd64
```
Flutter×Firebase×routemaster×riverpod×flutter_hooks×freezedを使ってアプリを作ってみた！

# なんのアプリ？
プログラミングをする学生団体の会員用アプリです！
ってなに？というと、タスク管理やスケジュール管理、会議の議事録を一つに統一できて、なおかつ、どこにもないオリジナルアプリです！
ここで、宣伝。私は**学生団体IDEA**のアプリチーフを務めています。まだまだ最近の団体なのですが、私含めさまざまなプログラマーがいるので、ぜひ私以外のメンバーの記事も読んでください！

## 動機
単純にオリジナルアプリってなんかかっこよくない？アプリ作ってみたくない？という舐めたノリで作ってみました。

## 開発環境
作成者：2人(最初は3人だったけど途中からフェードアウトしちゃった)
分担：議事録→もう一人のメンバー, それ以外→私...(議事録の実装については私は説明しません)
期間：勉強期間を含めて役5ヶ月(本当は3ヶ月の予定だったけど、学校とかね、色々あってね...)
PC：MacBook Pro (M1 Pro) 16GB
コード管理：GitHub(コードがまとまり次第リンク載せます！)
これくらい？それ以外聞きたい等ことあればコメント残して！

## 感想
ぶっちゃけると結構疲れたし、もっとちゃんとドキュメントに詳細を落としながらすればよかったと思ってる。
Androidはリリースまだ準備できてないけど、iPhoneはリリース申請してて、書いてる時点ではまだ通ってないけど、すべての記事を書き終わるまでにはリリースされてると信じてる。
まぁ、なんだかんだ、めちゃくちゃ勉強になったし、楽しかった！

# ここから本編...
といきたいところなんだけど、作った部分全部書くと、とてつもない量になるので、機能等で分けて記事にしていこうかなと思います。

1. アプリの概要
2. Flutterでアプリを作成する
3. Firebaseと接続する
4. BottomTabBarを作る
5. アカウント作成・ログインページを作る
6. ホーム画面・設定画面を作る
7. ホーム画面の内容 その1
8. タスク管理画面を作る
9. 予定管理画面を作る
10. ホーム画面の内容 その2
11. ApplepStoreに申請する

こんな感じの目次で記事作成を進めていこうかなと思います。
結構文章多くなると思うので、気にかけてくださる方は気長に応援していただけると幸いです。

## 以下注意事項
・このアプリでは個人情報やアプリ情報を含む部分は掲載しません。
・初心者であることを忘れないで見て下さい。つまりコードが汚すぎます。
・リファクタリングしながら一応記事は書きますけど、まぁ我慢してください。
・疑問や改善点はコメントに残していただけると、自分も記事を読んだ方にとってもお得になると思うので、よろしくお願いします！

# アプリの概要
言語: Dart
フレームワーク: Flutter
データベース: Firebase
状態管理: riverpod, flutter_hooks

## 主な機能
・アカウント作成・削除
・アカウントに付随する個人情報の編集
・ログイン/ログアウト
・タスクの追加・編集・削除・閲覧
・予定の追加・編集・削除・閲覧
(・議事録の追加・編集・削除・閲覧)
・会員情報の閲覧
・SNSやWebサイト等へのサクセス

## 今後の展開
さてさて、最後まで読んだくださり、ありがとうございます！！！
何も技術的な情報なくてすいませんmm
記事が出来次第、リンク付けしたり、更新していこうと思うので、ぜひこれからも読んだり参考にしたり、コメントを残していってください！

###### それでは次回の投稿はとりあえず5月1~日にしたいと思います！（それまでにコードとドキュメントをまとめます！）あと、Appleの申請も・・・
ChatGPTをPythonから呼び出す

PythonからChatGPTを含むOpenAIの各種モデルのAPIを叩く方法。

APIは課金用の請求先を登録する必要がある. APIは月額課金ではなく従量課金になっており、gpt-4で750 word=0.03USD と普通に使う分にはそこまで高くない。
https://openai.com/pricing

1. Set up paid accountから請求先のクレジットカード情報を登録する。
https://platform.openai.com/account/billing/overview

2. APIキーを作成する。
https://platform.openai.com/account/api-keys

3. ライブラリをインストールする。
pip install openai

4. 以下を実行する。
```python
import openai

openai.api_key = "<YOUR API KEY>"

response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    # model="gpt-4",
    messages=[
        {"role": "user", "content": "How to use chatgpt?"},
    ],
)
print(response.choices[0]["message"]["content"].strip())
```

使用できるモデルの一覧
```python
openai.Model.list()
```

APIリファレンス
https://platform.openai.com/docs/api-reference
Nested ESXi 6.7 を ESXi 7.0 にバージョンアップ後、「No compatible network adapter found.」と表示されWeb接続できない

Nested構成のESX6.7を7.0にバージョンアップを行った後、再起動後に以下エラーが表示されvSphere Web Clientで接続できなくなりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/de088e9f-0b96-ceaf-85ea-aecfc14efdf1.png)


>No compatible network adapter found. Please consult the product's Hardware Compatibility Guide (HCG) for a list of supported adapters.

# 構成
**VMware Player**
`VMware Workstation 15.5 Player`

**ESXi**
`VMware ESXi 6.7.0 build-14320388`
　↓
`VMware ESXi 7.0.3 build-20328353`


# 解決手順
(1)VMware Playerのバージョンアップ　→　改善せず
(2)仮想マシンバージョンのバージョンアップ　→　改善せず
(3)ネットワークドライバの変更　→　改善


## (1)VMware Playerのバージョンアップ　→　改善せず
VMware Playerを`15.5`から最新の`17`にバージョンアップしました。
（改善しなかったので割愛します）

## (2)仮想マシンバージョンのバージョンアップ　→　改善せず
仮想マシンバージョンを`16`から`20`までバージョンアップしました。
（改善しなかったので割愛します）

## (3)ネットワークドライバの変更　→　改善
vmxファイル(`vm名.vmx`)をテキストエディタで開き、以下部分を修正します。

```text:vmx(before)
ethernet1.virtualDev = "e1000"
```

```text:vmx(after)
ethernet1.virtualDev = "vmxnet3"
```

設定変更後、VM(ESXi)を起動したところ正常に起動しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201787/e6f0c183-5653-f138-3231-98f3f0fd6927.png)


# 参考
**仮想マシンのネットワーク アダプタを選択する (1001805)**

https://kb.vmware.com/s/article/1001805?lang=ja

<br>
<br>

**vSphere ESXi 7.0 を VMware Workstation にインストール**

https://qiita.com/ama7650/items/2667e1a522401ed1b444

<br>
<br>

**Installing ESXi 7.0 on VMware Workstation**

https://vinfrastructure.it/2020/04/installing-esxi-7-0-on-vmware-workstation/

<br>
<br>

**ESXi 6.5から7.0へのアップグレード**

https://rohhie.net/esxi-upgrading-esxi-from-65-to-70/
ネットワークについて（IP、トランスポート層、IMAP4）

## IP（インターネットプロトコル）
OSI参照モデルの第3層（レイヤ3）のプロトコル。
ネットワークからネットワークへとパケットを運んで相手に送り届ける役割を持つ。
コネクションレス型の通信（一方的にパケットを送る）であるため、
通信品質の保証については、TCPやUDPなどの上位層に任せる。
## トランスポート層
OSI参照モデルの第4層（レイヤ4）で定義されている層。
データ送受信に関しての信頼性の取り決めを行うことを役割としている。
トランスポート層で使うプロトコルには、
コネクション型のTCPと、コネクションレス型のUDPがある。
### TCP
トランスポート層で使用される信頼性の高い通信プロトコル。
通信相手とのコネクションを確立してから、データを送受信するコネクション型の通信プロトコル。
相手の存在確認をして、しっかり握手した上で通信を行う。
パケットの順序や送信エラー時の再送などを制御し、送受信するデータの信頼性を保証する。
### UDP
同じくトランスポート層で使用されているプロトコルで、
多少の間違いを許すスピード重視の通信プロトコル。
映像配信サービスなどはこの通信プロトコルが使われている。
データの信頼性よりリアルタイム性を重視する用途に適している。
参考記事：
https://medium-company.com/%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%88%E5%B1%A4/
参考文献：
キタミ式イラストIT塾　基本情報技術者
## IMAP4
>IMAP4（アイマップフォー）とは、メールをPC等のクライアントにダウンロードせずメールサーバーに置いたまま読むことができるプロトコルである。
>> 参考記事：
https://www.pi-pe.co.jp/miteshiru/word/imap4/
IMAP4を使った有名なサービスとしては、GmailやYahooメールがある。
特徴点の移動量が一定になるように動画を画像に分割する

MarkDownがよくわかっていないので、あんまりきれいにはかけないかもです。
備忘録的に進めていければと思います。

①きっかけ
非GPS環境で飛ぶようなドローンを使ってSfM処理をしようとすると、必要なラップ率を満たすように画像を作成するのが難しいから。

②解決方法
特徴点の移動量を取得したすべてのフレームに対して計算して、各特徴点のマグニチュードを計算し、その平均値の変動量から計算すればいいのでは

③コーディング
がんばれ、ChatGPT君。

```
import cv2
import os
import numpy as np
from tqdm import tqdm
from multiprocessing import Process, cpu_count

def optical_flow_magnitude(gray1, gray2):
    flow = cv2.calcOpticalFlowFarneback(gray1, gray2, None, 0.5, 3, 15, 3, 5, 1.2, 0)
    mag, _ = cv2.cartToPolar(flow[..., 0], flow[..., 1])
    return np.mean(mag)

def process_video(video_file, input_dir, output_dir, threshold):
    video_path = os.path.join(input_dir, video_file)
    video = cv2.VideoCapture(video_path)

    frame_count = 0
    ret, prev_frame = video.read()
    prev_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)
    cv2.imwrite(os.path.join(output_dir, f'frame{frame_count:04d}.png'), prev_frame)

    with tqdm(desc=f"Processing {video_file}", total=int(video.get(cv2.CAP_PROP_FRAME_COUNT))) as pbar:
        while video.isOpened():
            ret, frame = video.read()
            pbar.update(1)
            if not ret:
                break

            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            mag = optical_flow_magnitude(prev_gray, gray)

            if mag > threshold:
                frame_count += 1
                output_path = os.path.join(output_dir, f'frame{frame_count:04d}.png')
                cv2.imwrite(output_path, frame)
                prev_gray = gray

    video.release()

def main():
    input_dir = './input'
    output_dir = './output'
    threshold = 5

    os.makedirs(output_dir, exist_ok=True)

    video_files = [f for f in os.listdir(input_dir) if f.endswith('.MOV')]

    processes = []
    num_processes = min(cpu_count(), len(video_files))

    for i in range(num_processes):
        p = Process(target=process_video, args=(video_files[i], input_dir, output_dir, threshold))
        p.start()
        processes.append(p)

    for p in processes:
        p.join()

    cv2.destroyAllWindows()

if __name__ == '__main__':
    main()

```

カレントディレクトリのInputフォルダ内にmp4でデータを入れて、閾値を調整したら実行。
Node.jsでThree.jsを使う方法

いつも忘れるので...

## ディレクトリ内にindex.html,script.js(とその他必要な)ファイルを用意

```html:index.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>Node.jsでThree.js</title>
        <link rel="stylesheet" href="style.css">
        <script type="module" src="script.js"></script>
    </head>
    <body>
        <h1>Hello, World</h1>
        <div id="webgl"></div>
    </body>
</html>
```

```JavaScript:script.js
import * as THREE from 'three';

let scene, camera, renderer;

function init(){
    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,1,1000);
    camera.position.set(0,15,0);
    camera.lookAt(0,0,0);

    renderer = new THREE.WebGLRenderer();
    renderer.setClearColor(0x000000);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setPixelRatio(window.devicePixelRatio);

    //環境光
    let ambientLight = new THREE.AmbientLight(0xcccccc,0.1);
    scene.add(ambientLight);

    //平行光源
    let directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
    directionalLight.position.set(10, 100, 0);
    scene.add(directionalLight);

    //立方体を一つ描画
    let boxGeometry = new THREE.BoxGeometry(5,5,5);
    let boxMaterial = new THREE.MeshLambertMaterial({
        color:0xff0000
    });
    let box = new THREE.Mesh(boxGeometry, boxMaterial);
    box.position.set(0,0,0);
    box.rotation.x = Math.PI * 0.5
    scene.add(box);
    //console.log(box);
    
    document.getElementById('webgl').appendChild(renderer.domElement);

    render();

    function render(){
        requestAnimationFrame(render);
        renderer.render(scene, camera);
        box.rotation.x += 0.01;
        box.rotation.y += 0.01;
    }
}

window.onload = init;

```

```css:style.css
*{
    margin: 0;
    padding: 0;
    list-style: none;
}
```

## ターミナルでthreeとviteをインストール

Three.js本体をインストール
```
npm install --save three
```

ビルドツール「Vite」をインストールして実行
```
npm install --save-dev vite
npx vite
```

`npx vite`を実行すると、ターミナルに Local: `http://127.0.0.1:0000/` のように表示されるので、こちらにブラウザでアクセスすると、実行結果が表示されます。

## 止め方
`Ctrl + C` でサーバーが停止します。

#### 参考
https://threejs.org/docs/#manual/en/introduction/Installation
Last.fm の再生回数ランキングをもとに YouTube Music のプレイリストを作る

# やりたいこと

Last.fm で曲の再生回数を記録している。

https://www.last.fm/

Last.fm は API を提供しており、任意の期間で再生回数ランキングを出力することができる。
これを使って、YouTube (YouTube Music) のプレイリストを作りたい。

# リポジトリ

https://github.com/tsubasaogawa/lfm2ytm

# 実装のポイント

## Last.fm で曲単位の再生回数ランキングを取得するには getWeeklyTrackChart

https://www.last.fm/api/show/user.getWeeklyTrackChart

Weekly とあるがパラメータで対象期間を自由に設定できるため Weekly にとらわれずに利用できる。
なお、Docs にもあるが Auth は不要なので API Key さえあれば利用可能。

## Last.fm の シークレット (API Key) をどう埋め込むか

コードにべた書きするのは避けたい。
シークレットを返すサーバーを別途立てるとか、あるいはクラウドのパラメータストアサービスを使うなど考えられるが、少し大袈裟な気もする。
ここでは GitHub Actions + GoReleaser を使って ldflags からシークレットを注入することにした。
シークレットの値自体は GitHub Actions の Secrets に格納しておき、GoReleaser でバイナリ生成と GitHub の Releases にアップ。

## YouTube Music 向けの動画を探す

YouTube Music 専用の API は公式からは提供されていないため、YouTube の API (Data API v3) を使う。
YouTube Music でいうところの楽曲は Art Track と呼ばれており、これを優先的に検索できるようにしたい。(音質が優れているため)

https://support.google.com/youtube/answer/6007071

普通の動画と区別する方法がわからなかったため、以下どちらかを満たす動画は Art Track と判定するようにした。

- チャンネル名の末尾に「- Topic」がある
- 説明の冒頭に「Provided to YouTube」がある

https://github.com/tsubasaogawa/lfm2ytm/blob/ed398cd29a2074476cb07bc15c54a76701e57236/ytmusic/search.go#L90-L93

# 結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49525/cbb4589d-8cfb-c314-6d6b-5443ae2ebd69.png)

こんな具合にプレイリストを作ることができた。
レガシーなcallbackとprototypeをテストと一緒に書き直す

こんばんは。@Esperna です。

## 背景

前回[レガシーなcallbackをasync/awaitで書き直す](https://qiita.com/Esperna/items/2e37fce54cf2c5b8085f)という記事を書きました。
その際、protoptypeやテストコードについても書きたかったのですが、長くなり過ぎると思ったので別記事にすることにしました。いつもながら車輪の再発明ですが自身の理解を深めるために書いてます。

# prototypeでクラスを実現するメソッドの例

* 前回の[レガシーなcallbackをasync/awaitで書き直す](https://qiita.com/Esperna/items/2e37fce54cf2c5b8085f)の関数を簡素化して、クラスメソッド化した例です
* レガシーなprototypeを使って書いてます

```javascript:asyncTaskOld.js
function AsyncTask() {
    console.log(`made at Showa`);
}

AsyncTask.prototype.doAsync = function (callback) {
    const TIMEOUT = 10;
    const SUCCESS = 1;
    setTimeout(() => {
        callback(SUCCESS);
    }, TIMEOUT);
};

module.exports = new AsyncTask();
```

# classを使ってprototypeを書き直す

下記の通りです。
```asyncTask.js
class AsyncTask {
    constructor() {
        console.log(`made at Heisei`);
    }
    doAsync(callback) {
        const TIMEOUT = 10;
        const SUCCESS = 1;
        setTimeout(() => {
            callback(SUCCESS);
        }, TIMEOUT);
    }
}

module.exports = new AsyncTask();
```

個人的な所感ですが、callback版よりもC++やJavaで見慣れたこちらの方がしっくり来ます。

# (async/await使いたいので)Promiseで書き直してみる

```javascript:asyncTaskNew.js
class AsyncTask {
    constructor() {
        console.log(`made at Reiwa`);
    }
    doAsync() {
        return new Promise((resolve) => {
            const TIMEOUT = 10;
            const SUCCESS = 1;
            setTimeout(() => {
                resolve(SUCCESS);
            }, TIMEOUT);
        });
    }
}

module.exports = new AsyncTask();
```

今回は上述のasyncTaskOld.jsとasyncTaskNew.jsに対してテストコードを書いてみます。

# callbackを引数に取る関数に対するテストコード

```javascript:asyncTaskOld.test.js
const asyncTask = require("./asyncTaskOld");

describe("asyncTask old class test", () => {
    const SUCCESS = 1;
    test("doAsync shall call callback with SUCCESS", (done) => {
        asyncTask.doAsync((result) => {
            expect(result).toBe(SUCCESS);
            done();
        });
    });
});
```

# Promiseを返すコードに対するテストコード

```javascript:asyncTaskNew.test.js
const asyncTask = require("./asyncTaskNew");

describe("asyncTask new class test", () => {
    const SUCCESS = 1;
    test("doAsync shall return SUCCESS", async () => {
        const result = await asyncTask.doAsync();
        expect(result).toBe(SUCCESS);
    });
});
```

* テストコードを書くという観点でcallback版とPromise版を比べると
   * callback版は引数をマッチャでチェックすることになりネストが深くなります
   * Promise版は戻り値をマッチャでチェックすることになりネストが浅いです
   * callback版はcallbackの処理をチェックしたい場合はcallback関数内でdoneの呼び出しを書いてあげる必要があります

   

# 所感

* テストコードも書きやすくなるのでcallbackではなくPromiseでasync/awaitで書きたいです
* prototypeかclassかはテストコードには影響なさそうですが、C++やJavaを見慣れているのでprototypeは古い仕様だしできれば使いたくないです
画像生成AI Stable Diffusionを無料で試す方法！

### はじめに
画像生成AIサービスが台頭している中、Stable Diffusionは他のサービスと比べ、特にモデルの学習を自由にカスタマイズできます。

このStable Diffusionをweb上で簡単に操作できるものがStable Diffusion web UIです。

https://github.com/AUTOMATIC1111/stable-diffusion-webui


### Stable Diffusion web UIの問題点
Stable Diffusionを使って画像生成するためには[GPU](https://ja.wikipedia.org/wiki/Graphics_Processing_Unit)が必要になります。

そのため、GPUがないPCを使用している人は[google colab](https://colab.research.google.com/)や[paper space](https://www.paperspace.com/)を利用する必要があります。

### Google Colabで警告表示が！
私は当初Google Colabの無料枠を使用してStable Diffusion web UIを使っていたのですが、警告が出てしまうようになってしまいました。

paperspaceも試したのですが、月額$8程度の有料プランへの登録が必要になります。

リソースを大量に使用したい場合はpaperspaceを使用するべきですが、軽く20~30枚程度気になるモデルを簡単に試す方法を探してみました。


### Draw Things
[Draw Things](https://drawthings.ai/)というアプリを使用すれば、ダウンロードしたモデルを読み込んで好きな画像を作成できます。
枚数制限がありますが、簡単にStable Diffusionを試したい人には最適だと思います。

モデルはこちらのサイトからダウンロードしました。

https://civitai.com/

### Draw Thingsを試してみる

civitaiの投稿を参考に画像を生成してみた結果

![スクリーンショット 2023-05-05 22.41.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/34c93c6d-46cc-7962-3421-571f52fd5ae8.png)

すごいクオリティの画像が簡単に生成できました。
civitaiでは画像とそれを生成するためのモデルやプロンプトなどの設定が見れるのでかなり便利ですね。

https://civitai.com/images/648360?period=AllTime&periodMode=published&sort=Newest&view=categories&modelVersionId=55911&modelId=43331&postId=180127

### 作成した作品

![best_quality__masterpiece__ultra_high_res___photorealistic_1_4___raw_photo__1girl__offshoulder__in_the_dark__deep_shadow__low_key__cold_light__lora_film_0_4_palette___large_breasts___lo_3984483382.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/2e456f15-84b3-43b6-a4ff-2c859013fdbd.png)

![hyperrealist_portrait_of_female_by_david_hockney_and_alphonse_mucha_fantasy_art__photo_realistic__dynamic_lighting__artstation__poster__volumetric_lighting__very_detailed_faces__4_k__aw_4042471286.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/c99429b0-229a-3ce6-fc23-f9eb2558f4e9.png)

![best_quality__masterpiece__ultra_high_res___photorealistic_1_4___raw_photo__handsome_male__-ng_deepnegative_v1_75t__badhandv4___worst_quality_2____low_quality_2____normal_quality_2___low_518925706.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/78506574-0019-e4a6-fb69-e0d58f023760.png)

すごいクオリティですよね。

モデルやプロンプトを変更することで、あなた好みの理想の画像を生成できます。

### 最後に

これを応用することで、自分の写真を美化するアプリとか作れたらなと思います。
実際に自分の写真でimageToImageを試してみましたが、モデルに引っ張られすぎたので、適切なモデルが見つかればチャレンジしてみたいです。

良かったら[Twitter](https://twitter.com/js_manabitai)もフォローしていただけると嬉しいです！

https://twitter.com/js_manabitai

AIに関する開発などをTweetしていきます。
PandasのGroupbyについて np.sum(), np.sum(), aggもろもろのメモ

### np.size
カウント値（レコード数）を計算する
（np.count)は存在しない
### np.sum
合計値を計算する

```python 
df.groupby(['col1','col2'], as_index=false).agg(
    'col_3': np.sum,
    'col_4': np.size)
```
<b>as_index=false</b>はgroupybyの['col1','col2']がそのまま出るので、CSVやDBに出力する時にデータとしてそのまま使える。
```
col1       col2   col3  col4
2023/04/01 tokyo  100   1
2023/04/01 oosaka 200   4
2023/04/01 tokyo  150   2
```
[Oracle] 新入社員＆初心者シリーズ#03 Oracle Database 19c への接続とSQL実行

## やりたいこと
Oracle Databaseをテスト用に自分の環境にインストールして、
SQLを実行できるようになるまでを解説するシリーズ

第三回は、Oracle Database に接続して、SQLを実行します。

私がはじめてOracleを使用したとき、インストールはできたのですが
次に何をすればよいか、まったくわかりませんでした。
しかも、何かパソコンの動作が遅くなる・・・
まず何をすればいいのか？、そんな疑問を払しょくする第三回です。

#環境
・Windows 10 Pro ( Windows 2016 , 2019 も同様）
・Oracle Database 19c

・OracleをインストールしたOSユーザ

## 第三回 オラクルデータベースでSQL文を実行する
１． Windowsのスタートメニューや検索から、「コマンドプロンプト」を起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/78a4d5af-353f-95b9-2191-73dd906be6a1.png)

２．以下のコマンドでログインします。
　　コマンド実行後、「接続されました。」と表示されたらログイン成功です。

```sql
-- Oracleにログイン
sqlplus / as sysdba
または
sqlplus system/password   ※passwordはインストール時に指定したもの
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/6a8c5774-6125-bb0c-0d0b-424784a9b8e5.png)

３．プロンプトが「SQL>」となっていれば、SQL文を実行できます。
　　たとえばDBユーザ「test」を作成するSQLの例です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/1bb7a724-7542-0ecb-7eed-2b3ec8205507.png)

４．終了するときは「exit」コマンドで終わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/2bec32fc-40aa-5b06-5c7e-ff8c3fc6b204.png)

## Oracle Databaseの起動と停止（Windowsサービスの利用）
Oracleは起動している間、常にPCのリソースを使用します。
たとえばデフォルトインストールではメモリの40%を常に使用した状態となります。
スペックの低いPCを使用しているときは、常に起動していると他の作業が遅くなるため不要な時は停止してしまいましょう。

# 停止
１．Windowsの「コンピュータの管理」を開きます。
Oracleという名前ではじまるサービスが複数ありますが、すべて停止してしまいます。
複数のなかでメインとなるものは「OracleServiceORCL」と「OracleOraDB19Home1TNSListener」の2つです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/1537faac-0514-7db4-1387-9b929e7825b3.png)

# 起動
１．Windowsの「コンピュータの管理」を開きます。
Oracleという名前ではじまるサービスが複数ありますが、
最低限「OracleServiceORCL」と「OracleOraDB19Home1TNSListener」の2つを起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/1537faac-0514-7db4-1387-9b929e7825b3.png)
【iOS】リリースに必要なスクリーンショット作成を簡単にする最強ツール

# はじめに
個人開発をしていて、一番面倒なのはデザイン面だったりします。
特にスクリーンショット作成はアプリのインストール率に関わってくるのでちゃんと作りたいです。

今回は、私がスクリーンショット作成に必須なツールを紹介します。

結論から言うと、Figmaなんです。

「Figmaは知ってるよー」
「どうせ自分でデザインしないといけないじゃんー」

って思った人も多いはず。

違うんです。

Figmaにはスクリーンショットのテンプレを無料で公開してくれている神がたくさんいるんです。

# 一部の神を紹介
https://www.figma.com/community/file/1057267104690766331/AppStore-Screenshot-Template

https://www.figma.com/community/file/891325178364097650/Template-for-App-Store-Screenshots

https://www.figma.com/community/file/973686904793673118/Play-store-%26-AppStore-Screenshots-Template---freebies-design-%40atik_gohel

https://www.figma.com/community/file/1226020009288330288/iOS-App-Store-Screenshot-Preview-Template

https://www.figma.com/community/file/1071476530354359587

https://www.figma.com/community/file/1165594034578098226

# やってみる
今回はサンプルとしてこちらのテンプレを使ってスクリーンショットを作成してみます。

https://www.figma.com/community/file/1165594034578098226

現在開発している「QiitaWidget」というアプリのスクリーンショットを作ってみます。

### Figmaを開く
「Open in Figma」を選択します。
![スクリーンショット 2023-05-05 21.29.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/58d318e4-fe84-9962-aa5e-d9b6086a55b0.png)

### 背景色を変更する
背景色はQiitaのテーマカラーのグラデーションにしてみたいと思います。
今回はグラデーションにしたいので`AccentGradient_✅ Change Here!!`を変更します。

![スクリーンショット 2023-05-05 21.37.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/b0d218a9-eefe-1a75-105f-1a9982b3a94e.png)

`6.5_FirstShot_✅ Change Here!!`の背景色を`AccentColor_✅ Change Here!!`から`AccentGradient_✅ Change Here!!`に変更します。
![スクリーンショット 2023-05-05 21.38.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/4a9a5446-b6e6-bee8-9633-cf9deb6d55b9.png)

背景色を変更できました。

### スクリーンショットを設定する
設定したい画像を2枚用意します。
今回は以下の2枚です。
|||
|-|-|
|![Simulator Screen Shot - iPhone 14 - 2023-05-05 at 21.41.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/96931b52-6a42-bcd6-0916-74261642a3a9.png)|![Simulator Screen Shot - iPhone 14 - 2023-05-05 at 21.42.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/d4082f5c-f6cc-9e43-0f10-0338f5718a2f.png)|

① `6.5_FirstShot_✅ Change Here!!`の`Component 2`を選択します
② 画像部分をタップします
③ 「Choose image」を選択します
![スクリーンショット 2023-05-05 21.44.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/9a3c4761-98de-3961-2cdf-5f1ab7120ea3.png)

選択が完了したらスクリーンショットに入ります。
![スクリーンショット 2023-05-05 21.47.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/1172363b-23dc-0ea8-61d8-9b7daaaaee87.png)

`Component 3`でも同じことをします。

![スクリーンショット 2023-05-05 21.48.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/c2ddb7ef-aa02-2ba5-286b-465102807085.png)

できました。

### その他設定をする(文字など)
適当に文字などを変更してこんな感じになりましたー！
![スクリーンショット 2023-05-05 21.57.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/0cf41170-96c3-9668-3979-bb5863986a6f.png)

# おわり
めっちゃかっこいいスクリーンショットが10分くらいで手作りできましたー！
個人開発者にとってこのテンプレート達は偉大な存在ですね