OmniAICreator/Qiita-1.07M huggingface dataset:
Swift: テキストファイルの書き込み

## プログラム

```text:text_write.swift
// -----------------------------------------------------------------
//
//	text_write.swift
//
//						Oct/20/2024
// -----------------------------------------------------------------
import Foundation

let arguments = CommandLine.arguments
let filename=arguments[1]

let fileManager = FileManager.default
let url = URL(fileURLWithPath: filename)
let filePath = url.path        

let result = fileManager.createFile(atPath: filePath, contents:nil)
print(result)
	
let file = FileHandle(forWritingAtPath : filename)!

var str_out = "*** start ***\n"
str_out += "こんにちは\n"
str_out += "*** end ***\n"

file.write(Data(str_out.utf8))

try file.close()
// -----------------------------------------------------------------
```

## 実行

```bash
swift text_write.swift out01.txt
```

実行結果

```text
$ swift text_write.swift out01.txt
true
```

```text:out01.txt
*** start ***
こんにちは
*** end ***
```

## テキストファイルの読み込み

[テキストファイルの読み込み](https://qiita.com/ekzemplaro/items/d0bfd88f873276f97a31#%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%81%BF)

## 確認したバージョン

```text
$ swift --version
Swift version 6.0.1 (swift-6.0.1-RELEASE)
Target: x86_64-unknown-linux-gnu
```
[PostgreSQL]自動インクリメントとUUIDの違い

## はじめに
オリジナルアプリを作成するにあたって、Supabaseを使用してデータベースを構築しました。その際に、各テーブルのIDカラムの型を指定する際に新しく学んだことがあったため、備忘録も兼ねてまとめていきます。


## 調べるきっかけになったこと
データベース設計を行う際に、各テーブルに主キーを設定すると思います。
その際、私は以下のようにInteger型を指定していました。

|| カラム名 | 型 | 
| ---- | ---- | ---- |
|PK| id | Integer |
|| nickname | String |
|| email | String |
|| password | String |

今までMySQLを使ってデータベース構築をすることが多く、主キーに対して自動インクリメント(ID)でidフィールドを設定していたのですが...

**Supabaseの場合だとUUIDで保存されるので、idカラムはString型にしましょう**

とレビューをいただいたので、自動インクリメント型(Integer型)とUUID(String型)で主キーを保存する違いについて調べてみました。


## 自動インクリメント型(Integer)
IDが連番の整数値で管理される。
データベースのIDフィールドに新しいレコードが追加されるたびに、`1,2,3...`と順番にID番号が増加する。

#### 特徴
- 一意性
1つのデータベース内で一意のIDを持つ。
ただし、異なるデータベースやシステムの間では重複する可能性がある。
<br>

- メモリ効率がよい
32ビットまたは64ビットの整数型で、最大でも10桁や19桁の数値で表されるため、インデックスや検索を効率的に行うことができる。
<br>

- 管理がシンプルだが、特定がしやすい
数値で管理をするので、視覚的に分かりやすくデータ管理ができる。
一方で、連番でデータを管理するため次のIDが予測しやすく、セキュリティリスクがある。


## UUID
全世界で一意の識別子を生成するための方法。
現在多くのRDSで採用されており、どのIDとも重複しないのでユニーク性の高さが保証されている。

- 一意性
世界中で一意のIDを生成できる。
異なるシステム間やデータベース間でUUIDが衝突する可能性が極めて低い。
<br>

- サイズが大きい
128ビットのデータを使って生成されるため、一般的に36文字で表現される。
そのためかなり長い文字列になり、インデックスや検索性能に影響を与える場合がある。
<br>

- 推測されにくい
ランダムに生成されるため、外部からIDを推測することが非常に困難。
人間が読みやすい形式ではないため、視認性は落ちるがセキュリティの安全性は高い。

## 両者の比較
|特徴| 自動インクリメント | UUID | 
| ---- | ---- | ---- |
|一意性|データベースの中のみ一意|全世界で一意|
|サイズ|32bitまたは64bit|128bit|
|推測性|高い|低い|
|用途|小規模システム, パフォーマンス重視|分散システム,セキュリティ重視のシステム|
|パフォーマンス|高速かつ効率的|インデックス効率が低いことがある|
|セキュリティ|低い|高い|
|データベースサイズ|小さい|大きい|

## 使い分けは？
システムの要件や規模、用途によって選択をする必要があるが、以下をベースに判断する。

- 小規模、シンプルな構成のアプリケーション→自動インクリメント(Integer型)
- 分散システムや高いセキュリティを求める場合→UUID
Android Studioでまとめて操作

Android Studioでまとめて操作したい時、いつもショートカットを調べているので、よく使用するものをメモする。


#### ファイル移動
左のタブから移動させたいファイルをまとめて指定 → 右クリック → Rifactor → Moveで、まとめて操作できる。(最近知った)

#### 変数を置き換える。
`Shift + F6`で指定した変数に置き換え後の変数を記述、Enterで置き換える。


#### プロジェクト全体から検索した文字列を置き換える。
`コマンド + Shift + R`で置き換えたい文字列と置き換え後の文字列を記述しEnterで置き換える。


#### `Ctrl + R`と`Shift + F6`の違い
`Shift + F6`は選択した変数名やクラス名を使っている単語を入れ替える。`Ctrl + R`や`コマンド + Shift + R`での置き換え事故を防ぐことができる。

#### `command + shift + F`と`Shift * 2`の違い
どちらも同じ検索機能がある。`command + shift + F`は指定した単語を全体検索する。`Shift * 2` はクラス名、ファイル名などを全体から検索できる。単語自体を検索している分、前者の方がより多く検索に引っかかる。

####  参考

https://qiita.com/arai-wa/items/b0957d042c479577e8e3
【Next.js×Supabase】"supabaseUrl is required."エラーの解消方法

# はじめに
各バージョンはこちらです。

**Next.js：14.2.13
Supabase：2.45.4**
# 問題
**"supabaseUrl is required."のエラー**が出ました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/d0c3d2dc-5f4b-0173-d419-3acc30f587de.png)

# 解決方法
**環境変数の冒頭に`NEXT_PUBLIC_`を付けないと参照されない**ようです。
```ts:supabase.ts
import { createClient } from "@supabase/supabase-js";

const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL as string;
const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_KEY as string;

export const supabase = createClient(supabaseUrl, supabaseKey);
```
# おわりに
**Reactでも似たようなエラー**が起きたことがありましたが、今回Next.jsでも遭遇しました。

下記はReact_APPの例ですが、SupabaseのDeveloperさんが「Reactだったら環境変数の冒頭に"REACT_APP_"って付けないとダメなんだよね～」って言ってます。

https://github.com/orgs/supabase/discussions/3218

公式ドキュメントでもしれっと`NEXT_PUBLIC_`付いているのでこの通りに設定をしたらいいかと思います。

https://supabase.com/docs/guides/getting-started/quickstarts/nextjs

# ※追記
**`NEXT_PUBLIC_`をつけるとクライアント側で情報公開されてしまうリスクもあります。**
下記記事にて、`NEXT_PUBLIC_`を参照せずにサーバー側で使用する手順を説明しています。

https://qiita.com/AK_React/items/dbbff87c7215c09fe7b5
ルーターとは

# ルーターとは
>`ネットワークの中心的な役割を果たす機器`です。その機能を一言で言えば、`「ネットワーク層（レイヤー３）のプロトコルであるIPにおいて、IPパケットを転送する」`働きをします。使い方の視点で見ると、`「相互に独立しているイーサネットネットワークの間に入って、両者の間でパケット（情報）を中継するもの」`ということもできます。そのままではお互いに通信できない個別のネットワークが、`ルーターが間に入ることにより、相互に通信できる`ようになります。それでいて、個別のネットワークの独立性は失われません。
　レイヤーの考え方で見ると、`物理層（レイヤー１）とデータリンク層（レイヤー２）からなるイーサネットの範囲では独立`しているネットワークを、ネットワーク層（レイヤー３）の働きで中継するものがルーターということになります。

https://www.sbcr.jp/product/4797386677/

* ネットワーク層（レイヤー３）のプロトコルであるIPにおいて、IPパケットを転送する
* 相互に独立しているイーサネットネットワークの間に入って、両者の間でパケット（情報）を中継するもの

# 
アクセスポイントによって無線で使用端末とルーターの間を取りもち、ルーターはどのような動きをするのか、具体的に理解したい。

# Wi-Fiを使用するためにはルーターが必要
>自宅や職場などでWi-Fiを利用するには、Wi-Fiルーターが必要となります。Wi-Fiルーターとは、`Wi-Fi機器と電波の送受信を行いLANとの仲介を行うための機器`で、無線LAN親機とも呼ばれています。

