OmniAICreator/Qiita-1.07M huggingface dataset:
Windowsを入れ直したら、Gitリポジトリが全滅した話

## 発端
ある日、Cドライブの残り容量が少なくなってきたので一念発起、Windowsをクリーンインストールすることにしました。
主要アプリや作業データなど、必要なデータ類は日頃から別ドライブで保存するようにしているため、特別バックアップの必要なく、さっさとCドライブをフォーマット、Windowsのインストールに進んでいきます。
インストール自体は一時間ほどで終わり、あとはアプリのインストール、作業環境の構築をしていきます。
と、そこでちょっとした違和感に気づきます
あれ？Gitの作業フォルダがリモートリポジトリに接続できない。。

![1718923832875.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181945/64a00769-9312-24b3-de20-fa59942d0c7b.jpeg)
どうもすべての作業フォルダで、ワケのワカランエラーが出て拒否されるようです。
さあたいへんだ
## ぐぐる先生の旅へ
git x is not owned by current user でぐぐる先生にお伺いを立ててみます。
その結果、
> .gitconfigにコマンドを実行する設定を入れることで任意のコマンドを実行させるという攻撃があるので、ディレクトリーの所有者をチェックするようになったみたいです。
https://mas3lab.net/sasai/git-not-owned-by-current-user.html

ということだそうです。（ヨケイナコトヲ。。）
また、この対処としては、
1. リモートリポジトリから必要なリポジトリをCloneしまくる
0. エラーメッセージにあるように git config --global --add safe.directory のコマンドでチェック例外ディレクトリに指定する
0. takeown コマンドでフォルダの所有者を変更

ってとこらへんが見えてきました。
数十ある作業ディレクトリに対処することを考えると、１．は論外。２．ってのも、あんましやりたくない作業量になりそうです。まあ、こんなことでセキュリティを低下させるってのがけったくそ悪い、ってのもあったりします。
残るは３．ですが、なんかバッチファイルでも作って自動化するかー、とか考えていて、ふとGUIの操作でできるんじゃね？と思いつきます。
## 試行錯誤
フォルダのプロパティ画面から、セキュリティタブ、詳細設定ボタンで詳細設定画面が開きます。
そこに所有者の表示があります。
![1718935993808.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181945/e6c53c1f-15a8-7905-8541-71caa512a3de.jpeg)
おお、ワケワカラン所有者表示になってる。。（作業フォルダは修正済みになってるので、別フォルダです）

では、改めてCloneしたフォルダは、というと
![1718936130939.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181945/fcdb3672-626e-f426-cef3-19a8faad9956.jpeg)
もろにアカウント名になってる、ってことで、他の作業フォルダもみんなこのユーザに変更してしまえばええんや、っておはなしとなります。
## 解決編
アクセスできなくなった作業フォルダを右クリックしてプロパティを出します。
セキュリティタブ＞詳細設定ボタンで、詳細設定画面を出し、所有者名を確認します。
所有者名の横の変更のリンクを押します。
ユーザーまたはグループの選択が開きますんで、オブジェクト名の入力欄にユーザ名を入力。私の場合は
アカウント名のメールアドレスを入れて、名前の確認ボタンで、フルのユーザ名が出てきました。
OKボタンを押したあと、詳細設定画面に、サブコンテナーとオブジェクトの所有者を置き換える、のチェックボックスが出てきますんでこれにチェックを入れます（これ重要）。

![1718940367853.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181945/78cc5a9c-eebc-fe7c-5b4b-af0315a03816.jpeg)

で、OKボタンを押せば、めでたく！Gitのリポジトリが復活します。
ばんざーい
VS Code の拡張機能 Background を使ってみた

@Crysta1221 さんの記事【"kawaii"開発環境を作ろう】https://qiita.com/Crysta1221/items/d3e889ae64754d18e312
を読んでやってみました。

画像は
https://sakuranouta.biz/island/
とても素敵な背景ありがとうございます。

ロゴは変えずに背景のみ変えました。

![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812230/ffa4245f-f98a-5378-6dff-fea607d1f08e.png)

簡単に設定できるので、気分によって画像を変えて使おうと思います。
safariだけoffsetTopの値が他のブラウザと違う

## これは何

`offsetTop`を使ってコンポーネントの位置を取得して発火するイベントが、Safariでだけ挙動がおかしくなったので、その原因を探った時の記録です。

## 結論

本来offsetTopは最も近い祖先要素（`offsetParent`）からの距離を取得します。

> The HTMLElement.offsetTop read-only property returns the distance from the outer border of the current element (including its margin) to the top padding edge of the offsetParent, the closest positioned ancestor element.

https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop

この時、最も近い祖先要素の選定方法がブラウザによって異なることが原因でした。

今回の場合、ChromeやFirefoxでは最も近い祖先要素が`section`要素でしたが、Safariでは該当する要素がないため`body`要素となっていました。

### 解決法

ひとまずの解決策として、ChromeやFirefoxで祖先要素になっている`section`に`position: relative`を指定しました。

これにより、Safariでも同じ`section`が祖先要素となり、計算結果が一致するようになりました。

ただ、そもそも`offsetTop`は以下の記事でも紹介されているように挙動が複雑なので、使用しないようにするのが良いと思います。

https://susie-t.hatenadiary.org/entry/20061004/1159942798

## 具体的に起こったこと

ページ内のコンポーネントの位置を`offsetTop`を利用して取得し、コンポーネントの位置までスクロールしたらイベントを発火させる処理を作成していました。

```tsx
const componentPosition =
  componentWrapperRef.current?.offsetTop +
  componentRef.current?.offsetTop

if (scrollY > componentPosition) {
  hogehoge();
}
        
<main>
  <section ref={componentWrapperRef}>
    <div ref={componentRef}>
      {コンポーネントの中身}
    </div>
  </section>
</main>
```

このとき、ChromeやFirefoxでは`componentRef.current?.offsetTop`が`div`から`section`までの距離を返しますが、Safariでは`div`から`main`までの距離を返してしまいました。

結果として、Safariだけイベントが発火する位置がずれてしまっていました。
SevletとJSPで開発していた時に突然特定のページ全体が???になり文字化けする

## Eclipseを使うのはもう新卒だけかもしれないけど

Eclipse、Sevlet、jsp、Tomcatという古代のツールを使って開発していると様々なわけわからないエラーに遭遇します。

### 特定のページだけが文字化けする問題

ServletからJSPにフォワードする仕組みですが突然JSP全体が文字化けというかすべて「???」になりました。これはWindows XP時代に海外のPCを使って日本語を表示させたときに似ていました。

文字化けというか日本語全部が「???」と表示されていました。

ウェブには

**「文字エンコーディングが`UTF-8`になっていること」**

を確認しろとありましたが、その面は全く問題ありません。


### 原因はServletのミス

詳しいことは私の性格上忘れましたがSevletにミスがあったようです
Microsoft 365 OneDriveコマンドでファイルアップロードができない場合の対処法

## 概要
Automation Anywhere A360のOneDriveコマンドを使用してSharePoint上のファイル操作を行う際、
SharePoint側のアクセス設定によって、アップロードコマンドのみ動作しないケースがあります。
今回は、OneDriveコマンドを使用する際にSharePoint側で行うべき設定についてご紹介します。

## アクセス許可設定手順
① 対象フォルダの「アクセス許可を管理」を開く。
② リンクタブの「新しいリンクを作成して共有する」を押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3811534/5d8202a1-f47a-048f-f4f8-c9d8349bb1ce.png)

③ 権限で「編集可能」を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3811534/f04543e5-8f30-b4e7-d612-e768ff92e3d3.png)

④ ユーザー名にAPIアカウントを入力し、「リンクのコピー」を押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3811534/a9729e4a-c3a5-3353-9fa5-54d5813ef21c.png)

⑤ アップロードコマンドに④でコピーしたリンクを設定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3811534/96cfba88-a2c6-ce6d-b505-55237f6f6f85.png)

## まとめ
アップロードコマンドが動作しない場合は、
SharePointのアクセス許可設定を確認してください。
ABC358参加記録　by Python

# リアルタイムに解けた問題

## [A - Welcome to AtCoder Land](https://atcoder.jp/contests/abc358/tasks/abc358_a)

### 問題文
> 高橋くんはAtCoder Landを目指しています。目の前に看板が置かれているので、ここがAtCoder Landであるかどうか判定したいです

文字列$S$,$T$が空白区切りで与えられます。$S=$ <font color="Red">`AtCoder`</font>かつ$T=$ <font color="Red">`Land`</font>であるかどうか判定してください。

### 制約
- $S$,$T$は英大小文字からなる長さ１以上１０以下の文字列

### アルゴリズム
if文で条件分岐。$S$,$T$がそれぞれ<font color="Red">`AtCoder`</font>、$T=$ <font color="Red">`Land`</font>であればYes、そうでなければNoを出力。

### ソースコード
``` python
S, T = input().split()

if S == 'AtCoder' and T == 'Land':
  print('Yes')
else :
  print('No')
```

## [B - Ticket Counter](https://atcoder.jp/contests/abc358/tasks/abc358_b)

