OmniAICreator/Qiita-1.07M huggingface dataset:
【Java】入出力についてざっくり

## Javaの入出力(I/O)の基本的な概念
### バイトストリーム
バイナリデータの読み書きに使用される。**InputStream**と**OutputStream**が基底クラス。
主なクラスとインタフェースは以下。
**FileInputStream**/**FileOutputStream**
ファイルをバイナリで読み書きするためのストリーム。

**BufferedInputStream**/**BufferedOutputStream**
バッファリングを行うことでI/O効率を向上させる。

**DataInputStream**/**DataOutputStream**
データストリームで、プリミティブ型のデータを扱うためのストリーム。

**DataInputStream**/**DataOutputStream**

### 文字ストリーム
テキストデータの読み書きに使用される。**Reader**と**Writer**が基底クラス。
主なクラスとインタフェースは以下。

**FileReader**/**FileWriter**
テキストファイルを読み書きするためのストリーム。

**ObjectInputStream**/**ObjectOutputStream**
オブジェクトのシリアライズとデシリアライズを行うためのクラス。

:::note info
**シリアライズとデシリアライズ**
シリアライズ: オブジェクトを保存・転送可能なバイナリ形式に変換するプロセス。
デシリアライズ: 保存・転送されたバイナリ形式のデータを元のオブジェクトに復元するプロセス。
:::

## I/Oの基本的な操作
### ファイルの読み込み
BufferedReaderは、ファイルから行単位でテキストを読み込むために使用される。

```java
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;

public class FileReadExample {
    public static void main(String[] args) {
        try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
```

### ファイルへの書き込み
BufferedWriterを使って、テキストをファイルに書き込むことができる。
```java
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.IOException;

public class FileWriteExample {
    public static void main(String[] args) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
            writer.write("Hello, World!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

```

## エラーハンドリングの必要性
I/O操作は多くの例外を投げる可能性があり、特にIOExceptionは頻繁に例外が発生するため、例外処理が非常に大事になる。


## 標準入力と標準出力
**標準入力**と**標準出力**を使ってコンソールでデータをやり取りできる。

### 標準入力
**System.in**を利用して、ユーザーからの入力を取得。
**Scannerクラス**を使うと便利。

```java
import java.util.Scanner;

public class StandardInputExample {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("名前を入力してください:");
        String name = scanner.nextLine();
        System.out.println("こんにちは、" + name + "さん！");
    }
}
```

### 標準出力
**System.out**を利用してデータを表示。
**System.out.printf**を使うとフォーマット指定が可能。

```java
public class StandardOutputExample {
    public static void main(String[] args) {
        int age = 25;
        System.out.printf("年齢: %d歳\n", age);
    }
}
```

## リソースの自動解放
Java7以降では**try-with-resources**を使用してI/Oリソースを自動的に解放できる。

```java
import java.io.*;

public class TryWithResourcesExample {
    public static void main(String[] args) {
        try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"));
             BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {

            String line;
            while ((line = reader.readLine()) != null) {
                writer.write(line);
                writer.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
```
Ubuntuに入っている特定パッケージをアップデートするメモ

## 何のメモか
Ubuntuに入っているパッケージに脆弱性が報告され、アプデが必要になる時があります。そういう時に迷わないためのメモ。

なおaptを使うものとします。
 
## 手順
「アップデート可能なパッケージのリスト」を更新する
```bash
apt update
```

アップデート必要なパッケージが1のリストにあることを確認する
```bash
apt list --upgradable
```

アップデートをシミュレーションしてみる
```bash
apt install -s <パッケージ名>
```

アップデートを実施する
```bash
apt install --only-upgrade <パッケージ名>
```

アップデート成功を確認する（対象パッケージのバージョンを確認する）
```bash
apt list -a <パッケージ名>
```

## おまけ
アップデート成功確認のコマンドで「focal-updates」とか出てくるかもしれません（Ubuntu 20.04の場合）。focalとはなんぞや？　と思うかもしれませんが、これはUbuntuバージョン毎にあるコードネームです。Ubuntuはバージョン毎に「形容詞＋動物の名詞」で、頭文字で韻を踏むようにコードネームをつけるらしい。20.04なら「Focal Fossa」。
【PowerShell】指定フォルダ内のサブフォルダ内のすべてのファイル・フォルダを一つ上の階層に移動するスクリプト

手動ではあまりやりたくない大量のフォルダ・ファイル操作。記事タイトルの作業を行う必要に迫られたので、スクリプトを作成した。再利用できるようここに記載しておく。

### 仕様
- 指定したフォルダに含まれる全てのサブフォルダに対して、そのサブフォルダに含まれるファイル・フォルダを上の階層に移動する。
- 移動後、元のサブフォルダは削除する。
- 名前の重複を避けるため、移動するファイル・フォルダには元のサブフォルダを名前の先頭に付ける。

つまり、これを、
```
TargetFolder/
    ├── SubFolder1/
    │   ├── SubFolder4/
    │   │   └── Text2.txt
    │   └── Text3.txt
    ├── SubFolder2/
    │   └── Text4.txt
    ├── SubFolder3
    └── Text1.txt
```
こうする。
```
TargetFolder/
    ├── SubFolder1_SubFolder4/
    │   └── Text2.txt
    ├── SubFolder1_Text3.txt
    ├── SubFolder2_Text4.txt
    └── Text1.txt
```

### コード

```PowerShell:MoveToParentLayer.ps1
# パラメータ設定
$targetFolder = "C:\Path\TargetFolder" # 操作対象のフォルダ
$delimiter = "_"                       # サブフォルダ名と元のファイル・フォルダ名の間の区切り文字

# 確認ダイアログ
$response = Read-Host "この操作は元に戻せません。続行しますか？ (Y/N)"
if ($response -ne "Y") {
    Write-Host "操作がキャンセルされました。"
    exit
}

# 指定フォルダ直下の全てのフォルダを取得
Get-ChildItem -Path $targetFolder -Directory | ForEach-Object {
    $currentFolder = $_.FullName                    # 現在のフォルダパス
    $folderName = $_.Name                           # 現在のフォルダ名

    # 現在のフォルダ内の全てのファイルを一つ上の階層に移動
    Get-ChildItem -Path $currentFolder -File | ForEach-Object {
        $sourceFilePath = $_.FullName                        # 元のファイルパス
        $newFileName = "${folderName}${delimiter}$($_.Name)" # 新しいファイル名
        $destinationPath = Join-Path -Path $targetFolder -ChildPath $newFileName

        Move-Item -Path $sourceFilePath -Destination $destinationPath
        Write-Host "Moved File: $sourceFilePath to $destinationPath"
    }

    # 現在のフォルダ内の全てのサブフォルダを一つ上の階層に移動
    Get-ChildItem -Path $currentFolder -Directory | ForEach-Object {
        $sourceFolderPath = $_.FullName                        # 元のサブフォルダパス
        $newFolderName = "${folderName}${delimiter}$($_.Name)" # 新しいフォルダ名
        $destinationPath = Join-Path -Path $targetFolder -ChildPath $newFolderName

        Move-Item -Path $sourceFolderPath -Destination $destinationPath
        Write-Host "Moved Folder: $sourceFolderPath to $destinationPath"
    }

    # 元のフォルダを削除
    Remove-Item -Path $currentFolder -Recurse -Force
    Write-Host "Removed Folder: $currentFolder"
}

Write-Host "処理が完了しました。"
```

確認ダイアログも出すようにしているが、一度実行してしまうと元に戻すのは難しいので注意してほしい。
Raspberry Pi Pico - Python SDK のドキュメントを読む⑤

# 4 IDE

開発環境としての IDE をいくつか紹介している。

## 4.1 Thonny

