OmniAICreator/Qiita-1.07M huggingface dataset:
Google ColaboratoryにAIが搭載されたから使ってみた！スゴい！！！

ついに日本語でもGoogle Colaboratoryで「Colab AI」というコーディングアシストAIが利用できるようになりました！！！

元々アメリカでは2023年5月頃から使えたみたいですが、2023年10月にやっと日本でも利用できるようになったので、早速使ってみます。

## Colab AIとは

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356814/f462cf25-963a-3988-2ef8-459415e73cf2.png)


「Colab AI」はGoogle Colab上で、GIthub CopilotのようにAIからコーディングのサポートを受けることができるペアプログラミング機能です。

![generate-cropped (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356814/c54ead99-f811-c279-cab2-aef08791206a.gif)


この機能を利用することで、ユーザーがコードを記述する際、AIがその続きを予測して提案を行うAI補完機能や、自然言語に基づきコードを自動生成する機能、さらにはColab内でコーディングの疑問点などを直接質問できるチャット機能が利用できます。

更なる詳細や、料金・始め方などについては以下の記事で解説しています。

https://generativeinfo365.com/?p=1857

## Colab AIでできること

### 自然言語でのコード自動生成

Colab AIには自然言語での簡単な指示だけで、欲しいコードを自動で生成してもらう機能が搭載されています。

具体的には、Colabのノートブックに追加された”生成”ボタンを押すことで表示される入力欄に、テキストでの指示を入力することで対応するコードが生成されます。

![generate-cropped (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356814/c54ead99-f811-c279-cab2-aef08791206a.gif)

例えば、「フィボナッチ数列のn番目を計算する関数」という指示を入れると、Colab AIはその指示に沿って「フィボナッチ数列のn番目を計算する関数」のコードを自ら記述して提案してくれます。

これによりユーザーは自らコードを記述する量を大幅に減らし、効率的に開発を行うことができるようになります。

### AIにより自動補完機能
Colab AIは「GitHub Copilot」と同様に、入力した関数名やこれまでのコードに基づいて適切なコードを自動的に提案してくれます。

例えば、二つの日付の間に何日があるかを計算する「days_between_dates」いう名前の関数を作成するとします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356814/7a1b7316-9a24-287d-5060-6c23f461a119.png)

Colab AIを有効にしていると、「days_between_dates」という名前の関数を作成するだけで、自動的に適切なコードをグレーの文字で提案してくれます。

このように表示された提案が適切であれば、Tabキーを押すだけで提案されたコードを受け入れることができます。

### チャット機能

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356814/12cd595b-03a1-4f02-e5b5-751f77300615.png)


Colab AIは、自然言語を使ったコード生成やAI補完機能に加え、ChatGPTやbardのようにチャット形式でAIにプログラミングに関する質問ができるチャット機能が組み込まれています。

このチャットボットを利用することで、プログラミングに関する疑問を持った際に、Google Colab内ですぐに質問して解決することができるようになります。

これにより、Googleなどの外部ブラウザで情報を探す時間が大幅に削減され、開発の効率が向上します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356814/93a028d1-78d4-958c-9d68-840b22d02a0b.png)


具体的には、「Googleシートからデータのインポート方法は？」や「PandasのDataFrameのフィルタリングはどう行うのか？」といった質問にも、速やかで的確な回答を提供してくれます。

さらに、この機能はColabの既存環境に組み込まれているため、追加のセットアップやインストール作業なしで手軽に利用することが可能です。

### エラーの説明＆原因特定機能
Colab AIの利用中、エラーが発生した際には、Colab AIがそのエラーの原因や解決方法を推測して、ユーザーに対して説明や提案を行ってくれる「エラーの説明」機能を利用することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356814/ba9597a6-a4f6-23ab-ec0d-b861f973e398.png)

Colab AIを有効にしていると、エラーが発生した際に出力結果にエラーメッセージの下に「エラーの説明」というボタンが表示されます。

もしエラーの原因や解決方法が知りたい場合には、このボタンをクリックすると、エラーの詳細な原因や修正に関する提案をチャット形式で受け取ることができます。

特に、複雑なプログラムや長いコードの中でエラーを追跡し、原因を特定するのが難しい場合には、この機能は非常に役立ちます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356814/6b1d2dac-7a37-5161-dfa1-4ff665462811.png)

デフォルトでは英語で説明されますが、チャット上で「日本語で説明してください」とお願いすれば日本語でも説明してくれます

この機能を有効活用することで、これまでかかっていたエラー解決の際の手間や時間を大幅に削減し、効率的に開発を進めることができます。

## 

更なる詳細や、料金・始め方などについては以下の記事で解説しています。

https://generativeinfo365.com/?p=1857
paiza.ioでelixir その255

# 概要
paiza.ioでelixirやってみた。
匿名関数、やってみた。

# サンプルコード

```

double = fn x ->
   2 * x
end
double.(3)
|> IO.inspect

sum3 = fn x1, x2, x3 -> 
    x1 + x2 + x3 
end
sum3.(1, 2, 3)
|> IO.inspect
sum3 = &(&1 + &2 + &3)
sum3.(4, 5, 6)
|> IO.inspect

hello = &IO.puts("Hello " <> &1)
hello.("Taro")

f = &Enum.sort/1
f.([1, 3, 2, 5, 4])
|> IO.inspect

f = &(&1 + &2)
f.(2, 3)
|> IO.inspect

double = fn num -> 
    num * 2 
end
double.(3)
|> IO.inspect

Enum.map([1, 2, 4, 8], double)
|> IO.inspect

swap = fn [a, b] -> 
    [b, a] 
end
swap.([1, 2])
|> IO.inspect

reverse = fn
    [a, b] ->
        [b, a]
    [a, b, c] -> 
        [c, b, a]
  end
reverse.([1, 2])
|> IO.inspect
reverse.([1, 2, 3])
|> IO.inspect

whichfizz = fn
  (0, 0, _) -> 
    "FizzBuzz"
  (0, _, _) -> 
    "Fizz"
  (_, 0, _) -> 
    "Buzz"
  (_, _, n) -> 
    n
end
fizzbuzz = fn (n) ->
  whichfizz.(rem(n, 3), rem(n, 5), n)
end
IO.inspect Enum.map(1..100, fizzbuzz)



```

# 実行結果

```
6
6
15
Hello Taro
[1, 2, 3, 4, 5]
5
6
[2, 4, 8, 16]
[2, 1]
[2, 1]
[3, 2, 1]
[1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11, "Fizz", 13, 14,
 "FizzBuzz", 16, 17, "Fizz", 19, "Buzz", "Fizz", 22, 23, "Fizz", "Buzz", 26,
 "Fizz", 28, 29, "FizzBuzz", 31, 32, "Fizz", 34, "Buzz", "Fizz", 37, 38, "Fizz",
 "Buzz", 41, "Fizz", 43, 44, "FizzBuzz", 46, 47, "Fizz", 49, "Buzz", ...]




```

# 成果物

https://paiza.io/projects/S7ainnzyMYzr9BL6n2rqvg?language=elixir


以上。
Java JDKとSDKとは

## JDKとは

- JDK (Java Development Kit)
ソフトウェアパッケージのこと
ソースコードを機械語へ変換するコンパイラや
機械語を実行するJVM (Java仮想マシーン)等が含まれている

## SDKとは

- SDK (Software Development Kit)
コンパイラ等、開発時に使用するツールのこと
Javaの場合はJDKのことを指す
SRE NEXT2023に参加した感想

