OmniAICreator/Qiita-1.07M huggingface dataset:
[AWS Q&A 365][Step Function]Daily Five Common Questions #55

# 1. What other services can be integrated with AWS Step Functions? 
Answer: AWS Step Functions can be integrated with a variety of other AWS services, including AWS Lambda, Amazon SNS, Amazon SQS, Amazon DynamoDB, and more. 

# 2. How can AWS Step Functions be used for microservice orchestration? 
Answer: AWS Step Functions can be used to orchestrate the execution of multiple microservices, allowing for complex workflows to be automated and managed. 

# 3. Can AWS Step Functions be used for data processing tasks? 
Answer: Yes, AWS Step Functions can be used for data processing tasks, such as processing data from Amazon S3 or DynamoDB, or running machine learning models on data. 

# 4. How can AWS Step Functions be used for IT and security automation? 
Answer: AWS Step Functions can be used for IT and security automation tasks, such as automating incident response workflows or managing security and compliance checks. 

# 5. Are there any limitations to integrating other services with AWS Step Functions? 
Answer: While AWS Step Functions can integrate with many AWS services, there may be some limitations or compatibility issues depending on the specific services being used. It is important to carefully review the documentation and ensure that all services are compatible before integrating with AWS Step Functions.
【Python】コーディング練習_2日目（LeetCode：Solving Questions With Brainpower）

# はじめに
コーディング練習２日目です。

# 実装内容
一番大きな獲得ポイント値を返す。以下に詳細を記載する。

（例） 入力 = [[3, 2], [4, 3], [4, 4], [2, 5]]
配列の１つ目の数字は獲得ポイント、２つ目の数字はスキップ数を表している。
例えば、最初の組（[3, 2]）を選択した場合、獲得ポイントは３で、その後２つの組をスキップした後の配列（[2, 5]）に移動する。
ここで獲得できるポイントは２なので、出力は３＋２で５となる。
２つ目の組（[4, 3]）を選択した場合は、３つスキップした後に配列が存在しないので、獲得ポイント数は４。
同様に３つ目の組は４、４つ目の組は２となる。
この中で獲得ポイント数が最大のものは５なので、この値を出力する。

# 実装
```python:Solving_Questions_With_Brainpower.py
from typing import List

class Solution:
    def mostPoints(self, questions: List[List[int]]) -> int:
        # ポイントとスキップ数の組の数
        n = len(questions)
        # 組の数の分だけ０を持つリストを作成
        dp = [0] * n
        # 作成したリストの末尾を、与えられた配列（question）の末尾の組の1つ目の値で置き換える。（ポイントのみを作成したリストに入れる）
        dp[-1] = questions[-1][0]
        # 0~2のインデックスについてもポイントを入れる（最後の組については、スキップできないため含めない）
        for i in range(n - 2, -1, -1):
            dp[i] = questions[i][0]
            skip = questions[i][1]
            if i + skip + 1 < n:
                dp[i] += dp[i + skip + 1]

            dp[i] = max(dp[i], dp[i + 1])
        return dp[0]

# テスト
if __name__ == "__main__":
    questions = [[3, 2], [4, 3], [4, 4], [2, 5]]
    print(Solution().mostPoints(questions))
```

# 参考
https://leetcode.com/problems/solving-questions-with-brainpower/editorial/
SOA-C02受験期

## 対象読者
- SOA-C02 を受験予定の方
- 試験ラボの情報を知りたい方
- 試験ラボで失敗したくない方


## はじめに
**AWS Certified SysOps Administrator - Associate** (以下 <mark>SOA-C02</mark>)で
盛大に失敗したので、失敗談を記載します！

2021/7/27 から SOA-C02になりました。

何が変わったかというと 「<span style="color: #d61b09">試験ラボ</span>」が新たに追加されたことが大きな変更点だと思います。

※現在試験ラボは停止中のようです。
>2023 年 3 月 28 日以降、AWS Certified SysOps Administrator - Associate 試験には、追って通知があるまで試験ラボが含まれなくなります。試験ラボが含まれなくなるというこの状況は、受験者に最適なエクスペリエンスを提供するために当社が試験ラボを評価および改善する間に生じる一時的なものです。この変更により、試験は 65 問の択一問題と多肢選択間題で構成され、試験時間は 130 分となる予定です。


ネット上でも「試験ラボ」の情報はあまりなく…

自分も受験するまで、ものすごく不安でした。（案の定、悪い予感が的中）

私のこの失敗を反面教師に今後の受験に役立てて頂けると幸いです！


## 失敗談

どうやら、試験ラボの不具合？というか<mark>ピアソンVueの不具合</mark>が結構あるみたいです。

私は、自宅で受験して<mark>何も回答できず試験終了</mark>になりました。

その理由は

**<span style="font-size: 150%">試験ラボ全く動かん</span>**


余裕を持って、60分以上時間を確保して試験ラボに！と思って挑んだのですが、

<span style="font-size: 150%"> **いきなり何も動かない！** </span>

試験監督に、「試験ラボ動きません」とチャットしようとすると、

なんと

<span style="font-size: 150%">**チャットも動かない…**</span>

その後、携帯に電話がきて、（<mark>もしかしてAWSからか？</mark>）と思い、電話に出ることにしました。

以下試験監督の方とのやり取り。

```
試験監督：tkunさんですか〜？何かお困りですか〜（片言

tkun（私）：はい。試験ラボもチャットも動かないです。

試験監督：おそらくピアソンVueの不具合ですね〜よくあるみたいです〜（片言

tkun（私）：どうしたらいいですか？

試験監督：PCを再起動してください。ピアソンVueへのアクセスコードはメールしますので再度ログインをお願いします（片言

tkun（私）：わかりました。
```

5分後…

メール来ないやん！

しかも非通知で電話がきていたので、試験監督さんに折り返し電話もできない…

なんと、会社のメールに来ていました。

というようなことをしているとかれこれ、30~40分くらいロスしてしまいました…

やっと、ピアソンVueの試験画面に戻ってきた！試験ラボ再開できる！と思ったら、

Chromeに40個くらい謎のタブ ＋ 複数のウィンドウ が開いていました。
（多分、何も操作できない時にクリックしたものが後で反応していた！？）

とりあえず、余計なものを削除していこうとすると…

<span style="font-size: 150%">**試験ラボの画面がブラックアウト！**</span>

何も見えません、何も操作できません…（絶望

その後、試験監督さんとは別の方から電話がきて、またPC再起動してくださいとのこと…

「またか...」と思いながらPC再起動で、ピアソンVueの試験画面に再度ログイン！

**試験が終わった後のアンケートの画面でした！**

結局PCの再起動とかあたふたしているだけで、約60分間無駄にしました…


## 対策【当日】
- テストセンターで受験する（推奨）

- 自宅で受験する場合は、<mark>受験前にPCを再起動</mark>する


## 対策【準備】

試験ラボで満点を狙いに行くというより、失点を最小限に抑えて、

55問の問題で、8割くらい得点することを目標に学習する方が良いと思います！

[TechStock](https://techstock.jp/) を利用して理解できれば合格できると思います！

1から順番に勉強するのではなく、後から遡って学習する方法がおすすめです！
※私は、後半ほど試験に似ている問題が出題された傾向にあったと思います。


## 試験対策に必要と思った内容のメモ
- 暗号化（S3、EBS、RDS）
- コスト配分タグ
- Organizations SCP
- S3 403原因
- ポイントインタイムリカバリ/バックトラック 
- Config 
- Systems Manager Run Command
- Lambda ロール
- PrivateLink
- VPCエンドポイント
- CloudWatch Insight
- Athena
- EBSボリューム変更
- ログ（ELB、VPCグローログなど何を選択するべきか）
- アクセス許可セット
- Route53 エイリアスレコード
- 位置情報ルーティング
- ライフサイクルフック
- Storage Gateway  キャッシュボリューム
- 仮想インターフェイス

 
## さいごに
ある意味良い体験ができました。

AWSアソシエイトの中では、SOAが一番難しく感じました！
（所感は、DVA＜SAA＜SOA でした。）

今後受験される方のお役に立てば幸いです。
フレームレートとリフレッシュレート

ゲーム開発において、フレームレートやリフレッシュレートの知識は重要です。しかし、これらの基本的な概念を解説した記事は意外と見つけにくいのが現状です。そこで、この機会に簡単に説明してみたいと思います。

# **フレームレートとは何か？**

フレームレートは、ゲームが1秒間に何回画面を更新（描画）するかを示す値です。「このゲームは60fpsで動作する」という表現は、1秒間に60回の画面更新、つまり各フレームが約16ミリ秒ごとに描画されることを意味します。高いフレームレートは、ゲームの描画が滑らかに見え、プレイヤーにとってよりリアルな体験を提供します。

# **リフレッシュレートとは何か？**

一方、リフレッシュレートは、ディスプレイが1秒間に何回新しい画像を表示するかを示す値です。たとえば、60Hzのディスプレイは、1秒間に60回新しい画像を表示します。近年では、120Hzやそれ以上のリフレッシュレートを持つディスプレイも増えてきています。

この値は、ディスプレイの性能を示しています。つまり、ディスプレイが1秒間にどれだけの新しい画像を表示できるかを示しています。

- **フレームレート
1**秒間のゲームの更新回数
- **リフレッシュレート
1**秒間のディスプレイの更新回数

以下はWindowsの「システム > ディスプレイ > ディスプレイの詳細設定」で確認出来るものです。

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/a9ebfbc2-cecd-7387-982b-5dbfd833ac26.png)

