OmniAICreator/Qiita-1.07M huggingface dataset:
paizaラーニングレベルアップ問題集の「配列の最大最小」をやってみた。

paizaラーニングレベルアップ問題集の[配列の最大最小](https://paiza.jp/works/mondai/array_primer/array_primer__array_minmax)をやってみました。
- - -
###### 問題
https://paiza.jp/works/mondai/array_primer/array_primer__array_minmax
- - -
###### 方針
問題文中にある通り、$N$個の整数を大きい順や小さい順に並び替える操作を考えて解いてみましょう。
受け取った配列を昇順ソートし、末尾と先頭を出力します。
- - -
###### C
```c
#include <stdio.h>
#include <stdlib.h>

int cmp(const void *a, const void *b) {
	int x = *(int*) a;
	int y = *(int*) b;
	if (x < y) return -1;
	if (x > y) return 1;
	return 0;
}

int main() {
	int n;
	scanf("%d", &n);
	int A[n];
	for (int i = 0; i < n; i++) scanf("%d", &A[i]);
	qsort(A, n, sizeof(A[0]), cmp);
	printf("%d %d\n", A[n-1], A[0]);
	return 0;
}
```
- - -
###### C++
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
	int n;
	cin >> n;
	vector<int> A(n);
	for (int i = 0; i < n; i++) cin >> A[i];
	sort(A.begin(), A.end());
	cout << A.back() << ' ' << A.front() << endl;
	return 0;
}
```
- - -
###### C#
```cs
using System;

class Program
{
	public static void Main()
	{
		int n = int.Parse(Console.ReadLine());
		int[] A = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
		Array.Sort(A);
		Console.WriteLine("" + A[n-1] + ' ' + A[0]);
	}
}
```
- - -
###### Go
```go
package main
import (
	"fmt"
	"sort"
)

func main() {
	var n int
	fmt.Scan(&n)
	A := make([]int, n)
	for i := 0; i < n; i++ {
		fmt.Scan(&A[i])
	}
	sort.Ints(A)
	fmt.Println(A[n-1], A[0])
}
```
- - -
###### Java
```java
import java.util.*;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		sc.nextLine();
		int[] A = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
		Arrays.sort(A);
		System.out.println("" + A[n-1] + ' ' + A[0]);
	}
}
```
- - -
###### JavaScript
```js
const [n, A] = require("fs").readFileSync("/dev/stdin", "utf8").trim().split('\n').map((s, i) => i ? s.split(' ').map(Number) : Number(s));
A.sort()
console.log(A[n-1], A[0]);
```
- - -
###### Kotlin
```kotlin
fun main() {
	val n = readLine()!!.toInt()
	val A = readLine()!!.split(" ").map { it.toInt() }.toTypedArray()
	A.sort()
	println("" + A[n-1] + ' ' + A[0])
}
```
- - -
###### PHP
```php
<?php
	$n = intval(fgets(STDIN));
	$A = array_map("intval", explode(' ', fgets(STDIN)));
	sort($A);
	echo $A[$n-1], ' ', $A[0], PHP_EOL;
?>
```
- - -
###### Perl
```pl
my $n = int(<STDIN>);
my @A = map { int($_) } split ' ', <STDIN>;
@A = sort(@A);
print "$A[$n-1] $A[0]$/";
```
- - -
###### Python3
```py
n = int(input())
A = list(map(int, input().split()))
A.sort()
print(A[-1], A[0])
```
- - -
###### Ruby
```rb
n = gets.to_i
A = gets.split.map(&:to_i)
A.sort!()
print A[n-1], ' ', A[0], "\n"
```
- - -
###### Scala
```scala
import scala.io.StdIn._

object Main extends App{
	val n = readInt()
	val A = readLine().split(' ').map { _.toInt }
	val B = A.sorted
	println("" + B(n-1) + ' ' + B(0))
}
```
- - -
###### Swift
```swift
let n = Int(readLine()!)!
var A = readLine()!.split(separator: " ").compactMap { Int($0) }
A.sort()
print(A[n-1], A[0])
```
windows11で、sketchup6 その110

# 概要
windows11に、sketchup6を入れてみた。
rubyで、3Dを書く。
練習問題やってみた。

# 練習問題
正八面体を細分化せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/c6e979b5-326f-4116-878e-3053b2bcb60e.png)

# サンプルコード

```
def create_sei8b
	model = Sketchup.active_model
	entities = model.active_entities
	obj_v = [
		Geom::Vector3d.new(	0.0,	-10.0,	0.0),
		Geom::Vector3d.new( 10.0,	0.0,	0.0),
		Geom::Vector3d.new(	0.0,	0.0, 	10.0),
		Geom::Vector3d.new(-10.0,	0.0,	0.0),
		Geom::Vector3d.new(	0.0, 	10.0,	0.0),
		Geom::Vector3d.new(	0.0,	0.0,	-10.0)
	]
	obj_f = [
		[obj_v[0], obj_v[1], obj_v[2]],
		[obj_v[3], obj_v[0], obj_v[2]],
		[obj_v[4], obj_v[3], obj_v[2]],
		[obj_v[1], obj_v[4], obj_v[2]],
		[obj_v[3], obj_v[4], obj_v[5]],
		[obj_v[4], obj_v[1], obj_v[5]],
		[obj_v[1], obj_v[0], obj_v[5]],
		[obj_v[0], obj_v[3], obj_v[5]]
	]
	group0 = entities.add_group
	obj_f.each { |faces|
		expand_face(faces, 0, 10.0, group0.entities)
	}
	trans = Geom::Transformation.translation [20, 0, 0]
	group0.transform! trans
	group1 = entities.add_group
	obj_f.each { |faces|
		expand_face(faces, 1, 10.0, group1.entities)
	}
	trans = Geom::Transformation.translation [40, 0, 0]
	group1.transform! trans
	group2 = entities.add_group
	obj_f.each { |faces|
		expand_face(faces, 2, 10.0, group2.entities)
	}
	trans = Geom::Transformation.translation [60, 0, 0]
	group2.transform! trans
end






```

以上。
【解決】`mamba install` が終わらない！ → `micromamba` に切り替えて爆速で解決した話【conda地獄脱出】

## はじめに

Python の開発環境構築といえば `conda`。でも依存解決が遅すぎて、環境構築に何十分もかかること、ありませんか？

そこで登場するのが `mamba`。
「conda互換」「爆速」「C++製で依存解決が速い」と聞いて試してみたのですが──

> `mamba` のインストールすら終わらない。

という新たな地獄に落ちました。

その状況を救ってくれたのが `micromamba`。
今回は、`mamba` が詰まりまくっていた私の環境で、`micromamba` によって劇的に改善した体験を共有します。

---

## 背景：環境構築に `mamba` を使いたかった理由

* OS: Ubuntu 22.04
* 目的：AI系ライブラリ（kedro, scikit-learn, mlflow など）をまとめた開発環境を作成
* 手元の `environment.yml` には 10個以上の依存パッケージが定義

`conda` では `Solving environment` に数十分かかっていたため、`mamba` を使って高速化したいと思ったのがきっかけです。

---

## 問題：`mamba` のインストールが終わらない

```bash
conda install mamba -n base -c conda-forge
```

と打ったのですが、ずっとこの状態：

```
Solving environment: unsuccessful initial attempt using frozen solve...
retrying with flexible solve...
retrying with repodata.json...
```

**1時間以上たっても進まない。**

しかも `conda clean --all` を試しても改善せず、プロセスを強制終了せざるを得ない状況に。

---

## 解決策：`micromamba` に切り替える

### ✅ `micromamba`とは？

`mamba` の軽量版で、単一の実行ファイルで動作する **高速・自己完結型パッケージマネージャ**。condaと完全互換。

### ✅ インストール方法（1分で完了）

```bash
curl -Ls https://micro.mamba.pm/api/micromamba/linux-64/latest | tar -xvj bin/micromamba
export PATH=$PWD/bin:$PATH
eval "$(micromamba shell hook --shell bash)"
```

これだけで `micromamba` が使えるようになります。

---

## 爆速で環境作成できた！

```bash
micromamba create -n lecture-ai-engineering -f environment.yml
micromamba activate lecture-ai-engineering
```

たった数十秒で環境構築完了。
`conda` や `mamba` で止まっていたのが嘘のようでした。

---

## 注意点とコツ

* `micromamba` は基本的に `conda-forge` チャンネルを使うのが無難です（`defaults` は避ける）。
* `pip:` セクションでトラブルが出ることがあるので、手動で `pip install` に切り出すのもおすすめ。
* シェル初期化が必要な場合は：

```bash
micromamba shell init --shell bash --root-prefix=~/.local/share/mamba
source ~/.bashrc
```

---

## まとめ：`micromamba` はcondaユーザーの救世主

| 比較     | conda   | mamba    | micromamba  |
| ------ | ------- | -------- | ----------- |
| 速度     | 🐢 遅い   | 🚗 速い    | 🚀 爆速       |
| 安定性    | ◯       | △（環境による） | ◎           |
| 導入の手軽さ | 要インストール | 要conda依存 | 単体実行ファイルでOK |
| 容量     | 大       | 中        | 小（100MB以下）  |

---

## おわりに

`mamba` すらインストールできず詰んでいる方へ。
**`micromamba` があなたを救ってくれるかもしれません。**

環境構築で悩んでいた時間が嘘のように解消されました。
ぜひ一度試してみてください！
ChatGPTを使用したアプリ開発記【プロフィール編集画面で編集した名前を投稿画面に表示】

## ログインユーザーのプロフィール名を取得して表示

### ロジックコード
```App.js
  const [profileName, setProfileName] = useState('');
  
