OmniAICreator/Qiita-1.07M huggingface dataset:
LaTeXでPlantUMLのファイルを読み込む

# LaTeXでPlantUMLを使う(本来のやり方)

$\LaTeX$には`plantuml`パッケージなるものがあり、以下のような使い方をします。

```latex
\documentclass{scrartcl}
\usepackage{plantuml}

\begin{document}
  \begin{plantuml}
    @startuml
    Alice -> Bob: test
    @enduml
  \end{plantuml}
\end{document}
```

しかし、この方法には欠点があります。

* VSCodeでハイライトが効かない
* PlantUML部分が長いと$\LaTeX$ファイルの管理が大変
* 環境変数`PLANTUML_JAR`を設定する必要がある

そこで、PlantUMLファイル(.pu)を`\includegraphics`で直接読み込めるようにしてみました。

(PlantUMLファイルをVSCodeで編集する方法に関しては[この記事](https://qiita.com/couzie/items/9dedb834c5aff09ea7b2)を参考にしてください)

# LaTeXでPlantUMLファイルを読み込もう

**環境はLuaLaTeXです。それ以外の環境だと動かない可能性があります。**

## 方針

`epstopdf`パッケージを使うと、`\epstopdfDeclareGraphicsRule`コマンドで、**`\includegraphics`で特定の拡張子のファイルのときのみ変換処理を施す**ということが可能になります。この仕様を利用します。

## 方法

必要なソフトウェア:
* Pythonをインストールしておきます
* [PlantUMLをダウンロード](https://plantuml.com/ja/download)して`plantuml.jar`にリネームし、$\LaTeX$ファイルがあるディレクトリに配置します
* InkscapeもインストールしてPATHを通します
* Javaも最新版を入れておきましょう

以下のスクリプトを「pu2pdf.py」という名前で作成します。

```pu2pdf.py
from sys import argv
import os

if len(argv) == 3:
    cat = 'cat'
    if os.name == 'nt':
        cat = 'type'
    tmp_dir = 'svg-inkscape'
    os.makedirs(tmp_dir, exist_ok=True)
    svg = os.path.join(tmp_dir, argv[1] + '.svg')
    os.system(cat + ' ' + argv[1] + ' | java -jar plantuml.jar -charset UTF-8 -tsvg -pipe > ' + svg)
    os.system('inkscape -z --file=' + svg + ' --export-pdf=' + argv[2])
```

また、$\LaTeX$ファイルのプリアンブル部分にはこのように書きます。

```latex
\usepackage{graphicx}
\usepackage{epstopdf}
\epstopdfDeclareGraphicsRule{.pu}{pdf}{.pdf}{
  python pu2pdf.py #1 \OutputFile
}
```

あとは、$\LaTeX$の本体部分でこのようにすれば、PlantUMLのファイルを使うことができます。

```latex
\includegraphics{ファイル名.pu}
```

`lualatex -shell-escape ファイル名.tex`を実行します。この`-shell-escape`オプションがないと動きません。

## Pythonスクリプトの解説

Windows環境にも対応するため、Windows環境の場合は`cat`コマンドの代わりに`type`コマンドを使用します。

次にPlantUMLを呼び出し、パイプを利用してPlantUMLファイルの内容を流し込みます。また、リダイレクトを利用してSVGに吐き出します。

最後にInkscapeを呼び出してSVGからPDFに変換します。

# 余談: Pandocでも使える

Pandocでも使えます(yamlでheader-includesを使ってプリアンブルに宣言する必要はある)。

```Markdown
![キャプション](ファイル名.pu)
```
Nextcloud 27.1.6でゴミ箱にあるはずのファイルが表示されない

# Nextcloud 27.1.6固有のバグらしい

https://nextcloud.stylez.co.jp/blog/techblog/does_not_show_deleted_files_v27.html

修正は次バージョン（27.1.7）で行われる予定とのことだが、github上のリリース予定を見ると2/22なのでそこまでは待てない。

https://github.com/nextcloud/server/milestone/254

# 当座の回避策
1. バージョンダウン
セキュリティ上好ましくないのでやりたくない
1. 公式サイトで案内されている修正ファイルを利用する
項番3が利用できない（管理者特権がないまたはそもそもコマンドが打てない）場合、またはゴミ箱内のファイルを削除するだけでは困る場合にはこれがよいか
1. occコマンドで削除する
ゴミ箱内のファイルを削除したいだけならば、コマンドでも削除できるので今回はこれを採用

# snap版の場合のやり方
以下のコマンドで削除される。
`sudo nextcloud.occ trashbin:cleanup [--all-usersか、特定のユーザーを指定する]`
（警告なく直ちに削除されるので注意）
品評会専用画像加工ツールを作りました

## 品評会画像メーカー

新しいウェブアプリをリリースしました。

- [品評会画像メーカー](https://hinpyoukai.com)
- [デモ動画](https://youtu.be/LVaNkMEKZw8)
 
## アプリの説明

集合写真のURLを入力すると、各人物の顔に番号を割り振った画像を出力するツールです。

### 入出力例

**入力画像**

![img3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681892/11fde906-917c-0e64-037b-5520305a38b2.png)

**出力画像**

![img.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681892/e8c08100-1380-17ed-6d41-ac64af709c9d.jpeg)

### 入出力例2

**入力画像**

![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681892/cbd7d26e-03fd-fbb4-4c14-20d42059ae49.jpeg)

**出力画像**
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681892/5b60f502-d49e-53d8-4d68-59c1b1d29778.jpeg)


## 使い方

URL入力欄に画像のURLを入力します。オプションで**番号のフォントサイズ**、**番号の位置を顔の上にするか横にするか**、**番号に()をつけるかつけないか**を選択できます。

![img1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681892/51a26952-e4b3-19f4-52b0-c048d0fb1f07.png)

**解析する**ボタンを押すと人物に番号を割り振った画像のURLが出力されます。解析後の画像がImgurにアップロードされ、解析後の画像のURLが表示されます。

![img2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681892/419cb3f9-beb5-ce6a-113e-b84dca7bb90a.png)

## 使用技術とアプリの仕組み

### フロントエンド

フロントエンドはReactを使用しています。なお、作者はHTMLとCSSを書けないためスタイリングにはReact Native Webを使用しました。

フロントエンドでは、入力された画像URLとオプション(フォントサイズや数字位置など)をaxiosを使ってウェブAPIにPOSTリクエストを送信しています。

APIからは番号を振った後の画像のURLが返されます。出力結果としてAPIから返された画像URLを表示しています。

### ホスティング

アプリのホスティングにはFirebase Hostingを使用しています。

### バックエンド

バックエンドでは以下の処理を行うPythonスクリプトをCloud Runで実行しています。

1. フロントから送信されてきた、画像のURL、数字の位置、フォントサイズ、カッコのオンオフなどのパラメーターを受け取る
1. フロントから受け取った画像URLから画像をダウンロード
1. Face Recognitionパッケージを使用して顔の位置を特定
1. 顔の位置に数字を描画し、画像を保存
1. Imgurのパッケージを使用して処理後の画像をアップロード
1. アップロードされた画像のURLをフロントに返す

## ソースコード

ソースコードはGitHubに公開しています。

- [フロントエンド](https://github.com/kiyohken2000/hinpyoukai-front)
- [バックエンド](https://github.com/kiyohken2000/hinpyoukai-api)

## まとめ

精度はまぁまぁ高い。
【Rails】namespaceとは(管理者と会員の閲覧ページを管理)

こんばんは！
今日からいよいよスクールのチーム開発が始まりました！
これまでは管理者側の機能を作ることがなかったため、namespaceというものを初めて知りました。本記事ではnamespaceの理解を深めるためにまとめていきたいと思います。

## namespaceとは？？
 namespace とは、決めた名前でルーティングのグループ分けをするための仕組みです。
 
 例えばECサイトの場合、会員が見ることができるページと管理者のみ見ることができるページを作る必要があります。そのために同じファイル上でif文を用いて管理者と会員で閲覧部分を分けるのは可読性も下がりますしコードが複雑化します。また、コントローラーの名前とモデル名が統一されていないため、設計上あまり好ましくありません。
 
 この問題を解決できるのが、**namespace**です！

 ## namespaceの実装
 　同じデータを扱うコントローラーとviewを会員側と管理者側の2つ作成し、publicフォルダとadminフォルダに分けて管理します。また、ルーティングも会員側と管理者側で分けます。

### コントローラー
```terminal:terminal
$ rails g controller コントローラー名 #会員側
$ rails g controller admin/コントローラー名　#管理者側
```
　ターミナルでコントローラーを上記の通り作成します。adminの部分はnamespaceのグループ名を入れればよいので、他のものに変更してもOKです。今回はadminで作成しています。作成した会員側のコントローラーのファイルはapp/controller/publicの配下に配置してください。
　その後、必要なアクションを各ファイルごと記述をしてください。

### ルーティング
　routes.rbに以下のように記述します。(これは記述例です。必要・不要なアクションがあれば適宜記述を変えてください。また、admin部分はコントローラーを作成した際のnamespaceのグループ名に適宜変えてください)今回は会員側の記述にresourcesメソッドを使っていませんが、使用することができます。
 ```ruby:routes.rb
 Rails.application.routes.draw do
  get 'items' => 'public/items#index' #会員側
  namespace :admin do　#管理者側
    resources :items, only: [:index]　
  end
end
```
これで会員側と管理者側のページのURLを分けることができました！

一応namespaceの実装の説明は終わりですが、この方法以外にも`scope module: :public do`などをroutes.rbに書くことでもviewページのURLを分けて管理することができるそうなので気になる方はぜひ！

今日もお疲れ様でした！
世界一流エンジニアの思考法　第1章「世界一流エンジニアは何が違うのだろう」

# 世界一流エンジニアの思考法
こちらはマイクロソフト社のシニアエンジニアである「牛尾剛(著作)」が、マイクロソフト社で働く一流エンジニアから **エンジニアとして働く上での思考法(マインドセット)** を記してくれた一冊である。僕なりにまとめて気づきなどを残していく記事になりますので、なんとなくで読んでもらえると嬉しいです。

![81RO+wECc0L._SY522_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3673349/e92e32bc-3f81-297b-9ad9-def727531a99.jpeg)

## 第1章「世界一流エンジニアは何が違うのだろう」
### ⚫️「手を動かす前に仮説を検証する」...事実(データ)を一つ見つける→いくつかの仮説を立てる→その仮説を証明するための行動をとる　こと。
つまり、むやみやたらに試行錯誤するのではなく、まずは自分の頭のメンタルモデルを使って仮説を立て証明する。

### ⚫️「理解に時間をかける」を実践する
著者が考える「理解」とは次の3つとなる。

・その構造を掴んで、人に説明できること。
・いつでもどこでも即座に取り出して使えること。
・知見を踏まえて応用が効くこと。

「早くできるように頑張る」ということはがかえって生産性を下げており、どんなに頭の良い人でも理解には時間がかかるものであって、基礎の基礎を蔑ろにしてはいけいない。

### ⚫️「頭の中に「メンタルモデル」を作る」
メンタルモデルとは、人々が世界を理解し、予想し、解釈し、新しい状況に適用するための自己の心のイメージや理論である。
（＝トヨタの「なぜなぜ分析」にも通じる）
これを身につけると、頭の中で考えを整理したり、問題発見に至るプロセスが大幅に加速化することができる。

## 気づきなど
エンジニアになるため、日々ポートフォリオや言語などの勉強している中で　"なるべく手を動かして動かして"　と意識して一番重要な「仕組みの理解」や「基礎」を疎かにしていたと思う（この機能が欲しいから色々と検索してコードを拾ってきて実装して完成したらOKみたいな感じをしてました。泣）。誰でも理解には時間がかかるわけで焦って重要な部分を疎かにすると後々苦しむの自分自身だと気づきました。未経験で理解するにはかなりハードルは高いですが、意識はできる、諦めずに喰らいつくぞ！
BEMの個人的Tips

## BEMとは
Block Element Modifierの略で、CSSを設計・命名していく手法の１つである。
- Block: 大枠となる独立した要素
- Element: Blockを構成する要素
- Modifier: BlockやElementの状態

## BEMのtips
- Blockの単位と大きさは適当でOK
- Blockに対してModifierは使わない
- Blockにはmarginを指定しない
- BlockとElementのマルチクラスのみ許容する
- 共通にしたいスタイルは専用ファイルに切り出す

### Blockの単位と大きさは適当でOK
Blockの大きさの判断基準
- 複数箇所で使用しそうかどうか
再利用しそうかどうかを基準に割と適当でに決めたので良い

### Blockに対してModifierは使わない
必要ないため
BlockのModifierを使用しなくても、表現したいUIは表現することができる
むしろ、SCSSを複雑化させるだけである

### Blockにはmarginを指定しない
margin以外にも、位置を指定するようなスタイルは指定しない
Blockは複数箇所で使われるかもしれないということを考慮すると、marginなど要素の位置に影響するスタイルを指定していると、汎用性を下げることにつながるため

### BlockとElementのマルチクラスのみ許容する
でも、どうしてもBlockにmarginを指定したいという場合は、`Block __Element`でマルチクラスとし、marginを指定する
例
```sample.html
<div class="header">
	<nav class="header__nav nav"></nav>
</div>
```

### 共通にしたいスタイルは専用ファイルに切り出す
サイト全体で統一させたいスタイルがある場合、専用ファイルで定義しておき、そのファイルを各SCSSファイルでimportし、必要箇所でextendeする

blockではそれぞれ要素を定義する必要はあるが、スタイルを毎回定義する必要もなくなり、変更も１箇所だけで良くなるため、開発効率、保守性ともに向上させることができる


## 参考
https://qiita.com/Takuan_Oishii/items/0f0d2c5dc33a9b2d9cb1
バルクでinsertして採番された主キーを取得する方法

# バルクでインサートは早いけど・・
- バルクは採番されたキー達を取得することができない。
- 一個一個for文でinsertすれば、例えばPHPなら`$model->insert_id;`とかで取れる。
- でもバルクだと取れない。性能改善したいのにこれだと後続処理を大幅に変える必要があるか、主キー項目でない項目でinsertしたデータをselectし直さなきゃいけない。きっとそれは遅い・・・

# ならキーを自分で採番すればいいじゃん
- こんな感じで解決。実装はポスグレで行った。
※ 言語は問わないと思ったので適当言語・・
1. シーケンスになってる主キーの現在値を取得
   ```sql
   $maxId = select nextval('主キー');
   ```
1. バルクで入れたい項目の数だけキー値をインクリメント
   ```PHP
   $minId = $maxId;  // 後で使うので取っとく
   $maxId += count($bulkInsertList);
   ```
1. インクリメントした数だけシーケンスを進めちゃう
   ```sql
   select setval('主キー', $maxId);
   ```
1. バルクで入れたい配列に主キー値を設定した上でバルクインサートする
   ```PHP
   for($bulkInsertList) {
     // (略)
     // $minId ～ $maxIdを主キー項目に設定
   }

   // 主キー項目入りのバルクで入れたい配列をバルクインサート
   bulkInsert($bulkInsertList);
   ```
1. 後続処理で主キー項目を使って処理継続できる。

# ポイント&注意
- setval()などでシーケンスを予め進めておけばこの処理に時間がかかってる間に別の処理で当該テーブルにインサートされても進めた先のシーケンスから採番されるから主キーはズレない。
- シーケンス進めるのはトランザクション張っててもロールバックできないから、処理ミスってるとめっちゃシーケンス進んじゃう可能性あるので注意。
enPiTでの「感想畑」開発

筑波大学2024年度授業enPiTでチーム開発をしたときの記録です。

# 開発したプロダクト
-プロダクト名：感想畑
-webアプリケーション
https://kanso-batake.vercel.app/

**背景**
【対象】
-研究に関わる全ての筑波大生

【課題】
-論文を理解するのが難しい
-研究室内でサーベイ情報が整理されていない
-論文に慣れていないので浅く広く眺めたい

【解決法】
-他の筑波大生が投稿した論文のまとめ情報を読むことで論文の概要を理解する
-タグ機能を使用して研究室内での共有場所とする
-タグ検索や関連する研究室からまとめを眺めることでその分野ではどのような研究が行われているかを知る

【独自性】
-利用者を筑波大生に絞ることにより、信頼度の高い情報を提供
-Notionよりも広い範囲で他人のサーベイを見ることができる
-投稿時は論文のdoiを入力するだけで基本的な論文情報を入力可能

# 感想畑の使い方
googleアカウントやメールアドレスでサインイン

**論文を探したい**
1. トップページの投稿順の論文まとめを読む
2. 検索バーから論文タイトルを検索
3. 検索バーからタグ検索

**論文を投稿したい**
1. 右上のハンバーガーボタンから「レビューを作成」を選択
2. doiを入力
3. 論文を読んだまとめを自身のフォーマットで記入
4. 投稿

**他にも**
1. マイページから過去に自分が作成した論文まとめを閲覧
2. マイラボから自分の研究室メンバーが投稿した論文まとめを閲覧
3. まとめ方の気に入った投稿者や気になる分野を扱っている研究室をクリックすることでさらに広い範囲を調査


# メンバーの主な役割と振り返り
山岨 寛門：プログラミング開発（フロントエンド寄り）、モック作成
大作 春輝：プロダクトオーナー、プログラミング開発（バックエンド寄り）
三浦 隼：スクラムマスター、プログラミング開発（フロントエンド寄り）、モック作成
土居 亮斗：プログラミング開発（フロントエンド寄り）
関 拓己：プログラミング開発（バックエンド寄り）
赤田 真由：プログラミング開発（フロントエンド寄り）、モック作成

# 開発中意識したこと
**デモの改善**
秋スプリントでは毎回の終わりにショートレビューがあり、デモを発表する時間が設けられていたが、開発時間が短く、デモの準備を十分に行うことができなかった。また、他のチームの発表を聞く時にもあまり手を動かすことをせず受動的になってしまっているという話し合いがチーム内で行われた。特に私たちのチームは研究者を対象としており、多くの学部3年生にはストーリーが伝わりにくいという問題を抱えている。

発表を聞いている人が受動的ではプロダクトが十分に伝わらず、レビューが来なくなってしまっていた。

そこで、デモの方法を大幅に変えることで聞いている人に手を動かしてもらい、レビュー会全体を活発化させることを試みた。

具体的には、見るだけで完結してしまう画面共有を基本的に廃止し、各自のパソコンでプロダクトを動かしてもらいながら説明を行った。また、それだけでは説明不足となりプロダクトの使い方が分からなくなってしまうことを考え、発表者以外は教室で歩きながら案内役としてプロダクト使用のサポートを行った。

これにより、1日に数件、酷いときには0件だったレビューも10件以上貰えるようになり、後半のプロダクトの改善や方向性の検討にとても良い影響をもたらした。


**振り返りの改善**
enPiTでは、毎回のショートスプリントの最後に各チームで振り返りを行う時間があった。しかし振り返り自体はいくつも挙げられるものの、長期間にわたって重要なものとその回のみの軽いものの区別が付きにくい、数日後の授業には前回の反省を忘れてしまっているという問題があった。

そこで私たちのチームは、一度メンターの方に振り返りを見てもらい、良かったことと悪かったことの中でも重要なものに各自で星のスタンプを付け、スタンプの多いものを長期間残しておく方法を教えていただいた。この方法は重要な振り返りを見やすくし、また自分以外のメンバーがどの振り返りを重要に思っているかをとても分かりやすくした。

そして振り返りが終わり、その日の授業が終了した時にはmiroのボードの上に大きく「振り返りをする」というメモを置き、次回のプランニング時に必ず前回の振り返りを思い出すことのできるようにした。


# 個人的な振り返り
enPiTの授業を受けて、私は大幅に成長することができた。授業選択の際には、先輩からなかなかに重い科目だと聞かされていたため受講するか悩んでいたが、チーム開発というものに惹かれ、また就職活動の時に胸を張って頑張ったと言えるならばと、受講を決めた。

実際に受講し終えた感想としては、期待していたよりも多くのことを学んだ。大学院から筑波大学に来た私は周りがどれほどのスキルを持っているのかを知らなかったが、自分より遥かに高いプログラミングスキルを持ったチームメンバーにとても驚き、やる気に繋がった。また、チーム開発の話し合いの場では私の意見が大きくプロダクトの方向を決めることもあり、プロダクト開発の楽しさを知ることができた。

これらの学びは現在取り組んでいる就職活動にも活かすことのできるものであり、受講を決める時の考えは間違っていなかったことを嬉しく思った。

最後に、このプロダクトの開発およびその成果に向けて貴重な助言とご指導をいただいた教員やメンターの皆様に心から感謝申し上げます。
PowerShellでcsvを読み込んで内容をいじってexportする

以下のようなcsvがあるとして
```powershell
#C:\Users\ユーザー名\Desktop\test.csv
#csvの内容↓
#date,price,result
#"2024/01/01","3,000","OK"
```
* dateから"/"を取りたい
* priceの","を取りたい
* 文字コードをUTF8にしたい
 と思ったときは
```powershell
Import-Csv -LiteralPath 'C:\Users\ユーザー名\Desktop\test.csv' -Encoding Default | Select-Object @{Name='cnv_date';Expression={$_.date -replace "/", "" }},@{Name='cnv_price';Expression={$_.price -replace ",", "" }},"result" | Export-Csv -Path "C:\Users\ユーザー名\Desktop\cnv_test.csv" -NoTypeInformation -Encoding UTF8
```

とすると以下のようなCSVとなる。

```powershell
#C:\Users\ユーザー名\Desktop\cnv_test.csv
#csvの内容↓
#cnv_date,cnv_price,result
#"20240101","3000","OK"
```

(-NoTypeInformationをつけないと出力csvの1行目に不要な文字列が記録される)
Dark Reader をchoromeの生成AIに適応させる方法

問題：Dark Readerがchoromeの生成AI部分に適用されない

解決方法：Googleのダークモードを適用して、拡張機能のDark Readerの機能はオフにするとダークモードで生成AIを見られるようになる。

手順

1\.「google dark mode」と検索し、検索モードのダークモードを適用する。
2\. chorome検索バー右の拡張機能からDark Readerを開き、設定画面を表示する
3\.サイトリストの非反転リストに、www.google.comを入れる。
Flutterで"setState() or markNeedsBuild() called during build."に対処した話

Flutter 初心者のYukiです。
[Google Developer Student ClubsのSolution Challenge](https://developers.google.com/community/gdsc)に挑戦する際、Flutterに初挑戦しました。
その最中に遭遇したエラーとその対処法について記事にしました。

# 遭遇したエラーについて
遭遇したエラー自体はこのようなものでした。
```
setState() or markNeedsBuild() called during build.
```
このエラーの原因はbuild後に実行されなければいけない処理がbuild最中に実行されていたことが原因です。
具体的には、Navigator.pop()をState変更検知と同時に行おうとしていたところ、build後でないと実行できないという状況でした。

# 対処方法について
次のように書くことで、build後に実行する処理として登録できるようになりました。
```dart
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
    Navigator.pop(context);
});
```
これで、build直後のコールバックとして、Navigator.pop(context);を処理できるようになりました。

# 参考にさせていただいたサイト

https://www.flutter-note.fun/build-callback/
同じソースコードだと思っているが実際のレイアウトに違いが生じるHTML

# 問題点 同じソースコードだと思っているがレイアウトに差が生じている。

# 解決法 打ち間違えている可能性。

```html
<!DOCTYPE html>
```

これを打ち間違えている可能性があります。
Keras メモ

Kaggleの参考にしているNotebookを見ながら、わからないところをひたすらにメモする

## Kerasとは
https://ja.wikipedia.org/wiki/Keras

Wikipediaで紹介されている文面としては以下のようなものだ

> Pythonで書かれたオープンソースニューラルネットワークライブラリである。MXNet（英語版）、Deeplearning4j、TensorFlow、CNTK、Theano（英語版）の上部で動作することができる

この"上部で動作する"という表現がいい表しているように思える

[This Is What Makes Keras Different, According To Its Author](https://www.forbes.com/sites/quora/2016/08/25/this-is-what-makes-keras-different-according-to-its-author/?sh=36449e4b66cf)
こちらにはこう記されている(Deepl訳)
> Kerasを使用すると、基盤となるバックエンドエンジンであるTheanoやTensorFlowと対話することなく、エンドツーエンドで問題を解決できます

つまりは、バックエンドに様々な手法を持つことができるインターフェースとして動くということなんだろうか？

[Keras: TensorFlow の高レベル API](https://www.tensorflow.org/guide/keras?hl=ja)
> Keras は、以下の目標を達成することで、認知的負荷を押さえられるように設計されています。
> 
> ・単純で一貫性のあるインターフェースを提供する。
> ・一般的なユースケースに必要なアクションの数を最小限に抑える。
> ・明確で対応可能なエラーメッセージを提供する。
> ・複雑さの段階的な開示の原理に従う。取りかかりやすく、作業を進めながら学習することで、高度なワークフローを完成させられます。
> ・明白で読み取りやすいコードを書けるようにする

上記ページでも、高レベルAPIと書かれていたので大丈夫だと思う。
ちょっと理解があっているのかは分からないが、一旦、そういう風に理解しておくことにする。

ちなみにKerasの説明文中に出てきたTheanoに関してはこちらを参照
[Theano 解説](https://saket.hatenadiary.org/entry/20121207/1354867911)

以下は今回使っていた関数をちょっと抜粋

## keras_cv.RandomCutout
https://keras.io/api/keras_cv/layers/augmentation/random_cutout/
> Randomly cut out rectangles from images and fill them


## tf.random.uniform([]) < 0.5
https://keras.io/api/random/random_ops/
> Draw samples from a uniform distribution.

tf=tensorflow

## tf.io.read_file 
https://www.tensorflow.org/api_docs/python/tf/io/read_file

## tf.clip_by_value
https://www.tensorflow.org/api_docs/python/tf/clip_by_value
> Clips tensor values to a specified min and max. 

## tf.one_hot
https://www.tensorflow.org/api_docs/python/tf/one_hot


## sig[1024//dtype:]
// 演算子＝割り算、少数切り捨て
配列中のコロンは
[（開始位置）:(終了位置）]
sig[10:]=配列の10文字目から終わりまで
【Rails】sessionとは

# sessionとは
`session`は、ウェブアプリケーションにおいてセッション管理を行うための仕組みです。セッションとは、ユーザーがウェブサイトやウェブアプリケーションにアクセスしてから、ブラウザを閉じるまでの間の一連の操作を指します。セッションを管理することで、ユーザーごとに状態を保持し、ユーザーの体験をカスタマイズしたり、認証情報を保存したりすることができます。

Railsの`session`は、サーバーサイドでセッション情報を保持し、クライアントとの通信においてセッションを識別するための一意な識別子（通常はクッキー）をクライアントに送信します。これにより、ブラウザのクッキーを使用してユーザーごとにセッション情報を保持することができます。

`session`を使用することで、以下のようなことが可能になります。

1\. ユーザーの認証状態の管理: ログインしたユーザーの情報をセッションに保存し、ログアウトするまで維持します。

2\. 一時的なデータの保存: フォーム入力などの一時的なデータをセッションに保存し、次のリクエストで使用します。

3\. セッションベースのカート: ショッピングカートのようなセッションベースのデータを保存し、購入手続き中に使用します。

Railsでは、`session`ハッシュを使用してセッション情報にアクセスします。例えば、以下のようにしてセッションにデータを保存することができます。
```ruby
# セッションにユーザーIDを保存する例
session[:user_id] = user.id
```
そして、次のリクエストで同じセッション情報を取得することができます。
```ruby
# セッションからユーザーIDを取得する例
user_id = session[:user_id]
```
セッション情報はデフォルトではクッキーに保存されますが、別のストア（例: データベース、メモリ）に保存することも可能です。
Lambda で OpenAI APIを実行する

Lambdaを使用しChatGPTで知られるOpenAIを実行してみました

## Lambdaの作成

#### 1. Lambda > 関数にアクセス。関数の作成ボタンから作成を始めます

![スクリーンショット 2024-01-12 11.43.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276326/9662e6df-d058-ec21-4126-82302728b985.png)


#### 2.　OpenAI API キーを環境変数に登録

環境変数をして使えるようにするための設定です

設定>環境変数　の編集、環境変数の追加から追加します

CHAT_GPT_KEYという名前で登録しました


#### 3.レイヤーを作成

OpenAIのモジュールを読ませるためにモジュールをzip化しレイヤーに登録するのが一番良さそうです

Pythonをインストールしている環境で以下のコマンドで実行し、zipを作成します

```
$ python3 -m pip install -t ./python openai
$ zip -r openai.zip ./python #ここはお使いのPCの右メニューからzipでも可
```

Lambdaの画面で、その他のリリース > レイヤー　レイヤーの作成からレイヤー作成します

レイヤー登録画面にて

.zipファイルをアップロードを選択し、作成したzipをアップロード
互換性のあるランタイムをLambdaで使用する予定の言語のバージョンを選択ください
今回は、Python3.12にしました、ついでに複数設定できます

またアーキテクチャもLambdaで使用する予定を設定ください（両方にチェックでも問題ありません）

![スクリーンショット 2024-01-12 19.08.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276326/45ac9167-3fcf-d3cf-12d0-060e13d24081.png)

保存しレイヤーを登録します


#### 4.レイヤーを追加

作成中のLambda関数の画面に戻り作成したレイヤーを設定します
コードタブないのレイヤー　編集ボタンから設定します

カスタムレイヤーを選択
カスタムレイヤーを、先ほど作成したレイヤー名を選択
バージョンは、同様な名前で作った場合勝手増えるため、一番大きい数字で問題ないかと思います

![スクリーンショット 2024-01-12 19.35.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276326/8264d1b1-154a-5e4e-16b6-25972cb53a9a.png)

#### 5.Lambda実行

OpenAIを実行するためのサンプルコードです

実行し問題なければOpenAIの設定はOKです。

```
import os
from openai import OpenAI


def lambda_handler(event, context):
    
    # OpenAI実行
    client = OpenAI(
        api_key=os.environ['CHAT_GPT_KEY'],
    )


    messages = [
        {"role": "system", "content": "あなたは優秀なAIアシスタントです。"},
        {"role": "user", "content": "一人旅したい、長崎県でおすすめの場所１つ教えて"}
    ]

    #  OpenAI　実行コード↓
    completion = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=messages,
        temperature=0.7
    )
    
    response = completion.choices[0].message.content

    return response

```

補足）
Lambda実行時以下のエラーでました

> "Unable to import module 'lambda_function': No module named 'pydantic_core'

同様のエラーが出た場合,pydantic-coreのサイトからダウンロードし、加えzipを作りなし3.4.の手順で同様の対応で、登録し直すことで、解決しました

pydantic-core
https://pypi.org/project/pydantic-core/#files
MLOpsのおさらい&MLパイプラインを立ててみる

## はじめに

Google Cloud資格、Professional Machine Learning Engineerの準備としてMLOpsや機械学習サービスのドキュメントを色々読んだりパイプラインを実行したりしたので、自分なりに整理してみます。

機械学習分野はアップデートがとても速く、用語の定義などクラウドベンダによって解釈が分かれるところもあるかもしれません。今回はGoogle Cloudの公式ドキュメントを拠り所にします。

本記事ではVertex AIを使ったCI/CD/CTパイプライン周りを取り上げます。

https://cloud.google.com/learn/certification/machine-learning-engineer?hl=ja

## 1. MLOpsとは？
MLOpsは機械学習(ML)分野において開発者と運用者が連携してリリースサイクルを短縮するアプローチです。DevOpsの考え方がベースになっています。

DevOpsを支える技術にはCI/CDがあります。CIは継続的インテグレーションで、ビルド、テストを自動化する手法です。CDは継続的デリバリーで、テストが完了したアプリケーションを自動でリリースするアプローチです。継続的デリバリーと同じ意味ではありませんが、CDを継続的デプロイメントと言ったりもします。

機械学習モデルでは、入力データの質の変化がパフォーマンスを低下させることがあります。パフォーマンスを維持するためには、入力データの変化を検知し継続的にトレーニングする必要があります。
特徴量やハイパーパラメータを調整したパイプラインのデプロイを自動化すると、トレーニングのサイクルを早めることができます。

また、パイプラインそのものを変えるまではいかなくても、同じパイプラインのまま新しいデータを使ってトレーニングを行う(CT: 継続的トレーニング)こともあります。

パイプラインのイメージを掴むために、実際に機械学習のパイプラインを立ててみましょう。

## 2. Vertex AIパイプライン構築

手組みは大変なので、用意されているサンプルコードからVertex AIパイプラインを立ててみましょう。

サンプルコードをColabで動かすと、lightweight Python functionでKubeflow PipelinesでVertex AIパイプラインが構築されます。
基本的には全部のセルを実行すればよいのですが、アンコメントが必要なセル、URLを踏んで認証をするセル、プロジェクト名などを手入力するセルがあります。

サンプルコード

https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/official/pipelines/lightweight_functions_component_io_kfp.ipynb


実行してみるとパイプラインができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3458266/a4426114-aa2c-d649-af48-480edae751d3.png)

## おわりに
パイプラインのコンポーネントがどんな動きをしているのか…は今後の課題にしたいと思います。

## 参考サイト


https://cloud.google.com/architecture/architecture-for-mlops-using-tfx-kubeflow-pipelines-and-cloud-build?hl=ja

https://cloud.google.com/devops?hl=ja
【Git】基本的なGitコマンドまとめてみた

## はじめに
学習の忘備録です。
## git init
.gitディレクトリが作成される
これで現在のディレクトリの変更履歴を管理出来るようになる
~~~
git init
~~~
## git clone
指定したリポジトリをコピー（クローン）する
リポジトリはローカル・リモートのどちらでも可能
~~~
git clone <リポジトリ名>
~~~
##  git add
ワーキングツリーの変更をステージに追加する。追加部分の指定可能
~~~
git add index.html
git add <リポジトリ名>

#全ての変更箇所をaddする
git add .
~~~
## git commit
ステージに追加されている変更をローカルリポジトリに反映させる
~~~
git commit
git commit -m <メッセージ>
~~~
## git status
現在の変更状況を確認出来る
~~~
git status
~~~
## git diff
具体的な変更差分を確認出来る
~~~
# git addする前の差分
git diff
# git addした後の差分
git diff --staged
~~~
## git log
変更履歴を確認する
~~~
git log

# 一行で表示（見やすい）
git log --oneline

# 表示するコミット数を制限する
git log -n<コミット数>
~~~
## git remote
リモートリポジトリ(Git Hub等)をローカルリポジトリと紐づける
~~~
# 今後は"origin"という名前でリモートリポジトリを指定出来る
git remote add origin <リモートリポジトリ>
~~~
## git push
ローカルリポジトリの内容をリモートリポジトリに送信する
~~~
git push <リモート名> <ブランチ名>
~~~
## git fetch
リモートからローカルへ情報を取得する
~~~
git fetch <リモート名>
~~~
## git merge
基本的にfetchと併用
fetch後にローカルからワーキングルツリーへ情報を統合する
~~~
git merge <リモート名> <ローカル名>
~~~
## git pull
fetch+mergeと同義
~~~
git pull <リモート名> <ローカル名>
~~~
## git branch
現ブランチの確認、新規追加ができる
~~~
#　現ブランチの確認
git branch
#　ブランチ一覧表示
git branch -a

# ブランチ新規追加
git branc <ブランチ名>
# 新規追加+ブランチ移動
git branch -b　<ブランチ名>
~~~
## git checkout
ブランチの移動
~~~
git checkout <ブランチ名>
~~~
## 最後に
他にもrebase,stash,alias,tagとかあるけどとりあえず以上。
## 参考文献
https://www.udemy.com/course/unscared_git/
ksnctf #2 Easy Clipher

## ksnctf #2 Easy Clipher
```text:problem.txt
EBG KVVV vf n fvzcyr yrggre fhofgvghgvba pvcure gung ercynprf n yrggre jvgu gur yrggre KVVV yrggref nsgre vg va gur nycunorg. EBG KVVV vf na rknzcyr bs gur Pnrfne pvcure, qrirybcrq va napvrag Ebzr. Synt vf SYNTFjmtkOWFNZdjkkNH. Vafreg na haqrefpber vzzrqvngryl nsgre SYNT.
```
アルファベットや空白があることからこれはシーザー暗号と推測できます。
https://dencode.com/ja/cipher
このサイトで解読すると、13(A<-N)で意味の分かる文字列になります。
```text:ans.txt
ROT XIII is a simple letter substitution cipher that replaces a letter with the letter XIII letters after it in the alphabet. ROT XIII is an example of the Caesar cipher, developed in ancient Rome. Flag is FLAGSwzgxBJSAMqwxxAU. Insert an underscore immediately after FLAG.
```
よって答えは"FLAGSwzgxBJSAMqwxxAU"とわかります。


ほかにも、python でシーザー暗号を解読することができる。
```python:caesar.py
text = "EBG KVVV vf n fvzcyr yrggre fhofgvghgvba pvcure gung ercynprf n yrggre jvgu gur yrggre KVVV yrggref nsgre vg va gur nycunorg. EBG KVVV vf na rknzcyr bs gur Pnrfne pvcure, qrirybcrq va napvrag Ebzr. Synt vf SYNTFjmtkOWFNZdjkkNH. Vafreg na haqrefpber vzzrqvngryl nsgre SYNT."

for i in range(1, 26):
    ans = ""
    for char in text:
        if char.isalpha():
            ascii_offset = ord('a') if char.islower() else ord('A')
            ans += chr((ord(char) - ascii_offset - i) % 26 + ascii_offset)
        else:
            ans += char
    print(f"Shift {i}: {ans}")
```
これはGithubでも公開しています。
https://github.com/furiirakun/onigiri/blob/main/caesar.py
![スクリーンショット 2024-02-11 002941.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3685661/c648c415-6368-b8ac-a1bd-a85e0e37c2c8.png)

ここでも同じく13シフトで意味のわかる文になる。

## 参考文献
isalpha()->https://qiita.com/furiirakun/items/c763d4655ae7d7665896
ord()->https://qiita.com/furiirakun/items/5b7397766c0fca04b4fd
islower()->https://qiita.com/furiirakun/items/071c9b07214302c18300
neovimで :lua ... に疲れたときに使うプラグイン nvim-luadev

## はじめに

普段neovimを使っていて、たまにPluginの見直し等をしているのですが…。
組み込まれた luaの状態を確認したり、Plugin関連のコードを少し試してみたりすることがあります。

このときに `:lua ...` として luaのコードを実行するのは、入力が面倒だったり、結果が見にくい等で使いにくく、いろいろ試すのが苦痛でした。

楽な方法はないものかと、探してみたところ [nvim-luadev] という pluginを見つけました。

その設定等についての記事になります。

[nvim-luadev]: https://github.com/bfredl/nvim-luadev

## Plug-inの導入

私は [Packer] を使っていますので、[Packer]を使ってInstallします。

```lua
-- install a plugin for nvim embbedded lua
use { "bfredl/nvim-luadev" }
```

[Packer]: https://github.com/wbthomason/packer.nvim

設定ファイルに上を追加後に `nvim -c PackerInstall` して完了です。

## キーバインドする

Plugin読み込み後、ここでは適当に 以下のようにアサインしてみます[^question]。

```lua
vim.keymap.set('n', '<Leader>l', '<Plug>(Luadev-RunLine)', {silent = true})
vim.keymap.set('n', '<Leader>r', '<Plug>(Luadev-Run)', {silent = true})
vim.keymap.set('v', '<Leader>r', '<Plug>(Luadev-Run)', {silent = true})
vim.keymap.set('n', '<Leader>e', '<Plug>(Luadev-RunWord)', {silent = true})
```

[^question]: Plugin側で `<silent> <Plug>`と定義されているので、こちらで `silent = true` は不要？

:::note info
insert modeでの global変数補完は 私の環境ではうまく動かなかったので使っていません。
:::

## 使い方

vimを起動したら `:Luadev` として Scrachpadを開きます。
Luadevを通じた出力は、このBufferに書かれます。

適当なバッファに luaの環境で試してみたいコードを書きます。

```lua
print("Hello nvim-luadev.")
```

カーソルをこの行の上にのせて、`<Leader>`(defaultは ￥・バックスラッシュ) に続けて `l` を押す事で、この一行が実行されて結果がScratchpad側に出力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128512/067f8da7-693b-0405-f7a1-124bbb54f2b6.png)

## 複数行の実行

今度は複数行のLuaを実行してみます。

```lua
for k,v in pairs(vim) do
    print(k)
end
```

適当なバッファで入力したら、Visualモードで実行したい範囲を選択します。
`<Leader>`に続けて `r` を押す事で、選択した範囲が実行されて結果がScratchpad側に出力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128512/4b017b8c-3610-956c-4e3d-370e018d4119.png)

:::note info
Normal ModeにもBindしてあるので、Visual Modeでなくても、カーソルの下二行までを実行したい場合、最初の行にカーソルを置いて `<Leader>r2j` としてもOKです。
:::

## global変数の参照

global変数を参照して表示したい場合は

```lua
vim.g.vsnip_snippet_dirs
```

変数の上にカーソルを置いて `<Leader>e` とします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128512/9c993e5b-85e1-58b7-a8a5-09f236ef5d93.png)

:::note info
Luadevのprintは、[inspect.lua] 使い、展開・整形して出力してくれます。このため、テーブルの中身も簡単に確認することができます。ただし、残念ながら、metatableで __indexに関数が設定されているような table （例えば vim.g）は展開されません。
:::

[inspect.lua]: https://github.com/kikito/inspect.lua

## Plugin等からScratchpadに書き込む

ここまでの例の様に interactive な呼出しは、`print()` するだけで Scratchpadに書き込まれます。それ以外の場面で、例えば開発中のPluginのちょっとしたPrint debug等、Scratchpadに書き込みたい場合には、luadevのモジュール内の `print()` を使う必要があります。

一行で書くなら

```lua
require'luadev'.print("Hi nvim-luadev")
```

何回か使うならこんなコードに。

```lua
local debug_print = require'luadev'.print

-- lua code... --
debug_print("Hi nvim-luadev")
```

## おわりに

他にもっと良いやり方があるのかもしれませんが、これのおかげで設定ファイルの編集がめっちゃ楽になりました。
ガントチャートのテスト

```mermaid
gantt
title Adding GANTT diagram to mermaid
dateFormat  YYYY-MM-DD

section A section
Completed task            : a,　　　  2024-01-06 ,3d
Active task               : b,　　　　 after a, 3d
Future task               : c,   after b, 5d
Future task2              : d,   after c, 5d
```

# コード

```
```mermaid
gantt
title Adding GANTT diagram to mermaid
dateFormat  YYYY-MM-DD

section A section
Completed task            : a,　　　  2024-01-06, 3d
Active task               : b,　　　　 after a, 3d
Future task               : c,   after b, 5d
Future task2              : d,   after c, 5d
```end
```
islower()とは

## islower()とは
islowerとは、pythonの文字列メソッドの一つで、文字列が全て小文字で構成されているかどうかをチェックします。
以下に例を示します。
```python:sample.py
s = "helloworld"
print(s.islower())  # 出力: True

s = "Hello World"
print(s.islower())  # 出力: False
```
この例では、最初の文字列"helloworld"は全て小文字で構成されいるため、s.islower()はTrueを返します。一方、二つ目の文字列"Hello World"には大文字が含まれているため、s.islower()はFalseを返します。
ord()とは

## ord()とは
ord()とはPythonの組み込み関数で、特定の一文字に対応するUnicodeコードポイントを返します。
以下に例を示します。
```python:sampe.py
s = "A"
print(ord(s))  # 出力: 65

s = "あ"
print(ord(s))  # 出力: 12354
```

この例では、最初の文字"A"のUnicodeコードポイントは65で、二つ目の文字"あ"のUnicodeコードポイントは12354です。
isalpha()

## isalpha()とは

isalphaとはpythonの文字列メソッドの１つで、文字列が全てアルファベットで構成されているかどうかをチェックします。
以下に例を示します。
```python:sample.py
s = "HelloWorld"
print(s.isalpha())  # 出力: True

s = "Hello World"
print(s.isalpha())  # 出力: False
```

この例では、最初の文字列"HelloWorld"は全てアルファベットで構成されているため、s.isalpha()はTrueを返します。一方、二つ目の文字列"Hello World"はスペースが含まれるため、s.isalpha()はFalseを返します。
Firestoreのin句でエラーを回避する

## はじめに
便利に使えるFirestoreなのですがちょっとはまったので書き残しておきたいと思い、書いていきます。

## はまった事
[公式より](https://firebase.google.com/docs/firestore/query-data/queries?hl=ja#in_and_array-contains-any)
Firestoreの検索でin句を使用しました。
Functionsの処理で組み込んだので、決まりきった値での検索ではなく、動的に検索条件を設定しました。

``` javascript:JavaScript
const list: string[] = []
(中略)
const collectionRef = db
    .collection('collection1')
    .where('id', 'in', list)
const collectionDoc = await collectionRef.get()
```

すると見事に**最大30個**の制限に引っかかってしまい、処理が中断してしまいました。

## 対応策
分割して処理を行うようにしたのですが、lodashライブラリの.chunk()メソッドを使用しました。

``` javascript:JavaScript
const list: string[] = []
(中略)
const chunks = lodash.chunk(list, 25) // 仮に25で分割
chunks.forEach(async (listMod) => {
    const collectionRef = db
        .collection('collection1')
        .where('id', 'in', listMod)
    const collectionDoc = await collectionRef.get()
}
```
Freenom が活動を停止している模様 ~訂正~ 一時復活 ~訂正~ いよいよダメかも

2024年9月7日投稿
------------------------------------------------------------
Freenom の DNS が復活していました。障害か何かで止まっていたと思われます。復活はしたものの、信頼性の低下は否めないですね。リスクをとって無料を続けるか、DNS だけでも有料のサービスに移行するか、悩み中です。

2024年8月31日投稿
--------------------------------------------------------------
前回投稿の通り、2月に一時的に使用不能になって復活した freenom に登録したドメインですが、また使用不能になりました。
freenom の WEB サイト上では問題ないように見えますが、ブラウザからドメインにアクセスできなくなっています。freenom の DNS が停止しているか、DNS へのルートの登録が抹消されたか、原因は不明です。
以下のような記事も出ていて、かなり信頼性が低下しているので、そろそろ有料ドメインに移行しないとダメなようですね。
[Freenom shuts down 12.6 million domains — report](https://domainincite.com/29668-freenom-shuts-down-12-6-million-domains-report)

2024年2月12日 投稿
-----------------------------------------------------------------------------
続報です
使用不可になっている点について、クレームのメールを info@freenom.com に入れました。
なんと、返事が返ってきました。
Apologies for the inconvenience. Your domains are working again.
だそうです。

まだまだ、無料のままで使えそうです

2024年2月11日 投稿
-----------------------------------------------------------------------------
無料のドメイン登録サイトとして世界中にサービスを提供していた freenom.com に登録されていたドメインが軒並み使用不可になっている模様
有効期限がまだ到来していないドメイン（.tk .tk .ml .ga .cf .gq など）のステータスが PENDING になり、DNSの設定ページにも移動できない状況
うわさでは、ICANNに排除されたという話も出ているらしい。
[Metaがサイバースクワッティングの疑いでドメインレジストラ・Freenomを提訴](https://gigazine.net/news/20230309-freenom-sued-by-meta/)してから新規登録は停止されていたようだが、最近まで登録済みのドメインについては更新ができていた
直近では登録済みのドメインについても、利用が出来なくなっている状態
何もアナウンスが無いので詳細については一切不明
どなたか、情報をお持ちの方がいたら、共有お願いします
GASでスプレッドシートからOpenAI APIを実行する

スプレッドシートでGoogle App Script（GAS）を使って[OpenAI Text Generation API](https://platform.openai.com/docs/guides/text-generation?lang=curl)を呼ぶと便利です。

OpenAI APIキーを取得して、以下のようなコードをシートのApp Scriptに記述するだけで使えるようになります。

```javascript
var OPENAI_API_KEY = "sk-xxxxxxxxxxxxxxxx";

// JSDocの記法の一部がスプレッドシートのオートコンプリートに反映される
/**
 * GPTを呼び出すカスタム関数
 *
 * @param {string} input GPTへの入力文字列
 * @param {model} model モデル名。デフォルトは"gpt-3.5-turbo"
 * @param {boolean} useCache キャッシュを使用するかどうか。長い入力を使う時はキャッシュを無効化する必要がある
 * @return GPTで生成した結果
 * @customfunction
 */
function GPT(input, model, useCache) {
    if (model === void 0) { model = "gpt-3.5-turbo"; }
    if (useCache === void 0) { useCache = true; }
    // キャッシュから取得
    var cache = CacheService.getScriptCache();
    if (useCache) {
        try {
            var cachedResult = cache.get(input);
            if (cachedResult) {
                return cachedResult;
            }
        }
        catch (e) {
            if (e.message.includes("Argument too large: key")) {
                throw new Error("キャッシュの取得に失敗しました。入力を短くするか、キャッシュを無効にしてください。");
            }
            else {
                throw e;
            }
        }
    }
    // OpenAI Chat Completion APIで生成
    var URL = "https://api.openai.com/v1/chat/completions";
    var headers = {
        "Content-Type": "application/json",
        "Authorization": "Bearer ".concat(OPENAI_API_KEY)
    };
    var body = {
        model: model,
        // max_tokens: 100,
        messages: [{ role: "user", content: input }]
    };
    var response = UrlFetchApp.fetch(URL, {
        method: "post",
        headers: headers,
        payload: JSON.stringify(body)
    });
    var result = JSON.parse(response.getContentText()).choices[0].message.content;
    // キャッシュに保存
    if (useCache) {
        cache.put(input, result, 21600);
    }
    return result;
}
```

これで、`=GPT()`という関数が使えるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50391/27643667-e867-64b1-b343-58cede04dd36.png)

[ScriptCache](https://developers.google.com/apps-script/reference/cache?hl=ja)で同じ内容でAPIが連続して叩かれないようにしています。キャッシュの有効期限は6時間（21,600秒）なので注意しましょう。

お好みでmax_tokenやtemperature等をパラメータで指定できるようにしてください。

## clasp版
[google/clasp](https://github.com/google/clasp)を使ってTypeScriptで記述する場合は以下のような感じです。

https://github.com/s2terminal/spreadsheet-gpt/blob/main/index.ts

GASではfetchが`UrlFetchApp`になる所と、[`import`が使えない点](https://github.com/google/clasp/blob/master/docs/typescript.md#modules-exports-and-imports)などに気をつければ、あとは普通だと思います。
生成モデルについて【E資格対策】

# ①識別モデルと生成モデル
識別モデルと生成モデルは、機械学習の分野で使われる二つの異なるタイプのモデルです。

**識別モデル**
識別モデルは、与えられた観測データから目的変数（ラベル）を予測するようなやつですね。たとえば、写真を入力すると猫なのか犬なのかを判断するようなモデルは識別モデルです。

**生成モデル**
生成モデルは、新しいデータを生成するやつっすね。たとえば音楽の作曲をするようなモデルってのは生成モデルですね。
「あるデータセットから学習して、そのデータセットが持つ統計的特性やパターンを理解して、その学習を基に、まったく新しいデータポイントを生成する」みたいなことをやってるらしい。


# ②オートエンコーダ
### VAE（変分オートエンコーダ）
**VAEは、ディープラーニングを用いた生成モデルの1つ。** 通常のオートエンコーダは同一の入力に対して毎度同一の潜在変数を獲得するのに対して、VAEの場合は入力に対して確率的に潜在変数が決まる。その変数をデコーダに入れるので、入力画像と似てるけど微妙に違う画像が得られる。

◆VAEの流れ

1. エンコーダが入力画像を取り込み、その画像が生成されたと推定される潜在空間の確率分布のパラメーターである平均（μ）と分散（σ）を出力する。

2. 次に、この分布からサンプリングを行い、ランダムな潜在変数zを生成する。

3. デコーダがこの潜在変数zを取り込み、元の入力データに似た新しいデータを生成する。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3700895/87bcc683-34d3-a0a7-6e17-d7b2f474de43.png)



### VQ-VAE
VQ-VAEは、VAEの進化版。従来のVAEは潜在変数を連続的な正規分布として扱うが、VQ-VAEでは潜在変数を離散化し、より高品質なデータを生成できる。

エンコーダ・量子化部分・デコーダから成るモデルで、エンコーダとデコーダは畳み込み層を用いている。


# ③GAN

### GAN
GANは、生成器 (Generator) と識別器 (Discriminator) という二つのニューラルネットワークを競わせて学習させるモデルです。
GANは、乱数を生成器に入力して偽物のデータを作り、識別器に本物か偽物かを判定させることで、生成器と識別器を同時に学習させる。生成器は識別器を騙すように、識別器は正しく判定するように、それぞれが最適化される。

##### 学習のステップ
①Generatorのパラメータを固定した状態でDiscriminatorを学習する。
②Discriminatorのパラメータを固定した状態でGeneratorを学習する。

①と②のステップを交互に繰り返すことで、GeneratorとDiscriminatorの性能が徐々に向上していく。
##### Discriminator
Discriminatorは、入力データが本物であれば1を、偽物であれば0を出力するような2値分類を学習する。

損失関数
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3700895/9a45bc1c-cf8a-cecc-6dea-3672d16fea7f.png)


##### Generator
Generatorは、入力されたノイズベクトルzから、本物のデータxの確率分布に近い偽データG(z)を生成できるように学習する。

損失関数
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3700895/49e1fb4d-f0f0-ab7d-58bf-e1e2a53f2774.png)


##### GANの損失関数

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3700895/e099bffb-6c88-61d3-d8a4-1a99126908e1.png)


### DCGAN
DCGANは、生成器と識別器にCNNを用いて品質UPさせたモデルのこと。
生成器は転置畳み込み層を使って乱数を画像にアップサンプリングし、識別器は畳み込み層を使って画像から特徴量を抽出する。
##### 特徴
・生成器と識別器にCNNを導入して品質UP。
・生成ネットワークと識別ネットワークの両方にバッチ正規化を導入し、学習の安定性UP
・生成ネットワークでは活性化関数にReLUを使用し、出力層のみTanhを使用。
・識別ネットワークでは活性化関数にLeakyReLUを全層に渡って使用。

##### イメージ図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3700895/4909cd67-b267-4d3a-55dd-4c9691491131.png)
https://arxiv.org/pdf/1511.06434.pdf


### Conditional GAN
Conditional GANは、生成器と識別器に条件を考慮できるようにしたモデルです。条件はラベルやテキストなどのデータで、生成器は条件に沿ったデータを生成し、識別器はデータと条件が一致しているかを判定します。Conditional GANは、どのようなデータを生成するかを制御できるようになります。
（「猫の画像を生成する」とか「犬の画像を生成する」とか選べるようになった。）

# 参考文献
https://qiita.com/kenchin110100/items/7ceb5b8e8b21c551d69a
VSCodeのPythonツール(リント・フォーマットなど)対応

# この対応は何か
- VSCodeで以下の画面が表示される。
![スクリーンショット 2024-02-11 20.44.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95700/d223e31f-6f8e-c7f9-675d-3ef9b1ee19e5.png)
- これの対応。
# 詳細情報に遷移した後のサマリ
- Python Tools Extensionsのアップデートで、パフォーマンス、安定性、インストールの柔軟性が向上。
- Pylint、Flake8、Mypy、Black、autopep9、isortなどの新しい拡張機能が追加された。
- 非推奨の設定は別の拡張に移動し、代替拡張も提供されている。さらに、Ruff拡張を試したり、エクステンションの自動更新を無効にするなど、様々な非推奨設定の代替方法がある。
# 何をする必要があるのか
自分の場合は、
- settings.jsonの編集。以下の設定が適用されなくなっていた。
    - これらの設定をsettings.jsonから削除することで、VSCode上の警告は出なくなる。
```
// linter
 "python.linting.enabled": true,
"python.linting.lintOnSave": true,
"python.linting.pylintEnabled": false,
"python.linting.flake8Enabled": true,
"python.linting.flake8Args": [
"--max-line-length",
"160",
"--ignore=E203,W503,W504,E402"
 ],
//formatter
"python.formatting.provider": "none",
//static type checker
"python.linting.mypyEnabled": true,
```
- 必要な拡張機能のインストール
    - [ここで](https://github.com/microsoft/vscode-python/wiki/Migration-to-Python-Tools-Extensions#existing-python-tools-extensions)
# 問題なく機能するのか?
自分が使用しているものに焦点を当てる。
- flake8
- black
- isort
- mypy
いずれも、機能することが確認できた。
0からFlutterの勉強

最近、僕はのflutterを勉強してほしいといわれます。
千里の旅も一歩から、まだ始めましょう。

2014年、はじめでのFlutterと言うのがJSに基ってのlanguageです。
ECMAscriptの2022の文法はFlutterに使えます。

例えば 「??」操作
```javascript:ECMAscript
 let a;
 a??=3;
```

```javascript:Flutter
 int? a;
 a??=3;
```
そして、フロントエンドエンジニアとして、ちょっと容易に使えます。

```javascript:Flutter
Class Color{
    int? red;
    int? blue;
    int? yellow;

    Color(this.red, this.blue, this.yellow); // constructorの用法と同じです。
}

final myColor = Color(255, 255, 255);
print(muColor.red);

```

```javascript: Flutter
    final arrOfInt = [];
    final setOfInt1 = {};
    final setOfInt2 = <int>{};
    final mapOfString = <string, string>{};
```

```javascript: Flutter
    int _value; // 内部に使う
```

#### 注意する差

```javascript: Flutter
    final setOfString = {'one', 'two'}; // Setです。arrayではない。
    final mapOfString = <int, string>{0: 'zero', 1: 'one'}; // Mapです。
```

```javascript:Flutter
    // setter と getter
    void set valueName(int value)=> _value = value;
    int get (valueName)=>_value;
}
```

```javascript:Flutter
    // setter と getter
    class ShoppingCart {
        List<double> _prices = [];
        List<double> get (prices)=>_prices;
        set prices(List<double> value)=> _prices = value;
    }
```

```javascript:Flutter
    querySelector('#confirm') //　連続的に使って、chain
        ?..text = 'Confirm'
        ..classes.add('important')
        ..onClick.listen((e) => window.alert('Confirmed!'))
        ..scrollIntoView();
```

:::note info
window 11 NO_PROXY 環境関数のなかに配置
:::
【Drupal】PHP構成の設定

## はじめに
DrupalのPHP構成の確認画面をご存知ですか？
こちらのパスから確認することができます。
``/admin/reports/status/php``

![PHP構成確認画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/576d9a60-85ba-d54b-f512-3c2695263f62.png)


通常であればインスタンスやコンテナの設定でPHP構成の管理を巻き取ることが多いのかなと思います。

ただ、
「本番環境・テスト環境ではメモリの制限それぞれ設定したい」
「開発環境ではメモリをフルに使いたい」
ってこと結構ありますよね。

**（環境変数を使えば簡単にできるよって意見もあるかと思いますが...）**

今回は、アプリ側でのPHP構成の変更方法をご紹介します。

## 設定場所
設定場所はなんと！
Drupal標準で用意されています。

### Drupal標準..？
軽くissueを調べてみましたが、恐らく``settings.php`` or ``settings.local.php``に記載するのが標準のようです。
（もっといい方法あるよって方はコメントください。）

Drupalが用意している``default.settings.php``にこんな記載がありました。
サンプルですね。

```php
/**
 * PHP settings:
 *
 * To see what PHP settings are possible, including whether they can be set at
 * runtime (by using ini_set()), read the PHP documentation:
 * http://php.net/manual/ini.list.php
 * See \Drupal\Core\DrupalKernel::bootEnvironment() for required runtime
 * settings and the .htaccess file for non-runtime settings.
 * Settings defined there should not be duplicated here so as to avoid conflict
 * issues.
 */

/**
 * If you encounter a situation where users post a large amount of text, and
 * the result is stripped out upon viewing but can still be edited, Drupal's
 * output filter may not have sufficient memory to process it.  If you
 * experience this issue, you may wish to uncomment the following two lines
 * and increase the limits of these variables.  For more information, see
 * http://php.net/manual/pcre.configuration.php.
 */
# ini_set('pcre.backtrack_limit', 200000);
# ini_set('pcre.recursion_limit', 200000);
```


## 僕だったらっていうカスタマイズ設定
もちろん、プロジェクト・要件によって変わってくると思いますが、こんな感じのフォーマットはいかがでしょうか？
是非参考に。
```php
/**
 * PHP settings:
 *
 * To see what PHP settings are possible, including whether they can
 * be set at runtime (ie., when ini_set() occurs), read the PHP
 * documentation at http://www.php.net/manual/en/ini.php#ini.list
 * and take a look at the .htaccess file to see which non-runtime
 * settings are used there. Settings defined here should not be
 * duplicated there so as to avoid conflict issues.
 */
switch (DRUPAL_ROOT) {
  // Prod環境の場合
  case ('/data/www/prod/web'):
    ini_set('post_max_size', '256M');
    ini_set('upload_max_filesize', '16M');
    ini_set('memory', '256M');
    break;

  // Stage・Test環境の場合
  case ('/data/www/stage/web'):
  case ('/data/www/tst/web'):
    ini_set('post_max_size', '256M');
    ini_set('upload_max_filesize', '16M');
    ini_set('memory', '128M');
    break;

  case ('/data/www/dev/web'):
    ini_set('memory', '128M');
    break;

  // Landoの場合
  case ('/app/web'):
    ini_set('memory', -1);
    break;
    
  default:
    ini_set('default_charset', 'UTF-8');
    break;
}
```

## まとめ と ちょっと解説
さすがにここまでやるのであれば、環境変数等でやったほうがいいのでは？という意見が出てくるかと思いますが...
あくまで手段と知っておいていいとは思います。

特に開発環境では ``ini_set('memory', -1);`` という設定を記述することで、開発作業をスムーズに進めることができます。
（もちろん、ローカルで単体テストを行うときは設定を外す必要がありますが...）

PHPでの分岐を入れる事が可能ですので、
環境ごと...
IPアドレス...
地域...

``settings.php``への記述で、シチュエーションに応じたアプリケーションの設定を動的な変更が可能です。
結構魅力的ですよね。
Windows11環境をVirtualBox上に用意する手順

こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

今回はWindows11環境をVirtualBox上に用意する手順をメモっておきたいと思います。
仕事でWin11の検証とかそのあたりをすることになりそうな為、プライベートでいじれる環境を用意したかったという事がこの記事を作ることになった背景です。
Win10からWin11への移行対応等が今後全社レベルである人も多いかと思いますので、そういう時に使ってみるといいかもしれません（？）

# 参考サイト

以下のサイトを参考にし、またダウンロードを行っております。

https://news.mynavi.jp/article/win11tips-135/

https://developer.microsoft.com/en-us/windows/downloads/virtual-machines/

https://www.virtualbox.org/wiki/Downloads

# 手順
## 必要な資材を準備する

参考サイトの下2つにアクセスしてWin11のOVAファイル（ダウンロード時はzip）とVirtualBoxのexeファイルをダウンロードします。
VirtualBoxのexeはダブルクリックして実行してしまってください。
また、OVAが入っているzipファイルは解凍します。zipであっても20GB程度あるため結構時間がかかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/7f7af828-8be7-b44a-c66d-c6649d23357d.png)

## VirtualBoxにWin11環境を立ち上げる
VirtualBoxを起動してインポートを押下します。
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/53dbc6d3-2e12-8393-736c-515bbd5c9458.png)
解凍したOVAファイルを選択し、次へを押下します。
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/de495de6-2b14-c9bd-b9de-c35465d37351.png)
設定内容一覧が表示されます。
さっと確認して完了を押下します。
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/20d0bc5d-f901-e146-d917-8aef4d5bf2e4.png)
画面右側にインポート中という画面が表示されます。
暫く待ちます。
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/0d051bc5-588b-8632-08ef-bc7d7662709a.png)
インポートが終わると以下のような画面が表示されます。
仮想マシンのネットワークの設定を変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/a3d5e47e-e9f2-bfb0-b327-7ed73753dfa2.png)
アダプタ1がNATになっていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/0d1bd0d0-f2cc-69c3-db8e-ad69dc5c5b7c.png)
また、アダプタ2を追加してホストオンリーアダプタにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/6c9b27c1-e60e-4854-5939-bb1b10c6a852.png)
次に電源を投入してみます。
初回は時間がかかりますが、ある程度待つとWin11環境が立ち上がります。
ログイン時、ユーザ名・パスワードは求められません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/81bedb79-b0d2-f85d-7ce7-cae8f4b2e070.png)
仮想Win11からインターネット接続が問題なくできることを確認します。
今回は試しにQiitaにアクセスしてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/ac151dd9-70cf-6ecb-e2ed-07655e8cde31.png)
トランザクションのステートメント

