OmniAICreator/Qiita-1.07M huggingface dataset:
【Google Cloud Next Tokyo ’23レポート】2023 年版: アプリケーションをどこで動かすべきか

# 概要
 Google Cloud では、 VM からサーバーレスまでアプリを動かすための様々な選択肢があります。また、開発プロセス全体を考えると、開発環境や CI/CD なども検討する必要があります。本セッションでは、アプリ基盤の特徴、ユースケースをご紹介するとともに、一連の開発プロセスにおける開発者体験を向上させる方法について、2023 年現在の最新情報を交えて紹介します。

 
Google Cloud 岩成 祐樹
カスタマー エンジニア、スタートアップ リード

https://cloudonair.withgoogle.com/events/next-tokyo?talk=d1-app-03
# 所感
GCPには、コードを実行する環境としてこんなのがあるよ、な話。

やはりプロダクトをどう動かしたいか？で選ぶサービスが変わりそう。
特に大きなポイントは、サーバーレスで構築するかどうか。

この辺りはどのクラウドベンダーでも同じ印象。


# 内容メモ
## コードの実行サービスたち
### conpute engine
- いわゆるクラウドサーバー。AWSでいうEC２
- ライブマイグレーション
    - 物理ホストの更新に際に再起動不要
        - 正確には、仮想マシンをを動かしているので、サービスを止めないで、パッチ適用ができる
### GKE（kubernetes）
- フルマネージドなk8sサービス
    - standard
        - ノード設定の柔軟性
        - コントロールプレーンがマネージド
    - AutoPilot
        - 完全マネージド
        - standart + ノードもマネージド
        - 本番ワークロードに適したベストプラクティスに

### cloud run
- コンテナ＋サーバレス
- サーバーレスのアジリティにコンテナ化したサービス
- 100ミリ秒単位で課金
- 8vCPU 32G RAM
- デプロイするとURLエンドポイントが発行される

### App Engine
- マネージドなサーバーレスプラットフォーム
- インフラ管理は不要
- 対応言語あり
    - python
    - java
    - php
    - Goなどなど
- 静的・動的コンテンツを利用するWEBアプリ

### cloud Functions
- 様々なGCPリソースのイベント連携
- Faasフレームワークを利用し、ロックインを回避
- サーとパーティのAPIとの統合
- リアルタイムファイル処理

### ユースケース
GKEか、サーバーレスか、が大きな分岐

## アプリケーションをどう動かすか
- 開発
    - cloud workstations
    - GCPユーザーのためのマネージドな開発環境
    - ブラウザで動くIDE。VScodeなイメージ
    - AWSでいうcloud9
    - 全体の開発環境の管理
    - セキュリティポリシー
    - 開発者は、オンデマンドで利用できる
        - どこからでもアクセス可能
        - 設定済みの開発ツール
        - チーム間で統一、一貫性
    - 生成AIによる支援
    - クラウドで動くが、ローカルサーバー的な使い方もできる
        - portに対してのURLが発行される
- CI
    - cloud build
    - jobにおるbuild環境
- CD
    - cloud Deploy
    - GKE、cloud Runへのデリバリー