useEffect(() => {
  const unsub = onAuthStateChanged(auth, (currentUser) => {
    setUser(currentUser);

    if (currentUser) {
      console.log('ログインユーザーのUID:', currentUser.uid);

      (async () => {
        try {
          const profileDoc = await getDoc(doc(db, 'users', currentUser.uid));
          if (profileDoc.exists()) {
            const data = profileDoc.data();
            setProfileName(data.name || currentUser.displayName || '匿名');
          }
        } catch (err) {
          console.warn("プロフィール情報の取得に失敗しました", err);
        }
      })();
    }
  });
  return () => unsub();
}, []);
```

### UIコード
```App.js
         {profileName}
        </span>さん
      </p>
```

・onAuthStateChanged によってログイン状態を監視。
・ユーザーがログインしていたら、currentUser.uid を使って Firestore の users コレクションからドキュメントを取得。
・users/{uid} から name を取得し、なければ displayName、それもなければ "匿名" を表示名とする。

## 投稿一覧のユーザー名をFirestoreのusersコレクションから取得して表示

### ロジックコード
```App.js
useEffect(() => {
  const fetchPosts = async () => {
    try {
      const postsCollection = collection(db, 'posts');
      
    // 	Firestoreのpostsコレクションから、すべての投稿ドキュメントを取得します。
	// 	snapshot.docsでドキュメント配列を取得できます。
      const snapshot = await getDocs(postsCollection);

      const postsData = await Promise.all(snapshot.docs.map(async (docSnap) => {
        const postData = docSnap.data();
 
    //	postData.uid（投稿者のUID）を使って、users/{uid} というドキュメントを取得。
	//	このusersコレクションには、プロフィールのnameやphotoURLが保存されていると想定されます。
        const userDoc = await getDoc(doc(db, 'users', postData.uid));

	//	投稿時に保存された displayName を初期値とします。
	//	userDoc が存在していれば、そこから userData.name を取り出し、投稿に表示する名前として上書きします。
        let nameFromUserCollection = postData.displayName; // 投稿保存時の名前を初期値として使用
        if (userDoc.exists()) {
          const userData = userDoc.data();
          nameFromUserCollection = userData.name || nameFromUserCollection;
        }

        return {
          id: docSnap.id,
          ...postData,
          displayName: nameFromUserCollection,
        };
      }));

	//	投稿一覧に表示されるデータとして、プロフィールから取得したdisplayNameを含めた投稿情報をReactの状態に保存。
      setPosts(postsData);
    } catch (err) {
      console.error("Error getting posts:", err);
    }
  };

  fetchPosts();
}, [setPosts]);
```


### UIコード
```
<p className="font-semibold text-sm">{post.displayName}</p>
```
・ここで表示される post.displayName は、上記ロジックによって users/{uid} から取得された name に基づいています。

## Firestore

![スクリーンショット 2025-05-15 9.54.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058366/6524748e-b8ba-473a-8776-96c57f551503.png)

## UI

![スクリーンショット 2025-05-15 9.51.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058366/45319764-a0e2-4cbf-8ce7-394e5212c687.png)
16ビットの並びを逆転して遊ぶ 


いろいろ注意
----

- 過去ログを見よ!!!
- arduinoでの予定は、未定


プログラム
----

オンラインコンパイラpaiza


```c++



#define bit16_put(aa) for(int ii=16;ii!=0;ii--){if(aa & 0x8000){printf("1");}else{printf("0");}aa=aa<<1;}

//8ビットの並び順を逆転させるデータセット(テーブル)
unsigned char rev[] = {
0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0,0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0,
0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8,0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8,
0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4,0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4,
0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec,0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc,
0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2,0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2,
0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea,0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa,
0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6,0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6,
0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee,0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe,
0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1,0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1,
0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9,0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9,
0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5,0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5,
0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed,0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd,
0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3,0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3,
0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb,0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb,
0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7,0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7,
0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef,0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff
};

#include <stdio.h>
int main(void){
    // Your code here!
    
    int in = 0b0000000001010101;
    
    int a = (in >> 4) & 0xff;
    int b = ((in >> 8) & 0xf0) |  (in & 0xf);
    
    a = rev[a];
    b = rev[b];
    
    a = a << 4;
    b = ((b & 0xf0) << 8) | (b & 0xf);

    int out = a | b;

    bit16_put(a);printf("\n");
    bit16_put(b);printf("\n\n");
    
    bit16_put(out);printf("\n");
    
}



```

```

0000101000000000
1010000000000000

1010101000000000


```
「変更の取り消し可能な処理」を実装するためのユーティリティをTypeScriptで書いてみた

意識したのは次のこと。

- このユーティリティを使う側が、ロールバックや変更の取り消し処理を手続き的に書かずに済むようにしたい
- 心的イメージとして「コマンド」と「シーケンス」を採用。コマンドは一つの処理とその取り消し処理。シーケンスはそのコマンドの連なり

というわけで書いてみた

## 結論

こうなった

```ts
/**
 * 実行したい処理をrunに、戻し処理をrevertに指定する。
 */
export class RevertibleCommand<T> {
  constructor(
    public readonly run: () => Promise<T> | T,
    public readonly revert: () => Promise<void> | void,
  ) { }
}

/**
 * 例外発生時には戻し処理（revert）がまとめて実行される。
 * 正常時は、各コマンドの戻り値をタプルとして返す。
 * 返却値の型はコマンドごとに異なっていても問題ない（タプルが個別の型を持つ）。
 */
export class Sequence<Commands extends RevertibleCommand<any>[]> {
  constructor(
    private readonly commands: readonly [...Commands]
  ) { }

  async run(): Promise<{
    [K in keyof Commands]: Commands[K] extends RevertibleCommand<infer R> ? R : never
  }> {
    const reverts: Array<() => Promise<void> | void> = [];
    const results: unknown[] = [];

    for (const command of this.commands) {
      try {
        const result = await command.run();
        results.push(result);
        reverts.push(command.revert);
      } catch (error) {
        await Promise.allSettled(reverts.map(fn => fn()));
        throw error;
      }
    }

    return results as {
      [K in keyof Commands]: Commands[K] extends RevertibleCommand<infer R> ? R : never
    };
  }
}
```

## 使い方

下記のようにして使う。例外発生時には戻し処理（revert）がまとめて実行される。
正常時は、各コマンドの戻り値をタプルとして返す。
返却値の型はコマンドごとに異なっていても問題ない（タプルが個別の型を持つ）。

```ts
const command1 = new RevertibleCommand<number>(
  () => { console.log('Run A'); return 10; },
  () => { console.log('Revert A'); },
);

const command2 = new RevertibleCommand<string>(
  () => { console.log('Run B'); return 'OK'; },
  () => { console.log('Revert B'); },
);

const command3 = new RevertibleCommand<boolean>(
  () => { console.log('Run C'); return true; },
  () => { console.log('Revert C'); },
);

const seq = new Sequence([command1, command2, command3]);