### 問題文
AtCoder Landの入口には1つのチケット売り場があり、来園客はこのチケット売り場の前位に一列に並んで順にチケットを購入します。チケットの購入手続きには一人当たり$A$秒かかり、列のセントの人がチケットを購入し終わると、（存在すれば）次の人がすぐさま購入手続きを開始します。

現在チケット売り場に並んでいる人はおらず、今から$N$人の人が順にチケットを買いに来ます。具体的には、$i$番目の人は今から$T_{i}$秒後にチケット売り場を訪れ、すでに列が存在すればその最後尾に並び、存在しなければすぐさま購入手続きを開始します。ここで、$T_{1} < T_{2} < ･・・ < T_{N}$です。

各 $i$ $(1 \leq i \leq N)$について、$i$番目の人がチケットを購入し終わるのは今から何秒後か求めてください。

### 制約
- $1 \leq N \leq N$
- $0 \leq T_{1} < T_{2} <･･･< T_{N} \leq 10^{6}$
- $1 \leq A \leq 10^{6}$
- 入力はすべて整数

### アルゴリズム
チケットの購入タイミングを測るための変数countを定義。
for文でループを回し、$i=0$の時、一人目の購入者は、その人が来た時間にチケットを購入するのにかかる時間$A$を足して出力。$N>1$、二人目以降は、チケット売り場に訪れた時間$T[i]$と変数countとの大小関係で処理を変える。countのほうが大きい場合は、先に訪れた人のチケット購入が終わっていないので、countにAを加えて出力。そうでない場合は、先に訪れた人のチケット購入が終わっているので、countに、$(T[i]-count)$の差と$A$を加えて出力。

### ソースコード
``` python
N, A = map(int, input().split())

T = list(map(int, input().split()))

count = 0

for i in range(N):
  if i == 0:
    count = T[i] + A
    print(count)
  else:
    if T[i] < count:
      count += A
      print(count)
    else:
      count = count + (T[i] - count) + A
      print(count)
```
TomcatサーバーがEclipseで突然起動できなくなってしまう！

# Eclipseって使ってますか？

Eclipseで動的Webアプリケーションプロジェクトをつかって
バックエンドのアプリを作っている新卒向けに書きました。

## 開発途中に突然「Tomcatのサーバーが起動に失敗しました」というアラートが表示される

私は

1. Eclipseを取り換える
1. 設定ファイルを消す
1. 別のワークスペースに切り替える
1. もう1度プロジェクトをクローンしなおす

などいろいろと試しましたがうまくいきませんでした

## 原因はServletのマッピング

Sevletのマッピングに同じ名前があるとサーバー自体起動できなくなるということでした。
新卒の中で同じ問題にあったらぜひServletのマッピングを確認してみてください
`@WebServlet`でアノテーションでつけているパスに同じものがあるとサーバー起動に失敗します。

## 新卒たちもおじさんたちも頑張る！

日々勉強です。与えられた人生を精一杯生きていこうと思いました。
【Python】【matplotlib】NetworkXで描画したグラフを画像として保存できない問題の対処

# はじめに
ネットワークの作成・描画ができるPythonモジュール「NetworkX」にて、描画したグラフを画像として保存する方法で詰まったのでその解決策について紹介します。

:::note warn
今回題材とするのはnetworkXですが、紹介している内容自体はmatplotlibと連携して図表を描画するモジュールすべてに当てはまるものです
:::

# 背景と今回起こった問題
NetworkXには、matplotlibを使って作成したグラフを描画する機能があります。そのため。描画したものもmatplotlibと同様に`plt.savefig('hogehoge.png')`コマンドで保存できる...はずです。実際、これを実装している方もいます（以下リンク参照）。

https://qiita.com/moriaki3193/items/21186bae39d71314cc8f

しかし、自分の環境(Jupyter Notebook)で同じことをしようとした結果、真っ白な画像が保存されてしまい、描画したグラフは映らないのでした…状態としては以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3601602/bf25c94b-15c0-500c-d861-f707de658689.png)

`<Figure size 640x480 with 0 Axes>`というメッセージが出てきています。Axesオブジェクトがない、つまりグラフを構成する要素がないと言われている状況になります。

# 解決策
:::note info
**`nx.draw()`と`plt.savefig()`を同一セルで実行する**だけでした…
:::
Jupyter notebook上で実行するのではなく、Pythonスクリプトとしてコードを実行しても問題なく動作します。

こんなことで引っかかっていたのが恥ずかしい...

~~matplotlibにオブジェクト指向じゃない部分があって分かりにくかったんだ…（言い訳）~~

## この問題の原因
**matplotlibでは、画像表示するプロセスと画像保存するプロセスが競合してしまうことが原因です。**

基本的なmatplotlibの操作であれば、画像表示（`plt.show()`）を行う前に画像保存（`plt.savefig()`）を行えば問題ありません。

しかし、networkxの描画メソッドを使う場合、このアプローチは取れません。作成したネットワークを図表化するには`nx.draw()`や`nx.draw_networkx()`を使う必要がありますが、これらメソッドは「図表の作成」と「図表の表示」の両方の機能を有しており、これらをJupyter notebook上で実行すると必ずグラフが表示されてしまうためです…（※スクリプトとして実行すれば表示されません）

# 参考
networkx同様、matplotlibを使って可視化を行うlibrosaというライブラリを使って画像保存を試みている方がいました。

https://qiita.com/n91-takayuki/items/6efc3f5c267e5d17e0ba

グラフ作成と画像保存を同一セルで実施した上で、`plt.close()`を使えば、そもそも画像表示自体を防げるようです。これはnetworkxでも同様でした。メモリ節約等の目的で、そもそも画像自体の表示を防ぎたい場合はこちらも活用すると良さそうです。

# 最後に
NetworkXの公式リファレンスも貼っておきます。描画方法やメソッドについて詳しく知りたい方はこちらもご参照ください。

https://networkx.org/documentation/stable/reference/drawing.html
ChatGPTにサッカーのデータを解析してもらった

# 目的
ChatGPTにKaggleで手に入るサッカーのデータを解析してもらいました。どういうふうに聞くとデータを解析してくれるのか試してみるのが目的です。結果からすると、あんまり細かく指示しなくてもデータラベルをちゃんと解釈していい感じにデータを解釈してくれます。これはすごいと思う。

元データ：[European Soccer Data🏴󠁧󠁢󠁥󠁮󠁧󠁿🇪🇸🇩🇪🇮🇹🇫🇷](https://www.kaggle.com/datasets/audreyhengruizhang/european-soccer-data)

# Q1:ホームでの勝率が高いチームはどこか
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512829/8261c666-f40a-cf9f-0f0b-e7211672d188.png)

バイエルン・ミュンヘンとレバークーゼンはホームでは８割以上勝つのか。

# Q2:アウェイでの勝率が高いチームはどこか
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512829/b8d6ac47-9227-c326-db95-4770181ad66b.png)

なんとレバークーゼンはアウェイでも８割勝つ。勝率ぶっちぎりで最強か！ホームゲームとの勝率が同じなので、検証してもらったがあっているらしい。まあどちらも試合数が同じだったのでしょう。

# Q3:ホームチームが勝つ場合に前半に点が入る確率
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512829/ca5bde68-90f5-5ca5-db61-c525e6954e0b.png)

ホームが勝利する場合は、77%くらいの確立で前半に点が入る。やっぱり前半が大事ってことね。

# Q4:バイエルン・ミュンヘンが前半に点を入れて勝つ確率
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512829/b894ff3c-9e00-7efe-9dbe-fa1fd2ae6e7a.png)

バイエルン・ミュンヘンはホームゲームで前半に点が入ると９割ぐらいの確立で勝利する。すごいな。やっぱりホームで強豪相手に後半巻き返すのって難しいようだ。

# Q5:勝率とゴール数の相関
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512829/d93df339-857e-fb31-5ec5-00c15c8db50d.png)

勝率とゴール数は密接に結びついている。多くゴールを上げるチームが強い。

# Q6:勝率と前半ゴール数の相関
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512829/b2f4017c-d189-5e93-19d1-7c3288cd6018.png)

前半にゴールを上げられるチームが強いということか。得点力が高いということかね。

# 考察
データの内容自体はまあどうでもいいんですけど、ChatGPTにデータを渡してあとは知りたいことを聞くとちゃんと計算してくれるということがわかりました。エクセルでごにょごにょデータを扱っている人の仕事はなくなりそう。ChatGPTを使えばもっと生産性の高いことに集中できるということですね。
知られざる紙と鉛筆の議事録の世界

# 紙と鉛筆の議事録の世界

こんにちは。
布川シーランド公爵👑です！

地方の、そこそこ歴史の長い中小企業で働いています。

IT企業ではありますが、歴史が長いがゆえに、結構あちこちにアナログな習慣が残っています。
かくいう私自身も入社して数年はバインダーに裏紙を挟み、議事録をとってきました。
（数年前くらいの、ギリギリ平成の話です。）

今ではいろいろと別の手段をとれるようにもなっているのですが、紙と鉛筆の議事録の世界の過渡期の様子をご紹介します。

## 紙と鉛筆での議事録

