OmniAICreator/Qiita-1.07M huggingface dataset:
カメラでリアルタイム物体検知システムの作成

# github
https://github.com/Go21032/object_detection_golib

# 背景
物体検知をカメラでやりたくて、GoogleColabでコード書いて実行しました
# 前準備
1. 自分のGoogleDriveにアクセスし、機械学習用のフォルダを作成
2. 機械学習用のフォルダの中に、学習させる元の写真データフォルダを作成（例：僕の場合「切り抜き」という名前でフォルダを作成）
3. このgithubにあるコード3つすべてを機械学習用のフォルダの中にアップロードする
4. フォルダの構造が以下のようになればよし！（**注意:**この時「Hasu_data_verjpg」と「ReSizeAfter」というフォルダが無くて大丈夫。リサイズ.ipynbで自動的に作成するフォルダなので、手動で作成しないこと）
![スクリーンショット (1940)](https://github.com/Go21032/object_detection_golib/assets/88703525/1edcbccd-94e6-4173-abe0-49dceb546ad4)

# 全体における使い方
基本全て上から順にコードを実行していきましょう！

# リサイズ.ipynbの使い方
## HEICからJPGへ
上から４つ目のコードは、HEICからJPGに変換するコードなので、iPhoneで写真を撮った場合のみこのコードを実行する。  
最初からJPGなら実行する必要はない。
この時、34行目  
`input_folder = '/content/drive/MyDrive/蓮ノ空CD機械学習/切り抜き'`  
のinput_folderのパスで学習データが入っているフォルダのパスを入力。  
パスはGoogleColabo内のファイルというところでフォルダを右クリックするとパスがコピーできるのでそれをペーストすると楽  
36行目`output_folder = '/content/drive/MyDrive/蓮ノ空CD機械学習/Hasu_data_verjpg'`  
のフォルダ作成するフォルダの名前は自分の好きなように変更していいですよ

## JPG画像のリサイズ
一番最後のコードが画像を小さくするコードです。  
35行目`new_size = (320, 320)  # 幅と高さを指定`の所でサイズを調整する。  
**元からJPGで学習フォルダを作った場合やフォルダ名を変えた人**は、  
31行目`input_folder = '/content/drive/MyDrive/蓮ノ空CD機械学習/Hasu_data_verjpg'`  
のパスを正しく指定する。

# モデル作成.ipynb
## 上から4個目のコード
変更すべき場所は16行目`source_dir = "/content/drive/MyDrive/蓮ノ空CD機械学習/Hasu_data_verjpg"`と  
28行目`os.makedirs("%s/HoliHoli" % train_dir)`から下すべて  
**train_dirが学習用フォルダでvalid_dirがテスト（評価）フォルダです**  
28から31行目までが、学習用フォルダの分類分けで、画像処理した時それが何かを示すための**ラベル付け**のようなもの

## 上から5個めのコード
ラベル付けし名前の所を自分のやつに変更

## 上から9個目のコード
前処理のコードになります。  
基本的に変更すべきところは、5,7,10行目  
**バッチサイズは2の３乗で決めます。値として32がいいらしい**

## 上から15個目のコード
学習モデルの構築コード！  
変更すべき所は、4,6,8行目  
**学習率は根性で見つける**  
**バッチサイズは前処理で指定した数値と同じにしましょう**  
**エポック数は経験から150~200。これは後々でるlossグラフから過学習しているかを判断し、過学習の場合エポック数を下げるといいでしょう**  

## 上から16個目のコード
変更すべきは5,6,10行目  
Conv2Dの第一引数がフィルターの数で、Denseがユニット数

## 上から18個目のコード
モデル１(畳み込み層とプーリング層が一回)で指定した数値と同じにする

## 学習結果の可視化から始まるグラフが出るコード
これは誤差を出すグラフで以下のようにギザギザの振幅がでかいと過学習と言える。0に近似すると誤差が少ないという事なのでいいモデルと言える。
![学習結果の可視化](https://github.com/Go21032/object_detection_golib/assets/88703525/7db21856-8d86-4de4-81ed-883093e558f9)

## acc（精度）を確認する．から始まるコード
これは精度のグラフで1に近似するほど良いモデル。  
振幅が大きい場合は、先ほど紹介した上から9個目のコード以降の数値を変更すると良くなる。

## Google Driveに最適なKerasのモデルを保存，「my_janken_best_model.h5」ファイル名の変更が可能から始まるコード
モデルの名前は何でもいいけど拡張子は「h5」にしないとだめです

## 一番最後のコード
変更すべきところ、28,50,52,54行目  
自分のモデル名とラベル名に変更

# カメラでテスト.ipynbの使い方
## AIモデルファイルを自分のDriveからGoogle Driveからコピーするで始まるコード
3行目の所はモデルのパスをコピーすること

## 最適モデルは自分が作ったモデルまたはVGG16_model_4の場合，これを実行：で始まるコード
自身のモデル名にすること

## 最適モデルはEfficientNetモデルより作ったものの場合，これを実行：で始まるコード
自身のモデル名にすること

## 処理を行うコールバック関数を定義で始まるコード
18行目`img_w, img_h = 192, 192`は学習モデルと同じサイズにすること  
35行目以降  
`  if prelabel == 0: #if,elifの部分は具体的な問題に対して変更
    label='HoliHoli'
  elif prelabel == 1:
    label='Kabe'
  elif prelabel == 2:
    label='Natumeki'
  elif prelabel == 3:
    label='lttf'`
の所も自身のラベルに変更すること

## Webカメラを使うJavascriptのコード（標準コード）で始まるコード
19行目の`display_size = 540`は自身のPCに合わせて変更するといいでしょう。

# 実行したらこんな感じ
丸とか×とかは動画編集したものなので普通は出ない。
![無題の動画 ‐ Clipchampで作成.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771189/21b51b62-5d3b-02db-a905-dba0e2dfb070.gif)
Rustの環境構築とHelloWorld

### Rustのインストール

公式サイトからRustをインストールしてexeを実行するとすぐできます。

https://www.rust-lang.org/ja/learn/get-started

### Rustのプログラム作成

好きなテキストエディタで以下のプログラムを作成し、「main.rs」というファイル名で保存します。

```
fn main(){
	print!("Hello,World");
}
```

### Rustのコンパイル、実行

コマンドプロンプトでプログラムファイルを保存したディレクトリまで移動し、以下のコマンドでコンパイル、実行する

```
rustc main.rs
```

```
main.exe
```

### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533750/ba51624c-85ac-cc87-b830-cebe493491f0.png)

「Hello,World」が出力されました。
robloxでassistant その101

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
触ると、Healthが減るパーツを作れ。

# 手順
- ReplicatedFirstに、LocalScriptを追加。
- スクリプトを書く。
```
local part = Instance.new("Part", workspace)
part.Position = Vector3.new(0, 1, -10)
part.Touched:Connect(function(hit)
	local humanoid = hit.Parent:FindFirstChildWhichIsA("Humanoid")
	if humanoid then
		humanoid.Health -= 1
		print("okk")
		Label.Text = humanoid.Health
	end
end)
```

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/4b0a1f3a-7f4e-ae71-cc66-7ad809e03f87.png)


以上。
robloxでassistant その100

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
Healthを表示せよ。


# 手順
- ReplicatedFirstに、LocalScriptを追加。
- スクリプトを書く。

```
local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local character = game:GetService("Players").LocalPlayer.Character or game:GetService("Players").LocalPlayer.CharacterAdded:Wait()
local hrp = character:WaitForChild("HumanoidRootPart")
local humanoid = character:FindFirstChildOfClass("Humanoid")
if humanoid then
	print("ok")
end
local PlayerGui = Player:WaitForChild("PlayerGui")
local Gui = Instance.new("ScreenGui")
Gui.Parent = PlayerGui
local Frame = Instance.new("Frame")
Frame.AnchorPoint = Vector2.new(0.5, 0.5)
Frame.Position = UDim2.new(0.5, 0, 0.2, 0)
Frame.Parent = Gui
local Label = Instance.new("TextLabel")
Label.Text = humanoid.Health
Label.TextSize = 100
Label.Parent = Frame
```



# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/ef1f8024-3070-213a-2052-6a1716f4b33c.png)


以上。
Playwright で window.alert ( メッセージ ダイアログ )をのメッセージ内容を検証する

Expect message and comfirm dialog


# Good

```js
  page.on('dialog', async (dialog) => {
    expect(dialog.message()).toContain('Expected Message')
    await dialog.accept()
  })
```

# BAD

No Async / Await

```js
  page.on('dialog', (dialog) => {
    expect(dialog.message()).toContain('Expected Message')
    dialog.accept()
  })
```

# Ref

https://playwright.dev/docs/dialogs
curl コマンドで レスポンス内容の標準出力を捨てる 

# 例

```
curl http://example.com 1>/dev/null
```


# 結果の例

OKの場合

```
curl http://example.com 1>/dev/null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1256  100  1256    0     0   3732      0 --:--:-- --:--:-- --:--:--  3783
```

エラー発生時

```
curl http://xxxxxxcsadgadsgdagdaga.com 1>/dev/null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0curl: (6) Could not resolve host: xxxxxxcsadgadsgdagdaga.com
```

# --slinet

`--silent` と組み合わせると何も出力されなくなってしまう

```
curl --silent http://example.com 1>/dev/null
```

```
curl --silent http://xxxxxxcsadgadsgdagdaga.com 1>/dev/null
```


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# プロフィール・経歴

https://github.com/YumaInaura/YumaInaura
is や not などは値の計算には使わない

## TL;DR

- `is` や、`is not` はオブジェクトの同一性を判定するための演算子(Identity operator, 同一性演算子)
- 同一性演算子は数値計算には使わないほうがよい

## 事例

とあるPythonコード

```python
a = 255
b = 1
a + b is a + b
True
b = 2
a + b is a + b
False
```

### ポイント

- 数は違うがどちらも同じ値を比較している
- `is` を使用している
- なぜか２回目の比較ではFalseになる

### なぜなのか

- `is` や、`is not` は同一性演算子(Identity operator)とよばれ、値ではなく更に厳密にオブジェクトが同じかを判定する
- 数を足したり引いたりしたものを比較する際にも、Pythonでは新たにオブジェクトが作成される
  - Pythonでは、すべてのリテラル(数値や文字列)に対してオブジェクトが作成される
  - ***ただし1回目の比較では、Pythonが用意したオブジェクトプールの値が使用されているため結果がTrueとなる***

### オブジェクトプールとは

- 頻繁に使われる値を持つオブジェクトを、再利用する思想
- Pythonが用意したオブジェクトプールとは
  - メモリにもともと用意されているオブジェクト ( intは-5から256 )

公式doc:

https://docs.python.org/ja/3/c-api/long.html#c.PyLong_FromLong

### オブジェクトプールを踏まえた挙動

**1回目の比較**

- 256以下のオブジェクトを比較しているためプールのオブジェクトが使用されている、同じオブジェクトを比較しているため True

**2回目の比較**

- 新たにオブジェクトが作成され、別々のオブジェクトが比較されているため False

また新たに定義したオブジェクトを自動的にプーリングしてくれるインターンという仕組みもあります

参考記事:

https://qiita.com/kahibella/items/cd8b48f1d2c109b76e10

公式doc:

https://docs.python.org/ja/3/c-api/long.html#c.PyLong_FromLong

## 結論

- こういった事柄もあるため、 `is` や、`is not` などは値の計算に使わず、== や != を使って計算する
- オブジェクト指向プログラミングではオブジェクトを比較するのか、値を比較しているのかを意識する( 等値と等価なんて言われる: [Javaの等価と等値](https://tech.noricgeographic.com/%E3%80%90%E8%AA%A4%E8%A7%A3%E3%81%95%E3%82%8C%E3%82%84%E3%81%99%E3%81%84%E3%80%91java%E3%81%AE%E7%AD%89%E4%BE%A1%E6%AF%94%E8%BC%83%E3%81%A8%E7%AD%89%E5%80%A4%E6%AF%94%E8%BC%83%E3%81%AE%E9%81%95/) )
Reactのvideo埋め込みでつまづいた話と解決策

## 結論 ...！
htmlでは動画を埋め込む際に
```
<video src="hogehoge" muted autoplay loop ...></video>
```
のようにプロパティを指定するが、Reactの場合はこれらをキャメルケースで指定すること！
```
<video src="hogehoge" muted autoPlay loop playsInline ...></video>
```
## 終わりに ...
いい加減こんなところでつまづくのはやめにしたいですが...どこかの初心者の方のおお役に立てれば...
[rails7]背景画像が表示されない件

## 目的
rails7でwebアプリを作成している途中で、トップページに背景画像を挿入する際に何をやっても挿入されない事態に陥りました。
その問題の解決記事も少なく少しハマったので備忘録として残したいと思います。

#### 対象者
rails7で背景画像を設定したいけどうまくいかない人

## 開発環境
- Rails 7.0.4.3
- ruby 3.1.2
- bootstrap 5.3.3

## 問題
まず背景画像を表示する際にHTMLとCSSを下のように設定しました。

```top.html
<div class="container-fluid background-image">
    本文
</div>
```

```top.scss
background-image{
  background-image: image-url('app/assets/images/background.jpg');
}
```

これで表示されると思いきや、全く表示されず。画像の欠片も表示されず。
「まぁHTMLとCSS書くの久しぶりやし、設定が間違っているっしょ。調べれば余裕っしょ」と、たかを括っていました。

とりあえずググると下の記事が出てきたので全て試しました。

https://qiita.com/mihooo24/items/f34ed3f4a63569cdbec3

しかし、、、表示されず。。。最初にやった時と同じく画像の欠片も表示されませんでした。
そして泥沼戦へ、、、割とハマりました

上の記事を試しても表示されないよという人がいたら次の解決方法を試してみてください。

## 解決方法
```top.scss
background-image{
  background-image: image-url('app/assets/images/background.jpg');
}

#上のコードを下のように修正

background-image{
  background-image: url('background.jpg');
}

#6月21日追記
#シングルクォーテーションが入っていると本番環境で画像が表示されませんでした
#下のように直してください

background-image{
  background-image: url(background.jpg);
}

```

クォーテーションはいらなかったよ
これで無事映るようになったよ

解決できた記事

https://ja.stackoverflow.com/questions/89355/rails7-scss%E3%81%AB%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E6%9B%B8%E3%81%84%E3%81%A6%E3%82%82background-image%E3%81%8C%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%81%BE%E3%81%9B%E3%82%93

補足説明や他の方法でも映るよという方がいたらコメントください
OAuthってなんて読むの？

# OAuthってなんて読むの？
「オーオース」らしい。

# OAuthって何？
こんな状況を考える。
>- A君がGoogleCalendarで予定を管理している。
>- あるアプリBは、GoogleCalendar APIを使い、GoogleCalendarにあるA君の予定を取得したい。
>- しかし、A君の許可なく勝手にGoogleCalendarから予定を取得することはできないので、A君に許可をもらいたい。

このような状況で、
「A君が、アプリBに対し、「GoogleCalendar上の僕の予定を引っ張っていいよ」と許可をする」
標準的な方法がOAuthらしい。

# 最後に
図とか使ってもう少し詳しく書きたかったけど、もう眠いので今度にする。

参考文献：[Web API: The Good Parts](https://www.oreilly.co.jp/books/9784873116860/)
厳密な C++ 用語

C++ の説明でしばしば登場する用語ながら言語仕様上は使われていなかったり、違う意味で使われがちな用語をまとめてみることにした。 とりあえずぱっと思いつくものを挙げているがこれから追加することもあるかもしれない。

あくまでも言語仕様内の表現を尊重するならばというものであって、必ずしもこれらの用語を使うのが誤っているという主張ではないことはお断りしておく。 文脈で理解できるカジュアルな場面で慣例として定着しているものもある。

詳しい言語仕様を調べるときは正確な用語を使ったほうが資料を見つけやすいということはありうるので知っておくのが望ましいだろうという程度のものだ。

# STL (Standard Template Library)

C++ の言語仕様の中に STL という言葉はない。 元々はアレクサンドル・ステパノフが作ったライブラリが STL と名乗っていて、その一部が C++ の言語仕様に取り入れられたという経緯がある。

厳密に言えばステパノフのライブラリ、または言語仕様内でそれに由来する範囲を STL と呼ぶのが妥当そうに思うが、別の起源を持つ `iostream` や `string` なども含めて STL と呼んでいる例も多く、何を指して STL と呼ぶかは明瞭な定義はない。

# 構造体

C++ に構造体はない。

ただし、クラスが条件を満たすことで特殊な性質が保証されるようになる場合があり、 C の構造体に近い性質を持つこともある。

C++ が C と連携する必要性から言語仕様が上手く辻褄合わせがされていること、 C ユーザ向けの C++ 解説だと C の仕様を起点にすることが多いといった事情から混乱が起こりがちなように思われる。

# 宣言と定義

しばしば宣言と定義を分けて説明している資料があるが、言語仕様上では定義は宣言の一種として規定されている。 逆に言えば定義は常に宣言でもあり、宣言としての機能を持つ。

「定義ではない宣言」について説明するときにいちいちそう書くことが煩わしいことから宣言と定義を分けて説明する慣例になっているものと思われる。

# ヘッダファイル

言語仕様上はヘッダファイルという用語は使われない。 一貫してヘッダ (header) と呼んでいる。

ヘッダが必ずしもソースファイルであるとは限らず、 `#include` に指定するのがファイル名であるとも限らない (名前に対応づいたなんらかの内容を持つものであればよい) ということが注釈に書かれており、ファイルであると決めつけるのを避けたものと思われる。

# メソッド、メンバ変数

C++ においてはメソッドという用語は用いられず、メンバ関数が正式である。 メンバ変数という用語もそこそこ定着しているが正式にはデータメンバである。

# インスタンス

C++ の言語仕様上の用語としてのインスタンスは関数テンプレートから作られる関数、クラステンプレートから作られるクラスやそのメンバ関数のことである。 プログラミング用語一般ではある型に対応するオブジェクトのことをインスタンスと呼ぶことがあるが C++ の言語仕様ではそのような言い回しをしていない。

C++ ではメモリ上を占めるデータの塊 (ビットパターン) をオブジェクトといい、それを型で解釈したものを値 (value) と呼ぶ。 オブジェクトが構築されたときの lvalue の型を「有効型」と称し、オブジェクトを値として解釈するときの扱いに制限が加えられている。 いわゆる Aliasing Rule だ。

C++ の世界観ではビットパターンを記憶するメモリが広がっていてそれの読み書きをすることで計算をする形になっている。 抽象度の高い概念もこの世界観の上に立脚して体系づけられているので言語仕様の細部を理解しようとするとメモリを意識することになる。

# テンプレート関数、テンプレートクラス

公式な用語は関数テンプレート、クラステンプレートである。

関数テンプレートは関数ではなく、クラステンプレートはクラスではない。 関数・クラスを**生成する (instantiation) 元**になるテンプレートだからテンプレートと名前が付いているという前提をわかっていれば用語の妥当性に納得しやすいだろう。

# 万能参照

参照が文脈によって右辺値参照か左辺値参照かが自動的に選択されることがあり、これが万能参照と呼ばれている。

言語機能の組み合わせによって結果的に起こることだということもあり、元々は直接的にこれを指す用語が言語仕様の中に無かった。 スコット・メイヤーズが著書の中で万能参照と呼んだことで万能参照という用語が定着したという経緯がある。

C++17 で転送参照 (Forwarding Reference) という用語が正式名称として与えられた。

# 条件式

C++ 用語では演算子 `?:` を使った式を条件式という。

`for` や `while` などで継続条件の部分に書く式を条件式と呼ぶのは誤りで、それらは単に条件 (the condition) と呼ばれている。 C ではこの継続条件の式に制御式 (controlling expression) という用語を使っているが C++ では用語を変えたようだ。

# 返り値・戻り値

関数から返ってくる値 (return value) のことを**返り値**や**戻り値**と呼ぶことがあるが、 JIS では**返却値**という訳語をあてている。

# 完全式

full expression の訳語として完全式という用語も定着しているが JIS の訳語では完結式となっている。

# オーバーフロー

以下のコードでは `unsigned char` で表現できる範囲より大きい値である `266` を入れているために結果は `10` に変わっている。 (`char` の大きさが 8 ビットではない場合は異なる結果になる可能性もあるが現代ではほぼ考えなくてよいので脇に置くことにする。)

```cpp
#include <cassert>

int main(void) {
    unsigned char foo = 266;
    assert(foo == 10);
}
```

この挙動のことがオーバーフローとして説明されることがよくあるのだが、言語仕様上は「オーバーフローしない」と明記されている場合に当てはまる。

整数を型変換した結果として変換後の型の表現範囲に収まらない場合、そして変換後の型が符号なし整数型である場合には変換後の型の最大値に 1 を足した値で mod を取った値に調整される規則がある。

つまり、 C++ の考え方ではオーバーフローした結果として値が化けたのではなく、値がオーバーフローしない範囲に調整されるということになっている。

# キャスト

C++ の仕様書中の用語の使い方ではキャストとは明示的な型変換 (をする**記法**) のことを指しているようで、型変換の同義語というわけではないようです。

# グローバル変数

C++ の規格の中でグローバル変数という言葉はほんの数か所だけ使われているが、思わぬときに書き換えられる可能性があるものという意味合いで使われており、文法規則上の定義はない。
Pythonで入力値に記号が含まれるかチェックする

# はじめに
pythonで空文字と記号が入力値に含まれているかをチェックし、それらをはじけるバリデーションを設けたい事がありました。本記事はその内容を備忘録形式でまとめたものになります。

# 環境
- Python 3.12.2


# ソース
詳細はコメントで記載している通りです。

```python:main.py
import re

# 入力値に記号が含まれているかを正規表現でチェック
def check_for_symbols(input_value):
    # 入力値が空だった場合
    if not input_value:
        return False

    # 全角と半角の記号を含む正規表現パターン
    pattern = r'[!-\/:-@\[-`{-~、-〜「」【】『』（）〔〕［］｛｝〈〉《》＊？．，。・：；％！＃＠＆＜＞＼｜￥＄＾＊＋〜]'

    if re.search(pattern, input_value):
        # 記号が見つかった場合
        return False
    # 記号が見つからなかった場合
    return True

# 仮の入力値
input_value = "これはサンプルテキストです"

# 実行
if check_for_symbols(input_value):
    print("すべての入力値に記号は含まれていません。")
else:
    print(f"入力値が空かもしくは '{input_value}' に記号が含まれます。")
```

### ◆正規表現

`re.search` メソッドを使用し、入力値にこのパターンにマッチする文字が含まれているかどうかをチェックしています。

```python
pattern = r'[!-\/:-@\[-`{-~、-〜「」【】『』（）〔〕［］｛｝〈〉《》＊？．，。・：；％！＃＠＆＜＞＼｜￥＄＾＊＋〜]'
```


# 実行 & 結果

下記コマンドで実行し結果を確認いたします。

```
python main.py
```


### ◆入力値に記号を含めていない場合
`これはサンプルテキストです` を仮の入力値と想定し実行すると、以下のように記号が含まれないとのログが出力される事を確認。

```
すべての入力値に記号は含まれていません。
```

### ◆入力値に記号を含めた場合（空文字も同様）
`これはサンプルテキストです！。` を仮の入力値と想定し実行すると、以下のように記号が含まれるとのログが出力される事を確認。

```
入力値が空かもしくは 'これはサンプルテキストです！。' に記号が含まれます。
```
SSRとSSGの理解を深める

# SSRとSSGの理解を深める

`Next.js` の勉強をしているのですが、`SSR` と `SSG` を説明できるのか、適切に使い分けられるのかと考えたとき、よくわかってないと感じたので、今回 `SSR` と `SSG` について調べました。

## SSR

まず、`SSR` は、`Server Side Rendering` の略です。  
名称の通り、サーバー側でHTMLを生成し、クライアントサイドに返してブラウザに表示します。
生成するタイミング は、クライアントサイドから呼ばれた時です。クライアントサイドでリクエストした際に、サーバーサイドでHTMLを生成し、クライアントサイドに返します。

## SSG

`SSG` は、`Static Site Rendering` の略です。
ビルドした際に、すべてのページHTMLを生成します。そして、クライアントサイドからリクエストがあった際に、ビルド時に生成して保管しておいたHTMLをクライアントサイドに返し表示します。

## SSRとSSGの違い

上記の説明それぞれにも説明していますが、`SSR` と `SSG` 、この2つの違いは、HTMLを生成するタイミングが違います。`SSR` は、クライアントサイドからリクエストがあるたびにHTMLを生成し、クライアントサイドに返します。`SSG` は、ビルド時にサーバーサイドでHTMLを生成し、クライアントサイドからレスポンスがあった際に、生成しておいたHTMLを返します。  
`SSR` は、***動的***なHTML、`SSG` は、***静的*** なHTMLを生成するということです。

<dl>
<dt>SSR: 動的なHTML</dt>
<dd>
クライアントサイドがリクエストするたびにサーバーサイドでHTMLを生成するため、下記の特徴があります。
<ul>
<li>リクエストした時に、HTMLを生成するので、常に最新の情報を得ることができる</li>
<li>動的な最新の情報に基づいて、一意なコンテンツを作成できる</li>
<li>ブラウザでの仕事量が少ないため、CSR よりページの表示速度が速い</li>
<li>ブラウザでの仕事量が少ないため、ユーザーのデバイスのメモリや通信環境による影響が少ない</li>
<li>リクエストするたびにHTMLを生成するため、ページ遷移のたびにサーバーの通信が発生する</li>
</ul>
</dd>
<dt>SSG: 静的なHTML</dt>
<dd>
ビルド時にいっきに全ページのHTMLを生成します。よって下記の特徴があります。
<ul>
<li>ビルド時にHTMLを生成しているので、リクエスト後のブラウザの表示が SSR より速い</li>
<li>あらかじめビルド時に読み込んでいるため、クローラーが読み取ることができ、SEOに強い</li>
<li>ページを更新したい場合、手動で再ビルドし直す必要がある</li>
</ul>
</dd>
</dl>

### SSRとSSGの選択

- SSR: 上記から、更新が頻繁に起こる常に最新の情報を得たいページの場合  
    → 商品ページ、タイムラインページ
- SSG: 更新頻度が少ない静的なページの場合
    → ヘルプページ、会社紹介ページ、問い合わせページ

## まとめ

今回は、`SSR` と `SSG` の特徴や違い、使い分けについて調べました。  
`SSR` は動的なページ、`SSG` は静的なページに使用するとこが分かりました。 
他にも `CSR` などもあるため、機会があったら調べて、実際に書いてみたいと思います。


参考：[AWS - SSG とSSR の比較](https://aws.amazon.com/jp/blogs/news/ssg-vs-ssr-in-next-js-web-applications-choosing-the-right-rendering-approach/)

---

**ご覧いただきありがとうございました**

今後もフロントエンド開発で気になったことや分からないことを調べて、共有していきたいと思います。
間違いなどございましたら、教えていただきたいです。
Socialiteアプリのユーザーエクスペリエンス向上方法

この記事では、SocialiteというAndroidアプリのユーザーエクスペリエンスを向上させる3つの具体的な方法について解説しています。

## 1. エッジツーエッジデザインの追加
Android 15では、アプリを画面全体に拡張し、ステータスバーとナビゲーションバーを非表示にする機能が導入されました。これにより、ユーザーはより没入感のある、現代的なデザインを体験できます。

**手順**:
- **ステップ1**: `WindowInsetsController` を使用してステータスバーとナビゲーションバーを非表示にする設定を行います。
- **ステップ2**: XMLレイアウトファイルで、アプリの主要コンテンツがエッジツーエッジデザインをサポートするように `fitsSystemWindows` 属性を適切に設定します。
- **ステップ3**: 3ボタンナビゲーションの互換性問題に対処するために、必要に応じてパディングやマージンを調整します。

## 2. 予測バックアニメーション
予測バックアニメーションは、ユーザーが「戻る」アクションを行う際に、次に表示される画面のプレビューを提供します。これにより、ユーザーが次に何が表示されるのかを予測しやすくなり、アプリの操作性が向上します。

**手順**:
- **ステップ1**: `OnBackPressedDispatcher` を使用して、カスタムバックアクションを定義します。
- **ステップ2**: アニメーションを設定し、ユーザーがスワイプバック動作を行った際に、前の画面がスムーズに表示されるようにします。
- **ステップ3**: アニメーションの遷移を最適化し、ユーザーがバックアクションをキャンセルした場合にも適切に処理されるようにします。

## 3. Jetpack Glanceを使用したウィジェット
**説明**: Glanceは、Jetpackのウィジェット作成ライブラリで、ユーザーのホーム画面にインタラクティブなUI要素を追加するためのツールです。このライブラリを使用して、Socialiteのウィジェットを作成し、ユーザーのアプリ体験を向上させます。

**手順**:
- **ステップ1**: Glanceライブラリをプロジェクトに追加し、必要な依存関係を設定します。
- **ステップ2**: ウィジェットのレイアウトを定義し、表示するコンテンツ（例：お気に入りの連絡先、未読メッセージ数）を設定します。
- **ステップ3**: ウィジェットのデータを定期的に更新し、ユーザーのアプリ使用状況に応じて動的に変化するようにします。
- **ステップ4**: ウィジェットのクリックイベントを設定し、ユーザーがウィジェットをタップした際にアプリ内の特定の機能に直接アクセスできるようにします。

## まとめ
これらの3つの機能（エッジツーエッジデザイン、予測バックアニメーション、Jetpack Glanceを使用したウィジェット）を統合することで、Socialiteアプリの外観と使用感を大幅に向上させることができます。これにより、アプリがより視覚的に魅力的で、ユーザーフレンドリーで、インタラクティブなものになります。

## 参考動画
[Improve your app experience](https://www.youtube.com/watch?v=RimGfoOU67s)
心に残った科学者・音楽家・哲学者の名言


## 心に残った科学者の名言
### コンラート・ローレンツ(オーストリアの動物行動学者)
>誰もが見ていながら、誰も気づかなかったことに気づく。研究とはそういうものだ。　

### アイザック・ニュートン
>I can calculate the motion of heacenly bodies but not the madness of people.
私は天体の動きは計算できるが、人々の狂った行動は計算できない。

### アルバート・アインシュタイン
>私は天才ではない。ただ人より長く一つのことに向き合っていただけである。



### 「科学の価値」アンリ・ポアンカレ著より

>数学は何の役にたつのか、数学というこの精巧な機構は、われわれが頭の中から全部ひねり出すものなのだから、こしらえもので、われわれの気まぐれの産物ではないのかーおそらく、こういった疑問に接することがたびたびあることだろう、と思われる。
こういった疑問を投げかける人々のうちには、見分けをつけておかなければならない。実際家たちは、ただ、われわれから金儲けの手段を要求するばかりである。彼らは返事をしてやるに値しない。むしろ、あんなにも多くの富を蓄積するのは何のためなのか、また、その富を享受してこれを楽しむ力のある魂にわれわれを育ててくれるのは芸術や科学だけであるのに、富を得るのに時間を費やすため、これら芸術や科学をなおざりにしなければならないのではないか、
生活のために生活の目的を放棄するのではないか、と彼らにきいてみる方がふさわしい、というものである。

### 湯川秀樹（日本の物理学者）
>科学が全てであると思っている人は、科学者として未熟である。

### コンスタンツィン・E・ツィオルコフスキー（ソビエト連邦の科学者・ロケット研究者）
>地球は人類のゆりかごである。しかし人類はいつまでもこのゆりかごに留まってはいないだろう。

## 心に残った芸術家の名言
### ピョートル・チャイコフスキー（ロシアの作曲家)
>Inspiration is a guest which does not willingly visit the lazy.
インスピレーションは、怠けているもののもとには決してやってこないものである。

### モーツァルト(オーストリアの作曲家)
>Our riches, being in our brains.
財産は私たちの頭の中にある。

### ミケランジェロ
>私がこの芸術の域に達するまでにどれほどの努力を重ねているかを知ったら、芸術家になりたいとは誰も思わないだろう。

### レオナルドダ・ヴィンチ
>充実した一日が幸せな眠りをもたらすように、充実した一生は幸福な死をもたらす。


## 心に残った哲学者の名言
### ロジャー・ベーコン（イギリスの哲学者）
>人は賢明になればなるほど、ますます腰を低くして他人から学ぼうとする。

### ジャン＝ジャック・ルソー（フランスの哲学者）
>知らぬものは決まっておしゃべりだが、知るものは決まって無口である。
(People who know little are usually great talkers, while men who know much say little.)

### ソクラテス（古代ギリシアの哲学者）
>唯一の真の英知とは、自分が無知であることを知ることにある。

>生きるために食べよ、食べるために生きるな

##
以上、私が心に残った科学者・音楽家・哲学者の名言でした。彼らの名言を聞くと自分もまだまだ学ぶことが多いと感じます。皆さんもぜひ今後の活力にしてください。
好きなエイリアスを発表します

## 目次

1.  [エイリアス(alias)について](#1-エイリアスについて)
    1-1.  [エイリアスとは](#1-1-エイリアスとは)
    1-2.  [エイリアスの設定方法](#1-2-エイリアスの設定方法)
2.  [好きなエイリアス](#2-好きなエイリアス)
    2-1.  [オプション](#2-1-オプション)
    2-2.  [OS互換](#2-2-os互換)
    2-3. [事故防止](#2-3-事故防止)
    2-4. [コマンドまとめて便利にする奴](#2-4-いくつかまとめて便利にする奴)
3. [さいごに](#3-最後に)


## 1. エイリアスについて

### 1-1. エイリアスとは

コマンドの仮名のようなもの．
仮名なので，元のコマンドと登録した仮名が重複してなければ，元のコマンドに影響はない．

"ただ手間を省いただけ"だけとも思えるが，使い方次第でちょっと便利につかえる．
そんな感じのaliasが好きなので紹介する．

### 1-2. エイリアスの設定方法

> 環境: ubuntu 22.04

特定ファイルを編集した後，記入した内容を有効化する．
例として`ls -la`を`ll`を動かせるようにする

1. `vi ~/.bashrc`でファイルに，エイリアス設定を記入して保存する．

```sh:.bashrc
alias ll='ls -la'
```

2. ターミナルで以下を実行し，編集したファイルを有効化する．

```console
source ~/.bashrc
```

## 2. 好きなエイリアス

### 2-1. 省略形(略式詠唱)

The 王道の使い道(だと思う)．
上記で登録した`ll='ls -la'`のように，デフォルトでオプションをつけるようにする．
オプションの種類が多かったり，省略形がないオプションとかはエイリアス登録しておくと便利だと思う．
```shell:diffで差分を取る時，横に並べつつ差分がある行のみ表示
alias differ='diff -y --suppress-common-lines'
```
シンプルに，よく使うけど早く打ちたいものも登録する
```shell:できるだけ省略したコマンド
alias ..='cd ..'
alias c='clear'
```
### 2-2. OS互換

「えっ，linuxのコマンドってどっちでしたっけ」と言うのがよくある．
それのパワー解決策が，"aliasによく使う別OSのコマンドを登録する"方法である．
```sh:画面を一掃する際のコマンド
alias cls='clear'
```

### 2-3. 事故防止

ファイル削除や移動時の上書きなど，コマンドのデフォルトではEnter1発で消える．
誤削除を防ぐために，取り返しのつかないようなコマンドを打つ際はオプションを打って確認することが多い．
```sh:危なげなコマンドには事故防止のオプションを
alias rm='rm -i'
alias mv='mv -i'
alias cp='cp -i'
```
こんな感じで登録しておくと，誤削除事故が減るのでおすすめ．

### 2-4. いくつかまとめて便利にする奴

コマンドとそのオプションを略称として登録するだけじゃなく，
複数コマンドを指定して実行することも可能．
```sh:画面一掃後に情報出力
alias cll='clear && ll'
```

## 3. さいごに

なんとなく分類形態として覚えておくと，設定漏れが少なくなりそう．
「事故防止だとこれが足りない」とかに気づける気がする．

【閑話】
エイリアスが何かを説明する時，よくウォッカマティーニの話をする．
行く頻度の高いバーで「ウォッカマティーニ，ステアでなくシェイクで」毎回言っていると
いくらなんでもそのうち，「長いから省略したいなぁ」と思う時が来ると思う．
そこで，「いつもの」と頼めると面倒では無くなる．

でも心のどこかに，「省略せず言った方がカッコいいよな...」という自分もいる．
Rustのお勉強 #2 Hello World!編

# はじめに
前回に続きRustのお勉強をします。

前回は、Dockerを使ってコンテナを作成しDev Containerで開発環境を構築しました。

今回はプロジェクトを新規作成し、**Hello World!** を出力します。

## プロジェクト作成
- 上タブの新規メニューからNew -> Projectを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799440/d54e24a5-c09f-79d5-4e19-b44570bd769e.png)
<br/>

- 次にプロジェクト作成のディレクトリを指定します<br/>
1. Location: プロジェクトを作成する場所<br/>
2. ToolChain Location: cargo cli等で必要になるファイルが格納されている場所（変更しなくてOK）<br/>
3. Standard library: ライブラリが格納されている場所（変更しなくてOK）<br/>
4. Project Template: 文字通りプロジェクトのテンプレート。今回はBinaryを選択<br/>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799440/9676be34-34ef-414d-2458-8cedc722a9f1.png)

# Hello World!
プロジェクトを作成したら以下のようなディレクトリ構造になっていると思います。

```
rust
├ .devcontainer
├ src
│ └ main.rs
├ target
├ Cargo.lock
└ Cargo.toml
```

#### Cargoとは
Rustのビルド兼パッケージ管理ツールです。
コードが依存するライブラリのインストールを勝手に行ってくれます。
以下、[公式ドキュメント](https://doc.rust-jp.rs/book-ja/ch01-03-hello-cargo.html)より引用
> CargoはRustのビルドシステム兼パッケージマネージャです。 ほとんどのRustaceanはこのツールを使ってRustプロジェクトを管理しています。 なぜなら、Cargoは多くの仕事、たとえばコードのビルド、コードが依存するライブラリのダウンロード、それらのライブラリのビルドなどを扱ってくれるからです。 （コードが必要とするライブラリのことを依存（dependencies）と呼びます）

#### Cargo コマンド
`Rust`にも様々コマンドが存在するので、一部紹介します。
- バージョン確認

    ```
    cargo --version
    ```
- ビルド
`Cargo.toml`に記載しているライブラリを自動ダウンロードしてビルドを行う

    ```
    cargo build 
    または
    cargo b
    ```
- 実行
実行可能ファイルを作成する。その際にビルドが必要であればビルドも行ってくれる

    ```
    cargo run
    ```
- コンパイルチェック
ビルドと違ってコンパイルが通るかのみ確認

    ```
    cargo check
    ```
- 外部パッケージ追加
外部パッケージを追加すると`Cargo.toml`内の`dependencies`にライブラリが記載されます。

    ```
    cargo add package-name
    ```
    - Cargo.toml
    ```
    [package]
    name = "rust"
    version = "0.1.0"
    edition = "2021"
    
    [dependencies]
    proconio = "0.4.5"
    ```

- パッケージ構成確認
現在のパッケージ構成を確認する
    ```
    cargo tree

    -- 実行結果 --
    rust v0.1.0 (/app/rust)
    proconio v0.4.5
    ```

- バイナリパッケージインストール
バイナリパッケージをインストールできます。`cargo add`とは異なります。
    ```
    # install
    cargo install package-name
    
    # uninstall
    cargo uninstall package-name
    ```

### やってみよう！
- main.rsを開き、以下のコードを記述
    ```
    fn main() {
        println!("Hello World!")
    }
    ```
- ターミナルを開いて`cargo run`を実行
    ```
    cargo run
    ```

おめでとうございます。
ターミナルに`Hello World!`と表示されれば成功です。

# さいごに
Hello World!編は以上になります。
次回は何を書くか決めていませんが、何かしら書きます。
以上、お疲れ様でした。


# 参考文献
https://zenn.dev/mebiusbox/books/22d4c1ed9b0003/viewer/9c00b6

https://doc.rust-jp.rs/book-ja/ch01-03-hello-cargo.html
【gcloud】プロジェクト毎にコンフィグを切り替えるための設定

## 対象読者
複数のプロジェクトを扱う人

### 権限*があるすべてのアクティブなプロジェクトを一覧表示
```shell
gcloud projects list
```
指定できるパラメータは [レファレンス](https://cloud.google.com/sdk/gcloud/reference/projects/list)参照
> *アクティブなアカウントに所有者、編集者、ブラウザー、または閲覧者の権限

### 現在アクティブな設定(Configuration)のプロパティを一覧で表示
```shell
gcloud config list
```
結果
- 以下の例はアクティブな設定（Configuration)はdefaultという意味
```
[accessibility]
screen_reader = True
[core]
account = YourAccount@email.com
disable_usage_reporting = True
project = your-project-id

Your active configuration is: [default]
```
### 新規で設定(Configuration)のNAME({設定名})を作成
```
 gcloud config configurations create {任意の設定名}
```
結果
```
Created [｛任意の設定名｝].
Activated [{任意の設定名}].
```
- 設定が作成され、アクティブな設定が上記で作った設定に変更される

確認
先ほどの`gcloud config list`を打つとactive configurationが下記のようになる
```
Your active configuration is: [{任意の設定名}]
```
- アクティブな設定（Configuration)が今作成した設定に変更されたという意味
### 新規で作成した設定(Configuration)に各項目を紐づけ
#### PROJECTを設定
```
gcloud config set project {PROJECTのID}
```
#### ACCOUNTを設定
```
gcloud config set account {GCPのemailアドレス}
```
### ZONE,REGIONはデフォルトでも入っていなかったので要らないかもしれない・・・
#### ZONEを設定
```
gcloud config set compute/region {ZONE}
```
#### REGIONを設定
```
gcloud config set compute/region {REGION}
```
- zoneやregionはAPIが有効でない場合、以下のように聞かれるので有効にする場合はyを入力
```
API [compute.googleapis.com] not enabled on project [your-project-id]. Would you like to enable and retry (this will
take a few minutes)? (y/N)?
```
### 上記で設定した値を解除する
```
gcloud config unset {PROJECTのID,GCPのemailアドレス,ZONE,REGION}
```
### 設定した値を確認
- osによって若干表示が違うかもです
```
gcloud config configurations list
// 結果
NAME                    IS_ACTIVE  ACCOUNT                PROJECT              COMPUTE_DEFAULT_ZONE  COMPUTE_DEFAULT_REGION
default                 False      YourAccount@email.com 　your-project-ID
任意の設定名             True       YourAccount@email.com  new-project-ID        ZONE　　　　　            REGION
```
### アクティブな設定を切り替える
```
gcloud config configurations activate {設定名}
```
例
```
// アクティブな設定をdefaultに切り替える
gcloud config configurations activate default
// アクティブな設定を新規作成した設定に切り替える
gcloud config configurations activate {自分が上で作成した設定名}
```
### 設定の削除
- activeだと削除できないので他の設定に切り替えて行う
```
gcloud config configurations delete {設定名}
```
結果
```
The following configurations will be deleted:
 - {設定名}
Do you want to continue (Y/n)?  Y

Deleted [{設定名}].
```


# 参考資料
- [Google Cloud | Cloud SDK | gcloud CLI の構成の管理 ](https://cloud.google.com/sdk/docs/configurations?hl=ja)
- [gcloud projects list](https://cloud.google.com/sdk/gcloud/reference/projects/list)
- [gcloud config configurations list](https://cloud.google.com/sdk/gcloud/reference/projects/list)
- [gcloud config configurations delete](https://cloud.google.com/sdk/gcloud/reference/config/configurations/delete)
- [よく使うgcloudコマンドたち](https://qiita.com/masaaania/items/7a83c5e44e351b4a3a2c)
- [gcloud configで複数の設定を持って切り替える](https://qiita.com/sky0621/items/597d4de7ed9ba7e31f6d#%E6%96%B0%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%ABgcloud%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%A7%E6%8E%A5%E7%B6%9A%E3%81%A7%E3%81%8D%E3%82%8B%E3%81%8B%E7%A2%BA%E8%AA%8D)
- [gcloudでプロジェクトを切り替える](https://zenn.dev/taka_baya/articles/ef12fe9a043560)
勾配ブースティング決定木の性能比較

勾配ブースティング決定木はライブラリが3つあり
- XGBoost
- LightGBM
- Scikit-Learn

があります。
という訳で、この3つについてアヤメのデータセットで条件を同じにして100回検証し時間と精度で比較してみようと思います。
# プログラムと出力
```Python3
from xgboost import XGBClassifier
from lightgbm import LGBMClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import train_test_split as tts
from sklearn.metrics import accuracy_score
import pandas as pd
import matplotlib.pyplot as plt
import time

df = pd.read_csv("iris.csv")

y = df["category"]
x = df.drop("category", axis=1)
print("XGBoost:", end="")
acc1= []
start = time.time()
for i in range(100):
    x_train, x_test, y_train, y_test = tts(x, y, test_size=0.3, random_state=i)
    model1 = XGBClassifier()
    model1.fit(x_train, y_train)
    y_pred1 = model1.predict(x_test)
    acc1.append(accuracy_score(y_test, y_pred1))
print(time.time()-start)

print("LightGBM:", end="")
acc2 = []
start = time.time()
for i in range(100):
    x_train, x_test, y_train, y_test = tts(x, y, test_size=0.3, random_state=i)
    model2 = LGBMClassifier()
    model2.fit(x_train, y_train)
    y_pred2 = model2.predict(x_test)
    acc2.append(accuracy_score(y_test, y_pred2))
print(time.time()-start)

print("Scikit-Learn:", end="")
acc3 = []
start = time.time()
for i in range(100):
    x_train, x_test, y_train, y_test = tts(x, y, test_size=0.3, random_state=i)
    model3 = GradientBoostingClassifier()
    model3.fit(x_train, y_train)
    y_pred3 = model3.predict(x_test)
    acc3.append(accuracy_score(y_test, y_pred3))
print(time.time()-start)

df_acc = pd.DataFrame(acc1).describe()
df_acc = pd.concat([df_acc, pd.DataFrame(acc2).describe()], axis=1)
df_acc = pd.concat([df_acc, pd.DataFrame(acc3).describe()], axis=1)
df_acc.columns = ["XGBoost", "LightGBM", "Scikit-Learn"]
df_acc
```
出力結果はこうなりました
```
XGBoost:10.425119638442993
LightGBM:8.228994369506836
Scikit-Learn:27.98310923576355
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782889/334e2e89-2831-d84d-12cb-542b92194e83.png)

次にこれをグラフにして精度を可視化します。
```Python3
plt.boxplot([acc1, acc2, acc3], labels=df_acc.columns, positions=[0, 1, 2])
plt.scatter([0, 1, 2], [sum(acc1)/100, sum(acc2)/100, sum(acc3)/100], marker="x", color="#000000")
plt.show()
```
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782889/9fdbd8d0-268c-201c-e51f-b36169fa8958.png)

# 結果の解釈
これらの結果から考えられることとして(あくまでアヤメデータですが)
予測時間→LightGBM>XGBoost>>Scikit-Learn
精度の安定性→Scikit-Learn>XGBoost>LightGBM
精度の高さ→Scikit-Learn>LightGBM>XGBoost

# まとめ
一長一短ですね
PHPアプリケーションで、標準出力の文字の色やフォーマットをカスタマイズする

# 前提

Symfonyがインストールされていること。（LaravelやCakePHPなどにはインストールされているはずです。）

# 概要

SymfonyのConsoleOutputクラスを使って、簡単に標準出力のフォーマットを指定できたのでその方法と具体例を軽く紹介します。

# 具体例

```php
$output = new \Symfony\Component\Console\Output\ConsoleOutput();

$output->writeln('<info>これは情報メッセージです。</info>');
$output->writeln('<comment>これはコメントメッセージです。</comment>');
$output->writeln('<question>これは質問メッセージです。</question>');
$output->writeln('<error>これはエラーメッセージです。</error>');
$output->writeln('<fg=cyan>これはカスタムカラーのメッセージです。</>');
$output->writeln('<bg=blue;fg=white>これは青い背景に白い文字のメッセージです。</>');
$output->writeln('<options=bold>これは太字のメッセージです。</>');
$output->writeln('<options=underscore>これは下線付きのメッセージです。</>');
$output->writeln('<options=reverse>これは反転したメッセージです。</>');
$output->writeln('<fg=black;bg=yellow>これは黄色い背景に黒い文字のメッセージです。</>');
$output->writeln('<fg=green;bg=black;options=bold>黒い背景に緑色の太字のテキスト。</>');
```

CLIで実行すると下記のように出力されます。

![スクリーンショット 2024-06-03 0.02.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552943/161c0f71-85e9-bfc1-809b-27bc512f4a0b.png)

`fg={color}` で文字の色、`bg={color}` で背景色を指定できます。
また、`options=bold` で太文字にできます。

# 追記（2024-06-04）

下記のように書くと、標準エラー出力もできます。

```php
$output = new \Symfony\Component\Console\Output\StreamOutput(\STDERR);
```
スキルチェック問題を解いてみる

## はじめに
ハンズオン学習の一環として、昨日からpaizaのプログラミング問題集をのそのそ取り組みだし、
Dランクの問題がすんなり解けるようになったので、本日はCランクを解いてみました。

使用言語はRubyです。

## 問題1：じゃんけんの結果

自分の回答
``` qiit.rb
n = gets.to_i

win = 0

n.times do
    alice, bob = gets.chomp.split
    if (alice == "G" && bob == "C") || (alice == "C" && bob == "P") || (alice == "P" && bob == "G")
        win += 1
    end
end

puts win
```

## 問題2：プレゼント応募企画の実施

自分の回答
``` qiit.rb
N,X,Y = gets.split.map(&:to_i)

(1..N).each do |i|
    if i % X == 0 && i % Y == 0
        puts "AB"
    elsif i % X == 0
        puts "A"
    elsif i % Y == 0
        puts "B"
    else
        puts "N"
    end
end
```

設問を読んで、FizzBuzz問題だ！となったのが嬉しい
文章問題で、この感じ見覚えあるな〜とか思たり、
前はこういう式を用いて解いたな〜という感じで見当がつくようになると
自分の中に知識がストックされていっている実感があって楽しいです。

## 問題３：枠で囲む

自分の回答
``` qiit.rb
n = gets.chomp

i = n.length + 2
i.times do
end

puts "+" * i
puts "+" "#{n}" "+"
puts "+" * i
```
出力例1
+++++++
+Paiza+
+++++++

### 躓いたところ


- まず、上下の"+"は、nに代入される文字数＋２なので、
nの文字数を出すlengthメソッドを使い、それに＋２をした数字をiに代入。
その数字分、”+”を出力するには...？というところで止まってしまい、
以下のようにしました。

``` qiita.rb
i.times do
 print i
end
```

  しかしこれだと、puts "+" "#{n}" "+"の下にもう一度同じ式を書かなきゃいけない...？
  もっと良い記述方法はないかと思ったのですが、
  **単純に"+"に変数iに代入した数字を掛け算すればいい**
  こんな簡単なことがパッと出てきませんでした...
  なので、nを囲む上下の"+"は以下のように記述。

 ``` qiita.rb
 puts "+" * i
 ```

 - puts "+" "#{n}" "+"で出力した文字が以下のように崩れる
 
 +Paiza
 +

末尾の"+"が改行されてしまいます。
これは単純に入力値をnに代入する時、chompメソッドをつけることで解消。
設問にも
**入力は 1 行となり、末尾に改行が 1 つ入ります。**
と丁寧に書いてあったのに見落としてました...
chompメソッドは入力値末尾の改行コードを消してくれるメソッドです。
慣れてくると、設問内容の読み飛ばしをしてしまう癖があるので、気をつけたいと思います。

## 問題４：渋滞の距離

自分の回答
``` qiita.rb
N,M = gets.split.map(&:to_i)

count = 0

N.times do
    A = gets.to_i
    if A <= M
        count += A
    end
end

puts count
```

## 問題５：折り紙の貼り合わせ

自分の回答
``` qiita.rb
N,D = gets.split.map(&:to_i)

overlap = 0

(N-1).times do
    overlap += gets.to_i
end

i = N * D - overlap
volume = D * i

puts volume
```


今後の課題
- 設問の意味を理解するのに時間を使ってしまいがち
- 設問内容の読み飛ばしを気をつける
- 変数名
- 問題５のコード後半にある単純な計算式などの記述をもっと短縮させたい
SQLite TablePlusで開けるようにする



## 概要

ローカルのSQLiteにTablePlusで開く方法をまとめる。
SQLiteは下記のRemixの構築で用意したものに接続する。

## 方法

1. SQLiteを選択する

    ![CleanShot 2024-06-02 at 23.49.41@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/ffc83448-5b74-08c7-2239-bdeace4cf72d.png)

1. Database pathでRemix構築時に作成されたプロダクトルート/prisma/dev.dbを選ぶ

    ![CleanShot 2024-06-02 at 23.56.45@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/905786bc-c94c-3dcf-094c-9bb3ba5ad6d2.png)

1. 下記のように接続する事ができた

    ![CleanShot 2024-06-03 at 00.04.55@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/87bfea6e-7267-4bdc-2fde-43b9724282bc.png)
fatal: Authentication failed for エラー解決方法

## Authentication failed for'https://github.com/githubusername/repositoryname.git/' が発生するときの解決法

補足：repositoryname.gitは各自のrepository名、githubusernameは各自のgithubユーザー名に読み替えてください。

# 記事を書こうと考えた背景
wsl2の中でubuntu上に作成したプロジェクトディレクトリをpushをしようとした際にエラーが出てしまった為

# エラーの原因
githubでの認証にアクセストークンが必要なため

# エラー対処で間違えたところ
Authentication failedというエラーが出たときにgithubのパスワードを入力してしまった
→パスワード認証は廃止されている為トークン認証をする必要がある。

# エラー解決手順
１設定ボタンをクリックする（Settings）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789688/4bbfbfce-b18d-c2f4-c169-fe6ef223f69b.png)

2設定ボタンを押したら下までスクロールして左側にあるDeveloper settingをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789688/b96049e2-82a3-eda4-3033-f8af0ab75e66.png)