# 関連記事
- [【Google Cloud Next Tokyo ’23レポート】 by yukiMiyoshi_fcafe](https://qiita.com/yukiMiyoshi_fcafe/items/18ad65426e1a71311419)
- [【Google Cloud Next Tokyo ’23レポート】 by sho_fcafe](https://qiita.com/sho_fcafe/items/a97ee90d6a05f68e1c01)
【Google Cloud Next Tokyo ’23レポート】働き方と働く環境をデータで可視化！イトーキ様分析ツール開発事例に学ぶ

# 概要
自由度の高い働き方が広まる昨今、従業員の働き方の実態やそれがもたらす影響を把握することが難しくなっています。今回アイレットはイトーキ様の分析ツール「ITOKI OFFICE A/BI」の開発を支援いたしました。Cloud Storage や BigQuery 上のデータを ETL し、アプリケーションから参照し可視化を実現。豊富な開発実績を活かしオフィス内センシングデータを用いた分析ツール開発事例をご紹介します。

アイレット株式会社 後藤 和貴 氏
執行役員 エバンジェリスト

# 所感
オフィスの行動データを可視化し、より効率のいいオフィスであるにはどうすればいいか？
という分析を行うその着眼点は、さすがイトーキさん。

ここでの話は、OFICCE　A/BIというツール開発において、イトーキさんと協力して
必要な機能を取捨選択し、UI改善を行なっていったという話。

実際にどんな分析データがあって、どう活用して・・・というのは、
イトーキさん自身による別のセッションで話がありましたが、
なんとそれに出れず。。。ちょっと悔やまれる。

# 内容メモ
## データ活用における課題
- 日本は、米国・ドイツなどに比べると進んでいない
- 企業がデータ収集をおこない、活用する事で、経営に役立つ

## コロナ後の働き方
- オフィス回帰の傾向
- 平均出社日数 4.6日/w
- オフィス内でのWEB会議の場所が不足
    - オフィス回帰をしても、WEB会議は依然として残る

オフィス回帰により、オフィス利用が変容している
↓
オフィス利用のデータが必要

## イトーキの事例
働く環境づくりに力をいれている。
### 課題TOP３
- せっかく作ったのに使われないスペースがある
- 決めたルール通りにオフィスを使ってもらえない
- オフィスの変化に社員の意識が追いつかない

### OFICCE　A/BI
イトーキが運用するオフィス内における従業員の行動データを可視化し分析するプロダクト
- 稼働データ
- 環境データ
- 活動データ
を収集し、可視化。
様々なサービスの創出へ

オフィスワーカーの働き方をサポート
業務恋率化
提案活動のサポート

従来のオフィス構築プロセスから変革

## どんなデータ？

- レイアウト
    - スペースの座席、面積、用途、目的

### workers trail
- IkTセンサーを活用してアクティビティ分析
    - 誰がどのように動いたか
    - どれぐらい滞在したか
    - APIからデータ取得可能

### performance trail
- アンケートサービス
    - 一人一人のサーベイデータ
- 別のサービスを利用していて、エクスポートデータを活用


## プロトタイプの機能の絞り込み
- 多機能すぎて選別が必要になった
- ソースコードも複雑な状況
→サービスとして必要な機能は何か？を検討
あるべきアプリケーションの姿を定義

## ETL
workers trail、performance trailから、
cloud storage → cloud functions → BigQuery

## UI/UXの改善
- 従業員のパフォーマん
- データを組み合わせた分析

　### 課題
 PocフェーズではpythonフレームワークDashを活用。これをこのまま採用したいが、
 デザインにこだわったレイアウトを実装するにはやりづらい。

 ### 改善例
 - 社員属性による絞り折り込み
 - 特定の位置における利用者の専有率表示

## まとめ
- 提案型のアプリ機能の絞り込み
    - 必要な機能の絞り込み
- 分析機能の向上
    - CSVからBigQueryの連携でパフォーマンス向上
- UI/UXの改善
    - エンジニアとデザイナーのコラボで、採用技術の変更なしに機能的で使いやすい形に
# 関連記事
- [【Google Cloud Next Tokyo ’23レポート】 by yukiMiyoshi_fcafe](https://qiita.com/yukiMiyoshi_fcafe/items/18ad65426e1a71311419)
- [【Google Cloud Next Tokyo ’23レポート】 by sho_fcafe](https://qiita.com/sho_fcafe/items/a97ee90d6a05f68e1c01)
ITパスポートに合格した話

先日ITパスポートを受験して<font color="Silver">ギリギリ</font>合格したので勉強方法を備忘録として執筆しました。
<img width="300" alt="IT パスポート試験結果レポート 黒塗り" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2866526/29f48c97-db43-6e39-b2dd-5b20394d6e78.png">

ネットを見ると「２週間で合格」とかいう記事があったり。。。でも、記憶力や現時点での知識量は人それぞれ。自分がこれから覚えるべき知識量、勉強に割ける時間などを見積もったうえで、勉強計画を立てるところをスタートラインにする。

# 必要なもの
- 参考書
　可能な限り新しいバージョン、かつ使いやすいと感じる参考書。自身は用語索引がついていた「[いちばんやさしいITパスポート](https://it-pass.jp/)」を使用。

- 過去問題集
　[公式の過去問](https://www3.jitec.ipa.go.jp/JitesCbt/html/openinfo/questions.html)があるが、問題と正答のみで解説はなし。「なぜこの選択肢は間違いなのか」が理解できないといけないので、**解説付きの教材がおすすめ**。自身は参考書と同会社の無料アプリ「[ITパスポート 絶対合格の問題集](https://apps.apple.com/jp/app/it%E3%83%91%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%88-%E7%B5%B6%E5%AF%BE%E5%90%88%E6%A0%BC%E3%81%AE%E5%95%8F%E9%A1%8C%E9%9B%86/id1644270066)」[^1]を使用。

# 勉強手順
自分の場合、どのような勉強計画を立てるにしても、この３つが軸。

１．１回で完璧に覚えない
２．過去問練習は正義
３．得意を伸ばすより苦手をつぶす

以下に詳しく👇

## １回で完璧に覚えない
覚える量がとにかく多い。じゃあどうするか。

**脳は繰り返すことで覚える**[^2]ので、参考書を何周もする。全く知識がなければ、最初から最後までページをめくるだけとか、各章のまとめを一通り読むだけとかで大丈夫。
単語が分からなくても気にせず次に進む。

上記を何回か繰り返したら本文を読む。
内容がスラスラ入ってくるまで参考書を周回。

## 過去問練習は正義
参考書をスラスラ読めるようになったら過去問を解く。これは「どこを理解していないのか」をあぶりだすためにやるので、正答率はあまり気にしない。

間違えた選択肢を確認して、「なぜ自分が選んだ選択肢は違うのか」や「なぜ正答はこの選択肢なのか」など**根拠を明確にする**。もちろん間違えた問題はチェック✅

正解だったけど自信がなかった問題も、「正答の根拠」と「他の選択肢と迷った理由」を明らかにしておく。

これを繰り返して苦手分野を浮き彫りにする。
もちろんチェック✅したは定期的に復習。

## 得意を伸ばすより苦手をつぶす
苦手分野が分かったら、その範囲の参考書読み込みと過去問練習。

こうすることで克服することで全体の得点が上がりやすくなる。
過去問と似通った問題が本番出題されることも…！

あと、参考書に手をかける前に、**試験日を決めて受験料払っちゃう**のがおすすめ。モチベーションがあがるので。

今回は以上です。

[^1]:投稿時点ではApp Storeでの配布のみ。Google Playにはありませんでした。
[^2]:STUDY HACKER「[確実に結果がついてくる “繰り返し” 勉強法。最高の学習回数は「7回」「3回」「4回」だ！](https://studyhacker.net/study-7-3-4-times)」より引用。「同じ情報を繰り返し脳に送ると、海馬に「生きていくのに必要な情報だ」と判断させ、記憶として定着させることができる」。
SteamDeckからrEFIndをアンインストールする方法

SteamDeckからrEFIndをアンインストールする方法の日本語の情報が存在していなかったのでメモ
Windoswを入れてデュアルブートにしてみたものの、Windows全然使わなかったので消すときに必要でした。

Konsoleから
```Konsole
$ efibootmgr
BootCurrent: 0000
Timeout: 0 seconds
BootOrder: 0002,0000,0001
Boot0000* rEFInd
Boot0001* SteamOS
Boot0002* Windows Boot Manager
```

表示されたrEFIndの番号(ここでは0000）を使って
```Konsole
$ sudo efibootmgr -b 0000 -B
```

詳しくはこちらを参照のこと。
https://github.com/jlobue10/SteamDeck_rEFInd
【Google Cloud Next Tokyo ’23レポート】AWSとGoogle Cloud の垣根を超えてデータを活用する方法

#　概要
AWS上のRDSやCloud SQLなどのデータベースからBigQueryへのリアルタイムなデータ連携を実現し、またGoogle CloudにおいてOpenSearchやCassandraなどAWSと同じマネージドのデータ管理基盤を整えることで、クラウドの垣根を超えて新規プロジェクトや新規事業にデータを活用する方法を、ベスト プラクティスやユースケースも含めてご紹介します。

Aiven Japan 合同会社 嘉門 延親 氏
カントリーマネージャー

https://cloudonair.withgoogle.com/events/next-tokyo?talk=d1-pl-01
# 所感
マルチクラウド、という選択は現状では選択肢に上がってきたことはないが、
その冗長性の確保やいいとこ取りをする、という観点は確かにその通りで、
クラウドは誰にも平等に使用できるようになっているので、いいとこ取りで使えるなら、ひとつのクラウドに固執せずに使うべきと思いました。

しかしながら、それを実現するためのハードはかなり高く、
aiveさんのようなサービスがないと運用コスト、構築コストがかなりのものになる。

マルチクラウドの課題を解決するソリューションを使う事で、
それぞれのサービスにとって、まさにいいところだけを活用していく、
僕らクラウドユーザー側にとってのメリットは大きそう。
# 内容メモ
## なぜマルチクラウド？
- クラウドのいい部分を使う
- ベンダーロックインの回避
- 費用対効果
    - クラウドによって、サービスによって価格が違う
- 革新的なテクノロジー
- 高度なセキュリティと規則遵守
- 信頼性と冗長性の向上

## 現実
- 管理の複雑性
    - リソースが限られている
- 一貫したセキュリティーの維持
- ソフトウェア環境の統合
- クラウド間で一貫したパフォーマンスの信頼性と実現が難しい
*GCPではマネージドで提供されていないものもある*
→追加コスト、リソース
- apache kafka
- openseach

## aiven
- 自社の既存の利用はそのまま活用
- 複数のクラウドで利用可能
- コストも全てまとめて固定で提供
- OSSのデータ基盤をマルチクラウドで展開
-  クラウドにはそれぞれのお作法ががある
    - セットアップ
    - バックアップの有無、方法
    - コスト
    - モニタリング
- 各クラウドの上位レイヤーにaivenが存在する
    - aiven上で、サービスと展開したいクラウドを選択
    - 10分でプロビジョニング
- コストを、全てのクラウドを含めて固定で一括で提供


## 普通にマルチクドにする際の課題
- マルチクラウドの管理の複座さ、運用コスト
- データ抽出のバッチ
- NWコストの読みづらさ
- 既存構成の変更は最小限にしたい
- クラウド感のデータ転送によるセキュリティ
*→これらをaiveが解決*

## AWS　にはあるがGCPにはないマネージドサービス
- コストの問題
    - ライセンス購入
- セルフマネージドのリスク、煩雑さ
# 関連記事
- [【Google Cloud Next Tokyo ’23レポート】 by yukiMiyoshi_fcafe](https://qiita.com/yukiMiyoshi_fcafe/items/18ad65426e1a71311419)
- [【Google Cloud Next Tokyo ’23レポート】 by sho_fcafe](https://qiita.com/sho_fcafe/items/a97ee90d6a05f68e1c01)
【Next.js】CSR, SSR, SSGの違いについて

業務でCSRアプリの開発に携わる機会があったので、これを機にSSRやSSGとの違い等について整理しておこうとおもいます。

## CSR
### 概要
1. client side rendering
2. 名前の通り、クライアント側（ブラウザ）でレンダリングする

### 処理の流れ
1. 初回アクセス時に、ほぼ空っぽのHTML, CSS, JavaScriptをレスポンスとして受け取る
2. 受け取ったブラウザは、HTML, CSS, JavaScriptをもとにレンダリングする

## メリット
1. 静的ファイルを返せるホストサーバーであれば、(S3でも可)デプロイができる
1. ページ遷移のたびに、サーバにリクエストする必要がない
1. 処理がブラウザ内で完結するのでページ遷移が速い
1. サーバーは初回リクエスト時にHTML, CSS, JavaScriptを返すだけなので、負荷が軽い

## デメリット
1. 初期ロードが重くなる
1. 初期ロードのHTMLは空っぽなので、SEOに不利

## SSR
### 概要
1. server side rendering
1. 名前の通り、サーバー側でレンダリングする

### 処理の流れ
1. 初回アクセス時に、ほぼ空っぽのHTML, CSS, JavaScriptをレスポンスとして受け取る
2. 受け取ったブラウザは、HTML, CSS, JavaScriptをもとにレンダリングする


メリデメは基本的にCSRの逆になる。
## メリット
1. 初期ロードが軽い
1. SEOに有利

## デメリット
1. デプロイするのに、Node.jsを必要とする
1. ページ遷移のたびに、サーバにリクエストする必要があるので、CSRより遅い
1. リクエストのたびにサーバーでレンダリングするため、CSRより負荷が高い

## SSG
### 概要
1. static site generator
1. 静的サイトジェネレーター
1. CSRもSSRもリクエスト後にレンダリングするが、SSGはビルド時にプリレンダリングしておく点がCSR、SSRと異なる


### 処理の流れ
1. アプリケーションのビルド時に、APIなどからデータを取得し、HTMLをプリレンダリングしておく
1. サーバーにリクエストがきたら、このHTMLファイルを返す


## メリット
1. CSR同様、静的ファイルを返せるホストサーバーであれば、(S3でも可)デプロイができる
1. プリレンダリングされたHTMLを返すだけなのでSSRより表示速度が早い


## デメリット
1. データ量が多いと、ビルドに時間がかかる
1. コンテンツのリアルタイム性がない

## メリデメまとめ
この観点でみると、SSG最強に見えますが、SSGの利用範囲は限定的ですし、用途に応じて適切に使い分けできるとよいですね！

||CSR|SSR|SSG|
|--| -- | -- | --|
|初期表示速度	|×	|○|	◎|
ページ遷移速度	|○|	△|	○
デプロイ|	○|	×|	○
|SEO	|×|	○|	○
サーバー負荷	|○|	×|	○
|リアルタイム性|○|○|×
REST APIって何なの？

# 背景

DjangoとVue.jsでブログサイトを作成中にDjango REST frameworkを使おうとしたが、  
そもそもREST APIがよくわからなかったため調査。

&nbsp;

# 調査結果

REST とは設計思想(あるいはアーキテクチャパターン)。  
下記4つを満たしていればREST APIを自称していい様子。

| 設計思想 | 説明  |
| --- | --- |
| 統一インターフェース | GETやPOSTなどのHTTPメソッドを使用する。レスポンスにJSON形式などを用いる。 |
| ステートレス | クライアントやサーバがセッションなどで状態を記憶する必要がない。 |
| 階層型システム | クライアントはURIをもとにAPIに接続するため、接続先のサーバやプロキシを意識する必要がない。  <br>たぶん。。。 |
| キャッシュ性 | キャッシュを用いてクライアントとサーバ間の通信を減らす。 |

&nbsp;

本当はRESTの設計原則6つなので下記2つの点も満たしたほうがよい。

| 設計思想 | 説明  |
| --- | --- |
| コードオンデマンド | JavaScriptなどのコードをクライアントがDLして実行する。 |
| クライアント/サーバ | クライアント。サーバアーキテクチャのこと。つまり、クライアントがリクエストを送信して、サーバが処理するようなアーキテクチャ。 |

Django REST frameworkなどのフレームワークを使ってWeb APIを作れば、自然とREST APIが作れます。

# 所感

今までWeb APIを作る仕事をいくつかしてきたが、  
それがREST APIなのかを特に意識せずに作業していました。  
  
しかし、Web APIなら当たり前だと思っていたことがREST APIの特徴として挙げられていました。  
私はREST APIを作成した経験があると自称ししていいのかもしれないと感じました。（自信がないので経歴書に大きくアピールはしませんが。。）

# 参考サイト

https://docs.aws.amazon.com/ja\_jp/appsync/latest/devguide/what-is-rest.html  
https://www.infraexpert.com/study/sdn09.html  
https://www.strategit.jp/column/041304/  
https://www.redhat.com/ja/topics/integration/whats-the-difference-between-soap-rest  
  
公式ドキュメント  
https://restfulapi.net/
【Day 3】画面デザインを作ろう

## はじめに

![スライド4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/41cce49a-d05d-bb80-6578-0304a211f9f9.png)

---

**2023年アドベントカレンダー3日目**です。

https://qiita.com/advent-calendar/2023/life-sync-app

昨日はユーザーストーリーを作成しました
今回からは際にストーリーを消費していきます。

デザインのストーリーについてとりかかろうと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/de517270-a63d-a5cf-eb2f-92ef9ca67244.png)

デザインの作成には**Figma**を使ってみようと思います。

https://www.figma.com/ja/

## Figmaとは

https://ferret-plus.com/13195

## Figmaの使い方

私はFigmaをきちんと学んだことはないので、私のやり方は敢えて載せません
本格的にFigmaを学びたい場合は`Udemy`や、技術ブログ、`Youtube`などで学ぶことをお勧めします

https://www.profuture.co.jp/mk/column/39138

ただし、デザインを作りながら、コンポーネントの設計をなんとなくしておくと実装時に楽ですし、コンポーネントを意識したデザインになっていると実装時に楽になります。

### コンポーネントとは

要素・グループを再利用可能な「コンポーネント」として定義して、プロジェクト全体で呼び出せるようにする機能のことです。
これにより一貫性が維持され、変更容易性が向上します。

例えば**Submit Button**コンポーネントを作成し、それをコピーして作っ**Submit Button**インスタンスがあるとします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/9dc0ca01-733f-127e-26f4-b10996f9a1ae.png)

プロジェクトで使うボタンをコンポーネントからのインスタンス作成にしておくと、もしもSubmitボタンのデザインが変更されたとき、コンポーネントを変更するだけで、全てのプロジェクト内のインスタンスに変更が反映されます。

![SubmitButton.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/1366b64c-5101-f8f4-7524-267a6f698d2e.gif)

また、プロパティを設定してプロパティごとのデザインを設定することもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/e0bcfa26-abf4-f3e6-e301-0632d6316588.png)

:::note info
私のおすすめとしては、使う色や余白は、
使う予定のCSSのフレームワークに合わせておくことです。
今回はTailwindCSSのスタイルに合わせてデザインしました。
:::

## 完成品

### リンク

https://www.figma.com/file/x3naaj1e69BxmwaYY4dbTY/LifeSync?type=design&node-id=0-1&mode=design&t=1GqPefwi0i9skFNI-0

### コンポーネント

#### Button

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/cd1b9283-d328-9965-1bb7-43fb012c7aed.png)
左）type=submit
右）type=cancel


#### BlogCard

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/10a6fb9c-97cf-164f-5f18-5b8120554419.png)

#### BlogForm

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/f6dfd8ba-d8d1-67f5-a947-c4823b839717.png)


### TOPページ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/57ad5e90-abf8-bd9b-87e6-e544b004614b.png)

### ブログ詳細画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/971464f8-c271-da05-1fad-4fe41722f711.png)

### ブログ作成画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/d6aa7aee-fc85-f708-00d6-f7167cd4783b.png)

### ブログ編集画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/76cf1f3e-0531-c790-6a06-8008aa5c612c.png)

まとめて紹介してしまいましたが、これでデザイン系の3ストーリーが消費できました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/fb216c71-29aa-ed87-a4e7-f599820ab851.png)

明日からは開発環境を構築していきます！
死の呪文になりうるコマンド「ｒｍ」


## 何故この題材にしたのか
　Linuxを触る機会が増えて、新卒文系ということもあり先輩にこのコマンドが実行されてしまった場合、どれほど恐ろしいことになってしまうのかというのを教えていただきました。
実際にテスト環境でテストフォルダを作成してコマンドを試した所、本当に全部消えてしまって新卒なりにこのコマンド怖いなと感じ、間違いは起こさないようにしたいと思ったからです。

## 「ｒｍ」コマンドについて
```
rm
```
このコマンドはファイルを削除するものです。
使い方は「rm オプション」「rm -rオプション」といった形をとって使用します。
オプションの種類を抜粋すると以下があります。
| オプション| 内容                                        |
| :------: | :------------------------------------------------- |
| rm -f| 確認せずに削除する |
|rm -i|削除実行前に確認メッセージを表示する         |
|rm -I|3つ以上のファイル・ディレクトリ毎削除する際に確認確認メッセージを表示する|
|rm -r|ファイルを再帰的に削除する|
|rm -v|削除されたファイルのリストを表示する|
|rm -d|空のディレクトリを削除する|
||               etc... |



そして一番使用してはいけないのは、、、
```
rm -rf
```

こちらです。
コマンドの意味としては「再帰的に強制的にファイルを削除する」です。
このコマンドは多大な危険性を孕んでいるので使用自体を禁止する場所も多いそうです。
これを使用すると全てを無に帰すので細心の注意を払わなければなりません。。。


## rm -rfの危険性

　一つの危険性としては、もしroot権限でこれを実行してしまうとバックアップなどを取っていない限り今までの努力が全て消えてしまう恐れすらあることです。
また同プロジェクトに関わっている全ての人に迷惑がかかることは間違いないでしょう。。。

## この危険を回避するために・・・
①まずこのコマンドを使用しないのが一番良い対策となるでしょう。
　藪をつついてわざわざ蛇を出さないのが安心安全です。
②万一、使用する場合は隣に他のエンジニアを付けて二重確認をガチガチに行うのを徹底しましょう。
これらを徹底すれば間違いを起こすのは限りなく減らすことができるでしょう。。。

## まとめ
　この「rm」コマンドは使用に注意しなければならない削除コマンドのほんの一部の一部です。
これから自分がコマンドを使用していく中で、「rm」コマンドや別のコマンドに触れる際にはしっかり危険性を理解して使用しようと思います。
数値を異なる長さで 2 行出力 Python3編

続いてこちら
https://paiza.jp/works/mondai/stdout_primer/stdout_primer__variable_array_step2

数値 N と M が与えられるので、 1 行目には N 個、 2 行目には M 個の数値を出力する、という問題。

私はこちらの回答.

```py
arr = input().split()
for i in range(1,int(arr[0])+1):
    if i == int(arr[0]):
        print(i)
    else:
        print(i,end=" ")
for j in range(1,int(arr[1])+1):
    if j == int(arr[1]):
        print(j)
    else:
        print(j,end=" ")

```
可読度をあげるなら、
問題にかかれているように

```py
arr = input().split()
N = int(arr[0])
M = int(arr[1])
```
としたほうがわかりやすい。

ちょっと回答を出すのに手間取ったので復習

range(1,3）という場合には
1,2だけとなって３は含まれない。
**だから、1~3まで出したい場合は、
range(1,4)としないといけない。**

逆に、ifなどでループカウント数がMAXの時
を指定したい場合は
普通に i = Nのときと出せばOK
【Flutter】Flutter x Firebaseで作成したアプリのリポジトリを公開するまでにしたこと

先日、[リリースしたFlutterアプリ](https://qiita.com/yakuran1/items/1ecfbb2ba70cb80f88ea)をGithubに公開しました。

個人でしっかり作成したアプリを公開するのは初めてだったので、
各種サービスへの接続情報や機密情報の取り扱いであったり、セキュリティの設定で悩んだので、
備忘録もかねてまとめたいと思います。

利用しているサービスによって設定の要否が変わってくると思うので、
分類別に記載していきます。



## 公開したソースコード

https://github.com/yakitama5/korehosi



## 🔥Firebase

### 全般 (App Check)

Firebaseを利用している場合、基本的にはApp Checkを適用することをおすすめします。

App Checkの機能や設定方法については、こちらの記事が大変参考になりました。

https://zenn.dev/flutteruniv_dev/articles/20230316-172748-flutter-firebase-app-check

Webの対応についても[公式ドキュメント](https://firebase.google.com/docs/app-check/web/recaptcha-provider?hl=ja)に沿ってやれば問題なく行うことが出来ます。
[Cloud Functionsにも適用可能](https://firebase.google.com/docs/app-check/cloud-functions?hl=ja)なので、適用しておきましょう。

:::note warn

執筆時点(2023/11/15)では、[**WebのreCAPTCHA Enterpriseにバグがある**](https://github.com/firebase/flutterfire/issues/11777)ようで適用すると動かなくなりました。
状況を確認して適用して下さい。

:::

### Cloud Firestore / Firebase Storage (セキュリティルール)

ソースを公開しなくても必要ですが、公開の前にあらためて見直しした方がいいと思います。

セキュリティルールのためにドキュメント構造自体を変更する必要も出てくるので、
早い段階でセキュリティを意識して設計を組むことをおすすめします。

セキュリティルールについてはこちらの記事を参考にしました。

https://qiita.com/KosukeSaigusa/items/18217958c581eac9b245

Firebase Storageのルールについては、
Firestoreのデータ参照などが必要でしたので、こちらの記事を参考にしました。

https://zenn.dev/sgr_ksmt/articles/b6590bf2a474ba

### Firebase Auth (with Identity Platform)

料金プランが変わってしまいますが、
**Identity Platform**へのアップグレードをおすすめします。

認証方法が広く選択できることもありますが、
**App Checkを適用する場合に必須要件**となることが一番の理由になります。

通常のFirebase Authとの違いについては、こちらのドキュメントを参照して下さい。

https://cloud.google.com/identity-platform/docs/product-comparison?hl=ja

## 💻Flutter

### 接続情報/設定ファイル

アプリをリリースする以上、完全に非公開にすることは出来ませんが、
Github上で管理対象外に設定したり、難読化したり、ある程度のセキュリティを担保できます。

対応は大きく分けて3種類行いました。

#### .gitignore

業務でGitを利用していればアタリマエの話ではありますが、
アクセスキーなどの接続情報や設定ファイルについては、`.gitignore`に設定して管理対象外にしておきましょう。

FirebaseのAPIキーなどは公開しても問題ないのですが、
App Checkを設定していなかったり、セキュリティルールが不足していた場合に簡単にアクセス出来てしまうので、
私はGithub上には公開しないようにしています。

```gitignore
# アクセスキーなどの接続/設定ファイル
ExportOptions.plist
dart_defines/**
scripts/**
GoogleService-Info.plist
google-services.json
env*.g.dart
firebase_options*.dart
firebase_app_id_file.json
```

#### Envied (難読化)

設定ファイルの難読化を行ってくれます。

「難読化すれば全部あげて大丈夫🤪」というわけではなく、
あくまでリリースした資産をデコンパイルされた場合の保険です。

Enviedで難読化したとしても、
生成したファイルをGithub上などに公開すると簡単に復元出来てしまうので注意が必要です。

導入はとても簡単で、[パッケージの利用方法](https://pub.dev/packages/envied#usage)で完結してます。
補足としては以下の点のみです。

- 定義ファイルに型を指定する必要がある
- 難読化(`obfuscate`)を指定する場合は定数利用できなくなる

[**公開リポジトリ**](https://github.com/yakitama5/korehosi/blob/main/lib/env/env.dart)でも利用していますので、参考になれば幸いです。

#### Secret scanning (Githubの設定)

キチゲ解放のためにAPIキーをプッシュしたくなる時ありますよね

そんな時に備えて、
Github上でも[**Secret scanning**](https://docs.github.com/ja/enterprise-cloud@latest/code-security/secret-scanning/about-secret-scanning#about-secret-scanning-for-partner-patterns)を設定しました。

すべてのアクセスキーが100%防げるかどうかはわかりませんが、
プッシュ操作自体をブロックすることも可能なので、念のため設定しました。

## 🙇最後に

**最後までお読み頂きありがとうございました。**

セキュリティ対策はどこまでやっても不安が拭えないと思います。
これからアプリを作成する方や、ソースを公開したいと思っている方に少しでも参考になれば幸いです。

また、対策に不備や不足などありましたらご指摘下さい。
AtCoderメモ

# この記事について
AtCoderのコンテスト参加中に操作がわからなくなったりした時のためのメモ
（ほぼ自分用です。。）

# 参加中に見るためのマニュアル
## テンプレコード
とりあえずファイル作ったらこれ貼っとけ（実務では決してこんなことすなよ）
```cpp
#include<bits/stdc++.h>
using namespace std;

template<class T> inline bool chmin(T& a, T b) {
    if (a > b) { a = b; return true; }
    else return false;
}
template<class T> inline bool chmax(T& a, T b) {
    if (a < b) { a = b; return true; }
    return false;
}

int main () {
  
}
```
ACLとchmin/chmaxはほぼ必須なイメージですな。。
## AtCoder CLI

http://tatamo.81.la/blog/2018/12/07/atcoder-cli-tutorial/

## VScodeでのデバッグ

https://note.com/fuuuuusha/n/n9c16247c49bc

# 環境構築系

https://qiita.com/EvtHorizonCoder/items/145724e16c1b57ab64eb

https://qiita.com/llr114/items/e7beb02d0bf461b3f8b8

https://spiralray.sakura.ne.jp/blog/cp/devenv-cpp
Adafruit_GFXとAdafruit_ST7735、ST7789でST7735、ST7789の表示(ESP32)まとめ


https://qiita.com/caa45040/items/285a406d1a033a3ddc59



---------------------------------------------------

aitendo ST7735 SPI


https://qiita.com/caa45040/items/e533f4c23f1237079ee6


https://qiita.com/caa45040/items/ee840fd94c91871d17ef


---------------------------------------------------

秋月 ST7789V2


https://qiita.com/caa45040/items/f27d84e4cebbe5567134


https://qiita.com/caa45040/items/ce3ad9e626482592f925
【Swift】Firestoreのエラーをローカライズする

# はじめに
Firestoreは便利ですが、SDKで定義されているエラーのerrorDescriptionは英語でそのまま使うとユーザーにとってわかりにくいものになってしまいます。
そこでFirestoreのエラーを自前でローカライズしてみようという記事です。

# 実装
StringCatalogを使うために`String(localized:)`で実装しています
```swift
import FirebaseFirestore
import FirebaseFirestoreSwift
import Foundation

public enum PostError: Error, LocalizedError {
    case firestore(FirestoreErrorCode.Code)

    public var errorDescription: String? {
        switch self {
        
        case .firestore(.OK):
            return String(localized: "操作は正常に完了しました")
        
        case .firestore(.cancelled):
            return String(localized: "操作がキャンセルされました")
        
        case .firestore(.unknown):
            return String(localized: "不明なエラーが発生しました")
        
        case .firestore(.invalidArgument):
            return String(localized: "無効な引数が指定されました")
        
        case .firestore(.deadlineExceeded):
            return String(localized: "操作がタイムアウトしました")
        
        case .firestore(.notFound):
            return String(localized: "ドキュメントが見つかりません")
        
        case .firestore(.alreadyExists):
            return String(localized: "作成しようとしたドキュメントは既に存在しています")
        
        case .firestore(.permissionDenied):
            return String(localized: "アクセス許可が拒否されました")
        
        case .firestore(.resourceExhausted):
            return String(localized: "リソースが枯渇しています")
        
        case .firestore(.failedPrecondition):
            return String(localized: "操作が拒否されました")
        
        case .firestore(.aborted):
            return String(localized: "操作が中止されました")
        
        case .firestore(.outOfRange):
            return String(localized: "許可されていない操作です")
        
        case .firestore(.unimplemented):
            return String(localized: "未実装またはサポートされていません")
        
        case .firestore(.internal):
            return String(localized: "内部エラーが発生しました")
        
        case .firestore(.unavailable):
            return String(localized: "サービスが利用できません")
        
        case .firestore(.dataLoss):
            return String(localized: "データの損失または破損しています")
        
        case .firestore(.unauthenticated):
            return String(localized: "認証情報が無効です")
        
        case .firestore:
            return String(localized: "不明なエラーが発生しました")
        }
    }
}
```

# 使い方
```diff_swift
private func fetchSample() async throws -> [Sample] {
    do {
        /// ... 処理

        let querySnapshot = try await query.getDocuments()
        
        /// ... 処理

        return querySnapshot.documents
+   } catch let error as NSError where error.domain == FirestoreErrorDomain {
+       let firestoreErrorCode = FirestoreErrorCode.Code(rawValue: error.code) ?? .internal
+       throw PostError.firestore(firestoreErrorCode)
    } catch {
        throw error
    }
}
```

# おわり
Firestoreのエラーを日本語対応する事ができました
単一スリットを通る波の回折と干渉および波の強度の定性的考え方

秋葉原ロボット部の読書会の教科書「量子力学10講」第1講で触れられた前提項目のうち、高校物理の教科書で取り上げられていない内容をメモ書きしたものです。

波面を無数の波源の集まりであるとみなし、波源から送り出される球面波を素元波といいます。
波面の各点からは、波の進む前方に素元波が出る。これらの素元波に共通に接する面が、次の瞬間の波面になります。これをホイヘンスの原理といいます。

また、図１の点Aの上側や点Gの下側で観察されるように、波が障害物の背後に回る現象を回折といいます。すき間の幅に対して、波長が小さいときの、波の回折の模式図を図に示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693019/89167f73-c263-d873-c504-d056243be343.png)
図１．波の回折の模式図。黒い太線は障害物。a)観測開始。太い白線が平面波。b)t秒後に平面波が障害物に到達。点AからGは波源。c)2t秒後。波源AからGから素元波（細い白線）が発生。観測されるのは、太い白線の波。d)3t秒後の波。点Aの上側や点Gの下側の点線は障害物の背後に回り込んだ波面。

次にスリットを通った波が、スクリーンに作る模様を考えます。単色光がスリットを通った場合、スリットの延長線上に、明線が現れ、その両側に明暗の縞現れます。これは、スリットで回折した光の干渉によるものです。

単一スリットを通った光が全て打ち消しあう場合を、図２の例で考えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693019/b5417a25-2464-b3af-3474-6ea3a112997d.png)
図２．波が打ち消しあう場合の単一のスリットを通る光a)幅dのスリットの部分を拡大。黒線はスリット、白線は一つの波源からの波の通り道。実線の白線は角度θ1傾いた場合。破線の白線はまっすぐ進んだ場合。点　　A、B、Cは波源。DはBからAA’に下した垂線の足。EはCからAA’に下した垂線の足。b)黒線はスクリーン。P0はまっすぐ進んだ光の到着点。P1は角度θ1に傾いて進んだ光の到着点。

スリットに対してまっすぐ進む光は、スリットの延長線上に明線を作ります。

スクリーンに対してθ1の角度で傾いた場合、例えば、波Aと波Cの光が同時にP1点につく場合、AとCの光路差はAE=dsinθ_1になります。波長をλとした場合、AE=λ/2×2、 AD=λ/2であるなら、波Aと波Bの点P_1での位相差はπなので、打ち消しあいます。同様の考え方をすると、隣接する波の光路差が波長の半分になる場合、スクリーンの到達点の位相差はπとなり打ち消しあい、P_1は暗点となります。

最後に、光が一部打ち消しあう場合を、図３の例で考えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693019/9c4ab9e5-c2be-7f6b-a0fa-e6c54e552fda.png)
図３．波が一部打ち消しあう場合の単一のスリットを通る光。a)スリット近傍の拡大図、b)スクリーン近傍。線の意味は図２と同様。

