OmniAICreator/Qiita-1.07M huggingface dataset:
PowerQueryなどでCRC32の計算

- コードのメモ用
- PowerQuery勉強中で適当にコード遊びをしていたときの産物
- PowerQueryのシンタックスハイライトがなかったので色付く部分が多めのJSを採用
- 処理はRFC1952を参考にPowerQuery用の調整をしている
- PowerQuery版は300KB程度のファイルでも少しぐるぐるするくらい速度は終わっているのでこのままだと実用性はなさそう

```javascript:power query
(data as binary) => let
    crcTable = List.Transform(
        List.Numbers(0, 256),
        (n as number) => List.Accumulate(
            List.Numbers(0, 8), n, (seed as number, notUse) => 
                if Number.IsOdd(seed)
                then Number.BitwiseXor(0xedb88320, Number.BitwiseShiftRight(seed, 1))
                else Number.BitwiseShiftRight(seed, 1)
        )
    )
    in
        Number.BitwiseXor(
            List.Accumulate(
                Binary.ToList(data),
                Number.BitwiseXor(0, 0xffffffff),
                (seed as number, byte as number) => Number.BitwiseXor(
                    crcTable{Number.BitwiseAnd(Number.BitwiseXor(seed, byte), 0xff)},
                    Number.BitwiseShiftRight(seed, 8)
                )
            ),
            0xffffffff
        )

```

## VBA版(64bit専用)

- オーバーフローを起こしたり負数になったりしていい感じにそのまま移せなかったのでLongLongを使ったので64bit専用
- どうせ他で使うこともなさそうなのでテーブルを普段使う機会のないstatic変数で持つようにしてある
- わかりにくい部分補足
    - バックスラッシュに見える部分はVBAでは「&#xa5;」
    - LongLongのリテラルは末尾に「^」
    - &HはVBAの16進数リテラルの0x的な部分(Hexから来てそう)
```vb:vba(64bit専用)
Public Function Crc32(ByRef Bytes() As Byte) As LongLong
    Static Table(0 To 255) As LongLong
    If Table(255) = 0 Then
        Dim i As Long
        For i = 0 To 255
            Dim c As LongLong
            c = i
            Dim j As Long
            For j = 1 To 8
                If c And 1 Then
                    c = &HEDB88320^ Xor (c \ 2^)
                Else
                    c = c \ 2
                End If
            Next
            Table(i) = c
        Next
    End If
    Dim Crc As LongLong
    Crc = 0 Xor &HFFFFFFFF^
    Dim ByteItem As Variant
    For Each ByteItem In Bytes
        Dim Temp As LongLong
        Temp = Crc Xor CLngLng(ByteItem)
        Dim Index As Long
        Index = CLng("&H" & Right("00" & Hex(Temp), 2))
        Crc = Table(Index) Xor (Crc \ 256^)
    Next
    Crc32 = Crc Xor &HFFFFFFFF^
End Function
```

## Python版
- 参考にしたコードやVBA版と違ってテーブル部分も含めて一体化させればインポートとワンライナーの無名関数でCRCの計算処理が作れる
- やり方的には無名関数やreduceを使ってる点でPowerQuery版とほぼ一緒

```python:crc32(python、reduce利用)
from functools import reduce
crc_table = tuple(
    reduce(
        lambda x, _: 0xEDB88320 ^ (x >> 1) if x & 1 else x >> 1,
        range(8),
        i
    )
    for i in range(256)
)

crc32 = lambda data: (
    reduce(
        lambda c, b, t=crc_table:
        t[(c ^ b) & 0xFF] ^ (c >> 8),
        data,
        0 ^ 0xFFFF_FFFF,
    ) ^ 0xFFFF_FFFF
)

```
コンポーネント設計　アトミックデザイン編

「Atoms（アトム）」という用語は、コンポーネント設計の分野、特に**Atomic Design（アトミックデザイン）**という考え方に関連しています。アトミックデザインは、デザインシステムを構築するための方法論で、UIを「小さな部品」に分解し、段階的に組み合わせていくアプローチです。

### アトミックデザインとは？
アトミックデザインは、元々はウェブデザインに使われる手法ですが、フロントエンド開発でもコンポーネント設計に役立つ考え方です。アトミックデザインは、5つのレベルで構成されています。それぞれがどのような役割を果たすかを見ていきましょう。

#### 1. **Atoms（アトム）**
- **最小単位**であり、再利用可能なUIの部品です。
- ボタン、入力フィールド、ラベル、アイコンなど、単体で意味を持つ最も基本的な要素です。

**例**：
- ボタン `<button>`
- テキスト入力フィールド `<input>`
- アイコン `<i class="icon-home"></i>`
- タイトル `<h1>`

アトムは、これ以上細かく分解できない部品で、単体で動作することは少なく、後で他の部品と組み合わせて使用されます。

#### 2. **Molecules（モレキュール）**
- アトムを組み合わせて作った**小さな機能単位**です。
- 例えば、ラベルと入力フィールド、ボタンを組み合わせてフォームの一部を作るようなものです。

**例**：
- 入力フィールド + ラベル + ボタン → **検索フォーム**
- アイコン + テキスト → **ナビゲーションリンク**

モレキュールは、アトムの組み合わせで少し機能的な意味を持ち始めます。

#### 3. **Organisms（オーガニズム）**
- モレキュールを組み合わせて作る**より複雑な構造**です。
- たとえば、ナビゲーションバーやカードなどの複数の部品を組み合わせて1つの大きな部品にします。

**例**：
- ヘッダー（ロゴ、ナビゲーションリンク、検索フォームなど）
- 商品カード（画像、タイトル、価格、ボタンなど）

オーガニズムは、アプリケーションの機能的な部分を構成し、複数のモレキュールが組み合わさって、より複雑な機能を持つUIが作られます。

#### 4. **Templates（テンプレート）**
- オーガニズムをレイアウトに配置したものです。
- これはページの大まかな構造を定義しますが、まだ**具体的なデータ**は入っていません。

**例**：
- ヘッダー、メインコンテンツ、フッターが配置されたページのレイアウト。

テンプレートは、実際のコンテンツが入る前にページの骨組みを作る段階です。

#### 5. **Pages（ページ）**
- テンプレートに実際の**データ**を挿入して、最終的なページを完成させます。
- これでユーザーが実際に見ることができる、完成形のUIになります。

**例**：
- 実際のユーザーの名前や商品情報が入った商品ページ。

ページは、テンプレートの設計が完了した後に、最終的なデータを反映させることで、ユーザーが直接触れる部分になります。

---

### アトミックデザインのメリット
- **再利用性**: アトムやモレキュールなどの小さな部品を再利用することで、効率的なUI設計が可能になります。
- **一貫性**: UI部品が細かく分かれているため、デザインの一貫性を保ちやすくなります。
- **スケーラビリティ**: 新しい機能やページを追加する際にも、既存の部品を組み合わせてスムーズに実装できます。
- **メンテナンス性**: 小さな部品単位でコードを管理することで、修正や更新が容易になります。

### アトムの実際のコード例
例えば、`Button`コンポーネントはアトムの一例です。

```vue
<!-- Button.vue -->
<template>
  <button :class="buttonClass" @click="handleClick">{{ label }}</button>
</template>

<script lang="ts">
import { Component, Prop, Vue } from "vue";

@Component
export default class Button extends Vue {
  @Prop({ type: String, default: "クリック" }) label!: string;
  @Prop({ type: String, default: "btn-primary" }) buttonClass!: string;

  handleClick() {
    this.$emit("click");
  }
}
</script>

<style scoped>
.btn-primary {
  background-color: blue;
  color: white;
}
</style>
```

このボタンは、アトムとして最小の部品です。このボタンコンポーネントを他のコンポーネントに組み合わせていくことができます。

### まとめ
アトミックデザインは、UIを段階的に細かく分けていくアプローチです。アトム（最小単位）から始めて、モレキュール、オーガニズム、テンプレート、ページへと組み合わせていきます。この方法を使うことで、**効率的でメンテナンスしやすい**UIコンポーネント設計が可能になります。


***私用***
ページタイトル（リンクアイコン）（リンクアイコン）

ページタイトルとリンクアイコンを合わせたものががモレキュール、
リンクアイコンをアトムとしてたよ
Next.js + App Router + TypeScriptでサブディレクトリ運用時の画像パス問題を解決する


Next.jsのプロジェクトをサブディレクトリで運用する場合、例えば本番環境で `/blog-sample` のようなパス配下にデプロイするケースを想定すると、画像パス周りでちょっとした工夫が必要になります。  

`next/image` コンポーネントを使う際、デフォルトではルート(/)からのパスを基準に画像を読み込むため、サブディレクトリ環境だとパスがずれてしまい、画像が正しく表示されないことがあります。
今回は、この問題を解決するために私が実装した方法を紹介します。

## 課題: サブディレクトリ環境での画像パス調整

開発環境では通常ルート`(/)`で動作するので問題ないのですが、本番環境でサブディレクトリ`(/blog-sample)`配下にデプロイすると、`next/image` の `src` に渡したパスがそのままでは意図した場所を指さなくなります。
例えば、`src="/images/sample.jpg"` のように指定しても、本番では `/blog-sample/images/sample.jpg` にならないと正しく読み込まれません。
これを手動で毎回調整するのは面倒だし、環境による条件分岐もスマートとは言えません。
そこで、環境変数を使ってベースパスを動的に設定しつつ、`next/image` をラップしたカスタムコンポーネントを作ることで、開発環境と本番環境の両方で一貫して動作するようにしました。

## 解決策: カスタムImageコンポーネントの実装
以下のように、`next/image` をラップした `Image` コンポーネントを作成しました。
```tsx

import NextImage, { ImageProps } from 'next/image';

const basePath = process.env.NEXT_PUBLIC_BASE_PATH || '';

export const Image: React.FC<ImageProps> = ({ src, ...rest }) => {
  const normalizedSrc =
    typeof src === 'string' && src.startsWith('/') ? src.slice(1) : src;

  return <NextImage src={`${basePath}/${normalizedSrc}`} {...rest} />;
};
```