3Developer settingをクリック後Personal access tokensのトグロを開きtokens (classic)をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789688/445edf22-685b-f513-63db-ff20fa06fefe.png)
4Generate new tokenをクリックし、Generate new　token (classic)をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789688/46922c1f-3fbb-bb16-8ff0-77ce43d9224e.png)

5noteにアクセストークン名を入力し、必要なところにチェックを入れる
※今回はrepoのみにチェックを入れた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789688/c51612f6-4065-5562-0694-de79aea5f6dc.png)
6Generate tokenのボタンをクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789688/c1af6556-a987-b494-7579-1b0dba22159b.png)

7 6でボタンをクリック後下記画像にはアクセストークン名が表示されているが表示前に数字と英語などを組み合わせた文字列が生成される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789688/1287f91e-7831-b48b-bbb4-ae5dd0b45c3b.png)
8 7で生成されたアクセストークンを使用するとgithubにpushができるようになる。
【VSCode】簡単にスニペットを作成する方法

Snippet Generatorという拡張機能を使用すると簡単にスニペットを作成できます。

https://marketplace.visualstudio.com/items?itemName=wenfangdu.snippet-generator

![スクリーンショット 2024-06-22 23.57.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/1e0b64a1-b4d7-43a9-bbd2-74217ec89703.png)