最後に、波が一部打ち消しあう例を考えます。図３でFL方向の延長上に点P_2があるとします。FL=dsinθ_2=λ/2×3の場合、FJ=JK=KL=λ/2となるので、点Fから点Hの間に入射した光は図2の点Aから点Cに入射した光と同様に打ち消しあいます。一方、点Hと点Iの間に入射した光は打ち消しあわずに点P2に到達します。点P_2の明るさは点P0のものより暗くなります。

光路差とスクリーン上での明暗の結果をまとめます。
sinθ_1=λ/2×2：暗い
dsinθ_2=λ/2×3：やや明るい

さらにスリット幅を4分割、5分割して考えると、以下の様になります。
sinθ_3=λ/2×4：暗い
sinθ_4=λ/2×5：わずかに明るい
これらをまとめると、光路差と明るさの関係は以下の様になります。
dsinθ=λ/2×2n：暗い(nは自然数)
dsinθ=λ/2×(2n+1)：明るい(nは自然数)。ただし、nが大きくなると、明るさは急激に小さくなる。

本稿には、単一スリットを通る波の回折と干渉および波の強度の定性的な考え方を示しました。定量的に考える場合、無限個の光に対して上記の考え方を適用することと、スクリーン上の光強度分布を考える際に、波の振幅の2乗が光の強度に相当することを使うことの2点を使って導出します。例えば、2000年の鳥取大学の入試問題の物理の大問4が参考になります。

