OmniAICreator/Qiita-1.07M huggingface dataset:
【Rails】has_manyでオートセーブが設定できるのは便利

どうもこんにちは。

今回は、モデル同士の関連付けを定義する時によく使用される`has_many`での便利なオプション`autosave: true`についてメモします。

以降は、以下の記事の知識（`build`メソッド）を使用しています。

https://qiita.com/PDC-Kurashinak/private/413059bf52c7ab14ed16

## has_manyってなに？

`has_many`とは、モデル同士を関連付けるために`belongs_to`と一緒に使用するものです。

UserモデルにPostモデルが子として紐づいていることを定義したい場合は、以下のように定義します。

```ruby
# Userモデル
class User < ApplicationRecord
    has_many :posts
end

# Postモデル
class Post < ApplicationRecord
    belongs_to :user
end
```

has_manyにはオプションがいくつかあり、最も使用されるものは`dependent: :destroy`だと思います。

`dependent: :destroy`については以下の記事で紹介しています。

今回は`autosave: true`について紹介します。

# 定義の仕方

`autosave: true`の定義の仕方は、以下のように記述するだけです。

```ruby
# Userモデル
class User < ApplicationRecord
    has_many :posts, autosave: true
end
```

これだけです。あとは`create`メソッドを記述して動きをみてみます。

# 実際の動き

以下のコードは「ユーザが作成されると同時にPostオブジェクトも作成される」前提でコードを記述しています。

```ruby
class UsersController < ApplicationController
    def create
        user = User.new(name: '試験太郎', age: 25)
        post = user.posts.build(title: 'テスト投稿', content: '今日はいい天気ですね')

        if user.save
            redirect_to users_path
        else
            render :new
        end
    end
end
```

上記のコードでは、`post.save`を実行していません。しかし、DBには、保存されています。

これは、modelに`autosave: true`を記述しているからです。これによって、`user.save`が実行されたタイミングでpostも保存されます。

以上
WSL上でエディタを開く@VSCode

# はじめに
WSLとVScodeユーザーです。  
最近、VScodeを使うのが不安でした。毎回、`reopen in wsl?`なんて聞いてくるから。  
この親切をうっかり消してしまったとき、とんでもないことが起こるんじゃないか・・・と。（たぶん、linuxコマンドが使えなくなる）

それが解決しましたので、簡潔に方法を書きます。
## 前提
念のためですが、WSLはWindowsでLinuxを動かす（？）ものです。
Macユーザーの方は必要ないものです。
# 解決方法
## `code`コマンドを使うだけ

`code`コマンドはVSCodeを開くコマンドです。  
wsl上で開きたいディレクトリに移動し、`code`コマンドを実行します。

```bash
$ cd Projects/sample-project
$ code .
```

これで、sample-projectをWSL / VScode上で編集できます。

## 雑記：wsl上のファイルへのアクセス@エクスプローラー
エクスプローラーや、各アプリからwsl上のファイルへアクセスできないことがあります。

そんなときは、ファイルパスへ
### `\\wsl$`
と入力するだけです。

## 雑記：wslを通さずに開くと？
困ったときのChatGPT！
> VSCode（Visual Studio Code）を使用してWSL（Windows Subsystem for Linux）上のプロジェクトにアクセスする場合、「Reopen in WSL?」というメッセージが表示されるのは、VSCodeがWSLの統合環境を通じてより効率的にプロジェクトを扱うことを推奨しているからです。WSLを通さずにVSCodeで直接プロジェクトを開くと、いくつかの問題が生じる可能性があります。
> 
> 1. **パフォーマンスの問題**: WSL上で動作しているLinuxベースの開発ツールやサーバーは、Windowsのファイルシステムを介してアクセスすると、パフォーマンスが低下する場合があります。WSL経由で直接アクセスすることで、これらのツールがより高速に動作するように最適化されています。
> 
> 2. **パスの不整合**: WindowsとLinuxではファイルシステムの構造が異なるため、WSLを介さずにファイルにアクセスすると、パスが正しく解決されないことがあります。これは、ビルドスクリプトや開発ツールが正しく動作しない原因になり得ます。
> 
> 3. **環境の整合性**: WSLはLinux環境をエミュレートしており、多くのLinux固有の機能やツールをWindows上で直接利用できるようにしています。WSLを通さずにプロジェクトを開くと、これらのツールや機能が正しく動作しない、または期待通りの結果が得られない可能性があります。
> 
> 4. **権限の問題**: Linuxのファイルシステムは、Windowsと比較してより厳格な権限管理を行っています。WSLを経由せずにファイルにアクセスすると、権限に関連する問題が発生する可能性があります。
> 
> これらの問題を回避するため、VSCodeではWSL統合機能を使用して、WSL上のプロジェクトを「Reopen in WSL」オプションで開くことを推奨しています。これにより、開発環境の整合性を保ちつつ、パフォーマンスやツールの互換性を最適化できます。

また、

> WSLを通さずにVSCodeで直接WSL上のプロジェクトを開いた場合、Linuxコマンドを利用することに関しても問題が生じる可能性があります。
# 終わりに
`code`コマンド！
これだけ覚えればヨシ！
【Go/Gin】画像をアップロードしてディレクトリ内に保存する

## やりたいこと
画像をGinのAPIサーバーへアップロードし```./images```ディレクトリに保存したい。

## 実装方法
```go:main.go
package main

import (
	"net/http"
	"path/filepath"

	"github.com/gin-gonic/gin"
)

func main() {
	router := gin.Default()
	router.MaxMultipartMemory = 8 << 20

	router.POST("/images", func(c *gin.Context) {
		file, err := c.FormFile("images")
		if err != nil {
			c.String(http.StatusBadRequest, "get form err: %s", err.Error())
			return
		}

		savepath := filepath.Join("images", file.Filename)
		if err := c.SaveUploadedFile(file, savepath); err != nil {
			c.String(http.StatusBadRequest, "upload file err: %s", err.Error())
			return
		}

		c.String(http.StatusOK, "File %s uploaded successfully.", file.Filename)
	})

	router.Run(":8080")
}
```

### アップロード用のディレクトリを作成しておく
今回は```./images```に保存します。

![スクリーンショット 2024-02-01 17.02.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2932655/6a38a40a-5c67-1de5-7d7f-1e3f2a4d3427.png)

### ```path/filepath```を使う
os間の物理ファイルパスのセパレータがUNIX系は```/```で、Windows系は```\```のように異なるので、その差異を吸収してくれるようによしなに扱ってくれるライブラリ。


## 動作確認
### Postmanで確認
![スクリーンショット 2024-02-01 17.04.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2932655/21f8fcd4-0f0b-cde7-3fa8-e98d43c3969d.png)

```form-data```にアップロードしたい画像ファイルを添付し、POSTする。
keyは```file, err := c.FormFile("image")```の部分で指定した```image```に合わせる。

![スクリーンショット 2024-02-01 17.06.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2932655/37a2aeaa-1e12-8486-e552-ed31aece94e8.png)

無事アップロード完了。


### サーバーサイドで確認
![スクリーンショット 2024-02-01 17.07.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2932655/0d5ba60a-b8ad-ff11-df87-9befd91e6beb.png)

しっかり指定したディレクトリに画像がアップロードされていることを確認。
画面タッチのスワイプでScrollViewerを反応させたい

PanningModeを使う。デフォルトはNone。

```C#:xaml
<ScrollViewer PanningMode="Both">

```

## 参考
https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.controls.scrollviewer.panningmode?view=windowsdesktop-8.0

https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.controls.panningmode?view=windowsdesktop-8.0
ListBoxの最上段/最下段で画面タッチでスワイプするとWindowごと動いてしまう対策

ManipulationBoundaryFeedbackを使う
```C#:xaml

<ListBox ManipulationBoundaryFeedback="ListBox_ManipulationBoundaryFeedback">

```

```C#:C#

private void "ListBox_ManipulationBoundaryFeedback(object sender, System.Windows.Input.ManipulationBoundaryFeedbackEventArgs e)
{
    e.Handled = true;
}