スニペットを作成したいコードを選択してコマンドパレットから`Generate Snippet`を実行し、必要事項を入力するとスニペットを設定するためのオブジェクトがクリップボードに保存されます。

`Snippets Configure User Snippets`を実行します。

![スクリーンショット 2024-06-23 0.01.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/cccfb97c-6f77-ce0e-3f96-f49b1fc78078.png)


開いた設定ファイルにクリップボードの内容を貼り付けるとスニペットを使用できるようになります。

以下のようにショートカットキーを設定すると`Generate Snippet`の必要事項を入力した後に`Snippets Configure User Snippets`が実行されファイル選択できるようになり、より簡単に作成できます。

```jsonc:keybindings.json
{
  {
    "key": "任意のキー",
    "command": "runCommands",
    "args": {
      "commands": [
        "snippet-generator.generate-snippet",
        "workbench.action.openSnippets"
      ]
    }
  }
}

```
Mac（というよりEmacs）っぽい操作感とWindowsショートカットを両立してみた


## はじめに

突然だが皆はキーボードのホームポジションは適切に使えているだろうか。
自分はというと専門学生のころにタイピング練習用のゲーム（名前は確か「特打」）をやって以来、ホームポジションを崩さずにブラインドタッチを徹底できるようになった。

しかし、実際にコーディングをしていたりすると漠然と以下の2つの悩みがあった。