![Untitled 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/23f87d0a-34c8-0b44-60c2-5a4f12f34a52.png)

![Untitled 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/99610338-12dd-cb73-366e-beaee0badfdc.png)

フレームレートもリフレッシュレートも勿論ですが高いほうが、1秒間の処理できる数が増えるのですから精度が良くなります。

### フレームレートとリフレッシュレートの関係性

フレームレートとリフレッシュレートは、異なる概念ですが、ゲームの体験においては密接に関連しています。たとえゲームが非常に高いフレームレートで描画できたとしても、それを表示するディスプレイのリフレッシュレートがそれに追いつかなければ、その効果を十分に発揮することはできません。

そのため、もしリフレッシュレートが低いディスプレイで高フレームレートのゲームをプレイすると、全てのフレームが正確に表示されず、画面のちらつきや遅延を感じることがあります。これは、ディスプレイがゲームの描画速度に対して遅れてしまい、その結果として生じる現象です。

この問題を解消するために、ディスプレイのリフレッシュレートとゲームのフレームレートが同期するようにVSYNC（垂直同期）と呼ばれる仕組みを使っていました。

垂直同期（VSYNC）は、ゲームのフレームレートとディスプレイのリフレッシュレートを同期させるための技術です。具体的には、ディスプレイが新しい画像を表示するタイミング（リフレッシュ）に合わせて、ゲームが新しいフレームを生成するタイミングを調整します。これにより、ゲームのフレームレートがディスプレイのリフレッシュレートを超えてしまい、画像の乱れ（ティアリング）を引き起こすのを防ぐことができます。

ただし、VSYNCを使用すると、新しいフレームが生成されるまでの待機時間が発生し、これが入力遅延（ゲームへの入力と画面上での反応の間の遅れ）を引き起こす可能性があります。また、ゲームのフレームレートがディスプレイのリフレッシュレートを下回ってしまうと、フレームレートが大幅に低下する可能性があります。

### ****フレーム落ち（フレームドロップ）とは何か？****

さらに、「フレーム落ち」や「フレームドロップ」という現象について説明します。これは、ゲームがフレームを生成するのに必要な時間が、ディスプレイのリフレッシュ間隔を超えてしまった場合に発生します。例えば、60fpsのゲームでは、新しいフレームを16ms以内に生成しなければなりませんが、もし16msを超えてしまった場合、そのフレームはディスプレイに表示される前にスキップされてしまいます。これがフレーム落ちです。

この現象は、ゲームが重くなり、カクつきを感じる原因となります。そのため、ゲームの開発者は、フレームレートを安定させ、フレーム落ちを最小限に抑えるための最適化を行います。

以上が、フレームレートとリフレッシュレートの基本的な説明です。これらの理解は、ゲームのパフォーマンスを最大限に引き出すために重要な要素となります。
2年目エンジニアがうつ病になり、休職した話

# この記事で言いたいこと
- うつ病から休職するまでの道のりを共有したいです
- 心身の調子が「いつもと違う」と思ったら心療内科(など病院)へ行きましょう
- 会社の上司、同僚、どなたでも良いので早めにヘルプを出しましょう
- 無理はダメ！ぜったい！！

# 記事にした理由
好きでエンジニアになったはずなのに、うつ病になってしまいました。うつ病の原因と経緯を客観的に見直し、再発しないよう備忘録として記事にしました。最近少し不調だなって方の参考になれば幸いです。

# 休職までの大まかな時系列
- 2022年9月　心療内科受診
- 2022年11月　休職開始
- 現在も休職中

# 心療内科を受診したきっかけ
- たまたまうつ病の記事を目にしたときに「物事に集中できない」「好きなものに興味が湧かない」の項目に当てはまり、とりあえず受診してみようと思いました。

# 心療内科受診時の私
- プロジェクトが終了し、燃え尽き症候群気味になっていた。
- 仕事を残業してでも終わらせないととわかっているが、仕事に身が入らず、体力が追いつかなくなっていた。
- 休日も半日以上寝て過ごしていた。
- それまで好きだったものに興味が湧かなくなっていた。

今思えば正常ではないとわかるのですが、当時は普通だと思っていました。

# 休職までの具体的な流れ
### 前提
- 先輩社員や課長には「仕事を進めるよう頑張るべきとわかるが、体力が追いつかない」と相談済。

### 1. 人事課の方への相談
- 採用時にお世話になった先輩社員から、以前「助けてほしい時はいつでも連絡してね」と言っていただいたことを思い出す。
- その先輩社員にヘルプメールを出す。
- すぐに相談にのってくださり、産業医担当の社員に繋いでいただいた。
- 産業医に相談してもいいが、心療内科で休職の相談をしてみては？とアドバイスいただいた。

### 2. 心療内科への相談
- 親同伴で心療内科を再受診し、症状が悪化していることを伝える。
- 当時、初診から2ヶ月近く経過していたが、回復の兆しが見えないため医師から診断書が出る。

### 3. 会社を休職する手続き
- 産業医担当の社員の力を借りながら手続きを進める。
- 課長がテレワーク中だったため、電話で休職したい旨を伝える(対面じゃなくて助かった…)

### その他 
- 本来は部長以上のお偉いさんにも手続書を回さないといけないところを、課長が代わりにやってくださりました。
- 他の課員も全員テレワークだったので、休職するとメッセージを送り、ほぼ夜逃げ状態で休職することになりました。

# どうしてうつになった？
- 完璧主義
-- 仕事を含め何事も100%ですべきと考えていた。(できるに越したことはないですよ！)
-- 休むことを甘えと考え、自身の体調を蔑ろにしていた。
-- 仕事が終わらないのは努力不足と考え、残業を何時間してでも終わらせるべきと考えていた。(課長がこの考えなので、そう教育されていたし、私も納得していました。)

- 無理と言えない
-- 仕事をお願いされるとなかなか断れない
-- 仕事が間に合わないとわかった時に相談はしていたが、次の期日もかなり無理をすれば間に合う期日で報告していた。(できるに越したことはないですよ！)

# おわりに
- 私が休職した原因と経緯をまとめました。ここまでお付き合いいただいた皆様ありがとうございました。同じような心当たりがある方は今すぐ病院へ行くことをオススメします！

- 現在は休職し、心身穏やかに過ごせています。復職して落ち着いたら休職期間にやっていたことを載せます…？
BIG-IP r-Series

BIG-IPのi-SeriesのEoSが発表されたので、r-Seriesについて調べた内容をメモ。

# Hardware情報
https://www.f5.com/ja_jp/products/big-ip-services/rseries-adc-hardware-appliance
r2000/r4000/r5000/r10000 の4種類の製品ラインナップ。
iシリーズにあった、i850相当の製品はない。
iシリーズまでは BIG-IP iSeriesだったが、rシリーズからは F5 rSeriesとなり筐体からBIG-IPの名称が外れた。

## r2000/r4000関連の情報
https://techdocs.f5.com/en-us/hardware/platform-guide-r2000r4000-series/title--platform-overview.html
https://clouddocs.f5.com/f5os/F5OS-A/v1.1.0/F5OS-A-1.1.0-rSeries-r4000-r2000-Platform-Overview.html
なぜか、F5OS-Aのところに割と詳しく載っている。
i2000/4000シリーズと異なり、Cupperポートが最初から搭載されている。

## r5000/r10000関連の情報
https://techdocs.f5.com/en-us/hardware/platform-guide-r5000r10000-series/title--platform-overview.html

### 参考リンク
https://techdocs.f5.com/en-us/hardware/platform-guide-r2000r4000-series.html
https://techdocs.f5.com/en-us/hardware/platform-guide-r5000r10000-series.html

# Software情報
https://clouddocs.f5.com/training/community/rseries-training/html/_images/image110.png
VM Tenant (BIG-IP)
Guest Kernel TMOS & TMM
Platform SW (F5OS) K3S
Hardware ATSE, NSE, ASW, Crypto

上に書いたように、Hardwareと TMOSの間に、K8S(K3S)ベースの OS層が r-Seriesでは追加されている。
r-Seriesで動作するものを F5OS-Aと呼ぶ（VELOSで動くものはF5OS-C）。
F5OS-Aの Aは Appliance, F5OS-Cの Cは Chassisを意味する。
https://my.f5.com/manage/s/article/K03278510

現状、F5OS-Aの上では、今までの BIG-IPと同様の Softwareしか動かないが、ここを再構成する構想があり今のモノシリックな構造からモジュラー構造に変更しようとしているようだ（r-Seriesの rは re-Architectという意味らしい）。

## F5OS-A
今のところcentos 7.8ベースで作られている。
https://my.f5.com/manage/s/article/K34100152
bash利用は可能だが、使用しないことが推奨されている。
コンソール接続で初期設定をした後は、Webインターフェースでアクセスして操作することを前提としている。

