OmniAICreator/Qiita-1.07M huggingface dataset:
panic!とrecoverable errorの分断



> _"すべてのエラーは同じではない。回復可能性が分けるのは、構造への信頼か、破壊かである。"_  

多くの言語では、「例外」はひとつの枠にまとめられ、**回復可能なものと致命的なものが混在**している。  
その結果、**どこで処理を止めるべきか／継続するべきかの判断がコード上で曖昧になる**。

Rustはこれに明確な境界線を引いた。

- **回復可能なエラー** → `Result<T, E>` で処理を設計に含める  
- **回復不能なエラー** → `panic!()` でプロセスを停止する

この分断は、単なる構文的選別ではない。  
**エラーを“扱うもの”と“止めるべきもの”に設計段階で分ける**という、構造的な誠実さの宣言である。

---

## panic!は「発生してはならないこと」を表明する構文

```rust
fn get(index: usize, values: &[i32]) -> i32 {
    values[index] // 範囲外アクセス → panic!
}
```

このようなコードは、安全な範囲チェックがなければ**実行時にpanicを発生させる**。  
Rustの哲学において、panicは「**設計上“絶対に起きない”と考えられていたが、起きてしまった例外**」である。

つまり、panicは**論理的保証の失敗であり、プログラムを続行すべきではないという判断**が静的に表明される。

---

## 回復可能性とは何か：その設計的意味

```rust
fn read_config() -> Result<String, std::io::Error> {
    std::fs::read_to_string("config.toml")
}
```

このように `Result` で返されるエラーは、「**発生し得るが、対処可能な事象**」として設計に組み込まれる。

例：

- ネットワーク切断  
- ファイルが見つからない  
- ユーザーの入力ミス

これらは、**「予想された異常」**であり、設計上「**エラーであっても処理を続行できる**」ことが求められる。

---

## panic!は「バグの発露」であるべき

Rustコミュニティの多くでは、`panic!` は「**到達してはならないコードへの到達**」を意味するものとして設計するべきとされている。

たとえば：

```rust
match some_enum {
    Known(v) => handle(v),
    Unknown => panic!("Unreachable: unknown variant"),
}
```

これは、「**設計上このパターンには到達しないはず**」という意志の表明であり、  
もしpanicが起きたならば、**設計者が見落としていた世界が存在した**ことになる。

---

## 例外を握り潰さない。panic!に意味を持たせる設計

多くの言語では例外を `catch` して無視することができる。  
Rustでは `panic` を捕捉することも可能だが、**それは最後の手段**であり、  
基本的には **「例外が起きないよう設計する」** ことが大前提となっている。

Rustにおいて「catchする」という行為は、**設計の再考を促すサイン**である。

---

## 回復可能性の設計責任を、設計者に返す

例外があると、「失敗しても誰かがなんとかするだろう」という設計の他人任せが生まれる。  
Rustでは、`Result` を返す設計者が、**「ここは失敗する可能性がある」と明示的に言語化する**必要がある。

これは、**意図のないエラー発生を未然に防ぎ、責任の所在をコードに刻む行為**である。

---

## panic!に頼るとき、それは構造的敗北の兆しである

`unwrap()` や `expect()` は `Result` や `Option` を強制的に展開する。  
しかしこれは、**エラー処理をスキップしてpanic!に委ねる危険なショートカット**である。

```rust
let content = std::fs::read_to_string("file.txt").unwrap(); // panicのリスク
```

このようなコードが許されるのは、**“失敗する可能性が設計上存在しない”と確信したときだけ**である。

それ以外で使えば、**設計の信頼性を破壊する毒に変わる**。

---

## ユーザー体験としてのpanicの扱い

- GUIアプリケーションでのpanicは、エラーメッセージと共に**ユーザーの操作中断**となる  
- サーバーサイドでは、panicがプロセスをkillするため、**意図的に境界で分離（e.g., thread::spawn）される**

つまり、Rustにおいて `panic!` は、**アプリケーションの終了を設計に組み込む構文**でもある。

それは、**システムが「壊れてはいけない」箇所における“破壊の設計”**なのだ。

---

## 結語：panic!は恐怖ではなく、設計責任の証明である

Rustは例外を捨てた。しかし失敗の可能性を捨てたのではない。  
むしろ、「失敗を構文で責任として定義せよ」という思想に転換した。

`panic!` とは、その責任を明示できなかった場合の**最終的な設計上の敗北点**である。

それを避けるために、設計者はあらゆる失敗を `Result` で表し、**処理可能な構造へと昇華させる**必要がある。

> _"panicは設計者の敗北ではない。設計に対して誠実であろうとした意志の証である。"_
Resultとエラー設計：例外なき世界の責任



> _"例外が許されるということは、設計者がエラーを曖昧に扱ってもいいという合意である。"_  

多くのプログラミング言語において、エラーは「例外」として扱われる。  
それは、関数の振る舞いとは独立した、特殊な“割り込み的構造”だ。  
try-catch-finally、throw、raise——それらは**予測されない振る舞いを「あとから包み込む」構文**だった。

Rustはこのパラダイムを拒絶する。  
Rustが提供するのは、**例外なき世界**であり、**「エラーもまた値である」という構文的真理**である。  
この章では、Rustにおける `Result<T, E>` を中心に、**例外のない設計がなぜ誠実なのか**を掘り下げていく。

---

## Result<T, E>：エラーもまた“構造化された状態”である

```rust
enum Result<T, E> {
    Ok(T),
    Err(E),
}
```

この定義において重要なのは、**「成功」と「失敗」が同等に扱われている**という点だ。  
片方は正常系、片方は異常系という“感情的”な扱いではなく、  
**どちらも「起こりうる状態」として設計段階で定義される。**

そして、呼び出し元のコードはそれを**必ず扱わなければならない**。

```rust
match do_something() {
    Ok(value) => println!("Success: {}", value),
    Err(e) => eprintln!("Error: {}", e),
}
```

これにより、**「エラーを考慮しない」という設計上の怠惰が、構文レベルで許されなくなる**。

---

## エラー処理が“設計の責務”としてコードに現れる世界

例外ベースの言語では、関数のシグネチャに**「この関数が例外を出すか否か」**が書かれていないことが多い。  
Rustでは `Result` の戻り値がそのまま**エラー可能性の契約**となる。

```rust
fn read_file(path: &str) -> Result<String, std::io::Error>
```

この関数は、「失敗する可能性がある」ということを**構文として示している**。  
**関数と設計の責任が一致している**のだ。

---

## “投げる”のではなく、“返す”ことが信頼を生む

例外はコントロールフローを破壊する。  
どこでthrowされたか、どこでcatchされるかは**しばしば不透明な階層をまたぐ**。

対してRustの `Result` は、常に「返される値」として文脈に残る。  
それは、**制御の流れを壊さず、エラーを明示的に文脈へと渡す構文**である。

```rust
fn process() -> Result<(), String> {
    let data = load_data()?; // 詳細は次章で扱う
    validate(&data)?;
    Ok(())
}
```

このように、**エラーは制御不能な事象ではなく、“処理の帰結”として返される**。

---

## Result型は「振る舞いのすべてをコード化する」構文である

Resultを使うということは、「この関数がどういう世界を扱っているか」を明示することだ。

- 成功する場合はどうなるか  
- 失敗した場合は何を返すか  
- それに対して、呼び出し側は何を選ぶか

これは**設計思想を“分岐可能な構文”へと翻訳する行為**である。

---

## 組み合わせ可能な失敗：map / and_then による関数合成

`Result` はただの構文的保険ではない。  
それは、関数型的な合成が可能な、**失敗を伴う計算の文脈**でもある。

```rust
fn double(x: i32) -> Result<i32, String> {
    if x > 100 {
        Err("Too large".to_string())
    } else {
        Ok(x * 2)
    }
}

fn transform(val: Result<i32, String>) -> Result<i32, String> {
    val.map(|x| x + 10)
}
```

これは、**文脈を保ったまま処理を連鎖させる**という設計美を持っている。

---

## “無視”を許さないという強さ

例外ベースの言語では、例外をcatchしなければプログラムが落ちる。  
それゆえ、開発者はcatchを入れるが、**何を捕まえているのか明確でないことが多い**。

Rustでは、`Result` を扱わないとコンパイルが通らない。  
**“失敗を考慮しない設計”が物理的に存在できない**。

それは強制ではない。  
**設計に対する誠実さの最小単位**なのだ。

---

## Result型は「予測不可能性の構文的可視化」である

世界は予測できない。  
ファイルは消えるし、ネットワークは落ちるし、入力は破損する。

`Result<T, E>` は、その予測不可能性を「構文に昇華する」手段である。  
それは**“壊れることがある”という現実を、設計に組み込む思想**である。

---

## 結語：例外のない世界は、設計者の誠実によって成立する

Rustの `Result` は、ただのテクニカルな手段ではない。  
それは、「失敗とは設計すべき構造である」という言語からの哲学的メッセージだ。

例外を廃し、結果を明示的に返す構文。  
それによって、開発者はエラーに対して責任を持つ。  
そしてその責任こそが、**設計に信頼をもたらす唯一の根拠**である。

> _"失敗を隠すな。それを構文に取り込み、設計に正直であれ。"_
implブロックの設計的責任：拡張性と封印



> _"型とはただの形ではない。振る舞いを宿す容器であり、責任を閉じ込める構造である。"_  

Rustにおける `impl` ブロックは、単に「メソッドを定義する場所」ではない。  
それは、**型に対して意味と責任と振る舞いを明示的に付与する構造的枠組み**である。

そしてこの構文は、**「どこまで開き、どこまで閉じるか」という設計判断の要約**でもある。  
拡張性と封印――これは、システム設計における永遠の対立軸だ。  
Rustの `impl` は、その二項対立を構文の中でバランスさせる。

---

## implとは「型の振る舞いを受け持つ場所」である

```rust
struct Circle {
    radius: f64,
}

impl Circle {
    fn area(&self) -> f64 {
        std::f64::consts::PI * self.radius.powi(2)
    }
}
```

この構文が意味するのは、「Circleという型が、面積という概念を理解している」ということ。  
つまり、**型と振る舞いの対応関係を、構文レベルで明示している**。

ここで `impl` は、**ただの構文ではなく、“意味を設計に閉じ込める”装置**として機能している。

---

## implは「どこに責任を置くか」を決める構造