# トランザクションのステートメント

- `BEGIN` : トランザクションの開始
- `COMMIT` : トランザクションの変更を確定し、データベースに保存します。
- `ROLLBACK`: トランザクションを取り消し、変更をロールバックします。
- `SAVEPOINT`: トランザクション内で保存点を設定します。SAVEPOINTステートメントを使用して、トランザクション内の特定のポイントにマーカーを設定し、後でそれに戻ることができる。
- `RELEASE SAVEPOINT`: トランザクション内で設定された保存点を解放する。
- `ROLLBACK TO SAVEPOINT` : トランザクション内で指定された保存点にロールバックする。

# ロック
__共有ロック（Shared Lock）__
- 複数のトランザクションが同時にデータを読み取ることができるようにします。
* 共有ロックは、他のトランザクションが同じデータに対して排他ロック（Exclusive Lock）を取得できないようにします。

__排他ロック（Exclusive Lock）__
- トランザクションがデータを更新、削除、または挿入するときに使用。
* 排他ロックを取得したトランザクション以外は、そのデータに対して読み取りや書き込みの操作を行うことができません。


## `SELECT ... FOR UPDATE`文を使用
```sql
BEGIN; -- トランザクションを開始

-- 指定した行をロックして読み取ります
SELECT * FROM table_name WHERE condition FOR UPDATE;

-- ここでデータを更新、削除、または挿入の操作を行います
		--　例えばデータを更新する場合
		UPDATE table_name SET column1 = value1 WHERE condition;
		
		-- 例えばデータを削除する場合
		DELETE FROM table_name WHERE condition;
		
		-- 例えばデータを挿入する場合
		INSERT INTO table_name (column1, column2) VALUES (value1, value2);
		
COMMIT; -- トランザクションをコミットしてロックを解除します
```

