OmniAICreator/Qiita-1.07M huggingface dataset:
PowerShellでSelenium4.0.0 Preview-3を導入する (成功)

# 動機
前回Selenium 3.0.1をインストールしようと思ったところなぜか動かず、最後のエラーを見てバージョンに問題があるのかなと思いバージョンを4.0.0 Preview-3でやってみようと思ったこと。なお成功しました。

※なおSeleniumを使って何をするか、は自己責任でお願いします。

* 参考：前回の記事

https://qiita.com/_Sasaki_/items/d001f79e640f1134db12


# Windowsのエディション
* Windows 10 EnterPrise

# 手順1: Selenium4.0.0 Previewのインストール1回目(失敗)
* 旧VersionのSeleniumがあると邪魔だろうと思ったので旧Seleniumをアンインストール
```PowerShell
Uninstall-Module -Name Selenium
```

* PowerShell Galleryを見ると下記コマンドでSelenium 4.0.0 Preview-3はインストールできるはずと判断。
    * 上記の根拠：右記リンクの下記画像黄色ハイライト部 (https://www.powershellgallery.com/packages/Selenium/4.0.0-preview3)
```PowerShell
Install-Module -Name Selenium -AllowPrerelease
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343332/dba23a0a-a02b-2a13-8fc7-6f923f903555.png)


* Force パラメータ付けて実行するもなぜかエラー。AllowPrereleaseパラメータが使えないとのこと。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343332/53714b96-eaee-f5cd-532e-bd97fdb10e60.png)


* これについて調べたら、PowerShellGet Moduleを更新する必要がありそうだと確認
    * 根拠は右記リンクの下記黄色ハイライト部分：https://www.easy365manager.com/install-module-a-parameter-cannot-be-found-that-matches-parameter-name-allowprerelease/ 
        * あと余談ですがPowerShellの日本語情報源って少ないな、と改めて思いました。ちょっと調べると英語のサイトよく出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343332/6dacb52e-046f-3895-99eb-21895949ffcf.png)

<br>


# 手順2: PowerShellGet Moduleの更新

* というわけで上記コマンドでPowerShellGet Moduleを更新するもなぜかエラー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343332/b0175ea7-1f61-6df5-fff3-59d632063226.png)

* これについて調べたら、既存のPowerShellGetがInstall-Moduleコマンドレットでインストールされてないことによるものらしく、下記コマンドで実行したら無事更新されました。
    * 上記の根拠：右記リンク https://blog.shibata.tech/entry/2017/12/18/004105

```PowerShell
Install-Module PowerShellGet -Force -AllowClobber
```

* 更新に成功した場合の画面 (PowerShellGetのバージョンが2.2.5に更新されてます)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343332/4435a618-9d22-a60d-9e75-4b86ba36731c.png)

<br>

# 手順3: Selenium4.0.0 Previewのインストール2回目(成功)
* 一応Forceも付けて下記コマンド実行してみたらようやく成功
```PowerShell
Install-Module -Name Selenium -AllowPrerelease -Force
```

* Get-CommandでSelenium Moduleのものが表示されるようになりました。
    * Selenium 3.0.1とは異なり、ブラウザ起動は"Start-SeEdge"といったブラウザ名が入ったコマンドではなく"Start-SeDriver"となってたりするようなので、Seleniumの記事を検索するときはバージョンに気を付けないといけないな、と思いました。
    * あとPowerShellの書籍で口酸っぱく出る「ヘルプを使いこなす」ことの必要性を実感しました。というのもマイクロソフト公式のモジュールではないのでネットで探してもまとまったものは無く、PSコンソール内で確認するほかないからです。私は非ITのド素人なので「そういうことだったのかー」と今更府に落ちました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343332/2791e791-d834-949a-0f59-17c277186201.png)



# ためしに
* 下記コマンドでEdgeを起動したら無事に立ち上がりました。さんざん悩まされたSelenium導入もこれで終わりです。丁寧に「自動テストソフトウェアによって制御されてます」って出てますね。
    * なお前回のSelenium 3.0.1の際に設定した環境変数NO_PROXYに関しては、消しても下記の動作するのにエラーが出ることはなかったので、不要なら消しておくといいのでは、と思いました。


```PowerShell
$driver = Start-SeDriver -Browser Edge -StartURL https://www.google.com/
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343332/6180eb9c-8cc9-7c8b-8aea-3fba7dc34be6.png)




# おわりに

* 基本自分用メモですがどこかの誰かの役に立てば幸いです。

* もし知見のある方でコメントある方いれば是非よろしくお願いします。
特定のディレクトリ以外はgit監視対象から外す

- 以下では`themes/sample/`以外の`themes/`にあるファイルやディレクトリをgitignoreに設定しています。
- 逆に、`themes/`の中の`sample/`以外は監視対象から外しています。
- ポイントは`/themes/*`ここでアスタリスクを指定してることかな。

###### .gitignore
```
# 必要なテーマ以外を監視対象から外す
/wp-content/themes/*
!/wp-content/themes/sample/
```
UE5でマルチユーザー編集(無線)