(async () => {
  const [a, b, c] = await seq.run();
  console.log(a, b, c);
})();
```
【公ド読】考えられる機能実装について確認する

【公式ドキュメントを読もうシリーズ】考えられる機能実装について確認する

## シリーズ概要

[https://qiita.com/yasu_programming/items/cec66f9e8d5d571e9ce3](https://qiita.com/yasu_programming/items/cec66f9e8d5d571e9ce3)

## URL

[https://docs.github.com/ja/copilot/copilot-chat-cookbook/functionality-analysis-and-feature-suggestions/exploring-potential-feature-implementations](https://docs.github.com/ja/copilot/copilot-chat-cookbook/functionality-analysis-and-feature-suggestions/exploring-potential-feature-implementations)

## 説明

新しい機能の実装や既存の機能の強化をするときのアプローチの提案をしてくれる。

具体的には、ダッシュボードに最近閲覧された項目を表示する機能を追加するときの方法について書かれている。

issueをもとに、どのように実装するかが書かれている。

- 実装方法の提案
- 要件に応じた、最適なissueの解決方法の提案

## 所感

プロンプトの技術やissueの段階で言語化する技術が必要になる。
AIにインプットするのと同時に、エンジニアとしてのスキルの向上が必要なんだと感じた。
株式会社LIGNEA

LIGNEA【ライブ＆セトリ情報】
https://lignea.co.jp/

初めてアーティストのライブに参加する方へ、ライブスケジュール・参加条件・難しいチケットの購入方法（一般販売開始情報）などをまとめて、最新情報を配信するWEBメディアを運営しています。

こども、ファミリー向けのエンターテイメント情報を無償配信することで、インターネットリテラシーの差から発生する、情報格差による不平等を改善、平等に選択できる機会の提供を目指します。
WEB開発技術の成長を継続することで、新しい文化、産業など、人が新しい価値観に触れる瞬間の創造に取り組みます。

株式会社LIGNEA【会社概要】
https://lignea.co.jp/company/
2025/5/20主にITとかセキュリティの記事

2025年5月1日～2025年5月7日までに報告されたWordPress関連の脆弱性情報(5/18)
https://news.mynavi.jp/techplus/article/wordpressvulnerability-4/

日本や台湾を狙う標的型攻撃：「Earth Kasha」が攻撃手法を更新して新たな攻撃キャンペーンを開始(5/19)
https://www.trendmicro.com/ja_jp/research/25/e/earth-kasha-updates-ttps.html

欧州 ENISA サイバー・ストレステストのためのハンドブック (2025.05.15)(5/18)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2025/05/post-733d11.html

【今すぐ確認】Microsoftが72件のセキュリティ脆弱性に対処。7件のゼロデイ脆弱性も(5/18)
https://www.lifehacker.jp/article/2505-microsofts-patch-tuesday-update-fixes-seven-zero-days/

【2025】サイバー攻撃の種類39選をジャンルごとに徹底解説！攻撃の割合や対策・最新IPAランキングも紹介
https://cad-kenkyujo.com/saiba-kougeki-syurui/

Mandiant後継者が警告：AIを活用したサイバー攻撃が1年以内に現実化へ(5/18)
https://innovatopia.jp/cyber-security/cyber-security-news/54575/

Incogni調査：米国企業幹部の約8割がプライバシー危機に直面、個人情報が簡単に検索可能に(5/18)
https://innovatopia.jp/cyber-security/cyber-security-news/54578/

新型SMSフィッシング詐欺がスマホを狙う！FBI警告(5/17)
https://www.epochtimes.jp/2025/05/302023.html

バイナンスとクラーケン、コインベース型攻撃を未然に阻止｜AIセキュリティで顧客情報守る(5/17)
https://crypto-times.jp/news-binance-and-kraken-thwart-coinbase-style-attack/

オープンウェブインデックス、欧州はGoogleへの戦争に向けて武器を研ぎ澄ます(5/17)
https://ja.futuroprossimo.it/2025/05/open-web-index-leuropa-affila-le-armi-per-la-guerra-a-google/

AppleとAlibabaの提携に米政府が懸念〜AI企業との提携禁止も検討(5/18)
https://iphone-mania.jp/apple-intelligence-594964/

巧妙化するサイバー犯罪 生成AIの進化で多様化　被害防ぐには？(5/18)
https://www.ncctv.co.jp/news/article/15773424

トランプ一家が支援するステーブルコイン「USD1」、複数のブロックチェーンで利用可能に──チェーンリンクのCCIP活用【Consensus 2025】(5/18)
https://www.coindeskjapan.com/293090/

もし「このサイトは安全に接続できません」と表示されたら？エラー表示が出る原因と対処法(5/18)
https://dime.jp/genre/1961401/

イーサリアム研究者、ビットコインの51%攻撃コスト減少に懸念(5/18)
https://cryptodnes.bg/jp/bitcoin-ethereum-51percent-attack-comparison-security/

システム開発の工程について整理してみた(5/18)
https://blog.serverworks.co.jp/dev-flow-waterfall

【応用情報】IT未経験の文系大学生が半年で応用情報を取った戦略と勉強法(5/16)
https://qiita.com/misato729/items/0c77641c884b253e4d36

MCPとは何か 〜AIエージェントの為の標準プロトコル〜(5/18)
https://blog.cloudnative.co.jp/27994/

下呂市の６０代男性会社員　パソコン警告画面の特殊詐欺で３００万円被害(5/18)
https://news.yahoo.co.jp/articles/bc6b9147c1f63266b97e17ff6b46239624bc0011

ネットの海へＰＣ指導(5/18)
https://www.yomiuri.co.jp/local/tottori/feature/CO070116/20250517-OYTAT50010/

AI言語モデルが人間のように社会規範を形成：研究者がLLMの自己組織化能力を発見(5/17)
https://innovatopia.jp/ai/ai-news/54563/
【Canvas】回る野獣先輩BB


ローディング画面に使ってください。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="myyYBxX" data-pen-title="Untitled" data-user="mogamoga1024" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/mogamoga1024/pen/myyYBxX">
  Untitled</a> by mogamoga1024 (<a href="https://codepen.io/mogamoga1024">@mogamoga1024</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>

## ソース

```main.js
const canvas = document.querySelector("canvas");
const context = canvas.getContext("2d");

const yjsnpiWidth = 120;
const yjsnpiHeight = 150;

canvas.width = yjsnpiWidth;
canvas.height = yjsnpiHeight;

const yjsenpiImage = new Image();
yjsenpiImage.src = "回る野獣先輩.png";

yjsenpiImage.addEventListener("load", () => {
    spinningYajuuSenpai();
});

let index = 0;
const yjsnpiCount = 20;

function spinningYajuuSenpai() {
    setInterval(() => {
        context.clearRect(0, 0, canvas.width, canvas.height);
        context.fillStyle = "rgb(0, 0, 255)";
        context.fillRect(0, 0, canvas.width, canvas.height);

        const colCount = yjsenpiImage.width / yjsnpiWidth;
        const sx = yjsnpiWidth * (index % colCount);
        const sy = yjsnpiHeight * Math.floor(index / colCount);

        context.drawImage(
            yjsenpiImage,
            sx, sy, yjsnpiWidth, yjsnpiHeight,
            0, 0, canvas.width, canvas.height
        );

        index = (index + 1) % yjsnpiCount;
    }, 1000 / 60 * 10);
}
```

![回る野獣先輩.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649673/4d5b8a4d-5c8f-4b6c-b658-1f379a1be76c.png)

## 元ネタ

https://www.nicovideo.jp/watch/sm24975764
Railsとセキュリティの概念について学んだよ①　〜ユーザーの操作によっておこる問題編〜

こんにちは。
Railsを学び始めたばかりの初学者です。  
今回は「ユーザーの操作によっておこるセキュリティの問題」と、それをどう防ぐかについて学んだことをまとめます。

## はじめに

Railsには「**Rails Way（レールズウェイ）**」という考え方があるようです。
知らなかったです。
これは「Railsが想定する標準的な書き方に沿って開発すれば、安全性・保守性・拡張性が高まる」というものです。
セキュリティの観点からも、**Rails Wayに従えば基本的には安心**と言われてるようです。

## セキュリティの問題は大きく2つ
Railsアプリケーションでは、大きく以下の2つのセキュリティリスクがあるみたいです。
1. **ユーザーの操作によっておこる問題**  
2. **悪意のある攻撃者による問題**
今回の記事では、1つ目の「ユーザーの操作によっておこる問題」に焦点を当て、記事を残します。

## ユーザーの操作で起きる問題

例えば、ログインしているユーザーが以下のようなことを意図せずに行えると危険。

- 他人のデータを見れてしまう  
- 他人のデータを編集・削除できてしまう

これは、本来アクセスできるはずのないデータにアクセスできてしまうという、非常に重要なセキュリティ問題。

---

## 例：問題のあるコード

以下は、一見それっぽく見えるけれど、他のユーザーの投稿を削除できてしまう危険なコード。

```ruby
class ArticleController < ApplicationController
  before_action :authenticate_user!

  def destroy
    article = Article.where(user_id: params[:user_id], article_id: params[:article_id])
    article.destroy!
  end
