OmniAICreator/Qiita-1.07M huggingface dataset:
.envファイルを開発環境と本番環境で自動で切り替える（PHP）

## はじめに
PHP初学者がDB接続を学び、開発環境（XAMPP）と本番環境で秘匿情報の``.env``ファイルってどうればいいんだろう？ 開発環境から本番環境に切り替える際、コードを書き換えるの？
という疑問からようやくたどり着いた現時点でのベストプラクティスを残します（フレームワーク等は未着手）。

:::note warn
PHPで.envを読み込むためのvlucas/phpdotenv パッケージをComposerでインストールしてある前提です。
:::

## アウトライン
①.envファイルを2つ用意（開発用・本番用）
②2つの.envファイルの読み込みを切り替える記述
③ローカル（XAMPP）および本番サーバーで環境変数の設定

## 手順

##### ①.envファイルを2つ用意（開発用・本番用）
開発DB情報を記載した``.env.development``ファイルを用意（ここではルートディレクトリに配置します）。
```
APP_ENV=development
DB_HOST=localhost
DB_NAME=dev_db
DB_USER=dev_user
DB_PASSWORD=dev_password
```
本番環境DB情報を記載した``.env.production``ファイルを用意（ここではルートディレクトリに配置します）。
```
APP_ENV=production
DB_HOST=your.production.db.host
DB_NAME=prod_db
DB_USER=prod_user
DB_PASSWORD=prod_password
```
:::note warn
``.gitignore``に``.env.production``と``.env.development``ファイルを忘れすに記述します。
:::

##### ②2つの.envファイルの読み込みを切り替える記述
``APP_ENV``環境変数を使って、現在の環境（開発環境または本番環境）に応じて適切な``.env``ファイルを読み込む処理を作成します。
```php5
// 環境変数に基づいて読み込む .env ファイルを決定
$envFile = '.env.development';  // 暫定でデフォルトは開発環境用を読み込む

// 本番環境の場合（APP_ENV が 'production' の場合）は .env.productionを使用
if (getenv('APP_ENV') === 'production') {
    $envFile = '.env.production';
}

// .env ファイルの読み込み
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__, $envFile);
$dotenv->load();

// ここで環境変数にアクセスする
$host = $_ENV['DB_HOST'];
$dbname = $_ENV['DB_NAME'];
$user = $_ENV['DB_USER'];
$password = $_ENV['DB_PASSWORD'];

//$_ENV['DB_HOST'];はgetenv('DB_HOST');と書いても問題ない。
```

##### ③ローカル（XAMPP）および本番サーバーで環境変数の設定

XAMPP の場合、``APP_ENV``をdevelopmentに設定するために、Apacheの設定ファイルで設定を追加することができます。
以下にある``httpd.conf``ファイルを編集します。
```bash
/Applications/XAMPP/xamppfiles/etc/httpd.conf
```
以下の記述がある箇所を見つけて
```apache
<Directory "/Applications/XAMPP/xamppfiles/htdocs">
    Options Indexes FollowSymLinks Includes ExecCGI
    AllowOverride All
    Require all granted
</Directory>
```
以下の1行を追記します。
```apache
<Directory "/Applications/XAMPP/xamppfiles/htdocs">
    Options Indexes FollowSymLinks Includes ExecCGI
    AllowOverride All
    Require all granted
    SetEnv APP_ENV development
</Directory>
```
これで、開発環境（XAMPP）では``APP_ENV``は``.env.development``の方を読み込みます。

続いて、本番環境（本番サーバー）側の設定です。
``APP_ENV``を``.env.production``に設定するには、サーバーの環境設定や .bashrc、.htaccess などに設定を追加することができます。
本番環境のサーバーのweb公開用ディレクトリ（通常は``www``や``public_html``）を確認し、``.htaccess``ファイルに以下のように追記します（``.htaccess``ファイルがない場合は作ります）。
```apache
SetEnv APP_ENV production
```
``.htaccess``を保存して、web公開用ディレクトリにアップロードします。

以上完了です。
``.env``ファイルを書き換えせず、開発環境（XAMPP）と本番環境で、それぞれ動作を確認することができます。

## 補足
PHP初学者の僕が気になっていて放置していたポイントを整理しました。今後どなたかの参考になれば幸いです。
DatadogでJVMヒープメモリの推移とGC発生頻度を見える化してみた

:::note info
この記事はLITALICO Engineers Advent Calendar 2024 カレンダー3の7日目の記事です。
:::

## はじめに
QAエンジニアの@s12iです。
以前、DatadogでJVMヒープメモリの推移とGCの発生頻度を一度に見る方法がパッとわからず苦労したので、簡単な経緯と設定方法を残しておきたいと思います。小ネタです。
なお、前職ではSE（言語はおもにJava）をやっておりました。

## 経緯
- ある機能のデプロイ後、CPU使用率が上がっているとの共有がありました
- その機能はJavaで動いておりメモリも多く必要とする処理だったので、CPU使用率があがっている＝GCが多発しているのではと考え、根拠となる事実集めを行いました
- DatadogでJVMの情報を収集する設定などはすでに済んでいる状態でした（SREチームのみなさんありがとうございます）

## ダッシュボードの設定
さっそくですが以下がダッシュボードウィジェットの設定例です。
Event Overlaysを使って時系列データに加えたい情報を指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152950/f1fb7197-439b-bc0f-500c-19a1fbdacf02.png)


- Select your visualization
-> Timeseries
- Graph your data（JVMヒープメモリの推移）
-> Metrics `max:jvm.heap_memory{cluster_name:xxxxx-cluster} by {task_arn}.rollup(max, 60)`
- Event Overlays（GCカウントをイベントとして重ねる）
-> Metrics `avg:jvm.gc.major_collection_count{cluster_name:xxxxx-cluster}`

## ダッシュボードの表示
上記設定での時系列データの表示例です。
ある時期以降からGC頻度（上部の赤いマーク、色が濃いほど頻度が高い）が高まっていることが視覚的にわかりやすくなりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152950/022d1978-40d6-ad43-4b92-d2ca64ceb71b.png)

## おわりに
- 目につきやすい事象としてはCPU使用率が上がっている！ということだったのですが、仮説を持ちながら複数の情報を組み合わせてみてみることで、メモリ使用量UP -> ヒープ不足 -> GC多発 -> CPU使用率UP　という関係性を明らかにすることができました
- 結果として、CPUじゃなくてメモリをどうにかしないといけないんだね、という解決の方向性を関係者の間で理解しやすい状態がつくれました
- 今回の内容に限らず、時系列データと何かのイベント、メトリクスを重ねてみるという手法はいろいろな場面で役立つのではと思います、他の活用事例があればぜひ教えてください！
Better Editを久々に修正して公開した話

# はじめに
今年にPukiWiki標準プラグインであるedit.inc.phpを改良してbetter_edit.inc.phpを開発したのだが、WikiChree.COMでしか動かないシステムとなっていたため、誰でも使えるように久しぶりに修正してみました。

このプラグインは、WikiChree.COM用にPukiWikiの編集画面を便利にしたいので作ったものでそれを改善して配布できるようにした感じです。利用するには少しだけPukiWiki本体改造をする必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015774/ec1a0cc6-ac1a-7032-a45c-7c2f86c379de.png)

## プラグインの特徴



1. **プレビューのタブ化**  
   プレビューをタブで切り替えられるように
2. **添付ファイルのD＆D/Ctrl+V対応**
   ファイルをドラッグ＆ドロップしたり、クリップボードにある画像をCtrl+Vでそのまま貼り付けてページへ添付できるように

3. **添付ファイル一覧の表示**  
   ページ内にある添付ファイルを一覧で確認できるように

## 導入方法
https://github.com/TeamWikiChree-COM/developed-pukiwiki-plugins/blob/main/better_edit.inc.php

1. 上記リンクからプラグインをDL
2. PukiWikiの`plugin`フォルダに突っ込む  

~~それだけ！~~ ではなくて、このままじゃ編集ボタンを押してもデフォルトの編集画面になるので以下のように変更しなければならない

- lib/html.php 59行目
```lib/html.php
-	$_LINK['edit']     = "$script?cmd=edit&amp;page=$r_page";
+	$_LINK['edit']     = exist_plugin("better_edit") ? "$script?cmd=better_edit&amp;page=$r_page" : "$script?cmd=edit&amp;page=$r_page";

```

- lib/make_link.php 896行目
```lib/make_link.php
		// Dangling link
		if (PKWK_READONLY) return $s_alias; // No dacorations
		$symbol_html = '';
		if ($_symbol_noexists !== '') {
			$symbol_html = '<span style="user-select:none;">' .
				htmlsc($_symbol_noexists) . '</span>';
		}
-		$href = $script . '?cmd=edit&amp;page=' . $r_page . $r_refer;
+		$href = $script . '?cmd=' . (exist_plugin("better_edit") ? "better_edit" : "edit") . '&amp;page=' . $r_page . $r_refer;
		if ($link_compact && $_symbol_noexists != '') {
			$retval = '<a href="' . $href . '">' . $_symbol_noexists . '</a>';
			return $retval;
		} else {
			$retval = '<a href="' . $href . '">' . $s_alias . '</a>';
			return '<span class="noexists">' . $retval . $symbol_html . '</span>';
		}
```

## 最後に
時間があったらいろいろな機能を付け加えたいと思ってたりします。

リアルタイム編プラグインとか作ったことあるんですけど入力時、毎回サーバーからプレビュー結果を取得するのでサーバーの負荷が多いかなって感じで。
なのでJavaScriptで擬似的にプレビューできたらいいなぁとか思ってたりします。
Boxでランサムウェア対策

みなさんはなぜBoxを使うことがランサムウェア対策につながるのか、
または万が一ランサムウェアに感染してしまった際の対処はご存知でしょうか？

本記事ではBoxとランサムウェアをテーマに情報を共有いたします！