```
XcodeのStorybordで使用した用語整理

# 用語整理
# GUIコンポーネント（Graphical User Interface Components）
・Interface Builder（IB）との違いが良くわかっていない。
・xcodeの上部にある＋ボタンで（カーソルを合わせるとShowLibraryと表示される）
![スクリーンショット 2024-02-02 14.58.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2823837/161f2a1b-b067-4293-f5c9-267c679e8f74.png)
・Label部品やButton部品とも呼ばれる。
・LabelやButtonの総称。
![スクリーンショット 2024-02-02 15.15.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2823837/de5286b8-5353-442e-4ea6-fb5a94871193.png)



# class ViewController: UIViewController {}
・画面の表示やユーザーインターフェースの管理を行う。

# override func viewDidLoad(){}
・UIViewControllerクラス内で使用されるメソッド。

# placeholder(プレースホルダー)
・空欄のテキストフィールドに薄く文字が記載されている。
・記入事項の指示が書いてある。
目に見えない文字対応、基本的にスペース、タグ、改行文字程度でいい説


## 「目に見えない文字対応」とは？

なんかの入力処理とかで、目に見えない文字列だった場合は不正な入力と見なすみたいな感じのやつ。

よくこんな風に書く。

```js
function isReadableText(text) {
    return text.trim() !== "";
}
```

## trimで取り除けない不可視な文字の存在

基本時にはtrimして空文字かを判定すれば事足りるのだが、残念なことにそれをすり抜ける文字が存在する。

例えば、これ→`ㅤ`←これ
（ハングルジュンソンフィラーというらしい。）

これだけでなく、不可視な文字はいくつかあるようだ。

https://invisible-characters.com/

## で、「目に見えない文字対応」はこれら全てを対応するべきなのか？

要件による。

で終わるとつまらないので私の考えを書く。

うっかりミスによるヒューマンエラーを防ぐ目的で「目に見えない文字対応」をする場合は、JSのtrimで取り除ける文字だけを対応すればよい。

何故か？

それは、**ハングルジュンソンフィラーのような不可視な文字のみの入力**は**意図的に入力しない限り、ほとんどあり得ない**からであり、

また逆に**スペース、タグ、改行のみの入力**は**うっかり入力してまう可能性が現実的な確率であり得る**からだ。
（例えば、アプリが遅いなーとイライラしながら適当にキーを連打したら、あるかもしれない。）

**うっかり**ハングルジュンソンフィラーだけの文字入力をすることは、天文学的な確率だと思われるため、ヒューマンエラーとしての対応に含む必要はないだろう。

---

またハングルジュンソンフィラーなどを弾く必要があるのは、例えば、対戦ゲームで相手の名前が見えないと不利になるなど、目に見えない文字がサービスに害をもたらす場合などが考えられる。
Androidでmapを使った簡易cacheを作成する

# 背景
Androidでサーバへ何度も問い合わせ必要の無い値や、app起動後しばらく同じ値を使いまわしたい時、値を保持しておくためのRepositoryが欲しくなったというシーンがあり、お試しで作ってみました。（なお本導入には至ってはおらず）

# 実践

開発環境や構成によってインタフェースがあったりDIがあったりと制約が多少はあるかもしれませんがお手軽にmapを使ってcacheするクラスを作成してみました。

```kotlin
/**
 * 簡易的なcache クラス.
 *
 * @author st-miz
 */
class CacheRepository {
    companion object {
        // defaultは5分cacheする想定
        private const val EXPIRED_TIME_MINUTES = 5L
    }

    private val cacheMap = mutableMapOf<String, CacheValue>()

    fun <T : Any> load(key: String): T? {
        cacheMap[key]?.let {
            if (it.expired()) {
                cacheMap.remove(key)
                return null
            } else {
                return it.data as? T
            }
        }
        return null
    }

    fun <T : Any> save(key: String, data: T, expiredMinutes: Long = EXPIRED_TIME_MINUTES) {
        cacheMap[key] = CacheValue(
            data = data,
            expiredMinutes = expiredMinutes,
        )
    }

    fun remove(key: String) {
        cacheMap.remove(key)
    }

    fun clear() {
        cacheMap.clear()
    }

    private data class CacheValue(
        val data: Any,
        private val expiredMinutes: Long,
    ) {
        private val expired: LocalDateTime = LocalDateTime.now().plusMinutes(expiredMinutes)
        fun expired(): Boolean {
            return LocalDateTime.now() > expired
        }
    }
}
```


# 感想

map使ってもいいんですが、普通にLruCacheとかでいい気がしてきたのでそのうち別記事を書くかもしれない。
【Google Apps Script × GitHub 】新規ブランチで"Error [github assistant] undefined"と出た時の対処法

結論
--
結論からお伝えしますと、ブランチ名に"#"がある場合は、"＃"を消しましょう！

Branch名に"#"を入れているとpush,pull時にエラーが出ました。
>例：feature#1

予想としましては、Apps Scriptはコンパイル時にC言語を生成している？ような気がしており、コメントアウトの"#"が何かしらの不具合を起こしている可能性があると思っています。(有識者の方いましたら教えていただきたいです...)

>ちなみに" / "、" _ "は大丈夫なこと確認済み

この問題の厄介なところはGitHub側では何も問題がないところです。GasHubの中だけで動作しないので気づきにくいエラーとなっていました。

終わりに
--

友人とApps scriptのプロダクトGitHubにあげようとしていたら、GAS関連のDocument少ないので問題解決に1時間要しました…。解決してよかったです…。(共に試行錯誤してくれた友人に感謝)

ちなみに単純にAPIをオンにしていないと同じエラーが出る場合もあるので参考までに。
途中参考にさせていただいた先人の方の記事を貼らせていただきます。感謝

https://qiita.com/ryotab22/items/677ab0cd1611062b8ae8
Vim で雑に公開鍵をダウンロードする

## 目的

まっさらなホストに自分の SSH 公開鍵を入れたいとき、 vCenter コンソールとかのコピペできない環境だと一旦パスワード認証を開けて ssh-copy-id とかだるいことをしないといけないので、めんどうくさい。

Vim からコマンドを呼び出すことで、直接 SSH 公開鍵をダウンロードしてファイルに差し込む方法を書く。  
これは SSH 公開鍵のダウンロードに限らずいろんなことに雑に使えると思う。  
スクリプト呼び出した結果を書きたい時とか。

## 方法

ノーマルモードで：

```
:r !コマンド
```

たとえば GitHub から鍵を取る[^github-keys]とき：

[^github-keys]: GitHub に登録している公開鍵はこんなふうに簡単に取れるのだが、意外と知らない人が多い。他の人の鍵を登録するときとかに結構重宝する。

```
:r !curl -sSL https://github.com/kino-ma.keys
```

すると以下のようにカーソルの位置にテキストが挿入される。

![Screenshot 2024-02-01 at 16.07.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508344/95031180-2068-7c48-cc89-791a8e13ec06.png)

`r` なのか `w` なのか、 `!r` なのか `r!` なのかとか毎回忘れるので、メモしておく。
QH88 HƯỚNG DẪN SOI CẦU - GIÀN ĐỀ BẤT BẠI

nhà cái QH88 hướng dẫn soi cầu và dự đoán kết quả xổ số để có cơ hội nhận được những phần thưởng hấp dẫn, cung cấp môi trường chơi cá cược an toàn, minh bạch và công bằng. Tìm hiểu chi tiết qua links bài viết sau:
https://qh883.com/soi-cau/
#qh88 #nhacaiqh88 #qh883com #linkqh88 #soi_cau #soi_cau_qh88 #lode
AWS SageMkaer Studio起動時にAccessDeniedExceptionが表示された際の対処方法

AWS SageMkaerを利用する際にSageMkaer　Studioをを立ち上げることがあるが、起動時にAccessDeniedExceptionが表示された際の対処方法を記載する。

## 事前に準備していたこと
事前にAmazonSageMakerFullAccessの権限をもつロール(ここではAmazonSageMakerFullAccess0201)を作成。
SageMaker Studioノートブックを暗号化したかったため事前にKMSでキーを作成(ここではキーの名称はkmsとした)。

## 何をしていたときに発生したか
notebookインスタンスの
AWS SageMkaerを新規で利用する際にドメインを作成するが、作成時に組織向けの設定を選択。
![スクリーンショット 2024-02-01 15.15.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278752/bc66eb7a-51ed-0d55-7142-79f548ef6cc4.png)

ぽちぽち画面を進めていき、SageMaker Studioノートブック設定時に作成しておいたキーを選択。
![スクリーンショット 2024-02-01 15.22.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278752/4d583df5-3001-00ec-6e5e-daf78b6a8f76.png)

その後、ユーザーのロールを設定する際に作成しておいたロールを選択しドメインの作成を完了させる。
![スクリーンショット 2024-02-01 15.41.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278752/da5eddfd-06f9-8d68-46b5-1861a3aa9287.png)

## どのようなエラーだったか
ドメイン作成後、SageMaker Studioを起動しようとしたところ以下のエラーが表示され、起動出来ず。
```
If you continue to experience issues, please contact Customer Service.