end
```
 ## 問題点
 - `params[:user_id]`や`params[:article_id]`をそのまま使っている
- ログイン中のユーザー（current_user）を使っていない
これでは、悪意がなくてもURLを少しいじるだけで、他人の投稿を削除できてしまう。

## 解決策：current_userを使う
このような問題は、常に「current_user」からデータを参照することで防げるみたいです。
```ruby
 class ArticleController < ApplicationController
  before_action :authenticate_user!

  def destroy
    article = current_user.articles.find(params[:id])
    article.destroy!
  end
end
```
`current_user.articles.find(params[:id]) `のようにすることで、ログイン中のユーザーが所有する記事しか操作できなくなります。

## まとめ
- Railsのセキュリティは 「Rails Way」に従うことが基本
- `current_user`からデータを取得・操作することで、他のユーザーの情報を守れる
- `params[:user_id]`などを不用意に使うと、重大な問題を引き起こす可能性がある

## 
私はまだRails初学者ですが、「セキュリティ」というテーマはとても大事だと感じています。
次は、悪意のある攻撃者による問題について記事を残します。
OpenAIとTwitter APIを使って、“続けたくなる”アプリを作ってみた話

## はじめに
最近、個人開発で「ぽもログ」というWebサービスを作りました。
スキマ時間を活用してポモドーロタイマーを記録し、その日の頑張りを AI がやさしく採点してくれるサービスです。

[ぽもログ](https://pomolog.net/)

この中で、以下の2つの外部サービスを活用しました：

✅ OpenAI API（ChatGPTを使った自動採点・フィードバック生成）

✅ Twitter API（Xアカウントでのログインやシェア連携）

本記事では、これらのAPIを使った理由や実装の流れ・つまずいたポイントなどを、技術者向けにまとめてみました。
同じように「AI」や「SNS連携」を自分のサービスに組み込みたい方の参考になれば幸いです。

## 使う流れ(ChatGPTモデル)
１OpenAIでアカウントを作成し、APIキーを取得(.envなどに持たせる)
２PythonなどのプログラムでAPIを呼び出す
（使った分だけ課金される従量課金制です）
```python:main.py

from openai import OpenAI
client = OpenAI(api_key="YOUR_API_KEY")

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "system", "content": "あなたは親切なAIです"},
        {"role": "user", "content": "AIとは何ですか？"}
    ]
)

print(response.choices[0].message.content)


```
OpenAI APIの大きな魅力のひとつは、使用するモデルやプロンプト（AIへの指示文）を自由に設計できる点です。
これにより、サービスの目的やユーザー体験に合わせて、最適なAIの挙動を引き出すことが可能になります。
APIでは、モデル名を指定するだけで、GPT-3.5やGPT-4、最新のGPT-4oといったさまざまなモデルを使い分けることができます。たとえば、
```python:example.py

model="gpt-3.5-turbo"  # 軽量・高速・安価
model="gpt-4"          # 高精度・論理的思考に強い
model="gpt-4o"         # 最新・高性能・画像も扱える

```
また、AIに渡すメッセージ（プロンプト）も完全に自由に設計可能です。
たとえば、AIに「やさしく励ましてほしい」「プログラマー風に厳しく指摘してほしい」など、キャラや口調、目的に合わせて個性を持たせることができます。
```python:example.py

messages=[
    {"role": "system", "content": "あなたはやさしくユーザーを応援するAIです。"},
    {"role": "user", "content": "～を頑張りました…"}
]

```
## 使う流れ(X API+Flask)
１Twitter Developerアカウント登録
[こちらで登録](https://developer.x.com/en)
２プロジェクトとアプリを作成（X APIの鍵を得るため）
３ APIキー・シークレットを取得
```python:main.py

@main_bp.route("/login/twitter")
def login_twitter():
    redirect_uri = "https://pomolog.net/login/callback"
    return current_app.twitter.authorize_redirect(redirect_uri)

@main_bp.route("/login/callback")
def twitter_callback():
    token = current_app.twitter.authorize_access_token()
    resp = current_app.twitter.get("account/verify_credentials.json")
    user_info = resp.json()
    username = user_info["screen_name"]

```
authlib を使って Twitter OAuth 1.0a を登録

app.twitter に認証機能をアタッチ

これにより /login/twitter で Twitterログインができるようになる

```python:_init.py

from authlib.integrations.flask_client import OAuth

oauth = OAuth(app)
twitter = oauth.register(
    name='twitter',
    client_id=os.getenv("TWITTER_API_KEY"),
    client_secret=os.getenv("TWITTER_API_SECRET"),
    request_token_url='https://api.twitter.com/oauth/request_token',
    access_token_url='https://api.twitter.com/oauth/access_token',
    authorize_url='https://api.twitter.com/oauth/authorize',
    api_base_url='https://api.twitter.com/1.1/',
)

```
## 終わりに
今回は、OpenAI APIとTwitter APIを使って、実際に「ぽもログ」というサービスに機能を組み込んだ経験を紹介しました。

どちらのAPIもドキュメントが充実しており、初心者でも取り組みやすい反面、OAuthの認証フローやトークン管理など、細かい部分では意外とハマりどころも多かった印象です。
AIを活用しながらの開発でしたがかなりつまずくこともありました。

もしこの記事が、同じように「AI」や「SNS連携」をサービスに組み込みたい方のヒントになればうれしいです。
コンビネータ論理Extra practice 2.35(a)

コンビネータ論理の問題。

[Lambda-Calculus and Combinators: An Introduction](https://amzn.to/4iYmQU3)
Hindley & Seldin より
# Extra practice 2.35(a)
次のコンビネータを簡約化せよ。
ただし、
$BXY\ \triangleright_\omega\ X(YZ) $
$CXYZ\ \triangleright_\omega\ XZY $
$WXY\ \triangleright_\omega\ XYY $

### (i)
$KSuxyz$
$\equiv(KSu)xyz\equiv Sxyz\equiv xz(yz)$
### (ii)
$S(Kx)(KIy)z$
$\equiv(Kx)z((KIy)z)\equiv x(Iz)\equiv xz$
### (iii)
$CSIxy$
$\equiv(CSIx)y\equiv SxIy\equiv xy(Iy)\equiv xyy$
### (iv)
$S(CI)xy$
$\equiv(CI)y(xy)\equiv CIy(xy)\equiv I(xy)y\equiv(xy)y\equiv xyy$
### (v)
$B(BS)Bxyzu$
$\equiv(BS)(Bx)yzu
\equiv B\underline{S}(\underline{Bx})\underline{y}zu
\equiv S(\underline{(Bx)y})\underline{z}\ \underline{u}$
$\equiv(B\underline{x})\underline{y}\ \underline{u}(zu)
\equiv x(yu)(zu)$
### (vi)
$BB(BB)uvwxy$
$\equiv B((BB)u)vwxy
\equiv (BB)u(vw)xy
\equiv B(u(vw))xy$
$\equiv (u(vw))(xy)$
### (vii)
$B(BW(BC))(BB(BB))xyzu$
$\equiv(BW(BC))((BB(BB))x) yzu$
$\equiv(BW(BC))(B(BBx)) y zu$ by $(BB(BB))x=B(BBx)$
$\equiv W((BC)(B(BBx))) y zu$
$\equiv ((BC)(B(BBx))) y y zu$
$\equiv C((B(BBx)) y) y zu$
$\equiv ((B(BBx))y) zy u$
$\equiv (BBx)(yz) yu$
$\equiv B(x(yz)) yu$
$\equiv (x(yz)) (yu)\equiv x(yz) (yu)$
DevinのDeepWikiを使ってみた！

# DevinのDeepWikiを使ってみた！

最近話題のAIエージェント「Devin」ですが、Devinが持つ技術が活用された「DeepWiki」を実際に使ってみたので、概要や使い方、所感をQiita記事としてまとめます。

## 参考：Devinとは？
Devinは、米Cognition AI社が開発したAIソフトウェアエンジニアです。チャットベースで高度な開発タスクをこなせる次世代のAIエージェントとして注目されています。これまでは、数万円～からでしたが、20ドルから使えるようになりました。

- 公式サイト: [Devin](https://devin.ai)
- 安野氏youtube動画：[【マジで触るべき】月20ドルでチームに"開発エージェント"!? Devinをはじめるなら今!【お得な招待URLもあるよ】](https://www.youtube.com/watch?v=AgCmdRpFd18&t=11s)

- Devinの招待URLはこちら👇　こちらを通して、SignUpするとお得です。
  https://app.devin.ai/invite/Hg3CtMTlCckLdd1F

## DeepWikiとは？

**DeepWiki**は、Cognition Labs（Devin開発元）が開発した、AIによるGitHubリポジトリ自動ドキュメント生成・ナレッジベース化ツールです。
**GitHubのURL中の「github」を「deepwiki」に置き換えるだけで、誰でもそのリポジトリの構造・技術スタック・主要機能・依存関係などを、分かりやすいWiki形式で閲覧できます。**
さらに、AIによる深掘り分析も可能です。

### 使い方

1. 任意のGitHubリポジトリのURL（例: `https://github.com/owner/repo`）の「github」を「deepwiki」に変更  
   例: `https://deepwiki.com/owner/repo`