我々は、週１で部門会議があり、各自、今どのようなジョブをしているのかを共有していました。
書記当番というものがあり、当番は**紙と鉛筆でメモを取ります。**
書記は新人からベテランまで平等に回ってきます。

作成した議事録はテキストファイルを社内のサーバーに置いて、保存場所をメーリングリストで通知します。

それを各々で確認し、間違っていた場合は、サーバーにおいてあるテキストファイルを編集することになります。

とくに会議室に電子機器を持ち込んでいけない事情はありませんが、当時はデスクトップパソコンしか支給されていないため、会議室にパソコンを持ち込むのは現実的ではありませんでした。

全体的に年齢層は高めですが、交代で議事録をとっているように、きつめの上下関係はありません。

## 現在のフロー

議事録はOneNoteに移行しました。
また、テレワーク用にノートPCが支給されるようになっていて、パソコンか手書きかを選ぶことができます。
（社内には根強くアナログメモ派もいますが、会議資料がパソコンを通じて配布されることも多いため、しぶしぶといった形でパソコンに移行しています。）

また、会議自体の開催回数が見直されて、回数自体が減っています。

各自、自分のしている仕事をOneNoteのノートで共有しています。
書記は主に連絡事項などのみを追記します。

とてもラクになりました。

## アナログ議事録の良い点、悪い点

新人にとって、アナログ議事録の作成は大きなハードルがありました。
**まず、新人が耳でのみ情報を聞き取るのは至難の業です。**

それはIT業界の用語であることもあれば、固有名詞であることも、社内でのみ通じるような用語であることもあります。
とにかくそれについていくのでいっぱいいっぱいですが、それに加えて何月何日までに出張だとか誰々さんが××さんというのまで怒涛のように出てくるので頭がパンクします。

会議が終わった後に聞き取れなかった部分を各自に聞きに行き、日付など間違ってはいけない数字を確認し、メーリングリストにシュートします。
不足点があればフィードバックを受けることになります。

### 良い点

- 用語の理解

やっぱり理解していない言葉は耳で聞き取れません。
この聞き取れなかった部分を聞きに行かなきゃならないのがのちのち効いてくるようになります。また、聞かれる側も「ああ、ここがまだわからないんだな」という把握につながり、相互のコミュニケーションができます。

（デジタルメモを取ろうとも同様ではありますが、スピードが出る分メモをし損ねることが少ないです。）

- 要約しながら書かざるを得ない

PCで議事録をとると、人にもよりますが、タイピング速度が出るので、会議の流れをそのままメモしておくのも難しいことではありません。

>A：あ、じゃあ機材〇〇用意しますか？
B：いや、あそこはそれはいらないはず。でも購入してもいいかもね。
C：稟議にかけましょう。

みたいなメモをとれなくもないですが、議事録的には

>・機材〇〇は不要。ただ、予備として購入するのはあり。稟議。

といったように要約するのが望ましい（＊求められている形式による）です。

このあたりが、制約によって自然と身につくようになります。

- アナログな議事録を取らなくてはならないシチュエーションも存在する

たとえば現場や、お取引様との会議の時など、ノートPCが使用できないシチュエーションが存在します。
アナログメモは気にしないけど、パソコンを開かれるとムッとするようなお客さんも実はおります。
そんなときにアナログでメモができると便利です。

### 悪い点

・工数がかかる

メリットがないわけではないのですが、上のことは本当にめんどくさいわけです。

## DXが進んだきっかけ

チームが紙と鉛筆を脱したのは、アナログ解放運動でもない、陳情でもない、社内の働き方改革でもない、コロナ禍によるテレワークの導入とノートパソコンの支給でした。
（おそらく、国の補助があったことが大きい）。

それまでは全社員デスクトップPCで、メモを取る手段がアナログ以外存在しなかったのです。

それからSlackと少しずつデジタルな環境がそろっていったときに、チームのひとりがOneNoteで議事録をとってみるのはどうかと提案して、「じゃあ試しに……」とやっていって、それ以降「変えよう」という動きはなく、音沙汰がなくなり、事実上承認されました。

# まとめ

- 紙も悪いところばかりではない
- 根強い支持者がいるやり方を変えたいときは、声をあげたり、「こうしましょう！」とやるよりも環境を作って実績を積むほうが早い（体感） 

私はすっかりデジタルに移行しましたが、依然として紙と鉛筆派もいます。

「このやり方にもメリットがあって、できるようになっておくと将来役に立つから」といってしてきたもんですが、下の人たちはアナログメモの習慣を通ってきていません。
違いはあまり実感できていません（笑）

元気よく「ハイ！」と言って、やり方を踏襲しつつ……効果のほどはあんまり真には受けず、フローの改善点を探っていくこと、ヌルっと便利にしていくことが大切なのではないかと思います。
（今回はテレワークでノートパソコンが使用できるようになったのが、本当に追い風でした。）

ツールを提案して、試用してもらったとき、**「あ、これ、いいね。ふーん……」となって何も言わなくなったら勝ち**です。

# 補足

社内探検ツアーをするたびに１６インチフロッピーや手書きのフローチャート用の定規なんかを発掘していると、ガチのアナログの時代というのを感じます。
古臭さは一方で連綿と受け継がれてきた技術でもあるわけです。
楽にお仕事していきたいので、便利にしていきたいとは強く思うのですが、枯れた技術への敬意も忘れずに持ちたいものです。
【ChatGPT＋DALL-E3】【Dream Machine】の動画をアニメGIFに変換。


　どうも、カーブミラーです。

　今回は、Dream Machineの動画をアニメGIFに変換します。たぶん、ほかの動画も可能（未確認）

:::note info
本記事は、ChatGPT（有料版）
＋DALL-E3で行なっております。
画像はありません。あしからず。
:::

　まずは、BIGニュース。

　AnthropicのClaudeが、
　　バージョンアップして
　　　Claude 3.5となりました。

　現在、我々に提供されている
　　モデルのうち、Sonnetが
　　　バージョンアップされて
　　　　います。

　Claude 3 Opusの
　　2倍の速度で
　　　これまでの5分の1のコスト。

　ほかのモデルも
　　今後数ヶ月で
　　　バージョンアップされるとか。

　また新しく、
　　"Artifacts"という新機能が登場。
　　　これがまたすごい。

　　・ゲーム（音付き）開発して遊べる
　　　　シミュレーションゲーム
　　　　横スクロールゲーム
　　　　3Dシューティングゲーム　他
　　・フローチャート作成
　　・マークダウンの表示
　　・SVGでの描画
　　・アニメ作成
　　・簡単なUIの作成・表示
　　・スライド作成

　　ようするに、Code Interpreterの
　　　環境を用意して、そこで
　　　　実行するわけです。

　　わからんでしょ😅

　　画面上、左手側はこれまでのもの
　　　右手側に描画エリアが出てきて
　　　　遊べる感じです。

　また、
　　言語能力の向上とともに
　　　Vision系の能力も向上しています。

　　細かい文字も認識したり
　　　画像からUIを作成したりが
　　　　簡単にできてしまうのです。

　上記はすべて
　　2024/06/20の23時の
　　　Anthropicのポストから
　　　　はじまったX-Twitter民の
　　　　　ポストをまとめたものです。

