OmniAICreator/Qiita-1.07M huggingface dataset:
almalinux9でkubernetesのコントロールプレーンを構築しようとするが挫折する話

なんかdockerは使いたくないし、RHELの開発サブスクでopenshiftなんちゃらを構築するのも何か嫌だし

というなんだろう直感？でdockerは使わずにcontainerdを使うOSはredhatクローンalmalinuxで構築しようという方針で進めたら挫折したという内容となります。

(1) kubernets公式のドキュメントはいけてない

まず初めになにをどう構成すれば良いのか書いてないし、記載どおりの手順で構築してもまともに動かない、まぁ有料なマネージトなk8sサービスが色々あるし、それを使えという雑さがあるよね。
言い方を変えるとkubanetesは、containerdなりCNIなりを入れろって言うけど導入とか設定までもそれらに投げっ放しでkubanetesでどう設定すれば良いのか記載がない！


(2) 日本語版の罠

https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

さらに日本語版では既に構築できない手順で、、
日本語版にしたがってCentOS7入れてもyumリポジトリがディレクトリだけあって中身空なんだよね
まぁ英語版を日本語翻訳して読めば正解に近いのかな？


(3) 英語版の手順で構築してもまともに動作しない

https://kubernetes.io/docs/setup/production-environment/container-runtimes/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606569/b81e1d5f-ab57-5332-eea7-674092900edc.png)

その中のクラスタ導入後orCNI導入後かクラッシュループするときはcontainerdのデフォルト設定に余分なものがあるから調べてね的な記載はあるけど具体的にエラーになる要因を書いてないし、構築させる気はゼロだな

containerdの正しいconfigも分からないし
クラッシュループしているpodたちはネットワークがちゃんとしていない、CNIの初期設定ができていっていうけどCNIの初期設定手順ないしkubernetesのドキュメントがイケテナイところ


(4) じゃしょうがないubuntuで立てるか

kubernetsのcontainerdの導入から下のページに飛んで

https://github.com/containerd/containerd/blob/main/docs/getting-started.md

の option2から ubuntu を選ぶと

https://docs.docker.com/engine/install/ubuntu/

dockerのページに飛ばされる、、終わった。なんでcontainerdのページからdockerのサイトに飛ぶんだよ


妥協してdockerのリポジトリから構築するか、RHELのリポジトリから構築するか

kubeadm initの引数にCNI的なオプションをつければk8sがCNIの定義起こしてcontainerdの定義読み込みしてくれるかなと思ったんだけど、んー

ということでdockerリポジトリから構築するネタはたくさんあると思うので以降は割愛
【JavaScript・初学者】コンポーネントの基礎となるDefault import/exportの基本的な使い方

# はじめに
前回の記事で、`モジュール化`するこによって**名前空間を狭くすることができ衝突を防ぐ**という話をしました。
今回は、その`モジュール`をファイル分割によって読み込む`import/export`について考えていきます。

https://qiita.com/ke_sukesakuma/items/29efb9beeaa4ab38e142



# import/exportの種類
`import/export`の方法にはいくつか種類があります。
大きく、`default import/export`と`named import/export`の2種類です。
今回は`default import/export`について見ていきます。

# default import / export

まず、事前準備として`scriptタグ`に`type="module"`を設定して、モジュールとして扱えるように設定します。

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>app</title>
  </head>
  <body>
    <script src="index.js" type="module"></script>
  </body>
</html>
```
次に同じ階層に`index.js`と`default.js`を作成します。`default.js`にまず`export`できるようにコードを書いていきます。

`greet変数`を定義して、それを別ファイルで使えるように`export(出力/書き出し)`をしています。

```javascript:default.js
// default export
const greet = "hello";
export default greet;
```
そして、`index.js`で`dafault.js`で`export`された変数を`import(輸入する/取り込む)`します。
そうすると`default.js`で定義された`greet変数`を使うことができます。

```javascript:index.js
// default import
import greet from './default.js';
console.log(greet);
```

![スクリーンショット 2023-11-11 9.12.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517817/bdb5087a-98ef-be81-5996-14a8300f72a7.png)

変数以外にも**関数**も渡すことができます。

```javascript:default.js
// default export
const greet = () => {
  return "これは関数です";
}
export default greet;
```

```javascript:index.js
// default import
import greet from './default.js';
console.log(greet());
```

![スクリーンショット 2023-11-11 9.22.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517817/fcf63db8-efe8-d724-1fdc-d15ca79cee3d.png)

これが基本的な使い方です。

# default import / export の特徴
基本的な使い方を理解できたところで特徴について見ていきます。

### 1モジュールにつき1度しか定義できない。
**1モジュール(ファイル)につき一度しか定義できません。** そのため、この使い方は`A module cannot have multiple default exports.`エラーが出てしまいます。

```javascript:default.js
// default export
const greet = () => {
  return "これは関数です";
}
export default greet;

const hoge = "hoge";

export default hoge;
```

### importの方法
importする際には、`{}`ではなく**そのまま指定する**必要があります。
```javascript:index.js
import greet from "./default.js";
```

# default import / exportの内部的な仕組み
実際には**変数や関数が渡されているのではなく、評価された値**が入っています。
そのため、直接値を渡していることと同じ動きになっています。

```javascript:default.js
// default export
const greet = "hello";
export default greet;
```

```javascript:default.js
// default export
export default "hello";
```

```javascript:index.js
// default import
import greet from './default.js';
console.log(greet);
```
![スクリーンショット 2023-11-11 9.36.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517817/baf6de57-6cf5-7ac0-f089-78276d8d7028.png)
AI Code Review Actionを使ってコードレビューを自動化する

## はじめに

個人開発ではコードレビューも自分でやらなければならず、~~さぼり~~後回しにしがちです。
今時ChatGPTがあり、GitHubActionsもあるのでレビューはおまかせできるのでは！？と思いやってみました。

[ChatGPT CodeReviewer](https://github.com/marketplace/actions/chatgpt-codereviewer)もありますが、今回はこちらを利用しました。
https://github.com/marketplace/actions/ai-code-review-action
![スクリーンショット 2023-11-11 8.59.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618958/d7939bf7-fd8e-8898-cfab-a1fb1d4a82bb.png)

## 結果

さっそくですがPull Requestを作るとこうなります。Actionsが動き始め...
![スクリーンショット 2023-11-11 8.33.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618958/14111190-4616-d07b-71ac-36295b395fbe.png)

PRに結果がコメントされます。ハードコードしてるから定数化してねと言われてます。PRの大きさにもよると思いますが、これ以外も10個程度コメントしてくれました。
![スクリーンショット 2023-11-11 8.36.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618958/bc78f0d7-7cfd-719a-6339-febb6cb5bb9d.png)

## 手順

基本は[AI Code Review ActionのSetup](https://github.com/marketplace/actions/ai-code-review-action#setup)に書いてある通りです。

#### 1. OpenAI の API Keyを発行する

以下で`Create new secret key`を選択してAPI Keyを発行します。
https://platform.openai.com/api-keys


#### 2. OpenAI APIの支払い設定

以下で支払い設定します。初回最低5ドルの支払いが必要です。
https://platform.openai.com/account/billing/overview

#### 3. OpenAI APIの課金上限を設定

最後に以下で使いすぎや不正利用防止で上限を決めましょう。
https://platform.openai.com/account/limits

お試しのため上限3ドルで、1ドル使った時点でメールが来るようにしました。

#### 4. GitHubリポジトリにOpenAI API keyを設定する

リポジトリのSettings > secrets and variables > Actionsで`New repository secret`を押して`1`のAPI keyを`OPENAI_API_KEY`という名称で設定します。

![スクリーンショット 2023-11-11 9.14.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618958/7cc336cf-dff0-de4c-cc39-c32759c47cb7.png)

#### 5. Actionsを設定

以下をリポジトリの`.github/workflows/main.yml`に配置します。

```yml
name: AI Code Reviewer

on:
  pull_request:
    types:
      - opened
      - synchronize
permissions: write-all
jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v3

      - name: AI Code Reviewer
        uses: freeedcom/ai-codereviewer@main
        with:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
          OPENAI_API_MODEL: "gpt-4" # Optional: defaults to "gpt-4"
          exclude: "**/*.json, **/*.md" # Optional: exclude patterns separated by commas
