OmniAICreator/Qiita-1.07M huggingface dataset:
【個人開発】実務経験1年と半年が３日で個人開発してみた！

# はじめに
実務経験1年と半年のWebエンジニア(27)です！
ここ最近のトレンド(VercelAI、Clerk、v0)を抑えたいなと思い、自分が触りたいものを詰め込んでアプリを作りました。世に公開するのは2度目となり1度目の反省を活かしてます。
無料かつ登録から1分程度でカロリー計算できるので興味ある方は触ってみてください😃

# サービス概要
## CalorieSnap
写真で撮った料理のカロリーを測定できます。

https://calorie-snap.com/

## 実際の動作
![calorieSnap.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798471/3b3430dd-af95-c168-d280-b1f7782614a7.gif)

# 今回触りたかった技術
## VercelAI
### VercelAIとは
[VercelAI](https://vercel.com/ai)とは、ChatGPTやらを使用したいときに便利なSDKを提供してくれます。

### 感想
使い勝手良かったですが、画像をbase64を送信する場合、meta情報はいらないとか細かいところがドキュメントに書いてなかったのがちょっと気になりました。
基本exampleコードもしっかりあり実装で何日も悩まず使えそうだなと思いました！

## Clerk
### Clerkとは
[Clerk](https://clerk.com/)とは、フロントエンドフレームワーク向けの認証・認可サービスです。また、新規登録画面やプロフィール画面のコンポーネントまで用意してくれます。

### 感想
めちゃくちゃ良かったです。今後個人開発でログイン機能実装する場合一択だと思います。
自前で実装するには１〜2週間はかかるであろう実装が半日で終わりました。
UIも綺麗ですし、使わない手はありません。

## v0
### v0とは
[v0](https://v0.dev/)とは、shadcn-uiを使ってコードを自動生成してくれます

### 感想
及第点！
ダッシュボードを生成してもらいました！1回目のクオリティはすごいですがそこから「???修正してください」などの指示通りには修正されず....課金するとクオリティモードなるものがあるのですがいつか使ってみたいですね...
実装前にコード生成してもらい、細かいところを自分で修正していく分には使い勝手良いなと思いました！

## 最後に
以前は３〜4ヶ月使ってがっつりしたものを作成したので、軽めのものを作りました！
ChatGPT登場前だと1~3ヶ月かかっていたものがこうして３日ほどで使えるようになったのは感激ですね😭
今後使ってくれる方がいれば履歴機能や1日に必要なカロリーを計算してくれる機能など随時実装したいと思うのでぜひ使っていただけると☺️

自分の所属している　[PRUM](https://prum.jp/)では未経験エンジニアを募集しています！
やる気と人柄で30代以上の方も採用しているの興味のある方は、コメントください！
JavaScriptで存在しない関数を呼び出した場合、エラーにせずに何らかの処理を実行する

## はじめに

PHPの`マジックメソッド`やRubyの`method_missing`に近い機能をJavaScriptで実装する方法です

通常、javascriptでは、存在しない関数を呼び出すとエラーが発生します

```js:test.js
const obj = {};
obj.some_method();
```

```
$ node test.js
E:\Users\tkykn\git\proxy\js_method_missing\test.js:2
obj.some_method();
    ^

TypeError: obj.some_method is not a function
    at Object.<anonymous> (E:\Users\tkykn\git\proxy\js_method_missing\test.js:2:5)
```

この`obj`を[Proxy](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Proxy)でラップすることで、メソッドを呼び出すことができるようにします


## プログラムソース

```js:method_missing.js
/**
 * 【javaScriptで存在しない関数を呼び出した場合、エラーにせずに何らかの処理を実行する】
 *   --- PHPのマジックメソッドやRubyのmethod_missingに近い機能をJavaScriptで ---
 *
 * javascriptでは、存在しない関数を呼び出すとエラーが発生してしまうが、
 * Proxyを使うことで、存在しないプロパティーアクセスや関数呼び出しのエラーを回避することができる
 *
 * ①存在しないプロパティーにアクセスがあった場合「Proxyのget()ハンドラー」で何もしない関数を返す
 * 　⇒関数呼び出しでのエラー回避と
 * ②何もしない関数もProxyでラップしておく。関数呼び出し時、apply()が呼び出されるので任意の処理をお個々なうことができる
 */
const target = { hoge: 'taget.hoge', bar: () => 'target.bar' };

const proxy = new Proxy(target, {
  get(target, name, receiver) {
    console.log(`get property ${name}`);
    if (name in target) {
      // オブジェクトに存在するプロパティーは値をそのまま返す
      return target[name];
    } else {
      // 存在しないプロパティーにアクセスがあった場合temp_func(空の関数)を返す
      //  ⇒ 呼び出し元では、指定した関数が定義されているように見える
      const temp_func = () => {};
      // Proxyでラップして返すことで、temp_func関数呼び出し時にapplyフックが実行される(割り込む)
      const func_proxy = new Proxy(temp_func, {
        apply(target, thisValue, args) {
          // 関数名と引数を表示する(nameはプロパティーアクセス時のキー名)
          console.log(`call missing function ${name}(${args})`);
          // return target.apply(thisValue, args); // 関数を呼び出すならこのように記載する
          return name; // 任意の処理を行い結果を返す(ここでは呼び出された関数名を返している)
        },
      });
      target[name] = func_proxy;
      return target[name];
    }
  },
});

// targetに存在するプロパティーを呼び出した場合は、apply()が実行されない(元の関数が呼ばれる)
console.log(proxy.hoge);
console.log(proxy.bar());

// targetに存在するプロパティーを呼び出した場合、temp_funcが返される
// temp_func()を関数として呼び出すと、proxyのapply()が呼び出されるので任意の処理を行うことができる
console.log(proxy.callFunc(12, 'ab'));
console.log(proxy.findById(12345));
```

* 実行結果
  * 存在しない関数(callFunc())が呼び出され、引数が表示されている
  * 戻り値として、関数名が帰ってきている
```
$ node method_missing.js
～～ 一部省略 ～～
get property callFunc                  ・・・存在しないプロパティーにアクセス⇒temp_funcが返される
call missing function callFunc(12,ab)  ・・・temp_func()を呼び出した結果、apply()が割り込み、ログを出力している
callFunc
get property findById
call missing function findById(12345)
findById
```
【Copilot】CopilotキーがないPCにもCopilotキーの設定をしたい

# はじめに
Windows Insider Programで、Win+CでCopilotを呼び出せなくなったので、回避策を作成しました。

※この記事はChatGPTで添削しました。

# 環境
- Windows 11 (24H2)
- OSビルド 26120.751
- PowerToys

# 背景
これまで、Copilotを呼び出すショートカットキーとしてWin+Cを使用していましたが、現在このショートカットが無効になっています。調査の結果、Copilotキーの実際の仕様が「3つのキーを同時に押す」というものだと判明しました。

> "So I used AutoHotkey, a keyboard macro scripting program that can also be used to log key strokes, to find out how the Copilot key registers. To my shock and surprise, I discovered that, under the surface, the Copilot key is a combination of three keys pressed at once: Left Shift + Windows key + F23." ([Tom's Hardware](https://www.tomshardware.com/software/windows/windows-copilot-key-is-secretly-from-the-ibm-era-but-you-can-remap-it-with-the-right-tools))

そこで、この3つのキーの組み合わせをPowerToysのKeyboard Managerを使用してショートカットとして登録することで、再びCopilotを呼び出せるようにしました。

# 手順

## 1. PowerToysのインストール
PowerToysがインストールされていない場合、[Microsoftの公式サイト](https://docs.microsoft.com/en-us/windows/powertoys/install)からダウンロードしてインストールしてください。

## 2. Keyboard Managerの設定
1. PowerToysを開きます。
2. 左側のメニューから「Keyboard Manager」を選択します。
3. 「Remap a key」をクリックします。

## 3. ショートカットキーの設定
1. ショートカットの再マップをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576919/5deba53a-c501-96bb-4dfe-e8b677833e26.png)
2.  ショートカットにWin+C
3. マップ先に「Left Shift + Windows key + F23」を入力します。
4. 「OK」ボタンをクリックして設定を保存します。

設定画面は以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576919/581cdf5d-e9c4-412a-16fe-b51769734dbf.png)


これで、Win+Cのショートカットで再びCopilotを呼び出せるようになります。

# 最後に
Win+Cのショートカットが無効になったのは予想外でしたが、PowerToysを使用することで簡単に解決することができました。この記事が同じ問題に直面している方の助けになれば幸いです。

# 参考
[Tom's Hardware](https://www.tomshardware.com/software/windows/windows-copilot-key-is-secretly-from-the-ibm-era-but-you-can-remap-it-with-the-right-tools)
Elixir Phoenix エンドポイントにアクセスしたときに変数を表示する

こんにちは！
プログラミング未経験文系出身、Elixirの国に迷い込んだ？！見習いアルケミストのaliceと申します。
今回はPhoenixのrouterとコントローラ、ビューに値を渡す方法について学んだことをまとめます。2024/6/2に開催したイベント[piyopiyo.ex #34：もくもく作業タイム](https://piyopiyoex.connpass.com/event/319664/)の成果です。

# 目的
エンドポイント/sampleにアクセスした時、下記のテキストを画面に表示する
```
Hello ほげ さん
Your Number is 1234
```

# 前提
`hello`という名前でPhoenixプロジェクトを作成済
```bash:bash
mix phx.new hello
cd hello
mix ecto.create
```

## 実行環境
Windows 11 ＋ WSL2 ＋ Ubuntu 22.04
Elixir v1.16.2-otp-26
Erlang v26.0.2

# 仮説
下記の実装が必要
・エンドポイント`/sample`のrouterを追加
・コントローラに変数を定義する処理を追加
・ビューに変数を呼び出して描画する処理を追加

# 結果
## エンドポイント`/sample`のrouterを追加
```diff_elixir:lib/hello_web/router.ex
 scope "/", HelloWeb do
     pipe_through :browser
     
+    get "/sample", SampleController, :index
   end
```
### コントローラに変数を定義する処理を追加
:::note info
`render/3`関数の第三引数で変数を定義しています
:::

```diff_elixir:lib/hello_web/controllers/sample_controller.ex
 defmodule HelloWeb.SampleController do
   use HelloWeb, :controller

   def index(conn, _params) do
+    render(conn, :index, foo: "ほげ", bar: 987)
   end
 end
```

## ビューに変数を呼び出して描画する処理を追加
:::note info
`@変数名`で変数を呼び出します
:::
```html:lib/hello_web/controllers/sample_html/index.html.heex
<p>Hello <%= @foo %> さん</p> 
<p>Your Number is <%= @bar %></p> 
```
## できました(^▽^)/
```bash:bash
mix phx.server
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677280/a9f28502-80ef-ebe5-b840-86667287c77e.png)




# ～Elixirの国のご案内～
↓Elixirって何ぞや？と思ったらこちらもどぞ。Elixirは先端のアレコレをだいたい全部できちゃいます:laughing::sparkles::sparkles:

https://qiita.com/piacerex/items/09876caa1e17169ec5e1

↓ゼロからElixirを始めるなら「エリクサーチ」がおすすめ！私もエンジニア未経験から学習中です。

https://elixir-lang.info/topics/entry_column


↓[We Are The Alchemists, my friends!:bouquet:](https://qiita.com/torifukukaiou/items/6bcd5bbb80df9e594e9e "Awesome-san's Awesome article")[^10]
Elixirコミュニティは本当に優しくて温かい人たちばかり！
私が挫折せずにいられるのもこの恵まれた環境のおかげです。
まずは気軽にコミュニティを訪れてみてください。[^11]


https://speakerdeck.com/elijo/elixirkomiyunitei-falsebu-kifang-guo-nei-onrainbian




[^10]: @torifukukaiouさんのAwesomeな名言をお借りしました。Elixirコミュニティを一言で表すと、これに尽きます。


[^11]: @kn339264さんの素敵なスライドをお借りしました。Elixirコミュニティはいろんな形で活動中！
「うまくいかない」というのも重要な知見である

## 主旨
「うまくいかない]という知見も重要な知見である。
うまくいかなかった状況も共有することで、道が開けてくることがある。


## 仕事でもうまくいかないことはよくあることです
- あるもくろみがあって、なにかしかのトライをしてみた。しかしうまくいかなかったということはよくあることです。
- むしろ簡単にはうまくいかないからこそ、「仕事」なんだと思うことにしている。
- うまくいかない状況でどのように改善したらうまくいくのかを考えることが「仕事」なんだと思っている。
- 特許にしても、学術論文にしても、従来の方法ではうまくいかない部分があるからこそ、書く意味がでてくるというものです。
- まずは、そう思って、うまくいくように再挑戦することも考えてみましょう。

## それでもやっぱりうまくいかなかったとき

- うまくいかないという知見も重要な知見です。
- 特許は書けませんが、論文は書けるかもしれません。
- 会社で工数をかけて作業したのであれば、業務報告は書く必要があるでしょう。
- 担当した私には解決できなくて行き詰まっても、別の人だったら解決できるかもしれません。
- あるいは、だれがやっても成功しない作業かもしれません。
- その場合には、同じ失敗を他の人にさせないために、「うまくいかない」という知見を共有することです。

## うまくいかなかったを共有できるのは信頼関係のあかし
- うまくいかなかったを共有できる組織は健全だと思います。
- うまくいかなかったを隠す組織は、どこかで「うまくいったふりをする」組織になりかねません。
- 「うまくいったふりをする」組織の例は、いやというほどありますね。

## うまくいかなかったという知見がもたらすもの
- 人はポジティブサンプルだけで学習をすることはできません。
- ポジティブサンプルとネガティブサンプルとの両方があってこそ、たいがいの学習が成立します。

## うまくいかなかった事例を知った第3者にできること
- うまくいかない無駄なトライをしなくて済むようになる。
- 課題設定を適切にすることができる。
- 課題設定をし直したうえで、うまくいかなかった要因をふまえて、次のトライをする。

# 結論
- うまくいかなかったという知見は、次のトライを有効なものにする効果がある。
M5Stamp SIM7080G搭載 CAT-Mモジュールの信号電圧は3.3V

[M5Stamp SIM7080G搭載 CAT-Mモジュール](https://www.switch-science.com/products/8194)は、電源電圧に5Vと3.3Vが使えます。

信号電圧が書いてなかったので調べたところ 3.3V でした。5V 印加でも 3.3V です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/423bd2d8-9bc6-f415-132a-e2c53f489f0b.png)

## あとがき

ほんとにそれだけのエントリーになってしまった、もはや~~ツイート~~ポスト。
Flask requestsを使った受け渡し

# サーバ側
```
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/EmployeeSystem', methods=['POST'])
def register():
    data = request.get_json()
    id = data.get('id')
    name = data.get('name')
    

    data = {
        f"id: {id}, name: {name}"
    }
    
    return jsonify(data), 200

if __name__ == '__main__':
    app.run(host="0.0.0.0")
```
# リクエスト側
```
import requests

url = 'http://127.0.0.1:5000/EmployeeSystem'

data = {
    'id': 1,
    'name': '小林'
}

response = requests.post(url, json=data)

print("Response from server:", response.json())
print("Status code:", response.status_code)
```

# レスポンスコードの表示
https://qiita.com/mink0212/items/52e0ebd66bd94e1303c1
【UE5】ゼロから極めるゲーム開発　その2

# 初めに

細かくメモを取っておこうとすると投稿に時間がかかってしまうことに気が付きました。
モチベ的にも悪そうなので、今度から重要そうなことだけを書いていこうと思います。

# カメラの向きとブックマーク

ビューポートで調整したカメラの向きをブックマークとして保存できる。
保存したらキーボードの数字を押下することで、設定した向きになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779049/af7cfa29-d940-ed1d-cd7a-8b3e25909d41.png)

# オブジェクトの配置

[アクタを配置]からキューブを配置してみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779049/e0f2a8b3-2637-76af-276a-9809a7c66b3b.png)

ライトが設定されていないため、配置したオブジェクトがわかりにくい。
そんな時は[ライティングなし]に設定すると良い
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779049/4929bcf9-9aa2-101e-ffc4-8798e849a034.png)

`オブジェクトを選択した状態でFキーを押すとそのオブジェクトにフォーカスさせられる`

カメラタイプを変更することで配置しやすくできる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779049/9e5724fa-95a4-540c-508a-230b2d1cc36e.png)


# プレイヤーの開始地点を設置する
[アクタを配置]から[Player Start]を配置すると、ゲームのスタート地点を設置することができる。
現状配置してスタートさせても真っ暗なままなので、ライトを追加する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779049/42b67745-25fe-7a74-f748-ca88351b5a20.png)

# ライトの配置
[アクタを配置]からライトを設置できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779049/630bc3b2-81e6-17bd-9b25-73964ae974cf.png)

明るくなった！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779049/9a6ab9ae-cd37-a47c-1d38-4de9bc6084f2.png)

[詳細パネル]の[Intensity]をいじることで明るさを変えられる
ライトについてはいつか詳しく記事を書きたいな
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779049/cd4337de-d238-f895-dd58-b54379d13e93.png)

# 終わり
今回はここまで！
【Unity】Windows(IL2CPP)時にIL2CPP C++ code builderエラーが発生する

# エラー内容
Windows向けにIL2CPPビルドした際に、以下エラーが発生したので解決方法を調べました。

> Internal build system error. BuildProgram exited with code 1. error: Could not set up a toolchain for Architecture x64. Make sure you have the right build tools installed for il2cpp builds. Details: IL2CPP C++ code builder is unable to build C++ code. In order to build C++ code for Windows Desktop, you must have one of these installed:

# 対処方法
VisualStudio Installerから `C++によるデスクトップ開発` を追加するとエラーが解消されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336886/1d88a6b0-3cc8-c4f3-0bff-a9e7fc05f402.png)
統計検定準1級に85点で合格した方法

統計検定準1級に85点で合格できました。
なかなかタフな道のりでしたので準1級合格を目指している方、特に同じようなバックグラウンドの方のご参考になれば嬉しいです。
あと単純に嬉しいのでアウトプットします。

統計検定2級はあるor取れそうくらいのレベルかつ業務で分析っぽいことをしている方には参考になるのではと思います。

### 統計検定挑戦歴
- 2024/5 準1級合格（CBT）
    1. 確率と確率分布 100%
    2. 統計的推測 83%
    3. 多変量解析法 76%
    4. 種々の応用 85%
- 2024/4 いろいろあって準1級再受験を決意する
- 2021/6 準1級不合格（PBT 45点くらい）以後受験をさぼる
- 2021/2 2級合格（75点）

### 統計関連基礎知識など
- 仕事はデータ分析関連でRやpythonは日常的に使用（しかしデータサイエンスと呼ぶには恥ずかしいレベルと組織、、、）
- 大学は理系だがバイオ系なので数学不要
- 大学受験で行列と微積は使った

## 使った教材
以下2点が95%です。
### 統計学実践ワークブック
ベタですがこれが一番大事です。

**前半部分を丁寧に仕上げる**

特に時間をかけたのは確率分布、推測統計周り+確率過程の1~15章でした。
私が数学苦手というのもありますが、本を流し読みしているだけだと理解がふわっとしたままで、厄介なことにわかったつもりになってしまいます。
面倒くさいですが自分で演習問題含めて式展開までして導出もできるようになればCBTには余裕で対応できると思います。
特に各種確率分布のモーメント母関数と平均分散の導出、変数変換、統計量等8章、確率過程はワークブックと後にご紹介するyoutube動画を参考にして自分で数式がかける、演習問題が解けるレベルにしておくと良いでしょう。
逆に言えば実務でよく使う回帰分析等後半部分は前半ほどがっちり理解を深める必要はなかったです。というよりワークブックもそこまで丁寧に書いていないですし、難しいときは対応しようがないほど難しいので、ある程度できるようになればOKくらいの感覚でした。
ベースとして前半の方が私の基礎知識や理解が乏しかったというのはありますが、勉強の費用対効果としては前半の方が大きく見込める印象です。

### [Yuya Kawaguchiさんのyoutube](https://www.youtube.com/@Yuya-Kawaguchi)
これがなければ合格は無理だったといえるくらい頼りにさせていただきました。
こちらで解説されているワークブックの問題は全て視聴し、解法もほぼ完コピしました。
投稿主様も独学で統計検定準1級を取得されており、そこまでには並々ならぬ努力があったようで私のような「なんとなくしかわかっていない勢」の痒い所に手が届く解説を提供してくださっています。

### その他参考にしたもの
これといったものはありませんが、どうしても導出がわからない式や定理に悩んだ時はその都度検索して個人ブログなど先人の皆様のお知恵を拝借しました。
[とけたろうさんのチートシート](https://toketarou.com/quasi_1_cheatsheet/)は移動中やスマホしか見られない時によく見ていました。
あとChatGPTも知識の整理や確認に使えました。
例: ARモデルとMAモデルのコレログラムの違いは？、欠損値補完における平均値代入と回帰代入それぞれで平均分散相関係数が過大もしくは過小評価されるか教えて？

## 日常でできること
ワークブックを中心とした座学をしっかりするのは大前提です。その上で業務や研究、授業でデータ分析をする機会がある人は日常から準1級合格につながることもあると思います。
私は機械学習のライブラリを使うこともあるのですが、公式ドキュメントやvignetteを積極的に読むようにしました。数式アレルギー克服にもなりますし、機械学習系に直接役立ちます。
データを触る機会があるなら分布を確認してどの分布が当てはまりが良いか、最尤推定したらどうなるか、AICでモデル選択したらどうなるか、などインプットもアウトプットもできる機会が日常にはたくさん転がっています。

## 受験までの心構え
受験までは合格できるか不安で、やればやるほど自分の理解不足が露呈するのでこんなんで受かるのか？と疑心暗鬼に陥っていました。
CBT試験中は手ごたえもあったのでそこでやっと自信に変わった感覚です。勉強していてなかなか自信がつかない方もいると思いますが正常です。むしろちゃんと成長している証拠かと思います。
3年前にPBTで不合格食らった私はふわっと理解しかしていないのに変に自信のある勘違い野郎でしたので。

## 今後
社内に準1級ホルダーもしくは準ずる方を見かけないので仕事でも少し自信を持ちたいです。（偉そうにもしたいです）
次は一級目指して頑張ります。一級目指している方は一緒に頑張りましょうー
【AtCoder】上下左右のマス移動

### 反復処理で各方向に移動させる場合

```C++
const vi dx = { -1, 0, 1, 0 };
const vi dy = { 0, 1, 0, -1 };

int x, y; cin >> x >> y;
printf("(x, y): (%d, %d)\n", x, y);
for (int i = 0; i < 4; i++) {
  int nx = x + dx[i], ny = y + dy[i];
  printf("(nx, ny): (%d, %d)\n", nx, ny);
}
```

<br>

### 移動条件がある場合

仮移動させた後、更新するかを決める。

```C++
int x, y; cin >> x >> y;
printf("(x, y): (%d, %d)\n", x, y);
int nx = x + dx[i], ny = y + dy[i];
if (A[nx][ny] == '.') { x = nx; y = ny; }
printf("(x, y): (%d, %d)\n", x, y);
```

例題：[ABC265C - Belt Conveyor](https://atcoder.jp/contests/abc265/tasks/abc265_c)
Windows11 ローカルアカウントのパスワードを忘れたときのリセット手順

# はじめに
最近、Windows11のローカルアカウントのパスワードを忘れた友だちの支援をしたので、その備忘録です。ネット上ではUbuntuで起動してユーティリティマネージャの実行ファイルをコマンドプロンプトの実行ファイルに書き換えるという説がありますが、セーフモードで起動するときなどのオプション詳細のコマンドプロンプトでもできたので、その手順メモです。

# 前提条件
Windows11 Pro 22H2
USBメモリにはリセットキーが退避されていない
セキュリティの質問の答えも忘れた場合

# Windows Utility managerの実行ファイル
これはwindows\system32フォルダ内に格納されているutilman.exeというファイルです。このファイルはWindowsログイン画面で、ログイン前に実行できるファイルということからターゲットになります。

※Windowsログイン画面の右下の電源アイコンの左となりの大の字になっているひとのアイコンをクリックすると表示されるメニューがutilman.exeによる動作です。

# コマンドプロンプトの実行ファイルをWindows Utility managerの実行ファイル名にする

これによって、Windowsログイン画面で、ログイン前にコマンドプロンプトを実行できるようにしてしまおうということです。

## トラブルシューティング用のコマンドプロンプトを起動する

まず、そのためにはトラブルシューティング用のコマンドプロンプトを起動します。シフトキーを押しながら起動、または再鼓動してブルースクリーンの「オプションの選択」を起動します。
「オプションの選択」からは下記の選択でコマンドプロンプトを起動します。

「オプションの選択」→「トラブルシューティング」→「オプション詳細」→「コマンドプロンプト」

管理者権限でコマンドプロンプトが起動します。
```:管理者:X:\Windows\System32\cmd.exe
Microsoft Windows [Version 10.0.22621.525]
(c) Microsoft Corporation. All rights reserved.

X:\Windows\System32>
```

X:\Windows\System32フォルダにはutilman.exeは存在しませんし、ログイン画面で起動されるのはシステムドライブのWindows\System32フォルダのutilman.exeなので、システムドライブのWindows\System32フォルダに移動しておくとよいでしょう。

```:管理者:X:\Windows\System32\cmd.exe
X:\Windows\System32>C:
C:\>

C:\>cd \Windows\System32
C:\Windows\System32>
```
## コマンドプロンプトcmd.exeをutilman.exeとしてコピーします。
このフォルダ上でutilman.exeをバックアップしてコマンドプロンプトcmd.exeをutilman.exeとしてコピーします。
```:管理者:X:\Windows\System32\cmd.exe
C:\Windows\System32>ren utilman.exe utilman.org

C:\Windows\System32>copy cmd.exe utilman.exe
        1 個のファイルをコピーしました。
```

これで準備OKです。トラブルシューティング用のコマンドプロンプトを抜けて、オプションの選択に戻ってWindows11の通常実行に進行します。

# windowsログイン画面でコマンドプロンプトutilman.exeを起動

Windowsログイン画面の右下の電源アイコンの左となりの大の字になっているひとのアイコンをクリックするとコマンドプロンプトが起動します。

```:C:\Windows\System32\utilman.exe
メッセージ番号 0x2350 のメッセージ文が Application のメッセージ ファイルに見つかりません。
(c) Microsoft Corporation. All rights reserved.
このコマンドを処理するにはメモリ リソースが足りません。
C:\Windows\System32>

```
この状態で下記のnet userコマンドでパスワードをリセットします。
userの次のuserはデフォルトのuserアカウントです。（Administratorグループ）ログイン画面には別名で表示されている場合があります。新規に追加したアカウントでフルネームと物理名がわかっている場合は物理名を指定してください。
*****は新しいパスワードをタイプします。下図は伏字になっていますが実際はそのままエコーされます。

```:C:\Windows\System32\utilman.exe
C:\Windows\System32>net user user *****
コマンドは正常に終了しました。
C:\Windows\System32>
```

# おわりに
ほとんど自分用の備忘録ですが、なにかのお役に立てれば幸いです。現時点ではこの手順でリセットできましたが、のちのセキュリティアップデートでこの手順は無効化されるかもしれません。
Raspberry Pi 5 の GPIO14/15を UART(/dev/ttyAMA0) として扱う設定

確認環境: Raspberry Pi 5 (8GB) + bookworm

```bash:有効化
sudo raspi-config nonint do_serial_hw 0
sudo raspi-config nonint do_serial_cons 1
sudo systemctl reboot
```

```bash:再起動後のチェック
# ttyAMA0 デバイス認識の確認
$ dmesg | grep ttyAMA
[    0.010493] 107d001000.serial: ttyAMA10 at MMIO 0x107d001000 (irq = 15, base_baud = 0) is a PL011 rev2
[    0.530390] 1f00030000.serial: ttyAMA0 at MMIO 0x1f00030000 (irq = 125, base_baud = 0) is a PL011 AXI

# /dev/ttyAMA0 の存在の確認
$ ls -lF /dev/ttyAMA*
crw-rw---- 1 root dialout 204, 64 Jun  3 21:38 /dev/ttyAMA0
crw-rw---- 1 root dialout 204, 74 Jun  3 21:38 /dev/ttyAMA10

# GPIO14, GPIO15 の状態
$ pinctrl get 14-15
14: a4    pn | hi // GPIO14 = TXD0
15: a4    pu | hi // GPIO15 = RXD0
```

```bash:/dev/ttyAMA0の使用
screen /dev/ttyAMA0 9600
cu -l /dev/ttyAMA0 -s 9600
```

### raspi-config が行っていること

`raspi-config` は実際のところ、 `config.txt` や `cmdline.txt` を編集しているだけです。

```diff:do_serial_hw 0 の結果
$ sudo diff -u ./config.txt.orig /boot/firmware/config.txt
--- ./config.txt.orig   2024-06-03 21:32:55.159999986 +0900
+++ /boot/firmware/config.txt   2024-06-03 21:35:36.000000000 +0900
@@ -46,3 +46,4 @@
 otg_mode=1

 [all]
+dtparam=uart0=on
```

```diff:do_serial_cons 1 の結果
$ sudo diff -u ./cmdline.txt.orig /boot/firmware/cmdline.txt
--- ./cmdline.txt.orig  2024-06-03 21:32:59.519999983 +0900
+++ /boot/firmware/cmdline.txt  2024-06-03 21:35:40.000000000 +0900
@@ -1 +1 @@
-console=serial0,115200 console=tty1 root=PARTUUID=dcb19b3b-02 rootfstype=ext4 fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles cfg80211.ieee80211_regdom=JP
\ No newline at end of file
+console=tty1 root=PARTUUID=dcb19b3b-02 rootfstype=ext4 fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles cfg80211.ieee80211_regdom=JP
\ No newline at end of file
```

## 戻し方

```bash
sudo raspi-config nonint do_serial_hw 1
sudo raspi-config nonint do_serial_cons 0
sudo systemctl reboot
```

## 解説

TODO: これでなぜ `/dev/ttyAMA0` ができて動くのかは、後日書く

## あとがきと参考情報

* [Configure UARTs - Raspberry Pi Documentation](https://www.raspberrypi.com/documentation/computers/configuration.html#configure-uarts)
* [raspi-config - Raspberry Pi Documentation](https://www.raspberrypi.com/documentation/computers/configuration.html#serial-nonint)
* [Raspberry Pi 5でGPIOするPythonコード - Seeed K.K. エンジニアブログ](https://lab.seeed.co.jp/entry/2024/04/20/120000#UART)
    * 「`3 -> I5 -> No -> Yesを選択すればOK`」のコマンドライン化と、何が行われているのかを書いただけのブログです、スミマセンスミマセン。

EoT
docker-composeのcommandで、複数コマンドを実行する方法

# はじめに
　docker-compose.ymlのcommandで、複数のbashコマンドを記述する方法を紹介する。gitlab-ci.ymlなどにも応用可能。
 
# 動作確認環境
* Ubuntu 20.04

# 方法

commandキーの後ろに、bash -c と```|```を併用する。

```bash
command:
  - /bin/bash
  - -c
  - |
    echo "Command 1"
    echo "Command 2"
```

YAMLの```|```は、改行がそのまま解釈される。よって、上記は上から順番の処理されてい以下のような結果になる。

```bash
Command 1
Command 2
```

## 注意: ```>```との```|```の違い

```>```でも、複数コマンドを実現できるが、```>```では、**改行=空白**扱いとなるため、```&&```で連結する必要があり不向き。下記のようなwhile文はエラーとなる。

```bash
command: >
      /bin/bash -c "echo 'Command 1' &&
      while true; do echo 'Command 2'; sleep 1s; done"
```

エラー内容
```bash
for: -c: 行 1: 構文エラー: 予期しないファイル終了 (EOF) です
```

```|```なら実行可能。


```bash
command: 
  - /bin/bash
  - -c
  - |
    echo 'Command 1'
    while true; do echo 'Command 2'; sleep 1s; done
```

# まとめ
　docker-composeのcommandで、複数コマンドを実行する方法を紹介した。bash -c と```|```を使うことで、可読性を上げて複数行コマンドを記述することができた。

# 参考

https://stackoverflow.com/questions/55767496/docker-compose-run-multiple-commands-for-a-service

https://devlights.hatenablog.com/entry/2021/11/04/073000

# おまけ：Microsoft Copilotに聞いた解説 (```>```と```|```の違い)

非常にわかりやすい解説でした。

質問

> YAMLの複数コマンドの記述について教えてください。
\> と \| の違いは何ですか？


回答

>YAMLでは、複数行の文字列を記述するために > と | という2つの記号が使われます。これらの記号は、それぞれ異なる方法で改行を扱います。

>\>: この記号は “フォールド” を意味します。複数行の文字列を1行に折りたたむ（つまり、改行をスペースに置き換える）ために使用されます。例えば、以下のように使用します：
```yaml
key: >
  これは
  複数行の
  文字列です
```

> 上記のYAMLは次のように解釈されます："これは 複数行の 文字列です"

|: この記号は “リテラル” を意味します。複数行の文字列をそのまま保持し、改行も保持します。例えば、以下のように使用します：
```yaml
key: |
  これは
  複数行の
  文字列です
```
> 上記のYAMLは次のように解釈されます：
```bash
"これは\n複数行の\n文字列です\n"
```
> したがって、YAMLで複数のコマンドを記述する場合、それぞれのコマンドが新しい行に来るように | を使用することが一般的です。例えば：
```yaml
commands: |
  echo "Command 1"
  echo "Command 2"
```
> 上記のYAMLは、2つのechoコマンドを順番に実行します。それぞれのコマンドは新しい行に配置されます。このように、| はシェルスクリプトや複数行のコマンドを記述するのに便利です。一方、> は長い文章やメッセージを記述するのに便利です。それぞれの記号が適している状況を理解することが重要です。それぞれの用途に応じて適切な記号を選択してください。
Unity 6 PreviewでColor32にIEqutable<Color32>が実装された

Unity 6000.0.3f1にて、[Color32構造体](https://docs.unity3d.com/6000.0/Documentation/ScriptReference/Color32.html)が[`IEquatable<Color32>`](https://learn.microsoft.com/ja-jp/dotnet/api/system.iequatable-1?view=net-8.0)を実装しました。

[リリースノート](https://unity.com/ja/releases/editor/whats-new/6000.0.3)では、

> Scripting: Added IEquatable support to Color32.

と紹介されています。

こちらのアップデートは、タイミング的にUnity Forumのユーザーからの[Feature Request](https://forum.unity.com/threads/color32-should-implement-iequatable-color32.1589232/
)がきっかけのようにみえます。そのUnity Forumの投稿によると、Color、Vector2、Vector2IntなどはUnity 2017で`IEquatable<T>`が実装されたけど、Color32には今まで実装されていなかったらしい・・・（まじで？）

https://forum.unity.com/threads/color32-should-implement-iequatable-color32.1589232/

GitHubの「[Unity-Technologies/UnityCsReference](https://github.com/Unity-Technologies/UnityCsReference)」の差分でも、Color32が`IEqutable<Color32>`を実装したことを確認できます。

https://github.com/Unity-Technologies/UnityCsReference/commit/1d7b2b49b93ea5773aa4e8dfa504e3c1533ce282#diff-42ccd11c5f9b508fe61f02c9ab55d18748a35075cebeb614e2cc47eae00ef334R111-R123

ナイスユーザーフィードバック & フィーチャーリクエスト！

「Unity 6 Preview」、こんな感じの機能とか、気がついたらどんどんフィードバックやフィーチャーリクエストを送りたいですね。
ローカルからリモートサーバーへファイルをアップロード

今回はWindowsPCからLinuxサーバーに送信
# scpコマンドを使用
### scpコマンド
```cmd
scp -r [元ファイルorフォルダ] [先ユーザー名]@[先IP]:[先ディレクトリパス]
```
### scpコマンド（鍵ファイル指定実行）
```cmd
scp -r -i [秘密鍵ファイル] [元ファイルorフォルダ] [先ユーザー名]@[先IP]:[先ディレクトリパス]
```
クラスなしむき出しmainのjavaを試してみた

### サンプルソース

```sample.java
void main(String[] args){
        System.out.println("hoge");
}
```

### 実行結果

```
$ java --enable-preview --source 21 sample.java
Note: sample.java uses preview features of Java SE 21.
Note: Recompile with -Xlint:preview for details.
hoge
```

### Javaのバージョン

```
$ java --version
openjdk 21.0.2 2024-01-16
OpenJDK Runtime Environment (build 21.0.2+13-Ubuntu-120.04.1)
OpenJDK 64-Bit Server VM (build 21.0.2+13-Ubuntu-120.04.1, mixed mode, sharing)
```

### 解説

- 今どきのJava（今回はopenjdk 21）はjavaソースをそのまま実行できる
- ちなみにopenjdk 21はUbuntu20のaptで素直に入った
- opendk21であっても、クラスなしのmainむき出しは構文エラーになるが、`--enable-preview --source 21 ` のコマンドラインオプションで、プレビュー機能が使える

### 感想

- 今更だけどhellowordが簡単というのはとてもいい
- ただしまだプレビュー機能なのでしばらくは本番では使わないほうが良さそう
- そもそもJavaという言語自体が寿命の長いプロジェクトで使われるため、陽の目をみることはほとんどないかも
Qiita Engineer Festa 2024 投稿記事一覧

# Qiita Engineer Festa 2024 に参加！

こんにちは、テラりんです。
さて、23年ののAdvent Calendarに引き続き、今回のEngineer Festaも完走賞を狙っていきたいと思います。

今回も記事一覧を毎日以下に追加していきますので、全ての記事にご一読いただけると幸いです。

## とこでも好みの環境を整えたいという話

投稿日：06/10・1日目

https://qiita.com/0_terarin_0/items/603c73e2b54e7d2fb224
【Reactアプリ100本ノック】12 Gallery

![gallery.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/30de184b-088a-212e-b59e-6cdd75682d78.png)

# はじめに

<h3>こんにちは！！ Watanabe Jin (@Sicut_study)です！</h3>

https://qiita.com/Sicut_study/items/78910cd8d103b8d45a73

こちらの記事が嬉しいことに多くの方に見ていただきました。
そこで**React**が多くの初心者の方に注目されているんだなということを実感させられました。

私の記事では何度も言っている通り

<font color="red"><h4>最速で学ぶならとにかく何か作る</h4></font>

というのが大事になってきます。そこで **「Reactアプリ100本ノック」** というのに挑戦していこうかと思います。徐々に難易度を挙げていってどこまでお題を作りきれるかの腕試しでやっていただければと思います。

今回はライブラリを使って便利に作れることを体験していきます

# 前回のお題

https://qiita.com/Sicut_study/items/3bfdce97ca51b609eb02

# Reactアプリ100本ノックルール

- 主要なライブラリやフレームワークはReactである必要がありますが、その他のツールやライブラリ（例: Redux, Next.js, Styled Componentsなど）を組み合わせて使用することは自由
- TypeScriptを利用する
- 要件をみたせばデザインなどは自由

# 12. Gallery

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/f4d6fcd4-25f2-cdd2-2ce3-15dc948c6a62.png)


## 問題

画像ギャラリーを作成します

## 目的

ブログサイトやECサイトなどで必要になるギャラリーを作ります
ライブラリで便利に作成できる体験をします

## 達成条件

- 画像ギャラリーが表示されている
- react-image-galleryを利用して実装する

## 実際に解いてみた

![Peek 2023-12-06 21-05.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/45a1b4a0-06ff-5ef7-12f7-c88e9b5d9b2b.gif)

### 利用技術

- React
- TypeScript
- Vite
- Emotion
- react-image-gallery


解答時間 : 0.5時間

今回のお題は以下のライブラリを利用して作ります

https://www.npmjs.com/package/react-image-gallery

このライブラリがものすごく優秀なのでライブラリの利用方法がわかっていれば、すぐにお題が終わるかと思います。

最近難しいお題が多かったので息抜きになりますね。

# 次のお題

Comig Soon...

# おわりに

ここまで読んでいただけた方はいいねとストックよろしくお願いします。
@Sicut_study をフォローいただけるととてもうれしく思います。

また明日の記事でお会いしましょう！

# JISOUのメンバー募集中！
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
実践的なカリキュラムで、あなたのエンジニアとしてのキャリアを最短で飛躍させましょう！
興味のある方は、ぜひホームページからお気軽にカウンセリングをお申し込みください！
▼▼▼

https://projisou.jp
privateVPC作成

```

AWSTemplateFormatVersion: "2010-09-09"
Description: 
  VPC and Subnet Create
Metadata: 
  "AWS::CloudFormation::Interface": 
    ParameterGroups: 
      - Label: 
          default: "Project Name Prefix"
        Parameters: 
          - atai
      - Label: 
          default: "Network Configuration"
        Parameters: 
          - VPCCIDR
          - PrivateSubnetCIDR
    ParameterLabels: 
      VPCCIDR: 
        default: "VPC CIDR"
      PrivateSubnetIDR: 
        default: "PrivateSubnet CIDR"

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  atai:
    Type: String

  VPCCIDR:
    Type: String
    Default: "10.1.0.0/16"

  PrivateSubnetCIDR:
    Type: String
    Default: "10.1.200.0/24"

Resources: 
# ------------------------------------------------------------#
#  VPC
# ------------------------------------------------------------#
# VPC Create
  VPC: 
    Type: "AWS::EC2::VPC"
    Properties: 
      CidrBlock: !Ref VPCCIDR
      EnableDnsSupport: "true"
      EnableDnsHostnames: "true"
      InstanceTenancy: default
      Tags: 
        - Key: Name
          Value: !Sub "${atai}-vpc"
# ------------------------------------------------------------#
#  Subnet
# ------------------------------------------------------------#          
# Private RouteTable Create
  PrivateRouteTable: 
    Type: "AWS::EC2::RouteTable"
    Properties: 
      VpcId: !Ref VPC 
      Tags: 
        - Key: Name
          Value: !Sub "${atai}-private-route"

# ------------------------------------------------------------#
# Routing
# ------------------------------------------------------------# 
# None

# ------------------------------------------------------------#
# RouteTable Associate
# ------------------------------------------------------------# 
# PrivateRouteTable Associate Subnet
  PrivateSubnetCRouteTableAssociation: 
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties: 
      SubnetId: !Ref PrivateSubnet
      RouteTableId: !Ref PrivateRouteTable

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#                
Outputs:
# VPC
  VPC:
    Value: !Ref VPC
    Export:
      Name: !Sub "${atai}-vpc"

  VPCCIDR:
    Value: !Ref VPCCIDR
    Export:
      Name: !Sub "${atai}-vpc-cidr"

# Subnet
 
  PrivateSubnet:
    Value: !Ref PrivateSubnet
    Export:
      Name: !Sub "${atai}-private-subnet"

  PrivateSubnetCIDR:
    Value: !Ref PrivateSubnetCIDR
    Export:
      Name: !Sub "${atai}-private-subnet-cidr"

# Route
  PrivateRouteTable:
    Value: !Ref PrivateRouteTable
    Export:
      Name: !Sub "${atai}-private-route"




```

VPC作れるところまで確認
robloxでassistant その102

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
梯子を作れ。

# 手順
- ReplicatedFirstに、LocalScriptを追加。
- スクリプトを書く。

```


local center = Vector3.new(0, 0, -20)
local stepCount = 10

for i = 1, stepCount, 1 do
	local scaffold = Instance.new("Part", workspace)
	scaffold.Size = Vector3.new(5, 1, 1)
	scaffold.Anchored = true
	scaffold.Position = center + Vector3.new(0, i * 2, 0)
end


  
```

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/15136e3c-50f7-3216-8ccf-d98f90d4aee4.png)


以上。
PowerShellでちょっと複雑なフォルダ階層を作ってみる

# はじめに
PowerShellの練習がてら、ちょっと複雑なフォルダ階層を作る関数を実装してみました。
現時点ではとりあえずの備忘録です。暇があればもっと汎用的に使えるよう書き直したいところ。

```
folder
├─fuga
│  ├─No.1
│  ├─No.2
│  └─No.3
├─hoge
│  ├─No.1
│  ├─No.2
│  └─No.3
└─piyo
    ├─No.1
    │  ├─bar
    │  ├─baz
    │  └─foo
    ├─No.2
    │  ├─bar
    │  ├─baz
    │  └─foo
    └─No.3
        ├─bar
        ├─baz
        └─foo
```
第一階層：folder。一番大きなディレクトリ。
第二階層：hoge/fuga/piyo。ここは固定で作成します。
第三階層：No.1~No.x。キー入力を受け取り、任意の数だけ作成します。
第四階層：foo/bar/baz。piyoディレクトリの下にだけ、さらに深い階層を作成します。

# サンプルコード
```powershell
function makeFolders {
    ("hoge","fuga","piyo") | new-item -path "./folder" -itemtype directory -name {$_} -force
    1..$n | new-item -path "./folder/*" -itemtype directory -name {"No." + $_} -force
    ("foo","bar","baz") | new-item -path "./folder/piyo/*" -itemtype directory -name {$_} -force
}

# キー入力で任意の数字を受けとる
$n = read-host "フォルダを作りたい個数を入力してください"

# フォルダを作る
makeFolders | out-null

# 実行結果を出力
write-host "`n下の通りフォルダを作りました`n"
tree "./folder"
```

# ポイント
## function
当たり前すぎてどこにも書いてないレベルですが、関数は使う場所より上に定義する必要があります。
もっとレベルの高い説明は [こちら](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_functions?view=powershell-7.4)

## -force オプション
new-item のオプションに `-force` を指定しています。
この記述があることにより、既にフォルダがある場所に同名のフォルダを作成した場合に、上書きされる（＝エラーにならない）ようになります。
今回の例くらいなら特に気にする必要はありませんが、消えたら困るデータがある場合は注意して使ったほうが良いかも？

## out-null
関数の内部にある `new-item` などを実行するといろいろコンソールに表示されますが、邪魔なので表示しないようにしています。
引数を渡しているわけでもないのに処理を関数に切り出しているのも、この非表示にしたい意図があるためだったりします。

詳しくは [こちら](https://tex2e.github.io/blog/powershell/New-Item)

## エスケープ文字
多くのプログラミング言語では `\`（バックスラッシュ）でエスケープすることが多い印象ですが、PowerShellでは ` （バッククオート）を使います。

詳しくは [こちら](https://tex2e.github.io/blog/powershell/escape-sequence)

# 参考
[New-Item](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.management/new-item?view=powershell-7.4)
[PowerShellでNew-Itemの出力結果を表示させない方法](https://tex2e.github.io/blog/powershell/New-Item)
[PowerShellのエスケープシーケンス](https://tex2e.github.io/blog/powershell/escape-sequence)
MVCモデルの基礎知識

# はじめに

こんにちは！
社会人一年目の石川です。
記事をご覧いただきありがとうございます。

今回は、MVCモデルについてまとめました。


## 目次
1. [MVCモデルとは？](#mvcモデルとは)
1. [MVCモデルのそれぞれの役割](#mvcモデルのそれぞれの役割)
・[M(モデル)](#mモデル)
・[V(ビュー)](#vビュー)
・[C(コントローラ)](#cコントローラ)
3. [MVCモデルのメリットとデメリット](#mvcモデルのメリットとデメリット)
・[MVCモデルのメリット](#mvcモデルのメリット)
・[MVCモデルのデメリット](#mvcモデルのデメリット)
4. [最後に](#最後に)

## MVCモデルとは？
MVCモデルはアプリ開発においてコードを整理する考え方のことです。

MVCは、モデル（Model）、ビュー（View）、コントローラー（Controller）の頭文字を取ったもので、それぞれの役割を明確に分離します。この3つが独立して連携することで、コードの管理が容易になり、開発効率が向上します。

つまり、役割によってどこに何のプログラムを書くかルール化された開発方法の一つです。

:::note info
効率を最優先する場合や、開発スタッフの負担を軽減する場合に適した開発方法
:::


## MVCモデルのそれぞれの役割
次は「MVC」のそれぞれの役割についてです。 MVCの役割は色々ありますが、ここでは一般的に考えられている役割について紹介していきます！

### M(モデル)

モデルではDB操作に関わる処理を作ります。

タスク（やること）を登録するプログラムを例にします。
アプリの完成画面には、既に登録されているタスクの一覧が表示されています。

このようなアプリを作る場合、DBに登録されているタスクのデータを取得し、画面に表示する指令をコンピューターに出さなければなりません。このとき、DBから取得する指令を書く場所がモデルです。



### V(ビュー)
ビューでは画面を表示する処理を作ります。

ユーザーが見る画面を作ります。モデルの説明同様、タスクを登録するアプリを再度例にします。モデルではデータを取ってきただけなので、取ってきたデータを表示する画面を作る必要があります。それを行うのがビューとなっています。どこに何が入ってくるかがわかるように、画面の元となる素材を作るイメージです。

### C(コントローラ)
コントローラではモデルとビューの橋渡しとなる処理を作ります。

モデルでデータ取得、ビューで画面の作成などを指示するのがコントローラです。つまり、モデルとビューの処理をコントローラが制御してコンピュータ画面にその結果を表示させています。コントローラがモデルとビューとコンピュータ画面の間で橋渡しをしているイメージです。

:::note
コントローラでは例えば次のような指令を出します。
1．モデルに指示を出して、DBからデータを取得
2．取得したデータをビューに渡して、画面を作成
3．パソコンの画面に、ビューで作った画面を表示する
:::

## MVCモデルのメリットとデメリット

### MVCモデルのメリット

#### それぞれの役割が明確化されている
モデル、ビュー、コントローラに役割が分かれているので、どこに何を書けばいいかわかりやすいです。そのため、どんなファイル構成にしてアプリを作ろうかを考えなくてもアプリを作ることができ、効率的に開発ができます。

#### 保守性が高い
アプリは開発してから機能を追加することはよくあります。そのとき、プログラムに修正が必要となるケースもあります。このような場合でも、機能を追加するためにどこに何を書いたら良いか役割がわかれているので、見るだけで判断しやすくなります。

#### 分担して開発しやすい
モデル担当、ビュー担当、コントローラ担当のように分担することができます。画面のデザインが得意な人、DB処理が得意な人のように、分担できるので1つの機能を作り終えるまでにかかる時間も少なくなります。このようなことから結果として効率的に開発できるようになります。

### MVCモデルのデメリット

#### 情報データの管理が大変
それぞれの機能を書き分ける必要があるため、コード記述に制約が増えることにつながります。場合によってはかえって時間がかかってしまう可能性もあります。

#### コントローラーの処理が大変
機能拡張により、データベースとのやり取りやデータ変換を行うモデル部分やその仲介をするコントローラ部分に負担がかかることで、処理速度が遅くなってしまう可能性が生じます。

#### 「V」と「C」の依存性が高い
コントローラからモデルへの支持が増大しすぎることで、モデルのコントローラへの依存度が高くなってしまい、MVCモデルのメリットである機能ごとの独立性を保てなくなる恐れがあります。


## 最後に
今回はMVCモデルについてまとめました。
PHPの「Laravel」やRubyの「Ruby on Rails」など、非常に多くのフレームワークがこのMVCモデルを採用しているので、理解を深めて開発効率を上げられるように頑張ります！
最後まで読んでいただきありがとうございました。
Python 拡張のアップデート手順

:::note warn
互換性を気にする場合は個別対応してください。
:::

## pip でインストールした Python 拡張

```bash:pip_update.sh
### pip 本体の更新
pip3 install --break-system-packages --upgrade pip

### 更新が必要なパッケージリストの取得
pkgs=`pip3 list --outdated | grep wheel | awk '{print $1}'`
pkgs_array=($pkgs)

### 要更新パッケージを個別に更新
for pkg in "${pkgs_array[@]}"; do
    echo pip3 install --break-system-packages --upgrade ${pkg}
    pip3 install --break-system-packages --upgrade ${pkg}
done
```


## conda でインストールした Python 拡張

```bash:conda 本体のアップデート
conda update -n base conda
```

```bash:conda でインストールした全パッケージをアップデート
conda update --all
```
UbuntuにGnomeShell拡張機能を入れる方法

UbuntuにGnomeShell拡張機能を入れる方法を解説していきます

## 環境
バージョン - Ubuntu24.04LTS
カーネル - 6.8.0-31-generic

## 拡張機能を入れる際の注意
Ubuntuを最新バージョンにアップグレードした際に、
GnomeShell拡張機能の多くは互換性が失われるので、注意してください

## 1. 下準備
まずは下準備として、必要なアプリをダウンロードします
ターミナルで以下のコマンドを順に実行してください
```
sudo apt-get update
sudo apt install gnome-shell-extension-manager
```

そうすることで、アプリライブラリに、「拡張機能」というのが追加されます
これで、下準備は完了です

## 2. 拡張機能をインストール
アプリライブラリから「拡張機能」を開きます
上のタブから「探す」を選んでください（下の画像のようになります）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3691296/aaeecae6-46d6-b04b-4d65-8928c04ff0ef.png)

そしたら、自分が入れたい拡張機能を選択して、（記事では Blur my Shellを使います）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3691296/09b10aec-1119-fd18-f5fe-44add722fede.png)

「インストール」を押します
これで、インストールが完了しました！

あとは、再ログインすれば、拡張機能が適用されます
O_2_0_Node-REDの基本_flipper's circuit Project -電子工作人口を増やすためのプロジェクト-

ここでは、Node-REDの画面と基本的な使い方について説明します。
Node-REDのインストール方法については[こちら](https://qiita.com/comchiki66/items/4127c46c1703d9740964)の記事を参照ください。

# 1 画面の説明

まずは画面のエリアについて。

左から **「パレット」「ワークスペース」「ノード情報ウィンドウ/デバッグ・ウィンドウ」** です。
順番に説明します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308477/63e65d86-e6fd-dfde-4f72-0db63a06919f.png)

## 1-1 パレット

様々な機能をもつ「ノード」が配置されています。
カテゴリごとに利用できる「ノード」が一覧で表示され、「オリジナルのノード」も追加可能です。

## 1-2 ワークスペース

「フロー」（プログラム）を作る場所です。
「パレット」から「ノード」をドラッグ＆ドロップして配置し、「ノード」同士をつなぐことで「フロー」を作っていきます。

## 1-3 ノード情報ウィンドウ/デバッグ・ウィンドウ

「ノード情報ウィンドウ」は、操作時の様々な情報が表示されます。例えば、「パレット」で「ノード」をクリックすると、そのノードの情報が表示され、「ワークスペース」にある「ノード」や「フロー」をクリックした場合は、設定された値の詳細が表示されます。
また、「debugノード」を使っている場合は、「デバッグ・ウィンドウ」としても機能します。

# 2 「ノード」と「フロー」

## 2-1 ノード

「ノード」は、処理をする”点”です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308477/375c59e6-a8e4-7861-dbb9-97f9f9e23e6e.png)

下図の赤丸の部分が「端子」（ポート）です。
「端子」から、ほかのノードにつなぐことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308477/a3d93ac2-93c9-b6ae-b8ae-046173ecd1a6.png)

## 2-2 フロー

「フロー」とは、「ノード」をつないで一連の流れにしたものです。「フロー」の処理は、左から右に流れていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308477/6724ec62-9099-3d82-35cf-b04a535aff03.png)

# 3 「フロー」の作り方

「パレット」からノードを選択し、「ワークスペース」にドラッグ＆ドロップします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308477/13938c56-02f0-8e02-ead9-818b2f87b046.png)

処理の流れでノード同士をつないでいきます。

ノードをダブルクリックで「プロパティ設定」の画面になります。処理の詳細はここから設定できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308477/1043fbe2-154b-392f-62c1-ea0d4c642a74.png)

# 4 「ノード」の種類

## 4-1 入力ノード

「入力ノード」は、端子が右についています。
「ノード」のもつ条件が当てはまると、「右のノード」にデータを送ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308477/8af7d1a2-60b6-ffd6-be4f-a9067f0a68eb.png)

## 4-2 機能ノード

「機能ノード」は、端子が右と左の両方に付いています。
「左のノード」からデータが来ると、自分のノードが持つ処理を行い「右のノード」にデータを送ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308477/ff50c28a-d2df-d9ad-1cef-c2981b86cace.png)

## 4-3 出力ノード

「出力ノード」は、端子が左に付いています。
左のノードからデータが来ると、自分のノードがもつ処理を行い、「フロー」が終わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308477/4ce1136f-73a5-258b-1129-062808d8951a.png)

ここまでで基本の説明は終わりです。
次は実際のフローを組みながら、使い方を説明します。

[トップへ戻る](https://qiita.com/drafts/615c0c8cb87cd0c5c575/edit)
ChatGPTによるリアルタイムテキスト化

はじめまして、小磯と申します。
ChatGPTという言葉が、ネットで色々取り上げられています。
そのChatGPTを業務で利用する場合は、どうするのかを紹介したいと思います。

# ChatGPTによるリアルタイムテキスト化とは
ChatGPTを利用し、音声データをテキストデータとしてアウトプットが可能。

## 1.サーバーの構成
サーバを構築する場合、以下の2パターンあります。

①オンプレミス（ハードウェアにて準備するサーバ）
- 通話録音サーバ
- 音声認識サーバ
- DBサーバ<br>
- WEBサーバ<br>
- 認識キャプチャサーバ（他拠点がある場合、他拠点に設置）

②クラウド
- キャプチャサーバ
- 認識サーバ
- DBサーバ
- WEBサーバ
- ATSサーバ
  
## 2.事前学習
ChatGPTへ用語等を学習させる必要があり、事前に学習させる場合は主に3つのデータ形式で読み込ませます。
- CSV
- PDF
- URL

## 3.テキストファイル出力の種類
音声をテキスト化する種類として、以下の2パターンあります。
①通話中の音声をテキストデータをテキスト化
- 通話終了後、数分以内でサーバーへテキストデータ保存
　　　(通話の分数や文字数により、処理時間が変更)

②録音システムのデータを読み込みテキスト化
- 通話終了後の録音データを読み込み、テキストデータとして保存。
今度①を導入する予定です。

### 4.補足
3-1 テキスト化したファイルを振り分ける。
　　　利用する場合、ライセンスが必要となり任意のアカウントを作成します。
　　　サーバ上でアカウント毎にフォルダを作成し、テキストファイルを振り分け、誰が対応したかが明確になる。
　　　同じアカウントを同時利用は出来ませんが、利用している時間帯で誰が対応したかの確認が可能。
3-2 ChatGPTへ未学習部分の追加を行う。
　　事前学習を行っているが、業種により新しい名称が出てくるためメンテナンスを実施する必要がある。
　　メンテナンスとして上記にある「2.事前学習」と同じ対応が必要です。

## まとめ
ChatGPTの用途は、様々な分野で取り込まれています。
ChatGPTを使うことにより、会議の議事メモ作成や録音データを聞くことが少なくなり、時間短縮に繋がります。
今後、問い合わせ窓口等はほぼ無人化となりモンスタークレーマーの減少につながると思います。
窓口の担当は、テキスト化されたファイルを一覧化したり、よくある質問として整理する作業を行うのみになります。
次回は、問い合わせ窓口受け側の利用について纏めようと思います。

以上、小磯でした。
StoryBook で "invariant expected app router to be mounted" というエラーが出た時の解決方法

![スクリーンショット 2024-06-03 20.00.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764154/a8955284-66a5-e719-cc0f-14b467c0da11.png)

先日 Next.js(App Router) プロジェクトで Storybook を利用している際に、上記の`invariant expected app router to be mounted` というエラーに直面したので、解決方法を記載しておきます。

## エラーの原因
https://storybook.js.org/docs/get-started/nextjs#nextjs-navigation

Story で next/navigation を利用したコンポーネントをインポートしようとすると、エラーが発生するようです。この問題を解決するためには、appDirectory パラメータを true に設定する必要があります。

## エラー発生当時のコンポーネントと Story の状態
```tsx:ExampleComponent.tsx
import { ExampleComponent } from "./ExampleComponent";

import { Meta, StoryObj } from '@storybook/react'

const meta = {
  title: 'ExampleComponent',
  component: ExampleComponent,
} satisfies Meta<typeof ExampleComponent>

export default meta

type Story = StoryObj<typeof meta>

export const Default: Story = {
  render: () => (
    <ExampleComponent />
  )
}
```
```tsx:Example.stories.tsx
import { useRouter } from 'next/navigation'
import { useForm } from 'react-hook-form'

export const ExampleComponent = () => {

  const router = useRouter()
  
  const form = useForm()

  const onSubmit = (data) => {
    router.push('/some-route')
  }

  return (
    <form onSubmit={form.handleSubmit(onSubmit)}>
      {/* フォーム内容 */}
    </form>
  )
}
```

## 解決方法
上記でも説明しましたが、 `nextjs.appDirectory` パラメータを `true` に設定することで、このエラーを解決できます。
```tsx:ExampleComponent.tsx
import { ExampleComponent } from "./ExampleComponent";

import { Meta, StoryObj } from '@storybook/react'

const meta = {
  title: 'ExampleComponent',
  component: ExampleComponent,
  parameters: {
    nextjs: {
      appDirectory: true, 
    },
  },
} satisfies Meta<typeof ExampleComponent>

export default meta

type Story = StoryObj<typeof meta>

export const Default: Story = {
  render: () => (
    <ExampleComponent />
  )
}
```

また、プロジェクト全体で appDirectory を設定することもできます。`preview.ts` ファイルで以下のように設定を行います。
```tsx:preview
import { Preview } from '@storybook/react';

const preview: Preview = {
  parameters: {
    nextjs: {
      appDirectory: true,
    },
  },
};

export default preview;

```


## まとめ
Next.js の App Router を使用するコンポーネントを Storybook に追加する際には、特に `next/navigation` の `useRouter` や `usePathname` を使用している場合、`nextjs.appDirectory` パラメータを設定することを忘れないようにしましょう。これにより、コンポーネントが正しくレンダリングされ、`invariant expected app router to be mounted` エラーを回避できます。

この記事が、同じ問題に直面している他の開発者の助けになれば幸いです。
Raspberry Pi 5 におけるGPIO操作は `pinctrl` を使う (raspi-gpio後継コマンド)

Raspberry Pi のGPIO操作には [`pinctrl`](https://github.com/raspberrypi/utils/tree/master/pinctrl)を使いましょうという話です。

確認環境: Raspberry Pi 5 (8GB) + bookworm

https://github.com/raspberrypi/utils/tree/master/pinctrl

## Raspberry Pi 5 では、raspi-gpio コマンドがサポート外となった

Raspberry Pi 5 でGPIO操作コマンド `raspi-gpio` を実行すると、以下のように「`pinctrl` を使え」と指示されます。

```bash
$ raspi-gpio get
raspi-gpio is not supported on Pi 5 - use `pinctrl`
```

### pinctrl の出力

以下のようになります。

```bash
$ pinctrl
 0: ip    pu | hi // ID_SDA/GPIO0 = input
 1: ip    pu | hi // ID_SCL/GPIO1 = input
 2: no    pu | -- // GPIO2 = none
 3: no    pu | -- // GPIO3 = none
 4: no    pu | -- // GPIO4 = none
《省略》
```

`pinctrl help` を見てみると、コマンド形態は `raspi-gpio` と似ています。が、出力は前述の通り、かなり異なります。

ヘッダピンとして出ている40ピンに限定しての表示は `-p` を使います。

```bash
$ pinctrl -p
 1: 3v3
 2: 5v
 3: no    pu | -- // GPIO2 = none
 4: 5v
 5: no    pu | -- // GPIO3 = none
 6: gnd
 7: no    pu | -- // GPIO4 = none
 《省略》
 ```

 ピンに割り当てられている機能を確認するには `funcs` サブコマンドを使います。

 ```bash
 $ sudo pinctrl funcs 14-15
14, GPIO14, PWM0_CHAN2, DPI_D10, CTS4, SDA3, TXD0, SYS_RIO014, PROC_RIO014, PIO14, SPI5_SIO0
15, GPIO15, PWM0_CHAN3, DPI_D11, RTS4, SCL3, RXD0, SYS_RIO015, PROC_RIO015, PIO15, SPI5_SCLK
```

## `pinctrl` の使い方と出力の読み方

### GPIO の読み取り

```bash:準備: ピンをINPUTに設定
$ pinctrl -e set 10 ip pd
#=> 10: ip    pd | lo // GPIO10 = input
```

* `-e` は `set` サブコマンドの実行結果を表示(echo)してくれます。確認に便利です。

```bash:読み取り
# GPIO10 が Low だった場合
$ pinctrl get 10
#=> 10: ip    pd | lo // GPIO10 = input

# GPIO が High だった場合
$ pinctrl get 10
#=> 10: ip    pd | hi // GPIO10 = input
```

* `|` の左側がピンの設定状態です。ipはinput、pdはpull-down状態になります。詳しくは `pinctrl help` を見てください。
* `|` の右側の `lo` もしくは `hi` がピンの状態です。lo = Low(gpioコマンドなら0)、hi = High(gpioコマンドなら1)です。

```bash:ピンの解放
$ pinctrl -e set 10 no
#=> 10: no    pd | -- // GPIO10 = none
```

### GPIO の出力

準備は不要です。Output設定と同時に出力値を設定できます。

```bash
# GPIO10 を Low にする
pinctrl -e set 10 op dl
#=> 10: op dl pd | lo // GPIO10 = output

# GPIO10 を High にする
pinctrl -e set 10 op dh
#=> 10: op dh pd | hi // GPIO10 = output
```

### pinctrl get の出力を gpio コマンドと同様にする

awk コマンドを組み合わせれば、lo=0 hi=1 と読み替えが可能です。

```bash
$ awk --version
#=> GNU Awk 5.2.1, API 3.2, PMA Avon 8-g1, (GNU MPFR 4.2.1, GNU MP 6.3.0)
```

```bash
pinctrl get 10 | awk 'match($0, /\| (.+) \/\//, a){print (a[1]=="hi" ? 1 : 0)}'
```

* match で `|` と `//` という文字間の文字をキャプチャ
* キャプチャした文字をが hi だったら 1 、そうでなければ 0 を返す(三項演算子を利用)

```bash:実行例
$ pinctrl set 10 op pu # pull-up に設定
$ pinctrl get 10 | awk 'match($0, /\| (.+) \/\//, a){print (a[1]=="hi" ? 1 : 0)}'
#=> 1
$ pinctrl set 10 op pd # pull-down に設定
$ pinctrl get 10 | awk 'match($0, /\| (.+) \/\//, a){print (a[1]=="hi" ? 1 : 0)}'
#=> 0
```

## あとがき

[Wiring Piが無くなって、raspi-gpioコマンドを使いましょう](https://qiita.com/ma2shita/items/b11045717333bcd79d15)のエントリーで

> まあ Raspberry Pi のなかのひと(Serge-san)がメンテしてるので、長いこと使えるんじゃないでしょうか。

とかドヤってしまったが、使えなくなってしまったとは。見通しが甘かった、正直スマン。

EoT
Ansible Tips: handlerはis changedで良く無い？

handlerで行うことは、is changedで対応可能と思われる。

```
- name: 設定処理1
  task01:
  register: task01_result

- name: 設定処理2
  task02:
  register: task02_result

...

- name: 反映処理
  task0Z:
  when: |-
    task01_result is changed 
    or task02_result is changed
```

## handler構成に対するis changed対応構成のメリット
- handler, notifyといった概念が不要となり、学習コストが削減、かつplaybookがシンプルに

## is changed対応構成に対するhandler構成のメリット

- is changedの場合にはwhenにおけるor文が対応するtaskだけ必要となるが、handler構成ではその様なことはない
Government Marketplace GeM

Government e Marketplace GeM

Visit for more information:   https://gem.gov.in/training/training_module
In FY23-24, GeM welcomed 5,694 new #Startups, allowing them to list their disruptive products & services under 14 globally – recognised sub-sectors on the platform to ensure greater visibility of listed products.

This remarkable growth shows the immense trust placed by India’s Startup ecosystem in GeM.

Through initiatives like #GeMStartupRunway, GeM is dedicated to directly connecting innovative startups with government buyers.

To know more about GeM Startup Runway, visit - https://gem.gov.in/Startup_Runway

#GeMIndia
【AtCoder】順列の全探索

## ポイント
- next_permutation/prev_permutationを使う
- do-while文を使う
- 事前に配列をソートしておく

```C++
vector<int> arr = { 3, 1, 4, 7, 2 };

// 昇順探索
sort(arr.begin(), arr.end());
do {
  for (int x : arr) cout << x << " ";
  cout << endl;
} while (next_permutation(arr.begin(), arr.end()));

// 降順探索
sort(arr.rbegin(), arr.rend());
do {
  for (int x : arr) cout << x << " ";
  cout << endl;
} while (prev_permutation(arr.begin(), arr.end()));
```

例題：[典型90問032 - AtCoder Ekiden（★3）](https://atcoder.jp/contests/typical90/tasks/typical90_af)
Macのスクリーンショット保存先の変更方法

# デスクトップがスクショ画像でいっぱい！邪魔！！
MacOSのスクリーンショットのデフォルトの保存先はデスクトップです。
今回はスクリーンショットの保存先の変更方法を紹介します。

# スクリーンショットアプリからの変更
 実はMacにはデフォルトでスクリーンショットアプリがインストールされています。
 私は普段「command + shift + 4」でスクショを撮っていたので、このアプリの存在に気づいていませんでした笑
 以下、手順です。
 

### 1.スクリーンショットアプリを起動
Launchpadのその他フォルダから、スクリーンショットアプリを開きます。

![スクリーンショット 2024-06-03 13.14.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3485350/739f98ee-07a1-d76c-ab7f-913d4c781420.png)

### 2.保存先の変更
「オプション」メニューから、保存先を変更。
私は新たに「スクショ」フォルダを作成し、これを保存先に指定しました。

簡単ですね！
以上、MacOSでのスクショの保存先の変更方法でした！
プロセスって何？聞いたことあるけどよくわからない人へ

# はじめに
皆さんはプロセスについてどれくらい知っていますか？
業務で耳にすることはあっても、その実態が掴めずにいる方もいるのではないでしょうか？

私は2020年の4月に異業種からエンジニアへ転職して約４年ほどバックエンド開発に携わってきました。その中で、「プロセス」、「PID」、「プリフォーク」などのキーワードを耳にしましたが、雰囲気で理解している程度でした。

そんな時、PHPerKaigi2024で[「サーバーとは何かを理解して、コンテナ1つで実行しよう」](https://speakerdeck.com/sadnessojisan/sahatohahe-kawoli-jie-site-kontena1tuteshi-xing-siyou-phperkaigi2024)と言う登壇を拝見し、「プロセス？スレッド？よくわかんねぇけどもっと知りたい！」と思いました。そして、プロセスの解像度を上げる為に学習を決意しました。

その後、良い本を探していたところ[「なるほどUnixプロセス ― Rubyで学ぶUnixの基礎」](https://tatsu-zine.com/books/naruhounix)という本に出会いました。読んでみると他の人にもお勧めしたいと感じる本だったので、学んだことの一部を紹介し、プロセスの理解を深める手助けになればと思います。

# 実際に動かして試してみる

```shell:コンテナの外
docker run --rm --name ruby -it ruby /bin/bash
```

rubyのコンテナを立てて、bashを起動します。


```shell:コンテナの中
irb
```

`irb`は`Interactive Ruby`の略で、ターミナル上でRubyを1行ずつ実行できるようになります.


```ruby:irb
puts Process.pid
```

このコマンドでプロセスID(PID)を出力します。あとで確認するために、このPIDを覚えておいてください。


次に、別のタブや別ウインドウで同じrubyコンテナにアタッチしてみましょう。

```shell:コンテナの外
docker exec -it ruby bash
```

アタッチしたら、現在のプロセスを表示してみます。

```shell:コンテナの中
ps -A
```

```shell:ps -A の出力
  PID TTY          TIME CMD
    1 pts/0    00:00:00 bash
    7 pts/0    00:00:00 irb
    9 pts/1    00:00:00 bash
  394 pts/1    00:00:00 ps
```

`irb`がPID7で動いており、`puts Process.pid` で出力されたPIDと一致することが確認できます。


# まとめ
手順は簡単でしたね。このように、実際に動かしてみることで「こうなるんだ」という感覚を掴みつつプロセスへの理解を深めることができます。全てを完全に理解したわけではありませんが、この本を通じてプロセスというものの解像度が上がったと感じています。

「プロセスよくわかんないけど理解りてぇ〜」という人には非常にお勧めできる本です。興味を持った方はぜひ読んでみてください。

ちなみに以下のようなことが学べると書いてあります。
どれか一つでも当てはまったらぜひ！

:::note info
- ファイルディスクリプタって何？ どう動いているの？
- デーモンプロセスが必要な場合と、そうではない場合の判断の仕方
- fork(2)を使って子プロセスを生成する、とは？
- プロセスを終了させる方法が4つもある
- スクリプトから外部コマンドを実行する際の懸念事項とその回避方法
- プロセス生成のコストと落とし穴について
- 見よう見まねじゃない、シグナルハンドラの定義の仕方
- ResqueとUnicornの内部ではUnixプロセスをどう扱ってるか
:::

# 補足
私は普段PHPを触っていますが、Rubyで書かれていることに対して特に読みにくいと感じることはありませんでした。むしろ、少しRubyのコードに触れられるので一石二鳥かもしれません。

ちなみに、rubyのコンテナはDebian系のディストリビューションなので、パッケージは`apt`で追加します。

```shell
apt-get update
```

その後に、

```shell
apt-get install man
```

すると良いです。コンテナで簡単なコード書くことがあると思うので、`vim`とコマンドのマニュアルを見る為の`man`は入れておくと便利だと思います。

この記事を通じて、プロセスについての理解が深まり、興味を持っていただければ幸いです。

ちなみに英語だとタダで読めるっぽいです。
https://workingwithruby.com/