https://www.buffalo.jp/topics/select/detail/wifi-about.html#:~:text=%E8%87%AA%E5%AE%85%E3%82%84%E8%81%B7%E5%A0%B4%E3%81%AA%E3%81%A9%E3%81%A7Wi%2DFi%E3%82%92%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF%E3%80%81Wi%2DFi%E3%83%AB%E3%83%BC%E3%82%BF%E3%83%BC%E3%81%8C%E5%BF%85%E8%A6%81%E3%81%A8%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82Wi%2DFi%E3%83%AB%E3%83%BC%E3%82%BF%E3%83%BC%E3%81%A8%E3%81%AF%E3%80%81Wi%2DFi%E6%A9%9F%E5%99%A8%E3%81%A8%E9%9B%BB%E6%B3%A2%E3%81%AE%E9%80%81%E5%8F%97%E4%BF%A1%E3%82%92%E8%A1%8C%E3%81%84LAN%E3%81%A8%E3%81%AE%E4%BB%B2%E4%BB%8B%E3%82%92%E8%A1%8C%E3%81%86%E3%81%9F%E3%82%81%E3%81%AE%E6%A9%9F%E5%99%A8%E3%81%A7%E3%80%81%E7%84%A1%E7%B7%9ALAN%E8%A6%AA%E6%A9%9F%E3%81%A8%E3%82%82%E5%91%BC%E3%81%B0%E3%82%8C%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82


# LAN内の子機にもアクセス可能になる
>ルーターに接続された子機は、インターネットへの接続が可能になるとともに、`同じルーターに接続している他の子機（PC、周辺機器、スマートフォン、デジタル家電など）にもアクセスが可能`になります。これは、ひとつのネットワーク（＝LAN）に属することを意味します。

https://www.elecom.co.jp/pickup/column/wifi_column/vol13/#:~:text=%E3%83%AB%E3%83%BC%E3%82%BF%E3%83%BC%E3%81%AB%E6%8E%A5%E7%B6%9A%E3%81%95%E3%82%8C%E3%81%9F%E5%AD%90%E6%A9%9F%E3%81%AF%E3%80%81%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%8D%E3%83%83%E3%83%88%E3%81%B8%E3%81%AE%E6%8E%A5%E7%B6%9A%E3%81%8C%E5%8F%AF%E8%83%BD%E3%81%AB%E3%81%AA%E3%82%8B%E3%81%A8%E3%81%A8%E3%82%82%E3%81%AB%E3%80%81%E5%90%8C%E3%81%98%E3%83%AB%E3%83%BC%E3%82%BF%E3%83%BC%E3%81%AB%E6%8E%A5%E7%B6%9A%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E4%BB%96%E3%81%AE%E5%AD%90%E6%A9%9F%EF%BC%88PC%E3%80%81%E5%91%A8%E8%BE%BA%E6%A9%9F%E5%99%A8%E3%80%81%E3%82%B9%E3%83%9E%E3%83%BC%E3%83%88%E3%83%95%E3%82%A9%E3%83%B3%E3%80%81%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E5%AE%B6%E9%9B%BB%E3%81%AA%E3%81%A9%EF%BC%89%E3%81%AB%E3%82%82%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%8C%E5%8F%AF%E8%83%BD%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82%E3%81%93%E3%82%8C%E3%81%AF%E3%80%81%E3%81%B2%E3%81%A8%E3%81%A4%E3%81%AE%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%EF%BC%88%EF%BC%9DLAN%EF%BC%89%E3%81%AB%E5%B1%9E%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%82%92%E6%84%8F%E5%91%B3%E3%81%97%E3%81%BE%E3%81%99%E3%80%82

こう言うことで公衆Wi-Fiに接続することが危険なのか。
LANに関して調べたくなった。
Three.js）PlaneBufferGeometryが使えない

# 概要
古めのThree.jsの講座をやっていたら、PlaneBufferGeometryが使えずエラーになったので、対応内容をメモします。

# エラー内容
```javascript:
const mesh = new THREE.Mesh(
  new THREE.PlaneBufferGeometry(2, 2, 128, 128),
  new THREE.MeshBasicMaterial(),
);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3908466/ac5eee52-fcc4-8a35-bbe8-6e33b42ed7f3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3908466/2a5ecf17-72e7-59c7-f4db-7e9c8719fa26.png)

コンソールもコード上もエラーっぽい感じになっていました。

# 対応内容
```diff_javascript:
const mesh = new THREE.Mesh(
- new THREE.PlaneBufferGeometry(2, 2, 128, 128),
+ new THREE.PlaneGeometry(2, 2, 128, 128),
  new THREE.MeshBasicMaterial(),
);
```
`PlaneBufferGeometry` -> `PlaneGeometry` としたら治りました。
どうやら[過去のアップデート](https://github.com/mrdoob/three.js/pull/26175)で非推奨の記述は削除され、`◯◯BufferGeometry` というものは`◯◯Geometry` とシンプルに書けるようになったようでした。

# 終わりに
Three.jsはありがたいことに割と高頻度で更新があるので、変更点のキャッチアップも見逃せないなと思いました :writing_hand:
【Cコード解析】switchにdefaultを追加する

引き続き静的解析ツールの指摘を自動で対処するスクリプトを考える。
今回はswitchにdefaultケースがなければ追加するスクリプトを作成する。

## switchブロックを抜き出す
下記の正規表現でマッチできる。以前にブロック単位でパターンマッチングさせる方法を記載したため、そちらをベースに正規表現を考える。
``` regex
(?<=\n)\s*switch\s*\([^()]*\)\s*(\{(?:[^{}]|(?1))*\})
```
https://qiita.com/name_ko/items/afa78577907dbd124acb

## switchブロック内にdefaultケースがあるか判定する。
下記が完成形のスクリプト。
``` python
import regex

def repl_add_default(match):
	matchstr = match.group()

	# 既にdefaultがある場合は、そのままの文字をreturn
	if not regex.search("\s*default\s*:", matchstr, regex.DOTALL):
		index = matchstr.rfind("}")

		indent = regex.search(r"[\t ]*(?=\bswitch\b)", matchstr, regex.DOTALL).group()
		matchstr = matchstr[:index] + "default: /* 処理なし */ break;\n"+ indent + matchstr[index:]

	return matchstr

with open("test.c", "r", encoding="utf-8") as file_obj:
	codetext = file_obj.read()

	ret = regex.sub(r"(?<=\n)\s*switch\s*\([^()]*\)\s*(\{(?:[^{}]|(?1))*\})", repl_add_default, codetext, flags=regex.DOTALL)
	print(ret)