Details: ConfigurationError: AccessDeniedException: User: arn:aws:sts::XXXXXX:assumed-role/AmazonSageMakerFullAccess0201/studio is not authorized to perform: kms:CreateGrant on resource: arn:aws:kms:us-east-1:XXXXXX:key/XXXX because no identity-based policy allows the kms:CreateGrant action
```

## 原因
"ロール名　(ここではAmazonSageMakerFullAccess0201)" というIAMユーザーが、指定されたAWS Key Management Service (KMS) リソース上で "kms:CreateGrant" アクションを実行するための必要な権限を持っていなかった。
要するにSageMaker Studioノートブックを暗号化する設定を行っていたため、AmazonSageMakerFullAccessの権限のみでは起動することが出来なかった。

## 対処方法
IAMを表示させ、"AmazonSageMakerFullAccess0201" というロールを見つけて選択。
許可ポリシーからインラインポリシーを作成を選択し、さらにJSONを選択。
すると以下のように表示される。

![スクリーンショット 2024-02-01 15.47.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278752/ff537210-66a6-0282-ef77-83ca316a4761.png)

そこに以下のように記述して保存する。


```
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "Statement1",
			"Effect": "Allow",
			"Action": "(作成したキーの名前。ここではkms):CreateGrant",
			"Resource": "arn:aws:(作成したキーの名前。ここではkms):(リージョン名):　(AWSのアカウントID):key/XXXXXX"
		}
	]
}
```
その後改めてSageMkaer Studioを起動を試みると問題なく起動出来た。

## 最後に
SageMaker Studioノートブックを暗号化しなければこのような問題は発生しないが、暗号化したい場合はこのような対処が必要となると思われる。
【Rails】ActiveRecord::Base.transactionについて

どうもこんにちは。

今回はRailsでDB操作をする時に便利な`ActiveRecord::Base.transaction`についてメモします。

# トランザクションって何？

トランザクションをネットで検索すると、**「ここからここまでワンセット」な処理単位が「トランザクション」** というわかりやすく説明してありました。

まさにその通りです。

この考えをDBの操作でも活用しているものがRailsにおけるトランザクションです。

# 使い方

基本的に、データの登録、更新、削除する時のメソッドとして使われます。

`ActiveRecord::Base.transaction do ... end`ブロックでsaveメソッドやupdateメソッド処理の箇所を囲うようにして使用します。

```ruby
def create
    ## データを登録するためのデータを作成
    user = User.find(params[:id])
    profile = Profile.new(user_id: user.id, hobby: '野球をすること', favorite_food: 'カレーライス')
    post = Post.new(user_id: user.id, title: '自己紹介', content: '今日は野球の試合に行ってきました。')

    ## saveメソッドやupdateメソッドをtransactionブロックで囲う
    ActiveRecord::Base.transaction do
        user.save
        profile.save
        post.save
    end
    redirect_to posts_path
end
```

transactionブロックの中でエラーが発生しなければ何事もありませんが、どこかでエラーが起きたとします。

今回はPostモデルに以下のバリデーションが定義されているとして、インスタンスのtitleをnilとしましょう。

```ruby
validates :title, presence: true
```

```ruby
def create
    ## データを登録するためのデータを作成
    user = User.find(params[:id])
    profile = Profile.new(user_id: user.id, hobby: '野球をすること', favorite_food: 'カレーライス')
    ## エラーを発生させるためにtitleをnilとします
    post = Post.new(user_id: user.id, title: nil, content: '今日は野球の試合に行ってきました。')

    ## saveメソッドやupdateメソッドをtransactionブロックで囲う
    ActiveRecord::Base.transaction do
        user.save
        profile.save
        post.save
    end
    redirect_to posts_path
end
```

そうすると、`post.save`のところでエラーが発生するはずです。

transactionブロックで囲っていないと、userとprofileはデータベースに保存されるがpostが保存されないという状態になります。アプリケーションの要件によってはそれは良くない場合があります。

ただ、今回のコードではtransactionブロックで囲っているので、一度保存されたuserとprofileのデータはロールバックされ、どのデータも保存されていない状態になります。

これによってDBの整合性が保たれます。

transactionブロックを使用していると、開発も楽なのでおすすめです。

以上
PACベイズ理論のわかりやすい記事

# はじめに

機械学習の汎化誤差を分析する道具としてPACベイズ理論があります。
わたしが、わかりやすいと思った記事を共有します。

# リンク
https://ocw.nagoya-u.jp/courses/0577-%E7%B5%B1%E8%A8%88%E8%A7%A3%E6%9E%90%E7%89%B9%E8%AB%96-2016/

https://arxiv.org/abs/1901.05353

https://arxiv.org/abs/2110.11216

https://arxiv.org/abs/cs/0411099

https://speakerdeck.com/mkimura/lun-wen-shao-jie-user-friendly-introduction-to-pac-bayes

# おわりに

　統計的学習理論とPACベイズ理論の違いについてまだわかってないです。
　PACベイズ理論は、汎化誤差を調べるときに、事前分布と事後分布をKLダイバージェンスで測り、過学習してないかをみてそうです。
　統計的学習理論は、あんまりそこらへんは意識してなさそうで、より一般的な機械学習の汎化誤差を分析しているように思われます。
AtCoderのB - Pentagonを解いてみた。

# 注意
・ネタバレあり

https://atcoder.jp/contests/abc333/tasks/abc333_b

# 学んだこと
・正多角形の性質について(てか図形全般)
・正多角形の正は全ての内角と線分(辺)が等しい
Go学習２周目でのつまづいたところの気付き

## Goを1から学んでみた
この度Go言語を独学で学んで実務で使うことになりました。
チュートリアル、本、Udemyの講座で一通りGoの文法を学んでみて、１ヶ月経った後に実務で使うことになったのですが、１周目では気づかなかったけど２周目で腑に落ちて学べたことをメモします。
Go言語をやっている人には当たり前のことですが、他言語からスキルチェンジした人にとっては共感できることもあるかもしれません。

### packageはディレクトリごとに管理する
Goではファイルの先頭にpackageをまず宣言するが、それは同じディレクトリにあるものは同じpackageを使うのが慣例。

### 同じpackageにある定数や関数はそのまま使える
同じlessonというpackageに属している２つのファイル間で定数numberを共有できる。

```go:lesson.go
package lesson

const number int = 3 
```

```go:lesson_test.go
package lesson

const number2 int = number
```

ただし関数の中で宣言した場合、同じpackageや同じファイルであっても、関数の外で使うことはできない。
その場合スコープは関数の中のみとなる。

### 異なるpackageの変数や関数を使う場合はimportしてpackage名.関数名で使う
```go
import (
	"***/read"
)

read.create()
```

### 構造体の宣言は{}の中にフィールド名+スペース+型で、実体のデータは{}の中にフィールド名: 値を入れる
```go
type struct type {
    name string
    age  int
}