# はじめに
[IPA独立行政法人 情報処理推進機構が公表した2024年における情報セキュリティ10大脅威](https://www.ipa.go.jp/security/10threats/10threats2024.html)でトップ3に入った項目は以下の通りです。

- 3位 内部不正による情報漏洩
前職場が保有する情報を持ち出し転職先へ共有、など

- 2位 サプライチェーンの弱点を悪用した攻撃
VPN機器の脆弱性などを悪用して組織に潜入するパターンなど

- **1位 ランサムウェアによる被害**
システムがランサムウェアに感染し、数日間に渡り業務停止となってしまう、など。
近年はこのような事件をよく目にしますよね。本記事はこのランサムウェア対策に絞って記事を書いていこうと思います。


# Boxでの脅威対策
Boxでどのようにランサムウェアのリスクを回避できるでしょうか？実は、Boxをウェブブラウザでご利用いただくことが対策につながります。

一般的にランサムウェアの挙動として、OSが悪意のあるプログラムに感染することで、オンプレにあるファイルサーバーにも暗号化の影響が及んでしまいます。

しかしBoxウェブブラウザを介してファイルを取り扱う場合、ダウンロードせずにブラウザ上でファイルを閲覧していることになります。ですので、仮にPCが感染してしまっていてもブラウザ上のBoxに影響は及びません。

万が一、Boxブラウザ上に悪意のあるプログラムがアップロードされてしまった場合でも、プログラムを実行する"システム"がないため動くことができず、実行できないファイルとして存在するだけになるため被害は拡大しません。

またBoxはウイルスを検出する機能をいくつか用意しています。

# Boxのマルウェア検出機能
![Screen Shot 2024-12-04 at 17.35.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2975763/a350c9ce-da2a-9859-dbfd-9178984ef65e.png)

###### パターンマッチングによる既知のマルウェア対策
Boxにファイルをアップロードすると、リアルタイムで既知のウイルスのハッシュ値との比較をするウイルススキャンが実行されます。
※これはBoxの全てのライセンスエディションで標準機能として提供されている機能です。

###### マルウェアディープスキャン機能
また機械学習による未知のマルウェア検知機能も提供しています。
ハッシュ値での検知に加え、機械学習を用いて未知のウイルスにおいても一定割合で検知します。
※こちらは**Box Shield**というアドオンをご購入いただく必要がございます。

::: note info
Box Shieldについてはこちら
[過去セミナー「Box Shiedを知るどー！今日もBoxで安全にお仕事」](https://support.box.com/hc/ja/articles/23747274266643-Box-Shield%E3%82%92%E7%9F%A5%E3%82%8B%E3%81%A9%E3%83%BC-%E4%BB%8A%E6%97%A5%E3%82%82Box%E3%81%A7%E5%AE%89%E5%85%A8%E3%81%AB%E3%81%8A%E4%BB%95%E4%BA%8B)
:::

###### ただしBox Driveは要注意！
Box Driveをご利用の場合、エクスプローラーを介してBox Drive内のファイルがウイルスにより暗号化されてしまう可能性があります。感染に気づかずBox DriveとWebブラウザとの同期をとると、Webブラウザ側も暗号化されたファイルに置き換わってしまうことが考えられます。
ですので、ユーザーが感染してしまった場合、侵害を受けたシステムの切り離しなどを行い、Box Driveを終了してマルウェアが削除されていることを確認して追加の措置を取ることが必要です。

とはいえ、ユーザーの利便性を考えるとBox Driveを禁止しウェブ版のみを利用可とする運用もなかなか難しいと思います。
ここからは、万が一感染してしまった場合の対応策を記載します。

# ランサムウェア感染後のフロー
大まかな流れは以下です。
- [お客様→Box] Boxサポート(Boxをお買い求めいただいた販売代理店様の窓口)ならびにBoxアカウントチームにご連絡いただく
- [お客様⇄Box] 復旧対象の確認を行う
[ユーザーアクティビティレポート](https://support.box.com/hc/ja/articles/4415012490387--%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%A2%E3%82%AF%E3%83%86%E3%82%A3%E3%83%93%E3%83%86%E3%82%A3-%E3%83%AC%E3%83%9D%E3%83%BC%E3%83%88)より、ランサムウェアの処理の開始と終了日時、影響を受けたユーザーなどを絞り込み確認していきます。
- [Box] 復旧を行う

※コンテンツの復旧を確約するものではございません。
また復旧可能な目安は完全削除が行われてから**2週間程度**です。





# 参考サイト
以下のセミナーやサポート記事でも詳しく解説しておりますのでご参照ください。
- [ランサムウェアから内部不正まで、Boxで実現する鉄壁防御](https://support.box.com/hc/ja/articles/34814230342931-%E3%83%A9%E3%83%B3%E3%82%B5%E3%83%A0%E3%82%A6%E3%82%A7%E3%82%A2%E3%81%8B%E3%82%89%E5%86%85%E9%83%A8%E4%B8%8D%E6%AD%A3%E3%81%BE%E3%81%A7-Box%E3%81%A7%E5%AE%9F%E7%8F%BE%E3%81%99%E3%82%8B%E9%89%84%E5%A3%81%E9%98%B2%E5%BE%A1-Box%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E7%A5%AD%E3%82%8A-24-%E3%83%95%E3%82%A9%E3%83%AD%E3%83%BC%E3%82%A2%E3%83%83%E3%83%97%E3%82%BB%E3%83%9F%E3%83%8A%E3%83%BC)
- [Boxサポート記事 ランサムウェア](https://support.box.com/hc/ja/articles/360043694054-%E3%83%A9%E3%83%B3%E3%82%B5%E3%83%A0%E3%82%A6%E3%82%A7%E3%82%A2)
CML2をKVM上にデプロイしたときのメモ

個人用のメモ。記事としての体裁は整えてません。

CMLにfree tierが出ていることを教えてもらった。
https://developer.cisco.com/docs/modeling-labs/cml-release-notes/

VIRL時代はベアメタルサーバーにインストールして触っていたが、CML2になってからは全然触ってなかった。
今の自宅サーバはKVMで運用していて、動くかわからないのもあって、購入を踏み切れずにいた。
free tierが出て動作確認ができそうだったので、とりあえずKVM上にデプロイしてみた。

まずはここからダウンロード
https://software.cisco.com/download/home/286193282/type/286326381/release/2.8.0%20Free%20Tier

使うのはこの2つ。
- cml2_f_2.8.0-6_amd64-32-iso.zip
- refplat-20241016-freetier-iso.zip

.ovaを使ってデプロイしてみてもいいかなと思ったが、こっちは一応VMWareをメインに想定しているようなので、とりあえずisoからベアメタルと同じような手順で試してみることに。

まずはKVMを動作させているサーバでnested VMが有効になっているのを確認する。
```
# cat /sys/module/kvm_intel/parameters/nested
Y
```

僕は普段cockpitを使ってVMを管理しているので、cockpitのGUIからVMをとりあえず作ってみた。

- CPU: 2 core / 4 thread (1 socket)
- RAM: 16GB
- DISK: 64GB

ブート自体はできたが、UEFIブートする必要があるらしい。
BIOSブートだと「UEFIブートじゃないと多分うまくいかないよ」的なメッセージが出た。

一度VM定義を削除し、ovmfをインストールして、QEMUでUEFIファームウェアを使えるようにする。
```
sudo apt install ovmf
```

libvirtのXMLを一から作ると大変なのと、UEFIブートを使うVMの設定に馴染みがなかったので、とりあえずvirt-installから入れることにした。
diskは最初にBIOSブートを試したときに作ったものを流用(64GB)。
os-variantはよくわからなかったのでとりあえずunknownにしたが、ブート画面を見るとUbuntuっぽかったのでUbuntu系のどれかにしてもいいかもしれない。
```
sudo virt-install --name CML2 --ram 16384 --disk path=/mnt/ssd1/disk/CML2.qcow2 --vcpus 4 --os-variant unknown --network bridge=br0 --graphics vnc,listen=0.0.0.0,password=password --video vga --cdrom /mnt/ssd0/cml2_2.8.0-6_amd64-32.iso --boot uefi --noreboot
```
起動するとディスクへのインストール自体は自動的にやってくれる。

再起動後にCMLのインストールが始まるが、IOSなどのイメージファイルは別途refplat ISOと呼ばれるファイルで配布されており、CMLのインストールの際にこれが必要になる。
refplat ISOはCML2のインストールイメージと同じくCiscoのサイトからダウンロードできる。

CMLのインストールを始める前に、一度VMを落として、refplat ISOをcdromとしてVMにアタッチする。

cockpitの仮想マシンGUIからアタッチしてみたが、なぜか権限で怒られてうまくいかなかった。(パーミッションを777とかにしてみたがダメだった)
```
error: Failed to start domain 'CML2'
error: internal error: process exited while connecting to monitor: 2024-12-04T07:57:33.787885Z qemu-system-x86_64: -blockdev {"driver":"file","filename":"/mnt/ssd0/refplat-20241016-freetier.iso","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}: Could not open '/mnt/ssd0/refplat-20241016-freetier.iso': Permission denied
```

ので、virsh editでXMLを編集することにした。
特別なことはなく普通にcdromを使うときと同じ容量で書いてあげればいい。
```
  <disk type='file' device='cdrom'>
    <driver name='qemu' type='raw'/>
    <source file='/mnt/ssd0/refplat-20241016-freetier.iso'/>
    <target dev='hdb' bus='ide'/>
    <readonly/>
    <address type='drive' controller='0' bus='0' target='0' unit='1'/>
  </disk>
```
（cockpitからアタッチしたものは、何故かdisk type="volume"になっており、qcow2をアタッチする際のような設定だった。これが良くなかったように思う）

VMを起動して、あとは指示に従ってCMLのインストールを進める。

インストール完了後、CML2が正常に起動した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218316/11af1c75-8d18-aadb-c8e8-ddc7a9f32602.png)

とりあえずIOLと、ASAvを動かしてみる。
IOLはコンテナなので特に懸念はしておらず、実際問題なく動いた。
ASAvはVMで、NestedVMな環境で動くことになるためこっちが不安であった。
とりあえず簡単な疎通確認はできた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218316/9e24852b-51db-e7d2-c881-2a4a8332ac74.png)

アプライアンス、機能・設定によっては動かないのもありそうだが、ひとまず全く動かないわけではないことが分かった。

VIRL時代のVM Maestroに比べて、GUIが使いやすくなっていていいね！！！！
エンジニア勉強会「テック塾」の紹介 

現在私は、所属組織主催の「テック塾」という勉強会(コミュニティ)運営に関わっています。
この記事ではその概要と、運営にあたって思うことなどを共有してみようと思います。

## そもそもテック塾とは
### 経緯
2013年12月「博多テック塾」として発足。
「ちょっと寄って行かんね？」をコンセプトに、企業や組織に関係なくエンジニアが集まり、仕事や技術の情報交換を通じてキャリアやスキルを向上させるコミュニティを目指す。
2024年から「テック塾」としてリニューアル、全国展開中。

### 目的
テック塾の目的は、ターゲットに合わせて3つ設定しています。
- パソナのエンジニア集団という社会的な認知を得る（対社外）
- 参加者と一緒に楽しむ（対社内）
- 勉強会開催者として、自分達も一緒に学びを得る（運営スタッフ）

## どのように運営している？
さまざまな部署から有志が集まり運営しています。
テック塾の運営は<b>メイン業務ではなく、みんなそれぞれ他の案件を抱えている</b>状態です。
隔週の定例会と、テック塾専用のslackチャンネルでコミュニケーションを取っています。

## 2024年度の実績
今年度は下記の勉強会を開催しました！

- 1月: ローコード（PowerPlatform）
- 3月: スクラム/アジャイル開発入門
- 6月: テスト駆動開発(TDD)
- 9月: 振り返り手法

そして、今後開催が決まっている勉強会はこちら。

- 2025年1月: デザイン勉強会
- 2025年3月: アジャイル勉強会

絶賛準備中です！
時期が来たら発信していくので、乞うご期待。

## 運営の楽しさ
ここからは運営メンバーとしての私の個人的お話となります。

じつは、筆者は一番の新米メンバーで、運営として加わったのは直近の9月の回からです。
6月の回には講師として登壇したのですが、運営メンバーがみんなで勉強会を作り上げていくようすが楽しそうで羨ましくなってしまい...
大変かもしれないと数日間悩んだ末、お願いしてメンバーに入れてもらうことにしました！

1つ勉強会運営を終えた今、この活動のなにが魅力的なのかあらためて考えてみると、

- <b>ふだんの業務では関われない人とも関わることができる</b>
- <b>ふだんの業務では行わないタスクができる</b>(半分息抜きですね)
- 勉強会を作りあげるという<b>達成感を得ることができる</b>
- 勉強会の運営を通して<b>技術の知見を広げることができる</b>
- エンジニア組織としての<b>ブランディングに貢献することができる</b>

といったことが大きいように思います。

次のテーマの候補を決めるときに「それ分かる！」「私もそれ深掘りしたいと思ってた！」などと盛り上がったり、みんなであれこれ意見を出し合って「それいいね！」となったり、単純に楽しいと感じる瞬間が多いです。

おそらく、他の先輩運営メンバーの皆さんも同じように「楽しい」という気持ちがあるからこそ、今の空気感が生まれているような気がします。

## 運営のこれから

テック塾運営のようなメイン業務ではない活動にとって、前段で出した「楽しい」というキーワードは結構大きな肝になると考えています。

テック塾運営の中でも、

- メイン業務ではないので定例会に集まりづらい
- メイン業務で忙しい時期があると、運営メンバーの温度感に差が出てしまう
- 少ない運営メンバーでコンスタントに勉強会を企画・開催する必要がある

といった問題が挙がってきています。

ここで、「定例会は絶対参加！欠席NG！」とか言ってしまうと、なんだか楽しさは失われてしまいそうですよね？
それでは意味がないということで、テック塾運営では、<b>できるだけ負担を減らしていく</b>という方針を検討することにしました。

具体的には、

- 毎週開催していた定例会を隔週開催にする
- 勉強会の開催直前までは、勉強会の担当者(ex. 代表者、広報担当)のみが集まる
- 企画持ち寄り制を試してみる

という3つのやりかたを試しています。

3つ目の企画持ち寄り制について補足しておくと、`年に1回は運営メンバー1人ひとりが企画案を出しましょう`という方針です。モチベーションの高い勉強会であれば、より楽しく運営に関われるのでは…というアイデアから生まれました。

このように、テック塾運営は、今もなおより良い運営の形を目指して模索・改善を続けています！
(アジャイルにかぶれている筆者は、このような状況が大好物だったりします。)


# これから勉強会(コミュニティ)を運営したい人に向けて

この記事を読んでくださっている方の中には、勉強会を運営していたり、これから企画しようとしていたりという方がいるかもしれません。
そのような方々に向けて、今の私が言えることは、

- 目的はしっかり定めましょう
    - 人数が増えたときに進む方向性がブレなくてすみます
- メイン業務でないのであれば、運営側が負担にならないような工夫を随時考えましょう
- フェーズによって運営のあり方は柔軟に見直しましょう

の3点です！

私自身、楽しむ気持ちを忘れず、これからもテック塾の運営に貢献していきたいと思います。
お読みくださり、ありがとうございました！
Kotlin ラムダ式 関数

関数
``` Kotlin
val v = calc(10, 20)

fun calc(a: Int, b: Int): Int {
    return a + b
}
```
ラムダ式
``` Kotlin
val v = calc(10, 20)

val calc = { a: Int, b: Int -> a + b }
```
ラムダ式 型指定
``` Kotlin
val calc:(a: Int, b: Int) -> Int = { a: Int, b: Int -> a + b }
```
人生やっぱり幸せにいきたいよね

## はじめに
みなさん幸せですか？
そもそもエンジニアにとっての幸せってなんでしょうね？
私個人としては、自分で手を動かして何かしら作り上げる、その作り上げる過程で何かしら問題が発生して解決してすっきりしたり、できあがったものを見てわーいってなったり、お客さんが使ってるのを見てニヤニヤしたりすることだと思っています。
つまりものづくりを通して自分が悦に入る瞬間を増やすということかと。

あとは没頭すること。これはエンジニアに限りませんが没頭できるくらい夢中になれることをやれると幸せだよな、って思います。というか幸せとか考えなくて済むので幸せな状態にあるんじゃないかと想像します。

みなさんが思うエンジニアの幸せの定義、教えてください。

## 私には向いていなかったらしい
で、幸せな状態ではないんですよ、私。たぶん。他人から見れば恵まれた状態にはあるかもしれませんが。

新卒で入った会社はメーカーで、ちゃんと売っているものが手で触れました。その方が作っている実感があるかなと思い、何となく入社を決めました。
入ってみたら、まあまあ大きい組織だったので縦割り行政になっていて、良くも悪くも自分の担当領域がきっちり決まっていました。その範囲は責任を持つけど、それ以外のことは誰か何とかしといてという雰囲気です。のりしろ部分の仕事は押し付け合いに近いものがあります。
そして裁量労働制です。会議には出ないといけないけど、何時に出社してもいいし何時に退社してもいいってことです。まあ暗黙の了解で定時っぽいものは存在しますが。
あとは何だかんだ正社員だったので、やることはプロジェクトを転がすことです。私がやりたかった実働は別の人がやります。

従って生来ナマケモノの私は自分の担当領域最低限をこなすだけの組織の歯車になってしまいました。給料も出ないのになぜ自己研鑽しないといかんのだ。今のプロジェクトは上手く回っているからいいじゃないか。私が新たに何かできるようになったところで仕事内容は変わらないし。忙しい時期はめっちゃ残業してるし、暇なときは休ませてよ。となりの人はなんか知らんけどネットサーフィンしてるし。

情熱は失われるばかりです。

## 本気でやらないとやっぱだめかも
こんな後ろ向きな気持ちで仕事をしていると人生全体に悪影響がでてきます。なんせ1日の半分くらいはあんま楽しくない仕事のこと考えているのですから。（休日もTeamsのチャットは飛んでくるし）
さらに後ろ向きに仕事をしていると、やめようと思ったときに踏ん切りがつきません。だってまだ本気でやってないから楽しくないだけかもしれない、もう少し知識があれば没頭できるのかもしれない、のようなだってたらればが無限に湧いてきます。

エンジニアとして幸せじゃないかも、と思い出して1年ちょっとが経過したところで一転、なんだか面白そうなことを始めている人たちに声をかけてもらうという幸運に恵まれました。ということで転職します。今度こそ主体的に仕事を楽しんで幸せなエンジニア人生を送りたいなと思います。

## おわりに
感情や考えたことなんて書いておかないとすぐ忘れてしまうのでここに残させていただきます。
仕事を主体的に楽しむコツがあればこれも教えてください。
ではまた。
MySQLエラー「The server quit without updating PID file」の原因と解決方法

## エラー内容
```
ERROR! The server quit without updating PID file (/usr/local/var/mysql/*.local.pid).
```
このエラーは、MySQLサーバーが起動しようとした際に、何らかの理由で正常に動作できず、PIDファイルを更新せずに終了したことを意味します。

## PIDファイルとは？
PID (Process ID) ファイルは、MySQLサーバーが稼働していることを示すファイルです。このファイルには、サーバープロセスのIDが記録されます。
正常に起動した場合に生成され、サーバー停止時には削除されるべきものですが、エラー発生時には適切に更新されない場合があります。

## 原因
指定されているPIDファイルのディレクトリやファイルが適切に構成されていないことが原因で発生していました。

## 環境
```
% mysql --version
mysql  Ver 8.0.40 for macos15.1 on arm64 (Homebrew)

% bundle list | grep mysql2
  * mysql2 (0.5.6)
```

## 解決手順
```
#インストール
brew install mysql@8.0

#サーバー起動
mysql.server start

####エラー発生####
=> ERROR! The server quit without updating PID file (/opt/homebrew/var/mysql/*.local.pid).

「ls -la /opt/homebrew/var/mysql」で権限確認

「cat /opt/homebrew/var/mysql/*.local.err」でエラーの詳細を確認
#・ibdata1、InnoDBなどが作成されない

「/opt/homebrew/var/mysql/」の初期化コマンドを実行 → ibdata1、InnoDBなどが作成されない
#※ mysqld --initialize --user=$(whoami) --datadir=/opt/homebrew/var/mysql

「/opt/homebrew/var/mysql」の中のファイル権限を変更
# sudo chown -R $(whoami):staff /opt/homebrew/var/mysql
# chmod -R 755 /opt/homebrew/var/mysql

「sudo rm -rf /opt/homebrew/var/mysql」で配下のデータを削除

新しくデータを作成＋権限修正
# sudo chown -R $(whoami):staff /opt/homebrew/var

「/opt/homebrew/var/mysql」を初期化（デフォルトのファイルを自動生成）
# mysqld --initialize --user=$(whoami) --datadir=/opt/homebrew/var/mysql
# ログに「A temporary password is generated for root@localhost: 6Py<O:W#-Tiy」にあるパスワードをメモする
# 「mysql -u root -p」でログインする時に使う

mysql.server start
# SUCCESS! 

データベース作成
# rails db:create

libmysqlclient.23.dylibが見つからない
# エラーLibrary not loaded: /opt/homebrew/opt/mysql/lib/libmysqlclient.23.dylib
# 特定のバージョンを指定する場合に発生する

検索をかけるとファイル発見（※場所が違う）
# find /opt/homebrew -name "libmysqlclient*.dylib" 2>/dev/null
# homebrewでは関連データが全てCellarで格納される。呼び出す際にはoptというフォルダが変数になっており、自動的に適切なデータが入るようになっている

強制的にファイルを作成
# mkdir -p /opt/homebrew/opt/mysql/lib

参照名を変更
# ln -s /opt/homebrew/Cellar/mysql@8.4/8.4.3_3/lib/libmysqlclient.24.dylib /opt/homebrew/opt/mysql/lib/libmysqlclient.23.dylib

リンクが設定されるか確認
# ls -la /opt/homebrew/opt/mysql/lib/

データベース作成
# rails db:create

パスワード、ユーザー名が違うということでエラー
# ActiveRecord::DatabaseConnectionError: There is an issue connecting to your database with your username/password, username: root.

初期化時に発行されたパスワードでログイン
# 87voW!(2akg4

アカウント作成
# ALTER USER 'root'@'localhost' IDENTIFIED BY '自分のパスワード';

db作成完了
# rails db:create
```

その他のエラー事例：
```
# エラー：「mysql.server stop」してから「mysql.server start」した時
Do you already have another mysqld server running on socket: /tmp/mysql.sock ?

mysql.server start
ls -l /tmp/mysql.sock
sudo rm -f /tmp/mysql.sock
```

## まとめ
このエラーは、MySQLサーバーの設定やプロセスの異常が原因で発生することが一般的です。上記の手順を一つずつ試していくことで、問題の解決が可能です。特に、エラーログの確認が有効な対処法となります。

MySQLの安定した運用を保つために、設定や環境の変更時には注意深く作業を進めることをおすすめします。
[Amazon Web Services]AWS re:Invent2024 レポート#1 「Amazon Bedrock の回答精度が向上！」

AWS re:Invent2024 が開催中です！
大変有難いことに、自分は現地参加させていただいております。

12/2・12/3と各セッションを受講して感じたことは、参加者のAWSへの熱量ハンパナイ！、です。
特に、生成AI（GenAI）関連のセッションは大盛況で、最新のAI技術への関心の高さが顕著でした。

そこで、今回は「Amazon Bedrock の回答精度が向上！」と題しまして、
自分が気になったAmazon Bedrockのアップデート情報をご紹介させていただきたいと思います！

## Amazon Bedrock が Rerankerモデル（Rerank API） をサポート!

>Amazon Bedrock が Rerank API を通じて再ランク付けモデルのサポートを発表しました。これにより、RAG アプリケーションの応答の関連性が向上します。再ランク付けモデルは、ユーザークエリに基づいて取得したドキュメントをランク付けし、最も関連性の高い情報を Foundation Models に提供します。
https://aws.amazon.com/jp/about-aws/whats-new/2024/12/amazon-bedrock-rerank-api-accuracy-rag-applications/

## 改善点の詳細 - RAG アプリケーションの精度を向上
RAGが回答を生成する際に使用する、セマンティック（意味的）検索は、
ベクトル空間で意味的に類似したユーザのクエリとソースドキュメントを管理し、より正確な応答を生成する上で重要な役割を果たしています。
ただし、ユーザークエリが複雑な場合は、ユーザーの質問に部分的にしか関連しないドキュメントが取得される可能性がありました。

Rerankerモデルは、上記の課題を解決するために、
セマンティック検索で取得したドキュメントの中から、ユーザーのクエリに最も適した情報を優先的に選び出すアルゴリズムを使用することで、生成AIの回答の質の向上に貢献してくれます。

Rerankの重要性やその仕組み、効果については下記に記載がございましたので、
さらに詳細が気になる方はご参照ください！
https://aws.amazon.com/jp/blogs/machine-learning/cohere-rerank-3-5-is-now-available-in-amazon-bedrock-through-rerank-api/

## ユースケース
AWSドキュメントを参照すると、主なユースケースは下記2点で記載があります。
Amazon Bedrock Knowledge Basesでは、Rerankerモデルの有効化⇛サービスロールの権限設定、という簡単な手順で、Rerankの実装ができるようですのでお試しいただければと思います！

- クエリ、ドキュメント、および再ランキング設定を入力し、開発者がRerank APIを独立して（直接）使用
- Amazon Bedrock Knowledge Basesを使用して RAGアプリケーションを構築し、RetrieveまたはRetrieveAndGenerateオペレーションを呼び出すときにRerank APIを使用

https://aws.amazon.com/jp/blogs/aws/new-apis-in-amazon-bedrock-to-enhance-rag-applications-now-available/
【TypeScript】配列の最初の要素を返す型の実装（type-challenges 初級編 14・First of Array）

## お題
配列`T`を受け取り、その最初の要素を返す型`First`を実装する。

## やりたいこと
```typescript
type arr = ["a", "b", "c"]
type result = First<arr>  // => "a"
```

## 解答
```typescript
type First<T extends any[]> = T extends [infer U, ...any[]] ? U : never;
```

## 解説

### 処理の流れ
- `<T extends any[]>`
Tを配列のみ受け取るように制約。
- `T extends [infer U, ...any[]] ? ...`
条件分岐（`T`が`[infer U, ...any[]]`の形だったら...）で評価を行う。
- `[infer U, ...any[]]`
  - `infer U`
  要素の最初の要素の型推論を行う。
  - `...any[]`
  配列の残りの要素を表す。
- `... ? U : never`
最初の要素があれば`U`、なければ`never`を返す。

### Conditional Types（型の条件分岐）とは...
- 条件によって型を決めることができる。
- 三項演算子で記述する。
- `extends`の記述が必要
```typescript
T extends U ? X : Y;
// trueならX、falseならY

type IsString<T> = T extends string ? true : false;
type IsString<"a"> // => true;
```

### inferとは...
- `infer`は型推論を行う（inferの直訳は推論）。
型の中から必要な部分を取り出して名前をつける」ための道具。
- `extends`の右辺にのみ記述が可能。

### なぜ型推論をして、具体的な値（"a"や0）を抽出できるのか？ 
TypeSciptは型推論の際に、可能な限り具体的な型推論を行うから。

`["a", "b", "c"]`の配列の最初の要素は明確に`"a"`という文字列
→ 型として`string`よりも具体的な`"a"`という文字リテラル型が推論される。

### 残余パターン（...）とは...
- 省略して書いてるイメージ
- `[infer U, ...any[]]`の部分は、「最初の要素の型をUとして推論し、残りは何でも良い」という意味合いを持つ。


## 参考記事
### Conditional Types
-  [Conditional Types | TypeScript入門『サバイバルTypeScript』](https://typescriptbook.jp/reference/type-reuse/conditional-types)
- [TypeScriptのinferを今度こそちゃんと理解する | Zenn](https://zenn.dev/brachio_takumi/articles/464106a6a80eca8ab919#conditional-types)
### infer 
- [infer | TypeScript入門『サバイバルTypeScript』](https://typescriptbook.jp/reference/type-reuse/infer)
- [TypeScriptのinferを今度こそちゃんと理解する | Zenn](https://zenn.dev/brachio_takumi/articles/464106a6a80eca8ab919#infer)
- [配列の最初の要素を返す型を作ろう | mosya-TC](https://mosya.dev/blog/tc-first#infer%E3%82%92%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B)
### 残余パターン
- [残余部分の代入 | TypeScript入門『サバイバルTypeScript』](https://typescriptbook.jp/reference/values-types-variables/array/destructuring-assignment-from-array#%E6%AE%8B%E4%BD%99%E9%83%A8%E5%88%86%E3%81%AE%E4%BB%A3%E5%85%A5)

## 今回の問題
https://github.com/type-challenges/type-challenges/blob/main/questions/00014-easy-first/README.ja.md
トランスポート・サービス・プリミティブ

>最初に単純な（仮の）トランスポート・サービスとそのインタフェースを扱うことで本質的な部分を述べ、その後、実際の例に移ることにする

# トランスポート・サービス・インターフェース
>ユーザーがトランスポート・サービスにアクセスできるようにするために、トランスポート層は`アプリケーション・プログラムに対して操作命令を提供しなければならない`。これがトランスポート・サービス・インターフェースである。

# 低信頼ネットワーク上で高信頼サービスを提供する　トランスポート・サービス
>ネットワーク・サービスに似ているが、いくつかの重要な違いがある。大きな違いは、`ネットワーク・サービスが実際のネットワークにより提供されるサービスそのままのモデル化を行なっている`ことである。現実のネットワークはパケットをロスすることがあるので、`ネットワーク・サービスは一般的に信頼性がない`。

>対照的にコネクション指向のトランスポート・サービスには信頼性がある。もちろん、実際のネットワークに誤りがないのではなく、`低信頼ネットワーク上で高信頼サービスを提供する`ことこそが、トランポート・サービスの目的なのである。

* `ネットワーク・サービスが実際のネットワークにより提供されるサービスそのままのモデル化を行なっている`の意味が理解できていない

# ２つのプロセス間の動作は100％信頼性のもとに動く
>UNIXのパイプ（または別のプロセス間通信機能)で接続されている２つのプロセスが一台のマシン上で動作するところを考えてみよう。プロセスはその間のコネクションが100％完全であると仮定しており、確認通知やパケット・ロス、輻輳などについては全く管理したくない。単純に100％信頼性のあるコネクションが必要としているのである。

### トランスポート・サービスが不完全性を隠蔽することで異なるもの同士で通信ができる
>プロセスAがパイプの一方にデータを流したら、Bはもう一方からそれを取り出す。これがトランスポート・サービスの仕事である。`ネットワーク・サービスの不完全性を隠蔽することで、ユーザー・プロセスは異なるマシン上であっても誤りのないビット・ストリーム転送を仮定`することができる。

* ユーザー・プロセスとは？

https://qiita.com/masatom86650860/items/599a437d942283dc2326

# トランスポート・サービスは便利で使いやすい
>ネットワーク・サービスとトランスポート・サービスの２つ目の違いは、`そのサービスが誰のためのものか`ということである。ネットワークのエンド・ポイントから見れば、`ネットワーク・サービスはトランスポート・エンティティにのみ`使われる。
...
ユーザーやプログラムが裸のネットワーク・サービスを利用することはほとんどない。逆に、多くのプログラムがトランスポート・プリミティブを利用するので、トランスポート・エンティティにのみ使われる。逆に、多くのプログラムがトランスポート・プリミティブを利用するので、`トランスポート・サービスは便利で使いやすくなければならない`。

# トランスポートサービスで利用されるプリミティブ
| プリミティブ | 送信パケット         | 意味                                           | 
| ------------ | -------------------- | ---------------------------------------------- | 
| LISTEN       | なし                 | プロセスが接続することを試みるまでブロックする | 
| CONNECT      | CONNECTION REQUEST   | コネクションの確立を能動的に試みる             | 
| SEND         | DATA                 | 情報を送信する                                 | 
| RECEIVE      | なし                 | DATAパケットが到着するまでブロックする         | 
| DISCONNECT   | DISCONNECTION REQEST | コネクションの解放を要求する                   | 

* これらのシステムコールを使うことによって安全にデータを受け取る

# ネットワーク層のプロトコルを用いて複雑さをユーザーに対して隠蔽する
>トランスポート層においては、単純な単一方向のデータ交換でさえ、ネットワーク層よりも複雑である。送信されるすべてのパケットはそのうち）確認通知がなされる。`制御セグメントを運ぶパケットも明示的あるいは暗黙に確認通知がなされる`。これらの確認通知は、トランスポート・エンティティがネットワーク層のプロトコルを用いて行うものであり、トランスポート・ユーザーには見えない。`トランスポート・エンティティは、タイマーや再送についても気を配る必要`があるが、このメカニズムもトランスポート・ユーザーから全く見えない。トランスポート・ユーザーにとって、`コネクションは信頼できるビット列のパイプ`である。つまり、あるユーザーがその中にビット列を入れると、同じ順序でもう一方から出てくる。このようにして`複雑さを隠蔽することこそが、階層化プロトコルの利点`と言える。
https://bookplus.nikkei.com/atcl/catalog/23/03/16/00728/

# 感想
* トランスポート層がなければ不完全なネットワークのもと通信しなければならない
* クライアントとサーバーとの間でプリミティブを行い、コネクションが確立されて、データが送受信される
*
3Dレーザースキャンの方法

レーザースキャンは、物体の表面形状を効率的に取得する技術で、リバースエンジニアリング、アート制作、工業デザインに非常に適しています。以下は、3Dレーザースキャナーの基本的な操作手順と注意点です。


#### **1. 準備作業**
- **スキャナーの選定：**  
  スキャナーが目的に適していることを確認します。ハンドヘルド型は中小型の物体に、固定型は家具などの大型物体に適しています。  
- **スキャンエリアの清掃：**  
  スキャン対象の表面を清潔にし、ホコリや反射点を取り除きます。また、環境光を均一に保つことで干渉を減らします。

![f987d396d47b42e47c07efabf967c1cd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3824290/2f86ae13-152c-f790-1ff6-b1c464b07699.png)

https://www.revopoint3d.jp/products/3d-laser-scanner-metrox


#### **2. スキャナーの設定**
- **設置と校正：**  
  説明書に従ってスキャナーを設置し、スキャンヘッドを校正して精度を確保します。一部の高性能機種は自動校正に対応していますが、丁寧に実施しましょう。  
- **ソフトウェアの準備：**  
  専用ソフトを起動し、スキャンモードを選択します。高速モード（低精度）や高精度モード（詳細なデータ）から適切な設定を選びます。


#### **3. スキャンの実行**
- **物体の固定：**  
  物体が移動しないように固定し、スキャン中のズレを防ぎます。  
- **スキャン角度の調整：**  
  重要な部分を網羅するようにスキャンします。複雑な形状の場合は、異なる角度から複数回スキャンを行います。  
- **動的操作：**  
  ハンドヘルド型を使用する場合は、一定の速度で動かし、スキャンの中断やブレを防ぎます。

![c1a99ea8af32c3d7b7f8c31057ffb059.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3824290/9d9fbf1d-ad0d-5925-61a2-d457ee9f36b3.png)


#### **4. データ処理**
- **点群データの結合：**  
  ソフトウェアを使用して、複数回スキャンした点群データを結合し、完全な3Dモデルを作成します。多くのソフトは自動結合機能を備えていますが、手動修正も可能です。  
- **モデルの最適化：**  
  欠損箇所を修正し、メッシュを簡素化または滑らかにして、最終的なモデルを目的に合うよう調整します。

![91ea505adbd1f860865dbc2a5a80cc67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3824290/d3eea148-350f-56d7-a09a-863e9d36bdcc.png)


#### **5. 出力と活用**
- **ファイルの保存：**  
  STLやOBJなど、一般的な3Dファイル形式でデータをエクスポートし、後続の加工やプリントに備えます。  
- **実際の活用：**  
  取得したデータは、リバースエンジニアリング、3Dプリント、NC加工など多くのプロジェクトで活用可能です。

![0f47edf3e8d5d135ff7e1a2438f93735.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3824290/09d9aa8e-1dd3-a4cc-0026-acae0a1c1c69.png)

#### **注意事項**
- **安全な使用：**  
  レーザー機器は一定の強度があるため、直視や長時間の眼の露出を避けてください。


適切な設定と操作を行うことで、3Dレーザースキャナーは複雑な形状を効率的にキャプチャし、DIYやエンジニアリングプロジェクトに無限の可能性を提供します！

https://www.revopoint3d.com/products/3d-laser-scanner-metrox
Blenderとおでんの違い

この記事は、[木更津高専 Advent Calender 2024](https://qiita.com/advent-calendar/2024/nit_kisarazu) 6日目の記事です。

前→ [Pythonで最も難しい大学入試のアプリを作る話](https://qiita.com/Wing2C1/items/24ef32569df098e597e3) by @Wing2C1   
後→ [teamsがあまりよろしくないので学食botを作る](https://qiita.com/yukipeti/items/8e555f12c7877c972de8) by @yukipeti

# Blenderとは
NeoGeoによって開発されたオープンソースの3Dモデリングツール．
3DCG・アニメーションの制作に特化しており，だれでも**無料**で利用することができる．
有料CGソフトのMayaと比べ**無料**なため始めるにあたっての敷居が低く，趣味から始めやすいのが特徴．もちろんBlenderでも十分高クオリティな作品の制作が可能．

# おでんとは
東京発祥の煮物の一種．
ルーツは室町時代に流行した**豆腐田楽**と言われており，江戸時代にはファストフードとして江戸庶民に愛され、やがて煮込みおでんへと進化。 さらに屋台や居酒屋で食べる料理から家庭で食べる料理へと変化し、現代の定番料理となった

## 機能
|Blender|おでん|
|---|---|
|3Dコンピューターグラフィックス，<br>アニメーション等を制作できる．|冬場の夕食にピッタリ．<br>寒い夜でもあったかい．|

## 知名度
|Blender|おでん|
|---|---|
|3DCGソフトウェアの中ではトップシェア．<br>ユーザー数は100万 ～ 300万人と言われている．|日本人ほとんど全員が認知している．<br>外国人への人気も高く，ユーザー数は2億人を超えると考えられる．|

## ユーザー層
|Blender|おでん|
|---|---|
|10代から50代まで幅広く分布．<br> 20代のシェアが最も多く，37%となる．|幼児期から高齢者にまで幅広く分布．<br> 誰でもおいしく楽しむことができる．|

## 料金
|Blender|おでん|
|---|---|
|基本無料．一部有料のアドオンが存在するが，<br> なくても十分制作が可能．|具材一つあたり100～150円(コンビニ)<br>自炊すればもう少し安く済ませられる．|

## 拡張性
|Blender|おでん|
|---|---|
|公式・有志含め数多くのアドオンが存在．<br>自分好みにBlenderをカスタマイズできる．|様々な具材を入れることでいろいろなおでんを作ることができる．<br>はんぺん，ちくわ，こんにゃく等，定番が存在するため実際はワンパターンになりがち．|

## 互換性
|Blender|おでん|
|---|---|
|バージョン間の互換性はあまり高くない．<br>マテリアルの破損・ジオメトリノードのエラー<br>などが報告されている．|そのものの味は良いがごはんとの相性はお世辞にもいいとは言えず，<br>海苔の佃煮等に軍配が上がると言えるだろう．|

## おいしさ
|Blender|おでん|
|---|---|
|おいしい！|おいしい！|

# まとめ
### Blender
たのしくてすごくておもしろい！
### おでん
おいしくてあったかくて安い！
Xcode16にしたらiOS18だけやたら落ちるようになった話

# iPhone 16シミュレータでのクラッシュ問題
最近、Macのアップデートが来ていたので、早速バージョンアップを実行。
そして、ついでにXcodeのバージョンも最新にしたんですよ。
ここまでは順調…と思っていたのですが。

いざ、iPhone 16のシミュレータを使ってみると、特定のシチュエーションでアプリが突然クラッシュ！「あれ、なんでだ？」と思って、少し状況を変えてみても…また落ちる。落ちる、落ちる…まるでiPhoneの中で何かが暴れているかのような勢い。

こりゃ一体、何が起こってるんだ？という感じである。

試しにiOS17.5に落としてみると落ちない。
さっきまでの状況が嘘のようだ。

# 原因調査
さて、ついに始まりました！
みんな大好きな「原因調査タイム」がやってきましたよ。

まずはクラッシュレポートをチェックしてみましょう。
そこにはこんなエラーメッセージが…
```
Terminating app due to uncaught exception 
'NSInternalInconsistencyException', reason: 'Expected dequeued view
to be returned to the collection view in preparation for display.
When the collection view's data source is asked to provide a view 
for a given index path, ensure that a single view is dequeued and 
returned to the collection view. Avoid dequeuing views without
a request from the collection view. 
```
ん？なんだこれ？よく分からんぞ…。
DeepLさんにお願いしてみました。
コレクションビューが必要とするビューを取り出す処理（デキュー）を適切に行う必要があり、ビューを取り出して返す操作が不正だったことが原因でクラッシュが発生しているということです。

うーん、でもいまいちピンと来ないので、次はデバッグだ！
「もしかしてここが怪しいんじゃないか？」と思ってブレイクポイントを設置。
```
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
```
すると…やっぱり、ここで落ちてる！そして、同じエラーメッセージが出現。

どうやら原因特定完了です。
さあ、次は修正作業！
# 修正編
問題の特定ができたので、あとは修正するだけ！ というわけで、やっとこさゴールが見えてきました。

今回は、コレクションビューでビューを取り出す処理（dequeueReusableCell()）を使って、セルをいろんなパターンに分けて作成していました。最初に複数のセルを一度に宣言しておいて、あとはreturnで返すという方法です。こんな感じで…
```
let cellA:collectionViewCellA = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCellA", for: indexPath) as! collectionViewCellA
let cellB:collectionViewCellB = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCellB", for: indexPath) as! collectionViewCellB

swtich indexPath.section{
    case 0:
        return cellA
    case 1:
        return cellB
    default:
        return cellA
}

```
ところが、これがちょっと面倒なことになってしまったのが、Xcode 16 + iOS 18 の環境で動かした時。どうやら「必要ないセルをデキューするのはよろしくないよ！」という警告が出るようで、最終的には「1つだけ取り出してね！」というお達しが。
必要なセルを必要な時にだけ取り出すようこんな風に修正しました。
```
swtich indexPath.section{
    case 0:
        let cellA:collectionViewCellA = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCellA", for: indexPath) as! collectionViewCellA
        return cellA
    case 1:
        let cellB:collectionViewCellB = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCellB", for: indexPath) as! collectionViewCellB
        return cellB
    default:
        let cellA:collectionViewCellA = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCellA", for: indexPath) as! collectionViewCellA
        return cellA
}

```
今のところ問題なく動作しているので、修正としてはこれで合ってるはず。作り方としては少し独特だったので、情報を探すのに時間がかかりましたが、なんとか解決に至ってホッとしています。最終的にうまく修正できたので、結果オーライですね！

# 最後に
という事で今回はChatGPTちゃんの協力により、文章を面白く読みやすいように作り直してもらってみました。変な部分もありますが、意外と文章打てるんだなって印象でしたがいかがでしたか？楽しんで読んでもらえたなら何よりです。
そのExceptionをおにぎりにしますか？

この記事は[株式会社カオナビ Advent Calendar 2024](https://qiita.com/advent-calendar/2024/kaonavi)の21日目の記事です。

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


おにぎらずが好きです

https://cookpad.com/jp/recipes/20224904

## PHPにおける例外（Exception）の基本

### 例外（Exception）とは？
プログラムの実行中に発生するエラーや異常を処理するためのメカニズムです。

> PHP 内で例外がスローされ (throw され)、それが 捕捉され (catch され) ます。発生した例外を 捕捉するには、コードを try ブロックで囲みます。
> マッチする catch ブロックが見つからない場合は、 グローバルな例外ハンドラが設定されていない限り fatal error となり、 プログラムが終了します。
https://www.php.net/manual/ja/language.exceptions.php

## 基本的な構文
PHPではtryブロック内で例外がスローされると、catchブロックでその例外をキャッチして処理します。

構文の例:

```php
try {
    // 例外が発生するコード
    throw new Exception("エラーが発生しました。");
} catch (Exception $e) {
    // 例外をキャッチして処理する
    echo "例外がキャッチされました: " . $e->getMessage();
    // 再スロー
    throw $e;
}
echo "処理は継続しています";
```

実行結果

```
例外がキャッチされました: エラーが発生しました。
Fatal error: Uncaught Exception: エラーが発生しました。 
```


## おにぎりとは

Exceptionを補足し、再スローせずに処理を継続することです。
Exceptionを握りつぶす、の意味でおにぎりと言います。

```php
try {
    // 例外が発生するコード
    throw new Exception("エラーが発生しました。");
} catch (Exception $e) {
    // 例外をキャッチして処理する
    echo "例外がキャッチされましたが握りつぶします: " . $e->getMessage();
    // 再スローしない
}
echo "処理は継続しています";
```

実行結果

```
例外がキャッチされましたが握りつぶします: エラーが発生しました。処理は継続しています 
```

## おにぎり注意点

すべてのExceptionを握りつぶすことはしないほうがいいです。
アプリケーションの状態が不整合になったり、デバッグや監視が困難になったりする可能性があります。

## 特定のケースに当てはまる場合は、おにぎりしたい

あるケースに当てはまる場合だけおにぎりしたい場合、
特定のExceptionクラスを作ってそのExceptionだけ、おにぎりするといったやり方がよいでしょう。

```php
class MyOnigiriException extends Exception {}

try {
    throw new MyOnigiriException("おにぎりしたいカスタム例外が発生しました");
} catch (MyOnigiriException $e) {
    echo "おにぎりします: " . $e->getMessage();
}
```

上記の場合、`MyOnigiriException`はおにぎりされますが
それ以外の`Exception`はスローされます。

## 特定のケースとはどういったものでしょうか？

特定のケースとはどういったものが考えられるでしょうか?
処理自体は成功にして、エラーがあったことをログを出すだけでとどめたい場合が考えられます。

例えば

- ログファイルの書き込み失敗やログ通知の失敗
ログファイルの書き込みやログ通知の失敗はアプリケーションの正常な動作には不要であるため、失敗しても例外をスローせずに処理を続行することが考えられます。

- 処理終了後の一時ファイルの削除などのお掃除処理
アプリケーションの終了時に一時ファイルの削除などが失敗した場合、例外をスローせずに処理を続行することが考えられます。

- オプションの機能
ユーザーが特定のオプション機能を使用するとき（例えば、操作ガイドモードなど）、その機能がうまく動かなくても基本機能には影響しない場合、その例外を握りつぶすことが考えられます。


## まとめ

PHPの例外処理は、エラーの発生箇所とその処理を分離し、
堅牢なアプリケーションを作るための強力なツールです。
日々の開発にぜひ役立ててください！
ファイルアップロード時にプレビューする機能の作り方

# ファイルアップロード時にプレビューする機能の作り方

ファイルアップロード時にプレビューする機能の作り方です。
画像の作り方はdataURLとblobの2種類紹介します。

## HTML

HTMLはシンプルです。

1. HTMLはinputタグでアップロードできるようにします
2. アップロードした画像をプレビューするimgタグを用意します

``` html
<input type="file" id="file"/>                    
<img id="img">
```

## JavaScript(DataURL)

1. inputタグに値が変更されたときに動くようにイベントを設定します
2. ファイルの内容を読み取るためFileReaderを用意します
3. imgタグのsrc属性を書き換えます
4. readAsDataURLを使ってDataURLの画像を生成します

``` javascript
window.addEventListener("load", function () {
    //ファイルアップロード時
    document.getElementById("file").addEventListener('change', (e)=>{
        let fileReader = new FileReader();
        fileReader.onload = (function () {
            document.getElementById("img").src = fileReader.result;
        });
        //画像がアップロードされている場合
        if(e.target.files.length > 0){
            fileReader.readAsDataURL(e.target.files[0]);
        }
    })
});
```

## JavaScript(blob)

1. inputタグに値が変更されたときに動くようにイベントを設定します
2. URL.createObjectURLを使ってblobの画像を生成し、imgタグのsrc属性を書き換えます

``` javascript
window.addEventListener("load", function () {
    //ファイルアップロード時
    document.getElementById("file").addEventListener('change', (e)=>{
        //画像がアップロードされている場合
        if(e.target.files.length > 0 ){
            document.getElementById("img").src =  URL.createObjectURL(e.target.files[0]);
        }
    })
});
```

以上です。
実装する環境で使い分けてみてください！
30年記念誌の作成 (その3)

pandas の DataFrame をブラウザーで表示する方法です。

## DataFrame を JSON に変換

```text
df.to_json('data.json',orient='records')
```

## JSON を表示する

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8"/>
<title>JSONデータ表示</title>
</head>
<body>
<div id="app"></div>
<hr />
<p>Dec/04/2024</p>
<script src="./df_display.js"></script>
<link rel="stylesheet" href="df_display.css">
</body>
</html>
```

```js:df_display.js
fetch('data.json')
  .then(response => response.json())
  .then(data => {
//    console.log(data); // コンソールに表示

var str_out = ""

str_out += "<table>"
for (it in data)
	{
	str_out += "<tr>"
	str_out += "<td>" + data[it]['school'] + "</td>"
	str_out += "<td>" + data[it]['date_held'] + "</td>"
	str_out += "<td>" + data[it]['1'] + "</td>"
	str_out += "<td>" + data[it]['2'] + "</td>"
	str_out += "<td>" + data[it]['4'] + "</td>"
/*
	str_out += "<td>"
	str_out += JSON.stringify(data[it])
	str_out += "</td>"
*/
	str_out += "</tr>"
	}
str_out += "</table>"

const app = document.getElementById('app')
app.innerHTML = str_out
	
})
```

```css:df_display.css
/* -------------------------------------------------------------- */
/*
	df_display.css

						Dec/04/2024
*/
/* -------------------------------------------------------------- */
table.main,td,th {
table-layout:fixed;
border:1.5px #7e7e7e solid;
border-collapse: collapse;
height: 16px;
}

th {
	background: #c6c6c6;
}

/* -------------------------------------------------------------- */
```

## 簡易サーバーを立ち上げる

```bash
http-server
```

```text
$ http-server
Starting up http-server, serving ./

http-server version: 14.1.1
```

ブラウザーで
http://127.0.0.1:8080/
にアクセス
[Android] ScrollViewのonScrollChangedコールバックが呼ばれない！

めちゃハマりました。
ScrollViewを継承したクラスを作成したのですよね。
```kotlin
class MYScrollView(
    context: Context,
    attrs: AttributeSet? = null
) : ScrollView(context, attrs) {
    override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {
        super.onScrollChanged(l, t, oldl, oldt)
    }
    // ...いろいろ
}
```
こんなのです。で、これをとりあえずAndroid Studioからアクティビティ一つだけのプロジェクトを作って、そこにこのViewを張り付けて動作確認したら、なんと <b>onScrollChangedがコールバックされない！</b>

まじ？？一瞬目を疑いました。そこからググって色々な方法を試しましたが結局解決せず。
この方法は別のアプリでは動いていたんです。新規プロジェクトを作ったからといって動かないはずはない。

で、あれこれ調べてようやく解決しました。
原因は、<b>Acitivtyのレイアウトに直接MyScrollViewを書いていたこと。</b>
で、解決策は<b>FragmentのレイアウトにMyScrollViewを書くこと。</b>

でした。

。。。何を言っているかわからない。と思いますが、私も何を言っているのかよくわかっていません。なぜこれで動いたのか。なんてことは考えたくもないです。とにかく動いた。よかったよかった。

で、この問題、ScrollViewだけでなくRecyclerViewとかも同じようです。とにかくコールバックされたければFragmentにViewを配置すべし。ってことですかね。

教訓：動作確認用プロトでも、Fragmentは履かせましょう
API Best Practices ~利用しないフィールドを含めないこと

## 利用しないフィールドを含めないこと

https://protobuf.dev/programming-guides/api/#dont-include-fields

API定義はシステムとやり取りをするための項目だけに留めましょう。
余計な情報は混乱のもとです。

デバッグしたい場合に、`RPCレスポンス拡張（サイドチャネル）`を利用するとよいなどと書いてありましたが、よくわかりませんでした。

実機上でのトレースであれば、昨今は Datadog など便利なサービスも充実しています。
余計なデバッグ用フィールドを挿入せず、シンプルに保っていきましょう。
IoTで飲み会を計測したい「システム構成編」

前回の記事ではIoTお猪口のハードウェアについて解説しました。IoTお猪口の最後の記事ではシステム構成を解説します。POC段階のため、とにかく取り回しの良さと変更の容易さを重視しています。

![iot_ochoco1.drawio2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948175/5d3867a9-7673-a06d-1d55-a9a43e7f0b8e.png)


## ネットワーク

ネットワークは全て私用スマホのテザリングを使用しております。社内ゲストwifiを使う方法も考えましたが、まだPoC段階であるため影響が個人に閉じるスマホのテザリングにしております。2台のIoTお猪口を2時間稼働させてほぼ毎秒に1回データを送信し、それをmqttサーバーで受信してGCP datastoreへ転送しても通信量や通信プランの料金で支障が出ることはありませんでした。


## 各種プロトコル

Raspberry Pi Pico W はHTTP・BLEともに対応していますが、今回はHTTPのみとしました。理由としては最終的にdatastoreへ格納するデータのタイムスタンプをデバイス側で管理したいこと、BLEの接続が複数台運用する前提を考えると手間であったことです。データのタイムスタンプについてもう少し説明しますとdatastoreにはmqttサーバーを経由して書き込んでいますが、IoTお猪口から送信したデータをmqttサーバーで受信するタイミングが頻繁に遅延します。そのため、仮にmqtt上の処理が実際のデータ取得時間から数十秒ずれてもその遅延の影響を受けないように、データ取得時のタイムスタンプを用いる必要がありました。Raspberry Pi Pico Wは時刻の情報を持っておりませんので基準となる時刻を取得してそこからの経過時間を計算することで送信するデータにタイムスタンプを追加しています。

時刻の取得には当初NTPを使用していましたが接続が悪く、しばしば結果が戻ってこないため別の方法を採る必要がありました。代替案としてHTTPでgoogleにアクセスした際のサーバータイムを利用しております。この方法は安定性が高く、かつ1,2秒の誤差は許容できるシステムであるため正確性も問題ありませんでした。

## クラウド

現在、GCPにマネージドのIoTサービスはありません。

https://cloud.watch.impress.co.jp/docs/column/infostand/1435452.html

AWSにはIoT系のサービスが存在しますが手間を考えるとAWSを経ずにGCPのみで完結することが理想でした。大規模な運用であればdataflowを立ててmqttを受けるという選択肢もありますが、dataflowは非常に高額かつ大掛かりであるため今回の用途には不適です。結局、mqttサーバーからdatastoreへ格納する方式を取っています。


## 可視化

datastoreに格納した結果はStreamlitで可視化しています。

![スクリーンショット 2024-12-07 11.42.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948175/42a3cdae-2f9b-f640-9c6f-dd6caa482527.png)


最終的にはGCPのCloud Runに置くつもりでしたが、まだ頻繁に編集するためローカルのdockerで稼働させております。PoC当日はモバイルディスプレイにstreamlitの結果を投影しており、複数名で挙動を確かめたり結果について議論したりとIoTらしいモニタリングを行うことができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948175/fe2fac19-aae6-6ded-7441-a1236f7dcccb.png)


## システム的な展望

今回は結果をほぼ毎秒mqttサーバーへ送信していましたが将来的な利便性を考えると飲んだ・注いだ瞬間だけ通信を行うことにして、かつ通信はmqttサーバーを排してスマホのテザリングにhttpで行うと構成がコンパクトになって理想的です。ついでに現在は私物PCで確認しているstreamlitをGCP Cloud Runに置けば手元のスマホで進捗が確認可能で、私物PCを排すことができます。これで私物PCに誤って日本酒をかけたりスルメをキーボードに落としたりする心配もなくなります。

また、IoTお猪口側からGCPにアクセスして蓄積しているデータを取得し活用するような双方向のやり取りを安定した通信のもとに行うことでデバイスの可能性は格段に拡がります。GCP datastoreに溜まっているデータを加工して戻す Cloud Run Function は構想しております。例えば、その日飲んだ量を端末に戻すことも可能なはずです。

## コードについて

コード自体はあまりに拙いので掲載はやめておきました。MicroPythonで書かれており、時刻の取得や各種センサーからの値の取得とmqttサーバーへの通信が書かれているくらいです。次のプロトタイプではジャイロセンサー（MPU-6050）は無くして現在はアームの動きを検知しているホールセンサーの設置位置を変えて傾きも同時に取得することを考えておりますのでコード自体が大幅に変わる都合もあります。

続報をお楽しみに！
IoTで飲み会を計測したい「ハードウェア編」

前回の記事ではIoTお猪口の開発の経緯について書きましたが、今回はハードウェアをご紹介します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948175/05917933-714b-2bca-982f-73443d28df90.jpeg" width=50%>

## 回路

![回路の図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948175/d50bc45c-bce1-b353-e5ee-20c200f4f4df.png)
（※単4電池2本は描画の都合上電池1本で示しています）


## マイコンとセンサー

- Raspberry Pi Pico WH
  - 小型で安定しており、wifi・BLEが使用可能です。秋月電子で買えば技適ももちろん問題ありません
  - 次のプロトタイプへ使い回せるようにピンヘッダ付を選択しました

https://akizukidenshi.com/catalog/g/g118086/

- MPU-6050
  - 秋月電子で取り扱っていないためAmazonで適当に買いました
  - I2CかつMicroPythonのライブラリが存在するためお手軽です

https://docs.sunfounder.com/projects/ultimate-sensor-kit/ja/latest/components_basic/05-component_mpu6050.html

- HC-SR04
  - 価格が安く、取得できる最短距離が2cmです
  - I2CかつMicroPythonのライブラリが存在するためお手軽です
  - 計測の誤差が1cmほどあり、別のセンサーにするか迷っています

https://akizukidenshi.com/catalog/g/g111009/

- ホールIC SK8552G SIP-3
  - 実装を楽にするため両極検知としました

https://akizukidenshi.com/catalog/g/g111029/

## 電源

- 電池ボックス 単4×2本
  - スイッチを兼ねており、電池が入った瞬間に電源ONです。今回は秋月電子で購入していますが購入元により若干大きさに差があるようです

https://akizukidenshi.com/catalog/g/g102245/

- 単4電池
  - 格納場所がタイトだったため単4としました
  - エネループを使ったり100円ショップのアルカリ電池使ったり適当です

## 導線と3Dプリンター

- 導線 AWG24相当
  - 格納場所がタイトだったため細い導線を使用しています

- デュポンコネクター各種
  - raspai pico wを別プロトタイプで使い回しできるようにするためコネクターを使用しています
  - Amazonで適当に買ったものと秋月電子で買ったものを両方使用しましたがあまり違いは感じませんでした

https://akizukidenshi.com/catalog/r/rqi2550/

- eSUN PLA Plus 3Dプリンターフィラメント
  - 特にこだわりはないため安いものを選びました

https://www.esun3d.com/pla-pro-product/

## その他

- Seria クリアカップ 110ml（18個）
  - 容量が小さく、比較的側面が垂直に近いプラ製の使い捨てカップです
  - 入手性が良いもので小さめなカップを探して選んでおります

- Seria 丸型超強力マグネット 8P（直径6mm,厚み2.5mm）
  - ホールセンサーで検知するための磁石です

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948175/834d6399-052f-c069-10a4-acfc4ddd7844.jpeg" width=50%>

- 粗面用強力両面テーブ
  - クリアカップは両面テープで貼り付けています
  - 厚みのある粗面用で取れないようにしっかり貼り付けております

- マスキングテープ（黒）
  - 今回はまだPoCのため分解しやすいようにマスキングテープを多用しています
  - 色は目立たないように黒です

- 輪ゴム
  - 超音波センサーの付いているアームを戻すバネとして使用しています

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3948175/867bc0ec-beec-a159-ca10-66e7f5253c95.jpeg" width=50%>
「機械工学で学ぶオブジェクト指向プログラミング#(その1)使用例」様を参考に、sympyのBeamでやってみたい。

・（2024−12−05）タイトルに#使用例を追加しました。
旧タイトル　
「機械工学で学ぶオブジェクト指向プログラミング」様を参考に、sympyのBeamでやってみたい。

**・SFD　と　BMDは、ver0.2で対応予定です。**

:::note info
 次 [(その2)はりの基本問題　へ
](https://qiita.com/mrrclb48z/items/a6f5ecb20b793b563bdc)
:::

# オリジナル 
・#使用例

https://qiita.com/ShuseiNakahara/items/bfbe9069b4f5fffd02ac#%E4%BD%BF%E7%94%A8%E4%BE%8B

# sympyのBeamで 「集中荷重による変位」
・作図しました。
```python
# ver0.1
from sympy import *
from sympy.physics.continuum_mechanics.beam import Beam
from sympy import symbols
E,I,P =symbols('E,I,P')
l,a,lp=symbols('l,a,lp',positive=True)
var("R,x,M,A1,A2,M1,M2")
var("p0,m0")
R1,M1=symbols('R1,M1')
R2,M2=symbols('R2,M2')
def myBeam_Katamoti_Tawami(l,E,I,P):
    b=Beam(l,E,I)
    b.apply_load(P,l,-1) 
    b.apply_load(R,0,-1)   
    b.apply_load(M,0,-2)
    b.bc_deflection.append((0,0))
    b.bc_slope     .append((0,0))
    b.solve_for_reaction_loads(R,M)
    return b.deflection()
def myBeam_Katamoti_lP_Sakuzu(l,E,I,P ,lp):
    b=Beam(l,E,I)
    b.apply_load(P,lp,-1) 
    b.apply_support(0, 'fixed')
    p = b.draw()  
    p.show() 
    return 
δ =myBeam_Katamoti_Tawami(a,E,I,P)             
δa=myBeam_Katamoti_Tawami(a,E,I,P).subs({x:a})   #;print("#",δa)
θa=diff(δ,x)                      .subs({x:a})   #;print("#",θa)
δl=δa+(l-a)*θa
rep={l:5000,a:4000,E:205,I:8333333,P:1}
print("# 集中荷重による変位:",float(δl.subs(rep)))
# # 作図
myBeam_Katamoti_lP_Sakuzu(5000,205,8333333,1,4000)
# 集中荷重による変位: 17.17073239414637
```
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/9fb63e53-89ff-284d-23c3-e281ca3e1b74.png)

# sympyのBeamで 「分布荷重による変位」
・勉強中

# いつもの? sympyの実行環境と 参考のおすすめです。
[(テンプレート)](https://qiita.com/mrrclb48z/items/00dd08b0317069be9342) 　開発環境


# いつもと違うおすすめです。

https://docs.sympy.org/latest/modules/physics/continuum_mechanics/beam.html

https://ja.wikipedia.org/wiki/%E3%81%AF%E3%82%8A%E9%83%A8%E6%9D%90

https://ja.wikipedia.org/wiki/%E5%BC%BE%E6%80%A7%E6%9B%B2%E7%B7%9A%E6%96%B9%E7%A8%8B%E5%BC%8F#%E3%83%99%E3%83%AB%E3%83%8C%E3%83%BC%E3%82%A4%E3%83%BB%E3%82%AA%E3%82%A4%E3%83%A9%E3%83%BC%E3%81%AE%E4%BB%AE%E5%AE%9A#微分方程式の直接解法
キャリアブレイク中にやっている勉強① アルゴリズム問題を解く

今日はキャリアブレイク中に具体的にやっている勉強について書きます。結構色々やっているのですが、最初に書くのは「アルゴリズム問題を解く」です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100916/79a873d2-acb2-b3e0-ba36-71766351fcac.png)

# アルゴリズム問題を解くことに興味はなかった
自分は去年ぐらいまでアルゴリズム問題を解くことは殆どありませんでした。あまり重要視していなかったし、Paizaなどで遊び程度でやった時もあまり意義は感じていませんでした。それよりも物作りの方が楽しいので、そっちに時間を割きたいと思っていました。

# コミュニティがきっかけで初めてみる
ところが、自分が[参加しているコミュニティ](https://greek-academy.org/)でアルゴリズム問題を解くことを重要視しているので、それがきっかけで解くようになりました。ちゃんとやってみると普段使っていない部分の脳が汗をかくような感じがして、プログラマの筋トレ！？として良いかもと思うようになりました。

# とはいえ解くのは難しい
そのコミュニティで20問ぐらい解いたと思いますが、正直得意ではないなとずっと思っていました。短い時間で解けることは少なく、説明を聞いてもすぐに実装出来ないことも多かったです。自分としては解くことを日課にして基礎力を上げたいという思いがあり、今回アルゴリズム問題を解くことを日々の勉強課題にしました。

# LeetCode→NeetCode
そのコミュニティでは[LeetCode](https://leetcode.com/)を推していました。自分もとても良いサイトだと思いますが、勉強を初めてから知った[NeetCode](https://neetcode.io/)が自分には一番合っていると感じました。なので今は日々NeetCodeを使っています。ちなみにNeetCodeはLeetCodeの問題を独自のルールで順番付けしたり、解説を充実させたりしているだけでアルゴリズム問題自体は同じです。

# NeetCodeの気に入ったところ
NeetCodeは解いていく順番が決まっており、ジャンル毎にすすめていくスタイルです。計算量毎に回答コードが書いてあって、別途、動画の解説も用意してあります。回答の言語も多くてC#が選べます。どれもLeetCodeでも探したら見つかる気もしますが、オールインワンパッケージみたいにまとまっているところが気に入りました。気に入らない所はC#のバージョンが最新ではない所ですかねｗ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100916/ebec98b0-57b9-66d5-9e4b-19e40f47a24a.png)

# 自分の進め方
基本1日1時間を上限にして問題を解いています。まずは計算量を気にせず解けそうな方法を考えて解きます。ここは最大で1日考えます。解けた場合はより速い計算量で解けるかまた考えます。但し、この場合は最大で15分にしています。それで分からなければ動画を見て、それでも分からなければ回答を見た上で、自分で書けるようになるまで解きます。問題によって違いますが、1問に3日以上かけたものもありました。11月で解いた問題数は7問でした。

# 基本サイト上で解く
まず解く時は基本サイト上でやっていて、分からない限りググったりIDEは使いません。何となく使わずに書いたら結構気づくこともあったので、その後も使わずに書いています。デバッグもprintfが中心です（ただ、これはたまたま今回そうしただけで、基本的にIDEを使うことは賛成派です）。あと、回答を変えて解いていくとその行程が残らないので、最近は、解いた結果は[Github](https://github.com/binnmti/SolveLeetCode)に残すようにしました。

# 翻訳しない
キャリアブレイク中の勉強の1つに英語学習もあるのでどちらかというとそのためのルールですが、「日本語に翻訳」も使わないようにしています。正直、英語のサイトとか動画とかまだ殆ど理解出来ないのですが、なぜかアルゴリズム問題に関しては結構英語が分かった気になったのでそれが嬉しかったことが大きいです。（ただ、[この問題](https://neetcode.io/problems/valid-sudoku)は完全に文章を読み間違えて、純粋に数独を解くアルゴリズムを考え出して無駄に2日ぐらい悩んでしまいました。。）

# やってみて
こんな感じでアルゴリズム問題を解いており、解いてみた感想としては、色々気づきがあって楽しいです。[HashSet](https://neetcode.io/problems/valid-sudoku)とか[PriorityQueue](https://neetcode.io/problems/top-k-elements-in-list)とか仕事では使ったことないし、末尾から追加していく場合は[ListよりArrayの方が良い](https://neetcode.io/problems/top-k-elements-in-list)なとか初めて思いました。まだ、力がついた！みたいな実感は薄いですが、同じジャンルの問題をまとめて解くスタイルは進めやすいと感じています。