# 概要
2023年9月29日に開催された[SRE NEXT 2023](https://sre-next.dev/2023/)に参加してきました。この記事は、そのときの感想レポです。
# 自分の立ち位置
現在の自分：アプリケーション開発
やってみたいこと：クラウド、インフラ系、SRE
参加した目的：SREについてより知るため

# 全体的な感想
* どのSREもシステムの信頼性をより高めていきたいという思いが感じられた。

* SREチームだけではなく、開発チームもSREを意識することが重要である。
* SREチームは開発チームと協力関係を築くべき。
* 属人化の解消の実績が多かった。
* 玄人向けな仕事であると前々から聞いていたが、そのような人が取り組むことで始めて真価が発揮される仕事だと思った。

# 参加したセッションの感想

## 1.ギークがイオンに飛び込んだ結果がやばい〜Reliabilityと経営〜
内製化チームの立ち上げから、設計、コーディングをCTOとして全てに関与していくのは、かなりすごいと思った。また、イオンネクストのプラネットフォーム開発において、後から変えられない根幹の設計をとにかく厳格にしていくのは、いいアイデアと思ったと同時にそれを他の開発メンバーは意図を理解しているのかと疑問も浮かんだ。個人的に、入社当時の山積みの問題に思い当たる節がいくつかあって共感した。

## 2.LINEスタンプのSREing事例集：大量のスパイクアクセスを捌くためのSREing
万全な準備をするために3カ月前からサーバーの増設と様々な検証を行うところに本気度の高さをひしひしと感じた。特に、カオスエンジニアリングの考え方を検証に取り入れて、高負荷の試験を行っているのは、テスト環境よりも一層に本番に近い環境で検証可能ないい取り組みだと思った。システムの信頼性の向上には、先を見据えて準備をする姿勢も重要であると今回の事例紹介で実感した。

## 3.備えあれば患いなし：効率的なインシデント対応を目指すSREの取り組み
インシデント対応におけるセキュリティレベルズの明確化は非常に重要だと思った。インシデントの重要度を明確化することで対応時の動きをメンバーで統一することができ、余計なタスクをそぎ落とすことができると感じられた。また、インシデントファイヤードリルといったインシデント対応における模擬訓練を定期的に実践することはインシデント対応に課題があるチームではやっておくことが推奨されると思われる。LINEのセッションでも出てきたが、ドリルの取組はカオスエンジニアリングのツールを用いたものだったため、運用の現場においてカオスエンジニアリングの考え方の取り組みが活発化しているのを認識した。

## 4.勘に頼らず原因を見つけるためのオブザーバビリティ
オブザーバリティの向上のためドリルダウン探索を採用しているメリットがかなりわかった。ベテランのデバッガーは確かに頼りになると思われるが、セッションでも話されていた属人化、勘または思い込みによる調査難航、複合要因を見逃すケースなどといったデメリットがあるため、ドリルダウン探索を用いることで他のデバッガーも質の高いデバッグができると感じた。将来的には、ドリルダウン探索とベテランデバッガーの知見を両方使えるとより良いデバッグができると思った。

## 5. プロダクトオーナーとしてSLOに向き合う。Mackerelチームの事例
SLOを導入することでシステムの信頼性を定量化ができ、それを根拠にすることでチームメンバーだけでシステムの信頼性が担保されていることを判断できるようになる手法が面白かった。プロダクトオーナー自身が介入するタイミングをSLOの導入で減らすことで開発速度を上げるのは良い事例だと感じた。セッションでも言ってた通り、信頼性はユーザー側からしたら、反応が薄い事柄なのはその通りでしかないため、オーナーや開発メンバーの説明による理解を得る課題があるのは共感した。
2023/10/11主にITとかセキュリティの記事

サイバー攻撃が前四半期比で4割増、医療と金融がメインターゲットに─BlackBerry調査(10/9)
https://it.impress.co.jp/articles/-/25445

米タニウムCEO「SBOMでサイバー脆弱性を即座に把握」(10/9)
https://www.nikkei.com/article/DGXZQOUC11AU70R10C23A9000000/

楽しくセキュリティーを学ぶ　「サイバー防犯かるた」を香川大の学生団体が制作(10/9)
https://nordot.app/1084040446124442041

ブロックチェーンが変革する「生成AI」の未来(10/9)
https://zuuonline.com/archives/266006

Microsoft Defender for Storage のマルウェアスキャン機能が GA となったので有効化して検出テストしてみた(10/9)
https://dev.classmethod.jp/articles/ga-malware-scanning-in-defender-for-storage/

Serverless Agents を利用して ECS on Fargate 環境で Sysdig Secure の悪意のあるファイル名の書き込みを検知してみた(10/9)
https://dev.classmethod.jp/articles/malicious-filenames-written-detected-in-sysdig/

curlの脆弱性公開予告の情報まとめ（CVE-2023-38545, CVE-2023-38546）(10/8)
https://qiita.com/M_Yanagihara/items/9b0012fbc8c060eef0b1

Z世代はどの世代よりもインターネットを恐れている?(10/9)
https://news.mynavi.jp/techplus/article/20231009-2786929/

Windows Insider「Devチャネル」のすすめ - 阿久津良和のWindows Weekly Report(10/9)
https://news.mynavi.jp/article/20231009-windows_report/

9月のマルウェアランキング、第1位は？FBIの「Qbotマルウェア撲滅」作戦は成功(10/9)
https://news.mynavi.jp/techplus/article/20231009-2787491/

サイバーセキュリティの10大設定ミス、米国NSAとCISAが警告(10/9)
https://news.mynavi.jp/techplus/article/20231009-2786617/

なぜHTTP/3は急速に普及していったのか、その利点とは？(10/9)
https://gigazine.net/news/20231009-http-3-quic-eating-world/

毎年数十億もの資金を費し、世界に虚偽情報を広める中国共産党(10/9)
https://www.epochtimes.jp/2023/10/178243.html

「電池パスポート」欧州義務化、デンソーはQRコードで追跡(10/10)
https://xtech.nikkei.com/atcl/nxt/mag/at/18/00006/00628/

2つの「宿題」前進も　理想と現実にギャップ［Part 1］(10/10)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/092900381/092900001/

誤登録対応遅れの陰に　当事者意識の欠如［Part 2］(10/10)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/092900381/092900002/

マトリックス組織の功罪　マイナでもろさ露呈［Part 3］(10/10)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/092900381/092900003/

ガバクラと法制審査　司令塔役果たせるか［Part 4］(10/10)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/092900381/092900004/

富士通からIBMへ電子カルテ刷新　サーバーもPCも仮想環境で稼働(10/10)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600004/092900141/

13億人以上がID保有の「アーダール」、経済を一変させたインド版マイナンバーの正体(10/10)
https://xtech.nikkei.com/atcl/nxt/column/18/02608/100500002/

ソフトバンクグループのECサイトに不正アクセス、IPSが検知し詳細は調査中(10/10)
https://xtech.nikkei.com/atcl/nxt/column/18/00598/100500235/

パソコンに被害をもたらす「マルウエア」、サポート切れのアプリは危険にさらされる(10/10)
https://xtech.nikkei.com/atcl/nxt/column/18/02577/091100001/

高専発ベンチャーがAI開発　目指すは地域の課題解決(10/10)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600002/092900076/

国内全14工場を止めたDB保守作業　手順書とリスク分析に不備か トヨタ自動車(10/10)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600011/100200141/
top, vmstat, iostat, lnstat の1回目の結果が変になる罠

## なんなの
統計間隔を指定できるコマンド、top, vmstat, iostat, lnstat には１回目の結果値が、指定した統計間隔での統計値にならないという罠があるので気を付けたい。

## ダメな例
例えば、
```bash:
top -b -d10 -n1
```
は、```-d[N]``` オプションが統計秒数、```-n[M]``` オプションが測定回数なのだが、１回目は ```-d[N]``` で指定した秒数を待たずにすぐさま表示がなされ、全然設定した N 秒平均の値になっていない。
また、非常に短い統計秒数での値が表示されるため、表示値のぶれも大きい。

```bash:
top -b -d10 > log
```
のようなコードでログを取るなら、１つ目の結果だけを無視すればいいのだが、
```bash:
#!/bin/bash
echo "" > log
while true
do
  top -b -d10 -n1 >> log
  sleep 0.1
done
```
などで１回１回独自で値を取ろうとすると毎回どれも全然指定した 10 秒間の統計にならない。(やってみるとめちゃめちゃ高速に何回も実行されます)

## どうすればいいのか
```-n1``` を使わず ```-n2``` で２つの結果を出すようにして、
１回目の結果を ```tail``` などで捨てて、２回目の結果だけを拾えばよい。
```bash:
#!/bin/bash
echo "" > log
while true
do
  top -b -d10 -n2 | tail -14 >> log
  sleep 0.1
done
```
辛い

※ top -b -d10 > log でいい、というのは、それでいいときはそれはそう。top, vmstat, pidstat を統合して同期した結果を得たいときの話
※ /proc/stat をパースして全部自分でやれ、それはそう

## 同じ感じのコマンドはいないか

統計間隔指定オプションのある似たコマンドを全部調べました

|パッケージ|調べたバージョン|コマンド|１つ目の結果|こうすればいいよ|
|-|-|-|-|-|
|procps|<a href="https://salsa.debian.org/debian/procps/-/blob/upstream/3.3.16/top/top.c">procps-ng 3.3.16</a>|top -b -d[N] -n1|<font color="red">**×**</font> 謎の時間の平均|top -b -d[N] -n2 \| tail -14|
|procps|<a href="https://salsa.debian.org/debian/procps/-/blob/d8d920383c7e95e2faf0aef0d2c6d72b28e9c006/vmstat.c#L306-328">procps-ng 3.3.16</a>|vmstat [N] 1|<font color="red">**×**</font> 起動時からの長時間平均|vmstat [N] 2 \| tail -1 
|sysstat|<a href="https://salsa.debian.org/debian/sysstat/-/blob/upstream/12.2.0/iostat.c">sysstat 12.2.0</a>|iostat [N] 1|<font color="red">**×**</font> 非常に大きい謎の値|iostat [N] 2 \| tail -9
|sysstat|sysstat 12.2.0|mpstat [N] 1|<font color="green">**〇**</font> N 秒の平均||
|sysstat|sysstat 12.2.0|pidstat [N] 1|<font color="green">**〇**</font> N 秒の平均||
|iproute2|<a href="https://salsa.debian.org/kernel-team/iproute2">lnstat</a> 0.02|lnstat -i[N] -c1|<font color="red">**×**</font> 非常に大きい謎の値|lnstat -i[N] -c2 \| tail -1

mpstat, pidstat は素直でした

## 教訓

10秒指定とかしたときに10秒かからずに1つ目の値が返ってくるコマンド、１つ目の値だけ飛んだ値がくるコマンドは要注意です。

## その他
top は指定した統計秒数にプロセスが生きていても、統計終了時点でそのプロセスが生きていないとプロセスのランキングに出てこず、なかったことになるので注意。

たとえば、top -d100 で 100 秒の統計を取っているとき、n 回目の表示が終わったときを時刻 0 秒目として、時刻1秒目にプロセス mycmd が負荷100%で動き出し、98秒間動いて時刻99秒目でプロセスが終了し、100秒目で n+1 回目の top 表示がなされたときには mycmd は負荷 98% と表示してほしいものだが、100秒目には mycmd はもういなかったのでランキングに出てきません。
ただ、user time と idle time の計算には入っているみたいです。(user time は 98% と表示される。)
alembicで作成されるカラムの順序を指定するmapped_columnとsort_orderの使い方

# よくある実装と発生する問題
SQLAlchemyとalembicを使用している場合、モデルのベースを作り、下記のように継承させる方法をよくとると思います。

```base.py
from sqlalchemy import Column, DATETIME, Integer, func

class ModelBase:
    id = Column(Integer, primary_key=True)
    created_at = Column(DATETIME, nullable=False, server_default=func.now())
    updated_at = Column(
        DATETIME,
        nullable=False,
        server_default=func.now(),
        onupdate=func.now(),
    )

```

```:user.py
from sqlalchemy import Column, String
from app.db.base_class import Base
from app.models.base import ModelBase

class User(Base, ModelBase):
    __tablename__ = "users"
    name = Column(String(255), nullable=False)
```

しかし、上記の実装では、
`name, id, created_at, updated_at`の順に作成されてしまいます。
使えなくはないですが、なんだかしっくりこないですね。
![table.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/852882/0af78633-f488-a62a-ec0e-f04a3399dbb5.png)

実際に、migrationファイルも下記のように書かれています。
```
def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('users',
    sa.Column('name', sa.String(length=255), nullable=False),
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('created_at', sa.DATETIME(), server_default=sa.text('now()'), nullable=False),
    sa.Column('updated_at', sa.DATETIME(), server_default=sa.text('now()'), nullable=False),
    sa.PrimaryKeyConstraint('id')
    )
    # ### end Alembic commands ###
```

# 対処法
下記のように、`mapped_column`と`sort_order`を使用することで、順番を正しいものにすることができます。

```:base.py
from sqlalchemy import DATETIME, Integer, func
from sqlalchemy.orm import mapped_column


class ModelBase:
    id = mapped_column(Integer, primary_key=True, sort_order=-10)
    created_at = mapped_column(
        DATETIME, nullable=False, server_default=func.now(), sort_order=98
    )
    updated_at = mapped_column(
        DATETIME,
        nullable=False,
        server_default=func.now(),
        onupdate=func.now(),
        sort_order=99,
    )

```

# 結果
![table2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/852882/c743e84e-2560-6a8f-e29d-b9a4d79491ba.png)
JavaScriptからPHPへのAPIリクエスト: POSTメソッドの実践ガイド

# JavaScriptからPHPへのAPIリクエスト: POSTメソッドの実践ガイド

## 1. XMLHttpRequestを使った方法

### JS側のコード

```javascript
// XMLHttpRequestオブジェクトを作成
var xhr = new XMLHttpRequest();

// POSTメソッドとAPIのエンドポイントを指定してリクエストを初期化
xhr.open('POST', 'https://your-server-endpoint.com/api', true);

// リクエストヘッダーを設定
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

// リクエストの状態が変わったときのイベントハンドラを設定
xhr.onreadystatechange = function() {
    // リクエストが完了し、レスポンスが成功だった場合
    if (xhr.readyState == 4 && xhr.status == 200) {
        console.log(xhr.responseText);  // レスポンスをコンソールに出力
    }
};

// 送信するデータを設定
var data = 'key1=value1&key2=value2';

// リクエストを送信
xhr.send(data);
```

### PHP側のコード

```php
<?php
// POSTデータを取得
$data = $_POST;

// レスポンスを作成
$response = array('message' => 'Data received!', 'data' => $data);

// レスポンスヘッダーを設定
header('Content-Type: application/json');

// JSON形式でレスポンスを出力
echo json_encode($response);
?>
```

## 2. Fetch APIを使った方法

### JS側のコード

```javascript
// Fetch APIを使用してPOSTリクエストを送信
fetch('https://your-server-endpoint.com/api', {
  method: 'POST', // メソッドを指定
  headers: {  // ヘッダーを設定
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({  // ボディにJSON形式のデータを設定
    key1: 'value1',
    key2: 'value2'
  })
})
// レスポンスをJSON形式で解析
.then(response => response.json())
// データをコンソールに出力
.then(data => console.log(data));
```

### PHP側のコード

```php
<?php
// 入力データを取得
$input = file_get_contents('php://input');

// JSONデータをデコード
$data = json_decode($input, true);

// レスポンスを作成
$response = array('message' => 'Data received!', 'data' => $data);

// レスポンスヘッダーを設定
header('Content-Type: application/json');

// JSON形式でレスポンスを出力
echo json_encode($response);
?>
```

## 3. FormDataを使った方法

### JS側のコード

```javascript
// FormDataオブジェクトを作成
var formData = new FormData();

// データを追加
formData.append("key1", "value1");
formData.append("key2", "value2");

// Fetch APIを使用してPOSTリクエストを送信
fetch('https://your-server-endpoint.com/api', {
  method: 'POST',  // メソッドを指定
  body: formData  // ボディにFormDataを設定
})
// レスポンスをJSON形式で解析
.then(response => response.json())
// データをコンソールに出力
.then(data => console.log(data));
```

### PHP側のコード

```php
<?php
// POSTデータを取得
$data = $_POST;

// レスポンスを作成
$response = array('message' => 'Data received!', 'data' => $data);

// レスポンスヘッダーを設定
header('Content-Type: application/json');

// JSON形式でレスポンスを出力
echo json_encode($response);
?>
```

## 結論

今回は、JavaScriptからPHPへのAPIリクエストをPOSTで送る方法について、3つの手法を中心に解説しました。それぞれの方法にはメリットとデメリットがありますので、実際のプロジェクトに合わせて適切な方法を選んでください。最後まで読んでいただき、ありがとうございます！

## 所感・感想

業務でAPIを作成している時にFetch APIを使って、
「あれ...APIリクエスト送信できてるのに、サーバー側で$_POSTにないぞ..!?」
となったのが今回記事を書いたきっかけです。
POSTリクエストは全部スーパーグローバルに入ると勝手に思ってました（笑）
一つ勉強になりました。めでたしめでたし！
ようつべ体験記12

[前回](https://qiita.com/matsukatsu/items/910e9418844d5a29074b)

9月が終わりました（テキストを書いたのが9月末、記事を投稿したのが10/10となりました）。
8月末時点で20だったチャンネル登録者数がギリギリで30となりました。
いちおう、今月の目標が達成できました。

![チャンネル登録者数.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/9f6503b1-2132-d03b-3785-6f4e2dca0508.png)

正直、9月上旬は視聴回数も右肩上がりだったので余裕で達成しちゃうだろと思っていました。
中旬で発生した無風事件以降、インプレッションされるもののクリックされず、遂にはインプレッションもされなくなるという感じでめちゃくちゃでした。

![Frame 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/d72575da-f6db-bc89-f814-55709d2f7b72.png)

30日の夜にコメント欄で質問してこられた方がいて、回答してあげた直後にチャンネル登録者数が増えて30になりました。
多分チャンネル登録してくれたのかと思います。ありがとうございます。
ほんとうにギリギリの達成です。


個々の動画を見ていくと、1番見られているものは2か月間で視聴回数が1000をこえました。
最初に投稿した動画が無風事件の日を除いて順調に伸びてくれた形になります。
本来なら、最初に公開した動画が好評だったのでそれを擦り続ければいいのですが、ネタ切れでそれができずに残念です。

別の素材を利用せざるを得ず、なかにはそこそこ伸びる動画もあるのですが、結果的にテーマが散漫なチャンネルとなってしまいました。
僕的には共通するテーマなのですが、視聴者あるいはYouTubeのAIはそう判断していない感じがします。

![チャンネルアナリティクス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/5b5acd34-4d17-d711-dc49-9795aae3c268.png)

無風事件以降、インプレッションのクリック率が下がったままで回復しません。
もちろん作った動画のサムネイルの品質が低かったり、対象の国が興味を持たれにくい可能性などがあるのですが。
事件以降インプレッション数が下がり続け、たまに上がるとインプレッションのクリック率がガタ落ちするのが続いています。

事件発生時点ではハッシュタグを修正し、インプレッションが戻ったかに見えていましたが、下落が続いたかと思うと突然大量にインプレッションが発生し、また下落するという状況が続いています。
まだ問題が残っているという事なのでしょう。

突然インプレッションが大量に発生するのは、新しい動画を投稿したタイミングです。
新しい動画が強くインプレッションされる事は正常なのでしょうが、それが維持されないのは動画の質が期待外れという事かなと感じます。
インプレッション数が下落を続けるのは、チャンネルの質が一時期に比べて低くなったという事なのかなと感じます。

今月は
- 動画の質の改善
- チャンネルの質の改善
に取り組みます。
チャンネル登録者数の目標は設定しません。
インプレッション数と視聴回数が右肩上がりの状態に戻す事を目指します。


### チャンネルの質の改善
まず、チャンネルの質を下げている動画の公開をやめます。
質が良い動画へインプレッションを集中させるのと、チャンネル全体の平均値を上げてみます（非公開化で平均があがるのかは不明）。
チャンネルの質を下げている動画の見極めのため、動画のデータをLooker Studioで可視化しました。
Looker StudioのYouTubeデータソースだと確認できる指標が少ないので、YouTube Studioからダウンロードしたデータを利用しました。
見えるものはYouTube Studioと変わらないのですが、Looker Studioのヒートマップや条件式を使って傾向や問題を見やすくしただけです。
可視化する事で問題が一目瞭然になりました。
平均再生率が40%を割り、インプレッションのクリック率も2%を割っている動画を非公開にしてみます。

![スクリーンショット 2023-10-10 19.37.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/1c979a4a-c027-68ba-73a5-25f29825df9a.png)

また、視聴者がアクセスしている時間帯がようやく表示されるようになりました。
18:00-24:00頃が視聴回数が多い時間帯で、ピークは21:00台です。
曜日としては、木、土、日が多いようです。
このタイミングに投稿直後のインプレッション数が上がるボーナスタイムを合わせるよう運用を変えます。
従来は午前中の公開でしたが、夕方の公開に変更します。

![スクリーンショット 2023-10-10 19.39.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/a5b1fd72-e830-6074-4d36-9eaa37931563.png)

### 動画の質の改善
そもそも、いまやっている事に価値はあるのかという疑問がありました。
チャンネルをはじめる前、似た事をしているチャンネルをいくつか見て、自分ならもっと良くできそうという考えに基づいたアレンジを加えています。
2か月チャンネルを運営して改めて他のチャンネルを見ると、見え方が変わった気がします。
そういったチャンネルごとのアレンジも果たして意味があるのかという気がしてきました。
各々の動画のコアの価値がある気がしており、実はそれを実現するだけで良いのではないかと感じてきました。
完コピしてみると良いという話も目にしていますが、ひとまず完コピの手前を出してみます。
このステップを踏んでおく事で完コピする場合のハードルも下がりますし、アレンジをしなかった場合の数字がどんなものか把握できるはずです。
sqlalchemy.exc.InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers.の対処法

# エラー全文


sqlalchemy.exc.InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers. Triggering mapper: 'Mapper[ProjectUser(projects_users)]'. Original exception was: When initializing mapper Mapper[ProjectUser(projects_users)], expression 'User' failed to locate a name ('User'). If this is a class name, consider adding this relationship() to the <class 'app.models.project_user.ProjectUser'> class after both dependent classes have been defined.


# 多対多モデルの定義
はじめ、下記のようにモデルを設定していました。

```:user.py
from sqlalchemy import Column, String
from sqlalchemy.orm import relationship

from app.db.base_class import Base
from app.models.project_user import ProjectUser


class User(Base):
    __tablename__ = "users"
    name = Column(String(255), nullable=False)

    projects = relationship(
        "Project",
        secondary=ProjectUser.__tablename__,
        back_populates="users",
    )
    project_user = relationship("ProjectUser")
```

```:project.py
from sqlalchemy import Column, String
from sqlalchemy.orm import relationship

from app.db.base_class import Base
from app.models.project_user import ProjectUser


class Project(Base):
    __tablename__ = "projects"
    title = Column(String(255), default="", nullable=False)
    users = relationship(
        "User",
        secondary=ProjectUser.__tablename__,
        back_populates="projects",
    )
    project_user = relationship("ProjectUser")
```

```:project_user.py
from sqlalchemy import Column, ForeignKey, Integer
from sqlalchemy.orm import relationship

from app.db.base_class import Base


class ProjectUser(Base):
    __tablename__ = "projects_users"
    project_id = Column(
        Integer, ForeignKey("projects.id", ondelete="RESTRICT"), nullable=False
    )
    user_id = Column(
        Integer, ForeignKey("users.id", ondelete="RESTRICT"), nullable=False
    )

    user = relationship("User")
    project = relationship("Project")

```

# 原因
エラー文を読み込むと、「`User`という文字列に該当するモデルクラスが見つからない」と言われていることがわかる。
SQLAlchemyのrelationshipを使用する際には、モデルを読み込む順序は内部で決まっているが、まだ`User`モデルを読み込んでいないにもかかわらず、`Project`モデルでリレーションを張ろうとしても失敗してしまう、ということを示している。

# 解決方法
`Project`モデルを設定する前に、`User`を読み込んであげればよい。
（`# noqa`を記述しているのは、Linterエラーに引っかかるのを防ぐため。）

```:project.py
from sqlalchemy import Column, String
from sqlalchemy.orm import relationship

from app.db.base_class import Base
from app.models.project_user import ProjectUser

# from app.models.feature import Feature  # noqa # 追加した部分


class Project(Base):
    __tablename__ = "projects"
    title = Column(String(255), default="", nullable=False)
    users = relationship(
        "User",
        secondary=ProjectUser.__tablename__,
        back_populates="projects",
    )
    project_user = relationship("ProjectUser")
```
[React] MUI TextFieldで文字列を入力すると動的に高さを変動させる方法

## 初めに
MUIを使ってフォームを作成している際に躓いたので、ここで備忘録として記事を残しておきたいと思います

##  結論
TextFieldコンポーネントのmutiline属性をつけるだけ！

```typescript
retutn(
    <>
        <TextField mutiline />
    </>
)
```

## 参考文献: 一部抜粋
*The multiline prop transforms the text field into a TextareaAutosize element. Unless the rows prop is set, the height of the text field dynamically matches its content (using TextareaAutosize). You can use the minRows and maxRows props to bound it.*

*multilineプロップは、テキストフィールドをTextareaAutosize要素に変換します。rowsプロップが設定されない限り、テキストフィールドの高さは動的に（TextareaAutosizeを使用して）そのコンテンツに一致します。minRowsプロップとmaxRowsプロップを使って、それを束縛することができます。*

## 参考文献
> https://mui.com/material-ui/react-text-field/#multiline
> https://mui.com/base-ui/react-textarea-autosize/
Html/CSS/Figma - CSS単位,JavaScript,Figma

[学習]CSS単位について

>px … 画面を構成する画素(ピクセル)を単位と指定
・文字の大きさはは16px程度が基本
・画面の最大幅は1,000px程度が基本

>in,cm,mm,Q,pc,pt
印刷・組版由来の単位

>%,em,ch,ec,lh
相対長の単位
em … 「M」の大きさが1em
rem … Root emの略、親要素に影響されない

>vw / vh … ビューポートの幅と高さの割合
>vmin / vmax … 端末の向きによらない短い辺と長い辺
>dvw / dvh(ダイナミック) … アドレスバーの表示状況にあわせる
>svw / svh(スモール) … アドレスバーが表示された時
> lvw / lch(ラージ) …. アドレスバーが隠れた時
ビューポートを基準とした単位
スマホ等で見えている範囲のこと

・論理的プロパティ
>border-inline-start
>direction: start

>「writing-mode:vertical-rl」縦書き、横書きの切り替え
「inline」横書きの時の横方向 … vi
「block」横書きの時の縦方向 … vb

——————————————————
[学習 - JavaScriptについて]12:30~
・Bootstrapの復習
↪︎Bootstrapのサイトにアクセス後「Get started」で取得
HTMLの<head>タグ内にペーストする。
・HTML内にJavascriptを記述する場合はscriptタグを使用
>      "script"
>          document.write('<p class="date">20xx/01/23</p>');
>       "script"

2023/10/10
——————————————————
[学習 - Figma]17:30~
<プロパティ>
・デザイン … 選択したオブジェクトの情報
・プロトタイプ … 制作物のプロトタイプを表示
・インスペクト 

<フレームの作成>
・フレームの選択 … 「Command+クリック」
・要素のコピー … 「option + コピー」
・キーボード操作だとフレームインしない
・ショートカット
ズームイン/アウト … 2本指
コピペ … Command + C,V
複製 … Command + D
スタイルを引き継かずペースト … Command + Shift + V
スタイルのみコピぺ … Comannd + Option + C / V
画面を動かす … Space + ドラッグ

<検索と置き換え>
検索 … Command + F
検索 + 置き換え … 全てのフレームの文字を置換可能

<ツールバーの使い方>
　「選択ツール」
移動ツール … V
拡大縮小 … K 縦横比を保ったまま拡大縮小
　「フレームツール」
フレーム … F デザインエリアの枠組/<div>のような役割でグループ化
↪︎ 右クリック[選択範囲のフレーム化]  or option + Command + G
セクション … Shift + S 
↪︎階層毎にセクション分け可能 / コンポーネントをまとめて配置 *フレーム名が見える
スライス … s
↪︎画像の一部分を書き出す
　「シェイプツール」
画像の配置 … オブジェクトへの配置が可能
↪︎ <塗り>からの配置も可能
　「描画ツール」
　「テキストツール」
　「リソースツール」
・コンポーネント
↪︎ブックマークのようなもの
・プラグイン
・ウィジェットを管理する機能
　「手のひらツール」… Space
　「コメントツール」
↪︎デザインにコメントを残せる/コミュニケーションツール

<プロパティパネルの使い方>
　「デザイン」
・整列
・制約
↪︎親フレームに対する位置
	・スクロールする際に位置を固定
	↪︎「プロトタイプ」チェック時に有効/画面に追従する
・レイヤーのプロパティ
↪︎透明度、レイヤーON/OFF、ブレンド
・線のプロパティ
↪︎線の形状、透明度
・エフェクト
↪︎シャドウ、ぼかし(組み合わせ、プリセット保存可能)
・エクスポート
↪︎重なるレイヤーの使用不使用を選択できる
・テキスト
↪︎詳細設定、テキストを切り捨てるで「…」と以降の文章を省略可能

　「プロトタイプ」
　「インスペクト」
・CSSデータなどが掲載されている

<Figmaの便利機能>
「オートレイアウト」
親フレームのサイズを自動調整したい場合→「コンテンツを内包」選択

「コンポーネント」
・「class」のようなもの
　↪︎セクションツールを使い管理する
・バリアントを追加
　↪︎バリエーションを追加、カラー/ネームを変更する事で「プロパディ」切替が可能

「スタイル」
・色スタイル/テキストスタイル/エフェクトスタイル
　↪︎プリセットを作って、コール可能

「マスクを使った写真合成」
　↪︎オブジェクトを重ねてグループ化、ぼかしなどエフェクト適用可
「グラデーションマスク」でビジュアル作成
　↪︎外側のオブジェクトを作成、グループ化、元イメージの複製、マスク化、グラデーションで合成していく

「プラグイン・ウィジェット」
・プラグイン … 作業者が使用するもの “Unsplush” “iconyfy”
　↪︎ショートカット … Command + /
・ウィジェット … 共有すれば他の人も使用できる “Todo”
[解決済]AMIからEC2を複製したらパスワード認証が出来なくなった。

# AMIからEC2を複製したら、パスワードログインができなくなった

DEV環境複製したいタイミングとかってあると思うんですけど、普通にAMIを作成してAMIから起動したらログインできなくなっちゃうんですよね。
新卒なので普通に何かぶっ壊したんじゃないかと焦りました。

##  原因と解決策

**原因:**  
AMIを使用してEC2を立ち上げる際、`/etc/ssh/sshd_config`の`PasswordAuthentication`がデフォルトで`no`に設定されているため。

**解決策:**

1. EC2インスタンスにSSH接続する。
2. `sudo vim /etc/ssh/sshd_config`を実行し、設定ファイルを開く。
3. `PasswordAuthentication no`を`PasswordAuthentication yes`に変更する。

```bash
# Before:
PasswordAuthentication no

# After:
PasswordAuthentication yes
```
 SSHDサービスを再起動して変更を適用する。
```bash
 $ sudo service sshd restart
```
## 3. 所感
いや〜。まさか自動でPasswordAuthenticationがOFFになるとは思いもしませんでした。。。
いい勉強でした！！
transactionの処理の流れについて調べてみた！

# Transactionとは
ChatGPT
>トランザクション（Transaction）は、データベースにおける一連の操作をまとめて、それらがすべて成功することを保証するための仕組みです。トランザクションは、データベースの整合性を保つために非常に重要な役割を果たします。

# railsにおけるTransactionについて調べてみた！

Railsでトランザクションを使用する場合は、トランザクションの範囲を
ActiveRecord::Base.transactionブロックで囲む必要がある。

```ruby
ActiveRecord::Base.transaction do
  # ここに処理を書く
end
```

transactionブロック内で例外が発生した場合、ブロック内で行われたデータベース更新処理が全てロールバックされる。


# 注意点

transaction内でrescue句を書くとロールバックされない。
理由は、Railsに実装されているtransactionメソッドで、transactionブロックに対して例外が発生した場合に、rescueしてロールバックするという処理が実装されているため。

```ruby
ActiveRecord::Base.transaction do
    user1.save
    raise 'error'
    user2.save
  rescue => e
    bar # 実行されるがuser1はロールバックは発動しない
  end
```
下記参照！
[Github/transaction](https://github.com/rails/rails/blob/291a3d2ef29a3842d1156ada7526f4ee60dd2b59/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb#L313-L318)


# まとめ
transactionの書き方を深く理解して使っていなかったので、勉強になりました！
時間がある時に他のメソッドも追ってみたいと思います！
iTunesで外付けdvdドライブからCDを読み込んだ時に全曲1分以内で切れてしまった時の対応

:::note warn
『これ試したらなんか解決した』レベルの内容です。
iTunesうんぬんというよりハードが原因の可能性が高そうです。
『似たようなことが起きた時に試す方法の一つ』という参考情報として見て下さい。
:::


# 現象

## メインの症状

下記がCDを読み込みした結果。
全部1分以内になってしまっている。
再生するとその時間でぷつんと切れる。
なので、メタデータの破損ではなく本当にこの時間分しか読み込めていないと思われます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/92ce0ec8-2624-f3b2-6b79-d974f03c9ea1.png)

元のCDの情報を見ると、やっぱり元の曲の長さは違う…。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/5fe7b503-2b12-1f10-c258-0427b4377f3b.png)

## サブの症状

下記のようになるまでに時間がかかる。
つまり『OSがCDを認識する』のに時間がかかる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/25e5a58b-ee9f-38fb-f04a-8ed54ef7365a.png)