Management IPアドレスの設定、テナントで利用するネットワークI/Fの設定、F5OS層でのNTP, DNS, syslogの設定ができる。
F5からは、ISOイメージでF5OSは提供される (MyF5から入手する）。

F5OS-A層でのHAサポートはない

## TMOS層
iシリーズと異なり、ネットワークI/Fは F5OS-Aで管理されるため、TMOS層ではLAGの設定は不要（できない）。ただし、TMOS層でも LAGの構成は把握できるため、そこは VE版とは異なる（F5OSとTMOSで連携ができている）。

https://my.f5.com/manage/s/article/K86001294
上記に記載されているように、F5OS-Aでは、17.1, 15.1系列のTMOSしかサポートされていない。
また、ここにAOMの記載があることから、r-SeriesでもAOMがサポートされていることがわかる。ただし、r-Seriesでは AOMへの ssh接続はサポートされておらずコンソール接続のみとなる。
テナントOSもF5OS-Aと同様にMyF5からダウンロードする。
iシリーズ以前のOSイメージはISO形式であったが、r-Seriesで利用するOSイメージはコンテナイメージなのでzip形式で提供される。

テナントイメージは、T1, T2, ALL, T4の4種類がある。T2では、LTM, DNSモジュールしか使用できない。基本的にALLを選択するのが良いように思う。T4はローカルディスク領域が多いという強みをもつ。T1はアップグレードができないので実験的な使用の場合に使う。

以前のBIG-IPと同様、TMOS層でHA構成を取り、冗長構成(F/O Cluster)をサポートする。

# Planning Guide
https://clouddocs.f5.com/training/community/rseries-training/html/

# 参考情報
英語での解説になるが、以下の YouTube (DevCentral) の内容が参考になる。
Part 1. Introduction to rSeries: F5's Next Generation Appliance: https://www.youtube.com/watch?v=rCc5D6MEMcI
Part 2. Setup, Configuration and Backup of F5OS - rSeries: F5's Next Generation Appliance: https://www.youtube.com/watch?v=CiXkvkBWt6M
Part 3. Tenant Sizing and Deployment - rSeries: F5's next generation appliance -: https://www.youtube.com/watch?v=WKC34L1xk5Q&t=235s
shap-eを使ったクリーチャーを3dPrintしてみる

GPT-4を開発するOpenAiが、テキストや画像を入力することによって3Dモデルを生成するshap-eを発表しました。
shap-eは、NeRF(Neural Radiance Fields)とテクスチャで3Dモデルを生成する仕組みになっているそうです。

論文 -> 

GitHub - openai/shap-e: Generate 3D objects conditioned on text or images
https://github.com/openai/shap-e

ブラウザからAPIをcallするサンプルが作られているので、それを試してみます

Shap-E - a Hugging Face Space by hysts
https://huggingface.co/spaces/hysts/Shap-E

テキストの入力欄にプロンプトを入力し、runを押下するだけで3Dモデルが生成されます。
例えば、
「 quadrupedal locomotion fish 」
のように入れると処理が行われます。

「Advance options」
Seed(シード値)
Guidance scale(ガイダンススケール)
Number of inference steps(ステップ数)

crocodile rabbit
![スクリーンショット 2023-05-15 14.16.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/8720535f-d8d6-f46f-1c73-c8fe2bc61947.png)

![IMG_1798 (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/154414c0-ae89-edea-da8b-d02223f54f50.jpeg)


fish quadrupedal locomotion
![スクリーンショット 2023-05-12 18.41.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/8ecd9cee-ec49-cf8f-971b-6ea958da1a2d.png)

cow with big wings on its back

![スクリーンショット 2023-05-12 18.41.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/cd2e0ddc-bd99-12d8-28ba-f20e62c5e577.png)


cow with big crab hands

![スクリーンショット 2023-05-12 18.42.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/8a78d254-30e5-c9ef-44e7-33b92d91a319.png)
Oracle Cloud Infrastructure (OCI) 上のVCN表示名を変更してみた

# はじめに
OCIを利用するにあたって、仮想クラウド・ネットワーク(Virtual Cloud Network : VCN) は最初に必ず作成するかと思いますが、VCN名は画面上からは変更ができません。
当初、設定したVCN名が今では分かりにくくなってしまったので、[VCNの更新](https://docs.oracle.com/ja-jp/iaas/Content/Network/Tasks/update-vcn.htm)を参考にVCN名を更新してみた。

# 1. 変更前のVCN名
現状、「**vcn-20220317-1743**」というVCN名。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079416/2dbb9f35-3656-d524-6ebc-bb31c1b31073.png "現状のVCN名")

# 2. VCN名の変更
1. OCIの上部バーの「**開発者ツール**」アイコンをクリック
2. Cloud Shellをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079416/197a25b8-50a9-092c-82d3-359e270ff94f.png "Cloud Shellを開く")
3. マニュアル通り、下記コマンドを実行
```$ oci network vcn update --vcn-id [vcn-ocidを入力] --display-name [変更後のvcn名]```

実行コマンド
```
$ oci network vcn update --vcn-id [vcn-ocidを入力] --display-name DemoVCN
```
# 3. 変更後のVCN名
VCN名を変更できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079416/cf4bf3ac-ff12-25d8-89c6-b00faeca0f18.png)

# 終わりに
画面上からはVCN名を変更できませんが、コマンドから変更することができました。
このVCNに関連付けられたDBなどもにも、ちゃんと変更が反映されていることを確認できております！
【初学者向け】データベースの正規化をわかった気になろう！(第１正規化)

# はじめに
データベースに関する教科書的な説明がわかりにくかったので、具体例を通してわかった気になれる記事を書きます。
今回は「第１正規化」について書きます。


# 第１正規化
ここでは、エクセルで何かを管理している場合にありがちな、正規化されていないダメな例2つをもとに第１正規化について理解していこうと思います。



### ダメパターン① : ひとつのセルに複数の情報がある

例えば、下記のようなテーブルがあるとします

・社員テーブル
|社員ID|名前 |電話番号                    |
|--|----|-------                    |
|1 |田中 |080-1234-5678, 03-1234-5678|
|2 |佐藤	|090-1234-5678              |

このテーブルは第一正規形に違反しています。なぜなら、「電話番号」の列に2つの電話番号がカンマで区切られて入っているからです。この問題を解消するために、テーブルを以下のように修正します。

|社員ID|名前 |電話番号                    |
|-|----|-------                    |
|1|田中	|080-1234-5678|
|1|田中	|03-1234-5678|
|2|佐藤	|090-1234-5678|

これで各セルには一つの値だけが入るようになり、第一正規化を満たすようになりました。



### ダメパターン② : 「セルの結合」を使っている
セルの結合もよく見ますよね。
以下の `(結合)` となっている部分が、その上のセルと結合していることを表しています。

・社員テーブル
|社員ID|名前 |電話番号   |
|-----|---- |--------------|
|1    |田中	|080-1234-5678|
|(結合)|(結合)|03-1234-5678 |
|2    |佐藤	|090-1234-5678|

第一正規形では、それぞれの行と列の交差点（セル）が一意の値を持つように設計することが求められます。つまり、一つのセルには一つの値のみが含まれるべきで、複数の行または列にまたがる情報（結合したセル）を持つべきではありません。

これも正しく正規化すると、繰り返しになってしまいますが、以下のテーブルのようになります。

・社員テーブル
|社員ID|名前 |電話番号                    |
|-|----|-------                    |
|1|田中	|080-1234-5678|
|1|田中	|03-1234-5678|
|2|佐藤	|090-1234-5678|

# 最後に
筆者が以前勤めていたところでは、上記の２パターンの両方が混在していました。
それどころか、「その他」のカラムに大量のデータが書き込まれている始末でした。。。
できればもう見たくないですね。
みなさんの職場でもエクセルで何かを管理している場合、この記事を参考に、まずは第１正規化から試してみてください。以降の第2〜３正規化がとてもしやすくなります！

ここまで読んでいただきありがとうございました！！
もし本記事が少しでも理解の助けになったなら、ぜひイイね！をよろしくお願いします。
それではまた！(^_^)ﾉｼ
React×TypeScript 処理のwaitを入れる

## こんな時ありませんか？
バックエンドAPI通信中に画面ローディングを実装したいな・・・・
例えば、こんな処理があったとします。バックエンドへ何回もAPIせずにローディングコンポーネントを作りたい！
```
処理１　　→　　バックエンドAPI処理　　→　　処理２
```

## 同期的に処理し、処理に待ちを発生させる
上記の例をもとに処理を書くとこんな感じです。
```XXXX.tsx

//ローディングを表示・非表示にするstate
const [isLoading, setIsLoading] = useState<boolean>();

//バックエンドAPIを実行するためのボタンをクリック
const onClick = async () => {
    処理１
    setIsLoading(true);
    // await バックエンドAPI処理();
    // 上記の代わりに以下を入れる3000は３秒
    await new Promise((resolve) => setTimeout(resolve, 3000));
    setIsLoading(false);
    処理２
};

```

## 最後に
ちょっとした役立つ情報を今後も発信していこうと思います！
[Vue3 CompositionAPI] nextTick() で同期的にDOM要素を操作する~DOM構築後に出現したinput要素に対してfocusを当てる~

## はじめに
この記事は、Vue3系でDOM構築後に出現したinput要素に対してfocusを当てることでnextTick() で同期的にDOM要素を操作する方法を説明します。
## 使用技術
- Vue3
- CompositionAPI
- script setup

## やりたいこと
DOM構築後に出現したinput要素に対してfocusを当てる

## 結論
`await nextTick();`でコンポーネントのデータ変更がDOMに到達するのを待つ
```vue:App.vue
<template>
  <button @click="handleClick">button</button>
  <input v-if="show" ref="input" />
</template>

<script setup>
import { ref, onMounted, nextTick } from "vue";

const input = ref();
const show = ref(false);

const handleClick = async () => {
  show.value = !show.value;
  await nextTick();
  input.value?.focus();
};
</script>
```