- 矢印キー、Home、Endなどホームポジションから離れすぎるキーがある
- 左手小指で押すキーの中でCapsLockだけ使い道がない

### MacBook（JIS配列）との出会い

そんな中、とある友人がMacBookを格安で譲ってくれることとなり、Macも触っておくかーという軽い気持ちで譲ってもらうことにした。

MacだとCtrl+●と打つことでカーソルを動かすことができ、しかもWindowsでいうCapsLockの位置（左手小指）にCtrlキーが割り当てられている。
これなら、カーソル操作などをするときにホームポジションを崩す必要がない。

後々調べた結果、その操作は「Emacsキーバインド」と呼ばれるもので、ホームポジションから手を離すことなく操作することを念頭に作られたエディターがVimとEmacsだった。

また、Macだと現在の入力状態（アルファベットか、ローマ字か）を意識せず、日本語キーと英語キーがあるので切り替えがしやすい。

この経験からMacやEmacsキーバインドの操作感が好きになり、Windowsでも実行したいと思ったのである。
しかし、単純にC-f（Control押しながらfキー）やM-f（Altキーを押しながらfキー）で実装するとアプリごとのショートカットが使えなくなってしまう。
Windowsショートカットも使いたいものも中にはある。
そこで普段使っていない右Ctrlと右AltをEmacsのキーとして割り当てることにした。