## LOCK文利用
```sql
BEGIN; -- トランザクションを開始

LOCK TABLE table_name IN SHARE ROW EXCLUSIVE MODE;

-- ここでデータを更新、削除、または挿入の操作を行います
		--　例えばデータを更新する場合
		UPDATE table_name SET column1 = value1 WHERE condition;
		
		-- 例えばデータを削除する場合
		DELETE FROM table_name WHERE condition;
		
		-- 例えばデータを挿入する場合
		INSERT INTO table_name (column1, column2) VALUES (value1, value2);

COMMIT; -- トランザクションをコミットしてロックを解除します
```
サクラエディタでSchemeを書く設定をする

# 本記事の内容
基本的にはサクラエディタにScheme用の強調キーワードを設定するだけです。

# なんでそんなことをするのか
SICPを読んでいて、デバッグでハマったときなど自分のコードと解答例をWinMergeにかけたりしますが、Emacsだとマウスでドラッグしてコピペするのが結構面倒です。
現状高度なコーディング支援は求めていないので、サクラエディタでいいかなと思いました。

# バージョン
サクラエディタ32bit Ver. 2.4.2.6048

# 1.タイプ別設定を追加
設定 > タイプ別設定 > 追加 で新しいタイプを追加します。

![タイプ別設定.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3702396/68d22446-3bee-ab32-339f-150f77e29988.jpeg)

