OmniAICreator/Qiita-1.07M huggingface dataset:
Alfred Workflowで短縮URL生成をx.gdに乗り換えた話

![250316_short_opt.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/fbb9c6d0-23b5-4286-8223-b90461b82537.jpeg)

## はじめに

Alfred WorkflowでURL短縮にTinyURLを使っていましたが、x.gdに乗り換えました。その理由と設定変更の手順をメモします。

## なぜx.gdに乗り換えたか

TinyURLも便利でしたが、**とにかくURLが短い**ことが決め手となり、x.gdに乗り換えました。

**x.gdを選んだ理由:**

* **圧倒的な短さ:** 他サービスより短く、文字数を抑えたい場合に最適。メールやLINEでの共有に有利。
* **シンプルなAPI:** 実装が容易。

**TinyURLの不満点:**

* **URLの長さ:** x.gdの方がさらに短い。

URLの短さを最優先するなら、x.gdが最適と判断しました。

## x.gdの設定手順

### 1. APIキーの発行

まずはx.gdでAPIキーを発行します。

1. [x.gdのウェブサイト](https://xgd.io/)にアクセスします。
2. 開発者向け > APIキー発行 でメールアドレスを入力します。
3. メールが届いたらアクティベートします

### 2. Alfred WorkflowのRun Scriptを変更

次に、Alfred Workflowの`shorten_url`のRun Scriptを以下のように変更します。

```bash
# x.gdバージョン

API_KEY="your_api_key"  # ここに取得したAPIキーを入力
URL_TO_SHORTEN="$1"

RESPONSE=$(curl -s "https://xgd.io/V1/shorten?url=${URL_TO_SHORTEN}&key=${API_KEY}&analytics=false")

SHORT_URL=$(echo "$RESPONSE" | jq -r '.shorturl')
echo -n "$SHORT_URL"
```

- `your_api_key`取得したご自身のx.gdのAPIキーに置き換えてください。

#### 変更点

* APIのエンドポイントを`https://xgd.io/V1/shorten`に変更
* APIキーを`key`パラメータで渡すように変更
* `analytics=false`を追加（任意）

#### `analytics`パラメータについて

`analytics=false`に設定し、クリック数などの分析情報を取得しないようにしています。分析情報が必要な場合は、`true`に変更するか、パラメータ自体を削除してください。

個人的には、詳細な分析はx.gdのウェブインターフェースで行えば十分だと考えているため、`false`に設定しています。

### 3. その他の設定

Run Scriptの結果を、`Copy to Clipboard` と `Large Type` に接続します

![SS 2025-03-16 11.26.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/6d118866-965a-4fbc-b1a5-05ff0f532936.png)

## まとめ

以上で、Alfred Workflowでの短縮URL生成をx.gdに移行する手順は完了です。x.gdの出力はとにかく短いので、短縮URLの利用が気持ちよくなることを期待しています。

## 参考

* [URL短縮サービス X.gd](https://x.gd/)
* [Developers | URL短縮サービス X.gd](https://x.gd/view/developer)
ソフトウェア開発組織におけるAIコーディングの活用

# コンテンツ

 - 非エンジニアのAIコーディング活用
 - 新規開発におけるAIコーディング活用
 - 成熟したソフトウェアにおけるAIコーディング活用

非エンジニアロール、エンジニアロールの新規開発、エンジニアロールの成熟したソフトウェアの開発という３つの視点からAIコーディングの活用方法について紹介します。

___

# 非エンジニアのAIコーディング活用
___

## 小規模なアプリケーション開発

エンジニアなしで下記のような開発が実現できるようになります。

 - 新規サービスのプロトタイピング
 - 業務を補助するツールの作成
 - データ分析やダッシュボードUIの作成

１画面で完結する範囲なら自由度高くさまざまなものが作れます。
ただし、外部公開にはセキュリティ上の理由などからエンジニアの介在が必須です。
___

## コーディングへの参加

なぜ簡単な変更すらエンジニアに依頼する必要があったか。

- コードをどう変更すればいいか分からない
- 膨大なコードのどこを修正すればいいか分からない
- 開発に必要なツールの使い方が分からない
- 開発のルールが分からない
___

### 障壁はなくなった

すべてAIエージェントが理解して処理してくれます。
非エンジニアがコーディングに参加する障壁はなくなりました。

エンジニアに十分な足場を作ってもらう必要はありますが、プロダクトマネージャやデザイナー、テスト担当者が直接コーディングすることも現実的な選択肢になってきます。
___

### 非エンジニアが直接対応可能になるタスク

下記のようなコーディングタスクを非エンジニアが直接対応可能になります。

 - ページデザインや文言の変更
 - 簡単なロジックの変更
 - 自動テストの追加
 - ログの追加など不具合調査を目的としたコード変更

___

### 非エンジニアがコーディングに参加する効果

ソフトウェア開発において下記の２つは開発生産性を大きく落とす要因です。

 - コミュニケーションコスト
 - タスクキューの待ち

依頼者とエンジニア間の認識齟齬を埋めるためのやり取りがタスク完了を遅らせます。
また、簡単なタスクでも他の作業待ちにより完了までに時間がかかります。

非エンジニアのコーディング参加はこういった問題を大幅に改善できます。
___
# Vibeコーディングによる高速な新規開発
___

## Vibeコーディングとは

Vibeコーディングとは、OpenAIの共同設立者である Andrej Karpathy が提唱し名称が広まったソフトウェア開発スタイルです。
厳密な定義はありませんが、ほとんどのコーディング作業をAIに任せてしまうことを言います。
エンジニアは自然言語やデザインファイルの添付などでAIに指示を出してコードを生成します。
コードとソフトウェアの動作を確認し、必要に応じて修正を指示します。

___

## 新規開発はVibeコーディングで生産性が飛躍的に向上

新規開発においてVibeコーディングを活用すると、開発速度が劇的に向上します。
エンジニアが自然言語で記述した仕様をAIが瞬時にコードへ変換するため、実装工程が大幅に短縮されます。

___

## 人間が行うのは仕様作成・設計・確認

AIがテストコードの作成から実行確認まで担当してくれるため、人間の作業は主に「仕様の策定」「ソフトウェア設計」「実装結果の検証」に集中できます。
仮に設計に問題があった場合でも、修正作業はAIが行うため、従来のような大きな手戻りコストが発生しません。

___

## 品質面にも良い影響

AIコーディングは品質面でも大きなメリットをもたらします。
従来の開発では、納期に追われると機能実装が優先され、コードの保守性を高めるリファクタリングやテスト作成が後回しになりがちでした。
しかしAIを活用すれば、これらの品質向上作業も短時間で並行して進められるため、高機能かつ保守性の高いソフトウェアを初期段階から構築できます。

___
# 成熟したソフトウェアの開発における効果的な活用
___

## 開発フェーズより保守的な活用になる

すでにリリースされていて大規模なコードベースを持ち、主に改善や不具合修正を行うような成熟したソフトウェア開発では、AIの活用効果は新規開発ほど劇的ではありません。
このような環境では、コード変更の安全性が優先されるため、AIコーディングツールの利用は慎重になります。

___

## それでも生産性は大きく上げられる

現在のAIは複雑な不具合の根本原因を特定するほど高度な分析はできませんし、大規模なシステムの仕様全体を理解して適切な修正を行うことも難しいです。

しかし、影響範囲が明確に限定できるタスクでは、成熟したソフトウェア開発においてもAIコーディングは大きな効果を発揮できます。

___

## 定型的なリファクタリング作業

Claude Sonnet 3.7 などの最新AIモデルは、コード理解の精度が飛躍的に向上しています。
エンジニアが最初にリファクタリングのパターンを示し、それに基づいて同様の変更を多数のファイルに適用する作業をAIに任せることで、
大規模なコードベースでも効率的かつ安全にリファクタリングを進められるようになりました。

___

## テストコードの拡充

テストコードの追加のようにプロダクションコードを変更しないタスクはAIコーディングを大胆に適用できます。テストカバレッジを向上させたい場合、AIコーディングを活用することで短期間に多くのテストを追加できます。
特に単体テストやE2Eテストの作成は時間のかかる作業ですが、AIを使えば既存コードの動作を分析して適切なテストケースを素早く生成できます。

___

## ドキュメント整備の効率化

ドキュメント更新は開発者にとって重要ながらも時間を取られがちな作業です。AIはコードの変更を理解し、それに合わせてドキュメントを自動的に更新できるため、この面倒な作業を大幅に効率化できます。

___

## フロントエンド開発

成熟したソフトウェアであっても、フロントエンド開発は比較的AIコーディングの恩恵を受けやすい領域です。
フロントエンドの変更はバックエンドと比べてシステム全体への影響が限定的であり、
UIデザインの実装やスタイル調整など、仮にミスがあっても重大な障害につながりにくいタスクが多いためです。

---

## まとめ

AIコーディングは専門家のエンジニアの生産性を大きく向上させるだけでなく、ソフトウェア開発組織に関わるさまざまロールの人々を直接的な実装作業に巻き込むことを可能とします。
これは開発の進行を遅らせるコミュニケーションコストやタスク待ちの問題を大きく改善させる効果を持ちます。
flaskの使い方

備忘録がてらflaskの使い方について投稿します。

# インストール
デフォルトが3系になっている場合はpipでいいですが
pip3で基本インストールです。

```bash:sh
pip3 install flask
または
pip install flask
```

# プロジェクト構成
reactなどと異なり、手動で作る必要があります
ただ速攻で作れるコマンドがあるので別記事で紹介します

## Hello, World!
app.pyを作成してファイルがあるフォルダにターミナルを移動して諸準備完了です。

```python:app.py
from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return "Hello, World!"

if __name__ == '__main__':
    app.run(debug=True)
```
## ※todoアプリの構成例
ついでにtodoの構成例です。
これだとflask_todo_appに移動するイメージをもってください

```csharp
flask_todo_app/
│── app.py  (Flaskアプリのメインファイル)
│── templates/
│   ├── index.html  (タスク一覧のページ)
│   ├── add.html  (タスク追加ページ)
└── static/
    └── style.css  (CSSファイル)
```

# 稼働

下記のコマンドで起動です
```bash
python app.py
```




下記URLでアプリが見れます
http://127.0.0.1:5000/


基本的にapp.pyだけで見ることができるシンプルな構成です
そこから、ファイルやフォルダなど多数構成していきますがそのさい
便利なテンプレートをダウンロードして作成を早めることもできるので
いろいろ試してみましょう。

私が使用しているテンプレートはこのようなものです

[flaskでテンプレートcookiecutterの使い方](https://qiita.com/quesman011/items/41f4ce5d675b803d3f69)
フロー　未解決のエラー



+ [Failure when saving an HTTP call out in flow](https://qiita.com/Keiji_otsubo/items/f361b7c323de5c0d9ca0)

# Hmm, that didn't work. Check your internet connection and refresh the page.

+ [Flow: DataTable Selection gives error "Hmm, that didn't work"](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000PWCX7)

# Save your flow and refresh the page. If the problem persists, contact Salesforce Customer Support. Error ID: 1810384176.

+ [ctrl z in a flow label will crash the back end of the flow](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000KEO5B)
Amazon RDS

## RDS(Amazon Relational Database Service)とは
フルマネージドのリレーショナルデータベースサービス

## DBエンジンの種類
- Oracle
- MySQL
- MariaDB
- PostgreSQL
- SQL Server
- Db2
- Amazon Aurora（MySQL互換・PostgreSQL互換の独自DB）

## メリット
- データベース運用の手間を削減
- 要件への対応が容易
- コスト最適化

## 機能
### リードレプリカ
読み取り専用のデータベースを作成し、読み込み負荷を分散させるための機能

### 自動バックアップ
データベースの自動バックアップを作成し、過去の特定時点に復元できる機能

### 自動パッチ作業
データベースのソフトウェアを自動でアップデートし、最新のパッチを適用できる機能

### 暗号化
データの暗号化をサポートし、データの安全性を確保できる機能

### マルチAZ
プライマリDBとスタンバイDBを異なるアベイラビリティゾーン（AZ）に配置し、障害発生時に自動フェイルオーバーできる機能

### IAM認証
AWS IAM（Identity and Access Management）を使ったアクセス管理や、VPCセキュリティグループを利用したネットワーク制御が可能

## まとめ
AWS RDSは、主要なリレーショナルデータベースエンジンをサポートするフルマネージドサービスで、運用負担の軽減やコスト最適化を実現します。リードレプリカやマルチAZ、暗号化、自動バックアップなどの機能により、高可用性・セキュリティ・スケーラビリティを確保できます。
プログラム入門：Pythonのバージョン体系を自分なりに整理してみた

## はじめに

Pythonはバージョンごとに新機能や改善が加えられ、開発者にとって重要な選択肢となります。

:::note info
**しかし、どのバージョンを使うべきか迷うことも多く、適切なバージョンを選択することがプロジェクトの安定性や保守性に影響を与えます。**
:::

そこで、Pythonのバージョン管理について分かりやすく整理し、最適なバージョン選択の手助けとなるようにこの記事を書きました。

## Pythonのバージョン体系

Pythonのバージョンは、次の形式で管理されています。

```
メジャー.マイナー.パッチ
```

- **メジャーバージョン (Major)**: 破壊的な変更が加えられることがある。
- **マイナーバージョン (Minor)**: 後方互換性を保ちつつ、新機能が追加される。
- **パッチバージョン (Patch)**: バグ修正やセキュリティアップデートが行われる。

## 最新のPythonバージョンと特徴

現在のPython 3系では、以下のような特徴的な機能が追加されています。

- **Python 3.9 以降**: 型ヒントの強化
- **Python 3.10**: `match-case` 構文の追加
- **Python 3.11**: 実行速度の大幅な改善
- **Python 3.12**: エラーメッセージの改善、構文の最適化

## Pythonの最新バージョンを確認する方法

Pythonのインストールされているバージョンを確認するには、以下のコマンドを実行します。

```sh
python --version
# または
python3 --version
```

このコマンドを実行すると、使用中のPythonのバージョンが表示されます。

## 推奨されるPythonバージョン

- **新規開発**: 最新の安定版（例: Python 3.12）
- **既存のプロジェクトで互換性が必要**: Python 3.9 以降を推奨
- **LTS（長期サポート）を求める場合**: Python 3.11 以上

## まとめ

Pythonはバージョンごとに新機能が追加され、性能も向上しています。開発の目的やプロジェクトの要件に応じて適切なバージョンを選択することが重要です。

- 最新のPythonを使用することで、新機能や最適化の恩恵を受けられる。
- 既存プロジェクトの互換性を考慮する場合は、安定したマイナーバージョンを採用するのが良い。
- Pythonのバージョン確認方法を知っておくと、環境管理がスムーズになる。

適切なPythonのバージョンを選び、快適な開発環境を整えましょう！
4-React 受控表单绑定  react中获取dom

## 一：受控表单绑定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/f9650d2b-8022-465c-ad9f-2a70f87d7211.png)
通过react状态去控制Input框的状态
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/9b45cd9d-a7c7-4746-b7d7-b8673534a964.png)
## 二：react中获取dom
在react中获取dom元素：
1.useRef生成ref对象，绑定到想获取的dom标签身上
2.dom可用时，ref.current获取dom
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/436fdcb1-ed23-4018-a15d-8a4cf1cd1c01.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/c7729e79-aae4-44c1-94b8-62039c30a347.png)
## 三：案例--发表评论
#### 1.核心功能实现
①用数控绑定方式，可以把用户输入的东西，收集到content里面
②点击时发布评论，替换content字段，收集到的数据是什么就绑定什么
③延续数据修改不可变的方式，原本的所有数据都展开，增加一条自己的数据
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/809d56f3-c666-47d9-a995-7a902fec0156.png)
```java
// 发表评论
const [content,setContent] = useState("")
const handPublish =()=>{
  setCommentList([
      ...commentList,
      {
         rpid:100,
         user:{
            uid:"30009257",
            avatar,
            uname:"黑马前端",
         },
         content:content,
         ctime:"10-19 09:00",
         like:66,
         }
  ])
}
// 评论框
<textarea
    className="reply-box-textarea"
    placeholder="发一条友善的评论"
    value={content}
    onChange={(e)=>setContent(e.target.value)}
/>
// 发布按钮
<div className="reply-box-send">
   <div className="send-text" onClick={handPublish}>发布</div>
</div>
```
#### 2.id和时间处理
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/46090ea7-397e-4ec3-9ad3-c4dc1a409635.png)
1.①安装uuid
```java
npm install uuid
```
②使用方式
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/62c8ef74-e437-4d49-81c6-865e9e4eb0b5.png)
2.Day.js
1.①安装
```java
npm install dayjs
```
②使用方式
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/10c3f859-2dc7-4f38-ac5e-2368fd702497.png)
```java
{
import {v4 as uuidV4} from "uuid"
import dayjs from "dayjs"
         rpid:uuidV4(), //随机id
         user:{
            uid:"30009257",
            avatar,
            uname:"黑马前端",
         },
         content:content,
         ctime:dayjs(new Date()).format("MM-DD hh:mm"),// 格式化 月-日 时:分
         like:66,
         }
```
#### 3.清空内容和聚焦实现
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899383/b4f1b6d9-a61f-43c2-b846-a93bf8dfcfa0.png)
```java
// 1.清空输入框内容
setContent("")
// 2.重新聚焦 dom(useRef) -focus
const inputRef = useRef(null)
inputRef.current.focus()
// 评论框
<textarea
    className="reply-box-textarea"
    placeholder="发一条友善的评论"
    ref={inputRef}
    value={content}
    onChange={(e)=>setContent(e.target.value)}
/>
```
Raspberry pi3 model Bでベアメタルプログラム①