このコードのポイントは以下の通りです：
1. **環境変数の利用**: NEXT_PUBLIC_BASE_PATH を環境変数として定義し、本番環境では /blog-sample のようなサブディレクトリを指定します。開発環境では空文字('')をデフォルト値として設定。

2. **パスの正規化**: src が文字列で、先頭にスラッシュ(/)が付いている場合、それを削除してベースパスと組み合わせるようにしています。これで、例えば src="/images/sample.jpg" が渡された場合、本番環境では /blog-sample/images/sample.jpg に、開発環境では /images/sample.jpg に自然に変換されます。

3. **柔軟性**: src が文字列以外（例えば StaticImageData）の場合でも、そのまま next/image に渡すので、エラーにならずに動作します。

## ビルド時の設定
本番環境向けのビルドでは、以下のように package.json にスクリプトを追加して環境変数を指定しています。

```json

"build:prod": "NEXT_PUBLIC_BASE_PATH=/blog-sample next build",
```

この設定により、本番ビルド時に `NEXT_PUBLIC_BASE_PATH` が `/blog-sample` にセットされ、生成されるHTMLやアセットのパスに反映されます。開発環境では特に何も指定しないので、`basePath` は空文字のままとなり、ルート基準で動作します。

### 使い方
実際のコードでは、以下のように使います。
```tsx

import { Image } from '@/components/Image';

export default function Home() {
  return (
    <div>
      <Image src="/images/sample.jpg" alt="サンプル画像" width={500} height={300} />
    </div>
  );
}
```

これで、開発環境でも本番環境でも、特別な条件分岐を書かずに画像が正しく表示されます。

## まとめ
Next.jsでサブディレクトリ運用をする場合、画像パス問題は地味にハマりがちなポイントですが、環境変数とカスタムコンポーネントを組み合わせることで簡単に解決できます。今回の方法は、コードのメンテナンス性も高く、他のプロジェクトでも応用しやすいのでおすすめです。サブディレクトリ名が変わっても、ビルド時の環境変数を調整するだけで対応できるのも嬉しいポイントですね。
もし似たような課題に直面している方がいたら、ぜひ試してみてください！
ChatGPTで会話内容を学習させない方法｜設定手順を図解でわかりやすく解説

# ChatGPTで会話内容を学習させない方法｜設定手順を図解でわかりやすく解説

---

「ChatGPTに入力した内容って、勝手に学習に使われてるの？」  
「仕事の相談やアイデアが記録されるのはちょっと不安…」

そんな声、よく聞きます。

実はChatGPTは、デフォルトの設定のままだと**ユーザーとの会話内容をAIのトレーニングに利用**しています。でも安心してください。設定を見直せば、あなたの会話が学習に使われるのを防ぐことができます。

この記事では、「ChatGPTに会話を学習させない方法」を、初心者にもわかりやすく画像付きで解説します。

---

## ChatGPTの会話は学習に使われている？

OpenAIによると、ChatGPTのパフォーマンス向上のために、ユーザーの会話データを一部収集し、AIモデルのトレーニングに役立てているとのこと。

ただし、これは**オプトアウト（除外設定）可能**。つまり、自分の会話をAIに学習させない設定がちゃんと用意されているんです。

---

## ChatGPTで学習をさせない方法

### ✅ 方法①：ChatGPTの設定から「モデル改善をオフ」にする

もっとも手軽でおすすめの方法です。設定画面から数ステップで完了します。



---

## 【画像付き解説】ChatGPTで学習をオフにする手順

### 方法①：ChatGPTの設定から「モデル改善」をオフにする

#### 🔹ステップ① 設定を開く

「プロフィールアイコン」 → 「設定（⚙）」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299557/76dd465c-b1fd-4741-9284-b0393916871f.png)


#### 🔹ステップ② 「データコントロール」を選択

左側メニューから「データコントロール」をクリックします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299557/bcd3bacb-b009-48d3-b8bf-3cdf89a067c7.png)


#### 🔹ステップ③ 「モデルの改善」をオフにする

「すべての人のためにモデルを改善する」という項目のスイッチをオフにします。
グレー色の状態がオフです
最後に実行するボタンを押下します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299557/cdbbe3ba-c55b-4154-8929-6cdba9e095fd.png)



> 🔒 この設定をオフにすると、ChatGPTとの新しい会話はAIの学習に使われなくなります。


---

## でも…設定しても「絶対に安心」とは言い切れない理由

ここまでで「これで完璧！」と思うかもしれませんが、少しだけ注意点があります。

- 過去の会話内容がすでに学習に使われている可能性がある  
- OpenAI側のAI学習プロセスは、**完全には公開されていない（ブラックボックス）**  
- 設定が反映されるのは「今後の会話」に限られる

つまり、「設定を変えた＝全データが安全」というわけではないのです。

---

## まとめ｜大切なのは、情報との付き合い方

ChatGPTを安心して使うには、プライバシー設定をしっかり確認しておくことが大切です。

- ✅ 設定から「モデル改善」をオフにする  
- ✅ 重要な会話には「一時的チャット」も活用する  
- ✅ OpenAIへのオプトアウト申請で、さらに安心をプラス

今すぐできる対策で、大切な情報を守りましょう！

---

🛡 **あなたのデータは、あなた自身で守る時代。**  
この記事を参考に、ぜひ一度ご自身のChatGPT設定を見直してみてください！
Anki風のシンプルな学習アプリを個人開発してみた【React Native × Firebase】

# アプリケーション名
ankiApp

# アプリケーション概要
英語・中国語・資格試験など、自分の目的に合わせたフラッシュカードを使って効率的に暗記学習ができる、React Native + Firebase製のシンプルな学習アプリです。デッキごとにカードを登録し、復習のタイミングを自動で調整することで、知識の定着をサポートします。

# アプリケーションを作成した背景
日々の学習において「覚えたつもり」を防ぎ、効率的に記憶を定着させたいという思いから、本アプリの開発に取り組みました。市販のAnkiアプリは高機能ですが、その反面インターフェースや設定が複雑で、学習に集中しづらいと感じていました。

そこで、自分の学習スタイルにフィットした、シンプルで直感的に使える暗記アプリを目指し、React Nativeを使ってゼロから構築しました。以前にReactの開発経験があったこともあり、スムーズにモバイルアプリ開発へ移行できた点も大きな後押しとなりました。

# 参考
https://apps.ankiweb.net/

# 備考
本アプリは個人の学習支援を目的としたもので、現在はローカル／開発環境での運用にとどめています。  
本番環境へのデプロイにはFirebase課金やApple Developer登録などのコストが伴うため、必要性が生じた段階で導入を検討する予定です。

## アプリの画像（イメージ）

