OmniAICreator/Qiita-1.07M huggingface dataset:
人工知能を学ぶためのロードマップ：Level０

皆さん、こんにちは。

今日は「人工知能を学ぶためのロードマップ：Level０」について紹介いたします。

![Screenshot 2025-01-05 at 12.05.55 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3507088/45d127aa-f817-4c7a-7804-d37386d8c4ef.png)

# Step 1: 技術に触れる（学習想定時間：1時間）

まずは最新のAI技術に触れて，AIによってどのようなことができるのかを確認してみましょう．
メジャーなサービスを含めいくつか紹介します．

## コンテンツ

・ChatGPT
ChatGPT すでに利用したことがある方が多いかと思いますが、OpenAIが開発・運営する大規模言語モデル（LLM）チャットボットです。LLMでは他にGoogleのGemini、AnthropicのClaude、Mistral AIなどがサービス化しています。これらモデルの返答の違いを確かめてみるのも良いでしょう。

・Midjourney
こちらも有名ですが、同名の組織が開発・運営する画像生成AIです。テキストからの画像生成だけでなく、複数の画像のブレンドや画像によるプロンプトなど、様々な機能が提供されています。長らくDiscord上でのみ利用が可能でしたが、2023年末よりWebサイト上で利用できるようになりました。

・Dream Machine
Luma AIが開発・運営する動画生成AIです。2024年9月時点でOpenAIのSoraなど一部ユーザーしか利用できない動画生成AIが多い中、Dream Machineは誰でも利用することができます。

・Hugging Face Spaces
Hugging Faceは、様々なAIモデルやデータを共有・利用できる、開発者・研究者向けのプラットフォームです。そのSpacesでは、画像生成やLLM、物体検出、キャプショニングなど、様々な分野の最新モデルがWebアプリ化され、動かすことができます。 

・Segment Anything Model 2 (SAM2) 
SAM2はMeta AIが開発したビデオセグメンテーションモデルで、簡単に試せるデモが公開されています。このデモでは、自身の動画をアップロードし、セグメントした物体に対して編集を加えたりすることもできます。
# Step 2: 概要と歴史的背景を学ぶ（学習想定時間：10時間）

人工知能の概要や歴史的背景について学びましょう。以下の本などがおすすめです。

## コンテンツ

・人工知能は人間を超えるか
人工知能とは何かを知りたい場合は、まず読むといいでしょう。

・人工知能のアーキテクトたち
著名な人工知能研究者へのインタビュー集です。網羅的な内容ですが、興味のある研究者から先にピックアップして読んでいくこともできます。

・ディープラーニング　学習する機械　ヤン・ルカン、人工知能を語る
2018年にチューリング賞を受賞した3人のうちの一人であり、Meta AIをリードするヤン・ルカン自身と、それに伴うディープラーニングの歴史を知ることができます。

# Step 3: キーワードの概要や繋がりの理解（学習想定時間：20時間）

人工知能の概要がわかったら、次に現在の人工知能の中心技術である深層学習についての基礎知識を身につけましょう。深層学習は幅の広い分野です。まず大局的にキーワード同士の繋がりなどを理解しておくと、後にそれぞれの理論や技術を効率的に理解することができます。以下の本がおすすめです。

## コンテンツ

・深層学習教科書 ディープラーニング G検定（ジェネラリスト） 公式テキスト
ディープラーニング協会のG検定の公式テキストです。この一冊で機械学習の歴史も含めた基礎知識をカバーすることができます。また、G検定も受験すると良いでしょう。

[参考]
https://weblab.t.u-tokyo.ac.jp/lecture/learning-roadmap/

今日は以上です。

ありがとうございました。
よろしくお願いいたします。
PowerShellでファイル情報を取得

今まで、Windowsのファイル情報をVB6系(VBS)で取得していました。
そろそろVBSが無くなりそうな感じなので、
PowerShellでファイル情報を取得したかったので、やってみた。

ps1ファイルの内容 :

<pre>
# 「$result」にファイルパスを指定
$path = "C:\Users\(who)\Desktop\test.txt"

function getFileInformations([string]$inFullPathFile){
    $path = $inFullPathFile
    $shell = New-Object -COMObject Shell.Application

    # フォルダとファイル名を変数に設定
    $folder = Split-Path $path
    $file = Split-Path $path -Leaf

    $Getfolder = $shell.Namespace($folder)
    $Getfile = $Getfolder.ParseName($file)

    $gotDirectoryName = ""
    $gotName = ""
    $gotLastWriteTime = ""
    $gotLength = ""
    $gotHash = ""

    # ファイルが存在するか確認
    if((Test-Path $path) -eq "True"){
        #ファイルが存在する
        $gotDirectoryName = (Get-ItemProperty $path).DirectoryName
        $gotName = (Get-ItemProperty $path).Name
        $gotLastWriteTime = (Get-ItemProperty $path).LastWriteTime
        $gotLength = (Get-ItemProperty $path).Length

        #MD5のハッシュ値
        $gotHash = (Get-FileHash $path -Algorithm md5).Hash.toLower()
    }

    return $gotDirectoryName , $gotName , $gotLastWriteTime , $gotLength , $gotHash
}

$fileInfo = getFileInformations($path)

Write-host "チェック対象ファイル" = $path
Write-host "取得した項目数" = $fileInfo.Length
Write-host "0 . DirectoryName" = $fileInfo[0]
Write-host "1 . Name" = $fileInfo[1]
Write-host "2 . LastWriteTime" = $fileInfo[2]
Write-host "3 . Length" = $fileInfo[3]
Write-host "4 . gotHash" = $fileInfo[4]
</pre>

実行結果 :

<pre>
PS C:\Users\(who)> C:\Users\(who)\Desktop\test.txt
チェック対象ファイル = C:\Users\(who)\Desktop\test.txt
取得した項目数 = 5
0 . DirectoryName = C:\Users\(who)\Desktop
1 . Name = test.txt
2 . LastWriteTime = 2025/01/04 23:52:54
3 . Length = 1713
4 . gotHash = e3b4c930886dcd81d978c7249b965f7a
</pre>
Rails has_many :throughでできること 

## 読んで欲しい人
- 多対多のリレーションで`has_many :through`使ってるけどいまいち何が便利なのか、何ができるかわかってない人
- 過去の自分
## 例：今回のテーブル設計
- Booksテーブル
- Author_booksテーブル
- Authorsテーブル

本（Book）は複数の著者（Author）を所有することができ、著者（Author）も複数の本（Book）を所有することができる構造だとします。
そして中間テーブルとして`Author_book`を定義して、本と著者の関係性をレコードとして保存します。

Bookモデル
```book.rb
class Book < ApplicationRecord
  has_many :author_books, dependent: :destroy
end
```

Authorモデル
```author.rb
class Author < ApplicationRecord
  has_many :author_books, dependent: :destroy
end
```

AuthorBookモデル
```author_book.rb
class AuthorBook < ApplicationRecord
  belongs_to :author
  belongs_to :book
end
```

### `has_many :through`を追加してみる

BookモデルとAuthorモデルに`has_many :through`を追加してみます。

Bookモデル
```book.rb
class Book < ApplicationRecord
  has_many :author_books, dependent: :destroy
  has_many :authors, through: :author_books
end
```

Authorモデル
```author.rb
class Author < ApplicationRecord
  has_many :author_books, dependent: :destroy
  has_many :books, through: :author_books
end
```

## `has_many :through`でできるようになること

### 関連先の情報を持ってきやすい

`has_many :through`で`through`に指定したテーブルを経由して、関連先の情報を持ってくるのが簡単になります。ショートカット的な

例えば、Bookモデルに紐づいてるAuthorの情報が欲しい時

```ruby
book = Book.find(1)
authors = book.authors
```

これだけで、その本に関連している著者を取得できるようになります。

仮に`has_many :through`がないと下記みたいに書く必要があると思います(もっと良い方法ありそうですが)

```ruby
book = Book.find(1)
author_books = AuthorBook.where(book_id: book.id)
authors = author_books.map { |author_book| Author.find(author_book.author_id) }
```

関連先の情報使いたい時は使った方が良いです

### 中間テーブル作成めっちゃ楽

`has_many :through`を使うと、中間テーブルの作成が楽になります。

例えば、

本（Book）の作成時に、複数の著者（Author）を割り当てたいなぁという時に`books_controller`の`create`はこんな感じでかけます

```books_controller.rb
class BooksController < ApplicationController
  def new
    @book = Book.new
  end

  def create
    @book = Book.new(book_params)
    if @book.save
      redirect_to books_path
    else
      render :new, status: :unprocessable_entity
    end
  end

  private

  def book_param
    # 許可するパタメータにauthors_idsを配列として指定してあげる
    params.expect(book: [:title, :release_on, :price, { author_ids: [] }])
  end
end
```

フォームこんな感じ

```erb
<%= form_with(model: @book, local: true) do |form| %>
  <%= form.label :title %>
  <%= form.text_field :title %>

  <%= form.label :release_on %>
  <%= form.date_select :release_on %>

  <%= form.label :price %>
  <%= form.number_field :price %>

  <%= form.label :authors %>
  <%= form.collection_select :author_ids, Author.all, :id, :name, {}, { multiple: true } %>

  <%= form.submit %>
<% end %>
```

`Author_books`テーブルを明示的にビルドする必要なく、`author_ids`を`book`作成時に渡してあげると、よしなにRailsが作成してくれます。

## 感想

- 今まで中間テーブルをわざわざ作ってから、関連先のレコードを作成してました。ちゃんとRailsガイドにできることが書いてあったので反省してます。

## 参考