## 設定

ここで設定すべき項目は大きく3つある

- CapsLockキーの動作を変更する
- 変換・無変換キーの動作を変更する
- Emacsキーバインドを設定する

### CapsLockキーの動作を変更する

まずはCapsLockキーの動作を変更する。
Mac（JIS配列）ではControlキーの位置となっている。
そのためCapsLockキーに右Ctrlキーを割り当てるのが良いだろう。

CapsLockキーの動作変更はAutoHotKeyでうまくいかないケースがあるらしい。
確実に置き換えるためにレジストリを変更してキーの割当を変える。
しかしレジストリを直接変更するのはなんとなく嫌なので、KeySwapというソフトで行う
(![CapsLockキーの動作変更（KeySwap）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432981/1d41b618-558a-7cbd-6e4e-accf2aceb657.png))

### Google日本語入力

次にMac（JIS配列）と同じように
変換キー→かな
無変換キー→英数
に変更する。

ここでわざわざGoogle日本語入力で設定いることについては、単純にAutoHotKeyで変更してしまうと無変換キー、変換キーが使用できなくなるのを防ぐため、入力していない時のみ切り替え可能にする。

設定>一般>キー設定>キー設定の選択>編集

モード「入力文字なし」の
「Henkan」を「ひらがな」に変更
「Muhenkan」を「IMEを無効化」に変更