```
`regex.sub`でマッチした`switch`ブロックから`default`ケースがあるか`repl_add_default`関数でチェックする。`default`ケースがあれば、マッチした文字列をそのまま置換対象とする。(つまり置換前後で変化なし)
`default`ケースがない場合は、`switch`ブロックの末尾の`}`の直前に`default`ケースを追加した文字列を置換対象とする。

## まとめ
`switch`に`default`ケースがなくて指摘されるのは、わりといろんな職場で起きてる気がする。このレベルの指摘でも量が多ければ、作業工数が増えるためどんどん自動化したい。ちょっと考えて、以後自動化できるのであれば作業を一度止めてでも自動化した方がいいと思う。
ABC376回答メモ

# 0.はじめに
　12連勤後の久々のお休み。
　問題はＢから難しくＡで終わりかとも
　思いましたが、まぁなんとかＣまではクリアできました。
　レートは+4と微増でした。


# 1.A - Candy Button
　Aからちょっと複雑な問題。と、いつも言っている気がするけど
　よく見たら150点だったので、B寄りの難しさがあるんでしょうね。
　とはいえ、問題をそのままコード化すれば何とかなりました。
　キャンディーもらってからの時間を持っておいて、キャンディーもらったら
　クリア、貰えなかったら加算、貰ったタイミングで取得キャンディー数を
　加算しておき、最後に取得キャンディー数を表示して終了。

　https://atcoder.jp/contests/abc376/submissions/58937396


# 2.B - Hands on Ring (Easy)
　B問題も250点と若干難しめ。
　とはいったものの、若干どころかややこしすぎてとりあえずCをやるほどでした。
　ここも心を無にして、クエリ毎に、右回りと左回りをシミュレートして
　行けるほうを採用していく方式でACとれました。

　https://atcoder.jp/contests/abc376/submissions/58966860


# 3.C - Prepare Another Box
　COBOLのバッチ処理で鍛えた自分には簡単な問題。
　AとBを降順ソートし、A[i]とB[i]を比較していく
　A[i]>B[i]の時、合う箱が無いので、その分の箱を作るとし変数ansにセット。
　　その後は、A[i]とB[i-1]を比較していき、A[i]>B[i-1]が
　　発生したら、2個目の箱を作らなければいけないので、NG判定
　　発生しなかったら、ansを出力して終了
　A[i]>B[i]が一回も発生しなかったら、最後のA分の箱を作れば
　よいので、それを出力して終了

　https://atcoder.jp/contests/abc376/submissions/58954531


以上
[Rust] 素因数分解


rustで、何を作ろうかと思って、まず始めに、やっぱり基礎的なものから始めようと思い、素因数分解を作りました。
rustは書きやすそうですね。オブジェクト指向言語と言っても、ちゃんと手続き型言語的なものも書けそうだし。
rustに惚れちゃいました。

## 本体

```rust:factor.rs
use std::env;
fn primefactorization(mut n: i32) -> Vec<i32> {
  let mut f = vec![];
  if n==0 || n==1 {
    return f;
    }
  let mut i = 2;
  while n!=1 {
    if n%i == 0 {
      f.push(i);
      n/=i;
    }
    else {
      i=i+1;
    }
  };
  f
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let n=&args[1];
    let n:i32=n.parse().unwrap();
    let f=primefactorization(n);
    println! ("{:?} : {:?} ",n,f);
}
```

簡単なプログラムなので、cargoを動かす必要はありません。
`rustc factor.rs`、`./factor n`で動きます。
マネジメント｜相手の良いところを見つけよう

# はじめに

エンジニアのみなさま、日々の学習本当にお疲れ様です！
また本記事まで足を運んでいただき本当に感謝です。
約4分で読めるため、最後まで読んでもらえると幸いです。

-------------

最近インスタで、日本プロ野球（以下NPB）で活躍した **G.G.佐藤氏** のリールがよく流れてきます。思わず笑ってしまうリールがメインですが、彼の経験則で語られる内容がマネジメントにも通じるものが多い印象です。今回は個人的に特に良かった内容をご紹介しようと思います。

# そもそもG.G.佐藤ってどんな人？

https://ja.wikipedia.org/wiki/G.G.%E4%BD%90%E8%97%A4

今のNPBでも珍しい、大学卒業後にアメリカのマイナーリーグの選手として活躍しNPBのドラフトにかかった、いわゆる「逆輸入」の選手として注目を浴びました。NPBの実働は8年間ですが、北京オリンピックの代表選手としても選出された実力です。
NPBから戦力外通告後、イタリアに移って野球を続けた異色の経歴もあります。

ちなみに「G.G」の由来は、

>佐藤本人によれば、中学の野球チーム（港東ムース時代）にオーナーだった野村沙知代から「シャキッとしなさい。ジジイじゃないんだから」と叱られたのがきっかけだったと云う

らしいですw

そんな世界を渡り歩き、世界の文化に触れたG.G.佐藤氏が「日本とアメリカの指導の違いについて」語っているリールを見て、とても素敵な考えだなと感じることがあったためご紹介したいと思います。

# 以下、インタビュー形式で行われたリールの内容

インタビュアー：イ　G.G.佐藤氏：G


イ：もともとGGさんってプロになる前はアメリカでも野球されてましたよね？
　　その時のアメリカのエピソードを教えてもらえれば

G：学生時代は全然成長できなかったけど、アメリカに行って野球選手としてグっと伸びたので

### アメリカの指導法みたいなものはすごく好きなのね

日本は素晴らしいところもたくさんあるけど、まだ良くないところもある気がして

とりあえず怒ったりとか

足りないところを指摘したりとか

直すような指導が多くてあまり好きじゃなかったの

で、今は講演活動もやってるんだけど、特に子供達には

### あなたはあなたのもので素晴らしいんだと。良いもの持ってるんだから、良いところをどんどん伸ばしてください

ていうメッセージを送るんだけどアメリカもほんとそうなの。

### 常に認めてくれるし、褒めてくれるし、まずは良いところを見てくれる感じ

例えば、チャンスで回ってきて初球ショートゴロゲッツー。アウト。

ベンチに戻ると

### 『ナイススイング』

いや、どこがですが？今ゲッツーだったんですけど？

### 『アグレッシブだったじゃないか？』と。 『自分のスイングができてたぞ。』と。 『でもボール球に手を出しちゃったな。 次の打席は、打つボールをもっと絞っていこうぜ！』っていう。こういう感じなの

### まずは良いところを見つけてあげた後に改善点といえばここですよっていう感じで。分かる？

イ：もし日本だったら初球ゲッツー。ベンチに帰ったら怒られますよね？

G：『なんでお前ボール球に手を出してるんだよ！』で終わりじゃん。違う！

まずは良いところを見てより良くするためにはこうしたほうが良いよっていうこの順序な訳よ。

そうすると入ってくるじゃん。

### まずは聞く耳を持たせてあげる状態を作ってからポイントを教えてくれる

---------

リール自体は90秒ほど、テキストのみだと伝わりづらいとも思ったんですが、個人的にはすごく印象的なものだったので今回ご紹介させていただきました。不思議なもので、仕事を進める中で、またはプライベートでは、相手の悪いところは意識せずとも見えるケースが多い（性格悪いよね）ですし、実際に上記の様な形でやってしまっているケースもあるなと、このリールを見て反省しましたw

一方で、相手の良いところは意識せずとも見えてる可能性はあるものの、ちゃんと言葉に出して伝えているかで考えると少ないかもなとも思いました。

# さいごに

普段の仕事の中で、もしかしたら本人も気づいてない様な何気なく取り組んでいる内容であっても、個人的に良いなと思ったポイントがあれば感謝して伝える習慣をつけたいなと感じました。また指導する機会があった時には、一度立ち止まり、「本当に伝えるべき内容になっているか？」を考えてから伝えようとも感じました。

気がついたらスマホを触ってリールを見ながらだらけてしまう事が多いですが、今回はだらけて良かったなと思いましたw

良いリールに出会えて良かったです＿φ(￣ー￣ )

# おまけ

弊社のご紹介もさせてください！

### 「日本で一番エンジニアが成長できる会社を創る」

https://prum.jp/

### エンジニアリングの募集

https://www.wantedly.com/projects/1808638

### PM・Webディレクションの募集

https://www.wantedly.com/projects/1355235

### セールス・事業開発の募集

https://www.wantedly.com/projects/1792065

### コーポレート系の募集

https://www.wantedly.com/projects/1752874

### コンサルティングの募集

https://www.wantedly.com/projects/1794481

弊社メンバーは日々学習した内容をアウトプットしております！
少しでもご興味を持たれた方は求人を見てみてください！
ご応募もお待ちしております！

### 最後までご覧いただき、ありがとうございました！
BAKETAN Mamoridama まもりだま を買ったので調べてみた

<b>まもりだま</b> は2021年21月に発売された<b>世界初の「デジタルお守り」</b>で、周辺の状態を常にチェックし特殊な状態の時に自動でその場を浄化。好ましい状態の場合はより好ましく活性化させるデジタルガジェットです。今更ではあるのですが、デジタルで浄化？という部分が気になってしまい、購入してみることにしました。

https://www.value-press.com/pressrelease/263971

以前同社から発売されているお化け探知機のばけたんについて調べたことがありましたので、その時と同様に中身を空けて基盤を拝見することにしました。

## まずは中身を拝見

![omote_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199416/580cfc9c-b1c3-ec59-b448-f8e84bc6d6a1.jpeg)

真ん中に鎮座しているICは SC92F7352X という汎用マイコンです。<b>ばけたん</b>と同じマイコンですね。
そして、その左側に写っているのは汎用の２回路入りオペアンプのLMV358です。これは<b>ばけたん</b>にはありませんでした。
マイコンの右側に３つ並んでいる３本足の部品はトランジスタで、裏面のマルチカラーLEDのドライブ用のようです。オペアンプの左側の二つのダイオードはショットキーバリアダイオードというところまでは追うことができました。



![ura_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199416/52e86fa0-5cc5-0caf-8b2e-e6ccc40da439.jpeg)
裏面を見てまず目を引くのは二つの渦巻状のパターンでそれぞれANT-IN、ANT-OUTとコメントされています。ANT-OUTの裏側はオペアンプのあるほうなのでオペアンプで増幅した何かをANT-OUTに送っているものと推察されます。
このアンテナで場の状態を測定したり浄化したりということを行っているのでしょうね…

## 場の状態の測定について

まず、場の状態の測定についてですが、[以前書いた記事](https://qiita.com/uhmin/items/143e7b4197381f7ee887)で考察しているので詳細は省きますが、内部で乱数を発生させて乱数の偏りで状態の良しあしを決定しているものと思われます。



## 瞑想モードについて
以前紹介した[ねとラボの記事](https://nlab.itmedia.co.jp/nl/articles/2005/18/news106_2.html)にも書いてあったのですが、シューマン共振波を発生させているようです。
調べてみるとこの手の装置は、例えば「シューマン共振発生器」というキーワードで検索するとたくさんヒットしますのでここでは詳しくは書かないことにします。



## 場の浄化について

場の浄化については前回の記事では結論は出なかったのですが、この手の別の機械について調べていた時にヒントを得ることができました。[Arduinoでラジオニクスを作れる](https://kurobudo.hatenablog.com/entry/2024/10/19/023812?_gl=1*1qlw5vx*_gcl_au*MzI4NzI4MjE0LjE3MjU2NzQ0NjU)という記事について調べていた時に内部でやはり乱数を発生させていることが分かりました。乱数の発生方法は以前私がお化け探知機のオマージュを作った方法と違い、電圧を２回測定して電圧が上がったか下がったかを判定して乱数にしているようです。どうやら、HotBitsという真乱数の発生アルゴリズムでこの方法が使われているようです。

もし<b>まもりだま</b>もこの方法で乱数を生成しているのだとしたら、電圧測定のタイミングで隣で電圧を変化させる操作をすれば発生する乱数を操作できるのではないでしょうか？

例えば、２回目の電圧測定結果が１回目よりも高くなる方向に偏っている場合には、２回目の測定のタイミングで電圧が低くなるような操作を行う、などの操作を行えば出力される乱数の偏りは減少させ「場の浄化」ができたことになるのではないでしょうか？

### まとめ
場の浄化はHotBitsアルゴリズムで生成される乱数に偏りが生じた場合に外部から干渉して偏りを減らす作業である...かもしれない
Next.js 15 RC 2 まとめ

# 初めに
Nextの方でv15でのリリース候補のv2が出たのでめっちゃ簡単にざっとまとめていきたいと思います
[Next.js 15 RC 2](https://nextjs.org/blog/next-15-rc2)
上記リンクの方から詳細については確認することができます

# 改善内容

### 1. キャッシュが強制キャッシュからオプトインに変更
[Turbopack for Development](https://nextjs.org/blog/next-15-rc2#turbopack-for-development)
キャッシュの動作が自動的に適用されるのではなく、自分たちで明示的にキャッシュの使用を選択することができるよになりそうです
従来はSSRやSSGの際に自動でキャッシュが適用され、更新が頻繁に必要なデータや保護が必要な情報がキャッシュされてしまう可能性があったのですが、今回のオプトイン方式によりキャッシュを使用するかどうかを自分たちで細かく制御できるようになり、意図しないキャッシュが避けられるようになりそうです。


### 2. cookieの取得が非同期になる
[Async Request APIs (Breaking Change)](https://nextjs.org/blog/next-15-rc2#async-request-apis-breaking-change)
`cookies` や `headers` などリクエストに依存するAPIがこれまで同期的に扱われていたものが非同期に変更されるので、これらのAPIを利用しているコードは既存のコードベースに変更を加える必要がありそうです
Nextからコード変換のためのcodemodが提供されていそうです
```bash
npx @next/codemod@canary next-async-request-api .
```

### 3. Formコンポーネントが追加
[Form Component](https://nextjs.org/blog/next-15-rc2#form-component)
HTML の `<form>` を拡張したもので、下記の特徴がありそうです

- **Prefetching**: フォームが表示されたときナビゲーションに必要なレイアウトやロードUIが事前に読み込まれるため、ナビゲーションが高速になる
- **Client-side Navigation**: フォームが送信された際、クライアント側の状態を維持したままページ遷移が行われる
- **Progressive Enhancement**: JavaScript がまだ読み込まれていない場合でも、従来のページ遷移としてフォームが機能する

### 4. instrumentation.js が安定版（Stable）になった
[instrumentation.js](https://nextjs.org/blog/next-15-rc2#instrumentationjs-stable)
Next.js サーバーのライフサイクルにフックし、パフォーマンスの監視やエラーの追跡を行うことができます
`onRequestError` フックを使えばサーバー上で発生したエラーをキャプチャし、エラーレポートを Sentry のような外部の監視サービスに送信できるようです

### 5. Server Actions のセキュリティ強化
[instrumentation.js](https://nextjs.org/blog/next-15-rc2#enhanced-security-for-server-actions)
- **Dead codeの削除**：使用されていない Server Actions はビルド時に削除されクライアントサイドの JavaScript バンドルに公開されることがなくなることにより、バンドルサイズが縮小され、不要なコードの公開リスクが減る

- **セキュアなアクションIDの生成**：Next.js では、クライアントが Server Actions を呼び出すための 推測が難しいアクションIDを生成することにより、アクションIDを推測して不正にアクセスされるリスクが軽減される

- **公開エンドポイントの最小化**：使用されない Server Actions はビルド時に自動的に削除されるため、無意識に公開されてしまう HTTP エンドポイントの数が減る

### 6. 開発環境でのパフォーマンス向上
[Turbopack for Development](https://nextjs.org/blog/next-15-rc2#turbopack-for-development)
ビルド時間の短縮や Hot Module Replacement (HMR) による効率的なリフレッシュ、メモリ使用量の削減など開発中の体験を改善するための変更がありそうです。

### 7.Next.js の設定ファイル（従来は next.config.js）を TypeScript で書くことが可能
[Support for next.config.ts](https://nextjs.org/blog/next-15-rc2#support-for-nextconfigts)
ありがたし

### 8. ESLint 9 のサポート
[ESLint 9 Support](https://nextjs.org/blog/next-15-rc2#eslint-9-support)
Next.js 15 からはESLint 9 がサポートされそうです。今のプロジェクトでも9にできていなかったのでやっと修正できそうです

# まとめ
破壊的変更も含まれているため、自分のプロジェクトへの影響や改善点をしっかりと把握しておきたいですね
[Next Conf](https://nextjs.org/conf)も今週あるので、そこでの発表もキャッチアップしておかないとですね
WSL のセットアップ

# Windows の設定
コントロールパネルを開いて、[プログラム] を選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/02060e9b-b083-efea-de6b-212badb247bc.png)

[Windowsの機能の有効化または無効化] を選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/4ea1b7cb-66ec-5a57-e2ad-1c3c6c542324.png)

[仮想マシン プラットフォーム] にチェックを入れて有効にする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/9867e101-b890-f3f4-93bc-824c2b9b2460.png)

# BIOS の設定
BIOSで仮想化を有効にする必要がある。設定方法はマシンのメーカーによって異なるのでご自身で調べられたい。

# WSL2 のインストール
確実に信頼できる情報をもとに WSL をインストールしたい場合は、次のサイトから公式のドキュメントを参考にされたい。

https://learn.microsoft.com/ja-jp/windows/wsl/install

コマンドプロンプトを開き、次のコマンドを実行して WSL2 をインストールする。なお、2024年10月20日時点では、デフォルトで Ubuntu 24.04.1 LTS がインストールされる。
```sh: WSL のインストール
wsl --install
```

## 指定の Linux をインストールしたい場合
次のコマンド、もしくは ```wsl -l -o``` コマンドから、オンラインでインストール可能な Linux ディストリビューションを確認できる。
```sh: オンラインで入手可能な Linux ディストリビューション
wsl --list --online
```

参考として、2024年10月20日時点でインストール可能な Linux ディストリビューションを次に記す。

```sh
>wsl --list --online
インストールできる有効なディストリビューションの一覧を次に示します。
'wsl.exe --install <Distro>' を使用してインストールします。