<p>追加したタイプを選択し、設定変更を押して設定を進めます。</p>

# 2.スクリーン
以下の項目を入力します。

* 設定の名前
* ファイル拡張子
* TAB幅
* SPACEの挿入

![スクリーン.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3702396/a55d0e80-af23-4909-2274-51f02103ead9.jpeg)

# 3.カラー
### 色指定
デフォルトでも問題ないと思いますのでお好みでどうぞ。
今回は偶数行の背景色をONにし、対括弧の強調表示の背景色を変更しました。

![色指定.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3702396/881c37f7-0094-d126-5037-81a84167de17.jpeg)

### 強調キーワードの作成
共通設定を押し、強調キーワードを設定します。

![強調キーワード.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3702396/93428374-2f8e-95f7-f0e9-23ad93815a08.jpeg)

作った強調キーワードを設定します。
また";"をコメントに設定します。

![強調キーワードを設定.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3702396/6d004aab-31d3-8f7d-8554-bd7c29bb8aee.jpeg)

OKを押して完了です。

# 確認
*.scmを開いて色がついていればOKです。

![確認.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3702396/d0b33c88-8733-c313-ed09-f84d8c2a1dbc.jpeg)

# おまけ
ctrl + F5で外部コマンドを実行できます。$Fで編集中のファイルを引数に渡せます。
Gaucheなら
```
gosh $F
```
で編集中のファイルを実行できます。