Rustでは、関数をどこに定義するかは**単なる好みではない**。  
それは、「この処理はどの型の責任か？」という**設計的判断**の反映である。

- グローバル関数：責任が外にある（例：処理は外在化される）  
- impl内関数：型の責任として内在化される（例：処理の意味が型に属する）

この選択が、**設計の読みやすさ、保守性、再利用性に直結する**。

---

## implとトレイトの違いは「何に基づいて振る舞うか」

- `impl StructName { ... }` → **具象型に対して直接定義された振る舞い**  
- `impl Trait for StructName { ... }` → **“振る舞いの型”としての定義**

```rust
trait Drawable {
    fn draw(&self);
}

impl Drawable for Circle {
    fn draw(&self) {
        println!("Drawing a circle.");
    }
}
```

これは「CircleがDrawableであるということを型レベルで表明している」ということ。  
そして `impl` がその**表明と責任の境界**を規定している。

---

## implの分割は「責務の分離」そのものである

Rustでは、同じ型に対して複数の `impl` を定義できる。

```rust
impl Circle {
    fn radius(&self) -> f64 {
        self.radius
    }
}

impl Drawable for Circle {
    fn draw(&self) {
        // ...
    }
}
```

この設計は、**型そのものに属する振る舞い**と、**文脈に応じたインターフェース的振る舞い**を明確に分けることができる。

結果、**意味的モジュール性**が向上し、構造が読みやすくなる。

---

## implの公開範囲は「型の外部契約を決める鍵」

```rust
impl Circle {
    pub fn radius(&self) -> f64 { ... }       // 外部から使える
    fn compute_something(&self) -> f64 { ... } // 内部でしか使えない
}
```

このように、**関数の可視性（public/private）を制御できる**ことで、  
`impl` ブロックは**「型が何を他者に公開するか／内部に隠すか」という契約空間**になる。

設計者は、「何を隠し、何を開くか」を構文で表現しなければならない。  
それが設計という営みの本質だ。

---

## impl内でのデフォルト構築：`impl Struct { fn new(...) }` という慣習

Rustでは `new()` メソッドを `impl` に書くことで、**構造体の構築パターンを明示**する。

```rust
impl Circle {
    fn new(radius: f64) -> Self {
        Self { radius }
    }
}
```

これは、「どうやってこの型を安全かつ意図通りに作るか」を**設計者が明確にコントロールするための機構**である。

- 型そのものの設計
- 構築方法の制御
- 振る舞いの制限

すべてが `impl` ブロック内で結びついている。

---

## implによる拡張性と封印性のトレードオフ

Rustでは、`impl` を用いた拡張が強力である一方で、**孤立した実装が他者から再利用できない**ことがある。  
これは安全性の代償でもある。

- **他人の型に対してトレイトを実装することはできる**  
- **他人の型にメソッドを追加することはできない**

この制約が生むのは、**拡張における責任と境界の明示**である。  
つまり「設計者以外が構造を汚染しない」ための封印でもある。

---

## 結語：implは構造と振る舞いの“封印と開示”である

Rustにおける `impl` ブロックは、単なる「関数定義の場所」ではない。  
それは、**意味を閉じ込める構造であり、責任を可視化する構文であり、拡張と封印を同時に成立させる設計空間**である。

そしてそれは、「設計とは何か？」という問いに対して、Rustが与えた**静かで強い答え**である。

> _"設計とは、型に振る舞いを与え、構造に責任を宿すことである。implはその最前線にある。"_
AtCoder Beginner Contest 402 C - Dislike Foods

# [C - Dislike Foods](https://atcoder.jp/contests/abc402/tasks/abc402_c)
問題文は👆を確認してください

# 導入
atcoderで精進してますが、  
どこかにアウトプットしたかったので、qiitaに書くことにしました。  
ACしてから載せるようにしてますが、考え方が至っていない点があればご指摘頂けると幸いです。  
また、誰かの参考になると嬉しいです。

# 使用しているアルゴリズム
貪欲法
(必要最小限の状態更新を貪欲にやる)

# 解法のポイント
この問題の肝は、**毎日克服される食材が、どのメニューに影響するのかを効率よく調べること**です。  
NG実装のように毎日すべてのメニューを調べていると計算量が爆発してしまいます。

改善点は以下の通り：

- 食材→メニューのマッピングを `defaultdict` で保持（逆引き）
- 各メニューの「残り必要素材数」をカウント形式で保持し、0になったら達成済みとする
- これにより、毎日見るべきメニューを限定し、全探索を回避

---

# NG実装例

```python
N, M = map(int, input().split())

menus = []
for _ in range(M):
  menu = list(map(int, input().split()))
  menus.append((menu[0], set(menu[1:])))

menus.sort()
days = list(map(int, input().split()))
oks = set()
completes = [False] * M

for i in range(N):
  oks.add(days[i])
  for i, (k, menu) in enumerate(menus):
    if completes[i]:
      continue
    elif i + 1 < k:
      break
    if menu <= oks:
      completes[i] = True
  print(sum(completes))
```

### ❌ NG実装の問題点
- **menus.sort()** によるソートと break 判定の組み合わせが不自然かつ効果が薄い
- 毎日、すべてのメニューを1つずつ確認している（O(N×M×M)）ため、データ量が増えるとTLE必至
- 食材を克服したときに「関係あるメニューだけ更新する」構造になっていない

---

# ACサンプル（改善後の実装）

```python
from collections import defaultdict

n, m = map(int, input().split())

menu_requirements = []  # 各メニューが必要とする素材数
ingredient_to_menus = defaultdict(list)  # 素材 → 使用しているメニューのインデックス

for menu_index in range(m):
    menu_info = list(map(int, input().split()))
    k = menu_info[0]
    menu_requirements.append(k)
    ingredients = menu_info[1:]

    for ingredient in ingredients:
        ingredient_to_menus[ingredient].append(menu_index)

days = list(map(int, input().split()))
completed_menus = 0

for ingredient in days:
    for menu_index in ingredient_to_menus[ingredient]:
        menu_requirements[menu_index] -= 1
        if menu_requirements[menu_index] == 0:
            completed_menus += 1
    print(completed_menus)
```

### ✅ 改善点まとめ
- 各素材に関係するメニューだけを更新
- `menu_requirements` を使って、素材を1つ克服するたびに O(I) だけの処理で済む
- 全体で O((N+M)×I) まで計算量を抑えられる

---