2. ブラウザでアクセスすると、AIが自動生成したWikiページが表示されます
3. 追加で質問や深掘りも可能

なお、レポジトリがindex化されていなければ、Deepwikiの生成をリクエストすることができます。
- **パブリックリポジトリは無料・サインアップ不要**  
- プライベートリポジトリは有料・Devinアカウント連携が必要です。

nextjsの例：

- Github: https://github.com/vercel/next.js/  
- Deepwiki: https://deepwiki.com/vercel/next.js/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601976/5a7ae73f-ac8c-4ba3-8cf4-1372baed24da.png)

気になる、レポジトリがあれば、アクセスして、リクエストしましょう。
It looks like you're trying to use `tailwindcss` directly as a PostCSS plugin. の解消 🤩

## はじめに

`React.js` で `Tailwind CSS` をインストールした時に遭遇したエラーの解消方法を載せておきます。

```
it looks like you're trying to use `tailwindcss` directly as a postcss plugin.
```

## 🪄  解消法
エラー内容で検索した際にヒットした[本記事](https://qiita.com/masafumi1073/items/5746fe94615d0595ea6a)や[公式ドキュメント](https://tailwindcss.com/docs/installation/using-postcss)を試しましたが、イマイチ解消には至らずでした。

解消方法としては、以下対応でエラー解消することができましたので載せておきます😆
* `3.4.15`バージョン指定でインストール
* `tailwind.config.js`にて以下記述

```terminal
npm i -D @vitejs/plugin-react postcss tailwindcss@@^3.4.15
```

```js:tailwind.config.js
import react from '@vitejs/plugin-react';
export default {
  content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
  plugins: [react()],
};
```

## 💫 参考文献
* [【Tailwind CSS】It looks like you're trying to use `tailwindcss` directly as a PostCSS plugin. の解決方法](https://qiita.com/masafumi1073/items/5746fe94615d0595ea6a#%E8%A7%A3%E6%B1%BA%E6%96%B9%E6%B3%95)
* [Install Tailwind CSS](https://tailwindcss.com/docs/installation/using-postcss)
One-Way Differential Delay (OWDD) Used for Path Selection on Mobile Networks

One-Way Differential Delay (OWDD) Used for Path Selection on Mobile Networks
Kiyoshi Ogawa, Arata Sawai, Dr. Noboru Ilda, Dr. Takashi Watanabe
https://openreview.net/forum?id=zPCzWTbBRM
Published in: 18th International Conference on Advanced Information Networking and Applications, 2004. AINA 2004.

>Abstract
There are many paths where users can communicatewith wired and/or wireless links. Multiple links areused at the same time and in the same place. In thesesituations, users can select a better path by measuringthe path characteristics. This is also issue in Mobile IPtriangle routing [A Mobile IP expansion on pre/post-registration and selection of route optimization][A study on Mobile IP route optimization]. Upload and download trafficis significantly different at short period. For pathselection, a one-way measurement is needed, thus thispaper proposes a one-way differential delay which canbe used easily to select a better path. We havedeveloped a prototype and simulation system.
PDFからテキストを簡単に抽出するGoogle Colabスクリプトの紹介



近年、デジタルドキュメントとして広く利用されているPDFファイル。しかし、PDFからテキストを取り出して再利用したい場面は多くあります。特に研究やビジネス、教育の現場では、**PDFの内容をテキスト形式でコピー・編集・翻訳したい**というニーズが高まっています。

## そこで役立つのが「Google Colab」と「PyMuPDF」

Google Colabを使えば、Pythonスクリプトを**ブラウザ上で実行**でき、**ソフトのインストール不要**で作業を始められます。さらに、**PyMuPDF（fitzモジュール）**を利用することで、PDFファイルからテキストを**簡単かつ高速**に抽出できます。

## 特徴的なポイント

*  **ページごとに区切りを表示**
  各ページの始まりに「--- Page n ---」と表示し、区切りが一目で分かります。

*  **余計な空白を自動除去**
  各ページの先頭・末尾の空白を削除し、スッキリしたテキストを出力します。

*  **コピー・ペーストしやすい**
  出力結果をそのまま一括でコピーでき、別のドキュメントやエディターに貼り付けて活用できます。

## 実行手順

1. Google Colab でスクリプトを実行。
2. PDFファイルをアップロード。
3. 自動的にPDF全ページからテキストを抽出。
4. 画面に表示されたテキストをコピーして活用。



```python
# Program Name: pdf_text_extractor_colab.py
# Creation Date: 20250520
# Overview: A script to extract and display plain text from uploaded PDF files in Google Colab.
# Usage: Run each cell in order on Google Colab to upload and process PDF files.

# --- Install required libraries / 必要なライブラリのインストール ---
!pip install PyMuPDF --quiet

# --- Import required modules / 必要なモジュールのインポート ---
import fitz  # PyMuPDF
from google.colab import files

# --- File Upload / ファイルアップロード ---
print("Please upload your PDF file.")
uploaded = files.upload()

# --- Extract and display text / テキスト抽出と表示 ---
for file_name in uploaded.keys():
    print(f"\nProcessing file: {file_name}\n")
    with fitz.open(file_name) as pdf_document:
        extracted_texts = []
        for page_num in range(len(pdf_document)):
            page = pdf_document.load_page(page_num)
            text = page.get_text()
            page_header = f"\n--- Page {page_num + 1} ---\n"
            extracted_texts.append(page_header + text.strip())
        
        # Combine all pages' text and display as plain block / ページごとのテキストをまとめて表示
        final_output = "\n".join(extracted_texts)
        print(final_output)
```
FTPのインストールから接続できるようになるまで

■環境
さくらのVPS：RockyLinux

ftpの設定について、備忘録
サーバへftpをインストール
<pre>
sudo yum install vsftpd
sudo cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.org
sudo vi /etc/vsftpd/user_list　#アクセスを許容するユーザを追加
sudo systemctl enable vsftpd.service #サービスを有効化
sudo systemctl status firewalld #firewallのステータスを確認
sudo systemctl enable firewalld #firewallを有効化
sudo firewall-cmd --add-service=ftp 
sudo firewall-cmd --list-services
sudo systemctl restart vsftpd.service #再起動
sudo useradd user_name # ftp用のユーザを追加
sudo passwd user_name # ftpユーザのPWを変更
</pre>

httpd.conf
<pre>
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
allow_ftpd_full_access
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_std_format=YES
ascii_upload_enable=YES
ascii_download_enable=YES
chroot_local_user=YES
chroot_list_enable=YES
listen=NO
listen_ipv6=YES
userlist_deny=NO
pam_service_name=vsftpd
userlist_enable=YES
use_localtime=YES
</pre>

セキュリティの観点的には正しいか不明。
かつ設定の不整合があるかもしれないが、一応これで起動した。
各設定については、後日見直す予定。
TryHackMe practice day1

# はじめに
「7日間でハッキングを始める本」という本を買ったので，過程をメモする．情報セキュリティは学部レベルの知識しかない。

# Day1. ハッキングの準備をしよう
## wslでkali linuxインストール
ハッキング用のツールが最初から入ってるkali linuxというディストリビューションがあるとのこと。
書籍内ではvirtualboxを使っていたが，流石に現代ではwslで。

以下を参考にした
https://qiita.com/san_bay3/items/9c0c0f4a250e4fa73ede

GUI必須かわからないけど，一応インストール
```
sudo apt update && sudo apt install kali-win-kex
```

このコマンドでこけたため，以下を参考にして．解決
https://blog.cosnomi.com/posts/wsl-resolv-conf/
```/etc/resolv.conf
...
namespace 8.8.8.98
...
```
## TryHackMe登録

## VPN登録
VPNが必要な理由として，「プラクティスで間違って違うサイトを攻撃したり，他者に迷惑をかけないため」ってのは理解できたけど，「ターゲットのマシンと同じネットワークに接続する環境を作るため」というのがピンとこなかった。

それが一番大変なんじゃないの...？

TryHackMe上のこのConnectionが緑になればVPNに繋がったことの確認と書いてあったが，Refreshしても変わらなかったので，一旦飛ばす
![スクリーンショット 2025-05-20 001039.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774226/4b136582-b8d5-4f9e-ad6a-6f6c19478d6a.png)


## Tutorial Room
TryHackMeはRoomというものが課題の単位とのこと。
今回はTutorialというRoomでサイトの使い方確認。

本の写真とサイトの構造が少し違って，Roomを探すのに手間取った

Roomを開始するとターゲットのマシンが立ち上がり，どうにかハッキングすると文字列（答え）が手に入り，それを送信するとクリアとなるのが流れとのこと。

TutorialはIPアドレスが表示されるので，ブラウザで開いて，表示される文字列を答えるだけ

TryHackMe上でマシンを立ち上げて，それで問題に取り組むこともできるみたい。
windowsの中のkali linuxの中のFirefoxの中のマシンになってる。
![スクリーンショット 2025-05-20 001752.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774226/eb9dede2-7e80-4a61-ae88-7c24f07829e8.png)

VPNが緑（Connected）になってなくともアクセスできました。OpenVPNをプロセスキルしてから，同じアドレスにアクセスしようとしたらぐるぐるになったので，多分VPN設定はうまく行ってる。
![スクリーンショット 2025-05-20 001052.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774226/53579a96-ecaf-4096-a12c-20e1e6aa9a7f.png)


# メモ用
kali-linux起動
```
wsl.exe -d kali-linux
```

GUI起動
```
kex --win -s -m
```

VPN接続
```
sudo openvpn ~/vpn/<hogehoge>.ovpn
```
JavaScriptのジェネレータ関数を実務で使った話

**ジェネレータ関数**はJavaScriptの機能の中でもマイナーな機能で、`function`の代わりに`function*`で関数を作るのが特徴です（アロー関数版のジェネレータ関数式はありません）。また、その中では`yieid`式が使用可能になります。

ジェネレータ関数については、存在は知ってるけど実務で使ったことがないという方も多いのではないかと思います。

そこで、今回は筆者がこれまでの経験で唯一、ジェネレータ関数を実務で使ったケースを紹介します（具体的なユースケースについては実際の業務そのままではなくこの記事用に用意したシチュエーションとなるので、そこはご了承ください）。

## 配列の組み立てが複雑になりがち

例えば、「メインメニューの表示内容が、ユーザーが管理者ユーザーかどうかで異なる」という仕様を実装したい場合を考えましょう。普通に実装すると、こんな感じになるはずです。

```ts
function getMainMenu(user: User): Menu[] {
  return [
    { name: 'Home', url: '/' },
    { name: 'Profile', url: '/profile' },
    ...(user.isAdmin ? [{ name: 'Admin', url: '/admin' }] : [])
  ];
}
```

このように、配列の中身が条件分岐によって決まるため、配列のスプレッド構文を使って条件分岐を実装したという方もいるでしょう。

問題は、さらに条件分岐が増えた場合です。

```ts
function getMainMenu(user: User): Menu[] {
  return [
    { name: 'Home', url: '/' },
    { name: 'Profile', url: '/profile' },
    ...(user.isAdmin ? [{ name: 'Admin', url: '/admin' }] : []),
    ...(user.isSpecialUser ? [{ name: 'Special', url: '/special' }] : [])
  ];
}
```

さらに、条件分岐がネストする必要があったりすると、とんでもないことになります。

```ts
function getMainMenu(user: User): Menu[] {
  return [
    { name: 'Home', url: '/' },
    { name: 'Profile', url: '/profile' },
    ...(user.isAdmin
      ? [
          { name: 'Admin', url: '/admin' },
          ...(user.isSpecialAdmin
            ? [{ name: 'Special Admin', url: '/special-admin' }]
            : []),
        ]
      : []),
    ...(user.isSpecialUser
      ? [{ name: 'Special', url: '/special' }]
      : [])
  ];
}
```

🤮

## ジェネレータ関数による改善

このように配列の組み立てが複雑になってしまう場合、`Array.from`とジェネレータ関数を組み合わせると便利です。この例くらいだと配列のpushメソッドとかを使ってもいいのですが、配列を生成する部分を独立した関数に分けずにインラインで済ませたい場合とか、何が何でも配列を破壊的変更したくない場合はこの方法が役に立ちます。

```ts
function getMainMenu(user: User): Menu[] {
  return Array.from(function*() {
    yield { name: 'Home', url: '/' };
    yield { name: 'Profile', url: '/profile' };
    if (user.isAdmin) {
      yield { name: 'Admin', url: '/admin' };
      if (user.isSpecialAdmin) {
        yield { name: 'Special Admin', url: '/special-admin' };
      }
    }
    if (user.isSpecialUser) {
      yield { name: 'Special', url: '/special' };
    }
  }());
}
```

🤩

ちなみに、`yield*`を適宜活用するのも便利です。

```ts
function getMainMenu(user: User): Menu[] {
  return Array.from(function*() {
    yield* [
      { name: 'Home', url: '/' },
      { name: 'Profile', url: '/profile' },
    ];
    if (user.isAdmin) {
      yield { name: 'Admin', url: '/admin' };
      if (user.isSpecialAdmin) {
        yield { name: 'Special Admin', url: '/special-admin' };
      }
    }
    if (user.isSpecialUser) {
      yield { name: 'Special', url: '/special' };
    }
  }());
}
```

😍

以上です。
今更すぎるAndroidのXMLレイアウトの実装、Viewの参照/紐付けの仕方の変遷


## はじめに

Androidエンジニアとして働き始めてはや1ヶ月。
目の前の仕事とインプットをする日々であっという間に過ぎています。

そんな中今回はレイアウト関連で、当たり前だけど、今更なんだっけと聞けない人や僕のようなペーペーAndroiderが調べるであろうところを自分のアウトプットのためにも残しておこうと思います。
そもそも、自分の今入っているプロジェクトがかなり昔から続いているアプリでいろんな時代の技術が残っていたりするので、とりあえずJetpackCompposeだけを理解すれば良いみたいな感じではなく、このような記事を書くに至っています。

iOSエンジニア時代は、storyboardとなんか似てるけど色々書いたり、レイアウトがいまいち見た目でピンとこないなーとかって思っていました。（storyboardはピーってViewクラスの宣言先にGUIでアウトレットすればよかったし、UIのパーツも割と配置や間隔や見た目なども個人的には分かりやすかった）

## UI実装の変遷

まずは、UI実装はXMLレイアウトとJetpackComposeといった実装がある中でXMLレイアウトを利用した際のViewのコード、いわゆるActivityやFragmentとのbindingについて書いていきます。

調べた感じ登場の順序として、
最初期は**findViewById**

```kotlin
findViewById<HButton>(R.id.button)
```

次は**アノテーション@BindView**

```kotlin
@BindView(R.id.button)
lateinit var button: Button
```

その次はDataBinding
```kotlin
// 双方向バインディング
android:text="@={viewModel.text}"
```

その次はViewBinding

```kotlin
// 単一方向のビュー参照
binding.button.text = "Click me"
```

そしてJetpack Compose
```kotlin
@Composable
fun Xxx(){
   Scaffold {
       ~~~~~~~~~
   }
}

```

といった流れになっています。

findViewByIdはNullチェックが必要であったり型を明示的にしないといけなかったりと不安定なものですが、
その次はViewBindingによってNull安全、型安全なものになりました。（見た目もシンプル）

DataBindingとViewBindingと名前が似ていますが、どのような違いがあるか調べました。

上記の例でも少し触れていますが、単一な参照なのか双方向に参照し合うのかの違いが大きいです。
MVVMのデザインパターンを利用している場合やデータの状態をリアルタイムに画面の変更を反映したい場合はDataBindingが向いています。
単純に画面へデータの反映を行い、ユーザーのインタラクトに対して特定の処理を実行するものであればViewBindingが向いています。

※向いていますという表現があっているか疑問ではありますが、どちらもそのようなシーンに向いているというだけであってそれぞれでも実現できはします。

## 実際どんなのが多いの？

新規の案件は、多くはJetpack Composeでの実装だと思います。
Xの採用情報でもetpack Composeでしたし、Googleが公開しているアーキテクチャの学習/ベストプラクティスのサンプルもKotlinとJetpackComposeのみのものになっています。（[Now In Android](https://github.com/android/nowinandroid)）
それ以前の2023年までのサンプルは[こちら](https://github.com/google/iosched?tab=readme-ov-file)。

## 補足： inflateって何？

最初思いました、「inflateって何？」
これはXMLファイルをViewのコードから操作できるようにするお決まりの処理です。

```kotlin
// activity_main.xmlというXMLファイルを
// ActivityMainBindingというViewオブジェクトに変換
binding = ActivityMainBinding.inflate(layoutInflater)

// layoutInflaterはXMLレイアウトファイルを解析してViewオブジェクトを生成するサービスのようです。

```

## 最後に

基本的に新しい技術はそれまでの良いところ・悪いところを見直しつつできているのでどんどん最新化するのがベストだと思います。
実際、今のプロジェクトも色々と最新化の流れがあります。
自分も新たに書いていく機会は少ないかもしれないですが、最新化する際にアレルギー出ないよう知識として持っておきます。
Next.js App Router: なぜ components ディレクトリにブラウザからアクセスできないのか

最近 Next.js の App Router を使い始めた際に、少し混乱したポイントについて整理したのでここに記載します。

## 疑問点

Next.js のプロジェクトを開発していた時、`src/app/components`ディレクトリにコンポーネントを配置し、ブラウザから直接アクセスしようとしたところ、404 エラーが発生しました。

例えば：

- `/src/app/dashboard/page.tsx` → `http://localhost:3000/dashboard` でアクセス可能
- `/src/app/components/Button.tsx` → `http://localhost:3000/components/Button` でアクセスしようとしても 404

なぜ`components`ディレクトリ内のコンポーネントにブラウザから直接アクセスできないのか、理解するのに少し時間がかかったので、その理由をまとめました。

## App Router のルーティング仕組み

調査した結果、App Router においてブラウザからアクセス可能なルートは以下の条件を満たす必要があることがわかりました：

1. `app`ディレクトリ内のフォルダ構造が URL パスに対応する
2. そのフォルダ内に**page.js/page.tsx**または**route.js/route.tsx**ファイルが存在する

つまり、URL からアクセスするためには、フォルダ名がパスの一部になり、そのフォルダ内に`page.tsx`または`route.tsx`が必要です。

## components ディレクトリの役割

`components`というディレクトリ名は、Next.js の規約上特別な意味を持ちません。これは単に開発者間の慣習として、再利用可能な UI コンポーネントを格納するために使われています。

App Router では、以下のような特別なファイル名が予約されています：

- `page.js` - ルートにアクセス可能なページコンポーネント
- `layout.js` - 共通レイアウト
- `loading.js` - ローディング状態の UI
- `error.js` - エラー状態の UI
- `route.js` - API エンドポイント

一方で、`components`ディレクトリやその中のファイルはルーティングの対象外です。

## コンポーネントへのアクセス方法

コンポーネントの内容を直接 URL でアクセスしたい場合は、そのコンポーネントを使用するページファイルを作成する必要があります。

```tsx
// src/app/my-button/page.tsx
import Button from "../components/Button";

export default function ButtonPage() {
  return (
    <div>
      <h1>ボタンコンポーネントのデモ</h1>
      <Button />
    </div>
  );
}
```

このようにすれば、`http://localhost:3000/my-button`からアクセスできるようになります。

## まとめ

Next.js の App Router では：

- コンポーネントは他のページやレイアウト内でインポートして使用するもの
- 直接 URL でアクセスする対象ではない
- ブラウザからアクセスするには、そのコンポーネントを表示する専用の`page.tsx`ファイルが必要

初心者で触りはじめた自分にとって、なんでだろうって混乱してました。
claudeなどの生成AIと対話しながら、その回答をもとに整理しました。

## 参考資料

- [Next.js 公式ドキュメント - App Router](https://nextjs.org/docs/app)
- [Next.js 公式ドキュメント - Routing](https://nextjs.org/docs/app/building-your-application/routing)
『Azureの知識地図』を読み終えて

2025/05/13に発売された『Azureの知識地図』を、著者のおひとりである土田さんよりご恵贈いただきました。

https://x.com/ussvgr/status/1918510160877670574

こつこつ読み進め読了に至りましたので、感想を書き留めておこうと思います。

# 本書の狙いと対象読者
出版元である技術評論社の本書のページが以下です。

https://gihyo.jp/book/2025/978-4-297-14903-1

こちらに記載されている文章を引用しますと、

> 本書は「すぐにAzureを使いこなす」ことよりも「変化するドキュメントや仕様を理解できる基礎知識を身につける」ことを目指します。

とあります。

この本のみを参照してAzure上で何かを作ることに取り組んでも、おそらくどこかで躓いてしまうと思われます。Azureポータルの詳細な操作方法や細かな設定値の説明はほとんど記載されていないためです。これは本書が不親切というわけではなく、意図されたものでしょう。
クラウドサービスは随時アップデートが行われ続け、操作画面の構成や設定できる項目が変わっていきます。そのような変化が生じる要素はオンライン上の公式ドキュメントに委ね、本書は「各サービスがどんな役割を果たすものか」という概要の説明に重きを置いています。
そのような作りになっているので、本書は「Azureでどんなことができるか、広く浅くざっくり知りたい」という方に向いていると思われます。

広く浅くではなく、たとえば「AIを利用したWebアプリケーションをデプロイしたい」といった具体的な要件を既にお持ちの方もご安心ください。本書の4章ではいくつかの例を取って具体的な構成を解説しています。アーキテクチャ全体を見て、構成する要素となる各サービスの解説を3章で確認し、公式ドキュメントで具体的な設定を学ぶ、そんな逆引き的な使い方も可能だと思います。

各章でどんな内容が解説されているかは上記の技術評論社のサイトをご確認ください。項レベルのタイトルまで書いてあるので、記載されてる内容のイメージが付きやすいと思います。

# 地図が付いてます
本書の物理本を手に取っていただくとわかりやすいのですが、折り込み付録（という表現で合ってるのかな）として以下のものが付属しています。

- 本書内の記載内容の関連
- 用語のワードマップ
- Azureリソースの管理構造の図
- 認定資格の推奨ロードマップ

本書のタイトルどおりまさに地図といった趣きなので、購入された方はぜひ広げて眺めてみてください。

電子版を購入された方は以下からダウンロードできるみたいです。

https://gihyo.jp/book/2025/978-4-297-14903-1/support

# 本書のカバー範囲
本書ではWebアプリケーション関連のサービスだけでなく、データ分析やIoT、VDI（仮想デスクトップ基盤）といった領域までカバーされています。

Azureは広範な機能を備えたクラウドで、様々な場面での要求に対応できるサービスを有しています。とはいえ、ユーザーとしての目線で言えば「どんなことができるか」がわかっていないとピンと来ないのも事実です。Azureの入門として、本書を読んで「できること」の概観を掴むというアプローチは有用だと思います。

お仕事で使っていると、自分が関連しない領域のサービスを把握するのはなかなか難しいですよね。こういった解説書をきっかけに知識を付けておくといつか役に立つ日が来るはずです。Azureをお使いになるのであれば、ぜひ広い領域に興味を持って、うまくクラウドを使いこなせるようになっていただきたいと思います。

# サポートサイト
技術評論社のサイトからもリンクされていますが、以下のGitHubリポジトリがサポートサイトとなっています。

https://github.com/07JP27/az_km_support

現時点では正誤表と、書籍内でカバーできなかった「発展したアーキテクチャ」についてが掲載されているようです。本書を読み進める際に合わせてご参照いただくとよいのではと思います。

# おわりに
特にAzure初心者の方や、自分が触っている範囲外のところに知識を広げたい方におすすめの書籍です。

著者のみなさま、執筆お疲れ様でした！
プリザンターとNode-REDで開発エージェントをつくっている

昨日からプリザンターとNode-REDで開発エージェントをつくっています。

## プリザンター

オープンソースの業務アプリケーションです。最近使い始めたばかりですが、驚くほど機能豊富です。ワークフローという自動化処理が気にいっています。


![Screenshot 2025-05-19 at 23.51.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79562/fe195cac-296b-4638-b2c5-e54818f5cc93.png)

![Screenshot 2025-05-19 at 23.51.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79562/301df277-7f7e-4c01-8369-b36494ca60ad.png)

## Node-RED

ノードベースのローコードツールです。高速でPoCするためにバックエンドとして使っています。定期実行も可能で、十分な機能を備えています。

![Screenshot 2025-05-19 at 23.51.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79562/c73eaf57-420a-434c-8d69-5fc24a60b4f8.png)


## 開発エージェントのしくみ

どういうものかと言うと、プリザンターに作られたタスクをNode-REDからAPIで取得します。タスクのステータスが「レビュー」未満の場合、タスクをGemini APIに投げます。Geminiにはツールを提示しており、必要に応じてツール実行します。いまはGithubからファイルを読むツール、新しくブランチを作成し、変更をプッシュしてプルリクエストするツールを備えています。

Geminiによるタスク実行が終了するとステータスが「レビュー」になるのでユーザーが見直し、必要に応じて指示を追記してステータスを差し戻すと再びNode-REDの定期実行でタスクが実行されます。


## 今後の展望

100日後にdevinを自作する！
ある日突然動画ファイルのアップロード時に Out of Memory が発生するようになった

# 問題

これまでは問題なかったが、ある日突然 Chrome で動画ファイルをアップロードしようとすると以下のように Out of Memory が画面に表示されるようになった。

![SnapCrab_NoName_2025-5-19_22-55-41_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502582/3ca5c6ae-0534-473d-975a-c714106e310f.png)

# 調査（環境）

ここ最近、ということでちょうど最近 Chrome の CVE 対策でブラウザのバージョンアップがあったことを思い出した。 そのため、記事執筆時点の最新版（Chrome 136）と、ちょうど手元にあったひとつ前のバージョン（Chrome 135）で比較したところ、前者のみこのエラーが発生した。
また、Chrome 135 を最新化して同様のオペレーションを行うと、同様に問題が発生したので、問題は最新版の Chrome であると突き止めた。

同時に、Edge で実施しても、Edge 136 で同様の問題が発生したため、この問題は Chronium の問題かと考えられる。

# 調査（ソースコード）

今回はローカルのファイルを読み込み、それを S3 に分割アップロードする仕組みで問題が発生した。
その時のコードは以下のようになっていた。

```javascript
export async function readPartData(index, fileBlob) {
  const offset = index * FILE_CHUNK_SIZE;
  const slice = fileBlob.slice(offset, offset + FILE_CHUNK_SIZE, fileBlob.type);
  const buffer = await slice.arrayBuffer();
  const data = new Uint8Array(buffer);
  return {
    index,
    data,
  };
}
```

このコードの内、`new Uint8Array(buffer)` で問題が発生することまでを突き止めた。

更にいろいろなケースを探っていくと、動画ファイルのサイズが小さければこの状況でも正常にアップロードできる。 ということは、分割ファイル数に問題があるのか？ と捉えてみていくと、`FILE_CHUNK_SIZE = 47 * 1024 * 1024;` (47MB) の時は失敗して、46MB の時は成功することが分かった。 もともとは FILE_CHUNK を 100MB にしていたので、一定以上のファイルサイズの動画をアップロードする際にエラーが発生していた。

# Chronium 側の対応

これは以下で報告されている問題が Chromium 136 で顕現していると考えられる。

https://issuetracker.google.com/issues/415572399

処理の最適化のために Uint8Array で利用可能な最大サイズが 46,505,916 バイト（変更前は104,638,348バイト）になったことが原因らしい。

# 問題の対処方法

２種類の方法で対処可能。

1) そもそも Uint8Array を使わない：ファイルのアップロード（特に s3 への put）であれば、Uint8Array を使わずに buffer をそのまま返してもアップロードができる。 そのため、無駄な処理を行わないように Uint8Array を使わないようにすれば良い
2) 何らかの理由で Uint8Array を使う必要がある場合: チャンクを十分に小さく (例えば 32MB程度）にすれば利用できるので、チャンクサイズを制限して利用する


# まとめ

今回調査した結果、Uint8Array をソースコードで利用しないで処理の効率化ができることは分かったが、インスタンスの生成にそこそこ小さいメモリサイズでも制約があることを初めて知った。
同じようなタイミングで同じような問題に引っかかる人も多いかと思うので、この記事が修正の助けになれば幸いである。
Reactの超基礎1

# はじめに
1年前にやったreactを忘れてしまったので、基礎から思い出しをしました。
ハンズオン形式でと思ったのですが、思った以上に基礎的なものになってしまいました。
かなり勉強初期段階の方向けの資料になっております。

# 手順
## Step1　導入
### プロジェクトをViteで作成
```
npm create vite@latest my-lp-project -- --template react-ts
```

* プロジェクト名：my-lp-project（好きな名前でOK）
* フレームワーク：React
* バリアント：TypeScript

viteとはは下記サイトを参考にさせていただきました。
https://qiita.com/tomada/items/91c489e41a20a2fd11ea


### プロジェクトディレクトリに移動して起動
```
cd my-lp-project
npm install
npm run dev
```

### Emotionのインストール（CSS-in-JS）
```
npm install @emotion/react @emotion/styled
```

## Step2 Reactの基本文法
### HTMLを書く
```react
function App() {
  return (
    <div>
      <h1>Hello, React!</h1>
      <p>これはJSXで書かれたHTMLです。</p>
    </div>
  );
}

export default App;
```
**【ポイント】**
* HTMLのように見えるけど、JavaScriptの中で書くHTML風構文。
* タグは1つの親要素で囲む必要がある。

### Props
src/components/Greeting.tsxを作成。
下記を打ち込む。
```react
type GreetingProps = {
	name: string;
};

const Greeting = ({ name }: GreetingProps) => {
	return <p>こんにちは、{name}さん！</p>;
};

export default Greeting;
```
App.tsx
```react
import "./App.css";
import Greeting from "./components/Greeting";

function App() {
	return (
		<div>
			<h1>Hello, React!</h1>
			<Greeting name="太郎" />
		</div>
	);
}

export default App;
```
**【ポイント】**
* `name="太郎"`のように、親から子へデータを渡すのが props。
* Greetingコンポーネントは`name`という値を受け取って使えるようにする。

### State
```react
import { useState } from 'react';

function App() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <h1>Hello, React!</h1>
      <button onClick={() => setCount(count + 1)}>
        カウント: {count}
      </button>
    </div>
  );
}
```
**【ポイント】**
* `useState(0)`で状態を作成（今回は数値）。
* `setCount`を呼ぶと、画面が自動で再描画される。
* イベント（onClickなど）に関数を渡して動きをつけることができる。

## Step3 emotion（CSS）
```react
import "./App.css";
import styled from "@emotion/styled";

function App() {
	return <Box>これはスタイル付きのBoxです</Box>;
}

const Box = styled.div`
	padding: 16px;
	background-color: #f0f0f0;
	border-radius: 8px;
`;
export default App;
```
**【ポイント】**
* コンポーネント単位でCSSを適用できる。
* 同じデザインを複数箇所で使う時に便利である。
LeetCode #3024. Type of Triangle

# 【LeetCode #3024】Type of Triangle

## 問題概要
三角形を成す 3 つの数値が与えられるので，値によって下記のいずれかを返す．
* 3 辺が全て等しい = **equilateral**
* 2 辺が等しい = **isosceles**
* どの辺も等しくない = **scalene**
* 三角形が作れない = **none**

### 例
> **入力：** nums = [3, 3, 3]
> **出力：** "equilateral"

> **入力：** nums = [3, 4, 5]
> **出力：** "scalene"
 

### カテゴリ

問題難易度：easy
タグ：Array, Math, Sorting

## 解法：sort をして比較を単純に
まず，三角形が作成できるかを考えます．
3 辺が与えられて三角形が作成できるのは下記を満たす場合です．
3 辺の長さをそれぞれ $a, b, c$ とすると，
```math
\begin{align}
a + b > c  \\
a + c > b  \\
b + c > a
\end{align}
```
これは中学の数学で習うかと思います．
直感的には，
* a + b <= c の場合，a と b が繋がらない
* a + b == c の場合，ただの直線
となるためです．

これを用いて三角形が作成できるか判定し，できる場合はさらに細かく値を見ていく方針をとります．
ここで，前述の条件を満たすかについて，sort することで 1 つの条件で判定が可能になります．
sort をすることで，nums[2] が最大になるので，下記が満たされたら他の条件も満たされることになります．
```python
nums[0] + nums[1] > nums[2]
```
これを用いて実装したものが下記です．

```python
class Solution:
    def triangleType(self, nums: List[int]) -> str:
        a, b, c = sorted(nums)
        if a + b <= c:
            return "none"
        if a == b and a == c:
            return "equilateral"
        if a == b or a == c or b == c:
            return "isosceles"
        return "scalene"
```

## TypeScript
TypeScript では次のようになります．
```typescript
function triangleType(nums: number[]): string {
    const [a, b, c] = nums.sort((a, b) => a - b);
    if (a + b <= c){
        return "none";
    }
    if ((a === b) && (a === c)){
        return "equilateral";
    }
    if ((a === b) || (a === c) || (b === c)){
        return "isosceles";
    }
    return "scalene";
};
```

## まとめ
今回は三角形の 3 辺の長さによって返す文字列が変わる問題に挑戦しました．
簡単ですが，三角形が成り立つ条件を忘れているとちょっと困ってしまう問題だったかもしれません．
これを機に思い出しましょう！