iTunesのCD読み込みが異常に遅い。

外付けdvdドライブを使ってるんだけど、CD読み込み中にレーザーを出す部分が無駄に行ったり来たりして『ガコ…ガコ…』って音がしてた。

# これで直った

外付けdvdドライブを指していたUSBポートを変更。
これだけで直った…。

# 蛇足

USBポートがハード的に故障してたのかなー？
または故障しかけてた？

同じUSBインターフェースの別ポートにKensingtonの無線トラックボールのレシーバー差さってた。
そのために何かしらのパワーが足りてなかったのかなー？

『条件変えて検証』が面倒だったから、『直ったからよしっ！』で済ませちゃった。
何が原因かまでは調査せず…。

とりあえず、 **USBに差さってるやつが何かおかしかったら別のポートに差し替えてみるといいかも** という教訓を得た。
Flutter BottomNavigationBarでonTapを実装し表示切り替え

# BottomNavigationBarItemを3つ作成し、各アイコンをタップすると対象のWidgetを表示するようにコーディングしてみる。

```dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int _selectedIndex = 0;
  
  static const _pages =[
    Scaffold(body: Center(child: Text('Home'))),
    Scaffold(body: Center(child: Text('Article'))),
    Scaffold(body: Center(child: Text('Settings'))),
  ];

  void _onTap(final int index){
    setState((){
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('MyApp'),),
        body: _pages[_selectedIndex],
        bottomNavigationBar: BottomNavigationBar(
          items: const [
            BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home',),
            BottomNavigationBarItem(icon: Icon(Icons.article), label: 'Article',),
            BottomNavigationBarItem(icon: Icon(Icons.settings_accessibility), label: 'Settings',),
          ],
          currentIndex: _selectedIndex,
          onTap: _onTap,
        ),
      ),
    );
  }
}
```