　詳しくはこちらをどうぞ。
　　[木内翔大さんポスト](https://x.com/shota7180/status/1803803341161713989?t=VkM7B7T95tk7dEzqZIQbGw&s=19)
***
　さて、本題です。

　今回は、
　　動画をアニメGIFに変換します。

　なぜ、アニメGIFにするのか？

　だって、
　　QiitaにMP4そのままじゃ
　　　アップできない
　　　　じゃないですかw

　理由は、それだけです😅

　それでも
　　場面によっては
　　　使うこともあると思います。
***
　さて、やり方です。

　動画をアップロード。

　下記Promptを入力。
```Text:アニメGIF化Prompt
この動画をMoviePyでアニメGIFにしてください。
```
（2024/06/22更新↓）
　上記だと、サイズが大きくなります。
　こちらはカクカクしますが、
　　サイズは抑えられます。
```Text:アニメGIF化Prompt
この動画をファイルサイズをあまり変えずに、MoviePyでアニメGIFにしてください。
```
（2024/06/22更新↑）
　で、送信。

　処理が終われば、
　　ダウンロードリンクが
　　　表示され、タップすれば
　　　　ダウンロードされます。

　明日は、
　　動画を白黒に変換する予定。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
GoでRedisを使ったときの基本の備忘録

本記事は業務で利用したGoとRedisを使ったときの備忘録です。

AWSのElaticacheを使い、GoのRedisクライアントは`github.com/go-redis/redis/v8`を使うのが一般的のようだったのでその使い方をまとめる。

（Get、Setの基本のみ書くため、詳細は公式ドキュメントを参照してください）

## GoでRedisを使う

大まかな流れは

1. Redisクライアントを作成
1. Redisの操作

という超シンプルな流れです。

### Redisクライアントを作成

go-redis/redisのクライアントを作成するには、`NewClient`を使います。

```go
import (
    "context"
    "fmt"
    "github.com/go-redis/redis/v8"
)

func NewRedisClient() *redis.Client {
    rdb := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379",
        Password: "", // no password set
        DB:       0,  // use default DB
    })

    return rdb
}

```

Redisのアドレス、パスワード、DBを指定して`NewClient`を使ってクライアントを作成します。

Optionsにはリトライ回数やタイムアウトと、プールサイズなども指定できます。

### Redisの操作

超基本の使い方のデータをセットする、データを取得するを書いてみます。

```go
func SetData(ctx context.Context, rdb *redis.Client, key string, value string) error {
    err := rdb.Set(ctx, key, value, 0).Err()
    if err != nil {
        return fmt.Errorf("failed to set data: %w", err)
    }

    return nil
}

func GetData(ctx context.Context, rdb *redis.Client, key string) (string, error) {
    val, err := rdb.Get(ctx, key).Result()
    if err != nil {
        return "", fmt.Errorf("failed to get data: %w", err)
    }

    return val, nil
}

// SetDataとGetDataの使い方

func ExecuteSetAndGet() {
    // Redisクライアントを作成
    ctx := context.Background()
    rdb := NewRedisClient

    // データをセット
    err := SetData(ctx, rdb, "key", "value")
    if err != nil {
        fmt.Println(err)
    }

    // データを取得
    val, err := GetData(ctx, rdb, "key")
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(val)
}

```

ここでGetの戻り値の方について解説します。


上記の書き方をすると`GetData`関数の`rdb.Get`は[StringCmd型](https://pkg.go.dev/github.com/go-redis/redis/v8#StringCmd)を返します。
StringCmdのResultで返される第一返り値は`string`です。

一方でStringCmdからIntCmdやFloatCmdに変換して`int`や`float`などの型に変換することもできます。

```go
// int型を返す
func GetIntData(ctx context.Context, rdb *redis.Client, key string) (int, error) {
    val, err := rdb.Get(ctx, key).Int()
    if err != nil {
        return 0, fmt.Errorf("failed to get data: %w", err)
    }

    return val, nil
}

// float64型を返す
func GetFloatData(ctx context.Context, rdb *redis.Client, key string) (float64, error) {
    val, err := rdb.Get(ctx, key).Float64()
    if err != nil {
        return 0, fmt.Errorf("failed to get data: %w", err)
    }

    return val, nil
}

```

## 最後に

GoでRedisを使うときの基本の使い方をまとめました。

インメモリデータベースとして使うことでパフォーマンスを向上させることができるので、ぜひ使ってみてください。
⑩１日１０分で理解するコンテナ技術入門 - Docker Composeまとめ -

ここまで紹介してきたdocker composeの基本的な部分のまとめです。

 # docker composeでよく使うコマンド
 ```bash
 docker compose up -d # バックグラウンドでサービスを起動
 docker compose up -d --build # ビルドから行う
 docker compose up -d --scale <service_name>=<num> # スケール
 docker compose down -v # ネットワークやボリュームを削除し、コンテナを停止
 docker compose logs # サービスのログを確認
 ```

 # docker-compose.yamlの基本的な書き方
 ```yaml:docker-composeのサンプル
version: '3.8'

services:
  db:
    image: mysql:8.0
    container_name: mysql
    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_DATABASE=flask_app
    networks:
      - flask-net
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root -ppassword || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 5

  web:
    build: .
    ports:
      - "5000" # コンテナ側のみ指定
    networks:
      - flask-net
    volumes:
      - ./uploads:/app/uploads
    depends_on:
      db:
        condition: service_healthy
    environment:
      - DATABASE_HOST=db
      - DATABASE_USER=root
      - DATABASE_PASSWORD=password
      - DATABASE_NAME=flask_app
    restart: unless-stopped

networks:
  flask-net:
    driver: bridge

volumes:
  web-data:
    driver: local
```
最上位レイヤーには、`version`, `services`, `volumes`, `networks`を書く。
## services
サービス名とコンテナに関する設定を行う。ローカルのDockerfileからビルドする場合は`build`フィールドにDockerfileのパスを記述する。既存のイメージから起動する場合は`image`にイメージ名を記述する。
そのほか、コンテナ起動時に必要な設定（ボリュームやネットワーク、ポートなど）を記述する。また、サービス間の依存関係も記述する。例では、DBが起動してからwebが起動する。

## volumes
このセクションに記述する場合、名前付きボリュームになる。複数のコンテナで共有することができる。

## networks
使用するネットワークを定義する。

# まとめ
以上、docker composeの簡単な紹介でした。docker composeは、複数のコンテナを一つのyamlファイルで管理することができるので、起動順序など複雑なことを後から考える必要がなくなり、非常に便利なツールです。また、コンテナのスケールにも対応しています。しかし、docker composeでは単一のホストにしかコンテナをデプロイすることができないため、分散して配置することはできません。また、高度なセルフヒーリング機能なども備えておらず、簡単に扱える一方、できることは限定的です。

次回から、より高度にコンテナを管理することができるコンテナオーケストレーションツールである、Kubernetesについて説明していきたいと思います。
Google Cloud Storageのクラスとユースケース

## はじめに
Google Cloud Storageは、データの保存ニーズに応じて異なるクラスを提供しています。各クラスは、データのアクセス頻度やコスト効率に基づいて最適化されています。以下に、主要なCloud Storageクラスとそのユースケースについて表形式で説明します。

| クラス             | 特徴                                          | ユースケース                                |
|--------------------|-----------------------------------------------|---------------------------------------------|
| **Standard Storage** | 高可用性（99.99%）、低レイテンシー、地域冗長 | 頻繁にアクセスされるデータ<br>例：Webサイトコンテンツ、アプリケーションデータ |
| **Nearline Storage** | データアクセス頻度が低い、適度な取り出しコストと短いアクセス時間 | 月に1回程度のアクセス<br>例：バックアップ、長期保存データ |
| **Coldline Storage** | アクセス頻度が非常に低い、長期間保管するデータ向け、保管コストが安い | 年に1回未満のアクセス<br>例：アーカイブデータ、災害復旧データ |
| **Archive Storage** | 最も安い保管コスト、数年に一度のアクセス向け | 極めて低頻度のアクセス<br>例：法規制による長期保存データ |

## Standard Storage

**Standard Storage**は、頻繁にアクセスされるデータ向けのデフォルトストレージクラスです。低レイテンシーで高い可用性を提供し、データの読み書きが頻繁なシナリオに最適です。

- **高可用性**：99.99%の可用性を提供
- **低レイテンシー**：迅速なデータアクセス
- **地域冗長**：リージョン内の複数の場所にデータを保存

#### ユースケース
- **Webサイトコンテンツ**：頻繁にアクセスされる画像や動画ファイル
- **アプリケーションデータ**：ユーザー生成コンテンツやリアルタイムデータ

## Nearline Storage

**Nearline Storage**は、データアクセス頻度が低く、コストを抑えたいシナリオ向けのCloud Storageクラスです。適度な取り出しコストと短いアクセス時間を提供します。

- **低コスト**：データ保存コストが低い
- **適度な取り出しコスト**：取り出し回数に応じたコスト
- **短いアクセス時間**：迅速なデータアクセスが可能

#### ユースケース
- **バックアップ**：月に1回程度のデータ復旧
- **長期保存データ**：定期的にアクセスする必要のあるデータ

## Coldline Storage

**Coldline Storage**は、アクセス頻度が非常に低い、アーカイブデータなど長期間保管するデータ向けのCloud Storageクラスです。保管コストが最も安いですが、取り出しコストは高めです。

- **非常に低コスト**：データ保存コストが極めて低い
- **高取り出しコスト**：データ取り出し時のコストが高い
- **長期保存**：データを数年間保存するのに適している

#### ユースケース
- **アーカイブデータ**：年に1回未満のアクセス
- **災害復旧データ**：非常時のみアクセスするデータ

### Archive Storage

*Archive Storage**は、最も低コストで長期保存が可能なストレージクラスです。数年に一度のアクセスを想定したデータに最適です。

- **最低の保存コスト**：非常に低いデータ保存コスト
- **長期保存**：数年以上の長期保存向け
- **取り出しに時間がかかる**：データ取り出しに時間がかかる

#### ユースケース
- **法規制による長期保存データ**：数年間保存が義務付けられているデータ
- **歴史的データ**：研究用の古いデータ

## 最後に
各Cloud Storageクラスは、データのアクセス頻度とコスト効率に基づいて選択されるべきです。ユースケースに応じて適切なクラスを選択することで、効率的かつ経済的なデータ管理が可能になります。
Disable/Enable時のUniTaskを制御する

UniTaskは便利ですが、スクリプトをアタッチしているGameObject や 自身のComponentがDisabledになったとき、またGameObjectがDeleteされた時もタスクが残ってしまいます。

| (1)Active all | (2)Disable GameObject | (3)Disable Component |(4)Delete GameObject|
|:-:|:-:|:-:|:-:|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/5ae95606-366f-17d6-149c-1209c81f0f9b.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/2320a78f-2ee4-7ab6-21da-83cd85f4e708.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/c76768b1-bead-9ae6-b628-6ce2a668241f.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/2e8a480b-9bf2-f9eb-b69c-582e5219b70a.png)|
| 動き続ける | 動き続ける | 動き続ける | 動き続ける |

Coroutineの時とは違い、常に動き続けているので、(1)-(3)の対応は
```await UniTask.WaitUntil(() => this.isActiveAndEnabled)```
のみでよさそうです。

(4)については、```System.Threading.CancellationToken```をタスクに渡すことで自動的にタスクを削除してくれるようになります。

```
using UnityEngine;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using System.Threading;

[HelpURL("https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.html")]
public class UniTaskActiveCheck : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Start");
        System.Threading.CancellationToken ct = this.GetCancellationTokenOnDestroy();
        Task0(ct).Forget();
    }

    // Update is called once per frame
    void Update()
    {
    }

    async UniTask Task0(CancellationToken ct)
    {
        int m_count = 0;
        while (true)
        {
            await UniTask.WaitUntil(() => this.isActiveAndEnabled, cancellationToken: ct);
            Debug.Log($"Task0: {m_count}");
            m_count++;
            await Task.Delay(1000, ct);
        }
    }

    private void OnDisable()
    {
        Debug.Log("OnDisable");
    }
    private void OnEnable()
    {
        Debug.Log("OnEnable");
    }
    private void OnDestroy()
    {
        Debug.Log("[OnDestroy]");
    }
}

```

```await UniTask.WaitUntil()```の期間中はタスクが一つ増えます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/22bbe6f3-c84a-5cf5-e6cf-1756a513a60f.png)