NAME                            FRIENDLY NAME
Ubuntu                          Ubuntu
Debian                          Debian GNU/Linux
kali-linux                      Kali Linux Rolling
Ubuntu-18.04                    Ubuntu 18.04 LTS
Ubuntu-20.04                    Ubuntu 20.04 LTS
Ubuntu-22.04                    Ubuntu 22.04 LTS
Ubuntu-24.04                    Ubuntu 24.04 LTS
OracleLinux_7_9                 Oracle Linux 7.9
OracleLinux_8_7                 Oracle Linux 8.7
OracleLinux_9_1                 Oracle Linux 9.1
openSUSE-Leap-15.6              openSUSE Leap 15.6
SUSE-Linux-Enterprise-15-SP5    SUSE Linux Enterprise 15 SP5
SUSE-Linux-Enterprise-15-SP6    SUSE Linux Enterprise 15 SP6
openSUSE-Tumbleweed             openSUSE Tumbleweed
```

他の Linux ディストリビューションをインストールしたい場合は次のコマンドを実行されたい。

```sh
wsl --install -d ディストリビューション名
```

前述のコマンドを実行すると、次の内容が出力される。ここで、デフォルトユーザを設定する必要がある。

まずは、ユーザ名を入力する。ユーザ名は Windows のものと異なる任意のものでもよい。

続いて、パスワードを入力する。パスワードは確認を含めて2回入力する必要がある。

```sh
Installing, this may take a few minutes... 
Please create a default UNIX user account. The username does not need to match your Windows username. 
For more information visit: http://aka.ms/wslusers
Enter new UNIX username: 
```

これで，WSLでインストールしたLinuxにログインできる．

なお，次回以降は次のコマンドでWSLのLinuxにログインできる
```sh:WSL の Linux にログインする
wsl
```

ログアウトは次のコマンドを実行すればよい。
```sh:WSL の Linux からログアウトする
exit
```

# インストールした Linux の確認
無事に Linux がインストールされたかを確認したい場合は、WSL でインストールした Linux にログインした後に、```lsb_release -a``` コマンドを実行すればよい。

```sh: インストールした Linux の確認
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 24.04.1 LTS
Release:        24.04
Codename:       noble
```
Python でMaxPlus代数の計算法則を実装してみる

## はじめに
MaxPlus代数とは，我々が普段扱う世界とは別の線形な世界です．筆者の勉強不足により詳細についてはここで述べませんが，基本的な演算自体は簡単なのでそれを実装してみることにします．

## MaxPlus代数の演算
極めて単純で，以下の二つのみです．
1. 加法: $a\oplus b=\mathrm{max}(a,b)$
2. 乗法: $a\otimes b = a+b$

この世界でも線形代数でおなじみの固有値，固有ベクトルを議論できるのですが，そこまでは踏み込まず，一旦実装をメインに扱います．

## クラスによる実装
MaxPlus代数の数を扱えるクラス `MaxPlus` を実装します．
```Python
class MaxPlus():
    def __init__(self, x):
        self.x = x

    def __str__(self):
        return f"{self.x}"

    def __add__(self, other):
        return MaxPlus(max(self.x, other.x))

    def __mul__(self, other):
        return MaxPlus(self.x + other.x)
```

可視化用の `__str__` の他，足し算と掛け算を実装しています．

## 数値実験
MaxPlusの世界では，次の演算が成り立ちます．

$$
\begin{align}
    5\oplus 2 &= \mathrm{max}(5,2) = 5 \\\\
    5\otimes 2 &= 5+2 = 7
\end{align}
$$

この演算が成立しているか確認します．

```Python
a = MaxPlus(5)
b = MaxPlus(2)

print(a+b)
# >>> 5