(![Google日本語入力の設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432981/0733a0d0-3fc6-c953-bf09-6cb04ab0c91a.png))

### AutoHotKeyスクリプト

今回AutoHotKeyのスクリプトは自作した。
先駆者は結構いるのだが、2022年にAutoHotKeyのバージョンがv2に上がっており、せっかくだし自分で1から作成し直すことにした。
修正したものについてはGitHubに公開している。
<https://github.com/varubogu/emacs-like-rightkey.ahk>

### Emacsキーバインド

Emacsのキーバインドは以下の通りに設定。
<https://github.com/varubogu/emacs-like-rightkey.ahk/blob/main/README.ja.md>

## 余談①他キーを割り当てる方法もある

ControlではなくF13以降のキー（大抵のキーボードには存在しない）やPowerボタン（一部キーボードのみ存在）を右Ctrlや右Altの代わりに割り当てる方法もある。

## 余談②なんのキーボードを使ってる？

Realforce R2の静音、黒、全キー30gのやつを使ってる。
静電容量無接点方式信者。
外出用にHHKBの方も欲しい。
US配列も触ってみたさはある。

## さいごに

これでMacっぽい操作感とWindowsショートカットを両立することができた。
WindowsとMacで度々間違うことも減るだろう。（コピペとかはいまだによく間違うけど・・・）
Dockerのボリュームマウントとバインドマウント