## 解説
上記コードにコメントベースで解説します。
```vue:App.vue
<template>
  <button @click="handleClick">button</button>
  
  <!-- DOMにアクセスするため、refを使用してテンプレート参照を行う -->
  <input v-if="show" ref="input" />
</template>

<script setup>
import { ref, onMounted, nextTick } from "vue";

// inputタグで ref="input" としたため、 変数名を合わせ、refの引数を空にすることでDOMの内容を変数に受け取る
const input = ref();
// inputタグの表示非表示を管理する変数
const show = ref(false);

/**
 * buttonクリックイベント
 * inputタグの表示制御、focus制御を行う
 */
const handleClick = async () => {
  // inputタグの表示制御
  show.value = !show.value;
  // nextTickが引数なしで呼ばれた場合、コンポーネントのデータ変更がDOMに到達した時に解決されるPromiseを返します。
  // つまり、inputタグが実際に出現するまで処理を待ってくれます。
  await nextTick();
  // フォーカス
  input.value?.focus();
};
</script>
```
エンジニアに関する知識を蓄えるヒント

# はじめに
ITエンジニアやソフトウェア開発者向けの説明会終了後には、
使用した資料や録画が順次アップロードされます。
知識を蓄える際のヒントとしてご活用ください。

今回はIoTセキュリティー、チャットボット、プロセス・マイニング、
WASに関する内容を中心にしてピックアップいたしました。