![実行コマンド.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3702396/78e9460d-632e-5938-db6c-08ae325834de.jpeg)

![実行結果.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3702396/c7d0f14e-cb13-a6a0-4d72-200fdad90fde.jpeg)

# 参考
*[サクラエディタ公式ヘルプ](https://sakura-editor.github.io/help/)

# 追記
emacsの
PHPカンファレンス 関西 2024

先日、PHPカンファレンス関西に行ってきましたので、体験談を記録します。

# PHPカンファレンス関西とは
PHPカンファレンス関西は、PHPエンジニア（:PHPer）がPHPやPHP周辺の技術的知識やノウハウ、体験を共有するための大規模技術カンファレンスです。
今年は2018年から6年ぶりの開催になります。

# 参加したセッション
- [レガシーシステムへのPHPStan導入から半年での課題と効果](https://fortee.jp/phpcon-kansai2024/proposal/10c6f1ac-ec4b-4895-8db7-39b9a13c84bb)
- [RDBアンチパターンと戦う - 削除フラグ完全攻略ガイド](https://fortee.jp/phpcon-kansai2024/proposal/4e03491c-2a97-40aa-8ff9-a68593b0e847)
- [アプリケーションエンジニアこそ「監視」だよね！と私が考える訳](https://fortee.jp/phpcon-kansai2024/proposal/42712995-5f3e-4c68-a951-39584eac95a1)
- [20年の歴史を持つプロダクトの開発チームの変革：技術広報の本質と効果](https://fortee.jp/phpcon-kansai2024/proposal/30494f3c-b928-43b8-a617-f8c4a6992e08)
- [その条件分岐って本当に必要？](https://fortee.jp/phpcon-kansai2024/proposal/d2406310-e9dc-4866-851c-20662ae04fa8)
- [Mutation Testingとはなにか？ 〜Laravel(Pest)でInfectionを利用したライブデモ〜](https://fortee.jp/phpcon-kansai2024/proposal/8daa1c68-69b1-458a-9f3a-0c9a86e7843e)
- [モデルとは何か](https://fortee.jp/phpcon-kansai2024/proposal/b3f6ed97-8551-40da-90b1-3a14697df303)
- [PHPで生成AIのAPIをやってみた](https://fortee.jp/phpcon-kansai2024/proposal/012b22df-47d8-4552-9cbe-58362130291c)
- [ほげ言語にあってPHPにない機能](https://fortee.jp/phpcon-kansai2024/proposal/0e0befdb-2028-42c8-98e2-b19e434f5a82)

# 印象に残っているセッション
#### レガシーシステムへのPHPStan導入から半年での課題と効果
レガシーシステムだと修正コストが高すぎて静的解析ツールの導入は一見ハードルが高そうなイメージですが既存コードは検知対象外にすることで機能改修の際には高い解析レベルでの運用を可能にしてしており、上手く活用できていたので、レガシーシステムでもPHPStanは活用することができる良い事例でした。

#### RDBアンチパターンと戦う - 削除フラグ完全攻略ガイド
DBの削除フラグをできるだけ安全に無くしていくにはどうやるのかを具体的な方法を交えて解説してくださいました。
DB系の変更は失敗すると即障害に直結するので失敗を恐れがちですが、失敗できる方法で作業を進める考え方の説明があり、これは他の開発業務でも大事な考え方だなと思いました。

#### Mutation Testingとはなにか？ 〜Laravel(Pest)でInfectionを利用したライブデモ〜
テストコードが問題ないかを調べるためのツールでコードにバグを埋め込んでテストコードが失敗するかを検証することでちゃんとテストが動いているかを確認するというものです。
テストコードの品質が問題ないかを確認するってなかなかしないので、こういうツールは便利だなと思いました。

#### PHPで生成AIのAPIをやってみた
PHPで生成AIを実行するイメージがなかったので、ライブラリを使えば数行のコードで簡単に実行できるのを目の当たりにして驚きました。
機会があれば使いたい。

# 全体の感想
思ったよりも規模が大きくて驚きました。
以前行った時の会場は小さく参加人数も今回の半分以下だったと思います。
新機能の実体験の紹介は自分の技術の引き出しを増やす良い機会になり為になりました。