OmniAICreator/Qiita-1.07M huggingface dataset:
TCPって実際なにしてんの？(3.順序制御、再送制御編)

# これはなに
TCPの勉強をしたので忘れないようにまとめる。
主にヘッダ、コネクション管理、再送制御、順序制御、輻輳制御について書く。
OSI参照モデルの話はみんな書いているので書かない。

今回は順序制御、再送制御編。

参考文献:WEB+DB PRESS plusシリーズ TCP技術入門
https://gihyo.jp/book/2019/978-4-297-10623-2

### 目次
[1.順序制御の概要](#1順序制御の概要)
[2.シーケンス番号の割り振り](#2シーケンス番号の割り振り)
[3.具体的な順序制御の仕組み](#3具体的な順序制御の仕組み)
[4.再送制御の概要](#4再送制御の概要)
[5.再送タイマーを用いる方法](#5再送タイマーを用いる方法)
[6.重複ackを用いる方法](#6重複ackを用いる方法)
[7.おわりに](#7おわりに)
[8.参考文献](#8参考文献)

# 1.順序制御の概要
<a href="https://qiita.com/BEBE4410/items/dad48a6b7836dfb6c905">ヘッダ編</a>でセグメントにシーケンス番号が振られていることは既に述べた。
このシーケンス番号を使って順番通りにセグメントを送信することを順序制御と言う。

# 2.シーケンス番号の割り振り
シーケンス番号は0,1,2,…と割り振られているかと思いきや、そうではない。
n番目のシーケンス番号は「n-1番目のセグメントのシーケンス番号＋n-1番目のセグメントのデータサイズ」である。

# 3.具体的な順序制御の仕組み
送信側のシーケンス番号に対して、受信側が「次に受け取るべきセグメントのシーケンス番号」を確認応答番号として返すことで順序制御を行う。
送信側は次のシーケンス番号がわかっているので、想定通りの確認応答番号が返ってきたらセグメントが正しく受信されたことがわかる。


具体例を示す。
AとBが通信をしているとする。
1. Aがシーケンス番号1で100バイトのデータをBに送ったとする
1. Bは確認応答番号領域に101と書いて応答する
1. Aは想定通りの101が返ってきたので次はシーケンス番号101のデータを送信する

やってることは単純。
「次に受け取るべきセグメントのシーケンス番号」を確認応答番号として返すというのがミソ。
後述の再送制御でこの特性を用いるので覚えておいてほしい。

# 4.再送制御の概要
通信において符号誤りが発生したり、パケットロスなどで正確にデータが届かないことがある。
TCPではそのような場合、失われたセグメントを再び送信する。
これを再送と言う。
TCPでは主に二種類の消失検知を実装している。
* 再送タイマーを用いる方法
* 重複ACKを用いる方法

# 5.再送タイマーを用いる方法
TCPでは通信が始まるとセグメント送信に対する応答までの時間を継続的に計測する。
これをもとに平均応答時間(RTT)を算出し、RTTを少し超える時間を再送タイマー(RTO)として設定する。
RTOを超えても応答がなかったらセグメントが消失したと判断し再送する。

# 6.重複ACKを用いる方法
次回に書くがTCPでは複数のセグメントを応答を待たずに送信してもよい。
なぜなら一つ一つ応答を待っていたら効率が悪いからだ。

このとき途中のセグメントが一つ消失したとする。
そうすると消失セグメント以降のセグメントに対する応答は全て消失セグメントのシーケンス番号になる。
なぜなら受信側は「次に受け取るべきセグメントのシーケンス番号」を確認応答番号として返すからだ。
つまり消失セグメントを受信しない限り受信側はなにを受信しても消失セグメントの番号を返し続ける。
この特性を用いて送信側はセグメントの消失を検知する。
具体的には3つ重複ACKを受信したら再送を行う。

# 7.おわりに
今回は順序制御と再送制御について書いた。
少しづつアルゴリズム的な部分が出てきておもしろいと思う。
次回はTCPの目玉の輻輳制御について書く。
より高度なアルゴリズムが出てくるのでお楽しみに。
次回：未筆

# 8.参考文献
WEB+DB PRESS plusシリーズ TCP技術入門
https://gihyo.jp/book/2019/978-4-297-10623-2
OracleデータベースにOracle Clientなしでリモート接続する方法3つ

先日[Windowsローカル環境でOracleデータベースに入門](https://qiita.com/YouKnow/items/1d5b695629af75465dcd)したばかりの赤ん坊です。


Oracleデータベースにリモート接続するには「クライアントマシンにOracle Clientをインストールする必要がある」という説明が多かったので、Oracle Clientをインストールしなくても済む方法が無いか簡単に調べた。

# まとめ
**OracleデータベースにOracle Clientなしで接続する方法3つ**

- JavaアプリケーションからはODBC Thinを使う
- .NETアプリケーションではDLL形式のODP.NETを使う
-  A5:SQL Mk-2 では直接接続方式を使う

結構普通にあった。


# Oracle Clientをインストールすると
クライアントマシン向けのOracle Clientというソフトウェアをインストール・設定することで、別マシンのOracleデータベースにリモート接続できるようになる。

Oracle Clientをインストールすると、サーバー側用ソフトウェアをインストールした時と同じように、**ORACLE_HOME**や**tnsnames.ora**の置き場所も作られてしまう。

ちょっと気軽に接続したいぜぐらいのノリだったらいちいち仰々しくない？などと思ったのが今回調べるに至ったきっかけ。

# JavaアプリケーションからOracleデータベースにリモート接続する方法

以下2種類のうちどちらかのドライバを使う。
推奨は JDBC Thin とのこと。

- **JDBC Thin ドライバ**
Oracle Clientにも含まれているが、JARファイルにも含まれているので、Oracle Clientは必須ではない。
- **JDBC OCI ドライバ**
Oracle Client に含まれており、Oracle Clientインストールが必要。

# .NET アプリケーションからOracleデータベースにリモート接続する方法
**ODP.NET** ドライバ が必要。

**入手方法**
- Oracle Client (バージョンによっては Oracle Database Access Component)
- Nuget

**Nuget**からならODP.NETをパッケージという形で入手できるので、アプリケーションにDLLとして挿せばよく、Oracle Clientをインストールせずに済むようだ。

接続先情報については、tnsnames.oraファイルが無い代わりに自前で接続記述子を指定するようだ。

https://pita-gora.co.jp/c-sharp-oracle-no-client-1/

https://qiita.com/yaju/items/82df63b97a41720e197c

# A5:SQL Mk-2 からOracleデータベースにリモート接続する方法

思い返せば、私は仕事で開発マシンのA5からDBサーバーのOracleに難なく接続できていたが、そのマシンにはOracle Clientはインストールされていなかったので気になって調べた。

A5からOracleに接続するとき、以下の2つの方式から選択できるようになっている。
- **OCI経由**　Oracle Clientを使って接続する。
- **直接接続**　Oracle Clientを使わずに接続する。

直接接続方式ならOracle Clientインストールが不要。

直接接続方式では、A5の開発言語Delphi等で使えるUniDACという有償コンポーネントを使っているそうだ。A5開発者の方によれば、おそらくUniDACはOracle Clientと同等の機能を有しているとのこと。

https://a5m2.mmatsubara.com/wp/?topic=oracleoci%e7%b5%8c%e7%94%b1or%e7%9b%b4%e6%8e%a5%e6%8e%a5%e7%b6%9a%e3%81%ae%e7%9b%b4%e6%8e%a5%e6%8e%a5%e7%b6%9a%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6

https://a5m2.mmatsubara.com/wp/?p=358
Web 開発再入門 #23 ― Windows サービス化

# Web 開発再入門 #23 ― Windows サービス化

## はじめに
ビルドして作成した “fmockup-0.0.1.jar” を Windows サービス化します。
Windows サービスとは、Windows の OS のバッグラウンドで実行するプログラムです。

OS：Operating System

## ファイル・ディレクトリ構成

D:\\
├ Development\\
│&nbsp;└ Workspace\\
│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└ fmockup\\
│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└ build\\
│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└ libs\\
│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└ fmockup-0.0.1.jar ← コレ
└ Systems\\
&nbsp;&nbsp;&nbsp;&nbsp;└ fmockup\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ jdk-nn.nn.n\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ lib\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;└ fmockup-0.0.1.jar ← コレ
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ log\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ sql\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└ WinSW.NET-nnn\\ ← ココ
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ WinSW.NET461.exe
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└ WinSW.NET461.xml ← コレ

## ファイルの文字コード、改行コード

多分、UTF-8、Windows 改行（CR LF）が無難と思います。

## ビルド、デプロイ

1. Eclipse の [パッケージエクスプローラー] で [fmockup [boot] [devtools]] - [cn.com.xxxx.fmockup] を選択して右クリックし、[実行(R)] - [実行 の構成(N)...] で [実行構成] を開く。

2. [Gradle タスク] を設定する。
[名前(N)] テキストボックス：fmockup - build.jar
[Gradle タスク] テキストボックス：build
[作業ディレクトリー] テキストボックス：${workspace_loc:/fmockup}

3. [実行(R)] ボタンを押下し、ビルドする。

4. エクスプローラーで、フォルダー “D:\Development\Workspace\fmockup\build\libs” 配下のファイル “fmockup-0.0.1.jar” をフォルダー “D:\Systems\fmockup\lib” 配下にコピーする。

## Windows サービスの登録、起動

1. テキスト・エディターで、ファイル “WinSW.NET461.xml” を作成する。
    ```xml:WinSW.NET461.xml
    <service>
    	<id>springboot.fmockup</id>
    	<name>System - fmockup</name>
    	<description>Service for fmockup.</description>
    	<logpath>D:\Systems\fmockup\log</logpath>
    	<executable>D:\Systems\fmockup\jdk-17.0.2\bin\java</executable>
    	<workingdirectory>D:\Systems\fmockup\lib</workingdirectory>
    	<arguments>-Xmx256m -classpath "D:\Systems\fmockup\jdk-17.0.2" -Dserver.port=8081 -Dproperty.home-directory-path="D:\Systems\fmockup" -jar "D:\Systems\fmockup\lib\fmockup-0.0.1.jar"</arguments>
    	<logmode>rotate</logmode>
    </service>
    ```
    JDK、ポート番号、ホームパス、.jar ファイルを指定しています。

2. コマンド・プロンプトで、Windows サービスを登録する。
    ```bat:コマンド・プロンプト
    C:\Users\xxxx> D:
    D:\> cd D:\Systems\fmockup\WinSW.NET461
    D:\> cd D:\Systems\fmockup\WinSW.NET461> WinSW.NET461.exe install

    D:\> cd D:\Systems\fmockup\WinSW.NET461> exit
    ```
3. スタートメニュー隣の検索で “サービス” を検索してサービスを起動し、サービス名一覧から “System - fmockup” を選択し、“サービスの開始” をクリックする。

4. ブラウザーで “<http://localhost:8081/pages/login.html>” をアクセスする。
Web 開発再入門 #22 ― テスト（Burp Suite 使用）

# Web 開発再入門 #22 ― テスト（Burp Suite 使用）

fmockup

## はじめに

Burp Suite を使用して HTTP アクセスのテストを行います。す。
Burp Suite を使用することで、ブラウザーと Web サーバーとの間の HTTP アクセスをインターセプトし、HTTP リクエストや HTTP レスポンスを覗いたり改ざんしたりすることができます。

## Burp Suite を用いたテスト

1. “Web 開発再入門#21 - テスト（Eclipse 使用）” の方法で、Web アプリケーションを起動しておく。

2. スタートメニューから Burp Suite を起動する。

3. [Welcome to Burp Suite Community Edition. ...] ダイアログで、[Next] ボタンを押下する。

4. [Select the configuration that you would like to load for this project] ダイアログで [Start Burp] ボタンを押下する。

5. 画面の [Proxy] タブを押下する。

6. 画面の [Intercept] タブを押下し、[Open browser] ボタンを押下する。Chrome が開かれる。

7. Chrome で、“http://localhost:8080” をアクセスする。
この操作により、8. にて、Burp Suite が 8080 以外のポート番号を使用するようになる。

8. 画面の [Proxy settings] タブを押下し、[Proxy listener] の一覧で [127.0.0.1:8081] がチェックされていることを確認する。

9. 画面の [Intercept] タブを押下し、必要に応じて [Intercept is off] ボタンを押下し、HTTP リクエストをインターセプトする。

10. Chrome で Web ページをアクセスすると、Burp Suite がインターセプトし、画面にリクエスト・ヘッダーを表示する。

11. 画面の [Forward] ボタンを押下すると、インターセプトが解除される。

12. 画面の [Http history] ボタンを押下し、アクセス一覧を押下し、画面にリクエスト・ヘッダーやレスポンス・ヘッダーを表示する。

## 参考

**Burp Suite の使い方**

https://www.leon-tec.co.jp/blog/diary/10174/#second

https://qiita.com/abe_n/items/0c14fe70c4eb4ad602a4
Web 開発再入門 #21 ― テスト（Eclipse 使用）

# Web 開発再入門 #21 ― テスト（Eclipse 使用）

fmockup

## ファイル・ディレクトリ構成

D:\\
├ Development\\
└ Systems\\
&nbsp;&nbsp;&nbsp;&nbsp;└ fmockup\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ jdk-nn.nn.n\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ lib\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ log\\ ← コレ
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├ sql\\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└ WinSW.NET-nnn\\

## フォルダーの作成

1. エクスプローラーで、フォルダー “D:\Systems\fmockup\log” を作成する。

## プログラムの実行

1. Eclipse で、“fmockup [boot] [devtools]” を選択して右クリックし、 [実行 (R)] - [3. SpringBoot アプリケーション] をクリックする。

2. ブラウザーで “<http://localhost:8080/pages/login.html>” をアクセスする。
2024.4月新入社員向け・Power Platform 研修

# 新入社員のためのPower Platform研修

## はじめに

今回は、新入社員の皆さんのためにPower Platformの研修を作成する機会をいただきました。私自身は、AzureやXboxなどの分野で経験を積んできましたが、Power Platformは新入社員の方々にとって非常に適した学習ツールだと考えています。
この研修では、単にツールや製品の使い方を学ぶだけでなく、アプリ開発やデジタルトランスフォーメーション（DX）を推進するために必要な考え方を身につけることを目的としています。


## Power Platformの概要
Power Platformは、Microsoft社が提供するローコード/ノーコード開発プラットフォームです。以下の4つの主要コンポーネントで構成されています：

1. Power Apps：アプリケーション開発
2. Power Automate：ワークフローの自動化
3. Power BI：データの可視化と分析
4. Power Virtual Agents：チャットボットの作成

これらのツールを使用することで、プログラミングの専門知識がなくても、業務効率化やデータ活用のためのソリューションを素早く構築することができます。

## 研修の目的
この研修では、以下の目的を達成することを目指します：

1. Power Platformの基本概念と各コンポーネントの役割を理解する
2. 実際の業務シナリオを想定したアプリ開発や自動化のハンズオンを通して、Power Platformの活用方法を学ぶ






## RPAとローコードの基本


### RPA(Robotic Process Automation)とは

（よくある説明では）、RPAとは、ソフトウェアロボットを使って既存の業務プロセス、特に手作業による反復作業を自動化する技術のことです。
![RPA.png](https://i.gyazo.com/3e1085b9424940c75c5411653ac925c9.png)
ユーザーの操作を記録し、ロボットにそれを再現させることで、データ入力、システム間の連携、定型業務の自動化などが可能になります。

RPAは、おばあちゃんのお手伝いロボットみたいなものだと思ってください。
おばあちゃんには、毎日同じように繰り返す家事の手伝いが必要です。例えば、

- 新聞を取りに玄関まで歩く
- 掃除機をかける
- 洗濯物を干す
- 料理を作る

など、決まった作業をこなさないといけません。

そこで、おばあちゃんはロボット家事手伝いを雇うことにしたのです。最初は、おばあちゃん自身が作業手順を1つずつロボットに教え込みます。
「まず新聞を取りに玄関まで行き、次に掃除機をかける、そしてこうしてこうするんだ」と、作業の流れを覚えさせていくわけです。
そうすれば、翌日からはロボットが自動で家事を処理するようになる。おばあちゃんは横になってボケーッとしていても構いません。
ロボットは人間よりも器用で確実に作業をこなせます。ミスの心配もありません。おばあちゃんは楽々と、ロボットにうんざりする家事を任せられるのです。



![ROBO-OBAACHAN.png](https://i.gyazo.com/8356a9ebd0c21065bfab699c899b83f3.png)

このように、RPAはあらかじめ決められた作業工程を自動的に処理してくれる、おばあちゃんの「家事ロボット手伝い」みたいなものなのです。



### ローコード開発（と市民開発）、とは

ローコード開発というのは、プログラミングのコーディングをほとんど行わずに、ビジュアルな画面上でドラッグ&ドロップによりアプリケーションを作れる開発手法のことです。

これは、レゴブロックで簡単に建物を作るようなものだと思ってください。レゴには決まった形の部品があり、それらをくっつけ合わせるだけで家やビル、車などを自由に作れますよね。ローコードも同じように、画面パーツや機能ブロックを組み合わせることで、データ入力アプリや業務フロー、分析ツールなど、様々なアプリを作ることができます。

このローコード開発が可能にする大きな変革が、「市民開発」と呼ばれるものです。市民開発とは、ITの専門家ではなく、一般の社員や現場のビジネスユーザーがアプリ開発に参加することです。
従来のシステム開発は、ITエンジニアがユーザー要件を聞いて開発をするというプロセスでした。しかし、最初からユーザー自身がアプリ作りに関われば、要件の受け渡しロスがなくなり、現場の実態に沿ったシステムができるはずです。

ローコードのたとえ話です。

営業部門の社員なら、顧客管理アプリを自分で作れますし、人事部門の方なら社員スキル管理システムを開発できるかもしれません。現場の知見を詰め込めるので、使いやすく実用的なシステムが構築できるのは市民開発の強みです。
プログラミングが苦手な人でも、ローコードなら誰でもアプリ開発に参加できます。ITリソースが不足していても、業務プロセスのデジタル化が進められます。また、市民開発により現場主導のDXが実現できるでしょう。
このように、ローコード開発は単なる技術革新ではなく、「市民開発」という新しい開発スタイルを生み出しつつあります。

![3bea1dc5297750c5b8f0d875ca61c846[1].png](https://i.gyazo.com/3bea1dc5297750c5b8f0d875ca61c846.png)



## 今回のまとめ

Power Platformは、RPAやローコード開発により、誰もが手軽にデジタルソリューションを構築できる革新的なプラットフォームです。この研修を通じて、新入社員の皆さんがPower Platformの可能性を体感し、DXを自ら推進するスキルと発想力を身につけられることを願っています。デジタル時代に向けて、みなさんの成長を期待してます！
Crystalでクロスプラットフォームなリンカーのオプションをつける

## はじめに

Crystalを使用してクロスプラットフォームなCバインディングを書く際に、OSごとに適切なリンカーオプションを指定する方法がよくわからなかったので簡単に調べました。

## Crsytalにおけるリンカーオプションの書き方

CrystalでCバインディングを書く場合は次のようになります。

```sh
@[Link("ui")]
lib LibUI
  fun main = uiMain
  fun quit = uiQuit
end
```

ここで、`@[Link("ui")]` はアノテーション（注釈）です。


[codegen/link.cr](https://github.com/crystal-lang/crystal/blob/master/src/compiler/crystal/codegen/link.cr) を見るとリンカーアノテーションの挙動はOSごとに異なります。

- WindowsではMSVCリンカーのオプションを利用します。
- LinuxとMacOSではGNU ldリンカーのフラグをそれぞれ指定します。

このように２種類の異なるリンカーを使うため、最初から macro を利用してOSごとに場合分けをしてLinkアノテーションをつける方法が有効です。

```crystal
{% if flag?(:windows) %}
  @[Link("#{__DIR__}/../../libui")]
{% else %}
  @[Link(ldflags: "-L #{__DIR__}/../../ -lui")]
{% end %}
lib LibUI
```

この方法により、OSに応じて適切なリンカーオプションを動的に設定することが可能です。

## 共有ライブラリの作成と配布の課題

共有ライブラリの作成や配布は大きな課題で、現状は定まった方法がありません。

Rubyでは、必要なso、dll、dylibファイルをビルドしたり、ベンダーディレクトリにダウンロードするRakeタスクを作成することができました。同様の方向性としては、`syard.yml` の postinstall を利用できる可能性があります。


```yaml
scripts:
  postinstall: crystal run download.cr
```

しかし、shards.yml の postinstall はあまり評判がよくありません。

https://forum.crystal-lang.org/t/shards-postinstall-considered-harmful/3910

https://forum.crystal-lang.org/t/survey-use-cases-for-shards-postinstall/5836

今のところコミュニティで広く受け要られている方法はないと考えられます。
mt5linuxでcopy_ticks_rangeできない

リモート側でdatetimeがインポートされていないから、copy_ticks_rangeできない。
なんとも粗削りな実装だが、ゼロから書くよりは全然助かる。

```
# mt5linux/__init__.py
# 366行目に追加
        self.__conn.execute('import datetime')
```

結局mt5linuxは使うのをやめて、Windows+WSL2にするので、無用のノウハウとなったが。
環境をUbuntu22からWSL2+Ubuntu22に移行した

忘れないように、メモ。
Windows用のGPUドライバとPythonインタプリタはインストール済である前提。

# 必要なバージョンの確認

Tensorflow、Python、cuDNN、CUDAのバージョン対応表
https://www.tensorflow.org/install/source#gpu

この対応表の組み合わせでインストールすれば、GPUが有効になる。
例えばPython3.11（3.9-3.12）の場合、tensorflow-2.16.1、cuDNN8.9、CUDA（Toolkit）12.3で良い。

# CUDA

CUDA Toolkit 12.3 Downloads
https://developer.nvidia.com/cuda-12-3-0-download-archive?target_os=Linux&target_arch=x86_64&Distribution=WSL-Ubuntu&target_version=2.0&target_type=deb_local

こまかな手順はリンク先に掲載されている。

# cuDNN

cuDNNは通常のリポジトリから入れる
sudo apt install libcudnn8*

# Tensorflow

pip install tensorflow==2.16.1 で入れる。

# 動作確認

```
import tensorflow as tf
tf.test.is_gpu_available()
```

Trueが返れば成功
[レビュー分析] 六本木の叙々苑ってどこ行けばいいの？

# はじめに

ReviewAI (レビューアイ) で食べログのレビューができるようになりました！
せっかくなので、六本木の叙々苑 3店舗のレビューを分析して、
どの店舗に行くべきなのかを考えたいと思います。

## ReviewAI (レビューアイ)

弊社 RetegyLink が開発中のレビュー分析 AI です。
[https://reviewai.next-seed.work/](https://reviewai.next-seed.work/)
アルファ版を公開中で、現在は[食べログ](https://tabelog.com/)さん、[じゃらん](https://www.jalan.net/)さんに対応中です。

## 食べログ

言わずと知れた、レストラン検索・予約サイトです。
レビューが多く集まっており、多くの人が利用している印象です。


# レビュー分析

六本木の周辺には、

- 叙々苑 六本木本店
- 叙々苑 麻布十番店
- 游玄亭 西麻布本館

の3店舗の叙々苑がありますが、それぞれ、どのような違いがあるのでしょうか？

## 叙々苑 六本木本店

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3776808/25ff913e-4df8-2c41-84d4-72b3d4e9d2fe.png)

肉の評価が一番高いです。
メニューではカルビとサラダが人気のようです。

## 叙々苑 麻布十番店

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3776808/5b2f6ef9-72ca-b6c4-2894-ce11e733375c.png)

こちらもカルビとサラダを食べている人が多いようです。


## 游玄亭 西麻布本館

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3776808/693d6326-3134-70a9-8d10-bd934ba4aade.png)

ロースが人気のお店のようです。
また、他店舗では人気だったカルビとサラダはあまり食べられていないようです。

## 比較

六本木本店と麻布十番店では、カルビとサラダが人気で、
游玄亭ではロースが人気のようです。
また、どの店舗でもランチで利用している人が多いようです。


# さいごに

## 改善点

3店舗について可視化してみましたが、いくつか改善点が見えてきました。
1. 叙々苑が「叙々」と「苑」の2観点に分かれてしまっている。
1. 「円」「上」「塩」 といった、ユーザーによっては興味の薄い観点が多い
1. 個別に可視化されると、比較するのが難しい
1. 解析に時間がかかり、エラーが起きているのか解析中なのか判断できない

今後の開発では、
1. 分かれてしまったいる観点を修正する
1. 興味の薄い観点を削除する
1. 比較のための機能を開発する
1. 解析の進捗が分かる UI を開発する

といったことを進めていこうと思います。

## 宣伝

ReviewAI (レビューアイ) は、レビューを簡単に確認できるサービスを目指しています。
https://reviewai.next-seed.work/
アルファ版を公開中で、現在は食べログさん・じゃらんさんに対応中です。
食べログのレビューを確認する際は、 ReviewAI をご利用ください。

今後どんどん使いやすくしていく予定ですので、
ぜひ皆様の ReviewAI に関するご意見をアンケートで教えてくださると幸いです。
gitでpush後のコミットメッセージの変更方法

## はじめに
gitでpush後のコミットメッセージの変更の仕方を記載します。
調べればすぐにわかることですがメモります。

## 対応方法について
以下で記載する対応方法について、先に感想を記載させていただきます。
一人作業の時は何の問題もありません。
ただ、コミットメッセージを変えたい場合は、マージされる前のコミットメッセージまでです。
共同作業の場合、履歴にこだわる場合は、マージされたコミット名称は変えない方が無難です。

また、SourceTreeのようなGUIツールでもリベースやamendといった操作は可能ですが、操作手順や実行中の詳細がコマンドラインに比べて把握しにくいことが多く、特にエラー発生時の対処が複雑になることがありため、コマンドでの対応をお勧めします。予期せぬ結果が発生しかねません。

## 対応方法
Gitで既にpushした後のコミットメッセージを変更するには、以下の手順で行えますが、リポジトリを共有している他の人に影響を与える可能性があるため、注意が必要です。

1. **最新のコミットのメッセージを変更する場合:**
   - ローカルでコミットメッセージを修正します。
     ```
     git commit --amend -m "新しいコミットメッセージ"
     ```
   - 変更をリモートリポジトリに強制的にpushします。
     ```
     git push --force
     ```

2. **過去のコミットのメッセージを変更する場合:**
   - リベースを使用してコミットを修正します。`n`をそのコミットが現在から数えて何番目かに置き換えます。
     ```
     git rebase -i HEAD~n
     ```
   - エディタが開くので、変更したいコミットの行を見つけて、`pick`を`reword`に変更し、保存してエディタを閉じます。
   - 指示に従って新しいコミットメッセージを入力します。
   - リベースが完了したら、変更をリモートに強制的にpushします。
     ```
     git push --force
     ```

この方法は、特に他の人がその変更を既にpullしている場合、リポジトリの履歴を変更するため、使用には慎重を期する必要があります。他の開発者に対して事前に通告し、理解と協調を得ることが重要です。


## 参考
https://docs.github.com/ja/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/changing-a-commit-message

https://qiita.com/kenose0328/items/185f7e8634d816c85a84

https://www.granfairs.com/blog/staff/git-commit-fix
Ubuntu 24.04 LTSにすると多分マストドンv4.2ブランチじゃないと上手く動かないんじゃねって話

## ポイントリリース前に24.04 LTSを入れました

nodejsが18以上になっていました。動かしていたのがv4.1ブランチだったので象バンバンになりました。

nodejsだけの問題だけだと思っていたらそうでもない様子。postgreSQLも10がコケていました。Mastodonのサービスは動いている。

めんどくさそうです。

## v4.2ブランチにしてみました

rubyも3.2.3をいれて、さあ！

やっぱり象バンバン。DB動いてないからそらそうか。

## ログを見る

postgreSQL10のログを見るとTimezoneが「Japan」になっていてむーりーってなって落ちている。そんな書き方は無い！

「Asia/Tokyo」にしたところ動いて、DBがマイグレーションできて動きました。

## 時間がかかりました

DBが動いてないというのに気づくのが遅くてやたら時間だけかかりました。ログを見るというのは大切ですね。

v3ブランチとv4.0ブランチはEoLになったのでUbuntu 24.04 LTSにアップグレードするぞという人たちはもりもりDBマイグレーションしつつv4.2ブランチに追いついた方がいいですね。

特定のバージョンのnodejsが入れられるテクニックがある人はそのままでもいいかもしれません。nvmとかそういうので。あ、そうかnvmでやったらよかったのか…。

とっぴんぱらりのぷぅ。
Quill.jsでツールバーのデフォルトのアイコンを書き換える方法

`Quill.import('ui/icons');`を利用して、アイコンの表示内容を書き換えられる。

```html
<div class="toolbar">
  <button type="button" class="ql-underline"></button>
</div>
<div class="editor"></div>
```

```js
var icons = Quill.import('ui/icons');
　// ここではSVGを利用しているが、もちろんFontAwesomeなどのアイコンを利用することも可能
icons['underline'] = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="red" version="1.1" id="Icons" viewBox="0 0 32 32" xml:space="preserve"><g><path d="M29,27H3c-0.6,0-1,0.4-1,1s0.4,1,1,1h26c0.6,0,1-0.4,1-1S29.6,27,29,27z"/><path d="M5,24h4c0.6,0,1-0.4,1-1s-0.4-1-1-1H8.6l1.9-4h11.1l1.9,4H23c-0.6,0-1,0.4-1,1s0.4,1,1,1h4c0.6,0,1-0.4,1-1s-0.4-1-1-1   h-1.4L16.9,3.6C16.7,3.2,16.4,3,16,3s-0.7,0.2-0.9,0.6L6.4,22H5c-0.6,0-1,0.4-1,1S4.4,24,5,24z M16,6.3l4.6,9.7h-9.2L16,6.3z"/></g></svg>';

// Quill初期化処理
const editor = document.querySelector('.editor');
const toolbar = document.querySelector('.toolbar');
const quill = new Quill(editor, {
    theme: 'snow',
    modules: {
        toolbar: toolbar,
    }
});
```
プロンプトエンジニアリング～プロンプトの基本～について調べてみた

# 記事の概要
ChatGPTなどの自然言語モデル（LLM）を使うようになってプロンプトエンジニアリングという表現をよく聞くようになったが、そもそもプロンプトエンジニアリングってどういうものか調べてみた内容を記事にまとめました。

## プロンプトエンジニアリングってなに？
プロンプトエンジニアリングとは、AI、特に自然言語処理を担う言語モデル(LM)を効率的に使用するために、言語モデルへの命令(プロンプト)を開発・最適化する学問のこと。もうすこしかみ砕くとChatGPTのようなAIに対して、うまく指示を出して良い結果を引き出すための技術のことです。

AIに質問や指示を与えることを「プロンプト」と言います。プロンプトの与え方次第で、AIの出力結果は大きく変わります。例えば、「日本の首都はどこですか？」と聞くのと、「日本の首都である東京について説明してください」とプロンプトを工夫するのとでは、AIの答えの詳しさが変わってきます。

そのため、プロンプトエンジニアリングでは、AIの特性をよく理解し、タスクに合わせて効果的なプロンプトを設計します。プロンプトを適切に設計することで、AIの能力を最大限に引き出すことができるということです。

## なぜプロンプトエンジニアリングが必要なの？
ChatGPTなどで使われている大規模言語モデル（LLM）では、大量のテキストデータから言語の使い方を統計的に学習しているため、人間のように言葉の裏にある意味合いを汲み取ることが得意ではありません。そのため、あいまいな指示では的確な出力が得られず、意図しない内容が出力されます。

また、プロンプトであいまいな指示をすることにより、AIが学習データとは異なる事実や、学習データに存在しない情報を生成する可能性が高くなります。こうした事実と異なる情報や学習データに存在しない情報の出力のことは、一般的にハルシネーション（幻想）とよばれています。

## どうすれば出力内容を向上させられるの？
プロンプトエンジニアリングを使った自然言語処理の精度を向上させる方法はいくつかありますが、主だったものは以下のようなものになります。

### 指示の仕方
* 曖昧な表現は避け、具体的で詳細な指示を与える
* 望ましい出力形式やスタイル、文脈などを具体的に指定する
* 指示は常にプロンプトの先頭に置き、区切り文字などで指示と文脈を明確に分ける

### 具体例を提示する(Few-shot learningの活用)
* 文脈の中に望ましい出力形式の具体例を2、3個提示することで、言語モデルの理解を助ける

### 最新の高性能な言語モデル(LLM)を使う
* 一般的に最新で性能の高いモデルほど高精度の出力が期待できるため、可能な限り先進的なモデルを活用する
* OpenAIの最新モデルだけでなく、AnthropicやGoogle、Metaなど、各社で切磋琢磨してLLMモデルの開発しているため、各社の最新動向を参考にしながらより高性能なモデルを場面ごとに使い分ける

### プロンプトは簡潔に
* 冗長で複雑なプロンプトは言語モデルの理解を妨げる可能性がある
* 必要最小限の情報に絞ってコンパクトなプロンプトを心がける

### Chain of thoughtを利用する
* 推論プロセスを段階的にプロンプトに含めることで、複雑なタスクの精度向上が期待できる
* 言語モデルの出力をプロンプトに再利用することで、AIが反復的に推論を深められる

## プロンプトの例
このプロンプトでは、AIに演じてほしいペルソナ（役割）と、入力文に対して求める出力内容を明確に指示しています。また、制約条件を設けることで、より具体的で質の高い回答を引き出すことができます。

````
あなたは[ペルソナ]です。以下の制約条件と入力文をもとに、[出力内容]を出力してください。
# 制約条件
[制約条件1]
[制約条件2]
[制約条件3]

# 入力文
[入力文]

# 出力文
[出力内容の指示1]
[出力内容の指示2]
[出力内容の指示3]
````

上記例を使ったサンプルのプロンプトを作成してみましょう。

````
あなたは経験豊富な雑誌編集者です。
以下の制約条件と入力文をもとに、おいしい料理店を探すための情報を出力してください。

# 制約条件
・料理のジャンルは和食、イタリアン、中華料理の3つに絞る
・東京23区内の店舗のみを対象とする
・予算は1人あたり5,000円から10,000円の範囲内とする

# 入力文
読者におすすめしたい、東京でおいしい料理が楽しめるお店を探しています。
和食、イタリアン、中華料理の3ジャンルから、それぞれ2店舗ずつ選んでください。
雰囲気が良く、ゆったりと食事を楽しめる店舗が望ましいです。

# 出力文
・ジャンルごとに2店舗ずつ、合計6店舗を紹介してください
・各店舗について、以下の情報を箇条書きで提供してください
　・店名
　・最寄り駅からのアクセス方法
　・おすすめのメニューと価格帯
　・店舗の雰囲気や特徴
　・予約の必要性や予約方法
・紹介文は1店舗あたり100文字以内にまとめてください
````

このプロンプトでは、雑誌編集者のペルソナを設定し、おいしい料理店を探すための具体的な制約条件と求める情報を明示しています。出力形式も箇条書きで指定し、1店舗あたりの文字数制限も設けることで、より的確で簡潔な情報が得られるようにしています。

## まとめ
もちろん、こうしたプロンプトを作りこまなくてもAIによってある程度の内容は出力されますが、より求めている情報に早く近づけるためには、こうしたプロンプトを工夫してAIに指示する方が確実なため、プロンプトエンジニアリングという手法を駆使してAIが使われていると考えています。

ぜひ、いろんなプロンプトを作成してAIにたくさん質問してみましょう。
VScodeでDev ContainerのXdebugが起動しない原因を特定した


開発環境
・PHP v8系
・Docker v 25.0.2
・Dev Containers v0.354.0
・VSCode Version: 1.88.1 

Dev ContainerでDockerのコンテナにremote接続し、コードのエラーを確認する作業の中で
あるphpファイルの変数$cartをDEBUG CONSOLEに入力しても
```
Cannot evaluate code without a connection
```
「接続されていないからコードを評価できない」と出る。
iniファイルが機能していないぽい。
DockerfileでxdebugのiniファイルをCOPYするよう指示を書いたので確認。

```Dockerfile
COPY ./docker/app/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini. 
```

だが、コンテナ内のディレクトリ調べたらconf.dの中にxdebug.iniが入ってない。
（php.iniも）

Dockerfileが読み込まれていないのが原因。
テーブル消えるのは心許ないがDockerfileを更新するべく

```
$docker-compose up --build
```
（コンテナを作り直し）

すると
```
=> ERROR [app stage-0 3/7] RUN apt update     && apt install -y apache2     && docker-php-ext-install mysqli mbstring zip    && pecl inst 
configure: error: Package requirements (oniguruma) were not met:
```
onigurumaの件、インストールすべきパッケージがmbstringではなく libonig-devらしい
https://qiita.com/June8715/items/1df5958b95c1ff2d4c1b

ライブラリはmbstringではなくlibonigが必要とのこと。

※
libonig：マルチバイト文字を含む文字列を処理するライブラリ。php7.4.0以前はmbstringだったが、以降はlibonigがスタンダードになった模様。https://github.com/docker-library/php/issues/880


なのでDockerfileを書き換え
```
RUN apt-get update \
    && apt-get install -y apache2 \
    && docker-php-ext-install mysqli mbstring zip\
    && pecl install xdebug \
    && docker-php-ext-enable xdebug
```
を
```
RUN apt-get update \
    && apt-get install -y apache2 libonig-dev\
    && docker-php-ext-install mysqli zip\
    && pecl install xdebug \
    && docker-php-ext-enable xdebug
```
そしてふたたびコンテナをリビルドかけると
```
configure: error: Package requirements (libzip >= 0.11 libzip != 1.3.1 libzip != 1.7.0) were not met:
```
と。
libzip-devが必要とのことで
追記して再度実行。

※
libzip：zip処理のライブラリ。

```
 ✔ Container msr-db-1   Recreated                                                                                                            0.1s 
 ✔ Container msr-app-1  Recreated
 ```
 リビルド完了。
 
 リモート接続して
 iniファイルの所在を確認すると
 ```
 :/usr/local/etc/php# ls -a
.  ..  conf.d  php.ini  php.ini-development  php.ini-production

 :/usr/local/etc/php/conf.d# ls -a
.  ..  docker-php-ext-mysqli.ini  docker-php-ext-sodium.ini  docker-php-ext-xdebug.ini  docker-php-ext-zip.ini  xdebug.ini
```

コンテナ内にiniファイルが無事にCOPYされていた。
 xdebugの動作も確認完了。
renderを使用する際に生じるエラーと変数の取得について

## 導入
Ruby on RailsのDeviseは強力な認証ソリューションを提供しますが、時として複数のモデルを管理する際に予期しない振る舞いに直面することがあります。今回のケーススタディでは、複数モデルでのログインを避けるための対処法を探求しました。

## 問題発生

あるRailsアプリケーションにて、予約確認のアクションを処理中に`NoMethodError`が発生しました。

```
NoMethodError at /reservations/confirm
undefined method `reject' for nil:NilClass
```

コードの該当部分は以下の通りです：

```ruby
# app/controllers/reservations_controller.rb
def confirm
  ...
  @services = Service.where(id: reservation_params[:service_ids].reject(&:blank?))
  ...
end
```

このエラーは、`reservation_params[:service_ids]`が`nil`であるため、`nil`に`reject`メソッドを呼び出そうとした時に発生しています。

## 問題の解析と対処

### コントローラーでのエラーハンドリング

最初のステップは、`service_ids`が存在しない、または空の場合に適切なフィードバックを提供し、ユーザーをフォーム画面にリダイレクトするエラーハンドリングを追加することでした。

```ruby
# app/controllers/reservations_controller.rb
def confirm
  ...
  if reservation_params[:service_ids].nil? || reservation_params[:service_ids].empty?
    flash[:alert] = "サービスが選択されていません。"
    redirect_to back_to_form_path and return
  end
  ...
end
```

### リダイレクトとフラッシュメッセージ

しかし、リダイレクトを使用せずに`render :new`を呼び出すことにした際に、次のエラーが発生しました。

```
NoMethodError at /reservations/confirm
undefined method `each' for nil:NilClass
```

### 修正：必要なインスタンス変数のセット

`render`メソッドを使用する際には、フォームのビューで必要な全てのインスタンス変数をセットする必要があります。そこで、以下のようにエラーハンドリングを修正しました。

```ruby
# app/controllers/reservations_controller.rb
def confirm
  ...
  if reservation_params[:service_ids].nil? || reservation_params[:service_ids].empty?
    flash.now[:alert] = "サービスが選択されていません。"
    set_variables_for_form
    render :new and return
  end
  ...
end

private

def set_variables_for_form
  @categories = Category.all
  ...
end
```

## 結果

上記の修正を施した結果、ユーザーがサービスを選択せずに確認画面へ遷移しようとすると、適切にフォーム画面に戻され、フラッシュメッセージで「サービスが選択されていません」というアラートが表示されるようになりました。
小道具： ASCII/数字/アルファベットの全角文字を半角文字に変換

Qiita CLI 向けです。

Qiita の編集画面で全角のアルファベットが注意されるようになっていたので、全角(ASCII/数字/アルファベット)を半角にするものを作ってみました。(探せば良いツールがあるでしょうけど…)

コマンド ラインで変換したいファイル(複数:UTF-8のみ)を指定すると

- 入力ファイル: file.ext
- 出力ファイル: file.f2h.ext

として変換します。変換不要な場合はスキップします。

```python:
#!/usr/bin/env python3

import argparse
import os
import sys

parser = argparse.ArgumentParser()
parser.add_argument('-A', '--ascii', action='store_true', help='ASCII文字を半角化')
parser.add_argument('-a', '--alphabet', action='store_true', help='アルファベットを半角化')
parser.add_argument('-n', '--number', action='store_true', help='数字を半角化')
parser.add_argument('-f', '--force', action='store_true', help='強制出力')
parser.add_argument('-q', '--quiet', action='store_true', help='静寂モード')
parser.add_argument('files', metavar='FILE', nargs='+')
args = parser.parse_args()

TABLE = {
    chr(c+0xfee0): chr(c) for f, (s, n) in (
        (args.ascii, (0x21, 94)),
        (args.number, (0x30, 10)),
        (args.alphabet, (0x41, 26)), (args.alphabet, (0x61, 26)),
    ) if f for c in range(s, s+n)
}

if not TABLE:
    parser.print_help()
    print('\n変換する文字種を指定してください。\n')
    sys.exit(1)

for ifile in args.files:
    with open(ifile, 'r') as fp:
        idata = fp.read()
    odata = ''.join(map(lambda c: TABLE.get(c, c), idata))
    if idata == odata and not args.force:
        continue
    root, ext = os.path.splitext(ifile)
    ofile = f'{root}.f2h{ext}'
    if not args.quiet:
        print(f'{ifile} -> {ofile}')
    with open(ofile, 'w') as fp:
        fp.write(odata)
```
radikoを録音する話

## 概要

radikoを私的に録音してスマホで聞いています。この度、録音するところが自動化できたので公開します。

https://github.com/bugcity/rec_radiko_pg

## 背景

これまで「らくらじ」を使って手動でぽちぽち録音し、tagやアートワークはtermux上でpythonを動かし設定していました。しかし2週間超の海外出張が入りロケーション判定で録音できなくなるのでは？という課題が出てきました。VPNを使えば多分大丈夫だろうという予想はあったのですが、これを期にRaspberry PIで録音を自動化することにしました。

## 録音の骨幹

録音はrec_radiko_tsでやっています。

https://github.com/uru2/rec_radiko_ts

## rec_radiko_pgでの取り組み

- 番組名から録音開始時間と録音終了時間を見つけるので、rec_radiko_tsの引数設定が不要です
- tagやアートワークを設定できます  
  アートワークはradikoの画像を使用します
- ファイルはtagや日付でディレクトリを分類し整理できます
- 録音が完了するとメールで通知します

## うちでの運用

1. Raspberry PIのcronが1時間に1回rec_radiko_pgを実行し、録音ファイルをNASに保存する
1. スマホの「Folder Sync」が毎朝NASとスマホを同期する
1. スマホの「Poweramp」で聴く

エラーがあればはZabbixから通知しています。これかでエラーは無かったけど、過去１週間分は録音可能なので、リカバリーの猶予はあると思います。
gitでローカルのdevelopを書き換えてしまった対応例

## はじめに
gitフローに則って共同作業の時、間違ってローカルのdevelopにマージしてしまった時の対応方法をメモります。

## 状況
gitフローに則る場合、1から3の繰り返しです。
1.リモートブランチ(ex:develop)をプル
2.ローカルのdevelopより、作業ブランチを作成(feature/xxx)
3.マージリクエストを出し、OKならリモートブランチ(ex:develop)にマージ

今回はローカルのdevelopに何らかの変更を加えてしまった場合の対応例を記載します(本来ありえないですが、私は遭遇してしまったので)。

現場では何らかのツール(例えばソースツリー)を使用しているかと思いますが、以下ではコマンドでの対応例を記載しています。

## developブランチを書き換えてしまった対応
リモートブランチと同じ状態にローカルブランチをリセットすることは可能です。
ローカルの `develop` ブランチをリモートの `develop` ブランチと同じ状態に戻すには、以下のGitコマンドを使用します。
まず、最新の変更を取得し、その後でローカルの `develop` ブランチをリモートの状態にリセットします。

1. リモートから最新の情報を取得します:
   ```bash
   git fetch origin
   ```

2. ローカルの `develop` ブランチをリモートの `develop` ブランチにリセットします:
   ```bash
   git checkout develop
   git reset --hard origin/develop
   ```

これで、ローカルの `develop` ブランチはリモートの `develop` ブランチと全く同じ状態になります。
ただし、この操作はローカルで行った変更（まだリモートにプッシュしていないコミットなど）を完全に消去するので、実行する前に必要な変更がないか確認してください。

また、間違ってローカルで変更した内容がある場合は、それを新しいブランチに退避させてからリセットを行うことも考えられます。その場合、以下のように新しいブランチを作成してからリセットを行います:

```bash
git checkout -b new-branch-for-changes
git checkout develop
git reset --hard origin/develop
```

この方法で、変更を失うことなく安全に `develop` ブランチをリセットできます。

## 間違った内容(古いブランチ)から必要箇所を戻して進める方法
`develop` ブランチをリモートの最新状態に戻した後、以下の手順で新規ブランチを作成し、そこに必要な修正を反映してからマージリクエストを出すことが適切な流れになります。

1. **新規ブランチの作成**:
   - まず、リセットした `develop` ブランチから新しい作業用のブランチを作成します。
     ```bash
     git checkout develop
     git checkout -b new-feature-branch
     ```

2. **修正の反映**:
   - もし間違ったブランチで作業していたものや、古い `develop` から分岐したブランチにある修正を新しいブランチに取り入れたい場合は、`cherry-pick` や `rebase` を使うことができます。
   - 例えば、特定のコミットだけを新しいブランチに取り込みたい場合、`cherry-pick` を使用します:
     ```bash
     git cherry-pick <commit-id>
     ```
   - 複数のコミットを順序良く反映させたい場合は、`rebase` の使用を検討します。ただし、`rebase` はコミット履歴を書き換える操作なので、他のユーザーと共有しているブランチには適用しないよう注意が必要です。

3. **変更のプッシュとマージリクエストの作成**:
   - 修正を加えた後、新しいブランチをリモートにプッシュします。
     ```bash
     git push origin new-feature-branch
     ```
   - プッシュしたブランチに基づいて、リモートのリポジトリでマージリクエスト（プルリクエスト）を作成します。このリクエストを通じて、`develop` ブランチへのマージを提案し、レビューを依頼します。

これにより、古い状態や誤って作業した内容が正しく取り扱われ、`develop` ブランチに安全に統合することができます。

## cherry-pickの使い方
`git cherry-pick` コマンドを使用することで、他のブランチにある特定のコミットを現在のブランチに適用することができます。
これは、古い `develop` ブランチから分岐したブランチにある特定の修正を新しく作成したブランチに取り込む場合に便利です。

### `git cherry-pick` の使い方
1. **新しいブランチにチェックアウト**:
   - 最初に、作業を行う新しいブランチにチェックアウトします。
     ```bash
     git checkout new-feature-branch
     ```

2. **`cherry-pick` の実行**:
   - 次に、取り込みたいコミットのコミットIDを使って `cherry-pick` を実行します。
     ```bash
     git cherry-pick <commit-id>
     ```
   - `<commit-id>` は取り込みたいコミットのIDです。このIDは `git log` で見ることができます。

### 注意点
- **コンフリクトの可能性**: `cherry-pick` 中にコンフリクトが発生することがあります。この場合は、手動でコンフリクトを解決し、`git cherry-pick --continue` を実行して操作を完了させる必要があります。
- **選択的な取り込み**: 複数のコミットを取り込む場合は、それぞれのコミットIDに対して `cherry-pick` を複数回実行するか、範囲を指定して実行します（例: `git cherry-pick commit-id^..commit-id`）。

この手順により、古いブランチの重要な修正を新しいブランチに確実に適用することができます。


## 参考
https://cloudsmith.co.jp/blog/efficient/2020/08/1534208.html
Flutter の BottomNavigationBar で4つのアイテムを設定するとテキストが表示されない問題の解決方法

# なにこれ
Flutter で BottomNavigationBar を使ってメニューを作成しようと思ったらテキストが表示されなくて困ったので、その時の解消方法をメモ


# 事象
3つまでだとこのように良い感じに表示されるが
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819748/6a92eb77-dde2-29ad-04f8-fae74b6e81b6.png)

4つ以上になるとテキストが見えなくなった！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819748/4d66dc22-557e-87a3-bbd9-922a527f0d45.png)


# 解決方法
`type: BottomNavigationBarType.fixed` で固定にしないといけないらしい。
```
bottomNavigationBar: BottomNavigationBar(
  type: BottomNavigationBarType.fixed, // このプロパティを追加する
  items: // ...,
)
```


# 原因
4つ以上にすると `BottomNavigationBarType.shifting` に自動的に切り替わってしまい、テキストが表示されないようになってしまうとのこと。
公式ページ：https://api.flutter.dev/flutter/material/BottomNavigationBar-class.html
```
The bottom navigation bar's type changes how its items are displayed. If not specified, then it's automatically set to BottomNavigationBarType.fixed when there are less than four items, and BottomNavigationBarType.shifting otherwise.
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819748/69d6ce11-bf6c-30ef-d334-1c3af571ee77.png)


# そして…
無事に直った！よかったよかった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819748/2ad13873-bab2-fa40-d37e-84e25b055cdf.png)
SSHの鍵を複数管理するメモ

# 背景・目的
複数のSSHキーを管理する機会があったので、メモします
[【GitHub】複数GitHubアカウントのSSHキーを管理する。](https://zenn.dev/rabbit/articles/543355d334776b)を参考に試してみます。助かります。ありがとうございます。

# 実践
## 鍵の作成
1. １つ目の鍵を作成します
    ```
    ssh-keygen -t rsa -b 4096 -C "mailadress" -f "id_rsa_abc"
    ```

1. 2つ目の鍵を作成します
    ```
    ssh-keygen -t rsa -b 4096 -C "mailadress" -f "id_rsa_xyz"
    ```

## ssh configの修正
1. ~/.ssh/configを修正します
    ```
    Host github.com.abc
      HostName github.com
      User git
      Port 22
      IdentityFile ~/.ssh/id_rsa_abc #１つ目のssh鍵を指定
      TCPKeepAlive yes
      IdentitiesOnly yes
    
    Host github.com.xyz
      HostName github.com
      User git
      Port 22
      IdentityFile ~/.ssh/id_rsa_github_xyz # #2つ目のssh鍵を指定
      TCPKeepAlive yes
      IdentitiesOnly yes
    ```

## 公開鍵の設定
1. 接続先であるリモート側の鍵をコピーして設定します。　pbcopyによりクリップボードにコピーできます
    ```
    pbcopy < ~/.ssh/id_rsa_abc.pub
    ```

## 疎通
1. １つ目の確認
    ```
    ssh -T git@github.com.abc
    Hi XXXXX! You've successfully authenticated, but GitHub does not provide shell access.
    ```

1. 2つ目の確認
    ```
    ssh -T git@github.com.xyz
    Hi XXXXX! You've successfully authenticated, but GitHub does not provide shell access.
    ```

## git cloneする場合
1. 下記の{}内をConfig内で設定した内容に書き換えます
    ```
    git clone git@github.com.{abc}:username/repository-name.git
    ```

# 参考
今回、複数のSSH鍵を管理する方法をまとめてみました。

https://zenn.dev/rabbit/articles/543355d334776b

https://qiita.com/zumax/items/37592c0299fac8f737a5
PDO (PHP Data Objects)・3回目

## はじめに

PDOについてまとめる・3回目

###  結果セットの取得

結果セットとは、SQLのSELECT命令によって、一個または複数のテーブルから取り出されたレコード群を保持するために、メモリ上に用意された仮想テーブルのことを言う。

以下はbookテーブルの内容をテーブルに整形＆表示するコード。

```php:result.php
<?php
require_once '../DbManager.php';
require_once '../Encode.php';
?>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>結果セット</title>
</head>

<body>
    <table>
        <thead>
            <tr>
                <th>ISBNコード</th>
                <th>署名</th>
                <th>価格</th>
                <th>出版社</th>
                <th>刊行日</th>
            </tr>
        </thead>
        <tbody>
            <?php
            try {
                $db = getDb();
                $stt = $db->query('SELECT * FROM book ORDER BY published DESC');
                while ($row = $stt->fetch(PDO::FETCH_ASSOC)) {
            ?>
                    <tr>
                        <td><?= e($row['isbn']) ?></td>
                        <td><?= e($row['title']) ?></td>
                        <td><?= e($row['price']) ?>円</td>
                        <td><?= e($row['publish']) ?></td>
                        <td><?= e($row['published']) ?></td>
                    </tr>
            <?php
                }
            } catch (PDOException $e) {
                print "エラーメッセージ：{$e->getMessage()}";
            }
            ?>
        </tbody>
    </table>
</body>

</html>
```

```php:DbManager.php
<?php
function getDb(): PDO
{
    $dsn = 'mysql:dbname=selfphp; host=127.0.0.1; charset=utf8';
    $usr = 'selusr';
    $passwd = 'selfpass';

    $db = new PDO($dsn, $usr, $passwd);
    return $db;
}
```

### レコードポインター

レコードポインターとは、現在読み込み可能なレコードを表す内部的な目印のこと。
`execute`メソッドによって結果セットが生成された直後のタイミングで、レコードポインターは先頭行の直前を示している。PDOStatementオブジェクトでは、レコードポインターを次のレコードに移動しながら、移動した先のレコードを読み込むために`fetchメソッド`を使う。

### fetchメソッド

```php
PDOStatement::fetch([int $style = PDO::FETCH_BOTH]) : mixed

$style: フェッチモード
```
フェッチモードとは、結果セットから取りだしたデータをどのような形式の変数に格納するかを表すパラメーター。
result.phpでは`PDO::FETCH_ASSOC`を指定することで連想配列の形式で変数に格納している。
Swallow-MS-7b-instruct-v0.1はパソコンのキーボードを知っているのか

[Swallow-MS-7b-instruct-v0.1](https://huggingface.co/tokyotech-llm/Swallow-MS-7b-instruct-v0.1)がリリースされたので、[2023年12月22日の記事](https://qiita.com/KoichiYasuoka/items/553038ec96e49a0b6663)を横目に「[パソコンのキーボードは，なぜABC順・五十音順ではないのですか](https://kotobaken.jp/qa/yokuaru/qa-35/)」と尋ねてみることにした。プログラムはこんな感じ。

```
#! /usr/bin/python3
from transformers import pipeline
tgn=pipeline("text-generation","tokyotech-llm/Swallow-MS-7b-instruct-v0.1",max_new_tokens=128)
nlp=lambda txt:tgn(f"
 
\nあなたは誠実で優秀な日本人のアシスタントです。\n
\n\n{txt} 
\n",do_sample=True)[0]["generated_text"]
print(nlp("パソコンのキーボードは，なぜABC順・五十音順ではないのですか"))
```

実行してみたところ、私(安岡孝一)の手元では以下の結果が出力された。

> 
 &lt;&lt;SYS>>
> あなたは誠実で優秀な日本人のアシスタントです。
> &lt;&lt;/SYS>>
>
> パソコンのキーボードは，なぜABC順・五十音順ではないのですか 

> パソコンのキーボードはQWERTY配列で設計されています。これは、1860年代にクリストファー・レイランドによって考案されたもので、その後レントン・サントとアーサー・バデンによって改良されました。これは、打鍵スピードを減らし、タイピストの疲労を軽減するために、あるキーのすぐ後に他の一般的な文字が入っている可能性を減らすという原則を用いている。
>
> 一般的に、アルファベット順のキーボードでは、例えば2つ

クリストファー・レイランドって誰なんだろう。レントン・サントもアーサー・バデンも聞き覚えのない名前だ。もう一度やってみよう。

> 
 &lt;&lt;SYS>>
> あなたは誠実で優秀な日本人のアシスタントです。
> &lt;&lt;/SYS>>
>
> パソコンのキーボードは，なぜABC順・五十音順ではないのですか 

> なぜコンピューターのキーボードはABC順ではないのか、それは主に歴史的な理由によるものでしょう。キーの配列は、タイプライターのキーボードを模ったもので、タイプライターのキーボードの配列は、1920年代に一般的になったブライル配列に基づいています。ブライル配列は、より現代的な配列よりも効率的に打鍵できると考えられていた。
>
> 一般的に、この配列の方が早く打てる理由は、主に最もよく使われる文字が「ホームロー」になる

「ブライル配列に基づいています」って何の話なんだろう。どこかパラレルワールドの話なんだろうか。日本人のアシスタントなんだから、せめて日本の話を答えてほしいなあ。
GASｘTwitchAPIで視聴者数取得～スプシ出力

# はじめに
完全に趣味の範疇で調べてやっただけでほぼ無知です。詳しくは各自で調べてください
思いつきと調べながら適当に書いたコードなので命名規則とか色々ごちゃ許して


## 用意するもの
* TwitchAPIのDevelopアカウント
* スプシ(xlsxなど拡張子がない規定のスプシファイル)
* GASファイル

## いざ実践
まずはTwitchAPIのDevelopアカウントがないことには始まらないので
下記にアクセスして作成
* [TwitchDevelopers公式](https://dev.twitch.tv/)

TwitchDevelopアカウントを作成した後は
色々やってる人には馴染深い認証トークンとかを取得する必要がある
 [TwitchDevGuid: authentication](https://dev.twitch.tv/docs/authentication/)
 
 ガイド通りに進めていくと
 おそらくコンソールアプリケーションの追加までできるはずなのでこの記事では割愛

 実際に認証トークンを取得するところが個人的にはわかりにくかった
 Web関連専攻してなくて馴染ないから不確定だけどこんな理解
 * __ClientID__：
 コンソールアプリケーションを作成するとできるIDのこと、おそらく公開したらアカン奴
 * __クライアントの秘密__： 　
 __秘密鍵__  、一般公開したらアカン奴
* __ユーザID__：
Twitchにログインする時のID、各人のチャンネルURLとかに乗ってるIDでもある
バレバレだから気にしない
* __Authorization__：
API Referenceの随所に出てくるわからん奴、最大の要
アクセストークン、認証トークンなどそう呼ばれてる奴、偉い人言葉統一して広辞苑に書いてくれ

TwitchAPIはLinuxが必要らしいけど用意してられないので沢山しらべたところ
WindowsCMDでもいけるっぽい
[TwitchDevGuid: cURL](https://dev.twitch.tv/docs/api/guide/#curl-examples)
要約すると ' が " になって￥が ^ になるだけ、どこまで動くかは未検証

ちょうどcURLのDevページにアクセストークンの取得が書かれているので
```` CMD:CMD
curl -X POST "https://id.twitch.tv/oauth2/token" ^
-H "Content-Type: application/x-www-form-urlencoded" ^
-d "client_id=<your client id goes here>&client_secret=<your client secret goes here>&grant_type=client_credentials"
````
これをコピペして`<your client id goes here>`　`<your client secret goes here>`
この部分は上記で取得してきたClientIDや秘密鍵を入れて実行するとアクセストークンを作成してくれる

使用期限や破棄方法は不明。。。怖い

これでTwitchAPIを使用する準備は整った！


今回紹介するもの以外をやりたい場合は下記のAPI Referenceページから各自でがんばる
* [TwitchDevGuid: API](https://dev.twitch.tv/docs/api/reference/)

## GASコード

別途取得と記載ある箇所とシート名、セルなどは各人でお願いするとして
`notification`がメインに実行する関数でセルの更新など
`sendHttpPost`がTwitchAPIで取得してもらう関数
コンソールに取得してきた情報を全出力しているのでその中からほしい値がある場合は
`live["viewer_count"]`ここをうまくやればヨシ
あとはトリガー設定するなりお好きにどうぞ


それでは楽しいTwitchライフを～～
```` GAS:GAS全コード
var CLIENTID = '別途取得';//コンソールアプリケーション作成時のクライアントID
var TOKEN    = '別途取得';//秘密
var USERID   = 'Twitchログインする時のID'

function notification() {
  //スプシ読み込み
  const file = SpreadsheetApp.openById("別途取得");
  const sheet = file.getSheetByName('シート1');
  const now_viewer_sel = 'B4';
  const max_viewer_sel = 'B6';

  var res = sendHttpPost(USERID);
  var lives = JSON.parse(res.getContentText());
  for(var j = 0; j < lives["data"].length; j++){
    var live = lives["data"][j];
    console.log(live);//全出力
    
    //現視聴者数から最大視聴者数を入れ替える
    var liveViewer = live["viewer_count"];//現視聴者数

    var nowRange   = sheet.getRange(now_viewer_sel);//現視聴者セル指定
    nowRange.setValue(liveViewer);                  //現視聴者の更新

    var maxRange   = sheet.getRange(max_viewer_sel);//最大視聴者セル指定
    var maxVal     = maxRange.getValue();           //最大視聴者の値取得

    //最大視聴者の更新
    if ( liveViewer > maxVal)
    {
      maxRange.setValue(liveViewer);
    }
  }//  for(var j = 0; j < lives["data"].length; j++)
}

/** 
* Twitch 配信情報を取得
*/
function sendHttpPost(id){
  var endpoint = "https://api.twitch.tv/helix/streams?user_login="+id;
  console.log("endpoint::" + endpoint);
  var headers =
  {
    'Client-ID': CLIENTID,
    'Authorization' : "Bearer "+ TOKEN
  }
   var options =
   {
     "method" : "get",
     "headers" : headers
   };
   var res = UrlFetchApp.fetch(endpoint, options);
   return res;
}


````
nRF9160 LTE Ethernet Gateway の ソースコードを公開しました。

下記の記事のソースコードを GitHub にて公開しました。

https://qiita.com/Akihiro-Sakaniwa/items/4fc751ce5c827958ed06


https://github.com/Akihiro-Sakaniwa/nRF9160_LTE_Ethernet_Gateway


なにかのお役に立てば幸いです。

コードが煩雑になるので、FOTA 関連機能は省いてあります。

ご利用の際は、
prj.conf 
overlay.dts
の変更をお忘れなく。

LAN側装置のMTUは 1280 にしてください。

GWのIPアドレスは prj.confに記述しています。

DHCP関連機能はありません。

ポートマッピング機能を実装しているので LAN 側は複数台接続可能です。

MACアドレスは　overlay.dtsで指定できます。

LAN-CHIPの指定は、prj.confとoverlay.dtsの両方を変更する必要があります。


# 以上
Heroku有料化後の後継サービス有力候補とウワサを聞いたRenderを使ってみた

Qiitaに投稿されている記事でRender使えば簡単にWebサービス公開環境を作れるよっていうのを読んで、早速試しにやってみたわけです。

https://qiita.com/kizataka/items/10693e87f726a95499e4

あまり複雑なヤツだと何が原因で失敗しているかがよくわからんくなるので、今回はごぐごく簡単なflaskを使ったのをデプロイしてみました。

https://qiita.com/tonytani37/items/a9c7fafa3be582353771

https://qiita.com/tonytani37/items/b1e2b72b2465799271d0

資源はGithubにあるので、そいつを使ってちょいちょいとできるもんだと思ってたけれど、ちょっと失敗した部分があったから、そいつを忘れないように今回は忘備録ってことで書いてます。

今回デプロイしようとしたレポジトリの構成は以下の通り。

```
main
 |
  - app
 |   |
 |    - hazardmap.py
 |    - requirements.txt
 |
  - templates
     |
      - foliumで作成したハザードマップ表示するためのhtmlファイルがいくつか保存
```

上のリンクした投稿にあるのは"hello world!"を表示する簡単なソースコード事例なので、すべてのflask環境はmainブランチの下に保存されていますが、私がデプロイしようとした環境ではシェープ形式ファイルだの色々とごちゃ混ぜで保存しているため、ソースはmain配下の別フォルダに保存していますので、Renderの環境指定で少し調整が必要であり、かつソースプログラム名が一般的なappではないので、その点についても私みたいな初心者には事例とことなる点で混乱のタネになるのではと思いメモを残します。

```python:hazardmap.pyの一部
from flask import Flask,render_template,request,abort

app = Flask(__name__)

@app.route('/',methods=['GET', 'POST'])
def map():

## 以下、ゴニョゴニョと処理が続く

## おまじない
if __name__ == "__main__":
    app.run(debug=False)
```

ルートディレクトリの指定ができるので上にあるリポジトリ構成に従って、以下の通り指定します。
デフォルトだともちろんrootなので、Root Directoryの指定はその下にあるappを指定します。

```
app
```

リンク先のサイトでgunicornを起動するためのStart Command記述について
>これはwebアプリを起動するためのコマンドになります。
>Flaskでwebアプリを作成していれば
>```
> gunicorn app:app
>```
って書いてありますが、このどちらのソース名(今回はhazardmap.py）にするかでちょっと悩みましたが、この記述に２つappがあるけれど、左のほうがソース名で右がソース内に記述したflaskのオブジェクト名です。

なので
```
gunicorn hazardmap:app
```
となります。ここで私はhazardmapの拡張子(hazardmap.py)までくっつけて書いたらデプロイエラーとなりました。事例を見れば拡張子いらないのは丸わかりだから私のケアレスミスですが、デプロイエラーメッセージだけではよくわからなかったからこいつも忘れないように書いときます。

なおRender環境でPythonのWebサービスを動かす時にはサーバ機能にgunicornを使うらしいのでスタート時にgunucornを起動させるとの事。

***

最後にRenderのサイトをみるとPostgreSQLが使えて、ぐぐってみると無償で使えるっぽい雰囲気でGoogle Cloud Platformでデータベースの利用料について悩んでたから、無償で喜んでたんだけど、最近レギュレーションが代わって90日まで無償でそれ以降は有料契約じゃないと使えなくなったみたいでした。（データベース利用のみ有料契約が必要。最安が月額$7だったかな）

残念ですね。データベースが無償ならば続けてDjangoで作ったくま発見報告のやつをデプロイしようとしたけれど、これまたデータベースの利用料をどうしようかってことで一旦中止です。

とりあえずブラウザで確認できるハザードマップを作ってみたっていうサイトはこちら

https://hazardmap.onrender.com/

foliumで事前につくったhtmlを表示しているだけです。河川氾濫範囲はデータ量が多くて重たいので開くには時間がかかりますから表示まで根気よく待っててね。
【ChatGPT＋DALL-E3】で缶ジュースを作ります。PromptShare


　どうも、カーブミラーです。

　今回は、缶ジュースを作ります。

:::note info
本記事は、ChatGPT（有料版）
＋DALL-E3で行なっております。
画像はあります。　あしからず。
:::

　ニュースがないので、
　　本題です。

　缶ジュースは
　　簡単な部類です。

　では、やり取りをどうぞ。
***
***user***
缶ジュース。描画

***ChatGPT***
![1714272855696.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/c72c741d-c775-39c1-68d1-d88c67294584.jpeg)
（炭酸ジュースですね）

***user***
缶ジュースのパッケージは、アニメキャラの魔法少女。まわりには魔法の道具がある

***ChatGPT***
![1714272896529.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/8cbc11b2-251b-7f77-f761-08a9679f1810.jpeg)

***user***
英語プロンプト出力。和訳。

***ChatGPT***
Here's the English prompt used for the image:

"Redesign a soda can featuring an anime-style magical girl character on the packaging. The character should have a dynamic pose, dressed in a detailed magical outfit. The can should be surrounded by magical artifacts like a staff, an enchanted book, and mystical orbs, emphasizing the theme of magic. The background should feature a more intense magical aura, with glowing symbols and mystical elements in darker, richer colors to create a sense of power and enchantment."

And here's the Japanese translation:

"アニメスタイルの魔法少女キャラクターをフィーチャーしたソーダ缶のリデザイン。キャラクターはダイナミックなポーズで、詳細な魔法の衣装を着用しているべきです。缶の周りには、スタッフ、魔法の本、神秘的なオーブなどの魔法のアーティファクトがあり、魔法のテーマを強調するべきです。背景には、より強烈な魔法のオーラが特徴で、暗く豊かな色の輝くシンボルや神秘的な要素が力と魔法の感覚を生み出すべきです。"
***
　はい、おしまい。

　で、終わったら
　　つまりませんよねw

　そこで、
　　このプロンプトを
　　　Shareできる形にしてみましょう。

　まず、
　　要素を絞り込みます。

　キャラクター・服装・ポーズの
　　三つにしましょう。

　缶のまわりの物品なんかは
　　ShareしたPromptを使った人が
　　　拡張するということで。

　まずは、
　　日本語で作成しました。
```Text:缶ジュース（日本語）Prompt
[CHARACTER: キャラクター]
[FASHION: 服装]
[POSE: ポーズ]

[CHARACTER]をモデルにしたソーダ缶のリデザイン。[CHARACTER]は[POSE]で、[FASHION]を着用しているべきです。背景には、[CHARACTER]をより素敵な演出を生み出すべきです。アスペクト比は1:1
```
　このくらいにすれば、
　　扱いやすいでしょう。

　これをテストして
　　うまく描けることを確認。

　英語にします。
```Text:缶ジュース（英語）Prompt
[CHARACTER: キャラクター]
[FASHION: 服装]
[POSE: ポーズ]

[CHARACTER]-themed soda can redesign. The [CHARACTER] should be in the [POSE], wearing the [FASHION]. The background should enhance the portrayal of the [CHARACTER]. The aspect ratio should be 1:1.
```

　[CHARACTER: Magical Girl]
　[FASHION: Loose Mini Skirt Dress]
　[POSE: Casting a Spell]
　　にして描画したのがこちら。
![1714272873102.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/9028ff23-2de6-63e8-a2c7-4c0df6602a49.jpeg)

　こうやって、
　　PromptShareのPromptを
　　　作成しています。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
Gitで一番最初のコミットも含め変更する

## 複数のコミットがある段階で

このコマンドで最初のコミットも含め変更することができる

```
git rebase -i --root
```

## 最初のコミットだけの段階で

最初のコミットを取り消す

```
git update-ref -d HEAD
```

## Ref

1. https://suzuken.hatenablog.jp/entry/2014/03/28/100311
エンジニアのキャリアプランを決める方法

# はじめに
最近、1on1などをやっていく中でキャリアの悩み相談に乗ることが増えて来ました。
その中で私がアドバイスしているキャリアを決める方法をまとめました。
※エンジニアに限らず、他の職種でも共通する話かもしれません。

# キャリアプランとは
他の記事の説明を引用するとキャリアプランは簡単に言うと、「キャリアの具体的な計画や見通し」のことです。
```
キャリアプランとは、自分が今後どのようなキャリアを積み上げていくかという「具体的な計画や見通し」のことです。
似ている言葉に「キャリアビジョン」がありますが、これは「将来はこんなことを実現したい」
「こんな働き方をしていたい」など、プライベートも含めた将来のありたい姿や、理想像を指します。
つまりキャリアプランとは「キャリアビジョンを実現するための具体的な行動計画」と言って良いでしょう。
もうひとつ、似た言葉に「キャリアパス」がありますが、
これは企業内で社員が目標とするポストや職務に就くために必要な経験・スキルなどの道筋を指す言葉です。
```
引用：https://www.r-agent.com/guide/article16038/

# キャリアのゴールが決まる原理
私は将来の夢やキャリアのゴールは基本的には今までの体験や経験の中からしか決まらないと思っています。

例えば、いきなり子供が「将来はサッカー選手になりたい！」と言い出したとしても何かしらの体験の中からその選択に至っているはずです。
テレビで本田圭佑の活躍を見て憧れたり、友達とサッカーをして楽しかったなどの体験が紐付いているはずです。

なので、将来の夢が決まっていない人はたくさんの体験をしていく必要があると思います。ただ、闇雲に動いても時間を浪費するので仮説を持って動いていきましょう。

# キャリアプランは必要なのか？
キャリアプランを決めると下記のようなメリットがあると思っています。

1.行うべき事が明確化されて、日々の仕事に納得感がある。
2.会社選びの基準が明確になる。
3.やるべき事が整理されてモチベーションが上がる。

# 3つのキャリアプランを決める方法
一般的なキャリアプランの決め方としては、「Will・Can・Must」の3ステップがあると思います。
ただ、今回は一般的な方法を紹介するだけでは面白くないと思うので、私が考えたキャリアプランの決め方をお話します。

1.キャリアのゴールを決めて、ロールモデルを決める。
2.身近な人をロールモデルに設定して、徐々に解像度を上げていく
3.明確にはロールモデルを設定せずに独自のキャリアプランを決める

それでは、一つずつ解説していきます。

## 1.キャリアのゴールを決めて、ロールモデルを決める。
この方法としては、まず自分のキャリアのゴールを決めます。
例えば、「スタートアップ企業のCTOになって、IPOまで経験する」、「HR Tech企業でPdMになる」、「上場企業でテックリードになる」などこれ位の粒度で良いと思います。

そうしたら、次にそのゴールに近しいロールモデルとなる人を探します。近しい人が見つかったら、その人のこれまでの経歴や持っているスキルを調べます。

それがわかったら、後は自分のスキルとロールモデルのスキルとの差分を洗い出しましょう。そして、その人が歩んできたキャリアを辿るようにキャリアプランを作っていけばある程度、ロードマップは作れると思います。
![スクリーンショット 2024-04-28 1.02.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85181/138bc669-ecc0-d0a6-e227-f6662fc2ffb0.png)


## 2.身近な人をロールモデルに設定して、徐々に解像度を上げていく
1とは違って、キャリアのゴールをすぐには決められない。
明確にやりたい事が見つからない人は身近な人をロールモデルにしながら、ピボットしていく事をオススメします。

![スクリーンショット 2024-04-28 1.03.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85181/09c26f45-2931-f9b2-9e97-b4b000c0bcf6.png)

ただ、ここで注意したいのは、ある程度、仮説を持ってキャリアを仮設検証していく事です。仮説がなければ、自分に合っていたのか間違っていたのか判断がつきませんので、仮説を設定して試した後に振り返る必要があります。

例えば、「一つのプロジェクトだけだと飽きてしまう為、複数のクライアントの事業にコミットするのが向いてそうなので、受託開発のPjMをやってみたい。」など何故やってみたいと思ったかは仮説検証する前に整理しておきましょう。

![スクリーンショット 2024-04-28 1.13.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85181/0a588743-e76e-8358-8116-c4d0e482eafa.png)

そして、それぞれの仮説検証の期間を決めて動いていけば、いつの間にか歳を取っていたという事も減ると思います。

## 3.明確にはロールモデルを設定せずに独自のキャリアプランを決める
これは起業家など今まで誰も成し遂げたことのないような成功を収めたい人に向いていると思います。

歴史に残るような新しい事業を作って成功したければ、もちろん他の人の真似をしていても大成はしないと思います。独自のキャリアプランを作るにあたって、複数のロールモデルとなるような人を探して、それを組み合わせるのも良いと思います。

私の場合は、最初、ランサーズの社長秋好さんをロールモデルとしていました。ただ、沖縄でエンジニア出身の経営者で全く同じ事業をやっている経営者は存在しなかったので、いろんなロールモデルの組み合わせでキャリアプランを考えていました。
今も試行錯誤しながらキャリアプランはアップデートしていっています。

# まとめ
・キャリアプランを決めるメリットとしては、行うべき事が明確化されて、日々の仕事に納得感があったり、やるべき事が整理されてモチベーションが上がります。

・私がオススメするキャリアプランを決める方法は下記の3つです。

1.キャリアのゴールを決めて、ロールモデルを決める。
2.身近な人をロールモデルに設定して、徐々に解像度を上げていく
3.明確にはロールモデルを設定せずに独自のキャリアプランを決める
Twitter API v1.1→v2

レガシーシステムの改修に携わった際、Twitter API v1.1のログイン連携が動いていないという。
調査するとAPIは遥か昔に廃止されていた。ということでv2に移行。

    Create Project -> Create App

するだけだが、無料プランはサスペンドされたAppを一度削除して再作成しないといけない。
key関連は3rdPartyに指定するので、適宜、コピー。

アクセストークン等は一連の流れでは作成されないので別途以下の手順が必要

    App Setting（添付） -> Key and tokensタブ -> Authentication Tokens -> generate

![スクリーンショット 2024-04-28 11.11.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1552825/f23813c3-289e-cd30-8570-d3786026c7a0.png)
IntelliJ Ideaのライセンスを別の環境へ切り替える方法まとめ

# はじめに
PCを変えたことにより再度IntelliJ Ideaの環境を構築し直したのですが、その際ライセンスの紐付けに失敗する事象が発生しました。
どうやら別の環境で再度Activateする必要がある場合には、ライセンスを一度返却して再度連携→Activateし直す必要があるようですね。
この切り替え手順を忘れないよう備忘録的に残しておこうと思います。

# ライセンス切り替え方法
ライセンスの切り替えはJetBrainsのマイページより調整します。

https://account.jetbrains.com/licenses

![スクリーンショット 2024-04-28 10.55.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354522/f48f3ccc-cc2a-6686-f2b1-2f3dcc226d2a.png)

上記リンクより紐付けられているアカウントでログインすると、紐付いているライセンスの詳細が表示されます。
詳細内赤枠のreturn licenseより返却が可能です。

返却することにより紐付いているアカウントの情報も一度切り離されるので、再度Activateする前にライセンス自体に返却したアカウントを紐付け、改めてActivateすることで調整可能です。

設定は以上になります。

# さいごに
kotlin festの前にAWS Summitがありますね！

https://aws.amazon.com/jp/summits/japan-priority/

17日週は学びの多い１週間になりそうで楽しみですー！