```

以上で設定は完了です。
※MODELは`gpt-3.5-turbo`も使えます。

#### 6. 動かす

上記設定が完了していれば、Pull Requestを作るか、Pull Requestを作っているブランチにコミットするだけです。結果に書いた通りレビュー結果をコメントしてくれるようになります。

## 料金

https://openai.com/pricing には以下が書いてあるのですが、単位がtokenなのでわかりづらいです。
`gpt-4	$0.03 / 1K tokens	$0.06 / 1K tokens`

今回やった結果は3回PR作成と5回程度のコミットでしたが0.33ドルになってました。
今のレートで`50円`ですね。gpt-4なのもありますが結構かかります。

![スクリーンショット 2023-11-11 9.25.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618958/01f4635c-cadf-6208-57cd-2484c0492340.png)

正直これだと個人開発で継続的に使うのは厳しいので、常時ではなく利用を絞る必要があります。

## 苦労したところ

GPT plusになっていればOpenAIのAPIは使えると勘違いしており、APIは別で課金していないと使えないことを理解しておらず、Actionsが404エラーになって具体的なエラー内容もなかったため原因がわかりませんでした。色々検索していたら従量課金であることがわかり課金したらすんなり動きました。
VSCode ワークスペースのトップフォルダ名の改善方法

# ワークスペース（エクスプローラー）に複数フォルダを登録した場合の名称変更方法

### 似た名前のフォルダがあり、見た目や内容で区別がつきにくいため、これらのフォルダの名称を変更したい。

ワークスペースには .code-workspace という設定ファイルがあります。このファイル内でフォルダーの表示名を変更できますが、これはあくまでVSCode上での表示名であり、実際のファイルシステムには影響を与えません。ワークスペースファイルを開き、folders プロパティの下にある各フォルダーの name プロパティを変更してみてください。

```json:hoge.code-workspqce
"folders": [
   {
      "path": "path/to/folder",
      "name": "新しい名前"
   },
   // 他のフォルダー...
]
```

VSCodeを再起動すれば、git関連にも反映されます。
Redis® 7が登場

<font color="Grey">*[Redis® 7 is here](https://aiven.io/blog/redis-7-is-here)の翻訳です。*</font>

2022年9月7日

# Redis® 7が登場

史上最高のRedis® - バージョン7.0 - がAivenプラットフォームで利用可能になりました。

Redis® 7.0は、人気のオープンソースデータベースのほぼすべての側面に改善を導入しています。最も注目すべき新機能の一部をご紹介します：


* Redis Functionsによるスクリプティングの強化
* ACLv2によるアクセス・コントロール管理の向上
* 約50の新しいコマンドの追加


同時に、Redisを以前よりもさらに高性能で安定したものにするために、多くの努力が払われています。


**Redis Functions**は、Redisにおけるスクリプティングのための新しいソリューションをもたらし、ユーザがカスタム関数ライブラリをRedisにロードすることを可能にします。スクリプトの管理をアプリケーションに任せていた以前のEVAlコマンドを使用したエフェメラル・スクリプトとは異なり、Redisは現在、関数をデータベースの不可欠な部分として管理し、データの永続性とレプリケーションによってその可用性を保証しています。


**ACLv2**は、以前のバージョンとの互換性を維持しつつ、アクセス制御リストに2つの重要な新機能を追加した：


* ACLv2は、独立して評価される複数のACLルール（セレクタと呼ばれる）をサポートする。
ACLv2 は、独立して評価されるセレクタと呼ばれる複数の ACL ルールのセットをサポートする。 * ACLv2 は、特定のキーにアクセスタイプのパーミッションを設定することを可能にし、 ユーザーがキーのサブセットに対して読み取り専用、書き込み専用、または読み取り/書き込み 操作を行うことを排他的に制限することを可能にする。


ACLv2はAiven for Redis®ではまだ利用できませんが、現在取り組んでおり、近日中に機能をリリースする予定です。


Redisバージョン7.0では、Redisの進化をサポートし、既存の機能を拡張するために、ほぼ**50の新しいコマンド**とオプションが追加されました。また、例えば以下のデータ型はすべて、データ管理のユースケースをサポートする機能が追加されています：


* ビットマップ
* リスト
* セット
* 並べ替えセット
* ストリーム


### Aiven for Redis® 7の使い方


すでにAiven for Redisをご利用の場合は、必要に応じてアップグレードすることができます。そうでない場合は、現在のプランを変更した場合や、障害時にノードを交換した場合など、特定の場合にサービスがアップグレードされます。


まだAiven for Redisをお使いでない方は、ぜひお試しください！RedisについてはRedis入門をお読みいただくか、[Redisページ](https://aiven.io/redis)をご覧ください。
Pythonで「文字列の中の文字が数を表す文字かどうかを判定する(isdecimal, isdigit, isnumeric)」の動作を確認してみた

# 概要

Pythonで「文字列の中の文字が数を表す文字かどうかを判定する(isdecimal, isdigit, isnumeric)」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/python/string/index14.html

# 実装

ファイルを作成しました。
```sample.py
print("75120".isdecimal())
print("75F2".isdecimal())
print("０９８２".isdecimal())
print("７５ａ０".isdecimal())
print("-8052".isdecimal())
print("3.14".isdecimal())
print("7,524".isdecimal())
print("七五三".isdecimal())
print("".isdecimal())

print("85120".isdigit())
print("75F2".isdigit())
print("-8052".isdigit())
print("3.14".isdigit())
print("7,524".isdigit())
print("３７８５".isdigit())
print("４ｐ９０".isdigit())
print("七五三".isdigit())

print("⑤⑥⑦".isdecimal())
print("⑤⑥⑦".isdigit())
print("".isdigit())

print("9852".isnumeric())
print("87E2".isnumeric())
print("-8052".isnumeric())
print("3.14".isnumeric())
print("7,524".isnumeric())
print("３７８５".isnumeric())
print("七五三".isnumeric())
print("拾伍".isnumeric())
print("".isnumeric())
```

以下のコマンドを実行しました。
```
$ python3 sample.py
True
False
True
False
False
False
False
False
False
True
False
False
False
False
True
False
False
False
True
False
True
False
False
False
False
True
True
True
False
```

# まとめ

何かの役に立てばと。
Trello ネタ帳

この記事は [一分で読める小ネタのカレンダー | Advent Calendar 2023 - Qiita](https://qiita.com/advent-calendar/2023/raki) の３日目

# Trello の使い方を集めようぜ（できればフリーで

- [Trello](https://trello.com/) の便利な使い方を紹介していこう的な
- サービスの概要とかは他所で
- そこ、今更とか言わないのｗ

# 正直なところ

- カンバンやるなら backlog や github projects など、エンジニアの業務に向いてるツールは他にもいいのがあるよね
- Trello のいいところは一人でリスト作ったり分類したりをD&Dでぱぱっとできるところだと思ってる

# 例えばこんな使い方

## 画像コレクション

- ネットで拾ってきた覚えておくと良さそうな画像とかをカバーとして使うと眺めるだけで復習できちゃう
- 作ってないけど、SNSでよく使う煽り画像とか集めておくと楽かもしれないね（今思いついた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44420/d7707e6e-69cb-4e1c-6ea2-e5b53479719c.png)

## GTD

- 最近は Trello でやってないけど GTD はいいよね
- 昨日の記事を読んでくれていたら my-til リポジトリで projects と issue で同じことができるけど

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44420/3eded399-13ca-cb6c-13e2-cbe7c2d9138a.png)


## やりたいこと1000

- ゾン100はね、世界が終わるかもしれない世界観の中なので100個も出せばいいだろうけど
- 人生をよりよくするためにやりたいことをたくさん考えるのいいことだよ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44420/ab8073a5-4380-4207-ae4f-b9d887f173d8.png)


## 覚えておくリスト

- ビジネス書とかの使えそうなリストとか、あとでやってみよう的なものをリストにして残しておく
- 大変！よく助けてくれた人10人が4人しか入ってないのバレる！ｗ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44420/2df7b7b3-dc88-779f-e312-512f66e3a2e8.png)


## ビジネスフレームワークの風呂敷

- 画面はオズボーンのチェックリスト。これは眺めてるだけで思考を振り回すことができる
- 水平思考の６つの帽子とか、デリゲーションポーカーとか、テンプレートの例にあるやつも


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44420/91cd5399-d7be-f036-083f-92ff3eb14962.png)

## ジョエルテスト

- 前に書いた [エンジニアのためのオレオレジョエルテストシート #エンジニア - Qiita](https://qiita.com/raki/items/ff8cee8972978375cc2a) を見やすくしたもの
- ちょっとずつ検討範囲を増やしたりしてる。そう今だとチームのリポジトリの git log が気になるｗ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44420/e1f51e6d-72e0-aa3a-7505-f7da29811149.png)


# 改善依頼

- こんな使い方してるぜ、とか画像付きでください！
- ほとんど静的なリストツールとして使っているので、こんなパワーアップス使ってるぜとかぜひ。
Dockerのマルチステージビルド

### なぜマルチステージビルド？
AWS学習中、DockerをECRやECSにデプロイする機会があるが、Dockerのイメージサイズを小さくすることで、
* ECRのようなレジストリへの保管費用を削減
* pull時の通信費用を抑えることができる
* ローカルのストレージの圧迫を抑える

などマルチステージビルドの利点が大きかったのでそこで学んだことを公開します。

### マルチステージビルドとは？
マルチステージビルドとは「複数のステージを用いたビルド」となります。

マルチステージビルドの利点とは、通常 Docker イメージには、アプリケーションおよび実行に必要なものの他に、イメージのビルドに関わるライブラリ等も含まれています。しかし、本番環境では アプリケーションおよびその実行に必要なもののみ をビルドしたいですよね。
そこで複数のステージを用いると、この悩みが解消されます。

ここで、ステージを二つ用意するとします。
一つ目のステージでは、アプリケーションのビルドを行い Docker イメージを作成します。
二つ目のステージでは、一つ目のステージで作成したイメージの中から必要なものだけをコピーしてきます。

このようにステージを二つ用意することで、最終的な Docker イメージには必要なものだけが含まれるようになるのです。
その結果、イメージサイズが小さくなり、本番環境の運用のパフォーマンスが向上します。

https://zenn.dev/farstep/articles/a7819ec705dcc0

### 具体的な記述

#### Before
```Dockerfile
FROM golang:1.17.1