# はじめに
私は、OSの仕組みに興味があり、Raspberry piでとりあえずHDMI出力するところまでやってみようと思いはじめてみました。
ちなみに私はC言語の知識はありますが、OSやハードウェアについてはほとんど無知で調べても書いてある内容が難しくてわからなかったのでこのサイトのレッスンを主に、アセンブリ言語を調べながら一からやってみました。
https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/introduction.html
# 開発環境
今回Intel CPUのMacbookを使った。
コンパイラは32Bitで開発する場合gcc-arm-embedded、64Bitで開発する場合gcc-aarch64-embeddedをHomebrewでインストールする。
今回は32Bitで開発する。
# SDカードの準備
SDカードに必要なファイルは
<dl>
<dt>・bootcode.bin</dt> <dd>ブートローダー</dd>
<dt>・config.txt</dt> <dd>Raspberry piの起動の設定をここに書く</dd>
<dt>・start.elf</dt> <dd>ファームウェアファイル(X86でいうBIOSのようなもの)</dd>
<dt>・kernel.img</dt> <dd>本体プログラム(今回作るプログラム)</dd>
</dl>

なお、bootcode.bin、start.elfの中身は公開されていないので、私はSDカードにRaspberry piの公式のOSを専用ソフトでダウンロードして、そこからbootcode.bin、start.elf以外を全部消してSDカードを使用した。
config.txtはとりあえず空のテキストファイルとして置いておいた。
# Raspberry piのブートプロセス
1\. Raspberry piの電源を入れるとGPUが動き出す。
2\. GPUはSoC内にマスクされているブートローダーを実行。
3\. GPUはSDカード内にある２段目ブートローダー（bootcode.bin）を実行。
4\. GPUはstart.elfを実行。ここでCPUが起動。
5\. CPUがkernel.imgを実行。
# Raspberry pi3 model Bの概要
Raspberry pi3 model BはSoC(System on Chip)といい、CPUとGPUが1つのチップに搭載されている。
SoCはBroadcomのBCM2837でARMv8のクアッドコアCortex-A53 CPUを搭載し、GPUはデュアルコアのVideoCore IVが使用されている。
このRaspberry piは32bit、64bitどちらでも使える。
今回は32bitメインで開発する。
# Raspberry piの構造
Raspberry piの構造はメモリマップドI/O（MMIO）といい、決められた物理アドレス空間上に周辺機器のレジスタがマッピングされており、そのアドレスに書き込むことで周辺機器のレジスタを操作できるというもの。
# 最後に
今回はRaspberry piのベアメタルプログラミングについて必要最低限で知っておいた方がいいことをまとめてみました。
次回はLED点灯のプログラムをC言語とARMのアセンブリで書いてみたいと思います。
実務で身につけた小技＆ショートカット