# はじめに

どちらもDockerコンテナ内のデータを永続化するための機能ですが、それぞれの違いを調べたので簡単にまとめます。

# 結論

- ボリュームマウント
    - **Volumes** として、**コンテナの外部**に保存
    - 複数のコンテナから共有可能
    - Volumesを削除しない限り残り続ける
    - 永続化データの保存には公式もこちらを推奨
- バインドマウント
    - **指定したホストマシンのファイルシステム内**に保存
    - ホストマシンと同期しているため、どちらかでファイルを修正や削除した場合はもう片方（ホストマシン⇄コンテナ）に反映される
    - 開発中のソースコードやビルドファイルなど、即時反映させたいものはバインドマウントがおすすめ


# ボリュームマウント

コンテナのファイルシステムとは別に、**Volumes**としてデータを保存して使用するマウント方法です。

コンテナ外に保存されるため、**コンテナが削除されてもデータは残ります**。

また、**複数のコンテナから同じボリュームをマウントしてデータを共有**することも可能です。

<br>

以下、docker-compose.yml でボリュームマウントを設定する方法になります。

```docker-compose.yml
services:
    mysql:
        image: mysql
        ports:
            - 3306:3306
        volumes:
            - db_data:/var/lib/mysql    // 3. 作成したボリュームでコンテナ内のデータをマウント

volumes: 
    db_data:                            // 1. 名前を付けてボリュームを作成
    app_data:                           // 2. 複数作成することも可能（今回こちらは作成するのみ）
```

今回はMySQLのコンテナを例にしましたが、このようにすることで「**db_data**」というボリュームに対してコンテナ内の「/var/lib/mysql」というディレクトリをマウントしています。

「/var/lib/mysql」にはMySQLのデータが格納されていますが、それらをボリュームとして管理することで永続化を実現しています。


作成したVolumesは```docker volume ls```で確認し、```docker volume rm <volume_name>```で削除することができます。（```docker volume prune```で未使用ボリュームの削除）


# バインドマウント

パスで指定したホストマシンのファイルをマウントして使用する方法です。

こちらもコンテナ内に保存されるわけではないため、コンテナが削除されてもデータは残ります。

注意点として、**ファイルやディレクトリはホストマシンとコンテナ間で同期している**ため、**どちらかで更新や削除をすればもう片方にも反映されます**。

<br>

以下、docker-compose.yml でバインドマウントを設定する方法になります。


```docker-compose.yml
services:
    mysql:
        image: mysql
        ports:
            - 3306:3306
        volumes:
            - ./docker/db/data:/var/lib/mysql  // 2. ホストマシンの「./docker/db/data」にデータをマウント

                                               // 1. 今回はボリュームを作成しません
```

このように設定すると、**「:」の左側に指定しているパスに対してホストマシン側にマウント用のファイルやディレクトリを作成**します。

今回であれば指定したパスが「**./docker/db/data**」なので、**docker-compose.yml ファイルがある階層から相対パスで「docker/db/data」というディレクトリを参照**し、その中にコンテナ内の「**/var/lib/mysql**」をマウントします。

前述しましたが、バインドマウントはホストマシンとコンテナのファイルを同期している状態のため、片方でファイルの変更や削除を行うともう片方にも反映されます。

<br>

今回はDBデータを例にしましたが、開発中にアプリケーションのビルドファイル等をマウントしておけば変更を即時反映させることも可能です。


# まとめ

- ボリュームマウント
    - **Volumes** として、**コンテナの外部**に保存
    - 複数のコンテナから共有可能
    - Volumesを削除しない限り残り続ける
    - 永続化データの保存には公式もこちらを推奨
- バインドマウント
    - **指定したホストマシンのファイルシステム内**に保存
    - ホストマシンと同期しているため、どちらかでファイルを修正や削除した場合はもう片方（ホストマシン⇄コンテナ）に反映される
    - 開発中のソースコードやビルドファイルなど、即時反映させたいものはバインドマウントがおすすめ


<br>
用途に合わせて適切にマウント方法を指定しましょう。
長時間のモニター使用で固まった首を解消する「前首ストレッチ」動画の紹介

## はじめに 

こんにちは！今回は、モニターを長時間使っていて首が固まってしまった方におすすめしたい動画を紹介します。大分県大分市にある綜合整体GENRYUの動画で、ストレートネックや首の痛みを解消する「前首ストレッチ」を丁寧に解説しています。

<iframe width="560" height="315" src="https://www.youtube.com/embed/3wBkdFrg31k?si=lFkTbmBmo1lByMrG" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## 動画の概要

この動画では、首の筋肉をほぐし、正常な動きを取り戻すためのストレッチ方法を紹介しています。特に、以下のステップに分かれています。

```plantuml
@startuml
start
:首を包む;
:前頭直筋 & 外側頭直筋ストレッチ;
:頭長筋ストレッチ;
:胸鎖乳突筋ストレッチ;
stop
@enduml
```

### STEP 1: 首を包む
首の筋肉を伸ばしやすくするために、まずは首全体を包み込むようにして筋肉をほぐします。これにより、後のストレッチが効果的になります。

### STEP 2: 前頭直筋 & 外側頭直筋ストレッチ
右の首筋を伸ばすために、首を左に倒して15秒間キープします。反対側も同様に行います。

### STEP 3: 頭長筋ストレッチ
首の根元から動かし、天井を向いた状態で左に倒して15秒間キープします。反対側も同様に行います。

### STEP 4: 胸鎖乳突筋ストレッチ
右手で左の鎖骨を押さえ、天井を向いた状態で右に倒して15秒間キープします。反対側も同様に行います。

## おすすめポイント

- **簡単に実践できる**:
    動画で紹介されているストレッチは、自宅やオフィスで簡単に実践できます。特別な道具は必要なく、すぐに始められます。

- **効果が実感できる**:
    首の動きが良くなることを実感でき、日常生活での首の痛みや違和感を軽減できます。