WORKDIR /go/src/api/
COPY ./ /go/src/app

RUN apt-get update && apt-get install -y vim

RUN go get github.com/rubenv/sql-migrate/... && \
    go get github.com/pilu/fresh

CMD go run main.go
EXPOSE 8080
```

#### After
```Dockerfile
// 中間イメージに当たる
FROM golang:1.17.1-alpine as builder

RUN apk add --update --no-cache ca-certificates git && \
    apk add vim && \
    apk add --no-cache gcc && \
    apk add --no-cache musl-dev

WORKDIR /go/src/api/
COPY ./ /go/src/api

RUN go install github.com/pilu/fresh && \
    go install github.com/rubenv/sql-migrate/...

// バイナリファイルを作成する　（これが`as dev`にコピーされることでイメージサイズを小さくすることができる）
RUN GOOS=linux \
    GOARCH=amd64 \
    go build -a -installsuffix cgo -o main main.go

FROM alpine as dev
WORKDIR /go/src/api/
// ここでbuilder(中間イメージ)からバイナリファイルをCOPYする
COPY --from=builder /go/src/api/main /go/src/api/main
CMD [ "/go/src/app/main" ]
EXPOSE 8080
```
my-til リポジトリのすゝめ


この記事は [一分で読める小ネタのカレンダー | Advent Calendar 2023 - Qiita](https://qiita.com/advent-calendar/2023/raki) の２日目

# til とは

- TIL (Today I learned) とは、今日学んだことくらいの意味
- パブリックで til リポジトリを作るのが 2015 年前後頃に流行ったのじゃ（突然の老人会

# で？

- パブリックにコード書くことができるのはとてもすごいこと
- けどまぁ、凡人には真似できないし、書くこともそんなにないし、人に見られるのも恥ずかしい、と思ってる
- そんな同志に、プライベートで my-til リポジトリを作ることを薦める、という記事
- 個人的にプライベートリポジトリの命名規則として my- プレフィックスをつけているだけで til でもいいと思うよ


本文はここまで。github に my-til って名前のプライベートリポジトリ作りなよって話。
以下は時間外ｗ

# 何を書くのよ

なんでもいいと思うけども。

- 日記。マークダウンで日記を書く。新しい習慣付け
- コマンド類。エンジニアなら毎日何かしらコマンド叩くだろうし、学びや改善をメモする
- ちょっとしたプログラム。個人的には主にbash。他の言語は専用の別リポジトリを作る

# なんで書くのよ

理由なんてなんでもいいけども。

- エンジニア（プログラマ）の三大美徳を実践する。怠惰だから繰り返しを避けるし手抜きできるように工夫をするし、短気だから性能にこだわるしそれは普段の自分の処理能力にも言えるし、傲慢だから知らないことをなくしたいし手もつけてないなんてことがないようにしたい
- そのために常に手元で my-til を開いておいて、いつでも使えるようにしておくと便利
- 1.01 の法則ってのがあって、毎日少しずつでもやれ的な（詳しくはWEBで）
- 何もしないで気がついたら時間だけが過ぎてた、みたいな時に、少なくてもこれだけはやってきたからな、って自分に言えるものを残したい。みたいな（老人会の語り）

# いつ書くのよ

好きな時に書けばいいけど。

- 日記に関しては１日の終わりに書くことにしている。１日１コミット
- もちろんいつでもaddしていいし、ブランチ切ってもいいし、切らなくてもいいし、他の内容のコミットと混ざらないように、ログを汚さないように、git を工夫して使えるように練習してる
- コマンド類に関しては一連の流れでコミットするでいい。単発ならそれでも。コミットタイトルを丁寧に書く練習をしてる
- プログラムに関しては普段の業務に準じて書けばいい。できれば業務とは違うことのほうが楽しい。業務時間外に業務とは別のプログラムを書いたりエンジニアリングを楽しむことができる仲間が増えるとうれしい

# どんなこと書くのよ

プライベートだから何を書いてもいいけど。

- 日記は、業務日報だったり、四（とか１とか３とかある）行日記とかバレットジャーナルとか、振り返りに備えてKPTとかYWTとか、仕事,家族,健康,お金,人間関係,趣味,学び,社会貢献、みたいな分類をしておくといいかも
- あと、感謝とほめ日記、だったかな
- 個人的には１日１つ感謝の言葉を書くのおすすめ（この記事を読んでくれて感謝！！ｗ
- クレデンシャルには気をつけて
- ネガティブなことは書かない、と決めておくといいかも
- コマンド類、aws cli とか curl とか、オプションがたくさんあったり複雑だったりするやつを、ChatGPT に聞いて、試して、記録を残しておく、みたいな流れを作るといいかも

# 何になるのよ

自己成長？したつもりの自己満足？やらないよりはいいよ？

- 日記を付け始めたら、先のとおり、書くことを増やすから始まって、テンプレート化、ファイル分割、ディレクトリ構造、内容を分類する方法、振り返り用に再整理、みたいに考え方を進化させていく癖がつけられる
- もちろん日記自体の効果はそれぞれによる
- マークダウンを使い始めたら、きれいに見えるようにプレビューを使うし、ちゃんと見えるように lint をするし、git なんだから pre-commit 等を使うとか、いろいろ整備できる
- いろいろ書いてそれを git で管理するだけで、git の使い方を覚えたり、コマンドを深掘りしたりするようになる
- 要は my-til リポジトリを起点に、いろいろ追加してやっていく、1.01 を積み上げていく、という結果が残る
- 惰性になったと思ったら、そこが改善の起点なので、何を変えれば惰性でなくなるのか、を考えるの大事

# まとめ

- my-til プライベートリポジトリを作って日記をつける
- マークダウンとその周囲を理解する
- git を使いこなす工夫をする
- やってることを改善するための思考と工夫を継続する

みたいなことをおすすめするぜって話でした。

# おまけ

- テンプレートエンジンを使って日記のテンプレートを作っておくと楽
- 日記は daily より til ディレクトリがよさげ（目的を見失わないから）
- 日毎のファイル管理から、月次のファイル管理、年ディレクトリの作成、みたいに継続と共に変えたくなると思うので、gitをうまいこと使うチャンス
- notes ってディレクトリをコマンド類のノートを置くところにすると、node 使ってる時に node_modules ディレクトリと被って邪魔なので、大人しく docs ディレクトリにするのがよさげ

# 改善依頼

- こういうの書いたらいいよとか
- こんなツールがあるよとか

# 余談

いや、この話を就職活動中の娘（現役JD）と、現職の同僚氏らに話したわけよ。
ぶっちゃけあんまりピンと来てないってゆうか、実際やらないとわからないかもだし、やってもわかんないかもなんだけれども。
どうしたらそんなにいろいろできるの？って稀に聞かれるからこういうのの積み重ねなんだよって話をすると、みんな嫌がるんだよなぁ。。。ｗｗ
MySQLをアップデートしたらlibmysqlclient.so.20: cannot open shared object file

# 概要
MySQLクライアントを5.7系から、8.0系にアップデートしたところ、Railsが以下のようなエラーが発生して起動しなくなった。
```
libmysqlclient.so.20: cannot open shared object file: No such file or directory - /dir/shared/bundle/ruby/2.7.0/gems/mysql2-0.5.5/lib/mysql2/mysql2.so (LoadError)
```

# 環境
Amazon Linux 2
Ruby 2.7
Ruby On Rails 6.1.3.1
MySQL (gem mysql2 使用)
MySQL クライアントライブラリは yum で管理

# 以下の場所に libmysqlclient.so.20 が無い
```
$ ls -l /usr/lib64/mysql/
合計 20304
-rw-r--r-- 1 root root 9668352 10月 13 00:33 libmysqlclient.a
lrwxrwxrwx 1 root root      20 10月 25 09:45 libmysqlclient.so -> libmysqlclient.so.21
lrwxrwxrwx 1 root root      24 10月 25 09:45 libmysqlclient.so.18 -> libmysqlclient.so.18.1.0
-rwxr-xr-x 1 root root 3546456 10月 13 00:33 libmysqlclient.so.18.1.0
lrwxrwxrwx 1 root root      25 10月 25 09:45 libmysqlclient.so.21 -> libmysqlclient.so.21.2.35
-rwxr-xr-x 1 root root 7545032 10月 13 00:33 libmysqlclient.so.21.2.35
lrwxrwxrwx 1 root root      20 10月 25 09:45 libmysqlclient_r.so.18 -> libmysqlclient.so.18
lrwxrwxrwx 1 root root      24 10月 25 09:45 libmysqlclient_r.so.18.1.0 -> libmysqlclient.so.18.1.0
-rw-r--r-- 1 root root   23046 10月 13 00:33 libmysqlservices.a
drwxr-xr-x 2 root root     125 10月 25 09:45 plugin