# リンク
[ACサンプル集(アルゴリズム逆引き)](https://www.notion.so/motonao/1cc8aca4381b80f39713ddb52fa85e8f?v=1cc8aca4381b80519654000c236bb8d6&pvs=4)
ワーキングアグリーメントを作ってみました

# はじめに
わたしのチームは現在[スクラムガイド](https://scrumguides.org/docs/scrumguide/v2020/2020-Scrum-Guide-Japanese.pdf)をがっつり読み込んで、「基本に忠実に」をモットーにしたスクラムにチャレンジしています。
スプリントゼロと呼ばれるスクラム準備期間でインセプションデッキを作り、その過程で出会ったのが『ワーキングアグリーメント』という概念でした。
「 **チームメンバー全員が気持ちよく働くための約束事** 」というもので、これはぜひチームメンバー全員ですり合わせながら決めたい！とおもいミーティングを設定して実践したのが今日のことです。（HOT!）
作っていく過程がたのしかったという日記です！

# 作り方

[こちらのページ](https://www.agile-studio.jp/post/apm-working-agreement)を参考にさせていただきました。

1. チームメンバー全員で観点を洗い出す
1. チームメンバー全員各自で観点ごとに約束事の案を書く
1. それぞれ「これいいね」「明示しておきたい」「ルールとして書くならこういう文章にしたい」などなどを話し合い、決める
1. ひとまとめにして見やすい場所（Notion）に貼る

ブレストにはみんなだいすきスプレッドシートを使いました。
黄色いセルは案出ししてすり合わせ後、採用されたものです。
![スクリーンショット 2025-04-24 15.12.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3947757/6cbaa7bb-6f00-4b74-8005-d9f3f9592126.png)


# できたもの！
## ❤️ マインド・スタンス

- HRT（「Humility（謙虚）」、「Respect（尊敬）」、「Trust（信頼）」）を大切にしよう
- 感謝を伝え合おう 🤝🏻
- 初めてのことも苦手なことも挑戦していこう 💪🏻
- 最後まであきらめない 👊🏻
- 成功も失敗もチームのものととらえよう 👯
- チームの一人でも知らない情報・ノウハウがあるなと思ったら
    - 自分が知らない → 積極的に拾いに行こう
    - 自分が知ってる → 共有の機会を設けよう

## 👥 コミュニケーション

- メンバーの発言に対してリアクションしよう
    - meetでのリアクションは2割増しで！
- 勇気を持って発言しよう
- 困ったら相談しよう
- 朝来たらメンバー全員に聞こえる声で挨拶しよう
＋ちゃんと挨拶に反応しよう

## 💻 働き方

- 朝はデイリースクラムまでに始業しよう
- 出勤前・休憩中・退勤後・お休み中はslackに反応しなくてもいい
「働く」と「休む」のメリハリつけよう！
- 残業前提で予定を組まない
- 健康でいる、体調悪いときは無理しない！
- ちゃんと打刻していまの勤怠状況を共有しよう

## 💬 会議について

- 始まりも終わりも時間を守る！
- ファシリテータは持ち回りにしよう
- ファシリテータが責任を持って会議を進めよう
- メンバーも時間通りに終わらせる意識を持とう
- 話しすぎない、聞きすぎない。会議に積極的に参加しよう！

## 👁️ 見える化

- やりとりはSlackのオープンな場で、
なにかを残したいときもNotionなどのオープンな場で。
（プライベートチャンネルやマイドライブは✕）
- 情報はNotionから辿れるようにしよう
- 口頭で話したこともちゃんと見える場所に記録しておこう
- 未来の自分、未来のメンバーのためにも記録を残そう

## 今後の管理
月に一度&メンバーの増減があったとき、全員で見直しを行う

# 作ってみて

気持ちのいい約束ができたなと思いました！
何よりチームメンバー全員でブレストして決めていく過程で、それぞれ「こういうことを大事にしたい」という価値観がお互い話せてよかったです。
「勇気っていいよね」「スクラムの価値基準だしね」とか「あきらめないっていいよね」「挑戦していくしね」「やめるときはちゃんと考えてからみたいなね」などなど。

作成した後すぐに、meetでちょっと反応が薄いときに「リアクションは2割増しでおねがいします笑」「あっそうですよね！笑」などのやりとりもあったりして、リアルタイムでチームの雰囲気に変化が出たこともおもしろく嬉しい出来事でした。

実施するにあたってネット上のサンプルをいくつか見てるだけでも色が見えておもしろかったので、この記事（日記）を見て作った人もぜひアップしていただければな〜とおもいます！
Next.jsのプロジェクトとSupabaseのプロジェクトをリンクさせる方法

Next.jsとSupabaseのプロジェクトは作成している前提で話を進める。

### 1. Next.js プロジェクトに Supabase クライアントをインストール
```bash:ターミナル
npm install @supabase/supabase-js
```
### 2. Supabase クライアントを作成
app/supabase/supabase.ts に以下を記述する
```typescript:supabase.ts
import { createClient } from '@supabase/supabase-js'

const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!

export const supabase = createClient(supabaseUrl, supabaseAnonKey)
```
### 3. 環境変数を .env.local に設定
プロジェクトフォルダ直下に.env.localを作成し、以下を記述
``` .env.local
NEXT_PUBLIC_SUPABASE_URL=https://xxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```
Supabaseのプロジェクトにアクセスし、
Project Settings -> Data API から Project URL、anon public key を取得する。
NEXT_PUBLIC_SUPABASE_URL に Project URL、
NEXT_PUBLIC_SUPABASE_ANON_KEY に anon public key をペーストする。

.env.local は Git 管理対象外にしておく。（ .gitignore に追加する。）
「豆腐のサイズの種類を教えて下さい。県によって異なりますか。」AI先生に聞きました。

**・回答もwikipediaも 面白すぎる?ので、回答省略。**
・(本日の)ChatGPT先生は、なかなか私の言う事?を聞いてくれません。
# (本日の)ChatGPT先生へ
```
# 質問リスト
1. 豆腐のサイズの種類を教えて下さい。県によって異なりますか。  
2. 掘り下げお願いします。  
3. 私の質問をMarkdown形式でリスト化して出力して。Markdown形式でリストからアスタリスクは削除して。1行目に、# 質問リスト の文字を出力して。最後の質問も追加して下さい。追番を追加して下さい。Markdown形式で。  
4. 私の質問をMarkdown形式でリスト化して出力して。Markdown形式でリストからアスタリスクは削除して。1行目に、# 質問リスト の文字を出力して。最後の質問も追加して下さい。追番を追加して下さい。Markdown形式で。
```

# Gemini先生へ

# Copilot先生へ

# いつもの? sympyの実行環境と 参考のおすすめです。

https://qiita.com/mrrclb48z/items/b6351b48e47bcf6265c0

# いつもと違うおすすめです。
### wikipedia
Place of origin	China　＜ English版

https://en.wikipedia.org/wiki/Tofu

https://ja.wikipedia.org/wiki/豆腐

https://ja.wikipedia.org/wiki/Category:豆腐

### Qiita内

https://qiita.com/mrrclb48z/items/f144b4c495827a503421
VSCodeで等幅フォントを使っても、一部記号などのマルチバイト文字を使うとインデント文字数がずれる理由

## 問題

VSCodeでは等幅フォントを使っても、一部のマルチバイト文字を使うとインデント文字数がずれる。
たとえばインデント文字数4で、以下のようになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92354/1a30995c-b3f5-4ff7-bd64-74b6e6a5082f.png)

- 半角「A」や全角「Ａ］の後に「タブ」「B」を入力した場合、 **4文字目までインデント** されて次の5文字目に「B」が表示される。
- 全角「α」の後に「タブ」「B」を入力した場合、 **5文字目までインデント** されて次の6文字目に「B」が表示される。（インデント文字数がずれる）


※ちなみに、ずれているのは「インデント文字数」であり、フォントが原因の位置ずれは発生していない。
全角「Ａ」「スペース2文字」「B」と打った場合と、全角「α」「スペース2文字」「B」と打った場合で、「B」が表示される横位置は完全に一致する。

## 原因

### ギリシャ文字や数学記号は内部的には1文字幅として扱われているのが原因

VSCode（VSCodeのエディタ部分として採用される高機能なブラウザベースのコードエディタのMonaco Editor）は、「Ａ」や「漢字」、「全角カタカナ」は2文字幅と認識されるのに対し、「α」や「■」などのギリシャ文字や記号は1文字幅と認識している。
つまり「α」は見た目は全角に見えても内部的には半角（1文字幅）扱いされてるため、タブ位置計算がずれてしまう。

### なぜギリシャ文字や数学記号は1文字幅と認識されるのか

そもそも「文字幅」というものは、シングルバイト文字は1文字幅、マルチバイト文字は2文字幅と単純に決まるものではない。
Unicodeでは各キャラクタに East Asian Width (EAW) という「文字幅のヒント」プロパティが定義されており、VSCodeはこの定義で文字幅を判定している。

- Wikipedia: East Asian Width (EAW)
  https://ja.wikipedia.org/wiki/%E6%9D%B1%E3%82%A2%E3%82%B8%E3%82%A2%E3%81%AE%E6%96%87%E5%AD%97%E5%B9%85

「α」等はこのプロパティが「Ambiguous; 曖昧」と定義されており、東アジア環境では2文字幅、欧米環境では1文字幅に見えることがある文字とされている。
つまり「α」は日本語環境では全角に見えるが、OSやフォント次第で半角に見える可能性がある。
そしてVSCodeでは欧米環境を優先するために、この Ambiguous な文字を常に「1文字幅」扱いにしている。

## 対策は無い　※対策をご存知の方が居ればご教示ください

これは日本語で VSCode を動かすときのために、Ambiguousを2文字扱いにするような機能があれば解決する筈ではある。
しかしどうもAmbiguousを1文字扱いするのはエディタコア機能で、簡単には変更できないらしく「α」を2文字扱いする設定や拡張機能は存在しない。

一応、Ambiguousを2文字扱いするパッチはあるようだ。
https://github.com/laurent22/joplin/commit/45c73f79629a91108a1366c6e50771e67110d85a
https://github.com/laurent22/joplin/issues/2674

**結論としてはVSCodeではエディタのコア機能で「α」や「■」などは1文字扱いされているため、それを2文字扱いでインデントを入れることは出来ない。**
……ということになる。
（Ambiguousを2文字扱いするようコード変更してビルドしたVSCodeを使えば別だが）

----------

うーむ、ここ数年の検索しても解けなかった疑問だったがChatGPTがこの記事の７割くらいの内容を答えてくれた。
この子、賢すぎる。
codex CLIでCodex GUIを実装してみた

# codex CLIでCodex GUIを実装してみた
GitHub リポジトリ: 
https://github.com/HimizuNoa/Codex-GUI

OpenAIの提供するcodex CLIを活用し、Electron + Reactベースのデスクトップアプリ「Codex GUI」を実装しました。本記事では、プロジェクトの背景、アーキテクチャ、主要な機能、技術的ハイライト、そして今後の展望について解説します。

## 背景

- コマンドラインツールの利便性を保ちつつ、より直感的なGUI操作を実現したい
- コード生成やdiff表示、セキュリティレビューを一連の開発ワークフローとして統合したい
- Electronでクロスプラットフォーム対応し、ReactとChakra UIでモダンなUIを構築したい

## プロジェクト概要

- **リポジトリ**: https://github.com/HimizuNoa/Codex-GUI
- **ライセンス**: MIT
- **技術スタック**:
  - Electron (Main process)
  - React + Vite (Renderer process)
  - Chakra UI (デザインシステム)
  - child_process.spawn (codex CLI実行)
  - keytar (APIキー管理)
  - diff・code-reviewユーティリティ

## アーキテクチャ

1. **Main Process** (`main/index.js`)
   - `ipcMain.handle('run-codex', ...)` でCLIをspawn
   - `child_process.spawn` による codex CLI 実行、stdout/stderrをストリーミング
   - `saveFilesFromOutput`でコードフェンスからファイルを抽出し、作業ディレクトリに保存
   - `shellScanner` と `promptScanner` による安全性検証
   - keytarでAPIキーを安全に永続化

2. **Preload Script** (`main/preload.js`)
   - `contextBridge`でIPCをブラウザに公開
   - `window.electron.invoke('run-codex', ...)` を可能に

3. **Renderer Process** (`renderer/src/App.jsx`)
   - `ChatPanel`コンポーネントでプロンプトとbot応答をチャットUI表示
   - `Progress`インジケータで生成進捗を可視化
   - 保存されたファイルをファイルブラウザに反映
   - `SettingsModal`でCLIフラグやLLMモデル名を設定可能

## 主な機能

### 1. プロンプト実行（spawn-based flow）
```js
// main/index.js
const { spawn } = require('child_process');
ipcMain.handle('run-codex', async (_, { prompt, mode }) => {
  const cli = path.resolve(__dirname, '../vendor/codex-cli/bin/codex.js');
  const child = spawn(cli, ['--quiet', mode, prompt], { cwd: workingFolder, env: { OPENAI_API_KEY: apiKey } });
  child.stdout.on('data', chunk => mainWin.webContents.send('run-log', chunk.toString()));
});
```

### 2. Diffビューア & インタラクティブ編集
- `diff`パッチを解析し、ファイルに適用可能
- Monaco Editorと組み合わせたプレビューモードを実装

### 3. 自動セキュリティレビュー
- `codeReviewer`サービスでOpenAIを呼び出し、生成コードの脆弱性を検査
- レビュー結果をモーダルで表示し、適用前に確認可能

### 4. 設定管理 & プロンプト履歴
- Electron StoreでCLIオプション（モデル、temperatureなど）を永続化
- プロンプト履歴のリスト表示 & 再実行機能

## 技術的ハイライト

- **`node-pty`フォールバック**: Ink TUI互換のため試行しつつ、標準`spawn`へ安全に戻す
- **`saveFilesFromOutput`**: 出力中の```javascript```ブロックを自動抽出してファイル化
- **Streaming UI**: `useToast`と`Progress`フックでユーザー体験を向上
- **Vite最適化**: `manualChunks`設定でバンドルサイズを抑制
- **E2E IPCテスト**: `__tests__/runCodex.e2e.test.js`でハンドラ動作をモック検証

## 今後の展望

- Monaco Editorの統合による高度なコード編集機能
- プロンプトインジェクション対策フローの強化
- プラグイン機構 & アクセシビティ強化

## おわりに
> **追記**: 本プロジェクトのコードおよびこの記事の文章は、すべてcodex CLIを用いて生成・執筆されました。

Codex CLIのパワーを直感的なGUIで扱うことで、プロンプト開発やコード生成のワークフローを大幅に効率化できます。OSSとして公開していますので、ぜひフィードバックやPRをお寄せください。
  
**プロジェクトURL**: https://github.com/HimizuNoa/Codex-GUI
授業料無料のアメリカのオンライン大学のコンピューターサイエンス学部での経験

###### まず初めにバックグラウンド：現在やっていること
・受託の開発案件
・自主開発多数　モバイルアプリからシステム基盤　その他
・書類の作成　※多岐に渡る
・UoPeople ２コース履修　毎週木曜スタート
・Hack the Box / Hack the Box Academyでハッキングの学習
・ZTMなどでThree.JSやそのほか必要なことを学ぶ

これ１週間でうまく回している。



## 授業料無料のUoPeopleに入学してから
#### 入学に必要なこと
- 高校卒業の英語の証明書　または　高卒認定（大検）
※卒業した高校もしくは証明書の英文での発行依頼
- 英語力　TOEICや英検、英語力の証明がない場合は英語の授業から
- とにかくやる気

私の場合は、高校中退の大検取得なので両方の書類を英文で高校と文科省に依頼。英語はTOEICはしばらく受けていなかったのでDuolingo Test
https://englishtest.duolingo.com/applicants
で英語能力を証明。

#### 授業料無料だが、完全無料ではないので注意
授業料は基本無料です。でも、コース毎にFinalExamのあたりで＄120ほどかかります（しかし、返済不要の奨学金制度もあり。条件付き）

#### 初めてみての感想
思いの外、毎週のアセスメントがやっぱり多いよねw アメリカだぁ。
そんなわけで、私は１度放棄しましたw
仕事と家事といろんな両立がしんどい・・・というか無理だった。

・毎週決まったチャットでのディスカッション。返信も3件がマスト
・レポート類　APA形式で書かないとならない
・クイズ　これは特に問題ない
・プログラムを書くこと　決まったプログラムとデバッグ、そのプログラムについての学術的見解←何それw

#### リベンジ戦略
単位移行の道を選択。
もちろん、私は単位なんぞ持っていない。
使ったのはCourseraとSophiaというサイト。
https://www.coursera.org/
https://app.sophia.org/

CourseraではGoogleの資格を主に6つほど取得。
その中から関わる単位を移行できる。
Sophiaはちょっと高いけれど、コースを取るよりも低負荷で単位が取れて移行ができる。

何より、単位移行はそんなにかからない。時間もお金もコスパがいいかも？

#### 首の皮一枚の復学
今は５Term（学期）休んでしまったから、退学になりそうになり復帰。
取らなきゃいけないコースが自動でEnglish Conposition２。
　CS学部といえど、必須に加えて一般的なコースや選択コースで120単位の取得が必要。

 そんなわけで、4月から急遽忙しい中戦々恐々としながら無謀にも２コース同時チャレンジ。

#### English Composition２と心理学入門
あまりやる気のない英語のコース。興味のある心理学。
やってみたら・・・・

何？すげー学べるじゃん！楽しい！
アセスメントは全部APAになっているが教材やトピックが面白い。

知的好奇心を満たしてくれる神サービス！

#### 効率のいい学習法
Notionを使い倒す！

Chat GPTに内容をぶち込んで要約してもらう。
全てNotionにまとめる。

資料動画（主にTEDなど）は全部見る
レポート概要だけを作り、一旦AIで文章を作り、さらに自分で付け加える。
最後にGrammaryを使用してスペルチェック

実はこれ木曜スタートで金曜（1日）にはほぼ終わらせてます！！！

###### 今後の計画
またコースが終わった時点で一旦Sophiaで単位を取得しつつ、心理学の分野と数学をスタサプを使いつつ再学習しコースへ挑む。

### 結論
  - 効率さえ良くできれば、可能になる！
  - 隅々まで学ぶことはやめる（完璧は求めない）
  - できるだけ使えるツールを利用する
  - 効率よく、しかし自分の人生に役に立ちそうな情報はしっかり整理
  - さらには学歴コンプの私が大卒になれるチャンス（笑）
  - 何より、CSだけでなく色々な分野の知見が増える

正直、Hack the Boxも簡単ではないので、時間がかかるのでうまく時間を確保すること、そしてどのように学習しているのか、どうやって解決したのかを開発においてもなんでもとにかくドキュメント化しておくのはとても最近効果的だと感じました。

また別の投稿で他のトピックに触れていきたいと思います！
表示データを問い合わせformに入力 → 表示データが画面に表示

# 完成画面

![スクリーンショット 2025-04-24 18.51.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628823/df59dc42-c723-4675-abcc-d08c5255b2d8.png)


### 問い合わせフォームで入力されたデータ: fruit_name

```ruby:app.py
 <input type="text" name="fruit_name" placeholder="フルーツ名を入力">
```
### 問い合わせformのデータを取得

```ruby:app.py
input_text = request.form.get("fruit_name", "")
```

### 結果を表示用変数 "mix"に代入、代入できてなければエラー表示
```ruby:app.py
if input_text in fruits:
            mix = input_text
        else:
            mix = "not found"
```
<br>

### データ送受信　テンプレ(POSTとGET両方つかう)
```ruby:app.py
@app.route("/", methods=["GET", "POST"])  
    # 処理
```

### 表示したいdataの変数と、結果表示用変数をreturnで準備
```ruby:app.py
return render_template("index.html", fruits=fruits, mix=mix)
```

### 表示したいdataを、最初に定義

```ruby:app.py
app = Flask(__name__)

fruits = ["ストロベリー", "メロン", "大福", "オレンジ", "パイナップル"]
```

### htmlにdataを表示するとき、空配列"mix"をset

```ruby:
def index():
    mix = ""  
    
    # 処理
```

## code 全文

```ruby:app.py
from flask import Flask,render_template,request

# Flaskオブジェクトの生成
app = Flask(__name__)

fruits = ["ストロベリー", "メロン", "大福", "オレンジ", "パイナップル"]

@app.route("/", methods=["GET", "POST"])
def index():
    mix = ""  # 最初に mix を空で定義（これが重要）
    if request.method == "POST":
        input_text = request.form.get("fruit_name", "")
        if input_text in fruits:
            mix = input_text
        else:
            mix = "not found"
    return render_template("index.html", fruits=fruits, mix=mix)
```

```ruby:run.py
from app.app import app

if __name__ == "__main__":
    app.run(debug=True)
```

```ruby:index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>フルーツ検索</title>
</head>
<body>
  <h2>フルーツ一覧</h2>
  <ul>
    {% for fruit in fruits %}
      <li>{{ fruit }}</li>
    {% endfor %}
  </ul>

  <h2>問い合わせフォーム</h2>
  <form method="POST">
    <input type="text" name="fruit_name" placeholder="フルーツ名を入力">
    <input type="submit" value="送信">
  </form>
  
  <p>選ばれたフルーツ：{{ mix }}</p>
  
</body>
</html>
```
【Android/Kotlin】並列通信で401エラーになった場合、トークン更新&再通信

# はじめに

Androidの並列通信で401エラー時にトークン更新&再通信する処理について解説。

# 前提

通信時、Okhttp3を使用していること。


# 方法

## 401エラー検知

`Authenticator.authenticate()`メソッドを使用することにより、401エラー時の処理が記述可能

## 並列通信時、トークン更新を1回だけにする

- `@Synchronized`アノテーションにより、他通信と同期させる

- リクエストしたトークンと現在のトークンを比較して、同じだったらトークン更新していないとみなし、トークン更新を行う。異なっていたらすでにトークン更新しているとみなし、再通信を行うようにする

# コード

```Kotlin
OkHttpClient.Builder()
    .authenticator(object : Authenticator {
        @Synchronized
        override fun authenticate(route: Route?, response: okhttp3.Response): Request? {
            // ここにトークン更新処理を記載
        }
    })
    .build()
```

トークン更新処理については[こちら](https://note.com/naka_inc/n/n21b9357ef7b0)に記載。

https://note.com/naka_inc/n/n21b9357ef7b0


# 参考サイト

公式リファレンス:

https://square.github.io/okhttp/3.x/okhttp/okhttp3/Authenticator.html

https://stackoverflow.com/questions/77203433/how-to-prevent-parallel-refresh-token-requests-while-using-retrofit-okhttps-aut

https://qiita.com/Horie1024/items/dec5ec6508f8fc5aea3f
AWSサーバ障害に学ぶ安全なインフラ設計

先週AWSサーバに障害が起きいくつかのサービスがストップする、
アクシデントがありました
[15日のAWS東京リージョン障害、原因は「主電源と2次電源の遮断」](https://www.itmedia.co.jp/news/articles/2504/17/news155.html)

興味深いことに、同じサーバを使っていてもストップしたサービスと
そうでないサービスがあり、そこから安全なインフラ設計が浮き彫りとなっていました

## 結論
結論からいくと、この2点がAWSサーバ障害を見据えた設計となります
詳細は下で深堀していきます
・マルチAZの設計をせよ(3AZ以上)
・コンテナ化して、サービス復帰を早くする

## 詳細
#### マルチAZのサービスが落ちたのはなぜか?

:::note info
マルチAZとは
サーバの構成に複数のデータセンタ(AZ: Availability Zone)を用いること
データアクセスの分散を図り、安定した通信をおこなうことができる
:::

マルチAZの設計をせよと上で述べていますが、実はマルチAZのサービスでも
落ちていました

共通していたのは2AZで構成されていたサーバで、実は複数のAZのトラフィックを
分散するAWSの機能「ロードバランサー」(ELB)が最低でも2つ設定する必要があり、
2AZのうちの片方がダウンしたことでロードバランサーに障害が起きていました

2AZで構成することで片方がつぶれても安全かと思いきや、
その実1AZと変わらなかったという残念な結果に...

そのため3AZ以上にすることで、片方のAZが落ちてもロードバランサーダウンによる
サーバー落ちを防ぐことができます

#### コンテナ化していたサーバはなぜ復帰が早かったのか
サーバー復旧にかかる時間には、コンテナ化の有無が関わっていたようです

障害があったAZにインスタンスを固定していると、コンテナ化していなければ
バッチや実行環境を移すのに時間がかかってしまいます

しかしコンテナ化していれば、サーバを切り替えてコンテナを実行すれば
実行環境をうつすことができるため、復帰が早かったようです

また「AWS Fargate」で運用しているサービスは自動復帰することができたようです
Fargateはサーバ管理をAWSに任せてコンテナを実行できるサーバレスのサービスのため、
サーバを自動的に切り替えることができたのでしょう
論理和( OR )の基本 |

今回はPaizaの「OR演算」問題で、条件分岐を封印して論理和をスマートに書く方法を学んだ！

## <br>🧩 問題概要
入力で 0 または 1 の整数 A, B が与えられます。
「A OR B」の結果を出力せよ、という内容。

例）
入力: `0 1` → 出力: `1`
入力: `1 1` → 出力: `1`

「OR（論理和）」は、どっちかが 1 なら 1 を返すルール。
<br>
https://paiza.jp/works/mondai/logical_operation/logical_operation__basic_step2

## <br>🙅‍♂️ NGコード
```js
if (A === 1 || B === 1) {
  console.log(1);
} else {
  console.log(0);
}
```

## <br>✅ OKコード
```js
const [A, B] = input.split(' ');
console.log(A | B);
```
ビットOR演算子 `|` を使えば、条件分岐なしで「論理和」がそのまま表現できる。
<br>
<br>
```js
0 | 0 → 0

0 | 1 → 1

1 | 0 → 1

1 | 1 → 1
```

## <br>💡 ポイントまとめ
- `|` はビット演算子、論理和に使える
- `||`（論理演算子）と混同しないこと！
- `if`文を使わずスッキリ処理 → 可読性UP
- 入力が 0/1 に限定されてる場合は積極的に使いたい



<br><br>[僕の失敗談と解決話！](https://paizabeginner.wordpress.com/2025/04/24/paiza%e3%81%a7%e5%9f%ba%e6%9c%ac%e3%83%9e%e3%82%b9%e3%82%bf%e3%83%bc%ef%bc%9a%e8%ab%96%e7%90%86%e5%92%8c-or-%e3%81%ae%e5%9f%ba%e6%9c%ac/)
🎉✨ 初心者向けJava学習 ✨🎉



みなさん、こんにちは 韓国在住のsanaです！

今日は木曜日ですが、一週間あっという間な気がします私だけでしょうか…（笑）

Python学習したけど、Javaは難しそうで初められない…と悩んでいる方！
webアプリやソフトウェアの開発をしようと考えている方！

初めてJavaを学習する方でも簡単に取り組めれるJavaおすすめ講座を２つ紹介します:woman_tone1:


:one: 全講義を見ても３時間！ 雷のように早いスピードでJavaが学べる！

Javaの基本的な文法だけでも、たいていのプログラムはいくらでも作れます！Java学習を始める最初の一歩におすすめの動画です！


https://u.inf.run/42YLgbo


:two: Javaプログラミング講座

S/W開発者を目指している方必見の講座で、

・Java言語によるオブジェクト指向の概念

・Javaプログラムの設計能力と実装能力

・Javaサポートツールを使用したデバッグおよび開発能力

・ストリーム、ネットワーク、GUI、並行性、データベース学習

が学べます！　この講座は無料なので試していてください！

https://u.inf.run/3EJ6WyP


今日もお疲れ様でした　アンニョン～:sparkles:
Go学習記録4日目　レスポンスタイムを計測するCLIツールの作成②

Go言語学習の4日目です。

今日は昨日作成したWebサービスのレスポンスタイムを計測するCLIツールを改良しました。

https://qiita.com/rickeysan95/items/d4ec765977bcb392f295

### Golangの正規表現とリストのインデックス
コマンドライン引数の引数として、"https://"で始まっているかをチェックしたいと思い、正規表現で確認するようにしました。regexpライブラリを使って実装しました。PHPと同じように実装できたので、特に迷うところはありませんでした。

また、引数に複数のURLを入れることが出来るようにしました。URLという構造体のリストを作成し、その中に正規表現で確認したurlを追加するようにしました。
また、リストの参照の仕方をもう少し勉強しないといけないと思いました。

1).スライスのインデックスは0から始まる
2).3番目以降を取り出すには、``` numbers[2:] ```と記述する
3).8番目までを取り出すには、``` numbers[:8] ```と記述する

おそらく一般化すると、以下のようになるでしょうか？
numbers[x:]と書くと、x番目のインデックスは含む。
numbers[:x]と書くと、x番目のインデックスは含まない。

```
	// 適切なURL(https://から始まっているかをチェック)
	re := regexp.MustCompile(`^https://`)

	for _, arg := range os.Args[1:] {
		if re.MatchString(arg) {
			urls = append(urls, URL{Url: arg})
		} else {
			fmt.Printf("%sは不正なURLです", arg)
			return
		}
	}
```


### 次回の課題
今日は複数の引数を取って、正規表現で引数をチェックするまでで終わってしまいました。明日こそ、goroutineを使って、複数URLを並行チェックできるようにしたいです。
[エラー対応]Recoil はやめたほうがいいという教訓

## はじめに
ゆかっしゅです。
2021年に事務職からデザイナー/コーダーにジョブチェンジをし、現在はフロントエンドエンジニアにスキルアップするべく、モダンフロントエンドを学習しています。

今回はRecoilを使用して出たエラーについて備忘録として記録します。
RecoilとはReactの状態管理ライブラリです。
有名なReactの状態管理ライブラリはReduxというものがあります。

## エラー内容

```
Uncaught TypeError: Cannot destructure property 'ReactCurrentDispatcher' of 'import_react.default.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' as it is undefined.
    at currentRendererSupportsUseSyncExternalStore (recoil.js?v=af0bd706:359:5)
    at useRecoilValueLoadable (recoil.js?v=af0bd706:3390:26)
    at useRecoilValue (recoil.js?v=af0bd706:3400:20)
    at useRecoilState (recoil.js?v=af0bd706:3425:11)
    at Users (Users.jsx:29:35)
    at react-stack-bottom-frame (react-dom_client.js?v=d1b16516:17422:20)
    at renderWithHooks (react-dom_client.js?v=d1b16516:4204:24)
    at updateFunctionComponent (react-dom_client.js?v=d1b16516:6617:21)
    at beginWork (react-dom_client.js?v=d1b16516:7652:20)
    at runWithFiberInDEV (react-dom_client.js?v=d1b16516:1483:72)
```

## 原因
私のズッ友「Chat GPT」君に聞いてみるとどうやら原因はReactのバージョンにあるようです。

https://zenn.dev/nappa/articles/56df3129f2592b

Recoil は React 19では使用できず、今後アップデートもされないかも...という記事を発見しました。

## 対応
Reactをv18にダウングレードすれば使用できましたが、今後行く末が怪しいのでRecoilの学習はやめておこうと思います。
やはりReduxを勉強する他ないのか....
GitLabのssh-key登録一連

## GitLab-ssh-keyの登録作業

クローンするに当たって、ssh-keyの設定が必要になったりしたので以下にまとめ。

### 2.ssh-keyの作成→取得

```bash
ssh-keygen -t ed25519 -C "your_email@example.com"

```

出力1→そのままenter

```
Enter file in which to save the key (/home/yourname/.ssh/id_ed25519):

```

出力2→そのままenter

```
Enter passphrase (empty for no passphrase):

```

作成完了。その後、出力1に記載されていたパスにアクセス。

```bash
cd /home/yourname/.ssh/

```

catコマンドで、ssh-keyを表示→出てきた値をcopy

```bash
cat ~/.ssh/id_ed25519.pub

```

### 2.ssh-keyをgitlabに登録

2.1 Edit profileを開く


2.2 SSH keysを選択→Add new key をクリック

![2025-04-23_17h49_39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627370/27509696-9335-4704-b514-5350fc822d72.png)

2.3 先ほどコピーしたものを張り付ける。
![2025-04-23_15h19_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627370/3093df59-e785-4157-b73a-55bdf62b723a.png)
表示担当app.pyと動かす担当run.py

# ディレクトリ構造

```ruby:pフォルダ
├app/
 │　├templates/
 │　│　└index.html
 │　├static/
 │　└app.py
 └run.py
```

# 表示担当 app.py

```ruby:
from flask import Flask,render_template

# Flaskオブジェクトの生成
app = Flask(__name__)


# 「/」へアクセスしたら、"Hello World"表示
@app.route("/")
def hello():
    return "Hello World"


# 「/index」アクセスしたら、「index.html」表示したい
@app.route("/index")
def index():
    return render_template("index.html")
```

# 動かす担当 run.py

```ruby:run.py
from app.app import app

if __name__ == "__main__":
    app.run(debug=True)
```

# NomoduleError： 表示担当と動かす担当にmainが二つ

```ruby:app.py
if __name__ == "__main__":
    app.run(debug=True)
```

```ruby:run.py
if __name__ == "__main__":
    app.run()
```

# endifがないと表示される

![スクリーンショット 2025-04-24 16.21.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628823/735cfdae-0e1e-4054-aadb-27b90308d9be.png)

問題code
![スクリーンショット 2025-04-24 16.23.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628823/6e2b5f3e-a7bf-4f0f-adb6-f1e6378e7515.png)


### 変数名がfalseだった時エラー

![スクリーンショット 2025-04-24 17.55.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628823/fead3ffd-aae9-406a-aef3-25881ca6b0ab.png)

![スクリーンショット 2025-04-24 17.56.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628823/3e3077c5-d1cc-4575-b7f6-fad4a57a92f5.png)

![スクリーンショット 2025-04-24 17.58.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628823/ad03c85d-c115-4a44-aeb2-37f537fb984b.png)







# 勉強サイト

https://qiita.com/usaitoen/items/0184973e9de0ea9011ed

https://msiz07-flask-docs-ja.readthedocs.io/ja/latest/tutorial/index.html
Yanagawa_Yoshihisa Qiita 記事まとめ

# この記事の目的

Qiitaの記事数が増えてきており、一部の記事は更新済みですが、一部は情報が古くなってしまっています。そこで、皆様にご参照いただけそうな記事を整理し、このまとめページを作成しました。情報検索の際にお役立てください。

記事は概要把握や個人とトライアル利用の参考として、まとめたものなので、プロジェクトでの利用の際は、SAP社への問合せの実施や正式情報である[Help Portal](https://help.sap.com/docs/)を活用して下さい。

# 記事一覧

## シリーズ記事

大きめのテーマを数回に分けて解説しています。

- [**SAP Business Technology Platform (BTP)の基本的なことのまとめ**](https://qiita.com/Yanagawa_Yoshihisa/items/bea677d3b851f6604d0d)
    - [SAP BTPの歴史と現在の位置付け](https://qiita.com/Yanagawa_Yoshihisa/items/41ff8300c74a42147690)
    - [SAP BTPのアプリケーション概要](https://qiita.com/Yanagawa_Yoshihisa/items/af1f187980493ebf0642)
    - [SAP BTPのサービス提供のイメージ](https://qiita.com/Yanagawa_Yoshihisa/items/9b78f80c1fe4c4951004)
    - [SAP BTPのインフラ概要](https://qiita.com/Yanagawa_Yoshihisa/items/073dc9723c50f463d2a6)
    - [SAP BTPの情報の調べ方](https://qiita.com/Yanagawa_Yoshihisa/items/9940b1e0c525682944fb)
    - [SAP Business Technology Platform (BTP) の認定資格](https://qiita.com/Yanagawa_Yoshihisa/items/0cb22bc7e35296854c3d)
----
- [**SAP Side by Side開発の基本的なことのまとめ**](https://qiita.com/Yanagawa_Yoshihisa/items/4dd3694800576e094b0a)
    - [なぜ「Side by Side開発」を実施するのか？](https://qiita.com/Yanagawa_Yoshihisa/items/233992b6f3d759e43c1b)
    - [S/4HANAにおける追加要件の実装手段の整理](https://qiita.com/Yanagawa_Yoshihisa/items/b324316ef3c3ac9ff0d9)
    - [アーキテクチャ的な特徴と「In App開発」との違い](https://qiita.com/Yanagawa_Yoshihisa/items/fd6b4efca5925e148c61)
    - [｢Side by Side開発｣をBTPにて実施するメリット](https://qiita.com/Yanagawa_Yoshihisa/items/0a60f527117f8f0d4837)
    - [｢Side by Side開発｣と｢Composability｣](https://qiita.com/Yanagawa_Yoshihisa/items/67872cf58a57db99fbb4)

## 個別記事
- [｢SAP Build｣の基本的なことのまとめ](https://qiita.com/Yanagawa_Yoshihisa/items/207a935049707aeca672)
- [｢CDS View｣の基本的なことまとめ](https://qiita.com/Yanagawa_Yoshihisa/items/d1b601a9f37101b4fde0)
- [何がすごいの｢OData｣](https://qiita.com/Yanagawa_Yoshihisa/items/c0143ac499429ff75a05)
【EC-CUBE4.3】Chatwork API連携プラグインのご紹介

## はじめに
EC-CUBEのプラグインについて知識を深めるのと、ChatworkのAPIに興味があったので、ついででChatwork API連携プラグインを作ってみました。
その特徴と仕様を下記にまとめます。（ChatGPTまとめ）

---
## 📌 概要

このプラグインは、EC-CUBE4.3とChatworkを連携させることで、以下の機能を提供します：

- お問い合わせや注文完了時にChatworkへ通知を送信  
- 通知内容、ルームID、APIキーを管理画面から設定可能  
- Symfony HttpClientを使用してChatwork API v2を呼び出し  

## ✅ 主な仕様

| 項目             | 内容                                                                 |
|------------------|----------------------------------------------------------------------|
| 通知トリガー     | お問い合わせ（MAIL_CONTACT）および注文完了（MAIL_ORDER）             |
| 送信先           | 指定されたChatworkグループチャット（Room ID）                         |
| 通知内容         | 件名、送信者、本文を含むテンプレートメッセージ                         |
| API連携          | Chatwork API v2（トークン認証）                                       |
| 設定項目         | APIキー、ルームID、通知のON/OFF切替                                   |
| 安全設計         | 通知失敗時はログに記録し、ユーザーには影響を与えない設計             |
| テスト機能       | 管理画面から接続テスト、ルーム情報取得、テストメッセージ送信が可能   |

## 🧩 構成

- **Entity** : `Config.php`（APIキー、ルームID、通知ON/OFFの設定）
- **FormType** : `ConfigType.php`（設定フォームの定義）
- **Controller** : `ConfigController.php`（設定画面の制御）
- **Service** : `ChatworkApiService.php`（API呼び出しと通知処理）
- **EventListener** : `Event.php`（メール送信時のフック処理）
- **ナビゲーション追加** : `Nav.php`（管理画面メニューへの追加）

## ✉️ 通知メッセージフォーマット

通知メッセージは以下の形式でChatworkに送信されます：

```
件名: {件名}
送信者: {送信元のメールアドレス}

本文:
{本文}
```

例：

```
件名: 商品についての問い合わせ
送信者: user@example.com

本文:
商品Aの在庫はありますか？
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3850968/a9ecf198-321b-4c2d-94fd-c17721c997ec.png)


## 🛡️ 通知失敗時の挙動

通知処理中にエラーが発生した場合でも、ユーザーには影響を与えず、ログにエラー情報を記録します：

```php
try {
    $this->chatworkApiService->notify('お問い合わせ通知', $body);
} catch (\Throwable $e) {
    $this->logger->warning('[ChatworkApi] 通知失敗: ' . $e->getMessage());
}
```

## ⚙️ 管理画面からの接続テスト機能

管理画面には以下のテストボタンが用意されています：

- 接続テスト（`/v2/me`）
- ルーム情報取得（`/v2/rooms/{room_id}`）
- テストメッセージ送信（`/v2/rooms/{room_id}/messages`）

## 🎨 管理画面UI

- `c-toggleSwitch`を使用した通知ON/OFFの切替スイッチ
- Bootstrapベースのフォームレイアウト
- 管理画面ナビゲーションに「Chatwork API 設定」を追加

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3850968/471126af-8edd-4f78-a0a0-7ef0b37f45c5.png)