# 結果
下のアイコンをタップする都度、対象の文字列が表示されWidgetが切り替わっていることを確認できた。
![スクリーンショット 2023-10-11 0.20.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50452/b49cc93d-5bbd-0901-b790-5d43d6f6d548.png)
【Jetpack Compose】WebViewにpull-to-refreshを実装しようとしたらハマったこと

# はじめに
現在（2023/10/10）Jetpack　Composeでは、WebViewを使うにはAndroidViewで囲む必要があります。対して、pull-to-refreshはJetpackComposeに実装されているPullRefreshと以前のViewのSwipeRefreshLayoutがあります。

結論、SwipeRefreshLayoutで解決しました。

# WebView
Jetpack Composeでは、WebViewを使用するためにはAndroidViewというラッパーを用いてその中にWebViewを配置する必要があります。AndroidViewはJetpack Composeのコンポーザブルから従来のViewシステムを使うための架け橋的存在です。
以下にコード例を示します。

```kotlin
@Composable
fun WebViewContainer() {
    AndroidView(factory = ::WebView) { webView ->
        // WebViewの設定をここで行う
        webView.loadUrl("https://google.com")
    }
}
```
WebViewContainerというコンポーザブル関数の中でAndroidViewを設定しています。factoryの引数でWebViewを生成しています。