参考文献　「新課程　親切な物理　下巻」渡辺久夫著、正林書院、昭和58年。
#### djangoでイメージを表示するのにメッチャ苦労した件

#### djangoでイメージを表示するのにメッチャ苦労した件

この前linuxやwslで動かしていたdjangoの静的な画像ファイルを表示するのにものすごく苦労しました。

原因は{% get_static_prefix %}tcgcreatorとすべきところを{% get_static_prefix %}/tcgcreatorとしていました。

こんな単純なところでハマった私が恥ずかしいです
datadogのデプロイメントの追跡をversionタグで実施する


datadogマニュアル

https://docs.datadoghq.com/ja/tracing/services/deployment_tracking/

コンフィグレーション章の通り作業を実施
https://docs.datadoghq.com/ja/getting_started/tagging/unified_service_tagging/?tab=ecs#%E3%82%B3%E3%83%B3%E3%83%95%E3%82%A3%E3%82%AE%E3%83%A5%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3-1

`完全なコンフィギュレーション`で設定するが、環境変数に設定してればdocekr labelはなくても表示できた。

## 変更点

- ./docker/php/www.conf
```
env[DD_ENV] = $DD_ENV
env[DD_SERVICE] = $DD_SERVICE
env[DD_VERSION] = $DD_VERSION
env[DD_PROFILING_ENABLED] = true
```