# ピックアップ一覧
|日時|タイトル|
|:--|:--|
|5/10(水) 17:00 〜 18:00|[いまからでも遅くない！サイバーセキュリティ超入門（後編）](https://ibm-developer.connpass.com/event/279911/) |
|5/15(月) 15:00 〜 16:00|[マルチクラウドにおけるデータ収集とデータガバナンス](https://ibm-developer.connpass.com/event/282574/) |
|5/17(水) 15:00 〜 16:00|[IBM Cloud PLUS -＃5 バックアップ関連サービス](https://ibm-developer.connpass.com/event/281162/) |
|5/17(水) 17:00 〜 18:00|[いまからでも遅くない！IoTセキュリティー入門](https://ibm-developer.connpass.com/event/280859/) |
|5/19(金) 13:00 〜 14:00|[データドリブンな時代に求められるプロセスマイニング入門](https://ibm-developer.connpass.com/event/282017/) |
|5/23(火) 18:00 〜 18:40|[メインフレームで.Netを動かしてみた](https://ibm-developer.connpass.com/event/283546/) |
|5/24(水) 14:00 〜 15:00|[いまからでも遅くない！監視超入門 座学編](https://ibm-developer.connpass.com/event/278896/) |
|5/24(水) 17:00 〜 18:00|[OpenShiftPipelinesでドキュメントを自動生成してみよう！](https://ibm-developer.connpass.com/event/281349/) |
|5/25(木) 17:00 〜 18:00|[いまからでも遅くない！Git超入門 座学編 rerun](https://ibm-developer.connpass.com/event/280948/) |
|5/26(金) 12:15 〜 13:00|[1時間でできる！？ノーコード生成系AIチャットボット作成](https://ibm-developer.connpass.com/event/282428/) |
|5/26(金) 13:00 〜 14:00|[コンテナ入門](https://ibm-developer.connpass.com/event/280426/) |
|5/29(月) 16:00 〜 16:45|[いまからでも遅くない！データベース超入門 座学編 rerun](https://ibm-developer.connpass.com/event/282512/) |
|5/29(月) 17:00 〜 18:00|[いまからでも遅くない！データベース超入門 ハンズオン編](https://ibm-developer.connpass.com/event/281551/) |
|5/30(火) 11:00 〜 12:00|[VSCodeとLibertyで始めるエンタープライズJava入門](https://ibm-developer.connpass.com/event/281400/) |
|5/31(水) 14:00 〜 15:00|[IBM Cloud PLUS #6 Infra-as-Code 実践編](https://ibm-developer.connpass.com/event/280928/) |
Javaで球体を描画してみた（レイトレーシング：光源ありバージョン）

# 概要
先日は点光源を球面上に配置したバージョンで球体を描画していましたが、
今日は点光源を球面外に配置し球体を描画してみました。以前の記事は以下の通りです。

https://qiita.com/nori-channel/items/a694cd9768e08cdc4f40

# 位置関係
各オブジェクトの位置関係は以下の通りです。
![図面2023 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/8b919966-b138-9a3b-36f6-5d9a19f074f6.png)

# ソースコード
ソースコードは以下の通りです。点光源から離れれば離れるほど暗くなるように実装しました。
```Sphere2.java
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Sphere2 extends JPanel implements MouseListener {
    static int iWidth = 600;
    static int iHeight = 600;
    static double iShiten = -10.0;
    static double dSphereSize = 0.10;
    static double dX_Light = -1.0;
    static double dY_Light = -1.0;
    static double dZ_Light = -1.0;
    public Sphere2(){
	addMouseListener(this);
    }
    public void paint(Graphics g){
	super.paint(g);
	for(int i=-iWidth; i<iWidth; i++){
	    for(int j=-iHeight; j<iHeight; j++){
		for(double d=iShiten; d<+1.0; d+=0.1){
		    double x=(double)i/(double)iWidth;
		    double y=(double)j/(double)iHeight;
		    if(Math.sqrt(x*x+y*y+d*d)<dSphereSize){
			//g.setColor(Color.red);
			double dist = Math.sqrt((x-dX_Light)*(x-dX_Light)+(y-dY_Light)*(y-dY_Light)+(d-dZ_Light)*(d-dZ_Light));
			System.out.println(dist);
			if(dist > 2.30){
			    g.setColor(Color.black);
			}else{
			    g.setColor(new Color((int)((double)255.0*dist/2.30), (int)((double)255.0*dist/2.30), (int)((double)255.0*dist/2.30)));
			}
			g.drawLine(iWidth+i,iHeight+j,iWidth+i,iHeight+j);
		    }
		}
	    }
	}
	System.out.println("paint()");
    }
    public void mouseClicked(MouseEvent e){
        System.out.println("mouseClicked");
	dSphereSize += 0.1;
	repaint();
    }
    public void mouseEntered(MouseEvent e){
        System.out.println("mouseEntered");
	dSphereSize = 0.10;
    }
    public void mouseExited(MouseEvent e){
        System.out.println("mouseExited");
    }
    public void mousePressed(MouseEvent e){
        System.out.println("mousePressed");
    }
    public void mouseReleased(MouseEvent e){
	System.out.println("mouseReleased"); 
    }	 
    public static void main(String[] args) {
	JFrame jf = new JFrame();
	jf.getContentPane().add(new Sphere2());
	jf.setTitle("Sphere");	
	jf.setSize(iWidth*2, iHeight*2);
	jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	jf.setVisible(true);
    }
}
```

# 実行結果
以下の通りの球体が表示されました。画面右下に点光源を配置したのでそちらが明るくなっています。

![Screenshot from 2023-05-12 18-08-26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/6062ceb9-e09f-7dc4-c799-59aa2b93c559.png)

何かの役に立てばと。
PostgresでCreateUserが使えない時の救世主！Windowsでの解決策

こんにちは、皆さん！Windows 11でPostgresを使ってみたものの、createuserコマンドが使えないという絶望的な状況に直面したことはありませんか？今日はその解決策をお伝えします。

#### 1. ジレンマ：Postgresのcreateuserコマンドが使えない！
Windows 11にPostgresをインストールし、いざcreateuserコマンドを叩いてみたものの...エラーが出てしまった！以下に私の経験した具体的なエラーを共有します。

```shell:shell
PS C:\Users\windowsのユーザー名> createuser --interactive test
新しいロールをスーパーユーザーにしますか？ (y/n)n
新しいロールに対してデータベースを作成する権限を与えますか？ (y/n)n
新しいロールに対して別のロールを作成する権限を与えますか？ (y/n)n
パスワード:
パスワード:
createuser: エラー: "localhost"(::1)、
ポート5432のサーバーへの接続に失敗しました:
 FATAL:  password authentication failed for user "のユーザー名"
```

#### 2. 原因：PostgresにWindowsユーザー名が存在しない
エラーメッセージを見てみると、PostgresがWindowsのユーザー名でのユーザーを認識できていないことがわかります。

#### 3. 解決策：PostgresにWindowsユーザーを作成、権限を付与
では、どうすればいいのでしょうか？その答えは、「PostgresにWindows名と同じユーザーを作成し、そのユーザーに管理者権限を付与する」というものです。以下に具体的な手順を示します。


1: アプリケーションメニューからSQL Shell(psql)を起動します。
スタートボタンを押してアプリケーション一覧から選んで下さい
postgresの項目の中にあります

2: 以下の情報を入力します
```shell:SQL Shell(psql)
Server [localhost]: localhost
Database [postgres]: postgres
Port [5432]: 5432
Username [postgres]: postgres
Client Encoding [SJIS]: SJIS
パスワード: （Postgresをインストール時に設定したパスワード）
```

これで、postgresユーザーとしてPostgresにログインできます。
以下の画面が表示されるはずです

```shell:psqlshel
Copy code
psql (15.2)
postgres=#
```
以降#のあとに記載をしていきます

3: Postgresで新たなユーザーを作成し、権限を付与
まず、新しいユーザーを作成します。次に、そのユーザーにスーパーユーザー権限を付与します。以下のコマンドを使用します：
```sql:sql
-- ユーザーを作成
CREATE USER windowsのユーザー名 WITH PASSWORD '任意のパスワード';
-- 権限を付与
ALTER USER windowsのユーザー名 WITH SUPERUSER;
```

#### 4. 確認：作成したユーザーでの操作が可能かテスト
コマンドプロンプトを起動し、以下のコマンドを実行して新たに作成したユーザーでの操作が可能か確認します

```shell:shell
createdb -O windowsのユーザー名 testdb
psql testdb
```

実行後、下記のように画面が変われば実行に成功しています
```shell:shell
testdb=#
```
※上記の画面からログアウトするには、\qを入力して下さい。

以上で、Postgresのcreateuserコマンドが使えない問題が解決できるはずです。この投稿が皆さんの問題解決に役立つことを願っています！



※この投稿は、chatGPTで校閲しました。内容は、自身で実行・確認したものです。
指摘箇所などございましたら、コメントにてお願いします。
JuliaにPyCallとSymPyを入れるときの備忘録

# 初めに

Juliaを使って遊ぼうとしたらPyCallとSymPyを入れるのに少してこずったので備忘録として書き残す．
ネットの海に転がっているいくつかの記事のn番煎じである．

## 環境
windows10
Python:Python 3.10.6
Julia:julia version 1.8.4
備考：Anaconda未使用

## 手続き

まず，juliaのパッケージモードでPyCallとSymPyを入れる．
ここは素直に通る．

```
julia> ] add "PyCall"
julia> ] add "SymPy"
```

PyCallはjuliaからPythonを呼び出すライブラリで，SymPyはPythonでおなじみの記号計算ライブラリである．SymPyはPyCallに依存しているため，PyCallの設定を完了させなければならない．
PyCallやSymPyをaddして，おなじみの
```
julia> using PyCall
```
をしてもエラーが出る（ここではエラーメッセージは省略する）．これはエラーメッセージから推測するに，PyCallでPythonを呼び出す際に，Anacondaやシステムに入っているPythonを読み込むのだが，Anacondaが入っていなかったり，PCにPythonがデフォルトで入っていない場合にエラーが起こるのだと思われる．
このような状況や，あるいは呼び出すPythonのバージョンを指定したいときには，まずPythonのパスを設定する．筆者の場合は以下の通りである．
```
 ENV["PYTHON"] = raw"C:\Users\user\AppData\Local\Programs\Python\Python310\python.exe"
```
これをやったうえで，PyCallにこのPythonを読み込ませる．これにはPkgライブラリを用いる．
```
julia> using Pkg
julia>　Pkg.build("PyCall")
```
これで，Pycallをusingしてもエラーがでないはずである．
asadmin enable-secure-admin 実行後GlassFish5.1が起動できない

asadmin enable-secure-admin 実行後GlassFish5.1が起動できなくなった。
server.logには、以下のメッセージが出力される。

```
[2023-05-12T17:52:28.993+0900] [glassfish 5.1] [SEVERE] [] [] [tid: _ThreadID=53 _ThreadName=Thread-9] [timeMillis: 1683881548993] [levelValue: 1000] [[
  java.lang.NoClassDefFoundError: sun/security/ssl/HelloExtension
        at sun.security.ssl.SSLExtension.<clinit>(SSLExtension.java:224)
        at sun.security.ssl.SSLConfiguration.getEnabledExtensions(SSLConfiguration.java:380)
        at sun.security.ssl.ClientHello$ClientHelloKickstartProducer.produce(ClientHello.java:551)
        at sun.security.ssl.SSLHandshake.kickstart(SSLHandshake.java:509)
        at sun.security.ssl.ClientHandshakeContext.kickstart(ClientHandshakeContext.java:115)

```

### 環境
* Redhat 9
* java 1.8.0_361
* Eclipse GlassFish 5.1.0 

### 対応
google検索で、対応策が見つかった。
glassfish/modules/endorsed/grizzly-npn-bootstrap.jarからsunフォルダを削除するとのこと。

![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284235/68be6d3a-2a48-8d26-dd52-19069db5a0e0.jpeg)

削除したjarに入れ替えて起動、終了できることを確認。
unityでSpeechDictationRecognition

基本はこれ
https://docs.unity3d.com/ja/current/ScriptReference/Windows.Speech.DictationRecognizer.html

そしたらエラー
ERROR:  Dictation support is not enabled on this device (see 'Get to know me' in Settings > Privacy > Speech

これはunityの設定ではなくwindows10の設定のお話。
設定→プライバシー→音声認識→オン
更に『音声クリップを提供する』は有効にせずともエラーは起きませんでした。

戻ってくる出力は
DictationHypothesis：発声の度に都度認識変換されたもの。一応文節っぽい区切りにはなってる。
発声が終わるまでどんどん追加される。
例：
じゃあ
じゃあとりあえず
じゃあとりあえずエアコン
じゃあとりあえずエアコン入れてくるね

DictationResult：発声したワンセンテンスが完了したと判断されたら一文が出力される。
例：もうね前半はお客さんが空気を読んで歓声を上げてで発表してる方がそれを見て悲しくなって何度か言葉に詰まって

whisperと比べてみても、むしろこっちの方が良いんじゃないかっていうぐらい。
サーバとの応答考えたらunityspeechの方に軍配が上がるかなぁ。
AWS LambdaでPythonコード並列処理

## はじめに
ある日のことAWS Lambdaで並列処理して処理速度向上を図りたいとなりまして。。。

その際に四苦八苦して得た知見を備忘録としてアウトプットしておきたいと思います。

## 前提
まずAWS Lambdaでは
- 設定メモリに応じてvCPU数が増減する
- pythonのmultiprocessingのPoolが使えない

らしいです。

個人的にmultiprocessingのPoolを使い慣れていたので困ったもんだなぁと。

## 方法
Lambdaでの並列処理のやり方を色々調べたのですが、並列化したい処理に戻り値がない場合の解説ばかりでした。

そしてたどり着いたのが以下リポジトリ。

https://github.com/mdavis-xyz/lambda_multiprocessing

pip installもできるようですが、main.pyをコピペするだけで十分です。

使い方はmaltiprocessingのPoolのような感じで以下のように実装すれば並列処理をすることができます。

```python
from lambda_multiprocessing import Pool

with Pool() as p;
    results = p.map(function, iterator)
```

上記例では、main.pyをlambda_multiprocessing.pyとリネームしております。

## 最後に
ここまで読んでいただきありがとうございます。

大雑把な内容となっておりますが誰かのためになれば幸いです。

## 参考
https://qiita.com/teracy164/items/101f16a53f2262cbe8d8
OpenSWPCのシミュレーションプログラムのコンパイルで、NetCDFが開けない問題を解決する

今回、問題になったのは、
```
Fatal Error: Can't open module file ‘netcdf.mod’ for reading at (1): No such file or directory compilation terminated.
```
というエラーでした。
##

### 説明
OpenSWPCは、Fortran90で主に地震動の波動計算などのシミュレーションができるコードがオープンソースになっていて、[OpenSWPC](https://tktmyd.github.io/OpenSWPC/ja/ "OpenSWPC")から飛べるGithubからクローンできるのですが、ここのプログラム内では、NetCDFというデータ形式が利用されています。
ただ、githubからOpenSWPCのリポジトリをクローンしただけではNetCDFは利用できず、別途インストールする必要があります。
しかしこのNetCDFを利用可能にする時に詰まってしまいました。

なんせ使ってる人が少なく、ネットにもほぼヒントがないので苦労しました。
とりあえずOpenSWPCをコンパイルするところまでの手順を説明します。

### 環境
macOS
（また、Homebrewで必要なものをinstallする前提で話します。）
**事前に、fortranを、brew installでインストールしておいてください。**
```
brew install fortran
```

# コンパイルするまでの本来の手順
①クローンする
②NetCDFを利用可能な状態にする
③srcでmakeコマンドを打ち、src内の全てのF90をコンパイルする（swpc_*内からでもいい）

しかしこの②で詰まったので、簡単に②をクリアする手順を説明します。

# MacPorts をインストールする
[MacPorts](https://www.macports.org/ "macports")は、パッケージ管理システムです。これを使って必要なものをインストールします。
なぜhomebrewでインストールしないのかというと、
[OpenSWPC](https://tktmyd.github.io/OpenSWPC/ja/1._SetUp/0100_trial/ "OpenSWPC")に書かれているところでは、

>```
>! apt install libnetcdf-dev libnetcdff-dev
>```
>によって、libnetcdf-devとlibnetcdff-devの2つをインストールする手順が必要

とされていますが、手っ取り早く、代わりに使う**homebrewではlibnetcdf-devなんてない**と言われてしまって、インストールできません。

そこでMacPortsを利用するため、ターミナルで、次をうちます。（時間がかかります）
```
sudo port install netcdf-cxx netcdf-fortran
```
（必要に応じてですが、とりあえず上を打つ前に、バージョンアップをお勧めします。）
```
sudo port selfupdate
```
長いインストールの後、
```
port installed | grep netcdf
```
で、netcdfが存在することを確認してください。
後者は、PCにインストールされた、"netcdf"という文字列を含むパッケージのみをフィルタリングして表示してくれます。

# 設定を確認する
最後に、OpenSWPCを開き、src/makefile.arch、src/makefile-tools.archを見て、
```
## Mac OSX gfortran and netcdf provided by homebrew
```
という部分が、それぞれ、
```
## Mac OSX gfortran and netcdf provided by homebrew
##
ifeq ($(arch),mac-gfortran)

  FC      = gfortran
  FFLAGS  = -O2 -ffast-math -D_INFO -I../include
  NCFLAG  = -D_NETCDF
  NCLIB   = -L/opt/local/lib
  NCINC   = -I/opt/local/include
  NETCDF  = -lnetcdf -lnetcdff

  ifeq ($(debug),true)
    FFLAGS  = -Wall -pedantic -fbounds-check -O -Wuninitialized \
	          -ffpe-trap=invalid,zero,overflow -fbacktrace -O0 \
	          -D_INFO -D_DEBUG -I../include
  endif
```

となっていることを確認してください。（ここは今の所直しは必要なく、デフォルトのままでいいとは思います）

これでNetCDFのインストールが完了したので、makeコマンドでコンパイルできます。

以上！
npmの基本（Node.jsパッケージマネージャ）

# npmとは
Node.jsのライブラリ、パッケージマネージャーです。
（同種のツールではyarnも有名）

## npmとyarnの違い
- yarnはnpmのセキュリティ上の問題を解決するために生まれた。
- yarnはnpmの上位互換として使用されたが、現在はnpmと大きな差はない（らしい）
- どちらを使うかはお好みで！（今回はnpmを使用します）

## npmで出来ること
- Node.jsのライブラリやパッケージのインストール・アンインストール
- 依存パッケージのインストール・アンインストール
- package.jsonの作成

## package.jsonとは
- npmのライブラリ・パッケージの依存関係を記したJSONファイル
- package.jsonがあればコマンドひとつでパッケージをインストールすることが可能

# npmパッケージを個別にインストールする
ローカルとグローバルで分けてインストールします。
基本的には、プロジェクトごとにインストールするパッケージを分ける事が推奨されるのでローカルインストールすると良いと思います。

```terminal: ローカルインストール：プロジェクト単位でインストール
$ npm -v      # npmバージョン確認
$ npm install <package名>
$ npm list    # インストールされたパッケージ一覧を確認(ローカル)
```

```terminal: グローバルインストール：システム全体にインストール（非推奨）
$ npm -v      # npmバージョン確認
$ npm install -g <package名>
$ npm list -g  # インストールされたパッケージ一覧を取得(グローバル)
```

# npmパッケージのインストール（開発環境と本番環境）
開発環境でのみ使用するパッケージは、開発環境にインストールする事が基本です。
（本番環境は、パッケージを無闇に入れるとパッケージ同士が衝突し、依存関係に影響する）

開発環境に入れるべき例として、デバッグで使用するESLintなどは開発環境に入れると良いです。
```terminal: 開発環境にインストール
$ npm install -D <package名>
```

```terminal: 本番環境にインストール
$ npm install <package名>
```
# 流れで説明： npmの初期設定からパッケージインストールまで

```terminal:package.json ファイルが生成される。
  $ npm init
```

## パッケージのインストール
```terminal:個別パッケージのインストール
$ npm install <package名> # ローカルインストール
$ npm i <package名> # このように省略可
```

```terminal:インストール（バージョン指定）
 $ npm install パッケージ名@バージョン
```

# packegeの一括インストール
# npmパッケージを一括インストールする
package.jsonが置かれたディレクトリで`npm install`を実行する事で、
package.jsonに記述された通りのnpmパッケージが全てインストールされる。

```terminal: package.jsonに記述された通りインストールされる
$ npm install
```

:::note info
プロジェクトで使用する場合
GitHub上のプロジェクトにpackage.jsonがあれば、git cloneしてnpm installコマンドを一発叩けばnpmで管理するパッケージ群をインストールできる。
:::

# パッケージのアップデート状況の確認
このコマンドはレジストリをチェックして、インストール済みのパッケージが現在古いかどうかを確認します。
```terminal:アップデート確認
$ npm outdated -g # グローバルを確認
$ npm outdated # ローカルを確認
```

:::note info
パッケージの更新ステータス
npm outdatedを実行すると、各パッケージの更新バージョンのステータスが見れます。

■Current
現在インストールされているバージョン
■Wanted
存在するバージョンのうち、package.jsonに記載されたsemverの条件を満たす最新のバージョン
■Latest
パッケージの最新バージョン
:::

## パッケージのアップデート
package.jsonに記述されたパッケージをアップデートする

```terminal:アップデート
 $ npm update
```

```terminal:アップデート（バージョン指定）
$ npm install [パッケージ名@バージョン]
```
Pleasanter Ubuntu20.04＋PostgreSQL環境構築

基本的に以下の公式サイトに記載されている手順どおりですが、
<font color=red>留意点のみピックアップして記録します。</font>

**Pleasanter公式サイト-プリザンターをUbuntuにインストールする**
https://pleasanter.org/manual/getting-started-pleasanter-ubuntu


なお、今回はubuntu-22.04.2-live-server-amd64.isoでサーバを作成しました。
サーバインストーラで入れたソフトウェアはsshdのみです。
その他必要なソフトウェアは別途インストールします。

とりあえずupdateしときます。
```
sudo apt-get update
sudo apt-get upgrade
```

コンフィグファイルを書き換えるのでviを入れます。
```
sudo apt-get install vim
```

**【留意点①　プリザンターのセットアップ アプリケーションの準備】**
手順が省略されているので以下に詳細を記します。
```
sudo apt-get install -y wget
cd ~
wget https://github.com/Implem/Implem.Pleasanter/releases/download/Pleasanter_1.3.37.3/Pleasanter_1.3.37.3.zip

sudo apt-get install -y unzip
sudo mkdir /web
sudo chmod 777 /web
cd /web
unzip ~/Pleasanter_1.3.37.3.zip
```


**【留意点②　Pleasanterサービス用スクリプトの作成】**
/etc/systemd/system/pleasanter.service を以下の内容で作成します。ってところですが、
このpleasanter.serviceの14行目の User = \<loginUser>　となっているところは、User = root　とする。

```
User = <loginUser>
```
以下に修正する
```
User = root
```


**【留意点③　Http(80) へのアクセス許可】**
ufwがインストールされていない場合は以下にてインストールする。
また、80番以外にも22番（ssh）も通しておく。
```
sudo apt-get install ufw
sudo ufw allow 80/tcp
sudo ufw allow 22/tcp
sudo ufw enable
sudo ufw status
```

**【留意点④　postgresqlのtimezone設定】**
データ登録時に日時がUTCになってしまう。

/etc/postgresql/14/main/postgresql.conf のtimezoneを'Asia/Tokyo'にする。 
timezone = 'Asia/Tokyo'
プロジェクトのdocsフォルダの中身をmkdocsで動かしたかった

## 目的

docsフォルダにマークダウン形式のドキュメントを記述してるうちに、これmkdocsとしても動かしたいなと思うようになった。

各自でmkdocsをインストールさせたくない為、dockerで動かないかなと
調べたところ、やっている人が居たので参考にしながらメモのつもりで残しておく。

## 参考にしたサイト

[dockerでmkdocs環境を作る](https://zenn.dev/yoshiyasu1111/scraps/d77132dbd37d8e)


## ディレクトリのスケルトン構成

```
root
 ├ docker 
 |  └ mkdocs 
 |      └ Dockerfile 
 ├ docs
 |  └ index.md
 ├ develop.yml
 └ mkdocs.yml
```

## ファイル

### mkdocs.yml

ドキュメントの定義
基本的には各自の環境で好きに記述すべし


`theme`は好みで適当に設定すると良い

`markdown_extensions`は
`mermaid`が使いたいので追加しているのと
リンクを別窓で表示するために`{:target="_blank"}`を使うので`attr_list`を追加している

```
site_name: 'Document'
site_description: 'Document'
use_directory_urls: false

nav:
  - はじめに: index.md

theme:
  name: material
  language: 'ja'
  features:
    - navigation.tabs
    - navigation.footer

plugins:
  - search

markdown_extensions:
  - pymdownx.superfences:
      custom_fences:
        - name: mermaid
          class: mermaid
          format: !!python/name:pymdownx.superfences.fence_code_format
  - attr_list
extra:
  search:
    language: 'ja'

dev_addr: '0.0.0.0:8000'

```


### develop.yml

開発の時だけ`docker-compose`コマンドに`-f develop.yml`をつけて呼びだす目的
`healthcheck`は途中で`mkdocs serve`が死んでも起動しなおすために入れている

```
version: '3'
services:
  mkdocs:
    build:
      context: .
      dockerfile: ./docker/mkdocs/Dockerfile
    image: mkdocs
    volumes:
      - ./mkdocs.yml:/mkdocs/mkdocs.yml
      - ./docs:/mkdocs/docs
    working_dir: /mkdocs
    tty: true
    command: mkdocs serve
    ports:
      - "8000:8000"
    healthcheck:
      test: "curl -f http://localhost:8000 || exit 1"
      interval: 10s
      retries: 10
      timeout: 2s
    restart: always

```

### /docker/mkdocs/Dockerfile

参考サイトのをほぼ使用しました。

```
FROM python:3.10.6-bullseye

RUN adduser -q --gecos "" --disabled-login mkuser \
    && pip install mkdocs mkdocs-material fontawesome-markdown mdx_unimoji python-markdown-math pymdown-extensions \

```

## index.md

```
# はじめに

## 概要

アプリケーションのドキュメントになります。

```


## 動作確認

dockerを起動

```
docker-compose -f develop.yml up -d
```

起動後に`http://localhost:8000/`を開いて下記の画面が出れば成功

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389877/f4e05603-d55e-963e-6f5c-844aec45cd69.png)


## 最後に

最初は`docs`フォルダの中に`mkdocs.yml`を置いてさらに`docs`フォルダを置くとか考えていた

しかし、パッと見たディレクトリが`/docs/docs`になって気持ち悪いなって思い
よくよく考えれば`mkdocs.yml`をプロジェクトのrootに置けばいい話だったので直下に置いた。
what3wordsサジェスト機能を使ってみよう（JavaScript）

<h1>what3wordsサジェスト機能</h1>
入力された3つの単語の組み合わせ（what3wordsアドレス）に対して、似た三単語の組み合わせと、各組み合わせの凡その場所を候補として提示。

<img width="500" alt="![あおぐ。わすれた。あまえび.png]" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289659/02666772-3317-3b51-4266-bfd371daf8e4.png">

上の例の場合：
① **あおぐ。わすれた。あまえび**（青森県・青森市）
を入力すると、下記二つの候補もサジェストされる。
② **あおぐ。わすれ<font color="Red">て</font>。あまえび** （ドイツ・ベルリン）
③ **あおぐ。わすれた。あまえ<font color="Red">る</font>** （ワシントン州・タッカウィラ）
一文字違うだけで、全然違うところに該当するマス目があります！

<h6>何故サジェスト機能が必要なのか？</h6>
言い間違い・聞き間違い・打ち間違えは、どうしても起こってしまうもの。

待ち合わせはもちろん、事件や事故が起こった際、共有された三単語の組み合わせが間違ってたら、話にならない。
サジェスト候補はいくつか出る上、エリア情報も出てくるので、軌道修正が可能。
※国内だけにサジェスト結果を絞る事も可能。

:::note info
似た単語・組み合わせは、お互い可能な限り遠く設定しているため、選択時に間違えが起きにくい
:::


実装例
----
ラッパーとサジェスト機能

```html
<script type="module" src="https://cdn.what3words.com/javascript-components@4-latest/dist/what3words/what3words.esm.js"></script>
<script nomodule src="https://cdn.what3words.com/javascript-components@4-latest/dist/what3words/what3words.js?"></script>

<form id="form" method="GET">
   <div>
      <what3words-autosuggest api_key="YOUR-API-KEY">
        <input type="text" />
      </what3words-autosuggest>
   </div>
</form>
```
_後はライセンスキーを入力するだけ！_
_APIキーの発行は[こちら](https://qiita.com/iwai_shin/items/c21b1a31c7dfc010961a "APIキー取得")から確認できます。_


<h4>その他機能のご紹介</h4>
入力欄内のテキストの設置

```html
<label for="w3w">what3wordsアドレス（任意）：</label>
<what3words-autosuggest api_key="YOUR-API-KEY">
  <input
    id="w3w"
    placeholder="例：///あおぐ。わすれた。あまえび"
    type="text"
    optional
  />
</what3words-autosuggest>
```

サジェスト結果を（指定した国、例えば日本だけに）限定する
```html
<what3words-autosuggest api_key="YOUR-API-KEY" clip_to_country="ja">
  <input type="text" />
</what3words-autosuggest>
```

入力された場所のGPSを中心にした距離を考慮した優先順位の付与
```html
<what3words-autosuggest api_key="YOUR-API-KEY" autosuggest_focus="51.1,2.0">
  <input type="text" />
</what3words-autosuggest>
```

エラーメッセージ
```html
<what3words-autosuggest api_key="YOUR-API-KEY" invalid_address_error_message="エラー">
  <input type="text" />
</what3words-autosuggest>
```

以上JavaScriptにおけるwhat3wordsサジェスト機能のガイドでした！
繰り返し処理

# はじめに
授業で繰り返し処理を改めて扱ったのでまとめてみます。


# if文での繰り返し処理

もし、3回「こんにちは」と表示させたいときにif文のみで表示するには

```sample.py
i = 0

# 1回目の処理
if i < 3:
  print("こんにちは")
  i += 1
# 2回目の処理
if i < 3:
  print("こんにちは")
  i += 1
# 3回目の処理
if i < 3:
  print("こんにちは")
  i += 1
# 4回目の処理
if i < 3:
  print("こんにちは")
  i += 1
#仮に同じif文の処理が更に書かれたとしても3回目の処理以降は出力されない

print("----繰り返し処理終了----")

# 処理結果
#こんにちは
#こんにちは
#こんにちは
#----繰り返し処理終了----
```
と書きます。
　人間は３回表示されてたら見たら分かりますがプログラムは指定しないとわかりません。
　プログラムはiで出力したい回数を宣言し、if文の条件式で３回出力したかどうかを判断します。
　出力したら毎回if文内でiに1を足していきます。
　そして、４回目以降のif文の条件式内で既に３回出力したと判断され、これより下にいくらif文を書いたとしても同じように判断されるので「こんにちは」は出力されません。
　しかし毎回同じif文を書いて、条件を判断させるのは非効率なので、繰り返し処理を行う際はwhile文を使います。

```sample.py
while i < 3:
  print("こんにちは")
  i += 1
print("----繰り返し処理終了----")

#処理結果
#こんにちは
#こんにちは
#こんにちは
#----繰り返し処理終了----
```

　この時whileの条件式には継続条件を書く必要があります。上記の繰り返し処理を行いたい回数を宣言する変数（**i**）を**カウンタ変数**という。
　繰り返し処理を行うプログラムを書く上で、カウンタ変数（i）を繰り返し処理を終わらすために、値を増加（または減少）させる必要があります。
　この繰り返し処理はfor文でも書くことができます。

```sample.py
for i in range(3)
  print("こんにちは")

print("----繰り返し処理終了----")

#処理結果
#こんにちは
#こんにちは
#こんにちは
#----繰り返し処理終了----
```
　pythonでは、range関数を使用して繰り返し処理をする回数を宣言します。

# 二重の繰り返し処理
　授業では集計に繰り返し処理を使うプログラムを扱ったので、それの延長で九九を表示させるプログラムを書いてみます
```sample.py
i = 0
j = 0
k = 0
for i in range(11):
  for j in range(11):
    #i x j　を計算する
    k = i * j 
    # 計算したkを出力する
    print(str(k)+ " ",end="")
  # 改行処理のため入れてます
  print ("---")

"""
処理結果
0 0 0 0 0 0 0 0 0 0 0 ---
0 1 2 3 4 5 6 7 8 9 10 ---
0 2 4 6 8 10 12 14 16 18 20 ---
0 3 6 9 12 15 18 21 24 27 30 ---
0 4 8 12 16 20 24 28 32 36 40 ---
0 5 10 15 20 25 30 35 40 45 50 ---
0 6 12 18 24 30 36 42 48 54 60 ---
0 7 14 21 28 35 42 49 56 63 70 ---
0 8 16 24 32 40 48 56 64 72 80 ---
0 9 18 27 36 45 54 63 72 81 90 ---
0 10 20 30 40 50 60 70 80 90 100 ---
"""

```
　SQLのようにテーブル表示をpythonでもやってみたかったのですが、難しい😓

# 最後に
　自分ではプログラムを書けても人に教えたりで上手く言えないことが多いので、授業で習ったことは丁寧に復習してこれからも書いていきます。
nodebrewでNode.jsバージョンをプロジェクトごとに管理する

# nodebrewとは
- nodebrewは、一つのマシン上で複数のバージョンのNode.jsを管理するためのツール。
- 開発するプロジェクトごとに利用するNode.jsのバージョンが異なる場合などに便利。

## 環境
- Mac OS
- Homebrew
- nodebrew
- bash

## nodebrew公式
全ての手順はここに書かれてるので、詳しくは参照してください。

https://github.com/hokaccha/nodebrew

## 手順
こんな順番で進めます。
- Homebrewを使ってnodebrewをインストールする
- 環境変数PATHを通してから有効にする
- nodebrewを使って特定のバージョンのNode.jsをインストールする
- プロジェクトのルートディレクトリに移動する
- 使用するNode.jsのバージョンを切り替える

## 作業開始！

### Homebrewを使ってnodebrewをインストールする

https://formulae.brew.sh/formula/nodebrew

Homebrewでnodebrewを管理したいので今回はそうします。
```terminal: Homebrewを使ってnodebrewをインストールする
$ brew install nodebrew
```

### 環境変数PATHを通してから有効にする

```terminal: PATHを通す ※bashにパスを通す場合
$ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> .bash_profile
$ source ~/.bash_profile # bash_profileの再読み込みで有効にする
```

### nodebrewを使って特定のバージョンのNode.jsをインストールします。
```terminal: nodeをバージョン指定でインストール
$ nodebrew install 18.16.0
```

```terminal: nodeインストールバージョンのリスト表示
$ nodebrew ls
v6.11.4
v12.4.0
v12.6.0
v14.15.0
v18.16.0

current: v14.15.0  # （v14.15.0を使用中）
```

### プロジェクトのルートディレクトリに移動する
```terminal:nodeバージョン切替え、バージョン確認
$ cd [YourProject]
```

### 使用するNode.jsのバージョンを切り替える
```terminal:nodeバージョン切替え、バージョン確認
$ nodebrew use 18.16.0
$ node -v
v18.16.0
```


以上
GitHub、複数アカウントをターミナルでで切り替える方法（Mac,zsh)

複数のGitHubアカウントを使い分けるために、SSHキーとSSHの設定ファイルを使用してアカウントの切り替えを行う方法を紹介します。会社用と個人用を想定。


# 1. SSHキーの生成
まず、各アカウント用に異なるSSHキーペアをホームディレクトリーで生成します。
"アカウントのメールアドレス"は会社用でGitHubアカウントに登録している、emailアドレスに置き換えてください。
~~~
ssh-keygen -t ed25519 -C "アカウントのメールアドレス" -f ~/.ssh/id_ed25519_company
~~~
このコマンドを実行し、会社用のSSHキーペアを生成します。同様に、個人用にもSSHキーペアを生成します。
"アカウントのメールアドレス"は個人用でGitHubアカウントに登録している、emailアドレスに置き換えてください。
~~~
ssh-keygen -t ed25519 -C "アカウントのメールアドレス" -f ~/.ssh/id_ed25519_personal
~~~


# 2. SSHの設定ファイルの作成
SSHの設定ファイル（~/.ssh/config）を作成または編集します。
~~~
code ~/.ssh/config
~~~
[補足]VSCodeエディターで行っていますが、お好みのエディターで大丈夫かと思います。

以下のような内容を記述します。各項目は自身の環境に合わせて適宜変更してください。

~~~
# 会社アカウントの設定
Host github.com-NicName
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_company

# 個人アカウントの設定
Host github.com-NicName
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_personal
~~~

上記の例では、会社用の設定と個人用の設定を追加しています。
NicNameやHostNameは実際のGitHubに登録してあるニックネーム、ホストネームに置き換えてください。

# 3. GitHubに公開鍵を登録
生成したSSHキーの公開鍵をGitHubに登録します。

GitHubのウェブサイトにログインし、右上のアバターをクリックしてドロップダウンメニューを表示します。
「Settings」を選択し、左側のメニューから、「SSH and GPG keys」を選択します。
「New SSH key」または「Add SSH key」をクリックし、公開鍵を登録します。
タイトルに適切な名前を入力(例えば、MyCompanyKeyなど)し、公開鍵の内容を貼り付けます。
「Add SSH key」または「Add key」をクリックして、公開鍵を登録してGitHubの設定は完了です。

# 4. アカウントの切り替え方法

.zshrcファイルの編集
ターミナルを開き、.zshrcファイルを編集します。

~~~
code ~/.zshrc
~~~

以下のコードを.zshrcファイルの適切な場所に追加します。

~~~
# 会社アカウント
function gitCo() {
    git config --global user.name "[***]"   # ***には会社アカウントのusername
    git config --global user.email "[***]"  # ***には会社アカウントのemailアドレス
    echo "Switched to Company Account"　　　　　　　　　　　　#アカウントを切り替えると表示される内容
}

# 個人アカウント
function gitPe() {
    git config --global user.name "[***]"   # ***には個人用のusername
    git config --global user.email "[***]"  # ***には個人用のemailアドレス
    echo "Switched to Personal Account"　　　　　　　　　　#アカウントを切り替えると表示される内容
}
~~~

上記のコードでは、gitCo関数とgitPe関数を定義しています。(この関数は自分でわかりやすい名をつけてよい。ターミナルで切り替えのために入力する関数。)それぞれの関数は、会社用のアカウントと個人用のアカウントの設定を行います。***の表示箇所は"会社用のユーザー名"や"会社用のメールアドレス"、"個人用のユーザー名"や"個人用のメールアドレス"は、実際のアカウント情報に置き換えてください。

ファイルを保存してエディタを閉じます。

.zshrcファイルの変更を反映させるために、以下のコマンドをターミナルで実行します。

~~~
source ~/.zshrc
~~~

# 5. アカウントの切り替え
ターミナルで以下のコマンドを実行して、アカウントを切り替えます。
 職場用アカウントに切り替え。
~~~
gitCo
~~~
"Switched to Company Account"と表示され、切り替え成功。

個人用アカウントに切り替え。
~~~
gitPe
~~~
"Switched to Personal Account"と表示され、切り替え成功。



GitHubのターミナルでのアカウント切り替え方法は、以上となります。
ご観覧ありがとうございました！
Excluded Architectures:arm64とSwiftPackageManagerで、Compiled module was created by a different version of the compiler; rebuild 'SOME_LIBRARY' and try again: /PATH_TO_SOME_LIBRARY.swiftmodule/x86_64-apple-ios-simulator.swiftmodule エラー

Apple SilliconのMacでシミュレータをビルド対象にしてSwift Package Manager(以下SPM)で追加したライブラリをりようすると、`import` 文の場所で以下のエラーが発生します。

```
Compiled module was created by a different version of the compiler; rebuild 'SOME_LIBRARY' and try again: /PATH_TO_SOME_LIBRARY.swiftmodule/x86_64-apple-ios-simulator.swiftmodule
```

以下のような状況になっていて、この問題が発生していると考えられます。

* Excluded Architecturesにarm64を指定している
* Apple SilliconのMacでSPMで追加したライブラリはシミュレータを対象にすると、シミュレータがarm64なのでarm64用のバイナリのみ作成する
* プロジェクト全体の設定としてはarm64を除外しているので、PRMで追加したパッケージもx86_64のバイナリが必要で探しにいく
* でも見つからなくてエラー


# 解決方法
Excluded Architecturesのarm64を外すのがベストだと思いますが、おそらくいろいろな事情ですんなり外せないことがおおいと思います。
そこでXcode14.3ではSimulatorのみRossettaモードで起動できる機能があるので、ビルド対象のSimulatorをRossetaにすることで解決します。Xcode自体はRossetaモードではないので許容範囲ではないでしょうか？

`Product > Destination > Destination Architectures` から有効にすることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18273/2c435a8a-e6ac-c0bc-fd93-e3d1fca4557e.png)

有効にするとsimulator名に `(Rosseta)` がついたシミュレータが選択できるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18273/4e7cd6d0-6f0a-d1cf-7299-a80769133f2d.png)

# まとめ
長いことこの問題に苦労した人は多いのではないでしょうか？ Xcode自体をRossetaモードにしなくて良くなったので、Swift Package Managerの利用がしやすくなる気がします。

# 参考
https://sarunw.com/posts/open-using-rosetta-in-xcode-14-3/
【Pleasanter】URLクエリパラメータでグリッドをフィルターする方法

顧客リストテーブルがあり、【分類】項目A（ClassA）として電話番号があったとする。

'https://demo.pleasanter.org/items/9876543/index?tel=03-1234-1234

上記のURLでアクセスされた時に、クエリパラメータのtelにセットされている
03-1234-1234と一致する電話番号があれば、その行を表示する。
ヒットしなければ新規追加画面を表示する。
、という挙動を実装するための各種スクリプトは以下のとおりです。


【サーバスクリプト】ビュー処理時
```
let tel = context.QueryStrings.Data('tel'); 'クエリーパラメータを取得する

if( tel != '' ) {
	view.Filters.ClassA = tel; '項目Aに電話番号をセットしてフィルターをかける
}
```

【スクリプト】一覧画面時
```
$p.events.on_grid_load  = function () {
	let rowCnt = document.getElementsByClassName("grid-row").length;
	if( rowCnt > 0 ) {
	  //データ有りの場合は何もしない
	} else {
	  //データ無しの場合は新規入力画面へ遷移する
	  window.location.href = "https://demo.pleasanter.org/items/9876543/new"
	}
}
```

Pleasanter特有の関数についての詳細は以下

https://pleasanter.org/manual/server-script-context-query-strings

https://pleasanter.org/manual/server-script-view-filters

https://pleasanter.org/manual/script-events-on-grid-load
【Unity】【AgoraVideoSDK】リモートユーザーがビデオをオン・オフした時のコールバックメソッドについて

# リモートユーザーのビデオオン・オフのイベントを受け取る
リモートユーザーが`RtcEngine.EnableLocalVideo();`を呼び出した時、
ローカルユーザーでは以下のコールバックメソッドが呼ばれます。

* REMOTE_VIDEO_STATE_DECODING : ビデオをオン
* REMOTE_VIDEO_STATE_FAILED : ビデオの失敗
* REMOTE_VIDEO_STATE_FROZEN : なんらかの原因でフリーズした
* REMOTE_VIDEO_STATE_STOPPED : ビデオをオフ
* REMOTE_VIDEO_STATE_STARTING: 最初のリモートビデオのパケットを受信した

```
public override void OnRemoteVideoStateChanged(RtcConnection connection, uint remoteUid, REMOTE_VIDEO_STATE state,
            REMOTE_VIDEO_STATE_REASON reason, int elapsed)
        {
            base.OnRemoteVideoStateChanged(connection, remoteUid, state, reason, elapsed);
            
            Debug.Log("OnRemoteVideoStateChanged: " + remoteUid);
            switch (state)
            {
                case REMOTE_VIDEO_STATE.REMOTE_VIDEO_STATE_DECODING:
                    Debug.Log("REMOTE_VIDEO_STATE_DECODING");
                    break;
                case REMOTE_VIDEO_STATE.REMOTE_VIDEO_STATE_FAILED:
                    Debug.Log("REMOTE_VIDEO_STATE_FAILED");
                    break;
                case REMOTE_VIDEO_STATE.REMOTE_VIDEO_STATE_FROZEN:
                    Debug.Log("REMOTE_VIDEO_STATE_FROZEN");
                    break;
                case REMOTE_VIDEO_STATE.REMOTE_VIDEO_STATE_STOPPED:
                    Debug.Log("REMOTE_VIDEO_STATE_STOPPED");
                    break;
                case REMOTE_VIDEO_STATE.REMOTE_VIDEO_STATE_STARTING:
                    Debug.Log("REMOTE_VIDEO_STATE_STARTING");
                    break;
            }
        }
```

# さいごに
エンジニア向けバーチャルコミュニケーションアプリのピクセルトークを開発・運営しています。
コロナ禍でリモートワークになり便利さを実感していましたが、人との距離が広がってしまって寂しいと感じることが増えました。
離れていてもオフィスにいる感覚で仕事が出来ればいいという思いからピクセルトークの開発に着手しました。

https://www.pixeltalk.app/