# pull-to-refreshの選択肢
pull-to-refreshはViewのSwipeRefreshLayoutとJetpack　ComposeはexperimentalですがPullRefreshが実装されています。

## [View] SwipeRefreshLayout
```kotlin
@Composable
fun WebViewWithSwipeRefresh() {
    val swipeRefreshState = rememberSwipeRefreshState(isRefreshing = false)
    AndroidView(factory = {
        SwipeRefreshLayout(it).apply {
            setOnRefreshListener { /* 処理を記述 */ }
            addView(/* Viewを追加 */)
        }
    }) { swipeRefreshLayout ->
        swipeRefreshLayout.isRefreshing = swipeRefreshState.isRefreshing
    }
}
```
https://developer.android.com/jetpack/androidx/releases/swiperefreshlayout?hl=ja

## [JetpackCompose] PullRefresh
```kotlin
val refreshScope = rememberCoroutineScope()
var refreshing by remember { mutableStateOf(false) }
var itemCount by remember { mutableStateOf(15) }

fun refresh() = refreshScope.launch {
    refreshing = true
    delay(1500)
    itemCount += 5
    refreshing = false
}

val state = rememberPullRefreshState(refreshing, ::refresh)

Box(Modifier.pullRefresh(state)) {
    LazyColumn(Modifier.fillMaxSize()) {
        if (!refreshing) {
            items(itemCount) {
                ListItem { Text(text = "Item ${itemCount - it}") }
            }
        }
    }

    PullRefreshIndicator(refreshing, state, Modifier.align(Alignment.TopCenter))
}
```
https://developer.android.com/reference/kotlin/androidx/compose/material/pullrefresh/package-summary