- task difinition
    - DD_VERSIONはgithub　ationsの中で設定
```
省略
        {
            "name": "php",
            "image": "imagename",
            "cpu": 0,
            "portMappings": [],
            "essential": true,
            "environment": [
                {
                    "name": "DD_ENV",
                    "value": "dev"
                },
                {
                    "name": "DD_SERVICE",
                    "value": "datadog-test"
                },
            ],
            "mountPoints": [],
            "volumesFrom": [],
            "secrets": [],
            "dockerLabels": {},
省略
```

## 課題
- DD_VERSIONをデプロイの都度更新するにはどうすればいいか
    - `aws-actions/amazon-ecs-render-task-definition@v1` で解決
```
    - name: datadog
      uses: aws-actions/amazon-ecs-render-task-definition@v1
      id: render-datadog-container
      with:
        task-definition:task-definition.json
        container-name: datadog
        image: datadog/agent:latest
        environment-variables: |
          DD_VERSION=${{ github.sha }}
```
ElasticIPとパブリックIPの違いと必要性

# 【ElasticIP】パブリックIPとの違いと必要性

インターネット上でサーバーを運用する際、IPアドレスはそのサーバーへの「住所」として機能します。Amazon Web Services（AWS）で提供されるEC2（Elastic Compute Cloud）インスタンスには、パブリックIPとElastic IPという二種類のIPアドレスがあります。これらは似ているようでいて、重要な違いがあります。この記事では、EC2の概要と、パブリックIPとElastic IPの特徴、さらにElastic IPの必要性について初心者にも分かりやすく解説します。

## EC2の概要

### クラウド上の仮想サーバー

Amazon EC2は、AWSが提供するクラウドコンピューティングサービスの一つで、仮想サーバー（インスタンス）をオンデマンドで提供します。ユーザーは、必要に応じてサーバーの種類、サイズ、設定を選択し、クラウド上で自由に構築、管理することができます。

#### 特徴

- **柔軟性**: さまざまなタイプのインスタンスから選択可能で、用途に応じたリソースの確保が可能です。
- **スケーラビリティ**: 要求に応じてリソースを拡張・縮小でき、効率的な運用が可能です。
- **コスト効率**: 使用した分だけ料金を支払うため、コストを抑えてサーバーを運用できます。

## パブリックIPとElastic IP

### それぞれの特徴

#### パブリックIP

パブリックIPは、EC2インスタンスを起動する際に自動的に割り当てられる一時的なIPアドレスです。インスタンスを停止または終了すると、このIPアドレスは解放され、再起動時に新しいパブリックIPが割り当てられます。

- **一時的なアドレス**: インスタンスの起動・停止に応じて変動します。
- **コスト無料**: 追加料金なしで利用可能です。

#### Elastic IP

Elastic IPは、AWSが提供する静的なIPアドレスで、インスタンスに永続的に割り当てることができます。Elastic IPはユーザーに対して割り当てられ、特定のインスタンスに紐付けることが可能です。

- **静的なアドレス**: インスタンスを再起動しても変わりません。
- **コストが発生する場合がある**: 使用していないElastic IPは料金が発生することがあります。

## Elastic IPの必要性

### 固定アドレスの利点

Elastic IPは、インスタンスのIPアドレスを固定するために重要です。特に以下のような場面でその価値があります。

- **DNSとの統合**: 固定IPを持つことで、DNS設定を一度だけ行えば、その後のインスタンスの停止や再起動に影響されません。
- **信頼性の向上**: IPアドレスが変わらないため、外部からのアクセスやシステム間通信の信頼性が高まります。
- **管理の簡素化**: 複数のインスタンスを

運用する際に、IPアドレスを記憶したり、設定を変更したりする必要がなくなります。

## まとめ

AWSのEC2では、パブリックIPとElastic IPという二つの異なるタイプのIPアドレスが利用できます。パブリックIPは一時的でコストがかからない反面、インスタンスの停止や再起動で変更されるため、持続的な外部接続には不向きです。一方、Elastic IPは固定のIPアドレスを提供し、DNSとの統合や信頼性の向上に貢献しますが、使用していないとコストがかかる点に注意が必要です。これらの特徴を理解し、用途に応じて適切に選択することで、効率的かつ安全なクラウド環境を構築することが可能になります。
MinecraftServer機の移行をしてみた ~その3~

# Minecraft Server 移行大作戦その3
### 今回で移行完了までいきます

## ワールドデータをSCPでコピーしてくる
SSHでファイルをローカルにコピーしてくる方法がSCPなので、それを使ってコピーしていこうと思います  
私はwindowsからSSHしているので、WinSCPというフリーソフトを使ってGUI画面でSCPしました。(CUIのやり方難しかったのでチートしました)  
この時、移すデータはworld, world_nether, world_the_endの３つのディレクトリになります