今や、MicroPython の開発環境としての定番 IDE となってしまった Thonny である。[Raspberry Pi Pico の MicroPython 入門書](https://magpi.raspberrypi.com/books/get-started-micropython-pico-2ed)でも全面的に Thonny が使われている。

スクリプトの Pico への転送方法はここで初めて言及される。転送方法はもっと前にいろいろ方法を説明しておくべきだよな。

## 4.2 VSCode

VSCode については、やや記載が古いような気がする。今どきは Raspberry Pi Pico 拡張機能を紹介するべきだろう。

## 4.3 rshell

これは IDE というよりは、コマンドラインツール。今時であればコマンドラインツールを１つ紹介するなら [mpremote](https://micropython-docs-ja.readthedocs.io/ja/latest/reference/mpremote.html) にして欲しいところ。

# おわりに

以上です（付録については省略）。

全体を読んでみて、これだけで Pico プログラミングできるようにはならんだろうなという印象。MicroPython 本家ドキュメントを併せて合わせて参照するようにしよう。
誰でもすぐに真似できる！「話す」「提案する」ときに気を付けるべき4つのこと

こんにちは、ふるすです。
今日はITコンサルをしていたときに学んだ、誰でもすぐに真似できる「話す時に気をつけていること」をシェアします。

## 絶対に話を遮らない
言わずもがな、相手へのリスペクトを示す最低限のマナーだと思います。
これができなければどんな技術を使おうと、いくらほかのところで頑張ろうと好印象を与えることは難しいのではと考えます。

## 自分の案や意見を複数述べるときは最初にいくつあるのか言う

「セットザシーン」という技術だそうです。
「ぱっと思いつく案は3つあります。まずひとつめは…」というやつですね。

これをすることの最大のメリットは相手に心構えをしてもらえることです。
「お、今から3つ言うんだ」と受け入れ態勢を整えてもらうことで、頭を整理してもらいながら話を聞いてもらうことができます。

## 相手の理解度に沿って説明をする
MTGは「わたしの知識の豊富さ」をひけらかす場ではありません。
難しい言葉を使って自分の考えを押し付けるのはNGです。
MTGに出ている人、話を聞いてくれる人の理解度がなるべく揃うように努めることが必要です。質問がないかを丁寧に確認し、理解できていない人がいれば図を用いるなどその方に理解してもらえるようにしてみましょう。

## 主張と理由をセットで伝える
一方的に主張をしたのみでは、同意してもらうことは難しいです。
なぜそう考えるのかの根拠や理由をセットで伝え、質問をしてもらえるような話し方をすることが望ましいと思います。
そうすることで、相手の方も意見をしっかり受け止め、納得したうえで意思形成をしてもらうことができます。
キャリアブレイク中の時間の使い方

キャリアブレイクで一番悩んでいることは、時間の使い方です。でも最近、小2の息子ですら言っていました。「時間が足りない。。」と。結局、誰でも、何をしていても、時間の使い方は悩むものかと思いました。

# 無限の時間を手に入れた！
正直、キャリアブレイクを決断したときは、無限の時間を手に入れられるぐらいの万能感がありました。でも、実際にキャリアブレイクを過ごしてみると、時間は有限だという、当たり前のことにわりとすぐ気づいてしまいました。

# 仕事なら月20日勤務が普通
キャリアブレイク中は勉強に優先した時間の使い方をしていますが、当然ですが、1か月30日間勉強をしているわけではありません。仕事だと1ヶ月に働くのは20日ぐらいです。勉強に使う時間はそれよりも少なく恐らく15日ぐらいです。仕事でも有休があるように、イベントや用事で勉強しない日もあります。また妻に「今日は紅葉が綺麗だから見に行かない？」と言われたら優先しています。それぐらい自由にやっています。

# 仕事なら1日8時間勤務が普通
さらに言うとしっかりした[スケジュール](https://github.com/binnmti/Study/blob/main/README.md)を組んで毎日過ごしていますが、このスケジュール上でも勉強時間は9:00-17:00です。つまり時間も日にちも仕事よりは少ない時間しかしていません。きっちり守ったとて対価が出るわけではないので、延長することもあれば、短くなることもありますが、それでも1日7時間月15日ぐらいが上限だと思います。

# 実際に使える時間
そして、現状で勉強を「アルゴリズム、CS、コンパイラ開発、英語、仏教、栄養学」にしているので、1教科に1日1時間、教科によっては2日に1回のものもあります。そうなると一番出来る科目でも7カ月で100時間がせいぜいです。100時間が長いか短いは人によって違いますが、例えば英語をマスターするのに必要な時間は2000時間とも言われています。学校で１年習っても出来ないことを考えると100時間は長いとは言えない時間です。

# 時間を思ったきっかけ
具体的に時間について考えたきっかけは、外資を受けようかなとほんの少し思った時です。これからキャリブレイクで7ヶ月勉強するけれど、果たして英語が喋れるようになるかと言うと、まず間違いなく無理です。これから半年の生活の時間を全て使えば、600-800時間ぐらいは取れるかもしれませんが、それでも英語でコミュニケーションが出来るかはちょっと分からないです。そう考えると色々何科目もやるのは間違っているかもと思いました。

# 贅沢な時間の使い方
でも、その後、別のことも思いました。こんなに色々なことができる機会はもうないかも。例えば本気で英語を取得したいと思えば、仕事が終わっても休日も全部そこに時間を使って習得する人も一杯います。一点集中すれば出来ないことはないはずです（やれるかは別問題）。でも、働いている状態で6科目を少しずつ齧るような勉強方法は無理だと思います。そうするとこのやり方は今しかない、自分にとっては今のこのやり方はとても贅沢な時間な使い方だなと思いました。

# まとめ
はい。自分は今勉強をしているのがとても楽しいです。たまには勉強を完全に止めて、好きなことに時間を使ったり、妻と遊びに行ったりするのは最高です。人と会うことはなるべく優先しており、その時間は勉強を削ったりもします。これらすべてを含め、今後この形で過ごせるのは、もしかしたら定年退職するまでないかもしれません。そういう意味でこのキャリアブレイク中は目一杯今のやり方を楽しもうと思っています。
【Next.js】is missing required "width" property.の解決方法

# はじめに
Next.jsのImageコンポーネントを使用した際に発生したエラーについて、その原因と解決方法を解説します。

:::note warn
***この記事は<font color="Red">個人的なアウトプット</font>を目的として作成したものです。そのため、誤った情報や不足している内容が含まれている可能性があります。もし間違いや気になる点がございましたら、ぜひご指摘いただけますと幸いです***。
:::

# 原因
以下のように`Image`コンポーネントを使用した場合、エラーが発生しました。

```react
<Image src='https://qiita.com/image/aaaaa' alt='sample' />
```
このエラーの原因は、`width`と`height`プロパティを指定していないことにあります。`Next.js`の`Image`コンポーネントでは、`src`、`width`、`height`、`alt`のプロパティを正しく指定することが求められます。

https://nextjs.org/docs/pages/api-reference/components/image

ただし、`width`と`height`を指定しないようにした背景には、以下の理由がありました
+ 固定値で指定すると、レスポンシブデザインに対応しづらくなる。
+ 柔軟なレイアウトを実現したい場合、固定値は制約となる。



# 解決方法

以下のように修正することで、エラーを解消しつつレスポンシブデザインに対応しました。

```react
<Image src='https://qiita.com/image/aaaaa' alt='sample' className="w-[16px] h-[16px] pc:w-[20px] pc:h-[20px]" width={18} height={18}/>
```
+ widthとheightを指定することで、アスペクト比を固定。
`Next.js`の要件を満たします。
+ レスポンシブ対応のためにclassNameを使用してサイズを上書き。
例えば、PC表示時にサイズを変更する`pc:w-[20px]`や`pc:h-[20px]`を適用しました。

# 終わりに
`Next.js`の`Image`コンポーネントは、指定が必要なプロパティを忘れるとエラーが発生します。レスポンシブの際には気をつけていきたいと思います。

# 参考

https://nextjs.org/docs/pages/api-reference/components/image#width

『Next/Imageを何となく使ってたらボコボコにされた』Zenn

https://zenn.dev/pe_be_o/articles/maeta-187-articles_47620f22f6c459
【転職活動】面接官に褒められた職務経歴の書き方

転職活動中に面接官から「経歴分かりやすかったです」とお褒めの言葉をいただくことがしばしばありました。

本記事では個人的に意識していた経歴の書き方についてご紹介します。


# 経歴(自由記述パターン)

転職サービスによっては、一般的な年表形式でなく自由記述のパターンもありました。
その際、色々書くのではなく簡潔に書くようにしていました。

### 例
XXXX年に入社、XX部署でXX年間XXのプロジェクトを担当。
その後、XXのプロジェクトをXX年間担当。

ほぼ年表形式と変わらないレベルしか書いていませんでした。

# 職務経歴

こちらはプロジェクトレベルの内容を記載すると思います。
詳しめに書きたいところですが、プロジェクトを複数書くことになるため、文章量が多いと面接官は読むのが大変ですね。

ここでは、必要十分な情報量を要点をまとめて書くようにしていました。

### 例
基本は以下の項目を記載していました。

- プロジェクト概要
- 期間
- チーム構成
- 担当役割
- 使用技術

詳しく書く必要があるサービスでは以下の項目を追加していました。

- プロジェクト背景
- 課題・解決方法・成果・教訓


# なんちゃって所感

- プロジェクト概要
こちらは言わずもがな必須項目のため割愛します。
<br />

- 期間
どれくらいの規模感のプロジェクトをどれくらいで経験してきたのかを測るのに必要です。
一つのプロジェクトを長い期間で回す企業もあれば、複数のプロジェクトを短い間で回す企業もあります。
<br />

- チーム構成
メンバー経験が多いのか、リーダー経験が多いのかを測るのに必要です。
採用枠がテックリードなのか、メンバーなのかの判断材料になり得るところだと思います。
<br />

- 担当役割
バックエンドの経験が多いのか、フロントエンドの経験が多いのかなどを測るのに必要です。
こちらも採用枠の判断材料に必要な情報だと思います。
<br />

- 使用技術
絶対書きましょう。経験技術が似ているほど企業側は教育コストを抑えることができるため、内定まで辿り着きやすい印象です。
<br />

- プロジェクト背景
なぜこのプロジェクトが立ち上がったのか、何が目的だったのかまで説明できると良いと思います。
言われるがまま業務していたのではなく、自分で考えて業務していたことが伝わると好印象でした。

<br />

- 課題・解決方法・成果・教訓
こちらについてはプロジェクトを担当して詰まったことを起承転結で説明できると良いと思います。
面接でよく聞かれる苦労したエピソードですね。


# おわりに
自分の頭の中が整理されていないと要点をまとめて記載することができないため、面接でも詰まらず話せるようになるはずです。参考なれば幸いです。
UiPath Appsでマインスイーパー（もどき）を作ってみた話

# はじめに

本記事は、UiPath (produced with UiPath Friends) Advent Calendar 2024の記事になります。

https://qiita.com/advent-calendar/2024/uipath

2024年11月30日に行われたUiPath Friends Festival2024のテック三昧枠でご紹介した「UiPath Appsでマインスイーパーもどきを作ってみた」の裏側をご紹介したいと思います。

# 作ったもの

![minesweeper_demo01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526766/f2683b86-3548-40f9-3db7-a71319403b1c.gif)

# まずは遊んでみよう！
以下URLから、登録不要で遊べます！
※2025年1月中旬ごろまで公開しています。

https://bit.ly/4icMc1p

# 裏側の話

UiPath Appsには、パブリックアプリという公開形式があり、組織外のユーザーにもアプリを公開することが出来ます。（Enterprise環境では個別にパブリックアプリ利用のために有償ライセンスが必要です。）

https://docs.uipath.com/ja/apps/automation-cloud/latest/user-guide/use-public-apps

色々と裏側の解説をしていきたいと思いますが、詳しくは後日追記します。。。m(_ _)m
2024年Python学習の振り返り

## はじめに
この記事は、「Python Advent Calendar 2024」の23日目の記事です。

https://qiita.com/advent-calendar/2024/python


## 投稿主について

自分をご存じない方について一応紹介します。
この記事の投稿主は、普段RPAツール(UiPath)を使って顧客の業務自動化の開発～保守まで幅広く行っております。
なお業務でPythonに触れたことは一度もなく、現在の会社に入社して間もなく7年になりますがPythonを使用する案件に参画したことはありません。

## 現状の学習ツール

自分はPythonの理解を深めるために以下の教材を利用しています。
①Udemy
・米国AI開発者がゼロから教えるPython入門講座

https://www.udemy.com/course/python-ai/

・米国データサイエンティストが教える統計学超入門講座【Pythonで実践】

https://www.udemy.com/course/python-stats/

・米国データサイエンティストがやさしく教えるデータサイエンスのためのPython講座

https://www.udemy.com/course/ds_for_python/


上記3点はいずれも「かめ れおん」先生の教材で、評価も非常に高いものばかりです。

②Google Colaboratory

有料のほうができることは多いのですが、無料でも利用できるGoogleのツールです。

③書籍など
2024年は関連書籍を購入しておりません。
※2020年ごろは積極的に購入していました...

## 結果
①、②がメインになりますがどちらも<b>進捗率10%以下で進みませんでした...</b>:angel:。

## 理由
### ①本業務の優先
今年はRPAの開発現場が2回変わり、中には遠方出張や引継ぎ等の事情により学習時間の確保が難しい時期もありました。
現在の現場もほとんど1人で回しているため残業が増えがちになりつつあります。
今後は、残業時間を削減したうえで学習時間を確保する予定です。

### ②他ツールの学習優先
どうしても本業務でRPAを使用している関係で、Python学習へのエネルギーが注げなくなっていたことも理由に上がります。
今後は大学院でデータサイエンスとRPAによる業務効率化(DX)で統計を出して提案できるような業務へ挑戦したいので、Pythonの教材をもっと活用しないとです。

### ③現在の業務で利用しない
業務ではどうしてもPythonを使う機会がなく、本格的にプログラムを組んだりした経験はどうしても少ない状況です。
本当はハッカソンや競技プログラミング等の大会に出る方法もあります。やるべきこと、やりたいことに優先順位を決めつつ、2025年はPythonでブログ投稿を増やせるよう努めます。

## 教材の消化率
Udemyの教材は、いずれも2020～2022年にかけて購入したものです。
2024年は少ししか手を付けられておりませんが、実は教材購入当時から少しずつ履修しておりました。
2024/12時点の進捗率は以下の通りです。(単位はパーセント、四捨五入)

・米国AI開発者がゼロから教えるPython入門講座
→消化率：91%
・米国データサイエンティストが教える統計学超入門講座【Pythonで実践】
→消化率：53%
・米国データサイエンティストがやさしく教えるデータサイエンスのためのPython講座
→消化率：93%

## まとめ
当初はPythonとRPAツールのUiPathを使ってrandom関数で実験したいと考えていましたが、業務等の都合で時間確保が難しく検証も不十分なため、急遽差し替えました。
※もし楽しみにしておりました方がいらっしゃいましたら申し訳ありません...。
次回はPythonに関する気づきやノウハウを投稿できるよう努めます。

最後までお読みいただきありがとうございました。
Laravel eloquentのwith・loadでの特定カラム取得時のTIPS

# 概要
LaravelのEloquentにて利用できるwithとloadメソッドですが、
特定のカラムだけを取得したい時に、その手法や気をつけて欲しいことなどを下記2つTIPSとして紹介します。
1. 連続したリレーション先でも特定カラムを取得したい場合
2. クロージャを使いつつ特定カラムを取得したい場合

※例として、すべて`with`を使ってコードを載せていますが、同様の内容を`load`でも利用可能です。
※「Laravel9以降」「php8以降」を前提としてコードを記載しています。

## 前提知識
通常、`with`や`load`で必要な特定カラムを取得したい場合、
下記のように、リレーション名(`posts`など)のあとに`:`をつけて必要なカラム名(`id,user_id,title`など)を記載すればOKです。
```php
User::with('posts:id,user_id,title')->get();
```

## 1. 連続したリレーション先でも特定カラムを取得したい場合
基本的にドット記法で連続したリレーションを記載しつつ、`:`で必要なカラムを記載すればOKです。
```php
// postsに紐づいたcommentsも一緒に取得&カラムを絞りたい場合
User::with([
    'posts:id,user_id,title',
    'posts.comments:id,post_id,content',
)->get();
```
:::note warn
特定の時だけ連続したリレーション(`posts.comments`など)を取得したい、かつ、`when`を使って、それを表現したい場合は、`when`を書く場所に要注意です。(下記)
:::

<font color="red"><b>NG</b></font>パターン
`when`を`with`の後に記載
```php
User::with('posts:id,user_id,title')
    ->when($condition, fn ($q) => $q->with('posts.comments:id,post_id,content'))
    ->get();
```
こう書くと、<font color="red">`with('posts:id,user_id,title')`の方のカラム制限が外れてしまい</font>、
`with('posts')`と書いたのと同じように動いてしまいます。
(`comments`の方のカラム制限=`with('posts.comments:id,post_id,content')`は機能します。)

\
<font color="green"><b>OK</b></font>パターン
`when`を`with`の前に記載
```php
User::when($condition, fn ($q) => $q->with('posts.comments:id,post_id,content'))
    ->with('posts:id,user_id,title')
    ->get();
```
こう書くと、`posts`と`posts.cooments`、どちらも特定のカラムだけ取得できます。

意外と気付きにくいので、お気をつけください。

## 2. クロージャを使いつつ特定カラムを取得したい場合

`with`内でクロージャを使いたい場合は、`:`を使った書き方ができません。
```php
// NG(エラー発生)
User::with(['posts:id,user_id,title' => fn ($q) => $q->latest()])->get();
```
\
そのため、クロージャ内で`select`を使って絞りましょう。
```php
// OK
User::with(['posts' => fn ($q) => $q->select(['id', 'user_id', 'title'])->latest()])->get();
```

:::note warn
`select`内でカラムを絞る場合、リレーション元と先で、同じ名前のカラム名が存在する場合は、テーブル名を明示する必要があります。(下記)
:::
```php
// usersテーブルにも「id」、postsテーブルにも「id」カラムが存在する場合、'posts.id'と明示が必要
User::with(['posts' => fn ($q) => $q->select(['posts.id', 'user_id', 'title'])->latest()])->get();
```


# 終わりに
必要なカラムだけ取得する癖をつけると、プロダクトが拡大してDBテーブルにカラムを追加した場合などでもPFMの低下を抑えることができます。
普段から必要なカラムだけ取得するよう心がけていきたいですね。
(QA) IBM i のソケット通信でタイムアウトを設定したい

IBM i でクライアントとソケット通信でテータ送受信する仕組みを構築したお客様で、クライアント側の操作がおかしい場合や誤操作した際などにIBM i 側とのソケットコネクションを設定したインターバル時間経過後にIBM i 側から遮断（リセット）したい、というご相談です。

## 上手くいかなかった例

・ILE RPGでSOCKET()でソケットを作成
・LISTEN()で待ち受け → ACCEPT()でクライアントから接続
・通常は、RECV()でクライアントからのデータを受信
・この時、クライアント側の誤操作その他が発生した際に、あらかじめ決めた秒数経過後に、RECV()処理をタイムアウトにしたい。

ご相談いただいた時点では、タイムアウトが設定できずクライアントからの異常なリクエストの通信がスタックして滞留するケースが発生していました。

## 最初のトライ（失敗したケース）

ソケット作成後にSETSOCKOPT()のオプション名にSO_RCVTIMEOを指定してタイムアウト時間を指定する方法をトライしましたが、
SETSOCKOPT()でタイムアウトを設定するサンプルが分からず、、という事でした。

例えばこの辺の記事などを参考にしてプログラミングしたとの事
**setsockopt()--Set Socket Options**
https://www.ibm.com/docs/ja/i/7.5?topic=ssw_ibm_i_75/apis/ssocko.html

上記のソケットタイムアウト値の設定などの情報があまり見つからないようです・・

## 別なトライ（成功ケース）

結局SETSOCKOPTはあきらめて、別なプログラミングにトライしたところ期待通りの動作が実現できたとのことでした。大まかには下記になります。

**①SOCKET()でソケットを作成**
**②LISTEN()でクライアント要求を待機**
**③ACCEPT()でクライアントの接続要求を許可**
**④SELECT()でタイムアウトの秒数を設定**
**⑤ソケットが読み取り可能か確認**
**⑥ソケットが読み取り可能な場合以下実行**
**⑦ソケットから読み取りできず指定秒数でタイムアウトした場合、接続をクローズして①に戻る。**
**⑧RECV()でクライアントからのデータを読取り**
**⑨SEND()でクライアントへデータ送信**
**⑩接続を閉じて初期化し②に戻る**

K様ありがとうございました自身大変勉強になりましたm(_ _)m
027 AI屋さんの　LLMにトークン全文入力　streamlit＋cloudrun＋Gemini



027 AI屋さんの　LLMにトークン全文入力　streamlit＋cloudrun＋Gemini


すでに何度か、大規模言語モデルのwebアプリをクラウドのサーバーレスでデプロイしてきました。
一度、手順をまとめておきましょう。
色々方法はありますが、簡単な方法で行きます。



streamlitをクラウドのサーバーレスで　インターネット公開は、超絶難易度高そうなイメージですが、いえいえ、そんなことはございません。
むしろ

　streamlitのマルチページ　
 
だから超簡単なのです。全てのwebフレームワークの中で最も簡単かもしれません。



https://docs.streamlit.io/develop/concepts/multipage-apps/overview


ブラウザ画面　ポチポチ　のみで、完成します。
全体の構成は

　１、cloudrunにdockerイメージデプロイ　bono0/st
　２、ストレージをマウント　/app/pages
　３、ストレージにpythonファイルをコピー　app01.py
　
で完成です。
特にトラブルが無ければ、数分で完成します。
注意点としては、用意するイメージの内容です。
事前の　pip install 済みのライブラリと
アプリのディレクトリの場所です。
上記のサンプルの設定内容で、一通りは動きます。





![スクリーンショット 2024-12-23 21.00.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237930/731e9ea3-8a66-fc83-8b31-735ae3dc0415.png)



アプリの内容は、最小限度です。
必要な部分を後から足してください。



---

#app01.py

import streamlit as st

st.write("hello")
st.write("hello end")

---




cloudrunの設定


まずは、ストレージ向けの設定

![スクリーンショット 2024-12-23 20.41.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237930/1675c6fb-13b0-926f-803b-6ec49b6c38d5.png)


続いて、docker向けの設定

![スクリーンショット 2024-12-23 20.43.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237930/114ff349-8876-a3fb-2e61-b1b3ea89f447.png)


ついでに、環境変数の設定

![スクリーンショット 2024-12-23 20.44.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237930/d4299186-56be-2d2d-b049-2e25bf2d157c.png)


たった、これだけで　streamlit　をクラウドデプロイできてしまします。
ほんと、簡単すぎて　びっくりします。
しかも、アプリの修正も追加も　何個でも後から可能です。



目次

https://qiita.com/bono0/items/dc1d000c98af7e07c9a7


今回も無事に

　027 AI屋さんの　LLMにトークン全文入力　streamlit＋cloudrun＋Gemini
　できました。
 
完成です。おめでとうございます。





ー続くー
Power Automate for desktop の 「Graph HTTP要求送信」の使い方（リクエスト本文の指定方法）

# はじめに

Power Automate for desktop の 

・Teams の 『Microsof Graph HTTP 要求を送信する』
・Office 365 Outlook の 『HTTP 要求を送信します』

アクションで、Graph API を利用したリクエストを送信する際、
《本文》を **バイナリ** を指定する必要があります。
![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/f1e4be81-931a-838b-3339-8e602e52a744.png)

指定方法について、記載いたします。


# バイナリでの指定方法

リクエストの本文へは、『ファイルをバイナリデータに変換』アクションを利用して値を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/56a50656-bbe3-d238-3641-37ddbbcb4669.png)

以下、手順です。

## ① リクエスト本文を記載したテキストファイルを用意

ローカルPCの任意のフォルダに、API の本文を記載したテキストファイルを保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/a3194780-3950-fbfb-d476-d05e3c7fb929.png)

:::note info
文字コードは Shift-JIS で問題ありませんが、
2バイト文字を含む本文を作成する場合は　《UTF-16》や《UTF-16 Big Endian》 で指定することで、
Teams のスレッドでの文字化けを回避できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/60983bc1-8629-355e-be05-34897c400100.png)
:::