```

# MySQL クライアントバージョン
```
$ yum list mysql-community-client.x86_64
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
293 packages excluded due to repository priority protections
Installed Packages
mysql-community-client.x86_64    8.0.35-1.el7   @mysql80-community
```

# 対応
```
rm /dir/shared/bundle/ruby/2.7.0/specifications/mysql2-0.5.5.gemspec

cd /dir/current/
bundle install

↓の mysql2.so のバイナリが再生成される
/dir/shared/bundle/ruby/2.7.0/gems/mysql2-0.5.5/lib/mysql2/mysql2.so
```

# 原因
mysql2 gem を bundle install した際に生成される mysql2.so は、その時入っている MySQL クライアントのバイナリファイルのパス(libmysqlclient)を参照しているようで、MySQL クライアントをアップデートしたことによって、それまで参照していたバイナリファイルの名前が変わってしまい参照できなくなった。
一度gemspecファイルを消してbundle installし直すことで、その時のMySQL クライアントのバイナリファイルを参照するmysql.soファイルが生成され、直った。

# 参考
https://github.com/brianmario/mysql2/issues/1141
Gizmos.DrawGUITextureの挙動がややこしい

# 最初に
**Gizmos.DrawGUITexture**を使ったが挙動に癖があった。
Gizmosの中で唯一TextureをSceneView上に貼り付けられるが、**使用できる用途が限られている**ように感じた。

結論からいうと、**SceneView上でUI要素に対して使うのが主な用途**だと思う。
それ以外はかなり難しそう。

こちらで確認した動作をここにまとめておく。
動作の確認は **Unity 2021.3.19f1** で行った。

# screenRect引数は整数値
関数の引数にscreenRectという**Rect型の引数**があるが、
実際には座標や幅、高さが**int型**に直されて使われる。

このため最小サイズが決まっている。

# ScreenSpaceに表示される
ScreenSpaceとはUIが表示される場所のこと。
具体的にはCanvasを新規作成したときに表示される場所。
(普通のゲームオブジェクトに対してやたらデカく表示されるやつ)

なので、基本的な使い道は**SceneViewでUI要素に対して**使うこと。

# GameView上で見た時の挙動が不思議
ちなみにGizmoはGameView上でも表示できる。
Gizmos.DrawGUITextureで貼り付けたTextureもGameView上で表示できる。

しかしScreenSpace-Overlayのようにカメラ上に勝手に表示されない。
わざわざ**カメラで撮影しに行く必要がある**

設定するときの座標はScreenSpaceに準拠しているが、実際にはWorld空間にいる扱いのようだ。
(ScreenSpace-Overlayのように扱えれば、もっと使い道があるのに……)

----
挙動について補足があればコメントよろしくお願いします。
DevcontaierからQiita CLIを動かす

# Qiita CLI 
2023/8/23にQiita BlogからQiita CLIの正式版の公開が発表されました。
詳しい内容については、以下のURLから確認してください。

https://blog.qiita.com/release-qiita-cli-general/



# Qiita CLI を Devconianerから起動する
## きっかけ
Qiita CLIを使用するにあたり、私自身ローカル環境をあまり汚さずに使用したいと考えました。
以下Githubリポジトリにアップしているので、良ければ利用してみてください。


https://github.com/rfukudome/qiita_cli_devcontainer



## 利用前の準備
Devcontainer利用にあたり、事前に準備が必要になります。

### dockerのインストール
dockerのインストールが必要です。
以下の公式サイトの手順を参考インストールしてみてください。


https://docs.docker.com/engine/install/


### Vistual Studio Code のインストールと拡張機能追加
また、Vistual Studio Code のインストールと、拡張機能の Dev Containers のインストールが必要になります。


https://code.visualstudio.com/download



Vistual Studio Code の拡張機能からRemote Development をインストールすると一緒に Dev Containers がインストールされます
![スクリーンショット 2023-11-11 015027.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646964/937d1023-0b5c-c1e0-ef52-9eb543fb6d7e.png)


### Gitのインストール
公式サイトからGitをインストールが必要になります。

https://git-scm.com/book/ja/v2/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-Git%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB



## 利用方法
### リポジトリをクローンする
Vistual Studio Code から任意のフォルダを開き、以下コマンドにてリポジトリをクローンしてください。

```shell
git clone https://github.com/rfukudome/qiita_cli_devcontainer.git
```

### Devcontainer起動
クローンしたリポジトリをVistual Studio Code から開きます。
`qiita_cli_devcontainer/.devcontainer/postCreateCommand.sh`にある`$ACCESS_TOKEN`へQiitaのアクセストークンを記載します。

![スクリーンショット 2023-11-11 020329.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646964/a0dbc98d-8cc6-3dc5-3499-8020b51a1023.png)

※Qiitaのアクセストークン作成は以下の記事を参考にしてください。


https://qiita.com/maiamea/items/680cca06f7825595cba0


アクセストークン記載後、「Ctl」+ 「Shift」+「P」をクリックして、「開発コンテナー:コンテナーで再度開く」を選択してください。
選択後、コンテナのビルドが始まります。
以下が表示されればOKです。


![スクリーンショット 2023-11-11 021900.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646964/fcd921be-e192-aee9-40f1-c5081f82cd32.png)

### Qiita Preview へアクセス
ブラウザを立ち上げて以下のURLへアクセスしてください。
```
http://localhost:8888/
```
以下が表示されると思います。
あとは、Qiita Previewの内容をもとに記事を作成していけばOKです！
![スクリーンショット 2023-11-11 022306.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646964/e83d79c6-86ed-729f-1996-e14b3534802b.png)
GPT-Builderで構造式の画像からSMILES式を出力してみる

## 目的
Materials Informaticsではデータの収集が大事だが、自社の資料や特許などPDF中の構造式の画像からSMILES式に変換してまとめるのは大変に手間がかかる。
先日発表されたChatGPTのGPT-Builder機能を使って、構造式の画像をアップロードするとSMILES式を回答するbotを作成して回答精度を検証する。

## 準備
試薬サイトから、適当に構造式をスクショで撮った。

## 結果
### 一回戦
ターゲット①：メジャーかつシンプルな構造である、Bisphenol A
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475723/b300d255-b522-4da0-9f1d-e15ff64de63e.png)
凄い！
クリアかと思いきや、SMILES式を描画すると正しくなかった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475723/4a507642-cc7d-9d65-70f2-41992937b86a.png)

ターゲット②：今日のおすすめの構造
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475723/8e07a560-0e41-9cf9-f632-cd64e9145231.png)
またしても名称は分かっているようだ。
構造式は気持ちはわかるが、Nの数も違うし、正しくない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475723/0da8b92c-8839-5e56-5239-d7363297fa3f.png)

### 二回戦
2つの構造とも名前は正解したが、構造は正しくなかった。ファイル名につけた化合物名をカンニングしているだけの可能性があるため、ファイル名はtest_1.png、test_2.pngとしてみた。
ターゲット①：シンプルな構造(Bisphenol A)
ファイル名をマスクしても構造を読み取れた。凄い！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475723/5bdb8920-a40c-99d9-9e0c-609b862b872b.png)

SMILES式は間違っており先ほどと同じ構造。拘りがある模様。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475723/08e43a13-5b24-7189-133e-cce8eab3af38.png)

ターゲット②：少し複雑(Hexahydro-1H,4H,7H-3a,6a,9a-triazaphenalene)
名称は正しい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475723/083ddc8e-bc6d-8c21-838d-5a36b32f8584.png)
SMILES式は先ほどと同じで不正解。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475723/91077403-bdb7-f9f0-4baa-8f8a992adedd.png)
ターゲット③：光学異性体(L-Azidohomoalanine)
またしても、名称と構造は正解！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475723/58d48c4f-f156-7728-0864-8a332711e58b.png)
SMILES式は不正解だった。アジドまで理解していたのに惜しい。立体構造は読み取れなかった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475723/5d68675e-35f5-427a-cde9-2b0ed6976ea0.png)
ターゲット④：糖類(n-Dodecyl-β-D-maltoside)
正しくなかった。直鎖の構造に着目した模様。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475723/0ff5c31e-9a12-eb65-15da-212ad53e34ab.png)
SMILES式も正しくなかったが、含酸素構造は認識している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475723/44d2f683-79fe-d86f-f21a-ea2b0467ff47.png)

## まとめ
GPT-4Vでも構造式からSMILES式の出力はできなかった。
とはいえ、化合物自体は比較的認識できているので、PubchemのAPIと組み合わせて名称からSMILES式の出力はできそう。
ちなみに、深層学習による構造式変換ライブラリの[DECIMER](https://github.com/Kohulan/DECIMER-Image_Transformer#decimer-image-transformer-deep-learning-for-chemical-image-recognition-using-efficient-net-v2--transformer)では、①～③について正確にSMILES式を出力できたので、また次回に。
GPT-4 with Vision（GPT-4V）のAPIを使ってみる

2023年11月6日のOpenAI DevDaysにおいてOpenAIの新しい発表があった。どれも面白い。どれも使うのが簡単だが、Assistant APIとGPT-4 with VisionのAPIだけ少し複雑だ。

https://openai.com/blog/new-models-and-developer-products-announced-at-devday

ここではGPT-4 with Visionをpythonスクリプトから叩くサンプルコードをおいておく。OpenAIの公式にはpythonでローカルファイルをアップロードする方法がpython完結するものが書いてなかった。

# GPT-4 with Vision
ローカルに置いた画像ファイルはBase64形式でエンコードしてURLに入れ込むとそれでアップロードされる。

ちなみに、OpenAIによるとファイル形式はPNG (.png)、JPEG (.jpeg および .jpg)、WEBP (.webp)、および非アニメーション GIF (.gif)対応。サイズ制限は20MB。アップロードした画像は自動的に学習には使われず自動的に削除されるとのこと。

例えば、画像処理で有名なLennaさんの画像ファイルを同じフォルダでLenna.pngと置いておいて以下のスクリプトでGPT4から返答が来る。
実運用にはエラー処理など必要だが、ここでは最小限のコードにしている。

![Lenna.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40132/b865d479-a825-f6fd-ab43-4ee1c8e63b6e.png)



```python
import base64
from pathlib import Path
from openai import OpenAI
from dotenv import load_dotenv