# 起きた問題
なるべくJetpack Composeを使おうと機運が高まっていたのでPullRefreshとWebView(AndroidView)の組み合わせで実装したところ、うまく機能しませんでした。
原因としては、Jetpack ComposeとAndroidViewを横断してスクロール情報が伝達しなかったようです。

# 上手く行った解決策
WebViewとpull-to-refresh機能を組み合わせる場合はどちらもAndroidView内で実装することで上手くいきました。
SwipeRefreshLayoutとWebViewを同一のAndroidView内に配置することで、SwipeRefreshLayoutの持つスクロールの挙動とWebViewが連携できました。
```kotlin
@Composable
fun WebViewWithPullRefresh(
    webView: WebView
) {
    AndroidView(
        factory = {
            SwipeRefreshLayout(it).apply {
                setOnRefreshListener {
                    webView.reload()
                }
                addView(webView)
            }
        },
        update = { swipeRefreshLayout ->
            swipeRefreshLayout.isRefreshing = /* Refresh状態の制御 */
        }
    )
}
```
これでWebViewのスクロールがSwipeRefreshLayoutと同期して動作してくれました。
WebViewの読み込み状態については工夫して取得しないといけないので、これについてはまたいつか記事にしたいなと思っています。

# 結論
結局、今はJetpack Composeに移行している期間なので、Jetpack ComposeとViewを横断すると失敗するということでした。その時は、AndroidViewを使って、Viewを実装するというやり方が今は無難だと思われます。
【ReactHookForm】refを使用する方法

`React Hook Form`を使用している際にrefを使用するために以下のように記述すると`'ref' が複数回指定されているため、ここでの使用は上書きされます。ts(2783)`というエラーとなります。

```tsx
import React, { useRef } from 'react'
import { useForm } from 'react-hook-form'

type Inputs = {
  firstName: string
  lastName: string
}

export default function App() {
  const { register, handleSubmit } = useForm<Inputs>()
  const firstNameRef = useRef<HTMLInputElement | null>(null)
  const onSubmit = (data: any) => console.log(data)

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input ref={firstNameRef} {...register('firstName')} />

      <button>Submit</button>
    </form>
  )
}
```

refを使用するには以下のように記述します。

```tsx
import React, { useRef } from "react";
import { useForm } from "react-hook-form";

type Inputs = {
  firstName: string,
  lastName: string,
};

export default function App() {
  const { register, handleSubmit } = useForm<Inputs>();
  const firstNameRef = useRef<HTMLInputElement | null>(null);
  const onSubmit = data => console.log(data);
  const { ref, ...rest } = register('firstName');

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...rest} name="firstName" ref={(e) => {
        ref(e)
        firstNameRef.current = e
      }} />

      <button>Submit</button>
    </form>
  );
}


```
箱入り娘パズルを自動で攻略するシステムを作成した



    
# 今回つくったもの



![hakoiri_musumeclear.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092001/e3a45725-822e-f02a-0aa2-196d0d997478.gif)



**箱入り娘**というパズルを幅優先探索を使って自動で解くシステムを作りました。

# 箱入り娘パズルとは

箱入り娘とは、駒を空いている位置にスライドさせることによって、一番大きな**娘**の駒を、枠下部の出口に移動させるパズルです。




![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092001/e08872f0-9c94-8316-b124-e96b49c69cce.png)


枠の切れ目部分に**娘**の駒を運べればクリアです。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092001/3979c09b-ee3a-63ba-d69b-f47a069372a9.png)


# 使い方

以下のコードを実行すると、パズルが自動で解かれ、クリアまでの手順がファイル内に描画されます。