## 🔗 関連リンク

- [Chatwork API v2 リファレンス](https://developer.chatwork.com/reference/get-me)
- [EC-CUBE4 プラグイン開発ドキュメント](https://doc4.ec-cube.net/plugin_index)
- [GitHubリポジトリはこちら](https://github.com/to19960425/eccube-chatworkapi)

## 🙌 最後に
もしよければご自由にご活用ください。
改善案やフィードバックなどありましたら、コメント欄でぜひ教えていただけると嬉しいです 😊
Astroでファイルパスを相対パスにしてビルドする

Astroでbuildしたファイルを納品したら、「あのー、パスを全部相対パスにしてもらえますか？」と言われました。

さすがにconfigファイル設定しなおせば、それくらいできるだろと思って調べたら、そんな設定ない。
過去に機能改善の提案はあったようだが、今ではissueもクローズになっている。
Vercelなどのホスティングサービスで使われることを前提に設計されているため、手動でサーバーに置き、元々あったほかのファイルと共存するようなこと考慮されていないようだ。

おいおい、全置換して手動で直すのか？CSSの中の画像パスならまだしも、HTMLはいろんな階層あって一発じゃいけないぜ？そう思って現実逃避するように調べていくと…

神ツール現る！！！

# astro-relative-links
https://www.npmjs.com/package/astro-relative-links

## インストール
```zsh
npm install astro-relative-links
```

## configファイルの設定
```javascript
// astro.config.mjs

import { defineConfig } from 'astro/config';
import relativeLinks from 'astro-relative-links';

export default defineConfig({
  // ...
  integrations: [relativeLinks()],
});
```

## コマンド
```zsh
npm run build
```
※npmスクリプトの設定を変えている人はそれに合わせてbuildコマンドを実行

---

これだけでbuildされたファイルすべてのパスを相対パスに変換してくれます。

第2階層、第3階層もそれぞれに合わせたパスに、CSSの画像読み込みも相対パスにしてくれます。

ただしルート相対パスと共存し一部だけを相対パスに変えたいということはできないので注意。
そのほか、HTMLを同階層のファイル名でページ分けする（`example.html`など）場合も`index.html`以外は、一つ下の階層（`/example/index.html`扱い）にされてしまうようなので注意が必要そうです。

それでも導入のハードルは低く、別コマンドの必要もないので、Astroでつくりたいけど相対パスで納品が必要なときには、これを使うだけで解決できるのでとても便利です。

# 参考
[Astro でリンクや参照などを相対パスでビルドする](https://zenn.dev/ixkaito/articles/astro-relative-links)
[Astroでビルド時に絶対パスではなく相対パスで出力する【HTML/CSSデータ納品】](https://it-web.jp/post/astro-relative-links/)
 [HTML で納品するときは、Astro を使うといい](https://izanami.dev/post/bb7f7ee2-6de9-4c12-9b0d-bff730d2993d)
qiita初投稿を鬼教官ChatGPTにフルボッコにしてもらった話

# はじめに
初めての技術記事を書いてみたけど、あれは読者のためになっているのか...
と思い、ChatGPTに**鬼指導教官**になってもらって甘えた内容を容赦なくぶった切ってもらい、プロ品質の記事へ鍛えなおしてもらいました。

この記事では、ChatGPTに初めてのブログを添削してもらい、得られた改善のポイントとその意図を公開します。
同じように「文章の質を上げたい！」と思っている方の参考になれば嬉しいです。
※本記事はChatGPTの出力をもとに筆者が加筆・修正を行い作成しています。

# 想定読者（あなたです）
・読みやすくて伝わる文章に仕上げたい方
・技術ブログで「自己満足」と「読者ファースト」の違いを知りたい方
・ChatGPTを“鬼指導教官”として活用したい方

# ダメ出ししてもらった文章はこちら
[Qiita](https://qiita.com/yic011817/items/b6da0ad7620cc784613b)


# 主なダメ出しとプロンプト
修正は複数回行ってもらいました。
自己満・自分語りの記事であるため、読者ファーストの記事を作成せよとのことでした。

プロンプト↓
「鬼指導教官になって、あらゆるダメ出しとその修正案を示してください」
「もっと厳しくお願いします」
「完全プロ品質の技術ブログ風テンプレに仕上げて」

# :innocent: 公開処刑場
### 甘すぎる出だし
元記事「初めまして！masuです。~」

❌ **「誰の何の役に立つ記事なのか」が1秒で分からない。**
技術ブログには、読者は情報を探しに来ている。問題と解決方法を提示するべき。

✅ 修正案：なぜこの問題が重要かを述べる。
MediaPipeを用いたラジオ体操の動作解析において、「腕を振って足を上下に曲げ伸ばす運動」における肩の開き具合を角度で可視化する方法を検討しました。内積によるアプローチでは不正確だったため、外積＋`atan2`を用いて正確に求める手法を提案します。

技術ブログだからと甘く見てました。卒研発表でも似たような修正をされた記憶が蘇ります。

### 手法選択の選択理由の説明がない

❌ **「なぜこの計算が必要か」の説明がない**
外積使ったらよさそうだったのでやってみました！ではダメ。
書くならなぜそれが有効かを掘り下げるべき。

✅ 修正案
ラジオ体操の「腕を振る動き」において、**肩の開き具合を角度で表現**したい場合、2本のベクトルを使った角度算出が必要になります。
しかし、単純な内積では角度の絶対値しかとれないため**腕が肩より上に来たときの角度が正しく取れない**問題がありました。
それを解決するのが、**「内積＋外積＋atan2」**の合わせ技です。

ベクトルを正規化してから内積（cosθ）・外積（sinθ）を求めることで、2D平面上の角度θを`atan2(sinθ, cosθ)`で一発で求められます。これにより、肩より腕が上がるなどの複雑な動きでも、**向き付きで角度を捉えることが可能**になります。

「外積使ったらいけそうなのでやってみました！」→まんま見透かされて悲しくなってきます。

# 角度の定義が曖昧すぎる

元記事「肩と腕の角度を測りました！」

❌ 「肩と腕の角度」といっても、**どの面で？どの関節で？** が曖昧だと伝わらない。

✅ ベクトル定義の明示が必須
右肩(SR)→左肩(SL)をx軸とみなし、右肩→右ひじのベクトルがx軸からどれだけ開いているか（肩の開き角度）を、2次元平面上で求めます。

調べたところ、肩関節の可動域は様々種類がありました。これでは、医学系の方々や教授からどの角度？と言われてしまいますね。
![スクリーンショット 2025-04-24 152859.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4062951/748f72ee-b8cf-40b8-b09d-6c2226030c6a.png)
https://www.jsfr.jp/download/info/2021/20211129_03.pdf

# まとめは「行動につながる一言を！」

❌「参考になる部分があれば幸いです」←ふわっと終わる
得た知見を端的にまとめ、読者に「自分もやってみようと思わせる」ものがまとめ。

✅ 修正案
**MediaPipe × ベクトル角度計算のポイント**

- 肩の開き角度は、2本のベクトル（肩→肩、肩→ひじ）で定義できる！
- 内積・外積を組み合わせて atan2 で角度算出 → **180°超えにも対応可能**！
- ベクトルは必ず**正規化**（単位ベクトル化）してから使う！

次回はこの角度情報を使って、ラジオ体操の腕の振り方の良し悪しを分類してみたいと思います！

# 読者ファーストの章立てに

❌ 論文と同じく「背景 → 問題 → 解決策 → 実装 → 結果」の流れで説明すると読みやすい！

✅ 構成例
・はじめに
・背景と目的
・MediaPipeでの関節座標の取得方法
・ベクトルから角度を求める方法（内積 vs 外積）
・Python実装と解説
・なぜ外積＋atan2が有効なのか
・まとめと今後の展望

# 締めの文章もダメ
❌「ご意見お待ちしております」←フワッとしすぎて伝わらない

✅ 構成例
この記事が役立った・面白かったと思った方は「いいね」やコメントで教えてください！
また、MediaPipeやChatGPTを使った他の解析例や改良アイデアがあればぜひ共有してください。

youtubeの締めの決まり文句みたいだと思いましたが、しっかり視聴者に寄り添った文言だったんですね。

# 結論　読者ファーストとは
読者が欲しい情報を負担なく理解できるようにすること。

・自分の経緯ではなく、**問題の経緯**を述べる。
・**解決策を最初**に述べる
・用語や手順は**読者の知識レベル**に合わせる
・図解、コード、例で**直感的**に理解できる工夫をする
・読んだ後に**行動のきっかけ**がある

👹鬼教官からひと言
「読者ファーストって、優しさや丁寧さじゃない。
**相手の時間を奪わない設計力**と、**本当に欲しい情報を届ける洞察力**だ。」

# 本記事のまとめ
読者ファーストの視点、使いこなすにはかなり時間がかかりそうと感じました。
ChatGPTが読者ファーストになるように添削してくれるし別に使えなくても...？と思いましたが、人と話すときにはそうはいきませんね。
このようなアウトプットの場を通して、相手ファーストの説明ができる人に少しでもなっていこうと思います。
当面の目標は、鬼教官ChatGPTに褒められるよう頑張ります。
この記事が参考になった方は、ぜひ自分の記事を鬼教官に添削してもらってみてください！想像以上にフルボッコにされて、めちゃくちゃ学べます！（読者に自分もやってみようと思わせるのがまとめらしいので）
最後までお読みいただきありがとうございました。シリーズ化しようかな。
Cybergear Debuggerのセットアップ

1．[ダウンロードページ](https://kpan.mioffice.cn/webfolder/ext/3UN9fi%24e4us%40?n=0.28807380192881804)に行って説明書に記載されているコードである**QDD1**を入力

2．上位机软件.zipをダウンロード
3．解凍して、中のCyberGear调试器の**i18n**フォルダの中にある**zh_CN.qm**ファイルを削除
これをすることでソフト内言語が中国語から英語になる
4．CyberGear调试器_20231101.exeを実行
TrustedInstaller...って何?

# はじめに
　自作のPCを普段使いしており、2年ほど前にSSDを増設。Cドライブに加えDドライブがPCに搭載された。けど別に容量が無いわけでもないから使ってなかった。←いやなんでやねん
 
　ところが今あらためて確認すると使ってないはずのDドライブがなぜかパンパン。当時どんな操作をしていたのかわからないが、増設時のCドライブの中身をすべてDドライブにコピーしていたみたい。
　Dドライブの中身を見ると`User`とか`Program File`とか挙句の果てには`Windows`とか入ってやがった。  
 
　Windowsを支えているのはCドライブでDドライブはただのコピー。特に参照もされてない捨てドライブになってた...
　なんで増設した2年前の自分。

消しても問題ないか不安だけど、Dドライブの全ファイルを消していく。空にしてもいいんだよね...?やりきったうえで今のところ正常に動いているからいいよね。うん

# 環境と状況整理
- windows11
- SSDが搭載されているPCに新たにSSDを増設。
- 増設した方のドライブにもともとあったものをおそらく全コピーしちゃった。バックアップの設定とかかな
# TrustedInstaller...?
　ファイルを消す方法は普通に管理者権限で消すだけ。しかし問題が。
 削除しようとするとこんなエラーが出るファイルが...
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3363422/58719841-8a9c-34f0-6dfb-a2afb550aeb8.png)

TrustedInstaller...?なにそれ

調べてみると管理者のさらに上の権限のよう。このファイルの所持者がTrustedInstallerで今の自分の権限はAdministrators。なるほどむりですね。

## TrustedInstallerファイルの消し方
　消すためにはファイルの所有者をAdministratorsに変えたうえで権限を自身に権限を付与する必要があるのだそうで。

　やりかたはプロパティを開いてセキュリティのなんたらかんたら...........とかなりめんどくさい。しかもフォルダにもファイルにも個別に変更をしていかないといけない。[参考url](https://www.ipentec.com/document/windows-delete-file-owned-by-trusted-installer)

　こんな操作は普通はめったにすることもないのでこのやり方で一つづつ慎重にすればいいのだが、今回は何万というファイルがこのTrustedInstallerによって握られている。許せない

　消していいことは事前にしっかり確認したうえで、コマンドで一括削除してやった。
```PowerShell
takeown /F "D:\PAth" /R /A #所有者を変更
icacls "D:\Path" /T /grant Administrators:F #権限を付与
Remove-Item -Path "D:\Path\*" -Recurse -Force #削除
```
まちがえてCドライブ(大事なファイル)を選んでしまうとすべてが吹き飛ぶので注意♡
やるなら自己責任で...
ちなみにこれはPowerShellコマンドプロンプトならDELとかRMDIRとかかな。

# おわりに
　あきらか重要なファイルを消しているのでずっと不安なままです。バックアップにしてはやり過ぎな気がするが、自分が無知なだけでこれが普通なのかわからない。有識者の人教えていただけるとありがたいです。もう手遅れですが。
　同じように過去の自分自身の変な過ちで消せない大量のファイルがストレージを圧迫しているのなら消してみるのもいいかもしれない。
　ただこんなに厳重になっているということはPCにとってめっちゃ大事なファイルなんですよね。消すときは慎重に!!!
SPA、SSR、SSGの違い

## SPA（Single Page Application）
1つのHTMLページから成り立っており、URLが変わってもページ全体の再読み込みは発生せず、JavaScriptで画面の一部だけを切り替える仕組み

### 使用例
- Gmail
- Google Maps
- Notion
- Slack（Web版）

### 代表的なフレームワーク
- React
- Angular
- Vue.js

### メリット
-  一度読み込めば、ページ遷移がスムーズ
-  フロントエンドとバックエンドを分離しやすい（API通信だけで済む）
-  JavaScriptのフレームワーク（React、Vue、Angular）との相性がよい

### デメリット
- 初回読み込みが重い（JavaScriptやデータを一気に読み込むため）
- SEOが苦手（検索エンジンがJavaScriptをうまく解釈できないことがあるため）

※ SEO：Googleなどの検索エンジンで自分のサイトが上位に表示されやすくするための工夫

## SSR（Server Side Rendering）
ユーザーがWebページにアクセスしたときに、サーバー側でHTMLを生成してからブラウザに送る仕組み

### 動き方
1. ユーザーがページにアクセスします（例：`https://example.com/products`）
2. サーバーが必要なデータを取得し、HTMLを生成します
3. 生成されたHTMLをそのままブラウザに返します
4. ユーザーは完成したページをすぐに見ることができます
5. その後JavaScriptが読み込まれ、ページが動的になります

### 使用例
- Amazon
- Netflix
- Next.js公式サイト（動的記事など）

### 代表的なフレームワーク
- Next.js
- Nuxt.js

### メリット
- SPAと比べて初回表示が速い（読み込んだ瞬間にHTMLが完成してる）
- SEOに強い（検索エンジンがHTMLをそのまま読める）

### デメリット
- アクセスごとにサーバー処理が発生し、サーバーに負荷がかかる
- 表示が完了するまでにAPI通信の待ち時間がある（動的データを取りに行く必要がある）
- クライアントだけで完結しないので、サーバーが必要


## SSG（Static Site Generation）
予め静的なHTMLファイルを生成し、リクエスト時、ユーザーに返す仕組み

### 動き方
1. ビルド時（＝本番公開の前）に、データを使ってHTMLを生成します
2. 出来上がったHTMLをサーバーやCDNにアップロードします
3. ユーザーがアクセスすると、待ち時間なしでHTMLが返ります

### 使用例
- GitHub Docs
- Next.js公式サイト（トップページや静的ページ）

### 代表的なフレームワーク
- Next.js
- Nuxt.js

### メリット
- ページの表示が速い
- サーバーへの負担軽減
- SEOに強い（HTMLがすでに存在してるから検索エンジンに優しい）
- セキュリティリスクが低い（動的処理がないため）

### デメリット
- 更新頻度が高いページには不向き（更新のたびにビルドが必要なため）
- コンテンツが多いとビルド時間が長くなる

## 比較表
| 特徴 | SPA | SSR | SSG |
|:-----------|:------------|:------------|:------------|
| 表示速度 | 初回遅い、以降は高速 | 毎回サーバー処理有 | 最速 |
| SEO対策 | 弱い（要工夫） | 強い | 強い |
| 更新頻度 | 動的データ向き | 動的データ向き | 静的データ向き |
| ユースケース | Webアプリ | ニュースサイト、ブログ | ドキュメント、会社サイト |

## 向いているケース
### SPA
- リアルタイムなデータ更新と高いユーザー操作性を備えたWebアプリ

### SSR
SEOを重視し、コンテンツのクロールとインデックスを最適化したい場合に最適
- ECサイトの商品ページ
- ブログやメディア記事
- SEOが重要なページ

### SSG
更新頻度が低く、攻撃リスクの少ない構成を望む場面に最適
- 更新頻度が低く、セキュリティの確保が必要な会社のコーポレートサイト
- ドキュメントサイト

## まとめ
SPAは、動的なWebアプリに適しており、ページ遷移がスムーズですが、初回表示が遅く、SEOに弱いです。SSRはSEOを強化し、初回表示が速い一方、サーバー負荷が高く、更新頻度が高いコンテンツに適しています。SSGは高速でSEOに優れ、セキュリティも高いですが、更新頻度が低いサイトに最適です。
家計簿アプリを作る＃３７

![スクリーンショット 2025-04-24 162644.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/b3836185-6c77-47ec-be4b-2a74f056e891.png)
NavLinkでisActiveを利用します。これを利用することによって、選択されたメニューにTrueという値が返されます。

![スクリーンショット 2025-04-24 163006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/c42fd37a-ba57-4d98-9295-96b42dad22d1.png)
Reportを選択すると、trueになり、Homeは、falseになります。

![スクリーンショット 2025-04-24 163142.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/50d2056d-b89d-4256-9e73-901048d41878.png)
return文の中には、...baseLinkStyleの形で、展開します。
ターミナルを起動したときに特定のディレクトリに自動で移動する方法


## ✅️はじめに
Mac のターミナルを使って作業していると、毎回同じディレクトリに移動したい場面があると思います。例えば、プロジェクトフォルダや作業中のディレクトリなどに毎回ターミナルを開いたときに自動で移動したいときに便利な方法です。

今回は、ターミナル起動時に特定のディレクトリに自動で移動する設定方法を紹介します。

## ✅️ターミナルのシェル設定ファイル .zshrc を編集
### ① .zshrc ファイルを開く
macOSのターミナルでは、デフォルトで「zsh」というシェルが使われています。このシェルには設定ファイル .zshrc があり、ここにコマンドを記述することで、ターミナル起動時に自動で実行されるコマンドを設定できます。

まず、ターミナルで以下のコマンドを実行して .zshrc を開きます。
```
nano ~/.zshrc
```
### ② cd コマンドを追加する
次に、ターミナル起動時に自動で移動したいディレクトリへの cd コマンドを追加します。例えば「デスクトップ」へ自動で移動したい場合、以下のように記述します。
```
cd ~/Desktop
```
この行を .zshrc の最後に追加してください。
### ③ 変更を保存して終了
設定が完了したら、nano エディタで以下の操作を行ってファイルを保存し、終了します：

**Ctrl + O** → 保存

**Enter** → 確定

**Ctrl + X** → 終了

### ④変更を反映させる
設定を反映させるためには、ターミナルで以下のコマンドを実行します：
```
source ~/.zshrc
```
これで、次回ターミナルを開いたときに指定したディレクトリに自動で移動できるようになります。

## ✅️エラー対処法：ディレクトリが見つからない場合
もし、エラーが発生した場合（例：no such file or directory）、以下の点を確認してください

#### パスの確認
pwd コマンドで、現在作業しているディレクトリを確認して正しいパスが指定されているかチェックしましょう。

#### スペースや特殊文字が含まれている場合
パスにスペースが含まれている場合、ディレクトリ名を クォート で囲む必要があります。例えば、**Macintosh HD** という名前のディレクトリがある場合、次のように書きます：
```
cd "/Volumes/Macintosh HD"
```
これで、スペースを含むディレクトリにも正しく移動できます。

## ✏️まとめ
この設定方法を使えば、毎回ターミナルを開いたときに自動で指定したディレクトリに移動することができ、作業がさらに効率的になります。設定はとても簡単なので、ぜひ試してみてください！

もしエラーが出ても、パスを再確認したり、スペースを含むディレクトリ名をクォートで囲むなどで解決できます。自分の作業環境に合わせたディレクトリを指定して、ターミナルの作業を快適にしましょう！

## 💡最後に
今回の方法を参考に、自分好みにターミナルの設定をカスタマイズしてみてください。少しの設定変更で作業効率が大きく向上しますよ！さらに便利なターミナルの活用方法も今後紹介していけたらいいなと思っていますので、ぜひチェックしてみてくださいね。
DATUM STUDIOのインターンでsnowfrakeとawsを触ってきた(in2024夏)

## はじめに
2024年の9/5(木) ～ 9/11(水)に開催されていたDATUM STUDIO株式会社のサマーインターンシップに参加してきたので、体験記を残したいと思います。と言っても半年近く前の話になりますが、、、
DATUM STUDIO株式会社のインターンを知ったきっかけはサポーターズになります。余談ですが、研究室の同期も別口から同じインターンに応募しており、何も示し合わさず同じ企業に応募していることにはびっくりしました。
## DATUM STUDIO株式会社について
> - **最先端のテクノロジーを駆使してデータ業界を牽引する企業**、特にSnowflakeの導入実績は日本国内においてNo.1クラス
> 
> 
> - PyLadies Tokyo初代代表＆自然言語処理のスペシャリストである分析業界の女性トップリーダー真嘉比や全世界で30名日本唯一のDATA HERO OF THE YEARを受賞したデータエンジニア菱沼等、**業界のトップランナーとの距離が近く、和気藹々と楽しく一緒に働ける**
> 
> - **幅広いかつ新しい技術領域の勉強会、研修など教育プログラムが充実＆裁量がある環境であり最速成長できる**
>
## インターンの流れ
day1: s3(AWS)のデータをSnowflakeに効率よく読み込む
day2: dbtでデータを変換してパイプラインを作る
day3: 実態把握および施策立案を行うための顧客分析
day4: streamlitで可視化を行う
day5: RAGを使ったアプリケーションを作成する
となっており、一連の流れを経験することができます。
day5のうち1~4はリモート、5は対面となっていました。

取り組み際はチームになって行い、4~5人のインターン生に1人のメンターがつくような形です。
質問はその日の担当の方やメンターの方にする形でした。

## day1: s3(AWS)のデータをSnowflakeに効率よく読み込む
データウェアハウスなどの講義を受けたのち実際にAWS, Snowflakeを使って課題を行います。資料に基本的なことが記載されているため、何をしたらいいか分からないということはありません。そこから効率的に読み込んだらいいか、知識を持ち寄ったり調べたりして作成します。
最後にチームごとで発表を行い、フィードバックをもらいます。

## day2: dbtでデータを変換してパイプラインを作る
dbtに関することを学びながらハンズオンを行ったのち課題に取り組みます。楽天市場の購入データを使ってOBTを作成します。
最後にチームごとで発表を行い、フィードバックをもらいます。発表内容はどのように実装したか、難しかったところ、総実行時間になります。

## day3: 実態把握および施策立案を行うための顧客分析
RFM分析、Snowflakeに関する講義を受けたのち実態把握および施策立案を行う目的で顧客分析を行います。課題には細かいマイルストーンがあるため、1つずつ行なっていくことでできます。
最後にチームごとで発表を行い、フィードバックをもらいます。

## day4: streamlitで可視化を行う
streamlitに関する講義を受けたのち分析に適したダッシュボードを作成していきます。こちらの課題も作成するグラフの要件があるためこれに合わせて作成していきます。
最後にチームごとで作成したダッシュボードを見せながら発表を行い、フィードバックをもらいます。

## day5: RAGを使ったアプリケーションを作成する
ここで対面に切り替わります。チームメンバーやメンターの方ともリアルで会いました。RAGに関する講義を受けたのち、商品に対して対話的に検索ができるRAGアプリケーションを作成します。
最後にチームごとで作成したアプリケーションを見せながら発表を行い、フィードバックをもらいます。

## 感想
- Snowflakeなど普段触らないサービスを扱うことができてよかったです。
- 分析などで行ったデータは実際の楽天の購入データを使っており、名寄せなどの大変さを体験できました。コンペなどでは、大文字、小文字、似た文字などを正規化することはあったもの楽天の商品名寄せではバリエーションが豊富すぎて難しかったです。
- また難しかった点は、時間的制約です。色々と試してみたいことがある中で全てを試すことができず、何を優先して試すかの経験則などがなく難しかったです。