load_dotenv()

client = OpenAI()


def encode_image(image_path):    
    with open(image_path, "rb") as image_file:
        return base64.b64encode(image_file.read()).decode('utf-8')


image_path = "Lenna.png"
base64_image = encode_image(image_path)
file_extension = Path(image_path).suffix
file_extension_without_dot = file_extension[1:]

url = f"data:image/{file_extension_without_dot};base64,{base64_image}"

response = client.chat.completions.create(
    model="gpt-4-vision-preview",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text": "この画像の女性の名前はLennaです。なぜか有名らしいですが、なぜでしょう？",
                },
                {
                    "type": "image_url",
                    "image_url": {
                        "url": url,
                    },
                },
            ],
        }
    ],
    max_tokens=1000,
)

print(response.choices[0].message.content)

```

ちなみに、.pyファイルと同じ場所に.envファイルを置いておき、中身にOpenAIのAPIキーを書いておくのを忘れないこと

```
OPENAI_API_KEY = "sk-~~~"
```


すると、返答がくる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40132/67f08c67-16a4-5862-f424-e6c5ffc70097.png)

とても楽しい。


# 過去記事
https://qiita.com/ina111/items/0591ab8714139e67b19c

https://qiita.com/ina111/items/1a7c3aac1ca02259783f
CSS ModulesのClass付与

## はじめに
久しぶりの投稿です
Nextでcss modulesを使用しています
classの付与の仕方で注意する点がいくつかあったのでまとめました

## active
active時に色を変更するにはglobalを使用する
```scss
.title {
  color: "#333";
  &:global(.active) {
    color: "#666"
  }
}
```
## 状況別Classの付け方
```js
// 一単語
<div className={styled.name}></div>

// アンダーバー
<div className={styled.class__name}></div>

// キャメルケース
<div className={styled.classNameHoge}></div>

// ハイフンが含まれる場合
<div className={styled['class-name']}></div>

// 複数のclass名
<div className={`${styles.name} ${styles.class__name}`}></div>
```

```js
// 複数 && ハイフンが一部
<div className={`${styles.name} ${styles['class--name']}`}></div>
```

```js
// 動的にclassをだし分ける
const [state, setState] = useState(true)