上記ファイルを『ファイルをバイナリデータに変換』アクションを利用し、バイナリ型の変数を生成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/df87c831-ffb6-e6c6-ac5a-5d1478d7ae7f.png)


## ② Graph HTTP 要求実行

Teams の 『Microsof Graph HTTP 要求を送信する』や、Office 365 Outlook の 『HTTP 要求を送信します』の 《本文》 で、上記①で生成されたバイナリ型変数を指定します。

![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/564751ff-9fd6-e5ef-9c66-ed95aae3e9ff.png)



# まとめ

リクエスト本文をテキストファイルとして保存したのち、ファイルをバイナリで変換し利用するというひと手間が必要となりますが、何かと便利な Graph API リクエストを PAD から利用する際はぜひご参考ください。
Raspberry Pi Pico - Python SDK のドキュメントを読む④

## 3.9 PIO

さて PIO である。このドキュメント全般に言えることだが、サンプルコードばかりで、SDK が提供する API の説明が足りない。PIO は特にひどい。サンプルコードだらけで、PIO インストラクションの説明もない。

具体的なことは C/C++ SDK のほうを参照しろとある。しかし、MicroPython の場合、MicroPython の構文にうまくあうようにインストラクションのフォーマットが少し違っているので、C/C++ SDK ドキュメントを参照させるのはやや不親切。