# はじめに
実務を通じて、PC操作やショートカットキーについて先輩方に教わったり、実際に使用して効率が良いと感じたものをまとめました。

# 前提
- Macbookを想定
- 実務ベースの内容で、ある程度PCに慣れている人向け
- 基本的なショートカットキー、各種ツールの説明は省略

# 小技

## Raycast notes
ちょっとしたタスク管理やメモを取る際に、「Raycast Notes」を活用しています。

特に、言語化が必要な場面や電話のメモなど、本格的に記録するほどではない場合に重宝してます〜

こんな感じ↓

[![Image from Gyazo](https://i.gyazo.com/5383cf31dff119b2a39634027b031a7a.gif)](https://gyazo.com/5383cf31dff119b2a39634027b031a7a)

常にPC画面の最前面に表示されて他のアプリの背後に隠れることがなく、簡単に読んでメモができて忘れることが減りました。

https://www.raycast.com/

## Google Chromeタブ整理

使用するツールが増えると、いつの間にかブックマークが大量になり、管理が煩雑になります。

![スクリーンショット 2025-03-16 10.05.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3772961/095d8f07-eecd-4c5b-915b-3bdd85ad8785.png)

そのため、タブメニューにフォルダを作成し、整理することで管理が楽になります。
(タブメニューで右クリック→フォルダを追加→保存→ドラグ&ドロップ)

こんな感じ↓

[![Image from Gyazo](https://i.gyazo.com/f733678948ab39fb79a31e6fad9048a8.gif)](https://gyazo.com/f733678948ab39fb79a31e6fad9048a8)

# ショートカットキー
ここでは、VSCode(Cursor)やターミナルで使用するショートカットキーをまとめています。

## option
文字の選択や削除を効率化するために「option」キーと組み合わせます。

### option ＋ 削除
単語単位で削除でき可能。

こんな感じ↓

[![Image from Gyazo](https://i.gyazo.com/6e8b8ecf90b87215ec76d6f8c7ce9127.gif)](https://gyazo.com/6e8b8ecf90b87215ec76d6f8c7ce9127)

### option + 範囲選択
単語単位で効率的に編集可能。

こんな感じ↓

[![Image from Gyazo](https://i.gyazo.com/cc726b376cb8c6ee56bd8d5dc767c550.gif)](https://gyazo.com/cc726b376cb8c6ee56bd8d5dc767c550)

### ターミナル
ターミナルでも同様に単語単位で操作が可能。

こんな感じ↓

[![Image from Gyazo](https://i.gyazo.com/c3676b7e6decb12ef824f34eb490fa04.gif)](https://gyazo.com/c3676b7e6decb12ef824f34eb490fa04)

## 検索系
過去のコードを検索したり、特定のファイルを素早く開くため使います。

### 用語検索(command + shift + f)

プロジェクト全体から特定の用語を検索できます。

こんな感じ↓

[![Image from Gyazo](https://i.gyazo.com/7193a09d225243b1b7d9666961e3b65c.gif)](https://gyazo.com/7193a09d225243b1b7d9666961e3b65c)

### ファイル検索(command + p + /)

Command + P で検索メニューを開き、/ を入れるとファイル検索が可能。

こんな感じ↓

[![Image from Gyazo](https://i.gyazo.com/68dd24d4855205798de645ea554cfc5f.gif)](https://gyazo.com/68dd24d4855205798de645ea554cfc5f)

実務では、大量のファイルから一つずつ探すよりも、コマンドを活用する方が圧倒的に効率的です。

## 過去のファイルを開く (ctrl + r)
新しいウィンドウを開くのではなく、現在のウィンドウ内で別のフォルダのファイルを開く際に使用します。

こんな感じ↓

[![Image from Gyazo](https://i.gyazo.com/7a39dc8bb866de61564f44573a16fee1.gif)](https://gyazo.com/7a39dc8bb866de61564f44573a16fee1)

APIでつながっているファイルを開いたり、過去のコードを参考にする際、便利です。

# おわりに
技術力だけでなく、効率的な開発のためにPC操作や環境を整備することも重要だと感じています。
そして日々の業務で感じる面倒や不便さは、課題解決のヒントになるかもしれないと思っています。

この記事が、PC操作スキル向上に役立ちましたら幸いです。
記事の内容について気になることがあれば、お気軽にお知らせください。

# 参考

あらゆるショートカットキーをマスターするために必須の動画！


https://youtu.be/wf-8HkfMckM?si=Q-p7XZ-XgpYWCx6n
TeX Live 2024から2025へのアップデート Windows 編

# 概要
Windows環境にてTeX Live 2024から2025へのアップデートを実施したときの手順

# 詳細
1. インストーラー `install-tl-windows.exe` を用いてTeX Live 2025をインストールする 
    - [アップグレードの説明](https://tug.org/texlive/upgrade.html)には There is no comparable upgrade procedure for Windows. Doing a new installation is necessary. とある
    - `install-tl-windows.exe` は[インストール手順](https://tug.org/texlive/quickinstall.html)などからダウンロードできる
2. (任意) [tlgpg](https://texlive.info/tlgpg/)をインストールする
    - コマンドプロンプトで `tlmgr --repository http://www.texlive.info/tlgpg/ install tlgpg` を実行する
3. 既定のアプリを変更する
    - .texの既定値を2025のTeXworksに変更する
4. 2024のTeXworksの設定を引き継ぐ
    - `%USERPROFILE%\.texlive2025\texmf-config\texworks\configuration\tools.ini`
      - `%USERPROFILE%\.texlive2024\texmf-config\texworks\configuration\tools.ini` をファイルごと上書きする
    - `%USERPROFILE%\.texlive2025\texmf-config\texworks\TUG\TeXworks.ini`
      - defaultEngineを普段自分が使っているものに変更する
5. 動作確認を行う
    - TeXworksで適当なTeXファイルをタイプセットできることを確認する
6. TeX Live 2024をアンインストールする
    - `C:\texlive\2024\tlpkg\installer\uninst.bat` を管理者として実行
      - このバッチファイルは `%APPDATA%\Microsoft\Windows\Start Menu\Programs\TeX Live 2024\Uninstall TeX Live.lnk` の実体である
7. `%USERPROFILE%\.texlive2024` を削除する

:::note info
TeX Live 2024から2025へのパッケージの引き継ぎは実施していない
:::

# 参考
- [Upgrade - TeX Live - TeX Users Group](https://tug.org/texlive/upgrade.html)
- [Quick install - TeX Live - TeX Users Group](https://tug.org/texlive/quickinstall.html)
- [tlgpg - GnuPG packages in a TeX Live repository - texlive.info](https://texlive.info/tlgpg/)

<!--
# 参考
- https://twitter.com/denkiuo604/status/1638638962851086336
- https://twitter.com/denkiuo604/status/1638640107627618304
-->
Agnoを使ってエージェント同士を会話させたらオレオレ詐欺みたいになった話

Agnoの使い方を調べているところで、動作検証のために簡単なチャットボットを作ってみました。自分でチャットボットと会話するのも面倒なので、２つのエージェントを使って相互に会話するように設定しました。

試しに、「息子」と「母親」という設定でエージェント同士を会話させてみると、予想外にもオレオレ詐欺っぽい会話になりました。もちろん、この会話内容自体はAgnoとは直接関係ありませんが、予想外で面白かったです。

### 実行結果

```text
息子:あなたは都会で働く息子です。一人称は「オレ」、母親を「母さん」と呼びます。車で事故を起こし金が必要になったと、あわてて母親に電話しています。
母親:ひとり暮らしの母親です。比較的騙されやすく、相手の話を鵜呑みにしやすい性格です。息子を「あんた」と呼びます。

息子 『もしもし』

母親 『もしもし、あんた？どうしたの？何かあったの？』

息子 『もしもし、母さん、オレだ。ちょっと大変なことになっちゃったんだ。車で事故を起こしちゃったんだ。怪我はないけど、修理代がすごくかかりそうで…。今すぐお金が必要なんだ。助けてくれないかな…。』

母親 『えっ、事故って…大丈夫なの？怪我はないって言うけど、心配だわ。でも、お金が本当に必要なの？いくら必要なの？何か手伝えることがあったら言ってね。あんたのことが心配だから、急いで解決したいわ。』

息子 『うん、大丈夫だよ、母さん。怪我はないから安心して。だけど、車の修理代が多分十万円くらいかかりそうなんだ。ほんとに急いでるから、もしできるなら少しお金を貸してもらえないかな…？後でちゃんと返すから。母さんには心配かけたくなかったんだけど、どうしても助けが必要なんだ。』

母親 『わかった、あんたが無事でよかった。でも、そんなに急いでいるのなら…私も少し不安だけど、どうにかお金を用意してみるわ。どこに振り込めばいいの？大事に使ってね。後でちゃんと返してもらわないと、私も心配しちゃうからね。』

息子 『ありがとう、母さん。オレも母さんが心配するのはわかってる。振込先は〇〇銀行の〇〇支店で、口座番号は12345678だよ。本当に感謝してるから、大事に使うよ。後で必ず返すから安心して。母さんが怖がらないように、ちゃんとお金のことも報告するからね。』

母親 『うん、振込先もわかったわ。すぐに手続きするから、待っててね。でも、あんた、本当に安全には気をつけてね。事故のこともとても心配だから、ちゃんと報告してくれると助かるわ。無理しないで、何かあったらすぐに教えてね。』

息子 『うん、母さん、心配かけてごめん。気をつけるから安心して。振込の手続きしてくれるの、本当にありがとう。オレもちゃんと状況を報告するよ。無理はしないようにするから、また連絡するね。母さんも元気でいてね。』
```



## サンプルコード

これはAgnoのコーディングサンプルとして参考にしていただければ幸いです。

```python:sample.py
import sys, os
os.environ["AGNO_MONITOR"] = "false"
os.environ["AGNO_TELEMETRY"] = "false" # テレメトリを無効化
from utils import load_dotenv
from agno.agent.agent import Agent
from agno.models.message import Message
from agno.models.openai.chat import OpenAIChat
from agno.run.response import RunResponse

def main():

    prompt_list = {
        "息子": "あなたは都会で働く息子です。一人称は「オレ」、母親を「母さん」と呼びます。車で事故を起こし金が必要になったと、あわてて母親に電話しています。",
        "母親": "ひとり暮らしの母親です。比較的騙されやすく、相手の話を鵜呑みにしやすい性格です。息子を「あんた」と呼びます。",
    }
    agent_names:list[str] = []
    agents:dict[str,Agent] = {}
    for name,prompt in prompt_list.items():
        # エージェントの作成
        agent_names.append(name)
        agents[name] = Agent(
            description=prompt_list[name],
            model=OpenAIChat(id="gpt-4o-mini"),
            add_history_to_messages=True,  # チャット履歴を有効化
            num_history_responses=5,  # 過去の応答を表示する数
            markdown=False,  # マークダウン形式の出力
            exponential_backoff=True,  # エラー時の自動リトライ
            retries=2,  # リトライ回数
        )
        sys_msg = agents[name].get_system_message() or Message(role='system',content='')
        print(f"エージェント:{name}\nプロンプト:\n{sys_msg.content}\n")

    turn = 0
    while turn < 9:
        name = agent_names[turn % 2]
        if turn==0:
            mesg = "もしもし"
        else:
            res:RunResponse = agents[name].run(mesg)
            mesg = res.get_content_as_string()
        print(f"\n{name} 『{mesg}』")
        turn += 1

if __name__ == "__main__":
    load_dotenv()
    main()
```
Flutter講座(forROS2)04 Androidでビルドする

# 環境

この記事は以下の環境で動いています。

| 項目 | 値 |
|:--|:--|
| CPU | Core i5-8250U |
| Ubuntu | 22.04 |
| Flutter | 3.22.2 |

使用するタブレット環境
| 項目 |	値 |
|:--|:--|
| タブレット | Fire HD 8 Plus(第12世代) |
| android version | FireOS8 (Android 11相当) |
| android API level | 30 |

# 概要
ここまでflutterをUbuntuビルドで実行してきましたが、これをAndroid端末で動かせるようにします。

## android API level
一口にandroidといっても様々なバージョンがあります。重要なバージョンが2つあります

* Androidバージョン
こちらは「設定アプリ」の「デバイス情報」等で確認できます。販売ページなどで記載しているのはこちらのバージョン番号です。
* APIレベル
こちらはandroidバージョンに1対1で対応する値です。[Android開発者ページ](https://developer.android.com/tools/releases/platforms)で確認することが出来ます。
例えばandroid13はAPIレベルは33です。

APIレベルは後述のSDKのインストール時に指定する必要があります。例えばAPIレベル30のSDKをインストールすると、Android13(APIレベル33)では実行できますが、Android10(APIレベル29)では実行できなくなります。

## AndroidSDK
Android用のアプリを作るために必要なライブラリです。

## 開発者モード
通常のAndroid端末ではplayストアからインストールしたアプリしか実行できず、第3者の作成したアプリはインストールできません。Android端末で開発者モードを有効にすると、これらの操作が可能になります。

# AndroidSDKのインストール
開発PCにAndroidSDKをインストールします。

## javaとのインストール

```shell:javaのインストール
sudo apt update
sudo apt install openjdk-17-jdk
```

## AndroidSDKのインストール
[downloadページ](https://developer.android.com/studio)の下部にある
`commandlinetools-linux-xxxxxxxx_latest.zip`をダウンロードします。
これを展開して`~/android-sdk/`に置きます。

`flutter config --android-sdk /home/ubuntu/android-sdk/` を実行します。

## flutter doctorで確認

```shell:flutter doctorで確認
flutter doctor
```

これで`[✓] Android toolchain`という表示があれば成功です。

# Android用ビルド

## Android端末の開発者モード有効化
通常のAndroid端末は正式リリースされたアプリしかインストール・実行が出来ません。今回はローカルビルドしたアプリをインストール・実行するために「開発者モード」と「USBデバッグ」を有効にします。

* 「設定アプリ」を開く->「デバイス情報」を選択
    * 「ビルド番号」を10回ほど連続でタップする
* 「設定アプリ」を開く->「システム」を選択->「開発者向けオプション」を選択
    * 「USBデバッグ」をONにする

## Android端末とPCの接続
開発者モードにしたAndroid端末をPCと接続します。

## ADBの再起動
当環境だとこのままだとADBの接続不可のエラーが出ます。root権限で再起動します。

```shell
sudo ~/android-sdk/platform-tools/adb reboot
```

## デバイスの接続確認
`flutter devices`を実行して端末名を確認します。

```shell:実行結果
$ flutter devices
Found 3 connected devices:
  SO 52B (mobile) • HQ615X00B1 • android-arm64  • Android 13 (API 33)
  Linux (desktop) • linux      • linux-x64      • Ubuntu 22.04.4 LTS
  6.5.0-28-generic
  Chrome (web)    • chrome     • web-javascript • Google Chrome 123.0.6312.58
```

## Android用ビルドの実行

```shell:Android用ビルド
flutter run -d HQ615X00B1
```

を実行すると、Android用のアプリのビルドとインストールを実行します。
このあと端末側にアプリが出現するので、それを実行します。

## リリースビルド
上記のビルドはデバッグビルドで、問題発生時に様々な情報が提供される反面、処理負荷の問題があります（今回の例では問題になるほどではありませんが）
以下のコマンドでリリースビルドを行うことが出来ます。

```shell:Android用ビルド
flutter run -d HQ615X00B1 --release
```

# 参考

# 目次ページへのリンク
[ROS2講座の目次へのリンク](https://qiita.com/srs/items/5f0d765343ca78f524ed)
GROWIプラグインで、ReactのuseState/useEffectなどが使えます！

[オープンソースのWikiであるGROWI](https://growi.org/ja/)にはプラグイン機能が用意されています。自社のデータを表示したり、表示をカスタマイズするのに利用できます。

執筆時点での最新版である7.2から、ReactのuseStateやuseEffectなどのHooksが使えるようになりました。これにより、GROWIプラグインでユーザーのアクションなどを伴ったインタラクティブなプラグイン開発が可能になりました。

今回は、そのReact Hooksを使ったGROWIプラグインの開発方法を解説します。

## 実際の動作

GROWIのページにて、ボタンを押した際のリアクション（カウントアップ）や外部データの取得&表示を行っています。

![画面収録 2025-03-14 17.07.51.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/cb57b27a-4e01-491a-aad3-1080db3bc84f.gif)


## プラグインは3種類

GROWIで作れるプラグインは全部で3種類あります（組み合わせ可能です）。

- RemarkPlugin
- RehypePlugin
- React Component Plugin

今回対象となるのは、React Component Pluginです。これは、Reactコンポーネントを使って表示をカスタマイズできるプラグインです。

```ts
const { a } = options.components;
// replace
options.components.a = helloGROWI(a);
```

React Component Pluginでは、aタグやcodeタグ、imgタグなどの動作を標準のものと置き換えられます。上記のコードの場合、aタグをhelloGROWI関数で置き換えています。例は[こちらのコード](https://github.com/goofmint/growi-plugin-script-template/blob/main/client-entry.tsx)を参考にしてください。

## React Hooksを使ったプラグイン開発

プラグイン側で利用するのは `growiFacade.react` です。これは、GROWI本体側のReactオブジェクトが入っています。以下のようなコードで、各種React Hooksを取り出せます。

```ts
const { useEffect, useCallback, useState } = growiFacade.react;
```

後は通常のReactアプリケーションのように利用できます。

```tsx
const [count, setCount] = useState(0);

return (
  <div>Count: {count}</div>
  <button
    onClick={useCallback(() => setCount(c => c + 1), [])}
  >
    Up
  </button>
)
```

また、これまでは利用できなかった外部データの取得や画面への反映も可能になりました。

```ts
const [obj, setObj] = useState<FakeJson | null>(null);

const getFakeJson = async(count: number) => {
  const url = `https://jsonplaceholder.typicode.com/todos/${count}`;
  const response = await fetch(url);
  const json = await response.json() as FakeJson;
  setObj(json);
};

useEffect(() => {
  if (count > 0) getFakeJson(count);
}, [count]);

return (
  { obj && (
    <div>
      <h2>{obj.title}</h2>
      <div>{obj.id} & {obj.userId}</div>
      <p>{obj.completed ? 'Completed' : 'Not Completed'}</p>
    </div>
  )}
)
```

## 注意点

useEffectやuseStateなどは本体側のオブジェクトから取得する形で実現しています。通常のReactアプリケーションのように `import { useState, useEffect } from 'react'` ではないので注意してください。つまり、npmパッケージとして公開されているReactコンポーネントを、そのまま利用できない可能性があります。

その場合は `@r2wc/react-to-web-component` を使って、ReactコンポーネントをWeb Componentにする方法が利用できます。

参考例： [GROWIで手書き風ドローができるExcalidrawを使えるプラグインを作りました \#TypeScript \- Qiita](https://qiita.com/goofmint/items/6fb700d77aef1fe32133)

## まとめ

GROWIプラグインでReact Hooksを使ったプラグイン開発が可能になりました。これにより、ユーザーのアクションなどを伴ったインタラクティブなプラグイン開発が可能になります。外部データと連係するプラグインも作成できるでしょう。

プラグインを開発して、より便利にGROWIを活用してください。

[OSS開発wikiツールのGROWI \| 快適な情報共有を、全ての人へ](https://growi.org/ja/)
RustRover の "実行/デバッグ" 構成

以下の手順で準備を進めたプロジェクトを RustRover で開いても
"実行/デバッグ" 構成が未設定です。

1. リポジトリ追加
1. `git clone`
1. `cargo init`

もちろん、RustRover のメニューを使って登録することはできますが毎回行うのは大変です。
そんな時は以下の内容を `.idea/workspace.xml` に追加すると
"実行/デバッグ" 構成に反映されるので便利です。

👉 `APP_NAME` はご自身のプロジェクトの `package.name` に置換
👉 挿入場所は `<component name="RustProjectSettings">` の上

```xml
  <component name="RunManager" selected="Cargo.Run APP_NAME">
    <configuration name="Run APP_NAME" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
      <option name="buildProfileId" value="dev" />
      <option name="command" value="run --package APP_NAME --bin APP_NAME" />
      <option name="workingDirectory" value="file://$PROJECT_DIR$" />
      <envs />
      <option name="emulateTerminal" value="true" />
      <option name="channel" value="DEFAULT" />
      <option name="requiredFeatures" value="true" />
      <option name="allFeatures" value="false" />
      <option name="withSudo" value="false" />
      <option name="buildTarget" value="REMOTE" />
      <option name="backtrace" value="SHORT" />
      <option name="isRedirectInput" value="false" />
      <option name="redirectInputPath" value="" />
      <method v="2">
        <option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
      </method>
    </configuration>
    <configuration name="Test APP_NAME" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
      <option name="command" value="test --workspace" />
      <option name="workingDirectory" value="file://$PROJECT_DIR$" />
      <envs />
      <option name="emulateTerminal" value="true" />
      <option name="channel" value="DEFAULT" />
      <option name="requiredFeatures" value="true" />
      <option name="allFeatures" value="false" />
      <option name="withSudo" value="false" />
      <option name="buildTarget" value="REMOTE" />
      <option name="backtrace" value="SHORT" />
      <option name="isRedirectInput" value="false" />
      <option name="redirectInputPath" value="" />
      <method v="2">
        <option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
      </method>
    </configuration>
    <list>
      <item itemvalue="Cargo.Run APP_NAME" />
      <item itemvalue="Cargo.Test APP_NAME" />
    </list>
  </component>
```
Dockerのオンラインインストール方法

Docker公式が提供している「便利スクリプト(get-docker.sh)」を利用してshスクリプト一発でインストールできることが便利です。こちらは`apt`で手動設定する方法よりも手軽です。
なお、snap で完全オフライン Ubuntu に docker 環境を作る方法もあります。（略）

## 1. 前提条件
- Ubuntu環境であること
- `curl`コマンドがインストールされていること  
  インストールされていない場合は、以下コマンドでインストールできます。  
  ```bash
  sudo apt-get update
  sudo apt-get install -y curl
  ```

## 2. Dockerのオンラインインストール手順
1. 公式スクリプトをダウンロードする
   ```bash
   curl -fsSL https://get.docker.com -o get-docker.sh
   ```
2. ダウンロードしたスクリプトを実行する
   ```bash
   sudo sh get-docker.sh
   ```
   上記コマンドで、Dockerの最新バージョン(Stable版)が自動的にインストールされます。  
   なお、インストール作業中にいくつかのパッケージが追加でインストールされる場合があります。

3. インストール確認
   ```bash
   docker --version
   ```
   `Docker version XX.XX...` のようにバージョンが表示されればインストール成功です。

## 3. インストール後の設定例
- **一般ユーザーでのDocker実行**  
  Ubuntu環境では、デフォルトでDockerコマンドを実行する際に `sudo` が必要となります。一般ユーザーで`sudo`無しでも実行したい場合は、以下のようにユーザーを `docker` グループに追加してログインし直します。
  ```bash
  sudo usermod -aG docker $USER
  ```
  上記を実行したら、一度ログアウトして再度ログインし直すか、シェルを再起動すると設定が反映されます。  

- **サービスの状態確認**  
  Dockerデーモンが起動しているかを確認するには以下のコマンドを使用します。
  ```bash
  systemctl status docker
  ```
  Dockerが起動していない場合は以下で起動します。
  ```bash
  sudo systemctl start docker
  ```
  常に自動起動させる場合は以下を実行します。
  ```bash
  sudo systemctl enable docker
  ```

## 4. インストールがうまくいかない場合の対処例
- `curl`がない場合は先に`curl`をインストールしてから再度実行します。
- 既にSnap経由などでDockerがインストール済みの場合、競合を避けるために事前にアンインストール（`snap remove docker`など）しておきます。

---
AtCoder ABC 397 D - Cubes 個人的備忘録

https://atcoder.jp/contests/abc397/tasks/abc397_d

# この記事の内容

個人的に「これは解けただろ…」と悔しすぎたので、脳にこの手の発想を叩きこむためにまとめたメモです。

## ここを反省したい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798407/7cc130be-bde6-4305-92a5-8dadbc0dc817.png)

コンテスト中に、因数分解してみた紙を眺めていたのに、「x-y を他の値において、とりあえず x と y を消して変形してみよう」という **発想が出てこなかったこと** ですねぇ。

受験なんぞ、ン十年前の話のおっさんなので、こっちのほうに答えがあるというカンが働かないのは仕方ないとして、手詰まりになっているならとりあえずいじり倒してみるという考えがまったく頭になかった。

解けなかった、とか、できなかった、ではなくて、やろうとすらしなかったのが、本当に悲しい。反省します。

### ソースコード サンプル

```c++:Main.cpp
#include <bits/stdc++.h>
using ll = long long;
using namespace std;
int main( void )
{
	ll N; cin >> N;
	// (X-Y) を d とおく
	// X - Y = d  ⇒  X = Y + d だから
	// X^3 - Y^3 = N は
	// (Y+d)^3 -Y^3 = N
	// Y^3 + 3Y^2d + 3Yd^2 + d^3 - Y^3 = N
	// d^3 + 3Yd(Y+d) = N
	// 3Yd(Y+d) は正の整数なので
	// d^3 < N
	for( ll d = 1; d * d * d < N; ++d ){
		// 3Yd(Y+d) = N - d^3
		// Y(Y+d) = (N - d^3)/3d
		// 右辺を定数 C と置いた場合、
		// この式は以下の条件を持つ二次方程式
		//  ・Y^2 + Yd - C = 0
		//  ・Cは正の整数

		// Cが整数にならないdをスキップ
		ll C = N - ( d * d * d); // (N - d^3)
		if( C % (3*d)){
			continue;
		}
		C /= 3*d;	// ÷3dしてCを求めておく

		// 二次方程式の解の公式 ax^2 + bx + c = 0
		// ⇒ x = (-b [+-] sqrt(b^2 - 4ac))/2a
		//  Y = ((-d) + sqrt( d^2 - 4*1*(-C))) / (2*1)
		ll Y = (sqrt( d*d + 4*C )-d) / 2;

		// ここで求めたYに浮動小数点演算の誤差がないことを検算する
		if( Y*Y + Y*d - C == 0 ){
			// Y^2 + Yd - C = 0 が成り立つので答え
			// X = Y + d
			cout << (Y+d) << ' ' << Y << endl;
			return 0;
		}
	}

	// d^3 < N の範囲で答えがなければ -1
	cout << "-1" << endl;
	return 0;
}
```
VisionDevCamp 福岡 2025

Apple VisionPro が切り開いた空間コンピューティングの時代。 チームやソロでプロジェクトをハックし、ハッカソン形式で新しい空間体験を創造してみませんか。 経験は問いません。 デザイナー、Unity 開発者、デジタルアーティスト、AI エキスパート、モバイルアプリ開発者、ウェブ開発者、ストーリーテラー、スタートアップ起業家を募集します。 ハッキング用のデバイスも用意しています。

VisionDevCamp は、2007 年に iPhone のリリースとともにシリコンバレーで始まったハッカソン、iPhoneDevCamp から始まり、その後、iPhoneDevCamp は iPadDevCamp と iOSDevCamp に拡大しました。これらのハッカソンには長い歴史があります。決済会社 Square、Apple の Testflight ツール、OAuth プロトコルはすべて、もともと DevCamp ハッカソンで始まりました。このような名誉あるイベントが日本で開催されるのは今回が初めてです。

このイベントは無料ですが、登録が必要です。ハッカソンの形式を理解し、チームを組むために、金曜日の夜のセッションに参加することを強くお勧めします。直接参加してチーム間で協力することを推奨します。空間デザインの専門家、ネイティブ Swift 開発、ストーリーテリング/ナラティブの専門家、スタートアップ起業家が参加し、経験を共有します。

プロジェクトのために何をハックしたらいいのかアイデアがありませんか？大丈夫です。私たちはアイデアを掲載し、特定のプロジェクトのアイデアには報奨金としての報酬も提供します。

より詳しいイベント情報: https://visiondevcamp-fukuoka.pages.dev/

英語: https://visiondevcamp-fukuoka.pages.dev/en/

![visiondevcamp_design2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3902372/fabe7ae9-9a9a-41f5-82f8-aac2660f33c0.png)
私のシステム運用保守の学びについてまとめました

## はじめに
実務を通して実務のシステム運用保守で大切な事をまとめました。
私個人の学びをまとめております。

### 1.本来、あるべき姿を追求する
システムの設定は過去の設定を元になんとなく設定ではなく、
**本来、求められている設定になっているかの視点でシステムを設定する必要があります**
上記の視点を常に持つことです。

### 2. サービスを提供していることを意識する
運用保守の仕事は求められているサービス提供に影響が出るものに関しては
クリティカルに対応する必要がある。
**本来実施すべきことが出来ていないケースはより優先度が高めになります。**
特に監視設定は優先度が高くなります。

### 3.一つのサーバーに影響があれば他のサーバも調査

**一つのサーバに障害があれば同じ構成の他のサーバも同様な事象が起きていないか確認する習慣をつけた方が良いです。**
障害がある一つのサーバのみ調査して完了したつもりでいることが多いです。


### 4.本番環境で使用実績があるコマンドを使用する
本番環境で使用実績があるコマンドを優先して使用することをお勧めします。
普段使わないコマンドをいきなり本番環境で使用することはお勧めしません。

**必ずコマンドの動作確認を実施後、本番環境で使用する**
コンテナのコマンド「docker attach」の様に使い方によってはコンテナが停止するコマンドもあります。

### 5.新規の設定は必ず現行の設定と比較する
新規で設定する場合は必ず現行のサーバの設定ファイルとの差分を比較した方が良い。
設定漏れが隠れている可能性があります。

以下のコマンドは空行を非表示にして先頭に#がついたコメント行を非表示になり、見やすくなるためお勧めのコマンドです。
```
cat 設定ファイル | grep -v ^$ | grep -v ^#
```

### 6.説明するときは私と同じ情報を持っていない前提で会話する
ユーザやチームの方に説明するときは自分が頭の中にある情報がほかの方が持っていない前提で説明した方が丁寧で説明不足をなくせます。

### 7.自動化は大変工数を削減できるがミスると影響が大きくなります
例えば不要な設定ファイルを一括削除するスクリプトを作成したら一括で削除できて
工数削減出来て繰り返し使用できますが、スクリプトに間違いがあると大きな事故になります。

**自動化は大きな事故と隣り合わせのため、検証は十分に行う必要あり。**
すべての分岐条件でテストを実施する必要があります。


### 8.クラウド環境を使用する場合は一般公開できない設定にする
クラウド環境を使用する場合は還元を絞り、一般公開できない設定にすることをお勧めします。少しでも一般公開を選択した場合でも、セキュリティ事故になります。

## まとめ
システム運用保守で必要なことをまとめました
仮に環境がAWSであってもシステム運用保守で気を付ける点は同じです。
参考になれば幸いです。
リファクタリングの必要性を道路工事で理解してみた

## コードのリファクタリングは「道路工事」に似ている

### はじめに

ソフトウェア開発をしていると、だんだん開発スピードが落ちたり、バグが増えたりすることがありますよね。そんな問題を防ぐためには、コードを定期的にリファクタリングすることがとても大切です。

今回は、リファクタリングの大切さを「道路工事」に例えて、できるだけわかりやすくお伝えします。この記事を通して、コードのリファクタリングの必要性を再認識してもらえたら嬉しいです！

![エンジニアのイラスト](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuk_7IpIzoxmyLQPjEvjkMYCYBe4b8QCyBodesaM_Qz5R-6tOOS9lvTBpZc_9WSdMialYYqxjH1vHhK8wNudeaM6rLeeFPpI_p7PNM8h9VKeMOa8QB_Ah9aZu0U0vCJkqw4JaipkBS-EoF/s800/animal_chara_computer_inu.png)

### 道路工事が大切な理由

普段使っている道路は、時間とともに傷んできます。道路工事をしないと、道がデコボコになって車が走りづらくなり、スムーズに進めなくなりますよね。これが原因で事故やトラブルにつながることもあります。

実はソフトウェア開発も同じなんです。コードをずっと整備しないと、コードが複雑になり、開発がスムーズに進まなくなります。急いで機能を追加すると、品質が下がり、バグも起きやすくなります。

これはまさに、整備されていない道を無理やりトラックで荷物を運ぶような感じ。荷物は散らばり、タイヤにもダメージがあり、色々なトラブルが発生します。

![道路工事のイラスト](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHcIcb0ery2TEtDbxRWJYkQocBjTNE9nw9JuR5FkWoP7NoKTB46PX5c7cIxTJ6CwksuYQ-zYPIKW3nik2q_7FRnkJDbT52RpULta7yqdIqgJHHb34hCYVSvo9jy5VLxsETG_4V76Lw4z4h/s800/job_kukakusen_kouji.png)

### 状況に応じた道路工事とリファクタリング

道路工事って、状況に応じて道幅を広げたり、信号を設置したりと色々工夫しますよね。使いやすくするために、その時々に合った対応をします。

コードもそれと似ています。よく使う機能や処理を共通化して再利用できるようにしておけば、開発効率がぐっと良くなります。一度整えておくことで、次の開発が楽になりますよ。

![効率化のイラスト](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJeMMTgBaQh9l1bwQ00ZVDFsXHYgMo_OnsPjCnQ49AWl22Yqh9Eys8F6xcGfvZl5Ic8u0j_NtkEf2zHtVPcGV3hHKOW4wiiQixBqxuNOGUXixxAQIXkYVpJxfsApKOhwCMKjp-pZ3aLqFb/s1600/cafe_nomad_woman.png)

### 定期的なリファクタリングのメリット

道路を定期的に整備することで、スムーズな物流を維持できるように、コードも定期的に整備していれば、いつでも品質の高い機能をスピーディに提供できます。

リファクタリングを後回しにせず、日々の開発作業にちょっとずつ取り入れてみましょう。これがチーム全体の効率やソフトウェアの品質アップに繋がります。

### おわりに

リファクタリングは、一見すると地味な作業ですが、その効果は長い目で見ると非常に大きなものです。道路をちゃんと整備して快適に使えるようにするのと同じように、コードも定期的にリファクタリングして、効率よく良い品質を保ちましょう。

ぜひ毎日の開発でちょっと意識して取り組んでみてください！
Vimのキーバインドとよく使うコマンドまとめ

# Mac で Vim を統一して使う方法（ターミナル & VSCode）

## **はじめに**

Mac で **ターミナル Vim** と **VSCode の Vim 拡張（VSCodeVim）** をできるだけ統一して使いたい場合、設定の違いを理解して適用するのが大事です。

特に、`jj` / `ｊｊ` でノーマルモードに戻る設定や、Vim の便利な設定・コマンドを **ターミナル Vim** と **VSCode** の両方で統一する方法を解説します。

また、`jj` / `ｊｊ` を押したときに **IME を自動でオフ（英字入力に切り替え）** する方法や、Vim のクリップボード設定 (`yy` でコピー) が機能しない場合の対処法も紹介します。

---

## **1. Vim のおすすめ設定（.vimrc）**

Vim を快適に使うための `.vimrc` の設定を紹介します。

```vim
" 文字エンコーディング
set fenc=utf-8

" 表示関連
set number        " 行番号を表示
set cursorline    " カーソル行を強調
set visualbell    " ビープ音を視覚的に変更
set background=dark " ダークテーマ対応
set laststatus=2  " ステータスラインを常に表示
syntax on         " シンタックスハイライト有効
set ruler         " カーソル位置を表示

" 検索関連
set ignorecase    " 大文字小文字を区別しない検索
set smartcase     " 大文字を含む場合は区別
set incsearch     " インクリメンタル検索（リアルタイム）
set hlsearch      " 検索結果をハイライト表示

" タブ・インデント
set expandtab     " タブをスペースに変換
set tabstop=2     " タブ幅を2スペースに
set shiftwidth=2  " インデント幅を2スペースに
set autoindent    " 自動インデントを有効化

" クリップボード設定
set clipboard=unnamedplus " システムクリップボードと連携（`yy` でコピー）

" キーマッピング（すべてのモードで 'jj' / 'ｊｊ' でノーマルモードへ戻る）
inoremap <silent> jj <ESC>:silent !im-select com.apple.keylayout.ABC<CR>
inoremap <silent> ｊｊ <ESC>:silent !im-select com.apple.keylayout.ABC<CR>
cnoremap jj <C-c>
cnoremap ｊｊ <C-c>
vnoremap jj <ESC>
vnoremap ｊｊ <ESC>
xnoremap jj <ESC>
xnoremap ｊｊ <ESC>
onoremap jj <ESC>
onoremap ｊｊ <ESC>
snoremap jj <ESC>
snoremap ｊｊ <ESC>
```

---

## **2. `.vimrc` を VSCode にも適用する（設定の統一）**

Vim の設定を VSCode でも適用するには、`settings.json` に以下の設定を追加します。

```json
{
  "vim.vimrc.enable": true,
  "vim.vimrc.path": "~/.vimrc"
}
```

この設定を適用することで、**Vim の設定を VSCodeVim でもそのまま利用** できるようになります。


---

## **4. Vim で `yy` がクリップボードにコピーされないときの対処法**

Vim で `set clipboard=unnamedplus` を設定しているのに `yy` でクリップボードにコピーできない場合、Vim が `+clipboard` に対応しているか確認してください。

### **✅ Vim の `+clipboard` 対応を確認**
```sh
vim --version | grep clipboard
```

**出力例（対応している場合）**
```
+clipboard         +xterm_clipboard
```

**出力例（対応していない場合）**
```
-clipboard         -xterm_clipboard
```

### **✅ Mac で `+clipboard` に対応した Vim をインストール**
```sh
brew install vim
```
この後、Vim を再起動すると `yy` でクリップボードにコピーできるようになります。

---

## **5. よく使う Vim コマンド**

### **移動・検索関連**
- `gd` / `gD` : 変数や関数の定義へジャンプ
- `Ctrl-o` / `Ctrl-i` ：ジャンプ履歴を戻る・進む
- `gf` ：カーソル下のファイルを開く
- `[{` / `]}` ：関数やブロックの開始・終了へジャンプ
- `f<char>` / `F<char>` ：指定した文字へ移動（順方向 / 逆方向）
- `;` / `,` ：直前の `f` / `F` の移動を繰り返す
- `>>` / `<<` : インデントの追加

### **編集関連**
- `ciw` ：カーソル位置の単語を削除して挿入
- `di[` ： `[` を含むブロックの中身を削除
- `r<char>` ：カーソル下の1文字を `<char>` に置換
- `.` ：直前の編集操作を繰り返す（挿入後でも `Esc` でノーマルモードに戻れば使用可）
- `Shift-A` ：行末に移動して挿入モード
- `gU` ：選んだ文字を大文字にする

---

## **6. まとめ**

- **Vim の設定を `.vimrc` に統一** し、VSCode でもそのまま適用可能
- **`jj` / `ｊｊ` でノーマルモードに戻る + IME をオフ** にする設定を追加
- **`yy` でクリップボードにコピーするには `+clipboard` 対応の Vim が必要**

この `.vimrc` を導入すれば、Mac で Vim を統一して快適に使えるはず！
ABC397回答メモ

# 0.はじめに
　もうほぼ緑と言っていいくらいのレートになっているので
　後退だけはしたくない今日このごろ。
　A~Cは順調に回答できたものの、Dでブレーキ。
　回答のイメージはできたものの、実装方法が思いつかず時間切れ。
　これは落ちたなと思いつつレート更新を待っていたところ
　まさかのレート+5の804で緑コーダーに返り咲きました。
　まぁほぼ茶色と言っていいくらいのレートですが。


# 1.A - Thermometer
　かんたんかんたんと思って始めたら
　コンテストではあまり見かけない小数点を扱う問題。
　使い慣れないけど、float型を使用してインプットを受け取り
　あとは普通に判定してACでした。

　https://atcoder.jp/contests/abc397/submissions/63765049


# 2.B - Ticket Gate Log
　簡単な用でなかなかややこしい問題。
　前の文字と、現在の文字の比較で、iとoかoとiでない場合は
　文字を足す。あとは、最初はi、最後はoでhない場合も文字を足す。
　という感じで文字列をなめて算出しました。

　https://atcoder.jp/contests/abc397/submissions/63780229


# 3.C - Variety Split Easy
　尺取法？的な問題。
　リストの分割点を左から右にずらしていったとき、左の要素種類数と右の要素種類数の
　増減を計算し最大点をさぐりました。
　最初にカウンター関数で、左0で右にすべての要素を持って行った場合をもとめ
　そこから、1つずつ対象の要素を右から左に移した場合に
　左の要素数が増えるなら、左の要素数を+１
　右の要素数が減るなら、右の要素数を-１
　左の要素数と右の要素数を足した数が、いままでの最高値より高ければ置き換え
　といった感じで実装しました。

　https://atcoder.jp/contests/abc397/submissions/63790422


# 4.D - Cubes
　立方数を扱う問題。
　XとYの差を固定すれば、あとは2次方程式を解くのみ。
　と、言うところまでは思いついたのですが
　公式で2次方程式を解こうとするとどうしても小数点が
　入ってきて上手く実装できませんでした。

　コンテスト後、解説を見て整数だけというか、四則演算だけというかで
　求めていく方法を知り、なるほどとなりました。
　同じような問題に応用できるかは不安ですが覚えておきたいやり方です。

　https://atcoder.jp/contests/abc397/submissions/63862207


以上
ServiceNowには多言語対応があるのでDynamic Translationは不要では

# 機能概要
ServiceNowのDynamic Translation（動的翻訳）は、プラットフォーム上に入力されたテキストをリアルタイムに翻訳する機能です。
ユーザーの入力言語を自動検出し、システムが「テキスト入力の言語を検出し、同じ言語で自動的に応答」することで、リアルタイムな翻訳を実現します。​
# Dynamic Translation（動的翻訳）不要説
## 結論
事前に必要な言語対応記事を準備できるなら必要ない。
Dynamic Translationの真の価値は文字通り動的な翻訳が可能にあるので、ユーザとエージェントとのチャット対応といったリアルタイムでの活用シーン効果が大きい。
# 通常の多言語対応とDynamic Translationの違い
## 通常の多言語対応
事前に「英語版のUI」「日本語版のUI」などを用意しておき、ユーザーが言語を切り替えると翻訳済みの画面（UIラベルやナレッジ記事）を表示する。

メリット：UIや記事は正確に翻訳したものを提供できる。
デメリット：すべてのテキストを手動で翻訳・更新する必要があり、想定外のフリー入力テキスト（問い合わせなど）には対応が難しい。
## Dynamic Translation（動的翻訳）
ユーザーが入力した任意のテキスト（たとえば問い合わせ内容）を、その場でリアルタイムに翻訳して画面上に表示する。

メリット：問い合わせやチャットの自由記述テキストにもすぐ対応できる。エージェントが書いた内容も、ユーザーの言語に即時に翻訳可能。
デメリット：自動翻訳なので、専門用語や文脈に応じた調整が必要なケースもある。

# 翻訳の事前準備
## 通常の多言語対応
あらかじめ翻訳が必要なUI要素やドキュメントを各国語に翻訳・登録しておき、それを切り替える。

- 例：UIラベル・ナレッジ記事・FAQなどを多言語で準備する。
- 新しい言語を追加したい場合は、その分の翻訳と管理が発生する。
## Dynamic Translation（動的翻訳）
システム側で「入力された言語を自動検出し、リアルタイムで翻訳」するため、エージェントやユーザーがどの言語で入力してもやり取りが可能。

- 新たに対応したい言語が増えても、大規模な事前翻訳コストがかからない。
- 同じ会話の中で複数言語が混在しても対応できる。

# チャットや問い合わせのやり取り翻訳
## 通常の多言語対応
「UIのラベル・ボタンやナレッジ記事をあらかじめ翻訳した状態で提供する」ことが多い。

- たとえば顧客が日本語UIで操作し、エージェントは英語UIで操作する、という具合に画面自体は各自の言語で見られる。
- しかし、実際の問い合わせ内容ややり取り自体が自由入力（テキスト）で行われる場合、そこを自動翻訳する仕組みがなければ、お互い同じ言語で会話することは難しい。
## Dynamic Translation（動的翻訳）
「UI・画面のラベル」だけでなく、「問い合わせやチャットのやり取り」に含まれるテキストをすぐに翻訳する。

- エージェントは英語のUIで見て、返信するときも英語で書いてOK。
- ユーザーは日本語を入力してOK。お互いに自分の言語で入力したものが、相手のUIにリアルタイム翻訳される。
- **事前に準備された翻訳**だけではなく、**チャットの応答内容**自体が動的に翻訳される点が大きく異なる。

# 適用範囲の幅広さ
## 通常の多言語対応
主に画面UIの固定文言や、ナレッジ・FAQのような固定コンテンツに対して有効。

- 利用者が何か入力する場合には、都度翻訳が必要。
- 外部翻訳ツールを利用するなど、別の対応プロセスが不可欠。

## Dynamic Translation（動的翻訳）
問い合わせチケットの本文や、チャットボックスでの会話、さらにコメント欄など「動的に変わるテキスト」に対応可能。

- グローバル拠点から複数言語の問い合わせが来ても、各担当者は自分が慣れた言語で対応できる。
- リアルタイムで翻訳されるため、タイムリーなコミュニケーションが可能。

# 導入・運用コスト
## 通常の多言語対応
新言語を追加するたびに翻訳作業が発生し、UIやマニュアル、ナレッジベース、FAQなどの管理コストが増える。

- 一度翻訳してしまえば、画面やドキュメントは高い精度で提供できるメリットがある。
- ただし、問い合わせ対応など**ユーザーが自由に入力するテキスト**には都度人的リソースが必要になりがち。
## Dynamic Translation（動的翻訳）
自動翻訳サービスとの連携利用がメインになるため、翻訳エンジンの使用量に応じたコストモデルが多い。

- 言語を追加しても、あらたにすべてのUIやドキュメントを手動翻訳する必要がない。
- システムによる翻訳精度が上がれば、人的翻訳を大幅に削減できる。

# まとめ
## Dynamic Translationならではの強み
- 事前に作り込まれた翻訳ではなく、ユーザーの自由入力を含めた**やり取り**をリアルタイムに翻訳
- 多言語の問い合わせが混在しても、担当者は慣れた言語だけで対応でき、ユーザー側も自国語で返答が受けられる
- グローバル拠点や海外顧客向けサポートにかかる人的翻訳の手間・コストを削減でき、対応スピードを上げられる

「通常の多言語対応」でもUIやドキュメントは問題なく提供できますが、リアルタイムで動的に翻訳することで、問い合わせ応答やチャットサポートなどのコミュニケーション全体をスムーズに多言語化できる点が最大の特徴.

仮に「既に全画面の翻訳が用意されていて、問い合わせ内容ややり取りも常に1～2言語でしか行われない」のであれば、従来型の多言語対応でも十分かもしれません。
しかし、グローバル展開をしており、
**「どこの国からどんな言語で問い合わせが来るか分からない」**
**「問い合わせと返答をリアルタイムに翻訳したい」**
というニーズがある企業にとっては、Dynamic Translationの価値が非常に大きくなります。
手動でバージョン管理して炎上。。実例で学ぶ予防策

# 目次
- [はじめに](#はじめに)
- [背景](#背景)
- [ベンダ開発分のバージョン管理方法](#ベンダ開発分のバージョン管理方法)
- [内製分でデグレード発生](#内製分でデグレード発生)
    - [経緯](##経緯)
    - [原因](##原因)
- [内製分のバージョン管理方法](#内製分のバージョン管理方法)
- [後日談](#後日談)
- [まとめ](#まとめ)

# はじめに
本稿では、バージョン管理が不十分であったためにアプリケーションでデグレードが発生した経験をもとに、トラブルの防止策について述べています。
バージョン管理が不適切であると、会社の信用を失う可能性があり、それ以上に顧客や関係者にご迷惑をおかけしてしまいます。
二度と同じような問題が発生しないよう、ここでは具体的な事例を元に解説し、読者の皆さまの参考になれば幸いです。

※記載内容は、関係者のプライバシー保護のため一部修正を加えています。

# 背景
大手SIerの開発チーム（10名程）にサブリーダーとして着任しました。
以前、PMOアシスタントとして関わった別プロジェクトで、ベンダ開発のアプリがバージョン管理の不備によりデグレードを起こし、炎上する事態を目の当たりにしていました。
そのため、バージョン管理の重要性を痛感しており、着任早々に新任の開発リーダーに相談を持ちかけました。
しかし、リーダーからは「今までデグレードを起こしたことがないから大丈夫」という返答があり、バージョン管理の必要性を認識してもらえませんでした。
当時の開発体制は、内製開発部分は新任リーダーが前任者から引き継ぎ、ベンダ開発部分は私が担当することになりました。
内製開発部分のソースコードは、前任リーダーが忙しさを理由にバージョン管理システムに最新化していなかったため、新任リーダーが改めて最新ソースを整備することになりました。
私自身も、内製開発部分のバージョン管理体制の確立を提案しましたが、「現場に入ってまだ2ヶ月程度で、勝手なことをすると混乱を招く可能性がある」と判断し、今回は見送ることにしました。

# ベンダ開発分のバージョン管理方法
まずは、前例のないベンダ開発部分のバージョン管理体制を構築するため、ベンダ企業に現状のバージョン管理方法についてヒアリングを行いました。
その結果、ベンダ企業では、改修前後のソースコードをテキスト比較し、その結果を納品物に含める形でバージョン管理を行っていることが分かりました。
そこで、ベンダ企業から提出されたテキスト比較結果を元に、自社側でも改修内容をダブルチェックすることで、バージョン管理の精度を高めることにしました。

# 内製分でデグレード発生
## 経緯
そして悪夢は起こりました。
内製開発部分でリリース翌日に、前回リリース時と同様のデグレードが発生したとの連絡を顧客から受けたのです。
この時、私は初めて、前回リリース時にも内製開発部分でデグレードが発生していた事実を知りました。
緊急リリースが翌日に迫る中、チーム総出でデグレードの原因調査と修正作業を行いました。
具体的には、最新ソースの取得、ソースコードのマージ、デグレード発生箇所の特定と修正、修正箇所の重点的なテストなどを、徹夜で行いました。
なんとか翌日のリリース判定会議に間に合い、リリース作業を完了させることができましたが、顧客やエンドユーザーの方々に多大なご迷惑をおかけし、会社への信頼を失墜させてしまう結果となりました。

## 原因
このデグレード発生の原因を、自分なりに分析した結果、以下の３点が挙げられます。

- **原因１：** 前任リーダーが業務の都合上、前回改修時点での最新ソースをバージョン管理ソフトにアップデートしていなかった。
- **原因２：** 最新のソースコードを集める作業を一人の担当者が行なっており、その作業内容が適切に実施されているか、別の担当者がチェックする体制が整っていなかった。
- **原因３：** 受入テストでデグレードが発生していたにも関わらず、顧客側も改修点のみを確認しており、デグレード発生の観点での確認が漏れてしまっていた。

また、直接的な原因ではありませんが、新任リーダーの「今までデグレードを起こしたことがない」という発言について、裏付けを取ることなく鵜呑みにしてしまったことも、今回の事態を招いた一因だと感じています。
もし、前回リリース時にデグレードが発生していた事実を把握できていれば、チーム全体でバージョン管理の重要性を認識し、適切な対策を講じることができたかもしれません。

# 内製分のバージョン管理方法
今回のデグレード発生を受けて、内製開発部分のバージョン管理体制を早急に確立する必要性を痛感しました。
幸い、開発マシンのリリース用フォルダには過去リリース分のソースコードが全て残っており、このデータを元にバージョン管理システムの内容を最新化しました。
さらに、以下の内容を盛り込んだバージョン管理手順書を作成し、有識者や上席のレビューを経て、正式に運用を開始しました。

- 開発前にバージョン管理ソフトから最新ソースを取り出す手順書
- 開発後にバージョン管理ソフトに最新ソースをアップデートする手順書
- 上記2つの手順が適切に行われたかについてのチェックを、内部向けリリース判定資料の項目に含める

また、手順書には作業者と確認者のチェック欄を設け、ダブルチェックを徹底することで、人為的なミスを防止する仕組みを構築しました。
さらに、最新ソースの移動にツールを作成し、作業の効率化とミスの削減を図りました。

# 後日談
これらの対策を講じた結果、次回のリリース時には問題なくリリースを完了することができました。
デグレード発生原因として挙げた原因１と原因２については、上記の内製分のバージョン管理方法によって対策済みでしたが、原因３については、顧客側の管理部から経験豊富な担当者をアサインしてもらい、テスト管理体制を強化していただきました。

# まとめ
今回の経験を通して、バージョン管理の失敗は、広範囲に渡り多大な迷惑をかけることを痛感しました。
また、バージョン管理体制の構築・運用には、多少の工数がかかっても、徹底して取り組む必要があると改めて実感しました。
具体的には、以下の３点を常に意識することが重要です。

- バージョン管理の作業方法は適切に計画され、実施されているか、上位者が定期的にチェックする体制を構築する
- バージョン管理の作業は、作業者と確認者を分けてダブルチェックを行う体制を構築する
- 経験豊富な人の意見であっても、鵜呑みにせず、第三者に確認するなどして、裏付けを取るようにする

これらの教訓を活かし、今一度、自身の開発現場におけるバージョン管理体制を見直し、改善すべき点があれば、早急に取り組みましょう。
バージョン管理の不徹底によるデグレード発生が無くなる事を切に願います。
ABC397の振り返り

Writerてんこ盛り回(sotanishy,MtSaka,sounansya,kyopro_friends,blackyuki)
そしてレート下げええええええええええ
## [A問題](https://atcoder.jp/contests/abc397/tasks/abc397_a)(diff:6) ##
最近ABでペナルティを食らうのが安定してきました。やったね(良くない)
条件分岐すれば行けます。計算量は $O(1)$ です。
ACコード(pypy54ms,c++1ms)
```c++
X = float(input())
if X < 37.5:
  print(3)
elif X < 38.0:
  print(2)
else:
  print(1)
```
AC時間:4:04
## [B問題](https://atcoder.jp/contests/abc397/tasks/abc397_b)(diff:63) ##
深く考えすぎた
今見ているところの偶奇を管理していおいて、もしin/outと違う所があったら答えに1加算&偶奇反転すれば良いです。計算量は $O(|S|)$ です。
ACコード(1ms)
```c++
#include <bits/stdc++.h>
using namespace std;

int main() {
  string S;
  cin >> S;
  int ans = 0, guki = 0;
  for(char s : S) {
    if((s == 'o') != guki) {
      ans++, guki = 1 - guki;
    }
    guki = 1 - guki;
  }
  cout << ans + ((int)S.size() + ans) % 2 << endl;
}
```
AC時間:35:36(…)
## [C問題](https://atcoder.jp/contests/abc397/tasks/abc397_c)(diff:184) ##
Bより問題が分かりやすかった
要素ごとのカウントを持っておいて、それを1つずつ動かして、カウントが1以上の数の和を足したものをchmaxして行けばよいと思います。<code>std::map</code>を使って $O(NlogN)$ 、制約の $1 \le A_i \le N$ から、<code>std::vector</code>を使って $O(N)$ で解くことができます。
カウント関連の問題ではカウントが1以上かそうでないかが切り替わる瞬間に何かをすることが大切です。それを練習できる問題を載せておきます。
[ABC391C](https://atcoder.jp/contests/abc391/tasks/abc391_c)
ACコード(58ms)
```c++
#include <bits/stdc++.h>
using namespace std;

int main() {
  int N, tmp_1 = 0, tmp_2 = 0;
  cin >> N;
  vector<vector<int>> cnt(2, vector<int>(N + 1, 0));
  vector<int> A(N);
  for(int &o : A) {
    cin >> o, cnt[0][o]++;
    if(cnt[0][o] == 1) {
      tmp_1++;
    }
  }
  int ans = 0;
  for(int i = 0; i < N - 1; i++) {
    cnt[0][A[i]]--, cnt[1][A[i]]++;
    if(cnt[0][A[i]] == 0) {
      tmp_1--;
    }
    if(cnt[1][A[i]] == 1) {
      tmp_2++;
    }
    ans = max(ans, tmp_1 + tmp_2);
  }
  cout << ans << endl;
}
```
AC時間:6:01
## [D問題](https://atcoder.jp/contests/abc397/tasks/abc397_d)(diff:1132) ##
方程式を立式することはできましたが、そこからゴチャゴチャしてACできませんでした
## 感想 ##
やばいですね(パフォ459、レート665)
かなり忙しいですが精進頑張ります
DynamoDbの大小検索のやり方が分からずハマった

# はじめに
AWSのサービスで何かある程度無料で使えるものはないか？を探してDynamoDB を発見！

DynamoDB を使ってチャットアプリを作っていたのですが、その際に大小検索のやり方が分からずハマったので残しておきます。

# 環境
Java 21
Spring Boot 3.4.2
spring-cloud-aws-starter-dynamodb 3.2.1

# DynamoDBのテーブルレイアウト
TableName：message
Partition key: channelId 
Sort key: createdAt
※ キー項目以外は省略

# やりたかったこと
channelId指定 かつ createdAtが 1日前以降

# 実現したソース
※ fromDateは前日日付と仮定
```
import com.tarosuke777.hc.entity.Message;

import io.awspring.cloud.dynamodb.DynamoDbTemplate;
import software.amazon.awssdk.enhanced.dynamodb.model.Page;
import software.amazon.awssdk.enhanced.dynamodb.model.PageIterable;
software.amazon.awssdk.enhanced.dynamodb.model.QueryConditional;
import software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest;

～中略～

		QueryConditional keyEqual = QueryConditional
				.sortGreaterThan(b -> b.partitionValue(channelId).sortValue(fromDate));
		QueryEnhancedRequest tableQuery = QueryEnhancedRequest.builder().queryConditional(keyEqual).build();
		PageIterable<Message> pages = dynamoDbTemplate.query(tableQuery, Message.class);
  		Optional<Page<Message>> firstPage = pages.stream().findFirst();


```
アプリの画面にgoogleのマテリアルアイコンを表示させたい

:::note info
インターネットの通信部分で色々うまくいかず悩んでます。
通信エラーになったとき、わかりやすくエラーや画像が壊れいるアイコンを表示させたいなぁと考え、googleのマテリアルアイコンを使おうとなりました。

が、しかしいつものごとく、あれ？どうやるんだ？？？となり:joy:
自分メモ残しておこう💦
:::

### １．「res」フォルダ右クリック→New→VectorAsset
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556392/50f40f0e-11bf-4dc7-bff2-4eefc6f145a8.png)

### ２．アイコンマークをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556392/a6d60017-4dec-4c05-9625-88afdb203798.png)

### ３．いっぱいアイコンが出てくるので、検索窓にそれっぽい単語の一部を入力。
　今回は壊れている画像にしたいので、「broken」などと。
　これ！というアイコンを見つけたらクリックで選択、OKボタンクリック。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556392/1d27da9b-5845-4286-af0c-706bd6d6be23.png)

### ４．名前、サイズ、色、透明度を決めて、Nextボタンをクリック。
　Enable auto mirroring for RTL layoutには、通常チェックは入れない。
 　（チェックを入れると矢印などの向きが左右反転します）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556392/6fa4e0c4-c750-4b92-8a8a-208cd56b83ec.png)

### ５．最後に、データの保存場所を確認してFinish
指定の場所にxmlファイルが作成されます:ok_hand:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556392/ce76dcd5-f151-4678-b1cc-086c3ca264f5.png)

### ６．画面から呼び出す。
```kotlin:MainActivity.kt
@Composable
fun TestScreen(modifier: Modifier=Modifier) {
    Image(
        painter = painterResource(R.drawable.baseline_broken_image_24),  //画像指定
        contentDescription = "エラー画像",
        modifier=modifier
    )
}
```