<p className={`${state && "active"}`} ></p>
<p className={state ? "active" : ""} ></p>
```

## おわり
細かい違いですが、知らないとちょっとだけつまずきます
NPS の役割をインストール

# はじめに
何の変哲もない NPS のインストール手順です。
私が投稿した（投稿予定も含む） Qiita 記事では、ネットワークポリシーサービス (NPS) を扱う場面が出てきます。
そのため、この記事では NPS のインストール手順を Step by Step で紹介しておきたいと思います。

# ネットワークポリシーサービス の役割を導入する

1. Windows Server に 管理者 でサインインし、サーバーマネージャ を起動する
　<br>
1. 「管理」を押して、続いて「役割と機能の追加」を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/2699811d-b27f-88f6-1db3-5fdf27c21b6a.png)
　<br>
1. 以下の画面では「次へ」を押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/96128492-cf58-d6d3-1342-132ca6ca5f35.png)
　<br>
1. 以下の画面では、既定値のまま「次へ」を押す。
既定値＝「役割ベースまたは機能ベースのインストール」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/f321e9eb-9219-8770-d077-bf67766cbb90.png)
　<br>
1. 以下の画面では、既定値のまま「次へ」を押す。
既定値＝「サーバープールからサーバーを選択」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/7abfe733-6b70-7180-ff4b-962569eaacc1.png)
　<br>
1. 以下の画面では「ネットワークポリシーとアクセスサービス」にチェックを入れる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/2faa4f94-bf6a-5699-04cd-444f4a37059c.png)
　<br>
1. 以下の画面では、既定値のまま「機能の追加」を押す。
既定値＝「管理ツールを含める」が チェック ON
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/3c58f138-03be-fd31-de42-c6e64e80e352.png)
　<br>
1. 以下の画面では、既定値のまま「次へ」を押す。
既定値は、.NET Fremework 4.7 Features 以外にも、いくつかの項目にチェックが入っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/32c99e80-2dd4-8cf6-6e55-fc3b69240807.png)
　<br>
1. 以下の画面では「次へ」を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/2dfb6c5a-4079-3a2f-9895-c6e4fe6bedce.png)
　<br>
1. 以下の画面では、既定値のまま「インストール」を押す。
既定で「必要に応じて対象サーバーを自動的に再起動する」は OFF
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/61b990a4-52e7-a0ea-037a-f744e3507b4c.png)
　<br>
1. 以下の画面になったら「閉じる」を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/cda72762-ccea-aaba-3ec4-58d545eba3bd.png)

# 導入後の確認
1. サーバーマネージャーに以下の機能が加わるので、クリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/a2e57432-ddb9-6108-a7da-e6eb39fe13fd.png)
　<br>
1. 以下のような管理画面が起動されればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/0a0bfb4a-d54f-d7e1-a8f5-de612fab5a15.png)

# Next Step
以下に、具体的な NPS を使った構成について紹介しています。参照ください。

https://qiita.com/carol0226/items/05d8ef17a6d25018cd4e

https://qiita.com/carol0226/items/149503bf49810942da5a

https://qiita.com/carol0226/items/564a21455cd3e5f58906

# ご参考
Microsoft 公式 の NPS インストール手順です。

https://learn.microsoft.com/ja-jp/windows-server/networking/technologies/nps/nps-manage-install

その他の役割サービスについても 以下に 記事化しています。
ぜひ、併せて参照ください。

https://qiita.com/carol0226/items/0dea96f5ce09b8cf89a6
AD CS 証明書要求の承認

# はじめに
私が投稿した（投稿予定も含む） Qiita 記事では、AD CS で 証明書要求 (CSR) を承認する場面が出てきます。
そのため、この記事では CSR を承認する場面を Step by Step で紹介しておきたいと思います。

# 証明書要求 の承認
1. AD CS サーバーのサーバーマネージャで、「ツール」を開き「証明機関」を起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/ee94c78e-b900-0093-9900-6c7a264b1ad5.png)
　<br>
1. 初めは、以下の通り、発行した証明書は、空の状態です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/101b083b-3a3b-9453-f6eb-6d5134d6a9ae.png)
　<br>
1. 「保留中の要求」に、要求した証明書があるハズなので、想定された要求かどうかを確認後に「発行」を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/eba64e85-7204-a482-e9ea-5b7914960f4b.png)
　<br>
1. 「発行した証明書」に、以下のように表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/e32853e6-d30e-ca2e-a692-307851f5ff96.png)

これで、証明書要求の承認が行われて、要求者が 証明書をダウンロードすることが可能になりました。
元の手順に戻って、証明書のダウンロードから作業を継続してください。
App Service の デプロイ手順

# はじめに
何の変哲もない App Service のデプロイ手順です。
私が投稿した（投稿予定も含む） Qiita 記事では、App Service を扱う場面が出てきます。
そのため、この記事では App Service の デプロイ手順を Step by Step で紹介しておきたいと思います。

:::note info
私は、インフラ出身で 言語をガリガリ書くようなことはできないので、App Service のサイトの中身についての記事を書くことは まず無いと思います。
"カスタムドメイン" や、"証明書をサイトにバインドする"、"VNET統合"、"プライベートリンク" など、インフラ観点で関連性のあるアクションについての説明の際に、この App Service のデプロイ手順を使っていきますので、ご承知おきください。
:::

# 事前作業
"App Service" をデプロイする際には、"App Service プラン" が必要です。
以下の記事で、"App Service プラン" の説明と デプロイ手順について記載してあります。
"App Service プラン" が準備できてから、"App Service" をデプロイしましょう。

https://qiita.com/carol0226/items/7329e5de53ac9c55abce

# App Service の デプロイ手順
1. Azure Portal の検索窓で "app service" と入力し "App Service" を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/046fdbc9-4406-a6ae-883e-a0262b409695.png)
　<br>
1. 「＋作成」を押して「＋Web アプリ」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/589c5536-69b4-821f-9c3a-0560af8445cb.png)
　<br>
1. 下図を参考に 設定項目を入力してください。
「名前」については、インターネット上で被ることのない ユニーク な名前を付与する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/dfad4fe8-3d91-4fb7-a9f4-17817b74daa9.png)
　<br>
1. 以下の画面で、事前作成していた "App Service プラン" を選択し「確認及び作成」を押します。<br>なお、「新規作成」のボタンを押すことで 事前作成していなくても、ここで同時作成も可能ですが、わかりやすさを重視して、事前作成するようにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/aa1ab0a2-c9d8-c7f1-32b7-fcb2337d3585.png)
　<br>
1. 以下の確認画面で「作成」を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/50a69213-9a7c-536e-82c7-f4186d1f9480.png)
　<br>
1. デプロイが終わると 以下の画面になります。「リソースに移動」を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/a1da4425-7522-25c4-d462-7a67394337be.png)
　<br>
1. この画面がデプロイされた App Service の管理画面です。赤枠部分が サイトの URL になっているため、ここをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/5155deee-71ba-7324-22b2-87dc48d84b4c.png)
　<br>
1. デプロイされた Web サイト が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/b040a284-c0a9-4e49-c3ec-411796e6b90a.png)

# 参考
App Service についての公式ページです。

https://learn.microsoft.com/ja-jp/azure/app-service/overview
App Service プラン の作成について

# App Service プラン とは？
"App Service プラン" は、その名の通り "App Service" で利用する 機能と価格を決めるものではあるのですが、 それだけではありません。

"App Service" を動作させるための 実行環境 の定義とも言えるものとなっています。

"App Service" は、URL 単位のサイト構成が定義されており、そこに 開発言語が書かれたコードを紐づけた形のリソースになっています。Microsoft は これを "Web アプリ" と呼んでいます。

"App Serice プラン" は、"Web アプリ" を動作させるための実行環境です。この実行環境上に、複数の "Web アプリ" を配置して 動作させることが可能になっています。
実行環境は、OS や、Java , Python , .NET などのランタイム などを組み合わせた形で選択でき、さらに、CPU・メモリ・ディスク などの性能や、SSL対応・カスタムドメイン・スワップ・自動スケール などの機能についても選択します。
これによって、"App Service プラン" の価格が決定します。

これら、OS・ランタイム・性能・機能 を組み合わせたリソースに名前を付けたものが、"App Serive プラン" と呼ばれるものになっています。

# App Service プラン で 選択可能なプランについて
以下のリンク先の表で、詳細に説明されています。

https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/management/azure-subscription-service-limits?wt.mc_id=mvp_407731#app-service-limits

# App Service プラン の デプロイ手順
1. Azure Portal の検索窓に "app service" を入力し「App Service プラン」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/7f792bf7-8aa0-4232-4a0d-02ee6f127511.png)
　<br>
1. 「作成」を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/3d834480-160a-a316-8d29-d793a6b6a4c2.png)
　<br>
1. 以下の設定項目を入力して「確認および作成」を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/e7add2e8-d833-f459-060d-8ae0ac96513e.png)
　<br>
1. 以下の確認画面で「作成」を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/64d915d8-a940-02dc-0193-9561029df249.png)
　<br>
1. デプロイが完了したら「リソースに移動」を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/e631be41-a57a-f115-36ad-66e4025e1cc6.png)
　<br>
1. 以下の画面が表示されれば OK です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/b2063702-dad1-0834-991e-75b08f259460.png)

# 参考
App Service プランを Basic 以上でデプロイしたあとで、Free へダウングレードしようとしても出来ない場合があります。その場合の対処策は、以下に記事化してあります。

https://qiita.com/carol0226/items/ae8c46a4571aee048faa
LinuxでPT3でDockerでデジタル放送をIPでLAN内に配信するテスト


研究目的でLinuxでPT3でDockerでデジタル放送をIPでLAN内に配信するテストをしてみました。

https://github.com/gretchi/Docker-ISDB-IPBrodcastTest


2年近く前に作成したものなので環境は適宜調整してください
利用は自己責任で。


---

以下README

---

# Docker-ISDB-IPBrodcastTest

研究のためLinuxホスト上でDockerでPT3で[Mirakurun](https://github.com/Chinachu/Mirakurun) でデジタル放送をIPでLAN内に配信するテストをしてみた。
2年近く前に作成したものなので環境は適宜調整してください

このリポジトリは研究目的のために作成されたものです。ご利用は自己責任で。


## 実行環境

- Hyper Visor: Proxmox VE
- Host: Ubuntu Server 20.04 LTS
- Docker: 20.10
- docker-compose: 1.27
- Tuner: PT3

### 動作を確認したクライアント

研究のため以下のクライアントで動作を確認しました。

- EPGStation
- Miraktest
- TVTest


## やりたいこと(要件)

- PT3 で受信した地デジ放送を Mirakurun で再配信し､EPGStation で録画できる環境がある
- PT3 と Mirakurun を受け持つ recpt1 で､b25 の複合ができる
- S***C** が利用できる(*-*** を使用しない)
- Mirakurun で配信した放送を Mac 及び TVTest で視聴できる
- 録画した映像は SMB で共有される
- これらの環境が Docker で提供されている

## ホスト側構築

```bash
sudo apt-get update
sudo apt-get -y install curl

# docker
curl -fsSL https://get.docker.com/ | sh
curl -fsSL https://get.docker.com/gpg | sudo apt-key add

# docker-compose
sudo curl -L https://github.com/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
```

```bash
# Add user
adduser tv-server
usermod -a -G sudo tv-server
usermod -a -G docker tv-server
```

```bash
git clone https://github.com/gretchi/tv-server.git
git submodule init
git submodule update
```

```bash
# OS 標準インストールドライバを無効化
echo 'blacklist earth-pt3' | sudo tee -a /etc/modprobe.d/blacklist.conf
```

```bash
# ドライバのビルドとインストール
sudo apt install dkms