```
$ git clone https://github.com/mimic-asy/HakoiriCpp.git
$ cd HakoiriCpp
$ mkdir build
$ cd build
$ cmake ..
$ make
$ ./Hakoirimusume  
$ cd ..
$ python3 make_fig.py # 時間がかかります
```

## どのように動いているのか

### 前提
箱入り娘のパズルは、盤面同士の関係をグラフ構造で表すことができます。盤面がノード、駒の移動がエッジに相当します。

```plantuml
@startuml
<style>
root {
  Padding 0
  Margin 0
}
header {
  FontColor black
  FontSize 30
}
</style>
center header 図２　各盤面がノードに、駒の移動がエッジに相当する
title <img:https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092001/a4766122-f9f0-4b50-29d3-31bf4ce9c88a.png>
@enduml
```


### 手法
幅優先探索で、スタート盤面からクリア盤面までの経路を求めました。 

![habayuusen (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092001/d3d277f4-0120-4ddd-68c7-608a28d322c3.gif)

## なぜ幅優先探索を用いたのか

深さ優先探索では新しい盤面を発見できない場合、以前に探索した盤面に再び戻り、繰り返し探索を行います。
箱入り娘のパズルの特性上、同じ盤面に何度も遭遇するため、深さ優先探索では探索時間が莫大にふえてしまいます。このため今回は幅優先探索を用いています。

# 今後の展望
更に構造を理解して高速化を行い、１分以下になるようにする。

:::note info
2023/11/5  追記

１分以上探索＋経路捜索に時間がかかっていたが、今回の改良によって３秒位で処理が終わるようになった。


変更点

・幅優先探索の際vectorに既存の盤面を保存しFor文でvector内部の盤面と現在の盤面の確認をしていたが、unorderd_mapに保存するように変更した。辞書構造で既存の盤面を検索できるようにした。

・盤面を自動で動かす関数を見直し、余分なコピーを減らした。

・stringでいくつか比較を行っている箇所をIntで比較するように変更した

・保守性の向上のため、const,参照渡し等の見直しをした。

以上の点を改良した結果、高速化が実現した。
intel上でLXDCLIを用いてGO+Pythonの環境を爆速で構築する

## 目的
Goの環境を構築しろと言われることは多いと思う。今回はintel上でlxdcliを用いてgoの環境を構築しようと思う。

## 構築
lxdfile
```bash
CONTAINERNAME ubuntu-go
FROM ubuntu/23.04


RUN export DEBIAN_FRONTEND=noninteractive
RUN timedatectl set-timezone Asia/Tokyo && hostnamectl set-hostname ubuntu-go
RUN apt-get -y update

RUN dpkg --configure -a
RUN echo "\n\n\n" | apt-get -y install openssh-server
RUN apt-get -y install docker docker.io docker-compose nano curl

RUN echo -e "root:password" | chpasswd
RUN echo -e 'PermitRootLogin  yes' >> /etc/ssh/sshd_config


RUN systemctl enable ssh
RUN systemctl restart ssh
RUN systemctl start ssh


RUN apt-get -y update && apt-get -y install python3-pip nano
RUN mkdir .pip
RUN touch .pip/pip.conf
RUN echo "[global]" >> .pip/pip.conf
RUN echo "break-system-packages = true" >> .pip/pip.conf
RUN wget https://go.dev/dl/go1.20.4.linux-amd64.tar.gz
RUN mkdir -p /usr/local/go/bin
RUN tar -C /usr/local -xzf go1.20.4.linux-amd64.tar.gz
ENV PATH $PATH:/usr/local/go/bin
RUN export PATH=$PATH:/usr/local/go/bin
RUN echo "export PATH=$PATH:/usr/local/go/bin" >> ~/.bashrc
```

## ビルド
```bash
lxdcli build lxdfile
```
DOMの仕組みと構造を知る

## なぜ知る必要があるか？
JavaScriptを使ってWebページに動きを付けるには、DOMの操作が必要。でもその前に、DOMの仕組みと構造を知らないと、どうやって操作したら良いか混乱する


## DOMとは何か？
「Document Object Model」の略で、Webページ全体のコンテンツはオブジェクトだった。そして、JavaScriptから特定のオブジェクトにアクセスすれば、Webページに動きを付けることが出来る
つまりDOMは、JavaScriptからHTMLの「どこ」に「何」をするかを実現するための仕組みである


## DOMはどんな特徴があるか？
**①枝分かれした木構造になっている(DOMツリーと呼ぶ)**

```index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript basics</title>
  </head>
  <body>
    <ul id="list">
    </ul>
    <input id="input_text" type="text">
    <input id="button" type="button" value="Add!">
    <script src="main.js"></script>
  </body>
</html>
```

[index.html]のHTMLタグを、DOMツリーとして表現したもの

```
document(ドキュメントノード)
  └── html(要素ノード)
       ├── head
       │    ├── meta ─── charset(属性ノード)
       │    ├── meta ─── http-equiv ─── content
       │    ├── meta ─── name ─── content
       │    └── title
       │          └── #text JavaScript basics(テキストノード)
       └── body
            ├── ul ─── id
            ├── input ─── id ─── type
            ├── input ─── id ─── type ─── value
            └── script
```

要素タグや要素内の属性などは、オブジェクトでありDOMツリーとして構成されていた

**②HTMLの各要素をノードとして扱う**
DOMツリーではHTMLの各要素をノードと呼んでいる

・ドキュメントノード
全体を表すdocumentオブジェクト(DOMツリーだと根の部分)
・要素ノード
要素を表すオブジェクト(DOMツリーだと、document配下で起点となる部分)
・テキストノード
要素内のテキストを表すオブジェクト(DOMツリーだと、要素ノードに設定したテキスト)
・属性ノード
要素の属性を表すオブジェクト(DOMツリーだと横棒の部分)
・コメントノード
コメントを表すノード

※DOMツリーの位置に応じて各ノードの関係がある
・ルートノード
・親ノード
・子ノード
・子孫ノード
・兄弟ノード

```
document
  └── html
       ├── head
       │    ├── meta ─── charset(属性ノード)
       │    ├── meta ─── http-equiv ─── content
       │    ├── meta ─── name ─── content
       │    └── title
       │          └── #text JavaScript basics
       └── body
            ├── ul ─── id
            ├── input ─── id ─── type
            ├── input ─── id ─── type ─── value
            └── script
```
上記のhtml要素の場合、documentの子ノードで、headとbodyの親ノードである


## 調べてみて分かったこと
HTMLで指定した要素や属性は全てオブジェクトとして扱われ、JavaScriptでオブジェクトを指定してWebページに動きを付ける必要がある。
DOMツリーのノードを操作するメソッドが多いので、指定方法に困ったらDOMを確認した方が良さそう。
Jest toEqualとtoStrictEqualの違いについて理解する

# 目次
1. 背景
2. toStrictEqualとは
3. サンプルコード

# 背景
toStrictEqualをjestのdocumentで見て気になった為です。

# toStrictEqualとは
- undefinedの要素が考慮されます
    - [2]は[2, undefined]とは等しくないです。
    - {a: undefined, b: 2}は{b: 2}とは等しくないです。
- 配列の疎密がチェックされます。例えば、[, 1]は[undefined, 1]とは等しくないです。
- オブジェクトの型がチェックされます。例えばフィールドaとbを持つクラス・インスタンスは、フィールドaとbを持つリテラル・オブジェクトとは等しくないです。

# サンプルコード
こちらのリポジトリで確認可能です。
[jest-strict-equal](https://github.com/yamatai12/jest-strict-equal)

```StrictEqual.test.ts
class Class {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}

it("同一の確認", () => {
  //値が同じなのでpass
  expect(new Class("名前")).toEqual({ name: "名前" });
  //型が違うのでfail
  //   expect(new Class("名前")).toStrictEqual({ name: "名前" });

  expect([2]).toEqual([2, undefined]);
  // undefinedの要素が考慮されるのでfail
  //   expect([2]).toStrictEqual([2, undefined]);

  expect([, 2]).toEqual([undefined, 2]);
  // undefinedの要素が考慮されるのでfail
  //   expect([, 2]).toStrictEqual([undefined, 2]);
});

```

# 参考
- [JestのTips集10選。サーバーサイドでNode.jsのJestを書いたことない人向け](https://zenn.dev/kanasugi/articles/b49bd464311053)
- [Jestの比較メソッドについて](https://qiita.com/kitanote/items/511ca885e9ac304d7efc)

# 参考になる記事を書いてくださった皆様に感謝致します
Flutter BottomNavigationBarItem の必須属性 label

BottomNaviationBarを必要最低限書いて実行したところ。実行時エラーとなった。コンパイルエラーにはなっていなかった。
```dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  const Home({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Home'),),
      bottomNavigationBar: BottomNavigationBar(
        items: const [
          BottomNavigationBarItem(icon: Icon(Icons.home),),
          BottomNavigationBarItem(icon: Icon(Icons.article),),
          BottomNavigationBarItem(icon: Icon(Icons.accessibility),),
        ],
      ),
    );
  }
}
```
原因は、BottomNavigationBarItemの属性であるlabelが未設定(null)となったことで実行時エラー。コンパイル時にチェックはできないものなのだろうか。Flutterの仕様を理解すれば当たり前のことなのか、まだこれから学んで行きたいと思う。以下のように、適当なlabelを追記する。
![スクリーンショット 2023-10-10 23.21.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50452/df66ec9a-67c2-249a-63c7-84de025119de.png)
```dart
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home',),
BottomNavigationBarItem(icon: Icon(Icons.article), label: 'Article',),
BottomNavigationBarItem(icon: Icon(Icons.accessibility), label: 'Settings',),
```
今度は期待の通りアイコンが下に表示された。もちろん、onTapを実装していないので、アイコンを押しても画面の切り替わりなどは一切ない。
![スクリーンショット 2023-10-10 23.28.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50452/c40d7a6e-2e4e-b138-d0b3-fcb04e4bdb4f.png)
【React】複数の入力の処理

## 複数の入力の処理

:::note
複数の制御された`input`要素を処理する必要がある場合、それぞれの入力要素に`name`属性を追加することで、ハンドラ関数に`event.target.name`に基づいて処理を選択できるようになる。
:::


具体的なコード例

```react
class Reservation extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isGoing: true,
      numberOfGuests: 2
    };

    this.handleInputChange = this.handleInputChange.bind(this);
  }

  handleInputChange(event) {
    const target = event.target;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    const name = target.name;

    this.setState({ // 渡された入力名に対応するstateのキーを更新する構文
      [name]: value
    });
  }

  render() {
    return (
      <form>
        <label>
          Is going:
          <input
            name="isGoing" // name属性の追加①
            type="checkbox"
            checked={this.state.isGoing}
            onChange={this.handleInputChange} />
        </label>
        <br />
        <label>
          Number of guests:
          <input
            name="numberOfGuests"　// name属性の追加②
            type="number"
            value={this.state.numberOfGuests}
            onChange={this.handleInputChange} />
        </label>
      </form>
    );
  }
}
```


---

https://ja.legacy.reactjs.org/docs/forms.html
nginxのインストール方法【Windows編】

仕事でnginxをインストールする必要があり、調べたのでそのまとめ。
## nginxの導入
Windowsにnginxをインストールする際の手順は以下の通り。
①nginxのダウンロード
②ダウンロードファイルの展開
③nginxの実行
### nginxのダウンロード
[nginxの公式サイト](https://nginx.org/en/download.html)からnginxのwindows版をダウンロードします。

### ダウンロードファイルの展開
ダウンロードファイルを展開します。
今回はCドライブ直下に展開しました。
![nginx_install_windows_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493608/c42b7f82-ef5d-6d52-9f08-164854ad57b3.png)

### nginxの実行
nginxがあるディレクトリに移動して以下のコマンドで実行します。
![nginx_install_windows_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493608/687c2af2-f1d1-fa63-b0dd-9d58448ec4a2.png)

`http://127.0.0.1`にアクセスするとnginxの初期画面を表示できます。
![nginx_install_windows_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493608/feb88d6d-be52-5d2b-e3c3-410827ebb3d8.png)
Twitterで質問箱の画像が表示されない場合の対処法

# 状況
今回対象となる表示：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3382085/233f0997-cb33-e493-7aa2-bda1f24d9f5c.png)
正常な表示：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3382085/dd0ec458-837f-3988-4058-812ca022942c.png)

# 環境
Google Chrome Dev 120.0.6051.2

# 対処
・リンク先を開く。
・Ctrl+Shift+Iでデベロッパーツールを開き、head内のmeta name="twitter:image"の項目を探す。
・content=の中のリンクをアドレス欄にコピペする。

結果の例：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3382085/932caaae-3cef-7e07-dfab-a034fb53e45e.png)
MacのEmacsでC-M-dが効かない！

Emacsでのカーソルする際、`C-M-d` というキーバインドをよく使います。

`C-M-d` はデフォルトで `down-list` というコマンドにバインドされていて、上手く説明できませんが、とにかく一つ下の階層の括弧(っぽいもの)の中に入って行けます。

![ezgif-5-a606dd6a8f.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597113/15235666-df25-9e7a-9afc-93fec9108a15.gif)

ちなみに、括弧の外に出ていくのは `C-M-u`、対応する先の括弧に進むのは`C-M-f`、対応する前の括弧に戻るには `C-M-b`を使ってます。こんな感じです：

![ezgif-5-d1bd3fa8bd.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597113/5df5d9c6-72b9-a32c-a5ea-966f355e8451.gif)

本題ですが、最近新しくMacを買ってEmacsを使っていたら`C-M-d` が効かないことに気づきました。調べたところ、Macの辞書検索?の[ショートカット](https://support.apple.com/en-us/HT201236#:~:text=Command%2DD%3A%20Select%20the%20Desktop,definition%20of%20the%20selected%20word.)に取られてしまっているようです :cry: 

>Control-Command-D: Show or hide the definition of the selected word.

解決方法は[こちら](https://apple.stackexchange.com/a/114269)のページの通り、以下のコマンドを実行することで直ります :laughing: 

```
defaults write com.apple.symbolichotkeys AppleSymbolicHotKeys -dict-add 70 '<dict><key>enabled</key><false/></dict>'
```

**実行後はMacを再起動する必要があります!**

以上です！
[Angular] @Input,@Outputとちょっと@ViewChildについて

### @ Input

::: note

//@Input() property名:型;と定義する。

@Input()は、
子componentが親componentからの値を取得したい場合に使用します。
:::

```説明.
@Input()の使い方
【Paret側】
①htmlでChildcomponentのセレクタータグを記載。
 →下記例では、<app-child></app-child>
②childセレクタータグで、プロパティバインディング記載
 →[getValue]="$any(studyForm.get('memo'))"

補足１：getValueがChildcomponentで定義したInputデコレータpropertyです。

補足２：$any()は型チェックを一時的無視する意味を持ちます。
    　　型FormControlの値をbindingしようとすると型エラーとなり
　　　　解決できなかったので使いました。

【Child側】
①@Input() property名：型;を定義します。

```



```Parent.ts
  /**入力フォーム */
  studyForm = new FormGroup({
    startTime: new FormControl(''),
    endTime: new FormControl(''),
    category: new FormControl(''),
    memo: new FormControl(''),
    daily: new FormControl('')
  });
```

```Parent.html
<app-child
  [getValue]="$any(studyForm.get('memo'))"
></app-child>
```
----
```Child.ts
@Input() getValue:FormControl | undefined;
```
```Child.html
<p>
  {{ getValue?.value }}
</p>

//補足: ?(オプショナルチェイニング)は、
//オブジェクトのプロパティが存在するかチェックしなく存在しなければundefinedを返す機能です。
```

### @ Output

:::note

@Output() は、
子コンポーネントでイベント定義して、そのイベントが発火したときに
親コンポーネントで何らかの処理を実行したい際に利用する。

使用方法：
【Parent側】
①Childcomponentのセレクタータグを記載。
②イベントバインディングをセット。
　→<app-tChild (eventDD)="outputTest()"></app-tChild>
【Child側】
①@Output() eventDD = new EventEmitter();を定義
②eventプロパティを変更する処理を実装する
:::

```Parent.html
<app-tChild (eventDD)="outputTest()"></app-tChild>
```
```Parent.ts
  outputTest(){
    console.log("検知して親コンポーネントのmethodが実行された。");
  }
```
------
```Child.html
特に不要
```
```Child.ts
　//buttonタグclickで実行される。
  public submitClickForm(){
    console.log(this.studyForm.value);
    /**入力データグローバル変数保持処理 */
    this.topSerivce.variableSetting(this.studyForm.value);

    this.eventDD.emit("A");　//★
  }

```

@ViewChild()

:::note
@ViewChild()は、
親componentから子componentディレクティブまたは、
親componentからDOM要素へアクセスしたい際に利用する。
:::