https://railsguides.jp/association_basics.html
【Ghostty】アプリにフォーカスがない場合にもホットキーでクイックターミナルを開く方法

Ghosttyの設定ファイルに以下のように追記することでアプリにフォーカスがない場合にもホットキーでクイックターミナルを開けます。

```
keybind = global:ctrl+space=toggle_quick_terminal
```

上記の場合には`ctrl`と`space`の同時押しでクイックターミナルが開きます。

![画面収録 2025-01-05 0.04.45.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/20c4426c-708d-566f-23c9-ddce828804f4.gif)

https://ghostty.org/docs/config/keybind/reference#toggle_quick_terminal
人間のスキルを伸ばすAI活用術：代替から協働へのパラダイムシフト

AI技術の進展により、多くの企業や個人がAIの導入を検討しています。しかし、AIをどのように活用すればよいのか、その方向性に悩んでいる方も多いのではないでしょうか？

この記事では、AIを単なる業務の代替ツールとしてではなく、人間の能力を伸ばすパートナーとして活用する具体的な方法をご紹介します。

## AIとの関わり方で変わる成長の機会

AIとの関わり方には、主に2つのアプローチがあります：

1. 代替アプローチ：人間の作業をAIで置き換えることを目指す
2. 協働アプローチ：AIと人間が相互に学び合いながら成長する

一見すると、代替アプローチの方が効率的に見えるかもしれません。しかし、長期的には以下のような問題が発生する可能性があります：

- 人間のスキルが徐々に失われる
- AIへの依存度が高まり、改善や創意工夫の機会が減少
- 予期せぬ問題への対応力が低下

一方、協働アプローチでは：

- 人間が新しいスキルを習得できる
- AIからのフィードバックで改善のヒントが得られる
- より創造的な仕事に時間を使える

## 効果的な協働のための4つのモデル

AIとの協働には、以下の4つのモデルがあります：

### 1. 支援型モデル
人間が主導し、AIがサポート役として機能します。

**活用例：**
- データ分析での仮説検証
- 企画立案時のアイデア出し
- ドキュメント作成の効率化

**期待される効果：**
- 作業時間の短縮
- より多角的な視点の獲得
- クリエイティブな発想の促進

### 2. 拡張型モデル
人間が方向性を決め、AIが実行を最適化します。

**活用例：**
- レポート作成の効率化
- データの可視化
- コミュニケーション文書の品質向上

**期待される効果：**
- 作業品質の向上
- 試行錯誤の時間短縮
- 新しいアプローチの発見

### 3. 制限型モデル
AIが選択し、人間が実行方法を決定します。

**活用シーン：**
- 品質管理での異常検知
- セキュリティ監査
- コンプライアンスチェック

**導入のポイント：**
- 明確な判断基準の設定
- 人間による最終判断の確保
- 定期的な基準の見直し

### 4. 自動化型モデル
AIが主導的に実行する領域です。

**適用場面：**
- 定型的なデータ処理
- ルーチン作業の自動化
- 標準化された手順の実行

**実装のポイント：**
- 適用範囲の明確な定義
- エラー時の対応フローの整備
- 定期的な結果の検証

## 実践的なAI活用のポイント

### 1. 適切なモデルの選択

業務の特性に応じて、以下の点を考慮しましょう：

- 創造性の必要度
- 標準化の可能性
- リスクの程度
- 求められる判断の質

### 2. 学習機会の創出

AIとの協働から学ぶためのポイント：

- AIの提案内容を理解し、評価する
- 改善点を具体的に特定する
- 新しい使い方を積極的に試す
- 得られた知見を体系的に記録する

### 3. フィードバックの活用

効果的なフィードバックのために：

- 成功した部分の要因分析
- 課題となった点の明確化
- 具体的な改善案の記録
- チーム内での知見の共有

## 具体的な成功事例

実際の企業での活用例を見てみましょう：

1. データ分析チーム
    - AI活用前：手動での基礎的な分析が中心
    - AI活用後：複雑な分析が可能に、チームメンバーの分析スキル向上

2. 開発チーム
    - AI活用前：コーディングとデバッグに多くの時間
    - AI活用後：より創造的な設計に注力可能に

3. カスタマーサポート
    - AI活用前：定型的な対応が多い
    - AI活用後：複雑な案件に時間をかけられるように

## まとめ

AIとの効果的な協働のポイントは：

1. AIを代替ツールではなく学習パートナーとして活用
2. 業務の特性に応じた適切な協働モデルの選択
3. 継続的な学習とフィードバックの実践