cd ./driver/pt3
make
sudo make install
sudo ${SHELL} ./dkms.install
```

```bash
sudo reboot now
```

```bash
# イメージビルド
docker-compose build

# Systemd
ln -s /home/tv-server/tv-server/systemd/tv-server.service /usr/lib/systemd/system/tv-server.service
sudo systemctl daemon-reload

systemctl enable tv-server.service
systemctl start tv-server.service
```

## 付録

### 参照リンク

- https://github.com/m-tsudo/pt3
- https://github.com/stz2012/recpt1
- https://github.com/stz2012/libarib25
- https://github.com/Chinachu/Mirakurun
- https://github.com/l3tnun/EPGStation
- https://www.maspro.co.jp/contact/channel.pdf

### 考察

```plaintext
PCSC:
    スマートカードのサービス?
    pcscd:
        サーバ
    pcsc-tools:
        クライアント
S***C**:
    *-*** を不要にするDLL
b25:
    ARIB STD-B25
libarib25:
    multi2 を復号するツール(ライブラリ形式？)
        PCSC/winscard.h が pcsclite.h を include してる
        -> libpcsclite.so.1.0.0 が必要？
        -> S***C** と同じコンテナでビルドする必要あり？
recpt1:
    PT1(PTx)をLinuxで使うためのツール
    事実上の標準インターフェースになってるっぽい？
recdvb:
    recpt1のDVB版
Mirakurun:
    Windowsにおけるspinelみたいなもの？
    APIで提供されている
Chinchu:
    DVRソフト
EPGStation:
    DVRソフト
DVB:
    デジタルテレビ放送の規格
    DVBデバイス
    Ubuntu 20.04 では PT3 用の dvb ドライバが提供されている
    Docker版 Mirakurun はdvbドライバを利用する
        S***C** + b25decorder でのデコードはrecpt1が担う為､標準ドライバは使えない？
Ubuntu 20.04 LTS:
    PT3 用のドライバの有無、 Debian と CentOS では PCSC が上手く動かなかった
```

## 構成図

![device-flow](https://raw.githubusercontent.com/gretchi/Docker-ISDB-IPBrodcastTest/main/docs/device-flow.png)
【React】useEffectでasync/awaitを使用する方法

## 無名async関数

```react
useEffect(() => {
  (async () => {
    await sampleFunc()
  })()
}, [])
```

## async関数

```react
useEffect(() => {
  const sample = async() => {
    await sampleFunc()
  };
  sample()
}, [])
```
milk-V Duo First impression

最近僕の周りで高評価な milk-V Duo

![IMG_20231110_201321.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/f49c387c-f74a-7083-8a90-84472cdd9d0d.jpeg)

小さいです！

![IMG_20231110_201627.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/4b9693eb-0707-3739-34a1-076d33a63e2c.jpeg)

# 動かしてみる

イメージをダウンロード

https://milkv.io/docs/duo/resources/image-sdk
から、(Latest)を押して

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/daaf9c1c-bfa9-bae4-5541-1fc32781666c.png)

zipファイルをダウンロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/05df7828-ea4d-eb97-c9a6-0c3e6527bdc9.png)

それを書くのはいろいろありますが、今回は公式が紹介しているイメージャを使うことにしました。

https://etcher.balena.io/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/029047d8-ab5f-a57d-17f5-12f664a7cfef.png)

今回は、appimage をダウンロードしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/d70e6234-556a-28b9-a2dc-952ff4d83ec9.png)
```
$ chmod 555 balenaEtcher-1.18.11-x64.AppImage 
$ ./balenaEtcher-1.18.11-x64.AppImage 
```

イメージャーが起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/7bd90a03-2f9f-671d-33d7-91dcc603b423.png)
先ほどダウンロードした zip ファイルを選択し、書き込み先を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/3a7a520c-9c65-6189-3955-b76246561b91.png)
用意ができたら「Flash!」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/b2a61817-df47-5849-a8d2-d7a29231ab83.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/90aed70f-638f-371c-64a1-7b9e1aed4bc1.png)

書き込みができたら、milk-V Duoに刺して、母艦にUSBケーブルでつなげます。

ネットワークデバイスとして認識します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/d25e3918-3d28-4c3f-811e-7140a93452c9.png)

起動は早いです。10秒ちょっとでネットワークに反応が帰ってくるようになります。


```
$ ssh root@192.168.42.1
```
パスワードは milkv
```
root@192.168.42.1's password: 
[root@milkv-duo]~# 

```

ログインできました

LEDの点滅プログラムは ` /mnt/system/blink.sh ` にあります。

```
#!/bin/sh

LED_GPIO=/sys/class/gpio/gpio440

if test -d $LED_GPIO; then
    echo "GPIO440 already exported"
else
    echo 440 > /sys/class/gpio/export
fi

echo out > $LED_GPIO/direction

while true; do
    echo 0 > $LED_GPIO/value
    sleep 0.5
    echo 1 > $LED_GPIO/value
    sleep 0.5
done
```

パターンを変えて遊んでみました
```
#!/bin/sh

LED_GPIO=/sys/class/gpio/gpio440

if test -d $LED_GPIO; then
    echo "GPIO440 already exported"
else
    echo 440 > /sys/class/gpio/export
fi

echo out > $LED_GPIO/direction

while true; do
    echo 0 > $LED_GPIO/value
    sleep 0.2 
    echo 1 > $LED_GPIO/value
    sleep 0.2 
    echo 0 > $LED_GPIO/value
    sleep 0.2                      
    echo 1 > $LED_GPIO/value
    sleep 0.2               
    echo 0 > $LED_GPIO/value
    sleep 0.2               
    echo 1 > $LED_GPIO/value
    sleep 0.2               
    echo 0 > $LED_GPIO/value
    sleep 0.5               
    echo 1 > $LED_GPIO/value
    sleep 0.5               