コルーチンの制御については[こちら](https://qiita.com/ELIXIR/items/fb32aa8124c117aa83d7)
Awaitableの制御については[こちら](https://qiita.com/ELIXIR/items/70b1eb7a068853d9b408)
READMEファイルの書き方


# READMEファイルに盛り込むべき情報

アプリケーションのREADMEファイルを作成するにあたっては、複数のアプリケーションで使用できる標準形式を考えて、標準形式に従ってテンプレートを作成する必要があります。

以下のようにREADMEに盛り込むべきテンプレートを示しておきます。


| 要素 | 説明 |
|------|------|
| プロジェクトタイトル | プロジェクトタイトルかそれに類するものを必ず含めておきます |
| プロジェクト<br />の説明 | プロジェクトの一環として「プロジェクトの作成方法」セクションを含めておきます |
| 目次 | 全主要セクションの一覧 |
| インストール方法 | 明確なインストール方法を順次、提供できるように記載します |
| 使用方法 | 基本的なコマンドなどを記載します。サポートポータルの詳細ドキュメントやチュートリアルへのリンクを記載しておきます |
| 構成方法 | 構成が必要なソフトウェアプロジェクトの場合、各構成オプションの内容を詳しく説明する構成ファイルやコマンドの引数の例を記載しておきます |
| 依存関係 | 必要な依存関係を記載しておきます。インストールするための指示やスクリプトを記載しておきます |
| トラブルシューティング | よくある問題点と解決方法を記載しておきます |
| 貢献者 | このプロジェクトに貢献している方々などを記載しておきます |
| 教訓 | 開発中に習得した教訓を、READMEファイルを使って共有しておきます |
| ライセンス | ソフトウェアのライセンスのタイプとライセンスへのリンクを明記しておきます |
| 連絡先 | サポートや問い合わせのための連絡先情報(メールアドレスやサポートポータルへのリンク)を盛り込む |

## まとめ

多くの技術ドキュメントと同様、READMEファイルがじっくりと読まれることは少ないです。

そのため、ざっと読み流しできるように、わかりやすい言葉、説明的な見出し、論理的な構造を使って、専門的な用語は使わないようにします。

アプリケーションの使用方法を明確に示すように、コードスニペットやスクリーンショットなどの例を豊富に記載しておきます。

アプリケーションが複雑な場合は特に、ドキュメント、問題点、サポート・トレーニングのコンテンツを公開します。

ドキュメント計画だけでなく、プロジェクトの全体計画を含める必要があります。
製品リリースの直前に、READMEファイル全体を慌てて1から作成することのように、リリースの数日前から繰り返しアップデートができるようにしておくようにしましょう。
闘魂Elixir ーー AtCoder Beginner Contest 333(A)をElixirで楽しむ

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>

<b><font color="red">$\huge{闘魂とは己に打ち克つこと。}$</font></b>
<b><font color="red">$\huge{そして闘いを通じて己の魂を磨いていく}$</font></b>
<b><font color="red">$\huge{ことだと思います}$</font></b>


# はじめに

[AtCoder Beginner Contest 333](https://atcoder.jp/contests/abc333)を[Elixir](https://elixir-lang.org/)で解いてみます。

[AtCoder](https://atcoder.jp/)を解くのが趣味で、休憩時間に解いているという若い人がいて、それってすごい意識の高い休憩時間の過ごし方だと思って、私も真似してみることにしました。


# [AtCoderをElixirでやってみる](https://zenn.dev/torifukukaiou/articles/ac84c87736ceebf4da01)

入力の読み取り方や解答の作り方は、別の記事にまとめています。


https://zenn.dev/torifukukaiou/articles/ac84c87736ceebf4da01

ご参照くださいませ。

[Elixir](https://elixir-lang.org/)で[AtCoder](https://atcoder.jp/)を楽しむためには、エントリポイントを`Main.main/0`にする必要があります。つまり`Main`モジュールを作って、その中に`main/0`関数を定義するわけです。

# [A - Three Threes](https://atcoder.jp/contests/abc333/tasks/abc333_a)

問題はリンク先をご参照くださいませ。
私の解答を貼っておきます。


<details><summary>私の解答</summary>

_問題文を読んでいることを前提にひとこと解説をしておきます。_


文字列の複製には、[String.duplicate/2](https://hexdocs.pm/elixir/String.html#duplicate/2)を使いました。

```elixir
defmodule Main do
  def main do
    n = IO.read(:line) |> String.trim() #String.to_integer()
    
    String.duplicate(n, String.to_integer(n))
    |> IO.puts()
  end
end
```




</details>




---

# さいごに

[AtCoder Beginner Contest 333](https://atcoder.jp/contests/abc333)を[Elixir](https://elixir-lang.org/)で解くことを楽しみました。

あなたのお好きなプログラミング言語でお楽しみください。

---


**闘魂**とは、  **「己に打ち克つこと。そして闘いを通じて己の魂を磨いていくことである」** との猪木さんの言葉をそのまま胸に刻み込んでいます。
知っているだけで終わらせることなく、実行する、断行する、一歩を踏み出すことを自らの行動で示していきたいとおもいます。
**アントニオ猪木さんのメッセージから元氣をもらったものとして、それを次代に語り継ぎ、自分自身が「闘魂」を体現するものでありたいとおもいます。**

---

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>
<b><font color="red">$\huge{１、２、３ ぁっダァー！}$</font></b>
【Figma Plugins】Figma Pluginsからサムネイルを設定する

## はじめに
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/870e8bef-8502-286d-1d81-7b297532478f.png)

FigmaのPluginを開発する際、Figma Pluginsからファイルのサムネイルを設定したいと思ったことはありますか？
この記事では、Figma Pluginsからファイルのサムネイルを設定する方法を解説します。

## Figma Pluginsからファイルのサムネイルを設定する
Figma Pluginsからファイルのサムネイルを設定するには、`figma.setFileThumbnailNodeAsync()`を使うことで、設定することができます。

引数には、`FrameNode`・`ComponentNode`・`ComponentSetNode`・`SectionNode`・`null` を受け取ることができます。

*※ `ComponentNode`・`ComponentSetNode`には、`InstanceNode` が含まれていないので、注意してください。*

```ts
figma.setFileThumbnailNodeAsync(
    node: FrameNode | ComponentNode | ComponentSetNode | SectionNode | null
): Promise<void>
```

詳しくは、以下をリンクをご確認ください。

https://www.figma.com/plugin-docs/api/figma/#setfilethumbnailnodeasync

## 実際に使ってみる

```code.ts
const setThumbnail = async() => {
  // text を生成する
  const text = figma.createText()
  await figma.loadFontAsync(text.fontName as FontName)
  text.characters = 'This is Thumbnail'
  text.fontSize = 20

  // Auto Layout が設定されているFrameを生成する
  const thumbnailFrame = figma.createFrame()
  thumbnailFrame.appendChild(text)
  thumbnailFrame.layoutMode = "HORIZONTAL"
  thumbnailFrame.resize(640, 360)

  // サムネイルを設定する
  await figma.setFileThumbnailNodeAsync(thumbnailFrame)
}
```

こんな感じに記載することで、シンプルですが、以下のようなサムネイルを設定することができます。

![スクリーンショット 2024-06-18 1.49.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/a3f12a0c-92ee-bc85-1f51-db1d95c6510c.png)


## まとめ

この記事では、Figma Pluginsからファイルのサムネイルを設定する方法を解説しました。

ぜひこの記事を参考にFigma Pluginsからファイルのサムネイルを設定してみてください。

---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaで記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510
【CSS】一部のスマホで動画再生中に動画上の画像が見えなくなる問題の解決方法

ウェブページで動画を再生する際、一部のスマホでは、動画の上に配置した画像やボタンが見えなくなることがあります。この問題は、CSSの`transform`プロパティを使用して解決できました。

## 確認環境
- **デバイス**: iPhone X
- **ブラウザ**: Chrome、Safari

## 問題の概要

以下のようなHTMLとCSSを使用している場合、一部のスマホで動画を再生すると、動画の上に配置したロゴや音量ボタンが見えなくなることがあります。


これらのブラウザでは、特にiOSの仕様により、動画要素のレンダリングが他の要素と異なる方法で処理されるため、このような問題が発生するようです。



### HTML

```html
<section class="sec-kv">
    <div class="video-wrap">
        <div class="l-cont">
            <p class="kv_logo">
                <img src="path/to/logo.png" alt="ロゴ">
            </p>
        </div>
        <video autoplay muted loop playsinline poster="path/to/poster.jpg">
            <source src="path/to/video.mp4" type="video/mp4">
        </video>
        <div class="musicbtn-wrap">
            <p id="play"><i class="fas fa-volume-up"></i></p>
            <p id="stop" class="active"><i class="fas fa-volume-mute"></i></p>
        </div>
    </div>
</section>
```

### CSS

```css
.sec-kv .video-wrap {
    position: relative;
}

.sec-kv .video-wrap video {
    width: 100%;
}

.sec-kv .video-wrap .l-cont {
    position: absolute;
    z-index: 1;
}

.sec-kv .video-wrap .musicbtn-wrap {
    position: absolute;
    z-index: 2;
}

```

## 解決方法
上記のコードでは、動画が他の要素の前に表示されてしまうことがあります。この問題を解決するためには、CSSのtransform: translateZ(0)を使用します。これにより、GPUを使用してレンダリングされるようになり、動画のz-indexの問題が解消されます。

### 修正後のCSS

```css
.sec-kv .video-wrap {
    width: 100%;
    position: relative;
    overflow: hidden;
}

.sec-kv .video-wrap video {
    width: 100%;
    -webkit-transform: translateZ(0); /* GPUレンダリングを有効に */
    transform: translateZ(0);         /* GPUレンダリングを有効に */
}

```

この修正により、動画の上に他の要素が正しく表示されるようになります。具体的には、transform: translateZ(0)を追加することで、動画がGPUレンダリングされるようになり、z-indexの問題が解消されます。

## まとめ
一部のスマホで動画を再生すると動画の上に配置した画像やボタンが見えなくなる問題は、CSSのtransform: translateZ(0)を使用することで解決できます。この方法で、動画がGPUレンダリングされるようになり、他の要素が正しく表示されるようになります。
groundingDinoについて調査中　ー任意の言葉で物体検出ー

# 主旨
Open Vocaburary での物体検出ができる時代がやってきた。
そのライブラリがNVIDIA Jetson上でも動く。　
その情報の詳細にたどり着くためのリンクを示す。

## GroundingDino
![Screenshot from 2024-06-20 22-05-19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83761/c73987be-a076-71be-a1ac-f527c2055577.png)
https://github.com/IDEA-Research/GroundingDINO

![Screenshot from 2024-06-20 22-07-30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83761/ae8ce5f7-4dc6-a0b6-c11b-319f94f28988.png)

![Screenshot from 2024-06-20 22-10-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83761/94af233c-f713-bd4c-4045-28df4bb58ce8.png)
他のアプリケーションと組合せて画像の加工する例も書かれている。
まず、本家github, 論文を見て、自分のほしいものであるかを確かめよう。

### 何がうれしいのか
- 今までだと、特定のカテゴリの対象物だけを検出する検出器ばかりだった。
- しかも、学習結果は、カテゴリ番号何番というオブジェクトが見つかったという結果を返すのに十分なだけであって、ネコを検出したからといって"cat" などの自然言語になんら関係性を持たなかった。
- 視覚を含む大規模言語モデルでは、学習後のモデルの中に"cat"などの自然言語の情報を含んでいる。
- そのため、"black cat"　というプロンプトを元に、黒猫を見つけることができるようになっている。


## groundingDinoについての関連情報
- qiita 記事[GroundingDINOの使い方](https://qiita.com/HFMS/items/a21224983aa6e4ff6707)
    - インストールする方法が日本語で書かれている。

- NVIDIA　のGPU　向けの（Jetson 向けでもある）の情報がある。
https://docs.nvidia.com/tao/tao-toolkit/text/ds_tao/dino_ds.html
ということは、これをヒントにしてJetson用として動作させることができる。


- [Grounding DINO のインストールと動作確認（ゼロショットの物体検出とセグメンテーション） （Python，PyTorch を使用）（Windows 上）](https://www.kkaneko.jp/ai/win/groundingdino.html)
    - Windows上での動作例が書かれています。

- [Realtime Language-Segment-Anything on Jetson Orin](https://www.hackster.io/lurst811/realtime-language-segment-anything-on-jetson-orin-ccf6e1)
    - Segment Anything Model(SAM) との連携例が書かれています。

- [Groundingdino deployed in Docker](https://medium.com/@deandu/groundingdino-deployed-in-docker-e6ba708ba480)
Playwright で部分スクロールが出来ない場合の解決策はクリックで

# 問題

ページ本体ではなく、ページ内に部分スクロールできる要素がある場合
Playwrightでスクロール処理が出来ない

次のようなものを試してみたが無理だった

```ts
await page.mouse.move(0, 0)
await page.mouse.down()
await mouse.wheel(deltaX, deltaY)
await page.keyboard.press('PageDown')
```

https://playwright.dev/docs/api/class-mouse

https://playwright.dev/docs/api/class-keyboard

# 解決

スクロールさせたい位置にある要素をクリックすることで、ページ位置がそこまで移動してくれるので、これで暫定解決した

HTML

```html
<div data-testid="wanna-scroll-to">
なにかの要素
</div>
```

Playwright

```js
await page.getByTestId('wanna-scroll-to').click()
```

ただし当たり前だがクリック処理も起こってしまい、副作用が出る場合もあるので注意


# チャットメンバー募集


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

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


# プロフィール・経歴

https://github.com/YumaInaura/YumaInaura
AWS上に作ったk3sクラスタの証明書作り直し

せっかく作ったk3sクラスタですからローカル(Windows10)から接続して、色々試したいわけです。しかし、k3sクラスタを起動するのが久しぶりであったせいか、k3s内部証明書が期限切れしてしまったようです（デフォルトでは期限は1年）。また、同時にAWS Client VPNを使ってアクセスしようと思ったので、これを機に設定その他を見直しました。

以前に[似たような記事](https://qiita.com/yasuyuki_terashi/items/9f634fe6154ec13fdf96)を書きましたが、TLS認証を無理やりスキップするような内容だったので、あまりよくない記事だったと思います。色々試しながら以下のやり方に行きつきました(正しいと言い切る自信はない)。

# 手順
以下の操作は全て、k3sのコントロールプレーンのノードで行います。
### secrets/k3s-serving の変更


AWS Client VPNを利用して接続することとしたので、Windows端末側のIPアドレスを設定してあげる必要があります。調べるとWindows側は192.168.252.0/22の中から割り当てられる事が分かりました。
`sudo kubectl -n kube-system edit secrets/k3s-serving`
を叩くとエディタが開くので(苦手な)viを操作し

```diff_yaml
metadata:
  annotations:
    listener.cattle.io/cn-__1-f16284: ::1
    listener.cattle.io/cn-10.43.0.1: 10.43.0.1
    listener.cattle.io/cn-127.0.0.1: 127.0.0.1
    listener.cattle.io/cn-172.31.42.76: 172.31.42.76
    listener.cattle.io/cn-172.31.46.204: 172.31.46.204
    listener.cattle.io/cn-172.31.47.52: 172.31.47.52
    listener.cattle.io/cn-ip-172-31-42-76: ip-172-31-42-76
    listener.cattle.io/cn-ip-172-31-46-204: ip-172-31-46-204
    listener.cattle.io/cn-ip-172-31-47-52: ip-172-31-47-52
+   listener.cattle.io/cn-ip-192-168-252-0: 192.168.252.0/22
    #(以下略)
```
と追記します。

### キャッシュされた証明書の削除
kubernetes シークレットからキャッシュされた(期限切れ)証明書を削除します。
`sudo kubectl -n kube-system edit secrets/k3s-serving`

### k3s停止
証明書を作り直すために、一時停止します。
`sudo systemctl stop k3s`

### 証明書のローテーション
念のため先に、dynamic-cert.jsonを削除しておきます。
`sudo rm /var/lib/rancher/k3s/server/tls/dynamic-cert.json`
次に証明書を再作成します。
`sudo k3s certificate rotate`

### k3s再スタート
`sudo systemctl start k3s`

# .kube/configを再確認
`sudo cat /etc/rancher/k3s/k3s.yaml`の中身を参考に、Windows端末側の.kube/configファイルを見直しました。

以上で、再び接続が可能になりました。

# 参考URL
以下の記事が参考になりました。ありがとうございました。
[k3sクラスタを立ち上げたあとに、control-planeのIPアドレスを変えた時の対処方法](https://zenn.dev/yakumo/articles/7d875e709480c5)
[期限切れの K3s 証明書は自動ローテーションされないため接続問題が発生します](https://www.ibm.com/support/pages/soar-%E6%9C%9F%E9%99%90%E5%88%87%E3%82%8C%E3%81%AE-k3s-%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%81%AF%E8%87%AA%E5%8B%95%E3%83%AD%E3%83%BC%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%95%E3%82%8C%E3%81%AA%E3%81%84%E3%81%9F%E3%82%81%E6%8E%A5%E7%B6%9A%E5%95%8F%E9%A1%8C%E3%81%8C%E7%99%BA%E7%94%9F%E3%81%97%E3%81%BE%E3%81%99)
(Rust)ファイルを追記書き込みしたい

:::note warn
私的メモです。
理解足らずによる不備などあるかもしれません。
実行バージョンは 1.79.0 です。
:::

---

`OpenOption`の`write(bool)`、`append(bool)`をtrueにすることで追記の書き込みが可能になります。

```text:追記前のテキスト(sample.txt)
カレーライス
オムライス

```

```rust:書き込みコード
use std::fs::{OpenOptions};
use std::io::{BufWriter, Write};

fn main() {
  let f = OpenOptions::new()
    .write(true)
    .append(true)
    .open("sample.txt").unwrap();
  let mut bw = BufWriter::new(f);

  bw.write("ハンバーグ定食\n".as_bytes()).unwrap();
  bw.flush().unwrap();
}
```

```text:ハンバーグ定食が追記されます
カレーライス
オムライス
ハンバーグ定食

```
---
### おまけ
```rust:書き込み内容も出力するコード
use std::fs::{OpenOptions};
use std::io::{BufRead, BufReader, BufWriter, Write};

fn main() {
  let f = OpenOptions::new()
    .write(true)
    .append(true)
    .open("sample.txt").unwrap();
  let mut bw = BufWriter::new(f);

  bw.write("ハンバーグ定食\n".as_bytes()).unwrap();
  bw.flush().unwrap();

  let f = OpenOptions::new()
    .read(true)
    .open("sample.txt").unwrap();

  let bf = BufReader::new(f);

  let mut vec = Vec::new();

  for line in bf.lines() {
    vec.push(line.unwrap());
  }

  println!("{vec:#?}");
}
```
```text:結果
[
    "カレーライス",
    "オムライス",
    "ハンバーグ定食",
]
```
【DAY4】AWSについて

# AWSとは
AWSとは、Amazon Web Servicesの略称で、Amazonが提供しているクラウドサービスです。
## クラウドサービスとは
クラウドサービスとは、インターネット経由で誰でもいつでも自由に利用できるサービスです。そもそもクラウドとは、一言で言うと「ユーザーがインフラやソフトウェアを持たなくても、インターネットを通じてサービスを必要な時に必要な分だけ利用する考え方」のことです。
以前は、サービスの利用にはハードウェアの購入やソフトウェアのインストールが必要でしたが、クラウドの出現によりハードウェアの購入やソフトウェアのインストールをしなくても利用できるサービスが生まれました。
## クラウドサービスの種類（提供形態）
### 1. パブリッククラウド
パブリッククラウドとは、 **インターネット上でオープンにサービスが提供されているもの** を指します。
AWSはこれに当たります。
私の所属する東京大学では、2019年にLMS(学種管理システム)がオンプレミスからパブリッククラウドへ移行したようです。2019年は私が入学した年ですが初めて知りました。
#### オンプレミス
サーバーなどのハードウェアやIT機器、ファイルソフトなどのソフトウェアを自社で保有し、構築・管理する形態

### 1. プライベートクラウド
プライベートクラウドとは、 **自社や提携企業など特定のユーザーが利用する、クローズなクラウドサービス** を指します。
安否確認サービスなどがこれに当たります。

## クラウドサービスの種類（利用形態）
クラウドサービスは利用形態により以下の3種類に分けることもできます。
* SaaS（サース）
* PaaS（パース、パーズ）
* IaaS（アイアス）もしくはHaaS（ハース）

「SaaS」は一般の方も利用することが多いクラウドサービスですが、「PaaS」や「IaaS」は主にエンジニアの方の利用が多いクラウドサービスです。

## SaaSとは
SaaSは **Software as a Service** の略で、 **ネットワークを活用してアプリ・ソフトウェアを提供するサービス** を指します。
例）Googleマップ、Yahoo!メール、Micro office 365、zoom、slack

## PaaSとは
PaaSは **Platform as a Service** の略で、 **アプリケーションの開発環境を提供するサービス** を指します。
アプリケーションの開発環境というのは、ネットワーク、サーバーシステム、データベース、OS、ミドルウェアなどのプラットフォームのことです。
AWSもPaaS機能を持ったサービスを提供しています。

## IaaSとは
IPaaS(HaaS)は **Infrastructure as a Service（Hardware as a Service）** の略で、ITサービスの運営に必要不可欠なインフラである「仮想サーバー」や「回線」などを提供します。
IaaSを使えば、自社でサーバーやストレージなどのハードウェアを用意することなくネットワークを構築できます。
AWSもIaaS機能を持ったサービスを提供しています。

## SaaS,PaaS,IaaSの違い
アプリ開発を行うにあたり必要な構成要素には、以下の5つがあります。
1. ネットワーク
1. ハードウェア
1. OS(オペレーティングシステム)
1. ミドルウェア（データベースなど）
1. アプリケーション
この５つのうちどこまでがクラウドサービスとして提供されるかによって、SaaS、PaaS、IaaSと呼び名が変化します。
* SaaS
ネットワーク、ハードウェア、OS、ミドルウェア、アプリケーション
* PaaS
ネットワーク、ハードウェア、OS、ミドルウェア
* IaaS
ネットワーク、ハードウェア、OS

従って、IaaS>PaaS>SaaSの順で自分で構成する要素が多くなるため、自由度が高いかわりにその運用は難しくなります。
Unity VRで作成したものをMeta Quest 2で動かす

# プロジェクト作成
### プロジェクトの作成
Unity Hubで3Dのプロジェクトを作成する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/13a69376-47a2-8e75-74fb-7a4a7d41e082.png)

### プラットフォームの切り替え
- file - Build Settingsを選択
- PlatformからAndroidを選択し、右下のSwitch platformを押下
※下記の参考画像はすでにAndroidに切り替えた後、撮影したのでボタンの文言が異なっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/6a04e856-d5db-fb76-5cff-3f27983de865.png)

:::note info
切り替えにはしばらく時間がかかると思います。
:::

### Texture Compressionの変更
プラットフォームの切り替えと同じく、Build SettingsからTexture Compressionを`ASTC`に変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/2c02d4b4-034f-96eb-1ee6-aa47b8689ef8.png)

### XR Plugin Management
Build SettingsからPlayer Settingsを押下

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/0171f953-ed7f-5a5c-5fb4-f65c894beb01.png)

Project Settingsが開くので、左下のXR Plugin Managementを選択し、Install XR Plugin Managementを押下する

インストールが終わったら、Oculusにチェックを入れる

### Scripting Backendの変更
- edit - Project Settingsを開く
- Playerを選択し、Other Settingsを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/3d3a1d98-dfed-9ab4-1dc8-b7358db2e1a0.png)
- 真ん中くらいにあるScripting BackendをIL2CPPに変更する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/8e92cca3-b9f3-8283-1b25-58d526e561fb.png)

# Oculus側の設定
## Developer登録
下記にアクセスして、Meta Quest 2で利用しているアカウントでログインします。
https://developer.oculus.com/

Developer登録するにはクレジットカードを登録するか、テキストの二段階認証を設定する必要があるので、どちらかを設定します。

## 開発者モードをONにする
スマホにMeata questのアプリをインストールします
スマホとお使いのデバイスで、同じWifiを使用させます
アプリからお使いのデバイスを選択し、ヘッドセットの設定から開発者モードをONにします

# Unityで動かす
## Unityで起動するデバイスを設定する
### VRデバイスとPCをUSBで接続する
- お使いのデバイスとPCをUSBで接続します
:::note info
接続するとPC側で`Meta Quest Link`のソフトが立ち上がるはずですが、`Meta Quest Link`が起動しない場合はインストール、もしくはアップデートがひつようです。
:::
-  お使いのVRデバイスで、デバッグの許可のダイアログが表示されるので許可をします

### UnityでRun Deviceに設定する
接続できていればBuild SettingsのRun Deviceからお使いのデバイスを選択できるので、選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/667c1b7b-6217-c6b2-b861-a8aa3b14f7f4.png)

## 実行する
File - Build And Runを選択します
ダイアログが表示されるので、任意の保存名にして保存します
しばらくたつと、VR上で実行されます
Cloud DLPとデータ保護の基本

## Cloud DLP（Data Loss Prevention）とは

Google CloudのCloud DLPは、データ内の機密情報を発見、分類、および保護するためのツールです。これにより、データ漏洩のリスクを軽減し、規制遵守をサポートします。Cloud DLPは、個人を特定できる情報（PII）や財務情報、医療情報など、さまざまな機密データをスキャンして識別し、これらのデータを保護するための適切な措置を講じることができます。

## PII（Personally Identifiable Information）とは

PIIは、個人を特定できる情報のことを指します。これには、氏名、住所、生年月日、電話番号、メールアドレスなどが含まれます。PIIの保護は、データ漏洩を防ぎ、個人のプライバシーを守るために非常に重要です。

## サービスアカウント

サービスアカウントは、**Google Cloudのリソース**にアクセスするための特殊なアカウントです。サービスアカウントにはIAM（Identity and Access Management）ポリシーが適用され、特定の操作の認証と認可が行われます。

## IAM（Identity and Access Management）

IAMは、Google Cloudにおけるアクセス制御の基本ツールです。IAMを使用することで、**ユーザー、グループ、およびサービスアカウント**に対して特定のリソースへのアクセス許可を管理することができます。

## データ保護の例：医療機関でのデータ保護

### シナリオ

医療機関では、患者の医療記録や個人情報を厳重に保護する必要があります。この医療情報は、機密性が高く、規制によって保護が義務付けられています。ここでは、医療機関が**Cloud DLP**を使用して患者データを保護し、アクセス制御を行う方法について説明します。

### 要件

1. **医療記録の発見と分類**：患者の医療記録をスキャンし、機密情報を発見・分類する。
2. **アクセス制御**：医療記録へのアクセスを適切に制御する。
3. **データ暗号化**：データを暗号化して、アクセス権のないユーザーから保護する。

### ソリューション

#### 1. Cloud DLPの使用

- **Cloud DLP**を使用して、医療記録をスキャンし、PIIやその他の機密情報を識別します。
- データ内の機密情報を自動的に発見し、分類することで、適切な保護措置を講じることができます。

#### 2. Cloud Storageの利用

- 医療記録を**Cloud Storage**に保存します。Cloud Storageは、高い耐久性とスケーラビリティを提供し、データの暗号化もサポートしています。

#### 3. IAMとサービスアカウントの設定

- 各医療従事者には**個別のサービスアカウント**を作成し、サービスアカウントに必要なIAMロールを割り当てます。
- **IAMグループ**を設定し、グループごとに適切なアクセス権を付与します。例えば、医師グループには患者の医療記録全体へのアクセス権を付与し、看護師グループには特定の情報へのアクセス権のみを付与します。

### 実装のまとめ

1. **Cloud DLPで医療記録をスキャンし、機密情報を発見・分類する**。
2. **Cloud Storageにデータを保存し、暗号化する**。
3. **IAMを使用してアクセス権を適切に設定し、各ユーザーが必要な情報にのみアクセスできるようにする**。

## データ保護とデータクリーンルームの違い

データ保護とデータクリーンルームは、どちらもデータの安全性とプライバシーを確保するための手法ですが、目的とアプローチが異なります。

#### データ保護

- **目的**：データの機密性、完全性、および可用性を維持し、不正アクセスやデータ漏洩を防ぐ。
- **手法**：暗号化、アクセス制御、データマスキング、Cloud DLPの使用など。

#### データクリーンルーム

- **目的**：複数のパーティが共同でデータを分析する際に、データのプライバシーと機密性を維持する。
- **手法**：データの匿名化、制限付き環境での分析、コンプライアンスの確保など。

## まとめ

データ保護とデータクリーンルームは、データの安全性とプライバシーを確保するための重要な手法です。データ保護は、主にデータの機密性、完全性、および可用性を維持することを目的としており、Cloud DLPや暗号化、アクセス制御などが含まれます。一方、データクリーンルームは、複数のパーティが共同でデータを分析する際に、データのプライバシーと機密性を維持するために使用されます。それぞれのアプローチは異なる目的と手法を持ち、具体的なシナリオに応じて適切に使い分けることが重要です。
部分一致の実装のときのメモ

部分一致での検索機能を実装したときのメモ

nameの部分一致の記述はjsonでの書き方をしていた時
model_numberの部分一致はSqlHelperってものを使えば便利であると教わったもの
この後nameも同様に書き換えた。

### Item.Controller.php

```php
<?php

namespace App\Http\Controllers;

use App\Helpers\SqlHelper;
use Illuminate\Http\Request;
use App\Models\MtItem;

class ItemController extends Controller
{
    //商品検索
    public function get(Request $request)
    {

        $query = MtItem::query();

        if ($request->has('name')) {
            $query->where('name', 'LIKE', '%'.$request->input('name').'%');
        }

        if ($request->has('jancd')) {
            $query->where('jancd', 'LIKE', $request->input('jancd'));
        }

        if ($request->has('model_number')) {
            $query->where('model_number', 'LIKE', SqlHelper::escapePartialMatch($request->input('model_number')));
        }

        $items = $query->get();

        // 商品情報をJSON形式でレスポンスとして返す
        return response()->json($items);
    }
}

```

### SqlHelper.php

```php
<?php

namespace App\Helpers;

class SqlHelper {

    /**
     * 部分一致テキストへエスケープ
     */
    public static function escapePartialMatch(string $value, string $char = '\\')
    {
        return '%'.str_replace(
            [$char, '%', '_'],
            [$char.$char, $char.'%', $char.'_'],
            $value
        ).'%';
    }

    /**
     * 前方一致テキストへエスケープ
     */
    public static function escapePrefixMatch(string $value, string $char = '\\')
    {
        return str_replace(
            [$char, '%', '_'],
            [$char.$char, $char.'%', $char.'_'],
            $value
        ).'%';
    }

    /**
     * 前方一致テキストへエスケープ
     */
    public static function escapeBackwardMatch(string $value, string $char = '\\')
    {
        return '%'.str_replace(
            [$char, '%', '_'],
            [$char.$char, $char.'%', $char.'_'],
            $value
        );
    }
}
```
---
### まとめ

SqlHelperクラスは、SQLクエリで使用するテキストをエスケープするためのヘルパークラスです。エスケープ処理を行うことで、特定の文字（例えば、'%', '_'）がSQLで特別な意味を持つ文字として扱われることを防ぐ。
React19にuseTransitionが便利になるらしい

## はじめに
Reactは学習や静的個人Webサイトでしか使ったことがなく、業務経験はないのですが
そんな自分でも驚くような関数が追加されたので軽く解説していきたいと思います

## useTransitionがReact19でどのように使いやすくなったか
React19ではuseTransitionが強化され、非同期アクションの管理が容易になりました。
以前は、非同期処理中の状態を手動で管理する必要がありましたが、React19ではuseTransitionを使うことで、自動的にこの状態管理が行われます


### 以前の実装例：useStateでの送信中状態やエラー状態
```jsx
function UpdateName({}) {
    const [name, setName] = useState("");
    const [isPending, setIsPending] = useState(false); // useStateで読み込み状態を管理
    const [error, setError] = useState(null);
    
    const handleSubmit = async () => {
        setIsPending(true); // 呼び出し前は読み込み中にする
        cont error = await updateName(name);
        setIsPending(false);// 呼び出し後は読み込み中の状態を外す
        if (error) {
          setError(error)
          return;
        }
        redirect("/path");
    };

    return (
      <div>
        <input value={name} onChange={(event) => setName(event.target.value) } />
        <button onClick={handleSubmit} disabled={isPending}>
          update
        </button>
        {error && <p>{error}</p>}
      </div>
    );
}
```

## React19でuseTransitionに置き換えることで得られる効果
useTransitionを使用すると、非同期処理の状態管理が自動化され、コードが簡潔になります
また、UIの応答性が向上し、ユーザーエクスペリエンスが改善されます

### React19の実装例：useTransitionの使用
```jsx
function updateName({}) {
    const [name, setName] = useState("");
    const [error, setError] = useState(null);
    const [isPending, startTransition] = useTransition(false);

    const handleSubmit = async () => {
      setTransition(async () => { // isPendingが自動でtrueになる
        const error = await updateName(name);
        if (error) {
          setError(error);
          return;
        }
        redirect("/path");
    }) // 処理終了後にisPendingがfalseになる
};

return (
    <div>
      <input value={name} onChange{(event) => setName(event.taget.value)} />
      <button onClick={handleSubmit} disabled={isPending}
        Update
      </button>
      {error && <p>{error}</p>
    </div>
  );
}
```

このようにボタンを押してから非同期リクエストを実行して完了するまでの間に`isPending`が`true`を返すようになります
従来は`isPending`のようなステートを自前で管理しなければいけなかったところ、`useTransition`を使うことでReactが管理してくれるようになりました


## まとめ
Transitionが便利になったことで、非同期処理の管理が簡素化され、開発者はシンプルで保守しやすいコードをかけるようになりました
状態管理が把握しやすくシンプルで良いですよね
`useState`を乱用しなきゃいけなかった場面でこのアップデートはありがたいし予想以上に便利そうで驚きました
React19では`useTransition`の強化だけでなく様々なアップデートを施しているのでその内容も随時記事にしていこうと思います

参考

https://ja.react.dev/blog/2024/04/25/react-19

https://zenn.dev/uhyo/books/react-19-new/viewer/actions