より詳しい解説は、[元記事](https://tech.jugoya.ai/blog/2025-01-03-human-augmentation-with-ai)をご参照ください。

## 参考文献

- [IMF (2024) AIが世界経済に与える影響](https://www.imf.org/en/Blogs/Articles/2024/01/14/ai-will-transform-the-global-economy-lets-make-sure-it-benefits-humanity)
- [Harvard Business Review - AIの無人判断に関する考察](https://hbr.org/2022/09/ai-isnt-ready-to-make-unsupervised-decisions)
- [Dégallier-Rochat et al. (2022) 人間とAIの協働に関する研究](https://doi.org/10.3389/frobt.2022.997386)
UTM上のArch LinuxにGnomeをインストールしてVNC接続（Over SSH）するまで

# 筆者について

- もうすぐ卒業の高校３年生（もはや帰る気なさそう）

# 本編

前々回の記事でProxmox上にArch LinuxのVMを建てたと書いたのですが、実は練習がてらその時UTM上にもAarch64のArch Linuxを立てていました（だから記事では二つとも書いてあったのです。ここでおそらくみなさん疑問に思うのは、「なんでVNC接続？」だと思います。それは、将来的にはGUIアプリのビルド検証機として使ってみたいからです。ということで、今回僕はVNC接続をできるように設定していきたいと思います。

## VNC接続をする腕の問題

VNC接続をする腕の問題が、セキュリティの確保です。具体的に、僕は現在Macbookを使っているのですが、ここからだとVNC接続をしてもMacのリモート接続とはセキュリティタイプが違うのでセキュリティが確保されません。

https://blog.soracom.com/ja-jp/2021/08/16/best-practice-for-vnc-with-data-encrypt/

ということで、今回これを解決するために使うのがSSHトンネルです。要するにセキュアなSSHトンネルを作った中にノンセキュアのVNC接続を通すということですね！今回は以下の記事を参考にさせていただきました。

https://qiita.com/letian/items/ea6bebe7ebb46bff84e9

ということで、早速インストールしていきます。

## 前準備

まずはデスクトップ環境をインストールしていきましょう。ちなみに、Arch LinuxのAarch64版はCosmicがないですので、なくなくGnomeをインストールしていきます。

```bash
sudo pacman -S gnome
sudo systemctl enable gdm
sudo systemctl start gdm
```

また、ついでにSSHのサービスもスタートしておきましょう。

```bash
sudo systemctl enable sshd
sudo systemctl start sshd
```

## Tiger VNCのインストール

なんとありがたいことにTiger VNCのインストール方法はArch Linuxの公式ホームページに書かれています。これを参考に途中まで続けていきましょう。

https://wiki.archlinux.jp/index.php/TigerVNC#vncserver_.E3.82.92.E3.83.90.E3.83.BC.E3.83.81.E3.83.A3.E3.83.AB.28.E3.83.98.E3.83.83.E3.83.89.E3.83.AC.E3.82.B9.29.E3.82.BB.E3.83.83.E3.82.B7.E3.83.A7.E3.83.B3.E3.81.A7.E8.B5.B7.E5.8B.95.E3.81.99.E3.82.8B

さて、とりあえずインストールしていきましょう。

```bash
sudo pacman -S tigervnc
```

まずはユーザーの設定をしましょう。まずは、`vncpasswd`でパスワードの設定をします。

```bash
vncpasswd
```

続いて、ユーザーの設定をしていきましょう。`/etc/tigervnc/vncserver.users`を編集します。

```diff_config:/etc/tigervnc/vncserver.users
# TigerVNC User assignment
#
# This file assigns users to specific VNC display numbers.
# The syntax is <display>=<username>. E.g.:
#
+ :2=user # ユーザー名は適宜変更してください。また、ディスプレイナンバーは好きになさってください。
```

ここで、もう先ほどのガイドは使わなくなります。というのも、Gnomeは最近ずっとWaylandを使っているので、Xorgで動いているGnomeを使う必要があるんですよね。ということで、その設定をしていきたいと思います。

まずは、ホームディレクトリ（`~/`）に`.xinitrc`を作って編集します。

```config:.xinitrc
export XDG_SESSION_TYPE=x11
export GDK_BACKEND=x11
exec gnome-session
```

ここまで来たらあとはスタートできるのですが、GUIでログインしているままだと使えません。ので、まずはGUIからログアウトしてください。次に、SSHからログインして次のコマンドを入力します。

```bash
vncserver :2
```

そしたらこれで接続できる状態になっていますので、画面共有のアプリから接続しましょう。URIは`VMのIP:(5900+ディスプレイナンバー）`、パスワードは先ほど設定したものです。そしたら、下のように接続できるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583428/25d62b30-6278-b0e4-78dc-6b656ee18bf3.png)

さて、今回の本題はこれをSSHトンネルかで行うことです。やっていきましょう。ちなみに、VNCの接続ポートを5902としています。

```bash
ssh -L 5902:localhost:5902 user@ip
```

これで、SSHトンネルを使って接続することができます。

# 最後に

今回VNCを使ってみましたが、はっきり言ってめっちゃめんどくさいですね。Cosmicがまだまだ実力じゃないことも考慮すると、GnomeのRDP接続を使う方が現実的な気がします。
VSCodeのArduino開発で早速躓いた件

VSCodeで開発をしていたが早速「#include」のところで、つまづきました。。。

# どうなった？
#includeのところで波々線が・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/7effa473-9bbb-5bf0-9800-0bd558edce10.png)

どうもうまくライブラリーを読み込んでいないみたい。

# 対処
ファイル＞ユーザー設定＞設定　を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/08befdf5-84ad-5be2-1192-6e45ad20b4e7.png)

「c_cpp.default.browse.path」のところに
・C:\Users\ユーザー名\AppData\Local\Arduino15\libraries
・C:\Users\ユーザー名\AppData\Local\Arduino15\packages

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/f4cf820b-a3f2-6007-1ea0-63d70f525fb0.png)

これで無事に問題の箇所がなくなりました。
AWS Certified Cloud Practitioner (CLF-C02) 合格体験記

## 🎉 試験結果
- **試験日**: 2024/11/11  
- **スコア**: 743/1000  
- **合格ライン**: 700/1000  
- **結果**: 合格 🎉  

## 🕒 試験準備期間
- **期間**: 約2週間（毎日1～2時間程度学習）

## 📚 使用した教材・リソース
1. **YouTube**  
   - [AWS資格　対策講座](https://www.youtube.com/@AWS_course/playlists)さんの動画を視聴し基礎知識をインプットしました。
   - 無駄な説明がなく、図を用いて説明していたのでわかりやすく、動画が細かく別れているためスキマ時間を利用しやすかったのでおすすめです。
   
2. **模擬試験**  
   - Udemyの[【CLF-C02版】この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集（6回分390問）](https://www.udemy.com/course/aws-4260/?couponCode=NEWYEARCAREERJP)を使用。問題演習を繰り返し行い、出題形式に慣れました。  
   - 特に間違えた問題は解説を熟読して理解を深めるようにしました。
   - 本番試験よりやや難しかった印象です。

3. **その他の参考リソース**  
   - 特にありません。Udemyの問題集が優秀すぎたので他の参考書等を使用しなくて済みました。

## ✏️ 学習内容
### 1. 基本概念の理解
- YouTubeの動画をひたすら視聴し主要サービスの理解に努めました。この段階では覚えるのではなくなんとなくイメージできるレベルまでに収めました。

### 2. 問題演習
- Udemyの問題集をひたすら解きまくりました。各模擬問題で9割近い正答率を出せるまで反復しました。
- 問題と答えを覚えるのではなく、なぜこの答えになるのかを意識して取り組みました。

## 📝 試験中の感想
- 時間配分は問題なし。試験時間の中で、見直しも含めて余裕を持って終えることができました。
- Udemyの問題集と似たような問題が3割近く出題された気がします。

## 💡 所感・反省点
### 所感
- AWSの基本的なサービスの特徴や用途を把握していれば大部分の問題に対応可能。
- 結論、Udemyの問題集やりまくれば受かる。特にひねりのある問題は出題されなかったので、落ち着いて解けば誰でも受かると思います。

### 反省点
- もう少し高得点で合格したかった...
- ハンズオンで少し学習したほうが良かったかもしれない。

## 📆 次の目標
- AWS Certified Solutions Architect – Associate (SAA-C03)の取得を目指して、次はアーキテクチャ設計の学習を進める予定です。
macbook Finder 便利な機能　[システムデータのゴミ掃除]

macbook でシステムデータが70GBくらいあった時に調べて使った機能

備忘録．多分知ってる人多い．

shift+command+.  隠れファイルの表示/非表示
shift+command+G　パスの探索　/Users/users/Library/cash あたりは不要

表示＜表示オプション(command+J)＜すべてのサイズを計算　　これ大事

全てのサイズ計算をデフォルトにして隠れファイル表示ONにしてMachintosh HDから順に開いていくと大きいファイルが見つかった．
ルートファイルの中身を確認

## はじめに
この記事では、Railsのrouteファイルを確認した際に理解が難しかった部分について調べた内容をまとめます。特に、認証機能の設定、ルーティングの名前空間、モックページ、ELB（Elastic LoadBalancer）によるヘルスチェックについてまとめていきます。

:::note info 
#### この記事で調べたこと
- 認証設定用gemのdevice
- namespaceとscopeの違い
- モックページ
- ELBヘルスチェックの仕組み
:::


## device

```ruby
devise_for :admin_users, controllers: {
  sessions:  'admin_users/sessions',
  passwords: 'admin_users/passwords',
  confirmations: 'admin_users/confirmations',
}
```
DeviceというGemを利用することで、ユーザー認証に関するルートやコントローラを自動で生成してくれます。
### ``device_for``
たとえば、上のように``device_for`` を使うと、``admin_users``というモデルに対応する認証機能を有効にできるようになるらしいです。
そして、``controllers``オプションを使うことで、特定のコントローラをカスタマイズすることができるみたいです。


### ``device_scope``
``device_for``で定義されたルートを拡張またはカスタマイズするための機能
独自のルートを設定し、特定のコントローラやアクションを呼び出すことが出来ます。


## ルートファイルにおけるnamespace / scopeの役割
```ruby
Rails.application.routes.draw do
  namespace :admin do
    # /admin/dashboard で Admin::DashboardController を呼び出す
    get 'dashboard', to: 'dashboard#index'

    # /admin/users で Admin::UsersController を呼び出す
    resources :users, only: [:index, :show, :edit, :update]
  end
end
```


``namespace``
ルートを名前空間でグループ化する
admin_usersやapiなど、名前空間ごとに整理されている

```ruby
Rails.application.routes.draw do
  # /public/products で ProductsController を呼び出す
  scope '/public' do
    resources :products, only: [:index, :show]
  end
end
```
``scope``と``namespace``の違い
- scopeの時は、URLが変わるがファイル構成は変わらない
- namespaceの時は、URLもファイル構成も変わる。クラス名も``「namespace名」::``と変更

## モックページ
```ruby
# モック用のページ
get '/hello', to: 'hello#index'
```
#### モックページとは？
モックページとは**実際のウェブサイトやアプリケーションのデザインや機能を再現した試作的なページのこと**。主に開発や設計の初期段階で、完成のイメージや動作を確認するために作成される。モックページは最終的な製品がどのように見え、どのように動作するかを関係者間で共有し、フィードバックを得るために非常に重要な役割を果たす。

## ELBヘルスチェック
```ruby
# ELBヘルスチェック用
get '/elb', to: 'elb#index'
```

#### ELBヘルスチェックの目的
ヘルスチェックは、**「サーバーがちゃんと元気に働いているか？」** を定期的に確認する仕組みのこと。サーバーが正常に稼働していない場合に、適切に対応することが出来る。

**ELBはElastic Load Balancerの略で**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924509/edf21857-d265-82e5-747a-b38cc4a14863.png)



ELBによる**ヘルスチェック**はサーバー達に **「元気？」** と定期的にリクエストを送るイメージです。

正常に稼働していない場合は、**トラフィックから外す**。
トラフィックから外すというのは、ユーザーからのリクエストをそのサーバーに送らないようにすること。トラフィックとは、ITやネットワークの文脈で、ネットワーク上を流れるデータや通信のことを指します。もっと具体的に言うと、ユーザーが送信したリクエストや、サーバーから返されるレスポンスのことを指します。

ELBの役割はトラフィックの分散で、複数のサーバーにリクエストを分散させることで、サービスの高可用性を確保しています。

そもそもなぜ、サーバーが複数必要になるのかというと、

:::note info
- **高可用性**
    - 1つのサーバーだけでは、故障した時にサービスが止まってしまう
    - 複数のサーバーを用意しておけば、１つがダウンしても他のサーバーがカバーできるので、サービスを継続できる。
- **負荷分散**
    - 複数のサーバーにリクエストを分散させることで、負荷を分散し、処理の効率を上げる
- **スケーラビリティ**
    - 需要が増加した時に、簡単にサーバーの台数を増やして対応できる（スケールアウト）
    - 需要が減れば、不要なサーバーを減らしてコストを削減できる
:::

ELBとサーバーをレストランに例えると、ELBがホストで、サーバーがウェイター。
お客様（トラフィック）が来店すると、ホストは適切なウェイターに案内させます。
この時、忙しかったり、休憩中のウェイターにホストはお客さんを案内させたりはしません。
１人に負担を集中させるようなことはイメージできないと思いますが、これと似た考えです。
【React】MUIのAutocompleteでfreeSoloを使わずに入力されたテキストを残す

## 概要
MUIの[Autocomplete](https://mui.com/material-ui/react-autocomplete/)では、入力したテキストはリストが選択されない場合は、フォーカスを外れると入力内容がクリアされます。テキストを残したい場合に、ドキュメントでは`freeSolo`の設定が紹介されてますがこの設定は個人的に課題を感じ、別の実装方法があるか調べてみたのでそのメモ書きです。

## 前提
* 使用した`mui/material`のバージョンは6.3.1です。

## freeSoloに個人的に感じた課題
* [[Autocomplete] freeSolo prop makes onChange value type become T | string](https://github.com/mui/material-ui/issues/33093)の記事にある通り、`onChange`に入る型にstringが混じります。実際は選択時はoptionで選択した型が入るのですが、上記のバージョンの時点では型判定をしなければいけない状況です。
* Autocompleteのデフォルトでは、optionから選択後にクリアボタンが表示されます。しかしfreeSoloを設定すると、optionから未選択のテキスト入力時にも表示されます。クリアボタンを押したらテキストがクリアされるだけなのですが、optionから選択されたものかどうかが一見して分からないというふうにも感じてしまいます。

## 他の実装方法案
stateで入力されたテキストを管理し、`inputValue`にそのstateを設定することでテキストを残すことができます。
この実装では型にstringが混じることはないし、テキストを入力しただけではクリアボタンが表示されません。

## 実装サンプル
上記の実装案で実装したサンプルは、以下になります。

```react
export const AutoCompleteSample: FC = () => {
  // AutoCompleteの選択内容（型は公式ドキュメントの内容と同様）
  const [selectValue, setSelectValue] = useState<FilmOptionType | null>(null);
  // テキストの入力内容
  const [textValue, setTextValue] = useState<string | null>(null);

  return (
    <>
      <Autocomplete
        options={top100Films} // top100Filmsの内容は公式ドキュメントの内容と同様
        value={selectValue}
        getOptionLabel={(option) => {
          if (typeof option === "string") {
            return option;
          }
          return option.title;
        }}
        onChange={(_, newValue) => {
          setSelectValue(newValue);
          setTextValue(newValue?.title ?? "");
        }}
        inputValue={textValue ?? ""}
        renderInput={(params) => (
          <TextField
            {...params}
            label="Search input"
            onChange={(event) => {
              setTextValue(event.target.value);
            }}
          />
        )}
      />
      <div>
        <div>textValue:{textValue}</div>
        <div>selectValue:{selectValue?.title}</div>
      </div>
    </>
  );
};
```
Self-hosted Runnerを取りやめた話

[OSS "Pelemay Backend" で行っているGitHub Actionsによる自動化事例2023年12月版](https://qiita.com/zacky1972/items/c56da534e391de50f597)で報告していたように，Self-hosted Runnerを用いてmacOSのx86_64とApple Siliconの両方の自動テストを行っていましたが，最近のGitHubの仕様変更に伴い，セキュリティ上の理由でSelf-hosted Runnerの使用が危ぶまれたので，取り急ぎ，中止することにしました．本記事では，その経緯について説明します．

## GitHub Actions

https://github.co.jp/features/actions

> GitHub Actionsを使用すると、ワールドクラスのCI / CDですべてのソフトウェアワークフローを簡単に自動化できます。 GitHubから直接コードをビルド、テスト、デプロイでき、コードレビュー、ブランチ管理、問題のトリアージを希望どおりに機能させます。

GitHubで行ったソースコード変更等のトリガーで，自動テスト等のスクリプトを自動実行できる便利な仕組みです．

## Self-hosted Runner

GitHub Actionsでは，通常，GitHub-hosted Runnerと言って，GitHubが用意するクラウド環境上でスクリプトを自動実行することができるのですが，Self-hosted Runnerを用いると，レポジトリオーナーが用意したローカル環境でスクリプトを自動実行することができます．

## Self-hosted Runnerのセキュリティ上の注意点

公開レポジトリでは，任意のコードを含むPull Requestを送ることができます．したがって，Self-hosted Runnerを運用していると，悪意あるコードを実行してしまう恐れがあります．

## 今まで運用していた方式

[OSS "Pelemay Backend" で行っているGitHub Actionsによる自動化事例2023年12月版](https://qiita.com/zacky1972/items/c56da534e391de50f597)で今まで運用していた方式は次のとおりです．

* `main` ブランチへは `check_by_SHR` ブランチからのみ Pull Request を受け付けるように設定する
* 一般から受け付けた Pull Requestを元にして，`check_by_SHR` ブランチから `main` ブランチへ Pull Request を発行する際には，コードレビューを行い，悪意あるコードが含まれていないことをよく確認するフローとする．
* `main` ブランチへの Pull Request の時に Self-hosted Runnerによる自動テストを実行する

## いつの間にかGitHubの仕様が変わっていた点について

> * `main` ブランチへは `check_by_SHR` ブランチからのみ Pull Request を受け付けるように設定する

これをSetting>Rules>Rulesetsで `main` ブランチのルールを作成し，Restrict branch names を用いて `check_by_SHR` ブランチのみマッチするように設定していたように記憶しているのですが，いつの間にかEnterprise版でのみ利用できることになってしまっていました．

## 検討した結果

私事ですが，今，私が使える研究開発のための予算が年度末のため欠乏している関係で，Enterpriseにすぐに加入することができません．そこで，応急措置として，Self-hosted Runnerの運用自体を取りやめることにしました．
Linux上のVSCodeでC言語プログラムをデバッグする手順メモ

タイトルの通りです。
手順をメモっておきます。
検証した環境はRaspberryPi4Bです。

## 概略

CMakeとかは使わずに、Makefileだけを使います。

概略としては以下の通りです。
- Makefileでデバッグ情報付与オプションを指定する
- launch.json の "program"に、実行可能ファイルのパスを設定する


## 下準備する
 - ソースコード一式とMakefileをまとめるディレクトリを作る
例: ~/develop/hello
 - そのディレクトリに.vscodeディレクトリを作る
 - そのディレクトリにソースコード一式とMakefileを入れておく
 - vscodeを起動する
```
$ mkdir ~/develop/hello
$ cd ~/develop/hello
$ mkdir .vscode
$ code ./
```
## コードとMakefileを書く(.cとか.cppとか)
例として foo.c bar.c をファイル名とします。内容はなんでもいいです。


```Makefile
CC = gcc
OBJECTS = foo.o bar.o

#debugターゲット指定時に、デバッグシンボル付与および最適化なしオプション
debug: CFLAGS= -g -O0

.PHONY: clean debug

hello : $(OBJECTS)
	gcc -o hello $(OBJECTS)

debug : $(OBJECTS)
	gcc -o hello $(OBJECTS)
 
clean:
	rm $(OBJECTS) hello
```

## 一旦makeしてビルドできることを確認する
```
$ make

```

## デバッグシンボルを付与してmakeする
```
$ make debug
```

## VSCodeでデバッグを始めるための操作をする
 - VSCodeのメニュー Run -> Start Debugging (実行->デバッグを開始する)を選択する
 - "launch.json が見つからない"とか、デバッグを開始できない旨のメッセージが表示される
 - そのメッセージに含まれている【launch.json を作成する】旨の選択肢を選ぶ
 - エディタに launch.json の内容が表示される

## launch.jsonを編集する
launch.json の中にある設定項目"program"の横に、デバッグ対象のプログラムの実行可能ファイルのパスを設定する。そのほかの項目はとくに設定する必要はなさそう。
今回生成する実行可能ファイルの名前は"hello"としています。

```launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "C/C++ Runner: Debug Session",
      "type": "cppdbg",
      "request": "launch",
      "args": [],
      "stopAtEntry": false,
      "externalConsole": false,
      "cwd": "/home/pi/develop/hello/",
//=====↓↓↓この部分を変更する↓↓↓=====
      "program": "/home/pi/develop/hello/hello",
//=====↑↑↑この部分を変更する↑↑↑=====
      "MIMode": "gdb",
      "miDebuggerPath": "gdb",
      "setupCommands": [
        {
          "description": "Enable pretty-printing for gdb",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        }
      ]
    }
  ]
}
```
## 気を取り直して、もう一回デバッグを開始する
 - VSCodeのメニュー Run -> Start Debugging (実行->デバッグを開始する)を選択する
 - 今度はデバッグが開始される
 - VSCode右下の"DEBUG"タブにデバッグの進行状況が表示される
 - "TERMINAL"タブで標準入出力の確認ができる

これで、ブレークポイントの設定とか、変数のウォッチとかもできているはず。

以上
今週の学習記録（2024年12月28日～2025年1月4日）

## 🔍 学習内容
- **学習テーマ**: Docker
- **使用した教材**: Udemy講座　【理解して使う！Docker入門＋応用：初心者から実務で使えるスキルが身に付ける】
- **進捗**: セクション9、セクション10　　動画数：73/97

## ✏️ 学んだこと
### 主なポイント
- ホストマシンとコンテナのポートを紐づける方法。
- Dockerネットワークとブリッジネットワークについて。
- Docker Composeを使用した複数コンテナの扱い方。

## 💡 学び・反省点
### 学び
- ホストマシン内にあるコンテナ複数個をまとめたものがDockerネットワークである。Dockerネットワーク間では通信することができない。
- ブリッジネットワークとはコンテナを作成した際にデフォルトで配置されるネットワークのこと。
- Dockerネットワークは自分で作成可能。
- Docker Composeを使用することで多くのコマンド実行を簡略化することができる。
### 反省点
- Docker Composeの概要を理解できても具体的な記述方法がわからないまま勧めてしまい、動画のコードを淡々と写してしまった。
- 1日通して何も学習しない日があった。


## 📆 次週の予定
### 目標
- 簡単で良いのでDocker Composeの記載方法を学習する。
- Dockerの実践的な使用方法を学習する。
- 何も学習しない日を作らない。

### 行動計画
- 引き続きUdemyの講座を進める。
- 疑問点は放置せず必ず腑に落ちるまで調べる。
- QiitaやSNS等で一つでもいいから何かを毎日学ぶ。

## 🏄‍♂️所感
　今週はDockerについてひたすら学習する形で進めました。Udemyの講座がわかりやすく比較的スムーズに進めることができました。現在受講しているUdemyも終盤なので来週で終わらせたいと思います。
　ただ、一日何も学習しないしない日があったため、QiitaやSNS等で5分でもいいので何かを学習する習慣をつ蹴るよう努力したいと思います。
Astro で KaTeX をプリレンダリングする


```bash:インストール
$ npm i katex
```

## KaTeX の SSR

KaTeX には数式表現を HTML 文字列に変換する `katex.renderToString` API が用意されています。

https://katex.org/docs/api#server-side-rendering-or-rendering-to-a-string

以上を用いると、ヘッドレス CMS から返却された HTML など、remark/rehype を用いない場合でも KaTeX をプリレンダリングすることができます。

## 実装

HTML をパースするために `cheerio` を利用します。

https://github.com/cheeriojs/cheerio

```bash:インストール
$ npm i cheerio
```

```ts:初期化
import { load } from "cheerio";

// CMS から返ってきた HTML 文字列で初期化する
let $ = load(html);
```

### レンダリング処理

デリミタ（区切り文字）で囲われた部分の文字列のみレンダリングするようにします。インラインであれば `$`、別行立てには `$$` を用います。

> インラインと別行立てのデリミタ処理がバッティングしてはいけないため、`$$ $$` に囲まれた部分を抽出する正規表現は、`$` にマッチングしないように `[^\$]+` を用います。
> また、先に別行立てをレンダリングすることで、別行立てがインラインとしてレンダリングされることを防ぎます。

```ts:TypeScript
import katex from "katex";

// 先に別行立てをレンダリング
const renderedDisplayText = $.html().replaceAll(/\$\$[^\$]+\$\$/g, (text: string) => {
	return katex.renderToString(text.replaceAll("$", "").replaceAll(/(<br>|<\\br>|<br \/>|&nbsp;|amp;)/g, ""), { output: "html", displayMode: true });
});

// インラインをレンダリング
const renderedText = renderedDisplayText.replaceAll(/\$[^\$]+\$/g, (text: string) => {
  return katex.renderToString(text.replaceAll("$", "").replaceAll(/(<br>|<\\br>|<br \/>|&nbsp;|amp;)/g, ""), { output: "html", displayMode: false });
});
```

### code タグのエスケープ

`<code>` 内のテキストはデリミタとなる `$` が使用される可能性が高く、しかもレンダリングされると困ります。Cheerio を利用して `<code>` でラップされたテキストを取り出し、一時的に保持してレンダリング後に差し戻す処理を実装します。

```ts:TypeScript
// <code> のテキストを抽出
const innerTexts: string[] = [];
$("code").each((_, elm) => {
  innerTexts.push($(elm).text());
  $(elm).text("");
});

/*
 * レンダリング
 */

// 再び初期化
$ = load(renderedText);

// <code>にテキストを差し戻す
$("code").each((idx, elm) => {
	$(elm).text(innerTexts[idx]);
});
```

### HTML のレンダリング

```astro:Astro
---
import "katex/dist/katex.min.css";   // CSS

/*
 * レンダリング
 */

const renderedHtml = $.html();
---

<div set:html={renderedHtml} />
```

## おまけ：CSR による実装

以上の実装は KaTeX の [Auto-render Extension](https://katex.org/docs/autorender) を代わりに使うことで簡単に達成できます。
Astroの場合、Client で 処理する JS は `<script>` 内に記述します。

```astro:src/pages/article/[slug].astro
---
// .....
---
<script>
  import { renderMathInElement } from "katex/dist/contrib/auto-render";

  document.addEventListener("DOMContentLoaded", () => {
    renderMathInElement(document.body, {
      delimiters: [
          { left: '$$', right: '$$', display: true },
          { left: '$', right: '$', display: false },
          { left: '\\(', right: '\\)', display: false },
          { left: '\\[', right: '\\]', display: true },
      ],
      ignoredTags: ["code"],
    });
  });
</script>
```

## Usage

```tex:TeX
$$
\lim_{n \to \infty} \frac{1}{n} \sum_{k=0}^{n-1} f \left( \frac{k}{n} \right) = \int_{0}^{1} f(x) dx
$$
```

```math
\lim_{n \to \infty} \frac{1}{n} \sum_{k=0}^{n-1} f \left( \frac{k}{n} \right) = \int_{0}^{1} f(x) dx
```
技術はどう学べば良いか

## 技術を理解するには本質的な理解をしていかなければならない

技術を学ぶというと、簡単なテクニックで終わってしまうケースが多い。
しかし、理解の本質とは、その仕組みを説明でき、使いどころを自分で
考えられるようになる事です。

そのためには、それぞれの技術が「何者なのか」「なぜ登場したのか」
を押さえる事が重要となっています。

## 要件の多様さと複雑さにより求められる事

なぜ、これらが重要なのか。
それは、近年Web上で提供するサービスによって成り立つビジネスが
増えてきたからです。
これらのビジネスでは、Webシステムがサービスの主体であり、その質が
収益に特化します。

例：Googleのビジネスモデルは、無料の検索サービスを提供し、検索結果に
合わせた広告を提示することで、広告収入を得ます。

また、新たなビジネスの創出のため、これまでになかった新しいサービスが
次々と登場していきます。

このような新事業の立ち上げ期には、提供しようとしたサービスが市場に合っているか
どうか分かりません。

この場合、新たなサービスのためのシステム要件は、千差万別なので、比較的類型化しやすい
業務システムとは違い、要件に応じたシステム構成やアーキテクチャを考える必要があります。

## エンジニアに求められる広がり

このように自由度が大きく広がった裏返しとして、システムインフラとソフトウェアの
設計を一体的に考える必要性が増しました。

特にスタートアップ段階の小規模な組織では、1人のエンジニアが「多能工」として、
多くの領域をカバーせざるおえない事が増えています。

クラウドサービスを含む複数の領域で活躍できる技術を持ち、ビジネス価値の創出に
繋げられるエンジニアは多くないため、希少性から市場価値が高く評価されています。

そのためには、登場した技術を頭の中にある「技術の引き出し」の正しい位置にいかに
早くしまえるようになれるかが重要です。

そのためには、その技術が何者なのか、純粋な技術的背景だけでなく、当時の様々な環境を踏まえた背景、「なぜ登場したのか」を理解する必要があるのです。
npx ts-node --esm 実行時の TypeError [ERR_UNKNOWN_FILE_EXTENSION] の解決方法

## はじめに
batchファイルを
`npx ts-node --esm 'batchファイルのパス'）`
で実行しようとした際に、

``` bash
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for 'batchファイルのパス'
```
というエラーが発生しました。

今回はこちらのエラーの解決方法をご紹介します。

## 環境
Node.js: v22.9.0
ts-node: v10.9.2
TypeScript: v5.6.3

:::note info
ts-node とは？

ts-nodeは、TypeScriptファイルを直接Node.js環境で実行するためのツール。

TypeScriptコードをJavaScriptにコンパイルせずに直接実行可能。
:::

## 解決方法

``` bash
// tsxをインストール
npm install tsx
```

:::note info
tsx とは？

tsxは、Node.js環境でTypeScriptファイルを直接実行するためのモダンなツール。

ts-nodeとの違い:
ESM/CJS間の混在を気にせず実行可能。
:::

tsxをインストール後、
`npx tsx 'batchファイルのパス'`を実行するとbatchファイルが起動する。

## 補足
batchファイル内で環境変数を使用している場合、
`npx tsx -r dotenv/config 'batchファイルのパス'`
というふうに`-r dotenv/config`をコマンドに追加し、コマンド実行時に環境変数を事前に読み込ませる設定が必要です。

:::note warn
VITEを使用している場合、環境変数名の頭に`VITE_`を使用していると思いますが、`npx tsx -r dotenv/config`で環境変数を読み込む場合は環境変数名の頭の`VITE_`があるとエラーになります。

別途`VITE_`がついていない環境変数を追加するなど適宜対応してください。
:::

## まとめ
今回のエラーはNode.jsとts-nodeのバージョンが合わないために起こったエラーでした。

エラー解決の途中でNode.js環境でTypeScriptファイルを直接実行ツールであるts-nodeとよりモダンなツールであるtsxについて学ぶことが出来たので良かったです。
【競技プログラミング】AtCoder Beginner Contest 384_A問題とGo言語

# 会社からの緊急確認

お前、Go言語使えるよな？Goを使えるメンバー探してるからOKって言っておくよ。とのラインが・・・

Go言語は2,3年以上使っていないし、pythonに慣れすぎて、あの厳密な型定義に耐えられない気がする。

とはいえ、昔と違い今はChatGPT様がいるから対して問題じゃないんですよね。（メンバー探しているプロジェクトで生成AI使用禁止などのルールがなければですが）

とりあえず、AtCoderのA問題で確認しておきますか。

# Python

まずは、慣れているPython
```python:ac.py
def main() -> None:
    N,c1,c2 = input().split()
    S = input()

    T = [""] * len(S)

    for i in range(len(S)):
        if S[i] != c1:
            T[i] = c2
        else:
            T[i] = S[i]
    
    print("".join(T))



if __name__ == "__main__":
    main()
```

# Go言語
```go:ac.go
package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    reader := bufio.NewReader(os.Stdin)

    // 入力を読み込む
    var N string
    var c1, c2 string
    fmt.Scan(&N, &c1, &c2)

    S, _ := reader.ReadString('\n')
    
    // 文字列Sの長さを取得
    length := len(S) - 1 // 改行文字を除くため -1

    // 新しいスライスを作成
    T := make([]rune, length)

    for i, char := range S[:length] {
        if string(char) != c1 {
            T[i] = []rune(c2)[0] // c2の最初の文字を代入
        } else {
            T[i] = char // c1の場合はそのまま代入
        }
    }

    // 結果を出力
    fmt.Println(string(T))
}
```

思い出してきた。。。
pythonからGoに移るのって結構手間取るんだった。
付け焼き刃では心もとないな・・・
Goの学習開始時に非常に参考にさせていただいた、UdemyのGoの講座さっと復習した方が良さそうですね。

https://www.udemy.com/course/go-fintech/?couponCode=NEWYEARCAREERJP
ABC387振り返り


あけましておめでとうございます
2025年は緑帯維持を目標に、できればレート1000、入水を目指していきたいです
今年もよろしくお願いします

---

前回の振り返り

https://qiita.com/comet725/items/25a0d30d61c1a289d5e2

今日はABC開催日だったので参加結果を振り返る

https://atcoder.jp/contests/abc387

今週はA,Bの2完(0ペナ)


# A

入力と計算だけ

## ソースコード

今回からerr関数をupdateしました。

```python:main.py
import sys
import os
def rI(): return int(sys.stdin.readline().rstrip())
def rLI(): return list(map(int,sys.stdin.readline().rstrip().split()))
def rI1(): return (int(sys.stdin.readline().rstrip())-1)
def rLI1(): return list(map(lambda a:int(a)-1,sys.stdin.readline().rstrip().split()))
def rS(): return sys.stdin.readline().rstrip()
def rLS(): return list(sys.stdin.readline().rstrip().split())
IS_LOCAL = int(os.getenv("ATCODER", "0"))==0
err = (lambda *args, **kwargs: print(*args, **kwargs, file=sys.stderr)) if IS_LOCAL else (lambda *args, **kwargs: None)

def main():
    
    A, B = rLI()
    print((A+B)**2)
        
if __name__ == '__main__':
    main()

```

# B

内包表記と直積の組み合わせ

該当する値以外をすべて足し合わせる

## ソースコード

```python:main.py
from itertools import product
import sys
import os
def rI(): return int(sys.stdin.readline().rstrip())
def rLI(): return list(map(int,sys.stdin.readline().rstrip().split()))
def rI1(): return (int(sys.stdin.readline().rstrip())-1)
def rLI1(): return list(map(lambda a:int(a)-1,sys.stdin.readline().rstrip().split()))
def rS(): return sys.stdin.readline().rstrip()
def rLS(): return list(sys.stdin.readline().rstrip().split())
IS_LOCAL = int(os.getenv("ATCODER", "0"))==0
err = (lambda *args, **kwargs: print(*args, **kwargs, file=sys.stderr)) if IS_LOCAL else (lambda *args, **kwargs: None)

def main():
    X = rI()
    
    A = [i*j for i,j in product(range(1,10),repeat=2) if i*j != X]
    print(sum(A))
if __name__ == '__main__':
    main()

```

# C

桁数と最大桁の値で直積？

そしてL,Rと一致する桁数、最大桁の値部分だけ具体的に計算しようとしたがうまくいかず

順位表見る限り解いてる人少なそうなのでD問題へ

# D

直前の方向を覚えてそれとは違う方向にBFSしようとしたがWA…

距離のコードの判定が無駄に複雑のままなのが行けなかったかも

## ソースコード

WA: https://atcoder.jp/contests/abc387/submissions/61394747

# E

範囲の大きさに圧倒されて逃亡

# F

与えられた数列でグラフを作りそうと思ったくらい

# G

閉路の判定わからん…

# まとめ

Cが鬼畜でDが微妙にバグってつらい

完全にスランプです助けて😇
【GitHubActions】ローカル実行する方法

## GitHub Actions: ワークフローをローカルで実行する方法

### はじめに

GitHub Actionsのワークフローをサーバー上で実行するたびにコミットするのは面倒な作業です（スキルが発展途上のためやりがち...）
この記事では、[act](https://github.com/nektos/act)を使用してワークフローをローカルで実行する方法を紹介します。

### 準備

actを使用するにはDockerが必要です。
まず、Dockerが稼働していることを確認しましょう。

最近私は [colima](https://github.com/abiosoft/colima?tab=readme-ov-file#colima---container-runtimes-on-macos-and-linux-with-minimal-setup) を利用してDockerを稼働させています。

actのインストールは、さまざまなパッケージマネージャを通じて行うことができます（詳細は[こちら](https://github.com/nektos/act#installation-through-package-managers)）。
インストール後、初回起動時に使用するDockerイメージを選択するように求められます。イメージには軽量なもの（例: node:16-buster-slim）から大型のもの（18GB以上）まであります。作業内容に応じて適切なイメージを選びましょう。

### 実行手順

1. **ワークフローの一覧表示**  
   コマンドプロンプトでリポジトリを開き、以下のコマンドを使用してワークフローとジョブのトリガーを確認します:
   ```bash
   $ act pull_request -l
   ```

2. **ドライランの実行**  
   ワークフローを実行する前に、ドライランを行って問題をチェックできます:
   ```bash
   $ act pull_request -n
   ```

3. **ワークフローの実行**  
   ドライランが問題なければ、以下のコマンドで実際にワークフローを実行します:
   ```bash
   $ act pull_request
   ```
   ワークフローの結果は、GitHub上での実行結果と同様になります。

### 仕組み

actはDockerコンテナを使用してワークフローをローカルで実行することは前述しました。
`.github/workflows/ディレクトリ`内のGitHub Actionsを読み込み、必要なアクションを特定します。
Docker APIを利用して必要なイメージを取得または構築し、実行経路を決定した後、各アクションに対応するコンテナを実行します。

ワークフローでGITHUB_TOKENを使用している場合、個人用アクセストークン（PAT）を提供する必要がありますが、GitHub CLIを使用してトークンを自動的に取得することも可能です。

### さらに詳しく

actの課題の一つは、デフォルトのGitHubホストランナーのイメージが非常に大きいことです。しかし、ほとんどのワークフローではそれほど多くのツールを必要としません。
カスタムDockerイメージを使用することで、ローカルとサーバーでの実行環境をほぼ一致させることができます。詳細は[こちら](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container)をご覧ください。
ABC387をPythonで（A～D）

AtCoder Beginner Contest 387（Promotion of AtCoderJobs）の解答等の速報的まとめ

https://atcoder.jp/contests/abc387



# A問題
https://atcoder.jp/contests/abc387/tasks/abc387_a

問題文の通りに計算する
```python:A
print(sum(map(int, input().split()))**2)
```
# B問題
https://atcoder.jp/contests/abc387/tasks/abc387_b

$1 \times 1$から$9 \times 9$まで全部調べる
```python:B
x = int(input())

ans = 0
for i in range(1, 10):
    for j in range(1, 10):
        if i * j != x:
            ans += i * j

print(ans)
```
# C問題
https://atcoder.jp/contests/abc387/tasks/abc387_c

calc(x)でx以下の蛇数をもとめられるようにしたらcalc(R) - calc(L - 1)で出来ると考えた。
ただ、calcがうまくできなかった。

# D問題
https://atcoder.jp/contests/abc387/tasks/abc387_d

bfsをもとに上下移動で来たかを判定できるようにする
```python:D
from collections import deque

h, w = map(int, input().split())
s = [input() for _ in range(h)]

sx, sy, gx, gy = 0, 0, 0, 0
for i in range(h):
    for j in range(w):
        if s[i][j] == "S":
            sx, sy = i, j
        if s[i][j] == "G":
            gx, gy = i, j

INF = float("inf")
dist = [[[INF] * 2 for _ in range(w)] for _ in range(h)]
q = deque()
q.append((sx, sy, 0, -1))

while q:
    x, y, d_i, arr = q.popleft()

    if arr != 0:
        for i, j in [(x + 1, y), (x - 1, y)]:
            if 0 <= i < h and 0 <= j < w and s[i][j] != "#" and dist[i][j][0] > d_i + 1:
                dist[i][j][0] = d_i + 1
                q.append([i, j, d_i + 1, 0])
    if arr != 1:
        for i, j in [(x, y + 1), (x, y - 1)]:
            if 0 <= i < h and 0 <= j < w and s[i][j] != "#" and dist[i][j][1] > d_i + 1:
                dist[i][j][1] = d_i + 1
                q.append([i, j, d_i + 1, 1])

print(-1 if min(dist[gx][gy]) >= INF else min(dist[gx][gy]))
```
PythonでPDF中にハイライトをする方法

#### PyMuPDFを使用
```python
pip install pymupdf
```

#### 文字を検索し文字の上からハイライト
```python
import fitz

# PDFを開く
doc = fitz.open("sample.pdf")

# ハイライトするテキストの座標を取得
search_text = "この解釈において、次の各号に掲げる用語の定義は、当該各号による。"

# 各ページをループ
for page_num in range(len(doc)):
    page = doc[page_num]

    # ページ内で検索
    areas = page.search_for(search_text)

    # 見つかったエリアにハイライトを追加
    for area in areas:
        page.add_highlight_annot(area)

# 結果を保存
doc.save("sample_output.pdf")
doc.close()
```

#### 座標を指定してハイライト
```python
import fitz  # PyMuPDF

# PDFファイルを開く
doc = fitz.open("sample.pdf")

# ハイライトを追加するページと座標を指定
page_number = 0  # ページ番号 (0始まり)
highlight_rects = [
    (100, 200, 300, 250),  # (x0, y0, x1, y1) の座標 (左上と右下)
    (150, 300, 350, 350)   # 複数領域も指定可能
]

# 指定ページを取得
page = doc.load_page(page_number)

# 指定座標に塗りつぶしハイライトを追加
for rect in highlight_rects:
    # 矩形領域を定義
    annotation = page.add_rect_annot(fitz.Rect(rect))
    # 塗りつぶし色 (黄色) と透明度を設定
    annotation.set_colors(fill=(1, 1, 0))  # RGB: 黄色
    annotation.set_opacity(0.3)            # 透明度30%
    annotation.update()

# 保存
doc.save("sample_output.pdf")
doc.close()
```
#11.2025年の目標

# はじめに
あけましておめでとうございます！いよいよ2025年が始まりましたね。
私は正月に地元へ帰省し、家族と一緒にゆっくりと過ごしてきました。
やっぱり実家は落ち着きますね〜
ところが、帰ってきてすぐにインフルエンザにかかってしまい、現在は療養中です....
年末年始は屋内で人が密集したり、帰省の移動が多かったりするので、感染が広がりやすい時期とのことで、皆さんもぜひ気をつけてくださいね。

新年を迎えたということで、今年の目標をざっくりと設定してみました。
※進捗次第で変わるかもしれません。

# 今年の目標
- 小さなイベントからでも良いのでLTに参加してみる。
- 週1の記事投稿を継続。
- 気になったイベントや勉強会に積極的に参加する。
- 具体的にはまだ決まっていないのですが、AWSを用いて何かを作る。
- MENTAの課題を進める。
#### 資格系
- TOEICで800点以上。
- AWSのPROFESSIONAL資格を取得する。(こちらは余裕があれば）
---
目標としてはこんな感じですかね。
去年の目標よりだいぶハードルをあげたので達成できるかどうかはわからないですが、とりあえずやってみます。

短いですけど、今年の目標を掲げてみました！！
では、ありがとうございました〜
GitのRebaseについて

# はじめに
Gitでバージョン管理するときのRebaseの使い方についての備忘です。

## 開発コミットを繋げ直す
複数人で開発していると、開発コミットに対して他の人が自身の開発したソースをマージしていきます。

そうすると、自分が開発しているソースは現在の親ブランチとは状態が異なってきます。
この時にRebaseします。
手順は下記の通りです。
```bash
# 現在のブランチを確認する
git branch
# test1というブランチにいることを確認する

# 開発ブランチ（develop）に切り替える
git switch develop

# 現在の最新のソースをPullしてくる
git pull origin develop

# test1に切り替える
git switch test1

# Rebaseする
git rebase develop

# Rebase成功した場合は終了

# 競合した場合
# 競合したファイルを確認する
git status

# 競合したファイルの修正
vim file_name

# 競合したファイル全て修正完了したらaddする
git add file_name

# Rebaseを続行する
git rebase --continue
```

## コミットをまとめる
リモートリポジトリに対してPushする前に、ローカルのコミットを後で見て分かりやすい単位にまとめておきたい。

手順は下記の通り。

```bash
# 現状のログを確認する
git log --oneline

# コミットをまとめる
# 下記4つ分のコミットをまとめる際のコマンドの例
git rebase -i HEAD~4
```

Rebaseすると下記が出力される
```bash
pick xxxxx commit message
pick xxxxx commit message
pick xxxxx commit message
pick xxxxx commit message
```
### コミットをまとめる場合
2, 3番目のコミットを一番上のコミットにまとめる場合`pick`を`s`に変更して保存する

```bash
pick xxxxx commit message
s xxxxx commit message
s xxxxx commit message
pick xxxxx commit message
```

### コミットメッセージを変更する場合
4番目のコミットのコミットメッセージを変更する場合は`pick`を`r`に変更して保存する。

保存すると、コミットメッセージ変更画面に遷移するため、そこで変更したいメッセージに編集する
```bash
pick xxxxx commit message
pick xxxxx commit message
pick xxxxx commit message
r xxxxx commit message
```

# まとめ
以上Rebaseについての備忘です。

ご参考までに
PubSubのイベントでCloudRunFunctionsが起動しない

# 概要
GKE Autopilotを使用してアプリの運用を行っているが、自動アップグレードがされて、アプリが動かなくなったことがあり、GKEのアップグレード通知をSlackで受信して、事前に検証を行うようにしたかったが、
上手くPubSubとの連携が出来なかった時の対応方法を記す。
https://cloud.google.com/kubernetes-engine/docs/tutorials/cluster-notifications-slack?hl=ja
# 原因
流れ的には下記となる。
GKE→PubSub→CloudRunFunction→slack
どうしても、PubSub→CloudRunFunctionの部分だけが連携されないことがわかった。
CloudRunFunction（第二世代）は、CloudRunとして動作するので、そちらの連携を確認していたら、
下記のマニュアルに重要として関連ありそうな記載があった。
https://cloud.google.com/run/docs/tutorials/pubsub?hl=ja#integrating-pubsub

```
重要: 2021 年 4 月 8 日以前に作成したプロジェクトで Pub/Sub がトークンを作成できるようにするには、サービス エージェント service-{PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com にプロジェクトの iam.serviceAccountTokenCreator ロールを付与する必要があります。この日付以降に作成したプロジェクトでは、同等の権限を持つ roles/pubsub.serviceAgent ロールがあるため、このロールを付与する必要はありません。
```
なので、サービス エージェントにロールを付与しようと思ったが、このサービス エージェント自体が存在していないことがわかった。
他のプロジェクトでも同様の状況であり、手動で削除とかしていないので、
2021 年 4 月 8 日以前に作成したプロジェクトでは、サービス エージェント自体がない時期もあったと考えられる。（これ以降に作成されたプロジェクトには存在していたし、権限も付与されていた。）

# 対応
コンソールで、IAMのGRANT ACCESSのadd principalsで、service-{PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com　を作成し、権限も付与した。
これにより問題なく連携出来るようになった。
Github Copilotは、Arduino・ESP32の開発でも使用できるのか？

今回は開発スピードを向上させるためVSCodeにGithub Copilotを
導入してみました！

果たしてArduinoやESP32の開発でもGithub Copilotは、
きちんと動作してくれるのでしょうか？

# インストール方法
１、まずはGithubのアカウント登録をしてください。
　　登録は以下のURLから
https://github.co.jp/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/c4ff5160-ef2f-ecce-100e-20fb8f3b6e93.png)

２、アカウント登録後、ログインを行い、右上に表示されているアカウントアイコンをクリック。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/b445956e-4941-93bf-e3ba-73f08194a6dd.png)

３、「Your Copilot」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/c6e7bda4-4eb7-fe70-f9ba-c651646854e6.png)

４、「Start using Copilot Free」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/94eab0e2-a0b5-6a4b-8860-d0fe2764cc28.png)

５、「Visual studio Code」ボタンをクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/fdbaa313-8e4d-014b-34eb-7d411811f609.png)

６、「Install」ボタンをクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/a56ba397-c7ce-2587-5ca5-afa3f2c8715a.png)

これでインストールは完了です。

# 使ってみる
まずはESP32を使ってLチカをしてみよう！

チャットに以下の依頼をした。
「Esp32でLチカのプログラムを作って、 ピンはIO2を使用する。」
その結果以下の回答が来た。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/9a6c01f7-b7a8-e958-c7d9-dbe9271cdd14.png)

そしてエディターに適用ボタンを押したらファイルに反映される。

「AIカーソルを挿入します」ボタンを押すと、
ファイル内のカーソルの場所に現在のプログラムを挿入する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/86993c3c-ee42-2190-6f3b-00a46bd08eac.png)

地味に便利だが劇的に作業性が向上するまではない。
正直Copilotの結果をコピペするのとあまり変わらん。

しかし、驚いたのは次の予測機能だ。
pinMode(3,inputpullup);
を追加した途端以下の予測プログラムを作成した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/e5edfa29-db62-a180-3ee8-92c3ef0c7ebf.png)

確かにINPUTPULLUPを追加したと言うことはLOWで何か
処理を行いたいと思っているはず。

これはなかなか使えるかもしれない。

# 結果
Arduinoでも予測AIコードはかなり使えそう。
しかし無料版は制限回数があるので、有料にしようか迷うところです。
Streamlitで要素を削除する（≒出したり消したりする）（そのために全体の流れを理解する）

# やりたいこと

Streamlitで要素を削除したい。

画面に表示した要素を消すなんて簡単に出来そうですが、
Streamlitの処理の流れを理解していないとハマるので少しだけ説明におつきあいください。

# Strealitの処理の流れを理解する

## 画面上での動きを確認する

次のコードを実行してみます。

```py
import streamlit as st

st.title('Hello, World!')

if st.button('Say hello'):
    st.write('Hello, Streamlit!')
```

**Say hello** ボタンを押すと、**Hello, Streamlit!** が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33095/75b94402-491b-dd8a-ff60-3e31dbe21b51.png)

コード自体はとてもシンプルで直感的です。

## ログを入れて動きを確認する

と言いつつ、通常のPythonのコードとかに慣れていると
「これは `st.button()` でキー入力待ちが発生しているのかな？」
みたいな疑問が出てくるのでちょっとログを入れて動きを見てみます。

いろいろなところに print 入れてみました。

```py
import streamlit as st
import logging

st.title('Hello, World!')
print("Hello, World!") # ★LOGGING

if st.button('Say hello'):
    st.write('Hello, Streamlit!')
    print("Button - pressed!") # ★LOGGING
else:
    print("Button - Not pressed!") # ★LOGGING
```

これを実行してボタンを押してみると、、、

```text
Hello, World!
Button - Not pressed!
Hello, World!
Button - pressed!
```

こんなログが出ます。
およ？ **Hello, World!** がなんで２回出たの？？

ということでここが要注意ポイントです。

## なぜそうなったかを考えてみる

まず初回は **Hello, World!** と **Say hello** ボタン を描画しておしまいになります。
ボタンは描画しただけで押されていないので **else** のルートに行きます。

そして、ブラウザ上でボタンが押されると、このコードが再び動き出します！
今度は **Hello, World!** と **Say hello** ボタン を描画してさらにボタンが押された状態なので True のルートに入るので **Hello, Streamlit!** が描画されます。

この、同じコードが何回も実行されている ≒ 毎回すべての要素を書き直している、という動きを理解することが大事です。

> 同じ要素を何度も描画しているといっても、StreamlitはReactベースで作られている（らしく）DOMの変化があったところだけ描画されるので画面がチカチカすることはありません！かしこい！

## つまり「要素を削除する」方法は？

要素は削除できません！
削除ではなく、描いたり描かなかったりします。

毎回毎回すべての要素を描画しなおすということで、
**要素を追加して、削除する** ではなく、
**要素を追加したり、しなかったりする** という方法をとる必要があります！

## サンプルコード

こんな感じになります。

- 描画するしない用のフラグを用意する
- フラグは普通の変数だと消えてしまうので `st.session_state` というものを使う
- フラグを見て `st.write()` を呼び分ける

という点だけ注意してくれれば普通のコードです。

```py
import streamlit as st
import logging

if 'show_flag' not in st.session_state:
    st.session_state.show_flag = True

st.title('Hello, World!')

if st.button('Say hello'):
    if st.session_state.show_flag:
        st.session_state.show_flag = False
        st.write('Hello, Streamlit!')
    else:
        st.session_state.show_flag = True
```
Huggingface Datasetsを学ぶ

今更ながらHugging FaceのDatasetsについて，ロボティクスのデータセットを交えながらhow toを学ぼうと思う

https://huggingface.co/docs/datasets/index

利用するデータセット

https://huggingface.co/datasets/lerobot/pusht

Lerobotについてはこちらを参照

https://huggingface.co/lerobot

https://github.com/huggingface/lerobot

1. [第1回　Hugging Face Hubからデータセットをダウンロードする](https://qiita.com/kosei1515/items/01bb458fc63ac32eb499)
1. [第2回　Datasetを知る](https://qiita.com/kosei1515/items/5e786e3c39a8aae26d74)
1. [第3回　Preprocess](https://qiita.com/kosei1515/items/0aedca513131c8b1f8cb)
1. [第4回　Datasetを作る](https://qiita.com/kosei1515/items/2d79be1d298cdf698c9d)
1. [第5回　DatasetをHugging Face Hubで共有する](https://qiita.com/kosei1515/items/5f91fc69c4c903ba2382)

...
かんたん楽しいフローチャート

### ドラゴンの卵
```mermaid
flowchart TD
    A["ドラゴンのたまご🥚"] --> B["🔥 あたためる"]
    B --> C{"🌡️ おんどは？"}
    C -->|👍 いい| D["👀 みまもる"]
    C -->|だめ| B
    D --> F{"われた？"}
    F -->|👍 はい| G["🎉 ドラゴンがうまれる！"]
    F -->|いいえ| B
```
### ドラゴンでふうせんをわる
```mermaid

flowchart TD
    Start([スタート]) --> A[コスチュームを 🎈 に]
    A --> B{🐉 Dragon にふれた？}
    B -->|はい| C[♪音を鳴らす]
    C --> D[コスチュームを ❤ に]
    D --> E[⏳ 1秒待つ]
    E --> F[どこかの場所へ行く]
    F --> A
    B -->|いいえ| A
```
エンジニアのための情報発信戦略：Qiita・Zenn・note 活用術

エンジニアには、知識の共有や学び合いを重視する文化があります。
情報発信を通じて、技術力向上やネットワーク構築が促進されるのは良い文化ですね。
このような環境があることで、個々の成長と業界全体の発展が期待できます。

本記事では、エンジニアに人気の3大プラットフォーム
**Qiita**、**Zenn**、**note**の特徴と効果的な使い方をまとめました。

どこに投稿するのがベストか悩んでいるエンジニアの助けになれば幸いです。


## 情報発信のメリット

適切な情報発信は、以下のような多くのメリットがあります。

1. **技術力の向上**　アウトプットすることで、自身の理解が深まる
2. **キャリアチャンスの拡大**　企業やヘッドハンターの目に留まりやすくなる
3. **ネットワークの構築**　同じ興味を持つエンジニアとつながれる
4. **個人ブランドの確立**　専門性や独自の視点をアピールできる
5. **学習モチベーションの維持**　定期的な発信が学習の原動力になる

## プラットフォーム比較表

まずは Qiita、Zenn、noteの主要な特徴の比較を表にまとめました。

| 特徴 | Qiita | Zenn | note |
|------|-------|------|------|
| 対象読者 | エンジニア中心 | エンジニア・技術愛好家 | 幅広い一般ユーザー |
| コンテンツの特徴 | 短〜中程度の技術記事 | 技術書、長編チュートリアル、多様なトピック | エッセイ、体験談 |
| SEO効果 | 高い | 比較的高い | 中程度 |
| 収益化 | 不可 | 可能（有料記事、本） | 可能（有料記事、マガジン） |
| 主な用途 | 技術共有、問題解決 | 深い技術解説、学習記録、多様な情報共有 | 個人的見解、非技術的話題 |

## 各プラットフォームの効果的な使い方

### Qiitaの活用法
![logo-background-color.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264248/b5576059-b4b5-2490-b93f-53ba1059294f.png)

Qiitaは、エンジニア向けの技術情報共有プラットフォームとして確立されています。

- **最適な投稿内容**
  - 技術的な問題解決方法
  - プログラミングのハウツー記事
  - 新しいツールやライブラリの紹介
  - エラー解決のTips

- **投稿のコツ**
  - 具体的で再現可能な手順の記述
  - コードスニペットの多用
  - タグの適切な設定

### Zennの活用法
![logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264248/79c9d7c0-05f9-16ae-5da7-cd0c365658f0.png)


Zennは、技術的な内容だけでなく、幅広いトピックに対応しています。

- **最適な投稿内容**
  - 技術書や長編チュートリアル
  - 深い技術的な考察や分析
  - 個人的な技術学習の記録（スクラップ機能）
  - キャリアや働き方に関する記事
  - エンジニアライフに関する体験談

- **投稿のコツ**
  - シリーズ記事や本としての構成
  - 図表やダイアグラムの効果的な使用
  - 有料コンテンツとしての価値の高い情報提供
  - Tech（技術）とIdea（アイデア）のカテゴリーの適切な選択

### noteの活用法
![logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264248/d0696e9b-5e6d-7d57-5a7e-674360a3a85a.png)

noteは、より幅広い読者層に向けた、パーソナルな内容や非技術的な話題に最適です。

- **最適な投稿内容**
  - エンジニアとしての経験談
  - キャリア形成に関する考察
  - 技術業界のトレンド分析
  - ワークライフバランスに関する記事
  - 趣味や日常生活に関する記事

- **投稿のコツ**
  - 個人的な体験や感情の織り交ぜ
  - 読みやすい文体での親しみやすさの演出
  - 写真や図を使った視覚的な魅力の向上
  - マガジン機能を活用した定期的な情報発信

## 効果的な使い分けのポイント

1. **コンテンツの性質に応じた選択**
   技術的な深さや話題の範囲によって、最適なプラットフォームを選択します。

2. **読者層の意識**
   各プラットフォームの主な利用者を考慮し、内容や表現を調整します。

3. **クロスポストの活用**
   適切な形で内容を調整し、複数のプラットフォームに投稿することで、より広い読者層にリーチできます。

4. **個人ブランディングの意識**
   各プラットフォームでの活動を通じて、エンジニアとしての専門性と人間性の両面をアピールします。

5. **継続的な更新**
   定期的に質の高いコンテンツを投稿することで、フォロワーを増やし、影響力を高められます。

## その他のプラットフォーム

Qiita、Zenn、note以外にも、エンジニアが活用できる情報発信プラットフォームがいくつか存在します。

1. **GitHub** (https://github.com/)
   - GitHub Pagesを使った技術ブログの公開
   - プロジェクトのREADME.mdでの技術解説
   - GitHub Discussionsを活用したコミュニティ形成

2. **dev.to** (https://dev.to/)
   - 英語での技術情報発信に適した国際的なエンジニアコミュニティ

3. **Speaker Deck** (https://speakerdeck.com/)
   - 技術カンファレンスや勉強会での発表資料の共有に最適

4. **はてなブログ** (https://hatenablog.com/)
   - 技術ブログの運営に適した老舗のブログプラットフォーム

## まとめ：Qiita、Zenn、noteの効果的な使い分け

+ **Qiita**（https://qiita.com/）
    + 短〜中程度の技術記事、問題解決、コード共有に最適。SEO効果が高い

+ **Zenn**（https://zenn.dev/）
    + 長編チュートリアル、技術書、深い考察に適している。技術以外のエンジニア向け記事も可。有料コンテンツ提供可能

+ **note**（https://note.com/）
    + 個人的な経験談、エンジニアの日常、技術以外の話題に適している。一般読者にもリーチしやすい

内容に応じて適切なプラットフォームを選択し、クロスポスト(≠マルチポスト)や相互リンクを活用することで、多面的な情報発信と幅広い読者層へのリーチが可能になります。
継続的な発信を通じて、技術力向上、キャリア拡大、個人ブランド確立ができるといいですね。この記事が皆様の情報発信戦略の参考になれば幸いです。
CodeSandBoxのVSCodeでファイル名を変更したらエラーが出たときの対処法

# 事象
providersディレクトリの`UserProvider.jsx`をインポートしようとしたところエラーが出たので、確認するとファイル名が`userProvider.jsx`になっていたのでファイル名を変更しました。
すると、ファイルが開けなくなったので、削除して再作成しようとすると、下記のメッセージが出て新規作成できない状態になりました。

```
Unable to create file '/nodebox/src/providers/UserProvider.jsx' that already exists when overwrite flag is not set
```

# 解決策
結論から言うと、ログインし直してから新たなファイル名で再作成することで解決しました。
今回は短いコードだったのですぐに打ち直せましたが、タブを閉じる前にファイルの内容をコピーしておくことをおすすめします。
どうやら、CodeSandboxの問題というよりはリモート環境下のVSCodeの問題のようですね……

## 参考リンク
https://stackoverflow.com/questions/72247306/renaming-files-doesnt-take-effect-in-vscode-while-using-wsl2