::: note warn
Unreal Engine 5 のマルチユーザー編集プラグインはbeta段階にあります。
:::
![multiuserediting.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569952/daf043fb-da29-e050-4720-ac406ec0b7a1.jpeg "マルチユーザー編集レベル画面")
## 準備
- ホストがプロジェクトファイルを全員に配布する(discordで.zip送ったり、github repositoryにアップロードしたり...)
- UE5のバージョンを揃える
# 手順
1. [LogMeIn Hamachi](http://qiita.com "Hamachi")をインストールする
2. Hamachiのアカウントを新規登録する
3. 主側がIDとパスワードを指定し、サーバーをホストする
4. 他の人はIDとパスワードを入力し、サーバーに入る
    - 下の画像のようになっていればOK
![Screenshot 2023-10-15 182248.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569952/9ef6830b-ff8d-3783-b664-23ec07dd4ee8.png)
5. 全員UE5を起動し、Edit -> Plugins -> Multi-User Editing (beta)にチェックを入れて再起動
![Screenshot 2023-10-15 184150.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569952/17a9c2a9-0020-60e1-2972-c66f7961d8e1.png)
6. Edit -> Project Settings -> Plugins -> Multi-User EditingからEnable Multi-User Toolbar Buttonにチェックを入れる
7. 同じ欄からDisplay Name（表示されるユーザー名）とAvatar Color（アバターの色）を設定する
8. Plugins -> UDP MesssagingからUnicast EndpointとMulticast Endpointを設定する
    - Command promptからipconfigで「イーサネット Hamachi」のIPv4を取得する
    - Unicast Endpointに先ほどのIPv4 + ":0"を入力する
        - 例: もしIPがXXX.XXX.XXXだったらUnicast EndpointはXXX.XXX.XXX:0
        - Multicast Endpointは230.0.0.1:6666に設定する

![Screenshot 2023-10-15 184251.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569952/d5b07804-bd46-2303-a0e6-1adec5ee88ac.png)
9. エディタの上のほうにマルチユーザー編集のボタンが追加されてるはずなのでそれをクリックする
![Screenshot 2023-10-15 181610.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569952/91eddff0-9c85-ff95-1fc0-ec741504f2c2.png)
10. ホストはLaunch a Serverを押してサーバーを起動する
![Screenshot 2023-10-15 182218.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569952/e477b777-e768-ea21-056b-afa3db3869c0.png)
11. Create Sessionボタンを押してセッションを作成する
![Screenshot 2023-10-15 182201.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569952/aab11fad-be78-658e-518b-6afff0c73142.png)
12. 他の人はマルチユーザー編集ボタンの所からそのセッションに参加する
13. ホストがセッションを抜ける際はPersist Changesを選択

::: note warn
万が一編集した内容がセーブできていなくてもArchived SessionsからRestore Sessionを押すとセッションのアーカイブから復元できます
:::


## 使ってみた感想
このプラグインはbeta段階ではあるのですが特に不備は無く、滑らかに動きました。同じファイルは同時に編集できませんのでそれだけご注意ください。万が一同時に編集してしまっても先に編集したほうがファイルにロックをかけるので他の人が後から編集してもファイルを影響しないはずです。
レベル画面に行くと他の人も映ってたりして楽しかったです。ゲーム制作はやはり複数人で行うべきですね。
OpenInterpreterが書いたグラフをGPT-4Vに解説させる

![DALL·E 2023-10-07 14.36.21 - Render of a modern tech laboratory with advanced equipment and glowing screens. A central monitor prominently displays the GPT-4V logo with the taglin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/875e528e-7da9-ec94-6b4e-b6c5a17adb4c.png)

# お題
『この画像について説明をお願いします。グラフが変化するポイントについては、あなたがお持ちの知識を活用して詳細な解説を加えてください』
![ibm_stock_price.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/99a3764f-a73a-2864-e07c-4106233854a9.png)

# はじめに

[以前の記事](https://qiita.com/yanagih/items/466a5560bd771e2b9030)でOpenInterpreterを使用して『1991年から2023年までのIBM株価の推移』をグラフ化しました。

https://qiita.com/yanagih/items/466a5560bd771e2b9030

そして、今、急速に話題になりつつあるGPT-4Vに、そのIBM株価のグラフを解説させてみます。

# レッツ・プロンプト

といってもやり方はとても簡単です。画像ファイルとプロンプトを与えるだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/893d0d80-088c-c590-91bf-7cd56dd24bd9.png)

:::note
GPT-4VはChatGPT Plusユーザーに解放された機能ですが、2023/10/7の現時点で、すべてのChatGPT Plusユーザーに解放されているわけではなさそうです。自身のChatGPT Plus環境でGPT-4Vが使えるかどうかは、[こちらの記事](https://qiita.com/yanagih/items/4c8c57cdbbec2041d35f)で解説しています。
:::

# 結果

結果は、1分もかからずに出力されました。以下がその内容です。

(スクリーンショット)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/d1e69534-68bc-74df-76bf-4130ee755989.png)

(テキスト)
画像には「IBM Stock Price 1991-2023」というタイトルの下、1991年から2023年までのIBMの株価の変動がグラフで示されています。

以下は、グラフの変化する主なポイントとその背景についての説明です：

1. **1990年代初め**: この時期、グラフは比較的低い水準で安定しています。これは、IBMが深刻な経済的困難に直面していた時期に対応しています。1993年には、新しいCEOであるルー・ガーストナーがIBMの再構築を指揮し、サービスとソフトウェア中心の戦略にシフトしました。

2. **2000年代初め**: この時期には、株価は上昇しています。これは、IBMがサービスやソフトウェアの事業を強化し、利益を伸ばしていたためです。また、ITバブルが影響している可能性も考えられます。

3. **2008年頃**: この時期には、グラフに一時的な下降が見られます。これは、2008年の金融危機が影響していると考えられます。

4. **2010年代**: 2010年代の中頃から後半にかけて、株価は再び上昇傾向にあります。IBMはこの時期、クラウドコンピューティングや人工知能に関連する事業に力を入れ、特にWatsonなどのAI技術を市場に投入しました。

5. **2020年代**: 最近の数年間で、株価は一定の変動がありつつも、全体として上昇しています。これは、IBMがクラウド、AI、量子コンピューティングなどの新しい技術領域に注力していることが影響している可能性があります。

以上のように、グラフにはIBMの多くの歴史的な出来事や業界のトレンドが反映されています。ただし、具体的な年に発生した出来事や、その背景となる詳細については、特定の研究や情報に基づくものであり、常に最新の情報や詳細な背景を確認することが重要です。

# おわりに

GPT-4Vは１分足らずで、プロンプトで指示した通り、株価が上がり下がりするポイントについて、世の中の背景とIBMの業績や活動を使って解説してくれました。

これまでは、何かしらの分析業務を遂行する場合、**プログラミングの知識**、**世の中の情勢に対する知見**や**分析対象の知識**を必要とされていました。

今後もこれらの知識や知見は必要とされると思いますが、その一方で、それほど詳しい知識や知見がない方であっても、必要なプログラミングは**OpenInterpreter**にやらせ、その結果の解説/解釈を**GPT-4V**にやらせる、そんな世界観が今すぐそこにあらわれました。更なる進化を期待します。

GPT-4Vの凄さは、これにとどまりません。スクリーンショットを使ってアプリケーション作成にチャレンジした内容を別のQiita記事として書きました。興味のある方は下記リンクをクリックください。

https://qiita.com/yanagih/items/4c8c57cdbbec2041d35f

# 参考

* OpenInterpreterに関してはこちらで解説しています

https://qiita.com/yanagih/items/466a5560bd771e2b9030

* GPT-4Vに関してはこちらで解説しています

https://qiita.com/yanagih/items/4c8c57cdbbec2041d35f
flutterエンジニアとしてステップアップするために、inside flutterを読み込む。

## はじめに
こんにちは。

今回はinside flutter(flutterのレイアウトの仕組み)について勉強したので、共有します。

この記事は、自分の知識を言語化し、定着化するために書いているので、正直この記事をみるより、ほかのつよつよエンジニアさんが書かれている有名な記事や公式ドキュメントを参照することを強くお勧めします。

自分がこの記事を書くにあたって参考にした記事の一覧は、この記事にまとめてあるので、興味のある方は是非覗いて見てください。

https://qiita.com/yuto_swift_flutter/items/821df73334c2c1aea2ef


公式ドキュメントは以下です。

https://docs.flutter.dev/resources/inside-flutter


## 三つのツリーを理解する。

flutterを触ったことがある方なら、Widegetを使ったことがない方はいないでしょう。

そのwidgetは、別のwidget自体をネストしていき、
widget自体を積み重ねることでツリー状の構造を形成しています。

widgetに変更がある際に都度、変更を感知するたびに全てのwidgetを更新するようだと、あまりパフォーマンスの面でよろしくありません。

そこで、widgetの描画速度を高めるために、ElementとRenderObjectに役割を委任しています。

#### Elementについて

WIdgetと同様に、ElementやRenderObjectもツリー状の形状になっています。

そして三つのツリーの中で、このElementガ中心的な役割を担っています。

また、Elementは、Widgetとペアになっており、Widgetの数だけWidget.createElementによってペアになるElementが生成されます。

またElementの最大の特徴としては、親と子のElementを参照することができます。

実際に、Elementが親子のElementを上から下に走査することで、ライフサイクルやwidgetの変更差分の有無をbool値で管理したりといった役割を担っています。

#### RenderObjectについて

画面を描画する際に参照されるのがこのRenderObjectです。

RenderObjectは子のUI描画のための制約を更に、子に引き継いで末端のRenderObjectまで伝わります。

またその際に得られた計算結果はRenderObjectに保存され、
その計算結果に変化がない場合、計算を省くことによってパフォーマンスの高い処理を実現しています。


#### Widgetについて

widgetはほとんどの方にとって馴染み深いものと思いますが、実際にどのような責務を持っているのか説明しろと言われると。。。ってなっちゃいますよね。

実はwidgetの役割は非常にシンプルです。

具体的には、UIを構築するための設定（文字のスタイル、文言、カラーなど）の保持やWidget.createElementでwidgetのペアとなるElementを生成することです。

それ以外の計算やツリー構造の生成などをElementやRenderObjectに委任することで我々ユーザーは直感的にUIを構築できているんですね。（感謝）


## 最後に

最後まで、読んでいただきありがとうございました。
今回はかなりざっくりした記事になってしまいましたが、どなたかの役に立てば幸いです。
何か、ご指摘あればコメントいただけると非常に助かります。

ありがとうございました。
ThingSpeakでIoT

I2Cモジュールが不安定なので定期的にThingSpeakにデーターを投げてIoT(Internet of Test)しているので、状況をMATLAB Analysisで確認してみました。

```MATLAB
now = datetime('now');
t1 = now;
t2 = t1 - days(1);

while 1
data = thingSpeakRead(readChannelID,'Fields',valueFieldID,'ReadKey',readAPIKey,'OutputFormat','table','DateRange',[t2,t1]); 
[m,n] = size(data);
if t1 == now
last = data.Timestamps(m);
end
if m == 0
break;
else
fast = data.Timestamps(n);
t1 = t2;
t2 = t1 - days(1);
end
end

uptime = last - fast;

display(last,'last'); 
display(uptime,'uptime'); 
```

実行してみます。

```
last = 

  datetime

   07-Oct-2023 08:46:19


uptime = 

  duration

   17:28:21
```

thingSpeakRead()で最初のデータのとり方が分からなかったので、頭の悪いやり方になっています。

このやり方だと長期間になると、無料利用のCPU時間を使い切って、エラーになる可能性があるかもしれません。

また、データが空や止まってる場合の処理が入っていません。
Wordpress本番サイトをDockerに再現

# どんな人向けの記事なの？
- この記事はどこかのサーバー上にあるWordpressサイトをdocker環境に再現したい人向けの記事です。
- 僕のように、レンタルサーバー上のWordpressサイトをDocker環境で改修したい人向け。


# 何ができるようになるの？
- 本番のコンテンツ（記事内容などDBを含む）をまるっとプラグインとか一切使用せずに持ってきます。
- dockerと書いてありますが、このやり方であればサーバー移行でも使えますね。

# どうやってやるの？
- 以下のcomposerファイルを使えばサクッとできちゃう。
### 必要なものはこれ
- `/wp-content`
- `wp-config.php`
- `docker-composer.yml`
- `/mysqls/initdb.d/exported.sql`

### ポイント
- ここで`/sqls/initdb.d`以下のsqlファイルをコンテナ立ち上げ時に自動で実行
- sqlファイルは本番環境のものなので反映される。
- その前に`wp-config`のパスとか変えないと動かないんだどね。
```
     volumes:
       - ./mysqls/initdb.d:/docker-entrypoint-initdb.d
```

###### docker-compose.yml

```
## お掃除コマンド
# docker rmi $(docker images -q) && docker volume rm $(docker volume ls -qf dangling=true)
# sudo chmod -R 777 . && git reset . && git clean -df
version: '3'

services:
   db:
     image: mariadb:10.5-focal
     volumes:
       - ./mysqls/initdb.d:/docker-entrypoint-initdb.d
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: hello
       MYSQL_PASSWORD: world

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db
       WORDPRESS_DB_USER: hello
       WORDPRESS_DB_PASSWORD: world
     volumes:
       - ./wp-content:/var/www/html/wp-content
volumes:
    db_data:
```
Azure App Service カスタムバックアップをプレビュー中の仮想ネットワーク経由でやってみた

今までの Azure App Service カスタムバックアップは、パブリックネットワーク経由の Azure Storage しか選択肢がありませんでした。今回検証する仮想ネットワーク経由のカスタムバックアップはプレビュー中ですが、どのような設定が必要になるのか試してみました。これができるようになると、よりセキュアにシステムを構成する事が可能になりますね。

## 検証環境を Azure CLI で構築

```bash:bash
# 環境変数をセット
region=japaneast
prefix=mnrapbk

# リソースグループを作成
az group create \
  --name ${prefix}-rg \
  --location $region

# 仮想ネットワークを作成
az network vnet create \
  --name ${prefix}-vnet \
  --resource-group ${prefix}-rg \
  --address-prefixes 10.0.0.0/24

# ネットワークセキュリティグループを作成
az network nsg create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-nsg

# サブネットを作成
az network vnet subnet create \
  --resource-group ${prefix}-rg \
  --vnet-name ${prefix}-vnet \
  --name app-subnet \
  --address-prefix 10.0.0.0/26 \
  --network-security-group ${prefix}-nsg \
  --service-endpoints Microsoft.Storage

# ストレージを作成
az storage account create \
  --name ${prefix}stor \
  --resource-group ${prefix}-rg \
  --sku Standard_LRS

# バックアップ用のコンテナを作成
az storage container create \
  --account-name ${prefix}stor \
  --name backups

# 外部アクセスを無効化
az storage account update \
  --name ${prefix}stor \
  --resource-group ${prefix}-rg \
  --default-action deny

# サブネット経由のアクセスを許可
az storage account network-rule add \
  --account-name ${prefix}stor \
  --resource-group ${prefix}-rg \
  --vnet-name ${prefix}-vnet \
  --subnet app-subnet

# VNET 統合可能な B1 で App Service Plan を作成
az appservice plan create \
  --name ${prefix}-plan \
  --resource-group ${prefix}-rg \
  --is-linux \
  --sku B1

# Web App を作成
az webapp create \
  --name ${prefix}-app \
  --resource-group ${prefix}-rg \
  --plan ${prefix}-plan \
  --runtime "PHP|8.2" \
  --https-only true

# VNET 統合を追加
az webapp vnet-integration add \
  --name ${prefix}-app \
  --resource-group ${prefix}-rg \
  --vnet ${prefix}-vnet \
  --subnet app-subnet
```

## 「カスタムバックの構成」で設定

「仮想ネットワーク統合でのバックアップ/復元（プレビュー）」というチェックボックスが増えていました。

![appservice-backup-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675885/643a75a1-52f2-d874-3f37-45f240a3b92c.png)

## 「今すぐバックアップ」を実行

バックアップは成功。スクショにはありませんが、その後の復元ももちろん成功しました。

![appservice-backup-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675885/bf70f02b-546d-3c9e-3754-671e6ca046c9.png)

## 参考

https://azure.microsoft.com/ja-jp/updates/app-service-backup-and-restore-over-azure-virtual-network/

https://learn.microsoft.com/ja-jp/azure/app-service/manage-backup?tabs=portal#back-up-and-restore-over-azure-virtual-network-preview
アンケート結果をtoday関数で抽出する

抽出するquery関数(A1にtoday)
~~~:GAS
=QUERY('フォームの回答 1'!A:B, "SELECT * WHERE dateDiff(A, date '" & TEXT(A1, "yyyy-mm-dd") & "') = 0")
~~~
期限を過ぎていた場合の条件付き書式
~~~:条件付き書式
=HOUR(A1) >= 8
~~~

追記:todayの部分はカレンダーでもいいかもしれない。
CentOS9にscreenコマンドを導入する方法

IBM CloudのCentOS9にscreenコマンドを導入してみた。

```txt:CentOS Stream 9 環境情報
[root@syasuda-centos9 ~]# dnf update -y
[root@syasuda-centos9 ~]# cat /etc/redhat-release
CentOS Stream release 9
[root@syasuda-centos9 ~]# uname -a
Linux syasuda-centos9 5.14.0-361.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Aug 24 13:40:45 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
```

```txt:epelの導入。失敗
[root@syasuda-centos9 ~]# dnf config-manager --set-enabled crb
[root@syasuda-centos9 ~]# dnf install -y  https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm https://dl.fedoraproject.org/pub/epel/epel-next-release-latest-9.noarch.rpm
（途中省略）
Downloading Packages:
Public key for epel-release-latest-9.noarch.rpm is not installed
Public key for epel-next-release-latest-9.noarch.rpm is not installed
Error: GPG check FAILED
```

```txt:epelの導入。gpgをチェックしないようにする。
[root@syasuda-centos9 ~]# dnf config-manager --set-enabled crb
[root@syasuda-centos9 ~]# dnf install --nogpgcheck https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm https://dl.fedoraproject.org/pub/epel/epel-next-release-latest-9.noarch.rpm
（途中省略）
Downloading Packages:
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                                                                                                        1/1
  Installing       : epel-next-release-9-7.el9.noarch                                                                                                                       1/2
  Installing       : epel-release-9-7.el9.noarch                                                                                                                            2/2
  Running scriptlet: epel-release-9-7.el9.noarch                                                                                                                            2/2
Many EPEL packages require the CodeReady Builder (CRB) repository.
It is recommended that you run /usr/bin/crb enable to enable the CRB repository.

  Verifying        : epel-release-9-7.el9.noarch                                                                                                                            1/2
  Verifying        : epel-next-release-9-7.el9.noarch                                                                                                                       2/2

Installed:
  epel-next-release-9-7.el9.noarch                                                          epel-release-9-7.el9.noarch

Complete!
```

```txt:screenの導入
[root@syasuda-centos9 ~]# dnf install screen
```

以下は、screenのカスタマイズ例。エスケープをCtrl+Tにしている。

```txt:~/.screenrc
defutf8 on
defencoding utf8
encoding utf8 utf8

escape ^Tt
defscrollback 1000000
termcapinfo xterm* ti@:te@
autodetach on
allpartial off
startup_message off
hardstatus alwayslastline "%{= rw} %H %{= wk}%-Lw%{= bw}%n%f* %t%{= wk}%+Lw %{= wk}%=%{= gk} %y/%m/%d %c "
```
APIがなければクラウドプラットフォームの将来性はない

<font color="Grey">*[Your cloud platform isn't future-proof without an API](https://aiven.io/blog/your-cloud-platform-isn't-future-proof-without-an-api)の翻訳です。*</font>

2022年11月11日

#APIなしではクラウドプラットフォームの将来性はない

APIは、クラウドの購入を決定する際に重要な機能だ。その理由は以下の通りだ。

真にクラウドネイティブなアプリケーションは、利用可能な最良のコンポーネントからプラットフォームを構成し、アプリケーションやプラットフォームのニーズを満たすようにする。一般的に、これにはコンピュート・プラットフォーム、データを移動、保存、分析するためのデータ・コンポーネント、モニタリングや観測ソリューション、そしておそらくID管理などの追加サポート・システムが含まれる。


利用可能なサービスから最適なソリューションを構成する方法を決定する際には、現在のニーズだけでなく、プロジェクトの将来の成長と進化も考慮することが重要だ。最も基本的なレベルでは、使用するコンポーネント間に利用可能な既存の統合があることを確認することです。また、ニーズが変化することが予想される企業の場合は、将来の要件を予測し、それを含めて検討することも可能でしょう。


問題は、ソリューションが実装され、統合ルートがないまま、耐用年数の間に新しいコンポーネントがシステムに追加された場合に発生する。いつものように、未知の未知数は最悪であり、しばしば対処に最も費用がかかる。新しい携帯電話を買うたびに、他のどのデバイスにも適合しない新しいカスタム充電器が付属していた時代を覚えているなら、パズルの1ピースを交換するという決定がどれほど広範囲に及ぶ可能性があるか、よくお分かりだろう。新しい携帯電話には、新しいカーチャージャー、トラベルチャージャー、ヘッドセット...を購入する必要がある。


では、クラウドプラットフォームを決定する際に、新しいコンポーネントが既存のエコシステムと互換性がないという問題を回避し、将来性を確保するためにはどうすればいいのだろうか？


## APIの選択


2つのシステム間の接続の最初の選択肢は、テスト済みですぐに使える既存の統合やコンポーネントです。通常、これは実装にかかる時間や労力を最小限に抑え、Just Work™を実現することを意味します。時には、そのような統合があらゆるプラットフォームの組み合わせ間ですでに利用可能でない場合や、アプリケーションに特注の統合を必要とする特定のニーズがある場合があります。


成功するクラウド変換プロジェクトは、現在の要件だけでなく、選択したサービスの将来性も考慮している。広範な（そして公開されている）[統合リスト](https://aiven.io/integrations-and-connectors)は、通常、他のサービスとうまく連携できるクラウドサービスの良い兆候である。運が良ければ、現在必要なもの、そしてプロジェクトの残りのライフタイムに必要なものはすべて、これらの統合によってカバーされる。


![image](https://cdn.sanity.io/images/sczeoy4w/production/5077ac90b7a1693c839307ebfd48b38699456e40-1422x710.png?q=80&fit=min&auto=format&dpr=1.5)


これにより、サードパーティの拡張機能への扉が開かれ、また、お客様の完璧なクラウドプラットフォームを完成させる統合機能を自由に構築することができます。開発またはテスト用にプラットフォームを[自動的にプロビジョニング](https://aiven.io/blog/5-reasons-to-automate-your-data-infrastructure)したり、週末に不要なシステムをパワーダウンしてクラウド料金を節約したり、カスタムCI（継続的インテグレーション）やビルド・ツーリングと統合したりするために、私たちのAPIを使用しているお客様をよく見かけます。


APIを備えたクラウドサービスを選択することは、標準的なポートやコネクタを備えたデバイスを購入するようなものだ。どのメーカーの充電器を買っても、電話機、ヘッドセット、カーチャージャー、その他のコンポーネントをすべて交換する必要はない。同様に、将来的にエコシステムに何か新しいものを追加する場合、プロバイダーがタイムリーにコネクタを製造する可能性はあるが、APIが利用可能であるということは、必要であればいつでも自分で統合できるということだ。


## 次に何が起こるか？


これで電話のセットアップはすべて完了し、次に新しい充電器やヘッドセットを購入する必要が生じたときにも、すべてうまく機能することを確信してそうすることができる。この比喩を現実にし、電話をかける時だ。


次はこれらのリソースを試してみよう：


* [AivenのAPI](https://docs.aiven.io/docs/tools/api.html)についてもっと知る。
* [APIドキュメント](https://api.aiven.io/doc/)
* [AivenのAPIをPostmanで試す](https://www.postman.com/aiven-apis)


#### Aivenプラットフォーム: 必要なすべての統合のために

モニタリングが必要ですか？オーケストレーション？データ統合？Aivenのサービスを既存のインフラと簡単に統合できます。

[すべてのコネクタと統合を見る](https://aiven.io/integrations-and-connectors)

Aivenと私たちのサービスに関する最新ニュースやオープンソースに関する情報を入手するには、[月刊ニュースレターを購読](https://aiven.io/newsletter)してください！Aivenに関する日々のニュースは、[LinkedIn](https://www.linkedin.com/company/aiven/)と[Twitter](https://twitter.com/aiven_io)のフィードでご覧いただけます。


サービスのアップデート情報を知りたい方は、[変更履歴](https://aiven.io/changelog)をご覧ください。


マネージド・データ・プラットフォームをお探しですか？[Aiven Consoleにアクセスして無料トライアルにお申し込みください！[](https://console.aiven.io/signup)
MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017 対応

mongodb を M1 Macbook Pro で brew upgrade したら、それまで動いていたのが動かなくなった件。

対応後にとりあえず自分のメモ用に書いているので、きちんとまとまっていませんが、ヒントにはなると思います。

# やったこと

元々 mongodb@6 が入っていた Mac で、brew upgrade したら mongodb@7 になったが、mongosh を起動しようとすると、

` MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017 `

になる。このメッセージ自体は、socketへの接続が出来ないというエラー。
要は、mongod が動いていないということ。

brew services では、正常に動いたように見えるが実際にはエラーで動いていない。log を見ると exit しているので分かる。

この動いていない原因は多数あるらしいので、ネットで調べてもかなり昔から沢山出てくるので、なかなかヒットしない。

私のケースでは、どうも、6.0以前と7.0以降はコンパチビリティがないのでエラーになるっぽい。（と書いてあるサイトを見たのだが、後から探すと見つからない、、。）
ところが、 brew uninstall とか brew reinstall ではデータ（設定ファイルも？）が消えないので、再インストールしても状態が変わらない。データを残す方法もあるっぽいけど、自分は不要なのでとりあえず手で全部消す。
(もしかしたら、設定ファイルだけの問題かもしれないけど未確認。）

また、色々操作していると、brew services startを root で起動しろというメッセージが出てくるが、これをやるといくつかのファイルのownerがrootになってしまう。典型的なのは、socket（/tmp/mongoなんちゃら）がrootになってしまう。brew services で自動起動に設定すると、ownerは自分自身なので、途中で使うファイルの owner が root だと色々失敗する。（次やる時は、rootでの実行をしないようにすれば良いと思う。もう１台あるのでそれで試す。）

mongod を root で起動すると動くけど、services での起動では失敗するようになったら、ログを見ながらファイルのowner を変更するとそのうち動くようになる。
(もしかしたら、こっちだけの問題かもしれない。）

## 別マシンで確認

こっちも brew upgrade でエラーになった。機種は M1 Macbook Air。
以下の手順で動いた
- 自動起動をやめる
- brew uninstall
- データ（/opt/homebrew/var/mongodb）を全部消す
- 念の為、socketも消す。再起動
- brew install, brew services start
- OK

mongodb の公式ページを見ると、6.0から7.0へのupgradeの方法が書いてあるのを見つけたので、この通りやれば良いのかもしれないけど、すでに 7.0 になってエラーで焦っている状態だともう遅いかも。
S3のファイル数をCloudWatchでCLIより安く取得する

# 前提
S3バケット上のファイル数が1000個以上ある場合、コンソール上では999+と表示され正確なファイル数を確認できない。
取得するにはどうすればいいかググったところ、AWS CLI（aws s3 ls）を使用した記事が多く出るが
もし「シンプルにS3内のファイル数だけを知りたい（=特定のフォルダ配下のファイル数を知りたいとかではない）」場合はCloudWatchから確認した方がコスト安となる。
※もし「特定のフォルダ配下のファイル数を知りたい」場合、CloudWatchからは確認できないのでAWS CLIを使って確認する方法を採用する。

# CloudWatchでの確認方法
1. CloudWatchコンソールから左メニュー内の「全てのメトリクス」を選択し、検索欄にS3バケット名を入力する
![スクリーンショット 2023-10-07 2.43.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885498/efe674b4-7f4a-22d0-93a7-976052bef2ae.png)
2. 「S3 > ストレージメトリクス」を選択

![スクリーンショット 2023-10-07 2.45.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885498/de2f91eb-12eb-76d2-4f46-7c38e513a54e.png)
3. メトリクス名「NumberOfObjects」を選択し、グラフ上のポイントを選択することでファイル数を確認できます。
![スクリーンショット 2023-10-07 2.46.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2885498/c37bd5aa-71be-17c7-5e9e-6bf14c14dd8f.png)
redisをdockerで起動してみた。

## はじめに
redisというものを聞いたことはあったのですが、
実際使ったことはなかったので、今回挑戦してみました。
まずは、環境構築からやっていきます。

## 準備するもの
```yaml:docker-compose.ymal
version: '3.7'
services:
   #Redis
   redis:
    image: "redis:6.2.11"
    ports:
      - "6379:6379"
    volumes:
      - "./data/redis:/data"
```

## 構築手順
* docker-compose.ymalがあるディレクトリで「docker-compose up -d」
* 「docker-compose ps」でコンテナが起動していることを確認する
* 「docker-compose exec redis bash」でコンテナ内に入る
* 「redis-cli」でredisを扱える状態にする
* 「set test "hello"」でデータを登録する
* 「get test」でデータを参照する
 　⇨終了

## 詰まった部分
### docker-compose up -d で起動しようとすると以下のエラーが発生する。
```missing signature key```
```yaml:docker-compose.ymal
version: '3'

services:
  #Redis
  redis:
    image: "redis:latest"
    ports:
      - "6379:6379"
    volumes:
      - "./data/redis:/data"
```
解決方法：
「image: "redis:latest"」ではなく、バージョンを明記すること。（今回はredis:6.2.11にしています。）

### stateがExit 1になる
```yaml:docker-compose.ymal
version: '3'

services:
  #Redis
  redis:
    image: "redis:7.0.11"
    ports:
      - "6379:6379"
    volumes:
      - "./data/redis:/data"
```
解決方法：
バージョンがサーバのOS？docker？に対応していない可能性が
あるので、低いバージョンで試してみること。
今回は「6.2.11」で成功しました。
Djangoでプロジェクトを作成して、つながるか確認する

前回は、仮想環境にDjangoをインストールしました。
今回はプロジェクトを作成し、つながるか確認してみたのでメモとして残しておきます。

１．仮想環境をアクティベイトします。
　　　前回の投稿を参照してください
　　　https://qiita.com/norizo_no1/items/35ead30bf435608cac17
　　　　２．仮想環境をアクティベイト
　　　　４．activateを解除
　　　　５．pythonを終了
　　　あたりですかね。


２．Djangoのプロジェクトを作成します。
　　django-admin startproject フォルダ名
　　ここでは、フォルダ名を「asa_1」とします。
![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3571777/cd1e5437-bae5-1ac5-ca4a-943e2f454997.jpeg)
上手くいったみたいです。
フォルダasa_1も作成されていますね。
![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3571777/96783051-8907-aca0-1bf8-963ef9700bd9.jpeg)

３．それではサーバーを起動していきたいと思います。
　　　「python manage.py runserver」を入力して実行します。
　　　うまく起動できたみたいです。
　　　
![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3571777/6ce928d2-36cf-f8ed-7f1d-6a56eb5262ce.jpeg)
　　起動時のメッセージより、サーバーのIP=127.0.0.1、ポート番号は8000であることが
　　わかります 
　　このIPアドレスには意味があって、、、。以下のリンクから説明見れるので
　　内容を見てみてください。
　　https://saisoku-area.com/127-0-0-1/

    ちなみに「python manage.py runserver 12345」とすると
　　　ポート番号を変更できます。こうするとポー番号が１２３４５になります。
　　　デフォルトが８０００になるみたいですね。
　　　部屋番号８０００から部屋番号１２３４５へ引越した感じですかね(笑）

４．ブラウザからつながるか確認してみましょう
　　ｈｔｔｐ：／／１２７．０．０．１：８０００
　　![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3571777/a5732372-c717-1cde-8c4c-88bc71bdd54b.jpeg)
実行してみると、、、
![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3571777/917034c5-b194-313f-19f6-e01e1e350a46.jpeg)
上手くいきました。自分のパソコンから自分のパソコンへ。

そうだ、サーバーの落とし方ですが、「CTL＋C」で止まります。

５．コマンドプロンプトでちょっとお役立ちなめも情報
　（１）ディレクトリを作るコマンド
　　　　　https://website-note.net/windows/make-directory-mkdir/
　（２）ディレクトリを削除するコマンド
　　　　　https://www.freecodecamp.org/japanese/news/cmd-delete-folder-how-to-remove-files-and-folders-in-windows/
　（３）カレントディレクトリを移動したりするコマンド
　　　　　https://www.k-tanaka.net/cmd/cd.php
UE5でOculus LipSyncを用いてリアルタイムにVRMのリップシンクを行う

![lip_3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953041/e01f76ae-2d4f-c284-2141-05ba4330593b.gif)


# バージョンと環境、事前知識について
今回はUE5.1を使っています。他のバージョンは検証してません。
UE4でのOculus LipSyncは分かるけどUE5じゃどうやってリアルタイムにシーケンスを作成するか分からんて人向けです。
この記事はUE5で動かすのに苦労した自分の備忘録です。
リアルタイムの音声取り込みにはRuntime Audio Importerを使用し、WAVファイルの読み込みをbase64で行うことを想定しています。
https://unrealengine.com/marketplace/ja/product/runtime-audio-importer


## 必要な物

OculusLipsyncPlugin-UE5
①https://github.com/Shiyatzu/OculusLipsyncPlugin-UE5

UE4 OVR lipsync cook frame sequence
②https://github.com/IlgarLunin/UE4OVRLipSyncCookFrameSequence

今回はこちらのふたつを使用させせて頂きます

## 事前準備(今回のメイン)
①プロジェクトをC++化します

②UE4 OVR lipsync cook frame sequenceのInstallationを参考にし、ダウンロードしたファイルの中にあるCookFrameSequenceAsync.hとCookFrameSequenceAsync.cppを ovr lipsync integrationのPublic,Privateフォルダーの中に入れます。

③slnファイル(yourproject.sln)をVisual Studioで開き、プロジェクト自体をビルドします。これによりUE4 OVR lipsync cook frame sequenceがUE5でも使えるようになります。(cook frame sequenceノードが表れます)
![Desktop Screenshot 2023.10.07 - 00.54.59.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953041/e6a97a20-3d35-8daa-4d69-73011e1650a8.png)


## BPの実装
詳しい実装はおかずさんのを参考にしてください。https://pafuhana1213.hatenablog.com/entry/2018/11/26/011057
![Alice-EventGraph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953041/cf10b0f0-a9c5-1204-1fc7-2efd3f044e74.png)

base64デコードデータを取得→オーディオインポート→base64を元にシーケンス作成→startで解析開始→解析完了後リップシンク　という流れです。
NVSを使ってNode.jsのバージョン管理を簡単に

# はじめに
Node.jsは多くのプロジェクトで用いられていますが、プロジェクトごとに必要なNode.jsのバージョンが異なることも少なくありません。

このような場合に便利なのがNode Version Switcher（NVS）です。

# NVS（Node Version Switcher）とは
NVS（Node Version Switcher）はNode.jsのバージョンを簡単に切り替えられるツールです。
複数のNode.jsのバージョンをローカルにインストールし、プロジェクトごとに簡単にバージョンを切り替えることができます。

# NVSのインストール手順

```terminal: 環境変数の設定とリポジトリのクローン
$ export NVS_HOME="$HOME/.nvs"
$ git clone https://github.com/jasongin/nvs "$NVS_HOME"
$ . "$NVS_HOME/nvs.sh" install
```

```terminal: インストールされたNVSのバージョンを確認
$ nvs -v
1.7.0
```

## Node.jsのインストール方法
推奨バージョンの確認
公式サイトで現在推奨されているバージョンを確認しておきます。

https://nodejs.org/ja

※執筆時点での推奨バージョンは18.18.0でした。

```terminal: Node.jsのインストール（バージョン指定）
$ nvs add 18.18.0
Downloading [#########################################################################################################################################################################################################################################################] 100%      
Extracting  [#########################################################################################################################################################################################################################################################] 100%      
Added at: ~/.nvs/node/18.18.0/x64/bin/node
To use this version now: nvs use node/18.18.0/x64
```

インストール後の状態を確認します。
```terminal: Node.jsバージョンの確認
$ nvs ls
  node/18.18.0/x64 (Hydrogen)
  node/18.16.0/x64 (Hydrogen)
  node/14.15.0/x64 (Fermium)
$ 
$ node -v
bash: node: command not found  
# => nvs add 実行後のメッセージ通り、nvs useをしなければならない
```

## バージョンの適用
Node.jsを使用する前に、nvs use コマンドで使用するバージョンを選択する必要があります。

```terminal: nvs useを実行
$ nvs use 18.18.0
PATH += ~/.nvs/node/18.18.0/x64/bin
```

これで指定したバージョンのNode.jsが使用できるようになります。
```terminal: 
$ node -v
v18.18.0
```

# まとめ
NVSを使えば、複数のNode.jsのバージョンを簡単に管理できます。
プロジェクトごとに必要なNode.jsのバージョンが異なる場合でも、手軽に切り替えができるので非常に便利です。
是非活用してみてください。
フォルダ名とプロジェクトを移動したときは気をつけて

Flutterを触っていたときのこと。

突然アンドロイドもWindowsでも実行できなくなりました。
真の原因は何だったのか今でもわからないけど、
フォルダ名は極力というか必ずローマ字にするべき。
パスに日本語が含まれているだけでbuildできないなんて…
たぶんこれが原因の一部だったとは思います。

それとディレクトリを移動したときのエラーについて。
Cmakeerrerというのにぶち当たりました。
StackOverflowによると、どうしてうまくいったのかはさっぱりですが、

CMakeLists.txtを削除。
ターミナルで
```terminal
Flutter clean
```
```terminal
Flutter create .
REM 「.」は忘れずに！！
```
これで解決。
おそらくCMakeLists.txtに書かれている元々書かれていたディレクトリと実際に保存されているディレクトリが違うということなんじゃないかなと思いました。
AWS SAA-C03 合格体験記

# はじめに
先日，AWS SAA-C03に合格しました!
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">AWS SAA-C03合格しました!!<br>わ～い!! <a href="https://t.co/tRCV5mYSgk">pic.twitter.com/tRCV5mYSgk</a></p>&mdash; うみのやまねこ (@Umi_no_Yamaneko) <a href="https://twitter.com/Umi_no_Yamaneko/status/1708057669037388194?ref_src=twsrc%5Etfw">September 30, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

合格までにしたことを中心に，主に以下についてまとめてみました
- 教材
- 傾向と対策

因みに，受験時の私のステータスは次の通りです
- オンプレのネットワーク構築(SW, RT, LB)，Windowsサーバーセットアップ，VMWare構築の実務合わせて約1年
- クラウド実務なし(新人研修でちょっと触った程度)

# 教材
## AWS認定資格 ソリューションアーキテクトアソシエイトの教科書: 合格へ導く虎の巻
Kindle版で"無料"で手に入ります。SAA-C03にも対応し，AWSの各サービスについて要点を網羅しているのでこれを読めば基礎は完成します。特に出題されやすいサービスには★マークがついているので，そのサービスを確実に理解することが大切です。模擬問題もついているので理解度チェックもできます。「各サービスの定義」と「各サービスのよくある利用方法」に注目しながら読んできました。

## ping-t
上記の虎の巻を読み終えたら(もしくは各サービスのセクションを読み終えたら)ping-tでサービスの理解確認をしました。この時はまだ模擬問題を解きたくなかったので「試験レベル」の問題は後回しにしました。間違えた問題はその解説と，該当サービスの解説を熟読し，すべての問題を解きました。解説を読む際は虎の巻でサービス内容の確認をしてもいいでしょう。全ての問題を解き終えたら「試験レベル」の問題をすべて解きました。あとは，ミスした問題が正解になるまで繰り返しミスした問題に再挑戦していきました。

## udemy「【SAA-C03版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集」 
仕上げとしてこの問題集を解きました。見直しの時間など時間配分に注意して解きました。解説を読む際は，問題の解説内容だけでなく，併記されている公式ドキュメントのURLも読みました。
この問題集は隙間時間に解くのが難しいため，まとまった時間で解くようにしましょう。また，問題のレベルは本番レベルよりやや難しめなので，合格ラインを超えることを目標に解くと良いでしょう。
因みに教材の購入はセール時の1000円台が良いです。

# 傾向と対策
## サービス内容だけでなく，要件に適したサービスの組み合わせや設定が問われやすい
昔のSWA SAAではサービス内容だけで合格できたようですが，C03では問題文中で要件が提示され，「この要件を満たすアーキテクチャはどれ?」みたいな問題が良く問われます(公式サンプル問題参照)。このため，虎の巻や各種模擬問題で複数サービスの連携パターン(〇〇をトリガーにしてXXを実行する，のような)を把握しておくことが重要です。

## Well-Architectedを意識したアーキテクチャを考える
SAAの4つの評価分野はWell-Architectedの内容と重複します。即ち，Well-Architectedの考え方に従って選択肢を選ぶことが重要になります。

## オンプレの知識もかなり使える
オンプレ環境を仮想化しているサービスも多いので，Security Groupのインバウンド・アウトバウンドルールやALBの挙動，WAFなどオンプレの知識を使いまわすことができます。IT実務がない方はオンプレの知識を含めて体系的に学習すると良いと思います。

# まとめ
インフラの実務が浅く，クラウド実務が皆無でもSAAに合格できました。受験中に回答に自信のない問題を数えたら全問題数の30%程度でハラハラしました。実は今回は受験料半額キャンペーンを適用したわけですが，「試験に自信がないよ」っていう方は不定期でこのようなキャンペーンや「再受験無料キャンペーン」なども行われているので，チャンスがあればぜひ受験してみてください。
Github備忘録

参考にした、というかこちらのサイトの丸パクリです。
→https://programming-jissen.com/how-to-upload-an-existing-local-repository-to-github/
どちらかというと自分用の備忘録です。

### GitHubで新規リポジトリを作成する
まずは、リモートリポジトリを作成してください。
今回はGitHubで行いますが、ほかのGitLabなどでも基本的に同じだと思います。

### リモートリポジトリのアドレスをoriginという名前に紐づける
以下のコマンドを実行してください。


```terminal
git remote add origin https://github.com/{ユーザー名}/{リポジトリ名}.git
```
`git remote add origin ~`とすることで、`〜`で指定したリポジトリのアドレスを、`origin`という名前に紐づけることができます。
ここで紐づけることで、今後は`origin`という名前で利用できるようになります。

### ローカルリポジトリを、先ほど作成したリモートリポジトリへプッシュする
以下のコマンドを実行してください。

```terminal
git push -u origin master
```
オプションの`-u`は`--set-upstream`の略で、プッシュしたリポジトリの上流ブランチを設定するオプションです。

`git push -u origin master`とすることで、リモートのoriginブランチをローカルのmasterブランチの上流ブランチとして設定できます。

`git push -u origin master`のように上流ブランチを設定することで、今後は`git push`だけでmasterにプッシュすることができ、便利です。
参考：git push -u オプションの意味

ちなみに、上流ブランチとは、ざっくりいうと親となるブランチのことです。
ローカルからリモートへコマンド送る際、特に指定がない場合はデフォルトブランチが対象となります。

そのため、ローカルで単純に`git push`や`git pull`などとした際には、ここで設定した上流ブランチにプッシュ、プルされることになるわけです。

上流ブランチについては以下の記事が詳しかったです。
参考：Git用語：上流ブランチとは？

これで、リモートリポジトリにこれまでの作業分がプッシュされていると思います。
Next.jsでクリップボードに保存ボタンを実装

## はじめに

Next.jsでボタンをクリックしたらクリップボードに保存したいという要望があったため実装メモ。
(簡単でしたが、意外と知らなかったので、、、)

## 実装

```tsx
import React from 'react'

const Copy = () => {
  const clickHandler = async () => {
    const message = 'クリップボードに保存するメッセージ'
    try {
      await navigator.clipboard.writeText(message)
      alert('クリップボードに保存しました。')
    } catch (error) {
      alert('失敗しました。')
    }
  }

  return (
    <button className='btn m-5' onClick={() => clickHandler()}>
      COPY
    </button>
  )
}

export default Copy
```
expr コマンドで数値判定を行う（とバグになるシェルスクリプト）

## はじめに

シェルスクリプトで数値判定（整数判定）を行う方法として `expr` コマンドを使う方法が紹介されますが、これがうまく行かない例、つまりバグになる例を紹介します。

## expr で数値判定を行う

`expr` で数値判定を行うコードとしてよく見かけるのがこれです。数値ではない値を渡すとエラーになることを利用しています。

```sh
$ x = abc
$ expr "$x" + 1
expr: non-integer argument
$ echo $?
2
```

## expr で数値判定を行うとバグになる例

`expr` コマンドは計算結果が 0 だと偽 (0) を返し、終了ステータスはエラー扱いです。

```console:すべての実装（仕様）
$ expr "-1" + 1; echo "exit status: $?"
0
exit status: 1
```

GNU コマンドや Solaris では `expr` コマンドの最初の引数が、`length`、`substr`、`index`、`match` という文字の場合に特殊な処理を行います。なお POSIX では最初の引数これらだった場合の動作は未指定となっており POSIX に準拠した動作です（というか移植性がないから未指定とせざるを得ない）

```console:GNU コマンドの場合（Solaris除く）
$ expr "length" + 1; echo "exit status: $?"
1
exit status: 0
```

正規表現を使った数値判定も考えられますが、`length` という文字列だと正規表現比較になりません。`match` を使って GNU 版コマンドとそれ以外で処理を分岐させればなんとかなるかな？

```console:GNU コマンドの場合（Solaris除く）
$ expr 'length' : '[0-9]*$'
expr: syntax error: unexpected argument ‘[0-9]*$’
```

`--` はオプションと引数を区別するための引数です。ちなみに FreeBSD 版の `expr` コマンドは `-e` というオプションを持っています。

```console:GNU コマンドの場合
$ expr "--" + 1; echo "exit status: $?"
1
exit status: 0

$ # 補足 「--」 をちゃんと書こう
$ expr -- "--" + 1; echo "exit status: $?"
expr: non-integer argument
exit status: 2
```

## さいごに

`expr` コマンドを使って簡単に数値判定を行う方法があるかは不明です。`expr` は `&` (AND) とか `|` (OR) とかカッコが使えるので長く書けばできそうな気はするんですけどね。正規表現を使う方法もありますが、`expr` コマンドで使う正規表現は基本正規表現で、`?` や `+` は POSIX では使えない事になってるので注意してください。


正直な所、どちらにしろ `expr` コマンドは外部コマンドで遅いので興味がないです。私はこんな感じの関数を使ってそれで判定しています。

```sh
is_number() {
  case ${1:-} in
    '' | *[!0-9]* ) return 1
  esac
  return 0
}
```

もしくは bash、ksh、zsh などなら `[[ ... ]]` を使うと簡単ですね。

```sh
if [[ "$x" =~ ^-?[0-9]+$ ]]; then
  : 数値
fi
```

`test` コマンドが終了ステータス 2 を返すことを利用した判定方法もありますが、ksh（ksh93u+）、mksh、OpenBSD sh では動きません。ksh93u+m の POSIX モードなら動きます。あと何年かしたらこの方法を使えるようになるかもしれませんが、現時点の ksh は ksh93+ 止まりで ksh93u+m へ置き換わってはいません。

```console
【macOS 13 などの場合】
$ ksh -c '[ str -eq 0 ]; echo $?'
1

【Solaris 11の場合（str変数を参照している、mkshやOpenBSD shも同様）】
$ ksh -c '[ str -eq 0 ]; echo $?'
0

【ksh93u+m（POSIXモード）の場合は判定できる】
$ ksh -c 'set -o posix; [ str -eq 0 ]; echo $?'
ksh: [: str: bad number
2
```

この記事は `expr` コマンドで数値判定を行ってる例を見かけるけど、それ本当にちゃんと動く？と気になったので書いています。
【TailwindCSS】スピナーの作成方法

以下のように記述することでスピナーを作成できます。

## スピナー1

```html
<div class="h-32 w-32 animate-spin rounded-full border-4 border-t-transparent border-gray-900" />
```

![スクリーンショット 2023-10-26 23.53.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/dfa47c43-e1b8-4c57-f8bd-58588fc98da6.png)

## スピナー2

```html
<div className="animate-spin rounded-full h-32 w-32 border-t-2 border-b-2 border-gray-900" />
```

![スクリーンショット 2023-10-26 23.50.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/f9c36562-28cf-552c-2e04-ebe05a6fdac2.png)
AWS SDK for JavaScript v3 DynamoDB 操作覚書メモ

# はじめに

AWS SDK for JavaScript v3 で DynamoDB を扱う記事が少ない印象なのでメモ程度に書きなぐっておきます。

公式のサンプル実装もあり、見たのですが、改めて見返すのはちょっと……という抵抗感を感じてしまったので、本当に個人的に最小限メモしておきたいものだけ記載しています。

https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javascriptv3/example_code/dynamodb

# DynamoDB のテーブルアイテム操作

## テーブル設定

|設定項目|値|
|---|---|
|テーブル名|`Music`|
|パーティションキー|`Artist`|
|ソートキー|`SongTitle`|

## データ一括操作

### 一括で追加

`BatchWriteCommand`（API名としては `BatchWriteItem`）で最大一括で25件追加が出来る。  
25件を超えてしまうなら、事前に以下実装のようにファイルの分割を実施する必要がある。

```typescript
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, BatchWriteCommand } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({});

const docClient = DynamoDBDocumentClient.from(client);

const list = [
  ['Perfume', 1, '2005-09-21', 'リニアモーターガール'],
  ['Perfume', 2, '2006-01-11', 'コンピューターシティ'],
  ['Perfume', 3, '2006-06-28', 'エレクトロ・ワールド'],
  ['Perfume', 4, '2007-02-14', 'ファン・サーヴィス[sweet]'],
  ['Perfume', 5, '2007-09-12', 'ポリリズム'],
  ['Perfume', 6, '2008-01-16', 'Baby cruising Love'],
  ['Perfume', 6, '2008-01-16', 'マカロニ'],
  ['Perfume', 7, '2008-07-09', 'love the world'],
  ['Perfume', 8, '2008-11-19', 'Dream Fighter'],
  ['Perfume', 9, '2009-03-25', 'ワンルーム・ディスコ'],
  ['Perfume', 10, '2010-04-14', '不自然なガール'],
  ['Perfume', 10, '2010-04-14', 'ナチュラルに恋して'],
  ['Perfume', 11, '2010-08-11', 'VOICE'],
  ['Perfume', 12, '2010-11-10', 'ねぇ'],
  ['Perfume', 13, '2011-05-18', 'レーザービーム'],
  ['Perfume', 13, '2011-05-18', '微かなカオリ'],
  ['Perfume', 14, '2011-11-02', 'スパイス']];

const chunks = <T>(arrayData: Array<T>, chunkSize: number = 25): Array<Array<T>> =>
  Array.from({ length: Math.ceil(arrayData.length / chunkSize) }, (_, i) =>
    arrayData.slice(i * chunkSize, i * chunkSize + chunkSize));

const commands = chunks(list, 25).map(chunk => {
  const command = new BatchWriteCommand({
    RequestItems: {
      Music: chunk.map(item => ({
        PutRequest: {
          Item: {
            Artist: item[0],
            SongTitle: item[3],
            Release: item[2],
            Numeric: item[1]
          }
        }
      })),
    },
  });
  return docClient.send(command);
});

Promise.all(commands)
  .then(console.log);
```

### 一括で削除

以下の差分を適応することで`BatchWriteCommand`（API名としては `BatchWriteItem`）で最大一括で25件削除も出来る。  

パーティションキーとソートキー以外の属性は渡さないようにする必要があるので注意。

```diff
- PutRequest: {
-    Item: {
+ DeleteRequest: {
+    Key: {
      Artist: item[0],
      SongTitle: item[3],
-     Release: item[2],
-     Numeric: item[1]
    }
  }
```
git log あれこれ

## 概要

- `$ git log`コマンドのオプションをケース別に簡単に紹介する。

## ケース

### 単純にコミットのログだけを見たい

```shell
git log
```

### コミットのログと修正を加えたファイルの一覧を見たい

```shell
git log --stat
```

### コミットのログと修正を加えたファイルの差分を見たい

```shell
git log -p
```
從台灣國際學校到出國留學


台灣國際學校的優勢在於其國際化的教育體驗，但對於許多學生來說，出國留學是一個更廣闊的選擇。在進一步探討這一議題之前，我們將首先關注留學準備中的SAT考試，然後探討美國簽證流程，最後探討出國留學所提供的機會以及國際學校對此過程的影響。

SAT考試：
SAT（Scholastic Assessment Test）是一項廣泛用於美國大學入學申請的標準化考試。許多國際學校提供SAT準備課程，以幫助學生為這一挑戰做好準備。這門考試通常包括數學、閱讀和寫作三個部分，並且被許多美國大學視為申請的重要參考依據。對於計劃出國留學的學生來說，SAT的考試成績是一個不容忽視的因素，因此在國際學校中提前優化SAT準備是一個重要的步驟。

[美國簽證](https://www.apexcharity.org/news/3/94)：
一旦學生在[SAT](https://www.apexcharity.org/news/3/84)考試中表現出色並獲得了美國大學的錄取通知，他們需要處理簽證程序。美國的學生簽證通常是F-1簽證，而國際學校的學生已經習慣了簽證程序的一部分。然而，留學生簽證仍然需要嚴格遵守，包括確保學生有足夠的財力來支付學費和生活費，並且需要提交必要的文件。因此，國際學校可以在這一過程中提供重要的指導和支持，確保學生能夠順利地前往美國學習。

出國留學的機會：
[出國留學](https://www.apexcharity.org/news/3/83)提供了一個獨一無二的機會，讓學生在國際舞台上學習，體驗不同的文化和環境。這不僅僅是學術方面的機會，還有個人成長和發展的機會。留學生可以建立全球性的人際網絡，學習不同的思考方式，並拓寬他們的視野。國際學校的學習經驗為學生提供了從容應對這一挑戰的能力，並鼓勵他們追求更高的學術成就。台灣國際學校的學生通常已經受到高質量的教育，因此他們在國外學習時也有競爭優勢。然而，學生和家長仍然需要仔細研究不同的國際學校，以確保他們的需求和目標能夠得到滿足。

總之，從台灣[國際學校](https://www.apexcharity.org/news/3/82)出國留學是一個令人興奮的選擇，可以為學生提供多方面的機會和挑戰。SAT考試的成功，簽證程序的順利進行以及國際學校的豐富教育經驗都將為學生在美國的留學生活奠定堅實的基礎。當學生踏上這個全新的學術之旅時，他們將帶著自信和準備好面對未來的決心。這樣的經歷將不僅豐富他們的個人生活，還為他們的未來打開更多的可能性。
Next.jsを使ったAPI開発

## はじめに
Next.jsでAPIの開発をできるがあるので、メモ代わりに書いていきます。

## Next.jsにおけるAPI開発とは
Next.jsはReactのフレームワークになりますが、APIを作成して、同じコードベースの中で、フロントエンドとバックエンドのコードを書くことができ、呼び出すことができます。Node.jsなどを使ってサーバを立てなくても、DBにアクセスできたりすることができるということです。

## 基本的なフォルダ構成
今回はApp Routerを使用していきます。
基本的には、appフォルダ配下に、apiフォルダを作成して、その中にファイルを追加して、APIのコードを書いていくことができます。そして、そのディレクトリ名と、ファイル名がAPIのエンドポイントになります。

## サンプルコード
ドキュメントに沿って、簡単なAPIを作ります。
まずは、以下のコードを/api/router.jsに書いていきます。

``` /api/route.js
import { NextResponse } from "next/server";

export async function GET() {
  return NextResponse.json({
    message: "データを取得!",
  });
}

```

そしてこのコードをフロントエンドから呼び出してみましょう。
以下のコードを書きます。
``` page.tsx
"use client";

import axios from "axios";

export default function Home() {
  const getData = async () => {
    const response = await axios.get("/api");
    console.log(response);
  };

  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex">
        <button
          className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
          onClick={getData}
        >
          getDate
        </button>
      </div>
    </main>
  );
}

```

すると、以下のように/api/route.jsに作成したデータが取得できました！

![スクリーンショット 2023-10-26 23.12.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613586/216f08f0-abea-e9cc-cae2-72b38c9e6888.png)

次は、apiのエンドポイントを「/api/users」としてみましょう。
usersディレクトリをapiディレクトリ配下に作り、その中にrouter.jsを作り、以下のようなコード書いていきます。
``` /api/users/route.js
import { NextResponse } from "next/server";

export async function GET() {
  return NextResponse.json({
    message: "/api/usersからデータを取得!",
  });
}

```

フロントエンド側のコードは以下のようになります。
```page.tsx
"use client";

import axios from "axios";

export default function Home() {
  const getData = async () => {
    const response = await axios.get("/api/users");
    console.log(response);
  };

  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex">
        <button
          className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
          onClick={getData}
        >
          getDate
        </button>
      </div>
    </main>
  );
}

```
すると以下のように、データを取得できました!
![スクリーンショット 2023-10-27 9.04.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613586/cdacd0a9-a9bf-5d4f-2e8f-f77134b0959d.png)

## ドキュメント
以下が参考にしたドキュメントです。

https://nextjs-ja-translation-docs.vercel.app/docs/api-routes/introduction

## 最後に
以上がNext.jsを使ったAPI開発をしていきました。
今回は、App Routerを使いましたが、Page RouterとApp Routerでは作り方が違うので注意が必要になります。

他にも色々な記事を書いているので、よければ読んでいってください、、、

https://qiita.com/hukuryo/items/97797a91d7e2ee0bcabc

https://qiita.com/hukuryo/items/265c676d17fe21e75242

https://qiita.com/hukuryo/items/ebeb26823f944f143b11
Xcodeで簡単に複数選択する方法

# 記号の説明

この記事で出てくる記号の説明をします。

- ⌥： option キー
- ^： control キー

# マウスで複数の行を選択する方法

⌥キーを押しながらマウス選択すると、複数の行を選択できます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/707293/c5558d74-1d19-2c87-933d-d48ba1bb7001.gif" width=80%>


# 矢印キーで複数の行を選択する方法

 ^ + shift を押しながら上下の矢印キーを押すと、複数の行を選択できます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/707293/c675aa8a-2930-6217-e720-37841fed89f2.gif" width=80%>

# クリックで複数のカーソルを作成する方法

^ + shift を押しながらクリックすると、複数のカーソルを作成できます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/707293/8b71c34a-d739-7473-483f-9703142a2f79.gif" width=80%>

## さいごに

他にもあったら追記していきます。

「こんなのもあるよ」って方はコメント欄にお願いします！
【備忘録 #1】超簡潔！TypeScriptの基礎

# この記事について
YouTubeで、以下動画を視聴したので、
自分用の備忘録として超簡潔に記述しました。
なので、詳細な説明は書いてないです。


https://www.youtube.com/watch?v=F9vzRz6jyRk

# 目次
* [コンパイルのやり方](#コンパイルのやり方)
* [型について](#型について)

# コンパイルのやり方
現在のディレクトリ直下にある`index.ts`をコンパイルする場合
```shell:コンパイル
tsc index.ts
```
上記コマンド実行後、`index.js`ファイルが同階層に生成されます。
```shell:index.jsの実行
node index.js
```

# 型について
## any型
何でもありの型。
文字列、数値、真偽値、オブジェクト等何にでもなれる型。
``` typescript:any型
let name: any = "hello";
name = true;
name = 44;
name = "";
```

## enum型
列挙型。
変数sizeは、今後、Size.SHORT,size.MEDIUM,size.TALLの3つしか代入することができない。
```typescript:enum型
enum Size {
    SHORT = "SHORT",
    MEDIUM = "MEDIUM",
    TALL = "TALL",
}

let size = Size.SHORT;
```


## union型
型定義にOR演算子が使える型。
```typescript:union型
let name: string | number;
```

## リテラル型
特定の値のみしか代入不可にする。
```typescript:リテラル型
const name: "hello" = "hello";
```

## unknown型
基本的に、any型と同じ。
any型と異なるのは、any型は、どんな型の変数にも代入できるが、unknown型は代入不可という点。
```typescript:unknown型
let name: unknown = "hello";
name = 44;
name = true;
name = {
    type: "short",
    size: "hello",
};
```

## never型
返り値が無い型。
```typescript:never型
function add(num1:number, num2:number): never {
    console.log(num1 + num2);
}
```

## タイプエイリアス
型定義を変数化できます。
```typescript:タイプエイリアス
// ユニオン型の型定義を、タイプエイリアスによって行っている
let clothSize = "small" | "medium" | "tall";
let size: clothSize = "small";
```

## 関数
```typescript:関数
// 返り値が無い場合、`void`と記述
function add(num1: number, num2: number): void {
    console.log(num1+num2);
}
```

## オブジェクト 読み取り専用プロパティ
以下のように型注釈時、プロパティ名の前に`readonly`と記述すれば
そのプロパティの値は読み取り専用になる。
```typescript:readonly
let obj: {
    readonly name: string;
};
```

## ラッパーオブジェクト
JavaScriptにおいて、number,string,boolean型等の変数は
全て自動ボックス化される。
つまり、これらの変数は全てオブジェクトとして扱える。
```typescript:ラッパーオブジェクト
let num: number = 44;
console.log(num.toString());
```

また、以下のように全プロパティを読み取り専用にすることもできる。
```typescript:Readonly<>
let obj: Readonly<{
    a: number,
    b: number,
}>;
```


## オブジェクトの`?`
型注釈時、プロパティ名の後に`?`を記述することで
そのプロパティが存在しなくてもOKになる。
```typescript:?
let obj: {
    name?: string;
};
obj = {};
```

# watchモード
.tsファイルの保存時、自動でコンパイルを行ってくれるモードのこと。
`-w`を記述すると、watchモードになる。
```shell
tsc index.ts -w
```

## tsconfig.json
TypeScriptを実行する際の設定ファイル
（コンパイルするJavaScriptのバージョンを変更したりできる。）

### include
コンパイル対象のファイルを指定できる。
```json
"include": [
    "index.ts"
]
```

### exclude
コンパイルの対象外のファイルを指定できる。
```json:"exclude"
"exclude": [
    "index.ts"
  ]
```

### target
コンパイルするJavaScriptのバージョンを指定できる。
* es2016
* es6
等

### sourceMap
コンパイル後、.js.mapファイルを生成する。
ブラウザのDeveloper Toolsの「ソース」タブで.tsファイル内容を閲覧できるようになる。
500円以内で車のオーディオをbluetooth対応する方法

カーナビ付きの車では普通にbluetooth接続機能を持っているので、スマホを接続して、スマホで聴きたい音楽を流せますよね。

しかしカーナビをつけていない、GoogleMapで十分な人には、標準のオーディオしかついていないことがあります。
大抵の場合、ラジオとCDのみの装備です。

そういった車でも、わずか500円程度でbluetooth機能が付けられるデバイスを見つけました。

## ブルートゥース　スピーカーキット
それがこのキットです。

![71lxc+9js5L._AC_SX679_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50474/bf4c00ea-9351-dd2a-6fa6-e49d9f7c4ad6.jpeg)

amazonで「ブルートゥース　スピーカーキット」と検索すると、200円程度で売られています。とても安いです

端子はUSB-microBと、よくあるφ3.5mmのオーディオ端子です。

このキットは、USBで電源を供給すると、bluetoothで接続できるようになり
ペアリングして接続し、音楽を流すと、オーディオ端子から音声信号が流れます。

大抵の車には、AUXと書かれた、外部音声入力端子が備わっています。

したがって、ダイソーでUSBケーブルとオーディオケーブルを買って、
シガーソケットからUSBに給電し、オーディオケーブルでキットと車のAUXを繋げば
車をブルートゥース対応できてしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50474/9318a715-c4bc-2497-87f7-e962bda6fd75.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50474/4f748b8a-74b0-003c-e8f2-a7ae60b170da.png)


ブルートゥースじゃなくても良くて、スマホに3.5mmのオーディオ端子があれば、直接繋いでもいいんですけどね・・・

このキットとケーブル類を合わせても500円以下で実現できてしまいます。
シガーソケットでUSB電源が取れるカーチャージャーを持っていない場合は、
これもダイソーで100~500円で買えてしまいます


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50474/46f56021-0c4a-ab35-28ae-83fe9348e529.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50474/c1a2733d-8233-df73-b0b6-f12979c1029d.png)


## 終わりに
ケーブル類が増えるのと、基盤むき出しなので
見た目に気を遣う人には向いてないかもしれませんが
とにかく安くbluetooth機能をつけたい人にとっては良いと思います

最近の車には、標準装備でディスプレイ付きの高機能なカーオーディオがついていることが多いですが、
古い車に乗っている人におすすめです。
Git .gitignoreファイルで「指定したディレクトリ or ファイルを無視しない」設定をする

## 概要

- .gitignoreファイルで指定したディレクトリ or ファイルをgit管理するように記載する方法を簡単にまとめる。

## 方法

- ディレクトリ or ファイルの指定時に頭に`!`をつける。
- 例えば.gitignoreと同じ階層のpublicディレクトリをGit管理対象とし、それ以外のファイルを除外したい場合、下記の様に指定する。

    ```.gitignore
    *
    !/public
    ```

- 編集が終わったら下記の手順を参考にキャッシュクリアや、当該ディレクトリをgit管理対象にする

    ```shell 
    git add .gitignore # 先程!/publicを追記したもの
    git rm --cached /public # インデックから削除
    git add /public
    git commit
    ```