pome := dog　{
    name: "pochi",
    age: 9,
}
```
構造体の宣言では間はスペース、羅列する際はカンマなしで次の行。

構造体の実態は:で区切ってカンマで羅列する。フィールド名は省略可能。
一列に列記する場合は最後のカンマは不要だが、一列に一フィールドの場合最後にもカンマが必要。

当たり前のことだが、最初は混乱するので記載。

### 構造体のメソッドでもレシーバーや引数で変数名.フィールド名orメソッド名で構造体の持つフィールドやメソッドにを使える
```go
func (d dog) describe(d2 dog) string {
    return d.name + d2.dog
}
```

```go
func (d dog) get() {
    d.describe()
```

他のpackageを使う時と同じように.で使用するので混乱することがある。

### 構造体初期化のパターンの一例
```go:dog.go
type Dog struct{
    name string
}

func New(name string) *Dog {
    return &Dog{name}
}

dog := New("pochi")
```

引数で取得した値をポインタ型の構造体に入れてreturnする。

### 構造体のmap
```go
map[string]struct {
    name string
}{
    "テスト": {
        name: "犬"
    }
}

//空でも作成可能
map[string]string{}
```
テストケースを作るときによく使う形。キーの方と構造体の型を指定してキー:構造体を続けて記述する。
中身のフィールドで必要ないものは記述しなくても大丈夫。

### 型を統一したいときにインターフェースを使う
interfaceを使って異なる構造体を同じインターフェースで抽象化できる。
interfaceにはそれに属するためには持たなければならないメソッドを記述する。
そのメソッド名と引数と戻り値が同じメソッドを持つ構造体はそのインターフェースで抽象化される。

テスト作成でmockを使いたい時にinterfaceからmockを作成して、interfaceの持つメソッドの戻り値を仮の値にすることができる。まだ未定の値やそのメソッドから叩くAPIが未完成の場合、わざとエラーを起こさせてエラー系のテストをするときなどにmockを利用することがある。

interfaceをフィールドにもつ構造体をNewで生成
```go
type InterfaceLesson interface {
    Describe() string
}

func New(lesson lesson.InterfaceLesson) *Dog {
    return &Dog{
        lesson: lesson,
    }
}
```

Describe関数の戻り値を仮に設定してmockを作ることができる。
```
mock.Expect().Describe().Return("仮の戻り値")
New(mock)
```

### 変数宣言
```go
// 明示的宣言
var a int = 6
// 初期値デフォルト stringは空文字 intは0
var b string
// 暗黙的宣言
c := 8
//代入
c = 4
// 配列の宣言
array := [3]int{1,2,3}
var array2 [3]string = [3]string{abc}
```
関数の外で宣言する場合暗黙的宣言の変数は使用できない。
配列の場合値を入れる際にも型が必要。
配列の中身は他の言語だと[]で入れられるが、Goだと{}で入れることに注意。

### 定数宣言
```go
const A = "abc"
const B int = 7
```
定数は型宣言がなくても宣言できる。
配列、スライス、mapは宣言できない。
基本的には関数の外で宣言する。packageの外で使いたい場合は名前を大文字にする。

### print関数
```go
fmt.Print("a")
fmt.Fprint(w, "a")
```
APIレスポンスに書き込みたい場合はresponse writerに書き込み。
testなどでデバックしたい場合はPrintで書く。
go testコマンドで-vを使うと見ることができる。

### テスト関連
```go
r := httptest.NewRequest(http.MethodGet, "http://localhost?"+param.Encode(), nil)
```
httptestでは第二引数のURLはhostだけで良くてパスはなしでparamをつければ大丈夫。
その後に対象の関数を呼び出せばいい。
inputタグに入力した値が消去リセットできない

## はじめに
今回はJavascriptを用いてToDoアプリの作成に取り組みました。
仕様としては、inputタグにToDoを入力して「追加ボタン」をクリックすると、inputタグに入力したテキストはリセットされて、未完了のToDoに項目が追加されるといった仕様です。
ですがinputタグに入力したテキストがリセットされずに残ってしまう、といったエラーに直面しました。
ここでは実際のコードと、解決方法を記載します！

## 問題
```html
<input id="add-text" placeholder="TODOを入力">
    <button id="add-button">追加</button>
```
```js
const addButton = document.querySelector("#add-button");

const onClickAdd = () =>{
  //テキストの追加と消去
  const inputText = document.querySelector("#add-text").value;
  inputText = "";
```
上記のコードでhtmlの「追加ボタン」をクリックするとinputのvalueが空のテキスト("")に書き換わり、リセットされるという動きを想定していました。
しかしボタンをクリックしてもinputタグのvalueはリセットされませんでした。

## 解決策
```js
const addButton = document.querySelector("#add-button");

const onClickAdd = () =>{
  //テキストの追加と消去
  const inputText = document.querySelector("#add-text");
  inputText.value = "";
```
こちらのコードで解決しました。
変更した点は
`const inputText = document.querySelector("#add-text").value;`こちらのコードを
`const inputText = document.querySelector("#add-text");`こちらに変更。

`inputText = "";`こちらのコードを
`inputText.value = "";`こちらに変更しました。

変更前だとDOMを取得したのではなく、inputタグに入力されたテキストを取得しただけ。
ex)入力した値が「テスト」だとすると`inputText = "テスト";`になっている。
その後に`inputText = ""`としても「テスト」という言葉が「」空も文字になるだけで、inputのvalueは変わらない。

変更後はDOMをまず取得して`inputText.value = "";`のコードで取得したDOMのvalueにアクセスしている。

## まとめ
説明が難しかったのですが、constで要素を取得する時には、DOM操作のみで留めておこうと思いました。
Hinomi Vs Ergomeister

![Ergomeister Chair Review.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3623798/8b3118e0-a28f-c1a3-c679-12172609206b.png)

Both the Hinomi and Ergomeister chairs are designed to provide ergonomic support and comfort. The Hinomi Chair is a sleek and modern design that is made with high-quality materials, while the Ergomeister Chair is a premium ergonomic chair that is designed to provide maximum comfort and support. Both chairs have a built-in headrest that offers support for the neck and shoulders, and both chairs are contoured to provide a comfortable seating experience. The main difference between the two chairs is that the Ergomeister Chair has adjustable height, tilt, and lumbar support, while the Hinomi Chair does not. 

Experience ultimate comfort and productivity with our ergonomic chairs! Call us now at 6591093182 to place your order and transform your workspace.
Read More: https://dailygeekreviews.com/hinomi-vs-ergomeister-vs-nextchair-which-is-singapores-best-ergonomic-chair/
アナログ振幅変調（AM）


# 振幅変調とは

変調方式の一つ

送信信号は，$u(t) = ARe[\chi (s(t))e^{j2\pi f_ct}]$と表される．

送りたい信号（**ベースバンド信号**）$s(t)$が振幅に入っている．$\chi(s(t))$によって振幅変調の種類が変わる．
その信号を**搬送波**($e^{j2\pi f_ct}$)によって送信信号の周波数を$f_c$付近にしている．

# 信号の流れ

信号が変調・送信・受信・復調される図は下のイメージ

```mermaid
flowchart LR
     情報源-->情報/電気信号変換-->変調器-->送信
     受信-->復調器-->電気/情報変換-->受信者
```

# 使用する文字

$u(t)$：送信信号
$v(t)$：受信信号
$\gamma_i$：復調器に入力する信号(受信信号)の SNR
$\gamma_o$：復調器から出力された信号(受信者が受け取る信号)の SNR

SNR は信号対雑音電力比であり，以下のように表される．

```math
\begin{align}
\frac{E\left[ \left| 信号成分 \right|^2\right]}{E\left[\left|雑音成分\right|^2\right]}
\end{align}
```

## 包絡線検波を前提とした変調

### 送信信号

$\chi (s(t)) = 1 + m_a s(t)$

```math
\begin{align}
u(t) &= ARe\left[ \{1 + m_a s(t)\} cos(2\pi f_c t)\right] \\
    &= A(1 + m_a s(t))cos(2\pi f_c t)\\
\end{align}
```

### 受信信号

```math
\begin{align}
v(t) = A(1 + m_a s(t))cos(2\pi f_c t) + n(t)
\end{align}
```

### 復調器入力 SNR

```math
\begin{align}
\gamma_i &= \frac{E\left[ \left| A(1 + m_a s(t))cos(2\pi f_c t) \right|^2\right]}{E\left[\left|n(t)\right|^2\right]}\\
    &= \frac{\frac{A^2}{2}+m_a^2E\left[|s(t)|^2\right]}{N_0B}\\
    &= \frac{\frac{A^2}{2}+m_a^2E\left[|s(t)|^2\right]}{2f_mN_0}
\end{align}
```

### 復調後信号（同期検波）

```math
\begin{align}
y(t) &= [v(t)cos(2\pi f_ct)]_{LPF}\\
    &= [\{A(1+m_a s(t))cos(2\pi f_c t) + n_I(t)cos(2\pi f_ct) - n_Qsin(2\pi f_ct)\}cos(2\pi f_ct)]_{LPF}\\
    &= [A(1+m_a s(t))cos^2(2\pi f_c t) + n_I(t)cos^2(2\pi f_ct) - n_Qsin(2\pi f_ct)cos(2\pi f_ct)]_{LPF}\\
    &= \frac{A}{2}(1+m_as(t)) +\frac{n_I}{2}
\end{align}
```

:::note info
半角の公式より

```math
\begin{align}
[cos^2f_c]_{LPF} = \left[\frac{1}{2}+\frac{cos(2f_c)}{2}\right]_{LPF} = \frac{1}{2}\\
[sin(f_c)cos(f_c)]_{LPF} = \left[\frac{1}{2}sin(2f_c)\right] = 0
\end{align}
```

:::

### 復調器出力 SNR

```math
\begin{align}
\gamma_o &= \frac{E\left[ \left| \frac{A}{2}(1+m_as(t)) \right|^2\right]}{E\left[\left|\frac{1}{2}n(t)\right|^2\right]}\\
    &= \frac{\frac{A}{4}m_a^2E\left[|s(t)|^2\right]}{\frac{1}{4}N_0B}\\
    &= \frac{Am_a^2E\left[|s(t)|^2\right]}{2f_mN_0}
\end{align}
```

以下の信号でも送信信号さえ決めてしまうと同じことができる．

## DSB-SC

$\chi (s(t)) = m_a s(t)$

```math
\begin{align}
u(t) &= ARe\left[ m_a s(t) cos(2\pi f_c t)\right] \\
    &= Am_a s(t)cos(2\pi f_c t)
\end{align}
```

## SSB

$\chi (s(t)) = s(t) + js'(t)$

```math
\begin{align}
u(t) &= ARe\left[ \{s(t) + js'(t)\} cos(2\pi f_c t)\right]\\
    &= A\{s(t)cos(2\pi f_ct) - s'(t)sin(2\pi f_ct)\}
\end{align}
```

## QAM

$\chi (s(t)) = s_I(t) + js_Q(t)$

```math
\begin{align}
u(t) &= ARe\left[ \{s_I(t) + js_Q(t)\} cos(2\pi f_c t)\right]\\
    &= A\{s_I(t)cos(2\pi f_ct) - s_Q(t)sin(2\pi f_ct)\}
\end{align}
```
Red hat Linux cron

Red Hat Linuxでcronを使用してスクリプト`Foo.sh`を3分ごとに実行するには、以下の手順を実行します。

1. **Cronジョブを編集:**
   - ターミナルで `crontab -e` を実行して、cronジョブを編集します。

2. **ジョブの追加:**
   - エディタで新しい行を追加して、3分ごとに実行するジョブを設定します。

   ```bash
   */3 * * * * /path/to/Foo.sh
   ```

   - この例では、`*/3 * * * *` は3分ごとを指定しています。

3. **エディタの保存と終了:**
   - 保存してエディタを終了します。通常は `Ctrl + X` を押して、`Y` を押してから `Enter` キーを押します。

これで、`Foo.sh`スクリプトが3分ごとに実行されるようになります。必要に応じて、スクリプトのパスや実行権限に注意して設定してください。
CSSで特定の要素の兄弟要素を拾う

# 初めに
リストの要素をクリックするとis-activeクラスが付与されるが、それ以外は変わらない。
その状態で「is-activeがない状態」「is-activeがある状態のis-active」「is-activeがある状態のis-active以外」の要素デザインを切り替えねばならなかった。

# 解決策
CSSで以下のようになった。
```
ul{
    li{
        background: #FFFFFF;
        &:has( ~ .is-active),
        &.is-active ~ li{
          background: #F6F6F6;
        }
        &.is-active{
          background: #CCCCFF;
        }
    }
}
```
hasセレクタで「以下に兄弟が.is-active」と、「.is-active移行の兄弟要素」を選択することで
.is-active以前と以降を両方変えることが出来た。

# 参考
https://kasumiblog.org/css-brother/
【Git】リモートにpush後にブランチ名とコミットメッセージを変更する方法

## はじめに
この投稿は強制プッシュなど行なっていますので、特にチーム開発などをしている方は十分に注意してください。
ブランチをpushした後にブランチ名はコミットメッセージを変更したい場合が時々あり毎回忘れては調べてを繰り返していたので備忘録用にまとめます。

## ブランチ名の変更
~~~
git checkout ブランチ名を変更したいブランチ
git branch -m 新しいブランチ名
git push origin 新しいブランチ名
~~~
これでブランチ名の変更は完了です。
※正確には変更ではなくブランチ名を変更したブランチを新たにpushします。
　なので名前を変更する前のブランチも残っているので不要な場合は削除する
 　必要があります。

## コミットメッセージの変更
###### 最後のコミットメッセージを変更する場合
最後(直前)のコミットメッセージを変更する場合は簡単で
~~~
git commit --amend -m "新しいコミットメッセージ"
~~~
でコミットメッセージを変更できます。
次はpushするのですが、ここからが問題で変更した次はリモートにpushしたコミットを変更した場合は`--force`オプションを使用して強制的にpushする必要があります。
なので、pushするときは注意してください。
~~~
git push origin ブランチ名 --force
~~~

##### 最後から2番目以降のコミットメッセージを変更する場合
まずは
~~~
git rebase -i HEAD~2
~~~
で最後から2番目までのコミット情報を表示します。
`HEAD~`の後ろは表示させたいコミットに合わせて変更します。
表示させたいコミットは`git log --oneline`で探すのが楽かと思います。
`git rebase -i HEAD~2`を実行すると、
~~~
pick 1a64XXX 変更前のコミットメッセージ2
pick 8ba5XXX 変更前のコミットメッセージ1
~~~
エディタで変更したいコミットの先頭のpickをeditに変更して`:wq`で保存して閉じます。
~~~
pick 1a64XXX 変更前のコミットメッセージ2
edit 8ba5XXX 変更前のコミットメッセージ1
~~~
次にコミットメッセージを変更します
~~~
git commit --amend
~~~
エディタでeditにしたコミットの情報が表示されるので、新しいコミットメッセージに変更して`:wq`で保存してエディタを閉じます。
次にrebaseを続行します
~~~
git rebase --continue
~~~
リモートにpush済みの場合は強制プッシュが必要なので`--force`オプションをつけてpushして完了です。
~~~
git push origin ブランチ名 --force
~~~
Visual Studioでもターミナルからgitを使いたい

## TL;DR

以下のコマンドを管理者権限のPowershellで順に実行します。

```powershell
New-Item -ItemType File -Path $PROFILE -ErrorAction SilentlyContinue
```

```powershell
Add-Content -Path $PROFILE -Value 'Set-Alias -Name git -Value "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\cmd\git.exe"'
```

```powershell
Set-ExecutionPolicy RemoteSigned
```


下記で解説していきます。


## 背景
- Visual Studioに搭載されているGitの使い勝手が（個人的に）悪い
- Visual Studioにgitが入っているのに、別でGit Bashを入れたくない

→ Visual Studioにあるgitをコマンドラインで使いたい！

## Git本体の場所
Windows11に入れたVisual Studio 2022では以下のパスにありました。
```
C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\cmd\git.exe
```
これをエイリアス登録すれば良さそうです。


## エイリアス登録
これで今のセッションでgitコマンドが使えるようになります。

```powershell
Set-Alias -Name git -Value "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\cmd\git.exe"
```

毎回これを実行するのは面倒なのでプロファイル（.bash_aliasesのようなもの）に登録します。

---

- プロファイルを新たに作ります
- すでに作っていた場合エラーになりますが、`-ErrorAction SilentlyContinue` をつけることでエラーを無視できます

```powershell
New-Item -ItemType File -Path $PROFILE -ErrorAction SilentlyContinue
```

- プロファイルにSet-Aliasコマンドを追加します
```powershell
Add-Content -Path $PROFILE -Value 'Set-Alias -Name git -Value "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\cmd\git.exe"'
```

実際に書き込まれているか確認しましょう
```powershell
cat $PROFILE
```
以下のように表示されてばOKです
```powershell
Set-Alias -Name git -Value "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\cmd\git.exe"
```

- 毎回プロファイルを読まれるように実行ポリシーを変更します
```powershell
Set-ExecutionPolicy RemoteSigned
```

## Visual Studioでgitを使ってみる
- `View` -> `Terminal` または `` Ctrl + ` ``でターミナルを開きます
- このターミナルはPowershellなので、先ほど登録したエイリアスが使えるはずです


## 参考
- [[Git] Visual Studio 2019の中のGitコマンドを探せ！](https://h-sao.com/blog/2019/06/20/where-is-git-exe-on-vs2019/)
jdepp-pythonで日本語(二文節間)係り受け解析

[jdepp-python](https://pypi.org/project/jdepp/) 0.1.7がGoogle Colaboratoryに対応した、との[ご連絡をいただいた](https://zenn.dev/syoyo/articles/d642867aae9aee#comment-1457f528881db2)ので、[jagger-python](https://pypi.org/project/jagger/)とともに日本語形態素解析・[二文節間係り受け解析](http://kanji.zinbun.kyoto-u.ac.jp/~yasuoka/publications/kakariuke.html#2)に挑戦してみた。

```
!pip install jagger jdepp
!test -d model/kwdlc || curl -L https://github.com/lighttransport/jagger-python/releases/download/v0.1.0/model_kwdlc.tar.gz | tar xzf -
!test -d model/knbc || curl -L https://github.com/lighttransport/jdepp-python/releases/download/v0.1.0/knbc-mecab-jumandic-2ndpoly.tar.gz | tar xzf -
import jagger,jdepp
tagger=jagger.Jagger()
tagger.load_model("model/kwdlc/patterns")
parser=jdepp.Jdepp()
parser.load_model("model/knbc")
nlp=lambda x:parser.parse_from_postagged("\n".join(t.surface()+"\t"+t.feature() for t in tagger.tokenize(x))+"\nEOS\n")
doc=nlp("吾輩はここで始めて人間というものを見た")
print(doc)
import graphviz
graphviz.Source(jdepp.to_dot(str(doc)))
```

「吾輩はここで始めて人間というものを見た」を係り受け解析してみたところ、私(安岡孝一)の手元では以下の結果が得られた。

```
# S-ID: 1; J.DepP
* 0 6D
吾輩	名詞,普通名詞,*,*,吾輩,わがはい,代表表記:我が輩/わがはい カテゴリ:人
は	助詞,副助詞,*,*,は,は,*
* 1 2D
ここ	指示詞,名詞形態指示詞,*,*,ここ,ここ,*
で	助詞,格助詞,*,*,で,で,*
* 2 6D
始めて	動詞,*,母音動詞,タ系連用テ形,始める,はじめて,*
* 3 4D
人間	名詞,普通名詞,*,*,人間,にんげん,*
と	助詞,格助詞,*,*,と,と,*
* 4 5D
いう	動詞,*,子音動詞ワ行,基本形,いう,いう,*
* 5 6D
もの	名詞,形式名詞,*,*,もの,もの,*
を	助詞,格助詞,*,*,を,を,*
* 6 -1D
見た	動詞,*,母音動詞,タ形,見る,みた,*
EOS
```

![JDepP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428317/b40ab95d-c00d-c498-c89b-ccf4b38e8d96.png)

jdepp-pythonでは「人間という」が二文節となっている。[ja-ginza-bert-largeでは「人間という」が一文節だった](https://qiita.com/KoichiYasuoka/items/71b1044f2389c7b604d9)ので、その部分が異なっているものの、まあ、文節係り受けとしてはイイ線だと思う。この文は、CaboChaが解析できないタイプの文なので、jdepp-pythonやja-ginza-bert-largeへの移行を、ぜひ考えてほしい。
【ネットワーク】初心者のためのイーサネットの規格説明

## 概要
前回の記事はイーサネットのMDIとMDI-Xについて説明をしました。
今回はイーサネットの規格について説明していきます。

前回の記事は下記のものになります。
こちらの記事を読んでからの方が理解しやすいと思います。
是非、こちらも読んでみてください。

https://qiita.com/nakamura_slj/items/290723d137bfccfe03a1

## 対象とする読者
* ネットワークの基礎から学びたい人
* 前回の記事を読んだ人
* これからIT業界で仕事をしようと考えている人
* CCNAの資格を取ろうとしている人

## イーサネットの規格
イーサネットは、最も利用されている規格です。
元はIntel、Xerox、DECによって開発され、IEEE８０２.3委員会によって標準化されました。
イーサネットは接続やアクセス制御の方式、ケーブルの伝送速度や距離などを規定しています。
ネットワーク技術の向上に合わせ、伝送速度の速い仕様が追加されてきています。
主なイーサネットの企画の例としては下記のものになります。

※伝送速度が100Mbpsの100BASE-TXを**ファストイーサネット**と言います。
※伝送速度が1Gbpsの1000BASE-TXを**ギガビットイーサネット**と言います。

| 規格 | 伝送速度 | ケーブル | 伝送距離 |
|:--------|:----------|:----------|:----------|
|10BASE-2|10Mbps|同軸ケーブル|185メートル|
|10BASE-5|10Mbps|同軸ケーブル|500メートル|
|10BASE-T|10Mbps|UTP、STP|100メートル|
|10BASE-F|10Mbps|光ファイバ|1000メートル/2000メートル|
|100BASE-TX/T2/T4|100Mbps|UTP|100メートル|
|100BASE-F|100Mbps|光ファイバ|2000メートル/20キロメートル|
|1000BASE-T/TX|1Gbps|UTP|100メートル|
|1000BASE-SX/LX|1Gbps|光ファイバ|550メートル/5000メートル|
|1000BASE-CX|1Gbps|同軸ケーブル|25メートル|
|10GBASE-T|10Gbps|UTP|100メートル|
|10GBASE-LX4|10Gbps|光ファイバ|10キロメートル|

## LANケーブルのカテゴリ
LANに使われるUTPはカテゴリで分けられていて、カテゴリごとに対応するLANの規格が異なります。
例えば、下記のように100BASE-TXの場合はカテゴリ５以上のケーブルが利用可能となります。
LANの規格に対応するカテゴリのケーブルを選択する必要があります。

| カテゴリ | 対応する規格 |
|:--------|:----------|
|カテゴリ5e|100BASE-TX、1000BASE-T|
|カテゴリ6|1000BASE-T、1000BASE-TX|
|カテゴリ6a|10GBASE-T|
|カテゴリ7|10GBASE-T|

# 最後に
以上となります。
今回はイーサネットの規格について説明しました。
次回も何かネットワーク関連について説明しようと思います。
Incus: Ubuntu 23.10 でソースのコンパイル

こちらの指示の通りに、Ubuntu 23.10 で Build を試みました。結果は失敗です。
[How to install Incus](https://linuxcontainers.org/incus/docs/main/installing/)

cc のバージョン

```text
$ cc --version
cc (Ubuntu 13.2.0-4ubuntu3) 13.2.0
```

<ol>

<li>ソースのダウンロード</li>
incus-0.5.1.tar.xz

<p></p>
<li>解凍</li>

```bash
xz -dv incus-0.5.1.tar.xz
tar xfv  incus-0.5.1.tar
```

<li>make deps</li>

```bash
cd incus-0.5.1
make deps
```

<li>.bashrc の設定</li>

```text:$HOME/.bashrc
export CGO_CFLAGS="-I/home/uchida/tmp/feb01/incus-0.5.1/vendor/raft/include/ -I/home/uchida/tmp/feb01/incus-0.5.1/vendor/cowsql/include/"
export CGO_LDFLAGS="-L/home/uchida/tmp/feb01/incus-0.5.1/vendor/raft/.libs -L/home/uchida/tmp/feb01/incus-0.5.1/vendor/cowsql/.libs/"
export LD_LIBRARY_PATH="/home/uchida/tmp/feb01/incus-0.5.1/vendor/raft/.libs/:/home/uchida/tmp/feb01/incus-0.5.1/vendor/cowsql/.libs/"
export CGO_LDFLAGS_ALLOW="(-Wl,-wrap,pthread_create)|(-Wl,-z,now)"
```

<p></p>
<li>コンパイル</li>

```bash
make
```

```text
$ make
CC="cc" CGO_LDFLAGS_ALLOW="(-Wl,-wrap,pthread_create)|(-Wl,-z,now)" go install -v -tags "libsqlite3"  ./...
github.com/lxc/go-lxc
# github.com/lxc/go-lxc
lxc-binding.c: In function ‘go_lxc_set_timeout’:
lxc-binding.c:80:15: error: ‘struct lxc_container’ has no member named ‘set_timeout’
   80 |         if (!c->set_timeout(c, timeout))
      |               ^~
make: *** [Makefile:37: build] エラー 1
uchida@shimizu: incus-0.5.1$ pwd
/home/uchida/tmp/feb01/incus-0.5.1
```
[本番環境 | Laravel]laravel.logは削除しちゃダメ。

# 背景
https://qiita.com/minato-naka/items/ddb5f5301f9f590cdcbf

こちらをもとに初めて自分で1から本番環境を作った時の失敗談

# 結論
タイトルの通り、「laravel.logは消してはいけない」です。

# 経緯
laravel.logの過去のログが大量になったので中身だけ消したいなと思ってLaravelプロジェクト配下の以下を実行
```
rm storage/logs/laravel.log
```
その後、
```
touch storage/logs/laravel.log
```
でログ出力用ファイルを生成すればいいと思っていた。

# 事象
以後、touchで生成した出力されていたログが`storage/logs/laravel.log`に現れることはなかった
原因はちょっとわからなかった。。。

# 対策
Laravel プロジェクトをGit Cloneして1から作り直しました。。。
Ruby on Rails 環境構築 MacOS

MacOSでのRuby on Railsの環境構築(installまわりのみ)を記録用に残しておきたいと思います。
ChatGPTに聞けば一発でわかることかもしれませんが、誰かの経験を参考にしたいという方の手助けになれば幸いです。

至らない部分もある方と思いますが、その時はそっと教えていただけると励みになります！

Rubyのインストール
--
* まずはbrew入ってるのかなあと、確認
```
 brew -v
```
>version表示されたらOK



* rbenvのインストール
 
```
 brew install rbenv ruby-build
```
* インストールされたか確認

```
rbenv -v
```
>version表示されたらOK

+ rubyのインストール
```
rbenv install 3.2.0 //任意のversion
```
+ インストールされたか確認
```
ruby -v
```
>version表示されたらOK

2, bundlerのインストール
--
bundlerはRubyライブラリーの依存関係やversionを一元管理するツールになります。
ここからはgemというのを使いますので、gemが入っているかまず確認します。
```
gem -v
```
>version表示されたらOK
+ 次はbundlerをインストールします。
```
gem install bundler
```
>完了後ターミナルにversionが表示されたら成功です！

3, Railsのインストール
--
+ いよいよrailsのインストールです！
```
gem install rails （ここにversion入れてinstallも可能）
```
結構どかかーとインストールされます。ビビらないで
+ インストールされたか確認
```
rails -v
```
>version表示されたらOK

end　

>Rubyリスペクト

終わりに
--
お疲れ様です！
以上がMacOSでのRuby on Rails環境構築なります！

この後続けて開発もしてみたいと思います。
よかったらそちらもどうぞ！

参考にさせていただいた資料
--
>エラーについても書いてくださっており大変参考になりました。

https://qiita.com/kodai_0122/items/56168eaec28eb7b1b93b

>いつもお世話になっております

https://prog-8.com/docs/rails-env

>モダン開発といえばこの方の動画いつも参考にさせていただいています。

https://www.youtube.com/watch?v=CfdRXSrwLDo
「現代数理統計学の基礎」演習問題解法メモ　第5章問1～5

第5章に入りました。
極力緑文字で根拠を記載しています。
大学受験には「白とか黄とか青チャート」があって、それを繰り返し行って書き込みをしているのをYOU Tubeでみました。今回はそもそも略解又はネットにUPされているかたも頭がいいのでしょうね。途中の計算式やなぜそうなるのかがわからず、何とか「チャート」に少しは近いものを作成した段階です。しかし、これを基に繰り返し解くとなると正直気が遠くなります。
![第5章問1 P1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/a4e59b60-65e5-f769-396c-afafa9cc3177.jpeg)
![第5章問1 P2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/3ac5f256-de57-1526-2bab-fe37565425cb.jpeg)
![第5章 問2　P1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/dd0575dc-0ad0-a644-0e46-5d93c1c58309.jpeg)
![第5章問2　P2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/f6b5793c-78bf-7d32-2b1f-1936ebd9f2de.jpeg)
![第５章問2　P3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/5697967a-d291-7544-07bf-d87025ca4c0e.jpeg)
![第5章問3　P1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/89924d7e-37e5-14af-157e-47f03751253e.jpeg)
![第5章問3　P2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/53f5394e-5276-f489-808e-6e7b91d61a22.jpeg)
![第5章問3　P3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/0cb0822b-bc49-49f4-613a-54bb9ee7cc8c.jpeg)
![第5章問4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/807acc23-2eb1-47b5-3341-b50d93c15821.jpeg)
![第5章問5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/81da5eca-2533-eefc-6e35-6c3908bd3c1c.jpeg)
iPhoneの純正メッセージアプリのUIをコピーする Part1

iPhoneの純正メッセージアプリをコピーして、SwiftUIの技術力向上をしていきます。
このような状態を目指していきます。
処理は後々追加していきます。

![Simulator Screenshot - iPhone 15 Pro - 2024-02-01 at 13.23.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3638250/824c4963-04a3-cb61-66f9-ebde793ec12d.png)



ここで受信したメッセージセルのデータを定義します。

```swift
struct Message: Identifiable, Codable {
	
	var id: String
	var name: String
	var day: String
	var lastMessage: String
	
	init(id: String = "", name: String = "", day: String = "", lastMessage: String = "") {
		self.id = id
		self.name = name
		self.day = day
		self.lastMessage = lastMessage
	}
	
	var dictionary: [String:Any] {
		return ["id": id,"name": name, "day": day, "lastMessage": lastMessage]
	}
	
}

```


Messageで定義したデータを利用してセルを作成していきます。

```swift
struct MessageCell: View {
	
	@Binding var message: Message
	
	var body: some View {
		HStack {
			
			Image(systemName: "person.circle")
				.resizable()
				.aspectRatio(contentMode: .fit)
				.frame(width: 40, height: 40)
				.clipShape(Circle())
				.padding()
			VStack {
				Divider()
				HStack {
					Text(message.name)
						.frame(maxWidth: .infinity, alignment: .leading)
						.bold()
					Spacer()
					Text(message.day)
						.foregroundColor(.gray)
					Image(systemName: "chevron.right")
						.frame(width: 10, height: 10)
						.foregroundColor(.gray)
						.padding(.trailing, 15)
				}
				Text(message.lastMessage)
					
					.frame(maxWidth: .infinity, alignment: .leading)
					.foregroundColor(.gray)
					.lineLimit(2)
			}
		}
		.frame(height: 70)
	}
}
```

セルを追加した最終的なコードはこちらになります。

```swift
struct ContentView: View {
	
	@State private var list: [Message] = [Message(id: "1", name: "テスト1", day: "2024/01/01", lastMessage: "テスト"),Message(id: "2", name: "テスト2", day: "2024/01/02", lastMessage: "テスト"),Message(id: "3", name: "テスト3", day: "2024/03/02", lastMessage: "テストテス")]
	
	
	@State private var sheet = false
	@State private var searchText = ""
	
	@FocusState private var focus: Bool
	
    var body: some View {
		NavigationView {
			
			ScrollView {
				VStack {
					
					ZStack{
						TextField("検索", text: $searchText, onEditingChanged: { editing in
							
						})
						.background(.clear)
						.frame(height: 40)
						.padding(.leading, 30)
						.padding(.trailing, 30)
						
						HStack {
							Image(systemName: "magnifyingglass")
								.foregroundColor(.black)
								.frame(width: 20, height: 20)
								.padding(.leading, 5)
							Spacer()
							
							Button(action: {
								
							}) {
								Image(systemName: "mic.fill")
									.foregroundColor(.black)
									.padding(.trailing, 5)
							}
						}
					}
					.frame(height: 35)
					.background(.quinary)
					.cornerRadius(5)
					.padding()
					
					ForEach($list) { message in
						MessageCell(message: message)
					}
				}
			}
			.navigationBarTitle("メッセージ")
			.navigationBarItems(leading: Button("編集") {
				
			})
			.navigationBarItems(trailing: Button(action: {
				sheet = true
			}) {
				Image(systemName: "square.and.pencil")
			})
		}
		
		.sheet(isPresented: $sheet) {
			NewMessageView()
		}
    }
}
```
App Transport Security (ATS)制限下での安全でないhttpへの接続設定

# アップル製OSでは安全でないhttp:サイトへ接続できない

　Swiftでアプリケーションを制作していて早速つまづいた。なぜかSSL通信（https://)ではないhttpのサイトに接続できない。調べるとATSというアップル独自のセキュリティを導入しているためで、同時にその解除の方法も提供している。
　
 ただ、　アプリを申請するときにその解除の理由に正当性がないといけないらしい。現在ではログイン情報などを入力するサイトにはhttpを使用することは通例では考えられないため、仮にこうしたアプリを申請しても接続対象となるサイトさえ明示して情報漏洩の恐れがなけれ通過するのではないかと思われる。

　やはりアップルはセキュリティにかなりシビアなのだと痛感した。

# SSLでない接続をするときのXcodeでの設定

では、Xcodeでプログラムしていて実際どうやってATSを解除して接続するのだろうか？

やってみると簡単だ。文章で説明する。

 Xcode上でプロジェクトを開いた状態にする。
- 画面左側プロジェクトナビケーターのリスト最上段にあるプロジェクト名をクリックすると、右側画面に　InfoタブのあるiOSターゲットプロパティが表示される。
- infoタブをクリックすると「custom iOS target properties」が表示される。
- リストにある既存の項目を選択した状態で右クリックを押し、Add Rowを選択する。新しいリストが選択可能な状態になる。
- App Transport Security Settingsを選ぶ。

![2048 (1).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139807/25dfa39e-c9c8-5462-ec4b-730feb913c9a.jpeg)


- 追加されたApp Transport Security Settingsという項目の左側にある矢印を下にした状態で右クリックをおす（下矢印にしないと配下にRowが追加されない）。そして、Add Rowを選択。
- 再び自動で選択項目が表示される。Exception Domainsを選びエンターを押す。
- Exception Domains項目の左側矢印を下にして、右クリックしてAdd Rowを選ぶ。
- New Itemという項目が配下にできたら、http接続したいドメイン名を``http://``を抜いて入力する。　例：``http://www.example.com -> www.example.com``　ここはIPアドレスでもOKだ。
- ドメインを入力したら、エンターを押し、そのTypeをDictionaryに設定する。
- ``www.example.com``という項目ができたら左側の矢印を下に向ける。その状態で右クリックしAdd Rowを選択する。
- 配下にnew Itemができて、その名前を「NSExceptionAllowsInsecureHTTPLoads」と入力する。
- さらにNSExceptionAllowsInsecureHTTPLoadsという項目のTypeをBooleanに変更する。
- NSExceptionAllowsInsecureHTTPLoadsのValueをNo（False）からYes（True)に変更する。
- 解除が必要なドメインが複数あればException Domainsの配下に追加する。

![2048.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139807/fc05f20f-fc23-48a6-7395-b9e61d215784.jpeg)



以上の手順で任意のサイトでATS制限を解除できる。これらの設定はxml形式でinfo.plistというファイルに書き込まれる。アップルのサイトからドメインに関するATS解除設定を下記に記す。


```diff_xml
NSExceptionDomains : Dictionary {
    <domain-name-or-ip-address-string> : Dictionary {
        NSIncludesSubdomains : Boolean
        NSExceptionAllowsInsecureHTTPLoads : Boolean
        NSExceptionMinimumTLSVersion : String
        NSExceptionRequiresForwardSecrecy : Boolean
    }
}
```
QiitaとZennの人気度を比較したら面白かった

ふと、[Qiita](https://qiita.com/)と[Zenn](https://zenn.dev/)って今(2024年2月現在)どっちが良く使われているんだろう、と思い[Google Trends](https://trends.google.com/trends?geo=JP&hl=ja)でざっくり調べてみました。
イメージとしては、まだQiitaの方がユーザー数は多い印象ですがどうでしょうか。

個人的には予想外の結果があり面白かったです。

## 1. 直近1年間の比較　- Qiita強い

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260154/8dd5a7fd-81c2-83c5-2262-53c18afeccb4.png)
([Google Trendsで見る](https://trends.google.com/trends/explore?geo=JP&q=zenn,qiita&hl=ja))

Qiitaの人気度が平均して75付近であるのに対しZennは25付近なので、**Qiitaの方が3倍くらい多く検索されている**、といったところでしょうか。
感覚的にはもう少しZennがZenn戦している印象でした。

長期連休のあるゴールデンウイークや年末年始は両サービスとも検索数が落ち込んでおり、職業エンジニアの利用が多いことが分かりますね。

## 2. 直近5年間の比較　- Zennの成長

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260154/10b3a568-2916-97d3-3d1e-cc94ada6f727.png)

Zennのサービス開始時期が2020年9月なので、そこにZennの最初のピークが見られます。その後はZennが徐々に検索数を伸ばしていますが、直近1年で見るとほぼ横ばいでした。

Qiitaもここ数年、検索数では頭打ち感があります。

## 3. 利用地域の比較　- まさかの格差

![qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260154/fea1bd17-6138-4249-96f6-fb9884f18a07.png)

![zenn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260154/6c76393d-f11e-45ec-519e-0fceec0702aa.png)

・・・・・！！！！
Qiitaが全国的にほぼ満遍なく利用されているのに対し、**Zennは都市部に比べ地方ではあまり利用されていない**[^1]ことが分かりました！面白い！

IT企業が集中する都市部とZennの利用地域が一致していることから、Zennではサイト利用者のうち職業エンジニアの占める割合がQiitaよりも多くなっており、地方での利用率が相対的に下がっているということなのかもしれません。

この仮定が正しいとして、ユーザー構成の違いはどこから来るのでしょうか。
1つは有料コンテンツの有無が影響していそうです。Zennでは本(Book)といった課金コンテンツを販売・購入する仕組みがあるため、この点においては学生や趣味プログラマーよりも、職業エンジニア(社会人)との相性が良さそうです。
他には・・・

## 4. おわりに

今回はGoogle Trendsを使用してQiitaとZennの人気度を比較してみました。Google Trendsで比較できるのはあくまで「そのキーワードでの検索数」であり、人気度を示す1指標でしかないことにはご留意ください。

QiitaにしろZennにしろ、エンジニアにとっての情報共有の場がより一層盛り上がっていくことを期待しています。

[^1]: 少し正確には、都市部での検索数と地方での検索数の格差がQiitaよりも大きく、地方の検索インタレストが十分なデータなしになっている
【Rails】buildメソッド結構有能かもしれない

どうもこんにちは。

今回はRailsで使いこなすと楽そうな`build`メソッドについて調べました。

# buildメソッドとは？

`build`メソッドは`new`メソッドにかなり似たメソッドです。
ただし、場合によって、`new`メソッドを使用するより`build`メソッドを使用することでコードの簡略化ができます。

# newメソッドとの違い

## newメソッド

- Active Recordモデルの新しいインスタンスを作成する
- モデルクラス自体に対して直接呼び出される

```ruby
new_post = Post.new
```

- 関連付けを意識せずに単独でオブジェクトを作成する場合に使用される

## buildメソッド

- `has_many`、`has_one`、`belongs_to`などの関連付けが定義されている場合に使用される
- 関連付けられたオブジェクトの新しいインスタンスを作成し、そのインスタンスを親オブジェクトに自動的に紐付ける
- 関連付けを表すメソッドチェーンの一部として使用される

```ruby
user = User.find(1)
new_post = user.posts.build(title: '新しい投稿', content: '投稿の内容')
```

特定の関連付けのコンテキスト内で新しいモデルインスタンスを作成し、そのインスタンスを自動的に関連付けるために使用されます。

# 使用する場面

`build`メソッドを使用する場面は以下の条件が揃っている時です。

- モデル同士を`has_many`、`has_one`、`belongs_to`などでアソシエーション（関連づけ）を設定しているとき
- アソシエーションされた状態で新しいインスタンスを作成したいとき

# 使用方法

## has_manyで関連付けしているオブジェクトのインスタンスを作成する

以下のように関連付けが定義されているとします。

```ruby
class User < ApplicationRecord
  has_many :posts
end
```

IDが3のユーザーに紐づいたPostインスタンスを作成するには、以下のようにコードを記述します。

```ruby
user = User.find(3)
post = user.posts.build

# newメソッドを使用するとこんな感じ
user = User.find(3)
post = Post.new(user_id: user.id)
```

これで、Postインスタンスの`user_id`カラムには`3`と入っているはずです。

## has_oneで関連付けしているオブジェクトのインスタンスを作成する

以下のように関連付けが定義されているとします。

```ruby
class User < ApplicationRecord
  has_one :profile
end
```

`has_one`で関連付けされている場合には、**メソッド名が異なります**。

IDが4のユーザーに紐づいたPostインスタンスを作成するには、以下のようにコードを記述します。

```ruby
user = User.find(4)
user_profile = user.build_profile

# newメソッドを使用するとこんな感じ
user = User.find(4)
user_profile = Profile.new(user_id: user.id)
```

これで、Postインスタンスの`user_id`カラムには`4`と入っているはずです。

# まとめ

`belongs_to`で関連付けされているオブジェクトに紐づけてインスタンスを作成する方法もありますが、汎用性は高くないのでここでは紹介しないこととします。

`han_one`,`has_many`で関連付けしているオブジェクトのインスタンスを作成するには`build`メソッドを使えば、ぱっと見で「何と紐づいているのかな？」っていうのがわかりそうですね。
キャンバスアプリでDataverseの関連レコードを一緒に保存する処理

今回は、キャンバスアプリでDataverseの関連レコードを一緒に保存する処理について書きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/c6c2c50d-9dd6-b06f-0090-342b7cc8d62b.png)



一般的なキャンバスアプリでのリレーションの取り扱いについては以下をご参照下さい。

https://qiita.com/skuramoto/items/b26db9a5dbe7c88e9740

この記事の[関連レコードを含めたデータの登録方法](https://qiita.com/skuramoto/items/b26db9a5dbe7c88e9740#%E9%96%A2%E9%80%A3%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E5%90%AB%E3%82%81%E3%81%9F%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E7%99%BB%E9%8C%B2%E6%96%B9%E6%B3%95
)のセクションの応用です。

親テーブルのレコードを先に保存して、そのレコードに紐づいた子レコードの登録を同時に行うときには以下のような処理を書きます。
変数「myRecord」に親テーブルのGUIDを保存しています。
そのGUIDを子レコードのリレーションを保存する検索列に保存することで、紐付けをすることができます。

::: note
以下は、説明上一般的な値にしているので、それぞれテーブル名や列名などはご自身の値に設定して下さい。
:::

```
//親レコードの新規追加
UpdateContext({myRecord: Patch(親テーブル, Defaults(親テーブル), 
{
    列１:値１
    ,列２:値２
}
)}
);

//子レコードの新規追加
ForAll(子レコードのアイテム,
    Patch(子テーブル, Defaults(子テーブル),
    {
        列１:値１
        ,列２:値２
        ,親テーブルとリレーションを組んだ検索列:myRecord
        }
        )
)
;

```

私の生のコードも置いておきます。ご参考までに
私はAI Builderの領収書処理モデルで読み取ったアイテムを子テーブルに分けて、領収書テーブルの１レコードに紐づける処理をしています。

```
UpdateContext({myRecord: Patch(領収書処理_1, Defaults(領収書処理_1), 
{
    業者名:MerchantNameResult.Text
    ,業者住所:MerchantAddressResult.Text
    ,業者電話番号:MerchantPhoneResult.Text
    ,日付:TransactionDateResult.Text
    ,小計:SubtotalResult.Text
    ,税額:TaxResult.Text
    ,合計:TotalResult.Text
}
)}
);

ForAll(ReceiptProcessor1.PurchasedItems,
    Patch(領収書アイテムテーブル, Defaults(領収書アイテムテーブル),
    {
        アイテム名:Name
        ,価格:Price
        ,数量:Quantity
        ,合計金額:TotalPrice
        ,領収書処理テーブル:myRecord
        }
        )
)
;

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/71723064-38aa-5341-ffe9-0c62a6e2807e.png)
reactの学びなおし

# はじめに
reactで個人開発をしてるのですが、結構なあなあで開発してる部分も多く、型定義などもしっかりやれていませんでした。
個人開発してるものについては、動くレベルにはなってるので、一度横に置いてreactを学びなおそうとしています。
この記事は、その備忘録になります

# 環境構築
## vscodeの設定
```shell:コマンド
mkdir .vscode
touch .vscode/extensions.json
touch .vscode/settings.json
```

```shell:extensions.json
{
  "recommendations": [
    // jsのlinst
    "dbaeumer.vscode-eslint",
    // cssのlint
    "stylelint.vscode-stylelint",
    // コードの自動整形ツール
    "esbenp.prettier-vscode",
    // コード補完
    "VisualStudioExptTeam.vscodeintellicode",
    // インポートのパスを自動補完
    "christian-kohler.path-intellisense",
    // インデントを視認しやすく（好みで）
    "oderwat.indent-rainbow",
    // HTMLの開きタグ閉じタグを連動修正
    "formulahendry.auto-rename-tag",
    // エクスプローラーのアイコン設定
    "vscode-icons-team.vscode-icons",
    // jsonをtypeScriptのインターフェースに変換してくれる
    "MariusAlchimavicius.json-to-ts",
    // モジュールのコストを表示
    "wix.vscode-import-cost"
  ]
}
```
```shell:settings.json
{
  ////////////////////////////////////////////////////////////////
  // editor設定
  ////////////////////////////////////////////////////////////////
  "editor.formatOnSave": true,
  "editor.tabSize": 2,
  "editor.renderWhitespace": "all",
  "editor.fontSize": 14,
  "editor.fontFamily": "ＭＳ ゴシック",
  "editor.renderLineHighlight": "all",
  "editor.rulers": [40, 80, 120],
  "editor.bracketPairColorization.enabled": true,
  "files.trimFinalNewlines": true,
  "files.trimTrailingWhitespace": true,
  "files.encoding": "utf8",
  "terminal.integrated.fontFamily": "MS Gothic",
  "git.autofetch": true,
  "workbench.tree.indent": 15,
  // ココから拡張機能
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}

```

## nodeの設定
前回のrubyの時と同様にasdfでインストールします

asdfのインストールについては以下を参照

https://zenn.dev/youfuku/articles/a8177d420db979

プラグインにてnodejsを追加
```
asdf plugin add nodejs
```

バージョン確認
```
asdf list all nodejs
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632357/b73d9cc3-4b53-1771-a8ea-476c08e82fd1.png)

21.6.1が最新のようなので、これをインストールします
```
asdf install nodejs 21.6.1
```

ローカルとグローバルのnodejsも同じバージョンにしておきます
```
asdf local nodejs 21.6.1
asdf global nodejs 21.6.1
```

yarnなどもついでにインストール
```
npm install -g yarn typescript ts-node typesync npm-check-updates
```

## reactの環境構築
```
yarn create vite hello-world --template=react-ts
```

## 環境立ち上げ
```
cd hello-world
yarn install
yarn dev
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632357/0a3be1fb-f756-c08a-346f-186fe98d930f.png)


## さいごに
今回は環境設定および環境構築なので簡単な作業でした。
備忘録なので真新しい情報はないですが、自分がやった証拠として記載しました。
これを元に再学習開始！