具体的な説明は [rp2 モジュール](https://micropython-docs-ja.readthedocs.io/ja/latest/library/rp2.html)のドキュメントを参照しよう。

とりあげられているサンプルコードは以下のとおり。

* Lチカ
* IRQ (割込み)
* WS2812 LED (NeoPixel)
* UART TX
* SPI
* PWM

それぞれのプロトコルを PIO でどう実現しているのかの説明が欲しい。そのうち書くかな。

## 3.10 無線サポート

ここでも Wifi のプログラム例を示すのみ。極簡単な Web サーバの実装である。

network モジュールについては[ここ](https://micropython-docs-ja.readthedocs.io/ja/latest/library/network.html)を参照しよう。

socket モジュールについては[ここ](https://micropython-docs-ja.readthedocs.io/ja/latest/library/socket.html)を参照しよう。

あれ？　Bluetooth の説明がない。Pico W でのBluetooth実行が遅れたとはいえ、C/C++ SDK のほうはちゃんと書いてあるぞ。

ということで Bluetooth については[ここ](https://micropython-docs-ja.readthedocs.io/ja/latest/library/bluetooth.html)や micropython-lib の[aioble](https://github.com/micropython/micropython-lib/tree/master/micropython/bluetooth/aioble)を参照しよう。
Facebookグループ「kintone(キントーン)活用会」はじめます

![469650470_8751386991605598_6299710719104839367_n.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152073/c61e442a-d038-bc75-558c-db78e6cd5c6e.jpeg)

## kintoneの情報発信・情報収集のために
2014年から「kintone活用研究会」というFacebookグループでkintoneの情報を投稿させていただいてましたが、10周年の2024年12月末をもってグループ終了というアナウンスがありました。
グループの管理者による終了の意向を尊重したいので仕方がないかな、と思っていたところ、11月のCybozu Daysで直接お会いした方から、キュレーションされた情報を得られて助かっていた、終了と聞いて悲しい、というお声があり、どうしようか悩んでました。
自分としては、情報を発信したり共有させていただく場があるといいな、と思っていたので、新しく「[kintone(キントーン)活用会](https://www.facebook.com/groups/kinuse "kintone(キントーン)活用会")」というグループを作ることにしました。
継続して発信していきたいという意識で同じような名前にしたく、似たような名前に対して前グループの管理者は、新規に始めることだから大丈夫ですと温かいお言葉でした。
宜しければ、ぜひ皆さま、kintoneの情報発信・情報収集のために、「[kintone(キントーン)活用会](https://www.facebook.com/groups/kinuse "kintone(キントーン)活用会")」をご活用ください。

## グループの説明
サイボウズ kintone に関するニュース、イベント、セミナー、事例、ノウハウ、宣伝を投稿してください。また、kintoneでこんなことをやりたい／ここがうまくいかないけどどうしたら／kintoneでこんなことをやってますなどの話題を歓迎します。
当グループはどなたでも参加できます。投稿はメンバーになってからお願いします。
kintoneに関係のない投稿や過剰な宣伝は事務局の判断で削除することがあります。明らかなスパムを投稿したメンバーは即時削除してブロックします。グループの参加メンバーと投稿は公開されます。

## グループのURL
https://www.facebook.com/groups/kinuse

## 「すごくない」kintone Advent Calendar 2024
この記事は、「すごくない」kintone Advent Calendar 2024の12/24の記事です。
https://adventar.org/calendars/10426
SQLをmruby、mruby/c、Arduinoのソースコードに変換【完全版】

# はじめに

この記事は、2024年7月に投稿した記事 [SQLをmruby、mruby/c、Arduinoのソースコードに変換](https://qiita.com/arthur87/items/94063765315a9298c16c) の完全版です。

RubyでSQLをmruby、mruby/c、Arduinoのソースコードに変換するツールを作りました。
最終的なソースコードは [GitHub](https://github.com/arthur87/rossoc) にあります。

このツールは [RubyGems](https://rubygems.org/gems/rossoc) に公開しています。以下のコマンドでインストールできます。

```bash
gem install rossoc
```

# 使い方

例えば、SELECT din11 FROM mruby WHERE ((din1 = 0 AND din2 <= 1) OR din3 <> 9) のようなSQLは以下のようなコードに変換されます。mruby、mruby/cのCommon I/O APIに対応しています。

```rb
# SELECT `din11` FROM `mruby` WHERE ((`din1` = 0 AND `din2` <= 1) OR `din3` <> 9)

GPIO.setmode(11, GPIO::IN)
GPIO.setmode(1, GPIO::IN)
GPIO.setmode(2, GPIO::IN)
GPIO.setmode(3, GPIO::IN)

uart1 = UART.new(1)

while 1 do
  din11 = GPIO.read(11)
  din1 = GPIO.read(1)
  din2 = GPIO.read(2)
  din3 = GPIO.read(3)

  if ((din1 == 0 && din2 <= 1) || din3 != 9)
    uart1.puts("din11=#{din11}")
  end

end
```

この mruby コードは次のコマンドで出力できます。

```bash
rossoc query -i 'SELECT din11 FROM mruby WHERE ((din1 = 0 AND din2 <= 1) OR din3 <> 9)' -o test.rb
```

SELECTステートメントをサポートしています。
カラムには din1 から din20 と ain1 から ain20 を指定できます。dinはデジタルピン、ainはアナログピンです。
テーブル名には mruby と arduino を指定できます。

# 独自キーワード

独自キーワード RSLEEP を実装しています。RSLEEPの単位は秒で、指定した秒数分、処理を停止します。

```bash
rossoc query -i 'SELECT din11 FROM mruby WHERE ((din1 = 0 AND din2 <= 1) OR din3 <> 9) RSLEEP 100' -o test.rb
```

この mruby のコードを以下のようになります。

```rb
# SELECT `din11` FROM `mruby` WHERE ((`din1` = 0 AND `din2` <= 1) OR `din3` <> 9) RSLEEP 100

GPIO.setmode(11, GPIO::IN)
GPIO.setmode(1, GPIO::IN)
GPIO.setmode(2, GPIO::IN)
GPIO.setmode(3, GPIO::IN)

uart1 = UART.new(1)

while 1 do
  din11 = GPIO.read(11)
  din1 = GPIO.read(1)
  din2 = GPIO.read(2)
  din3 = GPIO.read(3)

  if ((din1 == 0 && din2 <= 1) || din3 != 9)
    uart1.puts("din11=#{din11}")
  end

  sleep(100)

end
```

同じく、 Arduino のコードは以下のようになります。

```c
// SELECT `din11` FROM `arduino` WHERE ((`din1` = 0 AND `din2` <= 1) OR `din3` <> 9) RSLEEP 100

void setup() {
  Serial.begin(9600);
  
  pinMode(11, INPUT);
  pinMode(1, INPUT);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
}

void loop() {
  
  int din11 = digitalRead(11);
  int din1 = digitalRead(1);
  int din2 = digitalRead(2);
  int din3 = digitalRead(3);


  if((din1 == 0 && din2 <= 1) || din3 != 9) {

    Serial.print("din11=");
    Serial.println(din11);

  }

  
  delay(100000);
  
}
```

生成されたソースコードをみると `sleep` というコードが追加されています。

# 仕組み

このツールはフロントエンドとバックエンドから構成されています。 独自のIR(中間表現)を介してフロントエンドとバックエンドを接続しています。フロントエンドは、字句、構文、意味解析を実行します。 バックエンドは、ターゲットのコードを生成します。


```mermaid
flowchart TB
    input --> FrontEnd
    subgraph FrontEnd
    parser --> columns --> tables --> condition --> rsleep
    end
    FrontEnd --> IR --> BackEnd
    subgraph BackEnd
    generate
    write
    end
    write --> output
```

# さいごに

実験的なツールのため予告なしに仕様変更することがあります。
はじまりの物語

# 自己紹介
初めましてLemonadeです！タイトルはあんな感じだけど別にすとぷり好きなわけじゃないです…普段はXでいろいろ投稿してるんだけどプログラミングはまあ初心者です！
AIが好きでいろいろいじくってます。欲を言えばいつかIOAIに出てみたいです
# プロフィール
・atcoder 灰色
・JOI １次予選通過
・彼女 いない
・できないこと 社会生活
# 最初にやること
ネタがないのでさっき作ったCNNモデルでもみてください
~~~
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
import torch.nn.functional as F 

# 前処理
transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

# CIFAR-10
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                        download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
                                          shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root='./data', train=False,
                                       download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
                                         shuffle=False, num_workers=2)

classes = ('plane', 'car', 'bird', 'cat',
           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

# CNN
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

net = Net()

# loss
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

# トレーニング
for epoch in range(10):  #ここの１０のとこいじくってepoch決めてね
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data

        optimizer.zero_grad()

        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()
        if i % 2000 == 1999:
            print(f'[{epoch + 1}, {i + 1}] loss: {running_loss / 2000:.3f}')
            running_loss = 0.0

print('終わり')

# 評価
correct = 0
total = 0
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print(f'精度: {100 * correct / total} %')
~~~
まだGPTに手伝ってもらって作りました。自分で作れるようになるといいね
じゃあばいばい
linebotを作った風に見せる

# linebotを...

![img_1119.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227398/2ed561ae-5419-5a43-7239-b0d6fcda515d.png)

# 作れませんでした！

### この記事について

でぶ Advent Calendar 2024 22日目の記事です。見事に遅刻しました。

https://adventar.org/calendars/10424


### 何があったか
でぶ Advent Calendar では毎年、何らかのアプリを作ろうというモチベーションを持っていたのですが、地球の重力により個人開発が出来ませんでした。
Difyを使用したAIのlinebotを予定していたのですが、思うように進まず今日に至ります。


### では上のbotは？

[LINE Official Account Manager](https://manager.line.biz/)からMessaging APIを作成します。

あいさつメッセージ（友達追加）と応答メッセージ（発言に対する返答）の設定が、GUIベースで行えます。

- あいさつmessageの設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227398/4e550433-f3d6-8a64-0d28-23255c7a4143.png)

- 応答メッセージの設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227398/b0b2e90f-f5bc-149a-b113-d28d1976e78f.png)

### 応用例
都度応答メッセージを変更するといかにもlinebotを作った風になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227398/0581bdb3-2174-3d68-bf27-6d526a4ae477.png)

### 念のためのQRコード
お化けとは以下から友達になれます！　残念ながら応答は１パターンのみです。どんな返答が来るかは、友だちになってからのお楽しみです。

![102aovkt.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227398/7354b85c-20a4-0873-419c-41963630bf8e.png)


### 補足
あいさつメッセージは2度目の確認が出来ないと思われがちですが、「ブロック」→「ブロック解除」を行うことで、送信を確認することが出来ます。


### 最後に
linebotを作った風に見せるという技術が、誰かに何がしかで役に立つ場面が来ることを祈ります。
幸せの青い鳥は転職でみつかる？転職活動で気づいた現実的な話

### 幸せの青い鳥は、転職先にいるのだろうか？
転職を思い立つタイミングは様々です。私の場合はこんな感じ
* 若いとき：
 1. レガシーシステムに囲まれ、こんなはずじゃない、もっと最新技術に携わりたい！
 2. `「ナニモノ」`かになりたい。自分探しの旅。青い鳥探し。
 3. 会社の名前、規模、見栄

* わりと年がいってから：
 1. ハードワークで気づく、ワークライフバランスの充実
 2. `続「ナニモノ」`かになりたい。自分探しの旅。青い鳥探し。

### 「新しい技術」という誘惑と現実
汎用機と同居しながら開発していた会社から転職した時に思ったことです。
転職すれば新しい技術に触れられる！そう思って飛び込んだ新天地で気づいたことがあります。
実は、私のような`炎上案件救助隊`を急いで募集する会社には、共通点があった気がします。
（自分のアピールも`炎上案件救助隊`であることを推したのもまずかった）

- 前任者が突然辞める(育休や病休のパターンもアリ)、辞めたから慌てて募集している
- 既存システムの保守や改善が山積みのシステムで捨ててしまいたいが、長年の付き合いで切るに切れない、出来るやつは新規案件にぶっ込みたいから古いシステムのお守りor戸締り役を探す
- 採用サイトに載っているような花形プロジェクトの採用ではない

正直に言えば、「こんなはずじゃなかった」と落胆したことも。
採用面接時にもっと詳しく配属部署の状況を確認すべきでした。
でも、これも一つの経験として、次の転職では細かく確認するようになりました。

### 「有名企業」という罠

恥ずかしい告白ですが、最初の転職は完全に会社名で決めました。
当時付き合っていた彼女＆そのご両親に、会社を言うのが少し引け目があったんです。「知名度の高い会社に行けば、きっと全てが良くなる」

**結果：**

- 給与はハードワークのわりに、大幅ダウン
- 実は前職の方が技術レベルが高かった、え、こんなにExcel世界なの？とか
- 結果、古いシステムのお守りでキャリアの上積みはほとんどなし

この経験から学んだのは、会社の知名度、規模より、実際の仕事内容やチームの雰囲気を重視することの大切さです。（当たり前だが・・・。）

### 青い鳥症候群との向き合い方

仕事が詰まってきたとき、辛いパターンに入るたび、これを越えたら転職する！
どこかに理想の職場があるんじゃないかと考えてしまいます。
完璧な環境、理解のある上司、最新技術、高給、ワークライフバランス...。
でも、本当にそんな天国はあるのでしょうか？

**現実的な考え方：**

- 完璧な職場は存在しないかもしれない
- でも、自分にとってのベストな環境は確実に存在する
- 現状の不満や不安から逃げるための転職は慎重に

### ワークライフバランスの確保

仕事とプライベートのバランスを考慮した転職の重要性を痛感しています。
過去には、立場上の変な？責任感から
娘が入院している時でも仕事に行くことがありました。冷静になればダメじゃん、人間的に。
そう思うようになり、ワークライフバランスを重視するようになりました。

冷静な判断が壊れたこんな状況は、普通じゃないです。でも、このジャッジができてなかった。
いまは、家庭やプライベートを大切にしながら、仕事に取り組む環境を選びたいと考えています。

### 長い目でのキャリアパスの明確化

色々なところで長期的なキャリア目標を設定することの重要性について書いていますが、実際には目標が定まらんなぁと思うこともあります。
昔はロールモデルになるような人が現れて、その人に付いていけば自分もナニモノかになれると考えてました。

現実的には、そんなばっちり、自分の目標、憧れな人は現れません（現れなかった・・・）。ただ、ロールモデルがいない中で、Aさん、Bさん、Cさんのような様々な役割を組み合わせたポジションに就きたいという漠然とした目標を持つようになりました。
キャリアパスは一つに絞るのではなく、自分の興味やスキルに応じて柔軟に考えることが大切だと感じています。

### 定期的な経歴書の更新とキャリアの見直し

1年に1度くらいは経歴書を更新し、次のキャリアについて考えるタイミングを持つことが重要だと感じています。
理想としては、第3者的な人に現在どんな旬な技術が求められているのか、また自分の年代では、どのような立場の人材が求められているのかについて指摘してもらえる形に持っていきたいと思います。

そういう中では各企業の人事担当者がレジュメを見てくれる、**転職ドラフト**を利用してキャリアの棚卸を行うのも非常に有効です。転職ドラフトは、スタートアップ企業、メガスタートアップ企業が、しっかりレジュメを見たうえで声を掛けてくれるのが自分にとって良かったです。

完璧な職場、青い鳥は見つからないかもしれません。
でも、自分の経験と技術を活かせる場所、さらに成長できる環境は必ず存在するはずです。
大切なのは、焦らず、でも妥協せず、自分に合った場所を見つけることなのかもしれません。
本当にあったSPAリプレイスで検索順位が低下した話

この記事は、[クラウドワークス Advent Calendar 2024](https://qiita.com/advent-calendar/2024/crowdworks) シリーズ1の24日目の記事です。
<br>
 # 「検索順位が急降下してます!!!」

![onepiece14_enel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1584967/03c2e387-8c7c-5b1c-9cb5-0c5f854aac03.png)

コンサル会社さんからのそんな連絡で始まったできごとです。


# できごとの背景
僕が開発に携わってる、フリーランスエージェントサービス、「[クラウドワークステック](https://crowdtech.jp/)」のユーザーさんが案件を検索する際に使う[案件一覧ページ](https://crowdtech.jp/job_offers)に関して、モノリスなRailsアプリケーションからSPAにリプレースしました。

そのリリースがあってから1ヶ月後に外部のコンサル会社さんから

 > **「案件一覧ページの検索順位が急降下してます!!!」**

> ・Googleのクローラーは、一般的に3,000ミリ秒（ms）をひとつの閾値として、
　その時点で表示がされているコンテンツをそのぺージのコンテンツとして見るといわれており、
　クラウドワークステックの案件一覧ページを見たところ、2,750ミリ秒のタイミングで「404ページ」として表示されています
→つまり、閾値ギリギリのタイミングまで404ページとして表示をされているのではと考えてます


「これはやばい！」

というわけで上記の報告を受けて、当日にエンジニアが集まって技術的な原因と対応策を考えました。

# 案件一覧ページの検索順位が落ちた原因として、考えられたもの
:::note alert
大きく分けて以下2つの原因がありました。
1. ローディング中の404エラー表示
2. 初期表示速度の低下
:::

### 1. ローディング中の404エラー表示
**▼事実**
- ページローディング中に`404 Not Found`のコンポーネントが挟まる仕様になっていたこと

**▼仮説**
Google公式の情報ではありませんが、「クローラーは通常、ページの読み込みから約3,000ミリ秒（3秒）後にコンテンツを評価する」と言われており、今回の場合、2,750ミリ秒の時点で404エラーページが表示されていたため、Googleがページを「存在しないページ」と誤って認識してしまい、検索順位が落ちたことに繋がったのでは？


### 2. 初期表示速度の低下

**▼事実**
- [ページスピードインサイト](https://pagespeed.web.dev/)でパフォーマンスを計測すると、スマホの初回読み込み速度が5秒以上かかっていた
- React側で動的に変更してるメタタグがクローラーに認識されてない 
  - Reactコンポーネントで動的に変更してる`description`タグ、`canonical_url`が空のサイトとして認識されているのが[ラッコツール](https://rakko.tools/tools/34/)で確認できた 



**▼仮説**
- Reactコンポーネントのレンダリングが完了するまでにクローラーがコンテンツを評価しているため、その間はReactで動的に設定しているメタタグがレンダリングされておらず、結果的に【メタタグが存在しないサイト】として認識されたのでは？ 
  - てか、Reactコンポーネントレンダリング前の空のHTMLファイルをクローラーがコンテンツとして評価しているのでは？ 



# 実際にとった解決策
### 「1. ローディング中の404エラー表示」への対応
- ページローディング中に、「404エラー」テキスト表示のコンポーネントが表示される仕様を撤廃

「404エラー」がクローラーに認識されるよりかは、まだ「ローディング中・・・」だけがクローラーに認識されるほうがマシだよねという結論になりました。

### 「2. 初期表示速度の低下」への対応
**空のHTMLの状態をクローラーが読み取っている**のは、SEO的にかなり悪影響と思い、こちらの対応を急ぎました。

対応としては、

- **APIレスポンスに2時間のキャッシュを設定**

全員のユーザーが案件一覧ページにリクエストした時のスマホでの初期表示速度が5秒以上かかってたのはさすがにイケてなかったので、Fastlyを活用してAPIレスポンスのキャッシュを設定しました。

実際にページスピードインサイトで計測すると
[First Contentful Paint](https://web.dev/articles/fcp?hl=ja)という「ユーザーがアクセスしてから画面にコンテンツの一部が表示されるまでのスピード指標」がスマホでは0.9秒になっています。
この対応によって、初期表示速度が大幅に向上し、特にスマートフォンでの表示速度が大幅に改善されました :ok_hand: 


# 落ち着いてみて、考察
前提として、
1年前からモノリスRails→SPAへのリプレース作業が始まったプロジェクトで、当時僕は違うチームにいて技術的な意思決定には関わっていなかったので、SPAが採用された詳細な背景は分かりませんし、当時のメンバーの判断をリスペクトしてます。

そのうえで振り返ってみると、
SEOで重要なページである案件一覧ページをリプレースする時の技術選定時に初回読み込みが遅くなるCSR(クライアントサイドレンダリング)のSPAをチョイスするのではなく、初回読み込みが高速のSSR(サーバーサイドレンダリング)を採用し、ReactフレームワークのNext.jsなどを用いて、SSRを実現すれば良かったのではと思いました。



▼CSRとSSRの違いについてわかりやすい動画です

https://www.youtube.com/watch?v=QckiJezDS_E&t=1105s



# 参照
https://zenn.dev/shunshimono/articles/2023-04-02_ssr-csr-mpa-spa
2024年にSpring BootアプリケーションをAzure Database for MySQLで開発運用してみた奮闘記　DBREJP編を振り返る

2024年にSpring BootアプリケーションをAzure Database for MySQLで開発運用してみた奮闘記DBREJP編を振り返リます。

あれからいろいろありました。
良いものを作るためにPoC開発へ参加してみたり、
DBリファクタで性能劣化を生み出すチームを止めに掛かったり、
AWS関連でSRE/DBRE/QA/SET (Software Engineer in Test)的なことを嗜んだりしておりました。

Oracle移転のお手伝いで、テーブル一覧を見るのにdescコマンドを打って関係者に🐬MySQL使いだとバレた🐬時は絶望的でした。

4年前のネタを持ち越すのもどうかと思いましたが、このお仕事数年ものの構想があり、2024年に良い知らせを受け取れました。DBREとして勝手に始めた活動に大きな穴はなかったと自負していますし、事業満足度はかなり高いようです。

ここまでやってこられたのは運用に強いマネジメントのおかげです。DBREや継続的開発にノウハウが少ないチームだったので、最後の半年でじっくり運用検討に回った甲斐がありました。

2020年の記事はこちらです。
[Spring Boot アプリケーションをMySQLで開発運用してみた奮闘記 DBREJP編](https://qiita.com/zoosm3/items/c177c35d967d45a88813)

特に見直すとしたら、スキーマ変更はインクリメンタルに行えるよう、アプリケーションのテストを整備したほうが良いかなというくらいです。それ以外は2024年でも十分に読める内容だと思います。

それではhappy holidays!
オーディオプレイヤーを作る DAY6

## はじめに
Pythonを使ったオーディオプレイヤーの実装過程を順次投稿しています。
前回までの進捗は以下の通りです。

https://qiita.com/Jun-JP/items/ba0e131fb27f4e0e9031

https://qiita.com/Jun-JP/items/faa2e86b158d60db34ab

https://qiita.com/Jun-JP/items/365ee46ea6aeef6aa0b2

https://qiita.com/Jun-JP/items/02660126c5d15d3375c7

https://qiita.com/Jun-JP/items/cf5002a66a485011c59d

## 今回実装した内容

* GUI
    * サイドメニュー
        * ファイル／フォルダ読み込み
        * ファイル／ファイル一覧表示の切り替え
        * 波形表示のオンオフ
    * 歌詞表示
* 機能
    * フォルダ読み込み
    * 歌詞の表示
    * 波形表示のオンオフ

## ソースコード

https://github.com/junpiyo/Simple-Audio-Player-with-Python/tree/main/Day6

##  環境

Windows11
Python3.12.7

## 動作イメージ
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483587/83901a2e-ccaf-ee18-730e-5266f75fd2f9.gif
 width=80%>

## 備考
* オーディオファイルはWAVとMP3だけに対応
    * 他のフォーマットは次回以降に対応
* CTkTableが重い。cellの数が100を超えるような表を、widgetを並べて作るとものすごい重い。

## おわりに
次回に続きます。
Qiitaの作法やソースコードに関するアドバイス、質問などがありましたらコメント欄までお願いします。
Fusionで点から面に対する垂直軸を作成する

面に垂直な軸を生やしたい！そんな時は

「構築」から「点の位置で面に垂直な軸」を選び、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124670/e70a0d79-7a73-aa7f-ca63-1f8392a5ffbb.png)

点と面を選択すると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124670/cf168ada-b16a-5053-9185-fd93ac825fd3.png)


軸が作れます。
面や軸を作りたいときは構築の中を見るといいかもしれないです。

以上！
LaTeXで図を並べる

## はじめに

この記事では、[subcaptionというLaTeXのpackage](https://ctan.org/pkg/subcaption)のPackage documentationを読みます。

そこにあった一部の例を列挙することにします。

## 前提

新しいバージョンのPackageでは、captionパッケージをロードする必要は**ありません**。
もしロードが必要なら、必ずsubcaptionパッケージの**前に**ロードする必要があります。
captionパッケージへのオプションは、`\captionsetup`コマンドで可能だと思います。まだ確かめていない

> Starting with version 1.4 the subcaption package requires at least version 3.1 of the caption package and loads it automatically. (Older versions of the subcaption package have required exactly the version of the caption package which was released with it.) If you need to use a specific version of the caption package you need to load it before the subcaption package


## subcaptionboxを用いる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533445/762ed488-a509-82a6-1ebf-d2c9f8fcb110.png)


```La
\begin{figure}
\centering
    \subcaptionbox{A cat\label{cat}}[.4\textwidth]{\includegraphics{cat}}
    \subcaptionbox{An elephant\label{elephant}}[.4\textwidth]{\includegraphics{elephant}}
    \caption{Two animals}\label{animals}
\end{figure}
```


## captionboxを用いる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533445/ac85144c-8480-4193-3f27-318588abde3e.png)

```LaTeX
\begin{figure}
    \centering
    \captionbox{A cat\label{cat}}
    [.4\textwidth]{\includegraphics{cat}}%
    \captionbox{An elephant\label{elephant}}
    [.4\textwidth]{\includegraphics{elephant}}
\end{figure}
```


## subcaptionblockを用いる

こっちは、TeXLive 2022以降を使っているユーザ向けになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533445/3ea5c85f-a227-19e0-468b-fd9285ea9916.png)

```LaTeX
\begin{figure}
    \centering
    \begin{subcaptionblock}{.4\textwidth}
        \centering
        \includegraphics{cat}
        \caption{A cat}\label{cat}
    \end{subcaptionblock}%
    \begin{subcaptionblock}{.4\textwidth}
        \centering
        \includegraphics{elephant}
        \caption{An elephant}\label{elephant}
    \end{subcaptionblock}%
    \caption{Two animals}\label{animals}
\end{figure}
```
たった1つの習慣でプログラミングの勉強効率を2.0倍にする方法なのだ！

ずんだもんなのだ。
今日は、プログラミング学習を効率的に進める方法を教えるのだ。

「プログラミングの勉強が思うように進まない...」
「用語の意味がよくわからなくて困っているのだ...」
そんな悩みを持っている人は多いのだ！

でも大丈夫なのだ！
今日は、**たった1つの習慣で勉強効率が2倍になる方法**を紹介するのだ。

その方法とは...**プログラミング用語を覚えること**なのだ！
**要は暗記なのだ！**

...

**もっと魔法のような別の勉強を期待していたら、申し訳ないのだ。**
でも、そんな魔法の勉強方法は無いのだ！

甘いマーケティングの言葉に騙されてはいけないのだ。
動画を見るだけでプログラミングができるようになるとか、そんなことは無いのだ。

「**苦しみながら暗記をする**」
これが辛いけど、一番実力が付く勉強法なのだ！

## なぜ用語を覚えることが大切なのだ？


プログラミングの勉強中、こんな経験はないのだ？

- 「この単語の意味がわからないから、また調べないと...」
- 「エラーメッセージの英語が読めない...」
- 「ドキュメントを読んでもチンプンカンプン...」

これらの問題は、**基本的な用語を知らない**ことが原因なのだ！

用語を知らないと
1. 勉強中に何度も検索して時間を無駄にするのだ
2. 教材の内容が理解できずに挫折してしまうのだ
3. エラーの解決に時間がかかってしまうのだ

だから、最初に用語をしっかり覚えることが大切なのだ！


## 用語を覚えるとどんないいことがあるのだ？

プログラミングでよく使う用語を暗記すると、こんなメリットがあるのだ。

### 1.**学習スピードが上がる**のだ
   - 調べる時間が減るのだ
   - 教材の内容がスッと頭に入るのだ
   - 新しい概念も理解しやすくなるのだ

### 2.**自信がつく**のだ
   - エラーメッセージが読めるようになるのだ
   - ドキュメントが理解できるのだ
   - 他の人との会話についていけるのだ

### 3.**応用力が身につく**のだ
   - 似た概念を結びつけられるのだ
   - 自分で問題を解決できるのだ
   - コードの意図が読めるようになるのだ

「**プログラミングは暗記しなくていい**」なんていう人もいるけど、
基本的な用語や単語は頭に入れて、パッと答えられるようにしておかないと、**普通に時間の無駄なのだ。**

もちろん辛いけど、他の人よりも効率的にプログラミングを身につけるには、それぐらいの努力は必要なのだ。

## 「プログラミングは暗記しちゃダメ」は嘘なのだ

よく「**プログラミングは暗記じゃない**」って言われるのだ。
でもそれは嘘なのだ！

確かに
- 全てのコードを丸暗記する必要はないのだ
- 考え方を理解することは大切なのだ
- コピペだけでは成長できないのだ

でも、**基本的な用語は暗記が必要なのだ！**

それは、こんな理由があるのだ。

### 1.**用語を知らないと考え方も理解できない**のだ
   - 説明を理解できないのだ
   - 概念が頭に入らないのだ
   - 応用もできないのだ

### 2.**開発効率が落ちる**のだ
   - 検索に時間を取られるのだ
   - コードが書けないのだ
   - エラーも直せないのだ

### 3.**学習のモチベーションが下がる**のだ
   - 挫折しやすくなるのだ
   - 自信が持てないのだ
   - 楽しくなくなるのだ

だから、最初は基本用語をしっかり覚えた方が効率的なのだ！

### **暗記は嫌いだからやりたくない？**

**暗記のような辛い努力はしたくない。**
それは僕たち人間が共通で持っている本能的な考えなのだ。
ずんだもんも、その気持ちはよくわかるのだ。

**でも気をつけるのだ。**
金儲けが上手なスクールはそんな学習者の気持ちを利用し、「暗記は不要」と謳い集客することで、楽をしたい初学者から数十万もの費用を巻き上げているのだ。

だから、**楽をしたいという考えは危ないのだ。**
**そうやって楽をしても、大したエンジニアになれないのだ。**

## 効率的に用語を覚えるコツなのだ！

用語を覚えるには、こんな方法がおすすめなのだ。

### 1. **毎日少しずつ覚える**のだ
   - 1日5個ずつでも十分なのだ
   - 無理なく続けることが大切なのだ

### 2. **実際に使ってみる**のだ
   - サンプルコードを書いてみるのだ
   - 友達と話してみるのだ
   - ブログに書いてみるのだ

### 3. **定期的に復習する**のだ
   - テストで確認するのだ
   - 忘れた頃に見直すのだ
   - 使う機会を作るのだ

## プログラミング単語帳を使うと便利なのだ！

効率的に用語を覚えるなら、「プログラミング単語帳」というサービスがおすすめなのだ！

このアプリの良いところは

### 1. **必要な用語が全部入っている**のだ
   - レベル別に分かれているのだ
   - 重要な用語が厳選されているのだ

### 2. **サンプルコードですぐ理解できる**のだ
   - 実際の使い方がわかるのだ
   - イメージがつかみやすいのだ

### 3. **テスト機能で復習できる**のだ
   - 楽しく覚えられるのだ
   - 定着度がわかるのだ

無料でダウンロードできるからまず使ってみるのだ。
https://apps.apple.com/jp/app/id6470341059

## プログラミングの用語を覚えて効率アップなのだ！

プログラミングの勉強で一番大切なのは、**基礎をしっかり固めること**なのだ！

そのために
- 毎日少しずつ用語を覚えるのだ
- プログラミング単語帳を活用するのだ
- 継続することが大切なのだ

これを続ければ、**きっと素晴らしいエンジニアになれる**のだ！

さあ、今日から単語学習を始めてみるのだ！
プログラミングがどんどん楽しくなっていくはずなのだ！

それでは、頑張るのだ！
42tokyoに入学してから変わったこと

こんにちは。
42tokyoアドベントカレンダー2024の24日担当のsomukaidです。
42tokyoに入学したのは今年2024年4月。
Piscineを受けたのが2024年1月でした。
1年経ちましたね。
以前よりコードはたくさんの行を書いても理解出来るようになったかな、と思います。
ただ42tokyoの本科生って、めっちゃコーディングがスゴいイメージがあって、まだ完成形にはいけてないです。ただいま成長中です。

さて、アドベントカレンダーですが、42に入学してから変わったことについて、書いていきたいと思いました。

- コードを書いている時間が長くなった
- エラーチェックを(ほんの少し)やるようになった
- 最初は難易度が高そうだなと思っても、少しずつ完成させることができるようになった
- コードを見てもらうのが楽しくなってきた
- 楽しい場所が一つ増えた

## コードを書いている時間が長くなった

42入学前からC言語の勉強をずっとしてました。理由についてはIPAの基本情報技術者の試験対策のためでした。(今は違うのよね)
https://www.ipa.go.jp/shiken/kubun/fe.html
コードの勉強はアルゴ式でやりました。勉強してた時は、1日1問ずつ取り組みました。(過去に本科生にここのサイトで勉強するといいよ、と教えてもらったので)
https://algo-method.com/
さて、42でPiscineを受けてから、1日1問のペースでは解けない問題も出てきました。
ここにくると1日1関数を作成だったり、githubに1日1commitだったりのペースになってきます。
42では週に35時間ほどのコミットが目安になっているようで、毎日コツコツとコードを書き続けていくのが、私のやり方に合ってるようです。
https://42tokyo.jp/
コードに向き合う時間も長くなってきました。つまりは他の趣味の時間が減った、とも意味します(涙)
他の時間を削ってでも続けるには色々と苦労もあるのですが、私は42のプログラミングに取り組んでいる時間が結構好きなで続けていけるようです。(目安時間には遠く及ばないけどね)

## エラーハンドリングを(ほんの少し)やるようになった

これ、語弊があるので説明すると42ではエラーハンドリングがっちりやります！
やるようになった、というのは自分の中の気持ちです。エラーハンドリングは面倒くさいし、コードは長くなるし、ああっ！もう誰だ！こんなのハンドリングさせようとしたやつ！とか思うわけです。
実際、エラーのことなど考えなければ最小限のコードで動き、かつ自分は納得できるプログラムが生まれるわけです。
特に、入力を通常ではあり得ない値を入れてそれでエラーが起きてハンドリングできてないってやつ。
プログラミング=ゲームの考えがある私にとってエラーは「裏ワザ」なわけですよ。
裏ワザなんだから、いいじゃん。裏ワザでバグったらバグらせた本人のせい、って感覚ですね。(ちゃんとこういう設計です。って言えればこれでいいんだけどね、設計考えてないから説明できないの)

そんな私でもエラーハンドリングを考えるようになったのは、42のおかげでしょう。言いたくはないが、ありがとう！Thank you!
エラーを一つ一つ潰していったり、そういうのを続けると最初から、ここはハンドリングしようと思えるようになりました。
これが設計いうものか…
というわけでエラーハンドリングなんかいらない！と思ってるこの記事を読んだアナタ、是非とも入学をオススメします。

## 最初は難易度が高そうだなと思っても、少しずつ完成させることができるようになった

42には
うーん絶対できんわ。無理無理
と思う課題もあったりします(諸説あり)
それを解くために調べたり、聞いたり、何度もトライしてやっていくのですが、この内、少しずつ完成させる、ということについて話します。



多くのプログラミング言語がそうなってると思いますが、ソースコードって分割して書いていける特徴があります。
参考書にも書いてありますね、「何度も同じ処理をするところは関数にして再利用しましょう」みたいなことが。
プログラミング初めての頃はよくわからんかったんですよ。なんで分割するのかな、最初の関数の中に全部書いちゃえばいいじゃん、とか思ってました。
今ならわかります。だんだん大きなプログラムを作っていくと、分割しなかったソースコードが問題ではなく、自分の記憶の限界(メモリ不足)が問題だったことに。
コードを長く書き続けていくと、最初の方を忘れます。(普通の42の本科生は忘れないのかもしれないが)
コツコツとコード書く私に出来ることは「これを作ったらこれより以前のことは考えなくていい」という関数を作るしかなかったのです。
そしてそれを繰り返すことで完成に近づくこともわかったのです。
つまり、難易度でつまずくより早く記憶が持たなくなるため、目の前の簡単な関数を積み上げていく方が実は確実なのでは、ということに気付き、やっぱりコツコツとやっています。

## コードを見てもらうのが楽しくなってきた
個人的に42といえばコードレビューです。ああ、なんて素敵な♪
コードレビューですが褒めてもらうのは嬉しいです！指摘されると苦しいです。よって永遠に誉めてくれるレビューがいいのですが、人生そればかりではありません。(人生だから)
指摘を苦しいと感じない時は、時間に余裕があるときなんだよな。焦ってしまうともう人の話を聞くことができなくなっちゃうのですよね。
レビューを行って、ブラッシュアップが出来るのが一番いいなぁと思います。
42に入って以来、コード以外にも、別の場面で自分の作った文章を確認してもらうときなど、なんだか楽しくなってきた気がします。
これは思ってもなかった副産物であると思います！

## 楽しい場所が一つ増えた
42のおかげで人生楽しく過ごしております。プログラミングが大きな意味を持つ環境って今までなくて、こんなにプログラミングしてて楽しいなと思えるのは幸せだなと思います。
色んな人に出会えます。
とても充実しています。
とはいえ、いつまでも続きはしないので、今はコードを書き続けたいと思います。
Biomeのlintに怒られた書き方ランキング

eslintからBiomeに変えてlintを走らせた時に怒られた記述方法ランキングです😿

## 第一位: noNonNullAssertion (84箇所)
nullを`!`で握りつぶすな

https://biomejs.dev/ja/linter/rules/no-non-null-assertion/

`useRef`で`someRef.current!.value`としているところが多く、ダントツでありました。すべて修正する時間が惜しかったので設定で`off`にしました


## 第二位: noArrayIndexKey(8箇所)
itemのkeyにindexを使うな

https://biomejs.dev/ja/linter/rules/no-array-index-key/

keyを一意にするため、安易にkeyにindexをする人への対策っぽいですね
自分も漏れなく引っかかりました…なんとkeyの文字列にindexを含むのもinvalid:x:
ただ、これはこちらの書き方、データ構造次第で回避できるので、これからのコーディングに活かせると思いました

## 第三位: noUselessElse(5箇所)
早期リターンされている場合のelseは不要

https://biomejs.dev/ja/linter/rules/no-useless-else/

早期リターンしている場合はelseが不要だというlintルールです。正直好みな気がします
```javascript
if (isWrong) {
  throw new Error('error.')
} else if (isInvalid) {
  return {message: "invalid"}
} else if (isCorrect) {
  return {message: "success"}
}
```
上記のコードの場合、elseが全部不要で、isCorrectのところはifがいらないので　下記のようになります
```javascript
if (isWrong) {
  throw new Error('error.')
} 
if (isInvalid) {
  return {message: "invalid"}
} 
return {message: "success"}
```



## 第四位: noExtraBooleanCast(4箇所)
過剰にBoolean Castするな
```diff_javascript
- if(!!inputValue) {}
+ if(inputValue) {}
```

https://biomejs.dev/ja/linter/rules/no-extra-boolean-cast/

これはBoolean Castをすべきという言説がありましたし、自分でもそうすべきでは？とは思います
使う場所によって賛否ありそうです

## 第五位: useNodejsImportProtocol(4箇所)
nodejsのモジュールはnode:と明示的に書け

https://biomejs.dev/ja/linter/rules/use-nodejs-import-protocol/

感想： 確かに…


## 番外編: noForEach
forEachは使うな

https://biomejs.dev/ja/linter/rules/no-for-each/

`for (const item of data)`という書き方を知っているのでforEachを使っている意識はなかったです　無意識に使っちゃってました
\* forEachはデバッグしにくいという理由で避けられています
ジャーナルをやってみた


## ジャーナルを行う意味

ジャーナルとは、日々の出来事、思考、感情、アイデアなどを記録する習慣のことを指します。ジャーナルを行うことには以下のようなさまざまな意味とメリットがあります。特に私は、普段の業務が少しずつ難易度が高くなり、やることも多くなってきたため、何をいつまでにやる必要があるのか整理がつかなくなり始めました。仕事だけでなくプライベートの時間でも、自分が何をしたいのか、どんなことを達成したいのかを考えるためにジャーナルを始めました。

### 1. 自己理解を深める

ジャーナルを書くことで、自分自身の感情や思考を振り返る時間を持てます。日々の出来事や自分の反応を書き出すことで、自分の価値観や考え方の癖に気づくことができます。

- **具体的な効果**:
  - 感情のパターンやストレスの要因を把握。
  - 自己成長や課題を明確化。

### 2. ストレスを軽減する

考えや感情を紙に書き出すことで、頭の中の混乱を整理し、感情を外に出すことができます。特にネガティブな感情を言語化することで、気持ちが軽くなることがあります。

- **具体的な効果**:
  - 心理的な負担を減らす。
  - 問題を冷静に見つめ直すきっかけとなる。

### 3. 目標達成を支援する

ジャーナルを使って目標を書き出し、進捗を記録することで、達成へのモチベーションを保つことができます。目標を可視化し、小さな成功を記録することで達成感を得られます。

- **具体的な効果**:
  - 目標の明確化と達成の計画が立てやすくなる。
  - 日々の進捗を追跡して改善点を見つけやすくなる。

### 4. 記憶の整理と保存

日々の出来事や感じたことを記録することで、時間が経ってもその時の自分の状態や経験を振り返ることができます。これにより、忘れてしまいがちな大切な記憶を保持できます。

- **具体的な効果**:
  - 過去の記録を参考に自己改善のヒントを得られる。
  - 特別な出来事や感動を振り返る機会を得られる。

## まとめ
私はジャーナルを毎日は行えていませんが、定期的に時間は確保して行っています。
人によってはデジタルで行っている人もいるでしょうが、私は紙やノートに書くことをおすすめします。普段の業務で永遠とパソコンを眺めているので、デバイスから避ける時間にもなります。思考と行動を連動させるために、紙に書いたほうがいいという意見もあります。（一応タイピングも連動はしている気がしてます…）
継続的に行うことが何より大事だと思います。
Dockerコンテナの起動順の制御

# はじめに
コンテナ間に依存関係がある場合、起動順を制御しないとエラーになるため整理しました。開発環境のためcomposeを想定します。

参考:

https://qiita.com/So1111/items/22a01374b88cbe4ae6e8

# 結論
healthcheckとdepends_onにより制御する。

```yml: compose.yml
services:
  backend:
    ports:
      - "5100:5000"
    health_check:
      test: "curl -f http://localhost:5000 || exit 1"
      interval: 10s
      timeout: 10s
      retires: 3
      start_period: 30s

  frontend:
    depends_on:
      backend:
        condition: service_healthy
```
## healthcheck
### test
ヘルスチェックとして実行するコマンドを指定する。
- localhost:5100はホスト(ローカルマシン)からアクセスするときのURL
- localhost:5000はコンテナ内からアクセスするときのURL
- ヘルスチェックはコンテナ内部の環境を基準に動作するため、コンテナ内部のポート番号(ここでは5000)を使う

### interval
コンテナが動作中の間、ヘルスチェックを繰り返し実行する。この「繰り返し間隔」を指定する(デフォルト: 30s)。

### timeout
ヘルスチェックコマンドを実行し、この時間内に応答がないと「失敗」とみなされる時間を指定する(デフォルト: 30s)。

### retries
ヘルスチェックの失敗が何回連続するとunhealthyと判定するかを指定する(デフォルト: 3)。

### start_period
コンテナが起動してからヘルスチェックを開始するまでの猶予時間を指定する(デフォルト: 0s)。この間に失敗してもカウントされない。
- コンテナが起動してすぐにヘルスチェックを開始すると、アプリケーションがまだ完全に起動していない場合に「失敗」と判定されることがあるため、このような場合に設定する

## depends_on
### condition
コンテナ間通信を可能にし、依存関係を定義する。ここではbackend→frontendの順にコンテナを起動する。
- service_healthyにより対象のコンテナが起動し正常に動作するのを確認してから起動する

# おわりに
Kubernetesもやります。

# 参考文献

https://docs.docker.jp/engine/reference/builder.html#builder-healthcheck

https://docs.docker.jp/compose/compose-file/index.html#healthcheck

https://docs.docker.jp/compose/compose-file/index.html#depends-on

https://gihyo.jp/book/2024/978-4-297-14017-5

https://tech.actindi.net/2022/02/21/083000