## ワールドの起動
データを移行したあと、サーバーの起動をして正しく起動するか確認します
```
$ java -Xms8192M -Xmx8192M -jar server.jar nogui
```
この時、初回起動時はeulaのエラーで必ず失敗します。  
eula.txtを書き換えてtrueにしてください。

## ワールドに入る
MInecraftを起動して、新しいサーバーのIPでサーバーにログインします  
ここで成功すれば、移行完了になります

## まとめ
移行完了まで大体半日程度かかりましたが、スペックアップが成功したので快適になりました。  
既存のRaspberry piは別の用途に使ってみようと思います

## あとがき
途中で忙しくなってしまい、記事の存在を忘れてました...w  
今後はたぶんPython関係の記事を書いていこうと思います
【Google Cloud Next Tokyo ’23レポート】DAY1 Google Maps Platform を使った 物流ラストマイル最適化問題への 取り組み

# 講演概要
主に、物流、小売、フィールド サービス等（消費財メーカー等も含む）の業界のお客様向けのメッセージを中心に、Google Optimization AI の Cloud Fleet Routing API（CFR）と、Google Maps Platform の Mobility Solutions を使ったラストマイル輸送の最適化についてご紹介します。

セッション レベル：初級
取り上げる主な Google Cloud 製品 / サービス
BigQuery 
Vertex AI 
Google Maps Platform 

https://cloudonair.withgoogle.com/events/next-tokyo?talk=d1-aiml-08

# 所感

以前は物流系のシステムを担当していたこともあり、ラストワンマイル問題への取り組みの難しさはわかっていただけにGoogleが提供するサービスを活用することでさまざまな最適化が実施される、というのは素直にすごいなという印象でした。

話としては物流向けの話ではあったけど、荷受け人や発送者の体験に寄与する仕組みづくりという点では自分達のソリューションに取り入れていく場面もあるし、そういった選択肢を持っておくのはありだなーと思いました。

# 講演内容

## ラストマイル最適化問題とは

配送センターから荷受人までの領域（ラストワンマイル問題）
宅配便の取り扱い数の急増、ドライバー不足、2024年問題
→ 一人あたりの配送の生産性向上が急務

配送コストの最適化
- アイドルしている配送能力はないか？ 
- 無駄なルート組みがないか？ 
- 着車位置に関するナビゲーションミスがないか？

解決案仮説
- 各配送センター横断での配送能力の平準化
- 各配送単位の時間ベースでの最適化・効率化
- ナビゲーション精度向上によるリワーク低減

## GoolgeCloudのソリューション

Google Maps Platform - Mobility Services
- どこに届けるか（サジェストなどの住所入力時のUI、配達先の詳細、シグナルなどの配達時のUI）
- ルート・荷物割り当ての最適化（AIを用いて複雑なファクターを解析して最適なプランを出す）
- ナビゲーション（NavigationSDKを使うことで当日配達先の概要ビューや専用ナビゲーションの作成）
- 配達状況の可視化（NavigationSDKを使うことで荷受け人にも細やかなでリアルタイムな情報を提供）
- 車両のモニタリングと改善（オペレータ向けに車両位置や配達状況をリアルタイムで可視化、BigQueryへの連携することによる分析）

これらによってドライバー,お客様、配送システムそれぞれの視点で良い効果を得られる

## データ蓄積による最適化効果の最大化

Cloud Fleet Routing API
車両のルーティングサービスで、ラストワンマイルにおける最も効率的な計画を策定
GoogleストリートViewの撮影車両の配車計画をベースに作られた最適化エンジン

Cloud Fleet Routingで計画、Google Maps Platform - Mobility Servicesでデータを蓄積それを還元することでさらに良い計画を立案できるようになる

## パートナーソリューション

ここまで紹介したAPIやサービスを使った具体的なソリューションの紹介
AGLOP


# 資料リンク
【Google Cloud Next Tokyo ’23レポート】DAY1 SLO 監視でサービス品質を 一段上げる！ Google Cloud Monitoring 活用法

# 講演概要
Google Cloud では Cloud Monitoring の中でサービス監視という機能があります。これを用いると、SLO の監視が容易に可能になるだけではなく、それを元にしたアラート設計までシームレスに設定できます。本セッションでは、なぜ SLO が重要なのかを簡単に紹介した後に、サービス監視による SLO の監視とそれに基づくアラートの設定を、デモを交えて紹介します。

セッション レベル：中級
取り上げる主な Google Cloud 製品 / サービス
App Engine
Cloud Functions
Cloud Monitoring
Cloud Run
Google Kubernetes Engine (GKE)

https://cloudonair.withgoogle.com/events/next-tokyo?talk=d1-app-05

# 所感
改めてSLI/SLOについてわかりやすい説明をしてくれたので整理がつきました。
まずこれらをしっかり定義することも大切だけれど、それをちゃんと継続的に運用することが大切。
開発チームとしてもエラーバジェットを意識することで今ここで新しいことをしてもいいのか、という目安になるというのはとても役に立つ情報だった。

# セッションメモ
Cloud Monitoringのお話

SRE
本番システムを信頼性高く開発運用するためのプラクティスと心構え

信頼性指標の計測
抽象的な概念なので計測が難しい
これを定量的に測るにはどうするか？
→ 求められる機能を定められた条件の下で定められた期間にわたり、障害を起こすことなく実行する確率

SLI
信頼性に関する指標

SLO
信頼性に関する目標値

元データ
リクエスト・レスポンス（可用性、レイテンシー、品質）
データ処理（カバレッジ、正確性、鮮度、スループット）
ストレージ（スループット、レイテンシー）

SLI
(良いイベント / 有効なイベント) * 100%

SLO
SLIが（計測期間）の間に（目標値）となることを目標値とする

エラーバジェット（許容できるエラーの数）
SLOが決まると許容できるエラー数がわかるのでその許容内であればチャンレンジができる

バーンレートアラート
エラーバジェットの消費速度＝どれだけ早く問題が顕在化するか、どれくらいのスピード感でエラーに対応をすればいいかがわかる

これらの仕組みを継続的に計測・モニタリングするのはとても大変
→ そこでサービスモニタリングの話

デモ
マイクロサービスをサービスモニタリングする


# 資料リンク
M1/M2 macでPython−MIPを動かすには？

## M1/M2でPython−MIPは動かない？