print(a*b)
# >>> 7
```

たしかにMaxPlusの演算ができています！！

最近まで筆者はMaxPlus代数を知らなかったのですが，別の世界の線形代数を学ぶことで，線形代数の基礎的な枠組みの理解が深まりました．

## 参考文献
* Max-Plus 線形代数とその応用 https://www.jstage.jst.go.jp/article/jsiamt/31/3/31_172/_pdf/-char/ja
EPGStationにエンコード開始の通知を送ってもらう

# 経緯
EPGStationには録画追加時や開始時、エンコード終了時に指定のコマンドを実行する機能がありますが、エンコード開始時だけは唯一実行できない仕様になっています(2024/10/19時点、見落としていたらすみません)。

標準で実行できるトリガーは以下の通りで、私はDiscordのWebhook経由で通知を送るようにしています。

* 予約新規追加時
* 予約更新時
* 予約削除時
* 録画準備開始時
* 録画準備失敗時
* 録画開始時
* 録画終了時
* 録画失敗時
* エンコード終了時

:::note info
詳しくは公式リポジトリの外部コマンド実行の欄をご覧ください。
https://github.com/l3tnun/EPGStation/blob/master/doc/conf-manual.md
:::

エンコードは予約時に指定していれば録画終了直後に開始されるわけですが、ここだけ通知がないのもなーと思い実装することにしました。

# enc.jsに加筆
力技になってしまいますがお許しください。
やってることは単純で、enc.jsの頭の方にDiscordへ通知するよう書き加えるだけです。


enc.jsは、実行される際にepgstationから環境変数として番組情報を受け取っています。
まずはそれを受け取っていきます。
(unixTimeをNumber型に変換しないとDate型を生成できず苦戦しました。)

```js:enc.js (一部GPT-4oと合作)
// この短さで UnixTimeをYYYY/MM/DD hh:mm:ssに すごい
// "2-digit" で0埋めまでしてくれる すごい
const unixTimeToDateTime = (unixTime) => 
  new Date(unixTime).toLocaleString('ja-JP', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false,
  });

// ミリ秒か秒のUnixタイムを判定し、差分を分に変換
const getDurationInMinutes = (start, end) => 
  Math.floor(((end - start) / 1000) / 60);

const title = process.env.NAME; // 番組タイトル
const channel = process.env.CHANNELNAME; // 放送局名

// 環境変数の受け取り
const startAt = process.env.START_AT
const endAt = process.env.END_AT

const startTime = unixTimeToDateTime(Number(startAt)); // 録画開始時刻
const endTime = unixTimeToDateTime(Number(endAt)); // 録画終了時刻
const durationMinutes = getDurationInMinutes(startAt, endAt); // 録画時間(分)
```

これで番組タイトル、放送局名や録画時間等が取得できます。他にもいろいろな情報を受け取れますが詳しくは公式リポジトリを。
あとはEmbedに加工して送信しましょう。ベースのコードはこちらからお借りしました。

https://qiita.com/n0bisuke/items/d6970e180355ce0e2fdc

```js:enc.js
const WEBHOOK_URL = `https://discord.com/api/webhooks/xxxxxxx`;

// POSTするデータの作成
const postData = {
  username: '予約通知',
  embeds: [
    {
      title: '🔄 エンコード開始',
      description: `**${title}**\n${channel}\n${startTime} ~ ${endTime} (${durationMinutes}分)`,
      color: 5814783,
    },
  ],
};

