OmniAICreator/Qiita-1.07M huggingface dataset:
PAY.JPの定期課金を使用してサブスクを実装

定期課金の実装を行いました。
備忘録として残したいと思います。
定期課金は単発課金と異なり、かなり処理が複雑でしたが
ドキュメントを熟読して、とってもよい経験となりました。



# 定期課金おおまかな流れ

### 1. 顧客がクレジットで定期課金を購入💳
[PAY.JPのcheck outに記載のカード情報入力フォームを用意します。](https://pay.jp/docs/checkout)
このフォームのdata属性に公開用APIKEYをセットする必要があります。

```js
<script
  type="text/javascript"
  src="https://checkout.pay.jp/"
  class="payjp-button"
  data-key="pk_test_0383a1b8f91e8a6e3ea0e2a9"
  data-submit-text="トークンを作成する"
  data-partial="true">
</script>
```

## 2. PAY.JPに顧客情報・プランを作成し、アプリケーション側のDBにも必要データを保持します。🖥️

顧客からプランの購入が行われたらPAY.JPに顧客登録とプラン作成をおこないます。
[PAY.JPへ顧客情報・プランを作成する処理](https://pay.jp/docs/api/?php#%E9%A1%A7%E5%AE%A2%E3%82%92%E4%BD%9C%E6%88%90)


```php
// 顧客作成
\Payjp\Customer::create(array("description" => "test"));

//　プランの作成
\Payjp\Plan::create(array(
        "amount" => 500,
        "currency" => "jpy",
        "interval" => "month",
        "trial_days" => 30,
));

```

#### アプリケーションのDBに必要情報を格納

顧客の定期課金情報をアプリケーション側のDBにも保存します。
DBにPAY.JPが保持している情報と同等のデータを保管していきます。
有事の際にPAY.JPではなく、システム側で顧客の履歴を確認できるようにするためです。

以下のような定期課金用のテーブルを作成し、
定期課金の決済が行われるごと（1サイクル分）にレコードを追加していきました。

```sql
create table subscriptions (
  id bigserial not null
  , user_id integer not null
  , is_deleted boolean default false not null
  , created timestamp default now() not null
  , modified timestamp default now() not null
) ;
```

さらに実装を進めるなかで以下のカラムを追加していきました。
- 定期課金開始・終了日
- 前後サイクルのプラン
- PAY.JPのサブスクID


## 3. webhook を受信して定期課金の更新処理を行う⚡

PAY.JPでは様々なイベントに応じてWebhookを送信してくれます。

発生するイベントの例

- 定期課金の更新
- キャンセルされて定期課金の停止
- 何かしらのエラー

:::note info
Webhookとは、イベント発生時にPOSTでパラメーターを送信すること。
:::

このWebhookを受信して、イベントに応じた処理を作成する必要があります。

- [PAY.JPのWebhookについて](https://pay.jp/docs/webhook)
- [Webhookで送信されてくるデータ](https://pay.jp/docs/api/?php#event%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88)


# 意識・工夫したこと🏃‍♂️

## エラーハンドリング

工夫したことでもあり、大変苦労したことでもあります。
テストしている際にも想定外の様々なエラーが発生するため適切にエラーを処理を行い、
システム運営が正常に行えるように意識しました。例えば、

- 不正なクレジットカードの使用
- PAY.JPへ不正な定期課金リクエストが送信された
- コントローラーのアクションで発生したエラー
- 全く想定していないエラー

当然のことですが、解約済みの定期課金の参照や、加入しているプランと同じプランに加入リクエストを送信してしまうとPAY.JPからエラーがレスポンスされるため、そのようなリクエストがされないように以下を意識しました。

- 画面で処理ができないようにする
- バリデーションチェックで弾く
- 仮に送信されてもエラーレスポンスを適切に処理

## ドキュメントとして残す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671845/ddf3c1de-65dc-ab86-1ccf-11952bcf3c46.png)


定期課金の処理は簡単かと思いきや、
様々なエラーに遭遇し複雑化していきました。
そのため、備忘録やバグや追加機能実装に備えて、
draw.ioのフローチャートを使用して
分かりやすく残しておく工夫をしました。


# まとめ🖊️

ご覧いただきありがとうございました！
定期課金の実装は正直とっても大変でした。
開発期間も想定していた1ヶ月を上回り2ヶ月半かかりました！
でもとっても良い経験で終わった後は達成感を感じました。

何か気になる点や、おかしな点ありましたらお気軽にコメントください！
GitHub Actions学んでみた⑦

# はじめに
初めまして！
エンジニアになって数年、今まで本を読むだけでしたが、もっとプライベートで楽しみながら成長したい！自分が学んだ足跡を残していきたい！と思い記事を書きました！
最終的には自在に開発できるようになりたいと思っています。:triumph:
いろいろな記事を参考にさせてもらっています。:bow_tone2:

# 今回の目的
自分の作ったコンポーネントを確認したり検証するための技術を身に付けたい！
公式のクイックスタートを参考に進めていきます。
項目ごとに補足のみ書いて進めています。わかりづらいところの理解の手助けになれば幸いです！

# 主に参考にさせていただいた記事

https://docs.github.com/ja/actions/quickstart

# 変数

## 単一のワークフローの環境変数の定義
ワークフローファイル内のenvキーを使用して環境変数を定義

DAY_OF_WEEK：ワークフロー全体
Greeting：job内
First_Name：step内

```yml
env:
  DAY_OF_WEEK: Monday

jobs:
  greeting_job:
    env:
      Greeting: Hello
    steps:
      - name: "Say Hello Mona it's Monday"
        run: echo "$Greeting $First_Name. Today is $DAY_OF_WEEK!"
        env:
          First_Name: Mona
```

## 複数のワークフローに対する構成変数の定義　｜　コンテキストを使用した変数の値へのアクセス

varsコンテキストを使用する

https://qiita.com/mr_noppo/items/80dfe7111848527ce68e

## 既定の環境変数
GitHubが設定する既定の環境変数は、ワークフローのどのステップでも使用可能

一覧はこちら

https://docs.github.com/ja/actions/learn-github-actions/variables#default-environment-variables

## オペレーティング システムの検出
現在実行中のOSの検出する。runner.osで抽出
```yml
on: workflow_dispatch

jobs:
  if-Windows-else:
    runs-on: macos-latest
    steps:
      - name: condition 1
        if: runner.os == 'Windows'
        run: echo "The operating system on the runner is $env:RUNNER_OS."
      - name: condition 2
        if: runner.os != 'Windows'
        run: echo "The operating system on the runner is not Windows, it's $RUNNER_OS."
```


# 次
スターター ワークフローの使用から
【論文毎日読んでみる #3】GPT-3の論文【"GPT-3: Language Models are Few-Shot Learners" (Brown et al., 2020)】

# 読んだ論文
本記事は以下の論文を読んだ際に記録した要約とメモです。
[Brown, Tom, et al. "Language models are few-shot learners." Advances in neural information processing systems 33 (2020): 1877-1901.](https://proceedings.neurips.cc/paper_files/paper/2020/file/1457c0d6bfcb4967418bfb8ac142f64a-Paper.pdf)

GPT-3は、少ないデータからでも高精度の予測や生成が可能なモデルです。

# 要約とメモ
### abstract
- GPT-3（Generative Pre-trained Transformer 3）は、OpenAIによって開発された大規模な言語モデルであり、1750億個のパラメータを持つ
- トランスフォーマーアーキテクチャに基づいており、事前に大量のテキストデータで学習され、様々な自然言語処理タスクに対応できる
### 1. introduction
- NLPは、タスクに特化した表現の学習やタスクに特化したアーキテクチャの設計から、タスクにとらわれない事前学習やタスクにとらわれないアーキテクチャの使用へとシフトしている
    - このシフトにより、読解、質問応答、テキストの含意など、多くの困難なNLPタスクが大幅に進歩した
- 大まかに言えば、NLPタスクにおいて、GPT-3はゼロショットとワンショットの設定で有望な結果を達成し、少数ショットの設定では、(微調整されたモデルによって最先端が保持されているにもかかわらず)最先端のモデルと競合する、あるいはそれを上回ることさえある

### 2. Approach
- 学習プロセスは、自己教師あり学習を使用し、特定のタスクに対する明示的な指導なしで、言語のパターンと構造を学習

### 3. Results
- Fine-tuned SOTA（最先端技術）の記録が最も高いことが多いが、GPT-3のFew-Shot設定もそれに匹敵する結果を出せた
- いくつかのタスクでは、GPT-3が最も高いスコアを達成
- タスクによってGPT-3の性能にはばらつきがあることが判明


### 7. Conclusion
- ゼロショット、ワンショット、少数ショットの設定において、多くのNLPタスクとベンチマークで強力な性能を示す1750億パラメータ言語モデルを提示した
- これらの結果は、非常に大規模な言語モデルが、適応可能な一般的な言語システムの開発において重要な要素である可能性を示唆している

# ゼロショット、ワンショット、少数ショットとは
ゼロショット、ワンショット、少数ショット（Few-Shot）は、機械学習や自然言語処理（NLP）におけるモデルの学習と評価の設定を指す用語で、それぞれ異なるトレーニングデータの利用方法を表しています。

## ゼロショット（Zero-Shot）
- 定義: モデルが事前に特定のタスクに関するトレーニングデータを一切受け取らずに、未知のタスクを直接処理する設定
- 例: モデルに一度も見たことのない翻訳タスクを与え、そのタスクに対する適切な出力を生成させる。例えば、英語からフランス語への翻訳を事前に学習していないモデルにその翻訳をさせること
- 用途: ゼロショット設定は、汎用性の高いモデルを評価するために使用されます。新しいタスクやドメインに迅速に適応できるかどうかを確認するための方法です

## ワンショット（One-Shot）
- 定義: モデルが特定のタスクに対して、たった一つの例のみを用いて学習し、その後にタスクを実行する設定
- 例: モデルに英語からフランス語への翻訳の例を一つだけ見せ、その後に他の英語文をフランス語に翻訳させる
- 用途: ワンショット設定は、少量の情報から新しいタスクを学習するモデルの能力を評価するために使用されます

## 少数ショット（Few-Shot）
- 定義: モデルが特定のタスクに対して、数個の例を用いて学習し、その後にタスクを実行する設定
- 例: モデルに英語からフランス語への翻訳の例を数個（例えば、5つ）見せ、その後に他の英語文をフランス語に翻訳させる
- 用途: 少数ショット設定は、限られた情報から新しいタスクを学習するモデルの能力を評価するために使用されます。ゼロショットよりも少し多くの情報を与えることで、モデルの適応能力を確認します

## 具体例
例えば、言語モデルに対して、次のようなタスクを設定するとします。

- ゼロショット例
    - 「Translate the following English sentence to French: 'The cat is on the mat.'」
    - モデルは事前に英仏翻訳の例を一切見たことがない状態で、翻訳を試みる
- ワンショット例
    - 「Translate the following English sentence to French: 'The cat is on the mat.'」
    - 「Example: 'The dog is on the rug.' -> 'Le chien est sur le tapis.'」
    - モデルは1つの翻訳例を見た後に、新しい文の翻訳を試みる。
- 少数ショット例
    - 「Translate the following English sentence to French: 'The cat is on the mat.'」
    - 「Examples: 'The dog is on the rug.' -> 'Le chien est sur le tapis.' 'The bird is in the cage.' -> 'L'oiseau est dans la cage.'」
    - モデルは複数の翻訳例を見た後に、新しい文の翻訳を試みる。

これらの設定を通じて、GPT-3のような言語モデルがどれだけ効率的に学習し、適応できるかを評価することができます。GPT-3は特に、これらの少数ショット設定で非常に高いパフォーマンスを示すことで注目されています。

# BARTとGPT-3のちがい
- BARTは事前学習とファインチューニングのパラダイムに基づいており、特定のタスクに対して高い性能を発揮するためには十分なラベル付きデータが必要
- GPT-3は非常に大規模な事前学習を行い、プロンプトベースでタスクを指定するだけで、多様なタスクに高い性能で対応できる点が特徴です。これにより、GPT-3は少数ショット学習の分野で革新的なモデルとされています
    - だからプロンプトエンジニアリングが効果的なのかも！
React→Github pages

自分用のメモとして書きます。
気が乗ったらちゃんと詳細付きで書きます。

①npm install gh-pages --save-dev
②package.jsonに以下
  "homepage": "https://< your-username >.github.io/< your-repo-name >",
  "scripts": {
    "predeploy": "npm run build",
    "deploy": "gh-pages -d dist"
  }
③vite.config.tsにbase: '/< your-repo-name >/'
④npm run build
⑤npm run deploy

`${import.meta.env.BASE_URL}images/Hachitan_trim.png`
publicフォルダの画像をデプロイ先でも指定したいときはこんな感じに環境変数使う！
小学校の担任の先生のはなし

## ★はじめに★
最高のエンジニアになるため、あえて幼いころの思い出・記憶をたどり、今の自分にどう影響しているかを「ねほりんはほりん♪」している、わーちゃんと申します。

https://qiita.com/wa-chan222/items/173e75f1c6ef5cbdd6d2

前回、衝撃のポケモン事件から学んだことを挙げました。今回は小学校の担任の先生から学んだ？お話です。

## ★あの先生は、今でも稀な存在★
皆さん、小学校の担任の先生を覚えていますか？叱られたり、褒められたり、いじられたり？
世代によっては廊下に立たされたり、罰として校庭●周とかあった人もいるかと思います。
私はあります。返事の声が小さく校庭の朝礼台から4階の教室に向かって返事をするという経験が・・・。
あの時いろんな経験をして、悔しさも恥ずかしさも、諸々覚え、少しのことでは折れない人間になりました。

私が小学校5・6年生の時の担任の方は、自分の事を「47億年生きている」とか、朝のHR的な時間には「`担任の名前`先生の超スーパーウルトラありがたーいお話」とか言って…いい意味で明るい、いい先生でした。~~メガネのカッパ大先生~~

そんな先生のお決まりの言葉がもう一つあります

**予定は未定であって決定ではない!**
▶その証拠に●●が○○に変更になります！
▶だがしかし、本日は予定通りになります！

この言葉に**一喜一憂**することがしばしば。
例えば
- [ ] 今日の道徳は席替えをします
- [ ] 漢字テストを一日ずらして今日行います
- [ ] 今日のプールは中止です


## ★学んだことは何か★
- 私自身予定表に計画通りに進めることができていないと自己肯定感が下がってしまう傾向があります。
`決めていたのにできなかった`。`予定通りに進めていないから自分はダメなんだ`

- 子供のお手本となる存在であろう先生の言葉に`予定って未定だったんだ`。`変えてもいいんだ`と思いました。自分を許すことができたような気がしました。
- また、最初のころは急な予定変更に困惑しましたが、徐々にうまく立ち回れるようになりました。(漢字テストの日程を事前に把握して早めに対策を立てておくなど)

## ★アピールするとしたらこんな感じ★
<details><summary>柔軟性と対応力</summary>

過去の経験から学んだこととして、予定が未定であることを受け入れ、柔軟に対応できるようにしています。具体的に…(今の仕事においてどう生かしているか)
</details>

<details><summary>自己肯定感の向上</summary>

予定通りに進まないことに対するストレスを減らし、自己肯定感を持つことができるようになりました。実際、仕事において・・・。
</details>

<details><summary>変化を受け入れる姿勢</summary>

急な予定変更にも対応できる積極的な姿勢を持っています。
</details>

<details><summary>事前準備と対策の計画性</summary>

不測の事態に備えて、事前に計画を立てて対策をとることを重視しています。
</details>

それぞれの項目において、「仕事の中でこういうことがあった時こうした、だから○○でもこの経験をいかして、貢献したい。」みたいにまとめる

## ★さいごに★
過去から掘り下げ、自分を見つめる作業は大切です。直近がすぐに思いつかない人は、次元を高くして、自分の姿を今一度見てみることをおすすめします。
今回の記事が何かの参考になれば幸いです。
rustでArduino uno をLチカ

https://book.avr-rust.org/

AVR-rustガイドブックを使って行っていく

## 環境
ubuntu 22.04
rustup 1.27.1 (54dd3d00f 2024-04-24)
cargo 1.79.0-nightly (d438c80c4 2024-03-19)
rustc 1.79.0-nightly (0ad927c0c 2024-03-21)

## rustの環境構築
省略

## コンパイラと関連ライブラリをインストール
rustupを使ってコンパイラとコンポーネントをインストール
```
$ rustup toolchain install nightly
...
$ rustup component add rust-src --toolchain nightly
```
ubuntu向け関連ライブラリのインストール
```
$ sudo apt install binutils gcc-avr avr-libc avrdude
```

## サンプルをビルド

```
$ git clone https://github.com/avr-rust/blink.git
$ cd /blink
```

```
$ rustup override set nightly

# Compile the crate to an ELF executable.
$ cargo build -Z build-std=core --target avr-atmega328p.json --release
```
or
```
cargo +nightly build -Z build-std=core --target avr-atmega328p.json --release
```
:::note info
ボードの種類によってjsonファイルは編集する。
指定するボード以外のjsonファイルも用意しておくと便利かも…
:::

## arduinoへ書き込む
```
avrdude -patmega328p -carduino -P/dev/ttyUSB1 -b115200 -D -Uflash:w:target/avr-atmega328p/release/blink.elf:e
```
:::note info
デバイスパスは都度変わるため確認してから書き込むとストレスがない
アクセス制限かかる場合はchmodコマンドで+666を付与
/dev/ttyUSB* or /dev/ttyACM*
:::

LEDがチカチカすれば成功

## まとめ
今回はLチカだけですし備忘録的にざっくりまとめました。なんとなくrustでarduino使えそうな感じしてきたので今度はarduinoのライブラリも使えるようにしてもう少し使い勝手良く動かせるようにしていきます。

## 参考
https://asukiaaa.blogspot.com/2020/08/rust-arduino-.html

https://qiita.com/tobisako/items/08f158df08304f167a55
空コミットしてドラフトのプルリクを作成しよう

Sierでは、開発用にブランチをきった後、空コミットを作成してドラフトのプルリクを作成することが多いと思うので、記事として残しておきます。
おそらくどこの会社でもこれは基本となると思うので、覚えておくべきだと感じます

## 1.ブランチの作成
開発環境を構築し、いざブランチを作成して開発していくという段階を想定して進めます。

```
git checkout -b feature/XXXXX origin/hogehoge
```

feature/XXXXX　がブランチ名となります。
hogehogeは開発環境のメインブランチを記述してください。

## 2. 空コミットしてドラフトのプルリクエストを作成する
```
git commit --allow-empty -m '{プルリクエストのタイトル}'
```
```
git push origin feature/XXXXX
```

コミットメッセージがgit hub上のプルリクエストのタイトルとなります。
## 3. Githubからドラフト状態でプルリクを作成します。

これでレビュワーからのGoサインが出ない限りはメインブランチにmargeは出来なくなりました。
間違って自身の開発ブランチをメインブランチにmargeすることを事前に防げるよう意識していきましょう。
GitHub Actions学んでみた⑥

# はじめに
初めまして！
エンジニアになって数年、今まで本を読むだけでしたが、もっとプライベートで楽しみながら成長したい！自分が学んだ足跡を残していきたい！と思い記事を書きました！
最終的には自在に開発できるようになりたいと思っています。:triumph:
いろいろな記事を参考にさせてもらっています。:bow_tone2:

**「いいね」か「ブックマーク」**
を頂けると僕のモチベーションアップになります！:thumbsup:
少しでも気に入っていただけたらよろしくお願いいたします！:thumbsup:


# 今回の目的
自分の作ったコンポーネントを確認したり検証するための技術を身に付けたい！
公式のクイックスタートを参考に進めていきます。
項目ごとに補足のみ書いて進めています。わかりづらいところの理解の手助けになれば幸いです！

# 主に参考にさせていただいた記事

https://docs.github.com/ja/actions/quickstart

# コンテキスト
#### vars
カスタムの構成変数を呼び出せる
設定されていない場合、変数を参照するコンテキストの戻り値は空の文字列。

設定方法はこの記事を参照

https://zenn.dev/kou_pg_0131/articles/gh-actions-configurations-variables

#### job
現在実行中のジョブに関する情報を取得できる
ジョブコンテナのIDや内部で動作しているサービス情報。

#### jobs
job名から結果や内容を取得できる

#### steps
job内のstep結果や内容を取得できる

#### runner
runs-on: ubuntu-latestの内部情報が見れる

#### secrets
Settingから指定する。特別値を編集するなどしなければ、ログや出力はマスクされ値が表示されることはない。
![スクリーンショット 2024-06-30 13.37.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/fc05105b-d82d-a4a3-86cc-3915bb617361.png)

#### strategy
jobのトータルや現在のジョブ数、実効結果の成否を表示できる

#### matrix
マトリックスプロパティを参考に全てのパターンのジョブを実行

```yml
build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest]
        node: [14, 16]
```
![スクリーンショット 2024-06-30 13.54.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/6672f15c-9e50-50a5-e0ec-a1abfa88a8bf.png)

#### needs
指定した値が取れるまで処理を待つことができる。
下記の場合、build処理を待ってから実行される
```yml
build:
    runs-on: ubuntu-latest
    outputs:
      build_id: ${{ steps.build_step.outputs.build_id }}
    steps:
      - name: Build
        id: build_step
        run: echo "build_id=$RANDOM" >> $GITHUB_OUTPUT
deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying build ${{ needs.build.outputs.build_id }}"
```

## nameの表示場所
「Build and deploy」という名前でグルーピングされる
```yml
name: Build and deploy
on: push

jobs:
  build:
...
```

![スクリーンショット 2024-06-30 14.01.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/6cb23239-0ad3-aa9c-9d20-2fdd68404591.png)


# 次
https://qiita.com/mr_noppo/items/ebec977f6af168fb4eca
Unity学習記録 #008 繰り返し（do while文）

# 繰り返しに使用される制御構文

繰り返しに使用される構文は4つです。
・for文（繰り返す回数が事前に分かっているとき）
・foreach文（配列やリストの要素を順番に処理していくとき）
・while文（繰り返す回数が分からないので、条件がtrueの間は繰り返す）
・do while（条件の判定がループ処理の最後なので、falseでもその回の処理は実行される）

繰り返し処理の中で、よく使われる予約語２つ
・continue（特定の条件を満たした時のループ処理をスキップ）
・break（特定の条件を満たした時にループ処理を終了）

今回はdo while文を学習していきます。

## do while文
まずは構文の書き方です。
```csharp
do
{
    //処理内容;
}
while (条件);
```
特徴は、処理を実行した後に条件の判定を行うことです。
実行できるサンプルコードを書いてみます。
```csharp
int number = 10;
do
{
    Debug.Log(number);
    number--;
}
while (number > 0);
```
カウントダウン処理を実行しましたが、初期値を次のように設定して、ループ処理の1回目から判定結果がfalseになるように書き換えてみます。
```csharp
//1ループ目から判定がfalse
int number = 0;

do
{
    Debug.Log(number);
    number--;
}
while (number > 0);
```
１回目のループでの判定からfalseが返ってきます。for文を使っていた場合は何の応答もなくループ処理は終了です。もしくはelse文を別途記述してfalseだった場合の条件処理を記述します。
do　while文で記述していた場合は1回目のループがfalseであったとしても、１回目で判定された値をコンソールに出力することができています。

少しゲームをイメージしたサンプルコードを見てみます。
```csharp
bool isPlaying = true;
int i = 0;  //試行回数カウンター

do
{
    Debug.Log("正解の番号を選択してください");

    //１から５のランダムな整数を生成
    System.Random random = new System.Random();
    int randomNumber = random.Next(1, 6);

    Debug.Log("選択された番号は：" + randomNumber);
    i++;
    
    //3が選択されたらループ処理を終了させる
    if (randomNumber == 3)
    {
        isPlaying = false;
    }
}
while (isPlaying);

Debug.Log(i + "回でクリアしました");
```
プレイヤーが正解の番号を当てるとゲームクリアになるシステムです。サンプルコードでは条件がtrueの間、何度でも回答できるようになっています。今回は回答の数値をランダムに出力させていますが、実際のゲームではプレイヤーに回答させます。
何回目でプレイヤーが正解を出すのかわからない場合の繰り返し制御ではdo while文は適しています。
Unity学習記録 #007 繰り返し（while文）

# 繰り返しに使用される制御構文
繰り返しに使用される構文は4つです。
・for文（繰り返す回数が事前に分かっているとき）
・foreach文（配列やリストの要素を順番に処理していくとき）
・while文（繰り返す回数が分からないので、条件がtrueの間は繰り返す）
・do while（条件の判定がループ処理の最後なので、falseでもその回の処理は実行される）

繰り返し処理の中で、よく使われる予約語２つ
・continue（特定の条件を満たした時のループ処理をスキップ）
・break（特定の条件を満たした時にループ処理を終了）

今回はwhile文を学習していきます。

## while文
まずは書き方ですが、構文で指定されているのは条件式のみです。
```csharp
while(条件式)
{
    //条件がtrueだった時の処理
}
```
処理できる簡単なコードを書いてみます。
```csharp
int i = 1;
while (i < 10)
{
    Debug.Log(i + "回目の処理");
    i++;
}
```
for文ではループ処理をカウントするループカウンターの設定が必須でしたが、while文ではループカウンターがなくても実行できます。注意することは、上記のサンプルコードでは "i++;" のカウンターがなかった場合に、条件式がfalseになることが無いので、ずっとループ処理を繰り返します。これを"無限ループ"というそうです。while文に限らず、どの繰り返し文でも無限ループには注意が必要です。

実際に実行して処理が止められなくなった場合は、Windowsではタスクマネージャーを開いてアプリ一覧からタスクを強制終了させることができます。これは最後の手段と考えて、まずは無限ループにならないように注意することが大事です。

![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822122/672cc02e-8060-8d84-537b-d6d0dd698d1b.png)
<br>

しかし、正しく設計された無限ループのシステムであれば用途はあるようです。

例えば、インターネットのアカウント登録システムでは２４時間ユーザーの入力を受け付け、ユーザーごとに入力情報を整理する処理を繰り返します。サービスが続く限り、アカウント登録システムは回数制限なく稼働し続けてもらう方が都合がいいです。このような場面において無限ループは有効的のようです。

説明が少しずれてしまいましたがコードの書き方に戻ります。
```csharp
string[] files = new string[]{"file01", "file02", "file03", "file04"};
int i = files.Length;  //ファイル数のカウント

while (i > 0)  //文字の数だけループ処理
{
    Debug.Log("A001_"+ filess[i-1]);
    i--;
}
```
今回はファイル操作のイメージをサンプルコードで書きました。実際のファイルではなく、文字列をファイルの代用にしています。ファイル名の先頭に特定の文字列を付ける処理を行います。

for文で同じ処理をしてみます。
```csharp
string[] files = new string[]{"file01", "file02", "file03", "file04"};

for (int i = 0; i < files.Length; i++)
{
    Debug.Log("A001_" + folders[i]);
}
```
処理する順番はwhile文と異なりますが、全てのファイル名の先頭に特定のコードを付けることができました。

for文はループ処理の条件が分かりやすく、コードを拡張していくことで、ある程度のループ処理のシステムを組むことができます。ループ処理の多くはfor文で記述されることが多いように思いますが、作りたいシステムによってはwhile文の方がシンプルに記述できるかもしれません。
RustでYAMLに埋め込まれた環境変数を展開 

# 使用ライブラリ

| ライブラリ | 説明 |
| -------- | -------- |
| [envsubst](https://docs.rs/envsubst/latest/envsubst/) | 文字列テンプレートにおける変数の置換に使用 |
| [env_logger](https://docs.rs/env_logger/latest/env_logger/) | log crateによって公開されるロギングファサードで使用するために、環境変数によって設定できるシンプルなロガー |
| [log](https://docs.rs/log/latest/log/) | ログ出力に使用（ログの設定は割愛） |
| [once_cell](https://docs.rs/once_cell/latest/once_cell/) | 「一度しか初期化できない」型を提供<br>正規表現のパフォーマンス改善に使用 |
| [regex](https://docs.rs/regex/latest/regex/) | 正規表現 |
| [serde](https://serde.rs/) | Rustデータ構造を効率的かつ汎用的にシリアライズおよびデシリアライズするためのフレームワーク |
| [confy](https://github.com/rust-cli/confy?tab=readme-ov-file) | 環境変数、設定ファイル、コマンドライン引数など、複数の設定ソースを統合して管理できるクレート |

```toml
[package]
name = "web"
version = "0.1.0"
edition = "2021"

[dependencies]
envsubst = "0.2.1"
env_logger = "0.11.3"
log = "0.4.21"
once_cell = "1.19.0"
regex = "1.10.5"
serde = { version = "1.0", features = ["derive"] }

[dependencies.confy]
version = "0.6.1"
features = ["yaml_conf"]
default-features = false
```

# 設定ファイル
- 環境変数を埋め込みたい部分は `${環境変数名}`で記述

```yaml:config.yml
cors:
  allowed_origin: ${ALLOWED_ORIGIN}
```

# 実装

## 環境変数を置換するようのコード

```rust:env.rs
use envsubst;
use log::error;
use once_cell::sync::Lazy;
use regex::Regex;
use serde::{Deserialize, Deserializer};
use std::env;
use std::process;

/// ${val}を環境変数の値に置換
pub fn deserialize_with_env<'de, D>(deserializer: D) -> Result<String, D::Error>
where
    D: Deserializer<'de>,
{
    let s: String = Deserialize::deserialize(deserializer)?;
    Ok(substitute_env_variables(&s))
}

static RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"\$\{(\w+)\}").unwrap());

fn substitute_env_variables(input: &str) -> String {
    if envsubst::is_templated(input) {
        let mut context = std::collections::HashMap::new();
        for (_, [cap]) in RE.captures_iter(input).map(|c| c.extract()) {
            match env::var(cap) {
                Ok(val) => context.insert(cap.to_string(), val),
                Err(e) => {
                    error!("{}", e);
                    process::exit(1);
                }
            };
        }
        envsubst::substitute(input, &context).unwrap()
    } else {
        input.to_string()
    }
}
```

## main処理
- `#[serde(deserialize_with = "deserialize_with_env")]`を環境変数を設定する可能性がある箇所に付与

```rust:main.rs
use common::config::env::deserialize_with_env;
use confy::{self, ConfyError};
use log::{info, error};
use serde::{Deserialize, Serialize};
use std::process;
use env_logger::Env;

mod env;

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct CorsConfig {
    #[serde(deserialize_with = "deserialize_with_env")]
    pub allowed_origin: String,
}

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct Config {
    pub cors: CorsConfig,
}

/// YAMLからコンフィグの値を取得
pub fn get_config() -> Config {
    let cfg: Result<Config, ConfyError> = confy::load_path("config.yml");
    match cfg {
        Ok(cfg) => cfg,
        Err(e) => {
            error!("{}", e);
            process::exit(1);
        }
    }
}

fn main() {
    env_logger::init_from_env(Env::default().default_filter_or("info"));
    let config = env::get_config();
    info!("{:?}", config);
}
```
loggingモジュールを使用してLambdaのログをS3に保存する

# はじめに
本記事では、AWS Lambda で logging モジュールを使ったログ出力と、S3バケットへのログファイルアップロードを実施してみます。


# 環境
python : 3.12

# 前提
- S3 バケット（ログを保存する先）
- IAMポリシー設定（Lambda 関数が S3 にアクセスするためのの付与）


# Lambda関数

ログの設定周りを行います。
それぞれ作成したハンドラに対して出力するログレベルを設定します。ログのフォーマットを設定して、時刻、関数名、ログレベル、メッセージを含むようにします。

```python:utils.py
import logging

def setup_logger(LOG_FILE):
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)

    # ハンドラの作成
    stream_handler = logging.StreamHandler()
    file_handler = logging.FileHandler(LOG_FILE)

    # ログレベルの設定
    stream_handler.setLevel(logging.INFO)
    file_handler.setLevel(logging.WARNING)

    # フォーマットの設定
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    stream_handler.setFormatter(formatter)
    file_handler.setFormatter(formatter)

    # ハンドラをロガーに追加
    logger.addHandler(stream_handler)
    logger.addHandler(file_handler)
```

debug～errorまでのログレベルでメッセージを出力してみます。
生成されたログファイルは指定されたS3バケットにアップロードします。

```python:lambda_function.py
import logging
import boto3
import os
from utils import setup_logger

# ログファイル名とS3バケット名
LOG_FILE = os.environ['LOG_FILE']
S3_BUCKET = os.environ['S3_BUCKET']

# ロガーの設定を初期化
setup_logger(LOG_FILE)

# S3クライアントの作成
s3_client = boto3.client('s3')

def lambda_handler(event, context):
    logging.debug("DEBUGレベルのログ")
    logging.info("INFOレベルのログ")
    logging.warning("WARNINGレベルのログ")
    logging.error("ERRORレベルのログ")

    # ログファイルをS3にアップロード
    try:
        s3_client.upload_file(LOG_FILE, S3_BUCKET, os.path.basename(LOG_FILE))
        logging.info("ログファイルがS3にアップロードされました")
    except Exception as e:
        logging.error("ログファイルのアップロード中にエラーが発生しました: %s", e)

    return {
        'statusCode': 200,
        'body': 'ログが出力されました'
    }
```


# 動かしてみる
Lambdaをテスト実行させてみて、CloudWatchのログに各レベルのログが出力されている事、S3バケットにログファイルが生成される事を確認できました。

### S3バケット

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/f377d00f-182c-ff9b-67b1-5828ffe28b32.png)


<details><summary>メモ：CWでのログ表示における改行文字の挙動と対処法</summary>

次のように `\n`を含む文字をprintで出力すると、CloudWatchで確認した際にそれぞれログが分かれてします。

```python
~~~
hoge = '''
aaaa\n
bbb\n
cc\n
'''

print("hoge", hoge)
~~~
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/98219b09-1386-6a19-6ada-3916eadb2226.png)


このような場合もloggingで出力する事で、1つにまとまります。

```python
logging.debug(hoge)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/b18950d0-29b5-b316-90c3-66655fa4a7cb.png)

</details>





# 参考

https://zenn.dev/dencyu/articles/2b58f669bcd473#print%E3%81%A8logging%E3%81%AE%E9%81%95%E3%81%84

https://zenn.dev/shogo_b/articles/2dc7d3bea7f32a

https://docs.python.org/ja/3/library/logging.html
GithubActionsの備忘録

## ■この記事の目的
- GithubActionsの基本情報をまとめていく
    - 過去に何をやったかの備忘録

## ■概要

[公式ページ](https://github.co.jp/features/actions)
[特徴まとめ](https://qiita.com/bigwheel/items/2ab7deb237122db2fb8d)
- [CI/CD]( https://qiita.com/choco_p/items/1bd1b106daee1fbd4449)をgithub上で実現できる機能
    - できるだけgithub上で完結したいのであれば積極利用
- 可能な限り手作業に依存しない開発フローを作っていく


## ■過去にやったこと
- 特定デプロイ時の書式チェック
- ユニットテスト
- docker imageのbuild
    - imageファイルのpush(アップロード)
- 必要なファイルのコピー
- Cloud Functions デプロイ
- vmインスタンスの設定変更

随時、追記

## ■設定構文

### 基本情報

`【name】`

- ワークフローの名前
    - 役割、やっている事がわかるように命名

### 処理対象・条件

`【on】`
- トリガーとなる対象を設定する
    - トリガーイベント https://docs.github.com/ja/actions/reference/events-that-trigger-workflows#page_build
- push や pull_requestを指定する
    - 複数指定の場合
```
on: [push, pull_request]
```

`【branches】`
- ワークフローの処理対象となるブランチを指定
    - 一意のブランチ名だけではなく、「feature/**」といったパターンでの指定も可
    - 複数指定の場合
```
branches: [develop, staging]
または
branches:
  - master
  - feature/**
```

`【paths】`
- 特定のディレクトリやファイルに変更が入った時のみを条件とする場合に設定
    - 一意のファイル名やディレクトリ名ではなく、パターンや拡張子の指定も可
    - 複数指定の場合 
```
patsh:
  - '**.py'
  - 'src/test_functions/**'
  - 'src/doc/README.md'
```

### ワークフロー時の環境変数指定

`【env】`
- ワークフローで環境変数を指定したい場合に設定

### ワークフロー本処理
`【jobs】`
- 以降に本処理を記述していく

`【uses】`
- あらかじめ用意されているアクション・コードの指定

`【if】`
- 条件分岐など

`【run】`
- コマンド実行など
Javaの開発キットJDKをインストールする

# 動機.イチからJavaの開発環境を整えたい。
当方、プログラミングの初学者の方向けに
学習コンテンツを提供させていただく機会がしばしばあります。
その際に初学者の方でもJDKをインストールできるよう
ドキュメントをしたためさせていただきます。

## 公式ドキュメント
[こちら](https://docs.oracle.com/javase/jp/17/install/overview-jdk-installation.html#GUID-E8A251B6-D9A9-4276-ABC8-CC0DAD62EA33)のページでJDKのダウンロード&インストールの手順がまとまっています。
Linux, MacOS, WindowsのそれぞれのOSでページがありました。
*今回、JDKのVersionは22にしています。
*AWSでJavaプロジェクトをデプロイするときに使いがちな[CorrettoもVersion22に対応しているよう](https://aws.amazon.com/jp/about-aws/whats-new/2024/03/amazon-corretto-22-generally-available/)なので、AWSへのデプロイも問題なさそうです。

## 忙しい方向け
1つ1つドキュメントを読んで理解しながら進めることも重要ですが
「とりま、手っ取り早くインストールまで終わらせたい！」方は下記からインストーラーをダウンロードください。
・Macなら[dmg](https://www.oracle.com/java/technologies/downloads/#jdk22-mac)
・Windowsなら[MSI](https://www.oracle.com/java/technologies/downloads/#jdk22-windows)
がよいと思います。

## どうなればOK??
Macならターミナルから、WindowsならコマンドプロンプトかPowershellから
```java -version```
のコマンドを実行できればOKです。
下記のような出力が得られるはずです。

```
$ java -version
$ java version "22.0.1" 2024-04-16
$ Java(TM) SE Runtime Environment (build 22.0.1+8-16)
$ Java HotSpot(TM) 64-Bit Server VM (build 22.0.1+8-16, mixed mode, sharing)
```

# ■参考記事

### Oracle JDK 22

https://docs.oracle.com/javase/jp/17/install/preface.html#GUID-A1E4DD95-DA5E-4441-BFCD-2E8AE63C573D

### AWS 
https://aws.amazon.com/jp/about-aws/whats-new/2024/03/amazon-corretto-22-generally-available/
🚀 アプリ開発を爆速化する12の秘訣: Twelve-Factor Appでクラウドネイティブを制覇！

**「クラウド、コンテナ、マイクロサービス…新しい技術や言葉が次々と出てきて、正直ついていけない…😰」**

そんな悩みをお持ちのあなたも大丈夫！

**Twelve-Factor App**は、クラウドネイティブ開発の複雑さを紐解き、誰にでも分かりやすく、実践的な指針を提供します。

リリースに時間がかかったり、環境依存のバグに悩まされたり、ユーザーが増えてもスケールできなかったり…😰 そんな悩みとはもうおさらば！👋

**Twelve-Factor App**は、クラウド時代のアプリ開発における12個の黄金律であり、これに従うことで開発がスムーズに進み、スケーラブルで堅牢なアプリを構築できるようになります。

## 🤔 Twelve-Factor Appってどんなもの？

Twelve-Factor Appは、Herokuのエンジニアたちが長年の経験から導き出した、クラウドネイティブなアプリ開発におけるベストプラクティス集です。

美味しい料理を作るためのレシピ集のように、Twelve-Factor Appは、開発者を成功に導くための道標となります。👨‍🍳

## 🎉 Twelve-Factor Appの12の秘訣！

## 1. コードベース: ソースコードは一箇所に集約！

GitHubやGitLabなどのバージョン管理システムを使い、コードは常に一元管理します。チーム全員が同じ場所に集まり、コードを共有することで、開発の混乱を防ぎ、スムーズな連携を実現します。

**例えば**: 5人の開発チームでECサイトを作るとします。Twelve-Factor Appに従えば、全員がGitHubのリポジトリにコードをプッシュし、変更履歴を共有しながら開発を進めます。

## 2. 依存関係: ライブラリは明確に管理！

外部ライブラリを使う場合は、どのライブラリをどのバージョンで使っているかを明確に定義します。Pythonなら`requirements.txt`、Node.jsなら`package.json`などが使えます。

**メリット**: 依存関係が整理されるので、環境構築が楽になり、バージョンの違いによる問題も防げます。新しいメンバーが加わっても、すぐに開発環境を整えられます。

## 3. 設定: 環境ごとに異なる設定は分離！

データベース接続情報やAPIキーなど、環境によって変わる設定は、コードに直接書き込まず、環境変数として管理します。

**メリット**: 環境ごとに設定ファイルを用意する必要がなくなり、デプロイがスムーズになります。また、機密情報漏洩のリスクも減らせます。

**例えば**: ECサイトの開発環境ではテスト用のデータベース、本番環境では本番用のデータベースを使う場合、データベースの接続情報は環境変数として設定します。

## 4. バックエンドサービス: 外部サービスは自由に接続！

データベースやメッセージキューなど、外部サービスはアプリに密結合させず、外部から自由に接続できるようにします。

**メリット**: 特定のサービスに縛られることなく、自由にサービスを選択・変更できます。

**例えば**: ECサイトでメール送信機能を使う際に、SendGridなどのメール配信サービスと連携します。サービスを変更する場合は、環境変数を書き換えるだけで対応できます。

## 5. ビルド、リリース、実行: 開発プロセスを効率化！

コードのビルド、リリース、実行をそれぞれ独立したプロセスとして定義します。

**メリット**: 自動化しやすくなり、開発の効率が飛躍的に向上します。CI/CDツールとの連携もスムーズです。

**例えば**: GitHubにプッシュされたコードは、自動的にテスト、ビルド、デプロイされるように設定できます。

## 6. プロセス: アプリはステートレスに設計！

アプリの状態を保持せず、リクエストごとに必要な情報を外部から取得するように設計します。

**メリット**: スケールアウトが容易になり、高負荷時にも安定したパフォーマンスを発揮できます。

**例えば**: ユーザーのカート情報は、アプリサーバーのメモリではなく、データベースに保存します。

## 7. ポートバインディング: サービスはポートで公開！

アプリは特定のポートで待ち受け、外部からのアクセスを受け付けます。

**メリット**: Webサーバーなどを別途用意することなく、アプリ単体で動作させることができます。

**例えば**: ECサイトは、ポート80でHTTPリクエストを受け付けます。

## 8. 並行性: 複数のプロセスで処理を分散！

複数のプロセスで処理を並列化することで、パフォーマンスを向上させます。

**メリット**: より多くのリクエストを処理できるようになり、スケーラビリティが向上します。

**例えば**: ECサイトへのアクセス集中時、複数のプロセスでリクエストを処理することで、ダウンタイムを防ぎます。

## 9. 廃棄容易性: アプリはいつでも停止・起動可能に！

アプリはいつでも停止・起動できるように設計します。

**メリット**: デプロイやロールバックが迅速に行えるようになり、システムの可用性も向上します。

**例えば**: ECサイトのバージョンアップ時、ダウンタイムを最小限に抑えながら、新しいバージョンをデプロイできます。

## 10. 開発/本番一致: 環境の差異を最小限に！

開発環境と本番環境の差異を最小限に抑えることで、予期せぬ問題発生を防ぎます。

**メリット**: Dockerなどの仮想化技術を使うことで、環境の差異を吸収しやすくなります。

**例えば**: ECサイトの開発環境と本番環境で、同じDockerイメージを使うことで、環境差異による問題を減らせます。

## 11. ログ: ログはイベントストリームとして処理！

ログはファイルではなく、イベントストリームとして出力します。

**メリット**: ログの管理・分析が容易になり、問題発生時の原因究明に役立ちます。

**例えば**: ECサイトのアクセスログやエラーログは、リアルタイムに収集・分析することで、問題発生時の迅速な対応を可能にします。

## 12. 管理プロセス: 管理タスクもコードで管理！

データベースのマイグレーションなどの管理タスクも、コードで管理します。

**メリット**: 管理タスクの自動化が容易になり、ヒューマンエラーを防ぐことができます。

**例えば**: ECサイトのデータベーススキーマの変更は、マイグレーションスクリプトをバージョン管理システムで管理し、自動実行します。

## 🚀 まとめ

Twelve-Factor Appは、クラウドネイティブなアプリ開発の成功に欠かせない原則です。これらの原則を理解し、実践することで、より高品質なアプリをより効率的に開発できるようになります。

あなたもTwelve-Factor Appをマスターして、クラウドの住人になりましょう 🚀
Docker DesktopとVSCodeを利用した開発環境のパフォーマンスを上げる方法

# 背景
開発環境をDockerコンテナで立ち上げ、VSCodeの拡張機能 (Dev Containers) でDockerコンテナに接続していた。
ソースコードはホストからDockerコンテナにマウントしていた。
この環境だとソースコードの読み込みやDockerコンテナにインストールした拡張機能の読み込みが極端に遅くなってしまう問題があった。
この問題を解消できたため記事に残す。

# 前提
* ホストOS: Windows
* Docker Desktop: WSL版
* VSCodeのDev Containers拡張機能を使って開発環境を立ち上げている

# 原因
WindowsとLinuxのファイルシステム差異によるものだった。
ソースコードは背景に書いたとおりである。ホスト（Windowsのファイルシステム）からDockerコンテナ（Linuxのファイルシステム）にマウントしていた。
Dockerコンテナにインストールした拡張機能についても同様である（多分）。Dockerコンテナにインストールした拡張機能は、ホストのマウント元に保存されてるみたい（Dev Containersのdocs見たけど情報を見つけられなかった）。

# 解消法
ファイルシステムを統一してしまえば解決する。
MicrosoftとDockerがdocsで推奨している。
* https://code.visualstudio.com/docs/devcontainers/containers#_open-a-wsl-2-folder-in-a-container-on-windows
* https://docs.docker.com/desktop/wsl/best-practices/

## 構成図
パフォーマンス改善後の開発環境の構成図を以下に示す。
![名称未設定ファイル.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750246/dbe2c143-1511-0975-7071-415da4cd1386.png)

## 手順
1. VSCodeにRemote Development拡張機能を導入する
1. WSLにUbuntuディストリビューションをインストールする
    1. https://learn.microsoft.com/ja-jp/windows/wsl/install#change-the-default-linux-distribution-installed
1. Docker DesktopがUbuntuで動くように設定する
    1. https://docs.docker.com/desktop/wsl/
1. Ubuntuのコマンドラインを開く
1. 必要に応じてGitやSSHの設定をする
1. VSCodeで開きたいディレクトリ (`.devcontainer`があるディレクトリ）に移動する
1. `code .`を実行する（VSCodeのWSL拡張機能でカレントディレクトリが開かれる）
1. 開かれたVSCodeのコマンドパレットで`Rebuild and Reopen in Container`を選択する
【Python】初心者でも理解できる！入力テンプレート・小技集

まえがき
----- 
どうも、著者の凛乃です。本当に無名の端くれですが、
本当にわかりやすく書いているので多分初心者でもわかりやすいと思います。
あとここに書いているのはかなーり基礎的な内容です。
本当に学びたいならもっと他のサイトの方がよっぽど参考になると思います。
今回は初心者向けに、
Pythonで入力を受け取って変換するまでの大体のパターンをまとめました。
この標準入力ネタはどこの界隈でも擦られすぎて$n$番煎じどころか$n^2$番煎じだと思ってます。

入力テンプレート(解説付き)
-----
<br>

```Python:basic_io.py
#この辺りは本当に基礎の基礎。使えないとコードを書けないレベル。　
#使用頻度:★★★★★ 難易度:★

string_data = input() #文字として受け取る
number_data = int(input()) #文字として受け取ったものをint型に変換
```
※基本的に使う型はint、string、list、場合によりfloatぐらい。他は大体代用品があります。

:::note warn
このコードを書いた時に読み取るのは1行分まとめて！
`1 2`のような入力は、`int(input())`では読めません。
(後でこれを読めるようなコードを説明します)
:::
<br>

```Python:multi_variables_io.py
#ちょっと応用してみよう 使用頻度:★★★ 難易度:★
number_data_1,number_data_2=int(input()),int(input())
```
実はただ横並びになっただけである。`,`で区切れば何個でも繋げられる。
そこまでいったら繰り返しを使ったほうがラクだと思うが…

:::note info
`1`<br>`2`のような**縦に並んだ入力**を読めるようになります。
:::
<br>

```Python:list_io.py
#リストの入力をやってみよう(文字)　使用頻度:★★★★ 難易度:★★
string_list = list(input())
#['f','o','o']←こんな感じに入ってます
```

文字のリスト化を行うと1文字ずつリストに入っていき1文字ごとの処理がしやすくなります。

#### ここから難易度少し上がります

```Python:multi_words_list_io.py
#リストの入力をしてみよう(文字列)　使用頻度:★★★★★ 難易度:★★
multi_words_list = list(input().split())
#['foo','bar']
```

さっきの`list_io.py`と一緒っぽいことしてるけど何が違うの？と言われそうですが、`.split()`というものが結構重要です。(というかそこをなくしたら一緒になる)

`.split()`はstring型で使える関数(厳密にはメソッドだが)のひとつであり、()内で指定した文字で区切られ、リストとして返ってくる。
<br>
次にやりたいことこそ、`1 2`のような空白区切りの入力を読むことです。
一応今まで習った知識だけでも一応書けないことはない。(非推奨)
まず紹介するのは今までに習った入力方法で書いてみる。
```Python:numbers_list_io.py
#リストの入力をしてみよう(数字) 使用頻度:★★★★★ 難易度:★★★
string_numbers_list = input().split() #まず文字として受け取る
numbers_list = [] #変換したリストを受け取るリスト
for i in string_numbers_list:
    i = int(i)
    numbers_list.append(i)
#[1, 2]
```

ちょっと応用した書き方だが、このような書き方もある。
ちなみに`.append()`はリストの1番後ろに要素を追加する関数である。
```Python:advanced_numbers_list_io.py
#これは無理に覚えようとしなくていい
numbers_list = list(map(int,input().split()))
```

ここで突然出てきた`map`関数の使い方だが、
今のところこの関数をリストに対してやってくださいぐらいの認識で問題ない。

入力受け取り・応用編
-----

ここからは大体ここまでの入力受け取りの合わせ技である。その一部を紹介。

#### 複数変数を一気に読む
```Python:multi_variables_io.py
a,b,c = map(int,input().split())
```

#### 縦に並んだリストを読む
```Python:vertical_list_io.py
x,y = [],[]
for i in range(リストの長さ):
    xy=input().split()
    x.append(xy[0])
    y.append(xy[1])
```

あとがき
-----
今回記事を初めて書いてみて、意外と書く内容が思いつかず思ったとしてもなんか違ったりと
苦戦しました。なのでこれから精進します。
かんたん曜日表示WEBアプリ※.html,.css,.js総計70行ない!

# はじめに
今日はサマーウォーズのフィルムコンサートということもあり，日付から秒で曜日を算出し表示するWEBアプリケーションを作ってみたのでここに残します．
本当に最低限の機能なので，デザインとかうんぬんかんぬんはありません！
実際のWEBアプリは[こちら](https://hiromu16.github.io/park/your-web-app/)です．
先週から，突発的に[WEBサイト](https://hiromu16.github.io/park/)も作り始めたので，これは研究の息抜きに成長させていきます．
html，css，javascriptの３つのファイルをすべて同じフォルダに格納してください！
## 注意！
現在，PCではギリで数値を打ち込めるようになってますが，スマホ等だとカレンダーしか出てこなくてただのカレンダーアプリと化しています

# HTML
```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>日付から曜日を求めるアプリ</title>
    <title>Date2DayOfWeek</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>日付から曜日を求めるアプリ</h1>
    
    <div id="app">
        <label for="dateInput">日付を入力してください（例：2024-06-30）:</label>
        <input type="date" id="dateInput" required>
        
        <button onclick="calculateDay()">曜日を表示</button>
        
        <div id="result"></div>
    </div>

    <h2><a href= "C:\Users\hiro_\git-box\park\index.html">HOMEへ戻る</a></h2>
    
    <script src="script.js"></script>
</body>
</html>
```

# CSS
```css:style.css
body {
    font-family: Arial, sans-serif;
    margin: 20px;
}

#app {
    margin-top: 20px;
}

input[type="date"] {
    margin: 10px 0;
    padding: 8px;
}

button {
    margin: 10px 0;
    padding: 10px 20px;
    background-color: #007bff;
    color: white;
    border: none;
    cursor: pointer;
}

button:hover {
    background-color: #0056b3;
}

#result {
    margin-top: 20px;
    padding: 10px;
    background-color: #f0f0f0;
    border-radius: 5px;
}
```

# Javascript
```javascript:script.js
function calculateDay() {
    const dateInput = document.getElementById('dateInput').value;
    if (dateInput) {
        const date = new Date(dateInput);
        const weekdays = ["日", "月", "火", "水", "木", "金", "土"];
        const day = date.getDay();
        const resultText = weekdays[day] + "曜日";
        
        document.getElementById('result').textContent = "入力された日付は " + resultText + " です。";
    } else {
        document.getElementById('result').textContent = "有効な日付を入力してください。";
    }
}
```
表記の訂正 (paizaランク C 相当)


問題
----------------------------------------------------------------------
paiza 研究所では実験データをわかりやすい形式で保存したいのですが、
機械によって得られる数値には、次のような表記ミスがあることがわかっています。

・ ミス 1
先頭に必要のない 0 がいくつかついてしまう
・ 本来 1 である数値が 0001 と表記されてしまう
・ 本来 0.001 である数値が 00.001 と表記されてしまう

・ ミス 2
小数である数値の末尾に必要のない 0 がいくつかついてしまう
・ 本来 0.1 である数値が 0.10 と表記されてしまう

・ ミス 3
小数である数値に小数点が複数個ついてしまう
ただし、 1 つめの小数点の位置が正しい小数点の位置であるものとします
・ 本来 0.123 である数値が 0.1.2.3 と表記されてしまう。

表記が正しくない可能性のある数値を表す文字列 S が与えられるので、その数値を正しい表記にしてください。
S を数値として扱うと上手く処理が行えないので気をつけてください。

----------------------------------------------------------------------
解答例だとループ回したりして面倒な感じだったので置換や正規表現でやりました
----------------------------------------------------------------------
```python3
import re
s=input()
if "." not in s:
    #ピリオドがなければ整数として扱う
    print(int(s))
else:
    #最初のピリオドを置換して退避
    s = s.replace('.','*',1)
    #その他のピリオドをカット
    s = s.replace('.','')
    #退避した文字をピリオドに戻す
    s = s.replace('*','.')
    #行頭の0の連続をカット、行末0の連続をカット
    s = re.sub('^0+','',s)
    s = re.sub('0+$','',s)
    #その結果、ピリオドで始まるなら0.に置換
    s = re.sub('^\.','0.',s)
    print(s)
 ```
tmuxを使って快適Linuxライフ

# はじめに
Linuxでkubernetesをいじっていた時にtmuxがとっても便利だったので使い方を以下に整理しました。

tmuxを使っている様子
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/d8bf4b66-d131-1326-4af8-631a8c8f9201.png)

# tmuxとは
1つのターミナルで複数のターミナルセッションを管理できるツールです。これにより、1つのターミナルウィンドウ内で複数のシェルセッションを実行し、それらを分割表示したり、バックグラウンドで実行したりすることができます。

主な機能は以下の通りです
- 複数のセッション管理
一つのターミナルウィンドウ内で複数のセッションを作成し、切り替えることができます
- ウィンドウとペインの分割
一つのセッション内でウィンドウを作成し、それをさらに縦や横に分割して複数のペインを表示できます
- セッションのデタッチとアタッチ
セッションを一時的にデタッチして、後で再度アタッチすることができます。これにより、長時間実行するタスクを中断することなく続行できます
- セッションの持続性
リモートサーバーでの作業中に接続が切れても、セッションが保持されるため、再接続後に作業を再開できます

# 用語
- セッション
一つのプロセスとかウィンドウみたいなイメージ。

- ウィンドウ
タブみたいなイメージ。

- ペイン
タブの中からさらに画面分割するみたいなイメージ。

# よく使うコマンド
新規セッション作成&そこに入る
```
tmux
```
セッション一覧
```
tmux ls
```
セッション、ウィンドウ、ペインの終了
```
exit
```
（セッションの状態を維持したまま）終了
```
Ctrl + b → d
```
Ctrl + bをprefixといい、prefixを押しても画面上何も変わらないが、その後に色々なキーと組み合わせることでtmux上の操作が可能な仕組み。

prefixを変更する
~/.tmux.confを新規作成し、以下を記載する（例）

```
set -g prefix C-q
unbind C-b

# | でペインを縦に分割する
bind | split-window -h -c '#{pane_current_path}'

# - でペインを横に分割する
bind - split-window -v -c '#{pane_current_path}'

# Vimのキーバインドでペインを移動する

bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

# VimのキーバインドでPaneをリサイズする
bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5
```

上記の後、以下を実行する。

```
tmux source-file ~/.tmux.conf
```


セッションに再接続
```
tmux a
```
セッションに名前を付けて、そこに接続
```
tmux new -s work1
```
名前をつけたセッションに接続
```
tmux a -t work1
```
ウィンドウの作成
```
prefix → c
```
ウィンドウの移動
```
prefix → ウィンドウ番号
```
ウィンドウの削除
```
prefix → &
```
ペインを上下分割
```
prefix → “
```
ペインを左右分割
```
prefix → %
```
ペインを移動
```
prefix →矢印キー
```
ペインのサイズ変更
```
prefix →Alt+矢印キー
```
時計を表示
```
prefix → t
```

全てのペインに対して操作をする方法

```
# シンクロの開始
tmux set-window-option synchronize-panes on

# 複数ペインに同じ入力が行われる

# シンクロの終了
tmus set-window-option synchronize-panes off
```

参考

https://mo-gu-mo-gu.com/tmux-basic/#i-4
【PHP】トレイトとは

## トレイトとは
PHPにおけるコード再利用のための仕組みの一つで、複数のクラスで共有したいメソッドやプロパティを定義するもの。
これにより、共通の機能を複数のクラスで簡単に共有でき、コードの重複を避けられる。


## 実装例
Cacheableというトレイトを定義し、その中にcacheMethodというメソッドを持たせている。
```php
// トレイトの定義
trait Cacheable {
   public function cacheMethod($key, $value) {
       // キャッシュ機能を実装するコード
   }
}
```
クラスでこのトレイトをuseすることで、cacheMethodが使えるようになる。
```php
// トレイトの使用
class SomeClass {
   use Cacheable;

   public function someMethod() {
       // このクラスはCacheableトレイトのメソッドを利用できる
       $this->cacheMethod('key', 'value');
   }
}
```

トレイトを使うことで、共通の機能を簡単に再利用できる。
【プラクティス紹介】1分でさらっと分かる「ユーザーサファリ」

## プラクティス名
ユーザーサファリ

## プラクティスの目的・狙い
* エンドユーザー像とその課題を掴む
* 誰がどのような状況でプロダクトを使っているのか理解を深める
* プロダクトの目的（意義）を再認識する

## どんな時に使うか
* プロダクトを改善するヒントを集めたい時
* 開発チームにユーザー（と使用環境）をリアルにイメージさせたい時

## 実施手順
1. プロダクトのユーザーがたくさん居そうな場所（＝訪問先）を探す
1. 事前に、何を観察するか/どんな質問をしたいか/記録方法などを決めておく
1. 現場ではペアに分かれて、目立たないようにユーザーがプロダクトを使う様子を観察する
1. ときどき静かに業務手順や使い勝手などについて質問し、メモする
1. 観察終了後、チーム全員でメモ/気づき/所感などを共有する


※チェックシートの例（観察目的によって内容は適宜見直す）
| 観察/質問のポイント | 記入欄/回答欄 |
|:--|:--|
| どんな環境（状況）で使っているか  |   |
| どんなデバイスで使っているか  |   |
| どの機能がよく使われているか|   |
| どの作業に時間がかかっているか|   |
| 操作に迷っている箇所はないか  |   |
| 前工程または後続作業は何か  |   |
| 他のアプリと併用しているか  |   |
| 改善したいところはあるか  |   |
| 追加で欲しい機能はあるか  |   |
| その他、印象に残ったことや気づき  |   |


## アレンジ例
* Yes/Noで回答できる質問だけでなく「使いやすくするには、どうしたらよいと思いますか？」といったオープンクエスチョンも織り交ぜる
* 中には批判的なユーザーがいることも想定しておき、批判も改善のヒントとして受け入れるようチームにマインドセットしておく

## アンチパターン
* 多人数で一人のユーザーを取り囲み、質問攻めにする（→プレッシャーを与えてしまう）
* 観察される側に、訪問日時や目的などが伝わっていない（→警戒され、防御的な反応に）

## 参考情報
出典は以下の書籍です。『ゾンビスクラムサバイバルガイド』

https://www.maruzen-publishing.co.jp/item/b304740.html

## こぼれ話（私的コメント）
自身のスクラムチームでもいつかはやりたいプラクティスです。
ただ僕の周囲ではあまり実施されているのを見かけません。実際にやるとなると、ユーザーオフィスへの入館手続きとかセキュリティ上のルールとか色々ダンドリが大変だったりするからでしょうか。プロダクトの利用現場がオフィス以外（例えば実店舗とか工場内とか）の場合はとくに。
それでも現場に出向いて初めて気づけることは山のようにあり、例えば工場内で手袋した状態じゃ細かいタッチ操作はできないとか、ちょっとアラーム鳴らしたぐらいじゃ騒音で気づけないとか、ユーザーからしたら当たり前のことでも開発者にとっては想像するのが難しかったりもします。
また実際に使う人たちの顔がイメージできている、ということはあらゆるモノづくりにおいて非常に重要な要素だと思います。自身の体験でも、自分たちのプロダクトをユーザーが使っているシーンを実際に目にした時、ハッキリと意識が変わったのを今でもよく覚えています。まさに「百聞は一見に如かず」ですね。チームのモチベアップにもつながりそう。

---
　[アジャイルプラクティス一覧へ戻る](https://qiita.com/kakashi_h5/items/20584998c5ca4594b9ea)
[ローカルLLM] dockerでOllama, web-uiをとりあえず動かしたい人用 CPU利用 [低スペックPC]

#  前提
Windows 10
Docker Desktopを使用

# 手順
1. yamlファイルをダウンロード
以下のURLにアクセスしyamlファイルをダウンロード
https://github.com/open-webui/open-webui/blob/main/docker-compose.yaml


2. 適当なフォルダに配置する
C:\docker\ollama_webui\docker-compose.yaml


3. PowerShellを起動し実行する

```
cd C:\docker\ollama_webui
docker compose up -d
```

4. URLにアクセス
http://localhost:3000/
【Rails】前のページに戻るボタンの実装方法

## はじめに
Railsの戻るボタンの実装について、「button_to」を使用した記事がなかったので、
link_toとbutton_toを使用した2パターンの実装についてまとめてみました！

## 実装コード
下記のコードで、「一つ前に表示していた画面に戻る」という機能を簡単に実装することができます！
### 戻るリンク
```
<%= link_to '戻る', :back %>
```

### 戻るボタン
```
<%= button_to '戻る', :back, method: :get %>
```

## 参考
[【Rails】戻るボタンの実装方法【複数ページ戻ることも可能】](https://qiita.com/nekojoker/items/cb662de7cbb65e438985)
[『戻る』ボタンを 『link_to』 ではなく、『button_to』 で作成したい](https://teratail.com/questions/280995)
SPIKE PrimeでもPybricksを導入する

## Pybricks インストール

今回は Pybricks を使用してプログラムを書いていくので、早速 SPIKE Prime にインストールしていきます。

https://docs.pybricks.com

### DFU モード接続

まず Hub を DFU モードで起動する必要があります。
一度 Hub の電源を切り、USB ケーブルも抜いてください。

Hub の Bluetooth ボタンを押した状態で USB ケーブルを繋げてみてください。
Bluetooth ボタンが紫色に光るはずです。でも Bluetooth ボタンを話すのは待って！もう少し押したままにしましょう。

カラフルに点滅し始めましたか？これが DFU モードです。

### ドライバーインストール

早速 Pybrick のインストールに進みたいですが、その前に Hub の USB ドライバーを書き換えなくてはなりません。

:::note info
もし Mac OS を使っている場合はドライバーのインストールは不要です。Zadig はダウンロードせず、次に進んでください。
:::

[Zadig - USB driver installation made easy](https://zadig.akeo.ie/)

![zadig_site](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883745/d0b02e19-013d-f36f-3b4d-1512558e3b68.png)

Zadig x.x をクリックしてダウンロードします。
今ダウンロードされた `Zadig-x.x.exe`を起動します。

![zadig](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883745/0e8d5df5-b88a-2f66-15b8-6c2bcf64209b.png)

「LEGO Technic Large Hub in DFU Mode」と「WinUSB」を選んでください。くれぐれも別のデバイスを選択しないように。気をつけろ～。

「Install Driver」を選び、ドライバーをインストールします。

しばらく待って、「The driver was installed successfully.」と表示されればドライバーインストールは完了です。

:::note info
こちらのドライバーは一度 Hub にインストールすると、その後はこの手順を踏む必要はありません。
:::

### いざインストール

[Pybricks Code](https://code.pybricks.com/)

こちらのサイトは Pybricks のオンラインエディタです。今回はこちらを使ってインストールを行います。

ロードが少し時間がかかるので、気長に待ちましょう。

「Install Pybricks Firmware」を押すと、デバイスの選択画面が表示されます。

![select_spike](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883745/a6f66765-c7bf-610f-59b4-d82419dc85d4.png)


SPIKE Prime を選択し、「Next」を押します。次に同意画面が表示されるので、チェックを入れて「Next」を押します。

![naming_spike](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883745/6d669f49-aaf0-d7eb-d557-7985e3a56663.png)


Hubの名前は 15 文字までかつ英数字のみ設定可能です。Bluetoothで接続するかつ複数Hubを持っている際は名前がないと接続先が指定できません。

先ほどと同じようにして DFU モードで接続しましょう。そして「Install」を押します。

![ubs_connect](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883745/c674a606-fac1-16b6-1cf9-f2d2e95967fb.png)


このようなポップアップが表示されるので、「LEGO Technic Large Hub in DFU Mode」をクリックし接続します。

すると自動で書き込みが始まるので少し待てば完了です。

## Pybricks インストール
Powershellで以下のコマンドを実行し、2つのツールをインストールします。
```bash
pip install pybricks
pip install pybricksdev
```

## デバッグ設定
VSCodeでデバッグできるように設定をします。

まずフォルダに`.vscode`フォルダの中に`launch.json`ファイルを作ってください。

```bash
pybricksdev run ble main.py
```
こちらのコマンドをデバッグで自動的に実行するように以下のようなJSONを書きます。
```json
{
  "version": "0.0.1",
  "configurations": [
    {
      "name": "Pybricks BLE",
      "type": "debugpy",
      "request": "launch",
      "module": "pybricksdev",
      "args": ["run", "ble", "${file}"],
      "console": "internalConsole"
    }
  ]
}
```

これにて`F5`キーを押すとデバッグが動き、SPIKEで現在のプログラムが実行されるようになります。

:::note info
現在、Pybricks は USB による接続ができないようです。
詳細はライブラリフォルダから`pybricksdev/connections/lego.py`の73行目あたりを見ればわかると思います。
:::
拡張機能（OneTab）でパソコンのパフォーマンスを上げよう

# どんな内容の記事?
- PCのパフォーマンスを上げる方法を紹介

# どんな人に読んでもらうのが良い?
- 普段、タブをたくさん開く人

# 先に簡単にまとめる
- タブをたくさん開くと、その分メモリやCPUなどを使うからパソコンのパフォーマンスが落ちる
- OneTabを使うとタブがまとめられてパフォーマンスが落ちない！

# OneTabとは?
- タブを１つにまとめられる拡張機能ツール。まとめられたタブはリスト状態になる。
- つまり、メモリなどを使わなくなるのでパソコンのパフォーマンスが落ちる原因を回避できる！！

# OneTabの使うまでの工程
1. [OneTab](https://chromewebstore.google.com/detail/onetab/chphlpgkkbolifaimnlloiipkdnihall?hl=ja)へ行く
1. 赤い矢印をクリックしてインストール
![OneTab.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1578844/cb668957-bef0-2ebb-537d-eb45911a3328.png)
1. すぐ使えるように赤い矢印を押してOneTabのアイコン（緑色の枠）を表示させておく
![キャプチャ6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1578844/0b31b5cd-bc6d-3f4b-2189-e3d40519fa37.png)

# OneTabを使ってみよう
1. こんな感じでタブが開いていたら……
![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1578844/07a3965a-67b2-dec4-c2b2-535058085159.png)
1. OneTabのアイコンをクリック！！すると、赤い枠のように1つのタブにまとまります
![OneTab (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1578844/73777e77-7a90-c366-08cc-a96610ee607a.png)
1. 閉じたタブを戻したい時は、戻したいタグをクリック！
![OneTab (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1578844/03074cbf-160f-2bf5-0829-f718364b213e.png)
1. ご覧のようにGoogleのタブだけ戻りました
![キャプチャ4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1578844/bc96f277-30a6-b6a6-f0dd-623047f1a3aa.png)

# OneTabを使った感想
慣れるまでは逆に効率が悪い感じでしたが、慣れると必要なタブだけ表示できるようになりスッキリします！

最後までご覧いただき、ありがとうございました！！
Power Query - 通信ログから、同じIDの送信と受信の時間を比較する

# 概要
入力テーブルとして、ID毎に送信と受信が対になっている、時系列順のテーブルを用意します。
この入力テーブルから、同じIDの送受信の組み合わせをマージしたテーブルを作成する方法を考えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/215a7681-769d-88bf-4f43-473dfa7566f0.png)

# コード
作成したコードは下記のとおりです。
```PowerQuery:送受信の比較
let
    ソース = 通信ログ,
    グループ化された行 = Table.Group(ソース, {"Id", "Dir"}, {{"AllRows", each _, type table [Time=nullable number, Id=nullable text, Dir=text]}}),
    追加されたカスタム = Table.AddColumn(グループ化された行, "AddRank", each Table.AddIndexColumn([AllRows], "Rank", 1, 1)),
    #"展開された AddRank" = Table.ExpandTableColumn(追加されたカスタム, "AddRank", {"Time", "Rank"}, {"Time", "Rank"}),
    TxTable = Table.SelectRows(#"展開された AddRank", each ([Dir] = "Tx")),
    RxTable = Table.SelectRows(#"展開された AddRank", each ([Dir] = "Rx")),
    マージされたクエリ数 = Table.NestedJoin(TxTable, {"Id", "Rank"}, RxTable, {"Id", "Rank"}, "RxTable", JoinKind.FullOuter),
    #"展開された RxTable" = Table.ExpandTableColumn(マージされたクエリ数, "RxTable", {"Id", "Time"}, {"Rx.Id", "Rx.Time"}),
    #"名前が変更された列 " = Table.RenameColumns(#"展開された RxTable",{{"Time", "Tx.Time"}, {"Id", "Tx.Id"}}),
    削除された他の列 = Table.SelectColumns(#"名前が変更された列 ",{"Tx.Time", "Tx.Id", "Rx.Time", "Rx.Id"}),
    #"追加された条件列 - Sequence" = Table.AddColumn(削除された他の列, "Sequence", each if [Tx.Time] < [Rx.Time] then "TxFirst" else if [Tx.Time] > [Rx.Time] then "RxFirst" else null),
    #"追加されたカスタム - Delay" = Table.AddColumn(#"追加された条件列 - Sequence", "Delay", each Number.Abs([Tx.Time] - [Rx.Time]))
in
    #"追加されたカスタム - Delay"
```

`Table.Group`を使って「Id」「Dir」をキーにグループ化します。
このあと「AllRows」の値を「Id」を使ってマージさせたいのですが、複数行が含まれる場合に問題となるのでもう一手間を加えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/2b2fc737-336c-e441-3a6a-a824b21bce05.png)

`Table.AddIndexColumn`を使って「AddRank」列を作成します。
これによって「Id」「Dir」「Rank」からマージするためのキーが一意に定まります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/9699fde7-d8ad-5942-a84d-b5d37ed29174.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/9dc003a8-0bc3-bec4-0a98-4f3f03db9c2c.png)

「Dir」によってフィルターした「TxTable」「RxTable」を作成して、それらをマージします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/5a8f1023-c20a-d031-b157-4db3044a43a9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/f5959c6d-e319-7e43-4218-eb2d052147c5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/cfb14761-c1c5-611a-4f9c-b9683bd554c8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/0bc1d562-bbbc-3c6d-ff03-817deb118845.png)

不要な列を削除してテーブルを整形します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/6854d50d-59b7-6a90-96fe-4f4705fa207d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/70bbc191-9641-22ee-f803-bdcfadff859d.png)

「Sequence」「Delay」列を計算したら完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/18c515b1-22cc-5ed0-7cd5-0b0aad222cfc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/cfbe9772-c520-500b-2514-5bd756d0c68b.png)
小数点以下の表示

整数同士の割り算は、小数点以下が切り捨てられる。

```
1 / 3
=> 0
```

直接数値同士を計算する場合は、どちらかの数値に.0をつけることで小数点以下を表示可能。

```
1.0 / 3
=> 0.3333333333333333
```

変数を使用して計算する場合はto_fメソッドで整数から少数に変更可能。

```
a = 1
=> 1

a / 3
=> 0

a.to_f / 3
=> 0.3333333333333333
```