普通に実行すると、M1/M2 macでは数理最適化のライブラリである[Python−MIP](https://www.python-mip.com/)が動きません。
Python 3.12ではPython−MIPの最新版をインストールできないので、Python 3.11を使います。最初に、Python−MIPが動かないことを確かめます。

```sh
% python3.11 -V

Python 3.11.6
```

Python−MIPをインストールします。

```sh
% pip3.11 install mip

（中略）
Successfully installed cffi-1.15.1 mip-1.15.0 pycparser-2.21
```

インストールは成功します。モデルを作ってみましょう。

```sh
% python3.11 -c 'import mip; m = mip.Model()'

An error occurred while loading the CBC library:
（中略）'.../lib/python3.11/site-packages/mip/libraries/cbc-c-darwin-x86-64.dylib'
 (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64')),
（中略）
NameError: name 'cbclib' is not defined
```

エラーになりました。これは、Python−MIPと一緒にインストールされたソルバーのCBCのライブラリがx86_64のバイナリだからです。

## M1/M2でPython−MIPを動かす方法

CBCのライブラリを動かすためには、x86_64のエミュレータであるRosetta2が必要です。
Rosetta2を有効にするには、一度だけ次のようにします。

```sh
% /usr/sbin/softwareupdate --install-rosetta --agree-to-license
```

Rosetta2を有効にすると`arch`というコマンドが使えます。
`arch`を使うと、次のようにしてx86_64のzshを起動できます。

```sh
% arch --x86_64 zsh
```

これだけでは、まだ動きません。さらに仮想環境で作業する必要があります。
仮想環境を作成し、アクティベートしましょう。

```sh
% python3.11 -m venv venv
% . venv/bin/activate
```

Python−MIPをインストールします。

```sh
(venv) % pip install mip

（中略）
Successfully installed cffi-1.15.1 mip-1.15.0 pycparser-2.21
```

ここまですると、次のように動かすことができます。

```sh
(venv) % python -c 'import mip; m = mip.Model()'
```

## まとめ

M1/M2 macでPython−MIPを動かすには、次の作業が必要でした。

- Rosetta2を有効にします。
- x86_64でzshを起動します。
- 仮想環境で作業します。

## 補足

PoetryでPython−MIPを動かしたい場合は、下記を参照してください。

https://qiita.com/SaitoTsutomu/items/aabb94db3f20cce3dc82

## 余談

Python−MIPは、[CFFI](https://cffi.readthedocs.io/)のインターフェースを使っているため、まとめで紹介したような作業が必要でした。
似たようなライブラリである[PuLP](https://coin-or.github.io/pulp/)は、CBCを外部アプリケーションとして使っているので、Rosetta2を有効にするだけで使えます。

参考：[M1/M2でIntel用ライブラリを利用する手順 - PyQドキュメント](https://docs.pyq.jp/python/library/install_m1_mac.html)

以上
Reactを学ぶために覚えたいJavascriptの基礎文法

# 目的
Reactを自己学習しています。その中でReactを学ぶにはjavascriptへの理解が必要であり、最低限の基礎的な文法をまとめました。自分の備忘録でもあり、これも学んだ方がいいというものがあれば、ぜひともコメントをお願いします。

# テンプレート文字列
${変数}のように記述する。javascriptでの変数や式はだいたい{}内に書く
```javascript
const name = "いとと";
 const age = "28";
 const message2 = `私の名前は${name}です。年齢は${age}です。`;
 console.log(message2);// 私の名前はいととです。年齢は28歳です。
```
# アロー関数
矢印=>を使って関数を定義する。従来のようにfunctionを使って定義をしなくてよいため、コードの可読性が上がる。
```javascript
functionでの定義
const func1 = function(str) {
    return str;
}
console.log(func1("func1です")); //func1です
```

```javascript
アロー関数
 const func2 = (str) => {
     return str;
 }
 console.log(func2("func2です"));//func2です
```

# 分割代入
配列から値を取り出したり、オブジェクトからプロパティを取り出して別個の変数に代入することができる。
```javascript
//オブジェクトからname,ageプロパティを取り出す場合
const myProfile  = { 
    name:"いとと",
    age: 28,
};
const {name, age} = myProfile;//name,ageプロパティを変数name,ageにそれぞれ割り当てる※この時、オブジェクトのプロパティ名と変数名は一致する必要がある。
const message2 =`名前は${name}です。年齢は${age}歳です`;//上記のname,age変数を参照
console.log(message2);
```

```javascript
//配列から取り出す場合
const myProfile =[`いとと`, 28]; //配列として定義
const [name, age] = myProfile;
const message4 = `名前は${name}です。年齢は${age}歳です`; // 順番が大事！
console.log(message4);
```
# スプレッド構文
...fooの形で定義され、配列やオブジェクトの要素を展開する。
```javascript
const arr1 =[1,2];
console.log(...arr1);//1 2 配列の中身を順番に処理
const sumFunc =(num1, num2) => console.log(num1 + num2);
sumFunc(...arr1);//3
```
# mapメソッドを使った配列の処理
ループを使った繰り返し処理をわざわざ書かなくてよい
returnされた結果に基づいて新しい配列を生成する
```javascript
const nameArr =["田中","山田","佐藤"];
const nameArr2 = nameArr.map((name)=>{
    return name;
})
 console.log(nameArr2);//["田中","山田","佐藤"]
```
配列をループして処理する場合
```javascript
const nameArr =["田中","山田","佐藤"];
nameArr.map((name) => console.log(name));//田中、山田、佐藤
nameArr.map((name, index) => console.log(`${index + 1}番目は${name}です`));
//1番目は田中です,番目は山田です,3番目は佐藤です
```
# Filter
ある条件に一致した値を取り出す
偶数を取り出す場合
```javascript
const numArr = [1, 2, 3, 4, 5];
const newNumArr = numArr.filter((num) => {
    return num % 2 == 0;
});
console.log(newNumArr);//[2,4]
```
特定の値だけ出力条件を変える（田中だけ呼び捨てにする）
```javascript
const nameArr =["田中","山田","佐藤"];
const newNameArr = nameArr.map((name) => {
    if (name == "田中"){
        return name
    } else {
        return `${name}さん`
    }
})
console.log(newNameArr);//['田中', '山田さん', '佐藤さん']
```
# 三項（条件）演算子
3つのオペラントをとる演算子。疑問符(?)、真値の場合の実行式、コロン(:)、偽値の場合の実行式の順に書く。
```javascript
const num = 1300;
console.log(num.toLocaleString()); //1,300カンマ区切りで表示
const formattedNum = typeof num == `number` ? num.toLocaleString() : `数値を入力してください`;
console.log(formattedNum); //数字の時はカンマ区切りで表示　文字ならば「数値を入力してください」

const checkSum = (num1, num2) => {
    return num1 + num2 > 100 ? `100を超えています!!` : `許容範囲内です`;
}
console.log(checkSum(20, 81)); //`100を超えています!!`
```

# 参考資料
Udemy　モダンJavaScriptの基礎から始める挫折しないためのReact入門
闘魂Elixir ── Slack上でタイピングしている風の演出をElixirでやってみる

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>

<b><font color="red">$\huge{闘魂とは己に打ち克つこと。}$</font></b>
<b><font color="red">$\huge{そして闘いを通じて己の魂を磨いていく}$</font></b>
<b><font color="red">$\huge{ことだと思います}$</font></b>



# はじめに

ChatGPT流行っていますね。AIブームです。つまりアントニオ猪木ブームです。**闘魂**のブームがきているのです。
これに乗るしかありません。

プログラマーのチャットツールといえば[Slack](https://slack.com/intl/ja-jp)ですよね。

ChatGPTが流行った理由の背景にはタイピングしている風の演出が一役買っているのだと私は思っています。
私が思っているのです。そう思っているのです。合っているのかどうかはわかりません。私はそう思っていると言っているだけです。私はそう思っているのです。

[Slack](https://slack.com/intl/ja-jp)上でタイピングしている風の演出をやってみたくなりました。
[chat.update](https://api.slack.com/methods/chat.update) APIを使えばいけるんじゃないかと思いました。
[Elixir](https://elixir-lang.org/)でやってみます。

# What is [Elixir](https://elixir-lang.org/) ?

[Elixir](https://elixir-lang.org/)という素敵なプログラミング言語があってがですね。
その素敵具合は「[Elixir Saves Pinterest $2 Million a Year In Server Costs](https://paraxial.io/blog/elixir-savings)」によく現れています。開発者も経営者もこの事実に瞠目することでしょう。 **$2 Million/年の節約ですってよ！、奥さん。**

https://paraxial.io/blog/elixir-savings

# サンプルプログラム

デモです。

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/7ca34345-94cb-396e-c3e1-fc53ff53a9ed.gif)



サンプルプログラムです。

```elixir
chat_update = (fn json -> 

    url = "https://slack.com/api/chat.update"

    headers = [
      "Content-type": "application/json; charset=UTF-8",
      Authorization: "Bearer #{System.get_env("SLACK_BOT_TOKEN")}"
    ]

    {:ok, _response} = HTTPoison.post(url, json, headers)
end
)

%{ts: "1692320035.004929", channel: "C02LWMFD3KK", text: "　　　　"} |> Jason.encode! |> chat_update.()
# 1692320035.004929 はメッセージのタイムスタンプ

"We are the Alchemists, my friends!!!"
|> String.codepoints
|> Enum.reduce("", fn char, acc ->
    Process.sleep(33)
    new_acc = acc <> char
    %{ts: "1692320035.004929", channel: "C02XXXXXX", text: new_acc} |> Jason.encode! |> chat_update.()
    IO.inspect new_acc
end)
# C02XXXXXXはチャンネルIDのサンプル値
```

一直線のタイピングなので演出としてはまだまだイマイチですが、それっぽいものはできそうです。

ただ[Rate Limits](https://api.slack.com/docs/rate-limits)の[Web API Tier 3](https://api.slack.com/docs/rate-limits#tier_t3)ですので1分間に50回くらいの制限がありそうです。_APIコールは計画的に。_





# さいごに

[Slack](https://slack.com/intl/ja-jp)上でタイピングしている風の演出の試作を[Elixir](https://elixir-lang.org/)でやってみました。

人類は不老不死の霊薬を意味する素敵なプログラミング言語[Elixir](https://elixir-lang.org/)を手に入れました。並行処理を他のプログラミング言語よりも比較的容易に書くことができます。それはきっとコンピュータ資源を有効活用できることにつながるでしょう。巡り巡って本当の世界平和を必ず実現します。世界文化の進展に寄与できます。

さあ、そこのあなたも[Elixir](https://elixir-lang.org/)の世界へようこそ。
_手始めに[エリクサーチ](https://elixir-lang.info/)なんていかがでしょうか。私のオススメです。_

---

**闘魂**とは、  **「己に打ち克つこと。そして闘いを通じて己の魂を磨いていくことである」** との猪木さんの言葉をそのまま胸に刻み込んでいます。
知っているだけで終わらせることなく、実行する、断行する、一歩を踏み出すことを自らの行動で示していきたいとおもいます。
**アントニオ猪木さんのメッセージから元氣をもらったものとして、それを次代に語り継ぎ、自分自身が「闘魂」を体現するものでありたいとおもいます。**

---

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>
<b><font color="red">$\huge{１、２、３ ぁっダァー！}$</font></b>
[Swift] 0.0 に限りなく近い値である Double.ulpOfOne の有用性について


## Swiftでの`Double.ulpOfOne`の有用性

Swift における `Double.ulpOfOne` の使い方とその重要性を、簡単な割り算の例を通じて説明します。`Double.ulpOfOne` は、Double の最小単位（ULP: Unit in the Last Place）を表し、これを使って非常に小さい値で割り算を行った場合の挙動を確認します。

### コード例

以下の関数は、与えられた分子（`numerator`）を非常に小さい値（`epsilon`）で割り、その結果と結果が無限大かどうかを返します。

```swift
func divideAndReturnResult(_ numerator: Double, epsilon: Double) -> (result: Double, isInfinite: Bool) {
    let result = numerator / epsilon
    return (result, result.isInfinite)
}

let value = 1.0

// Double.ulpOfOneを使った場合
let (resultWithUlp, isInfiniteWithUlp) = divideAndReturnResult(value, epsilon: Double.ulpOfOne)
print("Double.ulpOfOneを使用した場合の結果: \(resultWithUlp), 無限大？ \(isInfiniteWithUlp)")

// 0.0を使った場合
let (resultWithZero, isInfiniteWithZero) = divideAndReturnResult(value, epsilon: 0.0)
print("0.0を使用した場合の結果: \(resultWithZero), 無限大？ \(isInfiniteWithZero)")
```

このコードを実行すると、以下のような結果が得られます：

```swift
Double.ulpOfOneを使用した場合の結果: 4503599627370496.0, 無限大？ false
0.0を使用した場合の結果: inf, 無限大？ true
```

## 解説

Double.ulpOfOne を使用した場合、結果は非常に大きな値になりますが、無限大ではありません。
一方、0.0 で割ると結果は無限大（inf）になります。

この違いは、非常に小さな値での割り算の挙動を理解する上で重要です。
Double.ulpOfOne は、限りなく小さいがゼロではない値であり、計算の精度と安定性を保つ上で重要な役割を果たします。

以上です。
[Swift] 配列を比較して差分のあるindexの配列を返却する便利関数を作った件


# 結論

こちらになります。

```swift
extension Array where Element: Equatable {
    func diffIndices(from oldArray: [Element]) -> [Int] {
        self.indices.compactMap { index in
            if oldArray.indices.contains(index) {
                if self[index] != oldArray[index] {
                    return index
                }
            } else {
                return index
            }
            return nil
        }
    }
}
```

注意点として、順番も考慮します。

使い方は以下の通りです。

```swift
let stringsA: [String] = ["a", "b", "c", "d", ""]
let stringsB: [String] = ["x", "b", "a", "d", "", "hoge"]

let diffIndices = stringsB.diffIndices(from: stringsA)
print("diff: \(diffIndices)")
// diff: [0, 2, 5]

stringsB.diffIndices(from: stringsA).forEach {
    print("diff value: \(stringsB[$0])")
}

// diff value: x
// diff value: a
// diff value: hoge
```

本編は以上です。

# 番外編

順番を考慮したくない方は以下を使ってください。
（関数名のセンスがなくてすみません。。。）

```swift
extension Array where Element: Equatable {
    func diffIndicesNotConsideringOrder(from oldArray: [Element]) -> [Int] {
        self.indices.indices.compactMap { index in
            if !oldArray.contains(self[index]) {
                return index
            }
            return nil
        }
    }
}
```

使い方は同じです。

```swift
let stringsA: [String] = ["a", "b", "c", "d", ""]
let stringsB: [String] = ["x", "b", "a", "d", "", "hoge"]

let diffIndices: [Int] = stringsB.diffIndicesNotConsideringOrder(from: stringsA)

print("diff: \(diffIndices)")
// diff: [0, 5]

stringsB.diffIndicesNotConsideringOrder(from: stringsA).forEach {
    print("diff value: \(stringsB[$0])")
}

// diff value: x
// diff value: hoge
```

以上になります。
[Swift] [Combine] combineLatest() -> map() は combineLatest() {} で書き直せる


# 実際にやってみた

以下のサンプルコードをみれば、わかると思います。

## 共通コード

```swift
import Combine

var cancellables = Set<AnyCancellable>()

let pub1 = PassthroughSubject<Int, Never>()
let pub2 = PassthroughSubject<Int, Never>()
let pub3 = PassthroughSubject<Int, Never>()
```

## `combineLatest()` -> `map()` の場合

```swift
pub1
    .combineLatest(pub2)
    .map { $0 * $1 } // map() で処理
    .sink { print("Result: \($0).") }
    .store(in: &cancellables)

pub1.send(2)
pub2.send(3)
// Result: 6.

pub1.send(4)
// Result: 12.
```

## `combineLatest() {}` の場合

```swift
pub1
    .combineLatest(pub2) { $0 * $1 } // 変更
    .sink { print("Result: \($0).") }
    .store(in: &cancellables)

pub1.send(2)
pub2.send(3)
// Result: 6.

pub1.send(4)
// Result: 12.
```

このように `combineLatest()` -> `map()` で書いていた処理は `combineLatest() {}` で書き直せます。

## つなげることも可能

```swift
pub1
    .combineLatest(pub2, pub3) { $0 * $1 * $2 } // 変更
    .sink { print("Result: \($0).") }
    .store(in: &cancellables)

pub1.send(2)
pub2.send(3)
pub3.send(4)
// Result: 24.

pub1.send(5)
// Result: 60.
```


## `zip()` でも同様

```swift
pub1
    .zip(pub2) { $0 * $1 }
    .sink { print("Result: \($0).") }
    .store(in: &cancellables)

pub1.send(2)
pub2.send(3)
// Result: 6.

pub1.send(4)
// zip() は揃わないと出力なし！！
```

## `flatMap()` は以下のようになる

### `combineLatest() {}` を使わない場合

```swift
pub1
    .combineLatest(pub2)
    .flatMap { pub1, pub2 -> AnyPublisher<String, Never> in
        Just("\(pub1)\(pub2)").eraseToAnyPublisher()
    }
    .sink { print("Result: \($0).") }
    .store(in: &cancellables)

pub1.send(2)
pub2.send(3)
// Result: 23.

pub1.send(4)
// Result: 43.
```

### `combineLatest() {}` を使った場合

```swift
pub1
    .combineLatest(pub2) { pub1, pub2 -> AnyPublisher<String, Never> in
        Just("\(pub1)\(pub2)").eraseToAnyPublisher()
    }
    .flatMap { $0 }
    .sink { print("Result: \($0).") }
    .store(in: &cancellables)

pub1.send(2)
pub2.send(3)
// Result: 23.

pub1.send(4)
// Result: 43.
```

結局、`flatMap()` は残るので微妙ですね。
[Swift] [Combine] ストリームはcancel()やsend(completion:)を受け付けた時点で出力を受け付けない


# この記事でわかること

- Combine ストリームは `cancel()` や `send(completion:)` を受け付けた時点で出力を受け付けない


# 実験(1) `cancel()` の場合

## 前提条件

以下のようのなサンプルコードを用意します。

ポイントとしては、`map()` 処理に遅延を入れているところです。

```swift
import Combine
import Foundation

var cancellables = Set<AnyCancellable>()
let numPublisher: PassthroughSubject<Int, Error> = .init()

numPublisher
    .handleEvents(receiveOutput: {
        print("receiveRequest: \($0)")
    }, receiveCancel: {
        print("receiveCancel")
    })
    .map { num -> Int in
        Thread.sleep(forTimeInterval: 3.0) // 遅延処理
        return num
    }
    .sink { result in
        switch result {
        case .finished:
            print("finished")
        case let .failure(error):
            print("failure: \(error)")
        }
    } receiveValue: { value in
        print("receiveValue: \(value)")
    }
    .store(in: &cancellables)
```

## 実験内容

この状態で、以下を実行してみます。

1. `numPublisher` の出力
2. `cancellables` の `cancel()`
3. `numPublisher` の出力

```swift:実験
// 1. `numPublisher` の出力
numPublisher.send(1)
numPublisher.send(2)

// 2. `cancellables` の `cancel()`
cancellables.map { $0.cancel() }

// 3. `numPublisher` の出力
numPublisher.send(3)
```

## 確認ポイント

`map()` に3秒の遅延処理を入れているため、『2. `cancellables` の `cancel()`』を実行したタイミングでは、まだ、『1. `numPublisher` の出力』 が `receiveValue` まで到達していないとう状況で、『3. `numPublisher` の出力』がどう処理されるのかを確認します。

## 出力結果

出力の結果は以下のようになりました。

```swift:結果
// （出力）
// receiveRequest: 1
// receiveValue: 1
// receiveRequest: 2
// receiveValue: 2
// receiveCancel
↑
`numPublisher.send(3)` は受け付けられていない！！
```

このように「3. `numPublisher` の出力」が受け付けられていないことがわかります。

## このことからわかること

- Combine ストリームは cancel() を受け付けた時点で出力を受け付けない

# 実験(2) `send(completion:)` の場合

`cancel()` ではなく Publisher の `send(completion:)` を行った場合にどうなるかを検証してみます。

## `send(completion: .finished)` の場合

```swift
// 1. `numPublisher` の出力
numPublisher.send(1)
numPublisher.send(2)

// 2. `numPublisher` の `send(completion:)`
numPublisher.send(completion: .finished)

// 3. `numPublisher` の出力
numPublisher.send(3)

// （出力）
// receiveRequest: 1
// receiveValue: 1
// receiveRequest: 2
// receiveValue: 2
// finished
↑
`numPublisher.send(3)` は受け付けられていない！！
```

`cancel()` と同様に「3. `numPublisher` の出力」が受け付けられていないことがわかります。

## `send(completion: .failure())` の場合

```swift
enum TestError: Error {
    case testError
}

// 1. `numPublisher` の出力
numPublisher.send(1)
numPublisher.send(2)

// 2. `numPublisher` の `send(completion:)`
numPublisher.send(completion: .failure(TestError.testError))

// 3. `numPublisher` の出力
numPublisher.send(3)

// （出力）
// receiveRequest: 1
// receiveValue: 1
// receiveRequest: 2
// receiveValue: 2
// failure: testError
↑
`numPublisher.send(3)` は受け付けられていない！！
```

こちらも `cancel()` と同様に「3. `numPublisher` の出力」が受け付けられていないことがわかります。

# まとめ

- Combine ストリームは `cancel()` や `send(completion:)` を受け付けた時点で出力を受け付けない

以上になります。