OmniAICreator/Qiita-1.07M huggingface dataset:
学習、思案、協調について

この記事は、[適応型ソフトウェア開発 アドベントカレンダー 2024](https://qiita.com/advent-calendar/2024/adaptive-software-development) の 6日目です。


## 簡単なルール
適応型ソフトウェア開発には簡単な鉄のおきてがある。
それは、
「簡単なルール」× 「豊かな人間関係」 = 圧倒的な適応力を得ること。

これと実はもう１つある。
それは、
「状態の変化を常に最新化すること」
だ。

## 学習・思案・協調について
適応型ソフトウェア開発における「状態」とは、以下の３つの要素をさす。
今回はこの１つ１つを解説する。


### 学習
「学習」状態とは、何か始める前にこれからどんなことをするのか・そのためには何が必要なのか？わからないことは何か。を見極める必要がある「状態」を示す。

この学習状態というのは、非常に大切で、これからやることが何かまだわからないし、何をするのか決めるためにも情報やリサーチが必要になるケースが多々ある。

なので、適切な判断ができるように、学びを得るためにインプットをすることが求められる状態を学習とよぶ。


### 思案
「思案」状態とは、学習して得た結果やリサーチして手に入れた知見をもとに、私たちはどちらの方向に一歩踏み出してみるかを決める状態を示す。

実際思案といいつつ、本格的に何かを考えきるわけではない。ここが大事だった。
簡単に木の棒を倒して、まずこっちにすすんでみようか。とみんなで方向性を決めていくことが求められる状態であると考えてもらえるとよい。


### 協調
「協調」状態とは、思案した方向にみんなで進んでみたり、何かワークをしてみるといった、チーム活動を示すことが多かった。
例えばデザイナーさんと一緒に何かを決める。プロダクトオーナーと一緒に動く。
クロスファンクショナルなチームだと、横断的に動くことも可能になっているため、そこで何か一緒になってアウトプットを出してみるような状態である。

大切なことは、この成果物は実際の商品でなくてもよいというポイントだ。


## 状態の使い方
この状態は、単独で使うものではなく、次の状態に「至る」ために使う。

この状態は３つそれぞれリンクしており、学習→思案→協調→学習→思案....といった具合に繰り返し回っていくことを期待している。

つまり、このように解釈できる。

* 思案できるように、XXXXを学習する
* 協調できるように、XXXXを思案する
* 学習できるように、XXXXを片付ける


といった具合に、次の状態に至るための方法としてその状態を乗りこなすことが大切になってくる。


## 状態変化
この状態変化を毎回チームメイトに確認しながら進めると、非常にコストが高いフレームワークになってしまう。

そこで簡単な鉄のおきてである、「状態を常に最新化しておく」ということが最重要視されるのだ。


### 状態を常に最新化する。

この状態を常に最新化する方法は何でもよい。

バックログでもいいし、スプレッドシート、伝聞でも構わない。

どんな手段をもってしても、チームメイトの間で常に状態が明確なことを目指すのが、適応型ソフトウェア開発ではとても重要だった。
Python/メソッドとして独立させる

メソッドを1つの独立した部品として考える。

例
・車クラス
１、燃料メソッド
２、メーターメソッド...

修正前
```Python
# -*- coding: utf-8 -*-
class Main():

    def __init__(self):
        pass
    
    def main(self):
        base_fuel = 100
        add_fuel = 100
        # ガソリンの量
        fuel_amount = base_fuel + add_fuel
        return fuel_amount

# クラスのインスタンスを作成
main_instance = Main()
# メソッドを呼び出し、結果を表示
result = main_instance.main()
print(result)

```

修正後（内容が変わっててすみません）

```Python
# -*- coding: utf-8 -*-
class Main():

    def __init__(self):
        pass

    def main(self):
        ...メインのロジックやその他計算メソッドが書かれている
        fuel_amount = self.calculateFuel()
        return fuel_amount

    def calculateFuel(self):
        # ガソリン計算メソッド

        fuel_amount = 0
        base_fuel = 100
        add_fuel = 100
        if fuel_amount < 100:
            # ガソリンが100以下の場合は100追加する
            return fuel_amount ++ add_fuel
        else:
            fuel_amount = base_fuel
            return fuel_amount

# クラスのインスタンスを作成
main_instance = Main()
# メソッドを呼び出し、結果を表示
result = main_instance.main()
print(result)
```

・ある処理を行うかたまりでメソッドを独立させることでコードが読みやすくなる
→ここまでここが計算で、ここからが何かの判定処理で・・・のようなことがなくなる

・処理に伴ったメソッド名をつけることで内容を読まなくても大まかには理解ができる

・メソッド内の変更が他のコードに影響することがない（メソッド内で完結できることが多くなる）
LINE WORKS API Bot コンテンツ ダウンロード

# LINE WORKS API を使用して Bot で受信したファイルをダウンロードする

この記事では、LINE WORKS API を使用して Bot で受信したファイルをダウンロードする方法を説明します。

以下の URL で Google Colab を使って簡単に試せます。  
[Google Colab で試す](https://colab.research.google.com/drive/1ieQ5htMFNEU9czUp-UUp_rqA0rqXhVf5?usp=sharing)


## 必要な準備

1. **LINE WORKS Developer Console での設定**
   - Bot を作成し、`Bot ID` を取得します。

2. **Access Token の発行**
   - LINE WORKS API を使用するためのアクセストークンを取得します。

3. **添付ファイルの `fileId` を取得**
   - 対象のファイル ID を確認します。

## 使用するスクリプト

以下のスクリプトは、LINE WORKS API を使用してBot で受信したファイルをダウンロードする方法を示しています。

```python
import requests
import re

# 必要な変数を設定
ACCESS_TOKEN = "YOUR_ACCESS_TOKEN"  # @param {type:"string"}
BOT_ID = 2000001  # @param {type:"integer"}
FILE_ID = "jp1.1733205053418691464.1733291453.1.3725434.0.0.0"  # @param {type:"string"}
DEFAULT_DOWNLOAD_PATH = "downloaded_file"  # ファイル名が取得できなかった場合のデフォルト保存先

# API エンドポイント
DOWNLOAD_URL = f"https://www.worksapis.com/v1.0/bots/{BOT_ID}/attachments/{FILE_ID}"

# ヘッダー
headers = {
    "Authorization": f"Bearer {ACCESS_TOKEN}",
}

# ステップ 1: ダウンロード URL の取得
response = requests.get(DOWNLOAD_URL, headers=headers, allow_redirects=False)

if response.status_code == 302:
    # HTTP Location ヘッダーから実際のダウンロード URL を取得
    download_location_url = response.headers.get("Location")
    print(f"ダウンロード URL が取得されました: {download_location_url}")
else:
    print(f"ダウンロード URL の取得に失敗しました: {response.status_code}")
    print("レスポンス内容:", response.text)
    raise Exception("ダウンロード URL の取得に失敗しました。")

# ステップ 2: ファイルのダウンロード
download_response = requests.get(download_location_url, headers=headers, stream=True)

if download_response.status_code == 200:
    # ファイル名を `Content-Disposition` ヘッダーから取得
    content_disposition = download_response.headers.get("Content-Disposition", "")
    file_name_match = re.search(r'filename="?([^"]+)"?', content_disposition)
    if file_name_match:
        file_name = file_name_match.group(1)
    else:
        file_name = DEFAULT_DOWNLOAD_PATH  # ヘッダーにファイル名がない場合のデフォルト名

    # ファイルを保存
    with open(file_name, "wb") as file:
        for chunk in download_response.iter_content(chunk_size=8192):
            file.write(chunk)
    print(f"ファイルが正常にダウンロードされました: {file_name}")
else:
    print(f"ファイルのダウンロードに失敗しました: {download_response.status_code}")
    print("レスポンス内容:", download_response.text)
    raise Exception("ファイルのダウンロードに失敗しました。")
```

## スクリプトのポイント

### 必要なパラメータ

1. **`ACCESS_TOKEN`**
   - LINE WORKS API の認証に使用されるアクセストークンです。

2. **`BOT_ID`**
   - 使用する Bot の ID です。
   - LINE WORKS Developer Console から取得できます。

3. **`FILE_ID`**
   - ダウンロード対象のファイル ID です。

---

### ファイル名の取得と保存

- スクリプトは `Content-Disposition` ヘッダーからファイル名を抽出します。
- 抽出できない場合は、デフォルト名（`downloaded_file`）で保存します。

## 実行結果

- 成功時:
  ```
  ダウンロード URL が取得されました: https://apis-storage.worksmobile.com/...
  ファイルが正常にダウンロードされました: example.png
  ```

- 失敗時:
  ```
  ファイルのダウンロードに失敗しました: 401
  レスポンス内容: {
      "code":"UNAUTHORIZED",
      "description":"Authentication failed."
  }
  ```

## 応用例

- ダウンロードしたファイルを加工・送信する。
- ファイル名を自動生成して保存する。

## まとめ

このスクリプトを使用することで、LINE WORKS API を利用したファイルのダウンロードを簡単に実現できます。ぜひお試しください！
RPZ-IR-Sensor Rev2　再導入

RPZ-IR-SensorRev2
![71-MEhapEoL.__AC_SY300_SX300_QL70_ML2_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433305/4a8a7948-bc34-c5db-8a1a-3eeca95f16c9.jpeg)



センサー制御ソフトウェア「cgsensor」をインストール
```
sudo python3 -m pip install -U cgsensor
cgsensor all
```
結果
```
BME280#2
  温度[C]:  22.6
  湿度[%]:   39.5
  気圧[hPa]: 1011.0
TSL2572
  明るさ[lux]:  41.7
```
i2c-toolsでI2Cで接続されているデバイスを確認します。
```
i2cdetect -y 1
```
python 作成　bme280_tsl2572.py
```
sudo vim bme280_tsl2572.py
```
中身は以下　Indoor Corgiさんのサイトからサンプルをマージして作成。　
```
#!/usr/bin/env python3
import cgsensor  # インポート
bme280 = cgsensor.BME280(i2c_addr=0x77)  # BME280制御クラスのインスタンス, i2c_addrは0x76/0x77から選択
bme280.forced()  # Forcedモードで測定を行い, 結果をtemperature, pressure, humidityに入れる
print('気温 {}°C'.format(bme280.temperature))  # 気温を取得して表示
print('湿度 {}%'.format(bme280.humidity))  # 湿度を取得して表示
print('気圧 {}hPa'.format(bme280.pressure))  # 気圧を取得して表示
tsl2572 = cgsensor.TSL2572()  # TSL2572制御クラスのインスタンス
tsl2572.single_auto_measure()  # 条件を自動で調整しながら1回測定を行い, luxに結果を入れる
print('明るさ {}lux'.format(tsl2572.illuminance))  # 明るさを取得して表示
```
実行
```
python bme280_tsl2572.py
```
cgsensor allと同じ内容で表示された。ＯＫ。

温度は　ラズパイの熱の関係で実際の気温と異なるのでpythonを変更。

LCD接続して表示させようと考えています。

※何回か接続しなおしたりすると、接触不良なのか、エラーとなるので留意。
カーテンみたいに横から引き出すdiv

# はじめに
右側にユーザーが幅変更可能な設定メニュー欄を置くために、見つけたコードを見つけたので、少し改良しました。

![moving_div.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568190/edc43627-4b92-b0c0-e4a6-c9ffd760af14.gif)


# 参考資料
[stack overflow: Resize a div on border drag and drop without adding extra markup](https://stackoverflow.com/questions/26233180/resize-a-div-on-border-drag-and-drop-without-adding-extra-markup)

# コード
```html: index.html
<div id="right_panel"></div>
```

```css: style.css
#right_panel {
  position: absolute;
  width: 96px;
  min-width: 50px;
  max-width: 500px;
  height: 100%;
  right: 0;
  background-color: #d4ddff;
  cursor: ew-resize;
}

/* 境界線用 */
#right_panel::after {
  content: '';
  background-color: #ccc;
  position: absolute;
  left: 0;
  width: 4px;
  height: 100%;
  cursor: ew-resize;
}
```

```javascript: panel.js
const panel = document.getElementById("right_panel");
const BORDER_SIZE = 4; // リサイズ可能な領域の幅
const MIN_WIDTH = 50; // 最小幅
const MAX_WIDTH = 500; // 最大幅

let isResizing = false;
let startX = 0;

panel.addEventListener("mousedown", (e) => {
  if (e.offsetX < BORDER_SIZE) {
    isResizing = true;
    startX = e.clientX;
    document.addEventListener("mousemove", resize);
    document.addEventListener("mouseup", stopResize);
  }
});

function resize(e) {
  if (!isResizing) return;
  const dx = e.clientX - startX;
  startX = e.clientX;
  const newWidth = Math.min(
    Math.max(panel.offsetWidth - dx, MIN_WIDTH),
    MAX_WIDTH
  );
  panel.style.width = `${newWidth}px`;
}

function stopResize() {
  isResizing = false;
  document.removeEventListener("mousemove", resize);
  document.removeEventListener("mouseup", stopResize);
}
```
ACR使ってますか？

# はしめに
こんにちは たそ(@taso_int)です。
普段ははてなブログで技術ブログを投稿しております。
良かったら見てください。
https://taso-int.hatenablog.com/archive

今回はアドベントカレンダーということで、Azureネタを書きます。
Azure Container Registryサービスについてです。

# Azure Container Registry

Azure Container Registry (ACR) は、Microsoft Azure が提供するプライベートなコンテナイメージのレジストリサービスです。
Docker イメージや OCI アーティファクトを安全に保存・管理し、CI/CD パイプラインや Kubernetes クラスタなどに統合して利用できます。

AWSでいうところのECRで、コンテナイメージを保管する場所という印象があります。
このサービスを触っていくなかで、便利だと思う機能があったので、それを紹介していきます。

今回はサービス階層の中でもPremiumサービスで利用できる機能について紹介します。

詳しくは[サービス階層の機能と制限](https://learn.microsoft.com/ja-jp/azure/container-registry/container-registry-skus)を確認してください。

## ネットワークのアクセス制御

レジストリへのネットワークに関するアクセス制限を設定できます。
イメージとしては`Azure Storage Account`と同じようなネットワークに関するアクセス制限を設定できます。

- プライベートエンドポイント
- パブリックネットワークのアクセス制御
- 信頼されたサービスからのアクセス許可

プライベートエンドポイントに対応しているため、パブリックインターネットを経由せずに安全なアクセスができるため、システム要件として堅牢なアクセスを要求されている場合は利用すると良いです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2269290/6ea4b29e-4c30-10b4-49d2-27a7e7c7b83d.png)


## アーティファクトキャッシュ機能

アーティファクトキャッシュ機能は、外部のコンテナレジストリから取得するコンテナイメージやアーティファクトをキャッシュする機能です。

普段イメージを取得する際、Docker.ioだったり、Quay.ioなどの外部のコンテナレジストリから取得することがあります。ここにACRをキャッシュとして中継することで、ハブとしての役割を持ちます。
各サービスがACRから参照し、ACRは外部のコンテナレジストリをイメージの定義に基づいて参照します。

この機能があると外部のコンテナレジストリのRate limitの対策であったり、イメージのキャッシュ取得後のACRのネットワークのアクセス制限が利用できます。

ちなみにDocker Hubは、匿名および無料のDocker Hubユーザーについて、6時間あたり100および200のコンテナイメージプル要求に制限されています。(https://www.docker.com/ja-jp/increase-rate-limits/)

これにより、AKSのアップグレードやマニフェストの更新で、イメージをpullする際に、Dockerのレート制限に引っかかり失敗してしまいます。
そのため、pull先をACRにすることで、このレート制限を対策できます。

詳しくは[Azure Container Registry のアーティファクト キャッシュ](https://learn.microsoft.com/ja-jp/azure/container-registry/container-registry-artifact-cache?pivots=development-environment-azure-portal)を確認してください。


## Import機能

Import機能は、他のコンテナレジストリ（パブリックまたはプライベート）からコンテナイメージを ACR に直接インポートするための機能です。

通常、Dockerのイメージをコンテナレジストリに登録する場合、イメージを pull → run → build → push する必要があり、このプロセスは少々手間がかかります。また、DockerやPodmanの環境を事前に準備する必要があるため、作業が煩雑になることもあります。

しかし、`az acr import`コマンドを利用することで、これらの手順を省略し、コンテナイメージを他のレジストリから ACR に直接インポートすることが可能です。これにより、環境構築の手間を省きつつ、効率的に作業を進められます。

なお、Azure Cloud Shell にはこのコマンドがプリインストールされているため、Azure Cloud Shell のみを使用してイメージのインポートが可能です。

また、別のサブスクリプション内のレジストリからインポートできます。
そのため、開発環境や商用環境をサブスクリプションで分けている場合は、開発環境から出来たイメージ類をそのまま商用環境にインポートできるなど便利です。

詳しくは[コンテナー レジストリにコンテナー イメージをインポートする](https://learn.microsoft.com/ja-jp/azure/container-registry/container-registry-import-images?tabs=azure-cli)を確認してください。

# おわり
Azure Container Registryについて紹介させていただきました。
皆さんもぜひ使いましょう。

## おまけ 料金について

https://azure.microsoft.com/en-us/pricing/details/container-registry/

基本的には1日あたりの料金＋追加ストレージ量が基本的にかかる料金です。
主観にはなりますが、Premiumの基本ストレージ量が500GBとかなり多いため基本的に追加料金はそこまでかからないと思います。
Rustでロケットを打ち上げる！ネタコマンド「rocket-animation」を作ってみた 🚀

## 概要

Rust製のネタコマンドを作成してみました。
その名も「rocket-animation」コマンドを実行すると、なんとターミナル上でロケットが華麗に打ち上がるアニメーションが表示されます。
この記事では、このコマンドのインストール方法や公開までのプロセスを軽く解説します。
是非仕事につかれたらロケット打ち上げてみてください🚀

SLコマンドに感化され作成しました。

https://qiita.com/shota0616/items/790af016b70eb8a3a343

## インストール方法

以下の手順で簡単にインストール可能です。

1\. cargoインストール
```
# Debian系
apt install cargo

# RedHat系
yum install cargo
```
2\. rocket-animationのインストール
```
cargo install rocket-animation
```
3\. パス通ってなかったらパス通しておく
```
export PATH=$PATH:/root/.cargo/bin/
```


## 実行してみよう

準備が整ったらコマンドを実行してみましょう！
```
rocket
```
するとターミナルにこんな感じのアニメーションが表示されます！
```
          ^           
         / \         
        / _ \        
       |     |        
       |     |        
       |     |        
      /|JAPAN|\      
     / |     | \     
    /  |     |  \    
   |   |  O  |   |    
   |   |  o  |   |    
   |   |     |   |    
   |   |     |   |    
  /|##!#|   |#!##|\  
 | |##!#|   |#!##| |  
 | |##!#|   |#!##| |  
 | |##!#|   |#!##| |  
 | |##!#|   |#!##| |  
 \_|____|___|____|_/ 
     /  |   |  \     
    /___|___|___\    
       |  |  |       
       |  |  |       
       |  |  |       
         |||
        |||||
       |||||||

```
ターミナルに映し出されるロケット…ちょっとテンション上がる？

## Crates.ioに公開してみた

せっかく作ったので、Rustのパッケージレジストリ「Crates.io」に公開しました。これで誰でも簡単にインストールできます。

:::note info
Crates.ioってなに？

Rustの公式パッケージレジストリで、Rustで開発されたライブラリやツールを公開・共有するためのプラットフォームです。
Rustのパッケージは「crate（クレート）」と呼ばれ、Crates.ioでは世界中のRust開発者が作成したcrateを検索したり、プロジェクトで利用したりすることができます。
PythonでいうところのPyPI、Node.jsのnpmに相当する感じです。
:::

https://crates.io/


1\. プロジェクトをビルドしておく
```
cargo build --release
```
2\. Crates.ioにログイン
```
cargo login
### ここでtokenを入力します。
```
3\. パッケージを公開
```
cargo publish
```
4\. 公開したパッケージをインストール
```
cargo install rocket-animation
```


## 最後に

ぜひ、自分だけのネタコマンドを作ってみてはいかがでしょうか？もし評判が良ければオプションなどでもっと凝った作りにしてみようと思います。
🚀 あなたのターミナルにも楽しい時間を！
UUID v7 と化した Guid からタイムスタンプを抜き出す

# やりたいこと
前回の記事で UUID v7 に準拠した Guid を使えるようになりました。

https://qiita.com/higege-amdeker/items/5802120f6bcec7e763a0

ここからタイムスタンプ部分を抜き出してみようと思います。

# やり方
## 仕様を確認
- 先頭 48bit がタイムスタンプ
- UNIX 時間のミリ秒が16進数で格納されている

## 実装していく
### UUID v7 準拠の Guid を生成
```csharp
Guid guid = Guid.CreateVersion7();
```
### 先頭 48bit がタイムスタンプなので抜き出す
- 16進数にすると12桁
- 8-4-4-4-12 のうち 8-4 の部分

```csharp
string str = guid.ToString("N")[..12];
```

:::note
Guid.ToString メソッドで書式指定子 `N` を使うとハイフン抜きの文字列が取得できます。
:::

https://learn.microsoft.com/ja-jp/dotnet/api/system.guid.tostring

### UNIX 時間のミリ秒から DateTimeOffset を生成
- 16進数文字列を整数型に変換する
- `DateTimeOffset` のファクトリーメソッドを使う

```csharp
long milliseconds = Convert.ToInt64(str, 16);
DateTimeOffset timestamp = DateTimeOffset.FromUnixTimeMilliseconds(milliseconds);
```

### 完成

```csharp
Guid guid = Guid.CreateVersion7();
string str = guid.ToString("N")[..12];
long milliseconds = Convert.ToInt64(str, 16);
DateTimeOffset timestamp = DateTimeOffset.FromUnixTimeMilliseconds(milliseconds);
Console｡WriteLine(timestamp);
```

```
2024/12/04 11:58:49 +00:00
```

## Guid に拡張メソッドを追加

使いやすいように拡張メソッドにしてやりましょう。

```csharp
public static class GuidExtensions
{
    public static DateTimeOffset GetTimestamp(this Guid guid)
    {
        if (guid.Version == 7)
        {
            string str = guid.ToString("N")[..12];
            long milliseconds = Convert.ToInt64(str, 16);
            DateTimeOffset timestamp = DateTimeOffset.FromUnixTimeMilliseconds(milliseconds);

            return timestamp;
        }
        else
        {
            throw new NotSupportedException("This method is only supported for GUIDs with version 7.");
        }
    }
}
```

# まとめ

UUID v7 に準拠した Guid からタイムスタンプを抜き出す拡張メソッドを実装できました。ここまでやっといてなんですが、データベース上でソートできる点がメリットであって、そこからタイムスタンプを抜き出すのはあまり使わないかもなといったところです。
生成AIに騙されないために

# 生成AIが◯◯をすればOKって言ってたんですけど...
最近よくコレを言われながら相談を受けることが多いのですが、
体感30%くらいウソの回答されちゃってますね...。
（というか私で正誤判定しないでくれ😇）

それでは、どうすればウソつかれないのか

# 結論、生成AIは人間だと思って接するべし
例えば以下のようなコードがあるとします。
```
user = UserModel.objects.get(id=1)
user.email.delete()
```
人間に「このコードはDjangoのコードなんだけど、どういう意味でしょうか」と聞いたとき
大半の人間は「idが1のユーザーのメアドを削除してるのでは？」って言うと思います。

もちろん、生成AIもそう答えます。以下の通り。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493134/ec2581ff-ad57-29f1-bf25-17d9b76a6581.png)


しかし、Djangoにこんな書き方はありません。
`user.email = None`が正しいです。

ちなみに`user.delete()`をしたら、
そのユーザーのレコードごと削除されてしまうので恐いミスですね😇

言いたいこととしては、**人間が間違えそうなことは、生成AIも間違えます**。
逆もまた然りなので、人間だと思って接するようにしましょう。


# より正確な回答を引き出すためのテクニック
生成AIを人間だと思ってもらえれば当たり前すぎるのですけど、
一応、質問のコツを共有します。

## テクニック1：具体的すぎるくらいが丁度いい
### ❌ NG例
```
うちの会社の売上を伸ばす方法を教えて
```
これでは生成AIも背景情報をテキトーに推測するしかないですね。

### ✅ OK例
```
従業員10名の町の小さな雑貨店です。
今の売上は月50万円で、3ヶ月以内に売上を20%増やしたいです。
予算は月10万円です。
どんな施策が効果的でしょうか？
```
このように具体的な状況を説明すると、
AIはその条件に沿ったアドバイスができるようになります。

この例でも具体性は全然ない方ですね。
何もないところから具体的に状況を説明するのは難しいので、
あらかじめ「売上を伸ばす施策を検討するにあたって必要な項目を教えて」と生成AIに確認をして、
返ってきた項目に対して具体的に述べるのがよいでしょう。

## テクニック2：ガン詰め
### ✅ OK例
コード修正させたあとに、以下のように確認をする。
```
そちらのコードについて、以下を教えて下さい。
1. そのコードはスマートでベストプラクティスに沿っていますか？
2. その修正によってどんな効果が期待できるのでしょうか？
3. 考えられる副作用はありますか？
4. 他の対応方法は考えられますか？
を教えてください
```
「AIを人間だと思え！」と言っといてアレですけど、
もちろん人間じゃないので必要なハラスメントはしていきましょう。


# おわりに
まぁ、生成AIに長文いれるの正直めんどくさいですよね。
人間相手なら頑張って説明しようと思うものの、
機械相手になった途端「察してくれ〜」と思ってしまうのが人間というものです。

ただ、実体験として説明をサボらない方が結果的に早く仕事が済んでいるので、
その成功体験を積むことで、
いいプロンプトが書けるようになってくるんじゃないですかね。
しらんけどね。

また、工夫次第でウソ(ハルシネーション)の発生率を抑えられはするものの、
完璧に防ぐことは不可能なので、ミスったらヤバい箇所については、
公式ドキュメントを参照したり、テストなどでカバーするようにしてくださいませ。
LINE WORKS Bot Callback サーバーを Google Colab + Cloudflare Tunnel で構築する

# LINE WORKS Bot Callback サーバーを Google Colab + Cloudflare Tunnel で構築する

LINE WORKS Bot の Callback サーバーを簡単にセットアップする方法を解説します。この方法では、Google Colab と Cloudflare Tunnel を使用して、素早く外部からアクセス可能な環境を構築します。

以下の URL で Google Colab ノートブックを試せます。
[Google Colab ノートブック: LW_Bot_Callback_CloudflareTunnel.ipynb](https://colab.research.google.com/drive/1RzIWELcbNAxHXnwVndSJUG86w05BdUfS?usp=sharing)

## 必要な準備

1. **LINE WORKS Developer Console での設定**
   - Bot を作成し、Callback URL を登録します。Colab 実行後に生成される Cloudflare トンネルの URL を設定してください。
   
2. **Google Colab のアクセス**
   - Google アカウントで Colab にアクセスします。

3. **Python 環境の準備**
   - 必要なライブラリとツールはノートブック内で自動的にセットアップされます。

## スクリプト

以下のスクリプトは、Callback サーバーを Google Colab 上に構築し、Cloudflare Tunnel を使用して外部アクセス可能にします。

```python
# 必要なライブラリのインストール（既にインストール済みならスキップされます）
!pip install requests flask

# Cloudflareトンネルツールをダウンロード、設定（既にダウンロード済みならスキップ）
!wget -N https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64
!chmod +x cloudflared-linux-amd64

from flask import Flask, request, jsonify
import threading

# Flask アプリケーションの初期化
app = Flask(__name__)

@app.route('/', methods=['POST'])
def callback():
    # Callback のリクエスト内容を取得
    event = request.json
    print("受信したイベント:", event)

    # 必要に応じて非同期で処理
    if event.get('type') == 'message':
        print("メッセージ内容:", event.get('content', {}).get('text'))

    return jsonify({'status': 'ok'}), 200

# サーバーを起動する関数
def run():
    app.run(host='0.0.0.0', port=5000)

# Flask サーバーを別スレッドで実行
thread = threading.Thread(target=run)
thread.start()

# Cloudflareトンネルを起動し、外部アクセス用の URL を取得
!./cloudflared-linux-amd64 tunnel --url http://127.0.0.1:5000 &
```

## スクリプトのポイント

### 1. 必要なパッケージのインストール
Google Colab 環境で必要な `requests` と `flask` を自動的にインストールします。

### 2. Flask サーバーの構築
Flask を使用して Callback を処理するサーバーを構築します。`/` エンドポイントに POST リクエストを受信すると、イベントデータを取得し、コンソールに出力します。

### 3. Cloudflare Tunnel の活用
Cloudflare Tunnel を使用してローカルサーバーを外部アクセス可能にします。実行後、Cloudflare が提供する URL が生成されます。

---

## 実行結果

### 成功時のログ
```
 * Running on http://127.0.0.1:5000
 * Running on http://172.28.0.12:5000
2024-12-04T11:34:48Z INF Your quick Tunnel has been created!
2024-12-04T11:34:48Z INF Visit it at: https://inclusive-pc-path-dale.trycloudflare.com
```

この URL を Bot の Callback URL に設定してください。

## 注意点

- **トンネルの有効期限**:
  Cloudflare トンネルの URL は一時的です。Colab セッションが終了するとトンネルも無効になります。

- **署名検証**:
  実運用では、LINE WORKS から送られるリクエストの署名を検証してください。

## まとめ

この方法を使えば、LINE WORKS Bot の Callback サーバーを簡単にセットアップできます。開発・テスト環境に最適です。本番環境では、安定したホスティングサービスの利用を検討してください。
VSCodeでFlake8+autopep8からRuffに乗り換えました

Ruffに乗り換えたので、導入手順を残しておこうと思います:v:

:::note warn
この記事では、VSCodeの拡張機能としてのRuffの導入方法に限定して説明します。
Pythonプロジェクトに直接インストールする方法については、別の記事をご参照ください。
:::

# Ruffって？
ざっくりいうと`高速なLinter兼Formatter`です。
以下の3つのパッケージをまとめたオールインワンの静的解析ツールみたいです。
- Flake8
- Black
- isort

詳しくはこちら:point_down:

https://docs.astral.sh/ruff/

# 乗り換えた理由
深い理由はなかったですが、おもに以下点が気に入ったので、試しに使ってみました。
- めっちゃ早い
- LiterとFormatterを1つにまとめられる
- 使ってないパッケージを自動で消してくれる

# VSCodeに導入する方法
 1. [Ruffの拡張機能](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff)をインストール
 1. デフォルトのFormatterをRuffに設定する
 設定から`editor.defaultFormatter`で検索して、`Ruff`を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665258/cef3e683-207a-e423-479c-f19c2181d3ff.png)

 1. 自動整形をオンにする
設定から`editor.formatOnSave`で検索して、チェックを付ける
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665258/260f5100-8f53-be8a-6e94-8235776a3d71.png)

- UIからの設定が面倒な方はこちら
``` json: settings.json
{
    "editor.defaultFormatter": "charliermarsh.ruff",
    "editor.formatOnSave": true
}
```

# Flake8+autopep8から移行する方法
既存のLinterとFormatterの拡張機能を無効にするだけでOK:ok_hand:です。
不要になったら削除しちゃってください:thumbsup:

## 無効にする拡張機能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665258/5cc1e8e0-6bb4-857a-7b11-c2fe4866ee13.png)

- Linter
  - Flake8
  - Pylint
  - etc...
- Formatter
  - autopep8
  - Black
  - isort
  - etc...

# 使い方
[VSCodeに導入する方法](#VSCodeに導入する方法)を済ませれば、ファイルを保存するだけで自動整形されます。
ただし、以下の2つは手動で実行する必要があります。
- 未使用のパッケージの削除
- importの順番

# 設定の変更方法
Ruffでは自動的にシングルクォートをダブルクォートに変換してくれるのですが、私はシングルクォートのほうが好みなので、設定で変更しました。

フォーマットの設定方法は:point_down:このあたりに書いてありました。

https://docs.astral.sh/ruff/settings/#format

# 準備
1. `pyproject.toml`を作成する
1. 拡張機能に認識させる
設定から`ruff.configuration`で検索して、1で作成したファイルを指定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665258/568fea67-9e36-eb3b-e89c-1f47dcc0118e.png)

- UIからの設定が面倒な方はこちら
``` diff_json: setting.json
{
    "editor.defaultFormatter": "charliermarsh.ruff",
    "editor.formatOnSave": true,
+   "ruff.configuration": "./pyproject.toml"
}
```

## 設定の変更
``` toml:pyproject.toml
[tool.ruff.format]
quote-style="single"
```
[シングルクォートの設定](https://docs.astral.sh/ruff/settings/#format_quote-style)

# 個人的に切り替えて良かったポイント
切り替えて数日ですが、以下のポイントが良かったなと感じてます。
使っていく中で、他にいい所があれば追記していこうと思います。
## とにかく早い
私はファイル保存時にしかフォーマットをかけないのですが、体感で早くなった気がします。
autopep8だと、0.2,3秒かかってる感じがしていましたが、Ruffだと保存した瞬間に終わってる感覚があります。
## LinterとFormatterが一つになっている
Ruffを導入する前は以下の静的解析ツールを導入していましたが、Ruffは1つだけで済むのが嬉しいです:angel:
- autopep8
- Flake8
- isort
## pyproject.tomlを採用している
Flake8なんかは設定を変更したい場合は、専用の設定ファイルで定義する必要がありましたが、RuffはPythonの標準機能である、pyproject.tomlに設定を書けばよいのがとても嬉しいです。
プロジェクトが小さいうちは、1つのファイルにまとまっている方が管理しやすいので、結構嬉しいポイントでした。

プロジェクトが大きくなってきたら`ruff.toml`か`.ruff.toml`に書くこともできるみたいです。
:point_down:このあたりに書いてありました。

https://docs.astral.sh/ruff/tutorial/#configuration

# その他
Ruff以外の拡張機能について知りたい方は下記をご参照ください。

https://qiita.com/team7_403_poppin/items/03f52a6b33567f5a0f17
ソケット・プリミティブ

>もう一つのトランスポート・プリミティブのセットであるTCP用のソケット・プリミティブについて簡単に調べてみよう。
...
プリミティブは現在、多くのオペレーティング・システム、特にUNIXベースのシステムのインターネット・プログラミングにおいて広く使われおり、Winsockと呼ばれるWindowsのソケット・スタイルAPIも存在する。
プリミティブを一覧にしてまとめておく。基本的に前述のトランスポート・プリミティブと同じであるが、よりたくさんの機能と柔軟性を提供する

### プリミティブの種類
| プリミティブ | 意味                                                                   | 
| ------------ | ---------------------------------------------------------------------- | 
| SOCKET       | 新規に通信のポイントを作成する                                         | 
| BIND         | ローカル・アドレスをソケットに取り付ける                               | 
| LISTEN       | コネクションの受け取り意思をアナウンスする（キュートのサイズを与える） | 
| ACCEPT       | コネクション要求が到着するまでブロックする                             | 
| CONNECT      | コネクション確立を能動的に試みる                                       | 
| SEND         | コネクションへデータを送信する                                         | 
| RECEIVE      | コネクションからデータを受信する                                       | 
| CLOSE        | コネクションを解放する                                                 | 

### 新たなエンドポイントを作成　SOCKET
>`新しいエンド・ポイントを生成`し、`トランスポート・エンティティ内のテーブル・スペースの準備`を行う。プリミティブの呼び出しの際、`利用するアドレッシング・フォーマットや望ましいサービス・タイプ（例えば信頼性など）、プロトコルを指定`する。SOCKET呼び出しが成功すると、通常のファイル記述子が返され、後続の呼び出しはそのファイル記述子を利用する。これはOPEN呼び出しと同様である。

### アドレスを割り当てる　BIND
>新規に作成されたソケットはネットワーク・アドレスを持たない。`BINDプリミティブによりアドレスが割り当てられる`。サーバーがソケットにアドレスを設定すると、`遠隔のクライアントからのコネクションを受け入れる`ことができる。

### コネクション要求のキューイング　LISTEN
>`いくつかのクライアントが同時にコネクションを試みた場合に、そのコネクション要求をキューイングするための準備`をする。前述の例のLISTENとは対照的に、ソケット・モデルにおけるLISTEN呼び出しはブロックしない。

### 待ち状態で待ち次のコネクション要求を待つ　ACCEPT
>`ブロック状態（待ち状態）でコネクション要求を待つ`。コネクションを要求するセグメントが到着すると、トランスポート・エンティティは`元のソケットと同じ属性を持つソケットを新規に作成し、そのファイル記述子を返す`。サーバーはforkによりプロセスやスレッドを生成し、`新しいソケットによりクライアントと接続し、元のソケットで新たな次のコネクション要求`を待つことができる。ACCEPTは通常のファイル記述子を返すため、ファイルと同様に通常通り読み書きできる。

# クライアント側から見ると
### ソケットを作成するだけ　SOCKET
>SOCKETプリミティブによりソケットを作成するが、BINDする必要はない。クライアントがどんなアドレスを使おうともサーバーには関係ないからである。

### 呼び出したものを待ち、コネクション手順を開始する　CONNECT 
>呼び出したアプリケーションの処理をブロックし、コネクションの手順を開始する。コネクションが完了すると（すなわち、適切なセグメントをサーバーから受け取ると）、クライアント・プロセスはブロックを解除し、コネクションが確立される。

### SENDとRECEIVE
>クライアント・サーバーとも全二重のコネクション上でデータの送信、受信を行うことができる。


https://bookplus.nikkei.com/atcl/catalog/23/03/16/00728/

# 感想
ソケットはIPアドレスの割り当てを前やったことあったのでそれを思い出す。
全然理解できていないのでもっと理解したい
Rocky Linux USB Wi-Fi Driver Install

##### 初めに
USB Wi-Fi アダプター:
  0bda:c811 Realtek Semiconductor Corp. 802.11ac NIC
の Driver をgit org より ダウンロードし試してみましたが、ことごとく以下のようなエラーでビルドできませんでした。

```
  ~
Error! Bad return status for module build on kernel: .....
Consult /var/lib/dkms/rtl8723du/0.1/build/make.log for more information.
  ~
 ```
##### 試したDriver
88x2bu-20210702 , 8821cu-20210916 , rtl8821CU 等

ビルドできない理由は、kvdo モジュールが、最新のカーネル バージョン 5.14.0-503.15.1.el9_5.x86_64 にロードされないからのようです(詳しいことは分かりません! どなたか御教示頂ければ幸です)

あちこち検索してると、以下のような投稿欄を見つけました。
The right driver is packaged in elrepo. Execute the following commands to install the module(https://forums.rockylinux.org/t/wifi-usb-realtek/15445/9)

#### 投稿欄にある、次のコマンドを実行

```
 # sudo rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
 # sudo dnf install https://www.elrepo.org/elrepo-release-9.el9.elrepo.noarch.rpm
 # sudo dnf install --enablerepo=elrepo kmod-rtw88_usb
```
#### ネットワークデバイスの状態を表示

```
  # nmcli d
     DEVICE       TYPE      STATE            CONNECTION     
     wlp0s26u1u5  wifi      接続済み         Buffalo-*******
     lo           loopback  接続済み (外部)   lo             
     enp0s25      ethernet  切断済み          -- 
```
いとも簡単に認識しました！
(# modprobe kvdo はロードされています)
多端末テストにおけるAndroid端末選定について

# ■ はじめに
2024年のアドベントカレンダーの時期がやってまいりました。
今年の記事は、自身がAndroidの多端末検証の計画業務をおこなった際に検討や調査をして得たナレッジについて記載していきます。
ネットではAndroid端末の選定について細かく纏まっている記事があまりなかったので、今回は取りまとめようと思います。
※こちらの内容は絶対の正解ではなく、検討や考慮する際の参考にご活用いただけると幸いです

# ■ 多端末テストとは
多端末テストとは、複数の端末で動作確認を行うテストのことです。
今回はiOS端末より選定作業に工数のかかるAndroidのスマートフォン端末の選定における考慮しているポイントについて紹介していきます。

# ■ 端末選定で考慮しているポイント
多端末テストでは、テストする端末の選定が重要です。以下のポイントを考慮しています。

|ポイント|備考|
|:--|:--|
|シェア率|各社の運営タイトルのシェア率を参考にし、利用者の多い端末をターゲットに選定します|
|メーカー/キャリアのバランス|普及率の高い大手のメーカー、キャリアを中心に対象を選択するのが一般的です。メーカーの違いにより挙動が異なるケースはよくあるので、必要に応じて幅広いメーカーで確認できると良いです。　※検証対象を絞る際はそのバランスも考慮することを推奨します|
|OSのバージョン|各プラットフォーム（iOS、Android、PCなど）には複数のOSバージョンがあります。特に、ユーザー数の多いバージョンに対応することが重要です|
|端末スペック/形状|SoCの性能、ディスプレイの解像度、スマホ、タブレット、折り畳み端末など　※SoCについては下部に詳細を記載しています|

## ■ シェア率
### 市場シェアとユーザー層
Androidは世界中で広く使用されていますが、特に人気のある端末に対応することが重要です。市場シェアの高い端末を優先することで、多くのユーザーに対するテストが可能です。弊社で運用している、別ゲームの端末シェア率を参考に選定を実施したりしました。

### 地域別の人気端末
市場シェアは地域によって異なるため、ターゲット地域（日本、アメリカ、インドなど）で人気の端末を選定することが重要です。

### 価格帯の幅をカバーする
高価格帯（ハイエンド）から低価格帯（エントリーモデル）まで幅広い端末でテストすることが必要です。これにより、低スペック端末でも高品質な体験が提供されることを確認できます。
開発チームが定める推奨するスペックがあれば、そのスペックを基準にテストするなど調整もできるので、検証費用の最適化を考える上では意識すべきポイントです。

## ■ メーカー/キャリアのバランス
普及率の高い大手のメーカー、キャリアを中心に対象を選択するのがベストです。
メーカーの違いにより挙動が異なるケースはよくあるので、必要に応じて幅広いメーカーで確認できると良いです。

## ■ OSのバージョン
### Androidのバージョン別ユーザー数
Google Play Consoleなどのデータから、各Androidバージョンの普及率を確認し、それに基づいてテスト対象の端末やOSバージョンを選定します。

### 最新バージョンと普及率の高いバージョンをカバーする
AndroidはOSのバージョンが多岐にわたるため、最新のOS（例えば、Android 14）をテストすることはもちろん、普及率が高いバージョン（例：Android 12、Android 13）もカバーする必要があります。Androidのアップデートが遅れることが多いため、特に古いバージョンも考慮する必要があります。
AndroidにはOppoから出ている独自のColorOSというものがあり、このOS特有の不具合を検知することもありましたので、検証ではしっかりと抑えておいた方が良いかもしれません。

## ■ 端末スペック/形状
### SoC、メモリ、ストレージ、形状
ゲームやアプリのパフォーマンスが異なるため、低スペック端末、中スペック端末、高スペック端末それぞれでの動作確認を行います。特にメモリ（RAM）の容量やストレージ容量（ROM）の違いは、動作の安定性や処理速度に影響を与えます。
ゲームが特にパフォーマンスに依存する場合、ハイエンドやミッドレンジシリーズの端末でテストすることが不可欠です。また、低価格帯の端末の低スペック端末の動作確認も重要です。
最近では折りたたみスマホも増えてきており、自身が端末選定作業した際も縦折や横折など様々な形状も考慮するように気を付けました。

### SoCとは
「SoC」とは、一個の半導体チップ上にシステムの動作に必要な機能の多く、あるいは全てを実装するという設計手法、また、その手法を使って作られたチップのことを指す言葉です。
その名称は「システムを一個のチップ上に載せる」を意味する英語“System on a Chip”の略称で、そのままエスオーシーやソックと呼ばれます。
SoCは多くの場合、コンピュータの中枢となるCPUとメモリ、ビデオチップ、I/Oといった機能を統合したチップとして設計されます。

下記にはSoC選定の参考用に種類を表でまとめています。

|メーカー|SoC名称|詳細|備考|
|:--|:--|:--|:--|
|Qualcomm|Snapdragon|ハイエンドからローエンドまで幅が広く、様々な端末メーカーが採用しています|ミドルエンド以下の端末は動作推奨端末以下に該当するものが多く、クラッシュ等の率は高い印象|
|HiSilicon|Kirin|Huawei系の端末のみに搭載されているモデル||
|Samsung|Exynos|Samsungの端末のみに搭載されているモデル（ハイエンドモデルは海外モデルのみではありますが、ミドルエンド以下は格安端末などに搭載されていることが多い|格安系のミドルエンド以下の端末は動作推奨端末以下に該当するものが多く、クラッシュ等の率は高い印象|
|Google|tensor|Google謹製のチップセット。Pixel6から搭載されていて、初代tensorはSnapdragon888 Plusより少し劣るくらいのハイエンドとなります||
|MediaTek|Helio|ミドル～ローエンド（中～低価格帯）モデルのシェア率が高い||
|Unisoc|Tiger|2021年の時点では、Mediatek、Qualcomm、Appleに次ぐ世界第4位のモバイルプロセッサメーカーであり、世界市場シェアの9％を占めています||
|Xiaomi|Surge|Xiaomiの端末のみに搭載されているモデル（Xiaomiが日本でも大きく市場を広げてくると影響はありそうですが、基本XiaomiのハイエンドモデルはSnapdragonを搭載しています）||

# さいごに
Android端末の選定においては、端末の市場シェア、OSバージョン、解像度、性能、バッテリー容量などを考慮し、さまざまな端末をカバーすることが求められます。SoCに関しては、ゲームのパフォーマンスやエネルギー効率なども考慮し選定することが重要です。
年数が経つにつれて色々なスマートフォン端末が世に出てきていますので、今後もアンテナを広く張りながら環境を考慮して対応していきたいと思います。
LoRa_template

LoRa_template.json
https://jsonformatter.org/a3213d

lora_template-sdxl.json
https://jsonformatter.org/66e5c8

anotherjesse / lora-template 
https://replicate.com/anotherjesse/lora-template

anotherjesse / lora-template / API
https://replicate.com/anotherjesse/lora-template/api


https://lora-template.webflow.io


LoRA_template_20241127.ipynb
JavaScript/Python:備忘録と勉強

Python側でロードしたデータをJavaScriptで保持してHTMLで使用したかったため
部分的なものとなるがjsonへの変換方法を記録する

msg_jsonの値をHTML側で呼び出し、JavaScriptで処理を書くことで取り出すことが可能となる

```Python
# -*- coding: utf-8 -*-
import json  # jsonモジュールのインポート

class Main():
    def __init__(self):
        self.templates = [
            {
                'title': 'テストタイトル',
                'body': 'テスト本文',
                'signature': 'テスト署名'
            },
            {
                'title': 'テストタイトル1',
                'body': 'テスト本文2',
                'signature': 'テスト署名2'
            }
        ]

    def main(self):
        # JSON文字列を作成
        # 日本語対応のため ensure_ascii=False
        msg_json = json.dumps(self.templates, ensure_ascii=False)
        # 結果を返す
        return msg_json

# クラスのインスタンスを作成
main_instance = Main()
# メソッドを呼び出し、結果を表示
result = main_instance.main()
print(result)

```
Next.jsのlearnの紹介

リンク

https://nextjs.org/learn/dashboard-app

この記事はlearnページの全体像を伝えることを目的にしています

## 読者の想定レベル感
- Next.jsかReactをどこかで触った人
    - 一度も触っていないと、あまり実入りがないかも
- コメントアウトを空気読んで外せる人
    - 「Chapter XXXでこのコメントアウトを外して～」というのが多く、Reactに慣れていない人は事故ってハンズオン完走できないかも

## Optimizing Fonts and Images (Chapter 3)
- フォントのカスタマイズによるCLS(Cumulative Layout Shift)スコアの悪化を防ぐ利点。`next/font`で最適化してくれる。
- `<Image />`タグによる画像の最適化。

## Creating Layouts and Pages (Chapter 4)
- App Router
    - Next.jsの特別な意味を持つファイル　`page.tsx`と`layout.tsx`

## Navigating Between Pages (Chapter 5)
- `<Link />`タグによるクライアント側の移動(soft navigation)。`a`リンクによる画面の更新を含む移動はhard navigation。

## Fetching Data (Chapter 7)、Static and Dynamic Rendering (Chapter 8)
- SEOやキャッシュにより快適な静的レンダリング。
- データのリアルタイム性やユーザー個別コンテンツ向けの動的レンダリング。

## Streaming (Chapter 9)
- ローディング時、スケルトンによるSuspenseで画面を表示。
- Data Fetchはデータが必要な各コンポーネントで記述するように勧められています。

## Partial Prerendering (Chapter 10)
- 一部分を静的なコードで記述するという考え方

## Adding Search and Pagination (Chapter 11)
- `useSearchParams`によるクエリパラメータの操作
- `usePathname`によるパスの取得
- `useRouter`のreplaceによる遷移
- すべてクライアント側の操作なので、`"use client";`ディレクティブを使う

## Mutating Data (Chapter 12)
- データ作成を行うServer Actionについて
    - データ作成後にcacheのreavalidate
- `"use server";`ディレクティブ

## Adding Authentication (Chapter 15)
- `next-auth`のコード例

## Adding Metadata (Chapter 16)
- 動的なmetadataの設定方法

## learnを完走した感想
- getServerSidePropsを書かずになって、propsにデフォルトで存在するらしく、ここは混乱ポイント。
- Suspenseに関して、async FCですぐ子コンポーネントを書けてとても直観的(→これはSSRで、useEffectや`use()`互換とは異なる)。
- layout.tsx、page.tsx、route.tsxなど特別な意味を持つファイルがあり、覚える必要がある。https://nextjs.org/docs/app/api-reference/file-conventions
- `(overview)`ディレクトリなどの`()`を使った論理グループは下手に運用すると複雑になりそう。
- v14はキャッシュによる難化で`サーキット最速だけど非熟練者には厳しい`といった意見があったが、learnをやる限りではv15は難しくなさそうに感じた。
C_TS452_2021 - SAP Certified Application Associate - SAP S/4HANA Sourcing and Procurement対策（23/100）

【23日目】
トピック3：調達プロセス（4/13）

≪問題23≫
購買情報の価格条件を自動的に更新するには、どうすればよいですか。
▢基本契約の更新時に購買情報更新区分を選択する。
▢購買発注の登録時に購買情報更新区分を選択する。
▢見積の更新時に購買情報更新区分を選択する。
▢契約リリース受注の登録時に購買情報更新区分を選択する。

≪解答≫
▢基本契約の更新時に購買情報更新区分を選択する。
▢購買発注の登録時に購買情報更新区分を選択する。
█見積の更新時に購買情報更新区分を選択する。
▢契約リリース受注の登録時に購買情報更新区分を選択する。

≪解説≫  
◆購買伝票（購買発注、購買契約、または見積）を更新する際に購買情報更新区分を選択すると、自動的に購買情報の登録または更新が可能です。  
◆購買情報更新区分を使用して更新される項目は、伝票の種類によって異なります。  
（1）**見積**の場合：条件（価格、追加料金、値引、運送費など）、伝票番号、明細番号が更新されます。  
（2）**購買発注、契約リリース発注、分納契約**の場合：伝票番号および明細番号が更新されます。
【AWS】Lambda + RDS Proxyで「Lost connection to MySQL server during query」エラーになった場合の原因

# 概要
AWS LambdaからRDSにアクセスするたびにDB接続が確立すると、接続数の急増によりリソースが逼迫することがあります。RDS Proxyを使うとコネクションプールを利用できるので負荷を軽減できます。
と言うことで、RDS Proxyを導入してみたのですが、以下のエラーに遭遇。

> error: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query')

こちらの解決方法を紹介します。

# 解決方法
原因は、セキュリティグループにありました。
以下の記事を参考にしたら解決。

> RDSとRDS Proxyを同じSecurity Groupに紐付けると疎通エラーとなるので、個別に分けた方が良いかと思います。
https://blog.serverworks.co.jp/2022/01/20/093110

私は最初、以下のように設定していました。
・Lambda用のセキュリティグループx1
・RDS/RDS Proxy用のセキュリティグループx1

これを、上記記事にあるように、3つそれぞれ作成したら疎通できるようになりました。
・Lambda用のセキュリティグループx1
・RDS Proxy用のセキュリティグループx1
・RDS用のセキュリティグループx1

どうやら、RDSとRDS Proxyどちらにも接続できてしまうとルールの競合？的なものが起きて、エラーが発生するようです。

以下のstackoverflowにも記載がありました。

> The best thing you can probably do is to create a separate security group for the RDS Proxy.
It is not possible, right now through AWS web console, to create a self reference.
https://stackoverflow.com/questions/65634272/connection-error-when-using-aws-rds-proxy

stackoverflowの回答では、`'self referential' security group rule`を追加することでも対応できるそうですが、こちらの方は試していません。

また、RDS Proxyを使うと連続した負荷テストでは効果を発揮しますが、単発の処理性能が劣化するようです。これはコネクションプーリングの初期化で時間が要するため、その分長くなってしまっているのではないか？と思われます。以下の記事でも同じような現象がありました。詳細を把握できましたら別途更新します。

https://dev.classmethod.jp/articles/rds-proxy-connect-benchmark/
paizaラーニング問題集「陣取りゲーム」の自分のコードを改善してみた

▼問題

https://paiza.jp/works/mondai/a_rank_level_up_problems/a_rank_camp_boss

▼改善前の問題点とコード

A用の処理とB用の処理が似たような処理であるにもかかわらず、別々に書いていた。そのため、コードの行数が多くなった。また、A,Bそれぞれにリストや変数を用意したため使用したリソースが増えてしまった。

https://qiita.com/toytoy24/items/512003b0ff42c9aa40bb

▼改善後の考え方とコード、改善の成果

▽改善後の考え方

新しく考えた内容1.2.を以下に示します。

1. 問題文では、盤面は2次元で示されていますが、盤面のマスの内容は1次元のリストSで管理します。例えば3×3の盤面の場合、マスの内容はS[0]～S[8]で管理します。盤面の左上の座標を(y,x)=(0,0)とすると、(y,x)=(0,2)のマスの内容はS[2]で管理します。divmod(Sのindex,W)=div(0,3)の商がy,余りがxになります。(y,x)=(2,1)の要素はS[7]で管理します。上記と同様にdiv(7,3)の商がy,余りがxになります。

2. 前の番で勝ち取ったマスの(y,x)の情報をすべてchanges関数に送り、次の番で勝ち取れるマスの(y,x)を計算します。その結果の重複を排除し、再びp[n]に格納します。p[n]のとおり盤面のマスの内容を更新し、n = 1-n でAとBの順番を入れ替えます。while文を用いて上記の処理を、勝ち取ったマスがなくなるまで繰り返します。

▽改善の成果

・改善前がコードの行数が58だったのに対し、改善後は18にすることができました。

▽改善後のコード

```py
############### 関数処理 ###############

H, W = map(int, input().split())
N = input()

# S: 盤面のマスの内容を管理する一次元リスト
S = [s for _ in range(H) for s in input()]

# changes: 前の番で勝ち取ったマスの(y,x)から、次の番で勝ち取れるマスを計算する関数
def changes(positions):

    # posisions: 前の番で勝ち取ったマスの(y,x)を格納するリスト
    for (y, x) in positions:
         # ny,nx :前の番で勝ち取ったマスの(y,x)の上下左右のマスの座標を格納する変数
         for ny, nx in (y - 1, x), (y + 1, x), (y, x - 1), (y, x + 1):
             if 0 <= ny < H and 0 <= nx < W and S[ny * W + nx] == '.':
                 yield (ny, nx)

# 考え方1.

# n: n=0ならA、n=1ならBを示す変数
n = 0 if N == "A" else 1

# p: p[0]は、前の番でAが勝ち取ったマスの(y,x)を示す。p[1]はBのものを示す。
p = [
    {divmod(s_index, W) for s_index,s_value in enumerate(S) if s_value == "A"},
    {divmod(s_index, W) for s_index,s_value in enumerate(S) if s_value == "B"},
]

# 考え方2.
while p[0] or p[1]:
    p[n] = set(changes(p[n]))
    for y, x in p[n]:
        S[y * W + x] = "AB"[n]
    n = 1 - n

print(a := S.count("A"), b := S.count("B"))
print("A" if a > b else "B")
```
GithubへのPush時に403エラーが出た際の対処法

# はじめに

題名のエラーでいろいろ試してもなかなかうまくいかなかったので、記事にします。

# 問題

githubのリポジトリにPushしようとした際、以下のエラーが発生した。
```zsh
fatal: unable to access 'https://github.com/{ユーザ名}/{リポジトリ名}.git/': The requested URL returned error: 403
```

# 解決方法

Githubの設定の"Repository Permissions"から、"Read and write"を設定することで解決した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3456603/b7b223a4-eb4d-0103-36c8-e45f6fe09144.png)

# おわりに

前回pushした時は、エラーにならなかったので、最近追加された設定なのかもしれない。
ChainlitにLangfuseを導入する方法

# 概要

Chailitで作成したアプリのLLMOpsツールとしてLangfuseを導入しようとしたところ、公式のドキュメントやその他のサンプルコードが全く見つからかったのですが、試行錯誤の結果動作することがわかったためサンプルコードを残します。
同様の壁にぶつかった人の参考になれば幸いです。

## 導入手順

### 1. ChainlitのコードにLangfuseを追加する

LangChainにLangfuseを追加する手順と同様にChainlitのコード(ex: `main.py`, `app.py` etc...)に以下のコードを追加し、Langfuseを初期化します。

```py
from langfuse.callback import CallbackHandler
langfuse_handler = CallbackHandler(
    secret_key="sk-lf-...",
    public_key="pk-lf-...",
    host="https://cloud.langfuse.com"
)
```

https://langfuse.com/docs/integrations/langchain/tracing#add-langfuse-to-your-langchain-application

### 2. Chainlitの`@cl.on_message`にLangfuseのハンドラーを追加します

```py
# メッセージ受信時の処理
@cl.on_message
async def on_message(message: cl.Message):
    runnable = cast(Runnable, cl.user_session.get("runnable"))

    msg = cl.Message(content="")

    async for chunk in runnable.astream(
        {"question": message.content},
        config=RunnableConfig(callbacks=[
            cl.LangchainCallbackHandler(),
            langfuse_handler, #　ここにハンドラーを追加します
        ]),
    ):
        await msg.stream_token(chunk)

    await msg.send()
```

https://docs.chainlit.io/api-reference/integrations/langchain#langchain-callback-handler

## 結論

Langfuseの公式ドキュメントの`invoke`の例のように、`Runnable`の引数の`config(RunnableConfig)`の`callbacks`に指定してあげれば良いようです。

```py
chain.invoke({"input": "<user_input>"}, config={"callbacks": [langfuse_handler]})
```

https://python.langchain.com/api_reference/core/runnables/langchain_core.runnables.config.RunnableConfig.html

## 参考

https://github.com/orgs/langfuse/discussions/1449

https://github.com/Chainlit/cookbook/issues/125
C#でコンストラクターインジェクション【Microsoft.Extensions.DependencyInjection】

# 概要
- Microsoft.Extensions.DependencyInjection ServiceCollectionの機能の一つ
- 登録したクラスのコンストラクターにおけるDIを、別の登録したクラスによって自動解決
- クラスさえ登録しておけば、コンストラクターにおけるDIを意識せずにインスタンス化が可能

# 例
```Program.cs
using Microsoft.Extensions.DependencyInjection;

namespace TestDI
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            // クラスの登録
            var services = new ServiceCollection();
            services.AddTransient<IMessenger, Messenger>();
            services.AddTransient<ISplitter, Splitter>();

            var provider = services.BuildServiceProvider();
            // 登録したMessengerのインスタンスを取得する
            // MessengerにDIされているISplitterは
            // 登録済みのSplitterを使って自動的に解決される
            var messenger = provider.GetRequiredService<IMessenger>();
            messenger.SendMessage("Hello!");
        }
    }
}
```

```IMessenger.cs
namespace TestDI
{
    internal interface IMessenger
    {
        void SendMessage(string message);
    }
}

```

```Messenger.cs
using System;

namespace TestDI
{
    internal class Messenger : IMessenger
    {
        private ISplitter splitter;

        public Messenger(ISplitter splitter)
        {
            this.splitter = splitter;  // このDIは自動的に行われる
        }

        public void SendMessage(string message)
        {
            Console.WriteLine(message);
            this.splitter.SendSplitLine();
        }
    }
}
```

```ISplitter.cs
namespace TestDI
{
    internal interface ISplitter
    {
        void SendSplitLine();
    }
}
```

```Splitter.cs
using System;

namespace TestDI
{
    internal class Splitter : ISplitter
    {
        public Splitter()
        {
            ;
        }

        public void SendSplitLine()
        {
            Console.WriteLine("------------------------------");
        }
    }
}
```

# 所感
この機能を使用したコードを始めて見たときは少し混乱しました。
「あれ？？どこでDIしてるの？？」といった感じです。
一度分かってしまえば、とても便利に使えると思います。
複数のクラスにDIするときは特に。

# 参考にしたもの
公式ドキュメント：https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1
分かりやすいまとめ記事：https://qiita.com/TsuyoshiUshio@github/items/20412b36fe63f05671c9
ESLintのプラグインを自動公開する

# はじめに

こんにちは、エンジニアのkeitaMaxです。

前回までに作成したESLintのプラグインを実際にnpmに公開してみます。

https://qiita.com/keitaMax/items/f6f264194cfdc1f3167f

https://qiita.com/keitaMax/private/3feb1a43c24917a6ee69

# package.jsonの修正

package.jsonを以下のようにします。

公開するプラグインの名前は`"eslint-plugin-hitasura-system-develop"`としました。

```json:package.json
{
  "name": "eslint-plugin-hitasura-system-develop",
  "version": "0.0.5",
  "description": "",
  "main": "lib/index.js",
  "scripts": {
    "build": "tsc",  
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/NiheiKeita/eslint-plugin-hitasura-system-develop"
  },
  "files": [
    "lib"
  ],
  "private": false,
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^8.8.1",
    "@typescript-eslint/parser": "^8.8.1",
    "eslint": "^9.12.0",
    "typescript": "^5.6.3"
  }
}
```

# 公開する


https://www.npmjs.com

npmのアカウントをあらかじめ作成していたので、こちらで新しく今回公開するプラグインのパッケージを作成します。

以下のコマンドでnpmにログインをします。

`npm login`

そして以下コマンドで公開するためにpublishします。

`npm publish`

npmにログインをしてみてみると以下のようにライブラリが公開されています。

# GitHub Actionsで公開できるようにする

以下のようにGitHub Actionsを作成します。

```yml:publish.yml
name: publish to npm
on:
  push:
    tags:
      - 'publish.v.*'

permissions:
    id-token: write
    contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '21.x'
          registry-url: 'https://registry.npmjs.org'
      - run: npm ci
      - run: npm run build
      - run: npm publish --provenance --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

```

`'publish.v.*'`というタグをGitHub上でつけると自動的にbuildしてリリースされるようなものを作成しました。

# NPM_TOKENの作成

GitHubでnpmにアクセスするために`NPM_TOKEN`を設定します。

https://www.npmjs.com

先ほど登録したnpmでアクセストークンを作成します。

左メニューにある`Access Tokens`をクリックします。

![スクリーンショット 2024-12-02 19.57.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/3dce8f5b-a6e2-c6e2-d162-a75d73d705e9.png)

そうしたら、`Generate New Token`をクリックします。

![スクリーンショット 2024-12-02 19.58.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/ed903910-1ef3-824e-5d71-9513a0526478.png)

トークンの名前などを入力します。

アクセス権限は、今回作成したパッケージのみの読み書き権限を選択しました。

![スクリーンショット 2024-12-02 20.00.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/d9b5ff47-1eaa-010d-7859-0c4bda1b9ac0.png)

入力したら`Generate Token`をおすとトークンが作成され、表示されます。

これで`NPM_TOKEN`の作成は完了です。

# NPM_TOKENをGitHubに設定する

最後にGitHubにトークンを設定します。

ここから先は以前の記事とほぼ同じなので割愛させていただきます。

https://qiita.com/keitaMax/items/241248162d5ad4e80b79

こちらを参考にしてください。

これで、実際にタグを打てば自動的にリリーすることができます！

# おわりに

この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。

最後まで読んでいただきありがとうございました！

# 参考

https://qiita.com/keitaMax/items/241248162d5ad4e80b79
Workato：オンラインストレージからダウンロードしたテキストファイルに対して関数が利用できない場合の対応方法

# はじめに

BoxなどのオンラインストレージからダウンロードしたテキストファイルのFile contentsを文字列型のフィールドにセットし、関数を利用して文字列を加工しようとすると、次のようなエラーが発生します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/9444d72d-d509-d30c-ff8f-dba15383c03f.png)

エラーが発生する原因は、File contentsがInputStream型であるためです。InputStream型の値に対しては文字列型に対応する関数を適用することができません。

# 対応方法

対応方法として2つの方法があります。いずれかの方法で対応を行うことで、ダウンロードしたテキストファイルを文字列型として扱えるようになり、文字列型に対応した関数が利用できるようになります。

## １．File contentsを一旦変数に格納し、後続のアクションで変数に格納された値を加工する

BoxのFile contentsを変数に格納すると、文字列型の値として自動的にキャストされます。これにより、後続のステップでは変数に格納された値を文字列型の値として扱うことができ、文字列型に対応した関数の利用が可能になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/8b68373f-b2c4-28f7-e347-259d52ead877.png)

## ２．`to_s`メソッドで文字列型にキャストする

File contentsに対して`to_s`メソッドを適用することで、文字列型にキャストすることが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/b4a4b657-03f7-292e-6ec3-375a58767df7.png)

また、`to_s`メソッドに続いてメソッドチェーンの形で文字列型に対応した関数の利用も可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/eed3e492-c5af-40e1-4e46-0c0f3ceb2c79.png)
ESLintのプラグインのテストをGitHub Actionsで自動実行する

# はじめに

こんにちは、エンジニアのkeitaMaxです。

https://qiita.com/keitaMax/items/f6f264194cfdc1f3167f

https://qiita.com/keitaMax/items/6337fb82e222b66894fe

https://qiita.com/keitaMax/items/782dec32ecf2a6b52169

前回テストを作成しましたが、今回はGitHubにPushした時にテストを動かせるようにしたいと思います。

# やりたいこと

GitHubにPushした時に,GitHub Actionsを使用してテストを動かすCIを作成します。

# GitHub Actions作成

`.github/workflows/unittest.yml`ファイルを作成します。

内容は以下のようにしました。

```yml:.github/workflows/unittest.yml
name: Test

on: [pull_request]

jobs:
  test:
    name: Test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: install
        run: npm ci
      - name: build
        run: npm run build
      - name: test
        run: npm run test

```

これで準備完了です。


# Pushする

実際にPushしてPRを作成すると以下のように自動テストが走るようになります。

![スクリーンショット 2024-12-04 20.12.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/aae7ba3e-55dd-f795-4b49-007f34a0a4b4.png)

自動テストが完了し問題がないと、以下のようにマージができるようになれば成功です。

![スクリーンショット 2024-12-04 20.13.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/3b160fd7-55df-f33a-61a9-76b80598121e.png)



# おわりに

この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。

最後まで読んでいただきありがとうございました！

# 次の記事
サーバーに入った時に仕方なく触ったVimの操作がちょっと速くなるコマンド3選

## こんなことありませんか？
リモートサーバーの設定いじらないといけないな〜。

あー、でも普段使ってるエディタで接続するとなると設定が面倒だから最初から入っているVimもしくはviで書き換えちゃおう。

さて、ファイルを開いて、iを押して…
下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下右右右右右右右右右右右右右右右右右右右右右右右右バックスペースバックスペースバックスペースバックスペースバックスペースバックスペースバックスペースバックスペース書き換え

さて、次は下の行にも設定追加しなきゃ。

右右右右右右右右右右右右右右右右エンター追記:wq

よしOK！

## よしOK！じゃないっす。
いや、まぁ目的さえ達成できればOKなのですが、コマンドを3つ覚えるだけでちょっと速くできます！
たったそれくらいの労力で同じことができるなら速い方がいいですよね！？

ということで今回は3つに絞って紹介するので、手元で長いファイルをvimで開いてみましょう。
長い文章用意するの面倒だよってときは、`man ls | vim`とでも打っておけば、lsコマンドのマニュアルのテキストをVimで開くことができるので、簡単に手元でいじれると思います。

## 前提：移動はノーマルモードでお願いします。
※いきなりインサートモードに入らないでください

## 良い感じに下に移動したい
`Ctrl d` 

こちらを押すと画面半分の量だけ下にスクロールすることができます。
これで最初に連打していてた下の回数を圧倒的に減らせます。
移動幅は画面サイズにもよりますが、23インチくらいのディスプレイを横に使っている人であれば、30行分くらいジャンプできるので、下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下下が1コマンドで済むようになります。下移動が30倍速になります。

## ここを書き換えたい
`caw`

さぁ、書き換えたい文字の上までカーソルが来たら高らかに`caw`と打ちましょう。
すると、カーソルが乗っていた単語が消えて、しかもインサートモードのなっています！

`c`が文字を消しながらインサートモードに入るコマンドなのですが、`aw`とセットで使うことで今カーソルが乗っている単語全体に`c`の効果を発揮できるというわけです。

今までだったらその単語の末尾まで移動してバックスペースしまくっていたので、かなり簡単に単語を変更することができるようになりました。

## 下の行に追加したい
`o`
最後は`o`を押してみましょう。
すると下の行に改行されてインサートモードに入ることができました。
あとは入力したい文字を入れて保存するだけ！

## 以上
ちょっとだけ操作が早くなったと思うので、浮いた時間でお茶でも飲みましょう。

## 3つに厳選した理由
もちろんいっぱい知っておくに越したことはありません。

例えば画面半分だけでなく、一画面丸ごと行ったり、下じゃなくて上に行ったり、それはもう縦横無尽に移動する方法がたくさんあります。

そして大体こういう記事を書くと、Vimのコマンドの良さを余す所なく伝えたいという衝動に襲われてしまい、ついついいっぱい出しちゃうのですが、ここは仕方がなくvimを触った人の気持ちを考えてみましょう。

**「...3つが限界です！」**

ですよね！

私もVimを使い始める前だったら、なんでそんなにたくさんコマンド教えてくるんだ。覚えられるわけがないだろうと思ってしまいます。

慣れているとついつい忘れるけど一気に10個とか覚えるのきついんです！

ということで今回は3個に絞り切りました！

これを気に興味を持ったよという人がいるかどうかはわかりませんが、入門するならこの本が結構おすすめです。
[実践Vim](https://www.amazon.co.jp/dp/4048916599)

なんというかコマンドに込められた意味がわかって、単純記憶ではなく意味記憶でいろいろな操作を覚えていくことができる1冊です。
最終的には思考のスピードで編集できるんだとか…。

ちなみに余談ですが私は普段IntellJとかVS Codeを使っています。

もしこの内容が参考になった方はいいねしてもらえると今後のアウトプットの活力になりますので何卒よろしくお願いしますm(_ _)m
Git 新規リポジトリにプログラムをPushする方法

# git 新規リポジトリに既存のプログラムをPushする方法
### ～流れ～
①　GitHubでリポジトリ作成
②　ローカルでプログラムアップロード
③　バージョン管理用タグを付け（必要な場合）

### 1. GitHubで新規リポジトリを作成

1. GitHubにログインし、右上の「+」ボタンをクリックして「New repository」を選択します。
2. リポジトリ名を入力し、必要に応じて説明を追加します。
3. privateかpublicを選択（非公開か公開か） 
4. 「Create repository」をクリックします。

### 2. ローカルリポジトリの初期化と既存プログラムのアップロード

1. ターミナルを開き、既存のプロジェクトディレクトリに移動します。
    
    ```bash
    cd /path/to/your/project
    
    ```
    
2. Gitリポジトリを初期化します。
    
    ```bash
    git init
    
    ```
    
3. すべてのファイルをステージングします。
    
    ```bash
    git add .
    
    ```
    
4. 最初のコミットを行います。
    
    ```bash
    git commit -m "Initial commit"
    
    ```
    
5. GitHubリポジトリをリモートとして追加します。
    
    ```bash
    git remote add origin https://github.com/username/repository.git
    
    ```
    
6. ブランチを名変更（デフォルトがmainの場合変更しなくても良い）
    
    ```bash
    //ブランチ名がmasterの場合mainに変更（mainの方が書きやすいから）
    git branch -m master main
    または
    git branch -M main
    
    ```

7. ブランチをpush（アップロード）
    
    ```bash    
    git push -u origin main
    
    ```
    ※成功するとGitHubにアップロードされます。

### 3. タグの作成とプッシュ

　バージョンごとにタグを付けて管理する方法です。
　これをすることで過去のバージョンの状態を同じリポジトリで確認できます。

　※現在のローカルの状態をpushしたものにタグが付くものになるので
　リモートのmainブランチにタグが付くわけではないことにご注意ください。


1. タグを作成します。（メッセージ内容付き）
    
    ```bash
    git tag -a v1.0 -m "メッセージ内容（適当）"
    
    ```
    
2. タグをリモートリポジトリにプッシュします。
    
    ```bash
    git push origin v1.0
    ```