done         
```
MOPACによるAM1の計算とHOMO LUMO GAP

非経験的分子軌道法(AM1,PM6, PM7など)で計算をしたくなりMOPACを使うことにしました。(いつからか無料になったみたいです)

インストールします。
```
conda install -c conda-forge mopac
```


１　MOPAC入力用の構造ファイル.mopファイルを用意します。avogadroのソフトを使えば「extensions」から「mopac」を選べば.mop形式のファイルを作成できます。.mopファイル作成の際に、AM1かPM6か選ぶ箇所があります(何も選択しないとデフォルトのPM7が選択されます)。また、構造最適か遷移状態の計算か選ぶこともできます。

２　計算します。MOPACはjupyterやターミナルで動かせます。
```
#jupyter notebookでは以下のコードで計算が実行されます。
#計算手法は.mopファイル作成の際に選んだ手法で実行されます。
#計算後は.outファイルが自動で保存されます。
!mopac "benzene.mop"
```

３.outファイルにhomo lumo のエネルギーの情報が記載されています。メモ等で開けます。

以上
Raspbian Stretch から Buster へアップグレード時に遭遇したエラー

# アップグレードのきっかけ
Raspberry Pi 3 Model B+ を何年か前に購入して以来、小規模な WEB サーバとして運用しているのだが、先日 Node.js 18 をインストールしようとしたところ GLIBC のバージョンが古くてコケた。
(以下のブログと同じ状況だった。)
[nodeのv18を使ったらエラーになった（CentOS7）](https://it.ama2pro.net/2022/05/31/node%E3%81%AEv18%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E3%82%89%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%9F%EF%BC%88centos7%EF%BC%89/)

そこで `apt upgrade` を試してみようと思ったのだが、こっちもエラーになった。

```
E: リポジトリ http://raspbian.raspberrypi.org/raspbian stretch Release には Release ファイルがなくなっています。
```

Debian 9 (stretch) は 2022-07-01 に LTS も EOL を迎えていて、 Raspbian も stretch のレポジトリをいつの間にか他所に移していたらしい。

https://wiki.debian.org/LTS

[legacy materials moving from archive.raspbian.org to legacy.raspbian.org](https://forums.raspberrypi.com/viewtopic.php?t=237469) を読むに、 legacy.raspbian.org を参照すれば引き続き `apt` は使えるようなのだが、いつまでも古い OS を使い続けられないので、 Debian 10 (buster) にアップグレードすることにした。

# アップグレード
一応実機の型番を確認。
```
$ cat /proc/device-tree/model
Raspberry Pi 3 Model B Plus Rev 1.3
```

OS アップグレードはこのあたりを参考にした。

https://hodalog.com/upgrade-os-version-of-raspberry-pi/

`/etc/apt/sources.list` と `/etc/apt/sources.list.d/*` を手動で変更して
```
sudo apt update
sudo apt upgrade
```
する感じ。
時間がかなりかかりながらも、順調に進んでいるかに見えたのだが、、、

# エラー発生
```
python3-sense-hat (2.4.0-1~bpo10+1) を設定しています ...
  File "/usr/lib/python3/dist-packages/sense_hat/colour.py", line 185
    explanation = f" (different device id detected: {id})"
                                                         ^
SyntaxError: invalid syntax

dpkg: パッケージ python3-sense-hat の処理中にエラーが発生しました (--configure):
 installed python3-sense-hat package post-installation script subprocess returned error exit status 1
処理中にエラーが発生しました:
 python3-sense-hat
E: Sub-process /usr/bin/dpkg returned an error code (1)
```

invalid syntax と来た。 Python はある程度わかるのだが、ここに文法のエラーがあるとは全く思えなかった。そもそも文法エラーがあるようなライブラリを提供するわけないし。。。

https://github.com/astro-pi/python-sense-hat/blob/v2.4.0/sense_hat/colour.py#L185

GitHub のソースを見ると、 v2.4.0 ではたしかにそのようなコードになっているが、 v2.6.0 ではだいぶ変わっている。
しばらくいろいろ調べたのだが、深夜だったこともあり、頭が回っていなかったので諦めた。
そして翌日、目覚めた瞬間に思いつく。
「システムの Python が f-strings に対応していないバージョンなのでは?」

https://docs.python.org/3/whatsnew/3.6.html#pep-498-formatted-string-literals

案の定、 f-strings は 3.6 で導入されたが、システムの Python は 3.5 だった。
`apt` のアップグレード対象には Python が入っていなかったので、エラーになっている箇所にパッチを当ててみることにした。

```diff:colour_patched.py
--- colour.py	2023-11-09 09:27:16.529087729 +0900
+++ colour_patched.py	2023-11-09 09:32:32.205314267 +0900
@@ -182,7 +182,7 @@ class I2C(HardwareInterface):
             explanation = "(sensor not present)"
             raise ColourSensorInitialisationError(explanation=explanation) from e
         if id != 0x44:
-            explanation = f" (different device id detected: {id})"
+            explanation = " (different device id detected: {0})".format(id)
             raise ColourSensorInitialisationError(explanation=explanation) from e
     @staticmethod
     def i2c_enabled():
```

`sudo patch -p0 < colour.patch` の要領でパッチを適用して、再度 `sudo apt upgrade` を実行し、無事終了した。

# 余談
その後、 `sudo apt full-upgrade` を実施したところ、 Python 3.7 がインストールされた。
なので `upgrade` を飛ばして、いきなり `full-upgrade` を実施すれば回避できた問題だった模様。。。
ChatGPT、意外に実用的に使えるかも

今更だけど、意外に使えるかもと思ったのでメモ。

ChatGPTでコードを書かせるのは一般的だけど、全部書かせようとすると
結局プログラムを日本語で書いていることになるだけと思ってあまり試してなかったけど。

[argparse](https://docs.python.org/ja/3/library/argparse.html) の使い方、リファレンス調べるより早かった。

最近ライブラリの使い方覚えきれず、argparseとか使い方色々あるので、毎回リファレンス調べてたけど、
> ```
> -o と -o xxx で異なる値を引数として取れるようにしてください
> ```
と日本語でもちょっと意味わからない書き方でも、


> argparseで異なる値をとるオプションを設定するには、nargsとconstを利用します。以下は、-oオプションが単体で指定された場合と、-oの後に引数が続く場合で異なる値を取るようにした例です。
> 
> ```python
> import argparse
> 
> def main():
>     parser = argparse.ArgumentParser(description="Example with different values for option -o")
> 
>     parser.add_argument("-o", nargs='?', const="default_value", help="Option 'o' with optional argument")
> 
>     args = parser.parse_args()
> 
>     if args.o:
>         if args.o == "default_value":
>             print("Option -o is specified without a value. Using default_value.")
>         else:
>             print(f"Option -o is specified with value: {args.o}")
>     else:
>         print("Option -o is not specified.")
> 
> if __name__ == "__main__":
>     main()
> ```
>
> この例では、-oが指定されると、その後に引数が続くかどうかにかかわらず、args.oに異なる値が設定されます。もし-oが引数なしで指定された場合は、constで指定したデフォルトの値（ここでは"default_value"）が使われます。引数が指定された場合はその値がargs.oに設定されます。

とちゃんと意図をくみ取ってくれてる。

今まで無理難題の質問をして、使えないと思っていたけど、
適切なレベルのものを入力すると、期待値以上の仕事をしてくれるのかも！


その内、会社の文章とかメールとか、チャットのやり取り全部入力して、
あれなんだっけと思ったら、尋ねるとすぐいついつのどこどこのやり取りで、
というのを教えてくれると、探し物の時間が減っていいのかも！

# 【追記】ChatGPTだと、NMEAの緯度経度のパースは難しいみたい。
緯度はddmm.mmmmmmmで、経度はdddmm.mmmmmmmで表されるフォーマットだけど[(参考)](https://ales-corp.co.jp/technical-information-nmea/#i2)、
どうもまとめてやろうとして
```python
def nmea_to_deg(nmea_coord):
    # NMEA座標を度に変換する関数
    degrees = int(nmea_coord[:2])
    minutes = float(nmea_coord[2:])
    return degrees + minutes / 60.0
```
で経度が違うよと指摘すると、
```python
def nmea_to_deg(nmea_coord):
    # NMEA座標を度に変換する関数
    degrees = int(nmea_coord[:3])
    minutes = float(nmea_coord[3:])
    return degrees + minutes / 60.0
```
となって、今度は緯度が違うことを指摘すると、
変換の仕方が違うのはわかってますというのは返すけど、
変な回答ばかりする。
```python
def nmea_to_deg(nmea_coord, is_longitude=False):
    # NMEA座標を度に変換する関数
    degrees = int(nmea_coord[:3])
    minutes = float(nmea_coord[3:])
    
    if is_longitude:
        # 経度の場合は3桁整数部分を180度から引く
        degrees = degrees - 180
    
    return degrees + minutes / 60.0
```

どう間違いを指摘すればいいのかは難しい。。。

ちなみに、
```python
def nmea_to_deg(nmea_coord, is_longitude=False):
    n = 2
    if is_longitude:
        n = 3
    
    # NMEA座標を度に変換する関数
    degrees = int(nmea_coord[:2])
    minutes = float(nmea_coord[2:])
    return degrees + minutes / 60.0
```
が正しくないと聞いたら、

正しいですと言いつつ、間違っている部分知れっと直してる。。。
```python
def nmea_to_deg(nmea_coord, is_longitude=False):
    n = 3 if is_longitude else 2
    
    # NMEA座標を度に変換する関数
    degrees = int(nmea_coord[:n])
    minutes = float(nmea_coord[n:])
    return degrees + minutes / 60.0
```


それにしても、それっぽい回答をするので、間違いを見抜ける力がいるね。。。
GitHubでのコンフリクトの解消方法

# GitHubでのコンフリクト解消の指南

最近直面した問題。GitHubでのコンフリクト解消法をおさらい！

## コンフリクトはなんで起きるの？
　chatGPTによると「GitHubでのコンフリクトは、複数の開発者が同じコード行に異なる変更を加えた場合に発生します。特に、チームでの協力作業中には避けて通れない問題です。」と書いていますわざとコンフリクトを起こし、練習することでいい経験になりました。

### 解消前の準備
コンフリクトを解消する前に、最新の`main`ブランチをローカルリポジトリに`pull`して、変更を`rebase`することが重要です。

```
$ git pull origin main
$ git rebase main
```

#解消法
コンフリクトが発生した場合、以下の手順に従って解決しましょう。

1. コンフリクトの特定
コンフリクトが発生しているファイルを特定します。ターミナルで次のコマンドを実行してください。
```bash
$ git status
```
2. コンフリクトの解決
コンフリクトが発生している箇所をエディタで開き、以下のように修正します。

```ファイル上で

<<<<<<< HEAD
puts 'この行はあなたの変更です。'
=======
puts 'この行は他人の変更です。'
>>>>>>> branch-a
```

3.　手動で解決
　コンフリクトが起こっている部分を手動で編集して解消します。どちらの変更も重要な場合は、双方のコードを組み合わせたり、残したりする必要があります。

## まとめ
コンフリクトの解消は、エンジニアの基本的なスキルの一つですよね。慣れることが一番だと思うので様々な事象を解決をしてい木、経験値を増やしていきましょう。


### 心掛け
・定期的なコミットとプッシュ
・プルリクエストの小分けで作業
・コードレビュー重視