- **継続が重要**:
    ストレッチを1日2セットから3セット行うことで、固まった首の筋肉をほぐし、トラブルを予防できます。

## 感謝のコメント

この素晴らしいストレッチ動画を提供してくださった治療家のGENRYUさんに深く感謝いたします。GENRYUさんの丁寧な解説と実践的なアドバイスのおかげで、首の痛みや違和感を軽減することができました。これからも継続してストレッチを行い、健康な首を維持していきたいと思います。本当にありがとうございました！

## まとめ

長時間のモニター使用で固まってしまった首を解消するためには、定期的なストレッチが効果的です。紹介した動画を参考に、首の健康を保つためのストレッチを続けてみてください。首の痛みや違和感が軽減されることで、仕事や日常生活もより快適になるでしょう。

---

ぜひ、この記事を参考にして、首の健康を維持してください！
jsでFireStoreを使ってたら急に「Could not reach Cloud Firestore backend backend didn t respond within 10 seconds」が発生した

#  問題
ある日突然FireStoreから「Could not reach Cloud Firestore backend backend didn t respond within 10 seconds」というエラーがでてデータの取得ができなくなりました。

# 解決策
FireStoreのパッケージのバージョンを10.11.1に上げたら治りました。
応答していたとしても処理に時間がかかっているとエラーを出すようになっていたみたいです。
Firebaseのドキュメントに修正したと情報が載っていました。
[Firebaeドキュメント](https://firebase.google.com/support/release-notes/js?_gl=1*dtmu5t*_up*MQ..*_ga*MTMyMzUzMjUyLjE3MTkwNjUzNzg.*_ga_CW55HF8NVT*MTcxOTA2NTM3OC4xLjAuMTcxOTA2NTM3OC4wLjAuMA..#version_10111_-_april_25_2024)

# さいごに
自分のコードに問題があると思い調査に時間をかけてしまいましたが、まずはドキュメントを見てみるのが大事だなと痛感した出来事でした。
jmedllm-7b-v1は『雪国』の冒頭をどうトークナイズするのか

[jmedllm-7b-v1](https://huggingface.co/stardust-coder/jmedllm-7b-v1)という日本語生成AIが、[覚醒プロジェクト](https://kakusei.aist.go.jp)「JMed-LMM：医療分野における大規模マルチモーダルモデルの開発」からリリースされた。[Qwen2-7b-Instruct](https://huggingface.co/Qwen/Qwen2-7B-Instruct)をベースに日本語化したようなのだが、とりあえずトークナイザを試してみよう。

```
>>> from transformers import AutoTokenizer
>>> tkz=AutoTokenizer.from_pretrained("stardust-coder/jmedllm-7b-v1")
>>> print(tkz.convert_ids_to_tokens(tkz("国境の長いトンネルを抜けると雪国であった。","夜の底が白くなった。")["input_ids"]))
['åĽ½', 'å¢ĥ', 'ãģ®', 'éķ·ãģĦ', 'ãĥĪãĥ³', 'ãĥį', 'ãĥ«', 'ãĤĴ', 'æĬľ', 'ãģĳãĤĭ', 'ãģ¨', 'éĽª', 'åĽ½', 'ãģ§ãģĤãģ£ãģŁ', 'ãĢĤ', 'å¤ľ', 'ãģ®', 'åºķ', 'ãģĮ', 'çĻ½', 'ãģıãģªãģ£ãģŁ', 'ãĢĤ']
```

う、「国」が「åĽ½」ということは、もしや

```
>>> text="国境の長いトンネルを抜けると雪国であった。夜の底が白くなった。"
>>> x=tkz(text,return_offsets_mapping=True)                        
>>> for i,(s,e) in zip(x["input_ids"],x["offset_mapping"]):        
...   print(text[s:e],text[s:e].encode("utf-8"),ascii(tkz.convert_ids_to_tokens(i)))
...
国 b'\xe5\x9b\xbd' '\xe5\u013d\xbd'
境 b'\xe5\xa2\x83' '\xe5\xa2\u0125'
の b'\xe3\x81\xae' '\xe3\u0123\xae'
長い b'\xe9\x95\xb7\xe3\x81\x84' '\xe9\u0137\xb7\xe3\u0123\u0126'
トン b'\xe3\x83\x88\xe3\x83\xb3' '\xe3\u0125\u012a\xe3\u0125\xb3'
ネ b'\xe3\x83\x8d' '\xe3\u0125\u012f'
ル b'\xe3\x83\xab' '\xe3\u0125\xab'
を b'\xe3\x82\x92' '\xe3\u0124\u0134'
抜 b'\xe6\x8a\x9c' '\xe6\u012c\u013e'
ける b'\xe3\x81\x91\xe3\x82\x8b' '\xe3\u0123\u0133\xe3\u0124\u012d'
と b'\xe3\x81\xa8' '\xe3\u0123\xa8'
雪 b'\xe9\x9b\xaa' '\xe9\u013d\xaa'
国 b'\xe5\x9b\xbd' '\xe5\u013d\xbd'
であった b'\xe3\x81\xa7\xe3\x81\x82\xe3\x81\xa3\xe3\x81\x9f' '\xe3\u0123\xa7\xe3\u0123\u0124\xe3\u0123\xa3\xe3\u0123\u0141'
。 b'\xe3\x80\x82' '\xe3\u0122\u0124'
夜 b'\xe5\xa4\x9c' '\xe5\xa4\u013e'
の b'\xe3\x81\xae' '\xe3\u0123\xae'
底 b'\xe5\xba\x95' '\xe5\xba\u0137'
が b'\xe3\x81\x8c' '\xe3\u0123\u012e'
白 b'\xe7\x99\xbd' '\xe7\u013b\xbd'
くなった b'\xe3\x81\x8f\xe3\x81\xaa\xe3\x81\xa3\xe3\x81\x9f' '\xe3\u0123\u0131\xe3\u0123\xaa\xe3\u0123\xa3\xe3\u0123\u0141'
。 b'\xe3\x80\x82' '\xe3\u0122\u0124'
```

やはり、UTF-8の[Byte-Pair Encoding](https://huggingface.co/learn/nlp-course/chapter6/5)がナマで使われてる(ただし0x00～0x20・0x7f～0x9fはU+0100～U+0120・U+0121～U+0141へマッピング)。しかも「白」「くなった」は切れ目がおかしくて、かなり使いにくそうだ。さて、どうしたらいいかな。
LazyVimのインストールについて

# Lazy Vimについて
Vimを使用したいが、設定やプラグイン探しに疲れたので、比較的簡単に設定できるLazyVimをインストールしてみたのでその備忘録として投稿します。

**※この記事は2024/06時点での記事です。仕様、UI、バージョンなどの変更がされている可能性があります。**

[公式サイト](https://www.lazyvim.org/)

# インストール
## 今回使用する環境
- Windows11 Pro 23H2

## 必要なもののインストール
とりあえず、公式サイトのRequirementsを参考に必要なものをそろえていく。
1\. NeoVim 
windows11なら`winget`があるので、PowerShellから以下のコマンドで、インストールする。

```PowerShell
winget install Neovim.Neovim
```
公式サイトから直接インストールする場合。
[neovim公式サイト](https://neovim.io/)

2\. Git
以下のサイトから取得
[Git公式サイト](https://www.git-scm.com/)

3\. Cコンパイラ
1. 以下のGitHubから、`x86_64-13.2.0-release-posix-seh-msvcrt-rt_v11-rev0.7z`をダウンロード
[MinGW-W64](https://github.com/niXman/mingw-builds-binaries/releases)
![Cコンパイラダウンロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813024/f3cf1131-b8f4-bba1-cd3f-77ed6056611e.png)


2. 7-Zipで解凍する。

3. 適当なディレクトリに配置する。今回は、ProgramFilesに
![スクリーンショット 2024-06-22 224316.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813024/6bc6bc7a-8d59-d293-b8f3-6ea3bc475c8b.png)


4.  `mingw64/bin`のパスを取得する。
![スクリーンショット 2024-06-22 224413.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813024/bba337ae-e78c-adab-0461-393d08102518.png)

5. windowsキー + Pauseキー > システムの詳細設定 > 環境変数
6. ユーザー環境変数の`Path`を選択した状態で、編集を押下 
![環境変数.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813024/115cc7ca-b68e-22c1-1d96-c84d7845d869.png)


7. 先ほどコピーしたパスを張り付ける。
**※パスの前後についているダブルクォーテーションを抜くのを忘れずに**

4\. tarminal
今回は、WezTerm を入れました。以下のリンクから、exeファイルをダウンロードして実行するのみ
[WezTerm ](https://wezfurlong.org/wezterm/installation)
![terminal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813024/10d15606-64a3-6594-b863-b2d65bec2b95.png)


## LazyVimインストール

[公式 Installation](https://www.lazyvim.org/installation)より、PowerShellにてコマンドを実行する。

```PowerShell
Move-Item $env:LOCALAPPDATA\nvim $env:LOCALAPPDATA\nvim.bak
Move-Item $env:LOCALAPPDATA\nvim-data $env:LOCALAPPDATA\nvim-data.bak
git clone https://github.com/LazyVim/starter $env:LOCALAPPDATA\nvim
Remove-Item $env:LOCALAPPDATA\nvim\.git -Recurse -Force
```

## 起動確認
以下のコマンドで起動をする。
```PowerShell
nvim
```

以下の画面になれば完了です。お疲れさまでした。
![スクリーンショット 2024-06-22 231824.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3813024/3497a961-f975-b40b-dcff-bd4553c185f8.png)


# 参考URL
- [MinGW-w64のダウンロードとインストール](https://www.javadrive.jp/cstart/install/index6.html)