const post = async () => {
  try {
    const response = await fetch(WEBHOOK_URL, {
      method: 'POST',
      headers: { 
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(postData),
    });

    if (!response.ok) {
      throw new Error(`HTTPエラー: ${response.status}`);
    }
    console.log('通知が正常に送信されました');
  } catch (error) {
    console.error('通知の送信に失敗しました:', error);
  }
};

post();
```

正常に動作すれば、画像のように通知が来るはずです。お読みいただきありがとうございました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/823378/e307f5e2-f01c-5369-caf3-99ab23ddb4f2.png)


(予約追加のコマンドが実行されているのに、通知が70%位の確率で送られてこないのはおま環でしょうか？
それ以外の通知は正常なのですが...)

# 参考
https://github.com/l3tnun/EPGStation/blob/master/doc/conf-manual.md

https://github.com/PiedHarrier/EPGS-to-LINE

https://qiita.com/n0bisuke/items/d6970e180355ce0e2fdc

https://note.com/ukah/n/n6782aa4ca05c
【2024年】avr-gcc と make だけで C/C++ AVR 環境構築 (Windows, ATmega328P)

# はじめに

AVR マイコン開発環境を Windows で統合開発環境で用意するには、いくつか方法があります。

* Arduino IDE (C/C++ など)
* Microchip Studio (C/C++, 旧 Atmel Studio)

ただ、どの開発環境も裏側では avr-gcc コンパイラが使われています。そこで、なるべく avr-gcc だけを使った環境を、次の記事を参考に構築してみました。

* 玉虫色に染まれ!! over80 - [LinuxでAVR開発 （ビルド編）](https://over80.hatenadiary.jp/entry/20100506/avr_build)

初心者でも分かりやすいコマンド解説が行われているので、詳細は参考記事をご確認ください。

# 手順

## パッケージインストール

ビルドには avr-gcc コマンドなどが必要になります。

### Windows (winget)

```
winget install -e --id=ZakKemble.avr-gcc
winget install -e --id=GnuWin32.Make
```

### Debian, Ubuntu (apt)

```
sudo apt install gcc-avr binutils-avr avr-libc make
```

## ファイル準備

次のような内容の main.c を作成します。PB5 (Arduino UNO なら基板上のLED) が点滅するサンプルプログラムです。
クロック周波数は 1MHz を想定しているため、環境に合わせて F_CPU を変更してください。 

```c:main.c
#define F_CPU 1000000UL

#include <avr/io.h>
#include <util/delay.h>

#define BBLED 5

int main(void)
{
    DDRB  = _BV(BBLED);

    for(;;){
        PORTB ^= _BV(BBLED);
        _delay_ms(500);
    }
}
```

ビルドの自動化に必要な Makefile ファイルを作成します。

```make: Makefile
PROG=main
OBJS=${PROG}.o
MCU=atmega328p

ELF=$(PROG).elf
IHEX=$(PROG).hex

CC=avr-gcc
CFLAGS=-g -O2 -mmcu=$(MCU)
LDFLAGS=-g -O2 -mmcu=$(MCU)
OBJCOPY=avr-objcopy

# OSごとにRMを定義
ifeq ($(OS),Windows_NT)
    RM = del /F
else
    RM = rm -f
endif

all: $(IHEX)

$(IHEX): $(ELF)
	$(OBJCOPY) -j .text -j .data -O ihex $< $@

$(ELF): $(OBJS)
	$(CC) $(LDFLAGS) -o $@ $(OBJS)

# .o を生成するルール
%.o: %.c
	$(CC) $(CFLAGS) -c -o $@ $<

clean:
	-$(RM) $(ELF) $(IHEX) $(OBJS)

.PHONY: all clean

```

## ビルド

以下の手順で .hex ファイルまたは .elf ファイルが生成されるので、マイコンに書き込んで動作を確認できます。

### 手動

```
avr-gcc -g -O2 -mmcu=atmega328p -c -o main.o   main.c
avr-gcc -g -O2 -mmcu=atmega328p    -o main.elf main.o 
avr-objcopy -j .text -j .data -O ihex main.elf main.hex
```

### make による自動化

```
# ビルド
make

# クリーン（ファイル削除）
make clean
```
Python ライブラリとかimportの話 その1（自分用）

Python始めたての頃、ライブラリやimportの意味がよくわからなかったので、あの時の自分のために書き残しておく

1.importとは
-
スクリプトの冒頭によく出てくる呪文のことである
```python:example.py
import numpy as np
```
これは<strong>numpyというライブラリをnpという名前で使います</strong>みたいな意味である。

2.まとめ
-
<strong>ライブラリ</strong>：便利機能集（numpyは計算に特化した便利機能集である）
<strong>import</strong>：ライブラリを装備するイメージ（使える状態にする）
<strong>as</strong>：当該スクリプト（example.py）の中においては、np = numpy と解釈してプログラムを進めて欲しいというお願いと合意の証

次回はimportの応用編みたいなものを書くことにする。
OpenAI Realtime APIってどのくらい速いの？

どのくらい早いのかあまりまとまっていなかったので、調べた。

## サマリ

- Realtime APIのLatency (ユーザーの発話終端〜アシスタントの発話始端) は**平均1.26秒**

## Realtime APIの日本語会話における応答速度

- 前提
    - 実行環境
        - https://github.com/openai/openai-realtime-console
        - 上記に修正を加えたものをM2 Macbook Airで検証
    - 検証方法
        - ユーザーの発話が終了してからクライアントサイドでアシスタントの音声が発話されるまでの時間を計測
- 結果
    - **平均1.26秒 (min: 1.13, max: 1.45, 10 sample)**
    - 内訳 (推定)
        - 往路のネットワーク遅延: 150ms
        - VAD (silence_duration_ms の default): 200ms
        - speech-to-speech (最初の音声生成まで): 700ms
        - 復路のネットワーク遅延: 150ms
    - 備考
        - system instructionの長さやturn数、通信速度にも依存するので参考程度
        - なお、人間側の応答速度は同程度だったが、これは人間が会話行為時に相手とのリズムを合わせる癖があるためである。最短は0.1秒であった

## Appendix: ローカルマシンでRealtime APIと同様のものを実現する方法

- 必要なモジュール
    - VAD (ターン検出用途): SileroVAD
    - ASR: whisper (whisper-large-v3-turbo 等)
    - LLM: gemma-2-2b-jpn-it 等
    - TTS: edge-tts, Style-Bert-VITS2等
    - 完全にRealtime APIと同様のインターフェイスにする場合はwebsocket対応を別途行う必要がある
- 処理時間の目安
    - VAD: 200ms
    - ASR: 500 ms (リアルタイム処理を行ったときの処理遅延)
    - LLM: 500ms (発話可能な1文の出力まで)
    - TTS: 200 - 500ms
- 結論
    - 相槌等の即時生成機構を考慮しない場合、現状ローカルマシンで日本語の音声対話だと 1400 ms 程度は可能
- 参考実装
    - https://github.com/ggerganov/whisper.cpp/tree/master/examples/talk-llama
        - llama.cpp と whisper.cpp と 軽量 tts (edge-tts ライブラリのようなもの, MacのsayコマンドとWinのSpeechSynthesizerに対応) で構築されている

## Appendix2: 気持ち良い会話体験のために

https://x.com/gyakuse/status/1640748179976249350

上記でも触れたように、人間の会話反応はとても速い。
まず発話の重複が多く、相槌等でのリズム的な応答もある。
速度に関して、リアルな人間に近づけるために重要なのは以下の二点である。

- 会話内容の予測
- 話者交替の予測
- 相槌の予測

### 会話内容の予測

会話の予測に関しては比較的改善しやすい。発話途中文から複数の会話完了文候補とそれに対する返答をあらかじめ生成し、かつ音声合成し、実際の発話と会話完了文候補との類似度を取ればよい。

https://x.com/gyakuse/status/1631636438508007434

上記に関しては以下の論文で詳しく検討されている。

[大萩雅也、水本智也、吉川克正．「音声対話における応答速度改善に向けた先読み技術の検討」．言語処理学会 第30回年次大会 発表論文集](https://www.anlp.jp/proceedings/annual_meeting/2024/pdf_dir/B9-5.pdf)

### 話者交替と相槌の予測

京大の井上さんの[Realtime Voice Activity Projection (Realtime-VAP)](https://github.com/inokoj/VAP-Realtime)が非常によいので特に言うことはありません (利用される場合はライセンスをよく読みましょう)
今更Rustの環境構築をした VSCode

## これは何?

いまさら，Rustに入門したのでやった環境構築とかメモしておきます。

[GitHubのリポジトリ](https://github.com/RyosukeDTomita/rust_tutorial)

---

## install

```shell
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.80.0
apt-get install -y --no-install-recommends gcc=4cargo --version:12.2.0-3 libc6-dev=2.36-9+deb12u8
source "$HOME/.cargo/env"
```

---

## tools

### rustup

- rustのインストールやバージョン管理を行うことができるツール
- [公式サイト](https://rustup.rs/)
- rustcやcargoなども一括でインストールされる。

### rustc

rustのコンパイラ

### cargo

- rustのビルドシステム兼パッケージマネージャ
- `Cargo.toml`でプロジェクト管理する。

> [!NOTE]
> Rustではパッケージのことをクレート(Crate)と呼ぶ。

```shell
cargo new プロジェクト名
cargo clean
cargo check # コンパイルできるかチェックする
cargo build
cargo run
```

#### リリースに向けたビルド

`--release`をつけると最適化が行われ、コンパイル時間が長くなる代わりに実行速度が速くなる。

```shell
cargo build # target/debugに
cargo build --release # target/releaseに
```

### パッケージの追加

- `Cargo.toml`の`[dependencies]`に追加する。

```toml
[package]
name = "chapter2"
version = "0.1.0"
edition = "2021"

[dependencies]
rand = "0.8.3" # ここに追加
```

- `cargo build`でライブラリが追加される。

> [!NOTE]
> `Cargo.lock`には依存関係のバージョンが記録される。

- `cargo update`を使うと`Cargo.lock`を無視して`Cargo.toml`のバージョンを元に更新が走る。

#### コンパイラのエラーを直す

コードをコミットをせずに実行すると以下のようなエラーがでる。

```shell
cargo fix
error: the working directory of this package has uncommitted changes, and `cargo fix` can potentially perform destructive changes; if you'd like to suppress this error pass `--allow-dirty`, `--allow-staged`, or commit the changes to these files:
...
```

コードを修正してコミットするか、`--allow-dirty`をつけて実行するか，コードをステージ(`git add`)して`--allow-staged`をつけて実行するか選べるらしい。

```shell
cargo fix --allow-dirty
```

#### formatter

- `cargo fmt`でコードをフォーマットすることができる。

```shell
rustup component add rustfmt # 一括ダウンロードの場合は不要
cargo fmt
```

#### linter

```shell
rustup component add clippy
cargo clippy
```


---

## VS Codeの設定
以下をインストールする

- rust-lang.rust-analyzer: Language Server
- statiolake.vscode-rustfmt: Formatter
- dustypomerleau.rust-syntax: Syntax Highlighting
- vadimcn.vscode-lldb: Debugger
- swellaby.vscode-rust-test-adapter: Test Runner
- tamasfe.even-better-toml: TOML Highlighting

```settings.json
  "[rust]": {
      "editor.defaultFormatter": "statiolake.vscode-rustfmt",
      "editor.formatOnSave": true,
      "editor.semanticHighlighting.enabled": false
  }
```

---
Win11での 'プリンターとデバイス'の表示

# 1.Win11ではコントロールパネルの「デバイスとプリンター」に回り道が増えました……

<br>

ではどうするか？
「Winキー」を押しながら「Rキー」を押します。「ファイル名を指定して実行」
が起動しますので空欄に

「shell:::{A8A91A66-3A7D-4424-8D24-04E180695C7A}」

を入力して「Enterキー」を押せば出ます。以上

<br>

ここからはWin11でのGUIでの操作説明になるのでまじめに読む必要はないです。
万が一上のコマンド操作ができない場合くらいは役にたつかもしれません。

Windows10であれば「start control printers」のコマンドを実行すれば、
コントロールパネルを経由しなくても直接「デバイスとプリンター」にアクセスできました。

ところが11になってからコントロールパネルからクリックしても何故か回り道させられるます。

「Bluetoothとデバイス」 ⇒ 「プリンターとスキャナー」 ⇒ 任意のプリンターをクリックする。
「その他のデバイスとプリンターの設定」をクリックするか、
「ハードウェアのプロパティ」をクリックして「設定」タブをクリック、
「デバイスとプリンターフォルダを開く」なんてポチポチする。

# 2.GUI操作で削除できないプリンターを抹消する。

PowerShellを管理者起動し下記のコードを実行

:::
```.PoweShellのコード
rundll32 printui.dll,PrintUIEntry /dl /n “プリンタ名”
:::

<br>

以上です。
制約について【備忘録】

## データベースに記述するカラムに制約（条件）を付ける。
userテーブルにのemailカラムに重複したデータはダメよ、とか空欄はダメよ必ず何か入力してね、とか〇〇は必ず入れてねもしくは入れないでね、といった制約。以下は代表的なやつ。

**NOT NULL制約**
例）usersテーブルの「name」カラムにNOT NULL制約を設定すると、nameカラムが空のレコードだと保存できなくなる。この制約は、t.string :nameにnull: falseと記述して設定。

```ruby:db/migrate/2020XXXXXXXX_create_users.rb
class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name, null: false   #nullは「空の、ゼロの」の意味だから「空の」は「間違い」
      t.timestamps null: false
    end
  end
end
```
**一意性制約**
１つのテーブル内で重複するデータを禁止する制約。
例）usersテーブルの「email」カラムに対して一意性制約を設定すると、同じemailの値を持つレコードが二つ以上保存できなくなる。この制約はunique: trueと記述することで設定。
```ruby:db/migrate/2020XXXXXXXX_create_users.rb
class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name, null: false
      t.string :email, unique: true    #unique「唯一、独特」は「真実」
      t.timestamps null: false
    end
  end
end
#（注）deviseを使う場合emailカラムに一意性制約はデフォルトでついているので記載は不要
```
**主キー制約と外部キー制約**
主キーとは親。外部キーデータの出発点。各テーブルのidカラムの番号が主キーに当たる。子に対して親が存在するのが前提だし（NOT NULL）他に同じものもいない(一意性制約)。
Railsでテーブルを作成する場合、主キー制約はidカラムとして自動で設定される。
これに対し外部キーは主キーに属する依存するデータ。主キーがないと存在できない。例としてコメント者が主キーでコメントが外部キー。
```db/migrate/2020XXXXXXXX_create_comments.rb
class Createcomments < ActiveRecord::Migration[6.0]
  def change
    create_table :comments do |t|
      t.string :name
      t.string :text
      t.references :user, foreign_key: true   #外部キー
      t.timestamps
    end
  end
end
```
どうして制約を付けるの？ユーザーの利便性、安全性向上の為だったり、重複データを避けサーバー負荷を減らす為？かなあ。
Japanglish Tech Talk #3 プレゼンテーション紹介

# Japanglish Tech Talkとは？

東京で開催されるエンジニアのための英語オンリーLTイベントです！

日本では大半の会話が日本語で行われるため、英語を話す機会が少ないのが現状です。

そんな中、東京のLTイベントで気軽に話す機会を提供しようと企画しました。

# Japanglish Tech Talk #3 プレゼンテーション :-D

2024年10月16日、Japanglish Tech Talkを開催しました。 

そのプレゼンを簡単に紹介します。

- [Japanglish Tech Talk#3](https://japanglish.connpass.com/event/328117/)
- [Japanglish Tech Talk Youtube](https://www.youtube.com/channel/UCKC2d4f-k-f4KeRs_YV9q_g)

### ご協賛ありがとうございました！

今回のイベント開催にご協力いただきました[Ichizoku](https://ichizoku.io/)様、[Timee](https://timee.co.jp/)様、改めてお礼申し上げます。<br>ありがとうございました！🙏

Ichizokuブログ [https://ichizoku.io/category/sentry/](https://ichizoku.io/category/sentry/)

Timeeブログ [https://techplay.jp/community/timee/blog](https://techplay.jp/community/timee/blog)


### JavaScriptのシングルスレッドとイベントループ

- [Youtube](https://www.youtube.com/live/V-KoVt6V9J0?si=Gj_Ht4TeV75gAZcU&t=1462)
- Speaker: Xiaodong Hu 

JavaScriptエンジンは基本的にシングルスレッドであり、同じDOMツリーの競合を避けることができます(最近はマルチスレッドで動くになっています)。

重い処理がアプリケーションを停止させないように、タスクを同期処理と非同期処理に分けて効率的に管理する仕組みが実装されています。

---

### Edge AI

- [Youtube](https://www.youtube.com/live/V-KoVt6V9J0?si=pGp-f8_4NsGNCahy&t=2277)
- Speaker: Ken Shimizu

物体検出をAIモデルをマイコンに搭載した話について語っています。

普段から様々な個人開発をされている方で、非常に興味深い内容でした！

---

### フリーランスエンジニアとして生き残るには？

- [Youtube](https://www.youtube.com/live/V-KoVt6V9J0?si=HytoaUeXUYVgfMBu&t=5202)
- Speaker：yori

フリーランスエンジニアとしての経験談をユーモラスに語っています。

飲み会を通じてエンジニア仲間を増やす話は会場内が盛り上がりました！

---


# 次回開催も決定

次回開催は来年の1月です！XD ぜひ参加お待ちしています〜！

![集合写真](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/909919/5bc4ccf7-4449-08e7-f1ae-faf133da7f99.jpeg)


# 主催者について

- [Tamtam](https://x.com/TamtamFitness)
- [Naru](https://x.com/1026NT)

Japanglish Tech Talkは、TamtamとNaruが共同で企画・運営しているイベントです。エンジニアの皆さんに英語でのコミュニケーションの機会を提供し、国際的な技術交流を促進することを目指しています。
初心者向けPyTorch篇：2.線形回帰モデルの基本

# PyTorchを使った線形回帰モデルの基本

線形回帰は、データ間の関係をモデル化する最も基本的な手法の一つです。この記事では、PyTorchを使用して線形回帰モデルを構築する方法を初心者向けに解説します。

## データの準備

まずは、以下のリンクから収入と年齢のデータセットをダウンロードします。

[Income Dataset](https://github.com/reisanar/datasets/blob/master/income.csv)

このデータセットには、収入と年齢のほかに教育年数や性別の情報も含まれていますが、今回は収入と年齢の関係に焦点を当てます。

```python
import pandas as pd

data = pd.read_csv('income.csv')
print(data.head())
```

出力例：

```
   ID  Income  Age  Education  Gender
0   1     113   69         12       1
1   2      91   52         18       0
2   3     121   65         14       0
3   4      81   58         12       0
4   5      68   31         16       1
```

## データの可視化

データを可視化することで、収入と年齢の関係を目で見て確認します。

```python
import matplotlib.pyplot as plt

plt.scatter(data['Age'], data['Income'], alpha=0.3)
plt.xlabel("Age")
plt.ylabel("Income")
plt.show()
```
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2382903/073d1f3d-339e-b0b3-37e2-786a40a66199.png)
## モデルの構築

PyTorchを使い、線形回帰モデルを構築します。

```python
import torch
from torch import nn

# データをTensorに変換
X = torch.tensor(data['Age'].values, dtype=torch.float32).reshape(-1, 1)
Y = torch.tensor(data['Income'].values, dtype=torch.float32).reshape(-1, 1)

# モデル定義
class EIModel(nn.Module):  # nn.Moduleを継承する
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(1, 1)

    def forward(self, x):
        return self.linear(x)  # 入力xを受け取り、線形変換を適用して出力を返す

model = EIModel()  # モデルインスタンスの作成
```
このモデルは、入力特徴量として1つの数値を受け取り、それに基づいて1つの数値（予測値）を出力します。これにより、例えば年齢から収入を予測するようなタスクに使用することができます。
※ nn.Linear(1, 1)の引数1, 1は、入力特徴量（年齢）と出力特徴量（収入）がそれぞれ1つであることを示しています。
## 学習プロセス

損失関数とオプティマイザーを定義し、モデルを訓練します。

```python
loss_fn = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.001)

# 訓練ループ
for epoch in range(100):  # ここで100回訓練する
    for x, y in zip(X, Y):
        y_pred = model(x)  # モデルによる予測
        loss = loss_fn(y_pred, y)  # 損失の計算
        opt.zero_grad()  # 前回ループの勾配の初期化する
        loss.backward()  # 逆伝播
        opt.step()  # パラメータの更新
```

## モデルの評価

最後に、学習したモデルを使って予測結果をプロットします。

```python
plt.scatter(data['Age'], data['Income'], alpha=0.3)
plt.plot(X.numpy(), model(X).detach().numpy(), color='red')
plt.xlabel("Age")
plt.ylabel("Income")
plt.show()
```
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2382903/e767b6b8-8d6f-0250-cbcb-2f4b1df1f018.png)

このようにPyTorchを使って線形回帰モデルを構築することで、データ間の関係を簡単に理解し、予測することができます。
CakePHPでCSRF対策したフォームを送信する方法

# 対象の読者
CakePHPでフォーム画面の内容をサーバに送信する際、CSRF対策をしてなかったために、エラーが出て悩んでる方向けの記事です。

# 検証環境
■Windows11
■CakePHP(version 4.5.7)

# CSRF対策とは？
:::note warn
<b>CakePHPとLaravelではCSRF対策をしているForm以外はサーバに送信できません！！</b>

:::

クロスサイトリクエストフォージェリ（CSRF）とは、Webアプリケの「セッション管理」機能に対して、セキュリティ上の欠陥をピンポイントで狙ったサイバー攻撃の一種です。

このような攻撃からwebアプリケーションを防御するにあたって、CakePHPやLaravelではCSRF対策の技術が搭載されています。

今回は、CakePHPのアプリにおけるフォーム画面のCSRF対策の記述方法を見ていきましょう。

# 書き方はとてもカンタンです！
<form>タグのすぐ下に、下記のコードを記載するだけです！

```
<input type="hidden" name="_csrfToken" value="<?= $this->request->getAttribute('csrfToken') ?>"/>
```

では、フォーム画面の全体のコードを見てみましょう。↓
```index.php

<h1>ログインフォーム</h1>

<div class="registerFormArea">
    <form id="registerForm" class="" method="post" action="/registers/register" name="form">
        <input type="hidden" name="_csrfToken" value="<?= $this->request->getAttribute('csrfToken') ?>"/>
        <!--名前-->
        <input type="text" id="yourNAme" name="yourNAme" class="yourNAme"/>
        <!--メールアドレス-->
        <input type="email" id="yourEmail" name="yourEmail" class="yourEmail"/>
        <!--パスワード-->
        <input type="password" id="yourPassword" name="yourPassword" class="yourPassword"/>
    </form>
    <button type="submit" class="btn" form="registerForm">
        送信
    </button>
</div>

```

# CSRF対策をした<Formタグの中身を見てみる
さて、CSRF対策をしたフォーム画面の中身を見てみましょう。
キャプチャのとおり、何やらランダムな文字列が並んでいるのが分かりますね。
これでフォーム全体がCSRF対策が完了している証拠です。

![cakePhp Csrf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1169664/5b4d3e06-422d-cd7c-3aa9-b4e42fc9e98a.png)


以上となります。
Linuxメモ（コマンド別）

# 記事の目的
Linuxコマンドの投稿をまとめるページ。少しずつ更新する。

## sed
https://qiita.com/yuki_j/items/eaabe222a74edce58326

## zip, unzip
https://qiita.com/yuki_j/items/2e4d551036e9cf22e6e8

## リダイレクト
https://qiita.com/yuki_j/items/2ce513d7daf189f3170e
sedメモ

# 記事の目的
運用保守の現場で使用したり先輩から学んだコマンドなどを知識の定着かつ辞書が割りに記録する。
もし見ていただいた方でより良い方法などあればご教授いただけると有り難いです。

# sed
正規表現などを使い細かい条件の置換やファイルの編集をする事ができるコマンド。

### 基本構文
```bash
# 全ての文字列aを文字列bに置換する
$ sed 's/hoge/fuga/g' input.txt

# gを省くと最初に当てはまったものだけを置換する
$ sed 's/hoge/fuga/' input.txt

# catとパイプを使用してもできる
$ cat input.txt | sed 's/hoge/fuga/g'

# リダイレクトも可能
$ cat input.txt | sed 's/hoge/fuga/g' > output.txt
```

### 行末のカンマを改行に置換する
```bash
# input file
$ cat input.txt
aaa,bbb,ccc,ddd,

# 行末のカンマを改行に置換できる
$ sed 's/,$/\n/g' input.txt
aaa,bbb,ccc,ddd
　←改行が入る

# 単純に削除するだけなら
$ sed 's/,$//g' input.txt
aaa,bbb,ccc,ddd
```

### 空白以外の文字列をシングルクオーテーションで囲む
```bash
# input file
$ cat input.txt
hoge
fuga

piyo

# []内の^は否定を表す。以下は空白以外という意味。（[]外の^は行頭を表す）
# &はマッチした文字列自体を表す
$ sed "s/[^ ]\+/'&'/g" input.txt
'hoge'
'fuga'

'piyo'
```

### 特定のファイルをまとめてリネームする
```bash
# target files
$ ls -l
20241014_hoge1.csv
20241014_hoge2.csv
20241014_hoge3.csv
20241014_hoge4.csv

# ファイルから日付を削除する
# pで置換前のファイル名を出力
# 置換後に置換したファイル名を出力
$ find . -name "*hoge*.csv" -type f | sort | sed "p;s/20241014_//g" | xargs -t -n 2 mv
mv ./20241014_hoge1.csv ./hoge1.csv
mv ./20241014_hoge2.csv ./hoge2.csv
mv ./20241014_hoge3.csv ./hoge3.csv
mv ./20241014_hoge4.csv ./hoge4.csv
```
lang\en\jaのような階層構造

# vscodeのフォルダ謎（lang\en\ja）
まれに発生するこの事象、、
なぜこのような階層構造になってしまうのか、、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3913943/4d734584-717d-1fef-d88e-be6fce610797.png)

langフォルダの直下にenとjaフォルダを配置したいのに、lang\enとなってしまうせいでjaがlang\en\jaの階層構造になってしまった

# 解決策
vscodeの画面で、jaフォルダをドラッグし、langの上でドロップ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3913943/9be82b42-b698-556e-7cac-0a89824171c6.png)
すると上記のようなポップアップが出るので移動を押下

すると目的の階層構造になった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3913943/178ed386-8555-ba90-24ad-8d1fe4776975.png)
# 終わりに
今回のlang\enのようなフォルダは何度か見たことがある。
不思議なものだ。。。。lang\en\jaの使い方するわけなかろうに、、、
【CakePHPで検証】<form>タグの外側に送信ボタンを配置した時のマークアップ記法

# 対象の読者
フォーム画面の作成について、少し悩んでいるフロントエンジニアの方。

# 検証環境
■Windows11
■CakePHP(version 4.5.7)

# 記事を作成したきっかけ
<form>タグを記載しているときに、タグの外側に送信ボタンを配置した時の書き方が新鮮で、しかも<b>HTMLだけで<form>タグと送信ボタンが紐づけられる利点があったため、さっそく共有したかったから。</b>

# さっそくコードを見てみよう

記載方法はとってもカンタン(^^♪
<b>【手順】</b>
①<form>タグにId属性を付ける。
②<button>タグにform属性を付けて、属性の名前を<form>タグのid値を付ける。

たったこれだけで、<form>タグと外側に配置した<button>タグが紐づけられるんですね～。


```index.php

<h1>ログインフォーム</h1>

<div class="registerFormArea">
    <form id="registerForm" class="" method="post" action="/registers/register" name="form">
        <input type="hidden" name="_csrfToken" value="<?= $this->request->getAttribute('csrfToken') ?>"/>
        <!--名前-->
        <input type="text" id="yourNAme" name="yourNAme" class="yourNAme"/>
        <!--メールアドレス-->
        <input type="email" id="yourEmail" name="yourEmail" class="yourEmail"/>
        <!--パスワード-->
        <input type="password" id="yourPassword" name="yourPassword" class="yourPassword"/>
    </form>
    <button type="submit" class="btn" form="registerForm">
        送信
    </button>
</div>

```

以上です。
ぜひ、試してみてくださいね🌝
Pythonのコンテキストマネージャの仕組みと実装方法：リソース管理の効率化

Pythonには、リソース管理を効率化するための強力な機能である「コンテキストマネージャ」が用意されています。これにより、ファイル操作やデータベース接続などのリソースを、手動で管理する煩雑さを軽減し、安全でエレガントなコードを書くことができます。

### コンテキストマネージャとは？

コンテキストマネージャは、リソースの確保と解放を自動的に管理するための仕組みです。`with` 文を使って、特定のリソースを取得し、処理が終わった際にそのリソースを自動的に解放できます。最も一般的な例がファイル操作です。以下に、コンテキストマネージャを使ったファイル操作の例を示します。

```Python
with open("example.txt", "w") as f:
    f.write("こんにちは、世界！")
```

このコードでは、ファイル `example.txt` を開き、内容を書き込んだ後、`with` ブロックを抜けると自動的にファイルが閉じられます。f.close() を手動で呼ぶ必要がなく、例外が発生した場合でもリソースが確実に解放されるので安全です。

### コンテキストマネージャの仕組み

コンテキストマネージャは、`__enter__` メソッドと `__exit__` メソッドを持つオブジェクトによって構成されます。`__enter__` メソッドでリソースを確保し、`__exit__` メソッドでリソースを解放します。これにより、リソースの取得と解放の処理を一貫して行えます。



- コンテキストマネージャクラスの例
```Python
class MyContextManager:
    def __enter__(self):
        print("リソースの確保")
        return self
    
    def __exit__(self, exc_type, exc_value, traceback):
        print("リソースの解放")
        return False

# コンテキストマネージャを使用
with MyContextManager():
    print("処理中...")
```

- 実行結果
```
リソースの確保
処理中...
リソースの解放
```

この例では、`__enter__` メソッドでリソースを確保し、`__exit__` メソッドで解放しています。with ブロックを抜けると、リソースの解放が自動的に行われます。

### コンテキストマネージャの利点
- リソース管理が自動化される
手動で `close()` や `release()` といったリソース解放メソッドを呼ぶ必要がないため、コードがシンプルになります。特に例外が発生した場合でも、リソースは確実に解放されます。

- 可読性が向上
`with` 文を使うことで、リソースの管理範囲が明確になり、コードの可読性が向上します。リソースの確保と解放が同じブロックに収まるため、どこでリソースが管理されているかが一目でわかります。

- エラーに強い
`with` 文を使うことで、例外が発生してもリソースの解放が保証されるため、リソースリークのリスクが低くなります。`__exit__` メソッドは例外の情報を引数として受け取るため、エラーハンドリングを組み込むことも可能です。


Pythonのコンテキストマネージャは、リソースの確保と解放を安全かつ効率的に行うための重要なツールです。`with` 文を使うことで、ファイル操作やデータベース接続といったリソース管理が簡素化され、コードの可読性と安全性が向上します。
Apache Solrをbuildする

## Solrをビルトした時のメモ
ちょっと、Solrをビルドする必要ができたので、調べた時のメモ

<!--more-->

## 環境設定
環境はUbuntu 22.04を使ってやっていく
まずは必要パッケージのアップデートとインストールなど

javaとビルトツールとしてgradleを使っているのでインストールする

```bash 
sudo apt update
sudo apt install openjdk-17-jdk
sudo apt install gradle
```

## コードの取得〜ビルド
Solrでは、gradlewというコマンドをgradleのラッパーとして使っている
それのassembleを実行することでビルドができる

```bash
git clone https://github.com/apache/solr.git

#ビルドの実行
./gradlew assemble

#ビルドが成功すると以下の場所にビルドされたファイルができる
cd solr/packaging/build/VERSION
#起動する
bin/solr start -c
```

## その他

```
# いわゆるhelp
./gradlew help

# buildなので利用できるオプションの表示をする
./gradlew tasks


# テストの実行
./gradlew check
```

この辺を読んでおく
[github/solr/dev-docs](https://github.com/apache/solr/blob/main/dev-docs/solr-source-code.adoc)
【HTML】inert属性について

## `inert`属性とは

`inert`属性は、HTMLの要素に対して適用される属性で、要素を「無効化」するために使用されます。この属性が設定された要素は、ユーザーインターフェースの一部としては存在しますが、ユーザーがその要素に対して操作を行うことができなくなります。具体的には、以下のことをします。

- ユーザーが要素をクリックしたときにclickイベントが発生するのを防ぎます
- 要素にフォーカスが当たらないようにすることで、focusイベントが発生するのを防ぎます
- ブラウザのページ内検索機能の使用中に、要素の内容が検索/マッチされるのを防ぎます
- ユーザーが要素内のテキストを選択できないようにします（CSSプロパティのuser-selectを使用してテキストの選択を無効にするのと同じです）
- ユーザが要素の内容を編集できないようにします
- アクセシビリティ・ツリーから除外することで、要素やその内容を支援技術から隠します

## 使用例

以下は、`inert`属性を使用した簡単な例です。

```html
<div id="container" inert>
    <button>ボタン1</button>
    <button>ボタン2</button>
</div>

<button id="toggle">無効化の切り替え</button>

<script>
    const toggleButton = document.getElementById('toggle');
    const container = document.getElementById('container');

    toggleButton.addEventListener('click', () => {
        container.toggleAttribute('inert');
    });
</script>
```

この例では、`container`という`div`要素に`inert`属性が設定されており、「ボタン1」と「ボタン2」はクリックなどの操作ができなくなっています。
`toggle`ボタンをクリックし、`inert`属性を切り替えると「ボタン1」と「ボタン2」をクリックできるようになります。

## 参考

https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inert