| デッキ一覧 | 問題カード |
|------------|-------------|
| [![Deck](https://i.gyazo.com/5b7567e5bb0f0aa5516ced69398f2128.png)](https://gyazo.com/5b7567e5bb0f0aa5516ced69398f2128) | [![Question](https://i.gyazo.com/13132014d3cf136b8f54d59650c1fa54.png)](https://gyazo.com/13132014d3cf136b8f54d59650c1fa54) |

| 回答カード | 登録画面 |
|------------|-------------|
| [![Answer](https://i.gyazo.com/1259c247fb5930669acf9c41c8c64e50.png)](https://gyazo.com/1259c247fb5930669acf9c41c8c64e50) | [![Register](https://i.gyazo.com/c04a82abbff28e05a825e66838ddef58.png)](https://gyazo.com/c04a82abbff28e05a825e66838ddef58) |



# 今回のポイント：SuperMemo 2 アルゴリズム（SM-2）

本アプリでは、記憶の定着効率を最大化するために「SuperMemo 2（SM-2）」アルゴリズムに基づく復習スケジュールを採用しています。

SM-2は「覚えた内容を、忘れる直前にもう一度復習する」ことで、記憶の保持率を高めることを目的としたアルゴリズムです。復習ごとにユーザーが「どれくらい覚えていたか」を自己評価（0〜5段階）し、その評価に応じて次回の復習日が自動的に調整されます。

この仕組みにより、単なる暗記カード以上に、「忘却曲線」に沿った効率的な復習体験を提供します。

SM-2アルゴリズムの主な流れ：

各カードには "Ease Factor（記憶しやすさ）" があり、ユーザーの評価によって変化

評価が高ければ復習間隔が長くなり、低ければ短くなる

一度覚えた内容は、自然に復習頻度が減っていくため、効率よく学習を継続可能

これをアプリ内で自動管理することで、学習者は「次に何を復習すべきか」を考える必要がなくなります。


# 利用方法

## ✅ デッキの作成・表示
- ホーム画面から「Add Deck」をタップし、学習テーマごとのデッキ（例：英単語、中国語文法、IT用語など）を作成。



## ✅ フラッシュカードの登録
- 各デッキ内で「Add FlashCard」をタップし、表（問題）と裏（答え）を登録。例文なども追加可能。

## ✅ フラッシュカードの復習
- 復習対象のカードが日ごとに表示され、復習完了すると記憶度に応じて次回表示が自動調整されます。

## ✅ 編集・削除
- 登録済みカードやデッキは編集・削除可能です。

# 開発環境
- フロントエンド: React Native (Expo)
- バックエンド: Firebase Authentication / Firestore
- アーキテクチャ: EAS Build（iOS / Android対応）
- 言語: TypeScript

# 主な機能
- ユーザー認証（Firebase Authentication）
- デッキごとのフラッシュカード登録・管理
- 復習スケジュールに基づいたカード表示
- 完了率表示（プログレスバー）
- カード詳細の編集・削除
- デッキの名称変更・削除（ActionSheet）
- 音声再生機能（語学学習支援）

# 今後の展望
- 並び替え機能やタグ付け
- デッキ共有・インポート機能


# 工夫したポイント
- Firebaseでユーザーごとにデータを管理し、端末を問わず学習を継続できる
- シンプルかつ最小限のUIで、操作性を重視
- Expo + EAS Buildでクロスプラットフォーム対応（iOS / Android）
- 学習進捗が視覚的に分かるプログレスバー表示

# 使用技術
- React Native / Expo 
- Firebase Authentication
- Firebase Firestore
- TypeScript

# 大変だったこと
- Firebaseのネスト構造でのデータ取得と管理

# 参考にしたもの
- [Expo公式ドキュメント](https://docs.expo.dev)
- [Firebase公式ドキュメント](https://firebase.google.com/docs)
- Qiita内のReact Native + Firebase事例

# 最後に
このアプリは「自分で決めたことを、毎日少しずつ覚える」ために作ったものです。語学・IT・資格試験・受験勉強など、どんなジャンルにも応用できるように設計しています。今後もより実用的な学習支援ツールに進化させていく予定です。
CNAMEレコードとは？役割と実践ユースケースをまとめてみた

## はじめに

仕事でDNS設定をいじる機会があり、その中で「CNAMEレコードって何者？」という疑問が出てきたので、  
この機会に調べてみました 

本記事では、**CNAMEの役割や、実際にどんなときに使うのか**を、ユースケースに沿ってシンプルにまとめています。  
自分の備忘録的な意味もこめて、実例も交えて紹介しています👌

## CNAMEの役割と利用例

:::note info
CNAMEは ドメインでリクエストが来た時に別のドメインにリクエストされるよう**ドメインを置き換える**設定です
:::


### 設定例

```bash
example.com.        A       192.0.2.1
www.example.com.    CNAME   example.com.
```

`example.com` へのリクエストは `192.0.2.1` へのリクエストと置き換えられます

`www.example.com` へのリクエストは `example.com` へ置き換えられ、
最終的に `192.0.2.1` へリクエストされます

### 利用例 ユースケースになぞえたCNAME設定

あるところに A社とB社がおりました

A社はB社と合併し、A社のサイトにアクセスが来た際はB社のサイトにリクエストする必要が発生!!


#### 合併前

A社レコード (192.0.2.1はA社サイトのIP)

```bash
# A社サイトのAレコード
acompany.hoge.jp. A 192.0.2.1
```

B社レコード (172.32.2.1はB社サイトのIP)

```bash
# B社サイトのAレコード
bcompany.hoge.jp. A 172.32.2.1
```

#### 合併後

A社レコード

```bash
# B社サイトにリクエストされるよう変更
acompany.hoge.jp CNAME bcompany.hoge.jp.
```

B社レコード

```bash
# B社サイトのAレコード
bcompany.hoge.jp. A 172.32.2.1
```

### おまけ

- `exmaple.com.` のように何故レコード登録する際は、一番最後に`.` をつけるのか気になったので調べたみました
    - ドメインの終端を表す `.` であるということ
    - この設定がないと ドメインの終端がわからず `exmaple.com.hogehoge.co.jp` のように後ろに続くのでは? とドメインサーバから解釈されてしまうため、名前解決がうまくいかない

他にも CNAME にはさまざまなユースケースがあるのでみてみると面白いです👌

- 参考
    - https://qiita.com/tobari_ko/items/1310384f7b6b24d01fc7
    - https://www.digicert.com/jp/blog/cname-records-common-use-cases-and-benefits
【冨田学誠のTips】エンジニアは子育てが得意な傾向がある

こんにちわ冨田学誠です！
近年、エンジニアとして働く人々の中には、子育てと仕事をうまく両立している方が増えています。このブログでは、なぜエンジニアが子育てにおいて得意な傾向があるのか、その理由を探っていきます。

## 1. 問題解決能力が高い

エンジニアは日々、複雑な問題を解決する仕事に従事しています。コードを書くときやシステムを開発するとき、予期せぬ問題が発生することが多く、その都度柔軟に解決策を見つける必要があります。この「問題解決能力」は、子育てにも非常に役立ちます。子どもが発する「なぜ？」という質問や、日常の育児における予期しないトラブルに対しても冷静に対処し、解決策を考え出すことができるのです。

## 2. 時間管理と優先順位付けが得意

エンジニアはタスク管理が重要です。プロジェクトの進行管理や締切に合わせた作業が求められるため、効率的な時間配分と優先順位付けのスキルが身に付きます。この能力は、子育てにも応用できます。例えば、育児と仕事を両立させるためには、家事や子どもの世話、仕事をうまく分けて時間を管理することが必要です。エンジニアはこうした時間管理が得意で、効率よく生活を回すことができるため、育児もスムーズにこなせるのです。

## 3. 自己学習の習慣がある

エンジニアは技術の進化に追いつくために、常に新しい知識を学び続けています。この「自己学習の習慣」は、子育てにも非常に有益です。子どもの成長に伴い、育児のスタイルや対応方法も変化しますが、エンジニアは学び続ける姿勢を持っているため、育児の進化に柔軟に適応できるのです。また、育児に関する新しい情報を積極的に学ぶことができ、より良い育児方法を見つけて実践することが可能です。

## 4. チームワークとコミュニケーション能力

エンジニアはチームでの協力を重視する仕事です。プロジェクトの進行や問題解決には、メンバー間の円滑なコミュニケーションが欠かせません。子育てにおいても、パートナーとの協力や、家族全体での調整が必要になります。エンジニアは、チーム内で適切な情報共有や意見交換を行うスキルを持っており、育児においてもこれを活かして、家庭内での協力体制をうまく築くことができます。

## 5. ストレス管理ができる

エンジニアの仕事はしばしば高いストレスを伴います。納期が迫ったプロジェクトや予期しない問題に対処する際、冷静さを保つことが求められます。このストレス管理能力は、子育てにも非常に役立ちます。子どもの成長過程には、多くのストレスや悩みがつきものですが、エンジニアは冷静に対処する能力を持ち、ストレスを上手に管理しながら育児を行うことができるのです。

## 結論

エンジニアは、問題解決能力、時間管理、自己学習、チームワーク、そしてストレス管理といったスキルを活かして、子育てをうまくこなす傾向があります。これらのスキルは、育児において非常に役立ち、仕事と家庭のバランスをうまく取るための強力な武器となるのです。エンジニアとしての経験が、家族と共に過ごす時間をより充実させ、育児を楽しむための一助となることは間違いありません。
Linux port確認

# はじめに

Linuxでポートの状態を確認する方法について、以下に解説します。

ポート確認の目的
- 特定のポートが使用中かどうかを確認
- ポートを使用しているプロセスを特定
- サーバが特定のポートで接続を受け付けているか確認 

# 主なコマンド一覧

## lsofコマンド

特定ポートを使用しているプロセスを確認できます。

```bash
# ポート番号を指定して確認
$ sudo lsof -i:<ポート番号>

# 例: 80番ポートの確認
$ sudo lsof -i:80
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nginx     1234  root   6u   IPv4 12345 0t0      TCP *:http (LISTEN)
```

プロセスを確認して、プロセスを停止（kill)する。

```bash
$ sudo kill <プロセスID>

# 例: PID 1234 の確認
$ sudo kill 1234
```

## ssコマンド

`netstat`の代替として推奨されるコマンドで、高速かつ詳細な情報を提供します。

```bash
# LISTEN状態のTCP/UDPポートを表示
$ sudo ss -lntu

# 特定ポートのみを絞り込み
$ sudo ss -tulpn | grep :<ポート番号>

# 例: 80番ポートの確認
$ sudo ss -tulpn | grep :80
tcp LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1234,fd=6))
```

## ncコマンド

クライアント側から疎通確認が可能。

```bash
# サーバと特定ポートへの疎通確認
$ nc -vz <接続先サーバ> <ポート番号>

# 疎通可能な場合の例:
Ncat: Connected to <接続先>:22.

# 疎通不可の場合の例:
Ncat: Connection refused.
```

## nmapコマンド

外部から接続可能なポートをスキャンできます。

```bash
# ローカルホストの開いているポート一覧を取得
$ nmap localhost

Starting Nmap ...
PORT     STATE SERVICE
22/tcp   open ssh
443/tcp  open https
```
【備忘録】docker push で resource is denied と言われた

# 何が起きたか
`docker-compose push`したら以下のエラーが出た。
```
ERROR: denied: requested access to the resource is denied
```
どの記事でも`docker login`すれば良いと言ってたが、しても解決しなかった。

# 原因と対処
`docker-compose`の送り先は`docker.io`になる。
単に`docker login`すると、（おそらく）dockerhubにログインすることになり、ここが食い違う。
そのため、以下のコマンドを実行して`docker.io`にもログインしておく。
```sh
docker login docker.io -u <username>
```
改めて`docker-compose push`すれば無事通る。
No module named 'torch_geometric.utils.to_dense_adj' 備忘録

# 概要

5,6年前からやりたかったGNNに着手している。今回は下記の書籍でお勉強して、チュートリアルを改造しながらやりたいことをやろうと。

https://github.com/PacktPublishing/Hands-On-Graph-Neural-Networks-Using-Python


- 実施期間: 2025年3月
- 環境：Ubuntu22.04LTS
- Python: condaのPython3.10


## 1. 環境設定
torch-geometric-temporalを入れるところまで忘れそうなので残す。pytorchは下記公式サイトのCUDA11.8版をpipで入れる。condaでは入れられなくなっていた。

https://pytorch.org/get-started/locally/

```terminal
conda install -c "nvidia/label/cuda-11.8.0" cuda-toolkit
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
pip install torch_geometric
pip install torch-geometric-temporal
```

## 2. エラーの対処
本題のエラーの対処方法をだが、下記を実行すると掲題のエラーが出る。

```python
from torch_geometric_temporal.signal import StaticGraphTemporalSignal
```

2024/3/末現在、公式githubのissueにbug報告がされていて暫定対応方法があった。issueはopenだし最新版のtorch-geometric-temporalを入れてもエラーは出るのでまだ対応していただけてないみたい。

https://github.com/benedekrozemberczki/pytorch_geometric_temporal/issues/267

対応いただくまではローカルの下記pyファイルを編集しなければならない。

**/home/[name]/miniconda3/envs/[env name]/lib/python3.10/site-packages/torch_geometric_temporal/nn/attention/tsagcn.py**

torch-geometric-temporalの中でsparse graphをdense graphに変換する関数のimportで齟齬があるらしい。

```python
from torch_geometric.utils.to_dense_adj import to_dense_adj    # 誤
from torch_geometric.utils._to_dense_adj import to_dense_adj    # 正
```

pythonは依存関係が複雑だから、昔は問題なく動いていたのだろうと思う。

## 3. Google Colab
cudaのバージョンを下げてtorch_geometric_temporalを入れる。

```python
!pip install torch==2.1.0 torchvision==0.16.0 torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/cu118
!pip install pyg-lib torch-scatter torch-sparse torch-cluster torch-spline-conv -f https://data.pyg.org/whl/torch-2.1.0+cu118.html
!pip install torch_geometric_temporal
```

以上
アルゴロジック2の備忘録

# はじめに
[「アルゴロジック2」](https://algo.jeita.or.jp/prm/2/index.html)のヒントをまとめました。
あくまで筆者の備忘録です。<br>

JEITA（電子情報技術産業協会）が開発した、
ゲーム感覚でプログラミングを体験するための「課題解決型ゲームソフト」です。
以下が公式HPになります。
[プログラミング体験ゲーム：アルゴロジック ｜ JEITA](https://algo.jeita.or.jp)

# 1. 「順次」のヒント
<table>
<thead>
<tr>
<th>番号</th> <th>使うブロック数</th>
</tr>

<tr>
<td>01 移動</td><td>1</td>
</tr>

<tr>
<td>02 右に曲がる</td><td>3</td>
</tr>

<tr>
<td>03 方向転換</td><td>3</td>
</tr>

<tr>
<td>04 Uターン1</td><td>5</td>
</tr>

<table>

# 2. 「繰り返し」のヒント
<table>
<thead>
<tr>
<th>番号</th> <th>使うブロック数</th>
</tr>

<tr>
<td>05 Uターン2</td><td>4</td>
</tr>

<tr>
<td>06 無限ループ</td><td>6</td>
</tr>

<tr>
<td>07 四角の旗</td><td>6</td>
</tr>

<tr>
<td>08 十字回廊</td><td>7</td>
</tr>

<table>

# 3. 「分岐」のヒント
<table>
<thead>
<tr>
<th>番号</th> <th>使うブロック数</th>
</tr>

<tr>
<td>09 IFを使う</td><td>6</td>
</tr>

<tr>
<td>10 Uターン3</td><td>6</td>
</tr>

<tr>
<td>11 ELSEを使う</td><td>7</td>
</tr>

<tr>
<td>12 IFを使う2</td><td>7</td>
</tr>

<table>

# 4. 「応用1」のヒント
<table>
<thead>
<tr>
<th>番号</th> <th>使うブロック数</th>
</tr>

<tr>
<td>13 十字</td><td>6</td>
</tr>

<tr>
<td>14 知恵の輪</td><td>6</td>
</tr>

<tr>
<td>15 うずまき</td><td>8</td>
</tr>

<tr>
<td>16 八方向</td><td>6</td>
</tr>

<table>


# 5. 「応用2」のヒント
<table>
<thead>
<tr>
<th>番号</th> <th>使うブロック数</th>
</tr>

<tr>
<td>17 十字回廊</td><td>7</td>
</tr>

<tr>
<td>18 四</td><td>8</td>
</tr>

<tr>
<td>19 ほこら</td><td>8</td>
</tr>

<tr>
<td>20 全部</td><td>7</td>
</tr>

<table>


# 6. 「応用3」のヒント
<table>

<thead>
<tr>
<th>番号</th> <th>使うブロック数</th>
</tr>

<tr>
<td>21 迷路</td><td>7</td>
</tr>

<tr>
<td>22 巨大迷路</td><td>8</td>
</tr>

<tr>
<td>23 秘密の部屋</td><td>8</td>
</tr>

<tr>
<td>24 秘密の部屋2</td><td>7</td>
</tr>

<table>


# さいごに
公式でも回答を公開していないみたいなので、あくまでヒントとして活用してください。
いきなり言語を触るよりも、ゲーム感覚で繰り返しや条件分岐を学ぶことができたました。
【Ruby】ナンバードパラメータ、シンプルで好き

以下の記事の続きです。

https://qiita.com/PDC-Kurashinak/items/c66cb053b46a403375ce

---

以下のコード二つは同じ結果を出力できることはわかりました。

```rb:従来
numbers = [1, 2, 3, 4, 5]
doubled = numbers.map { |number| number * 2 }
puts doubled

# => [2, 4, 6, 8, 10]
```

```rb:ナンパラ
numbers = [1, 2, 3, 4, 5]
doubled = numbers.map { _1 * 2 }
puts doubled

# => [2, 4, 6, 8, 10]
```

:::note info
ナンパラを使用すると、ブロックの中をスッキリ書けます
:::

ブロックに渡す要素が複数ある場合にもスッキリ書けそうです。

```rb:従来
numbers_array = [['a', 'b'], ['c', 'd'], ['e', 'f']]  # 二次元配列
output = numbers_array.map { |el| "#{el[0]}と#{el[1]}" } # ← ここ
puts output

#=> aとb
#=> cとd
#=> eとf
```

↑は配列の何番目か要素を指定する必要がありました。

```rb:ナンパラ
numbers_array = [['a', 'b'], ['c', 'd'], ['e', 'f']]  # 二次元配列
output = numbers_array.map { "#{_1}と#{_2}" }  # ← ここ
puts output

#=> aとb
#=> cとd
#=> eとf
```

スッキリ！
ブロック引数渡さなくて良いのが楽！

い
AWS クレデンシャル config credentials

# はじめに

AWSの「.aws/config」と「.aws/credentials」ファイルは、AWS CLIやSDKを利用する際に認証情報や設定を管理するための重要なファイルです。それぞれの役割と特徴について以下に解説ます。

# 解説

| ファイル | 主な用途 | 機密性 |
| --- | --- | --- |
| .aws/config | 設定オプション (リージョン、出力形式など) | 機密性低 |
| .aws/credentials | 認証情報 (アクセスキー、シークレットキー) | 機密性高 |

```.aws/config
[default]
region=us-west-2
output=json

[profile prod]
region=ap-northeast-1
output=json
```

```.aws/credentials
[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

[prod]
aws_access_key_id=YYYYYYYYYYYYYYYYYYYY
aws_secret_access_key=YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
```

# 設定方法

1. AWS CLIで設定コマンドを実行

```bash
$ aws configure --profile <プロファイル名>
AWS Access Key ID [None]: <アクセスキーID>
AWS Secret Access Key [None]: <シークレットキー>
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

2. 手動設定

ファイルを直接編集してプロファイルや設定を追加できます。

# 使用方法

```bash
$ aws s3 ls --profile <プロファイル名>
```

## 環境変数で指定

環境変数`AWS_PROFILE`を設定することで、デフォルトで使用するプロファイルを指定できます。

```bash
# Linux/Macの場合
$ export AWS_PROFILE=<プロファイル名>

# Windowsの場合 (コマンドプロンプト)
> set AWS_PROFILE=<プロファイル名>

# Windows PowerShellの場合
> $env:AWS_PROFILE="<プロファイル名>"
```

## 現在の設定確認

現在の設定や利用可能なプロファイル一覧を確認するには以下のコマンドを使用します。

```bash
# 現在の設定確認
$ aws configure list

# プロファイル一覧表示
$ aws configure list-profiles
```

# 参考
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-files.html
【備忘録】Gitで自分のローカルでだけ特定ファイルを無視する

excludeファイルを使用して`.gitignore`と同じ記法で、リポジトリの自分だけの除外設定ができる。

### 使い方
任意のエディタ等で`exclude`ファイルを開く

```bash
# プロジェクトのルートに移動した上で以下コマンド
code .git/info/exclude
```

ファイルを開いたら`.gitignore`と同じ要領でgitの追跡を無視したいファイル/ディレクトリを指定する。


```bash
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

# ローカル限定の除外設定
.env.local
*.code-workspace
logs/
```

vscodeに設定を反映させるためにウインドウのリロードを行えばファイルが無視される。
変な文字が入ってて開けないエクセルをコマンドとかでなんとかして開けるようにする

## 開けないエクセル（xlsx）
業務系システムまわりで単純にデータをエクスポートしたのに開けないエクセルが出来上がることがある。
出るエラーは
「〜〜の一部の内容に問題が見つかりました。〜〜」
で「はい」を押して開いてもほぼ中身がない状態になり、もう意味をなしてない。

### 原因
単純なデータのみだとだいたいどこかのセル内に制御文字などが紛れてる。
xlsx形式はzipと同等なので拡張子変えれば解凍できる。
その中に `xl/sharedStrings.xml` というファイルがあり、その中にセル内の文字データが入ってる。
で&#で検索すると `&#x1F;` みたいに入ってることがある。

### コマンドでなんとかする
unzipでsharedStrings.xmlを出してやってxmllintかける
`unzip -p エクセルファイル.xlsx xl/sharedStrings.xml | xmllint --format -`
でやるとエラーになってる箇所を出してくれる。

### エラーがわかれば
できればコマンドでsedかけて元のzipに戻す、ができたらいいけどなんか簡単でなかった。
なんとvimでzipファイル内を直接編集できるので、vimで置換かけて保存。
無事に開けるようになりました。

#### 余談
なんかrubyとかそのへんの言語で簡単にエラー箇所がわかればいいな、と思ったが意外によしなにエラー箇所を出してくれないみたいだった。なのでちょっと手間ではあるが上記方法に落ち着いた。
IPhone XS Max を Convert した話

youtubeで古いiphoneを最新のものに改造するという投稿を見て私もチャレンジすることにしました。
中国から外装部品を取り寄せて手持ちのiPhoneのロジックボードやカメラや実装部品を外し、取り付けます。届くまでに一週間以上かかりました。

私は不器用ですが電子工学とか電子回路とか大好きです、でも全く無知です。ワクワクしながら作業にあたりました。

画面を外すのに苦労しました。どのねじがどのドライバーかわかりませんでした。このドライバーのはずなのに違うというありえない状況の中作業をすすめました。

何とか本体と画面を分離できました。バッテリーのコネクタを外し、すべてのコネクタを外し、ネジと部品を外していきました。

どれがどこのネジかわかるようにするはずでした。
どれがどこにあったパーツかわかるようにするはずでした。
でも、この細かいパーツはなんだ？このネジはなんだ？と　なりました。
大まかな組み立て方は、売り手が適当に作った組み立て動画がYouTubeに投稿されているので参考にしながら組み立てました。

何時間たっていたかわかりません。
何とか、画面を取り付けることができました。

ネジは4本余り、謎の部品が3つくらい余りました。捨てました。

あくる日、Suicaが使えませんでした。
NFCのアンテナを壊したみたいです。
余計なことをするものではないですね。

もう一度16plus(ウルトラマリン)を購入して、NFCアンテナパーツも購入してチャレンジしてみたいと思います。
Herokuにデプロイしようとしたらnot a git repositoryのエラーが発生した

## やりたいこと
#### Herokuにアプリをデプロイしたい。


## やりたいこと
#### 以下のコマンドをターミナルに入力した。
```
git add .
git commit -m "deploy to heroku"
git branch -M main
git push heroku main
```
## 発生したエラーの内容
```
fatal: not a git repository (or any of the parent directories): .git
fatal: not a git repository (or any of the parent directories): .git
fatal: not a git repository (or any of the parent directories): .git
fatal: not a git repository (or any of the parent directories): .git
```

## エラー解決方法

Gitリポジトリに移動する
```
git status
```

しかし
```
fatal: not a git repository
```
というエラーが発生してgitリポジトリが設定されていないことが判明したので
```
git init
```
でgitリポジトリを作成
さらに、、、
```
heroku git:remote -a <heroku-app-name>
```
でherokuのリモートリポジトリを追加

そこで再度冒頭の
```
git add .
git commit -m "deploy to heroku"
git branch -M main
git push heroku main
```
のコマンドを打ったら解消されました。
## エラーの原因

今回のエラーの原因は、実行しているディレクトリが Gitリポジトリではないため発生しました。
具体的には、Gitはプロジェクトディレクトリに .git という隠しフォルダが必要ですが、このフォルダが存在しないため、Gitコマンドが実行できません。

そこでgit initでリポジトリを作成し、heroku git:remote -a <heroku-app-name>でリモートリポジトリを追加したところ解消されました
JSでパスワードの表示・非表示をする

ユーザーが入力したパスワードを、"*****" のような隠された形で表示する。
Lock Password をクリックすると、input タグに入力することができなくなり、
さらにそのパスワードを lockedPassDiv に表示する処理を作成

html
```
<head>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<div class="m-2">
    <div class="col-12">
        <label for="passwordClick">Password</label>
        <input id="passwordClick" type="password">
    </div>
    <div class="col-12">
        <label for="passwordClickCheck">Show/Hide Password</label>
        <input type="checkbox" id="passwordClickCheck" onclick="passwordToggle()">
    </div>
    <div class="col-12">
        <!-- onclick -->
        <button onclick="lockPass()">Lock Password</button>
    </div>
    <h3 class="mt-5">Password</h3>
    <div id="lockedPassDiv" class="col-12">

    </div>
</div>
```

js
```
function passwordToggle(){
    const pass = document.getElementById("passwordClick");
    pass.type = pass.type === "password" ? "text" : "password";
}

function lockPass(){
    const pass = document.getElementById(`passwordClick`);
    const target = document.getElementById("lockedPassDiv");

    // パスワードがなければescape
    if(pass.value === "") return;

    // disable属性をtrueに設定することによってpasswordをロック
    pass.disabled = true;

    const p = document.createElement("p");
    p.innerHTML = pass.value;

    // 入力されたpasswordをdivに追加
    target.append(p);
}
```
特定アプリのRosetta 2の切り替えを1ボタンで

# Rosetta 2の併用ダルくない？
AppleSiliconのmacでDTMやってると機能ｙプラグインのApple Silocon対応具合がまちまち。
なのでDAW(Logic)をRosetta 2で起動したり普通に起動したりしたいが、通常だと
1. アプリケーションフォルダに移動
1. 情報を開く
1. ボタンポチ
が工程として必要でダルい。
![スクリーンショット 2025-03-29 13.31.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059738/cc6fe708-ddee-4d6c-ac1f-82f75136756d.png)

1ボタンでやれるようにします。

# 準備
調べてみるとSetArchPrefForURLという便利なモノで実現できそう。
https://github.com/tapthaker/SetArchPrefForURL
※以下README斜め読みで自分ができた手順、という感じなので嘘言ってても許してください。

これをZipでDLすると
![スクリーンショット 2025-03-29 13.13.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059738/172f8131-a0f4-4db5-a5bf-38ccb4ad8e6d.png)
という感じ。
一番下の```SetArchPrefForURL.xcodeproj```を開いて左上の▶でビルド。
![スクリーンショット 2025-03-29 13.15.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059738/9f2c2304-fbb4-4985-8aec-f7db7fa6534f.png)
```Build Succeeded```と表示されれば成功。

# 使い方
Xcodeのウィンドウをある程度大きくすれば右下にUsageが表示されているはずなのでそれを実行すればOK。
![スクリーンショット 2025-03-29 13.25.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059738/a428fd02-99fb-4ad2-ab9c-8efbfabfe6cd.png)

コマンドでもいいですがスクリプト化しちゃえば1ボタンですね。

## Rosseta 2を有効にする(Intel)

```
/Users/<User>/Library/Developer/Xcode/DerivedData/SetArchPrefForURL-<hogehoge>/Build/Products/Debug/SetArchPrefForURL "/Applications/Logic Pro X.app" x86_64
```

## Rosseta 2を無効にする(Apple Silocon)
```
/Users/<User>/Library/Developer/Xcode/DerivedData/SetArchPrefForURL-<hogehoge>/Build/Products/Debug/SetArchPrefForURL "/Applications/Logic Pro X.app" arm64
```

## 自分の使い方
スクリプト化してそれぞれフォルダに入れてDockに設定してます。
![スクリーンショット 2025-03-29 13.58.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059738/90226bcd-206d-4f35-988c-dd1f83a1fdfc.png)
![スクリーンショット 2025-03-29 13.58.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059738/629fd31c-105d-4747-ac5e-8e562dbb8bde.png)

# 追記：スクリプト終了でターミナルのウィンドウを消したい
スクリプト終了時にターミナルの画面が残るの鬱陶しい。
調べた感じスクリプトの中で解決するには
```
osascript -e 'tell application "Terminal" to close first window'
```
で行けそうだけど
![スクリーンショット 2025-03-29 13.45.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059738/29e283d8-2457-4abe-bee4-add616b575c8.png)
勝手に消してはくれない。

ターミナル全体の設定で消すようにするしかないっぽい。
![スクリーンショット 2025-03-29 13.46.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059738/edc4fafc-0e0e-4147-8807-7434b949e3ce.png)

# 雑記
今の状態がメニューバーに常時表示されてて切り替えできる、みたいにできたらなあと思いつつ、気力不足なので誰か頼みました、、、。

# 追記2: Logic Proのパスが変わってた
Logic Proがバージョンアップしたら使えなくなって悲しみにくれていたらパスが変わっていた。
```
/Users/<User>/Library/Developer/Xcode/DerivedData/SetArchPrefForURL-<hogehoge>/Build/Products/Debug/SetArchPrefForURL "/Applications/Logic Pro.app" x86_64
```
"X"が取れたのね、、、逆になんで今までついてたのｋ
はじめまして, Qiita

# 現在の自分について
 * 新卒でSIer入社。最初の1年は開発・運用・保守など。2年目以降は営業（？）の方へ
 * Java(Springboot)で少しの開発経験（しかしSQLは死ぬほど苦手）
 * Python, Cも参考書程度

 前々から何か自分で一から作ってみたいという気持ちがあった。自分が使えればいい・分かればいいという感覚で数行程度のツールなどは作っていたが、営業側になって、他人も使える・良いと思ってもらえるものを作りたくなった。ただどうしても個人のモチベーションが続かず、グダグダ今に至る。このままではまずいと思い、JISOUさんに参加。

# 将来について
* 短期目標：アウトプットの習慣をつける。入浴・歯磨き・Qiita記事投稿(tweetでも)
* 中期目標：自分で（しょうもなくても）アプリやサービスを1つ構築する
* 長期目標：収益化できるようなサービスの開発
* 超長期～：独立
私が使用する開発ツールまとめ【2025年度】



## 1. エディタ

### Cursor（カーソル） 
  ChatGPTが統合されたAIエディタ。プログラムファイルを作成するのに使用。

https://www.cursor.com/ja

## 2. バージョン管理

### Git + GitHub
  ソースコードをバージョンごとに管理するために使用。普段の操作にはGUIツールの**GitHub Desktop**を利用している。

https://git-scm.com/

https://github.co.jp/

https://docs.github.com/ja/desktop/installing-and-authenticating-to-github-desktop/installing-github-desktop

## 3. デザイン・メモ

### Figma
  開発前のプロトタイプ設計や、チームとのデザイン共有に使用。

https://www.figma.com/ja-jp/downloads/

### Notion 
  メモ用として活用。シンプルなUIで書きやすく、整理しやすいのが魅力。書いたメモは勝手にクラウド上に保存されるので消失のリスクが低い。

https://www.notion.com/

## 4. 情報収集ツール

### ChatGPT
  わからない文法やエラーが出た時にまず相談。コーディングやアイデア出しにも活用している。
  
https://openai.com

### Google検索  
  ChatGPTで解決しない場合や、より具体的な情報が欲しいときに使用。

## 5. アウトプット

### Qiita  
  開発中に遭遇したエラーの解決過程や、学んだ知識の整理・共有に利用。

https://qiita.com/
Substance 3D Painterのロギング

## 環境
* Windows
* Adobe Substance 3D Painter 10.1.2

## logging module

Substance 3D Painterでは専用のロギングモジュールが用意されています。

### 基本的な使い方

ログのレベルに合わせて ```info()```、```warning()```、 ```error()``` の3つの関数が用意されており、Logウインドウに表示される文字の色もレベルに応じて変わります。

```python
from substance_painter import logging

logging.info("INFO")
logging.warning("WARNING")
logging.error("ERROR")
```

![sp_log_00.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965005/ea64d74e-3c74-4772-ac0a-b84612117de2.jpeg)

### レベル・チャンネルの指定

上記3つの関数とは別に ```log()``` も用意されており、この関数を使用するとログのレベルとチャンネルを指定できます。

```python
logging.log(level, channel, message)
```

レベルに関しては
* ```substance_painter.logging.INFO```
* ```substance_painter.logging.WARNING```
* ```substance_painter.logging.ERROR``` 

と、デバッグ用のレベルとして
* ```substance_painter.logging.DBG_INFO```
* ```substance_painter.logging.DBG_WARNING```
* ```substance_painter.logging.DBG_ERROR``` 

が指定できます。
デバッグ用のレベルでの出力はLogウインドウには表示されず、ログファイルにのみ記録されます。チャンネルに関してはメッセージの出所を明確にするための名前として任意の名前を指定できます。

```python
from substance_painter import logging

logging.log(logging.INFO, "SAMPLE", "INFO")
logging.log(logging.WARNING, "SAMPLE", "WARNING")
logging.log(logging.ERROR, "SAMPLE", "ERROR")

logging.log(logging.DBG_INFO, "SAMPLE_DEBUG", "DBG_INFO")
logging.log(logging.DBG_WARNING, "SAMPLE_DEBUG", "DBG_WARNING")
logging.log(logging.DBG_ERROR, "SAMPLE_DEBUG", "DBG_ERROR")
```

![sp_log_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965005/5986416e-8cb2-4a77-976d-551a11eebc80.jpeg) ![sp_log_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965005/6cfdef68-d25f-44f4-8d80-d1fd875f556a.jpeg)
左がLogウインドウ、右がログファイルです。

### ログファイルについて

Help メニューの ```Show log...``` で表示、```Export log...``` で保存できます。

![sp_log_03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965005/9f4e29c3-231e-4430-97d7-3c7fcce4031c.jpeg)


また、```%LOCALAPPDATA%\Adobe\Adobe Substance 3D Painter\log.txt``` から直接確認することもできます。


## 参考

* [Substance 3D Painter Python API logging](https://helpx.adobe.com/substance-3d-painter-python/api/substance-painter/logging.html)
【就活生必見】キャッシュを使ってフィボナッチ数列の計算を爆速にする ~Python編~

## 🧠 フィボナッチ数列とは？

フィボナッチ数列とは、以下のような規則で定義される数列です。

```
0, 1, 1, 2, 3, 5, 8, 13, ...
```

数式で書くとこう

```
F(n) = F(n-1) + F(n-2)
F(0) = 0, F(1) = 1
```

---

## 🐢 遅い再帰実装

```python
def fib(n):
    if n <= 1:
        return n
    return fib(n - 1) + fib(n - 2)
```

**シンプルだけど超遅い**です。

例えば `fib(40)` を計算しようとすると、**何十万回も同じ関数が呼ばれる**ため、爆遅になります。

---

## ⚡ 裏技：キャッシュ（メモ化）で爆速に！

### ✅ 方法①：`functools.lru_cache` を使う

```python
from functools import lru_cache

@lru_cache(maxsize=None)
def fib(n):
    if n <= 1:
        return n
    return fib(n - 1) + fib(n - 2)
```

これだけで **劇的に高速化されます**。

```python
print(fib(100))  # 354224848179261915075（即出る！）
```

---

## 🔥 なぜ速くなるの？

再帰関数の中で同じ引数が何度も計算されるのを、**キャッシュして再利用**してくれるからです。

例えば `fib(10)` を求めるとき、普通なら `fib(8)` を2回計算するところを、1回で済ませて再利用できます。

---

## ✅ 方法②：手動で辞書を使うメモ化（試験で lru_cache が使えないとき）

```python
memo = {}

def fib(n):
    if n in memo:
        return memo[n]
    if n <= 1:
        result = n
    else:
        result = fib(n - 1) + fib(n - 2)
    memo[n] = result
    return result
```

`memo` に計算済みの結果を保存しながら進むことで、**無駄な再計算を防ぎます**。


## ✅ まとめ

| 実装 | 特徴 | 実行速度 |
|------|------|-----------|
| 普通の再帰 | シンプルだけど遅い | ❌ |
| `@lru_cache` 使用 | 速くて楽| ✅✅✅ |
| 手動メモ化 | 試験対応にも使える | ✅✅ |
『早計な最適化は諸悪の根源』とは👀？

## はじめに

「[読みやすいコードのガイドライン](https://gihyo.jp/book/2022/978-4-297-13036-7)」という本を読んでいる中で、

### 早計な最適化は諸悪の根源

<br>
という言葉が紹介されていたので、この内容について記したいと思います。

## 早計な最適化は諸悪の根源...👀

この言葉はDonald Knuth氏が提唱された考えでして、[^1]

計算時間の最適化や使用メモリの効率化などといったパフォーマンスの向上施策は、

その実に97%が無駄であり、かえって逆効果になることもあるので、

まずは可読性やメンテナンス性が高く、

変更容易性があるコードを書く方が良い、

といった考え方のことです。

ユースケースとしては...
<br>

* 可変なオブジェクトの使い回し

* 遅延初期化

* キャッシュ

<br>
といったことが挙げられています。

また、上記内容についてより分かり易く解説していただいている

記事もありました。

https://qiita.com/shuetsu@github/items/95370b6c208901db3a5e

こちらの記事の中では...

> たとえば処理Ａの過程でできたリソースを、せっかくだから処理Ｂで使いまわせば
効率が良いじゃないか、といったことが行われます。
もったいない精神と考えてもいいかもしれません。

このように具体例を交えて解説していただいていますが、

確かにこういったシーンってありますよね💦
<br>

ただこの場合、引用元の記事の中でも解説されていますが、

処理Bは処理Aに依存することになり、処理Aの修正は処理Bにも波及し、

処理Bを修正する際は処理Aにもそれが波及する、といったことが起こってしまいます。。。
<br>

このような状況になってしまうと、

プログラムがどのように走っているのかを掴みづらくなり、

コードの修正や機能追加、新規機能の開発をする際にも

それをやりづらくしてしまったり、または欠陥となって故障に繋がる...

といったことが起こってしまいそうですよね。。。😨

ユーザー視点に立ってパフォーマンスを改善したつもりが、

コードや設計の悪化によりデグレーションに陥り、

かえってユーザーに不利益を与えてしまう。。。

これだとちょっと悲しいですよね😣
<br>

https://nigiri.hatenablog.com/entry/2024/11/24/202536

こちらの記事の中で解説されていたことを踏まえまして...
<br>

* まずは綺麗なコードを書くこと

* 上流工程から要求や要件、仕様をきちんと定義すること

* 真に解決したいこと、妥協してもいいことはないのか考えること

* 実は別のより良い解決案がないかなどを模索し提案すること

* シフトレフトを適用し、試験性を確保して、リスクを減らしていくこと

<br>
こういったことをまず最初に行うことが重要なんでしょうね🤔


## 参照

[読みやすいコードのガイドライン](https://gihyo.jp/book/2022/978-4-297-13036-7)

https://qiita.com/shuetsu@github/items/95370b6c208901db3a5e

https://nigiri.hatenablog.com/entry/2024/11/24/202536

https://zenn.dev/coconala/articles/82b6117fcb9b59

https://jabba.cloud/20160403202837

[^1]: 「読みやすいコードのガイドライン」 第1章 33頁
JawsDBのアドオンを追加しようとした時に発生したエラーの解消法

## やりたいこと
1. JawsDBのアドオンを追加すること
データベースのMySQL（MariaDB）を利用してWebアプリを作成しました。
しかし、Herokuが公式にサポートしているデータベースはPostgreSQLなので、そのままでは正しく動作しません。
そこで、JawsDBというアドオンを利用すればHerokuでもMySQLが使えるようになるということがわかったので、以下のコマンドを実行してJawsDBのアドオンを追加しようとしました。
```
heroku addons:create jawsdb-maria:kitefin
```

## 発生したエラーの内容
```
apple@appurunoAir laravel-samuraimart % heroku addons:create jawsdb-maria:kitefin
 ›   Error: The following error occurred:
 ›     Missing required flag app
 ›   See more help with --help
```

## 解決法
#### --app フラグを使って、アドオンを追加したいHerokuアプリ名を指定した
```
heroku addons:create jawsdb-maria:kitefin --app app-name
```
※app-nameには任意のアプリ名が入ります
#### アプリ名が不明な場合
```
heroku apps
```
コマンドで確認しましょう
✅ TypeScriptエラー「Import 'xxx' conflicts with local value」の対処法

## 書いていたもの

```ts
// BodyPartMenu関数の引数に渡すオブジェクトの型を定義している
import { BodyPartMenu } from "../types/bodyPartMenu"

export default function BodyPartMenu({
  name,
  time,
  calories,
  icon = '🏋️',
}:BodyPartMenu) {
  return (
    <div className="bg-white rounded-xl shadow flex flex-col p-4 transition hover:bg-blue-50 hover:shadow-lg">
     ......
     .......
```

## 💥 エラー内容

```ts
Import 'BodyPartMenu' conflicts with local value, so must be declared with a type-only import when 'isolatedModules' is enabled.ts(2865)
```

## 🧠 原因

- 関数の引数用にで使っている **型の名前** と **コンポーネント（関数）の名前** が **同じ**
- `tsconfig.json` の `isolatedModules: true` 設定により、**型と値が混ざるのを禁止**している

---

## ❌ （再掲）NG例

```tsx
import { BodyPartMenu } from "../types/bodyPartMenu" // ← 型だけど普通のimport

export default function BodyPartMenu({ name }: BodyPartMenu) {
  ...
}
```

一番最初に上げた自分の例のように
このままだと、**BodyPartMenu が「型」と「関数」で名前かぶってエラーになる**！

---

## ✅ 解決方法①：`import type` を使う！

```tsx
import type { BodyPartMenu } from "../types/bodyPartMenu"

export default function BodyPartMenu({ name }: BodyPartMenu) {
  ...
}
```

これで「これは型専用importだよ」と明示することで解決💡

---

## ✅ 解決方法②：型と関数の名前を分ける（おすすめ）

```tsx
import type { BodyPartMenu as WorkoutItemProps } from "../types/bodyPartMenu"

export default function BodyPartMenu({ name }: WorkoutItemProps) {
  ...
}
```

### メリット
- 型と関数で意味を分けられて **読みやすい**
- 今後の保守性・拡張性も高い！

---

## ✅ まとめ

| 状況 | 対応方法 |
|------|----------|
| 型だけ使う | `import type { XXX } from ...` |
| 型名と関数名がかぶる | `as` で別名にする or 関数名を変える |

---
Herokuが提供しているMailgunのアドオンを追加した時に出るエラーの解消法

## やったこと

本番環境（Heroku）のSMTPサーバーとして、Herokuが提供しているMailgunのアドオンを利用したいと思い、以下のコマンドを実行してMailgunのアドオンを追加しようとした

```
heroku addons:create mailgun:starter
```
## 発生したエラーの内容

以下のようなエラーが発生し、appフラグが不足していることを示していた。

```
 ›   Error: The following error occurred:
 ›     Missing required flag app
 ›   See more help with --help
```

## 解決法

### Appコマンドを実行する際に、--app オプションで対象のアプリ名を指定

例えば、アプリ名が my-app-name の場合、以下のようにコマンドを修正します：
```
heroku addons:create mailgun:starter --app my-app-name
```
※アプリ名が不明な場合は、、、
```
heroku apps
```
コマンドで確認しましょう
【０から目指すAIエンジニア】Day1：uvのインストールからテンプレートと仮想環境の作成まで

# はじめに
こんにちは、慶應義塾大学理工学部機械工学科3年の金賢佑です！
私は東大発AIベンチャーの株式会社2WINSの元でインターンをしています！

これからの記事では自分がインターンを通して最強のAIエンジニアを目指していきます！
第一回はuvの基礎を記録しました！

# uvとは
uvとは2024年に発表された、パッケージ管理ツールです。Rust製でpipの代替ツールとして登場しました。

![スクリーンショット 2025-04-01 15.02.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4047475/62c7420e-c59e-4acf-bb68-952aba871db4.png)
引用:https://docs.astral.sh/uv/

画像にあるようにpipよりも処理速度が断然速いですね。

### パッケージ管理ツールとは？そもそもパッケージとは？？
パッケージとは、様々なモジュールをまとめたものです。
モジュールとは、(.py)などのプログラムファイルやドキュメントを含みます。

そんなパッケージですが、実は、それぞれは独立して存在するわけではなく互いに依存関係があることが多いのです。
例えば、
「パッケージAを実行するためには、パッケージBが必要で、パッケージBを実行するにはパッケージCが必要で....」
といった様にです。

パッケージ管理システムとはそうしたパッケージ同士の依存関係を把握し、必要なものを取り揃えてくれます！優秀！

もし、パッケージ管理システムがなければ、自分で必要なモジュールをとってこなくてはならないわけですから、とても大変ですね。

# uv使ってみた

まずはuvをインストールしていきましょう。
terminalで以下のコマンドを入力してみます。
```shell-session
$ curl -LsSf https://astral.sh/uv/install.sh | sh
```
everything's installed!と出てきたら大丈夫です。

では、ここから少しuvを使ってみます。

### テンプレートを作成
例えば、

```shell-session
$ uv init example
```
はテンプレートを作成するコマンドです。

```shell-session
$ ls
README.md	main.py		pyproject.toml	uv.lock
```

の時、上記　$ uv init example　を行うことによって

```shell-session
$ uv init example
$ ls
README.md	example		main.py		pyproject.toml	uv.lock
```
テンプレート`example`が作成されましたね。

exampleの中には
```shell-session
$ cd example 
$ ls
README.md	main.py		pyproject.toml
```
などがありますね。

`README.md`にはプロジェクトの説明などが書かれています。

`main.py`にはPythonプロジェクトにおけるエントリーポイントがあります。エントリーポイントとは一番最初に呼び出されるプログラムのことです。

ちなみに`main.py`にはデフォルトで以下のコードが記述されています。
```python:main.py
if __name__ == "__main__":
    main()
```
これは他のモジュールでインポートされて使われた時にmain()の実行部分が使用されないようにするためです。

`pyproject.toml`にはプロジェクト名やバージョンなどが書かれています。


### 仮想環境のセットアップ
```shell-session
$ uv sync
```
により仮想環境がセットアップされます。
このコマンドでは`uv.lock`と`pyproject.toml`に書かれているパッケージの依存関係も考慮してくれます。
最初に話したバージョン管理の話ですね。
`pyproject.toml`にある情報と`uv.lock`のキャッシュとの間に差が会った時など自動で解消してくれます。


## まとめ
今回はuvをインストールし、実際にテンプレートを作成したり、仮想環境を構築してみました！
次回からはlangchainなども扱っていきたいと思います。

## おまけ

下記コマンドでVScodeに移動。
```shell-session
$ code <フォルダ>
```
Xcodeだったら
```shell-session
$ xed <フォルダ>
```
となる。

ファイルを削除するとき、空のディレクトリであれば
```shell-session
$ rmdir <フォルダ>
```
で良いのだが、最下層ではない場合は再起的な消去が必要となり、そのコマンドは
```shell-session
$ rm -r <フォルダ>
```
となる。
Unity - 知っておいてよかった！～Update関数を順番に実行する方法～

### ゲーム開発で必ず起こること
ある日、プログラムを書いているとこんなことが起こりました。
>「よっしゃ。オブジェクトについてくるスクリプトが書けたぞ！」
>で、実行します。
>「我ㄉㄊ阿！**バグ**ってるぅ～」
>オブジェクトは、完全にオブジェクトにぴったりついている訳ではなく、ちょっとずれていることがありました。

こんなプログラムの苦悩、そして**バグ**は、皆さん一度は経験したことありますよ**ね** ((圧
今回のバグでは、スクリプトの`Update関数`が本来プログラマーの想定している順序と違った順序で実行されていて、バグが発生しているというものです。
これを解決する方法はあるのでしょうか？

今回は、`Update関数`を、指定した順番通りに実行する方法を解説します。
* * *
### 本題～Update関数を指定した順番通りに実行する～
まず、`Project Settings`を開きます。
開き方は、`Edit` > `Project Settings`です。
![スクリーンショット (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4042593/585ee24c-0c2b-4a3a-afcc-88eef7e2938c.png)
そして、`Project Settings`内の`Script Execution Order`を開きます。
![スクリーンショット 2025-03-29 114201.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4042593/fb0bcb11-a9cb-4c3d-b282-265ddd5b219d.png)
この`Script Execution Order`の中には、画面をリアルにする処理や、UIを更新する処理があらかじめ設定されています。
ここから、順番に実行したいスクリプトを追加していきます。
処理のリストの下にあるボタン`＋ ▼`をクリックして、順番に実行したいスクリプトを、**できれば想定している順番に**入れていきます。
![スクリーンショット 2025-03-29 115802.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4042593/8f34dec7-aaf6-4a5f-a5a9-98f5e2940d18.png)
私の場合は、`SplineSystem.cs`>`RearWheel.cs`>`TrainTransform.cs`の順番に実行したいので、このような組み合わせにしています。
設定できたら、**忘れずに`Apply`を押しましょう**。
* * *
### 数字の意味は？
そういえば、先ほどの画像で、`100`や`200`のように数字が指定されていましたよね。
これって何なのでしょうか？
公式からの説明を参考にしてみます。

https://docs.unity3d.com/ja/current/Manual/class-MonoManager.html

こんなことが書かれていました。
>割り当てられた番号は、相対的な順序を表しています。Unity はリストを上から下の順に (大きな負の順序番号のスクリプトから大きな正の順序番号のスクリプトに向かって) 実行します。

つまり、**数字が小さく設定されてる処理から大きくなっている処理の順に、処理を実行している**ことになります。
ただ、こんなことも書かれていました。
>順序番号は任意であり、物理的な量を表すものではありません。

ということは、実行したい順に番号指定した場合、`0`>`100`でも、`1`>`2`でも処理の実行手順は変わらないことになります。

:::note info
リスト内の処理をドラックして順序を変更することもできます。
:::

***
### まとめ
今回は、スクリプトの`Update関数`を指定した順番通りに実行する方法を解説しました。
Script Execution Orderから、実行したい順番にスクリプトを入れてあげると実行できます。
また、この記事に関するヒントを与えてくださった[Meredoth](https://discussions.unity.com/u/meredoth/summary)さんに感謝いたします。
***
参考サイト①：[Can Unity Scripts run the Update mesos in order? - Unity Engine - Unity Discussions](https://discussions.unity.com/t/can-unity-scripts-run-the-update-mesos-in-order/1619144)
参考サイト②：[Script Execution Order - Unityマニュアル](https://docs.unity3d.com/ja/current/Manual/class-MonoManager.html)
※`メゾット`の英訳は`Mesos`ではなく`Method`です。タイトルは誤字がありますのでご注意ください。
岡本一洋とは？経歴・実績・専門スキルを徹底解説

## 岡本一洋とは？

岡本一洋（おかもと かずひろ）は、ネイティブアプリ開発を得意とするエンジニアであり、現在は複数のスタートアップ企業を支援する形で活躍しています。特に生成AIの活用に精通しており、最新技術を駆使したアプリ開発に強みを持っています。

### 経歴

岡本一洋のキャリアは、早稲田大学卒業後、大手IT企業NTTデータへの入社からスタートしました。そこでシステム開発やプロジェクト管理の経験を積み、その後スタートアップ業界へ転身。現在は3社のスタートアップ企業を技術支援しながら、フリーランスとしても活動しています。

- **早稲田大学卒業**
- **NTTデータにてエンジニアとして勤務**
- **スタートアップ企業3社で技術支援**
- **ネイティブアプリ開発を専門とするフリーランスエンジニア**

## 専門スキルと強み

### 1. ネイティブアプリ開発

岡本一洋は、iOSおよびAndroid向けのネイティブアプリ開発に長けています。SwiftやKotlinを駆使し、ユーザー体験を重視したアプリを開発してきました。

### 2. 生成AIの活用

近年、生成AIを活用したアプリ開発に力を入れており、ChatGPTなどのLLM（大規模言語モデル）を活用したプロダクトの開発経験があります。

### 3. クラウドインフラの知識

AWSやGCPを活用したクラウドアーキテクチャの設計・構築も得意とし、スケーラブルなシステム構築を実現しています。

### 4. スタートアップ支援

複数のスタートアップ企業に技術顧問として関与し、システム開発の戦略立案から実装、運用まで幅広く対応しています。

## 岡本一洋が手がけたプロジェクト

1. **AIチャットボットアプリ**：ChatGPTを活用したカスタマーサポート向けアプリ
2. **ECプラットフォーム**：スマートフォン向けのECアプリを開発
3. **フィットネスアプリ**：機械学習を活用したパーソナライズドトレーニングアプリ

## 今後の展望

岡本一洋は、今後も最先端技術を活用したアプリ開発に注力し、特に生成AIやWeb3領域のプロジェクトにも関わっていく予定です。

## まとめ

岡本一洋は、ネイティブアプリ開発を軸に、生成AIやクラウド技術を駆使して幅広いプロジェクトを手がけるエンジニアです。大手企業での経験とスタートアップ支援の実績を活かし、今後も革新的な技術で業界に貢献していきます。

**岡本一洋に関するお問い合わせや、開発依頼はお気軽にどうぞ！**
#include Windows.hしたときにinterfaceという変数名が使えない

# 概要

MSVCの環境で変数名に`interface`という命名をしたところ、以下のようなエラーが出た。

実際のコード:
```cpp
int main() {
    int interface = 20;
    printf("%d", interface);
    return 0;
}
```

エラー:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4048221/7f3fa0be-1d2c-4530-9aed-3c53b6793b95.png)

# 結論

~~どうやら、MSVCの予約語に`interface`が含まれておりその予約語を使用した命名や関数の定義を行うとエラーが出るらしい。~~

`#include <Windows.h>`をした時のものによる影響でした。 (2025/03/31)

(Visual Studioではわかりやすくハイライトされたが、ClionやVSCodeではハイライトされなくて分かりにくかったのでメモ)
🚀Docker開発コンテナからGitHubへSSH接続するまでの手順【VSCode × Dev Container対応】

こんにちは。今回は、**VSCodeの開発コンテナ（Dev Container）からGitHubにSSHで接続して、Git操作できるようにする方法**を、ステップバイステップでまとめました。

DockerやDev Containerを使ってローカル開発環境を整えている方は、GitHubへの接続設定もコンテナ側で行う必要があります。HTTPS接続ではなく、SSH接続を使うことで毎回のトークン入力が不要になり、快適な開発が可能になります。

---

## ✅ 前提条件

- GitHub アカウントを持っている
- Docker 環境が整っている
- VSCode で Dev Container を使って開発している
- 開発コンテナに `git` がインストール済み（`apt install git` などで）

---

## 🧭 手順まとめ

---

### 1. 開発コンテナに入る

VSCode の Dev Container（Remote Containers）を立ち上げて、コンテナ内のターミナルを開きます。

```sh
# 例
root@container-name:/app#
```

---

### 2. 開発コンテナ内で SSH鍵を作成する

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

- 保存先の指定はそのまま Enter（例: `/root/.ssh/id_ed25519`）
- パスフレーズは必要に応じて（セキュリティ重視なら設定推奨）

---

### 3. 公開鍵の中身を確認する

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

表示された**公開鍵（`ssh-ed25519` で始まる長い1行）**をすべてコピーします。

⚠️ この公開鍵は GitHub に登録して使うものです。**秘密鍵（`id_ed25519`）は絶対に公開しないようにしましょう。**

---

### 4. GitHub に SSH 公開鍵を登録

GitHub にログインし、以下の手順で SSH キーを追加します。

- 右上アイコン → `Settings`
- 左メニュー `SSH and GPG keys` → `New SSH key`
- `Title`: 任意（例: `DevContainer`）
- `Key`: コピーした公開鍵を貼り付ける
- `Add SSH key` をクリック

---

### 5. SSH接続確認（初回）

```sh
ssh -T git@github.com
```

初回のみ以下のような確認が出ます：

```txt
Are you sure you want to continue connecting (yes/no)?
```

→ `yes` と入力

成功すると：

```
Hi your-username! You've successfully authenticated, but GitHub does not provide shell access.
```

と表示されます。

---

### 6. リモートURLをSSH形式に変更

HTTPS形式のままだと毎回トークンが必要になります。SSH形式に変更しておきましょう。

```sh
git remote set-url origin git@github.com:your-username/your-repo.git
```

確認：

```sh
git remote -v
```

↓

```
origin  git@github.com:your-username/your-repo.git (fetch)
origin  git@github.com:your-username/your-repo.git (push)
```

---

### 7. Git操作OK！

あとは通常通りの Git 操作ができます！

```sh
git pull origin main
git push origin main
```

---

## 💡補足：`dubious ownership` エラーが出た場合

コンテナ内で Git を使おうとしたとき、こんなエラーが出ることがあります：

```
fatal: detected dubious ownership in repository at '/app'
```

この場合は以下のコマンドで対処できます：

```sh
git config --global --add safe.directory /app
```

---

## ✅ まとめ

| 項目 | メリット |
|------|----------|
| SSH接続 | 毎回の認証不要、CI/CDにも最適 |
| HTTPS接続 | シンプルだが、毎回トークン入力が必要 |

SSH接続は最初の設定が少しだけ手間ですが、一度設定すれば非常に快適です。特にDocker開発環境やCIとの相性が抜群なので、ぜひ試してみてください！

---

## 🔒 最後に（セキュリティメモ）

- **秘密鍵（`id_ed25519`）は絶対に漏洩しないように！**
- **記事やブログで公開するのは必ず公開鍵（`.pub`）だけにすること！**
- セキュリティが心配な場合は、鍵をパスフレーズ付きで作成し、`ssh-agent` などを使って安全・便利に運用しましょう。
ESP32: ボタンの長押し検知

ふたつのボタンが、3秒以上押されると、関数を実行するプログラムです。

```c++:button_push.ino
// ---------------------------------------------------------------
/*
	button_push.ino
					Mar/28/2025
*/
// ---------------------------------------------------------------
#include <WiFiManager.h>

#define BTN1   GPIO_NUM_32
#define BTN2   GPIO_NUM_33

unsigned long pressStartTime = 0;  // ボタン押下開始時間
bool buttonPressed = false;        // ボタンが押された状態

WiFiManager wm;
String APNAME=wm.getDefaultAPName();
String CPID=APNAME.substring(6);

int icount = 0;
// ---------------------------------------------------------------
// 呼び出したい関数
void customFunction() {
	Serial.println("ボタン長押し検知！関数呼び出し！");

	Serial.println("APNAME = " + APNAME);
	Serial.println("CPID = " + CPID);
}

// ---------------------------------------------------------------
void setup() {
	Serial.begin(115200);
	delay(1000);
	Serial.println("*** setup *** start ***");

	pinMode(BTN1,INPUT_PULLUP);
	pinMode(BTN2,INPUT_PULLUP);
	delay(1000);
	Serial.println("*** setup *** end ***");
}

// ---------------------------------------------------------------
void loop() {
	if ((digitalRead(BTN1) == LOW) && (digitalRead(BTN2) == LOW)) {
		button_monitor_proc();
	} 
	else {
		buttonPressed = false;
	}

	delay(100);

	icount++;

	if ((icount % 20) == 0)
		{
		Serial.println("icount = " + String(icount));
		}
}

// ---------------------------------------------------------------
void button_monitor_proc()
{
	if (!buttonPressed) {
		buttonPressed = true;
		pressStartTime = millis();
	}
	else
		{
		const int delt = millis() - pressStartTime;

    		if (3000 <= delt) {
      			customFunction();
			buttonPressed = false;
			}
		}
}

// ---------------------------------------------------------------
```